xref: /openbsd-src/usr.sbin/bgpd/config.c (revision 8550894424f8a4aa4aafb6cd57229dd6ed7cd9dd)
1 /*	$OpenBSD: config.c,v 1.106 2022/12/28 21:30:15 jmc Exp $ */
2 
3 /*
4  * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 
22 #include <errno.h>
23 #include <ifaddrs.h>
24 #include <netdb.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <unistd.h>
29 
30 #include "bgpd.h"
31 #include "session.h"
32 #include "log.h"
33 
34 int		host_ip(const char *, struct bgpd_addr *, uint8_t *);
35 void		free_networks(struct network_head *);
36 
37 struct bgpd_config *
38 new_config(void)
39 {
40 	struct bgpd_config	*conf;
41 
42 	if ((conf = calloc(1, sizeof(struct bgpd_config))) == NULL)
43 		fatal(NULL);
44 
45 	if ((conf->filters = calloc(1, sizeof(struct filter_head))) == NULL)
46 		fatal(NULL);
47 	if ((conf->listen_addrs = calloc(1, sizeof(struct listen_addrs))) ==
48 	    NULL)
49 		fatal(NULL);
50 	if ((conf->mrt = calloc(1, sizeof(struct mrt_head))) == NULL)
51 		fatal(NULL);
52 
53 	/* init the various list for later */
54 	RB_INIT(&conf->peers);
55 	TAILQ_INIT(&conf->networks);
56 	SIMPLEQ_INIT(&conf->l3vpns);
57 	SIMPLEQ_INIT(&conf->prefixsets);
58 	SIMPLEQ_INIT(&conf->originsets);
59 	SIMPLEQ_INIT(&conf->rde_prefixsets);
60 	SIMPLEQ_INIT(&conf->rde_originsets);
61 	RB_INIT(&conf->roa);
62 	RB_INIT(&conf->aspa);
63 	SIMPLEQ_INIT(&conf->as_sets);
64 	SIMPLEQ_INIT(&conf->rtrs);
65 
66 	TAILQ_INIT(conf->filters);
67 	TAILQ_INIT(conf->listen_addrs);
68 	LIST_INIT(conf->mrt);
69 
70 	return (conf);
71 }
72 
73 void
74 copy_config(struct bgpd_config *to, struct bgpd_config *from)
75 {
76 	to->flags = from->flags;
77 	to->log = from->log;
78 	to->default_tableid = from->default_tableid;
79 	to->bgpid = from->bgpid;
80 	to->clusterid = from->clusterid;
81 	to->as = from->as;
82 	to->short_as = from->short_as;
83 	to->holdtime = from->holdtime;
84 	to->min_holdtime = from->min_holdtime;
85 	to->connectretry = from->connectretry;
86 	to->fib_priority = from->fib_priority;
87 }
88 
89 void
90 network_free(struct network *n)
91 {
92 	rtlabel_unref(n->net.rtlabel);
93 	filterset_free(&n->net.attrset);
94 	free(n);
95 }
96 
97 void
98 free_networks(struct network_head *networks)
99 {
100 	struct network		*n;
101 
102 	while ((n = TAILQ_FIRST(networks)) != NULL) {
103 		TAILQ_REMOVE(networks, n, entry);
104 		network_free(n);
105 	}
106 }
107 
108 void
109 free_l3vpns(struct l3vpn_head *l3vpns)
110 {
111 	struct l3vpn		*vpn;
112 
113 	while ((vpn = SIMPLEQ_FIRST(l3vpns)) != NULL) {
114 		SIMPLEQ_REMOVE_HEAD(l3vpns, entry);
115 		filterset_free(&vpn->export);
116 		filterset_free(&vpn->import);
117 		free_networks(&vpn->net_l);
118 		free(vpn);
119 	}
120 }
121 
122 void
123 free_prefixsets(struct prefixset_head *psh)
124 {
125 	struct prefixset	*ps;
126 
127 	while (!SIMPLEQ_EMPTY(psh)) {
128 		ps = SIMPLEQ_FIRST(psh);
129 		free_roatree(&ps->roaitems);
130 		free_prefixtree(&ps->psitems);
131 		SIMPLEQ_REMOVE_HEAD(psh, entry);
132 		free(ps);
133 	}
134 }
135 
136 void
137 free_rde_prefixsets(struct rde_prefixset_head *psh)
138 {
139 	struct rde_prefixset	*ps;
140 
141 	if (psh == NULL)
142 		return;
143 
144 	while (!SIMPLEQ_EMPTY(psh)) {
145 		ps = SIMPLEQ_FIRST(psh);
146 		trie_free(&ps->th);
147 		SIMPLEQ_REMOVE_HEAD(psh, entry);
148 		free(ps);
149 	}
150 }
151 
152 void
153 free_prefixtree(struct prefixset_tree *p)
154 {
155 	struct prefixset_item	*psi, *npsi;
156 
157 	RB_FOREACH_SAFE(psi, prefixset_tree, p, npsi) {
158 		RB_REMOVE(prefixset_tree, p, psi);
159 		free(psi);
160 	}
161 }
162 
163 void
164 free_roatree(struct roa_tree *r)
165 {
166 	struct roa	*roa, *nroa;
167 
168 	RB_FOREACH_SAFE(roa, roa_tree, r, nroa) {
169 		RB_REMOVE(roa_tree, r, roa);
170 		free(roa);
171 	}
172 }
173 
174 void
175 free_aspa(struct aspa_set *aspa)
176 {
177 	if (aspa == NULL)
178 		return;
179 	free(aspa->tas);
180 	free(aspa->tas_aid);
181 	free(aspa);
182 }
183 
184 void
185 free_aspatree(struct aspa_tree *a)
186 {
187 	struct aspa_set	*aspa, *naspa;
188 
189 	RB_FOREACH_SAFE(aspa, aspa_tree, a, naspa) {
190 		RB_REMOVE(aspa_tree, a, aspa);
191 		free_aspa(aspa);
192 	}
193 }
194 
195 void
196 free_rtrs(struct rtr_config_head *rh)
197 {
198 	struct rtr_config	*r;
199 
200 	while (!SIMPLEQ_EMPTY(rh)) {
201 		r = SIMPLEQ_FIRST(rh);
202 		SIMPLEQ_REMOVE_HEAD(rh, entry);
203 		free(r);
204 	}
205 }
206 
207 void
208 free_config(struct bgpd_config *conf)
209 {
210 	struct peer		*p, *next;
211 	struct listen_addr	*la;
212 	struct mrt		*m;
213 
214 	free_l3vpns(&conf->l3vpns);
215 	free_networks(&conf->networks);
216 	filterlist_free(conf->filters);
217 	free_prefixsets(&conf->prefixsets);
218 	free_prefixsets(&conf->originsets);
219 	free_rde_prefixsets(&conf->rde_prefixsets);
220 	free_rde_prefixsets(&conf->rde_originsets);
221 	as_sets_free(&conf->as_sets);
222 	free_roatree(&conf->roa);
223 	free_aspatree(&conf->aspa);
224 	free_rtrs(&conf->rtrs);
225 
226 	while ((la = TAILQ_FIRST(conf->listen_addrs)) != NULL) {
227 		TAILQ_REMOVE(conf->listen_addrs, la, entry);
228 		free(la);
229 	}
230 	free(conf->listen_addrs);
231 
232 	while ((m = LIST_FIRST(conf->mrt)) != NULL) {
233 		LIST_REMOVE(m, entry);
234 		free(m);
235 	}
236 	free(conf->mrt);
237 
238 	RB_FOREACH_SAFE(p, peer_head, &conf->peers, next) {
239 		RB_REMOVE(peer_head, &conf->peers, p);
240 		free(p);
241 	}
242 
243 	free(conf->csock);
244 	free(conf->rcsock);
245 
246 	free(conf);
247 }
248 
249 void
250 merge_config(struct bgpd_config *xconf, struct bgpd_config *conf)
251 {
252 	struct listen_addr	*nla, *ola, *next;
253 	struct peer		*p, *np, *nextp;
254 
255 	/*
256 	 * merge the freshly parsed conf into the running xconf
257 	 */
258 
259 	/* adjust FIB priority if changed */
260 	/* if xconf is uninitialized we get RTP_NONE */
261 	if (xconf->fib_priority != conf->fib_priority) {
262 		kr_fib_decouple_all();
263 		kr_fib_prio_set(conf->fib_priority);
264 		kr_fib_couple_all();
265 	}
266 
267 	/* take over the easy config changes */
268 	copy_config(xconf, conf);
269 
270 	/* clear old control sockets and use new */
271 	free(xconf->csock);
272 	free(xconf->rcsock);
273 	xconf->csock = conf->csock;
274 	xconf->rcsock = conf->rcsock;
275 	/* set old one to NULL so we don't double free */
276 	conf->csock = NULL;
277 	conf->rcsock = NULL;
278 
279 	/* clear all current filters and take over the new ones */
280 	filterlist_free(xconf->filters);
281 	xconf->filters = conf->filters;
282 	conf->filters = NULL;
283 
284 	/* merge mrt config */
285 	mrt_mergeconfig(xconf->mrt, conf->mrt);
286 
287 	/* switch the roa, first remove the old one */
288 	free_roatree(&xconf->roa);
289 	/* then move the RB tree root */
290 	RB_ROOT(&xconf->roa) = RB_ROOT(&conf->roa);
291 	RB_ROOT(&conf->roa) = NULL;
292 
293 	/* switch the aspa, first remove the old one */
294 	free_aspatree(&xconf->aspa);
295 	/* then move the RB tree root */
296 	RB_ROOT(&xconf->aspa) = RB_ROOT(&conf->aspa);
297 	RB_ROOT(&conf->aspa) = NULL;
298 
299 	/* switch the rtr_configs, first remove the old ones */
300 	free_rtrs(&xconf->rtrs);
301 	SIMPLEQ_CONCAT(&xconf->rtrs, &conf->rtrs);
302 
303 	/* switch the prefixsets, first remove the old ones */
304 	free_prefixsets(&xconf->prefixsets);
305 	SIMPLEQ_CONCAT(&xconf->prefixsets, &conf->prefixsets);
306 
307 	/* switch the originsets, first remove the old ones */
308 	free_prefixsets(&xconf->originsets);
309 	SIMPLEQ_CONCAT(&xconf->originsets, &conf->originsets);
310 
311 	/* switch the as_sets, first remove the old ones */
312 	as_sets_free(&xconf->as_sets);
313 	SIMPLEQ_CONCAT(&xconf->as_sets, &conf->as_sets);
314 
315 	/* switch the network statements, but first remove the old ones */
316 	free_networks(&xconf->networks);
317 	TAILQ_CONCAT(&xconf->networks, &conf->networks, entry);
318 
319 	/* switch the l3vpn configs, first remove the old ones */
320 	free_l3vpns(&xconf->l3vpns);
321 	SIMPLEQ_CONCAT(&xconf->l3vpns, &conf->l3vpns);
322 
323 	/*
324 	 * merge new listeners:
325 	 * -flag all existing ones as to be deleted
326 	 * -those that are in both new and old: flag to keep
327 	 * -new ones get inserted and flagged as to reinit
328 	 * -remove all that are still flagged for deletion
329 	 */
330 
331 	TAILQ_FOREACH(nla, xconf->listen_addrs, entry)
332 		nla->reconf = RECONF_DELETE;
333 
334 	/* no new listeners? preserve default ones */
335 	if (TAILQ_EMPTY(conf->listen_addrs))
336 		TAILQ_FOREACH(ola, xconf->listen_addrs, entry)
337 			if (ola->flags & DEFAULT_LISTENER)
338 				ola->reconf = RECONF_KEEP;
339 	/* else loop over listeners and merge configs */
340 	for (nla = TAILQ_FIRST(conf->listen_addrs); nla != NULL; nla = next) {
341 		next = TAILQ_NEXT(nla, entry);
342 
343 		TAILQ_FOREACH(ola, xconf->listen_addrs, entry)
344 			if (!memcmp(&nla->sa, &ola->sa, sizeof(nla->sa)))
345 				break;
346 
347 		if (ola == NULL) {
348 			/* new listener, copy over */
349 			TAILQ_REMOVE(conf->listen_addrs, nla, entry);
350 			TAILQ_INSERT_TAIL(xconf->listen_addrs, nla, entry);
351 			nla->reconf = RECONF_REINIT;
352 		} else		/* exists, just flag */
353 			ola->reconf = RECONF_KEEP;
354 	}
355 	/* finally clean up the original list and remove all stale entries */
356 	for (nla = TAILQ_FIRST(xconf->listen_addrs); nla != NULL; nla = next) {
357 		next = TAILQ_NEXT(nla, entry);
358 		if (nla->reconf == RECONF_DELETE) {
359 			TAILQ_REMOVE(xconf->listen_addrs, nla, entry);
360 			free(nla);
361 		}
362 	}
363 
364 	/*
365 	 * merge peers:
366 	 * - need to know which peers are new, replaced and removed
367 	 * - walk over old peers and check if there is a corresponding new
368 	 *   peer if so mark it RECONF_KEEP. Remove all old peers.
369 	 * - swap lists (old peer list is actually empty).
370 	 */
371 	RB_FOREACH_SAFE(p, peer_head, &xconf->peers, nextp) {
372 		np = getpeerbyid(conf, p->conf.id);
373 		if (np != NULL) {
374 			np->reconf_action = RECONF_KEEP;
375 			/* copy the auth state since parent uses it */
376 			np->auth = p->auth;
377 		} else {
378 			/* peer no longer exists, clear pfkey state */
379 			pfkey_remove(p);
380 		}
381 
382 		RB_REMOVE(peer_head, &xconf->peers, p);
383 		free(p);
384 	}
385 	RB_FOREACH_SAFE(np, peer_head, &conf->peers, nextp) {
386 		RB_REMOVE(peer_head, &conf->peers, np);
387 		if (RB_INSERT(peer_head, &xconf->peers, np) != NULL)
388 			fatalx("%s: peer tree is corrupt", __func__);
389 	}
390 
391 	/* conf is merged so free it */
392 	free_config(conf);
393 }
394 
395 uint32_t
396 get_bgpid(void)
397 {
398 	struct ifaddrs		*ifap, *ifa;
399 	uint32_t		 ip = 0, cur, localnet;
400 
401 	localnet = htonl(INADDR_LOOPBACK & IN_CLASSA_NET);
402 
403 	if (getifaddrs(&ifap) == -1)
404 		fatal("getifaddrs");
405 
406 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
407 		if (ifa->ifa_addr == NULL ||
408 		    ifa->ifa_addr->sa_family != AF_INET)
409 			continue;
410 		cur = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
411 		if ((cur & localnet) == localnet)	/* skip 127/8 */
412 			continue;
413 		if (ntohl(cur) > ntohl(ip))
414 			ip = cur;
415 	}
416 	freeifaddrs(ifap);
417 
418 	return (ip);
419 }
420 
421 int
422 host(const char *s, struct bgpd_addr *h, uint8_t *len)
423 {
424 	int			 mask = 128;
425 	char			*p, *ps;
426 	const char		*errstr;
427 
428 	if ((ps = strdup(s)) == NULL)
429 		fatal("%s: strdup", __func__);
430 
431 	if ((p = strrchr(ps, '/')) != NULL) {
432 		mask = strtonum(p+1, 0, 128, &errstr);
433 		if (errstr) {
434 			log_warnx("prefixlen is %s: %s", errstr, p);
435 			free(ps);
436 			return (0);
437 		}
438 		p[0] = '\0';
439 	}
440 
441 	memset(h, 0, sizeof(*h));
442 
443 	if (host_ip(ps, h, len) == 0) {
444 		free(ps);
445 		return (0);
446 	}
447 
448 	if (p != NULL)
449 		*len = mask;
450 
451 	free(ps);
452 	return (1);
453 }
454 
455 int
456 host_ip(const char *s, struct bgpd_addr *h, uint8_t *len)
457 {
458 	struct addrinfo		 hints, *res;
459 	int			 bits;
460 
461 	memset(&hints, 0, sizeof(hints));
462 	hints.ai_family = AF_UNSPEC;
463 	hints.ai_socktype = SOCK_DGRAM; /*dummy*/
464 	hints.ai_flags = AI_NUMERICHOST;
465 	if (getaddrinfo(s, NULL, &hints, &res) == 0) {
466 		*len = res->ai_family == AF_INET6 ? 128 : 32;
467 		sa2addr(res->ai_addr, h, NULL);
468 		freeaddrinfo(res);
469 	} else {	/* ie. for 10/8 parsing */
470 		if ((bits = inet_net_pton(AF_INET, s, &h->v4,
471 		    sizeof(h->v4))) == -1)
472 			return (0);
473 		*len = bits;
474 		h->aid = AID_INET;
475 	}
476 
477 	return (1);
478 }
479 
480 int
481 prepare_listeners(struct bgpd_config *conf)
482 {
483 	struct listen_addr	*la, *next;
484 	int			 opt = 1;
485 	int			 r = 0;
486 
487 	for (la = TAILQ_FIRST(conf->listen_addrs); la != NULL; la = next) {
488 		next = TAILQ_NEXT(la, entry);
489 		if (la->reconf != RECONF_REINIT)
490 			continue;
491 
492 		if ((la->fd = socket(la->sa.ss_family,
493 		    SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
494 		    IPPROTO_TCP)) == -1) {
495 			if (la->flags & DEFAULT_LISTENER && (errno ==
496 			    EAFNOSUPPORT || errno == EPROTONOSUPPORT)) {
497 				TAILQ_REMOVE(conf->listen_addrs, la, entry);
498 				free(la);
499 				continue;
500 			} else
501 				fatal("socket");
502 		}
503 
504 		opt = 1;
505 		if (setsockopt(la->fd, SOL_SOCKET, SO_REUSEADDR,
506 		    &opt, sizeof(opt)) == -1)
507 			fatal("setsockopt SO_REUSEADDR");
508 
509 		if (bind(la->fd, (struct sockaddr *)&la->sa, la->sa_len) ==
510 		    -1) {
511 			switch (la->sa.ss_family) {
512 			case AF_INET:
513 				log_warn("cannot bind to %s:%u",
514 				    log_sockaddr((struct sockaddr *)&la->sa,
515 				    la->sa_len), ntohs(((struct sockaddr_in *)
516 				    &la->sa)->sin_port));
517 				break;
518 			case AF_INET6:
519 				log_warn("cannot bind to [%s]:%u",
520 				    log_sockaddr((struct sockaddr *)&la->sa,
521 				    la->sa_len), ntohs(((struct sockaddr_in6 *)
522 				    &la->sa)->sin6_port));
523 				break;
524 			default:
525 				log_warn("cannot bind to %s",
526 				    log_sockaddr((struct sockaddr *)&la->sa,
527 				    la->sa_len));
528 				break;
529 			}
530 			close(la->fd);
531 			TAILQ_REMOVE(conf->listen_addrs, la, entry);
532 			free(la);
533 			r = -1;
534 			continue;
535 		}
536 	}
537 
538 	return (r);
539 }
540 
541 void
542 expand_networks(struct bgpd_config *c, struct network_head *nw)
543 {
544 	struct network		*n, *m, *tmp;
545 	struct prefixset	*ps;
546 	struct prefixset_item	*psi;
547 
548 	TAILQ_FOREACH_SAFE(n, nw, entry, tmp) {
549 		if (n->net.type == NETWORK_PREFIXSET) {
550 			TAILQ_REMOVE(nw, n, entry);
551 			if ((ps = find_prefixset(n->net.psname, &c->prefixsets))
552 			    == NULL)
553 				fatal("%s: prefixset %s not found", __func__,
554 				    n->net.psname);
555 			RB_FOREACH(psi, prefixset_tree, &ps->psitems) {
556 				if ((m = calloc(1, sizeof(struct network)))
557 				    == NULL)
558 					fatal(NULL);
559 				memcpy(&m->net.prefix, &psi->p.addr,
560 				    sizeof(m->net.prefix));
561 				m->net.prefixlen = psi->p.len;
562 				filterset_copy(&n->net.attrset,
563 				    &m->net.attrset);
564 				TAILQ_INSERT_TAIL(nw, m, entry);
565 			}
566 			network_free(n);
567 		}
568 	}
569 }
570 
571 static inline int
572 prefixset_cmp(struct prefixset_item *a, struct prefixset_item *b)
573 {
574 	int i;
575 
576 	if (a->p.addr.aid < b->p.addr.aid)
577 		return (-1);
578 	if (a->p.addr.aid > b->p.addr.aid)
579 		return (1);
580 
581 	switch (a->p.addr.aid) {
582 	case AID_INET:
583 		i = memcmp(&a->p.addr.v4, &b->p.addr.v4,
584 		    sizeof(struct in_addr));
585 		break;
586 	case AID_INET6:
587 		i = memcmp(&a->p.addr.v6, &b->p.addr.v6,
588 		    sizeof(struct in6_addr));
589 		break;
590 	default:
591 		fatalx("%s: unknown af", __func__);
592 	}
593 	if (i > 0)
594 		return (1);
595 	if (i < 0)
596 		return (-1);
597 	if (a->p.len < b->p.len)
598 		return (-1);
599 	if (a->p.len > b->p.len)
600 		return (1);
601 	if (a->p.len_min < b->p.len_min)
602 		return (-1);
603 	if (a->p.len_min > b->p.len_min)
604 		return (1);
605 	if (a->p.len_max < b->p.len_max)
606 		return (-1);
607 	if (a->p.len_max > b->p.len_max)
608 		return (1);
609 	return (0);
610 }
611 
612 RB_GENERATE(prefixset_tree, prefixset_item, entry, prefixset_cmp);
613 
614 static inline int
615 roa_cmp(struct roa *a, struct roa *b)
616 {
617 	int i;
618 
619 	if (a->aid < b->aid)
620 		return (-1);
621 	if (a->aid > b->aid)
622 		return (1);
623 
624 	switch (a->aid) {
625 	case AID_INET:
626 		i = memcmp(&a->prefix.inet, &b->prefix.inet,
627 		    sizeof(struct in_addr));
628 		break;
629 	case AID_INET6:
630 		i = memcmp(&a->prefix.inet6, &b->prefix.inet6,
631 		    sizeof(struct in6_addr));
632 		break;
633 	default:
634 		fatalx("%s: unknown af", __func__);
635 	}
636 	if (i > 0)
637 		return (1);
638 	if (i < 0)
639 		return (-1);
640 	if (a->prefixlen < b->prefixlen)
641 		return (-1);
642 	if (a->prefixlen > b->prefixlen)
643 		return (1);
644 
645 	if (a->asnum < b->asnum)
646 		return (-1);
647 	if (a->asnum > b->asnum)
648 		return (1);
649 
650 	if (a->maxlen < b->maxlen)
651 		return (-1);
652 	if (a->maxlen > b->maxlen)
653 		return (1);
654 
655 	return (0);
656 }
657 
658 RB_GENERATE(roa_tree, roa, entry, roa_cmp);
659 
660 static inline int
661 aspa_cmp(struct aspa_set *a, struct aspa_set *b)
662 {
663 	if (a->as < b->as)
664 		return (-1);
665 	if (a->as > b->as)
666 		return (1);
667 	return (0);
668 }
669 
670 RB_GENERATE(aspa_tree, aspa_set, entry, aspa_cmp);
671