From: Guus Sliepen Date: Mon, 9 Mar 2009 18:02:24 +0000 (+0100) Subject: Merge branch 'master' into 1.1 X-Git-Tag: release-1.1pre1~121 X-Git-Url: https://tinc-vpn.org/git/browse?a=commitdiff_plain;h=08aabbf9317806bc50a9a6693ca866c8936ce26b;p=tinc Merge branch 'master' into 1.1 Conflicts: NEWS README doc/tinc.conf.5.in doc/tinc.texi po/nl.po src/conf.c src/connection.c src/event.c src/graph.c src/net.c src/net_packet.c src/net_socket.c src/node.c src/node.h src/openssl/rsagen.h src/protocol_auth.c src/protocol_key.c src/protocol_misc.c src/subnet.c src/subnet.h src/tincd.c --- 08aabbf9317806bc50a9a6693ca866c8936ce26b diff --cc NEWS index 2ad93e5a,736f5e69..a993df5c --- a/NEWS +++ b/NEWS @@@ -1,9 -1,20 +1,26 @@@ +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.9 Dec 26 2008 + + * Fixed tinc as a service under Windows 2003. + + * Fixed reading configuration files that do not end with a newline. + + * Fixed crashes in situations where hostnames could not be resolved or hosts + would disconnect at the same time as session keys were exchanged. + + * Improved default settings of tun and tap devices on BSD platforms. + + * Make IPv6 sockets bind only to IPv6 on Linux. + + * Enable path MTU discovery by default. + + * Fixed a memory leak that occured when connections were closed. + Version 1.0.8 May 16 2007 * Fixed some memory and resource leaks. diff --cc README index b7ba7b6f,23b24581..c324e2b7 --- a/README +++ b/README @@@ -1,7 -1,7 +1,7 @@@ -This is the README file for tinc version 1.0.9. Installation +This is the README file for tinc version 1.1-cvs. Installation instructions may be found in the INSTALL file. - tinc is Copyright (C) 1998-2007 by: -tinc is Copyright (C) 1998-2008 by: ++tinc is Copyright (C) 1998-2009 by: Ivo Timmermans, Guus Sliepen , diff --cc src/conf.h index ee20c29c,d1eae978..dfa11231 --- a/src/conf.h +++ b/src/conf.h @@@ -56,9 -56,10 +56,10 @@@ extern bool get_config_string(const con extern bool get_config_address(const config_t *, struct addrinfo **); extern bool get_config_subnet(const config_t *, struct subnet_t **); -extern int read_config_file(avl_tree_t *, const char *); +extern int read_config_file(splay_tree_t *, const char *); extern bool read_server_config(void); -extern FILE *ask_and_open(const char *, const char *); +extern FILE *ask_and_open(const char *, const char *, const char *); extern bool is_safe_path(const char *); + extern bool disable_old_keys(FILE *); #endif /* __TINC_CONF_H__ */ diff --cc src/connection.c index 84d2ac4d,9fd4002b..230ec4ed --- a/src/connection.c +++ b/src/connection.c @@@ -80,11 -106,14 +80,14 @@@ void free_connection(connection_t *c) if(c->hischallenge) free(c->hischallenge); + if(c->config_tree) + exit_configuration(&c->config_tree); + - if(c->outbuf) - free(c->outbuf); - - if(c->rsa_key) - RSA_free(c->rsa_key); + if(c->buffer) + bufferevent_free(c->buffer); + + if(event_initialized(&c->inevent)) + event_del(&c->inevent); free(c); } @@@ -107,19 -139,20 +110,19 @@@ int dump_connections(struct evbuffer *o cp(); - logger(LOG_DEBUG, _("Connections:")); - for(node = connection_tree->head; node; node = node->next) { c = node->data; - logger(LOG_DEBUG, _(" %s at %s options %lx socket %d status %04x outbuf %d/%d/%d"), - c->name, c->hostname, c->options, c->socket, c->status.value, - c->outbufsize, c->outbufstart, c->outbuflen); + if(evbuffer_add_printf(out, - _(" %s at %s options %lx socket %d status %04x\n"), - c->name, c->hostname, c->options, c->socket, - c->status.value) == -1) ++ _(" %s at %s options %lx socket %d status %04x\n"), ++ c->name, c->hostname, c->options, c->socket, ++ c->status.value) == -1) + return errno; } - logger(LOG_DEBUG, _("End of connections.")); + return 0; } -bool read_connection_config(connection_t *c) -{ +bool read_connection_config(connection_t *c) { char *fname; int x; diff --cc src/cygwin/device.c index 6b0dbea4,c6e6f353..97b2a38d --- a/src/cygwin/device.c +++ b/src/cygwin/device.c @@@ -225,10 -227,14 +225,13 @@@ void close_device(void) CloseHandle(device_handle); kill(reader_pid, SIGKILL); + + free(device); + free(iface); } -bool read_packet(vpn_packet_t *packet) -{ - int lenin; +bool read_packet(vpn_packet_t *packet) { + int inlen; cp(); diff --cc src/graph.c index 02e8494f,e0c48d42..8e801b3d --- a/src/graph.c +++ b/src/graph.c @@@ -431,19 -366,19 +431,20 @@@ int dump_graph(struct evbuffer *out) /* now dump all edges */ for(node = edge_weight_tree->head; node; node = node->next) { e = node->data; - fprintf(file, " %s -> %s;\n", e->from->name, e->to->name); + if(evbuffer_add_printf(out, " %s -> %s;\n", + e->from->name, e->to->name) == -1) + return errno; } - fprintf(file, "}\n"); - - if(filename[0] == '|') { - pclose(file); - } else { - fclose(file); -#ifdef HAVE_MINGW - unlink(filename); -#endif - rename(tmpname, filename); - free(tmpname); - } + if(evbuffer_add_printf(out, "}\n") == -1) + return errno; + + return 0; +} + +void graph(void) { ++ subnet_cache_flush(); + sssp_dijkstra(); + check_reachability(); + mst_kruskal(); } diff --cc src/linux/device.c index 5be210a5,2e447556..b02e88e7 --- a/src/linux/device.c +++ b/src/linux/device.c @@@ -115,10 -122,14 +120,13 @@@ void close_device(void) cp(); close(device_fd); + + free(device); + free(iface); } -bool read_packet(vpn_packet_t *packet) -{ - int lenin; +bool read_packet(vpn_packet_t *packet) { + int inlen; cp(); diff --cc src/mingw/device.c index d6dde92d,e025cf78..915256f5 --- a/src/mingw/device.c +++ b/src/mingw/device.c @@@ -311,9 -313,13 +311,12 @@@ void close_device(void) cp(); CloseHandle(device_handle); + + free(device); + free(iface); } -bool read_packet(vpn_packet_t *packet) -{ +bool read_packet(vpn_packet_t *packet) { unsigned char bufno; cp(); diff --cc src/net.h index 1f7b4576,e07e6465..d320c15a --- a/src/net.h +++ b/src/net.h @@@ -33,13 -33,11 +33,11 @@@ #define MTU 1518 /* 1500 bytes payload + 14 bytes ethernet header + 4 bytes VLAN tag */ #endif -#define MAXSIZE (MTU + 4 + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE + MTU/64 + 20) /* MTU + seqno + padding + HMAC + compressor overhead */ +#define MAXSIZE (MTU + 4 + CIPHER_MAX_BLOCK_SIZE + DIGEST_MAX_SIZE + MTU/64 + 20) /* MTU + seqno + padding + HMAC + compressor overhead */ #define MAXBUFSIZE ((MAXSIZE > 2048 ? MAXSIZE : 2048) + 128) /* Enough room for a request with a MAXSIZEd packet or a 8192 bits RSA key */ -#define MAXSOCKETS 128 /* Overkill... */ +#define MAXSOCKETS 8 /* Probably overkill... */ - #define MAXQUEUELENGTH 8 /* Maximum number of packats in a single queue */ - typedef struct mac_t { uint8_t x[6]; } mac_t; @@@ -87,20 -85,7 +85,9 @@@ typedef struct vpn_packet_t uint8_t data[MAXSIZE]; } vpn_packet_t; - typedef struct queue_element_t { - void *packet; - struct queue_element_t *prev; - struct queue_element_t *next; - } queue_element_t; - - typedef struct packet_queue_t { - queue_element_t *head; - queue_element_t *tail; - } packet_queue_t; - typedef struct listen_socket_t { + struct event ev_tcp; + struct event ev_udp; int tcp; int udp; sockaddr_t sa; @@@ -114,9 -100,10 +102,11 @@@ typedef struct outgoing_t struct config_t *cfg; struct addrinfo *ai; struct addrinfo *aip; + struct event ev; } outgoing_t; + extern list_t *outgoing_list; + extern int maxoutbufsize; extern int seconds_till_retry; extern int addressfamily; diff --cc src/net_packet.c index 754e6699,544bbde7..7d640cb6 --- a/src/net_packet.c +++ b/src/net_packet.c @@@ -81,8 -88,9 +81,9 @@@ static void send_mtu_probe_handler(int len = 64; memset(packet.data, 0, 14); - RAND_pseudo_bytes(packet.data + 14, len - 14); + randomize(packet.data + 14, len - 14); packet.len = len; + packet.priority = 0; ifdebug(TRAFFIC) logger(LOG_INFO, _("Sending MTU probe length %d to %s (%s)"), len, n->name, n->hostname); @@@ -244,6 -265,11 +245,8 @@@ static void receive_udppacket(node_t *n inpkt = outpkt; } + inpkt->priority = 0; + - if(n->connection) - n->connection->last_ping_time = now; - if(!inpkt->data[12] && !inpkt->data[13]) mtu_probe_h(n, inpkt); else @@@ -268,8 -300,7 +275,7 @@@ static void send_udppacket(node_t *n, v int nextpkt = 0; vpn_packet_t *outpkt; int origlen; - int outlen, outpad; + size_t outlen; - vpn_packet_t *copy; static int priority = 0; int origpriority; int sock; @@@ -438,21 -476,8 +445,8 @@@ void broadcast_packet(const node_t *fro } } - void flush_queue(node_t *n) { - list_node_t *node, *next; - - cp(); - - ifdebug(TRAFFIC) logger(LOG_INFO, _("Flushing queue for %s (%s)"), n->name, n->hostname); - - for(node = n->queue->head; node; node = next) { - next = node->next; - send_udppacket(n, node->data); - list_delete_node(n->queue, node); - } - } - - void handle_incoming_vpn_data(int sock, short events, void *data) { -void handle_incoming_vpn_data(int sock) ++void handle_incoming_vpn_data(int sock, short events, void *data) + { vpn_packet_t pkt; char *hostname; sockaddr_t from; diff --cc src/net_setup.c index 033bf376,3eb56441..43adbc84 --- a/src/net_setup.c +++ b/src/net_setup.c @@@ -552,6 -603,11 +548,8 @@@ void close_network_connections(void) execute_script("tinc-down", envp); + if(myport) free(myport); + - EVP_CIPHER_CTX_cleanup(&packet_ctx); - for(i = 0; i < 4; i++) free(envp[i]); diff --cc src/net_socket.c index 808e1c66,82213e91..43b8ada2 --- a/src/net_socket.c +++ b/src/net_socket.c @@@ -484,15 -451,41 +475,39 @@@ void handle_new_meta_connection(int soc c->allow_request = ID; send_id(c); - - return true; } - void try_outgoing_connections(void) { + void free_outgoing(outgoing_t *outgoing) { + if(outgoing->ai) + freeaddrinfo(outgoing->ai); + + if(outgoing->name) + free(outgoing->name); + + free(outgoing); + } + + void try_outgoing_connections(void) + { static config_t *cfg = NULL; char *name; outgoing_t *outgoing; - + connection_t *c; - avl_node_t *node; ++ splay_node_t *node; + cp(); + if(outgoing_list) { + for(node = connection_tree->head; node; node = node->next) { + c = node->data; + c->outgoing = NULL; + } + + list_delete_list(outgoing_list); + } + + outgoing_list = list_alloc((list_action_t)free_outgoing); + for(cfg = lookup_config(config_tree, "ConnectTo"); cfg; cfg = lookup_config_next(config_tree, cfg)) { get_config_string(cfg, &name); @@@ -504,8 -497,9 +519,9 @@@ continue; } - outgoing = xmalloc_and_zero(sizeof(*outgoing)); + outgoing = xmalloc_and_zero(sizeof *outgoing); outgoing->name = name; + list_insert_tail(outgoing_list, outgoing); setup_outgoing_connection(outgoing); } } diff --cc src/node.c index a71a8735,4ee9ce72..80d28d64 --- a/src/node.c +++ b/src/node.c @@@ -73,19 -78,20 +73,15 @@@ node_t *new_node(void) n->subnet_tree = new_subnet_tree(); n->edge_tree = new_edge_tree(); - n->queue = list_alloc((list_action_t) free); - EVP_CIPHER_CTX_init(&n->packet_ctx); n->mtu = MTU; n->maxmtu = MTU; return n; } -void free_node(node_t *n) -{ +void free_node(node_t *n) { cp(); - if(n->queue) - list_delete_list(n->queue); - if(n->key) - free(n->key); -- if(n->subnet_tree) free_subnet_tree(n->subnet_tree); diff --cc src/node.h index 7b777288,55a1b530..f4fc88bb --- a/src/node.h +++ b/src/node.h @@@ -60,9 -61,6 +60,7 @@@ typedef struct node_t int compression; /* Compressionlevel, 0 = no compression */ - list_t *queue; /* Queue for packets awaiting to be encrypted */ - + int distance; struct node_t *nexthop; /* nearest node from us to him */ struct node_t *via; /* next hop for UDP packets */ diff --cc src/protocol_misc.c index 95a240e1,8f56aee5..02e38598 --- a/src/protocol_misc.c +++ b/src/protocol_misc.c @@@ -151,9 -155,10 +151,10 @@@ bool send_tcppacket(connection_t *c, vp { cp(); - /* If there already is a lot of data in the outbuf buffer, discard this packet. */ + /* If there already is a lot of data in the outbuf buffer, discard this packet. + We use a very simple Random Early Drop algorithm. */ - if(c->buffer->output->off > maxoutbufsize) - if(2.0 * c->outbuflen / (double)maxoutbufsize - 1 > drand48()) ++ if(2.0 * c->buffer->output->off / (double)maxoutbufsize - 1 > drand48()) return true; if(!send_request(c, "%d %hd", PACKET, packet->len)) diff --cc src/raw_socket/device.c index 3694cb12,f2a135d3..412ba41b --- a/src/raw_socket/device.c +++ b/src/raw_socket/device.c @@@ -88,10 -90,14 +88,13 @@@ void close_device(void) cp(); close(device_fd); + + free(device); + free(iface); } -bool read_packet(vpn_packet_t *packet) -{ - int lenin; +bool read_packet(vpn_packet_t *packet) { + int inlen; cp(); diff --cc src/route.c index f3622f59,e79fae51..8acabb1b --- a/src/route.c +++ b/src/route.c @@@ -575,10 -574,12 +589,12 @@@ static void route_neighborsol(node_t *s /* Generate checksum */ - checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0); + checksum = inet_checksum(&pseudo, sizeof pseudo, ~0); checksum = inet_checksum(&ns, ns_size, checksum); - checksum = inet_checksum(&opt, opt_size, checksum); - checksum = inet_checksum(packet->data + ether_size + ip6_size + ns_size + opt_size, ETH_ALEN, checksum); + if(has_opt) { + checksum = inet_checksum(&opt, opt_size, checksum); + checksum = inet_checksum(packet->data + ether_size + ip6_size + ns_size + opt_size, ETH_ALEN, checksum); + } if(checksum) { ifdebug(TRAFFIC) logger(LOG_WARNING, _("Cannot route packet: checksum error for neighbor solicitation request")); @@@ -632,10 -637,12 +652,12 @@@ /* Generate checksum */ - checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0); + checksum = inet_checksum(&pseudo, sizeof pseudo, ~0); checksum = inet_checksum(&ns, ns_size, checksum); - checksum = inet_checksum(&opt, opt_size, checksum); - checksum = inet_checksum(packet->data + ether_size + ip6_size + ns_size + opt_size, ETH_ALEN, checksum); + if(has_opt) { + checksum = inet_checksum(&opt, opt_size, checksum); + checksum = inet_checksum(packet->data + ether_size + ip6_size + ns_size + opt_size, ETH_ALEN, checksum); + } ns.nd_ns_hdr.icmp6_cksum = checksum; diff --cc src/solaris/device.c index 25f66f38,748b5459..295a2f88 --- a/src/solaris/device.c +++ b/src/solaris/device.c @@@ -111,10 -114,14 +112,13 @@@ void close_device(void) cp(); close(device_fd); + + free(device); + free(iface); } -bool read_packet(vpn_packet_t *packet) -{ - int lenin; +bool read_packet(vpn_packet_t *packet) { + int inlen; cp(); diff --cc src/subnet.c index 446d38b1,9547829f..75fe31f8 --- a/src/subnet.c +++ b/src/subnet.c @@@ -35,16 -35,38 +35,38 @@@ /* lists type of subnet */ -avl_tree_t *subnet_tree; +splay_tree_t *subnet_tree; + /* Subnet lookup cache */ + + static ipv4_t cache_ipv4_address[2]; + static subnet_t *cache_ipv4_subnet[2]; + static bool cache_ipv4_valid[2]; + static int cache_ipv4_slot; + + static ipv6_t cache_ipv6_address[2]; + static subnet_t *cache_ipv6_subnet[2]; + static bool cache_ipv6_valid[2]; + static int cache_ipv6_slot; + + void subnet_cache_flush() { + cache_ipv4_valid[0] = cache_ipv4_valid[1] = false; + cache_ipv6_valid[0] = cache_ipv6_valid[1] = false; + } + /* Subnet comparison */ static int subnet_compare_mac(const subnet_t *a, const subnet_t *b) { int result; - result = memcmp(&a->net.mac.address, &b->net.mac.address, sizeof(mac_t)); + result = memcmp(&a->net.mac.address, &b->net.mac.address, sizeof a->net.mac.address); + if(result) + return result; + + result = a->weight - b->weight; + if(result || !a->owner || !b->owner) return result; @@@ -117,7 -149,9 +149,9 @@@ void init_subnets(void { cp(); - subnet_tree = avl_alloc_tree((avl_compare_t) subnet_compare, (avl_action_t) free_subnet); + subnet_tree = splay_alloc_tree((splay_compare_t) subnet_compare, (splay_action_t) free_subnet); + + subnet_cache_flush(); } void exit_subnets(void) @@@ -165,16 -199,20 +199,20 @@@ void subnet_add(node_t *n, subnet_t *su subnet->owner = n; - avl_insert(subnet_tree, subnet); - avl_insert(n->subnet_tree, subnet); + splay_insert(subnet_tree, subnet); + splay_insert(n->subnet_tree, subnet); + + subnet_cache_flush(); } void subnet_del(node_t *n, subnet_t *subnet) { cp(); - avl_delete(n->subnet_tree, subnet); - avl_delete(subnet_tree, subnet); + splay_delete(n->subnet_tree, subnet); + splay_delete(subnet_tree, subnet); + + subnet_cache_flush(); } /* Ascii representation of subnets */ @@@ -332,7 -381,9 +381,9 @@@ subnet_t *lookup_subnet_mac(const mac_ subnet_t *lookup_subnet_ipv4(const ipv4_t *address) { - subnet_t *p, subnet = {0}; + subnet_t *p, *r = NULL, subnet = {0}; - avl_node_t *n; ++ splay_node_t *n; + int i; cp(); @@@ -372,7 -428,9 +428,9 @@@ subnet_t *lookup_subnet_ipv6(const ipv6_t *address) { - subnet_t *p, subnet = {0}; + subnet_t *p, *r = NULL, subnet = {0}; - avl_node_t *n; ++ splay_node_t *n; + int i; cp(); diff --cc src/subnet.h index 48eec520,3efed1be..22af0d3a --- a/src/subnet.h +++ b/src/subnet.h @@@ -81,6 -82,7 +82,7 @@@ extern subnet_t *lookup_subnet(const st extern subnet_t *lookup_subnet_mac(const mac_t *); extern subnet_t *lookup_subnet_ipv4(const ipv4_t *); extern subnet_t *lookup_subnet_ipv6(const ipv6_t *); -extern void dump_subnets(void); +extern int dump_subnets(struct evbuffer *); + extern void subnet_cache_flush(void); #endif /* __TINC_SUBNET_H__ */ diff --cc src/tincd.c index 3e3b7b0d,f909d9a0..ac0cbc6c --- a/src/tincd.c +++ b/src/tincd.c @@@ -229,6 -399,14 +229,14 @@@ static void make_names(void } } + static void free_names() { + if (identname) free(identname); + if (netname) free(netname); - if (pidfilename) free(pidfilename); ++ if (controlsocketname) free(controlsocketname); + if (logfilename) free(logfilename); + if (confbase) free(confbase); + } + int main(int argc, char **argv) { program_name = argv[0]; diff --cc src/uml_socket/device.c index 27fdd337,62a6f2eb..30194d9c --- a/src/uml_socket/device.c +++ b/src/uml_socket/device.c @@@ -169,10 -171,14 +169,13 @@@ void close_device(void) close(write_fd); unlink(device); + + free(device); + if(iface) free(iface); } -bool read_packet(vpn_packet_t *packet) -{ - int lenin; +bool read_packet(vpn_packet_t *packet) { + int inlen; cp();