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