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