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