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