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