]> git.meshlink.io Git - meshlink/blob - src/net_setup.c
0cb79bf25c8cacf3f07f7997bf0cf7789ec40849
[meshlink] / src / net_setup.c
1 /*
2     net_setup.c -- Setup.
3     Copyright (C) 2014-2017 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
20 #include "system.h"
21
22 #include "conf.h"
23 #include "connection.h"
24 #include "ecdsa.h"
25 #include "graph.h"
26 #include "logger.h"
27 #include "meshlink_internal.h"
28 #include "net.h"
29 #include "netutl.h"
30 #include "packmsg.h"
31 #include "protocol.h"
32 #include "route.h"
33 #include "utils.h"
34 #include "xalloc.h"
35
36 /// Helper function to start parsing a host config file
37 static bool node_get_config(meshlink_handle_t *mesh, node_t *n, config_t *config, packmsg_input_t *in) {
38         if(!config_read(mesh, n->name, config)) {
39                 return false;
40         }
41
42         in->ptr = config->buf;
43         in->len = config->len;
44
45         uint32_t version = packmsg_get_uint32(in);
46
47         if(version != MESHLINK_CONFIG_VERSION) {
48                 config_free(config);
49                 return false;
50         }
51
52         const char *name;
53         uint32_t len = packmsg_get_str_raw(in, &name);
54
55         if(len != strlen(n->name) || strncmp(name, n->name, len)) {
56                 config_free(config);
57                 return false;
58         }
59
60         return true;
61 }
62
63 /// Read just the devclass from a host config file. Used at startup when reading all host config files.
64 bool node_read_devclass(meshlink_handle_t *mesh, node_t *n) {
65         config_t config;
66         packmsg_input_t in;
67
68         if(!node_get_config(mesh, n, &config, &in)) {
69                 return false;
70         }
71
72         int32_t devclass = packmsg_get_int32(&in);
73         bool blacklisted = packmsg_get_bool(&in);
74         config_free(&config);
75
76         if(!packmsg_input_ok(&in) || devclass < 0 || devclass > _DEV_CLASS_MAX) {
77                 return false;
78         }
79
80         n->devclass = devclass;
81         n->status.blacklisted = blacklisted;
82         return true;
83 }
84
85 /// Read the public key from a host config file. Used whenever we need to start an SPTPS session.
86 bool node_read_public_key(meshlink_handle_t *mesh, node_t *n) {
87         if(ecdsa_active(n->ecdsa)) {
88                 return true;
89         }
90
91         config_t config;
92         packmsg_input_t in;
93
94         if(!node_get_config(mesh, n, &config, &in)) {
95                 return false;
96         }
97
98         packmsg_get_int32(&in); /* devclass */
99         packmsg_get_bool(&in); /* blacklisted */
100
101         const void *key;
102         uint32_t len = packmsg_get_bin_raw(&in, &key);
103
104         if(len != 32) {
105                 config_free(&config);
106                 return false;
107         }
108
109         n->ecdsa = ecdsa_set_public_key(key);
110         config_free(&config);
111         return true;
112 }
113
114 /// Read the full host config file. Used whenever we need to start an SPTPS session.
115 bool node_read_full(meshlink_handle_t *mesh, node_t *n) {
116         if(n->canonical_address) {
117                 return true;
118         }
119
120         config_t config;
121         packmsg_input_t in;
122
123         if(!node_get_config(mesh, n, &config, &in)) {
124                 return false;
125         }
126
127         packmsg_get_int32(&in); /* devclass */
128         packmsg_get_bool(&in); /* blacklisted */
129         const void *key;
130         uint32_t len = packmsg_get_bin_raw(&in, &key); /* public key */
131
132         if(len != 32) {
133                 return false;
134         }
135
136         if(!ecdsa_active(n->ecdsa)) {
137                 n->ecdsa = ecdsa_set_public_key(key);
138         }
139
140         n->canonical_address = packmsg_get_str_dup(&in);
141
142         uint32_t count = packmsg_get_array(&in);
143
144         if(count > 5) {
145                 count = 5;
146         }
147
148         for(uint32_t i = 0; i < count; i++) {
149                 n->recent[i] = packmsg_get_sockaddr(&in);
150         }
151
152         config_free(&config);
153
154         return packmsg_done(&in);
155 }
156
157 bool node_write_config(meshlink_handle_t *mesh, node_t *n) {
158         uint8_t buf[4096];
159         packmsg_output_t out = {buf, sizeof(buf)};
160
161         packmsg_add_uint32(&out, MESHLINK_CONFIG_VERSION);
162         packmsg_add_str(&out, n->name);
163         packmsg_add_int32(&out, n->devclass);
164         assert(n->devclass != 3);
165         packmsg_add_bool(&out, n->status.blacklisted);
166
167         if(ecdsa_active(n->ecdsa)) {
168                 packmsg_add_bin(&out, ecdsa_get_public_key(n->ecdsa), 32);
169         } else {
170                 packmsg_add_bin(&out, "", 0);
171         }
172
173         packmsg_add_str(&out, n->canonical_address ? n->canonical_address : "");
174
175         uint32_t count = 0;
176
177         for(uint32_t i = 0; i < 5; i++) {
178                 if(n->recent[i].sa.sa_family) {
179                         count++;
180                 } else {
181                         break;
182                 }
183         }
184
185         packmsg_add_array(&out, count);
186
187         for(uint32_t i = 0; i < count; i++) {
188                 packmsg_add_sockaddr(&out, &n->recent[i]);
189         }
190
191         if(!packmsg_output_ok(&out)) {
192                 return false;
193         }
194
195         config_t config = {buf, packmsg_output_size(&out, buf)};
196         return config_write(mesh, n->name, &config);
197 }
198
199 void load_all_nodes(meshlink_handle_t *mesh) {
200         DIR *dir;
201         struct dirent *ent;
202         char dname[PATH_MAX];
203
204         snprintf(dname, PATH_MAX, "%s" SLASH "hosts", mesh->confbase);
205         dir = opendir(dname);
206
207         if(!dir) {
208                 logger(mesh, MESHLINK_ERROR, "Could not open %s: %s", dname, strerror(errno));
209                 return;
210         }
211
212         while((ent = readdir(dir))) {
213                 if(!check_id(ent->d_name)) {
214                         continue;
215                 }
216
217                 node_t *n = lookup_node(mesh, ent->d_name);
218
219                 if(n) {
220                         continue;
221                 }
222
223                 n = new_node();
224                 n->name = xstrdup(ent->d_name);
225                 node_read_devclass(mesh, n);
226                 node_add(mesh, n);
227         }
228
229         closedir(dir);
230 }
231
232 /*
233   Add listening sockets.
234 */
235 static bool add_listen_address(meshlink_handle_t *mesh, char *address, bool bindto) {
236         char *port = mesh->myport;
237
238         if(address) {
239                 char *space = strchr(address, ' ');
240
241                 if(space) {
242                         *space++ = 0;
243                         port = space;
244                 }
245
246                 if(!strcmp(address, "*")) {
247                         *address = 0;
248                 }
249         }
250
251         struct addrinfo *ai;
252
253         struct addrinfo hint = {
254                 .ai_family = addressfamily,
255                 .ai_socktype = SOCK_STREAM,
256                 .ai_protocol = IPPROTO_TCP,
257                 .ai_flags = AI_PASSIVE,
258         };
259
260         int err = getaddrinfo(address && *address ? address : NULL, port, &hint, &ai);
261
262         free(address);
263
264         if(err || !ai) {
265                 logger(mesh, MESHLINK_ERROR, "System call `%s' failed: %s", "getaddrinfo", err == EAI_SYSTEM ? strerror(err) : gai_strerror(err));
266                 return false;
267         }
268
269         bool success = false;
270
271         for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) {
272                 // Ignore duplicate addresses
273                 bool found = false;
274
275                 for(int i = 0; i < mesh->listen_sockets; i++)
276                         if(!memcmp(&mesh->listen_socket[i].sa, aip->ai_addr, aip->ai_addrlen)) {
277                                 found = true;
278                                 break;
279                         }
280
281                 if(found) {
282                         continue;
283                 }
284
285                 if(mesh->listen_sockets >= MAXSOCKETS) {
286                         logger(mesh, MESHLINK_ERROR, "Too many listening sockets");
287                         return false;
288                 }
289
290                 int tcp_fd = setup_listen_socket((sockaddr_t *) aip->ai_addr);
291
292                 if(tcp_fd < 0) {
293                         continue;
294                 }
295
296                 int udp_fd = setup_vpn_in_socket(mesh, (sockaddr_t *) aip->ai_addr);
297
298                 if(udp_fd < 0) {
299                         close(tcp_fd);
300                         continue;
301                 }
302
303                 io_add(&mesh->loop, &mesh->listen_socket[mesh->listen_sockets].tcp, handle_new_meta_connection, &mesh->listen_socket[mesh->listen_sockets], tcp_fd, IO_READ);
304                 io_add(&mesh->loop, &mesh->listen_socket[mesh->listen_sockets].udp, handle_incoming_vpn_data, &mesh->listen_socket[mesh->listen_sockets], udp_fd, IO_READ);
305
306                 if(mesh->log_level >= MESHLINK_INFO) {
307                         char *hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr);
308                         logger(mesh, MESHLINK_INFO, "Listening on %s", hostname);
309                         free(hostname);
310                 }
311
312                 mesh->listen_socket[mesh->listen_sockets].bindto = bindto;
313                 memcpy(&mesh->listen_socket[mesh->listen_sockets].sa, aip->ai_addr, aip->ai_addrlen);
314                 mesh->listen_sockets++;
315                 success = true;
316         }
317
318         freeaddrinfo(ai);
319         return success;
320 }
321
322 /*
323   Configure node_t mesh->self and set up the local sockets (listen only)
324 */
325 bool setup_myself(meshlink_handle_t *mesh) {
326         /* Set some defaults */
327
328         mesh->localdiscovery = true;
329         keylifetime = 3600; // TODO: check if this can be removed as well
330         mesh->maxtimeout = 900;
331         mesh->self->options |= OPTION_PMTU_DISCOVERY;
332
333         /* Done */
334
335         mesh->self->nexthop = mesh->self;
336         mesh->self->via = mesh->self;
337         mesh->self->status.reachable = true;
338         mesh->self->last_state_change = mesh->loop.now.tv_sec;
339
340         node_add(mesh, mesh->self);
341
342         graph(mesh);
343
344         load_all_nodes(mesh);
345
346         /* Open sockets */
347
348         mesh->listen_sockets = 0;
349
350         if(!add_listen_address(mesh, NULL, NULL)) {
351                 if(strcmp(mesh->myport, "0")) {
352                         logger(mesh, MESHLINK_INFO, "Could not bind to port %s, asking OS to choose one for us", mesh->myport);
353                         free(mesh->myport);
354                         mesh->myport = strdup("0");
355
356                         if(!mesh->myport) {
357                                 return false;
358                         }
359
360                         if(!add_listen_address(mesh, NULL, NULL)) {
361                                 return false;
362                         }
363                 } else {
364                         return false;
365                 }
366         }
367
368         if(!mesh->listen_sockets) {
369                 logger(mesh, MESHLINK_ERROR, "Unable to create any listening socket!");
370                 return false;
371         }
372
373         /* Done. */
374
375         mesh->last_config_check = mesh->loop.now.tv_sec;
376
377         return true;
378 }
379
380 /*
381   initialize network
382 */
383 bool setup_network(meshlink_handle_t *mesh) {
384         init_connections(mesh);
385         init_nodes(mesh);
386         init_edges(mesh);
387         init_requests(mesh);
388
389         mesh->pinginterval = 60;
390         mesh->pingtimeout = 5;
391         maxoutbufsize = 10 * MTU;
392
393         if(!setup_myself(mesh)) {
394                 return false;
395         }
396
397         return true;
398 }
399
400 /*
401   close all open network connections
402 */
403 void close_network_connections(meshlink_handle_t *mesh) {
404         if(mesh->connections) {
405                 for(list_node_t *node = mesh->connections->head, *next; node; node = next) {
406                         next = node->next;
407                         connection_t *c = node->data;
408                         c->outgoing = NULL;
409                         terminate_connection(mesh, c, false);
410                 }
411         }
412
413         for(int i = 0; i < mesh->listen_sockets; i++) {
414                 io_del(&mesh->loop, &mesh->listen_socket[i].tcp);
415                 io_del(&mesh->loop, &mesh->listen_socket[i].udp);
416                 close(mesh->listen_socket[i].tcp.fd);
417                 close(mesh->listen_socket[i].udp.fd);
418         }
419
420         exit_requests(mesh);
421         exit_edges(mesh);
422         exit_nodes(mesh);
423         exit_connections(mesh);
424
425         if(mesh->myport) {
426                 free(mesh->myport);
427         }
428
429         return;
430 }