cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts="-c -d -D -K -n -o -L -R -U --config --no-detach --debug --net --option --mlock --logfile --pidfile --chroot --user --help --version"
- confvars="Address AddressFamily BindToAddress BindToInterface Broadcast Cipher ClampMSS Compression ConnectTo DecrementTTL Device DeviceType Digest DirectOnly ECDSAPrivateKeyFile ECDSAPublicKey ECDSAPublicKeyFile ExperimentalProtocol Forwarding GraphDumpFile Hostnames IffOneQueue IndirectData Interface KeyExpire LocalDiscovery MACExpire MACLength MaxOutputBufferSize MaxTimeout Mode Name PMTU PMTUDiscovery PingInterval PingTimeout Port PriorityInheritance PrivateKeyFile ProcessPriority Proxy PublicKeyFile ReplayWindow StrictSubnets Subnet TCPOnly TunnelServer UDPRcvBuf UDPSndBuf VDEGroup VDEPort Weight"
+ confvars="Address AddressFamily BindToAddress BindToInterface Broadcast Cipher ClampMSS Compression ConnectTo DecrementTTL Device DeviceType Digest DirectOnly ECDSAPrivateKeyFile ECDSAPublicKey ECDSAPublicKeyFile ExperimentalProtocol Forwarding GraphDumpFile Hostnames IffOneQueue IndirectData Interface KeyExpire ListenAddress LocalDiscovery MACExpire MACLength MaxOutputBufferSize MaxTimeout Mode Name PMTU PMTUDiscovery PingInterval PingTimeout Port PriorityInheritance PrivateKeyFile ProcessPriority Proxy PublicKeyFile ReplayWindow StrictSubnets Subnet TCPOnly TunnelServer UDPRcvBuf UDPSndBuf VDEGroup VDEPort Weight"
commands="add connect debug del disconnect dump edit export export-all generate-ecdsa-keys generate-keys generate-rsa-keys get help import info init invite join log pcap pid purge reload restart retry set start stop top version"
case ${prev} in
Higher values increase redundancy but also increase meta data overhead.
When using this option, a good value is 3.
.It Va BindToAddress Li = Ar address Op Ar port
-If your computer has more than one IPv4 or IPv6 address,
-.Nm tinc
-will by default listen on all of them for incoming connections.
-Multiple
+This is the same as
+.Va ListenAddress ,
+however the address given with the
.Va BindToAddress
-variables may be specified,
-in which case listening sockets for each specified address are made.
-.Pp
-If no
-.Ar port
-is specified, the socket will be bound to the port specified by the
-.Va Port
-option, or to port 655 if neither is given.
-To only bind to a specific port but not to a specific address, use
-.Li *
-for the
-.Ar address .
+option will also be used for outgoing connections. This is useful if your
+computer has more than one IPv4 or IPv6 address, and you want
+.Nm tinc
+to only use a specific one for outgoing packets.
.It Va BindToInterface Li = Ar interface Bq experimental
If your computer has more than one network interface,
.Nm tinc
This option controls the period the encryption keys used to encrypt the data are valid.
It is common practice to change keys at regular intervals to make it even harder for crackers,
even though it is thought to be nearly impossible to crack a single key.
+.It Va ListenAddress Li = Ar address Op Ar port
+If your computer has more than one IPv4 or IPv6 address,
+.Nm tinc
+will by default listen on all of them for incoming connections.
+This option can be used to restrict which addresses tinc listens on.
+Multiple
+.Va ListenAddress
+variables may be specified,
+in which case listening sockets for each specified address are made.
+.Pp
+If no
+.Ar port
+is specified, the socket will listen on the port specified by the
+.Va Port
+option, or to port 655 if neither is given.
+To only listen on a specific port but not on a specific address, use
+.Li *
+for the
+.Ar address .
.It Va LocalDiscovery Li = yes | no Pq no
When enabled,
.Nm tinc
.It Va ReplayWindow Li = Ar bytes Pq 16
This is the size of the replay tracking window for each remote node, in bytes.
The window is a bitfield which tracks 1 packet per bit, so for example
-the default setting of 16 will track up to 128 packets in the window. In high
+the default setting of 16 will track up to 128 packets in the window. In high
bandwidth scenarios, setting this to a higher value can reduce packet loss from
the interaction of replay tracking with underlying real packet loss and/or
-reordering. Setting this to zero will disable replay tracking completely and
+reordering. Setting this to zero will disable replay tracking completely and
pass all traffic, but leaves tinc vulnerable to replay-based attacks on your
traffic.
.It Va StrictSubnets Li = yes | no Po no Pc Bq experimental
MAC addresses are notated like 0:1a:2b:3c:4d:5e.
.Pp
A Subnet can be given a weight to indicate its priority over identical Subnets
-owned by different nodes. The default weight is 10. Lower values indicate
+owned by different nodes. The default weight is 10. Lower values indicate
higher priority. Packets will be sent to the node with the highest priority,
unless that node is not reachable, in which case the node with the next highest
priority will be tried, and so on.
@cindex BindToAddress
@item BindToAddress = <@var{address}> [<@var{port}>]
-If your computer has more than one IPv4 or IPv6 address, tinc
-will by default listen on all of them for incoming connections.
-Multiple BindToAddress variables may be specified,
-in which case listening sockets for each specified address are made.
-
-If no @var{port} is specified, the socket will be bound to the port specified by the Port option,
-or to port 655 if neither is given.
-To only bind to a specific port but not to a specific address, use "*" for the @var{address}.
+This is the same as ListenAddress, however the address given with the BindToAddress option
+will also be used for outgoing connections.
+This is useful if your computer has more than one IPv4 or IPv6 address,
+and you want tinc to only use a specific one for outgoing packets.
@cindex BindToInterface
@item BindToInterface = <@var{interface}> [experimental]
Under Windows, this variable is used to select which network interface will be used.
If you specified a Device, this variable is almost always already correctly set.
+@cindex ListenAddress
+@item ListenAddress = <@var{address}> [<@var{port}>]
+If your computer has more than one IPv4 or IPv6 address, tinc
+will by default listen on all of them for incoming connections.
+This option can be used to restrict which addresses tinc listens on.
+Multiple ListenAddress variables may be specified,
+in which case listening sockets for each specified address are made.
+
+If no @var{port} is specified, the socket will listen on the port specified by the Port option,
+or to port 655 if neither is given.
+To only listen on a specific port but not to a specific address, use "*" for the @var{address}.
+
@cindex LocalDiscovery
@item LocalDiscovery = <yes | no> (no)
When enabled, tinc will try to detect peers that are on the same local network.
io_t tcp;
io_t udp;
sockaddr_t sa;
+ bool bindto;
} listen_socket_t;
#include "conf.h"
return true;
}
+/*
+ Add listening sockets.
+*/
+static bool add_listen_address(char *address, bool bindto) {
+ char *port = myport;
+
+ if(address) {
+ char *space = strchr(address, ' ');
+ if(space) {
+ *space++ = 0;
+ port = space;
+ }
+
+ if(!strcmp(address, "*"))
+ *address = 0;
+ }
+
+ struct addrinfo *ai, hint = {0};
+ hint.ai_family = addressfamily;
+ hint.ai_socktype = SOCK_STREAM;
+ hint.ai_protocol = IPPROTO_TCP;
+ hint.ai_flags = AI_PASSIVE;
+
+ int err = getaddrinfo(address && *address ? address : NULL, port, &hint, &ai);
+ free(address);
+
+ if(err || !ai) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "getaddrinfo", err == EAI_SYSTEM ? strerror(err) : gai_strerror(err));
+ return false;
+ }
+
+ for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) {
+ // Ignore duplicate addresses
+ bool found = false;
+
+ for(int i = 0; i < listen_sockets; i++)
+ if(!memcmp(&listen_socket[i].sa, aip->ai_addr, aip->ai_addrlen)) {
+ found = true;
+ break;
+ }
+
+ if(found)
+ continue;
+
+ if(listen_sockets >= MAXSOCKETS) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Too many listening sockets");
+ return false;
+ }
+
+ int tcp_fd = setup_listen_socket((sockaddr_t *) aip->ai_addr);
+
+ if(tcp_fd < 0)
+ continue;
+
+ int udp_fd = setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);
+
+ if(tcp_fd < 0) {
+ close(tcp_fd);
+ continue;
+ }
+
+ io_add(&listen_socket[listen_sockets].tcp, handle_new_meta_connection, &listen_socket[listen_sockets], tcp_fd, IO_READ);
+ io_add(&listen_socket[listen_sockets].udp, handle_incoming_vpn_data, &listen_socket[listen_sockets], udp_fd, IO_READ);
+
+ if(debug_level >= DEBUG_CONNECTIONS) {
+ char *hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr);
+ logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Listening on %s", hostname);
+ free(hostname);
+ }
+
+ listen_socket[listen_sockets].bindto = bindto;
+ memcpy(&listen_socket[listen_sockets].sa, aip->ai_addr, aip->ai_addrlen);
+ listen_sockets++;
+ }
+
+ freeaddrinfo(ai);
+ return true;
+}
+
/*
Configure node_t myself and set up the local sockets (listen only)
*/
}
} else {
listen_sockets = 0;
- config_t *cfg = lookup_config(config_tree, "BindToAddress");
+ int cfgs = 0;
- do {
+ for(config_t *cfg = lookup_config(config_tree, "BindToAddress"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
+ cfgs++;
get_config_string(cfg, &address);
- if(cfg)
- cfg = lookup_config_next(config_tree, cfg);
-
- char *port = myport;
-
- if(address) {
- char *space = strchr(address, ' ');
- if(space) {
- *space++ = 0;
- port = space;
- }
-
- if(!strcmp(address, "*"))
- *address = 0;
- }
-
- struct addrinfo *ai, hint = {0};
- hint.ai_family = addressfamily;
- hint.ai_socktype = SOCK_STREAM;
- hint.ai_protocol = IPPROTO_TCP;
- hint.ai_flags = AI_PASSIVE;
-
- int err = getaddrinfo(address && *address ? address : NULL, port, &hint, &ai);
- free(address);
-
- if(err || !ai) {
- logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "getaddrinfo", err == EAI_SYSTEM ? strerror(err) : gai_strerror(err));
+ if(!add_listen_address(address, true))
return false;
- }
-
- for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) {
- if(listen_sockets >= MAXSOCKETS) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Too many listening sockets");
- return false;
- }
-
- int tcp_fd = setup_listen_socket((sockaddr_t *) aip->ai_addr);
-
- if(tcp_fd < 0)
- continue;
-
- int udp_fd = setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);
-
- if(tcp_fd < 0) {
- close(tcp_fd);
- continue;
- }
-
- io_add(&listen_socket[listen_sockets].tcp, handle_new_meta_connection, &listen_socket[listen_sockets], tcp_fd, IO_READ);
- io_add(&listen_socket[listen_sockets].udp, handle_incoming_vpn_data, &listen_socket[listen_sockets], udp_fd, IO_READ);
-
- if(debug_level >= DEBUG_CONNECTIONS) {
- hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr);
- logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Listening on %s", hostname);
- free(hostname);
- }
+ }
- memcpy(&listen_socket[listen_sockets].sa, aip->ai_addr, aip->ai_addrlen);
- listen_sockets++;
- }
+ for(config_t *cfg = lookup_config(config_tree, "ListenAddress"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
+ cfgs++;
+ get_config_string(cfg, &address);
+ if(!add_listen_address(address, false))
+ return false;
+ }
- freeaddrinfo(ai);
- } while(cfg);
+ if(!cfgs)
+ if(!add_listen_address(address, NULL))
+ return false;
}
if(!listen_sockets) {
terminate_connection(c, false);
}
- list_delete_list(outgoing_list);
+ if(outgoing_list)
+ list_delete_list(outgoing_list);
if(myself && myself->connection) {
subnet_update(myself, NULL, false);
static bool bind_to_address(connection_t *c) {
int s = -1;
- for(int i = 0; i < listen_sockets; i++) {
+ for(int i = 0; i < listen_sockets && listen_socket[i].bindto; i++) {
if(listen_socket[i].sa.sa.sa_family != c->address.sa.sa_family)
continue;
if(s >= 0)
{"IffOneQueue", VAR_SERVER},
{"Interface", VAR_SERVER},
{"KeyExpire", VAR_SERVER},
+ {"ListenAddress", VAR_SERVER | VAR_MULTIPLE},
{"LocalDiscovery", VAR_SERVER},
{"MACExpire", VAR_SERVER},
{"MaxConnectionBurst", VAR_SERVER},