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

View file

@ -1,6 +1,6 @@
/*
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
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;
}
char *myname = get_my_name(true);
myname = get_my_name(true);
if(!myname)
return 1;
@ -425,15 +425,13 @@ int cmd_invite(int argc, char *argv[]) {
xasprintf(&url, "%s/%s%s", address, hash, cookie);
// Call the inviation-created script
char *envp[6] = {};
xasprintf(&envp[0], "NAME=%s", myname);
xasprintf(&envp[1], "NETNAME=%s", netname);
xasprintf(&envp[2], "NODE=%s", argv[1]);
xasprintf(&envp[3], "INVITATION_FILE=%s", filename);
xasprintf(&envp[4], "INVITATION_URL=%s", url);
execute_script("invitation-created", envp);
for(int i = 0; i < 6 && envp[i]; i++)
free(envp[i]);
environment_t env;
environment_init(&env);
environment_add(&env, "NODE=%s", argv[1]);
environment_add(&env, "INVITATION_FILE=%s", filename);
environment_add(&env, "INVITATION_URL=%s", url);
execute_script("invitation-created", &env);
environment_exit(&env);
puts(url);
free(url);

View file

@ -1,6 +1,6 @@
/*
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
This program is free software; you can redistribute it and/or modify
@ -29,7 +29,7 @@
#include "process.h"
#include "sptps.h"
debug_t debug_level = DEBUG_NOTHING;
int debug_level = DEBUG_NOTHING;
static logmode_t logmode = LOGMODE_STDERR;
static pid_t logpid;
static FILE *logfile = NULL;

View file

@ -1,7 +1,7 @@
/*
logger.h -- header file for logger.c
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
it under the terms of the GNU General Public License as published by
@ -67,7 +67,7 @@ enum {
#include <stdbool.h>
extern debug_t debug_level;
extern int debug_level;
extern bool logcontrol;
extern int umbilical;
extern void openlogger(const char *, logmode_t);

View file

@ -1,7 +1,7 @@
/*
names.c -- generate commonly used (file)names
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
it under the terms of the GNU General Public License as published by
@ -25,6 +25,7 @@
#include "xalloc.h"
char *netname = NULL;
char *myname = NULL;
char *confdir = NULL; /* base configuration directory */
char *confbase = NULL; /* base configuration directory for this instance of tinc */
bool confbase_given;
@ -137,6 +138,7 @@ void free_names(void) {
free(logfilename);
free(confbase);
free(confdir);
free(myname);
identname = NULL;
netname = NULL;
@ -145,4 +147,5 @@ void free_names(void) {
logfilename = NULL;
confbase = NULL;
confdir = NULL;
myname = NULL;
}

View file

@ -1,7 +1,7 @@
/*
names.h -- header for names.c
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
it under the terms of the GNU General Public License as published by
@ -25,6 +25,7 @@ extern char *confdir;
extern char *confbase;
extern bool confbase_given;
extern char *netname;
extern char *myname;
extern char *identname;
extern char *unixsocketname;
extern char *logfilename;

View file

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

View file

@ -1,7 +1,7 @@
/*
protocol_auth.c -- handle the meta-protocol, authentication
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
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);
// Call invitation-accepted script
char *envp[7] = {NULL};
environment_t env;
char *address, *port;
xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
xasprintf(&envp[1], "DEVICE=%s", device ? : "");
xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
xasprintf(&envp[3], "NODE=%s", c->name);
environment_init(&env);
environment_add(&env, "NODE=%s", c->name);
sockaddr2str(&c->address, &address, &port);
xasprintf(&envp[4], "REMOTEADDRESS=%s", address);
xasprintf(&envp[5], "NAME=%s", myself->name);
environment_add(&env, "REMOTEADDRESS=%s", address);
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++)
free(envp[i]);
environment_exit(&env);
sptps_send_record(&c->sptps, 2, data, 0);
return true;

View file

@ -1,7 +1,7 @@
/*
script.c -- call an external script
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
it under the terms of the GNU General Public License as published by
@ -21,6 +21,7 @@
#include "system.h"
#include "conf.h"
#include "device.h"
#include "logger.h"
#include "names.h"
#include "script.h"
@ -63,7 +64,56 @@ static void putenv(const char *p) {}
static void unputenv(const char *p) {}
#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 *command;
@ -107,8 +157,8 @@ bool execute_script(const char *name, char **envp) {
/* Set environment */
for(int i = 0; envp[i]; i++)
putenv(envp[i]);
for(int i = 0; i < env->n; i++)
putenv(env->entries[i]);
if(scriptinterpreter)
xasprintf(&command, "%s \"%s\"", scriptinterpreter, scriptname);
@ -121,8 +171,8 @@ bool execute_script(const char *name, char **envp) {
/* Unset environment */
for(int i = 0; envp[i]; i++)
unputenv(envp[i]);
for(int i = 0; i < env->n; i++)
unputenv(env->entries[i]);
if(status != -1) {
#ifdef WEXITSTATUS

View file

@ -1,7 +1,7 @@
/*
script.h -- header file for script.c
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
it under the terms of the GNU General Public License as published by
@ -21,6 +21,18 @@
#ifndef __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__ */

View file

@ -1,6 +1,6 @@
/*
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
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
char *envp[10] = {NULL};
int n = 0;
xasprintf(&envp[n++], "NETNAME=%s", netname ? : "");
xasprintf(&envp[n++], "DEVICE=%s", device ? : "");
xasprintf(&envp[n++], "INTERFACE=%s", iface ? : "");
xasprintf(&envp[n++], "NODE=%s", owner->name);
environment_t env;
environment_init(&env);
environment_add(&env, "NODE=%s", owner->name);
if(owner != myself) {
sockaddr2str(&owner->address, &address, &port);
xasprintf(&envp[n++], "REMOTEADDRESS=%s", address);
xasprintf(&envp[n++], "REMOTEPORT=%s", port);
environment_add(&env, "REMOTEADDRESS=%s", address);
environment_add(&env, "REMOTEPORT=%s", port);
free(port);
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";
@ -238,12 +236,10 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) {
weight = empty;
// Prepare the SUBNET and WEIGHT variables
free(envp[n]);
free(envp[n + 1]);
xasprintf(&envp[n], "SUBNET=%s", netstr);
xasprintf(&envp[n + 1], "WEIGHT=%s", weight);
environment_update(&env, env_subnet, "SUBNET=%s", netstr);
environment_update(&env, env_weight, "WEIGHT=%s", weight);
execute_script(name, envp);
execute_script(name, &env);
}
} else {
if(net2str(netstr, sizeof netstr, subnet)) {
@ -255,15 +251,14 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) {
weight = empty;
// Prepare the SUBNET and WEIGHT variables
xasprintf(&envp[n], "SUBNET=%s", netstr);
xasprintf(&envp[n + 1], "WEIGHT=%s", weight);
environment_update(&env, env_subnet, "SUBNET=%s", netstr);
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++)
free(envp[i]);
environment_exit(&env);
}
bool dump_subnets(connection_t *c) {

View file

@ -74,6 +74,9 @@ bool netnamegiven = false;
char *scriptinterpreter = NULL;
char *scriptextension = "";
static char *prompt;
char *device = NULL;
char *iface = NULL;
int debug_level = -1;
static struct option const long_options[] = {
{"batch", no_argument, NULL, 'b'},
@ -89,7 +92,7 @@ static struct option const long_options[] = {
static void version(void) {
printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
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"
"tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
"and you are welcome to redistribute it under certain conditions;\n"