xref: /openbsd/usr.sbin/bgpd/config.c (revision 09467b48)
1 /*	$OpenBSD: config.c,v 1.95 2020/02/14 13:54:31 claudio 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 *, u_int8_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 	SIMPLEQ_INIT(&conf->as_sets);
63 
64 	TAILQ_INIT(conf->filters);
65 	TAILQ_INIT(conf->listen_addrs);
66 	LIST_INIT(conf->mrt);
67 
68 	return (conf);
69 }
70 
71 void
72 copy_config(struct bgpd_config *to, struct bgpd_config *from)
73 {
74 	to->flags = from->flags;
75 	to->log = from->log;
76 	to->default_tableid = from->default_tableid;
77 	to->bgpid = from->bgpid;
78 	to->clusterid = from->clusterid;
79 	to->as = from->as;
80 	to->short_as = from->short_as;
81 	to->holdtime = from->holdtime;
82 	to->min_holdtime = from->min_holdtime;
83 	to->connectretry = from->connectretry;
84 	to->fib_priority = from->fib_priority;
85 }
86 
87 void
88 free_networks(struct network_head *networks)
89 {
90 	struct network		*n;
91 
92 	while ((n = TAILQ_FIRST(networks)) != NULL) {
93 		TAILQ_REMOVE(networks, n, entry);
94 		filterset_free(&n->net.attrset);
95 		free(n);
96 	}
97 }
98 
99 void
100 free_l3vpns(struct l3vpn_head *l3vpns)
101 {
102 	struct l3vpn		*vpn;
103 
104 	while ((vpn = SIMPLEQ_FIRST(l3vpns)) != NULL) {
105 		SIMPLEQ_REMOVE_HEAD(l3vpns, entry);
106 		filterset_free(&vpn->export);
107 		filterset_free(&vpn->import);
108 		free_networks(&vpn->net_l);
109 		free(vpn);
110 	}
111 }
112 
113 void
114 free_prefixsets(struct prefixset_head *psh)
115 {
116 	struct prefixset	*ps;
117 
118 	while (!SIMPLEQ_EMPTY(psh)) {
119 		ps = SIMPLEQ_FIRST(psh);
120 		free_prefixtree(&ps->psitems);
121 		SIMPLEQ_REMOVE_HEAD(psh, entry);
122 		free(ps);
123 	}
124 }
125 
126 void
127 free_rde_prefixsets(struct rde_prefixset_head *psh)
128 {
129 	struct rde_prefixset	*ps;
130 
131 	if (psh == NULL)
132 		return;
133 
134 	while (!SIMPLEQ_EMPTY(psh)) {
135 		ps = SIMPLEQ_FIRST(psh);
136 		trie_free(&ps->th);
137 		SIMPLEQ_REMOVE_HEAD(psh, entry);
138 		free(ps);
139 	}
140 }
141 
142 void
143 free_prefixtree(struct prefixset_tree *p)
144 {
145 	struct prefixset_item	*psi, *npsi;
146 
147 	RB_FOREACH_SAFE(psi, prefixset_tree, p, npsi) {
148 		RB_REMOVE(prefixset_tree, p, psi);
149 		set_free(psi->set);
150 		free(psi);
151 	}
152 }
153 
154 void
155 free_config(struct bgpd_config *conf)
156 {
157 	struct peer		*p, *next;
158 	struct listen_addr	*la;
159 	struct mrt		*m;
160 
161 	free_l3vpns(&conf->l3vpns);
162 	free_networks(&conf->networks);
163 	filterlist_free(conf->filters);
164 	free_prefixsets(&conf->prefixsets);
165 	free_prefixsets(&conf->originsets);
166 	free_rde_prefixsets(&conf->rde_prefixsets);
167 	free_rde_prefixsets(&conf->rde_originsets);
168 	as_sets_free(&conf->as_sets);
169 	free_prefixtree(&conf->roa);
170 
171 	while ((la = TAILQ_FIRST(conf->listen_addrs)) != NULL) {
172 		TAILQ_REMOVE(conf->listen_addrs, la, entry);
173 		free(la);
174 	}
175 	free(conf->listen_addrs);
176 
177 	while ((m = LIST_FIRST(conf->mrt)) != NULL) {
178 		LIST_REMOVE(m, entry);
179 		free(m);
180 	}
181 	free(conf->mrt);
182 
183 	RB_FOREACH_SAFE(p, peer_head, &conf->peers, next) {
184 		RB_REMOVE(peer_head, &conf->peers, p);
185 		free(p);
186 	}
187 
188 	free(conf->csock);
189 	free(conf->rcsock);
190 
191 	free(conf);
192 }
193 
194 void
195 merge_config(struct bgpd_config *xconf, struct bgpd_config *conf)
196 {
197 	struct listen_addr	*nla, *ola, *next;
198 	struct peer		*p, *np, *nextp;
199 
200 	/*
201 	 * merge the freshly parsed conf into the running xconf
202 	 */
203 
204 	/* adjust FIB priority if changed */
205 	/* if xconf is uninitialized we get RTP_NONE */
206 	if (xconf->fib_priority != conf->fib_priority) {
207 		kr_fib_decouple_all(xconf->fib_priority);
208 		kr_fib_update_prio_all(conf->fib_priority);
209 		kr_fib_couple_all(conf->fib_priority);
210 	}
211 
212 	/* take over the easy config changes */
213 	copy_config(xconf, conf);
214 
215 	/* clear old control sockets and use new */
216 	free(xconf->csock);
217 	free(xconf->rcsock);
218 	xconf->csock = conf->csock;
219 	xconf->rcsock = conf->rcsock;
220 	/* set old one to NULL so we don't double free */
221 	conf->csock = NULL;
222 	conf->rcsock = NULL;
223 
224 	/* clear all current filters and take over the new ones */
225 	filterlist_free(xconf->filters);
226 	xconf->filters = conf->filters;
227 	conf->filters = NULL;
228 
229 	/* merge mrt config */
230 	mrt_mergeconfig(xconf->mrt, conf->mrt);
231 
232 	/* switch the roa, first remove the old one */
233 	free_prefixtree(&xconf->roa);
234 	/* then move the RB tree root */
235 	RB_ROOT(&xconf->roa) = RB_ROOT(&conf->roa);
236 	RB_ROOT(&conf->roa) = NULL;
237 
238 	/* switch the prefixsets, first remove the old ones */
239 	free_prefixsets(&xconf->prefixsets);
240 	SIMPLEQ_CONCAT(&xconf->prefixsets, &conf->prefixsets);
241 
242 	/* switch the originsets, first remove the old ones */
243 	free_prefixsets(&xconf->originsets);
244 	SIMPLEQ_CONCAT(&xconf->originsets, &conf->originsets);
245 
246 	/* switch the as_sets, first remove the old ones */
247 	as_sets_free(&xconf->as_sets);
248 	SIMPLEQ_CONCAT(&xconf->as_sets, &conf->as_sets);
249 
250 	/* switch the network statements, but first remove the old ones */
251 	free_networks(&xconf->networks);
252 	TAILQ_CONCAT(&xconf->networks, &conf->networks, entry);
253 
254 	/* switch the l3vpn configs, first remove the old ones */
255 	free_l3vpns(&xconf->l3vpns);
256 	SIMPLEQ_CONCAT(&xconf->l3vpns, &conf->l3vpns);
257 
258 	/*
259 	 * merge new listeners:
260 	 * -flag all existing ones as to be deleted
261 	 * -those that are in both new and old: flag to keep
262 	 * -new ones get inserted and flagged as to reinit
263 	 * -remove all that are still flagged for deletion
264 	 */
265 
266 	TAILQ_FOREACH(nla, xconf->listen_addrs, entry)
267 		nla->reconf = RECONF_DELETE;
268 
269 	/* no new listeners? preserve default ones */
270 	if (TAILQ_EMPTY(conf->listen_addrs))
271 		TAILQ_FOREACH(ola, xconf->listen_addrs, entry)
272 			if (ola->flags & DEFAULT_LISTENER)
273 				ola->reconf = RECONF_KEEP;
274 	/* else loop over listeners and merge configs */
275 	for (nla = TAILQ_FIRST(conf->listen_addrs); nla != NULL; nla = next) {
276 		next = TAILQ_NEXT(nla, entry);
277 
278 		TAILQ_FOREACH(ola, xconf->listen_addrs, entry)
279 			if (!memcmp(&nla->sa, &ola->sa, sizeof(nla->sa)))
280 				break;
281 
282 		if (ola == NULL) {
283 			/* new listener, copy over */
284 			TAILQ_REMOVE(conf->listen_addrs, nla, entry);
285 			TAILQ_INSERT_TAIL(xconf->listen_addrs, nla, entry);
286 			nla->reconf = RECONF_REINIT;
287 		} else		/* exists, just flag */
288 			ola->reconf = RECONF_KEEP;
289 	}
290 	/* finally clean up the original list and remove all stale entires */
291 	for (nla = TAILQ_FIRST(xconf->listen_addrs); nla != NULL; nla = next) {
292 		next = TAILQ_NEXT(nla, entry);
293 		if (nla->reconf == RECONF_DELETE) {
294 			TAILQ_REMOVE(xconf->listen_addrs, nla, entry);
295 			free(nla);
296 		}
297 	}
298 
299 	/*
300 	 * merge peers:
301 	 * - need to know which peers are new, replaced and removed
302 	 * - walk over old peers and check if there is a corresponding new
303 	 *   peer if so mark it RECONF_KEEP. Remove all old peers.
304 	 * - swap lists (old peer list is actually empty).
305 	 */
306 	RB_FOREACH_SAFE(p, peer_head, &xconf->peers, nextp) {
307 		np = getpeerbyid(conf, p->conf.id);
308 		if (np != NULL) {
309 			np->reconf_action = RECONF_KEEP;
310 			/* copy the auth state since parent uses it */
311 			np->auth = p->auth;
312 		} else {
313 			/* peer no longer exists, clear pfkey state */
314 			pfkey_remove(p);
315 		}
316 
317 		RB_REMOVE(peer_head, &xconf->peers, p);
318 		free(p);
319 	}
320 	RB_FOREACH_SAFE(np, peer_head, &conf->peers, nextp) {
321 		RB_REMOVE(peer_head, &conf->peers, np);
322 		if (RB_INSERT(peer_head, &xconf->peers, np) != NULL)
323 			fatalx("%s: peer tree is corrupt", __func__);
324 	}
325 
326 	/* conf is merged so free it */
327 	free_config(conf);
328 }
329 
330 u_int32_t
331 get_bgpid(void)
332 {
333 	struct ifaddrs		*ifap, *ifa;
334 	u_int32_t		 ip = 0, cur, localnet;
335 
336 	localnet = htonl(INADDR_LOOPBACK & IN_CLASSA_NET);
337 
338 	if (getifaddrs(&ifap) == -1)
339 		fatal("getifaddrs");
340 
341 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
342 		if (ifa->ifa_addr->sa_family != AF_INET)
343 			continue;
344 		cur = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
345 		if ((cur & localnet) == localnet)	/* skip 127/8 */
346 			continue;
347 		if (ntohl(cur) > ntohl(ip))
348 			ip = cur;
349 	}
350 	freeifaddrs(ifap);
351 
352 	return (ip);
353 }
354 
355 int
356 host(const char *s, struct bgpd_addr *h, u_int8_t *len)
357 {
358 	int			 mask = 128;
359 	char			*p, *ps;
360 	const char		*errstr;
361 
362 	if ((ps = strdup(s)) == NULL)
363 		fatal("%s: strdup", __func__);
364 
365 	if ((p = strrchr(ps, '/')) != NULL) {
366 		mask = strtonum(p+1, 0, 128, &errstr);
367 		if (errstr) {
368 			log_warnx("prefixlen is %s: %s", errstr, p);
369 			free(ps);
370 			return (0);
371 		}
372 		p[0] = '\0';
373 	}
374 
375 	bzero(h, sizeof(*h));
376 
377 	if (host_ip(ps, h, len) == 0) {
378 		free(ps);
379 		return (0);
380 	}
381 
382 	if (p != NULL)
383 		*len = mask;
384 
385 	free(ps);
386 	return (1);
387 }
388 
389 int
390 host_ip(const char *s, struct bgpd_addr *h, u_int8_t *len)
391 {
392 	struct addrinfo		 hints, *res;
393 	int			 bits;
394 
395 	bzero(&hints, sizeof(hints));
396 	hints.ai_family = AF_UNSPEC;
397 	hints.ai_socktype = SOCK_DGRAM; /*dummy*/
398 	hints.ai_flags = AI_NUMERICHOST;
399 	if (getaddrinfo(s, NULL, &hints, &res) == 0) {
400 		*len = res->ai_family == AF_INET6 ? 128 : 32;
401 		sa2addr(res->ai_addr, h, NULL);
402 		freeaddrinfo(res);
403 	} else {	/* ie. for 10/8 parsing */
404 		if ((bits = inet_net_pton(AF_INET, s, &h->v4, sizeof(h->v4))) == -1)
405 			return (0);
406 		*len = bits;
407 		h->aid = AID_INET;
408 	}
409 
410 	return (1);
411 }
412 
413 int
414 prepare_listeners(struct bgpd_config *conf)
415 {
416 	struct listen_addr	*la, *next;
417 	int			 opt = 1;
418 	int			 r = 0;
419 
420 	if (TAILQ_EMPTY(conf->listen_addrs)) {
421 		if ((la = calloc(1, sizeof(struct listen_addr))) == NULL)
422 			fatal("setup_listeners calloc");
423 		la->fd = -1;
424 		la->flags = DEFAULT_LISTENER;
425 		la->reconf = RECONF_REINIT;
426 		la->sa_len = sizeof(struct sockaddr_in);
427 		((struct sockaddr_in *)&la->sa)->sin_family = AF_INET;
428 		((struct sockaddr_in *)&la->sa)->sin_addr.s_addr =
429 		    htonl(INADDR_ANY);
430 		((struct sockaddr_in *)&la->sa)->sin_port = htons(BGP_PORT);
431 		TAILQ_INSERT_TAIL(conf->listen_addrs, la, entry);
432 
433 		if ((la = calloc(1, sizeof(struct listen_addr))) == NULL)
434 			fatal("setup_listeners calloc");
435 		la->fd = -1;
436 		la->flags = DEFAULT_LISTENER;
437 		la->reconf = RECONF_REINIT;
438 		la->sa_len = sizeof(struct sockaddr_in6);
439 		((struct sockaddr_in6 *)&la->sa)->sin6_family = AF_INET6;
440 		((struct sockaddr_in6 *)&la->sa)->sin6_port = htons(BGP_PORT);
441 		TAILQ_INSERT_TAIL(conf->listen_addrs, la, entry);
442 	}
443 
444 	for (la = TAILQ_FIRST(conf->listen_addrs); la != NULL; la = next) {
445 		next = TAILQ_NEXT(la, entry);
446 		if (la->reconf != RECONF_REINIT)
447 			continue;
448 
449 		if ((la->fd = socket(la->sa.ss_family,
450 		    SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
451 		    IPPROTO_TCP)) == -1) {
452 			if (la->flags & DEFAULT_LISTENER && (errno ==
453 			    EAFNOSUPPORT || errno == EPROTONOSUPPORT)) {
454 				TAILQ_REMOVE(conf->listen_addrs, la, entry);
455 				free(la);
456 				continue;
457 			} else
458 				fatal("socket");
459 		}
460 
461 		opt = 1;
462 		if (setsockopt(la->fd, SOL_SOCKET, SO_REUSEADDR,
463 		    &opt, sizeof(opt)) == -1)
464 			fatal("setsockopt SO_REUSEADDR");
465 
466 		if (bind(la->fd, (struct sockaddr *)&la->sa, la->sa_len) ==
467 		    -1) {
468 			switch (la->sa.ss_family) {
469 			case AF_INET:
470 				log_warn("cannot bind to %s:%u",
471 				    log_sockaddr((struct sockaddr *)&la->sa,
472 				    la->sa_len), ntohs(((struct sockaddr_in *)
473 				    &la->sa)->sin_port));
474 				break;
475 			case AF_INET6:
476 				log_warn("cannot bind to [%s]:%u",
477 				    log_sockaddr((struct sockaddr *)&la->sa,
478 				    la->sa_len), ntohs(((struct sockaddr_in6 *)
479 				    &la->sa)->sin6_port));
480 				break;
481 			default:
482 				log_warn("cannot bind to %s",
483 				    log_sockaddr((struct sockaddr *)&la->sa,
484 				    la->sa_len));
485 				break;
486 			}
487 			close(la->fd);
488 			TAILQ_REMOVE(conf->listen_addrs, la, entry);
489 			free(la);
490 			r = -1;
491 			continue;
492 		}
493 	}
494 
495 	return (r);
496 }
497 
498 void
499 expand_networks(struct bgpd_config *c)
500 {
501 	struct network		*n, *m, *tmp;
502 	struct network_head	*nw = &c->networks;
503 	struct prefixset	*ps;
504 	struct prefixset_item	*psi;
505 
506 	TAILQ_FOREACH_SAFE(n, nw, entry, tmp) {
507 		if (n->net.type == NETWORK_PREFIXSET) {
508 			TAILQ_REMOVE(nw, n, entry);
509 			if ((ps = find_prefixset(n->net.psname, &c->prefixsets))
510 			    == NULL)
511 				fatal("%s: prefixset %s not found", __func__,
512 				    n->net.psname);
513 			RB_FOREACH(psi, prefixset_tree, &ps->psitems) {
514 				if ((m = calloc(1, sizeof(struct network)))
515 				    == NULL)
516 					fatal(NULL);
517 				memcpy(&m->net.prefix, &psi->p.addr,
518 				    sizeof(m->net.prefix));
519 				m->net.prefixlen = psi->p.len;
520 				filterset_copy(&n->net.attrset,
521 				    &m->net.attrset);
522 				TAILQ_INSERT_TAIL(nw, m, entry);
523 			}
524 			filterset_free(&n->net.attrset);
525 			free(n);
526 		}
527 	}
528 }
529 
530 int
531 prefixset_cmp(struct prefixset_item *a, struct prefixset_item *b)
532 {
533 	int i;
534 
535 	if (a->p.addr.aid < b->p.addr.aid)
536 		return (-1);
537 	if (a->p.addr.aid > b->p.addr.aid)
538 		return (1);
539 
540 	switch (a->p.addr.aid) {
541 	case AID_INET:
542 		if (ntohl(a->p.addr.v4.s_addr) < ntohl(b->p.addr.v4.s_addr))
543 			return (-1);
544 		if (ntohl(a->p.addr.v4.s_addr) > ntohl(b->p.addr.v4.s_addr))
545 			return (1);
546 		break;
547 	case AID_INET6:
548 		i = memcmp(&a->p.addr.v6, &b->p.addr.v6,
549 		    sizeof(struct in6_addr));
550 		if (i > 0)
551 			return (1);
552 		if (i < 0)
553 			return (-1);
554 		break;
555 	default:
556 		fatalx("%s: unknown af", __func__);
557 	}
558 	if (a->p.len < b->p.len)
559 		return (-1);
560 	if (a->p.len > b->p.len)
561 		return (1);
562 	if (a->p.len_min < b->p.len_min)
563 		return (-1);
564 	if (a->p.len_min > b->p.len_min)
565 		return (1);
566 	if (a->p.len_max < b->p.len_max)
567 		return (-1);
568 	if (a->p.len_max > b->p.len_max)
569 		return (1);
570 	return (0);
571 }
572 
573 RB_GENERATE(prefixset_tree, prefixset_item, entry, prefixset_cmp);
574