2 net_socket.c -- Handle various kinds of sockets.
3 Copyright (C) 1998-2005 Ivo Timmermans,
4 2000-2016 Guus Sliepen <guus@tinc-vpn.org>
5 2006 Scott Lamb <slamb@slamb.org>
6 2009 Florian Forster <octo@verplant.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "connection.h"
27 #include "control_common.h"
38 int addressfamily = AF_UNSPEC;
40 int seconds_till_retry = 5;
41 int udp_rcvbuf = 1024 * 1024;
42 int udp_sndbuf = 1024 * 1024;
43 int max_connection_burst = 100;
45 listen_socket_t listen_socket[MAXSOCKETS];
50 list_t *outgoing_list = NULL;
54 static void configure_tcp(connection_t *c) {
58 int flags = fcntl(c->socket, F_GETFL);
60 if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0) {
61 logger(DEBUG_ALWAYS, LOG_ERR, "fcntl for %s: %s", c->hostname, strerror(errno));
64 unsigned long arg = 1;
66 if(ioctlsocket(c->socket, FIONBIO, &arg) != 0) {
67 logger(DEBUG_ALWAYS, LOG_ERR, "ioctlsocket for %s: %s", c->hostname, sockstrerror(sockerrno));
71 #if defined(IPPROTO_TCP) && defined(TCP_NODELAY)
73 setsockopt(c->socket, IPPROTO_TCP, TCP_NODELAY, (void *)&option, sizeof option);
76 #if defined(IPPROTO_IP) && defined(IP_TOS) && defined(IPTOS_LOWDELAY)
77 option = IPTOS_LOWDELAY;
78 setsockopt(c->socket, IPPROTO_IP, IP_TOS, (void *)&option, sizeof option);
81 #if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS) && defined(IPTOS_LOWDELAY)
82 option = IPTOS_LOWDELAY;
83 setsockopt(c->socket, IPPROTO_IPV6, IPV6_TCLASS, (void *)&option, sizeof option);
87 static bool bind_to_interface(int sd) {
90 #if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
93 #endif /* defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) */
95 if(!get_config_string (lookup_config (config_tree, "BindToInterface"), &iface))
98 #if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
99 memset(&ifr, 0, sizeof(ifr));
100 strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ);
101 ifr.ifr_ifrn.ifrn_name[IFNAMSIZ - 1] = 0;
103 status = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr));
105 logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to interface %s: %s", iface,
106 sockstrerror(sockerrno));
109 #else /* if !defined(SOL_SOCKET) || !defined(SO_BINDTODEVICE) */
110 logger(DEBUG_ALWAYS, LOG_WARNING, "%s not supported on this platform", "BindToInterface");
116 static bool bind_to_address(connection_t *c) {
119 for(int i = 0; i < listen_sockets && listen_socket[i].bindto; i++) {
120 if(listen_socket[i].sa.sa.sa_family != c->address.sa.sa_family)
130 sockaddr_t sa = listen_socket[s].sa;
131 if(sa.sa.sa_family == AF_INET)
133 else if(sa.sa.sa_family == AF_INET6)
134 sa.in6.sin6_port = 0;
136 if(bind(c->socket, &sa.sa, SALEN(sa.sa))) {
137 logger(DEBUG_CONNECTIONS, LOG_WARNING, "Can't bind outgoing socket: %s", sockstrerror(sockerrno));
144 int setup_listen_socket(const sockaddr_t *sa) {
150 nfd = socket(sa->sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
153 logger(DEBUG_STATUS, LOG_ERR, "Creating metasocket failed: %s", sockstrerror(sockerrno));
158 fcntl(nfd, F_SETFD, FD_CLOEXEC);
161 /* Optimize TCP settings */
164 setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof option);
166 #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
167 if(sa->sa.sa_family == AF_INET6)
168 setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
172 (lookup_config(config_tree, "BindToInterface"), &iface)) {
173 #if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
176 memset(&ifr, 0, sizeof ifr);
177 strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ);
179 if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof ifr)) {
181 logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to interface %s: %s", iface,
182 sockstrerror(sockerrno));
186 logger(DEBUG_ALWAYS, LOG_WARNING, "%s not supported on this platform", "BindToInterface");
190 if(bind(nfd, &sa->sa, SALEN(sa->sa))) {
192 addrstr = sockaddr2hostname(sa);
193 logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to %s/tcp: %s", addrstr, sockstrerror(sockerrno));
200 logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "listen", sockstrerror(sockerrno));
207 int setup_vpn_in_socket(const sockaddr_t *sa) {
212 nfd = socket(sa->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP);
215 logger(DEBUG_ALWAYS, LOG_ERR, "Creating UDP socket failed: %s", sockstrerror(sockerrno));
220 fcntl(nfd, F_SETFD, FD_CLOEXEC);
225 int flags = fcntl(nfd, F_GETFL);
227 if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) {
229 logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "fcntl",
236 unsigned long arg = 1;
237 if(ioctlsocket(nfd, FIONBIO, &arg) != 0) {
239 logger(DEBUG_ALWAYS, LOG_ERR, "Call to `%s' failed: %s", "ioctlsocket", sockstrerror(sockerrno));
246 setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof option);
247 setsockopt(nfd, SOL_SOCKET, SO_BROADCAST, (void *)&option, sizeof option);
249 if(udp_rcvbuf && setsockopt(nfd, SOL_SOCKET, SO_RCVBUF, (void *)&udp_rcvbuf, sizeof(udp_rcvbuf)))
250 logger(DEBUG_ALWAYS, LOG_WARNING, "Can't set UDP SO_RCVBUF to %i: %s", udp_rcvbuf, sockstrerror(sockerrno));
252 if(udp_sndbuf && setsockopt(nfd, SOL_SOCKET, SO_SNDBUF, (void *)&udp_sndbuf, sizeof(udp_sndbuf)))
253 logger(DEBUG_ALWAYS, LOG_WARNING, "Can't set UDP SO_SNDBUF to %i: %s", udp_sndbuf, sockstrerror(sockerrno));
255 #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
256 if(sa->sa.sa_family == AF_INET6)
257 setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
260 #if defined(IP_DONTFRAG) && !defined(IP_DONTFRAGMENT)
261 #define IP_DONTFRAGMENT IP_DONTFRAG
264 #if defined(IPPROTO_IP) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
265 if(myself->options & OPTION_PMTU_DISCOVERY) {
266 option = IP_PMTUDISC_DO;
267 setsockopt(nfd, IPPROTO_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option));
269 #elif defined(IPPROTO_IP) && defined(IP_DONTFRAGMENT)
270 if(myself->options & OPTION_PMTU_DISCOVERY) {
272 setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, (void *)&option, sizeof(option));
276 #if defined(IPPROTO_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
277 if(myself->options & OPTION_PMTU_DISCOVERY) {
278 option = IPV6_PMTUDISC_DO;
279 setsockopt(nfd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option));
281 #elif defined(IPPROTO_IPV6) && defined(IPV6_DONTFRAG)
282 if(myself->options & OPTION_PMTU_DISCOVERY) {
284 setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, (void *)&option, sizeof(option));
288 if (!bind_to_interface(nfd)) {
293 if(bind(nfd, &sa->sa, SALEN(sa->sa))) {
295 addrstr = sockaddr2hostname(sa);
296 logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to %s/udp: %s", addrstr, sockstrerror(sockerrno));
302 } /* int setup_vpn_in_socket */
304 static void retry_outgoing_handler(void *data) {
305 setup_outgoing_connection(data);
308 void retry_outgoing(outgoing_t *outgoing) {
309 outgoing->timeout += 5;
311 if(outgoing->timeout > maxtimeout)
312 outgoing->timeout = maxtimeout;
314 timeout_add(&outgoing->ev, retry_outgoing_handler, outgoing, &(struct timeval){outgoing->timeout, rand() % 100000});
316 logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Trying to re-establish outgoing connection in %d seconds", outgoing->timeout);
319 void finish_connecting(connection_t *c) {
320 logger(DEBUG_CONNECTIONS, LOG_INFO, "Connected to %s (%s)", c->name, c->hostname);
322 c->last_ping_time = now.tv_sec;
323 c->status.connecting = false;
328 static void do_outgoing_pipe(connection_t *c, char *command) {
332 if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) {
333 logger(DEBUG_ALWAYS, LOG_ERR, "Could not create socketpair: %s", sockstrerror(sockerrno));
340 logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Using proxy %s", command);
351 // Other filedescriptors should be closed automatically by CLOEXEC
356 sockaddr2str(&c->address, &host, &port);
357 setenv("REMOTEADDRESS", host, true);
358 setenv("REMOTEPORT", port, true);
359 setenv("NODE", c->name, true);
360 setenv("NAME", myself->name, true);
362 setenv("NETNAME", netname, true);
364 int result = system(command);
366 logger(DEBUG_ALWAYS, LOG_ERR, "Could not execute %s: %s", command, strerror(errno));
368 logger(DEBUG_ALWAYS, LOG_ERR, "%s exited with non-zero status %d", command, result);
371 logger(DEBUG_ALWAYS, LOG_ERR, "Proxy type exec not supported on this platform!");
376 static void handle_meta_write(connection_t *c) {
377 if(c->outbuf.len <= c->outbuf.offset)
380 ssize_t outlen = send(c->socket, c->outbuf.data + c->outbuf.offset, c->outbuf.len - c->outbuf.offset, 0);
382 if(!sockerrno || sockerrno == EPIPE) {
383 logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection closed by %s (%s)", c->name, c->hostname);
384 } else if(sockwouldblock(sockerrno)) {
385 logger(DEBUG_META, LOG_DEBUG, "Sending %d bytes to %s (%s) would block", c->outbuf.len - c->outbuf.offset, c->name, c->hostname);
388 logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not send %d bytes of data to %s (%s): %s", c->outbuf.len - c->outbuf.offset, c->name, c->hostname, sockstrerror(sockerrno));
391 terminate_connection(c, c->edge);
395 buffer_read(&c->outbuf, outlen);
397 io_set(&c->io, IO_READ);
400 static void handle_meta_io(void *data, int flags) {
401 connection_t *c = data;
403 if(c->status.connecting) {
405 The event loop does not protect against spurious events. Verify that we are actually connected
406 by issuing an empty send() call.
408 Note that the behavior of send() on potentially unconnected sockets differ between platforms:
409 +------------+-----------+-------------+-----------+
410 | Event | POSIX | Linux | Windows |
411 +------------+-----------+-------------+-----------+
412 | Spurious | ENOTCONN | EWOULDBLOCK | ENOTCONN |
413 | Failed | ENOTCONN | (cause) | ENOTCONN |
414 | Successful | (success) | (success) | (success) |
415 +------------+-----------+-------------+-----------+
417 if (send(c->socket, NULL, 0, 0) != 0) {
418 if (sockwouldblock(sockerrno))
421 if (!socknotconn(sockerrno))
422 socket_error = sockerrno;
424 socklen_t len = sizeof socket_error;
425 getsockopt(c->socket, SOL_SOCKET, SO_ERROR, (void *)&socket_error, &len);
428 logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Error while connecting to %s (%s): %s", c->name, c->hostname, sockstrerror(socket_error));
429 terminate_connection(c, false);
434 c->status.connecting = false;
435 finish_connecting(c);
439 handle_meta_write(c);
441 handle_meta_connection_data(c);
444 static void free_known_addresses(struct addrinfo *ai) {
445 for(struct addrinfo *aip = ai, *next; aip; aip = next) {
451 bool do_outgoing_connection(outgoing_t *outgoing) {
452 char *address, *port, *space;
453 struct addrinfo *proxyai = NULL;
457 if(!outgoing->ai && !outgoing->kai) {
459 logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not set up a meta connection to %s", outgoing->name);
460 retry_outgoing(outgoing);
464 get_config_string(outgoing->cfg, &address);
466 space = strchr(address, ' ');
468 port = xstrdup(space + 1);
471 if(!get_config_string(lookup_config(outgoing->config_tree, "Port"), &port))
472 port = xstrdup("655");
475 outgoing->ai = str2addrinfo(address, port, SOCK_STREAM);
479 outgoing->aip = outgoing->ai;
480 outgoing->cfg = lookup_config_next(outgoing->config_tree, outgoing->cfg);
485 freeaddrinfo(outgoing->ai);
489 free_known_addresses(outgoing->kai);
490 outgoing->kai = NULL;
495 connection_t *c = new_connection();
496 c->outgoing = outgoing;
498 memcpy(&c->address, outgoing->aip->ai_addr, outgoing->aip->ai_addrlen);
499 outgoing->aip = outgoing->aip->ai_next;
501 c->hostname = sockaddr2hostname(&c->address);
503 logger(DEBUG_CONNECTIONS, LOG_INFO, "Trying to connect to %s (%s)", outgoing->name, c->hostname);
506 c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
508 } else if(proxytype == PROXY_EXEC) {
509 do_outgoing_pipe(c, proxyhost);
511 proxyai = str2addrinfo(proxyhost, proxyport, SOCK_STREAM);
516 logger(DEBUG_CONNECTIONS, LOG_INFO, "Using proxy at %s port %s", proxyhost, proxyport);
517 c->socket = socket(proxyai->ai_family, SOCK_STREAM, IPPROTO_TCP);
521 if(c->socket == -1) {
522 logger(DEBUG_CONNECTIONS, LOG_ERR, "Creating socket for %s failed: %s", c->hostname, sockstrerror(sockerrno));
528 fcntl(c->socket, F_SETFD, FD_CLOEXEC);
531 if(proxytype != PROXY_EXEC) {
532 #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
534 if(c->address.sa.sa_family == AF_INET6)
535 setsockopt(c->socket, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
538 bind_to_interface(c->socket);
545 result = connect(c->socket, &c->address.sa, SALEN(c->address.sa));
546 } else if(proxytype == PROXY_EXEC) {
551 result = connect(c->socket, proxyai->ai_addr, proxyai->ai_addrlen);
552 freeaddrinfo(proxyai);
555 if(result == -1 && !sockinprogress(sockerrno)) {
556 logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not connect to %s (%s): %s", outgoing->name, c->hostname, sockstrerror(sockerrno));
562 /* Now that there is a working socket, fill in the rest and register this connection. */
564 c->last_ping_time = time(NULL);
565 c->status.connecting = true;
566 c->name = xstrdup(outgoing->name);
567 #ifndef DISABLE_LEGACY
568 c->outcipher = myself->connection->outcipher;
569 c->outdigest = myself->connection->outdigest;
571 c->outmaclength = myself->connection->outmaclength;
572 c->outcompression = myself->connection->outcompression;
573 c->last_ping_time = now.tv_sec;
577 io_add(&c->io, handle_meta_io, c, c->socket, IO_READ|IO_WRITE);
582 // Find edges pointing to this node, and use them to build a list of unique, known addresses.
583 static struct addrinfo *get_known_addresses(node_t *n) {
584 struct addrinfo *ai = NULL;
585 struct addrinfo *oai = NULL;
587 for splay_each(edge_t, e, n->edge_tree) {
592 for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) {
593 if(!sockaddrcmp(&e->reverse->address, (sockaddr_t *)aip->ai_addr)) {
602 ai = xzalloc(sizeof *ai);
603 ai->ai_family = e->reverse->address.sa.sa_family;
604 ai->ai_socktype = SOCK_STREAM;
605 ai->ai_protocol = IPPROTO_TCP;
606 ai->ai_addrlen = SALEN(e->reverse->address.sa);
607 ai->ai_addr = xmalloc(ai->ai_addrlen);
608 memcpy(ai->ai_addr, &e->reverse->address, ai->ai_addrlen);
615 void setup_outgoing_connection(outgoing_t *outgoing) {
616 timeout_del(&outgoing->ev);
618 node_t *n = lookup_node(outgoing->name);
620 if(n && n->connection) {
621 logger(DEBUG_CONNECTIONS, LOG_INFO, "Already connected to %s", outgoing->name);
622 if(!n->connection->outgoing) {
623 n->connection->outgoing = outgoing;
630 init_configuration(&outgoing->config_tree);
631 read_host_config(outgoing->config_tree, outgoing->name);
632 outgoing->cfg = lookup_config(outgoing->config_tree, "Address");
636 outgoing->aip = outgoing->kai = get_known_addresses(n);
638 logger(DEBUG_ALWAYS, LOG_DEBUG, "No address known for %s", outgoing->name);
643 do_outgoing_connection(outgoing);
647 list_delete(outgoing_list, outgoing);
651 accept a new tcp connect and create a
654 void handle_new_meta_connection(void *data, int flags) {
655 listen_socket_t *l = data;
659 socklen_t len = sizeof sa;
661 fd = accept(l->tcp.fd, &sa.sa, &len);
664 logger(DEBUG_ALWAYS, LOG_ERR, "Accepting a new connection failed: %s", sockstrerror(sockerrno));
670 // Check if we get many connections from the same host
672 static sockaddr_t prev_sa;
673 static int tarpit = -1;
680 if(!sockaddrcmp_noport(&sa, &prev_sa)) {
681 static int samehost_burst;
682 static int samehost_burst_time;
684 if(now.tv_sec - samehost_burst_time > samehost_burst)
687 samehost_burst -= now.tv_sec - samehost_burst_time;
689 samehost_burst_time = now.tv_sec;
692 if(samehost_burst > max_connection_burst) {
698 memcpy(&prev_sa, &sa, sizeof sa);
700 // Check if we get many connections from different hosts
702 static int connection_burst;
703 static int connection_burst_time;
705 if(now.tv_sec - connection_burst_time > connection_burst)
706 connection_burst = 0;
708 connection_burst -= now.tv_sec - connection_burst_time;
710 connection_burst_time = now.tv_sec;
713 if(connection_burst >= max_connection_burst) {
714 connection_burst = max_connection_burst;
719 // Accept the new connection
721 c = new_connection();
722 c->name = xstrdup("<unknown>");
723 #ifndef DISABLE_LEGACY
724 c->outcipher = myself->connection->outcipher;
725 c->outdigest = myself->connection->outdigest;
727 c->outmaclength = myself->connection->outmaclength;
728 c->outcompression = myself->connection->outcompression;
731 c->hostname = sockaddr2hostname(&sa);
733 c->last_ping_time = now.tv_sec;
735 logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection from %s", c->hostname);
737 io_add(&c->io, handle_meta_io, c, c->socket, IO_READ);
743 c->allow_request = ID;
749 accept a new UNIX socket connection
751 void handle_new_unix_connection(void *data, int flags) {
756 socklen_t len = sizeof sa;
758 fd = accept(io->fd, &sa.sa, &len);
761 logger(DEBUG_ALWAYS, LOG_ERR, "Accepting a new connection failed: %s", sockstrerror(sockerrno));
767 c = new_connection();
768 c->name = xstrdup("<control>");
770 c->hostname = xstrdup("localhost port unix");
772 c->last_ping_time = now.tv_sec;
774 logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection from %s", c->hostname);
776 io_add(&c->io, handle_meta_io, c, c->socket, IO_READ);
780 c->allow_request = ID;
786 static void free_outgoing(outgoing_t *outgoing) {
787 timeout_del(&outgoing->ev);
790 freeaddrinfo(outgoing->ai);
793 free_known_addresses(outgoing->kai);
795 if(outgoing->config_tree)
796 exit_configuration(&outgoing->config_tree);
799 free(outgoing->name);
804 void try_outgoing_connections(void) {
805 /* If there is no outgoing list yet, create one. Otherwise, mark all outgoings as deleted. */
808 outgoing_list = list_alloc((list_action_t)free_outgoing);
810 for list_each(outgoing_t, outgoing, outgoing_list)
811 outgoing->timeout = -1;
814 /* Make sure there is one outgoing_t in the list for each ConnectTo. */
816 for(config_t *cfg = lookup_config(config_tree, "ConnectTo"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
818 get_config_string(cfg, &name);
820 if(!check_id(name)) {
821 logger(DEBUG_ALWAYS, LOG_ERR,
822 "Invalid name for outgoing connection in %s line %d",
823 cfg->file, cfg->line);
828 if(!strcmp(name, myself->name)) {
835 for list_each(outgoing_t, outgoing, outgoing_list) {
836 if(!strcmp(outgoing->name, name)) {
838 outgoing->timeout = 0;
844 outgoing_t *outgoing = xzalloc(sizeof *outgoing);
845 outgoing->name = name;
846 list_insert_tail(outgoing_list, outgoing);
847 setup_outgoing_connection(outgoing);
851 /* Terminate any connections whose outgoing_t is to be deleted. */
853 for list_each(connection_t, c, connection_list) {
854 if(c->outgoing && c->outgoing->timeout == -1) {
856 logger(DEBUG_CONNECTIONS, LOG_INFO, "No more outgoing connection to %s", c->name);
857 terminate_connection(c, c->edge);
861 /* Delete outgoing_ts for which there is no ConnectTo. */
863 for list_each(outgoing_t, outgoing, outgoing_list)
864 if(outgoing->timeout == -1)
865 list_delete_node(outgoing_list, node);