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