Merge branch 'master' into 1.1
authorGuus Sliepen <guus@tinc-vpn.org>
Mon, 9 Mar 2009 18:02:24 +0000 (19:02 +0100)
committerGuus Sliepen <guus@tinc-vpn.org>
Mon, 9 Mar 2009 18:02:24 +0000 (19:02 +0100)
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

30 files changed:
1  2 
NEWS
README
doc/tinc.texi
src/bsd/device.c
src/conf.c
src/conf.h
src/connection.c
src/cygwin/device.c
src/graph.c
src/linux/device.c
src/mingw/device.c
src/net.c
src/net.h
src/net_packet.c
src/net_setup.c
src/net_socket.c
src/node.c
src/node.h
src/process.c
src/protocol_auth.c
src/protocol_key.c
src/protocol_misc.c
src/protocol_subnet.c
src/raw_socket/device.c
src/route.c
src/solaris/device.c
src/subnet.c
src/subnet.h
src/tincd.c
src/uml_socket/device.c

diff --cc NEWS
--- 1/NEWS
--- 2/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
--- 1/README
--- 2/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 <guus@tinc-vpn.org>,
diff --cc doc/tinc.texi
Simple merge
Simple merge
diff --cc src/conf.c
Simple merge
diff --cc 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__ */
@@@ -80,11 -106,14 +80,14 @@@ void free_connection(connection_t *c) 
        if(c->hischallenge)
                free(c->hischallenge);
  
 -      if(c->outbuf)
 -              free(c->outbuf);
 -
 -      if(c->rsa_key)
 -              RSA_free(c->rsa_key);
+       if(c->config_tree)
+               exit_configuration(&c->config_tree);
 +      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;
  
@@@ -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
@@@ -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();
  }
@@@ -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();
  
@@@ -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.c
Simple merge
diff --cc src/net.h
+++ b/src/net.h
  #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;
@@@ -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;
        }
  
 -      if(n->connection)
 -              n->connection->last_ping_time = now;
 -
+       inpkt->priority = 0;
        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
@@@ -552,6 -603,11 +548,8 @@@ void close_network_connections(void) 
  
        execute_script("tinc-down", envp);
  
 -      EVP_CIPHER_CTX_cleanup(&packet_ctx);
 -
+       if(myport) free(myport);
        for(i = 0; i < 4; i++)
                free(envp[i]);
  
@@@ -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);
  
                        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
@@@ -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
@@@ -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/process.c
Simple merge
Simple merge
Simple merge
@@@ -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))
Simple merge
@@@ -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
@@@ -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"));
  
        /* 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;
  
@@@ -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
  
  /* 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();
  
  
  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
@@@ -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
@@@ -229,6 -399,14 +229,14 @@@ static void make_names(void
        }
  }
  
 -      if (pidfilename) free(pidfilename);
+ static void free_names() {
+       if (identname) free(identname);
+       if (netname) free(netname);
++      if (controlsocketname) free(controlsocketname);
+       if (logfilename) free(logfilename);
+       if (confbase) free(confbase);
+ }
  int main(int argc, char **argv)
  {
        program_name = argv[0];
@@@ -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();