Put script environment creation/deletion in functions.

This makes environment handling safer, and also has a single place where
we can add new environment variables that should be present for all
scripts.
This commit is contained in:
Guus Sliepen 2017-03-21 21:21:23 +01:00
parent 3e643d5d7e
commit 5cbef90620
12 changed files with 134 additions and 94 deletions

View file

@ -1,6 +1,6 @@
/* /*
graph.c -- graph algorithms graph.c -- graph algorithms
Copyright (C) 2001-2013 Guus Sliepen <guus@tinc-vpn.org>, Copyright (C) 2001-2017 Guus Sliepen <guus@tinc-vpn.org>,
2001-2005 Ivo Timmermans 2001-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
@ -247,28 +247,23 @@ static void check_reachability(void) {
char *name; char *name;
char *address; char *address;
char *port; char *port;
char *envp[8] = {NULL};
xasprintf(&envp[0], "NETNAME=%s", netname ? : ""); environment_t env;
xasprintf(&envp[1], "DEVICE=%s", device ? : ""); environment_init(&env);
xasprintf(&envp[2], "INTERFACE=%s", iface ? : ""); environment_add(&env, "NODE=%s", n->name);
xasprintf(&envp[3], "NODE=%s", n->name);
sockaddr2str(&n->address, &address, &port); sockaddr2str(&n->address, &address, &port);
xasprintf(&envp[4], "REMOTEADDRESS=%s", address); environment_add(&env, "REMOTEADDRESS=%s", address);
xasprintf(&envp[5], "REMOTEPORT=%s", port); environment_add(&env, "REMOTEPORT=%s", port);
xasprintf(&envp[6], "NAME=%s", myself->name);
execute_script(n->status.reachable ? "host-up" : "host-down", envp); execute_script(n->status.reachable ? "host-up" : "host-down", &env);
xasprintf(&name, n->status.reachable ? "hosts/%s-up" : "hosts/%s-down", n->name); xasprintf(&name, n->status.reachable ? "hosts/%s-up" : "hosts/%s-down", n->name);
execute_script(name, envp); execute_script(name, &env);
free(name); free(name);
free(address); free(address);
free(port); free(port);
environment_exit(&env);
for(int i = 0; i < 7; i++)
free(envp[i]);
subnet_update(n, NULL, n->status.reachable); subnet_update(n, NULL, n->status.reachable);

View file

@ -1,6 +1,6 @@
/* /*
invitation.c -- Create and accept invitations invitation.c -- Create and accept invitations
Copyright (C) 2013-2015 Guus Sliepen <guus@tinc-vpn.org> Copyright (C) 2013-2017 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -239,7 +239,7 @@ int cmd_invite(int argc, char *argv[]) {
return 1; return 1;
} }
char *myname = get_my_name(true); myname = get_my_name(true);
if(!myname) if(!myname)
return 1; return 1;
@ -425,15 +425,13 @@ int cmd_invite(int argc, char *argv[]) {
xasprintf(&url, "%s/%s%s", address, hash, cookie); xasprintf(&url, "%s/%s%s", address, hash, cookie);
// Call the inviation-created script // Call the inviation-created script
char *envp[6] = {}; environment_t env;
xasprintf(&envp[0], "NAME=%s", myname); environment_init(&env);
xasprintf(&envp[1], "NETNAME=%s", netname); environment_add(&env, "NODE=%s", argv[1]);
xasprintf(&envp[2], "NODE=%s", argv[1]); environment_add(&env, "INVITATION_FILE=%s", filename);
xasprintf(&envp[3], "INVITATION_FILE=%s", filename); environment_add(&env, "INVITATION_URL=%s", url);
xasprintf(&envp[4], "INVITATION_URL=%s", url); execute_script("invitation-created", &env);
execute_script("invitation-created", envp); environment_exit(&env);
for(int i = 0; i < 6 && envp[i]; i++)
free(envp[i]);
puts(url); puts(url);
free(url); free(url);

View file

@ -1,6 +1,6 @@
/* /*
logger.c -- logging code logger.c -- logging code
Copyright (C) 2004-2015 Guus Sliepen <guus@tinc-vpn.org> Copyright (C) 2004-2017 Guus Sliepen <guus@tinc-vpn.org>
2004-2005 Ivo Timmermans 2004-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
@ -29,7 +29,7 @@
#include "process.h" #include "process.h"
#include "sptps.h" #include "sptps.h"
debug_t debug_level = DEBUG_NOTHING; int debug_level = DEBUG_NOTHING;
static logmode_t logmode = LOGMODE_STDERR; static logmode_t logmode = LOGMODE_STDERR;
static pid_t logpid; static pid_t logpid;
static FILE *logfile = NULL; static FILE *logfile = NULL;

View file

@ -1,7 +1,7 @@
/* /*
logger.h -- header file for logger.c logger.h -- header file for logger.c
Copyright (C) 1998-2005 Ivo Timmermans Copyright (C) 1998-2005 Ivo Timmermans
2000-2012 Guus Sliepen <guus@tinc-vpn.org> 2000-2017 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -67,7 +67,7 @@ enum {
#include <stdbool.h> #include <stdbool.h>
extern debug_t debug_level; extern int debug_level;
extern bool logcontrol; extern bool logcontrol;
extern int umbilical; extern int umbilical;
extern void openlogger(const char *, logmode_t); extern void openlogger(const char *, logmode_t);

View file

@ -1,7 +1,7 @@
/* /*
names.c -- generate commonly used (file)names names.c -- generate commonly used (file)names
Copyright (C) 1998-2005 Ivo Timmermans Copyright (C) 1998-2005 Ivo Timmermans
2000-2015 Guus Sliepen <guus@tinc-vpn.org> 2000-2017 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -25,6 +25,7 @@
#include "xalloc.h" #include "xalloc.h"
char *netname = NULL; char *netname = NULL;
char *myname = NULL;
char *confdir = NULL; /* base configuration directory */ char *confdir = NULL; /* base configuration directory */
char *confbase = NULL; /* base configuration directory for this instance of tinc */ char *confbase = NULL; /* base configuration directory for this instance of tinc */
bool confbase_given; bool confbase_given;
@ -137,6 +138,7 @@ void free_names(void) {
free(logfilename); free(logfilename);
free(confbase); free(confbase);
free(confdir); free(confdir);
free(myname);
identname = NULL; identname = NULL;
netname = NULL; netname = NULL;
@ -145,4 +147,5 @@ void free_names(void) {
logfilename = NULL; logfilename = NULL;
confbase = NULL; confbase = NULL;
confdir = NULL; confdir = NULL;
myname = NULL;
} }

View file

@ -1,7 +1,7 @@
/* /*
names.h -- header for names.c names.h -- header for names.c
Copyright (C) 1998-2005 Ivo Timmermans Copyright (C) 1998-2005 Ivo Timmermans
2000-2015 Guus Sliepen <guus@tinc-vpn.org> 2000-2017 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -25,6 +25,7 @@ extern char *confdir;
extern char *confbase; extern char *confbase;
extern bool confbase_given; extern bool confbase_given;
extern char *netname; extern char *netname;
extern char *myname;
extern char *identname; extern char *identname;
extern char *unixsocketname; extern char *unixsocketname;
extern char *logfilename; extern char *logfilename;

View file

@ -1,7 +1,7 @@
/* /*
net_setup.c -- Setup. net_setup.c -- Setup.
Copyright (C) 1998-2005 Ivo Timmermans, Copyright (C) 1998-2005 Ivo Timmermans,
2000-2016 Guus Sliepen <guus@tinc-vpn.org> 2000-2017 Guus Sliepen <guus@tinc-vpn.org>
2006 Scott Lamb <slamb@slamb.org> 2006 Scott Lamb <slamb@slamb.org>
2010 Brandon Black <blblack@gmail.com> 2010 Brandon Black <blblack@gmail.com>
@ -48,7 +48,6 @@
#endif #endif
char *myport; char *myport;
static char *myname;
static io_t device_io; static io_t device_io;
devops_t devops; devops_t devops;
bool device_standby = false; bool device_standby = false;
@ -705,29 +704,17 @@ void device_enable(void) {
/* Run tinc-up script to further initialize the tap interface */ /* Run tinc-up script to further initialize the tap interface */
char *envp[5] = {NULL}; environment_t env;
xasprintf(&envp[0], "NETNAME=%s", netname ? : ""); environment_init(&env);
xasprintf(&envp[1], "DEVICE=%s", device ? : ""); execute_script("tinc-up", &env);
xasprintf(&envp[2], "INTERFACE=%s", iface ? : ""); environment_exit(&env);
xasprintf(&envp[3], "NAME=%s", myname);
execute_script("tinc-up", envp);
for(int i = 0; i < 4; i++)
free(envp[i]);
} }
void device_disable(void) { void device_disable(void) {
char *envp[5] = {NULL}; environment_t env;
xasprintf(&envp[0], "NETNAME=%s", netname ? : ""); environment_init(&env);
xasprintf(&envp[1], "DEVICE=%s", device ? : ""); execute_script("tinc-down", &env);
xasprintf(&envp[2], "INTERFACE=%s", iface ? : ""); environment_exit(&env);
xasprintf(&envp[3], "NAME=%s", myname);
execute_script("tinc-down", envp);
for(int i = 0; i < 4; i++)
free(envp[i]);
if (devops.disable) if (devops.disable)
devops.disable(); devops.disable();
@ -1150,7 +1137,6 @@ void close_network_connections(void) {
exit_control(); exit_control();
free(myname);
free(scriptextension); free(scriptextension);
free(scriptinterpreter); free(scriptinterpreter);

View file

@ -1,7 +1,7 @@
/* /*
protocol_auth.c -- handle the meta-protocol, authentication protocol_auth.c -- handle the meta-protocol, authentication
Copyright (C) 1999-2005 Ivo Timmermans, Copyright (C) 1999-2005 Ivo Timmermans,
2000-2016 Guus Sliepen <guus@tinc-vpn.org> 2000-2017 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -180,21 +180,18 @@ static bool finalize_invitation(connection_t *c, const char *data, uint16_t len)
logger(DEBUG_CONNECTIONS, LOG_INFO, "Key succesfully received from %s (%s)", c->name, c->hostname); logger(DEBUG_CONNECTIONS, LOG_INFO, "Key succesfully received from %s (%s)", c->name, c->hostname);
// Call invitation-accepted script // Call invitation-accepted script
char *envp[7] = {NULL}; environment_t env;
char *address, *port; char *address, *port;
xasprintf(&envp[0], "NETNAME=%s", netname ? : ""); environment_init(&env);
xasprintf(&envp[1], "DEVICE=%s", device ? : ""); environment_add(&env, "NODE=%s", c->name);
xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
xasprintf(&envp[3], "NODE=%s", c->name);
sockaddr2str(&c->address, &address, &port); sockaddr2str(&c->address, &address, &port);
xasprintf(&envp[4], "REMOTEADDRESS=%s", address); environment_add(&env, "REMOTEADDRESS=%s", address);
xasprintf(&envp[5], "NAME=%s", myself->name); environment_add(&env, "NAME=%s", myself->name);
execute_script("invitation-accepted", envp); execute_script("invitation-accepted", &env);
for(int i = 0; envp[i] && i < 7; i++) environment_exit(&env);
free(envp[i]);
sptps_send_record(&c->sptps, 2, data, 0); sptps_send_record(&c->sptps, 2, data, 0);
return true; return true;

View file

@ -1,7 +1,7 @@
/* /*
script.c -- call an external script script.c -- call an external script
Copyright (C) 1999-2005 Ivo Timmermans, Copyright (C) 1999-2005 Ivo Timmermans,
2000-2015 Guus Sliepen <guus@tinc-vpn.org> 2000-2017 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -21,6 +21,7 @@
#include "system.h" #include "system.h"
#include "conf.h" #include "conf.h"
#include "device.h"
#include "logger.h" #include "logger.h"
#include "names.h" #include "names.h"
#include "script.h" #include "script.h"
@ -63,7 +64,56 @@ static void putenv(const char *p) {}
static void unputenv(const char *p) {} static void unputenv(const char *p) {}
#endif #endif
bool execute_script(const char *name, char **envp) { static const int min_env_size;
int environment_add(environment_t *env, const char *format, ...) {
if(env->n >= env->size) {
env->size = env->n ? env->n * 2 : min_env_size;
env->entries = xrealloc(env->entries, env->size * sizeof *env->entries);
}
if(format) {
va_list ap;
va_start(ap, format);
vasprintf(&env->entries[env->n], format, ap);
va_end(ap);
} else {
env->entries[env->n] = NULL;
}
return env->n++;
}
void environment_update(environment_t *env, int pos, const char *format, ...) {
free(env->entries[pos]);
va_list ap;
va_start(ap, format);
vasprintf(&env->entries[pos], format, ap);
va_end(ap);
}
void environment_init(environment_t *env) {
env->n = 0;
env->size = min_env_size;
env->entries = 0; //xzalloc(env->size * sizeof *env->entries);
if(netname)
environment_add(env, "NETNAME=%s", netname);
if(myname)
environment_add(env, "NAME=%s", myname);
if(device)
environment_add(env, "DEVICE=%s", device);
if(iface)
environment_add(env, "INTERFACE=%s", iface);
}
void environment_exit(environment_t *env) {
for(int i = 0; i < env->n; i++)
free(env->entries[i]);
free(env->entries);
}
bool execute_script(const char *name, environment_t *env) {
char scriptname[PATH_MAX]; char scriptname[PATH_MAX];
char *command; char *command;
@ -107,8 +157,8 @@ bool execute_script(const char *name, char **envp) {
/* Set environment */ /* Set environment */
for(int i = 0; envp[i]; i++) for(int i = 0; i < env->n; i++)
putenv(envp[i]); putenv(env->entries[i]);
if(scriptinterpreter) if(scriptinterpreter)
xasprintf(&command, "%s \"%s\"", scriptinterpreter, scriptname); xasprintf(&command, "%s \"%s\"", scriptinterpreter, scriptname);
@ -121,8 +171,8 @@ bool execute_script(const char *name, char **envp) {
/* Unset environment */ /* Unset environment */
for(int i = 0; envp[i]; i++) for(int i = 0; i < env->n; i++)
unputenv(envp[i]); unputenv(env->entries[i]);
if(status != -1) { if(status != -1) {
#ifdef WEXITSTATUS #ifdef WEXITSTATUS

View file

@ -1,7 +1,7 @@
/* /*
script.h -- header file for script.c script.h -- header file for script.c
Copyright (C) 1999-2005 Ivo Timmermans, Copyright (C) 1999-2005 Ivo Timmermans,
2000-2013 Guus Sliepen <guus@tinc-vpn.org> 2000-2017 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -21,6 +21,18 @@
#ifndef __TINC_SCRIPT_H__ #ifndef __TINC_SCRIPT_H__
#define __TINC_SCRIPT_H__ #define __TINC_SCRIPT_H__
extern bool execute_script(const char *, char **); typedef struct environment {
int n;
int size;
char **entries;
} environment_t;
extern int environment_add(environment_t *env, const char *format, ...);
extern int environment_placeholder(environment_t *env);
extern void environment_update(environment_t *env, int pos, const char *format, ...);
extern void environment_init(environment_t *env);
extern void environment_exit(environment_t *env);
extern bool execute_script(const char *name, environment_t *env);
#endif /* __TINC_SCRIPT_H__ */ #endif /* __TINC_SCRIPT_H__ */

View file

@ -1,6 +1,6 @@
/* /*
subnet.c -- handle subnet lookups and lists subnet.c -- handle subnet lookups and lists
Copyright (C) 2000-2013 Guus Sliepen <guus@tinc-vpn.org>, Copyright (C) 2000-2017 Guus Sliepen <guus@tinc-vpn.org>,
2000-2005 Ivo Timmermans 2000-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
@ -206,22 +206,20 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) {
// Prepare environment variables to be passed to the script // Prepare environment variables to be passed to the script
char *envp[10] = {NULL}; environment_t env;
int n = 0; environment_init(&env);
xasprintf(&envp[n++], "NETNAME=%s", netname ? : ""); environment_add(&env, "NODE=%s", owner->name);
xasprintf(&envp[n++], "DEVICE=%s", device ? : "");
xasprintf(&envp[n++], "INTERFACE=%s", iface ? : "");
xasprintf(&envp[n++], "NODE=%s", owner->name);
if(owner != myself) { if(owner != myself) {
sockaddr2str(&owner->address, &address, &port); sockaddr2str(&owner->address, &address, &port);
xasprintf(&envp[n++], "REMOTEADDRESS=%s", address); environment_add(&env, "REMOTEADDRESS=%s", address);
xasprintf(&envp[n++], "REMOTEPORT=%s", port); environment_add(&env, "REMOTEPORT=%s", port);
free(port); free(port);
free(address); free(address);
} }
xasprintf(&envp[n++], "NAME=%s", myself->name); int env_subnet = environment_add(&env, NULL);
int env_weight = environment_add(&env, NULL);
name = up ? "subnet-up" : "subnet-down"; name = up ? "subnet-up" : "subnet-down";
@ -238,12 +236,10 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) {
weight = empty; weight = empty;
// Prepare the SUBNET and WEIGHT variables // Prepare the SUBNET and WEIGHT variables
free(envp[n]); environment_update(&env, env_subnet, "SUBNET=%s", netstr);
free(envp[n + 1]); environment_update(&env, env_weight, "WEIGHT=%s", weight);
xasprintf(&envp[n], "SUBNET=%s", netstr);
xasprintf(&envp[n + 1], "WEIGHT=%s", weight);
execute_script(name, envp); execute_script(name, &env);
} }
} else { } else {
if(net2str(netstr, sizeof netstr, subnet)) { if(net2str(netstr, sizeof netstr, subnet)) {
@ -255,15 +251,14 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) {
weight = empty; weight = empty;
// Prepare the SUBNET and WEIGHT variables // Prepare the SUBNET and WEIGHT variables
xasprintf(&envp[n], "SUBNET=%s", netstr); environment_update(&env, env_subnet, "SUBNET=%s", netstr);
xasprintf(&envp[n + 1], "WEIGHT=%s", weight); environment_update(&env, env_weight, "WEIGHT=%s", weight);
execute_script(name, envp); execute_script(name, &env);
} }
} }
for(int i = 0; envp[i] && i < 9; i++) environment_exit(&env);
free(envp[i]);
} }
bool dump_subnets(connection_t *c) { bool dump_subnets(connection_t *c) {

View file

@ -74,6 +74,9 @@ bool netnamegiven = false;
char *scriptinterpreter = NULL; char *scriptinterpreter = NULL;
char *scriptextension = ""; char *scriptextension = "";
static char *prompt; static char *prompt;
char *device = NULL;
char *iface = NULL;
int debug_level = -1;
static struct option const long_options[] = { static struct option const long_options[] = {
{"batch", no_argument, NULL, 'b'}, {"batch", no_argument, NULL, 'b'},
@ -89,7 +92,7 @@ static struct option const long_options[] = {
static void version(void) { static void version(void) {
printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE, printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
BUILD_VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR); BUILD_VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
printf("Copyright (C) 1998-2016 Ivo Timmermans, Guus Sliepen and others.\n" printf("Copyright (C) 1998-2017 Ivo Timmermans, Guus Sliepen and others.\n"
"See the AUTHORS file for a complete list.\n\n" "See the AUTHORS file for a complete list.\n\n"
"tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n" "tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
"and you are welcome to redistribute it under certain conditions;\n" "and you are welcome to redistribute it under certain conditions;\n"