From 618ddadeab51f5243ca3da84c02ea539823d2807 Mon Sep 17 00:00:00 2001 From: thorkill Date: Thu, 23 Jul 2015 20:45:37 +0200 Subject: [PATCH] Fixed a segfault when all nodes available for autoconnect has been exhausted In cases when tinc has all available nodes in outgoing connections and can not establish those connection due to network outage periodic_handler() would crash since tmp_node_tree->count is 0. This commit adds also new flag node->status.has_cfg_address to prevent update_udp_address() from removing this flag. Fixed node_status_t->unused - 13 + 19 = 32 --- src/net.c | 27 +++++++++++++++------------ src/net_setup.c | 4 +++- src/node.h | 5 +++-- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/net.c b/src/net.c index fe89fb20..881c6b64 100644 --- a/src/net.c +++ b/src/net.c @@ -215,7 +215,7 @@ static void periodic_handler(void *data) { for splay_each(node_t, n, node_tree) { - if(!n->status.has_known_address || n->connection) + if ((!n->status.has_known_address && !n->status.has_cfg_address) || n->connection) continue; bool found = false; @@ -230,20 +230,23 @@ static void periodic_handler(void *data) { splay_insert(tmp_node_tree, n); } - int r = rand() % tmp_node_tree->count; - int i = 0; + if (tmp_node_tree->count) { + int r = rand() % tmp_node_tree->count; + int i = 0; - for splay_each(node_t, n, tmp_node_tree) { + for splay_each(node_t, n, tmp_node_tree) { - if(i++ != r) - continue; + if(i++ != r) + continue; - - logger(DEBUG_CONNECTIONS, LOG_INFO, "Autoconnecting to %s", n->name); - outgoing_t *outgoing = xzalloc(sizeof *outgoing); - outgoing->name = xstrdup(n->name); - list_insert_tail(outgoing_list, outgoing); - setup_outgoing_connection(outgoing); + logger(DEBUG_CONNECTIONS, LOG_INFO, "Autoconnecting to %s", n->name); + outgoing_t *outgoing = xzalloc(sizeof *outgoing); + outgoing->name = xstrdup(n->name); + list_insert_tail(outgoing_list, outgoing); + setup_outgoing_connection(outgoing); + } + } else { + logger(DEBUG_ALWAYS, LOG_INFO, "No more nodes available for autoconnect!"); } splay_delete_tree(tmp_node_tree); } else if(nc > 3) { diff --git a/src/net_setup.c b/src/net_setup.c index fe8cc675..d5f9f9eb 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -394,8 +394,10 @@ void load_all_nodes(void) { } } - if (lookup_config(config_tree, "Address")) + if (lookup_config(config_tree, "Address")) { n->status.has_known_address = true; + n->status.has_cfg_address = true; + } exit_configuration(&config_tree); } diff --git a/src/node.h b/src/node.h index 73170226..ec5f83c1 100644 --- a/src/node.h +++ b/src/node.h @@ -40,8 +40,9 @@ typedef struct node_status_t { unsigned int send_locally:1; /* 1 if the next UDP packet should be sent on the local network */ unsigned int udppacket:1; /* 1 if the most recently received packet was UDP */ unsigned int validkey_in; /* 1 if we have sent a valid key to him */ - unsigned int has_known_address; /* 1 if this node has Address in node's config */ - unsigned int unused:21; + unsigned int has_known_address; /* 1 if this node has UDP Address */ + unsigned int has_cfg_address; /* 1 if this node has Address in node's config */ + unsigned int unused:19; } node_status_t; typedef struct node_t {