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