Merge branch 'master' of black:tinc
authorGuus Sliepen <guus@tinc-vpn.org>
Sat, 18 Feb 2012 13:31:08 +0000 (14:31 +0100)
committerGuus Sliepen <guus@tinc-vpn.org>
Sat, 18 Feb 2012 13:31:08 +0000 (14:31 +0100)
1  2 
doc/tinc.conf.5.in
doc/tinc.texi
src/linux/device.c
src/net_setup.c

diff --combined doc/tinc.conf.5.in
@@@ -133,10 -133,7 +133,10 @@@ IPv6 listening sockets will be created
  If your computer has more than one IPv4 or IPv6 address,
  .Nm tinc
  will by default listen on all of them for incoming connections.
 -It is possible to bind only to a single address with this variable.
 +Multiple
 +.Va BindToAddress
 +variables may be specified,
 +in which case listening sockets for each specified address are made.
  
  .Pp
  This option may not work on all platforms.
@@@ -222,23 -219,23 +222,23 @@@ it can be used to change the way packet
  
  .Bl -tag -width indent
  
- .It tun Pq BSD only
+ .It tun Pq BSD and Linux
  Set type to tun.
  Depending on the platform, this can either be with or without an address family header (see below).
  
- .It tunnohead Pq BSD only
+ .It tunnohead Pq BSD
  Set type to tun without an address family header.
  Tinc will expect packets read from the virtual network device to start with an IP header.
  On some platforms IPv6 packets cannot be read from or written to the device in this mode.
  
- .It tunifhead Pq BSD only
+ .It tunifhead Pq BSD
  Set type to tun with an address family header.
  Tinc will expect packets read from the virtual network device
  to start with a four byte header containing the address family,
  followed by an IP header.
  This mode should support both IPv4 and IPv6 packets.
  
- .It tap Pq BSD only
+ .It tap Pq BSD and Linux
  Set type to tap.
  Tinc will expect packets read from the virtual network device
  to start with an Ethernet header.
diff --combined doc/tinc.texi
@@@ -759,8 -759,7 +759,8 @@@ both IPv4 and IPv6 or just IPv6 listeni
  @item BindToAddress = <@var{address}> [experimental]
  If your computer has more than one IPv4 or IPv6 address, tinc
  will by default listen on all of them for incoming connections.
 -It is possible to bind only to a single address with this variable.
 +Multiple BindToAddress variables may be specified,
 +in which case listening sockets for each specified address are made.
  
  This option may not work on all platforms.
  
@@@ -834,25 -833,25 +834,25 @@@ Also, in case tinc does not seem to cor
  it can be used to change the way packets are interpreted:
  
  @table @asis
- @item tun (BSD only)
+ @item tun (BSD and Linux)
  Set type to tun.
  Depending on the platform, this can either be with or without an address family header (see below).
  
  @cindex tunnohead
- @item tunnohead (BSD only)
+ @item tunnohead (BSD)
  Set type to tun without an address family header.
  Tinc will expect packets read from the virtual network device to start with an IP header.
  On some platforms IPv6 packets cannot be read from or written to the device in this mode.
  
  @cindex tunifhead
- @item tunifhead (BSD only)
+ @item tunifhead (BSD)
  Set type to tun with an address family header.
  Tinc will expect packets read from the virtual network device
  to start with a four byte header containing the address family,
  followed by an IP header.
  This mode should support both IPv4 and IPv6 packets.
  
- @item tap (BSD only)
+ @item tap (BSD and Linux)
  Set type to tap.
  Tinc will expect packets read from the virtual network device
  to start with an Ethernet header.
diff --combined src/linux/device.c
@@@ -45,6 -45,7 +45,7 @@@ int device_fd = -1
  static device_type_t device_type;
  char *device = NULL;
  char *iface = NULL;
+ static char *type = NULL;
  static char ifrname[IFNAMSIZ];
  static char *device_info;
  
@@@ -72,15 -73,19 +73,23 @@@ static bool setup_device(void) 
                return false;
        }
  
 +#ifdef FD_CLOEXEC
 +      fcntl(device_fd, F_SETFD, FD_CLOEXEC);
 +#endif
 +
  #ifdef HAVE_LINUX_IF_TUN_H
        /* Ok now check if this is an old ethertap or a new tun/tap thingie */
  
        memset(&ifr, 0, sizeof(ifr));
-       if(routing_mode == RMODE_ROUTER) {
+       get_config_string(lookup_config(config_tree, "DeviceType"), &type);
+       if(type && strcasecmp(type, "tun") && strcasecmp(type, "tap")) {
+               logger(LOG_ERR, "Unknown device type %s!", type);
+               return false;
+       }
+       if((type && !strcasecmp(type, "tun")) || (!type && routing_mode == RMODE_ROUTER)) {
                ifr.ifr_flags = IFF_TUN;
                device_type = DEVICE_TYPE_TUN;
                device_info = "Linux tun/tap device (tun mode)";
  static void close_device(void) {
        close(device_fd);
  
+       free(type);
        free(device);
        free(iface);
  }
diff --combined src/net_setup.c
@@@ -1,7 -1,7 +1,7 @@@
  /*
      net_setup.c -- Setup.
      Copyright (C) 1998-2005 Ivo Timmermans,
-                   2000-2011 Guus Sliepen <guus@tinc-vpn.org>
+                   2000-2012 Guus Sliepen <guus@tinc-vpn.org>
                    2006      Scott Lamb <slamb@slamb.org>
                    2010      Brandon Black <blblack@gmail.com>
  
@@@ -540,6 -540,8 +540,8 @@@ static bool setup_myself(void) 
  
        /* Open device */
  
+       devops = os_devops;
        if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
                if(!strcasecmp(type, "dummy"))
                        devops = dummy_devops;
                else if(!strcasecmp(type, "vde"))
                        devops = vde_devops;
  #endif
-               else {
-                       logger(LOG_ERR, "Unknown device type %s!", type);
-                       return false;
-               }
-       } else {
-               devops = os_devops;
        }
  
        if(!devops.setup())
  
        /* Open sockets */
  
 -      get_config_string(lookup_config(config_tree, "BindToAddress"), &address);
 +      cfg = lookup_config(config_tree, "BindToAddress");
  
 -      hint.ai_family = addressfamily;
 -      hint.ai_socktype = SOCK_STREAM;
 -      hint.ai_protocol = IPPROTO_TCP;
 -      hint.ai_flags = AI_PASSIVE;
 +      do {
 +              get_config_string(cfg, &address);
 +              if(cfg)
 +                      cfg = lookup_config_next(config_tree, cfg);
  
 -      err = getaddrinfo(address, myport, &hint, &ai);
 +              hint.ai_family = addressfamily;
 +              hint.ai_socktype = SOCK_STREAM;
 +              hint.ai_protocol = IPPROTO_TCP;
 +              hint.ai_flags = AI_PASSIVE;
  
 -      if(err || !ai) {
 -              logger(LOG_ERR, "System call `%s' failed: %s", "getaddrinfo",
 -                         gai_strerror(err));
 -              return false;
 -      }
 +              err = getaddrinfo(address, myport, &hint, &ai);
 +              free(address);
  
 -      listen_sockets = 0;
 +              if(err || !ai) {
 +                      logger(LOG_ERR, "System call `%s' failed: %s", "getaddrinfo",
 +                                 gai_strerror(err));
 +                      return false;
 +              }
  
 -      for(aip = ai; aip; aip = aip->ai_next) {
 -              listen_socket[listen_sockets].tcp =
 -                      setup_listen_socket((sockaddr_t *) aip->ai_addr);
 +              listen_sockets = 0;
  
 -              if(listen_socket[listen_sockets].tcp < 0)
 -                      continue;
 +              for(aip = ai; aip; aip = aip->ai_next) {
 +                      listen_socket[listen_sockets].tcp =
 +                              setup_listen_socket((sockaddr_t *) aip->ai_addr);
  
 -              listen_socket[listen_sockets].udp =
 -                      setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);
 +                      if(listen_socket[listen_sockets].tcp < 0)
 +                              continue;
  
 -              if(listen_socket[listen_sockets].udp < 0)
 -                      continue;
 +                      listen_socket[listen_sockets].udp =
 +                              setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);
  
 -              ifdebug(CONNECTIONS) {
 -                      hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr);
 -                      logger(LOG_NOTICE, "Listening on %s", hostname);
 -                      free(hostname);
 -              }
 +                      if(listen_socket[listen_sockets].udp < 0)
 +                              continue;
  
 -              memcpy(&listen_socket[listen_sockets].sa, aip->ai_addr, aip->ai_addrlen);
 -              listen_sockets++;
 -      }
 +                      ifdebug(CONNECTIONS) {
 +                              hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr);
 +                              logger(LOG_NOTICE, "Listening on %s", hostname);
 +                              free(hostname);
 +                      }
 +
 +                      memcpy(&listen_socket[listen_sockets].sa, aip->ai_addr, aip->ai_addrlen);
 +                      listen_sockets++;
 +              }
  
 -      freeaddrinfo(ai);
 +              freeaddrinfo(ai);
 +      } while(cfg);
  
        if(listen_sockets)
                logger(LOG_NOTICE, "Ready");