Require OpenSSL 1.1.0 or later.
[tinc] / src / subnet.c
1 /*
2     subnet.c -- handle subnet lookups and lists
3     Copyright (C) 2000-2019 Guus Sliepen <guus@tinc-vpn.org>,
4                   2000-2005 Ivo Timmermans
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License along
17     with this program; if not, write to the Free Software Foundation, Inc.,
18     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include "system.h"
22
23 #include "avl_tree.h"
24 #include "device.h"
25 #include "logger.h"
26 #include "net.h"
27 #include "netutl.h"
28 #include "node.h"
29 #include "process.h"
30 #include "subnet.h"
31 #include "utils.h"
32 #include "xalloc.h"
33
34 /* lists type of subnet */
35
36 avl_tree_t *subnet_tree;
37
38 /* Subnet lookup cache */
39
40 static ipv4_t cache_ipv4_address[2];
41 static subnet_t *cache_ipv4_subnet[2];
42 static bool cache_ipv4_valid[2];
43 static int cache_ipv4_slot;
44
45 static ipv6_t cache_ipv6_address[2];
46 static subnet_t *cache_ipv6_subnet[2];
47 static bool cache_ipv6_valid[2];
48 static int cache_ipv6_slot;
49
50 static mac_t cache_mac_address[2];
51 static subnet_t *cache_mac_subnet[2];
52 static bool cache_mac_valid[2];
53 static int cache_mac_slot;
54
55 void subnet_cache_flush(void) {
56         cache_ipv4_valid[0] = cache_ipv4_valid[1] = false;
57         cache_ipv6_valid[0] = cache_ipv6_valid[1] = false;
58         cache_mac_valid[0] = cache_mac_valid[1] = false;
59 }
60
61 /* Subnet comparison */
62
63 static int subnet_compare_mac(const subnet_t *a, const subnet_t *b) {
64         int result;
65
66         result = memcmp(&a->net.mac.address, &b->net.mac.address, sizeof(mac_t));
67
68         if(result) {
69                 return result;
70         }
71
72         result = a->weight - b->weight;
73
74         if(result || !a->owner || !b->owner) {
75                 return result;
76         }
77
78         return strcmp(a->owner->name, b->owner->name);
79 }
80
81 static int subnet_compare_ipv4(const subnet_t *a, const subnet_t *b) {
82         int result;
83
84         result = b->net.ipv4.prefixlength - a->net.ipv4.prefixlength;
85
86         if(result) {
87                 return result;
88         }
89
90         result = memcmp(&a->net.ipv4.address, &b->net.ipv4.address, sizeof(ipv4_t));
91
92         if(result) {
93                 return result;
94         }
95
96         result = a->weight - b->weight;
97
98         if(result || !a->owner || !b->owner) {
99                 return result;
100         }
101
102         return strcmp(a->owner->name, b->owner->name);
103 }
104
105 static int subnet_compare_ipv6(const subnet_t *a, const subnet_t *b) {
106         int result;
107
108         result = b->net.ipv6.prefixlength - a->net.ipv6.prefixlength;
109
110         if(result) {
111                 return result;
112         }
113
114         result = memcmp(&a->net.ipv6.address, &b->net.ipv6.address, sizeof(ipv6_t));
115
116         if(result) {
117                 return result;
118         }
119
120         result = a->weight - b->weight;
121
122         if(result || !a->owner || !b->owner) {
123                 return result;
124         }
125
126         return strcmp(a->owner->name, b->owner->name);
127 }
128
129 int subnet_compare(const subnet_t *a, const subnet_t *b) {
130         int result;
131
132         result = a->type - b->type;
133
134         if(result) {
135                 return result;
136         }
137
138         switch(a->type) {
139         case SUBNET_MAC:
140                 return subnet_compare_mac(a, b);
141
142         case SUBNET_IPV4:
143                 return subnet_compare_ipv4(a, b);
144
145         case SUBNET_IPV6:
146                 return subnet_compare_ipv6(a, b);
147
148         default:
149                 logger(LOG_ERR, "subnet_compare() was called with unknown subnet type %d, exitting!",
150                        a->type);
151                 exit(0);
152         }
153
154         return 0;
155 }
156
157 /* Initialising trees */
158
159 void init_subnets(void) {
160         subnet_tree = avl_alloc_tree((avl_compare_t) subnet_compare, (avl_action_t) free_subnet);
161
162         subnet_cache_flush();
163 }
164
165 void exit_subnets(void) {
166         avl_delete_tree(subnet_tree);
167 }
168
169 avl_tree_t *new_subnet_tree(void) {
170         return avl_alloc_tree((avl_compare_t) subnet_compare, NULL);
171 }
172
173 void free_subnet_tree(avl_tree_t *subnet_tree) {
174         avl_delete_tree(subnet_tree);
175 }
176
177 /* Allocating and freeing space for subnets */
178
179 subnet_t *new_subnet(void) {
180         return xmalloc_and_zero(sizeof(subnet_t));
181 }
182
183 void free_subnet(subnet_t *subnet) {
184         free(subnet);
185 }
186
187 /* Adding and removing subnets */
188
189 void subnet_add(node_t *n, subnet_t *subnet) {
190         subnet->owner = n;
191
192         avl_insert(subnet_tree, subnet);
193         avl_insert(n->subnet_tree, subnet);
194
195         subnet_cache_flush();
196 }
197
198 void subnet_del(node_t *n, subnet_t *subnet) {
199         avl_delete(n->subnet_tree, subnet);
200         avl_delete(subnet_tree, subnet);
201
202         subnet_cache_flush();
203 }
204
205 /* Ascii representation of subnets */
206
207 bool str2net(subnet_t *subnet, const char *subnetstr) {
208         char str[64];
209         strncpy(str, subnetstr, sizeof(str));
210         str[sizeof(str) - 1] = 0;
211         int consumed;
212
213         int weight = 10;
214         char *weight_separator = strchr(str, '#');
215
216         if(weight_separator) {
217                 char *weight_str = weight_separator + 1;
218
219                 if(sscanf(weight_str, "%d%n", &weight, &consumed) < 1) {
220                         return false;
221                 }
222
223                 if(weight_str[consumed]) {
224                         return false;
225                 }
226
227                 *weight_separator = 0;
228         }
229
230         int prefixlength = -1;
231         char *prefixlength_separator = strchr(str, '/');
232
233         if(prefixlength_separator) {
234                 char *prefixlength_str = prefixlength_separator + 1;
235
236                 if(sscanf(prefixlength_str, "%d%n", &prefixlength, &consumed) < 1) {
237                         return false;
238                 }
239
240                 if(prefixlength_str[consumed]) {
241                         return false;
242                 }
243
244                 *prefixlength_separator = 0;
245
246                 if(prefixlength < 0) {
247                         return false;
248                 }
249         }
250
251         uint16_t x[8];
252
253         if(sscanf(str, "%hx:%hx:%hx:%hx:%hx:%hx%n", &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &consumed) >= 6 && !str[consumed]) {
254                 /*
255                    Normally we should check that each part has two digits to prevent ambiguities.
256                    However, in old tinc versions net2str() will aggressively return MAC addresses with one-digit parts,
257                    so we have to accept them otherwise we would be unable to parse ADD_SUBNET messages.
258                 */
259                 if(prefixlength >= 0) {
260                         return false;
261                 }
262
263                 subnet->type = SUBNET_MAC;
264                 subnet->weight = weight;
265
266                 for(int i = 0; i < 6; i++) {
267                         subnet->net.mac.address.x[i] = x[i];
268                 }
269
270                 return true;
271         }
272
273         if(inet_pton(AF_INET, str, &subnet->net.ipv4.address)) {
274                 if(prefixlength == -1) {
275                         prefixlength = 32;
276                 }
277
278                 if(prefixlength > 32) {
279                         return false;
280                 }
281
282                 subnet->type = SUBNET_IPV4;
283                 subnet->net.ipv4.prefixlength = prefixlength;
284                 subnet->weight = weight;
285
286                 return true;
287         }
288
289         if(inet_pton(AF_INET6, str, &subnet->net.ipv6.address)) {
290                 if(prefixlength == -1) {
291                         prefixlength = 128;
292                 }
293
294                 if(prefixlength > 128) {
295                         return false;
296                 }
297
298                 subnet->type = SUBNET_IPV6;
299                 subnet->net.ipv6.prefixlength = prefixlength;
300                 subnet->weight = weight;
301
302                 return true;
303         }
304
305         return false;
306 }
307
308 bool net2str(char *netstr, int len, const subnet_t *subnet) {
309         if(!netstr || !subnet) {
310                 logger(LOG_ERR, "net2str() was called with netstr=%p, subnet=%p!", (void *)netstr, (void *)subnet);
311                 return false;
312         }
313
314         int result;
315         int prefixlength = -1;
316
317         switch(subnet->type) {
318         case SUBNET_MAC:
319                 snprintf(netstr, len, "%02x:%02x:%02x:%02x:%02x:%02x",
320                          subnet->net.mac.address.x[0],
321                          subnet->net.mac.address.x[1],
322                          subnet->net.mac.address.x[2],
323                          subnet->net.mac.address.x[3],
324                          subnet->net.mac.address.x[4],
325                          subnet->net.mac.address.x[5]);
326                 break;
327
328         case SUBNET_IPV4:
329                 inet_ntop(AF_INET, &subnet->net.ipv4.address, netstr, len);
330                 prefixlength = subnet->net.ipv4.prefixlength;
331
332                 if(prefixlength == 32) {
333                         prefixlength = -1;
334                 }
335
336                 break;
337
338         case SUBNET_IPV6: {
339                 inet_ntop(AF_INET6, &subnet->net.ipv6.address, netstr, len);
340                 prefixlength = subnet->net.ipv6.prefixlength;
341
342                 if(prefixlength == 128) {
343                         prefixlength = -1;
344                 }
345
346                 break;
347         }
348
349         default:
350                 logger(LOG_ERR, "net2str() was called with unknown subnet type %d, exiting!", subnet->type);
351                 exit(1);
352         }
353
354         size_t used = strlen(netstr);
355         netstr += used;
356         len -= used;
357
358         if(prefixlength >= 0) {
359                 result = snprintf(netstr, len, "/%d", prefixlength);
360                 netstr += result;
361                 len -= result;
362         }
363
364         if(subnet->weight != 10) {
365                 snprintf(netstr, len, "#%d", subnet->weight);
366         }
367
368         return true;
369 }
370
371 /* Subnet lookup routines */
372
373 subnet_t *lookup_subnet(const node_t *owner, const subnet_t *subnet) {
374         return avl_search(owner->subnet_tree, subnet);
375 }
376
377 subnet_t *lookup_subnet_mac(const node_t *owner, const mac_t *address) {
378         subnet_t *p, *r = NULL;
379         avl_node_t *n;
380         int i;
381
382         // Check if this address is cached
383
384         for(i = 0; i < 2; i++) {
385                 if(!cache_mac_valid[i]) {
386                         continue;
387                 }
388
389                 if(owner && cache_mac_subnet[i] && cache_mac_subnet[i]->owner != owner) {
390                         continue;
391                 }
392
393                 if(!memcmp(address, &cache_mac_address[i], sizeof(*address))) {
394                         return cache_mac_subnet[i];
395                 }
396         }
397
398         // Search all subnets for a matching one
399
400         for(n = owner ? owner->subnet_tree->head : subnet_tree->head; n; n = n->next) {
401                 p = n->data;
402
403                 if(!p || p->type != SUBNET_MAC) {
404                         continue;
405                 }
406
407                 if(!memcmp(address, &p->net.mac.address, sizeof(*address))) {
408                         r = p;
409
410                         if(p->owner->status.reachable) {
411                                 break;
412                         }
413                 }
414         }
415
416         // Cache the result
417
418         cache_mac_slot = !cache_mac_slot;
419         memcpy(&cache_mac_address[cache_mac_slot], address, sizeof(*address));
420         cache_mac_subnet[cache_mac_slot] = r;
421         cache_mac_valid[cache_mac_slot] = true;
422
423         return r;
424 }
425
426 subnet_t *lookup_subnet_ipv4(const ipv4_t *address) {
427         subnet_t *p, *r = NULL;
428         avl_node_t *n;
429         int i;
430
431         // Check if this address is cached
432
433         for(i = 0; i < 2; i++) {
434                 if(!cache_ipv4_valid[i]) {
435                         continue;
436                 }
437
438                 if(!memcmp(address, &cache_ipv4_address[i], sizeof(*address))) {
439                         return cache_ipv4_subnet[i];
440                 }
441         }
442
443         // Search all subnets for a matching one
444
445         for(n = subnet_tree->head; n; n = n->next) {
446                 p = n->data;
447
448                 if(!p || p->type != SUBNET_IPV4) {
449                         continue;
450                 }
451
452                 if(!maskcmp(address, &p->net.ipv4.address, p->net.ipv4.prefixlength)) {
453                         r = p;
454
455                         if(p->owner->status.reachable) {
456                                 break;
457                         }
458                 }
459         }
460
461         // Cache the result
462
463         cache_ipv4_slot = !cache_ipv4_slot;
464         memcpy(&cache_ipv4_address[cache_ipv4_slot], address, sizeof(*address));
465         cache_ipv4_subnet[cache_ipv4_slot] = r;
466         cache_ipv4_valid[cache_ipv4_slot] = true;
467
468         return r;
469 }
470
471 subnet_t *lookup_subnet_ipv6(const ipv6_t *address) {
472         subnet_t *p, *r = NULL;
473         avl_node_t *n;
474         int i;
475
476         // Check if this address is cached
477
478         for(i = 0; i < 2; i++) {
479                 if(!cache_ipv6_valid[i]) {
480                         continue;
481                 }
482
483                 if(!memcmp(address, &cache_ipv6_address[i], sizeof(*address))) {
484                         return cache_ipv6_subnet[i];
485                 }
486         }
487
488         // Search all subnets for a matching one
489
490         for(n = subnet_tree->head; n; n = n->next) {
491                 p = n->data;
492
493                 if(!p || p->type != SUBNET_IPV6) {
494                         continue;
495                 }
496
497                 if(!maskcmp(address, &p->net.ipv6.address, p->net.ipv6.prefixlength)) {
498                         r = p;
499
500                         if(p->owner->status.reachable) {
501                                 break;
502                         }
503                 }
504         }
505
506         // Cache the result
507
508         cache_ipv6_slot = !cache_ipv6_slot;
509         memcpy(&cache_ipv6_address[cache_ipv6_slot], address, sizeof(*address));
510         cache_ipv6_subnet[cache_ipv6_slot] = r;
511         cache_ipv6_valid[cache_ipv6_slot] = true;
512
513         return r;
514 }
515
516 void subnet_update(node_t *owner, subnet_t *subnet, bool up) {
517         avl_node_t *node;
518         int i;
519         char *envp[10] = {NULL};
520         char netstr[MAXNETSTR];
521         char *name, *address, *port;
522         char empty[] = "";
523
524         // Prepare environment variables to be passed to the script
525
526         xasprintf(&envp[0], "NETNAME=%s", netname ? netname : "");
527         xasprintf(&envp[1], "DEVICE=%s", device ? device : "");
528         xasprintf(&envp[2], "INTERFACE=%s", iface ? iface : "");
529         xasprintf(&envp[3], "NODE=%s", owner->name);
530         xasprintf(&envp[4], "NAME=%s", myself->name);
531
532         if(owner != myself) {
533                 sockaddr2str(&owner->address, &address, &port);
534                 // 5 and 6 are reserved for SUBNET and WEIGHT
535                 xasprintf(&envp[7], "REMOTEADDRESS=%s", address);
536                 xasprintf(&envp[8], "REMOTEPORT=%s", port);
537                 free(port);
538                 free(address);
539         }
540
541         name = up ? "subnet-up" : "subnet-down";
542
543         if(!subnet) {
544                 for(node = owner->subnet_tree->head; node; node = node->next) {
545                         subnet = node->data;
546
547                         if(!net2str(netstr, sizeof(netstr), subnet)) {
548                                 continue;
549                         }
550
551                         // Strip the weight from the subnet, and put it in its own environment variable
552                         char *weight = strchr(netstr, '#');
553
554                         if(weight) {
555                                 *weight++ = 0;
556                         } else {
557                                 weight = empty;
558                         }
559
560                         // Prepare the SUBNET and WEIGHT variables
561                         free(envp[5]);
562                         free(envp[6]);
563
564                         xasprintf(&envp[5], "SUBNET=%s", netstr);
565                         xasprintf(&envp[6], "WEIGHT=%s", weight);
566
567                         execute_script(name, envp);
568                 }
569         } else {
570                 if(net2str(netstr, sizeof(netstr), subnet)) {
571                         // Strip the weight from the subnet, and put it in its own environment variable
572                         char *weight = strchr(netstr, '#');
573
574                         if(weight) {
575                                 *weight++ = 0;
576                         } else {
577                                 weight = empty;
578                         }
579
580                         // Prepare the SUBNET and WEIGHT variables
581                         xasprintf(&envp[5], "SUBNET=%s", netstr);
582                         xasprintf(&envp[6], "WEIGHT=%s", weight);
583
584                         execute_script(name, envp);
585                 }
586         }
587
588         for(i = 0; i < 9; i++) {
589                 free(envp[i]);
590         }
591 }
592
593 void dump_subnets(void) {
594         char netstr[MAXNETSTR];
595         subnet_t *subnet;
596         avl_node_t *node;
597
598         logger(LOG_DEBUG, "Subnet list:");
599
600         for(node = subnet_tree->head; node; node = node->next) {
601                 subnet = node->data;
602
603                 if(!net2str(netstr, sizeof(netstr), subnet)) {
604                         continue;
605                 }
606
607                 logger(LOG_DEBUG, " %s owner %s", netstr, subnet->owner->name);
608         }
609
610         logger(LOG_DEBUG, "End of subnet list.");
611 }