From: Guus Sliepen Date: Sat, 17 Apr 2010 10:21:53 +0000 (+0200) Subject: Merge branch 'master' into 1.1 X-Git-Tag: release-1.1pre1~75 X-Git-Url: https://tinc-vpn.org/git/browse?p=tinc;a=commitdiff_plain;h=79e46d08a46f2fef2ee4e8eac7ba487007160564 Merge branch 'master' into 1.1 Conflicts: NEWS README configure.in src/net.c src/net.h --- 79e46d08a46f2fef2ee4e8eac7ba487007160564 diff --cc NEWS index 3b065969,b5ce4960..cee37ea8 --- a/NEWS +++ b/NEWS @@@ -1,9 -1,19 +1,25 @@@ +Version 1.1-cvs Work in progress + + * Use libevent to handle I/O events and timeouts. + + * Use splay trees instead of AVL trees. + + Version 1.0.14 not released yet + + * Fixed reading configuration files that do not end with a newline. Again. + + Version 1.0.13 Apr 11 2010 + + * Allow building tinc without LZO and/or Zlib. + + * Clamp MSS of TCP packets in both directions. + + * Experimental StrictSubnets, Forwarding and DirectOnly options, + giving more control over information and packets received from/sent to other + nodes. + + * Ensure tinc never sends symbolic names for ports over the wire. + Version 1.0.12 Feb 3 2010 * Really allow fast roaming of hosts to other nodes in a switched VPN. diff --cc src/conf.c index c734a0bb,ea33e9c3..d5bc9165 --- a/src/conf.c +++ b/src/conf.c @@@ -237,8 -237,7 +237,7 @@@ static char *readline(FILE * fp, char * Parse a configuration file and put the results in the configuration tree starting at *base. */ -bool read_config_file(avl_tree_t *config_tree, const char *fname) { +int read_config_file(splay_tree_t *config_tree, const char *fname) { - int err = -2; /* Parse error */ FILE *fp; char buffer[MAX_STRING_SIZE]; char *line; diff --cc src/net.c index 23b3e7ca,a04ba005..0e582364 --- a/src/net.c +++ b/src/net.c @@@ -220,115 -334,203 +220,145 @@@ void handle_meta_connection_data(int fd } } -/* - this is where it all happens... -*/ -int main_loop(void) { - fd_set readset, writeset; - struct timeval tv; - int r, maxfd; - time_t last_ping_check, last_config_check, last_graph_dump; - event_t *event; - - last_ping_check = now; - last_config_check = now; - last_graph_dump = now; - - srand(now); - - running = true; - - while(running) { - now = time(NULL); +static void sigterm_handler(int signal, short events, void *data) { + logger(LOG_NOTICE, "Got %s signal", strsignal(signal)); + event_loopexit(NULL); +} - // tv.tv_sec = 1 + (rand() & 7); /* Approx. 5 seconds, randomized to prevent global synchronisation effects */ - tv.tv_sec = 1; - tv.tv_usec = 0; +static void sighup_handler(int signal, short events, void *data) { + logger(LOG_NOTICE, "Got %s signal", strsignal(signal)); + reload_configuration(); +} - maxfd = build_fdset(&readset, &writeset); +int reload_configuration(void) { + connection_t *c; + splay_node_t *node, *next; + char *fname; + struct stat s; + static time_t last_config_check = 0; -#ifdef HAVE_MINGW - LeaveCriticalSection(&mutex); -#endif - r = select(maxfd + 1, &readset, &writeset, NULL, &tv); -#ifdef HAVE_MINGW - EnterCriticalSection(&mutex); -#endif + /* Reread our own configuration file */ - if(r < 0) { - if(!sockwouldblock(sockerrno)) { - logger(LOG_ERR, "Error while waiting for input: %s", sockstrerror(sockerrno)); - dump_connections(); - return 1; - } - } + exit_configuration(&config_tree); + init_configuration(&config_tree); - if(r > 0) - check_network_activity(&readset, &writeset); + if(!read_server_config()) { + logger(LOG_ERR, "Unable to reread configuration file, exitting."); + event_loopexit(NULL); + return EINVAL; + } - if(do_purge) { - purge(); - do_purge = false; + /* Close connections to hosts that have a changed or deleted host config file */ + + for(node = connection_tree->head; node; node = next) { + c = node->data; + next = node->next; + + if(c->outgoing) { + free(c->outgoing->name); + if(c->outgoing->ai) + freeaddrinfo(c->outgoing->ai); + free(c->outgoing); + c->outgoing = NULL; } + + xasprintf(&fname, "%s/hosts/%s", confbase, c->name); + if(stat(fname, &s) || s.st_mtime > last_config_check) + terminate_connection(c, c->status.active); + free(fname); + } - /* Let's check if everybody is still alive */ - - if(last_ping_check + pingtimeout < now) { - check_dead_connections(); - last_ping_check = now; - - if(routing_mode == RMODE_SWITCH) - age_subnets(); - - age_past_requests(); - - /* Should we regenerate our key? */ - - if(keyexpires < now) { - avl_node_t *node; - node_t *n; + last_config_check = time(NULL); - ifdebug(STATUS) logger(LOG_INFO, "Expiring symmetric keys"); ++ /* If StrictSubnet is set, expire deleted Subnets and read new ones in */ + - for(node = node_tree->head; node; node = node->next) { - n = node->data; - if(n->inkey) { - free(n->inkey); - n->inkey = NULL; - } - } ++ if(strictsubnets) { ++ subnet_t *subnet; + - send_key_changed(broadcast, myself); - keyexpires = now + keylifetime; - } ++ for(node = subnet_tree->head; node; node = node->next) { ++ subnet = node->data; ++ subnet->expires = 1; + } + - if(sigalrm) { - avl_node_t *node; - logger(LOG_INFO, "Flushing event queue"); - expire_events(); - for(node = connection_tree->head; node; node = node->next) { - connection_t *c = node->data; - send_ping(c); ++ load_all_subnets(); ++ ++ for(node = subnet_tree->head; node; node = next) { ++ next = node->next; ++ subnet = node->data; ++ if(subnet->expires == 1) { ++ send_del_subnet(broadcast, subnet); ++ if(subnet->owner->status.reachable) ++ subnet_update(subnet->owner, subnet, false); ++ subnet_del(subnet->owner, subnet); ++ } else if(subnet->expires == -1) { ++ subnet->expires = 0; ++ } else { ++ send_add_subnet(broadcast, subnet); ++ if(subnet->owner->status.reachable) ++ subnet_update(subnet->owner, subnet, true); + } - sigalrm = false; - } - - while((event = get_expired_event())) { - event->handler(event->data); - free_event(event); + } ++ } + - if(sighup) { - connection_t *c; - avl_node_t *node, *next; - char *fname; - struct stat s; - - sighup = false; - - /* Reread our own configuration file */ - - exit_configuration(&config_tree); - init_configuration(&config_tree); - - if(!read_server_config()) { - logger(LOG_ERR, "Unable to reread configuration file, exitting."); - return 1; - } - - /* Cancel non-active outgoing connections */ - - for(node = connection_tree->head; node; node = next) { - next = node->next; - c = node->data; - - c->outgoing = NULL; - - if(c->status.connecting) { - terminate_connection(c, false); - connection_del(c); - } - } - - /* Wipe list of outgoing connections */ - - for(list_node_t *node = outgoing_list->head; node; node = node->next) { - outgoing_t *outgoing = node->data; - - if(outgoing->event) - event_del(outgoing->event); - } - - list_delete_list(outgoing_list); - - /* Close connections to hosts that have a changed or deleted host config file */ - - for(node = connection_tree->head; node; node = node->next) { - c = node->data; - - xasprintf(&fname, "%s/hosts/%s", confbase, c->name); - if(stat(fname, &s) || s.st_mtime > last_config_check) - terminate_connection(c, c->status.active); - free(fname); - } + /* Try to make outgoing connections */ + + try_outgoing_connections(); - last_config_check = now; + return 0; +} - /* If StrictSubnet is set, expire deleted Subnets and read new ones in */ +void retry(void) { + connection_t *c; + splay_node_t *node; - if(strictsubnets) { - subnet_t *subnet; + for(node = connection_tree->head; node; node = node->next) { + c = node->data; + + if(c->outgoing && !c->node) { + if(timeout_initialized(&c->outgoing->ev)) + event_del(&c->outgoing->ev); + if(c->status.connecting) + close(c->socket); + c->outgoing->timeout = 0; + do_outgoing_connection(c); + } + } +} - for(node = subnet_tree->head; node; node = node->next) { - subnet = node->data; - subnet->expires = 1; - } +/* + this is where it all happens... +*/ +int main_loop(void) { + struct event timeout_event; + struct event sighup_event; + struct event sigterm_event; + struct event sigquit_event; - load_all_subnets(); - - for(node = subnet_tree->head; node; node = next) { - next = node->next; - subnet = node->data; - if(subnet->expires == 1) { - send_del_subnet(broadcast, subnet); - if(subnet->owner->status.reachable) - subnet_update(subnet->owner, subnet, false); - subnet_del(subnet->owner, subnet); - } else if(subnet->expires == -1) { - subnet->expires = 0; - } else { - send_add_subnet(broadcast, subnet); - if(subnet->owner->status.reachable) - subnet_update(subnet->owner, subnet, true); - } - } - } + timeout_set(&timeout_event, timeout_handler, &timeout_event); + event_add(&timeout_event, &(struct timeval){pingtimeout, 0}); - /* Try to make outgoing connections */ - - try_outgoing_connections(); - } - - /* Dump graph if wanted every 60 seconds*/ +#ifdef SIGHUP + signal_set(&sighup_event, SIGHUP, sighup_handler, NULL); + signal_add(&sighup_event, NULL); +#endif +#ifdef SIGTERM + signal_set(&sigterm_event, SIGTERM, sigterm_handler, NULL); + signal_add(&sigterm_event, NULL); +#endif +#ifdef SIGQUIT + signal_set(&sigquit_event, SIGQUIT, sigterm_handler, NULL); + signal_add(&sigquit_event, NULL); +#endif - if(last_graph_dump + 60 < now) { - dump_graph(); - last_graph_dump = now; - } + if(event_loop(0) < 0) { + logger(LOG_ERR, "Error while waiting for input: %s", strerror(errno)); + return 1; } + signal_del(&sighup_event); + signal_del(&sigterm_event); + signal_del(&sigquit_event); + event_del(&timeout_event); + return 0; } diff --cc src/net.h index 634e9e75,a97759fc..cd97e301 --- a/src/net.h +++ b/src/net.h @@@ -138,12 -139,7 +138,13 @@@ extern void terminate_connection(struc extern void flush_queue(struct node_t *); extern bool read_rsa_public_key(struct connection_t *); extern void send_mtu_probe(struct node_t *); +extern void handle_device_data(int, short, void *); +extern void handle_meta_connection_data(int, short, void *); +extern void regenerate_key(); +extern void purge(void); +extern void retry(void); +extern int reload_configuration(void); + extern void load_all_subnets(); #ifndef HAVE_MINGW #define closesocket(s) close(s) diff --cc src/net_setup.c index c2ae6491,cb70926a..593d8625 --- a/src/net_setup.c +++ b/src/net_setup.c @@@ -162,9 -209,9 +162,9 @@@ void load_all_subnets(void) struct dirent *ent; char *dname; char *fname; - avl_tree_t *config_tree; + splay_tree_t *config_tree; config_t *cfg; - subnet_t *s; + subnet_t *s, *s2; node_t *n; bool result; diff --cc src/protocol_auth.c index cf6b26f2,98d5b61d..8d4dfb93 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@@ -399,9 -495,9 +399,9 @@@ static void send_everything(connection_ } } -bool ack_h(connection_t *c) { +bool ack_h(connection_t *c, char *request) { char hisport[MAX_STRING_SIZE]; - char *hisaddress, *dummy; + char *hisaddress; int weight, mtu; uint32_t options; node_t *n; diff --cc src/route.c index f18bd268,1caf738f..9897d0d7 --- a/src/route.c +++ b/src/route.c @@@ -50,10 -50,11 +50,13 @@@ static const size_t ip6_size = sizeof(s static const size_t icmp6_size = sizeof(struct icmp6_hdr); static const size_t ns_size = sizeof(struct nd_neighbor_solicit); static const size_t opt_size = sizeof(struct nd_opt_hdr); - #define max(a, b) ((a) > (b) ? (a) : (b)) + + #ifndef MAX + #define MAX(a, b) ((a) > (b) ? (a) : (b)) + #endif +static struct event age_subnets_event; + /* RFC 1071 */ static uint16_t inet_checksum(void *data, int len, uint16_t prevsum) { diff --cc src/subnet.h index df48f60e,e129a959..f22e6d58 --- a/src/subnet.h +++ b/src/subnet.h @@@ -64,6 -64,8 +64,8 @@@ typedef struct subnet_t #define MAXNETSTR 64 -extern avl_tree_t *subnet_tree; ++extern splay_tree_t *subnet_tree; + extern int subnet_compare(const struct subnet_t *, const struct subnet_t *); extern subnet_t *new_subnet(void) __attribute__ ((__malloc__)); extern void free_subnet(subnet_t *);