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