]> git.meshlink.io Git - meshlink/blob - src/meshlink.c
Provide a way to open MeshLink in its own network namespace.
[meshlink] / src / meshlink.c
1 /*
2     meshlink.c -- Implementation of the MeshLink API.
3     Copyright (C) 2014-2018 Guus Sliepen <guus@meshlink.io>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License along
16     with this program; if not, write to the Free Software Foundation, Inc.,
17     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 #define VAR_SERVER 1    /* Should be in meshlink.conf */
20 #define VAR_HOST 2      /* Can be in host config file */
21 #define VAR_MULTIPLE 4  /* Multiple statements allowed */
22 #define VAR_OBSOLETE 8  /* Should not be used anymore */
23 #define VAR_SAFE 16     /* Variable is safe when accepting invitations */
24 #define MAX_ADDRESS_LENGTH 45 /* Max length of an (IPv6) address */
25 #define MAX_PORT_LENGTH 5 /* 0-65535 */
26 typedef struct {
27         const char *name;
28         int type;
29 } var_t;
30
31 #include "system.h"
32 #include <pthread.h>
33
34 #include "crypto.h"
35 #include "ecdsagen.h"
36 #include "logger.h"
37 #include "meshlink_internal.h"
38 #include "netutl.h"
39 #include "node.h"
40 #include "protocol.h"
41 #include "route.h"
42 #include "sockaddr.h"
43 #include "utils.h"
44 #include "xalloc.h"
45 #include "ed25519/sha512.h"
46 #include "discovery.h"
47
48 #ifndef MSG_NOSIGNAL
49 #define MSG_NOSIGNAL 0
50 #endif
51
52 __thread meshlink_errno_t meshlink_errno;
53 meshlink_log_cb_t global_log_cb;
54 meshlink_log_level_t global_log_level;
55
56 //TODO: this can go away completely
57 const var_t variables[] = {
58         /* Server configuration */
59         {"ConnectTo", VAR_SERVER | VAR_MULTIPLE | VAR_SAFE},
60         {"Name", VAR_SERVER},
61         /* Host configuration */
62         {"CanonicalAddress", VAR_HOST},
63         {"Address", VAR_HOST | VAR_MULTIPLE},
64         {"ECDSAPublicKey", VAR_HOST},
65         {"Port", VAR_HOST},
66         {NULL, 0}
67 };
68
69 static bool fcopy(FILE *out, const char *filename) {
70         FILE *in = fopen(filename, "r");
71
72         if(!in) {
73                 logger(NULL, MESHLINK_ERROR, "Could not open %s: %s\n", filename, strerror(errno));
74                 return false;
75         }
76
77         char buf[1024];
78         size_t len;
79
80         while((len = fread(buf, 1, sizeof(buf), in))) {
81                 fwrite(buf, len, 1, out);
82         }
83
84         fclose(in);
85         return true;
86 }
87
88 static int rstrip(char *value) {
89         int len = strlen(value);
90
91         while(len && strchr("\t\r\n ", value[len - 1])) {
92                 value[--len] = 0;
93         }
94
95         return len;
96 }
97
98 static void scan_for_canonical_address(const char *filename, char **hostname, char **port) {
99         char line[4096];
100
101         if(!filename || (*hostname && *port)) {
102                 return;
103         }
104
105         FILE *f = fopen(filename, "r");
106
107         if(!f) {
108                 return;
109         }
110
111         while(fgets(line, sizeof(line), f)) {
112                 if(!rstrip(line)) {
113                         continue;
114                 }
115
116                 char *p = line, *q;
117                 p += strcspn(p, "\t =");
118
119                 if(!*p) {
120                         continue;
121                 }
122
123                 q = p + strspn(p, "\t ");
124
125                 if(*q == '=') {
126                         q += 1 + strspn(q + 1, "\t ");
127                 }
128
129                 // q is now pointing to the hostname
130                 *p = 0;
131                 p = q + strcspn(q, "\t ");
132
133                 if(*p) {
134                         *p++ = 0;
135                 }
136
137                 p += strspn(p, "\t ");
138                 p[strcspn(p, "\t ")] = 0;
139                 // p is now pointing to the port, if present
140
141                 if(!*port && !strcasecmp(line, "Port")) {
142                         *port = xstrdup(q);
143                 } else if(!strcasecmp(line, "CanonicalAddress")) {
144                         *hostname = xstrdup(q);
145
146                         if(*p) {
147                                 free(*port);
148                                 *port = xstrdup(p);
149                         }
150                 }
151
152                 if(*hostname && *port) {
153                         break;
154                 }
155         }
156
157         fclose(f);
158 }
159
160 static bool is_valid_hostname(const char *hostname) {
161         if(!*hostname) {
162                 return false;
163         }
164
165         for(const char *p = hostname; *p; p++) {
166                 if(!(isalnum(*p) || *p == '-' || *p == '.' || *p == ':')) {
167                         return false;
168                 }
169         }
170
171         return true;
172 }
173
174 static bool is_valid_port(const char *port) {
175         if(!*port) {
176                 return false;
177         }
178
179         if(isdigit(*port)) {
180                 char *end;
181                 unsigned long int result = strtoul(port, &end, 10);
182                 return result && result < 65536 && !*end;
183         }
184
185         for(const char *p = port; *p; p++) {
186                 if(!(isalnum(*p) || *p == '-')) {
187                         return false;
188                 }
189         }
190
191         return true;
192 }
193
194 static void set_timeout(int sock, int timeout) {
195 #ifdef _WIN32
196         DWORD tv = timeout;
197 #else
198         struct timeval tv;
199         tv.tv_sec = timeout / 1000;
200         tv.tv_usec = (timeout - tv.tv_sec * 1000) * 1000;
201 #endif
202         setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
203         setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
204 }
205
206 struct socket_in_netns_params {
207         int domain;
208         int type;
209         int protocol;
210         int netns;
211         int fd;
212 };
213
214 static void *socket_in_netns_thread(void *arg) {
215         struct socket_in_netns_params *params = arg;
216
217         if(setns(params->netns, CLONE_NEWNET) == -1) {
218                 meshlink_errno = MESHLINK_EINVAL;
219         } else {
220                 params->fd = socket(params->domain, params->type, params->protocol);
221         }
222
223         return NULL;
224 }
225
226 static int socket_in_netns(int domain, int type, int protocol, int netns) {
227         if(netns == -1) {
228                 return socket(domain, type, protocol);
229         }
230
231         struct socket_in_netns_params params = {domain, type, protocol, netns, -1};
232
233         pthread_t thr;
234
235         if(pthread_create(&thr, NULL, socket_in_netns_thread, &params) == 0) {
236                 pthread_join(thr, NULL);
237         }
238
239         return params.fd;
240 }
241
242 // Find out what local address a socket would use if we connect to the given address.
243 // We do this using connect() on a UDP socket, so the kernel has to resolve the address
244 // of both endpoints, but this will actually not send any UDP packet.
245 static bool getlocaladdrname(char *destaddr, char *host, socklen_t hostlen, int netns) {
246         struct addrinfo *rai = NULL;
247         const struct addrinfo hint = {
248                 .ai_family = AF_UNSPEC,
249                 .ai_socktype = SOCK_DGRAM,
250                 .ai_protocol = IPPROTO_UDP,
251         };
252
253         if(getaddrinfo(destaddr, "80", &hint, &rai) || !rai) {
254                 return false;
255         }
256
257         int sock = socket_in_netns(rai->ai_family, rai->ai_socktype, rai->ai_protocol, netns);
258
259         if(sock == -1) {
260                 freeaddrinfo(rai);
261                 return false;
262         }
263
264         if(connect(sock, rai->ai_addr, rai->ai_addrlen) && !sockwouldblock(errno)) {
265                 closesocket(sock);
266                 freeaddrinfo(rai);
267                 return false;
268         }
269
270         freeaddrinfo(rai);
271
272         struct sockaddr_storage sn;
273         socklen_t sl = sizeof(sn);
274
275         if(getsockname(sock, (struct sockaddr *)&sn, &sl)) {
276                 closesocket(sock);
277                 return false;
278         }
279
280         closesocket(sock);
281
282         if(getnameinfo((struct sockaddr *)&sn, sl, host, hostlen, NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV)) {
283                 return false;
284         }
285
286         return true;
287 }
288
289 char *meshlink_get_external_address(meshlink_handle_t *mesh) {
290         return meshlink_get_external_address_for_family(mesh, AF_UNSPEC);
291 }
292
293 char *meshlink_get_external_address_for_family(meshlink_handle_t *mesh, int family) {
294         char *hostname = NULL;
295
296         logger(mesh, MESHLINK_DEBUG, "Trying to discover externally visible hostname...\n");
297         struct addrinfo *ai = str2addrinfo("meshlink.io", "80", SOCK_STREAM);
298         static const char request[] = "GET http://www.meshlink.io/host.cgi HTTP/1.0\r\n\r\n";
299         char line[256];
300
301         for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) {
302                 if(family != AF_UNSPEC && aip->ai_family != family) {
303                         continue;
304                 }
305
306                 int s = socket_in_netns(aip->ai_family, aip->ai_socktype, aip->ai_protocol, mesh->netns);
307
308                 if(s >= 0) {
309                         set_timeout(s, 5000);
310
311                         if(connect(s, aip->ai_addr, aip->ai_addrlen)) {
312                                 closesocket(s);
313                                 s = -1;
314                         }
315                 }
316
317                 if(s >= 0) {
318                         send(s, request, sizeof(request) - 1, 0);
319                         int len = recv(s, line, sizeof(line) - 1, MSG_WAITALL);
320
321                         if(len > 0) {
322                                 line[len] = 0;
323
324                                 if(line[len - 1] == '\n') {
325                                         line[--len] = 0;
326                                 }
327
328                                 char *p = strrchr(line, '\n');
329
330                                 if(p && p[1]) {
331                                         hostname = xstrdup(p + 1);
332                                 }
333                         }
334
335                         closesocket(s);
336
337                         if(hostname) {
338                                 break;
339                         }
340                 }
341         }
342
343         if(ai) {
344                 freeaddrinfo(ai);
345         }
346
347         // Check that the hostname is reasonable
348         if(hostname && !is_valid_hostname(hostname)) {
349                 free(hostname);
350                 hostname = NULL;
351         }
352
353         if(!hostname) {
354                 meshlink_errno = MESHLINK_ERESOLV;
355         }
356
357         return hostname;
358 }
359
360 char *meshlink_get_local_address_for_family(meshlink_handle_t *mesh, int family) {
361         (void)mesh;
362
363         // Determine address of the local interface used for outgoing connections.
364         char localaddr[NI_MAXHOST];
365         bool success = false;
366
367         if(family == AF_INET) {
368                 success = getlocaladdrname("93.184.216.34", localaddr, sizeof(localaddr), mesh->netns);
369         } else if(family == AF_INET6) {
370                 success = getlocaladdrname("2606:2800:220:1:248:1893:25c8:1946", localaddr, sizeof(localaddr), mesh->netns);
371         }
372
373         if(!success) {
374                 meshlink_errno = MESHLINK_ENETWORK;
375                 return NULL;
376         }
377
378         return xstrdup(localaddr);
379 }
380
381 void remove_duplicate_hostnames(char *host[], char *port[], int n) {
382         for(int i = 0; i < n; i++) {
383                 if(!host[i]) {
384                         continue;
385                 }
386
387                 // Ignore duplicate hostnames
388                 bool found = false;
389
390                 for(int j = 0; j < i; j++) {
391                         if(!host[j]) {
392                                 continue;
393                         }
394
395                         if(strcmp(host[i], host[j])) {
396                                 continue;
397                         }
398
399                         if(strcmp(port[i], port[j])) {
400                                 continue;
401                         }
402
403                         found = true;
404                         break;
405                 }
406
407                 if(found) {
408                         free(host[i]);
409                         free(port[i]);
410                         host[i] = NULL;
411                         port[i] = NULL;
412                         continue;
413                 }
414         }
415 }
416
417 // This gets the hostname part for use in invitation URLs
418 static char *get_my_hostname(meshlink_handle_t *mesh, uint32_t flags) {
419         char *hostname[4] = {NULL};
420         char *port[4] = {NULL};
421         char *hostport = NULL;
422
423         if(!(flags & (MESHLINK_INVITE_LOCAL | MESHLINK_INVITE_PUBLIC))) {
424                 flags |= MESHLINK_INVITE_LOCAL | MESHLINK_INVITE_PUBLIC;
425         }
426
427         if(!(flags & (MESHLINK_INVITE_IPV4 | MESHLINK_INVITE_IPV6))) {
428                 flags |= MESHLINK_INVITE_IPV4 | MESHLINK_INVITE_IPV6;
429         }
430
431         // Add local addresses if requested
432         if(flags & MESHLINK_INVITE_LOCAL) {
433                 if(flags & MESHLINK_INVITE_IPV4) {
434                         hostname[0] = meshlink_get_local_address_for_family(mesh, AF_INET);
435                 }
436
437                 if(flags & MESHLINK_INVITE_IPV6) {
438                         hostname[1] = meshlink_get_local_address_for_family(mesh, AF_INET6);
439                 }
440         }
441
442         // Add public/canonical addresses if requested
443         if(flags & MESHLINK_INVITE_PUBLIC) {
444                 // Try the CanonicalAddress first
445                 char filename[PATH_MAX] = "";
446                 snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, mesh->self->name);
447                 scan_for_canonical_address(filename, &hostname[2], &port[2]);
448
449                 if(!hostname[2]) {
450                         if(flags & MESHLINK_INVITE_IPV4) {
451                                 hostname[2] = meshlink_get_external_address_for_family(mesh, AF_INET);
452                         }
453
454                         if(flags & MESHLINK_INVITE_IPV6) {
455                                 hostname[3] = meshlink_get_external_address_for_family(mesh, AF_INET6);
456                         }
457                 }
458         }
459
460         for(int i = 0; i < 4; i++) {
461                 // Ensure we always have a port number
462                 if(hostname[i] && !port[i]) {
463                         port[i] = xstrdup(mesh->myport);
464                 }
465         }
466
467         remove_duplicate_hostnames(hostname, port, 4);
468
469         if(!(flags & MESHLINK_INVITE_NUMERIC)) {
470                 for(int i = 0; i < 4; i++) {
471                         if(!hostname[i]) {
472                                 continue;
473                         }
474
475                         // Convert what we have to a sockaddr
476                         struct addrinfo *ai_in, *ai_out;
477                         struct addrinfo hint = {
478                                 .ai_family = AF_UNSPEC,
479                                 .ai_flags = AI_NUMERICSERV,
480                                 .ai_socktype = SOCK_STREAM,
481                         };
482                         int err = getaddrinfo(hostname[i], port[i], &hint, &ai_in);
483
484                         if(err || !ai_in) {
485                                 continue;
486                         }
487
488                         // Convert it to a hostname
489                         char resolved_host[NI_MAXHOST];
490                         char resolved_port[NI_MAXSERV];
491                         err = getnameinfo(ai_in->ai_addr, ai_in->ai_addrlen, resolved_host, sizeof resolved_host, resolved_port, sizeof resolved_port, NI_NUMERICSERV);
492
493                         if(err) {
494                                 freeaddrinfo(ai_in);
495                                 continue;
496                         }
497
498                         // Convert the hostname back to a sockaddr
499                         hint.ai_family = ai_in->ai_family;
500                         err = getaddrinfo(resolved_host, resolved_port, &hint, &ai_out);
501
502                         if(err || !ai_out) {
503                                 freeaddrinfo(ai_in);
504                                 continue;
505                         }
506
507                         // Check if it's still the same sockaddr
508                         if(ai_in->ai_addrlen != ai_out->ai_addrlen || memcmp(ai_in->ai_addr, ai_out->ai_addr, ai_in->ai_addrlen)) {
509                                 freeaddrinfo(ai_in);
510                                 freeaddrinfo(ai_out);
511                                 continue;
512                         }
513
514                         // Yes: replace the hostname with the resolved one
515                         free(hostname[i]);
516                         hostname[i] = xstrdup(resolved_host);
517
518                         freeaddrinfo(ai_in);
519                         freeaddrinfo(ai_out);
520                 }
521         }
522
523         // Remove duplicates again, since IPv4 and IPv6 addresses might map to the same hostname
524         remove_duplicate_hostnames(hostname, port, 4);
525
526         // Concatenate all unique address to the hostport string
527         for(int i = 0; i < 4; i++) {
528                 if(!hostname[i]) {
529                         continue;
530                 }
531
532                 // Ensure we have the same addresses in our own host config file.
533                 char *tmphostport;
534                 xasprintf(&tmphostport, "%s %s", hostname[i], port[i]);
535                 append_config_file(mesh, mesh->self->name, "Address", tmphostport);
536                 free(tmphostport);
537
538                 // Append the address to the hostport string
539                 char *newhostport;
540                 xasprintf(&newhostport, (strchr(hostname[i], ':') ? "%s%s[%s]:%s" : "%s%s%s:%s"), hostport ? hostport : "", hostport ? "," : "", hostname[i], port[i]);
541                 free(hostport);
542                 hostport = newhostport;
543
544                 free(hostname[i]);
545                 free(port[i]);
546         }
547
548         return hostport;
549 }
550
551 static char *get_line(const char **data) {
552         if(!data || !*data) {
553                 return NULL;
554         }
555
556         if(! **data) {
557                 *data = NULL;
558                 return NULL;
559         }
560
561         static char line[1024];
562         const char *end = strchr(*data, '\n');
563         size_t len = end ? (size_t)(end - *data) : strlen(*data);
564
565         if(len >= sizeof(line)) {
566                 logger(NULL, MESHLINK_ERROR, "Maximum line length exceeded!\n");
567                 return NULL;
568         }
569
570         if(len && !isprint(**data)) {
571                 abort();
572         }
573
574         memcpy(line, *data, len);
575         line[len] = 0;
576
577         if(end) {
578                 *data = end + 1;
579         } else {
580                 *data = NULL;
581         }
582
583         return line;
584 }
585
586 static char *get_value(const char *data, const char *var) {
587         char *line = get_line(&data);
588
589         if(!line) {
590                 return NULL;
591         }
592
593         char *sep = line + strcspn(line, " \t=");
594         char *val = sep + strspn(sep, " \t");
595
596         if(*val == '=') {
597                 val += 1 + strspn(val + 1, " \t");
598         }
599
600         *sep = 0;
601
602         if(strcasecmp(line, var)) {
603                 return NULL;
604         }
605
606         return val;
607 }
608
609 static bool try_bind(int port) {
610         struct addrinfo *ai = NULL;
611         struct addrinfo hint = {
612                 .ai_flags = AI_PASSIVE,
613                 .ai_family = AF_UNSPEC,
614                 .ai_socktype = SOCK_STREAM,
615                 .ai_protocol = IPPROTO_TCP,
616         };
617
618         char portstr[16];
619         snprintf(portstr, sizeof(portstr), "%d", port);
620
621         if(getaddrinfo(NULL, portstr, &hint, &ai) || !ai) {
622                 return false;
623         }
624
625         while(ai) {
626                 int fd = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP);
627
628                 if(!fd) {
629                         freeaddrinfo(ai);
630                         return false;
631                 }
632
633                 int result = bind(fd, ai->ai_addr, ai->ai_addrlen);
634                 closesocket(fd);
635
636                 if(result) {
637                         freeaddrinfo(ai);
638                         return false;
639                 }
640
641                 ai = ai->ai_next;
642         }
643
644         freeaddrinfo(ai);
645         return true;
646 }
647
648 int check_port(meshlink_handle_t *mesh) {
649         for(int i = 0; i < 1000; i++) {
650                 int port = 0x1000 + (rand() & 0x7fff);
651
652                 if(try_bind(port)) {
653                         char filename[PATH_MAX];
654                         snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, mesh->name);
655                         FILE *f = fopen(filename, "a");
656
657                         if(!f) {
658                                 meshlink_errno = MESHLINK_ESTORAGE;
659                                 logger(mesh, MESHLINK_DEBUG, "Could not store Port.\n");
660                                 return 0;
661                         }
662
663                         fprintf(f, "Port = %d\n", port);
664                         fclose(f);
665                         return port;
666                 }
667         }
668
669         meshlink_errno = MESHLINK_ENETWORK;
670         logger(mesh, MESHLINK_DEBUG, "Could not find any available network port.\n");
671         return 0;
672 }
673
674 static void deltree(const char *dirname) {
675         DIR *d = opendir(dirname);
676
677         if(d) {
678                 struct dirent *ent;
679
680                 while((ent = readdir(d))) {
681                         if(ent->d_name[0] == '.') {
682                                 continue;
683                         }
684
685                         char filename[PATH_MAX];
686                         snprintf(filename, sizeof(filename), "%s" SLASH "%s", dirname, ent->d_name);
687
688                         if(unlink(filename)) {
689                                 deltree(filename);
690                         }
691                 }
692
693                 closedir(d);
694         }
695
696         rmdir(dirname);
697 }
698
699 static bool finalize_join(meshlink_handle_t *mesh) {
700         char *name = xstrdup(get_value(mesh->data, "Name"));
701
702         if(!name) {
703                 logger(mesh, MESHLINK_DEBUG, "No Name found in invitation!\n");
704                 return false;
705         }
706
707         if(!check_id(name)) {
708                 logger(mesh, MESHLINK_DEBUG, "Invalid Name found in invitation: %s!\n", name);
709                 return false;
710         }
711
712         char filename[PATH_MAX];
713         snprintf(filename, sizeof(filename), "%s" SLASH "meshlink.conf", mesh->confbase);
714
715         FILE *f = fopen(filename, "w");
716
717         if(!f) {
718                 logger(mesh, MESHLINK_DEBUG, "Could not create file %s: %s\n", filename, strerror(errno));
719                 return false;
720         }
721
722         fprintf(f, "Name = %s\n", name);
723
724         // Wipe all old host config files and invitations
725         snprintf(filename, sizeof(filename), "%s" SLASH "hosts", mesh->confbase);
726         deltree(filename);
727
728         if(mkdir(filename, 0777) && errno != EEXIST) {
729                 logger(mesh, MESHLINK_DEBUG, "Could not create directory %s: %s\n", filename, strerror(errno));
730                 return false;
731         }
732
733         snprintf(filename, sizeof(filename), "%s" SLASH "invitations", mesh->confbase);
734         deltree(filename);
735
736         // Create a new host config file for ourself
737         snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
738         FILE *fh = fopen(filename, "w");
739
740         if(!fh) {
741                 logger(mesh, MESHLINK_DEBUG, "Could not create file %s: %s\n", filename, strerror(errno));
742                 fclose(f);
743                 return false;
744         }
745
746         // Filter first chunk on approved keywords, split between meshlink.conf and hosts/Name
747         // Other chunks go unfiltered to their respective host config files
748         const char *p = mesh->data;
749         char *l, *value;
750
751         while((l = get_line(&p))) {
752                 // Ignore comments
753                 if(*l == '#') {
754                         continue;
755                 }
756
757                 // Split line into variable and value
758                 int len = strcspn(l, "\t =");
759                 value = l + len;
760                 value += strspn(value, "\t ");
761
762                 if(*value == '=') {
763                         value++;
764                         value += strspn(value, "\t ");
765                 }
766
767                 l[len] = 0;
768
769                 // Is it a Name?
770                 if(!strcasecmp(l, "Name"))
771                         if(strcmp(value, name)) {
772                                 break;
773                         } else {
774                                 continue;
775                         } else if(!strcasecmp(l, "NetName")) {
776                         continue;
777                 }
778
779                 // Check the list of known variables
780                 bool found = false;
781                 int i;
782
783                 for(i = 0; variables[i].name; i++) {
784                         if(strcasecmp(l, variables[i].name)) {
785                                 continue;
786                         }
787
788                         found = true;
789                         break;
790                 }
791
792                 // Ignore unknown and unsafe variables
793                 if(!found) {
794                         logger(mesh, MESHLINK_DEBUG, "Ignoring unknown variable '%s' in invitation.\n", l);
795                         continue;
796                 } else if(!(variables[i].type & VAR_SAFE)) {
797                         logger(mesh, MESHLINK_DEBUG, "Ignoring unsafe variable '%s' in invitation.\n", l);
798                         continue;
799                 }
800
801                 // Copy the safe variable to the right config file
802                 fprintf(variables[i].type & VAR_HOST ? fh : f, "%s = %s\n", l, value);
803         }
804
805         fclose(f);
806
807         while(l && !strcasecmp(l, "Name")) {
808                 if(!check_id(value)) {
809                         logger(mesh, MESHLINK_DEBUG, "Invalid Name found in invitation.\n");
810                         return false;
811                 }
812
813                 if(!strcmp(value, name)) {
814                         logger(mesh, MESHLINK_DEBUG, "Secondary chunk would overwrite our own host config file.\n");
815                         return false;
816                 }
817
818                 snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, value);
819                 f = fopen(filename, "w");
820
821                 if(!f) {
822                         logger(mesh, MESHLINK_DEBUG, "Could not create file %s: %s\n", filename, strerror(errno));
823                         return false;
824                 }
825
826                 while((l = get_line(&p))) {
827                         if(!strcmp(l, "#---------------------------------------------------------------#")) {
828                                 continue;
829                         }
830
831                         int len = strcspn(l, "\t =");
832
833                         if(len == 4 && !strncasecmp(l, "Name", 4)) {
834                                 value = l + len;
835                                 value += strspn(value, "\t ");
836
837                                 if(*value == '=') {
838                                         value++;
839                                         value += strspn(value, "\t ");
840                                 }
841
842                                 l[len] = 0;
843                                 break;
844                         }
845
846                         fputs(l, f);
847                         fputc('\n', f);
848                 }
849
850                 fclose(f);
851         }
852
853         char *b64key = ecdsa_get_base64_public_key(mesh->self->connection->ecdsa);
854
855         if(!b64key) {
856                 fclose(fh);
857                 return false;
858         }
859
860         fprintf(fh, "ECDSAPublicKey = %s\n", b64key);
861         fprintf(fh, "Port = %s\n", mesh->myport);
862
863         fclose(fh);
864
865         sptps_send_record(&(mesh->sptps), 1, b64key, strlen(b64key));
866         free(b64key);
867
868         free(mesh->name);
869         free(mesh->self->name);
870         free(mesh->self->connection->name);
871         mesh->name = xstrdup(name);
872         mesh->self->name = xstrdup(name);
873         mesh->self->connection->name = name;
874
875         logger(mesh, MESHLINK_DEBUG, "Configuration stored in: %s\n", mesh->confbase);
876
877         load_all_nodes(mesh);
878
879         return true;
880 }
881
882 static bool invitation_send(void *handle, uint8_t type, const void *data, size_t len) {
883         (void)type;
884         meshlink_handle_t *mesh = handle;
885         const char *ptr = data;
886
887         while(len) {
888                 int result = send(mesh->sock, ptr, len, 0);
889
890                 if(result == -1 && errno == EINTR) {
891                         continue;
892                 } else if(result <= 0) {
893                         return false;
894                 }
895
896                 ptr += result;
897                 len -= result;
898         }
899
900         return true;
901 }
902
903 static bool invitation_receive(void *handle, uint8_t type, const void *msg, uint16_t len) {
904         meshlink_handle_t *mesh = handle;
905
906         switch(type) {
907         case SPTPS_HANDSHAKE:
908                 return sptps_send_record(&(mesh->sptps), 0, mesh->cookie, sizeof(mesh)->cookie);
909
910         case 0:
911                 mesh->data = xrealloc(mesh->data, mesh->thedatalen + len + 1);
912                 memcpy(mesh->data + mesh->thedatalen, msg, len);
913                 mesh->thedatalen += len;
914                 mesh->data[mesh->thedatalen] = 0;
915                 break;
916
917         case 1:
918                 mesh->thedatalen = 0;
919                 return finalize_join(mesh);
920
921         case 2:
922                 logger(mesh, MESHLINK_DEBUG, "Invitation succesfully accepted.\n");
923                 shutdown(mesh->sock, SHUT_RDWR);
924                 mesh->success = true;
925                 break;
926
927         default:
928                 return false;
929         }
930
931         return true;
932 }
933
934 static bool recvline(meshlink_handle_t *mesh, size_t len) {
935         char *newline = NULL;
936
937         if(!mesh->sock) {
938                 abort();
939         }
940
941         while(!(newline = memchr(mesh->buffer, '\n', mesh->blen))) {
942                 int result = recv(mesh->sock, mesh->buffer + mesh->blen, sizeof(mesh)->buffer - mesh->blen, 0);
943
944                 if(result == -1 && errno == EINTR) {
945                         continue;
946                 } else if(result <= 0) {
947                         return false;
948                 }
949
950                 mesh->blen += result;
951         }
952
953         if((size_t)(newline - mesh->buffer) >= len) {
954                 return false;
955         }
956
957         len = newline - mesh->buffer;
958
959         memcpy(mesh->line, mesh->buffer, len);
960         mesh->line[len] = 0;
961         memmove(mesh->buffer, newline + 1, mesh->blen - len - 1);
962         mesh->blen -= len + 1;
963
964         return true;
965 }
966 static bool sendline(int fd, char *format, ...) {
967         static char buffer[4096];
968         char *p = buffer;
969         int blen = 0;
970         va_list ap;
971
972         va_start(ap, format);
973         blen = vsnprintf(buffer, sizeof(buffer), format, ap);
974         va_end(ap);
975
976         if(blen < 1 || (size_t)blen >= sizeof(buffer)) {
977                 return false;
978         }
979
980         buffer[blen] = '\n';
981         blen++;
982
983         while(blen) {
984                 int result = send(fd, p, blen, MSG_NOSIGNAL);
985
986                 if(result == -1 && errno == EINTR) {
987                         continue;
988                 } else if(result <= 0) {
989                         return false;
990                 }
991
992                 p += result;
993                 blen -= result;
994         }
995
996         return true;
997 }
998
999 static const char *errstr[] = {
1000         [MESHLINK_OK] = "No error",
1001         [MESHLINK_EINVAL] = "Invalid argument",
1002         [MESHLINK_ENOMEM] = "Out of memory",
1003         [MESHLINK_ENOENT] = "No such node",
1004         [MESHLINK_EEXIST] = "Node already exists",
1005         [MESHLINK_EINTERNAL] = "Internal error",
1006         [MESHLINK_ERESOLV] = "Could not resolve hostname",
1007         [MESHLINK_ESTORAGE] = "Storage error",
1008         [MESHLINK_ENETWORK] = "Network error",
1009         [MESHLINK_EPEER] = "Error communicating with peer",
1010         [MESHLINK_ENOTSUP] = "Operation not supported",
1011         [MESHLINK_EBUSY] = "MeshLink instance already in use",
1012 };
1013
1014 const char *meshlink_strerror(meshlink_errno_t err) {
1015         if((int)err < 0 || err >= sizeof(errstr) / sizeof(*errstr)) {
1016                 return "Invalid error code";
1017         }
1018
1019         return errstr[err];
1020 }
1021
1022 static bool ecdsa_keygen(meshlink_handle_t *mesh) {
1023         ecdsa_t *key;
1024         FILE *f;
1025         char pubname[PATH_MAX], privname[PATH_MAX];
1026
1027         logger(mesh, MESHLINK_DEBUG, "Generating ECDSA keypair:\n");
1028
1029         if(!(key = ecdsa_generate())) {
1030                 logger(mesh, MESHLINK_DEBUG, "Error during key generation!\n");
1031                 meshlink_errno = MESHLINK_EINTERNAL;
1032                 return false;
1033         } else {
1034                 logger(mesh, MESHLINK_DEBUG, "Done.\n");
1035         }
1036
1037         if(snprintf(privname, sizeof(privname), "%s" SLASH "ecdsa_key.priv", mesh->confbase) >= PATH_MAX) {
1038                 logger(mesh, MESHLINK_DEBUG, "Filename too long: %s" SLASH "ecdsa_key.priv\n", mesh->confbase);
1039                 meshlink_errno = MESHLINK_ESTORAGE;
1040                 return false;
1041         }
1042
1043         f = fopen(privname, "wb");
1044
1045         if(!f) {
1046                 meshlink_errno = MESHLINK_ESTORAGE;
1047                 return false;
1048         }
1049
1050 #ifdef HAVE_FCHMOD
1051         fchmod(fileno(f), 0600);
1052 #endif
1053
1054         if(!ecdsa_write_pem_private_key(key, f)) {
1055                 logger(mesh, MESHLINK_DEBUG, "Error writing private key!\n");
1056                 ecdsa_free(key);
1057                 fclose(f);
1058                 meshlink_errno = MESHLINK_EINTERNAL;
1059                 return false;
1060         }
1061
1062         fclose(f);
1063
1064         snprintf(pubname, sizeof(pubname), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, mesh->name);
1065         f = fopen(pubname, "a");
1066
1067         if(!f) {
1068                 meshlink_errno = MESHLINK_ESTORAGE;
1069                 return false;
1070         }
1071
1072         char *pubkey = ecdsa_get_base64_public_key(key);
1073         fprintf(f, "ECDSAPublicKey = %s\n", pubkey);
1074         free(pubkey);
1075
1076         fclose(f);
1077         ecdsa_free(key);
1078
1079         return true;
1080 }
1081
1082 static struct timeval idle(event_loop_t *loop, void *data) {
1083         (void)loop;
1084         meshlink_handle_t *mesh = data;
1085         struct timeval t, tmin = {3600, 0};
1086
1087         for splay_each(node_t, n, mesh->nodes) {
1088                 if(!n->utcp) {
1089                         continue;
1090                 }
1091
1092                 t = utcp_timeout(n->utcp);
1093
1094                 if(timercmp(&t, &tmin, <)) {
1095                         tmin = t;
1096                 }
1097         }
1098
1099         return tmin;
1100 }
1101
1102 // Get our local address(es) by simulating connecting to an Internet host.
1103 static void add_local_addresses(meshlink_handle_t *mesh) {
1104         char host[NI_MAXHOST];
1105         char entry[MAX_STRING_SIZE];
1106
1107         // IPv4 example.org
1108
1109         if(getlocaladdrname("93.184.216.34", host, sizeof(host), mesh->netns)) {
1110                 snprintf(entry, sizeof(entry), "%s %s", host, mesh->myport);
1111                 append_config_file(mesh, mesh->name, "Address", entry);
1112         }
1113
1114         // IPv6 example.org
1115
1116         if(getlocaladdrname("2606:2800:220:1:248:1893:25c8:1946", host, sizeof(host), mesh->netns)) {
1117                 snprintf(entry, sizeof(entry), "%s %s", host, mesh->myport);
1118                 append_config_file(mesh, mesh->name, "Address", entry);
1119         }
1120 }
1121
1122 static bool meshlink_setup(meshlink_handle_t *mesh) {
1123         if(mkdir(mesh->confbase, 0777) && errno != EEXIST) {
1124                 logger(mesh, MESHLINK_DEBUG, "Could not create directory %s: %s\n", mesh->confbase, strerror(errno));
1125                 meshlink_errno = MESHLINK_ESTORAGE;
1126                 return false;
1127         }
1128
1129         char filename[PATH_MAX];
1130         snprintf(filename, sizeof(filename), "%s" SLASH "hosts", mesh->confbase);
1131
1132         if(mkdir(filename, 0777) && errno != EEXIST) {
1133                 logger(mesh, MESHLINK_DEBUG, "Could not create directory %s: %s\n", filename, strerror(errno));
1134                 meshlink_errno = MESHLINK_ESTORAGE;
1135                 return false;
1136         }
1137
1138         snprintf(filename, sizeof(filename), "%s" SLASH "meshlink.conf", mesh->confbase);
1139
1140         if(!access(filename, F_OK)) {
1141                 logger(mesh, MESHLINK_DEBUG, "Configuration file %s already exists!\n", filename);
1142                 meshlink_errno = MESHLINK_EEXIST;
1143                 return false;
1144         }
1145
1146         FILE *f = fopen(filename, "w");
1147
1148         if(!f) {
1149                 logger(mesh, MESHLINK_DEBUG, "Could not create file %s: %s\n", filename, strerror(errno));
1150                 meshlink_errno = MESHLINK_ESTORAGE;
1151                 return false;
1152         }
1153
1154         fprintf(f, "Name = %s\n", mesh->name);
1155         fclose(f);
1156
1157         if(!ecdsa_keygen(mesh)) {
1158                 meshlink_errno = MESHLINK_EINTERNAL;
1159                 unlink(filename);
1160                 return false;
1161         }
1162
1163         if(check_port(mesh) == 0) {
1164                 meshlink_errno = MESHLINK_ENETWORK;
1165                 unlink(filename);
1166                 return false;
1167         }
1168
1169         return true;
1170 }
1171
1172 static void *setup_network_in_netns_thread(void *arg) {
1173         meshlink_handle_t *mesh = arg;
1174
1175         if(setns(mesh->netns, CLONE_NEWNET) != 0) {
1176                 return NULL;
1177         }
1178
1179         bool success = setup_network(mesh);
1180         add_local_addresses(mesh);
1181         return success ? arg : NULL;
1182 }
1183
1184 meshlink_open_params_t *meshlink_open_params_init(const char *confbase, const char *name, const char *appname, dev_class_t devclass) {
1185         if(!confbase || !*confbase) {
1186                 logger(NULL, MESHLINK_ERROR, "No confbase given!\n");
1187                 meshlink_errno = MESHLINK_EINVAL;
1188                 return NULL;
1189         }
1190
1191         if(!appname || !*appname) {
1192                 logger(NULL, MESHLINK_ERROR, "No appname given!\n");
1193                 meshlink_errno = MESHLINK_EINVAL;
1194                 return NULL;
1195         }
1196
1197         if(strchr(appname, ' ')) {
1198                 logger(NULL, MESHLINK_ERROR, "Invalid appname given!\n");
1199                 meshlink_errno = MESHLINK_EINVAL;
1200                 return NULL;
1201         }
1202
1203         if(!name || !*name) {
1204                 logger(NULL, MESHLINK_ERROR, "No name given!\n");
1205                 //return NULL;
1206         } else { //check name only if there is a name != NULL
1207                 if(!check_id(name)) {
1208                         logger(NULL, MESHLINK_ERROR, "Invalid name given!\n");
1209                         meshlink_errno = MESHLINK_EINVAL;
1210                         return NULL;
1211                 }
1212         }
1213
1214         if((int)devclass < 0 || devclass > _DEV_CLASS_MAX) {
1215                 logger(NULL, MESHLINK_ERROR, "Invalid devclass given!\n");
1216                 meshlink_errno = MESHLINK_EINVAL;
1217                 return NULL;
1218         }
1219
1220         meshlink_open_params_t *params = xzalloc(sizeof * params);
1221
1222         params->confbase = xstrdup(confbase);
1223         params->name = xstrdup(name);
1224         params->appname = xstrdup(appname);
1225         params->devclass = devclass;
1226         params->netns = -1;
1227
1228         return params;
1229 }
1230
1231 void meshlink_open_params_free(meshlink_open_params_t *params) {
1232         if(!params) {
1233                 meshlink_errno = MESHLINK_EINVAL;
1234                 return;
1235         }
1236
1237         free(params->confbase);
1238         free(params->name);
1239         free(params->appname);
1240
1241         free(params);
1242 }
1243
1244 meshlink_handle_t *meshlink_open(const char *confbase, const char *name, const char *appname, dev_class_t devclass) {
1245         /* Create a temporary struct on the stack, to avoid allocating and freeing one. */
1246         meshlink_open_params_t params = {NULL};
1247
1248         params.confbase = (char *)confbase;
1249         params.name = (char *)name;
1250         params.appname = (char *)appname;
1251         params.devclass = devclass;
1252         params.netns = -1;
1253
1254         return meshlink_open_ex(&params);
1255 }
1256 meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) {
1257         // Validate arguments provided by the application
1258         bool usingname = false;
1259
1260         logger(NULL, MESHLINK_DEBUG, "meshlink_open called\n");
1261
1262         if(!params->confbase || !*params->confbase) {
1263                 logger(NULL, MESHLINK_ERROR, "No confbase given!\n");
1264                 meshlink_errno = MESHLINK_EINVAL;
1265                 return NULL;
1266         }
1267
1268         if(!params->appname || !*params->appname) {
1269                 logger(NULL, MESHLINK_ERROR, "No appname given!\n");
1270                 meshlink_errno = MESHLINK_EINVAL;
1271                 return NULL;
1272         }
1273
1274         if(strchr(params->appname, ' ')) {
1275                 logger(NULL, MESHLINK_ERROR, "Invalid appname given!\n");
1276                 meshlink_errno = MESHLINK_EINVAL;
1277                 return NULL;
1278         }
1279
1280         if(!params->name || !*params->name) {
1281                 logger(NULL, MESHLINK_ERROR, "No name given!\n");
1282                 //return NULL;
1283         } else { //check name only if there is a name != NULL
1284
1285                 if(!check_id(params->name)) {
1286                         logger(NULL, MESHLINK_ERROR, "Invalid name given!\n");
1287                         meshlink_errno = MESHLINK_EINVAL;
1288                         return NULL;
1289                 } else {
1290                         usingname = true;
1291                 }
1292         }
1293
1294         if((int)params->devclass < 0 || params->devclass > _DEV_CLASS_MAX) {
1295                 logger(NULL, MESHLINK_ERROR, "Invalid devclass given!\n");
1296                 meshlink_errno = MESHLINK_EINVAL;
1297                 return NULL;
1298         }
1299
1300         meshlink_handle_t *mesh = xzalloc(sizeof(meshlink_handle_t));
1301         mesh->confbase = xstrdup(params->confbase);
1302         mesh->appname = xstrdup(params->appname);
1303         mesh->devclass = params->devclass;
1304         mesh->discovery = true;
1305         mesh->invitation_timeout = 604800; // 1 week
1306         mesh->netns = params->netns;
1307
1308         if(usingname) {
1309                 mesh->name = xstrdup(params->name);
1310         }
1311
1312         // initialize mutex
1313         pthread_mutexattr_t attr;
1314         pthread_mutexattr_init(&attr);
1315         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
1316         pthread_mutex_init(&(mesh->mesh_mutex), &attr);
1317
1318         mesh->threadstarted = false;
1319         event_loop_init(&mesh->loop);
1320         mesh->loop.data = mesh;
1321
1322         meshlink_queue_init(&mesh->outpacketqueue);
1323
1324         // Check whether meshlink.conf already exists
1325
1326         char filename[PATH_MAX];
1327         snprintf(filename, sizeof(filename), "%s" SLASH "meshlink.conf", params->confbase);
1328
1329         if(access(filename, R_OK)) {
1330                 if(errno == ENOENT) {
1331                         // If not, create it
1332                         if(!meshlink_setup(mesh)) {
1333                                 // meshlink_errno is set by meshlink_setup()
1334                                 return NULL;
1335                         }
1336                 } else {
1337                         logger(NULL, MESHLINK_ERROR, "Cannot not read from %s: %s\n", filename, strerror(errno));
1338                         meshlink_close(mesh);
1339                         meshlink_errno = MESHLINK_ESTORAGE;
1340                         return NULL;
1341                 }
1342         }
1343
1344         // Open the configuration file and lock it
1345
1346         mesh->conffile = fopen(filename, "r");
1347
1348         if(!mesh->conffile) {
1349                 logger(NULL, MESHLINK_ERROR, "Cannot not open %s: %s\n", filename, strerror(errno));
1350                 meshlink_close(mesh);
1351                 meshlink_errno = MESHLINK_ESTORAGE;
1352                 return NULL;
1353         }
1354
1355 #ifdef FD_CLOEXEC
1356         fcntl(fileno(mesh->conffile), F_SETFD, FD_CLOEXEC);
1357 #endif
1358
1359 #ifdef HAVE_MINGW
1360         // TODO: use _locking()?
1361 #else
1362
1363         if(flock(fileno(mesh->conffile), LOCK_EX | LOCK_NB) != 0) {
1364                 logger(NULL, MESHLINK_ERROR, "Cannot lock %s: %s\n", filename, strerror(errno));
1365                 meshlink_close(mesh);
1366                 meshlink_errno = MESHLINK_EBUSY;
1367                 return NULL;
1368         }
1369
1370 #endif
1371
1372         // Read the configuration
1373
1374         init_configuration(&mesh->config);
1375
1376         if(!read_server_config(mesh)) {
1377                 meshlink_close(mesh);
1378                 meshlink_errno = MESHLINK_ESTORAGE;
1379                 return NULL;
1380         };
1381
1382 #ifdef HAVE_MINGW
1383         struct WSAData wsa_state;
1384
1385         WSAStartup(MAKEWORD(2, 2), &wsa_state);
1386
1387 #endif
1388
1389         // Setup up everything
1390         // TODO: we should not open listening sockets yet
1391
1392         bool success = false;
1393
1394         if(mesh->netns != -1) {
1395                 pthread_t thr;
1396
1397                 if(pthread_create(&thr, NULL, setup_network_in_netns_thread, mesh) == 0) {
1398                         void *retval = NULL;
1399                         success = pthread_join(thr, &retval) == 0 && retval;
1400                 }
1401         } else {
1402                 success = setup_network(mesh);
1403                 add_local_addresses(mesh);
1404         }
1405
1406         if(!success) {
1407                 meshlink_close(mesh);
1408                 meshlink_errno = MESHLINK_ENETWORK;
1409                 return NULL;
1410         }
1411
1412         idle_set(&mesh->loop, idle, mesh);
1413
1414         logger(NULL, MESHLINK_DEBUG, "meshlink_open returning\n");
1415         return mesh;
1416 }
1417
1418 static void *meshlink_main_loop(void *arg) {
1419         meshlink_handle_t *mesh = arg;
1420
1421         if(mesh->netns != -1) {
1422                 if(setns(mesh->netns, CLONE_NEWNET) != 0) {
1423                         return NULL;
1424                 }
1425         }
1426
1427         pthread_mutex_lock(&(mesh->mesh_mutex));
1428
1429         try_outgoing_connections(mesh);
1430
1431         logger(mesh, MESHLINK_DEBUG, "Starting main_loop...\n");
1432         main_loop(mesh);
1433         logger(mesh, MESHLINK_DEBUG, "main_loop returned.\n");
1434
1435         pthread_mutex_unlock(&(mesh->mesh_mutex));
1436         return NULL;
1437 }
1438
1439 bool meshlink_start(meshlink_handle_t *mesh) {
1440         if(!mesh) {
1441                 meshlink_errno = MESHLINK_EINVAL;
1442                 return false;
1443         }
1444
1445         logger(mesh, MESHLINK_DEBUG, "meshlink_start called\n");
1446
1447         pthread_mutex_lock(&(mesh->mesh_mutex));
1448
1449         if(mesh->threadstarted) {
1450                 logger(mesh, MESHLINK_DEBUG, "thread was already running\n");
1451                 pthread_mutex_unlock(&(mesh->mesh_mutex));
1452                 return true;
1453         }
1454
1455         if(mesh->listen_socket[0].tcp.fd < 0) {
1456                 logger(mesh, MESHLINK_ERROR, "Listening socket not open\n");
1457                 meshlink_errno = MESHLINK_ENETWORK;
1458                 return false;
1459         }
1460
1461         mesh->thedatalen = 0;
1462
1463         // TODO: open listening sockets first
1464
1465         //Check that a valid name is set
1466         if(!mesh->name) {
1467                 logger(mesh, MESHLINK_DEBUG, "No name given!\n");
1468                 meshlink_errno = MESHLINK_EINVAL;
1469                 pthread_mutex_unlock(&(mesh->mesh_mutex));
1470                 return false;
1471         }
1472
1473         // Start the main thread
1474
1475         event_loop_start(&mesh->loop);
1476
1477         if(pthread_create(&mesh->thread, NULL, meshlink_main_loop, mesh) != 0) {
1478                 logger(mesh, MESHLINK_DEBUG, "Could not start thread: %s\n", strerror(errno));
1479                 memset(&mesh->thread, 0, sizeof(mesh)->thread);
1480                 meshlink_errno = MESHLINK_EINTERNAL;
1481                 event_loop_stop(&mesh->loop);
1482                 pthread_mutex_unlock(&(mesh->mesh_mutex));
1483                 return false;
1484         }
1485
1486         mesh->threadstarted = true;
1487
1488 #if HAVE_CATTA
1489
1490         if(mesh->discovery) {
1491                 discovery_start(mesh);
1492         }
1493
1494 #endif
1495
1496         pthread_mutex_unlock(&(mesh->mesh_mutex));
1497         return true;
1498 }
1499
1500 void meshlink_stop(meshlink_handle_t *mesh) {
1501         if(!mesh) {
1502                 meshlink_errno = MESHLINK_EINVAL;
1503                 return;
1504         }
1505
1506         pthread_mutex_lock(&(mesh->mesh_mutex));
1507         logger(mesh, MESHLINK_DEBUG, "meshlink_stop called\n");
1508
1509 #if HAVE_CATTA
1510
1511         // Stop discovery
1512         if(mesh->discovery) {
1513                 discovery_stop(mesh);
1514         }
1515
1516 #endif
1517
1518         // Shut down the main thread
1519         event_loop_stop(&mesh->loop);
1520
1521         // Send ourselves a UDP packet to kick the event loop
1522         for(int i = 0; i < mesh->listen_sockets; i++) {
1523                 sockaddr_t sa;
1524                 socklen_t salen = sizeof(sa.sa);
1525
1526                 if(getsockname(mesh->listen_socket[i].udp.fd, &sa.sa, &salen) == -1) {
1527                         logger(mesh, MESHLINK_ERROR, "System call `%s' failed: %s", "getsockname", sockstrerror(sockerrno));
1528                         continue;
1529                 }
1530
1531                 if(sendto(mesh->listen_socket[i].udp.fd, "", 1, MSG_NOSIGNAL, &sa.sa, salen) == -1) {
1532                         logger(mesh, MESHLINK_ERROR, "Could not send a UDP packet to ourself: %s", sockstrerror(sockerrno));
1533                 }
1534         }
1535
1536         if(mesh->threadstarted) {
1537                 // Wait for the main thread to finish
1538                 pthread_mutex_unlock(&(mesh->mesh_mutex));
1539                 pthread_join(mesh->thread, NULL);
1540                 pthread_mutex_lock(&(mesh->mesh_mutex));
1541
1542                 mesh->threadstarted = false;
1543         }
1544
1545         // Close all metaconnections
1546         if(mesh->connections) {
1547                 for(list_node_t *node = mesh->connections->head, *next; node; node = next) {
1548                         next = node->next;
1549                         connection_t *c = node->data;
1550                         c->outgoing = NULL;
1551                         terminate_connection(mesh, c, false);
1552                 }
1553         }
1554
1555         if(mesh->outgoings) {
1556                 list_delete_list(mesh->outgoings);
1557                 mesh->outgoings = NULL;
1558         }
1559
1560         pthread_mutex_unlock(&(mesh->mesh_mutex));
1561 }
1562
1563 void meshlink_close(meshlink_handle_t *mesh) {
1564         if(!mesh || !mesh->confbase) {
1565                 meshlink_errno = MESHLINK_EINVAL;
1566                 return;
1567         }
1568
1569         // stop can be called even if mesh has not been started
1570         meshlink_stop(mesh);
1571
1572         // lock is not released after this
1573         pthread_mutex_lock(&(mesh->mesh_mutex));
1574
1575         // Close and free all resources used.
1576
1577         close_network_connections(mesh);
1578
1579         logger(mesh, MESHLINK_INFO, "Terminating");
1580
1581         exit_configuration(&mesh->config);
1582         event_loop_exit(&mesh->loop);
1583
1584 #ifdef HAVE_MINGW
1585
1586         if(mesh->confbase) {
1587                 WSACleanup();
1588         }
1589
1590 #endif
1591
1592         ecdsa_free(mesh->invitation_key);
1593
1594         if(mesh->netns != -1) {
1595                 close(mesh->netns);
1596         }
1597
1598         free(mesh->name);
1599         free(mesh->appname);
1600         free(mesh->confbase);
1601         pthread_mutex_destroy(&(mesh->mesh_mutex));
1602
1603         if(mesh->conffile) {
1604                 fclose(mesh->conffile);
1605         }
1606
1607         memset(mesh, 0, sizeof(*mesh));
1608
1609         free(mesh);
1610 }
1611
1612 bool meshlink_destroy(const char *confbase) {
1613         if(!confbase) {
1614                 meshlink_errno = MESHLINK_EINVAL;
1615                 return false;
1616         }
1617
1618         char filename[PATH_MAX];
1619         snprintf(filename, sizeof(filename), "%s" SLASH "meshlink.conf", confbase);
1620
1621         if(unlink(filename)) {
1622                 if(errno == ENOENT) {
1623                         meshlink_errno = MESHLINK_ENOENT;
1624                         return false;
1625                 } else {
1626                         logger(NULL, MESHLINK_ERROR, "Cannot delete %s: %s\n", filename, strerror(errno));
1627                         meshlink_errno = MESHLINK_ESTORAGE;
1628                         return false;
1629                 }
1630         }
1631
1632         deltree(confbase);
1633
1634         return true;
1635 }
1636
1637 void meshlink_set_receive_cb(meshlink_handle_t *mesh, meshlink_receive_cb_t cb) {
1638         if(!mesh) {
1639                 meshlink_errno = MESHLINK_EINVAL;
1640                 return;
1641         }
1642
1643         pthread_mutex_lock(&(mesh->mesh_mutex));
1644         mesh->receive_cb = cb;
1645         pthread_mutex_unlock(&(mesh->mesh_mutex));
1646 }
1647
1648 void meshlink_set_node_status_cb(meshlink_handle_t *mesh, meshlink_node_status_cb_t cb) {
1649         if(!mesh) {
1650                 meshlink_errno = MESHLINK_EINVAL;
1651                 return;
1652         }
1653
1654         pthread_mutex_lock(&(mesh->mesh_mutex));
1655         mesh->node_status_cb = cb;
1656         pthread_mutex_unlock(&(mesh->mesh_mutex));
1657 }
1658
1659 void meshlink_set_node_duplicate_cb(meshlink_handle_t *mesh, meshlink_node_duplicate_cb_t cb) {
1660         if(!mesh) {
1661                 meshlink_errno = MESHLINK_EINVAL;
1662                 return;
1663         }
1664
1665         pthread_mutex_lock(&(mesh->mesh_mutex));
1666         mesh->node_duplicate_cb = cb;
1667         pthread_mutex_unlock(&(mesh->mesh_mutex));
1668 }
1669
1670 void meshlink_set_log_cb(meshlink_handle_t *mesh, meshlink_log_level_t level, meshlink_log_cb_t cb) {
1671         if(mesh) {
1672                 pthread_mutex_lock(&(mesh->mesh_mutex));
1673                 mesh->log_cb = cb;
1674                 mesh->log_level = cb ? level : 0;
1675                 pthread_mutex_unlock(&(mesh->mesh_mutex));
1676         } else {
1677                 global_log_cb = cb;
1678                 global_log_level = cb ? level : 0;
1679         }
1680 }
1681
1682 bool meshlink_send(meshlink_handle_t *mesh, meshlink_node_t *destination, const void *data, size_t len) {
1683         meshlink_packethdr_t *hdr;
1684
1685         // Validate arguments
1686         if(!mesh || !destination || len >= MAXSIZE - sizeof(*hdr)) {
1687                 meshlink_errno = MESHLINK_EINVAL;
1688                 return false;
1689         }
1690
1691         if(!len) {
1692                 return true;
1693         }
1694
1695         if(!data) {
1696                 meshlink_errno = MESHLINK_EINVAL;
1697                 return false;
1698         }
1699
1700         // Prepare the packet
1701         vpn_packet_t *packet = malloc(sizeof(*packet));
1702
1703         if(!packet) {
1704                 meshlink_errno = MESHLINK_ENOMEM;
1705                 return false;
1706         }
1707
1708         packet->probe = false;
1709         packet->tcp = false;
1710         packet->len = len + sizeof(*hdr);
1711
1712         hdr = (meshlink_packethdr_t *)packet->data;
1713         memset(hdr, 0, sizeof(*hdr));
1714         // leave the last byte as 0 to make sure strings are always
1715         // null-terminated if they are longer than the buffer
1716         strncpy((char *)hdr->destination, destination->name, (sizeof(hdr)->destination) - 1);
1717         strncpy((char *)hdr->source, mesh->self->name, (sizeof(hdr)->source) - 1);
1718
1719         memcpy(packet->data + sizeof(*hdr), data, len);
1720
1721         // Queue it
1722         if(!meshlink_queue_push(&mesh->outpacketqueue, packet)) {
1723                 free(packet);
1724                 meshlink_errno = MESHLINK_ENOMEM;
1725                 return false;
1726         }
1727
1728         // Notify event loop
1729         signal_trigger(&(mesh->loop), &(mesh->datafromapp));
1730
1731         return true;
1732 }
1733
1734 void meshlink_send_from_queue(event_loop_t *loop, meshlink_handle_t *mesh) {
1735         (void)loop;
1736         vpn_packet_t *packet = meshlink_queue_pop(&mesh->outpacketqueue);
1737
1738         if(!packet) {
1739                 return;
1740         }
1741
1742         mesh->self->in_packets++;
1743         mesh->self->in_bytes += packet->len;
1744         route(mesh, mesh->self, packet);
1745 }
1746
1747 ssize_t meshlink_get_pmtu(meshlink_handle_t *mesh, meshlink_node_t *destination) {
1748         if(!mesh || !destination) {
1749                 meshlink_errno = MESHLINK_EINVAL;
1750                 return -1;
1751         }
1752
1753         pthread_mutex_lock(&(mesh->mesh_mutex));
1754
1755         node_t *n = (node_t *)destination;
1756
1757         if(!n->status.reachable) {
1758                 pthread_mutex_unlock(&(mesh->mesh_mutex));
1759                 return 0;
1760
1761         } else if(n->mtuprobes > 30 && n->minmtu) {
1762                 pthread_mutex_unlock(&(mesh->mesh_mutex));
1763                 return n->minmtu;
1764         } else {
1765                 pthread_mutex_unlock(&(mesh->mesh_mutex));
1766                 return MTU;
1767         }
1768 }
1769
1770 char *meshlink_get_fingerprint(meshlink_handle_t *mesh, meshlink_node_t *node) {
1771         if(!mesh || !node) {
1772                 meshlink_errno = MESHLINK_EINVAL;
1773                 return NULL;
1774         }
1775
1776         pthread_mutex_lock(&(mesh->mesh_mutex));
1777
1778         node_t *n = (node_t *)node;
1779
1780         if(!node_read_ecdsa_public_key(mesh, n) || !n->ecdsa) {
1781                 meshlink_errno = MESHLINK_EINTERNAL;
1782                 pthread_mutex_unlock(&(mesh->mesh_mutex));
1783                 return false;
1784         }
1785
1786         char *fingerprint = ecdsa_get_base64_public_key(n->ecdsa);
1787
1788         if(!fingerprint) {
1789                 meshlink_errno = MESHLINK_EINTERNAL;
1790         }
1791
1792         pthread_mutex_unlock(&(mesh->mesh_mutex));
1793         return fingerprint;
1794 }
1795
1796 meshlink_node_t *meshlink_get_self(meshlink_handle_t *mesh) {
1797         if(!mesh) {
1798                 meshlink_errno = MESHLINK_EINVAL;
1799                 return NULL;
1800         }
1801
1802         return (meshlink_node_t *)mesh->self;
1803 }
1804
1805 meshlink_node_t *meshlink_get_node(meshlink_handle_t *mesh, const char *name) {
1806         if(!mesh || !name) {
1807                 meshlink_errno = MESHLINK_EINVAL;
1808                 return NULL;
1809         }
1810
1811         meshlink_node_t *node = NULL;
1812
1813         pthread_mutex_lock(&(mesh->mesh_mutex));
1814         node = (meshlink_node_t *)lookup_node(mesh, (char *)name); // TODO: make lookup_node() use const
1815         pthread_mutex_unlock(&(mesh->mesh_mutex));
1816         return node;
1817 }
1818
1819 meshlink_node_t **meshlink_get_all_nodes(meshlink_handle_t *mesh, meshlink_node_t **nodes, size_t *nmemb) {
1820         if(!mesh || !nmemb || (*nmemb && !nodes)) {
1821                 meshlink_errno = MESHLINK_EINVAL;
1822                 return NULL;
1823         }
1824
1825         meshlink_node_t **result;
1826
1827         //lock mesh->nodes
1828         pthread_mutex_lock(&(mesh->mesh_mutex));
1829
1830         *nmemb = mesh->nodes->count;
1831         result = realloc(nodes, *nmemb * sizeof(*nodes));
1832
1833         if(result) {
1834                 meshlink_node_t **p = result;
1835
1836                 for splay_each(node_t, n, mesh->nodes) {
1837                         *p++ = (meshlink_node_t *)n;
1838                 }
1839         } else {
1840                 *nmemb = 0;
1841                 free(nodes);
1842                 meshlink_errno = MESHLINK_ENOMEM;
1843         }
1844
1845         pthread_mutex_unlock(&(mesh->mesh_mutex));
1846
1847         return result;
1848 }
1849
1850 bool meshlink_sign(meshlink_handle_t *mesh, const void *data, size_t len, void *signature, size_t *siglen) {
1851         if(!mesh || !data || !len || !signature || !siglen) {
1852                 meshlink_errno = MESHLINK_EINVAL;
1853                 return false;
1854         }
1855
1856         if(*siglen < MESHLINK_SIGLEN) {
1857                 meshlink_errno = MESHLINK_EINVAL;
1858                 return false;
1859         }
1860
1861         pthread_mutex_lock(&(mesh->mesh_mutex));
1862
1863         if(!ecdsa_sign(mesh->self->connection->ecdsa, data, len, signature)) {
1864                 meshlink_errno = MESHLINK_EINTERNAL;
1865                 pthread_mutex_unlock(&(mesh->mesh_mutex));
1866                 return false;
1867         }
1868
1869         *siglen = MESHLINK_SIGLEN;
1870         pthread_mutex_unlock(&(mesh->mesh_mutex));
1871         return true;
1872 }
1873
1874 bool meshlink_verify(meshlink_handle_t *mesh, meshlink_node_t *source, const void *data, size_t len, const void *signature, size_t siglen) {
1875         if(!mesh || !data || !len || !signature) {
1876                 meshlink_errno = MESHLINK_EINVAL;
1877                 return false;
1878         }
1879
1880         if(siglen != MESHLINK_SIGLEN) {
1881                 meshlink_errno = MESHLINK_EINVAL;
1882                 return false;
1883         }
1884
1885         pthread_mutex_lock(&(mesh->mesh_mutex));
1886
1887         bool rval = false;
1888
1889         struct node_t *n = (struct node_t *)source;
1890         node_read_ecdsa_public_key(mesh, n);
1891
1892         if(!n->ecdsa) {
1893                 meshlink_errno = MESHLINK_EINTERNAL;
1894                 rval = false;
1895         } else {
1896                 rval = ecdsa_verify(((struct node_t *)source)->ecdsa, data, len, signature);
1897         }
1898
1899         pthread_mutex_unlock(&(mesh->mesh_mutex));
1900         return rval;
1901 }
1902
1903 static bool refresh_invitation_key(meshlink_handle_t *mesh) {
1904         char filename[PATH_MAX];
1905
1906         pthread_mutex_lock(&(mesh->mesh_mutex));
1907
1908         snprintf(filename, sizeof(filename), "%s" SLASH "invitations", mesh->confbase);
1909
1910         if(mkdir(filename, 0700) && errno != EEXIST) {
1911                 logger(mesh, MESHLINK_DEBUG, "Could not create directory %s: %s\n", filename, strerror(errno));
1912                 meshlink_errno = MESHLINK_ESTORAGE;
1913                 pthread_mutex_unlock(&(mesh->mesh_mutex));
1914                 return false;
1915         }
1916
1917         // Count the number of valid invitations, clean up old ones
1918         DIR *dir = opendir(filename);
1919
1920         if(!dir) {
1921                 logger(mesh, MESHLINK_DEBUG, "Could not read directory %s: %s\n", filename, strerror(errno));
1922                 meshlink_errno = MESHLINK_ESTORAGE;
1923                 pthread_mutex_unlock(&(mesh->mesh_mutex));
1924                 return false;
1925         }
1926
1927         errno = 0;
1928         int count = 0;
1929         struct dirent *ent;
1930         time_t deadline = time(NULL) - 604800; // 1 week in the past
1931
1932         while((ent = readdir(dir))) {
1933                 if(strlen(ent->d_name) != 24) {
1934                         continue;
1935                 }
1936
1937                 char invname[PATH_MAX];
1938                 struct stat st;
1939
1940                 if(snprintf(invname, sizeof(invname), "%s" SLASH "%s", filename, ent->d_name) >= PATH_MAX) {
1941                         logger(mesh, MESHLINK_DEBUG, "Filename too long: %s" SLASH "%s", filename, ent->d_name);
1942                         continue;
1943                 }
1944
1945                 if(!stat(invname, &st)) {
1946                         if(mesh->invitation_key && deadline < st.st_mtime) {
1947                                 count++;
1948                         } else {
1949                                 unlink(invname);
1950                         }
1951                 } else {
1952                         logger(mesh, MESHLINK_DEBUG, "Could not stat %s: %s\n", invname, strerror(errno));
1953                         errno = 0;
1954                 }
1955         }
1956
1957         if(errno) {
1958                 logger(mesh, MESHLINK_DEBUG, "Error while reading directory %s: %s\n", filename, strerror(errno));
1959                 closedir(dir);
1960                 meshlink_errno = MESHLINK_ESTORAGE;
1961                 pthread_mutex_unlock(&(mesh->mesh_mutex));
1962                 return false;
1963         }
1964
1965         closedir(dir);
1966
1967         snprintf(filename, sizeof(filename), "%s" SLASH "invitations" SLASH "ecdsa_key.priv", mesh->confbase);
1968
1969         // Remove the key if there are no outstanding invitations.
1970         if(!count) {
1971                 unlink(filename);
1972
1973                 if(mesh->invitation_key) {
1974                         ecdsa_free(mesh->invitation_key);
1975                         mesh->invitation_key = NULL;
1976                 }
1977         }
1978
1979         if(mesh->invitation_key) {
1980                 pthread_mutex_unlock(&(mesh->mesh_mutex));
1981                 return true;
1982         }
1983
1984         // Create a new key if necessary.
1985         FILE *f = fopen(filename, "rb");
1986
1987         if(!f) {
1988                 if(errno != ENOENT) {
1989                         logger(mesh, MESHLINK_DEBUG, "Could not read %s: %s\n", filename, strerror(errno));
1990                         meshlink_errno = MESHLINK_ESTORAGE;
1991                         pthread_mutex_unlock(&(mesh->mesh_mutex));
1992                         return false;
1993                 }
1994
1995                 mesh->invitation_key = ecdsa_generate();
1996
1997                 if(!mesh->invitation_key) {
1998                         logger(mesh, MESHLINK_DEBUG, "Could not generate a new key!\n");
1999                         meshlink_errno = MESHLINK_EINTERNAL;
2000                         pthread_mutex_unlock(&(mesh->mesh_mutex));
2001                         return false;
2002                 }
2003
2004                 f = fopen(filename, "wb");
2005
2006                 if(!f) {
2007                         logger(mesh, MESHLINK_DEBUG, "Could not write %s: %s\n", filename, strerror(errno));
2008                         meshlink_errno = MESHLINK_ESTORAGE;
2009                         pthread_mutex_unlock(&(mesh->mesh_mutex));
2010                         return false;
2011                 }
2012
2013                 chmod(filename, 0600);
2014                 ecdsa_write_pem_private_key(mesh->invitation_key, f);
2015                 fclose(f);
2016         } else {
2017                 mesh->invitation_key = ecdsa_read_pem_private_key(f);
2018                 fclose(f);
2019
2020                 if(!mesh->invitation_key) {
2021                         logger(mesh, MESHLINK_DEBUG, "Could not read private key from %s\n", filename);
2022                         meshlink_errno = MESHLINK_ESTORAGE;
2023                 }
2024         }
2025
2026         pthread_mutex_unlock(&(mesh->mesh_mutex));
2027         return mesh->invitation_key;
2028 }
2029
2030 bool meshlink_set_canonical_address(meshlink_handle_t *mesh, meshlink_node_t *node, const char *address, const char *port) {
2031         if(!mesh || !node || !address) {
2032                 meshlink_errno = MESHLINK_EINVAL;
2033                 return false;
2034         }
2035
2036         if(!is_valid_hostname(address)) {
2037                 logger(mesh, MESHLINK_DEBUG, "Invalid character in address: %s\n", address);
2038                 meshlink_errno = MESHLINK_EINVAL;
2039                 return false;
2040         }
2041
2042         if(port && !is_valid_port(port)) {
2043                 logger(mesh, MESHLINK_DEBUG, "Invalid character in port: %s\n", address);
2044                 meshlink_errno = MESHLINK_EINVAL;
2045                 return false;
2046         }
2047
2048         char *canonical_address;
2049
2050         if(port) {
2051                 xasprintf(&canonical_address, "%s %s", address, port);
2052         } else {
2053                 canonical_address = xstrdup(address);
2054         }
2055
2056         pthread_mutex_lock(&(mesh->mesh_mutex));
2057         bool rval = modify_config_file(mesh, node->name, "CanonicalAddress", canonical_address, 1);
2058         pthread_mutex_unlock(&(mesh->mesh_mutex));
2059
2060         free(canonical_address);
2061         return rval;
2062 }
2063
2064 bool meshlink_add_address(meshlink_handle_t *mesh, const char *address) {
2065         return meshlink_set_canonical_address(mesh, (meshlink_node_t *)mesh->self, address, NULL);
2066 }
2067
2068 bool meshlink_add_external_address(meshlink_handle_t *mesh) {
2069         if(!mesh) {
2070                 meshlink_errno = MESHLINK_EINVAL;
2071                 return false;
2072         }
2073
2074         char *address = meshlink_get_external_address(mesh);
2075
2076         if(!address) {
2077                 return false;
2078         }
2079
2080         bool rval = false;
2081
2082         pthread_mutex_lock(&(mesh->mesh_mutex));
2083         rval = append_config_file(mesh, mesh->self->name, "Address", address);
2084         pthread_mutex_unlock(&(mesh->mesh_mutex));
2085
2086         free(address);
2087         return rval;
2088 }
2089
2090 int meshlink_get_port(meshlink_handle_t *mesh) {
2091         if(!mesh) {
2092                 meshlink_errno = MESHLINK_EINVAL;
2093                 return -1;
2094         }
2095
2096         if(!mesh->myport) {
2097                 meshlink_errno = MESHLINK_EINTERNAL;
2098                 return -1;
2099         }
2100
2101         return atoi(mesh->myport);
2102 }
2103
2104 bool meshlink_set_port(meshlink_handle_t *mesh, int port) {
2105         if(!mesh || port < 0 || port >= 65536 || mesh->threadstarted) {
2106                 meshlink_errno = MESHLINK_EINVAL;
2107                 return false;
2108         }
2109
2110         if(mesh->myport && port == atoi(mesh->myport)) {
2111                 return true;
2112         }
2113
2114         if(!try_bind(port)) {
2115                 meshlink_errno = MESHLINK_ENETWORK;
2116                 return false;
2117         }
2118
2119         bool rval = false;
2120
2121         pthread_mutex_lock(&(mesh->mesh_mutex));
2122
2123         if(mesh->threadstarted) {
2124                 meshlink_errno = MESHLINK_EINVAL;
2125                 goto done;
2126         }
2127
2128         close_network_connections(mesh);
2129         exit_configuration(&mesh->config);
2130
2131         char portstr[10];
2132         snprintf(portstr, sizeof(portstr), "%d", port);
2133         portstr[sizeof(portstr) - 1] = 0;
2134
2135         modify_config_file(mesh, mesh->name, "Port", portstr, true);
2136
2137         init_configuration(&mesh->config);
2138
2139         if(!read_server_config(mesh)) {
2140                 meshlink_errno = MESHLINK_ESTORAGE;
2141         } else if(!setup_network(mesh)) {
2142                 meshlink_errno = MESHLINK_ENETWORK;
2143         } else {
2144                 rval = true;
2145         }
2146
2147 done:
2148         pthread_mutex_unlock(&(mesh->mesh_mutex));
2149
2150         return rval;
2151 }
2152
2153 void meshlink_set_invitation_timeout(meshlink_handle_t *mesh, int timeout) {
2154         mesh->invitation_timeout = timeout;
2155 }
2156
2157 char *meshlink_invite_ex(meshlink_handle_t *mesh, const char *name, uint32_t flags) {
2158         if(!mesh) {
2159                 meshlink_errno = MESHLINK_EINVAL;
2160                 return NULL;
2161         }
2162
2163         pthread_mutex_lock(&(mesh->mesh_mutex));
2164
2165         // Check validity of the new node's name
2166         if(!check_id(name)) {
2167                 logger(mesh, MESHLINK_DEBUG, "Invalid name for node.\n");
2168                 meshlink_errno = MESHLINK_EINVAL;
2169                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2170                 return NULL;
2171         }
2172
2173         // Ensure no host configuration file with that name exists
2174         char filename[PATH_MAX];
2175         snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
2176
2177         if(!access(filename, F_OK)) {
2178                 logger(mesh, MESHLINK_DEBUG, "A host config file for %s already exists!\n", name);
2179                 meshlink_errno = MESHLINK_EEXIST;
2180                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2181                 return NULL;
2182         }
2183
2184         // Ensure no other nodes know about this name
2185         if(meshlink_get_node(mesh, name)) {
2186                 logger(mesh, MESHLINK_DEBUG, "A node with name %s is already known!\n", name);
2187                 meshlink_errno = MESHLINK_EEXIST;
2188                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2189                 return NULL;
2190         }
2191
2192         // Get the local address
2193         char *address = get_my_hostname(mesh, flags);
2194
2195         if(!address) {
2196                 logger(mesh, MESHLINK_DEBUG, "No Address known for ourselves!\n");
2197                 meshlink_errno = MESHLINK_ERESOLV;
2198                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2199                 return NULL;
2200         }
2201
2202         if(!refresh_invitation_key(mesh)) {
2203                 meshlink_errno = MESHLINK_EINTERNAL;
2204                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2205                 return NULL;
2206         }
2207
2208         char hash[64];
2209
2210         // Create a hash of the key.
2211         char *fingerprint = ecdsa_get_base64_public_key(mesh->invitation_key);
2212         sha512(fingerprint, strlen(fingerprint), hash);
2213         b64encode_urlsafe(hash, hash, 18);
2214
2215         // Create a random cookie for this invitation.
2216         char cookie[25];
2217         randomize(cookie, 18);
2218
2219         // Create a filename that doesn't reveal the cookie itself
2220         char buf[18 + strlen(fingerprint)];
2221         char cookiehash[64];
2222         memcpy(buf, cookie, 18);
2223         memcpy(buf + 18, fingerprint, sizeof(buf) - 18);
2224         sha512(buf, sizeof(buf), cookiehash);
2225         b64encode_urlsafe(cookiehash, cookiehash, 18);
2226
2227         b64encode_urlsafe(cookie, cookie, 18);
2228
2229         free(fingerprint);
2230
2231         // Create a file containing the details of the invitation.
2232         snprintf(filename, sizeof(filename), "%s" SLASH "invitations" SLASH "%s", mesh->confbase, cookiehash);
2233         int ifd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
2234
2235         if(!ifd) {
2236                 logger(mesh, MESHLINK_DEBUG, "Could not create invitation file %s: %s\n", filename, strerror(errno));
2237                 meshlink_errno = MESHLINK_ESTORAGE;
2238                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2239                 return NULL;
2240         }
2241
2242         FILE *f = fdopen(ifd, "w");
2243
2244         if(!f) {
2245                 abort();
2246         }
2247
2248         // Fill in the details.
2249         fprintf(f, "Name = %s\n", name);
2250         fprintf(f, "ConnectTo = %s\n", mesh->self->name);
2251
2252         // Copy Broadcast and Mode
2253         snprintf(filename, sizeof(filename), "%s" SLASH "meshlink.conf", mesh->confbase);
2254         FILE *tc = fopen(filename,  "r");
2255
2256         if(tc) {
2257                 char buf[1024];
2258
2259                 while(fgets(buf, sizeof(buf), tc)) {
2260                         if((!strncasecmp(buf, "Mode", 4) && strchr(" \t=", buf[4]))
2261                                         || (!strncasecmp(buf, "Broadcast", 9) && strchr(" \t=", buf[9]))) {
2262                                 fputs(buf, f);
2263
2264                                 // Make sure there is a newline character.
2265                                 if(!strchr(buf, '\n')) {
2266                                         fputc('\n', f);
2267                                 }
2268                         }
2269                 }
2270
2271                 fclose(tc);
2272         } else {
2273                 logger(mesh, MESHLINK_DEBUG, "Could not create %s: %s\n", filename, strerror(errno));
2274                 meshlink_errno = MESHLINK_ESTORAGE;
2275                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2276                 return NULL;
2277         }
2278
2279         fprintf(f, "#---------------------------------------------------------------#\n");
2280         fprintf(f, "Name = %s\n", mesh->self->name);
2281
2282         snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, mesh->self->name);
2283         fcopy(f, filename);
2284         fclose(f);
2285
2286         // Create an URL from the local address, key hash and cookie
2287         char *url;
2288         xasprintf(&url, "%s/%s%s", address, hash, cookie);
2289         free(address);
2290
2291         pthread_mutex_unlock(&(mesh->mesh_mutex));
2292         return url;
2293 }
2294
2295 char *meshlink_invite(meshlink_handle_t *mesh, const char *name) {
2296         return meshlink_invite_ex(mesh, name, 0);
2297 }
2298
2299 bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) {
2300         if(!mesh || !invitation) {
2301                 meshlink_errno = MESHLINK_EINVAL;
2302                 return false;
2303         }
2304
2305         pthread_mutex_lock(&(mesh->mesh_mutex));
2306
2307         //Before doing meshlink_join make sure we are not connected to another mesh
2308         if(mesh->threadstarted) {
2309                 logger(mesh, MESHLINK_DEBUG, "Already connected to a mesh\n");
2310                 meshlink_errno = MESHLINK_EINVAL;
2311                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2312                 return false;
2313         }
2314
2315         //TODO: think of a better name for this variable, or of a different way to tokenize the invitation URL.
2316         char copy[strlen(invitation) + 1];
2317         strcpy(copy, invitation);
2318
2319         // Split the invitation URL into a list of hostname/port tuples, a key hash and a cookie.
2320
2321         char *slash = strchr(copy, '/');
2322
2323         if(!slash) {
2324                 goto invalid;
2325         }
2326
2327         *slash++ = 0;
2328
2329         if(strlen(slash) != 48) {
2330                 goto invalid;
2331         }
2332
2333         char *address = copy;
2334         char *port = NULL;
2335
2336         if(!b64decode(slash, mesh->hash, 18) || !b64decode(slash + 24, mesh->cookie, 18)) {
2337                 goto invalid;
2338         }
2339
2340         // Generate a throw-away key for the invitation.
2341         ecdsa_t *key = ecdsa_generate();
2342
2343         if(!key) {
2344                 meshlink_errno = MESHLINK_EINTERNAL;
2345                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2346                 return false;
2347         }
2348
2349         char *b64key = ecdsa_get_base64_public_key(key);
2350         char *comma;
2351         mesh->sock = -1;
2352
2353         while(address && *address) {
2354                 // We allow commas in the address part to support multiple addresses in one invitation URL.
2355                 comma = strchr(address, ',');
2356
2357                 if(comma) {
2358                         *comma++ = 0;
2359                 }
2360
2361                 // Split of the port
2362                 port = strrchr(address, ':');
2363
2364                 if(!port) {
2365                         goto invalid;
2366                 }
2367
2368                 *port++ = 0;
2369
2370                 // IPv6 address are enclosed in brackets, per RFC 3986
2371                 if(*address == '[') {
2372                         address++;
2373                         char *bracket = strchr(address, ']');
2374
2375                         if(!bracket) {
2376                                 goto invalid;
2377                         }
2378
2379                         *bracket++ = 0;
2380
2381                         if(*bracket) {
2382                                 goto invalid;
2383                         }
2384                 }
2385
2386                 // Connect to the meshlink daemon mentioned in the URL.
2387                 struct addrinfo *ai = str2addrinfo(address, port, SOCK_STREAM);
2388
2389                 if(ai) {
2390                         for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) {
2391                                 mesh->sock = socket_in_netns(aip->ai_family, aip->ai_socktype, aip->ai_protocol, mesh->netns);
2392
2393                                 if(mesh->sock == -1) {
2394                                         logger(mesh, MESHLINK_DEBUG, "Could not open socket: %s\n", strerror(errno));
2395                                         meshlink_errno = MESHLINK_ENETWORK;
2396                                         continue;
2397                                 }
2398
2399                                 set_timeout(mesh->sock, 5000);
2400
2401                                 if(connect(mesh->sock, aip->ai_addr, aip->ai_addrlen)) {
2402                                         logger(mesh, MESHLINK_DEBUG, "Could not connect to %s port %s: %s\n", address, port, strerror(errno));
2403                                         meshlink_errno = MESHLINK_ENETWORK;
2404                                         closesocket(mesh->sock);
2405                                         mesh->sock = -1;
2406                                         continue;
2407                                 }
2408                         }
2409
2410                         freeaddrinfo(ai);
2411                 } else {
2412                         meshlink_errno = MESHLINK_ERESOLV;
2413                 }
2414
2415                 if(mesh->sock != -1 || !comma) {
2416                         break;
2417                 }
2418
2419                 address = comma;
2420         }
2421
2422         if(mesh->sock == -1) {
2423                 pthread_mutex_unlock(&mesh->mesh_mutex);
2424                 return false;
2425         }
2426
2427         logger(mesh, MESHLINK_DEBUG, "Connected to %s port %s...\n", address, port);
2428
2429         // Tell him we have an invitation, and give him our throw-away key.
2430
2431         mesh->blen = 0;
2432
2433         if(!sendline(mesh->sock, "0 ?%s %d.%d %s", b64key, PROT_MAJOR, 1, mesh->appname)) {
2434                 logger(mesh, MESHLINK_DEBUG, "Error sending request to %s port %s: %s\n", address, port, strerror(errno));
2435                 closesocket(mesh->sock);
2436                 meshlink_errno = MESHLINK_ENETWORK;
2437                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2438                 return false;
2439         }
2440
2441         free(b64key);
2442
2443         char hisname[4096] = "";
2444         int code, hismajor, hisminor = 0;
2445
2446         if(!recvline(mesh, sizeof(mesh)->line) || sscanf(mesh->line, "%d %s %d.%d", &code, hisname, &hismajor, &hisminor) < 3 || code != 0 || hismajor != PROT_MAJOR || !check_id(hisname) || !recvline(mesh, sizeof(mesh)->line) || !rstrip(mesh->line) || sscanf(mesh->line, "%d ", &code) != 1 || code != ACK || strlen(mesh->line) < 3) {
2447                 logger(mesh, MESHLINK_DEBUG, "Cannot read greeting from peer\n");
2448                 closesocket(mesh->sock);
2449                 meshlink_errno = MESHLINK_ENETWORK;
2450                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2451                 return false;
2452         }
2453
2454         // Check if the hash of the key he gave us matches the hash in the URL.
2455         char *fingerprint = mesh->line + 2;
2456         char hishash[64];
2457
2458         if(sha512(fingerprint, strlen(fingerprint), hishash)) {
2459                 logger(mesh, MESHLINK_DEBUG, "Could not create hash\n%s\n", mesh->line + 2);
2460                 meshlink_errno = MESHLINK_EINTERNAL;
2461                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2462                 return false;
2463         }
2464
2465         if(memcmp(hishash, mesh->hash, 18)) {
2466                 logger(mesh, MESHLINK_DEBUG, "Peer has an invalid key!\n%s\n", mesh->line + 2);
2467                 meshlink_errno = MESHLINK_EPEER;
2468                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2469                 return false;
2470
2471         }
2472
2473         ecdsa_t *hiskey = ecdsa_set_base64_public_key(fingerprint);
2474
2475         if(!hiskey) {
2476                 meshlink_errno = MESHLINK_EINTERNAL;
2477                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2478                 return false;
2479         }
2480
2481         // Start an SPTPS session
2482         if(!sptps_start(&mesh->sptps, mesh, true, false, key, hiskey, meshlink_invitation_label, sizeof(meshlink_invitation_label), invitation_send, invitation_receive)) {
2483                 meshlink_errno = MESHLINK_EINTERNAL;
2484                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2485                 return false;
2486         }
2487
2488         // Feed rest of input buffer to SPTPS
2489         if(!sptps_receive_data(&mesh->sptps, mesh->buffer, mesh->blen)) {
2490                 meshlink_errno = MESHLINK_EPEER;
2491                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2492                 return false;
2493         }
2494
2495         int len;
2496
2497         while((len = recv(mesh->sock, mesh->line, sizeof(mesh)->line, 0))) {
2498                 if(len < 0) {
2499                         if(errno == EINTR) {
2500                                 continue;
2501                         }
2502
2503                         logger(mesh, MESHLINK_DEBUG, "Error reading data from %s port %s: %s\n", address, port, strerror(errno));
2504                         meshlink_errno = MESHLINK_ENETWORK;
2505                         pthread_mutex_unlock(&(mesh->mesh_mutex));
2506                         return false;
2507                 }
2508
2509                 if(!sptps_receive_data(&mesh->sptps, mesh->line, len)) {
2510                         meshlink_errno = MESHLINK_EPEER;
2511                         pthread_mutex_unlock(&(mesh->mesh_mutex));
2512                         return false;
2513                 }
2514         }
2515
2516         sptps_stop(&mesh->sptps);
2517         ecdsa_free(hiskey);
2518         ecdsa_free(key);
2519         closesocket(mesh->sock);
2520
2521         if(!mesh->success) {
2522                 logger(mesh, MESHLINK_DEBUG, "Connection closed by peer, invitation cancelled.\n");
2523                 meshlink_errno = MESHLINK_EPEER;
2524                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2525                 return false;
2526         }
2527
2528         pthread_mutex_unlock(&(mesh->mesh_mutex));
2529         return true;
2530
2531 invalid:
2532         logger(mesh, MESHLINK_DEBUG, "Invalid invitation URL\n");
2533         meshlink_errno = MESHLINK_EINVAL;
2534         pthread_mutex_unlock(&(mesh->mesh_mutex));
2535         return false;
2536 }
2537
2538 char *meshlink_export(meshlink_handle_t *mesh) {
2539         if(!mesh) {
2540                 meshlink_errno = MESHLINK_EINVAL;
2541                 return NULL;
2542         }
2543
2544         pthread_mutex_lock(&(mesh->mesh_mutex));
2545
2546         char filename[PATH_MAX];
2547         snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, mesh->self->name);
2548         FILE *f = fopen(filename, "r");
2549
2550         if(!f) {
2551                 logger(mesh, MESHLINK_DEBUG, "Could not open %s: %s\n", filename, strerror(errno));
2552                 meshlink_errno = MESHLINK_ESTORAGE;
2553                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2554                 return NULL;
2555         }
2556
2557         fseek(f, 0, SEEK_END);
2558         int fsize = ftell(f);
2559         rewind(f);
2560
2561         size_t len = fsize + 9 + strlen(mesh->self->name);
2562         char *buf = xmalloc(len);
2563         snprintf(buf, len, "Name = %s\n", mesh->self->name);
2564
2565         if(fread(buf + len - fsize - 1, fsize, 1, f) != 1) {
2566                 logger(mesh, MESHLINK_DEBUG, "Error reading from %s: %s\n", filename, strerror(errno));
2567                 fclose(f);
2568                 free(buf);
2569                 meshlink_errno = MESHLINK_ESTORAGE;
2570                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2571                 return NULL;
2572         }
2573
2574         fclose(f);
2575         buf[len - 1] = 0;
2576
2577         pthread_mutex_unlock(&(mesh->mesh_mutex));
2578         return buf;
2579 }
2580
2581 bool meshlink_import(meshlink_handle_t *mesh, const char *data) {
2582         if(!mesh || !data) {
2583                 meshlink_errno = MESHLINK_EINVAL;
2584                 return false;
2585         }
2586
2587         pthread_mutex_lock(&(mesh->mesh_mutex));
2588
2589         if(strncmp(data, "Name = ", 7)) {
2590                 logger(mesh, MESHLINK_DEBUG, "Invalid data\n");
2591                 meshlink_errno = MESHLINK_EPEER;
2592                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2593                 return false;
2594         }
2595
2596         char *end = strchr(data + 7, '\n');
2597
2598         if(!end) {
2599                 logger(mesh, MESHLINK_DEBUG, "Invalid data\n");
2600                 meshlink_errno = MESHLINK_EPEER;
2601                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2602                 return false;
2603         }
2604
2605         int len = end - (data + 7);
2606         char name[len + 1];
2607         memcpy(name, data + 7, len);
2608         name[len] = 0;
2609
2610         if(!check_id(name)) {
2611                 logger(mesh, MESHLINK_DEBUG, "Invalid Name\n");
2612                 meshlink_errno = MESHLINK_EPEER;
2613                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2614                 return false;
2615         }
2616
2617         char filename[PATH_MAX];
2618         snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
2619
2620         if(!access(filename, F_OK)) {
2621                 logger(mesh, MESHLINK_DEBUG, "File %s already exists, not importing\n", filename);
2622                 meshlink_errno = MESHLINK_EEXIST;
2623                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2624                 return false;
2625         }
2626
2627         if(errno != ENOENT) {
2628                 logger(mesh, MESHLINK_DEBUG, "Error accessing %s: %s\n", filename, strerror(errno));
2629                 meshlink_errno = MESHLINK_ESTORAGE;
2630                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2631                 return false;
2632         }
2633
2634         FILE *f = fopen(filename, "w");
2635
2636         if(!f) {
2637                 logger(mesh, MESHLINK_DEBUG, "Could not create %s: %s\n", filename, strerror(errno));
2638                 meshlink_errno = MESHLINK_ESTORAGE;
2639                 pthread_mutex_unlock(&(mesh->mesh_mutex));
2640                 return false;
2641         }
2642
2643         fwrite(end + 1, strlen(end + 1), 1, f);
2644         fclose(f);
2645
2646         load_all_nodes(mesh);
2647
2648         pthread_mutex_unlock(&(mesh->mesh_mutex));
2649         return true;
2650 }
2651
2652 void meshlink_blacklist(meshlink_handle_t *mesh, meshlink_node_t *node) {
2653         if(!mesh || !node) {
2654                 meshlink_errno = MESHLINK_EINVAL;
2655                 return;
2656         }
2657
2658         pthread_mutex_lock(&(mesh->mesh_mutex));
2659
2660         node_t *n;
2661         n = (node_t *)node;
2662         n->status.blacklisted = true;
2663         logger(mesh, MESHLINK_DEBUG, "Blacklisted %s.\n", node->name);
2664
2665         //Make blacklisting persistent in the config file
2666         append_config_file(mesh, n->name, "blacklisted", "yes");
2667
2668         //Immediately terminate any connections we have with the blacklisted node
2669         for list_each(connection_t, c, mesh->connections) {
2670                 if(c->node == n) {
2671                         terminate_connection(mesh, c, c->status.active);
2672                 }
2673         }
2674
2675         pthread_mutex_unlock(&(mesh->mesh_mutex));
2676 }
2677
2678 void meshlink_whitelist(meshlink_handle_t *mesh, meshlink_node_t *node) {
2679         if(!mesh || !node) {
2680                 meshlink_errno = MESHLINK_EINVAL;
2681                 return;
2682         }
2683
2684         pthread_mutex_lock(&(mesh->mesh_mutex));
2685
2686         node_t *n = (node_t *)node;
2687         n->status.blacklisted = false;
2688
2689         //TODO: remove blacklisted = yes from the config file
2690
2691         pthread_mutex_unlock(&(mesh->mesh_mutex));
2692         return;
2693 }
2694
2695 void meshlink_set_default_blacklist(meshlink_handle_t *mesh, bool blacklist) {
2696         mesh->default_blacklist = blacklist;
2697 }
2698
2699 /* Hint that a hostname may be found at an address
2700  * See header file for detailed comment.
2701  */
2702 void meshlink_hint_address(meshlink_handle_t *mesh, meshlink_node_t *node, const struct sockaddr *addr) {
2703         if(!mesh || !node || !addr) {
2704                 return;
2705         }
2706
2707         // Ignore hints about ourself.
2708         if((node_t *)node == mesh->self) {
2709                 return;
2710         }
2711
2712         pthread_mutex_lock(&(mesh->mesh_mutex));
2713
2714         char *host = NULL, *port = NULL, *str = NULL;
2715         sockaddr2str((const sockaddr_t *)addr, &host, &port);
2716
2717         if(host && port) {
2718                 xasprintf(&str, "%s %s", host, port);
2719
2720                 if((strncmp("fe80", host, 4) != 0) && (strncmp("127.", host, 4) != 0) && (strcmp("localhost", host) != 0)) {
2721                         modify_config_file(mesh, node->name, "Address", str, 5);
2722                 } else {
2723                         logger(mesh, MESHLINK_DEBUG, "Not adding Link Local IPv6 Address to config\n");
2724                 }
2725         }
2726
2727         free(str);
2728         free(host);
2729         free(port);
2730
2731         pthread_mutex_unlock(&(mesh->mesh_mutex));
2732         // @TODO do we want to fire off a connection attempt right away?
2733 }
2734
2735 static bool channel_pre_accept(struct utcp *utcp, uint16_t port) {
2736         (void)port;
2737         node_t *n = utcp->priv;
2738         meshlink_handle_t *mesh = n->mesh;
2739         return mesh->channel_accept_cb;
2740 }
2741
2742 static ssize_t channel_recv(struct utcp_connection *connection, const void *data, size_t len) {
2743         meshlink_channel_t *channel = connection->priv;
2744
2745         if(!channel) {
2746                 abort();
2747         }
2748
2749         node_t *n = channel->node;
2750         meshlink_handle_t *mesh = n->mesh;
2751
2752         if(n->status.destroyed) {
2753                 meshlink_channel_close(mesh, channel);
2754         } else if(channel->receive_cb) {
2755                 channel->receive_cb(mesh, channel, data, len);
2756         }
2757
2758         return len;
2759 }
2760
2761 static void channel_accept(struct utcp_connection *utcp_connection, uint16_t port) {
2762         node_t *n = utcp_connection->utcp->priv;
2763
2764         if(!n) {
2765                 abort();
2766         }
2767
2768         meshlink_handle_t *mesh = n->mesh;
2769
2770         if(!mesh->channel_accept_cb) {
2771                 return;
2772         }
2773
2774         meshlink_channel_t *channel = xzalloc(sizeof(*channel));
2775         channel->node = n;
2776         channel->c = utcp_connection;
2777
2778         if(mesh->channel_accept_cb(mesh, channel, port, NULL, 0)) {
2779                 utcp_accept(utcp_connection, channel_recv, channel);
2780         } else {
2781                 free(channel);
2782         }
2783 }
2784
2785 static ssize_t channel_send(struct utcp *utcp, const void *data, size_t len) {
2786         node_t *n = utcp->priv;
2787
2788         if(n->status.destroyed) {
2789                 return -1;
2790         }
2791
2792         meshlink_handle_t *mesh = n->mesh;
2793         return meshlink_send(mesh, (meshlink_node_t *)n, data, len) ? (ssize_t)len : -1;
2794 }
2795
2796 void meshlink_set_channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, meshlink_channel_receive_cb_t cb) {
2797         if(!mesh || !channel) {
2798                 meshlink_errno = MESHLINK_EINVAL;
2799                 return;
2800         }
2801
2802         channel->receive_cb = cb;
2803 }
2804
2805 static void channel_receive(meshlink_handle_t *mesh, meshlink_node_t *source, const void *data, size_t len) {
2806         (void)mesh;
2807         node_t *n = (node_t *)source;
2808
2809         if(!n->utcp) {
2810                 abort();
2811         }
2812
2813         utcp_recv(n->utcp, data, len);
2814 }
2815
2816 static void channel_poll(struct utcp_connection *connection, size_t len) {
2817         meshlink_channel_t *channel = connection->priv;
2818
2819         if(!channel) {
2820                 abort();
2821         }
2822
2823         node_t *n = channel->node;
2824         meshlink_handle_t *mesh = n->mesh;
2825
2826         if(channel->poll_cb) {
2827                 channel->poll_cb(mesh, channel, len);
2828         }
2829 }
2830
2831 void meshlink_set_channel_poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, meshlink_channel_poll_cb_t cb) {
2832         (void)mesh;
2833         channel->poll_cb = cb;
2834         utcp_set_poll_cb(channel->c, cb ? channel_poll : NULL);
2835 }
2836
2837 void meshlink_set_channel_accept_cb(meshlink_handle_t *mesh, meshlink_channel_accept_cb_t cb) {
2838         if(!mesh) {
2839                 meshlink_errno = MESHLINK_EINVAL;
2840                 return;
2841         }
2842
2843         pthread_mutex_lock(&mesh->mesh_mutex);
2844         mesh->channel_accept_cb = cb;
2845         mesh->receive_cb = channel_receive;
2846
2847         for splay_each(node_t, n, mesh->nodes) {
2848                 if(!n->utcp && n != mesh->self) {
2849                         n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n);
2850                 }
2851         }
2852
2853         pthread_mutex_unlock(&mesh->mesh_mutex);
2854 }
2855
2856 meshlink_channel_t *meshlink_channel_open_ex(meshlink_handle_t *mesh, meshlink_node_t *node, uint16_t port, meshlink_channel_receive_cb_t cb, const void *data, size_t len, uint32_t flags) {
2857         if(data || len) {
2858                 abort();        // TODO: handle non-NULL data
2859         }
2860
2861         if(!mesh || !node) {
2862                 meshlink_errno = MESHLINK_EINVAL;
2863                 return NULL;
2864         }
2865
2866         node_t *n = (node_t *)node;
2867
2868         if(!n->utcp) {
2869                 n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n);
2870                 mesh->receive_cb = channel_receive;
2871
2872                 if(!n->utcp) {
2873                         meshlink_errno = errno == ENOMEM ? MESHLINK_ENOMEM : MESHLINK_EINTERNAL;
2874                         return NULL;
2875                 }
2876         }
2877
2878         meshlink_channel_t *channel = xzalloc(sizeof(*channel));
2879         channel->node = n;
2880         channel->receive_cb = cb;
2881         channel->c = utcp_connect_ex(n->utcp, port, channel_recv, channel, flags);
2882
2883         if(!channel->c) {
2884                 meshlink_errno = errno == ENOMEM ? MESHLINK_ENOMEM : MESHLINK_EINTERNAL;
2885                 free(channel);
2886                 return NULL;
2887         }
2888
2889         return channel;
2890 }
2891
2892 meshlink_channel_t *meshlink_channel_open(meshlink_handle_t *mesh, meshlink_node_t *node, uint16_t port, meshlink_channel_receive_cb_t cb, const void *data, size_t len) {
2893         return meshlink_channel_open_ex(mesh, node, port, cb, data, len, MESHLINK_CHANNEL_TCP);
2894 }
2895
2896 void meshlink_channel_shutdown(meshlink_handle_t *mesh, meshlink_channel_t *channel, int direction) {
2897         if(!mesh || !channel) {
2898                 meshlink_errno = MESHLINK_EINVAL;
2899                 return;
2900         }
2901
2902         utcp_shutdown(channel->c, direction);
2903 }
2904
2905 void meshlink_channel_close(meshlink_handle_t *mesh, meshlink_channel_t *channel) {
2906         if(!mesh || !channel) {
2907                 meshlink_errno = MESHLINK_EINVAL;
2908                 return;
2909         }
2910
2911         utcp_close(channel->c);
2912         free(channel);
2913 }
2914
2915 ssize_t meshlink_channel_send(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
2916         if(!mesh || !channel) {
2917                 meshlink_errno = MESHLINK_EINVAL;
2918                 return -1;
2919         }
2920
2921         if(!len) {
2922                 return 0;
2923         }
2924
2925         if(!data) {
2926                 meshlink_errno = MESHLINK_EINVAL;
2927                 return -1;
2928         }
2929
2930         // TODO: more finegrained locking.
2931         // Ideally we want to put the data into the UTCP connection's send buffer.
2932         // Then, preferrably only if there is room in the receiver window,
2933         // kick the meshlink thread to go send packets.
2934
2935         pthread_mutex_lock(&mesh->mesh_mutex);
2936         ssize_t retval = utcp_send(channel->c, data, len);
2937         pthread_mutex_unlock(&mesh->mesh_mutex);
2938
2939         if(retval < 0) {
2940                 meshlink_errno = MESHLINK_ENETWORK;
2941         }
2942
2943         return retval;
2944 }
2945
2946 uint32_t meshlink_channel_get_flags(meshlink_handle_t *mesh, meshlink_channel_t *channel) {
2947         if(!mesh || !channel) {
2948                 meshlink_errno = MESHLINK_EINVAL;
2949                 return -1;
2950         }
2951
2952         return channel->c->flags;
2953 }
2954
2955 void update_node_status(meshlink_handle_t *mesh, node_t *n) {
2956         if(n->status.reachable && mesh->channel_accept_cb && !n->utcp) {
2957                 n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n);
2958         }
2959
2960         if(mesh->node_status_cb) {
2961                 mesh->node_status_cb(mesh, (meshlink_node_t *)n, n->status.reachable);
2962         }
2963 }
2964
2965 void handle_duplicate_node(meshlink_handle_t *mesh, node_t *n) {
2966         if(!mesh->node_duplicate_cb || n->status.duplicate) {
2967                 return;
2968         }
2969
2970         n->status.duplicate = true;
2971         mesh->node_duplicate_cb(mesh, (meshlink_node_t *)n);
2972 }
2973
2974 void meshlink_enable_discovery(meshlink_handle_t *mesh, bool enable) {
2975 #if HAVE_CATTA
2976
2977         if(!mesh) {
2978                 meshlink_errno = MESHLINK_EINVAL;
2979                 return;
2980         }
2981
2982         pthread_mutex_lock(&mesh->mesh_mutex);
2983
2984         if(mesh->discovery == enable) {
2985                 goto end;
2986         }
2987
2988         if(mesh->threadstarted) {
2989                 if(enable) {
2990                         discovery_start(mesh);
2991                 } else {
2992                         discovery_stop(mesh);
2993                 }
2994         }
2995
2996         mesh->discovery = enable;
2997
2998 end:
2999         pthread_mutex_unlock(&mesh->mesh_mutex);
3000 #else
3001         (void)mesh;
3002         (void)enable;
3003         meshlink_errno = MESHLINK_ENOTSUP;
3004 #endif
3005 }
3006
3007 static void __attribute__((constructor)) meshlink_init(void) {
3008         crypto_init();
3009         unsigned int seed;
3010         randomize(&seed, sizeof(seed));
3011         srand(seed);
3012 }
3013
3014 static void __attribute__((destructor)) meshlink_exit(void) {
3015         crypto_exit();
3016 }
3017
3018 /// Device class traits
3019 dev_class_traits_t dev_class_traits[_DEV_CLASS_MAX + 1] = {
3020         { .min_connects = 3, .max_connects = 10000, .edge_weight = 1 }, // DEV_CLASS_BACKBONE
3021         { .min_connects = 3, .max_connects = 100, .edge_weight = 3 },   // DEV_CLASS_STATIONARY
3022         { .min_connects = 3, .max_connects = 3, .edge_weight = 6 },             // DEV_CLASS_PORTABLE
3023         { .min_connects = 1, .max_connects = 1, .edge_weight = 9 },             // DEV_CLASS_UNKNOWN
3024 };