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