From ab0576a2034b03f92943ac477e4e97731a899554 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sun, 7 Jun 2015 22:25:22 +0200 Subject: [PATCH 01/16] Fix autoconf check for function attributes. GCC warns when a function attribute has no effect. The autoconf check turns warnings about attributes into errors, therefore thinking that they did not work. The reason was that the test function returned void, which is not suitable for checking both __malloc__ and __warn_unused_result__. --- m4/attribute.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/m4/attribute.m4 b/m4/attribute.m4 index 6a8f5558..9d673e96 100644 --- a/m4/attribute.m4 +++ b/m4/attribute.m4 @@ -9,8 +9,8 @@ AC_DEFUN([tinc_ATTRIBUTE], CFLAGS="$CFLAGS -Wall -Werror" AC_COMPILE_IFELSE( [AC_LANG_SOURCE( - [void test(void) __attribute__ (($1)); - void test(void) { return; } + [void *test(void) __attribute__ (($1)); + void *test(void) { return (void *)0; } ], )], [tinc_cv_attribute_$1=yes], From d8d1ab4ee1e92ec84fe9ea86eec2396275483a92 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sun, 7 Jun 2015 22:50:05 +0200 Subject: [PATCH 02/16] Fix warnings about missing return value checks. In some harmless places, checks for the return value of ECDSA and RSA key generation and verification was omitted. Add them to keep the compiler happy and to warn end users in case something is wrong. --- src/invitation.c | 16 +++++++++++++--- src/sptps_keypair.c | 8 ++++++-- src/sptps_speed.c | 13 ++++++++++--- src/tincctl.c | 6 ++++++ 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/invitation.c b/src/invitation.c index 415c2377..3102e416 100644 --- a/src/invitation.c +++ b/src/invitation.c @@ -335,7 +335,11 @@ int cmd_invite(int argc, char *argv[]) { return 1; } chmod(filename, 0600); - ecdsa_write_pem_private_key(key, f); + if(!ecdsa_write_pem_private_key(key, f)) { + fprintf(stderr, "Could not write ECDSA private key\n"); + fclose(f); + return 1; + } fclose(f); if(connect_tincd(false)) @@ -704,6 +708,8 @@ make_names: snprintf(filename, sizeof filename, "%s" SLASH "ed25519_key.priv", confbase); f = fopenmask(filename, "w", 0600); + if(!f) + return false; if(!ecdsa_write_pem_private_key(key, f)) { fprintf(stderr, "Error writing private key!\n"); @@ -725,10 +731,14 @@ make_names: snprintf(filename, sizeof filename, "%s" SLASH "rsa_key.priv", confbase); f = fopenmask(filename, "w", 0600); - rsa_write_pem_private_key(rsa, f); + if(!f || !rsa_write_pem_private_key(rsa, f)) { + fprintf(stderr, "Could not write private RSA key\n"); + } else if(!rsa_write_pem_public_key(rsa, fh)) { + fprintf(stderr, "Could not write public RSA key\n"); + } + fclose(f); - rsa_write_pem_public_key(rsa, fh); fclose(fh); rsa_free(rsa); diff --git a/src/sptps_keypair.c b/src/sptps_keypair.c index 399404e1..fde86227 100644 --- a/src/sptps_keypair.c +++ b/src/sptps_keypair.c @@ -88,7 +88,10 @@ int main(int argc, char *argv[]) { FILE *fp = fopen(argv[1], "w"); if(fp) { - ecdsa_write_pem_private_key(key, fp); + if(!ecdsa_write_pem_private_key(key, fp)) { + fprintf(stderr, "Could not write ECDSA private key\n"); + return 1; + } fclose(fp); } else { fprintf(stderr, "Could not open '%s' for writing: %s\n", argv[1], strerror(errno)); @@ -97,7 +100,8 @@ int main(int argc, char *argv[]) { fp = fopen(argv[2], "w"); if(fp) { - ecdsa_write_pem_public_key(key, fp); + if(!ecdsa_write_pem_public_key(key, fp)) + fprintf(stderr, "Could not write ECDSA public key\n"); fclose(fp); } else { fprintf(stderr, "Could not open '%s' for writing: %s\n", argv[2], strerror(errno)); diff --git a/src/sptps_speed.c b/src/sptps_speed.c index d03246c5..4cb1221b 100644 --- a/src/sptps_speed.c +++ b/src/sptps_speed.c @@ -102,19 +102,26 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Ed25519 sign for %lg seconds: ", duration); for(clock_start(); clock_countto(duration);) - ecdsa_sign(key1, buf1, 256, buf2); + if(!ecdsa_sign(key1, buf1, 256, buf2)) + return 1; fprintf(stderr, "%22.2lf op/s\n", rate); fprintf(stderr, "Ed25519 verify for %lg seconds: ", duration); for(clock_start(); clock_countto(duration);) - ecdsa_verify(key1, buf1, 256, buf2); + if(!ecdsa_verify(key1, buf1, 256, buf2)) { + fprintf(stderr, "Signature verification failed\n"); + return 1; + } fprintf(stderr, "%20.2lf op/s\n", rate); ecdh1 = ecdh_generate_public(buf1); fprintf(stderr, "ECDH for %lg seconds: ", duration); for(clock_start(); clock_countto(duration);) { ecdh2 = ecdh_generate_public(buf2); - ecdh_compute_shared(ecdh2, buf1, buf3); + if(!ecdh2) + return 1; + if(!ecdh_compute_shared(ecdh2, buf1, buf3)) + return 1; } fprintf(stderr, "%28.2lf op/s\n", rate); ecdh_free(ecdh1); diff --git a/src/tincctl.c b/src/tincctl.c index c9d8c67c..00757c47 100644 --- a/src/tincctl.c +++ b/src/tincctl.c @@ -233,6 +233,12 @@ FILE *fopenmask(const char *filename, const char *mode, mode_t perms) { perms &= ~mask; umask(~perms); FILE *f = fopen(filename, mode); + + if(!f) { + fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno)); + return NULL; + } + #ifdef HAVE_FCHMOD if((perms & 0444) && f) fchmod(fileno(f), perms); From a797b4a19235be740c51bcb3bb6ec5de01915f46 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sun, 7 Jun 2015 23:14:48 +0200 Subject: [PATCH 03/16] Fix receiving SPTPS data in sptps_speed and sptps_test. The sptps_receive_data() was changed in commit d237efd to only process one SPTPS record from a stream input. So now we have to put a loop around it to ensure we process everything. --- src/sptps_speed.c | 11 ++++++++--- src/sptps_test.c | 15 +++++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/sptps_speed.c b/src/sptps_speed.c index 4cb1221b..4d112dd7 100644 --- a/src/sptps_speed.c +++ b/src/sptps_speed.c @@ -47,11 +47,16 @@ static bool receive_record(void *handle, uint8_t type, const void *data, uint16_ } static void receive_data(sptps_t *sptps) { - char buf[4096]; + char buf[4096], *bufp = buf; int fd = *(int *)sptps->handle; size_t len = recv(fd, buf, sizeof buf, 0); - if(!sptps_receive_data(sptps, buf, len)) - abort(); + while(len) { + size_t done = sptps_receive_data(sptps, bufp, len); + if(!done) + abort(); + bufp += done; + len -= done; + } } struct timespec start; diff --git a/src/sptps_test.c b/src/sptps_test.c index f83307fe..9452ed1e 100644 --- a/src/sptps_test.c +++ b/src/sptps_test.c @@ -357,8 +357,19 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Dropped.\n"); continue; } - if(!sptps_receive_data(&s, buf, len) && !datagram) - return 1; + char *bufp = buf; + while(len) { + size_t done = sptps_receive_data(&s, bufp, len); + if(!done) { + if(!datagram) + return 1; + } else { + break; + } + + bufp += done; + len -= done; + } } } From bfe231b977284ba78a582db96a05b5854ddf0d91 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sun, 7 Jun 2015 23:20:14 +0200 Subject: [PATCH 04/16] Fix alignment of output of sptps_speed. --- src/sptps_speed.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sptps_speed.c b/src/sptps_speed.c index 4d112dd7..bde3d697 100644 --- a/src/sptps_speed.c +++ b/src/sptps_speed.c @@ -109,7 +109,7 @@ int main(int argc, char *argv[]) { for(clock_start(); clock_countto(duration);) if(!ecdsa_sign(key1, buf1, 256, buf2)) return 1; - fprintf(stderr, "%22.2lf op/s\n", rate); + fprintf(stderr, "%20.2lf op/s\n", rate); fprintf(stderr, "Ed25519 verify for %lg seconds: ", duration); for(clock_start(); clock_countto(duration);) @@ -117,7 +117,7 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Signature verification failed\n"); return 1; } - fprintf(stderr, "%20.2lf op/s\n", rate); + fprintf(stderr, "%18.2lf op/s\n", rate); ecdh1 = ecdh_generate_public(buf1); fprintf(stderr, "ECDH for %lg seconds: ", duration); From 45a46f068cf8fbe6cc8c59673de2d8580d18f87f Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Wed, 10 Jun 2015 23:42:17 +0200 Subject: [PATCH 05/16] Fix crash is sptps_logger(). Unfortunately, sptps_logger() cannot know if s->handle is pointing to a connection_t or a node_t. But it needs to print name and hostname in both cases. So make sure both types have name and hostname fields at the start with the same offset. --- src/connection.h | 2 +- src/logger.c | 2 ++ src/node.h | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/connection.h b/src/connection.h index b41cf46a..7fa769f8 100644 --- a/src/connection.h +++ b/src/connection.h @@ -59,9 +59,9 @@ typedef struct connection_status_t { typedef struct connection_t { char *name; /* name he claims to have */ + char *hostname; /* the hostname of its real ip */ union sockaddr_t address; /* his real (internet) ip */ - char *hostname; /* the hostname of its real ip */ int protocol_major; /* used protocol */ int protocol_minor; /* used protocol */ diff --git a/src/logger.c b/src/logger.c index ad7cef28..68a7fb2d 100644 --- a/src/logger.c +++ b/src/logger.c @@ -127,6 +127,8 @@ static void sptps_logger(sptps_t *s, int s_errno, const char *format, va_list ap if(message[len - 1] == '\n') message[--len] = 0; + // WARNING: s->handle can point to a connection_t or a node_t, + // but both types have the name and hostname fields at the same offsets. connection_t *c = s->handle; if(c) snprintf(message + len, sizeof message - len, " from %s (%s)", c->name, c->hostname); diff --git a/src/node.h b/src/node.h index 0800337c..02e2a6d6 100644 --- a/src/node.h +++ b/src/node.h @@ -45,12 +45,12 @@ typedef struct node_status_t { typedef struct node_t { char *name; /* name of this node */ + char *hostname; /* the hostname of its real ip */ node_id_t id; /* unique node ID (name hash) */ uint32_t options; /* options turned on for this node */ int sock; /* Socket to use for outgoing UDP packets */ sockaddr_t address; /* his real (internet) ip to send UDP packets to */ - char *hostname; /* the hostname of its real ip */ node_status_t status; time_t last_state_change; From 7f020cf456b327313f0cfa8d103fb14f06f71994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dato=20Sim=C3=B3?= Date: Tue, 16 Jun 2015 20:44:45 -0300 Subject: [PATCH 06/16] Fix typo in tinc.texi. --- doc/tinc.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tinc.texi b/doc/tinc.texi index b489042d..e939784a 100644 --- a/doc/tinc.texi +++ b/doc/tinc.texi @@ -735,7 +735,7 @@ You will also notice that log messages it appears in syslog as coming from @file and on Linux, unless specified otherwise, the name of the virtual network interface will be the same as the network name. However, it is not strictly necessary that you call tinc with the -n -option. If you don not use it, the network name will just be empty, and +option. If you do not use it, the network name will just be empty, and tinc will look for files in @file{@value{sysconfdir}/tinc/} instead of @file{@value{sysconfdir}/tinc/@var{netname}/}; the configuration file will then be @file{@value{sysconfdir}/tinc/tinc.conf}, From ebffa40aa7832459f63801e3a91cc741e6b339a8 Mon Sep 17 00:00:00 2001 From: Etienne Dechamps Date: Sat, 20 Jun 2015 11:41:20 +0100 Subject: [PATCH 07/16] Protect against callbacks removing items from the io tree. The definition of the splay_each() macro is somewhat complicated for syntactic reasons. Here's what it does in a more readable way: for (splay_node_t* node = tree->head; node;) { type* item = node->data; splay_node_t* next = node->next; // RUN USER BLOCK with (item) node = next; } list_each() works in the same way. Since node->next is saved before the user block runs, this construct supports removing the current item from within the user block. However, what it does *not* support is removing *other items* from within the user block, especially the next item. Indeed, that will invalide the next pointer in the above loop and therefore result in an invalid pointer dereference. Unfortunately, there is at least one code path where that unsupported operation happens. It is located in ack_h(), where the authentication protocol code detects a double connection (i.e. being connected to another node twice). Running in the context of a socket read event, this code will happily terminate the *other* metaconnection, resulting in its socket being removed from the io tree. If, by misfortune, this other metaconnection happened to have the next socket FD number (which is quite possible due to FD reuse - albeit unlikely), and was part of the io tree (which is quite likely because if that connection is stuck, it will most likely have pending writes) then this will result in the next pending io item being destroyed. Invalid pointer dereference ensues. I did a quick audit of other uses of splay_each() and list_each() and I believe this is the only scenario in which this "next pointer invalidation" problem can occur in practice. While this bug has been there since at least 6bc5d626a8726fc23365ee705761a3c666a08ad4 (November 2012), if not sooner, it happens quite rarely due to the very specific set of conditions required to trigger it. Nevertheless, it does manage to crash my central production nodes every other week or so. --- src/event.c | 10 ++++++++++ src/list.h | 6 ++++++ src/splay_tree.h | 6 ++++++ 3 files changed, 22 insertions(+) diff --git a/src/event.c b/src/event.c index 60d357d4..59b96e37 100644 --- a/src/event.c +++ b/src/event.c @@ -285,6 +285,16 @@ bool event_loop(void) { io->cb(io->data, IO_WRITE); else if(FD_ISSET(io->fd, &readable)) io->cb(io->data, IO_READ); + else + continue; + + /* + There are scenarios in which the callback will remove another io_t from the tree + (e.g. closing a double connection). Since splay_each does not support that, we + need to exit the loop now. That's okay, since any remaining events will get picked + up by the next select() call. + */ + break; } } #else diff --git a/src/list.h b/src/list.h index 0437bd92..b0e7a845 100644 --- a/src/list.h +++ b/src/list.h @@ -79,6 +79,12 @@ extern void list_delete_list(list_t *); extern void list_foreach(list_t *, list_action_t); extern void list_foreach_node(list_t *, list_action_node_t); +/* + Iterates over a list. + + CAUTION: while this construct supports deleting the current item, + it does *not* support deleting *other* nodes while iterating on the list. + */ #define list_each(type, item, list) (type *item = (type *)1; item; item = NULL) for(list_node_t *node = (list)->head, *next; item = node ? node->data : NULL, next = node ? node->next : NULL, node; node = next) #endif /* __TINC_LIST_H__ */ diff --git a/src/splay_tree.h b/src/splay_tree.h index 58488707..3ddf2172 100644 --- a/src/splay_tree.h +++ b/src/splay_tree.h @@ -106,6 +106,12 @@ extern splay_node_t *splay_search_closest_greater_node(splay_tree_t *, const voi extern void splay_foreach(const splay_tree_t *, splay_action_t); extern void splay_foreach_node(const splay_tree_t *, splay_action_t); +/* + Iterates over a tree. + + CAUTION: while this construct supports deleting the current item, + it does *not* support deleting *other* nodes while iterating on the tree. + */ #define splay_each(type, item, tree) (type *item = (type *)1; item; item = NULL) for(splay_node_t *node = (tree)->head, *next; item = node ? node->data : NULL, next = node ? node->next : NULL, node; node = next) #endif From 91355b9ac5a80d6d7da6951a72ea0c22651bdfa8 Mon Sep 17 00:00:00 2001 From: Florian Klink Date: Thu, 2 Jul 2015 12:35:41 +0200 Subject: [PATCH 08/16] (read|append)_config_file: log open errors as LOG_DEBUG In a "decentrally managed vpn" it is very likely that host config files for some reachable nodes do not exist. Currently, tinc fills the logs with "Cannot open config file" messages. This commit changes the log level to LOG_DEBUG so syslog doesn't get filled by default. --- src/conf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/conf.c b/src/conf.c index 2b323597..7756247b 100644 --- a/src/conf.c +++ b/src/conf.c @@ -298,7 +298,7 @@ bool read_config_file(splay_tree_t *config_tree, const char *fname) { fp = fopen(fname, "r"); if(!fp) { - logger(DEBUG_ALWAYS, LOG_ERR, "Cannot open config file %s: %s", fname, strerror(errno)); + logger(DEBUG_ALWAYS, LOG_DEBUG, "Cannot open config file %s: %s", fname, strerror(errno)); return false; } @@ -423,7 +423,7 @@ bool append_config_file(const char *name, const char *key, const char *value) { FILE *fp = fopen(fname, "a"); if(!fp) { - logger(DEBUG_ALWAYS, LOG_ERR, "Cannot open config file %s: %s", fname, strerror(errno)); + logger(DEBUG_ALWAYS, LOG_DEBUG, "Cannot open config file %s: %s", fname, strerror(errno)); return false; } From 0267aef826ba627aba3a525b36c0e7bfc0f9a221 Mon Sep 17 00:00:00 2001 From: Florian Klink Date: Thu, 2 Jul 2015 12:35:42 +0200 Subject: [PATCH 09/16] setup_outgoing_connection: log to LOG_DEBUG on if no known address With AutoConnect = yes, tinc tries to establish connections to known hosts. However, you could have set no Address for this host, which is perfectly fine (as long as there is at least one bootstrap node with an address or a local discovered node already part of the network) So log this to LOG_DEBUG --- src/net_socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net_socket.c b/src/net_socket.c index 526d382a..97d6c448 100644 --- a/src/net_socket.c +++ b/src/net_socket.c @@ -617,7 +617,7 @@ void setup_outgoing_connection(outgoing_t *outgoing) { if(n) outgoing->aip = outgoing->ai = get_known_addresses(n); if(!outgoing->ai) { - logger(DEBUG_ALWAYS, LOG_ERR, "No address known for %s", outgoing->name); + logger(DEBUG_ALWAYS, LOG_DEBUG, "No address known for %s", outgoing->name); return; } } From 1140ca6d3004b228947bad8736f0b49d6b169267 Mon Sep 17 00:00:00 2001 From: thorkill Date: Sat, 4 Jul 2015 00:29:36 +0200 Subject: [PATCH 10/16] Fixed 2 leaks in setup_myself() --- src/net_setup.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/net_setup.c b/src/net_setup.c index bf5ba04c..0033c008 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -364,6 +364,7 @@ void load_all_subnets(void) { if((s2 = lookup_subnet(n, s))) { s2->expires = -1; + free(s); } else { subnet_add(n, s); } @@ -962,6 +963,8 @@ static bool setup_myself(void) { devops = vde_devops; #endif } + if (type) + free(type); get_config_bool(lookup_config(config_tree, "DeviceStandby"), &device_standby); From 92df36a610421ed5fcae90e832f64e3acfb7d431 Mon Sep 17 00:00:00 2001 From: thorkill Date: Sat, 4 Jul 2015 02:39:12 +0200 Subject: [PATCH 11/16] Cleanup edges stored in edge_weight_tree on exit protocol_edge.c: 131 defines local_address using str2sockaddr str2sockaddr() allocates memory which has to be freed on exit. --- src/edge.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/edge.c b/src/edge.c index 2eaae5d1..65396309 100644 --- a/src/edge.c +++ b/src/edge.c @@ -64,6 +64,12 @@ void free_edge_tree(splay_tree_t *edge_tree) { } void exit_edges(void) { + // since edge_weight_tree does not have delete action defined + // we have to cleanup it on exit + for splay_each(edge_t, e, edge_weight_tree) { + sockaddrfree(&e->address); + sockaddrfree(&e->local_address); + } splay_delete_tree(edge_weight_tree); } From abb24e9d71b3edb9cacf4c04361cc0dfd4e6a061 Mon Sep 17 00:00:00 2001 From: thorkill Date: Sat, 4 Jul 2015 03:21:01 +0200 Subject: [PATCH 12/16] Cleanup local_address in protocol_edge.c In line 131 local_address has been defined, but the memory was never freed on return. --- src/protocol_edge.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/protocol_edge.c b/src/protocol_edge.c index 7478aaeb..0879613c 100644 --- a/src/protocol_edge.c +++ b/src/protocol_edge.c @@ -137,6 +137,7 @@ bool add_edge_h(connection_t *c, const char *request) { logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself which does not match existing entry", "ADD_EDGE", c->name, c->hostname); send_add_edge(c, e); + sockaddrfree(&local_address); return true; } else { logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) which does not match existing entry", @@ -151,9 +152,11 @@ bool add_edge_h(connection_t *c, const char *request) { logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself which does not match existing entry", "ADD_EDGE", c->name, c->hostname); send_add_edge(c, e); + sockaddrfree(&local_address); return true; } // Otherwise, just ignore it. + sockaddrfree(&local_address); return true; } else if(local_address.sa.sa_family) { // We learned a new local address for this edge. @@ -166,8 +169,10 @@ bool add_edge_h(connection_t *c, const char *request) { return true; } - } else + } else { + sockaddrfree(&local_address); return true; + } } else if(from == myself) { logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself which does not exist", "ADD_EDGE", c->name, c->hostname); @@ -177,6 +182,7 @@ bool add_edge_h(connection_t *c, const char *request) { e->to = to; send_del_edge(c, e); free_edge(e); + sockaddrfree(&local_address); return true; } From 37588b8d5cface1bc72424a198b1cc1a6044adb0 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sat, 4 Jul 2015 17:18:40 +0200 Subject: [PATCH 13/16] Don't #include OpenSSL headers when compiling without OpenSSL. --- src/nolegacy/crypto.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/nolegacy/crypto.c b/src/nolegacy/crypto.c index 96e4dda2..f1113b46 100644 --- a/src/nolegacy/crypto.c +++ b/src/nolegacy/crypto.c @@ -19,10 +19,6 @@ #include "../system.h" -#include -#include -#include - #include "../crypto.h" #ifndef HAVE_MINGW From 14ccf509540e338502ad806f60bdc3f71ddce66f Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Thu, 18 Jun 2015 23:58:31 +0200 Subject: [PATCH 14/16] fix musl compatibility Let configure include sys/if_tun.h when testing for netinet/if_ether.h to detect the Kernel/libc header conflict on musl. After this patch, configure will correctly detect netinet/if_ether.h as unusable and the subsequent compilation will not attempt to use it. Conflicts: src/have.h --- src/have.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/have.h b/src/have.h index 9dc3b04c..88733a1e 100644 --- a/src/have.h +++ b/src/have.h @@ -206,6 +206,10 @@ #include #endif +#ifdef HAVE_LINUX_IF_TUN_H +#include +#endif + #ifdef STATUS #undef STATUS #endif From 36cec9af88909cb2cf012d609e5c4d8c444ddab9 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sat, 4 Jul 2015 17:51:05 +0200 Subject: [PATCH 15/16] Coalesce two if statements that check for the same thing. --- src/net_setup.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/net_setup.c b/src/net_setup.c index 0033c008..23dd2521 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -962,9 +962,8 @@ static bool setup_myself(void) { else if(!strcasecmp(type, "vde")) devops = vde_devops; #endif - } - if (type) free(type); + } get_config_bool(lookup_config(config_tree, "DeviceStandby"), &device_standby); From de7d9ee437bc0e5d72f8c6744e1df7ea7b64d2e9 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sat, 4 Jul 2015 17:53:11 +0200 Subject: [PATCH 16/16] Call sockaddrfree(&e->local_address) in free_edge() instead of exit_edges(). The proper place to clean up resources of objects is in their destructor. This makes sure proper cleanup when edge_del() is called as well. At exit, free_edge() is called on all edges by free_edge_tree(), which is called by exit_nodes(). --- src/edge.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/edge.c b/src/edge.c index 65396309..0e35cd1e 100644 --- a/src/edge.c +++ b/src/edge.c @@ -64,12 +64,6 @@ void free_edge_tree(splay_tree_t *edge_tree) { } void exit_edges(void) { - // since edge_weight_tree does not have delete action defined - // we have to cleanup it on exit - for splay_each(edge_t, e, edge_weight_tree) { - sockaddrfree(&e->address); - sockaddrfree(&e->local_address); - } splay_delete_tree(edge_weight_tree); } @@ -81,6 +75,7 @@ edge_t *new_edge(void) { void free_edge(edge_t *e) { sockaddrfree(&e->address); + sockaddrfree(&e->local_address); free(e); }