Add DeviceStandby option to only enable the device when nodes are reachable.

This adds a new DeviceStandby option; when it is disabled (the default),
behavior is unchanged. If it is enabled, tinc-up will not be called during
tinc initialization, but will instead be deferred until the first node is
reachable, and it will be closed as soon as no nodes are reachable.

This is useful because it means the device won't be set up until we are fairly
sure there is something listening on the other side. This is more user-friendly,
as one can check on the status of the tinc network connection just by checking
the status of the network interface. Besides, it prevents the OS from thinking
it is connected to some network when it is in fact completely isolated.
This commit is contained in:
Etienne Dechamps 2014-06-22 10:48:34 +01:00
parent f0885b8d2f
commit bd451cfe15
4 changed files with 67 additions and 24 deletions

View file

@ -204,6 +204,9 @@ static void sssp_bfs(void) {
static void check_reachability(void) {
/* Check reachability status. */
int reachable_count = 0;
int became_reachable_count = 0;
int became_unreachable_count = 0;
for splay_each(node_t, n, node_tree) {
if(n->status.visited != n->status.reachable) {
n->status.reachable = !n->status.reachable;
@ -212,9 +215,13 @@ static void check_reachability(void) {
if(n->status.reachable) {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Node %s (%s) became reachable",
n->name, n->hostname);
if (n != myself)
became_reachable_count++;
} else {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Node %s (%s) became unreachable",
n->name, n->hostname);
if (n != myself)
became_unreachable_count++;
}
if(experimental && OPTION_VERSION(n->options) >= 2)
@ -277,6 +284,16 @@ static void check_reachability(void) {
}
}
}
if(n->status.reachable && n != myself)
reachable_count++;
}
if (device_standby) {
if (reachable_count == 0 && became_unreachable_count > 0)
device_disable();
else if (reachable_count == became_reachable_count)
device_enable();
}
}

View file

@ -137,6 +137,7 @@ extern int udp_sndbuf;
extern int max_connection_burst;
extern bool do_prune;
extern char *myport;
extern bool device_standby;
extern bool autoconnect;
extern bool disablebuggypeers;
extern int contradicting_add_edge;
@ -178,6 +179,8 @@ extern void send_packet(struct node_t *, vpn_packet_t *);
extern void receive_tcppacket(struct connection_t *, const char *, int);
extern void broadcast_packet(const struct node_t *, vpn_packet_t *);
extern char *get_name(void);
extern void device_enable(void);
extern void device_disable(void);
extern bool setup_myself_reloadable(void);
extern bool setup_network(void);
extern void setup_outgoing_connection(struct outgoing_t *);

View file

@ -46,6 +46,7 @@
char *myport;
static io_t device_io;
devops_t devops;
bool device_standby = false;
char *proxyhost;
char *proxyport;
@ -726,6 +727,34 @@ static bool add_listen_address(char *address, bool bindto) {
return true;
}
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", myself->name);
execute_script("tinc-up", envp);
for(int i = 0; i < 4; i++)
free(envp[i]);
}
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", myself->name);
execute_script("tinc-down", envp);
for(int i = 0; i < 4; i++)
free(envp[i]);
}
/*
Configure node_t myself and set up the local sockets (listen only)
*/
@ -918,6 +947,8 @@ static bool setup_myself(void) {
#endif
}
get_config_bool(lookup_config(config_tree, "DeviceStandby"), &device_standby);
if(!devops.setup())
return false;
@ -1048,18 +1079,8 @@ bool setup_network(void) {
if(!init_control())
return false;
/* 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", myself->name);
execute_script("tinc-up", envp);
for(int i = 0; i < 4; i++)
free(envp[i]);
if (!device_standby)
device_enable();
/* Run subnet-up scripts for our own subnets */
@ -1098,25 +1119,17 @@ void close_network_connections(void) {
close(listen_socket[i].udp.fd);
}
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", myself->name);
exit_requests();
exit_edges();
exit_subnets();
exit_nodes();
exit_connections();
execute_script("tinc-down", envp);
if (!device_standby)
device_disable();
if(myport) free(myport);
for(int i = 0; i < 4; i++)
free(envp[i]);
if (device_fd >= 0)
io_del(&device_io);
devops.close();