bgpd.c revision 1.215
1/* $OpenBSD: bgpd.c,v 1.215 2019/03/31 16:57:38 claudio Exp $ */ 2 3/* 4 * Copyright (c) 2003, 2004 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#include <sys/wait.h> 22#include <netinet/in.h> 23#include <arpa/inet.h> 24#include <err.h> 25#include <errno.h> 26#include <fcntl.h> 27#include <poll.h> 28#include <pwd.h> 29#include <signal.h> 30#include <stdio.h> 31#include <stdlib.h> 32#include <string.h> 33#include <syslog.h> 34#include <unistd.h> 35 36#include "bgpd.h" 37#include "mrt.h" 38#include "session.h" 39#include "log.h" 40 41void sighdlr(int); 42__dead void usage(void); 43int main(int, char *[]); 44pid_t start_child(enum bgpd_process, char *, int, int, int); 45int send_filterset(struct imsgbuf *, struct filter_set_head *); 46int reconfigure(char *, struct bgpd_config *); 47int dispatch_imsg(struct imsgbuf *, int, struct bgpd_config *); 48int control_setup(struct bgpd_config *); 49int imsg_send_sockets(struct imsgbuf *, struct imsgbuf *); 50 51int cflags; 52volatile sig_atomic_t mrtdump; 53volatile sig_atomic_t quit; 54volatile sig_atomic_t reconfig; 55pid_t reconfpid; 56int reconfpending; 57struct imsgbuf *ibuf_se; 58struct imsgbuf *ibuf_rde; 59struct rib_names ribnames = SIMPLEQ_HEAD_INITIALIZER(ribnames); 60char *cname; 61char *rcname; 62 63void 64sighdlr(int sig) 65{ 66 switch (sig) { 67 case SIGTERM: 68 case SIGINT: 69 quit = 1; 70 break; 71 case SIGHUP: 72 reconfig = 1; 73 break; 74 case SIGALRM: 75 case SIGUSR1: 76 mrtdump = 1; 77 break; 78 } 79} 80 81__dead void 82usage(void) 83{ 84 extern char *__progname; 85 86 fprintf(stderr, "usage: %s [-cdnv] [-D macro=value] [-f file]\n", 87 __progname); 88 exit(1); 89} 90 91#define PFD_PIPE_SESSION 0 92#define PFD_PIPE_ROUTE 1 93#define PFD_SOCK_ROUTE 2 94#define POLL_MAX 3 95#define MAX_TIMEOUT 3600 96 97int cmd_opts; 98 99int 100main(int argc, char *argv[]) 101{ 102 struct bgpd_config *conf; 103 struct rde_rib *rr; 104 struct pollfd pfd[POLL_MAX]; 105 time_t timeout; 106 pid_t se_pid = 0, rde_pid = 0, pid; 107 char *conffile; 108 char *saved_argv0; 109 int debug = 0; 110 int rflag = 0, sflag = 0; 111 int rfd = -1; 112 int ch, status; 113 int pipe_m2s[2]; 114 int pipe_m2r[2]; 115 116 conffile = CONFFILE; 117 bgpd_process = PROC_MAIN; 118 119 log_init(1, LOG_DAEMON); /* log to stderr until daemonized */ 120 log_procinit(log_procnames[bgpd_process]); 121 log_setverbose(1); 122 123 saved_argv0 = argv[0]; 124 if (saved_argv0 == NULL) 125 saved_argv0 = "bgpd"; 126 127 while ((ch = getopt(argc, argv, "cdD:f:nRSv")) != -1) { 128 switch (ch) { 129 case 'c': 130 cmd_opts |= BGPD_OPT_FORCE_DEMOTE; 131 break; 132 case 'd': 133 debug = 1; 134 break; 135 case 'D': 136 if (cmdline_symset(optarg) < 0) 137 log_warnx("could not parse macro definition %s", 138 optarg); 139 break; 140 case 'f': 141 conffile = optarg; 142 break; 143 case 'n': 144 cmd_opts |= BGPD_OPT_NOACTION; 145 break; 146 case 'v': 147 if (cmd_opts & BGPD_OPT_VERBOSE) 148 cmd_opts |= BGPD_OPT_VERBOSE2; 149 cmd_opts |= BGPD_OPT_VERBOSE; 150 break; 151 case 'R': 152 rflag = 1; 153 break; 154 case 'S': 155 sflag = 1; 156 break; 157 default: 158 usage(); 159 /* NOTREACHED */ 160 } 161 } 162 163 argc -= optind; 164 argv += optind; 165 if (argc > 0 || (sflag && rflag)) 166 usage(); 167 168 if (cmd_opts & BGPD_OPT_NOACTION) { 169 if ((conf = parse_config(conffile, NULL)) == NULL) 170 exit(1); 171 172 if (cmd_opts & BGPD_OPT_VERBOSE) 173 print_config(conf, &ribnames); 174 else 175 fprintf(stderr, "configuration OK\n"); 176 177 while ((rr = SIMPLEQ_FIRST(&ribnames)) != NULL) { 178 SIMPLEQ_REMOVE_HEAD(&ribnames, entry); 179 free(rr); 180 } 181 free_config(conf); 182 exit(0); 183 } 184 185 if (rflag) 186 rde_main(debug, cmd_opts & BGPD_OPT_VERBOSE); 187 else if (sflag) 188 session_main(debug, cmd_opts & BGPD_OPT_VERBOSE); 189 190 if (geteuid()) 191 errx(1, "need root privileges"); 192 193 if (getpwnam(BGPD_USER) == NULL) 194 errx(1, "unknown user %s", BGPD_USER); 195 196 log_init(debug, LOG_DAEMON); 197 log_setverbose(cmd_opts & BGPD_OPT_VERBOSE); 198 199 if (!debug) 200 daemon(1, 0); 201 202 log_info("startup"); 203 204 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 205 PF_UNSPEC, pipe_m2s) == -1) 206 fatal("socketpair"); 207 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 208 PF_UNSPEC, pipe_m2r) == -1) 209 fatal("socketpair"); 210 211 /* fork children */ 212 rde_pid = start_child(PROC_RDE, saved_argv0, pipe_m2r[1], debug, 213 cmd_opts & BGPD_OPT_VERBOSE); 214 se_pid = start_child(PROC_SE, saved_argv0, pipe_m2s[1], debug, 215 cmd_opts & BGPD_OPT_VERBOSE); 216 217 signal(SIGTERM, sighdlr); 218 signal(SIGINT, sighdlr); 219 signal(SIGHUP, sighdlr); 220 signal(SIGALRM, sighdlr); 221 signal(SIGUSR1, sighdlr); 222 signal(SIGPIPE, SIG_IGN); 223 224 if ((ibuf_se = malloc(sizeof(struct imsgbuf))) == NULL || 225 (ibuf_rde = malloc(sizeof(struct imsgbuf))) == NULL) 226 fatal(NULL); 227 imsg_init(ibuf_se, pipe_m2s[0]); 228 imsg_init(ibuf_rde, pipe_m2r[0]); 229 mrt_init(ibuf_rde, ibuf_se); 230 if ((rfd = kr_init()) == -1) 231 quit = 1; 232 233 /* 234 * rpath, read config file 235 * cpath, unlink control socket 236 * fattr, chmod on control socket 237 * wpath, needed if we are doing mrt dumps 238 * 239 * pledge placed here because kr_init() does a setsockopt on the 240 * routing socket thats not allowed at all. 241 */ 242#if 0 243 /* 244 * disabled because we do ioctls on /dev/pf and SIOCSIFGATTR 245 * this needs some redesign of bgpd to be fixed. 246 */ 247BROKEN if (pledge("stdio rpath wpath cpath fattr unix route recvfd sendfd", 248 NULL) == -1) 249 fatal("pledge"); 250#endif 251 252 if (imsg_send_sockets(ibuf_se, ibuf_rde)) 253 fatal("could not establish imsg links"); 254 conf = new_config(); 255 quit = reconfigure(conffile, conf); 256 if (pftable_clear_all() != 0) 257 quit = 1; 258 259 while (quit == 0) { 260 bzero(pfd, sizeof(pfd)); 261 262 timeout = mrt_timeout(conf->mrt); 263 264 pfd[PFD_SOCK_ROUTE].fd = rfd; 265 pfd[PFD_SOCK_ROUTE].events = POLLIN; 266 267 set_pollfd(&pfd[PFD_PIPE_SESSION], ibuf_se); 268 set_pollfd(&pfd[PFD_PIPE_ROUTE], ibuf_rde); 269 270 if (timeout < 0 || timeout > MAX_TIMEOUT) 271 timeout = MAX_TIMEOUT; 272 if (poll(pfd, POLL_MAX, timeout * 1000) == -1) 273 if (errno != EINTR) { 274 log_warn("poll error"); 275 quit = 1; 276 } 277 278 if (handle_pollfd(&pfd[PFD_PIPE_SESSION], ibuf_se) == -1) { 279 log_warnx("main: Lost connection to SE"); 280 msgbuf_clear(&ibuf_se->w); 281 free(ibuf_se); 282 ibuf_se = NULL; 283 quit = 1; 284 } else { 285 if (dispatch_imsg(ibuf_se, PFD_PIPE_SESSION, conf) == 286 -1) 287 quit = 1; 288 } 289 290 if (handle_pollfd(&pfd[PFD_PIPE_ROUTE], ibuf_rde) == -1) { 291 log_warnx("main: Lost connection to RDE"); 292 msgbuf_clear(&ibuf_rde->w); 293 free(ibuf_rde); 294 ibuf_rde = NULL; 295 quit = 1; 296 } else { 297 if (dispatch_imsg(ibuf_rde, PFD_PIPE_ROUTE, conf) == 298 -1) 299 quit = 1; 300 } 301 302 if (pfd[PFD_SOCK_ROUTE].revents & POLLIN) { 303 if (kr_dispatch_msg(conf->default_tableid) == -1) 304 quit = 1; 305 } 306 307 if (reconfig) { 308 u_int error; 309 310 reconfig = 0; 311 switch (reconfigure(conffile, conf)) { 312 case -1: /* fatal error */ 313 quit = 1; 314 break; 315 case 0: /* all OK */ 316 error = 0; 317 break; 318 case 2: 319 error = CTL_RES_PENDING; 320 break; 321 default: /* parse error */ 322 error = CTL_RES_PARSE_ERROR; 323 break; 324 } 325 if (reconfpid != 0) { 326 send_imsg_session(IMSG_CTL_RESULT, reconfpid, 327 &error, sizeof(error)); 328 reconfpid = 0; 329 } 330 } 331 332 if (mrtdump) { 333 mrtdump = 0; 334 mrt_handler(conf->mrt); 335 } 336 } 337 338 /* close pipes */ 339 if (ibuf_se) { 340 msgbuf_clear(&ibuf_se->w); 341 close(ibuf_se->fd); 342 free(ibuf_se); 343 ibuf_se = NULL; 344 } 345 if (ibuf_rde) { 346 msgbuf_clear(&ibuf_rde->w); 347 close(ibuf_rde->fd); 348 free(ibuf_rde); 349 ibuf_rde = NULL; 350 } 351 352 while ((rr = SIMPLEQ_FIRST(&ribnames)) != NULL) { 353 SIMPLEQ_REMOVE_HEAD(&ribnames, entry); 354 free(rr); 355 } 356 357 carp_demote_shutdown(); 358 kr_shutdown(conf->fib_priority, conf->default_tableid); 359 pftable_clear_all(); 360 361 free_config(conf); 362 363 log_debug("waiting for children to terminate"); 364 do { 365 pid = wait(&status); 366 if (pid == -1) { 367 if (errno != EINTR && errno != ECHILD) 368 fatal("wait"); 369 } else if (WIFSIGNALED(status)) { 370 char *name = "unknown process"; 371 if (pid == rde_pid) 372 name = "route decision engine"; 373 else if (pid == se_pid) 374 name = "session engine"; 375 log_warnx("%s terminated; signal %d", name, 376 WTERMSIG(status)); 377 } 378 } while (pid != -1 || (pid == -1 && errno == EINTR)); 379 380 free(rcname); 381 free(cname); 382 383 log_info("terminating"); 384 return (0); 385} 386 387pid_t 388start_child(enum bgpd_process p, char *argv0, int fd, int debug, int verbose) 389{ 390 char *argv[5]; 391 int argc = 0; 392 pid_t pid; 393 394 switch (pid = fork()) { 395 case -1: 396 fatal("cannot fork"); 397 case 0: 398 break; 399 default: 400 close(fd); 401 return (pid); 402 } 403 404 if (fd != 3) { 405 if (dup2(fd, 3) == -1) 406 fatal("cannot setup imsg fd"); 407 } else if (fcntl(fd, F_SETFD, 0) == -1) 408 fatal("cannot setup imsg fd"); 409 410 argv[argc++] = argv0; 411 switch (p) { 412 case PROC_MAIN: 413 fatalx("Can not start main process"); 414 case PROC_RDE: 415 argv[argc++] = "-R"; 416 break; 417 case PROC_SE: 418 argv[argc++] = "-S"; 419 break; 420 } 421 if (debug) 422 argv[argc++] = "-d"; 423 if (verbose) 424 argv[argc++] = "-v"; 425 argv[argc++] = NULL; 426 427 execvp(argv0, argv); 428 fatal("execvp"); 429} 430 431int 432send_filterset(struct imsgbuf *i, struct filter_set_head *set) 433{ 434 struct filter_set *s; 435 436 TAILQ_FOREACH(s, set, entry) 437 if (imsg_compose(i, IMSG_FILTER_SET, 0, 0, -1, s, 438 sizeof(struct filter_set)) == -1) 439 return (-1); 440 return (0); 441} 442 443int 444reconfigure(char *conffile, struct bgpd_config *conf) 445{ 446 struct bgpd_config *new_conf; 447 struct peer *p; 448 struct filter_rule *r; 449 struct listen_addr *la; 450 struct rde_rib *rr; 451 struct l3vpn *vpn; 452 struct as_set *aset; 453 struct prefixset *ps; 454 struct prefixset_item *psi, *npsi; 455 456 if (reconfpending) { 457 log_info("previous reload still running"); 458 return (2); 459 } 460 reconfpending = 2; /* one per child */ 461 462 log_info("rereading config"); 463 if ((new_conf = parse_config(conffile, &conf->peers)) == NULL) { 464 log_warnx("config file %s has errors, not reloading", 465 conffile); 466 reconfpending = 0; 467 return (1); 468 } 469 merge_config(conf, new_conf); 470 471 if (prepare_listeners(conf) == -1) { 472 reconfpending = 0; 473 return (1); 474 } 475 476 if (control_setup(conf) == -1) { 477 reconfpending = 0; 478 return (1); 479 } 480 481 expand_networks(conf); 482 483 cflags = conf->flags; 484 485 /* start reconfiguration */ 486 if (imsg_compose(ibuf_se, IMSG_RECONF_CONF, 0, 0, -1, 487 conf, sizeof(struct bgpd_config)) == -1) 488 return (-1); 489 if (imsg_compose(ibuf_rde, IMSG_RECONF_CONF, 0, 0, -1, 490 conf, sizeof(struct bgpd_config)) == -1) 491 return (-1); 492 493 TAILQ_FOREACH(la, conf->listen_addrs, entry) { 494 if (imsg_compose(ibuf_se, IMSG_RECONF_LISTENER, 0, 0, la->fd, 495 la, sizeof(struct listen_addr)) == -1) 496 return (-1); 497 la->fd = -1; 498 } 499 500 /* adjust fib syncing on reload */ 501 ktable_preload(); 502 503 /* RIBs for the RDE */ 504 while ((rr = SIMPLEQ_FIRST(&ribnames))) { 505 SIMPLEQ_REMOVE_HEAD(&ribnames, entry); 506 if (ktable_update(rr->rtableid, rr->name, rr->flags, 507 conf->fib_priority) == -1) { 508 log_warnx("failed to load rdomain %d", 509 rr->rtableid); 510 return (-1); 511 } 512 if (imsg_compose(ibuf_rde, IMSG_RECONF_RIB, 0, 0, -1, 513 rr, sizeof(struct rde_rib)) == -1) 514 return (-1); 515 free(rr); 516 } 517 518 /* send peer list to the SE */ 519 TAILQ_FOREACH(p, &conf->peers, entry) { 520 if (imsg_compose(ibuf_se, IMSG_RECONF_PEER, p->conf.id, 0, -1, 521 &p->conf, sizeof(struct peer_config)) == -1) 522 return (-1); 523 } 524 525 /* networks go via kroute to the RDE */ 526 kr_net_reload(conf->default_tableid, 0, &conf->networks); 527 528 /* prefixsets for filters in the RDE */ 529 while ((ps = SIMPLEQ_FIRST(&conf->prefixsets)) != NULL) { 530 SIMPLEQ_REMOVE_HEAD(&conf->prefixsets, entry); 531 if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIX_SET, 0, 0, -1, 532 ps->name, sizeof(ps->name)) == -1) 533 return (-1); 534 RB_FOREACH_SAFE(psi, prefixset_tree, &ps->psitems, npsi) { 535 RB_REMOVE(prefixset_tree, &ps->psitems, psi); 536 if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIX_SET_ITEM, 537 0, 0, -1, psi, sizeof(*psi)) == -1) 538 return (-1); 539 set_free(psi->set); 540 free(psi); 541 } 542 free(ps); 543 } 544 545 /* originsets for filters in the RDE */ 546 while ((ps = SIMPLEQ_FIRST(&conf->originsets)) != NULL) { 547 SIMPLEQ_REMOVE_HEAD(&conf->originsets, entry); 548 if (imsg_compose(ibuf_rde, IMSG_RECONF_ORIGIN_SET, 0, 0, -1, 549 ps->name, sizeof(ps->name)) == -1) 550 return (-1); 551 RB_FOREACH_SAFE(psi, prefixset_tree, &ps->psitems, npsi) { 552 struct roa_set *rs; 553 size_t i, l, n; 554 RB_REMOVE(prefixset_tree, &ps->psitems, psi); 555 rs = set_get(psi->set, &n); 556 for (i = 0; i < n; i += l) { 557 l = (n - i > 1024 ? 1024 : n - i); 558 if (imsg_compose(ibuf_rde, 559 IMSG_RECONF_ROA_SET_ITEMS, 560 0, 0, -1, rs + i, l * sizeof(*rs)) == -1) 561 return -1; 562 } 563 if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIX_SET_ITEM, 564 0, 0, -1, psi, sizeof(*psi)) == -1) 565 return (-1); 566 set_free(psi->set); 567 free(psi); 568 } 569 free(ps); 570 } 571 572 if (!RB_EMPTY(&conf->roa)) { 573 if (imsg_compose(ibuf_rde, IMSG_RECONF_ROA_SET, 0, 0, -1, 574 NULL, 0) == -1) 575 return (-1); 576 RB_FOREACH_SAFE(psi, prefixset_tree, &conf->roa, npsi) { 577 struct roa_set *rs; 578 size_t i, l, n; 579 RB_REMOVE(prefixset_tree, &conf->roa, psi); 580 rs = set_get(psi->set, &n); 581 for (i = 0; i < n; i += l) { 582 l = (n - i > 1024 ? 1024 : n - i); 583 if (imsg_compose(ibuf_rde, 584 IMSG_RECONF_ROA_SET_ITEMS, 585 0, 0, -1, rs + i, l * sizeof(*rs)) == -1) 586 return -1; 587 } 588 if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIX_SET_ITEM, 589 0, 0, -1, psi, sizeof(*psi)) == -1) 590 return (-1); 591 set_free(psi->set); 592 free(psi); 593 } 594 } 595 596 /* as-sets for filters in the RDE */ 597 while ((aset = SIMPLEQ_FIRST(conf->as_sets)) != NULL) { 598 struct ibuf *wbuf; 599 u_int32_t *as; 600 size_t i, l, n; 601 602 SIMPLEQ_REMOVE_HEAD(conf->as_sets, entry); 603 604 as = set_get(aset->set, &n); 605 if ((wbuf = imsg_create(ibuf_rde, IMSG_RECONF_AS_SET, 0, 0, 606 sizeof(n) + sizeof(aset->name))) == NULL) 607 return -1; 608 if (imsg_add(wbuf, &n, sizeof(n)) == -1 || 609 imsg_add(wbuf, aset->name, sizeof(aset->name)) == -1) 610 return -1; 611 imsg_close(ibuf_rde, wbuf); 612 613 for (i = 0; i < n; i += l) { 614 l = (n - i > 1024 ? 1024 : n - i); 615 if (imsg_compose(ibuf_rde, IMSG_RECONF_AS_SET_ITEMS, 616 0, 0, -1, as + i, l * sizeof(*as)) == -1) 617 return -1; 618 } 619 620 if (imsg_compose(ibuf_rde, IMSG_RECONF_AS_SET_DONE, 0, 0, -1, 621 NULL, 0) == -1) 622 return -1; 623 624 set_free(aset->set); 625 free(aset); 626 } 627 628 /* filters for the RDE */ 629 while ((r = TAILQ_FIRST(conf->filters)) != NULL) { 630 TAILQ_REMOVE(conf->filters, r, entry); 631 if (imsg_compose(ibuf_rde, IMSG_RECONF_FILTER, 0, 0, -1, 632 r, sizeof(struct filter_rule)) == -1) 633 return (-1); 634 if (send_filterset(ibuf_rde, &r->set) == -1) 635 return (-1); 636 filterset_free(&r->set); 637 free(r); 638 } 639 640 while ((vpn = SIMPLEQ_FIRST(&conf->l3vpns)) != NULL) { 641 SIMPLEQ_REMOVE_HEAD(&conf->l3vpns, entry); 642 if (ktable_update(vpn->rtableid, vpn->descr, vpn->flags, 643 conf->fib_priority) == -1) { 644 log_warnx("failed to load rdomain %d", 645 vpn->rtableid); 646 return (-1); 647 } 648 /* networks go via kroute to the RDE */ 649 kr_net_reload(vpn->rtableid, vpn->rd, &vpn->net_l); 650 651 if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN, 0, 0, -1, 652 vpn, sizeof(*vpn)) == -1) 653 return (-1); 654 655 /* export targets */ 656 if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN_EXPORT, 0, 0, 657 -1, NULL, 0) == -1) 658 return (-1); 659 if (send_filterset(ibuf_rde, &vpn->export) == -1) 660 return (-1); 661 filterset_free(&vpn->export); 662 663 /* import targets */ 664 if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN_IMPORT, 0, 0, 665 -1, NULL, 0) == -1) 666 return (-1); 667 if (send_filterset(ibuf_rde, &vpn->import) == -1) 668 return (-1); 669 filterset_free(&vpn->import); 670 671 if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN_DONE, 0, 0, 672 -1, NULL, 0) == -1) 673 return (-1); 674 675 free(vpn); 676 } 677 678 /* send a drain message to know when all messages where processed */ 679 if (imsg_compose(ibuf_se, IMSG_RECONF_DRAIN, 0, 0, -1, NULL, 0) == -1) 680 return (-1); 681 if (imsg_compose(ibuf_rde, IMSG_RECONF_DRAIN, 0, 0, -1, NULL, 0) == -1) 682 return (-1); 683 684 /* mrt changes can be sent out of bound */ 685 mrt_reconfigure(conf->mrt); 686 return (0); 687} 688 689int 690dispatch_imsg(struct imsgbuf *ibuf, int idx, struct bgpd_config *conf) 691{ 692 struct imsg imsg; 693 ssize_t n; 694 int rv, verbose; 695 696 rv = 0; 697 while (ibuf) { 698 if ((n = imsg_get(ibuf, &imsg)) == -1) 699 return (-1); 700 701 if (n == 0) 702 break; 703 704 switch (imsg.hdr.type) { 705 case IMSG_KROUTE_CHANGE: 706 if (idx != PFD_PIPE_ROUTE) 707 log_warnx("route request not from RDE"); 708 else if (imsg.hdr.len != IMSG_HEADER_SIZE + 709 sizeof(struct kroute_full)) 710 log_warnx("wrong imsg len"); 711 else if (kr_change(imsg.hdr.peerid, imsg.data, 712 conf->fib_priority)) 713 rv = -1; 714 break; 715 case IMSG_KROUTE_DELETE: 716 if (idx != PFD_PIPE_ROUTE) 717 log_warnx("route request not from RDE"); 718 else if (imsg.hdr.len != IMSG_HEADER_SIZE + 719 sizeof(struct kroute_full)) 720 log_warnx("wrong imsg len"); 721 else if (kr_delete(imsg.hdr.peerid, imsg.data, 722 conf->fib_priority)) 723 rv = -1; 724 break; 725 case IMSG_NEXTHOP_ADD: 726 if (idx != PFD_PIPE_ROUTE) 727 log_warnx("nexthop request not from RDE"); 728 else if (imsg.hdr.len != IMSG_HEADER_SIZE + 729 sizeof(struct bgpd_addr)) 730 log_warnx("wrong imsg len"); 731 else if (kr_nexthop_add(imsg.hdr.peerid, imsg.data, 732 conf) == -1) 733 rv = -1; 734 break; 735 case IMSG_NEXTHOP_REMOVE: 736 if (idx != PFD_PIPE_ROUTE) 737 log_warnx("nexthop request not from RDE"); 738 else if (imsg.hdr.len != IMSG_HEADER_SIZE + 739 sizeof(struct bgpd_addr)) 740 log_warnx("wrong imsg len"); 741 else 742 kr_nexthop_delete(imsg.hdr.peerid, imsg.data, 743 conf); 744 break; 745 case IMSG_PFTABLE_ADD: 746 if (idx != PFD_PIPE_ROUTE) 747 log_warnx("pftable request not from RDE"); 748 else 749 if (imsg.hdr.len != IMSG_HEADER_SIZE + 750 sizeof(struct pftable_msg)) 751 log_warnx("wrong imsg len"); 752 else if (pftable_addr_add(imsg.data) != 0) 753 rv = -1; 754 break; 755 case IMSG_PFTABLE_REMOVE: 756 if (idx != PFD_PIPE_ROUTE) 757 log_warnx("pftable request not from RDE"); 758 else 759 if (imsg.hdr.len != IMSG_HEADER_SIZE + 760 sizeof(struct pftable_msg)) 761 log_warnx("wrong imsg len"); 762 else if (pftable_addr_remove(imsg.data) != 0) 763 rv = -1; 764 break; 765 case IMSG_PFTABLE_COMMIT: 766 if (idx != PFD_PIPE_ROUTE) 767 log_warnx("pftable request not from RDE"); 768 else 769 if (imsg.hdr.len != IMSG_HEADER_SIZE) 770 log_warnx("wrong imsg len"); 771 else if (pftable_commit() != 0) 772 rv = -1; 773 break; 774 case IMSG_CTL_RELOAD: 775 if (idx != PFD_PIPE_SESSION) 776 log_warnx("reload request not from SE"); 777 else { 778 reconfig = 1; 779 reconfpid = imsg.hdr.pid; 780 } 781 break; 782 case IMSG_CTL_FIB_COUPLE: 783 if (idx != PFD_PIPE_SESSION) 784 log_warnx("couple request not from SE"); 785 else 786 kr_fib_couple(imsg.hdr.peerid, 787 conf->fib_priority); 788 break; 789 case IMSG_CTL_FIB_DECOUPLE: 790 if (idx != PFD_PIPE_SESSION) 791 log_warnx("decouple request not from SE"); 792 else 793 kr_fib_decouple(imsg.hdr.peerid, 794 conf->fib_priority); 795 break; 796 case IMSG_CTL_KROUTE: 797 case IMSG_CTL_KROUTE_ADDR: 798 case IMSG_CTL_SHOW_NEXTHOP: 799 case IMSG_CTL_SHOW_INTERFACE: 800 case IMSG_CTL_SHOW_FIB_TABLES: 801 if (idx != PFD_PIPE_SESSION) 802 log_warnx("kroute request not from SE"); 803 else 804 kr_show_route(&imsg); 805 break; 806 case IMSG_IFINFO: 807 if (idx != PFD_PIPE_SESSION) 808 log_warnx("IFINFO request not from SE"); 809 else if (imsg.hdr.len != IMSG_HEADER_SIZE + IFNAMSIZ) 810 log_warnx("IFINFO request with wrong len"); 811 else 812 kr_ifinfo(imsg.data); 813 break; 814 case IMSG_DEMOTE: 815 if (idx != PFD_PIPE_SESSION) 816 log_warnx("demote request not from SE"); 817 else if (imsg.hdr.len != IMSG_HEADER_SIZE + 818 sizeof(struct demote_msg)) 819 log_warnx("DEMOTE request with wrong len"); 820 else { 821 struct demote_msg *msg; 822 823 msg = imsg.data; 824 carp_demote_set(msg->demote_group, msg->level); 825 } 826 break; 827 case IMSG_CTL_LOG_VERBOSE: 828 /* already checked by SE */ 829 memcpy(&verbose, imsg.data, sizeof(verbose)); 830 log_setverbose(verbose); 831 break; 832 case IMSG_RECONF_DONE: 833 if (reconfpending == 0) { 834 log_warnx("unexpected RECONF_DONE received"); 835 break; 836 } 837 if (idx == PFD_PIPE_SESSION) { 838 imsg_compose(ibuf_rde, IMSG_RECONF_DONE, 0, 839 0, -1, NULL, 0); 840 841 /* finally fix kroute information */ 842 ktable_postload(conf->fib_priority); 843 844 /* redistribute list needs to be reloaded too */ 845 kr_reload(); 846 } 847 reconfpending--; 848 break; 849 case IMSG_RECONF_DRAIN: 850 if (reconfpending == 0) { 851 log_warnx("unexpected RECONF_DRAIN received"); 852 break; 853 } 854 reconfpending--; 855 if (reconfpending == 0) { 856 /* 857 * SE goes first to bring templated neighbors 858 * in sync. 859 */ 860 imsg_compose(ibuf_se, IMSG_RECONF_DONE, 0, 861 0, -1, NULL, 0); 862 reconfpending = 2; /* expecting 2 DONE msg */ 863 } 864 break; 865 default: 866 break; 867 } 868 imsg_free(&imsg); 869 if (rv != 0) 870 return (rv); 871 } 872 return (0); 873} 874 875void 876send_nexthop_update(struct kroute_nexthop *msg) 877{ 878 char *gw = NULL; 879 880 if (msg->gateway.aid) 881 if (asprintf(&gw, ": via %s", 882 log_addr(&msg->gateway)) == -1) { 883 log_warn("send_nexthop_update"); 884 quit = 1; 885 } 886 887 log_debug("nexthop %s now %s%s%s", log_addr(&msg->nexthop), 888 msg->valid ? "valid" : "invalid", 889 msg->connected ? ": directly connected" : "", 890 msg->gateway.aid ? gw : ""); 891 892 free(gw); 893 894 if (imsg_compose(ibuf_rde, IMSG_NEXTHOP_UPDATE, 0, 0, -1, 895 msg, sizeof(struct kroute_nexthop)) == -1) 896 quit = 1; 897} 898 899void 900send_imsg_session(int type, pid_t pid, void *data, u_int16_t datalen) 901{ 902 imsg_compose(ibuf_se, type, 0, pid, -1, data, datalen); 903} 904 905int 906send_network(int type, struct network_config *net, struct filter_set_head *h) 907{ 908 if (quit) 909 return (0); 910 if (imsg_compose(ibuf_rde, type, 0, 0, -1, net, 911 sizeof(struct network_config)) == -1) 912 return (-1); 913 /* networks that get deleted don't need to send the filter set */ 914 if (type == IMSG_NETWORK_REMOVE) 915 return (0); 916 if (send_filterset(ibuf_rde, h) == -1) 917 return (-1); 918 if (imsg_compose(ibuf_rde, IMSG_NETWORK_DONE, 0, 0, -1, NULL, 0) == -1) 919 return (-1); 920 921 return (0); 922} 923 924int 925bgpd_filternexthop(struct kroute *kr, struct kroute6 *kr6) 926{ 927 /* kernel routes are never filtered */ 928 if (kr && kr->flags & F_KERNEL && kr->prefixlen != 0) 929 return (0); 930 if (kr6 && kr6->flags & F_KERNEL && kr6->prefixlen != 0) 931 return (0); 932 933 if (cflags & BGPD_FLAG_NEXTHOP_BGP) { 934 if (kr && kr->flags & F_BGPD_INSERTED) 935 return (0); 936 if (kr6 && kr6->flags & F_BGPD_INSERTED) 937 return (0); 938 } 939 940 if (cflags & BGPD_FLAG_NEXTHOP_DEFAULT) { 941 if (kr && kr->prefixlen == 0) 942 return (0); 943 if (kr6 && kr6->prefixlen == 0) 944 return (0); 945 } 946 947 return (1); 948} 949 950int 951control_setup(struct bgpd_config *conf) 952{ 953 int fd, restricted; 954 955 /* control socket is outside chroot */ 956 if (!cname || strcmp(cname, conf->csock)) { 957 if (cname) { 958 free(cname); 959 } 960 if ((cname = strdup(conf->csock)) == NULL) 961 fatal("strdup"); 962 if (control_check(cname) == -1) 963 return (-1); 964 if ((fd = control_init(0, cname)) == -1) 965 fatalx("control socket setup failed"); 966 if (control_listen(fd) == -1) 967 fatalx("control socket setup failed"); 968 restricted = 0; 969 if (imsg_compose(ibuf_se, IMSG_RECONF_CTRL, 0, 0, fd, 970 &restricted, sizeof(restricted)) == -1) 971 return (-1); 972 } 973 if (!conf->rcsock) { 974 /* remove restricted socket */ 975 free(rcname); 976 rcname = NULL; 977 } else if (!rcname || strcmp(rcname, conf->rcsock)) { 978 if (rcname) { 979 free(rcname); 980 } 981 if ((rcname = strdup(conf->rcsock)) == NULL) 982 fatal("strdup"); 983 if (control_check(rcname) == -1) 984 return (-1); 985 if ((fd = control_init(1, rcname)) == -1) 986 fatalx("control socket setup failed"); 987 if (control_listen(fd) == -1) 988 fatalx("control socket setup failed"); 989 restricted = 1; 990 if (imsg_compose(ibuf_se, IMSG_RECONF_CTRL, 0, 0, fd, 991 &restricted, sizeof(restricted)) == -1) 992 return (-1); 993 } 994 return (0); 995} 996 997void 998set_pollfd(struct pollfd *pfd, struct imsgbuf *i) 999{ 1000 if (i == NULL || i->fd == -1) { 1001 pfd->fd = -1; 1002 return; 1003 } 1004 pfd->fd = i->fd; 1005 pfd->events = POLLIN; 1006 if (i->w.queued > 0) 1007 pfd->events |= POLLOUT; 1008} 1009 1010int 1011handle_pollfd(struct pollfd *pfd, struct imsgbuf *i) 1012{ 1013 ssize_t n; 1014 1015 if (i == NULL) 1016 return (0); 1017 1018 if (pfd->revents & POLLOUT) 1019 if (msgbuf_write(&i->w) <= 0 && errno != EAGAIN) { 1020 log_warn("imsg write error"); 1021 close(i->fd); 1022 i->fd = -1; 1023 return (-1); 1024 } 1025 1026 if (pfd->revents & POLLIN) { 1027 if ((n = imsg_read(i)) == -1 && errno != EAGAIN) { 1028 log_warn("imsg read error"); 1029 close(i->fd); 1030 i->fd = -1; 1031 return (-1); 1032 } 1033 if (n == 0) { 1034 log_warnx("peer closed imsg connection"); 1035 close(i->fd); 1036 i->fd = -1; 1037 return (-1); 1038 } 1039 } 1040 return (0); 1041} 1042 1043int 1044imsg_send_sockets(struct imsgbuf *se, struct imsgbuf *rde) 1045{ 1046 int pipe_s2r[2]; 1047 int pipe_s2r_ctl[2]; 1048 1049 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 1050 PF_UNSPEC, pipe_s2r) == -1) 1051 return (-1); 1052 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 1053 PF_UNSPEC, pipe_s2r_ctl) == -1) 1054 return (-1); 1055 1056 if (imsg_compose(se, IMSG_SOCKET_CONN, 0, 0, pipe_s2r[0], 1057 NULL, 0) == -1) 1058 return (-1); 1059 if (imsg_compose(rde, IMSG_SOCKET_CONN, 0, 0, pipe_s2r[1], 1060 NULL, 0) == -1) 1061 return (-1); 1062 1063 if (imsg_compose(se, IMSG_SOCKET_CONN_CTL, 0, 0, pipe_s2r_ctl[0], 1064 NULL, 0) == -1) 1065 return (-1); 1066 if (imsg_compose(rde, IMSG_SOCKET_CONN_CTL, 0, 0, pipe_s2r_ctl[1], 1067 NULL, 0) == -1) 1068 return (-1); 1069 1070 return (0); 1071} 1072