bgpd.c revision 1.157
1/* $OpenBSD: bgpd.c,v 1.157 2010/04/13 09:09:48 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 "mrt.h" 36#include "bgpd.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 = 0; 50struct filter_set_head *connectset; 51struct filter_set_head *connectset6; 52struct filter_set_head *staticset; 53struct filter_set_head *staticset6; 54volatile sig_atomic_t mrtdump = 0; 55volatile sig_atomic_t quit = 0; 56volatile sig_atomic_t sigchld = 0; 57volatile sig_atomic_t reconfig = 0; 58pid_t reconfpid = 0; 59struct imsgbuf *ibuf_se; 60struct imsgbuf *ibuf_rde; 61struct rib_names ribnames = SIMPLEQ_HEAD_INITIALIZER(ribnames); 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] ", __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 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 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 quit = reconfigure(conffile, &conf, &mrt_l, &peer_l); 248 if ((rfd = kr_init(!(conf.flags & BGPD_FLAG_NO_FIB_UPDATE), 249 conf.rtableid)) == -1) 250 quit = 1; 251 if (pftable_clear_all() != 0) 252 quit = 1; 253 254 while (quit == 0) { 255 bzero(pfd, sizeof(pfd)); 256 pfd[PFD_PIPE_SESSION].fd = ibuf_se->fd; 257 pfd[PFD_PIPE_SESSION].events = POLLIN; 258 if (ibuf_se->w.queued) 259 pfd[PFD_PIPE_SESSION].events |= POLLOUT; 260 pfd[PFD_PIPE_ROUTE].fd = ibuf_rde->fd; 261 pfd[PFD_PIPE_ROUTE].events = POLLIN; 262 if (ibuf_rde->w.queued) 263 pfd[PFD_PIPE_ROUTE].events |= POLLOUT; 264 pfd[PFD_SOCK_ROUTE].fd = rfd; 265 pfd[PFD_SOCK_ROUTE].events = POLLIN; 266 267 timeout = mrt_timeout(&mrt_l); 268 if (timeout > MAX_TIMEOUT) 269 timeout = MAX_TIMEOUT; 270 271 if ((nfds = poll(pfd, POLL_MAX, timeout * 1000)) == -1) 272 if (errno != EINTR) { 273 log_warn("poll error"); 274 quit = 1; 275 } 276 277 if (nfds > 0 && pfd[PFD_PIPE_SESSION].revents & POLLOUT) 278 if (msgbuf_write(&ibuf_se->w) < 0) { 279 log_warn("pipe write error (to SE)"); 280 quit = 1; 281 } 282 283 if (nfds > 0 && pfd[PFD_PIPE_ROUTE].revents & POLLOUT) 284 if (msgbuf_write(&ibuf_rde->w) < 0) { 285 log_warn("pipe write error (to RDE)"); 286 quit = 1; 287 } 288 289 if (nfds > 0 && pfd[PFD_PIPE_SESSION].revents & POLLIN) { 290 if (dispatch_imsg(ibuf_se, PFD_PIPE_SESSION) == -1) 291 quit = 1; 292 } 293 294 if (nfds > 0 && pfd[PFD_PIPE_ROUTE].revents & POLLIN) { 295 if (dispatch_imsg(ibuf_rde, PFD_PIPE_ROUTE) == -1) 296 quit = 1; 297 } 298 299 if (nfds > 0 && pfd[PFD_SOCK_ROUTE].revents & POLLIN) { 300 if (kr_dispatch_msg() == -1) 301 quit = 1; 302 } 303 304 if (reconfig) { 305 u_int error; 306 307 reconfig = 0; 308 log_info("rereading config"); 309 switch (reconfigure(conffile, &conf, &mrt_l, &peer_l)) { 310 case -1: /* fatal error */ 311 quit = 1; 312 break; 313 case 0: /* all OK */ 314 error = 0; 315 break; 316 default: /* parse error */ 317 error = CTL_RES_PARSE_ERROR; 318 break; 319 } 320 if (reconfpid != 0) { 321 send_imsg_session(IMSG_CTL_RESULT, reconfpid, 322 &error, sizeof(error)); 323 reconfpid = 0; 324 } 325 } 326 327 if (sigchld) { 328 sigchld = 0; 329 if (check_child(io_pid, "session engine")) { 330 quit = 1; 331 io_pid = 0; 332 } 333 if (check_child(rde_pid, "route decision engine")) { 334 quit = 1; 335 rde_pid = 0; 336 } 337 } 338 339 if (mrtdump) { 340 mrtdump = 0; 341 mrt_handler(&mrt_l); 342 } 343 } 344 345 signal(SIGCHLD, SIG_IGN); 346 347 if (io_pid) 348 kill(io_pid, SIGTERM); 349 350 if (rde_pid) 351 kill(rde_pid, SIGTERM); 352 353 while ((p = peer_l) != NULL) { 354 peer_l = p->next; 355 free(p); 356 } 357 while ((m = LIST_FIRST(&mrt_l)) != NULL) { 358 LIST_REMOVE(m, entry); 359 free(m); 360 } 361 if (conf.listen_addrs) 362 while ((la = TAILQ_FIRST(conf.listen_addrs)) != NULL) { 363 TAILQ_REMOVE(conf.listen_addrs, la, entry); 364 close(la->fd); 365 free(la); 366 } 367 368 control_cleanup(conf.csock); 369 control_cleanup(conf.rcsock); 370 carp_demote_shutdown(); 371 kr_shutdown(); 372 pftable_clear_all(); 373 free(conf.listen_addrs); 374 375 do { 376 if ((pid = wait(NULL)) == -1 && 377 errno != EINTR && errno != ECHILD) 378 fatal("wait"); 379 } while (pid != -1 || (pid == -1 && errno == EINTR)); 380 381 msgbuf_clear(&ibuf_se->w); 382 free(ibuf_se); 383 msgbuf_clear(&ibuf_rde->w); 384 free(ibuf_rde); 385 386 log_info("Terminating"); 387 return (0); 388} 389 390int 391check_child(pid_t pid, const char *pname) 392{ 393 int status; 394 395 if (waitpid(pid, &status, WNOHANG) > 0) { 396 if (WIFEXITED(status)) { 397 log_warnx("Lost child: %s exited", pname); 398 return (1); 399 } 400 if (WIFSIGNALED(status)) { 401 log_warnx("Lost child: %s terminated; signal %d", 402 pname, WTERMSIG(status)); 403 return (1); 404 } 405 } 406 407 return (0); 408} 409 410int 411send_filterset(struct imsgbuf *i, struct filter_set_head *set) 412{ 413 struct filter_set *s; 414 415 TAILQ_FOREACH(s, set, entry) 416 if (imsg_compose(i, IMSG_FILTER_SET, 0, 0, -1, s, 417 sizeof(struct filter_set)) == -1) 418 return (-1); 419 return (0); 420} 421 422int 423reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l, 424 struct peer **peer_l) 425{ 426 struct network_head net_l; 427 struct filter_head rules_l; 428 struct network *n; 429 struct peer *p; 430 struct filter_rule *r; 431 struct listen_addr *la; 432 struct rde_rib *rr; 433 434 if (parse_config(conffile, conf, mrt_l, peer_l, &net_l, &rules_l)) { 435 log_warnx("config file %s has errors, not reloading", 436 conffile); 437 while ((rr = SIMPLEQ_FIRST(&ribnames))) { 438 SIMPLEQ_REMOVE_HEAD(&ribnames, entry); 439 free(rr); 440 } 441 return (1); 442 } 443 444 cflags = conf->flags; 445 connectset = &conf->connectset; 446 staticset = &conf->staticset; 447 connectset6 = &conf->connectset6; 448 staticset6 = &conf->staticset6; 449 450 prepare_listeners(conf); 451 452 /* start reconfiguration */ 453 if (imsg_compose(ibuf_se, IMSG_RECONF_CONF, 0, 0, -1, 454 conf, sizeof(struct bgpd_config)) == -1) 455 return (-1); 456 if (imsg_compose(ibuf_rde, IMSG_RECONF_CONF, 0, 0, -1, 457 conf, sizeof(struct bgpd_config)) == -1) 458 return (-1); 459 460 /* send peer list and listeners to the SE */ 461 for (p = *peer_l; p != NULL; p = p->next) 462 if (imsg_compose(ibuf_se, IMSG_RECONF_PEER, p->conf.id, 0, -1, 463 &p->conf, sizeof(struct peer_config)) == -1) 464 return (-1); 465 466 TAILQ_FOREACH(la, conf->listen_addrs, entry) { 467 if (imsg_compose(ibuf_se, IMSG_RECONF_LISTENER, 0, 0, la->fd, 468 la, sizeof(struct listen_addr)) == -1) 469 return (-1); 470 la->fd = -1; 471 } 472 473 /* RIBs for the RDE */ 474 while ((rr = SIMPLEQ_FIRST(&ribnames))) { 475 SIMPLEQ_REMOVE_HEAD(&ribnames, entry); 476 if (imsg_compose(ibuf_rde, IMSG_RECONF_RIB, 0, 0, -1, 477 rr, sizeof(struct rde_rib)) == -1) 478 return (-1); 479 free(rr); 480 } 481 482 /* networks for the RDE */ 483 while ((n = TAILQ_FIRST(&net_l)) != NULL) { 484 if (imsg_compose(ibuf_rde, IMSG_NETWORK_ADD, 0, 0, -1, 485 &n->net, sizeof(struct network_config)) == -1) 486 return (-1); 487 if (send_filterset(ibuf_rde, &n->net.attrset) == -1) 488 return (-1); 489 if (imsg_compose(ibuf_rde, IMSG_NETWORK_DONE, 0, 0, -1, 490 NULL, 0) == -1) 491 return (-1); 492 TAILQ_REMOVE(&net_l, n, entry); 493 filterset_free(&n->net.attrset); 494 free(n); 495 } 496 497 /* redistribute list needs to be reloaded too */ 498 if (kr_reload() == -1) 499 return (-1); 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 /* mrt changes can be sent out of bound */ 519 mrt_reconfigure(mrt_l); 520 return (0); 521} 522 523int 524dispatch_imsg(struct imsgbuf *ibuf, int idx) 525{ 526 struct imsg imsg; 527 ssize_t n; 528 int rv, verbose; 529 530 if ((n = imsg_read(ibuf)) == -1) 531 return (-1); 532 533 if (n == 0) { /* connection closed */ 534 log_warnx("dispatch_imsg in main: pipe closed"); 535 return (-1); 536 } 537 538 rv = 0; 539 for (;;) { 540 if ((n = imsg_get(ibuf, &imsg)) == -1) 541 return (-1); 542 543 if (n == 0) 544 break; 545 546 switch (imsg.hdr.type) { 547 case IMSG_KROUTE_CHANGE: 548 if (idx != PFD_PIPE_ROUTE) 549 log_warnx("route request not from RDE"); 550 else if (imsg.hdr.len != IMSG_HEADER_SIZE + 551 sizeof(struct kroute_full)) 552 log_warnx("wrong imsg len"); 553 else if (kr_change(imsg.data)) 554 rv = -1; 555 break; 556 case IMSG_KROUTE_DELETE: 557 if (idx != PFD_PIPE_ROUTE) 558 log_warnx("route request not from RDE"); 559 else if (imsg.hdr.len != IMSG_HEADER_SIZE + 560 sizeof(struct kroute_full)) 561 log_warnx("wrong imsg len"); 562 else if (kr_delete(imsg.data)) 563 rv = -1; 564 break; 565 case IMSG_NEXTHOP_ADD: 566 if (idx != PFD_PIPE_ROUTE) 567 log_warnx("nexthop request not from RDE"); 568 else if (imsg.hdr.len != IMSG_HEADER_SIZE + 569 sizeof(struct bgpd_addr)) 570 log_warnx("wrong imsg len"); 571 else if (kr_nexthop_add(imsg.data) == -1) 572 rv = -1; 573 break; 574 case IMSG_NEXTHOP_REMOVE: 575 if (idx != PFD_PIPE_ROUTE) 576 log_warnx("nexthop request not from RDE"); 577 else if (imsg.hdr.len != IMSG_HEADER_SIZE + 578 sizeof(struct bgpd_addr)) 579 log_warnx("wrong imsg len"); 580 else 581 kr_nexthop_delete(imsg.data); 582 break; 583 case IMSG_PFTABLE_ADD: 584 if (idx != PFD_PIPE_ROUTE) 585 log_warnx("pftable request not from RDE"); 586 else 587 if (imsg.hdr.len != IMSG_HEADER_SIZE + 588 sizeof(struct pftable_msg)) 589 log_warnx("wrong imsg len"); 590 else if (pftable_addr_add(imsg.data) != 0) 591 rv = -1; 592 break; 593 case IMSG_PFTABLE_REMOVE: 594 if (idx != PFD_PIPE_ROUTE) 595 log_warnx("pftable request not from RDE"); 596 else 597 if (imsg.hdr.len != IMSG_HEADER_SIZE + 598 sizeof(struct pftable_msg)) 599 log_warnx("wrong imsg len"); 600 else if (pftable_addr_remove(imsg.data) != 0) 601 rv = -1; 602 break; 603 case IMSG_PFTABLE_COMMIT: 604 if (idx != PFD_PIPE_ROUTE) 605 log_warnx("pftable request not from RDE"); 606 else 607 if (imsg.hdr.len != IMSG_HEADER_SIZE) 608 log_warnx("wrong imsg len"); 609 else if (pftable_commit() != 0) 610 rv = -1; 611 break; 612 case IMSG_CTL_RELOAD: 613 if (idx != PFD_PIPE_SESSION) 614 log_warnx("reload request not from SE"); 615 else 616 reconfig = 1; 617 reconfpid = imsg.hdr.pid; 618 break; 619 case IMSG_CTL_FIB_COUPLE: 620 if (idx != PFD_PIPE_SESSION) 621 log_warnx("couple request not from SE"); 622 else 623 kr_fib_couple(); 624 break; 625 case IMSG_CTL_FIB_DECOUPLE: 626 if (idx != PFD_PIPE_SESSION) 627 log_warnx("decouple request not from SE"); 628 else 629 kr_fib_decouple(); 630 break; 631 case IMSG_CTL_KROUTE: 632 case IMSG_CTL_KROUTE_ADDR: 633 case IMSG_CTL_SHOW_NEXTHOP: 634 case IMSG_CTL_SHOW_INTERFACE: 635 if (idx != PFD_PIPE_SESSION) 636 log_warnx("kroute request not from SE"); 637 else 638 kr_show_route(&imsg); 639 break; 640 case IMSG_IFINFO: 641 if (idx != PFD_PIPE_SESSION) 642 log_warnx("IFINFO request not from SE"); 643 else if (imsg.hdr.len != IMSG_HEADER_SIZE + IFNAMSIZ) 644 log_warnx("IFINFO request with wrong len"); 645 else 646 kr_ifinfo(imsg.data); 647 break; 648 case IMSG_DEMOTE: 649 if (idx != PFD_PIPE_SESSION) 650 log_warnx("demote request not from SE"); 651 else if (imsg.hdr.len != IMSG_HEADER_SIZE + 652 sizeof(struct demote_msg)) 653 log_warnx("DEMOTE request with wrong len"); 654 else { 655 struct demote_msg *msg; 656 657 msg = imsg.data; 658 carp_demote_set(msg->demote_group, msg->level); 659 } 660 break; 661 case IMSG_CTL_LOG_VERBOSE: 662 /* already checked by SE */ 663 memcpy(&verbose, imsg.data, sizeof(verbose)); 664 log_verbose(verbose); 665 break; 666 default: 667 break; 668 } 669 imsg_free(&imsg); 670 if (rv != 0) 671 return (rv); 672 } 673 return (0); 674} 675 676void 677send_nexthop_update(struct kroute_nexthop *msg) 678{ 679 char *gw = NULL; 680 681 if (msg->gateway.aid) 682 if (asprintf(&gw, ": via %s", 683 log_addr(&msg->gateway)) == -1) { 684 log_warn("send_nexthop_update"); 685 quit = 1; 686 } 687 688 log_info("nexthop %s now %s%s%s", log_addr(&msg->nexthop), 689 msg->valid ? "valid" : "invalid", 690 msg->connected ? ": directly connected" : "", 691 msg->gateway.aid ? gw : ""); 692 693 free(gw); 694 695 if (imsg_compose(ibuf_rde, IMSG_NEXTHOP_UPDATE, 0, 0, -1, 696 msg, sizeof(struct kroute_nexthop)) == -1) 697 quit = 1; 698} 699 700void 701send_imsg_session(int type, pid_t pid, void *data, u_int16_t datalen) 702{ 703 imsg_compose(ibuf_se, type, 0, pid, -1, data, datalen); 704} 705 706int 707bgpd_redistribute(int type, struct kroute *kr, struct kroute6 *kr6) 708{ 709 struct network_config net; 710 struct filter_set_head *h; 711 712 if ((cflags & BGPD_FLAG_REDIST_CONNECTED) && kr && 713 (kr->flags & F_CONNECTED)) 714 h = connectset; 715 else if ((cflags & BGPD_FLAG_REDIST_STATIC) && kr && 716 (kr->flags & F_STATIC)) 717 h = staticset; 718 else if ((cflags & BGPD_FLAG_REDIST6_CONNECTED) && kr6 && 719 (kr6->flags & F_CONNECTED)) 720 h = connectset6; 721 else if ((cflags & BGPD_FLAG_REDIST6_STATIC) && kr6 && 722 (kr6->flags & F_STATIC)) 723 h = staticset6; 724 else 725 return (0); 726 727 bzero(&net, sizeof(net)); 728 if (kr && kr6) 729 fatalx("bgpd_redistribute: unable to redistribute v4 and v6" 730 "together"); 731 if (kr != NULL) { 732 net.prefix.aid = AID_INET; 733 net.prefix.v4.s_addr = kr->prefix.s_addr; 734 net.prefixlen = kr->prefixlen; 735 } 736 if (kr6 != NULL) { 737 net.prefix.aid = AID_INET6; 738 memcpy(&net.prefix.v6, &kr6->prefix, sizeof(struct in6_addr)); 739 net.prefixlen = kr6->prefixlen; 740 } 741 742 if (imsg_compose(ibuf_rde, type, 0, 0, -1, &net, 743 sizeof(struct network_config)) == -1) 744 return (-1); 745 746 /* networks that get deleted don't need to send the filter set */ 747 if (type == IMSG_NETWORK_REMOVE) 748 return (1); 749 750 if (send_filterset(ibuf_rde, h) == -1) 751 return (-1); 752 if (imsg_compose(ibuf_rde, IMSG_NETWORK_DONE, 0, 0, -1, NULL, 0) == -1) 753 return (-1); 754 755 return (1); 756} 757 758int 759bgpd_filternexthop(struct kroute *kr, struct kroute6 *kr6) 760{ 761 /* kernel routes are never filtered */ 762 if (kr && kr->flags & F_KERNEL && kr->prefixlen != 0) 763 return (0); 764 if (kr6 && kr6->flags & F_KERNEL && kr6->prefixlen != 0) 765 return (0); 766 767 if (cflags & BGPD_FLAG_NEXTHOP_BGP) { 768 if (kr && kr->flags & F_BGPD_INSERTED) 769 return (0); 770 if (kr6 && kr6->flags & F_BGPD_INSERTED) 771 return (0); 772 } 773 774 if (cflags & BGPD_FLAG_NEXTHOP_DEFAULT) { 775 if (kr && kr->prefixlen == 0) 776 return (0); 777 if (kr6 && kr6->prefixlen == 0) 778 return (0); 779 } 780 781 return (1); 782} 783