bgpd.c revision 1.174
1/* $OpenBSD: bgpd.c,v 1.174 2013/11/13 20:41:01 benno 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 <unistd.h> 34 35#include "bgpd.h" 36#include "mrt.h" 37#include "session.h" 38 39void sighdlr(int); 40__dead void usage(void); 41int main(int, char *[]); 42int check_child(pid_t, const char *); 43int send_filterset(struct imsgbuf *, struct filter_set_head *); 44int reconfigure(char *, struct bgpd_config *, struct mrt_head *, 45 struct peer **); 46int dispatch_imsg(struct imsgbuf *, int, struct bgpd_config *); 47int control_setup(struct bgpd_config *); 48 49int rfd = -1; 50int cflags; 51volatile sig_atomic_t mrtdump; 52volatile sig_atomic_t quit; 53volatile sig_atomic_t sigchld; 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 SIGCHLD: 72 sigchld = 1; 73 break; 74 case SIGHUP: 75 reconfig = 1; 76 break; 77 case SIGALRM: 78 case SIGUSR1: 79 mrtdump = 1; 80 break; 81 } 82} 83 84__dead void 85usage(void) 86{ 87 extern char *__progname; 88 89 fprintf(stderr, "usage: %s [-cdnv] [-D macro=value] [-f file]\n", 90 __progname); 91 exit(1); 92} 93 94#define PFD_PIPE_SESSION 0 95#define PFD_PIPE_ROUTE 1 96#define PFD_SOCK_ROUTE 2 97#define POLL_MAX 3 98#define MAX_TIMEOUT 3600 99 100int 101main(int argc, char *argv[]) 102{ 103 struct bgpd_config conf; 104 struct mrt_head mrt_l; 105 struct peer *peer_l, *p; 106 struct mrt *m; 107 struct listen_addr *la; 108 struct pollfd pfd[POLL_MAX]; 109 pid_t io_pid = 0, rde_pid = 0, pid; 110 char *conffile; 111 int debug = 0; 112 int ch, timeout, nfds; 113 int pipe_m2s[2]; 114 int pipe_m2r[2]; 115 int pipe_s2r[2]; 116 int pipe_s2r_c[2]; 117 118 conffile = CONFFILE; 119 bgpd_process = PROC_MAIN; 120 121 log_init(1); /* log to stderr until daemonized */ 122 log_verbose(1); 123 124 bzero(&conf, sizeof(conf)); 125 LIST_INIT(&mrt_l); 126 peer_l = NULL; 127 128 while ((ch = getopt(argc, argv, "cdD:f:nv")) != -1) { 129 switch (ch) { 130 case 'c': 131 conf.opts |= BGPD_OPT_FORCE_DEMOTE; 132 break; 133 case 'd': 134 debug = 1; 135 break; 136 case 'D': 137 if (cmdline_symset(optarg) < 0) 138 log_warnx("could not parse macro definition %s", 139 optarg); 140 break; 141 case 'f': 142 conffile = optarg; 143 break; 144 case 'n': 145 conf.opts |= BGPD_OPT_NOACTION; 146 break; 147 case 'v': 148 if (conf.opts & BGPD_OPT_VERBOSE) 149 conf.opts |= BGPD_OPT_VERBOSE2; 150 conf.opts |= BGPD_OPT_VERBOSE; 151 log_verbose(1); 152 break; 153 default: 154 usage(); 155 /* NOTREACHED */ 156 } 157 } 158 159 argc -= optind; 160 argv += optind; 161 if (argc > 0) 162 usage(); 163 164 if (conf.opts & BGPD_OPT_NOACTION) { 165 struct network_head net_l; 166 struct rdomain_head rdom_l; 167 struct filter_head rules_l; 168 169 if (parse_config(conffile, &conf, &mrt_l, &peer_l, &net_l, 170 &rules_l, &rdom_l)) 171 exit(1); 172 173 if (conf.opts & BGPD_OPT_VERBOSE) 174 print_config(&conf, &ribnames, &net_l, peer_l, &rules_l, 175 &mrt_l, &rdom_l); 176 else 177 fprintf(stderr, "configuration OK\n"); 178 exit(0); 179 } 180 181 if (geteuid()) 182 errx(1, "need root privileges"); 183 184 if (getpwnam(BGPD_USER) == NULL) 185 errx(1, "unknown user %s", BGPD_USER); 186 187 log_init(debug); 188 log_verbose(conf.opts & BGPD_OPT_VERBOSE); 189 190 if (!debug) 191 daemon(1, 0); 192 193 log_info("startup"); 194 195 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_m2s) == -1) 196 fatal("socketpair"); 197 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_m2r) == -1) 198 fatal("socketpair"); 199 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_s2r) == -1) 200 fatal("socketpair"); 201 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_s2r_c) == -1) 202 fatal("socketpair"); 203 session_socket_blockmode(pipe_m2s[0], BM_NONBLOCK); 204 session_socket_blockmode(pipe_m2s[1], BM_NONBLOCK); 205 session_socket_blockmode(pipe_m2r[0], BM_NONBLOCK); 206 session_socket_blockmode(pipe_m2r[1], BM_NONBLOCK); 207 session_socket_blockmode(pipe_s2r[0], BM_NONBLOCK); 208 session_socket_blockmode(pipe_s2r[1], BM_NONBLOCK); 209 session_socket_blockmode(pipe_s2r_c[0], BM_NONBLOCK); 210 session_socket_blockmode(pipe_s2r_c[1], BM_NONBLOCK); 211 212 /* fork children */ 213 rde_pid = rde_main(pipe_m2r, pipe_s2r, pipe_m2s, pipe_s2r_c, debug); 214 io_pid = session_main(pipe_m2s, pipe_s2r, pipe_m2r, pipe_s2r_c); 215 216 setproctitle("parent"); 217 218 signal(SIGTERM, sighdlr); 219 signal(SIGINT, sighdlr); 220 signal(SIGCHLD, sighdlr); 221 signal(SIGHUP, sighdlr); 222 signal(SIGALRM, sighdlr); 223 signal(SIGUSR1, sighdlr); 224 signal(SIGPIPE, SIG_IGN); 225 226 close(pipe_m2s[1]); 227 close(pipe_m2r[1]); 228 close(pipe_s2r[0]); 229 close(pipe_s2r[1]); 230 231 if ((ibuf_se = malloc(sizeof(struct imsgbuf))) == NULL || 232 (ibuf_rde = malloc(sizeof(struct imsgbuf))) == NULL) 233 fatal(NULL); 234 imsg_init(ibuf_se, pipe_m2s[0]); 235 imsg_init(ibuf_rde, pipe_m2r[0]); 236 mrt_init(ibuf_rde, ibuf_se); 237 if ((rfd = kr_init()) == -1) 238 quit = 1; 239 quit = reconfigure(conffile, &conf, &mrt_l, &peer_l); 240 if (pftable_clear_all() != 0) 241 quit = 1; 242 243 while (quit == 0) { 244 bzero(pfd, sizeof(pfd)); 245 pfd[PFD_PIPE_SESSION].fd = ibuf_se->fd; 246 pfd[PFD_PIPE_SESSION].events = POLLIN; 247 if (ibuf_se->w.queued) 248 pfd[PFD_PIPE_SESSION].events |= POLLOUT; 249 pfd[PFD_PIPE_ROUTE].fd = ibuf_rde->fd; 250 pfd[PFD_PIPE_ROUTE].events = POLLIN; 251 if (ibuf_rde->w.queued) 252 pfd[PFD_PIPE_ROUTE].events |= POLLOUT; 253 pfd[PFD_SOCK_ROUTE].fd = rfd; 254 pfd[PFD_SOCK_ROUTE].events = POLLIN; 255 256 timeout = mrt_timeout(&mrt_l); 257 if (timeout > MAX_TIMEOUT) 258 timeout = MAX_TIMEOUT; 259 260 if ((nfds = poll(pfd, POLL_MAX, timeout * 1000)) == -1) 261 if (errno != EINTR) { 262 log_warn("poll error"); 263 quit = 1; 264 } 265 266 if (nfds > 0 && pfd[PFD_PIPE_SESSION].revents & POLLOUT) 267 if (msgbuf_write(&ibuf_se->w) <= 0 && errno != EAGAIN) { 268 log_warn("pipe write error (to SE)"); 269 quit = 1; 270 } 271 272 if (nfds > 0 && pfd[PFD_PIPE_ROUTE].revents & POLLOUT) 273 if (msgbuf_write(&ibuf_rde->w) <= 0 && 274 errno != EAGAIN) { 275 log_warn("pipe write error (to RDE)"); 276 quit = 1; 277 } 278 279 if (nfds > 0 && pfd[PFD_PIPE_SESSION].revents & POLLIN) { 280 if (dispatch_imsg(ibuf_se, PFD_PIPE_SESSION, &conf) == 281 -1) 282 quit = 1; 283 } 284 285 if (nfds > 0 && pfd[PFD_PIPE_ROUTE].revents & POLLIN) { 286 if (dispatch_imsg(ibuf_rde, PFD_PIPE_ROUTE, &conf) == 287 -1) 288 quit = 1; 289 } 290 291 if (nfds > 0 && pfd[PFD_SOCK_ROUTE].revents & POLLIN) { 292 if (kr_dispatch_msg() == -1) 293 quit = 1; 294 } 295 296 if (reconfig) { 297 u_int error; 298 299 reconfig = 0; 300 switch (reconfigure(conffile, &conf, &mrt_l, &peer_l)) { 301 case -1: /* fatal error */ 302 quit = 1; 303 break; 304 case 0: /* all OK */ 305 error = 0; 306 break; 307 case 2: 308 error = CTL_RES_PENDING; 309 break; 310 default: /* parse error */ 311 error = CTL_RES_PARSE_ERROR; 312 break; 313 } 314 if (reconfpid != 0) { 315 send_imsg_session(IMSG_CTL_RESULT, reconfpid, 316 &error, sizeof(error)); 317 reconfpid = 0; 318 } 319 } 320 321 if (sigchld) { 322 sigchld = 0; 323 if (check_child(io_pid, "session engine")) { 324 quit = 1; 325 io_pid = 0; 326 } 327 if (check_child(rde_pid, "route decision engine")) { 328 quit = 1; 329 rde_pid = 0; 330 } 331 } 332 333 if (mrtdump) { 334 mrtdump = 0; 335 mrt_handler(&mrt_l); 336 } 337 } 338 339 signal(SIGCHLD, SIG_IGN); 340 341 if (io_pid) 342 kill(io_pid, SIGTERM); 343 344 if (rde_pid) 345 kill(rde_pid, SIGTERM); 346 347 while ((p = peer_l) != NULL) { 348 peer_l = p->next; 349 free(p); 350 } 351 while ((m = LIST_FIRST(&mrt_l)) != NULL) { 352 LIST_REMOVE(m, entry); 353 free(m); 354 } 355 if (conf.listen_addrs) 356 while ((la = TAILQ_FIRST(conf.listen_addrs)) != NULL) { 357 TAILQ_REMOVE(conf.listen_addrs, la, entry); 358 close(la->fd); 359 free(la); 360 } 361 362 control_cleanup(conf.csock); 363 control_cleanup(conf.rcsock); 364 carp_demote_shutdown(); 365 kr_shutdown(conf.fib_priority); 366 pftable_clear_all(); 367 free(conf.listen_addrs); 368 369 do { 370 if ((pid = wait(NULL)) == -1 && 371 errno != EINTR && errno != ECHILD) 372 fatal("wait"); 373 } while (pid != -1 || (pid == -1 && errno == EINTR)); 374 375 msgbuf_clear(&ibuf_se->w); 376 free(ibuf_se); 377 msgbuf_clear(&ibuf_rde->w); 378 free(ibuf_rde); 379 free(rcname); 380 free(cname); 381 382 log_info("Terminating"); 383 return (0); 384} 385 386int 387check_child(pid_t pid, const char *pname) 388{ 389 int status; 390 391 if (waitpid(pid, &status, WNOHANG) > 0) { 392 if (WIFEXITED(status)) { 393 log_warnx("Lost child: %s exited", pname); 394 return (1); 395 } 396 if (WIFSIGNALED(status)) { 397 log_warnx("Lost child: %s terminated; signal %d", 398 pname, WTERMSIG(status)); 399 return (1); 400 } 401 } 402 403 return (0); 404} 405 406int 407send_filterset(struct imsgbuf *i, struct filter_set_head *set) 408{ 409 struct filter_set *s; 410 411 TAILQ_FOREACH(s, set, entry) 412 if (imsg_compose(i, IMSG_FILTER_SET, 0, 0, -1, s, 413 sizeof(struct filter_set)) == -1) 414 return (-1); 415 return (0); 416} 417 418int 419reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l, 420 struct peer **peer_l) 421{ 422 struct network_head net_l; 423 struct rdomain_head rdom_l; 424 struct filter_head rules_l; 425 struct peer *p; 426 struct filter_rule *r; 427 struct listen_addr *la; 428 struct rde_rib *rr; 429 struct rdomain *rd; 430 431 if (reconfpending) { 432 log_info("previous reload still running"); 433 return (2); 434 } 435 reconfpending = 2; /* one per child */ 436 437 log_info("rereading config"); 438 if (parse_config(conffile, conf, mrt_l, peer_l, &net_l, &rules_l, 439 &rdom_l)) { 440 log_warnx("config file %s has errors, not reloading", 441 conffile); 442 reconfpending = 0; 443 return (1); 444 } 445 446 cflags = conf->flags; 447 prepare_listeners(conf); 448 449 /* start reconfiguration */ 450 if (imsg_compose(ibuf_se, IMSG_RECONF_CONF, 0, 0, -1, 451 conf, sizeof(struct bgpd_config)) == -1) 452 return (-1); 453 if (imsg_compose(ibuf_rde, IMSG_RECONF_CONF, 0, 0, -1, 454 conf, sizeof(struct bgpd_config)) == -1) 455 return (-1); 456 457 TAILQ_FOREACH(la, conf->listen_addrs, entry) { 458 if (imsg_compose(ibuf_se, IMSG_RECONF_LISTENER, 0, 0, la->fd, 459 la, sizeof(struct listen_addr)) == -1) 460 return (-1); 461 la->fd = -1; 462 } 463 464 if (control_setup(conf) == -1) 465 return (-1); 466 467 /* adjust fib syncing on reload */ 468 ktable_preload(); 469 470 /* RIBs for the RDE */ 471 while ((rr = SIMPLEQ_FIRST(&ribnames))) { 472 SIMPLEQ_REMOVE_HEAD(&ribnames, entry); 473 if (ktable_update(rr->rtableid, rr->name, NULL, 474 rr->flags, conf->fib_priority) == -1) { 475 log_warnx("failed to load rdomain %d", 476 rr->rtableid); 477 return (-1); 478 } 479 if (imsg_compose(ibuf_rde, IMSG_RECONF_RIB, 0, 0, -1, 480 rr, sizeof(struct rde_rib)) == -1) 481 return (-1); 482 free(rr); 483 } 484 485 /* send peer list to the SE */ 486 for (p = *peer_l; p != NULL; p = p->next) { 487 if (imsg_compose(ibuf_se, IMSG_RECONF_PEER, p->conf.id, 0, -1, 488 &p->conf, sizeof(struct peer_config)) == -1) 489 return (-1); 490 } 491 492 /* networks go via kroute to the RDE */ 493 if (kr_net_reload(0, &net_l)) 494 return (-1); 495 496 /* filters for the RDE */ 497 while ((r = TAILQ_FIRST(&rules_l)) != NULL) { 498 TAILQ_REMOVE(&rules_l, r, entry); 499 if (imsg_compose(ibuf_rde, IMSG_RECONF_FILTER, 0, 0, -1, 500 r, sizeof(struct filter_rule)) == -1) 501 return (-1); 502 if (send_filterset(ibuf_rde, &r->set) == -1) 503 return (-1); 504 filterset_free(&r->set); 505 free(r); 506 } 507 508 while ((rd = SIMPLEQ_FIRST(&rdom_l)) != NULL) { 509 SIMPLEQ_REMOVE_HEAD(&rdom_l, entry); 510 if (ktable_update(rd->rtableid, rd->descr, rd->ifmpe, 511 rd->flags, conf->fib_priority) == -1) { 512 log_warnx("failed to load rdomain %d", 513 rd->rtableid); 514 return (-1); 515 } 516 /* networks go via kroute to the RDE */ 517 if (kr_net_reload(rd->rtableid, &rd->net_l)) 518 return (-1); 519 520 if (imsg_compose(ibuf_rde, IMSG_RECONF_RDOMAIN, 0, 0, -1, 521 rd, sizeof(*rd)) == -1) 522 return (-1); 523 524 /* export targets */ 525 if (imsg_compose(ibuf_rde, IMSG_RECONF_RDOMAIN_EXPORT, 0, 0, 526 -1, NULL, 0) == -1) 527 return (-1); 528 if (send_filterset(ibuf_rde, &rd->export) == -1) 529 return (-1); 530 filterset_free(&rd->export); 531 532 /* import targets */ 533 if (imsg_compose(ibuf_rde, IMSG_RECONF_RDOMAIN_IMPORT, 0, 0, 534 -1, NULL, 0) == -1) 535 return (-1); 536 if (send_filterset(ibuf_rde, &rd->import) == -1) 537 return (-1); 538 filterset_free(&rd->import); 539 540 if (imsg_compose(ibuf_rde, IMSG_RECONF_RDOMAIN_DONE, 0, 0, 541 -1, NULL, 0) == -1) 542 return (-1); 543 544 free(rd); 545 } 546 547 /* signal the SE first then the RDE to activate the new config */ 548 if (imsg_compose(ibuf_se, IMSG_RECONF_DONE, 0, 0, -1, NULL, 0) == -1) 549 return (-1); 550 551 /* mrt changes can be sent out of bound */ 552 mrt_reconfigure(mrt_l); 553 return (0); 554} 555 556int 557dispatch_imsg(struct imsgbuf *ibuf, int idx, struct bgpd_config *conf) 558{ 559 struct imsg imsg; 560 ssize_t n; 561 int rv, verbose; 562 563 if ((n = imsg_read(ibuf)) == -1) 564 return (-1); 565 566 if (n == 0) { /* connection closed */ 567 log_warnx("dispatch_imsg in main: pipe closed"); 568 return (-1); 569 } 570 571 rv = 0; 572 for (;;) { 573 if ((n = imsg_get(ibuf, &imsg)) == -1) 574 return (-1); 575 576 if (n == 0) 577 break; 578 579 switch (imsg.hdr.type) { 580 case IMSG_KROUTE_CHANGE: 581 if (idx != PFD_PIPE_ROUTE) 582 log_warnx("route request not from RDE"); 583 else if (imsg.hdr.len != IMSG_HEADER_SIZE + 584 sizeof(struct kroute_full)) 585 log_warnx("wrong imsg len"); 586 else if (kr_change(imsg.hdr.peerid, imsg.data, 587 conf->fib_priority)) 588 rv = -1; 589 break; 590 case IMSG_KROUTE_DELETE: 591 if (idx != PFD_PIPE_ROUTE) 592 log_warnx("route request not from RDE"); 593 else if (imsg.hdr.len != IMSG_HEADER_SIZE + 594 sizeof(struct kroute_full)) 595 log_warnx("wrong imsg len"); 596 else if (kr_delete(imsg.hdr.peerid, imsg.data, 597 conf->fib_priority)) 598 rv = -1; 599 break; 600 case IMSG_NEXTHOP_ADD: 601 if (idx != PFD_PIPE_ROUTE) 602 log_warnx("nexthop request not from RDE"); 603 else if (imsg.hdr.len != IMSG_HEADER_SIZE + 604 sizeof(struct bgpd_addr)) 605 log_warnx("wrong imsg len"); 606 else if (kr_nexthop_add(imsg.hdr.peerid, imsg.data) == 607 -1) 608 rv = -1; 609 break; 610 case IMSG_NEXTHOP_REMOVE: 611 if (idx != PFD_PIPE_ROUTE) 612 log_warnx("nexthop request not from RDE"); 613 else if (imsg.hdr.len != IMSG_HEADER_SIZE + 614 sizeof(struct bgpd_addr)) 615 log_warnx("wrong imsg len"); 616 else 617 kr_nexthop_delete(imsg.hdr.peerid, imsg.data); 618 break; 619 case IMSG_PFTABLE_ADD: 620 if (idx != PFD_PIPE_ROUTE) 621 log_warnx("pftable request not from RDE"); 622 else 623 if (imsg.hdr.len != IMSG_HEADER_SIZE + 624 sizeof(struct pftable_msg)) 625 log_warnx("wrong imsg len"); 626 else if (pftable_addr_add(imsg.data) != 0) 627 rv = -1; 628 break; 629 case IMSG_PFTABLE_REMOVE: 630 if (idx != PFD_PIPE_ROUTE) 631 log_warnx("pftable request not from RDE"); 632 else 633 if (imsg.hdr.len != IMSG_HEADER_SIZE + 634 sizeof(struct pftable_msg)) 635 log_warnx("wrong imsg len"); 636 else if (pftable_addr_remove(imsg.data) != 0) 637 rv = -1; 638 break; 639 case IMSG_PFTABLE_COMMIT: 640 if (idx != PFD_PIPE_ROUTE) 641 log_warnx("pftable request not from RDE"); 642 else 643 if (imsg.hdr.len != IMSG_HEADER_SIZE) 644 log_warnx("wrong imsg len"); 645 else if (pftable_commit() != 0) 646 rv = -1; 647 break; 648 case IMSG_CTL_RELOAD: 649 if (idx != PFD_PIPE_SESSION) 650 log_warnx("reload request not from SE"); 651 else { 652 reconfig = 1; 653 reconfpid = imsg.hdr.pid; 654 } 655 break; 656 case IMSG_CTL_FIB_COUPLE: 657 if (idx != PFD_PIPE_SESSION) 658 log_warnx("couple request not from SE"); 659 else 660 kr_fib_couple(imsg.hdr.peerid, 661 conf->fib_priority); 662 break; 663 case IMSG_CTL_FIB_DECOUPLE: 664 if (idx != PFD_PIPE_SESSION) 665 log_warnx("decouple request not from SE"); 666 else 667 kr_fib_decouple(imsg.hdr.peerid, 668 conf->fib_priority); 669 break; 670 case IMSG_CTL_KROUTE: 671 case IMSG_CTL_KROUTE_ADDR: 672 case IMSG_CTL_SHOW_NEXTHOP: 673 case IMSG_CTL_SHOW_INTERFACE: 674 case IMSG_CTL_SHOW_FIB_TABLES: 675 if (idx != PFD_PIPE_SESSION) 676 log_warnx("kroute request not from SE"); 677 else 678 kr_show_route(&imsg); 679 break; 680 case IMSG_IFINFO: 681 if (idx != PFD_PIPE_SESSION) 682 log_warnx("IFINFO request not from SE"); 683 else if (imsg.hdr.len != IMSG_HEADER_SIZE + IFNAMSIZ) 684 log_warnx("IFINFO request with wrong len"); 685 else 686 kr_ifinfo(imsg.data); 687 break; 688 case IMSG_DEMOTE: 689 if (idx != PFD_PIPE_SESSION) 690 log_warnx("demote request not from SE"); 691 else if (imsg.hdr.len != IMSG_HEADER_SIZE + 692 sizeof(struct demote_msg)) 693 log_warnx("DEMOTE request with wrong len"); 694 else { 695 struct demote_msg *msg; 696 697 msg = imsg.data; 698 carp_demote_set(msg->demote_group, msg->level); 699 } 700 break; 701 case IMSG_CTL_LOG_VERBOSE: 702 /* already checked by SE */ 703 memcpy(&verbose, imsg.data, sizeof(verbose)); 704 log_verbose(verbose); 705 break; 706 case IMSG_RECONF_DONE: 707 if (reconfpending == 0) 708 log_warnx("unexpected RECONF_DONE received"); 709 else if (reconfpending == 2) { 710 imsg_compose(ibuf_rde, IMSG_RECONF_DONE, 0, 711 0, -1, NULL, 0); 712 713 /* finally fix kroute information */ 714 ktable_postload(conf->fib_priority); 715 716 /* redistribute list needs to be reloaded too */ 717 kr_reload(); 718 } 719 reconfpending--; 720 break; 721 default: 722 break; 723 } 724 imsg_free(&imsg); 725 if (rv != 0) 726 return (rv); 727 } 728 return (0); 729} 730 731void 732send_nexthop_update(struct kroute_nexthop *msg) 733{ 734 char *gw = NULL; 735 736 if (msg->gateway.aid) 737 if (asprintf(&gw, ": via %s", 738 log_addr(&msg->gateway)) == -1) { 739 log_warn("send_nexthop_update"); 740 quit = 1; 741 } 742 743 log_info("nexthop %s now %s%s%s", log_addr(&msg->nexthop), 744 msg->valid ? "valid" : "invalid", 745 msg->connected ? ": directly connected" : "", 746 msg->gateway.aid ? gw : ""); 747 748 free(gw); 749 750 if (imsg_compose(ibuf_rde, IMSG_NEXTHOP_UPDATE, 0, 0, -1, 751 msg, sizeof(struct kroute_nexthop)) == -1) 752 quit = 1; 753} 754 755void 756send_imsg_session(int type, pid_t pid, void *data, u_int16_t datalen) 757{ 758 imsg_compose(ibuf_se, type, 0, pid, -1, data, datalen); 759} 760 761int 762send_network(int type, struct network_config *net, struct filter_set_head *h) 763{ 764 if (imsg_compose(ibuf_rde, type, 0, 0, -1, net, 765 sizeof(struct network_config)) == -1) 766 return (-1); 767 /* networks that get deleted don't need to send the filter set */ 768 if (type == IMSG_NETWORK_REMOVE) 769 return (0); 770 if (send_filterset(ibuf_rde, h) == -1) 771 return (-1); 772 if (imsg_compose(ibuf_rde, IMSG_NETWORK_DONE, 0, 0, -1, NULL, 0) == -1) 773 return (-1); 774 775 return (0); 776} 777 778int 779bgpd_filternexthop(struct kroute *kr, struct kroute6 *kr6) 780{ 781 /* kernel routes are never filtered */ 782 if (kr && kr->flags & F_KERNEL && kr->prefixlen != 0) 783 return (0); 784 if (kr6 && kr6->flags & F_KERNEL && kr6->prefixlen != 0) 785 return (0); 786 787 if (cflags & BGPD_FLAG_NEXTHOP_BGP) { 788 if (kr && kr->flags & F_BGPD_INSERTED) 789 return (0); 790 if (kr6 && kr6->flags & F_BGPD_INSERTED) 791 return (0); 792 } 793 794 if (cflags & BGPD_FLAG_NEXTHOP_DEFAULT) { 795 if (kr && kr->prefixlen == 0) 796 return (0); 797 if (kr6 && kr6->prefixlen == 0) 798 return (0); 799 } 800 801 return (1); 802} 803 804int 805control_setup(struct bgpd_config *conf) 806{ 807 int fd, restricted; 808 809 /* control socket is outside chroot */ 810 if (!cname || strcmp(cname, conf->csock)) { 811 if (cname) { 812 control_cleanup(cname); 813 free(cname); 814 } 815 if ((cname = strdup(conf->csock)) == NULL) 816 fatal("strdup"); 817 if ((fd = control_init(0, cname)) == -1) 818 fatalx("control socket setup failed"); 819 restricted = 0; 820 if (imsg_compose(ibuf_se, IMSG_RECONF_CTRL, 0, 0, fd, 821 &restricted, sizeof(restricted)) == -1) 822 return (-1); 823 } 824 if (!conf->rcsock) { 825 /* remove restricted socket */ 826 control_cleanup(rcname); 827 free(rcname); 828 rcname = NULL; 829 } else if (!rcname || strcmp(rcname, conf->rcsock)) { 830 if (rcname) { 831 control_cleanup(rcname); 832 free(rcname); 833 } 834 if ((rcname = strdup(conf->rcsock)) == NULL) 835 fatal("strdup"); 836 if ((fd = control_init(1, rcname)) == -1) 837 fatalx("control socket setup failed"); 838 restricted = 1; 839 if (imsg_compose(ibuf_se, IMSG_RECONF_CTRL, 0, 0, fd, 840 &restricted, sizeof(restricted)) == -1) 841 return (-1); 842 } 843 return (0); 844} 845