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