Remove useless warning about signature length being shorter than expected.
[tinc] / src / net_setup.c
1 /*
2     net_setup.c -- Setup.
3     Copyright (C) 1998-2005 Ivo Timmermans,
4                   2000-2010 Guus Sliepen <guus@tinc-vpn.org>
5                   2006      Scott Lamb <slamb@slamb.org>
6                   2010      Brandon Black <blblack@gmail.com>
7
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.
12
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.
17
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.
21 */
22
23 #include "system.h"
24
25 #include "splay_tree.h"
26 #include "cipher.h"
27 #include "conf.h"
28 #include "connection.h"
29 #include "control.h"
30 #include "device.h"
31 #include "digest.h"
32 #include "ecdsa.h"
33 #include "graph.h"
34 #include "logger.h"
35 #include "net.h"
36 #include "netutl.h"
37 #include "process.h"
38 #include "protocol.h"
39 #include "route.h"
40 #include "rsa.h"
41 #include "subnet.h"
42 #include "utils.h"
43 #include "xalloc.h"
44
45 char *myport;
46 static struct event device_ev;
47
48 bool node_read_ecdsa_public_key(node_t *n) {
49         if(ecdsa_active(&n->ecdsa))
50                 return true;
51
52         splay_tree_t *config_tree;
53         FILE *fp;
54         char *fname;
55         char *p;
56         bool result = false;
57
58         xasprintf(&fname, "%s/hosts/%s", confbase, n->name);
59
60         init_configuration(&config_tree);
61         if(!read_config_file(config_tree, fname))
62                 goto exit;
63
64         /* First, check for simple ECDSAPublicKey statement */
65
66         if(get_config_string(lookup_config(config_tree, "ECDSAPublicKey"), &p)) {
67                 result = ecdsa_set_base64_public_key(&n->ecdsa, p);
68                 free(p);
69                 goto exit;
70         }
71
72         /* Else, check for ECDSAPublicKeyFile statement and read it */
73
74         free(fname);
75
76         if(!get_config_string(lookup_config(config_tree, "ECDSAPublicKeyFile"), &fname))
77                 xasprintf(&fname, "%s/hosts/%s", confbase, n->name);
78
79         fp = fopen(fname, "r");
80
81         if(!fp) {
82                 logger(LOG_ERR, "Error reading ECDSA public key file `%s': %s", fname, strerror(errno));
83                 goto exit;
84         }
85
86         result = ecdsa_read_pem_public_key(&n->ecdsa, fp);
87         fclose(fp);
88
89 exit:
90         exit_configuration(&config_tree);
91         free(fname);
92         return result;
93 }
94
95 bool read_ecdsa_public_key(connection_t *c) {
96         FILE *fp;
97         char *fname;
98         char *p;
99         bool result;
100
101         /* First, check for simple ECDSAPublicKey statement */
102
103         if(get_config_string(lookup_config(c->config_tree, "ECDSAPublicKey"), &p)) {
104                 result = ecdsa_set_base64_public_key(&c->ecdsa, p);
105                 free(p);
106                 return result;
107         }
108
109         /* Else, check for ECDSAPublicKeyFile statement and read it */
110
111         if(!get_config_string(lookup_config(c->config_tree, "ECDSAPublicKeyFile"), &fname))
112                 xasprintf(&fname, "%s/hosts/%s", confbase, c->name);
113
114         fp = fopen(fname, "r");
115
116         if(!fp) {
117                 logger(LOG_ERR, "Error reading ECDSA public key file `%s': %s",
118                            fname, strerror(errno));
119                 free(fname);
120                 return false;
121         }
122
123         result = ecdsa_read_pem_public_key(&c->ecdsa, fp);
124         fclose(fp);
125
126         if(!result) 
127                 logger(LOG_ERR, "Reading ECDSA public key file `%s' failed: %s", fname, strerror(errno));
128         free(fname);
129         return result;
130 }
131
132 bool read_rsa_public_key(connection_t *c) {
133         FILE *fp;
134         char *fname;
135         char *n;
136         bool result;
137
138         /* First, check for simple PublicKey statement */
139
140         if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &n)) {
141                 result = rsa_set_hex_public_key(&c->rsa, n, "FFFF");
142                 free(n);
143                 return result;
144         }
145
146         /* Else, check for PublicKeyFile statement and read it */
147
148         if(!get_config_string(lookup_config(c->config_tree, "PublicKeyFile"), &fname))
149                 xasprintf(&fname, "%s/hosts/%s", confbase, c->name);
150
151         fp = fopen(fname, "r");
152
153         if(!fp) {
154                 logger(LOG_ERR, "Error reading RSA public key file `%s': %s",
155                            fname, strerror(errno));
156                 free(fname);
157                 return false;
158         }
159
160         result = rsa_read_pem_public_key(&c->rsa, fp);
161         fclose(fp);
162
163         if(!result) 
164                 logger(LOG_ERR, "Reading RSA public key file `%s' failed: %s", fname, strerror(errno));
165         free(fname);
166         return result;
167 }
168
169 static bool read_ecdsa_private_key(void) {
170         FILE *fp;
171         char *fname;
172         bool result;
173
174         /* Check for PrivateKeyFile statement and read it */
175
176         if(!get_config_string(lookup_config(config_tree, "ECDSAPrivateKeyFile"), &fname))
177                 xasprintf(&fname, "%s/ecdsa_key.priv", confbase);
178
179         fp = fopen(fname, "r");
180
181         if(!fp) {
182                 logger(LOG_ERR, "Error reading ECDSA private key file `%s': %s",
183                            fname, strerror(errno));
184                 free(fname);
185                 return false;
186         }
187
188 #if !defined(HAVE_MINGW) && !defined(HAVE_CYGWIN)
189         struct stat s;
190
191         if(fstat(fileno(fp), &s)) {
192                 logger(LOG_ERR, "Could not stat ECDSA private key file `%s': %s'", fname, strerror(errno));
193                 free(fname);
194                 return false;
195         }
196
197         if(s.st_mode & ~0100700)
198                 logger(LOG_WARNING, "Warning: insecure file permissions for ECDSA private key file `%s'!", fname);
199 #endif
200
201         result = ecdsa_read_pem_private_key(&myself->connection->ecdsa, fp);
202         fclose(fp);
203
204         if(!result) 
205                 logger(LOG_ERR, "Reading ECDSA private key file `%s' failed: %s", fname, strerror(errno));
206         free(fname);
207         return result;
208 }
209
210 static bool read_rsa_private_key(void) {
211         FILE *fp;
212         char *fname;
213         char *n, *d;
214         bool result;
215
216         /* First, check for simple PrivateKey statement */
217
218         if(get_config_string(lookup_config(config_tree, "PrivateKey"), &d)) {
219                 if(!get_config_string(lookup_config(config_tree, "PublicKey"), &n)) {
220                         logger(LOG_ERR, "PrivateKey used but no PublicKey found!");
221                         free(d);
222                         return false;
223                 }
224                 result = rsa_set_hex_private_key(&myself->connection->rsa, n, "FFFF", d);
225                 free(n);
226                 free(d);
227                 return true;
228         }
229
230         /* Else, check for PrivateKeyFile statement and read it */
231
232         if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname))
233                 xasprintf(&fname, "%s/rsa_key.priv", confbase);
234
235         fp = fopen(fname, "r");
236
237         if(!fp) {
238                 logger(LOG_ERR, "Error reading RSA private key file `%s': %s",
239                            fname, strerror(errno));
240                 free(fname);
241                 return false;
242         }
243
244 #if !defined(HAVE_MINGW) && !defined(HAVE_CYGWIN)
245         struct stat s;
246
247         if(fstat(fileno(fp), &s)) {
248                 logger(LOG_ERR, "Could not stat RSA private key file `%s': %s'", fname, strerror(errno));
249                 free(fname);
250                 return false;
251         }
252
253         if(s.st_mode & ~0100700)
254                 logger(LOG_WARNING, "Warning: insecure file permissions for RSA private key file `%s'!", fname);
255 #endif
256
257         result = rsa_read_pem_private_key(&myself->connection->rsa, fp);
258         fclose(fp);
259
260         if(!result) 
261                 logger(LOG_ERR, "Reading RSA private key file `%s' failed: %s", fname, strerror(errno));
262         free(fname);
263         return result;
264 }
265
266 static struct event keyexpire_event;
267
268 static void keyexpire_handler(int fd, short events, void *data) {
269         regenerate_key();
270 }
271
272 void regenerate_key(void) {
273         if(timeout_initialized(&keyexpire_event)) {
274                 ifdebug(STATUS) logger(LOG_INFO, "Expiring symmetric keys");
275                 event_del(&keyexpire_event);
276                 send_key_changed();
277         } else {
278                 timeout_set(&keyexpire_event, keyexpire_handler, NULL);
279         }
280
281         event_add(&keyexpire_event, &(struct timeval){keylifetime, 0});
282 }
283
284 /*
285   Read Subnets from all host config files
286 */
287 void load_all_subnets(void) {
288         DIR *dir;
289         struct dirent *ent;
290         char *dname;
291         char *fname;
292         splay_tree_t *config_tree;
293         config_t *cfg;
294         subnet_t *s, *s2;
295         node_t *n;
296         bool result;
297
298         xasprintf(&dname, "%s/hosts", confbase);
299         dir = opendir(dname);
300         if(!dir) {
301                 logger(LOG_ERR, "Could not open %s: %s", dname, strerror(errno));
302                 free(dname);
303                 return;
304         }
305
306         while((ent = readdir(dir))) {
307                 if(!check_id(ent->d_name))
308                         continue;
309
310                 n = lookup_node(ent->d_name);
311                 #ifdef _DIRENT_HAVE_D_TYPE
312                 //if(ent->d_type != DT_REG)
313                 //      continue;
314                 #endif
315
316                 xasprintf(&fname, "%s/hosts/%s", confbase, ent->d_name);
317                 init_configuration(&config_tree);
318                 result = read_config_file(config_tree, fname);
319                 free(fname);
320                 if(!result)
321                         continue;
322
323                 if(!n) {
324                         n = new_node();
325                         n->name = xstrdup(ent->d_name);
326                         node_add(n);
327                 }
328
329                 for(cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
330                         if(!get_config_subnet(cfg, &s))
331                                 continue;
332
333                         if((s2 = lookup_subnet(n, s))) {
334                                 s2->expires = -1;
335                         } else {
336                                 subnet_add(n, s);
337                         }
338                 }
339
340                 exit_configuration(&config_tree);
341         }
342
343         closedir(dir);
344 }
345
346 /*
347   Configure node_t myself and set up the local sockets (listen only)
348 */
349 static bool setup_myself(void) {
350         config_t *cfg;
351         subnet_t *subnet;
352         char *name, *hostname, *mode, *afname, *cipher, *digest;
353         char *fname = NULL;
354         char *address = NULL;
355         char *envp[5];
356         struct addrinfo *ai, *aip, hint = {0};
357         bool choice;
358         int i, err;
359         int replaywin_int;
360
361         myself = new_node();
362         myself->connection = new_connection();
363
364         myself->hostname = xstrdup("MYSELF");
365         myself->connection->hostname = xstrdup("MYSELF");
366
367         myself->connection->options = 0;
368         myself->connection->protocol_major = PROT_MAJOR;
369         myself->connection->protocol_minor = PROT_MINOR;
370
371         if(!get_config_string(lookup_config(config_tree, "Name"), &name)) {     /* Not acceptable */
372                 logger(LOG_ERR, "Name for tinc daemon required!");
373                 return false;
374         }
375
376         if(!check_id(name)) {
377                 logger(LOG_ERR, "Invalid name for myself!");
378                 free(name);
379                 return false;
380         }
381
382         myself->name = name;
383         myself->connection->name = xstrdup(name);
384         xasprintf(&fname, "%s/hosts/%s", confbase, name);
385         read_config_options(config_tree, name);
386         read_config_file(config_tree, fname);
387         free(fname);
388
389         get_config_bool(lookup_config(config_tree, "ExperimentalProtocol"), &experimental);
390
391         if(experimental && !read_ecdsa_private_key())
392                 return false;
393
394         if(!read_rsa_private_key())
395                 return false;
396
397         if(!get_config_string(lookup_config(config_tree, "Port"), &myport))
398                 myport = xstrdup("655");
399
400         if(!atoi(myport)) {
401                 struct addrinfo *ai = str2addrinfo("localhost", myport, SOCK_DGRAM);
402                 sockaddr_t sa;
403                 if(!ai || !ai->ai_addr)
404                         return false;
405                 free(myport);
406                 memcpy(&sa, ai->ai_addr, ai->ai_addrlen);
407                 sockaddr2str(&sa, NULL, &myport);
408         }
409
410         /* Read in all the subnets specified in the host configuration file */
411
412         cfg = lookup_config(config_tree, "Subnet");
413
414         while(cfg) {
415                 if(!get_config_subnet(cfg, &subnet))
416                         return false;
417
418                 subnet_add(myself, subnet);
419
420                 cfg = lookup_config_next(config_tree, cfg);
421         }
422
423         /* Check some options */
424
425         if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice) && choice)
426                 myself->options |= OPTION_INDIRECT;
427
428         if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice) && choice)
429                 myself->options |= OPTION_TCPONLY;
430
431         if(myself->options & OPTION_TCPONLY)
432                 myself->options |= OPTION_INDIRECT;
433
434         get_config_bool(lookup_config(config_tree, "DirectOnly"), &directonly);
435         get_config_bool(lookup_config(config_tree, "StrictSubnets"), &strictsubnets);
436         get_config_bool(lookup_config(config_tree, "TunnelServer"), &tunnelserver);
437         strictsubnets |= tunnelserver;
438
439         if(get_config_string(lookup_config(config_tree, "Mode"), &mode)) {
440                 if(!strcasecmp(mode, "router"))
441                         routing_mode = RMODE_ROUTER;
442                 else if(!strcasecmp(mode, "switch"))
443                         routing_mode = RMODE_SWITCH;
444                 else if(!strcasecmp(mode, "hub"))
445                         routing_mode = RMODE_HUB;
446                 else {
447                         logger(LOG_ERR, "Invalid routing mode!");
448                         return false;
449                 }
450                 free(mode);
451         }
452
453         if(get_config_string(lookup_config(config_tree, "Forwarding"), &mode)) {
454                 if(!strcasecmp(mode, "off"))
455                         forwarding_mode = FMODE_OFF;
456                 else if(!strcasecmp(mode, "internal"))
457                         forwarding_mode = FMODE_INTERNAL;
458                 else if(!strcasecmp(mode, "kernel"))
459                         forwarding_mode = FMODE_KERNEL;
460                 else {
461                         logger(LOG_ERR, "Invalid forwarding mode!");
462                         return false;
463                 }
464                 free(mode);
465         }
466
467         choice = true;
468         get_config_bool(lookup_config(config_tree, "PMTUDiscovery"), &choice);
469         if(choice)
470                 myself->options |= OPTION_PMTU_DISCOVERY;
471
472         choice = true;
473         get_config_bool(lookup_config(config_tree, "ClampMSS"), &choice);
474         if(choice)
475                 myself->options |= OPTION_CLAMP_MSS;
476
477         get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance);
478
479 #if !defined(SOL_IP) || !defined(IP_TOS)
480         if(priorityinheritance)
481                 logger(LOG_WARNING, "%s not supported on this platform", "PriorityInheritance");
482 #endif
483
484         if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire))
485                 macexpire = 600;
486
487         if(get_config_int(lookup_config(config_tree, "MaxTimeout"), &maxtimeout)) {
488                 if(maxtimeout <= 0) {
489                         logger(LOG_ERR, "Bogus maximum timeout!");
490                         return false;
491                 }
492         } else
493                 maxtimeout = 900;
494
495         if(get_config_int(lookup_config(config_tree, "UDPRcvBuf"), &udp_rcvbuf)) {
496                 if(udp_rcvbuf <= 0) {
497                         logger(LOG_ERR, "UDPRcvBuf cannot be negative!");
498                         return false;
499                 }
500         }
501
502         if(get_config_int(lookup_config(config_tree, "UDPSndBuf"), &udp_sndbuf)) {
503                 if(udp_sndbuf <= 0) {
504                         logger(LOG_ERR, "UDPSndBuf cannot be negative!");
505                         return false;
506                 }
507         }
508
509         if(get_config_int(lookup_config(config_tree, "ReplayWindow"), &replaywin_int)) {
510                 if(replaywin_int < 0) {
511                         logger(LOG_ERR, "ReplayWindow cannot be negative!");
512                         return false;
513                 }
514                 replaywin = (unsigned)replaywin_int;
515         }
516
517         if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname)) {
518                 if(!strcasecmp(afname, "IPv4"))
519                         addressfamily = AF_INET;
520                 else if(!strcasecmp(afname, "IPv6"))
521                         addressfamily = AF_INET6;
522                 else if(!strcasecmp(afname, "any"))
523                         addressfamily = AF_UNSPEC;
524                 else {
525                         logger(LOG_ERR, "Invalid address family!");
526                         return false;
527                 }
528                 free(afname);
529         }
530
531         get_config_bool(lookup_config(config_tree, "Hostnames"), &hostnames);
532
533         /* Generate packet encryption key */
534
535         if(!get_config_string(lookup_config(config_tree, "Cipher"), &cipher))
536                 cipher = xstrdup("blowfish");
537
538         if(!cipher_open_by_name(&myself->incipher, cipher)) {
539                 logger(LOG_ERR, "Unrecognized cipher type!");
540                 return false;
541         }
542
543         if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime))
544                 keylifetime = 3600;
545
546         regenerate_key();
547
548         /* Check if we want to use message authentication codes... */
549
550         int maclength = 4;
551         get_config_int(lookup_config(config_tree, "MACLength"), &maclength);
552
553         if(maclength < 0) {
554                 logger(LOG_ERR, "Bogus MAC length!");
555                 return false;
556         }
557
558         if(!get_config_string(lookup_config(config_tree, "Digest"), &digest))
559                 digest = xstrdup("sha1");
560
561         if(!digest_open_by_name(&myself->indigest, digest, maclength)) {
562                 logger(LOG_ERR, "Unrecognized digest type!");
563                 return false;
564         }
565
566         /* Compression */
567
568         if(get_config_int(lookup_config(config_tree, "Compression"), &myself->incompression)) {
569                 if(myself->incompression < 0 || myself->incompression > 11) {
570                         logger(LOG_ERR, "Bogus compression level!");
571                         return false;
572                 }
573         } else
574                 myself->incompression = 0;
575
576         myself->connection->outcompression = 0;
577
578         /* Done */
579
580         myself->nexthop = myself;
581         myself->via = myself;
582         myself->status.reachable = true;
583         node_add(myself);
584
585         graph();
586
587         if(strictsubnets)
588                 load_all_subnets();
589
590         /* Open device */
591
592         if(!setup_device())
593                 return false;
594
595         if(device_fd >= 0) {
596                 event_set(&device_ev, device_fd, EV_READ|EV_PERSIST, handle_device_data, NULL);
597
598                 if (event_add(&device_ev, NULL) < 0) {
599                         logger(LOG_ERR, "event_add failed: %s", strerror(errno));
600                         close_device();
601                         return false;
602                 }
603         }
604
605         /* Run tinc-up script to further initialize the tap interface */
606         xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
607         xasprintf(&envp[1], "DEVICE=%s", device ? : "");
608         xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
609         xasprintf(&envp[3], "NAME=%s", myself->name);
610         envp[4] = NULL;
611
612         execute_script("tinc-up", envp);
613
614         for(i = 0; i < 4; i++)
615                 free(envp[i]);
616
617         /* Run subnet-up scripts for our own subnets */
618
619         subnet_update(myself, NULL, true);
620
621         /* Open sockets */
622
623         get_config_string(lookup_config(config_tree, "BindToAddress"), &address);
624
625         hint.ai_family = addressfamily;
626         hint.ai_socktype = SOCK_STREAM;
627         hint.ai_protocol = IPPROTO_TCP;
628         hint.ai_flags = AI_PASSIVE;
629
630         err = getaddrinfo(address, myport, &hint, &ai);
631
632         if(err || !ai) {
633                 logger(LOG_ERR, "System call `%s' failed: %s", "getaddrinfo",
634                            gai_strerror(err));
635                 return false;
636         }
637
638         listen_sockets = 0;
639
640         for(aip = ai; aip; aip = aip->ai_next) {
641                 listen_socket[listen_sockets].tcp =
642                         setup_listen_socket((sockaddr_t *) aip->ai_addr);
643
644                 if(listen_socket[listen_sockets].tcp < 0)
645                         continue;
646
647                 listen_socket[listen_sockets].udp =
648                         setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);
649
650                 if(listen_socket[listen_sockets].udp < 0) {
651                         close(listen_socket[listen_sockets].tcp);
652                         continue;
653                 }
654
655                 event_set(&listen_socket[listen_sockets].ev_tcp,
656                                   listen_socket[listen_sockets].tcp,
657                                   EV_READ|EV_PERSIST,
658                                   handle_new_meta_connection, NULL);
659                 if(event_add(&listen_socket[listen_sockets].ev_tcp, NULL) < 0) {
660                         logger(LOG_ERR, "event_add failed: %s", strerror(errno));
661                         abort();
662                 }
663
664                 event_set(&listen_socket[listen_sockets].ev_udp,
665                                   listen_socket[listen_sockets].udp,
666                                   EV_READ|EV_PERSIST,
667                                   handle_incoming_vpn_data, NULL);
668                 if(event_add(&listen_socket[listen_sockets].ev_udp, NULL) < 0) {
669                         logger(LOG_ERR, "event_add failed: %s", strerror(errno));
670                         abort();
671                 }
672
673                 ifdebug(CONNECTIONS) {
674                         hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr);
675                         logger(LOG_NOTICE, "Listening on %s", hostname);
676                         free(hostname);
677                 }
678
679                 memcpy(&listen_socket[listen_sockets].sa, aip->ai_addr, aip->ai_addrlen);
680                 listen_sockets++;
681
682                 if(listen_sockets >= MAXSOCKETS) {
683                         logger(LOG_WARNING, "Maximum of %d listening sockets reached", MAXSOCKETS);
684                         break;
685                 }
686         }
687
688         freeaddrinfo(ai);
689
690         if(listen_sockets)
691                 logger(LOG_NOTICE, "Ready");
692         else {
693                 logger(LOG_ERR, "Unable to create any listening socket!");
694                 return false;
695         }
696
697         return true;
698 }
699
700 /*
701   initialize network
702 */
703 bool setup_network(void) {
704         init_connections();
705         init_subnets();
706         init_nodes();
707         init_edges();
708         init_requests();
709
710         if(get_config_int(lookup_config(config_tree, "PingInterval"), &pinginterval)) {
711                 if(pinginterval < 1) {
712                         pinginterval = 86400;
713                 }
714         } else
715                 pinginterval = 60;
716
717         if(!get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout))
718                 pingtimeout = 5;
719         if(pingtimeout < 1 || pingtimeout > pinginterval)
720                 pingtimeout = pinginterval;
721
722         if(!get_config_int(lookup_config(config_tree, "MaxOutputBufferSize"), &maxoutbufsize))
723                 maxoutbufsize = 10 * MTU;
724
725         if(!setup_myself())
726                 return false;
727
728         return true;
729 }
730
731 /*
732   close all open network connections
733 */
734 void close_network_connections(void) {
735         splay_node_t *node, *next;
736         connection_t *c;
737         char *envp[5];
738         int i;
739
740         for(node = connection_tree->head; node; node = next) {
741                 next = node->next;
742                 c = node->data;
743                 c->outgoing = NULL;
744                 terminate_connection(c, false);
745         }
746
747         list_delete_list(outgoing_list);
748
749         if(myself && myself->connection) {
750                 subnet_update(myself, NULL, false);
751                 terminate_connection(myself->connection, false);
752                 free_connection(myself->connection);
753         }
754
755         for(i = 0; i < listen_sockets; i++) {
756                 event_del(&listen_socket[i].ev_tcp);
757                 event_del(&listen_socket[i].ev_udp);
758                 close(listen_socket[i].tcp);
759                 close(listen_socket[i].udp);
760         }
761
762         xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
763         xasprintf(&envp[1], "DEVICE=%s", device ? : "");
764         xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
765         xasprintf(&envp[3], "NAME=%s", myself->name);
766         envp[4] = NULL;
767
768         exit_requests();
769         exit_edges();
770         exit_subnets();
771         exit_nodes();
772         exit_connections();
773
774         execute_script("tinc-down", envp);
775
776         if(myport) free(myport);
777
778         for(i = 0; i < 4; i++)
779                 free(envp[i]);
780
781         close_device();
782
783         return;
784 }