* Menno Smits
* Michael Tokarev
* Miles Nordin
+* Nick Hibma
* Nick Patavalis
* Paul Littlefield
* Robert van der Meulen
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.
@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.
/*
device.c -- Interaction BSD tun/tap device
Copyright (C) 2001-2005 Ivo Timmermans,
- 2001-2011 Guus Sliepen <guus@tinc-vpn.org>
+ 2001-2012 Guus Sliepen <guus@tinc-vpn.org>
2009 Grzegorz Dymarek <gregd72002@googlemail.com>
This program is free software; you can redistribute it and/or modify
return false;
}
+#ifdef FD_CLOEXEC
+ fcntl(device_fd, F_SETFD, FD_CLOEXEC);
+#endif
+
switch(device_type) {
default:
device_type = DEVICE_TYPE_TUN;
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 */
/* 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");
/*
net_socket.c -- Handle various kinds of sockets.
Copyright (C) 1998-2005 Ivo Timmermans,
- 2000-2010 Guus Sliepen <guus@tinc-vpn.org>
+ 2000-2012 Guus Sliepen <guus@tinc-vpn.org>
2006 Scott Lamb <slamb@slamb.org>
2009 Florian Forster <octo@verplant.org>
return -1;
}
+#ifdef FD_CLOEXEC
+ fcntl(nfd, F_SETFD, FD_CLOEXEC);
+#endif
+
/* Optimize TCP settings */
option = 1;
return -1;
}
+#ifdef FD_CLOEXEC
+ fcntl(nfd, F_SETFD, FD_CLOEXEC);
+#endif
+
#ifdef O_NONBLOCK
{
int flags = fcntl(nfd, F_GETFL);
c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
+#ifdef FD_CLOEXEC
+ fcntl(c->socket, F_SETFD, FD_CLOEXEC);
+#endif
+
if(c->socket == -1) {
ifdebug(CONNECTIONS) logger(LOG_ERR, "Creating socket for %s failed: %s", c->hostname, sockstrerror(sockerrno));
goto begin;
/*
device.c -- raw socket
Copyright (C) 2002-2005 Ivo Timmermans,
- 2002-2011 Guus Sliepen <guus@tinc-vpn.org>
+ 2002-2012 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
return false;
}
+#ifdef FD_CLOEXEC
+ fcntl(device_fd, F_SETFD, FD_CLOEXEC);
+#endif
+
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ);
if(ioctl(device_fd, SIOCGIFINDEX, &ifr)) {
/*
device.c -- Interaction with Solaris tun device
Copyright (C) 2001-2005 Ivo Timmermans,
- 2001-2011 Guus Sliepen <guus@tinc-vpn.org>
+ 2001-2012 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
return false;
}
+#ifdef FD_CLOEXEC
+ fcntl(device_fd, F_SETFD, FD_CLOEXEC);
+#endif
+
ppa = 0;
ptr = device;
return false;
}
+#ifdef FD_CLOEXEC
+ fcntl(ip_fd, F_SETFD, FD_CLOEXEC);
+#endif
+
/* Assign a new PPA and get its unit number. */
if((ppa = ioctl(device_fd, TUNNEWPPA, ppa)) < 0) {
logger(LOG_ERR, "Can't assign new interface: %s", strerror(errno));
return false;
}
+#ifdef FD_CLOEXEC
+ fcntl(if_fd, F_SETFD, FD_CLOEXEC);
+#endif
+
if(ioctl(if_fd, I_PUSH, "ip") < 0) {
logger(LOG_ERR, "Can't push IP module: %s", strerror(errno));
return false;
/*
device.c -- UML network socket
Copyright (C) 2002-2005 Ivo Timmermans,
- 2002-2011 Guus Sliepen <guus@tinc-vpn.org>
+ 2002-2012 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
return false;
}
+#ifdef FD_CLOEXEC
+ fcntl(write_fd, F_SETFD, FD_CLOEXEC);
+#endif
+
setsockopt(write_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);
if(fcntl(write_fd, F_SETFL, O_NONBLOCK) < 0) {
return false;
}
+#ifdef FD_CLOEXEC
+ fcntl(data_fd, F_SETFD, FD_CLOEXEC);
+#endif
+
setsockopt(data_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);
if(fcntl(data_fd, F_SETFL, O_NONBLOCK) < 0) {
return false;
}
+#ifdef FD_CLOEXEC
+ fcntl(device_fd, F_SETFD, FD_CLOEXEC);
+#endif
+
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);
if(fcntl(listen_fd, F_SETFL, O_NONBLOCK) < 0) {
return false;
}
+#ifdef FD_CLOEXEC
+ fcntl(request_fd, F_SETFD, FD_CLOEXEC);
+#endif
+
if(fcntl(listen_fd, F_SETFL, O_NONBLOCK) < 0) {
logger(LOG_ERR, "System call `%s' failed: %s", "fcntl", strerror(errno));
running = false;
/*
device.c -- VDE plug
- Copyright (C) 2011 Guus Sliepen <guus@tinc-vpn.org>
+ Copyright (C) 2012 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
device_fd = plug.vde_datafd(conn);
+#ifdef FD_CLOEXEC
+ fcntl(device_fd, F_SETFD, FD_CLOEXEC);
+#endif
+
logger(LOG_INFO, "%s is a %s", device, device_info);
if(routing_mode == RMODE_ROUTER)