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