1 /* $OpenBSD: bgpd.c,v 1.280 2024/12/03 13:46:53 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 <netinet/ip.h> 24 #include <netinet/tcp.h> 25 #include <arpa/inet.h> 26 #include <err.h> 27 #include <errno.h> 28 #include <fcntl.h> 29 #include <poll.h> 30 #include <pwd.h> 31 #include <signal.h> 32 #include <stddef.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <syslog.h> 37 #include <unistd.h> 38 39 #include "bgpd.h" 40 #include "session.h" 41 #include "log.h" 42 #include "version.h" 43 44 void sighdlr(int); 45 __dead void usage(void); 46 int main(int, char *[]); 47 pid_t start_child(enum bgpd_process, char *, int, int, int); 48 int send_filterset(struct imsgbuf *, struct filter_set_head *); 49 int reconfigure(char *, struct bgpd_config *); 50 int send_config(struct bgpd_config *); 51 int dispatch_imsg(struct imsgbuf *, int, struct bgpd_config *); 52 int control_setup(struct bgpd_config *); 53 static void getsockpair(int [2]); 54 int imsg_send_sockets(struct imsgbuf *, struct imsgbuf *, 55 struct imsgbuf *); 56 void bgpd_rtr_conn_setup(struct rtr_config *); 57 void bgpd_rtr_conn_setup_done(int, struct bgpd_config *); 58 void bgpd_rtr_conn_teardown(uint32_t); 59 60 int cflags; 61 volatile sig_atomic_t mrtdump; 62 volatile sig_atomic_t quit; 63 volatile sig_atomic_t reconfig; 64 pid_t reconfpid; 65 int reconfpending; 66 struct imsgbuf *ibuf_se; 67 struct imsgbuf *ibuf_rde; 68 struct imsgbuf *ibuf_rtr; 69 struct rib_names ribnames = SIMPLEQ_HEAD_INITIALIZER(ribnames); 70 char *cname; 71 char *rcname; 72 73 struct connect_elm { 74 TAILQ_ENTRY(connect_elm) entry; 75 struct auth_state auth_state; 76 uint32_t id; 77 int fd; 78 }; 79 80 TAILQ_HEAD(, connect_elm) connect_queue = \ 81 TAILQ_HEAD_INITIALIZER(connect_queue), 82 socket_queue = \ 83 TAILQ_HEAD_INITIALIZER(socket_queue); 84 u_int connect_cnt; 85 #define MAX_CONNECT_CNT 32 86 87 void 88 sighdlr(int sig) 89 { 90 switch (sig) { 91 case SIGTERM: 92 case SIGINT: 93 quit = 1; 94 break; 95 case SIGHUP: 96 reconfig = 1; 97 break; 98 case SIGALRM: 99 case SIGUSR1: 100 mrtdump = 1; 101 break; 102 } 103 } 104 105 __dead void 106 usage(void) 107 { 108 extern char *__progname; 109 110 fprintf(stderr, "usage: %s [-cdnvV] [-D macro=value] [-f file]\n", 111 __progname); 112 exit(1); 113 } 114 115 #define PFD_PIPE_SESSION 0 116 #define PFD_PIPE_RDE 1 117 #define PFD_PIPE_RTR 2 118 #define PFD_SOCK_ROUTE 3 119 #define PFD_SOCK_PFKEY 4 120 #define PFD_CONNECT_START 5 121 #define MAX_TIMEOUT 3600 122 123 int cmd_opts; 124 125 int 126 main(int argc, char *argv[]) 127 { 128 struct bgpd_config *conf; 129 enum bgpd_process proc = PROC_MAIN; 130 struct rde_rib *rr; 131 struct peer *p; 132 struct pollfd *pfd = NULL; 133 struct connect_elm *ce; 134 time_t timeout; 135 pid_t se_pid = 0, rde_pid = 0, rtr_pid = 0, pid; 136 char *conffile; 137 char *saved_argv0; 138 u_int pfd_elms = 0, npfd, i; 139 int debug = 0; 140 int rfd, keyfd; 141 int ch, status; 142 int pipe_m2s[2]; 143 int pipe_m2r[2]; 144 int pipe_m2roa[2]; 145 146 conffile = CONFFILE; 147 148 log_init(1, LOG_DAEMON); /* log to stderr until daemonized */ 149 log_procinit(log_procnames[PROC_MAIN]); 150 log_setverbose(1); 151 152 saved_argv0 = argv[0]; 153 if (saved_argv0 == NULL) 154 saved_argv0 = "bgpd"; 155 156 while ((ch = getopt(argc, argv, "cdD:f:nRSTvV")) != -1) { 157 switch (ch) { 158 case 'c': 159 cmd_opts |= BGPD_OPT_FORCE_DEMOTE; 160 break; 161 case 'd': 162 debug = 1; 163 break; 164 case 'D': 165 if (cmdline_symset(optarg) < 0) 166 log_warnx("could not parse macro definition %s", 167 optarg); 168 break; 169 case 'f': 170 conffile = optarg; 171 break; 172 case 'n': 173 cmd_opts |= BGPD_OPT_NOACTION; 174 break; 175 case 'v': 176 if (cmd_opts & BGPD_OPT_VERBOSE) 177 cmd_opts |= BGPD_OPT_VERBOSE2; 178 cmd_opts |= BGPD_OPT_VERBOSE; 179 break; 180 case 'R': 181 proc = PROC_RDE; 182 break; 183 case 'S': 184 proc = PROC_SE; 185 break; 186 case 'T': 187 proc = PROC_RTR; 188 break; 189 case 'V': 190 fprintf(stderr, "OpenBGPD %s\n", BGPD_VERSION); 191 return 0; 192 default: 193 usage(); 194 /* NOTREACHED */ 195 } 196 } 197 198 argc -= optind; 199 argv += optind; 200 if (argc > 0) 201 usage(); 202 203 if (cmd_opts & BGPD_OPT_NOACTION) { 204 if ((conf = parse_config(conffile, NULL, NULL)) == NULL) 205 exit(1); 206 207 if (cmd_opts & BGPD_OPT_VERBOSE) 208 print_config(conf, &ribnames); 209 else 210 fprintf(stderr, "configuration OK\n"); 211 212 while ((rr = SIMPLEQ_FIRST(&ribnames)) != NULL) { 213 SIMPLEQ_REMOVE_HEAD(&ribnames, entry); 214 free(rr); 215 } 216 free_config(conf); 217 exit(0); 218 } 219 220 switch (proc) { 221 case PROC_MAIN: 222 break; 223 case PROC_RDE: 224 rde_main(debug, cmd_opts & BGPD_OPT_VERBOSE); 225 /* NOTREACHED */ 226 case PROC_SE: 227 session_main(debug, cmd_opts & BGPD_OPT_VERBOSE); 228 /* NOTREACHED */ 229 case PROC_RTR: 230 rtr_main(debug, cmd_opts & BGPD_OPT_VERBOSE); 231 /* NOTREACHED */ 232 } 233 234 if (geteuid()) 235 errx(1, "need root privileges"); 236 237 if (getpwnam(BGPD_USER) == NULL) 238 errx(1, "unknown user %s", BGPD_USER); 239 240 if ((conf = parse_config(conffile, NULL, NULL)) == NULL) { 241 log_warnx("config file %s has errors", conffile); 242 exit(1); 243 } 244 245 if (prepare_listeners(conf) == -1) 246 exit(1); 247 248 log_init(debug, LOG_DAEMON); 249 log_setverbose(cmd_opts & BGPD_OPT_VERBOSE); 250 251 if (!debug) 252 daemon(1, 0); 253 254 log_info("startup"); 255 256 getsockpair(pipe_m2s); 257 getsockpair(pipe_m2r); 258 getsockpair(pipe_m2roa); 259 260 /* fork children */ 261 rde_pid = start_child(PROC_RDE, saved_argv0, pipe_m2r[1], debug, 262 cmd_opts & BGPD_OPT_VERBOSE); 263 se_pid = start_child(PROC_SE, saved_argv0, pipe_m2s[1], debug, 264 cmd_opts & BGPD_OPT_VERBOSE); 265 rtr_pid = start_child(PROC_RTR, saved_argv0, pipe_m2roa[1], debug, 266 cmd_opts & BGPD_OPT_VERBOSE); 267 268 signal(SIGTERM, sighdlr); 269 signal(SIGINT, sighdlr); 270 signal(SIGHUP, sighdlr); 271 signal(SIGALRM, sighdlr); 272 signal(SIGUSR1, sighdlr); 273 signal(SIGPIPE, SIG_IGN); 274 275 if ((ibuf_se = malloc(sizeof(struct imsgbuf))) == NULL || 276 (ibuf_rde = malloc(sizeof(struct imsgbuf))) == NULL || 277 (ibuf_rtr = malloc(sizeof(struct imsgbuf))) == NULL) 278 fatal(NULL); 279 if (imsgbuf_init(ibuf_se, pipe_m2s[0]) == -1 || 280 imsgbuf_set_maxsize(ibuf_se, MAX_BGPD_IMSGSIZE) == -1 || 281 imsgbuf_init(ibuf_rde, pipe_m2r[0]) == -1 || 282 imsgbuf_set_maxsize(ibuf_rde, MAX_BGPD_IMSGSIZE) == -1 || 283 imsgbuf_init(ibuf_rtr, pipe_m2roa[0]) == -1 || 284 imsgbuf_set_maxsize(ibuf_rtr, MAX_BGPD_IMSGSIZE) == -1) 285 fatal(NULL); 286 imsgbuf_allow_fdpass(ibuf_se); 287 imsgbuf_allow_fdpass(ibuf_rde); 288 imsgbuf_allow_fdpass(ibuf_rtr); 289 mrt_init(ibuf_rde, ibuf_se); 290 if (kr_init(&rfd, conf->fib_priority) == -1) 291 quit = 1; 292 keyfd = pfkey_init(); 293 294 /* 295 * rpath, read config file 296 * cpath, unlink control socket 297 * fattr, chmod on control socket 298 * wpath, needed if we are doing mrt dumps 299 * 300 * pledge placed here because kr_init() does a setsockopt on the 301 * routing socket thats not allowed at all. 302 */ 303 #if 0 304 /* 305 * disabled because we do ioctls on /dev/pf and SIOCSIFGATTR 306 * this needs some redesign of bgpd to be fixed. 307 */ 308 BROKEN if (pledge("stdio rpath wpath cpath fattr unix route recvfd sendfd", 309 NULL) == -1) 310 fatal("pledge"); 311 #endif 312 313 if (imsg_send_sockets(ibuf_se, ibuf_rde, ibuf_rtr)) 314 fatal("could not establish imsg links"); 315 /* control setup needs to happen late since it sends imsgs */ 316 if (control_setup(conf) == -1) 317 quit = 1; 318 if (send_config(conf) != 0) 319 quit = 1; 320 if (pftable_clear_all() != 0) 321 quit = 1; 322 323 while (quit == 0) { 324 if (pfd_elms < PFD_CONNECT_START + connect_cnt) { 325 struct pollfd *newp; 326 327 if ((newp = reallocarray(pfd, 328 PFD_CONNECT_START + connect_cnt, 329 sizeof(struct pollfd))) == NULL) { 330 log_warn("could not resize pfd from %u -> %u" 331 " entries", pfd_elms, PFD_CONNECT_START + 332 connect_cnt); 333 fatalx("exiting"); 334 } 335 pfd = newp; 336 pfd_elms = PFD_CONNECT_START + connect_cnt; 337 } 338 memset(pfd, 0, sizeof(struct pollfd) * pfd_elms); 339 340 timeout = mrt_timeout(conf->mrt); 341 342 pfd[PFD_SOCK_ROUTE].fd = rfd; 343 pfd[PFD_SOCK_ROUTE].events = POLLIN; 344 345 pfd[PFD_SOCK_PFKEY].fd = keyfd; 346 pfd[PFD_SOCK_PFKEY].events = POLLIN; 347 348 set_pollfd(&pfd[PFD_PIPE_SESSION], ibuf_se); 349 set_pollfd(&pfd[PFD_PIPE_RDE], ibuf_rde); 350 set_pollfd(&pfd[PFD_PIPE_RTR], ibuf_rtr); 351 352 npfd = PFD_CONNECT_START; 353 TAILQ_FOREACH(ce, &connect_queue, entry) { 354 pfd[npfd].fd = ce->fd; 355 pfd[npfd++].events = POLLOUT; 356 if (npfd > pfd_elms) 357 fatalx("polli pfd overflow"); 358 } 359 360 if (timeout < 0 || timeout > MAX_TIMEOUT) 361 timeout = MAX_TIMEOUT; 362 if (poll(pfd, npfd, timeout * 1000) == -1) { 363 if (errno != EINTR) { 364 log_warn("poll error"); 365 quit = 1; 366 } 367 goto next_loop; 368 } 369 370 if (handle_pollfd(&pfd[PFD_PIPE_SESSION], ibuf_se) == -1) { 371 log_warnx("main: Lost connection to SE"); 372 imsgbuf_clear(ibuf_se); 373 free(ibuf_se); 374 ibuf_se = NULL; 375 quit = 1; 376 } else { 377 if (dispatch_imsg(ibuf_se, PFD_PIPE_SESSION, conf) == 378 -1) 379 quit = 1; 380 } 381 382 if (handle_pollfd(&pfd[PFD_PIPE_RDE], ibuf_rde) == -1) { 383 log_warnx("main: Lost connection to RDE"); 384 imsgbuf_clear(ibuf_rde); 385 free(ibuf_rde); 386 ibuf_rde = NULL; 387 quit = 1; 388 } else { 389 if (dispatch_imsg(ibuf_rde, PFD_PIPE_RDE, conf) == -1) 390 quit = 1; 391 } 392 393 if (handle_pollfd(&pfd[PFD_PIPE_RTR], ibuf_rtr) == -1) { 394 log_warnx("main: Lost connection to RTR"); 395 imsgbuf_clear(ibuf_rtr); 396 free(ibuf_rtr); 397 ibuf_rtr = NULL; 398 quit = 1; 399 } else { 400 if (dispatch_imsg(ibuf_rtr, PFD_PIPE_RTR, conf) == -1) 401 quit = 1; 402 } 403 404 if (pfd[PFD_SOCK_ROUTE].revents & POLLIN) { 405 if (kr_dispatch_msg() == -1) 406 quit = 1; 407 } 408 409 if (pfd[PFD_SOCK_PFKEY].revents & POLLIN) { 410 if (pfkey_read(keyfd, NULL) == -1) { 411 log_warnx("pfkey_read failed, exiting..."); 412 quit = 1; 413 } 414 } 415 416 for (i = PFD_CONNECT_START; i < npfd; i++) 417 if (pfd[i].revents != 0) 418 bgpd_rtr_conn_setup_done(pfd[i].fd, conf); 419 420 next_loop: 421 if (reconfig) { 422 u_int error; 423 424 reconfig = 0; 425 switch (reconfigure(conffile, conf)) { 426 case -1: /* fatal error */ 427 quit = 1; 428 break; 429 case 0: /* all OK */ 430 error = 0; 431 break; 432 case 2: 433 log_info("previous reload still running"); 434 error = CTL_RES_PENDING; 435 break; 436 default: /* parse error */ 437 log_warnx("config file %s has errors, " 438 "not reloading", conffile); 439 error = CTL_RES_PARSE_ERROR; 440 break; 441 } 442 if (reconfpid != 0) { 443 send_imsg_session(IMSG_CTL_RESULT, reconfpid, 444 &error, sizeof(error)); 445 reconfpid = 0; 446 } 447 } 448 449 if (mrtdump) { 450 mrtdump = 0; 451 mrt_handler(conf->mrt); 452 } 453 } 454 455 /* close pipes */ 456 if (ibuf_se) { 457 imsgbuf_clear(ibuf_se); 458 close(ibuf_se->fd); 459 free(ibuf_se); 460 ibuf_se = NULL; 461 } 462 if (ibuf_rde) { 463 imsgbuf_clear(ibuf_rde); 464 close(ibuf_rde->fd); 465 free(ibuf_rde); 466 ibuf_rde = NULL; 467 } 468 if (ibuf_rtr) { 469 imsgbuf_clear(ibuf_rtr); 470 close(ibuf_rtr->fd); 471 free(ibuf_rtr); 472 ibuf_rtr = NULL; 473 } 474 475 /* cleanup kernel data structures */ 476 carp_demote_shutdown(); 477 kr_shutdown(); 478 pftable_clear_all(); 479 480 RB_FOREACH(p, peer_head, &conf->peers) 481 pfkey_remove(&p->auth_state); 482 483 while ((rr = SIMPLEQ_FIRST(&ribnames)) != NULL) { 484 SIMPLEQ_REMOVE_HEAD(&ribnames, entry); 485 free(rr); 486 } 487 free_config(conf); 488 489 log_debug("waiting for children to terminate"); 490 do { 491 pid = wait(&status); 492 if (pid == -1) { 493 if (errno != EINTR && errno != ECHILD) 494 fatal("wait"); 495 } else if (WIFSIGNALED(status)) { 496 char *name = "unknown process"; 497 if (pid == rde_pid) 498 name = "route decision engine"; 499 else if (pid == se_pid) 500 name = "session engine"; 501 else if (pid == rtr_pid) 502 name = "rtr engine"; 503 log_warnx("%s terminated; signal %d", name, 504 WTERMSIG(status)); 505 } 506 } while (pid != -1 || (pid == -1 && errno == EINTR)); 507 508 free(rcname); 509 free(cname); 510 511 log_info("terminating"); 512 return (0); 513 } 514 515 pid_t 516 start_child(enum bgpd_process p, char *argv0, int fd, int debug, int verbose) 517 { 518 char *argv[5]; 519 int argc = 0; 520 pid_t pid; 521 522 switch (pid = fork()) { 523 case -1: 524 fatal("cannot fork"); 525 case 0: 526 break; 527 default: 528 close(fd); 529 return (pid); 530 } 531 532 if (fd != 3) { 533 if (dup2(fd, 3) == -1) 534 fatal("cannot setup imsg fd"); 535 } else if (fcntl(fd, F_SETFD, 0) == -1) 536 fatal("cannot setup imsg fd"); 537 538 argv[argc++] = argv0; 539 switch (p) { 540 case PROC_MAIN: 541 fatalx("Can not start main process"); 542 case PROC_RDE: 543 argv[argc++] = "-R"; 544 break; 545 case PROC_SE: 546 argv[argc++] = "-S"; 547 break; 548 case PROC_RTR: 549 argv[argc++] = "-T"; 550 break; 551 } 552 if (debug) 553 argv[argc++] = "-d"; 554 if (verbose) 555 argv[argc++] = "-v"; 556 argv[argc++] = NULL; 557 558 execvp(argv0, argv); 559 fatal("execvp"); 560 } 561 562 int 563 send_filterset(struct imsgbuf *i, struct filter_set_head *set) 564 { 565 struct filter_set *s; 566 567 TAILQ_FOREACH(s, set, entry) 568 if (imsg_compose(i, IMSG_FILTER_SET, 0, 0, -1, s, 569 sizeof(struct filter_set)) == -1) 570 return (-1); 571 return (0); 572 } 573 574 int 575 reconfigure(char *conffile, struct bgpd_config *conf) 576 { 577 struct bgpd_config *new_conf; 578 579 if (reconfpending) 580 return (2); 581 582 log_info("rereading config"); 583 if ((new_conf = parse_config(conffile, &conf->peers, 584 &conf->rtrs)) == NULL) 585 return (1); 586 587 merge_config(conf, new_conf); 588 589 if (prepare_listeners(conf) == -1) 590 return (1); 591 592 if (control_setup(conf) == -1) 593 return (1); 594 595 return send_config(conf); 596 } 597 598 int 599 send_config(struct bgpd_config *conf) 600 { 601 struct peer *p; 602 struct filter_rule *r; 603 struct listen_addr *la; 604 struct rde_rib *rr; 605 struct l3vpn *vpn; 606 struct as_set *aset; 607 struct prefixset *ps; 608 struct prefixset_item *psi, *npsi; 609 struct roa *roa; 610 struct aspa_set *aspa; 611 struct rtr_config *rtr; 612 struct flowspec_config *f, *nf; 613 614 reconfpending = 3; /* one per child */ 615 616 expand_networks(conf, &conf->networks); 617 SIMPLEQ_FOREACH(vpn, &conf->l3vpns, entry) 618 expand_networks(conf, &vpn->net_l); 619 620 cflags = conf->flags; 621 622 /* start reconfiguration */ 623 if (imsg_compose(ibuf_se, IMSG_RECONF_CONF, 0, 0, -1, 624 conf, sizeof(*conf)) == -1) 625 return (-1); 626 if (imsg_compose(ibuf_rde, IMSG_RECONF_CONF, 0, 0, -1, 627 conf, sizeof(*conf)) == -1) 628 return (-1); 629 if (imsg_compose(ibuf_rtr, IMSG_RECONF_CONF, 0, 0, -1, 630 conf, sizeof(*conf)) == -1) 631 return (-1); 632 633 TAILQ_FOREACH(la, conf->listen_addrs, entry) { 634 if (imsg_compose(ibuf_se, IMSG_RECONF_LISTENER, 0, 0, la->fd, 635 la, sizeof(*la)) == -1) 636 return (-1); 637 la->fd = -1; 638 } 639 640 /* adjust fib syncing on reload */ 641 ktable_preload(); 642 643 /* RIBs for the RDE */ 644 while ((rr = SIMPLEQ_FIRST(&ribnames))) { 645 SIMPLEQ_REMOVE_HEAD(&ribnames, entry); 646 if (ktable_update(rr->rtableid, rr->name, rr->flags) == -1) { 647 log_warnx("failed to load routing table %d", 648 rr->rtableid); 649 return (-1); 650 } 651 if (imsg_compose(ibuf_rde, IMSG_RECONF_RIB, 0, 0, -1, 652 rr, sizeof(*rr)) == -1) 653 return (-1); 654 free(rr); 655 } 656 657 /* send peer list to the SE */ 658 RB_FOREACH(p, peer_head, &conf->peers) { 659 if (p->reconf_action == RECONF_DELETE) 660 continue; 661 662 if (imsg_compose(ibuf_se, IMSG_RECONF_PEER, p->conf.id, 0, -1, 663 &p->conf, sizeof(p->conf)) == -1) 664 return (-1); 665 if (pfkey_send_conf(ibuf_se, p->conf.id, &p->auth_conf) == -1) 666 return (-1); 667 668 if (p->reconf_action == RECONF_REINIT) 669 if (pfkey_establish(&p->auth_state, &p->auth_conf, 670 session_localaddr(p), &p->conf.remote_addr) == -1) 671 log_peer_warnx(&p->conf, "auth setup failed"); 672 } 673 674 /* networks go via kroute to the RDE */ 675 kr_net_reload(conf->default_tableid, 0, &conf->networks); 676 677 /* flowspec goes directly to the RDE, also remove old objects */ 678 RB_FOREACH_SAFE(f, flowspec_tree, &conf->flowspecs, nf) { 679 if (f->reconf_action != RECONF_DELETE) { 680 if (imsg_compose(ibuf_rde, IMSG_FLOWSPEC_ADD, 0, 0, -1, 681 f->flow, FLOWSPEC_SIZE + f->flow->len) == -1) 682 return (-1); 683 if (send_filterset(ibuf_rde, &f->attrset) == -1) 684 return (-1); 685 if (imsg_compose(ibuf_rde, IMSG_FLOWSPEC_DONE, 0, 0, -1, 686 NULL, 0) == -1) 687 return (-1); 688 } else { 689 if (imsg_compose(ibuf_rde, IMSG_FLOWSPEC_REMOVE, 0, 0, 690 -1, f->flow, FLOWSPEC_SIZE + f->flow->len) == -1) 691 return (-1); 692 RB_REMOVE(flowspec_tree, &conf->flowspecs, f); 693 flowspec_free(f); 694 } 695 } 696 697 /* prefixsets for filters in the RDE */ 698 while ((ps = SIMPLEQ_FIRST(&conf->prefixsets)) != NULL) { 699 SIMPLEQ_REMOVE_HEAD(&conf->prefixsets, entry); 700 if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIX_SET, 0, 0, -1, 701 ps->name, sizeof(ps->name)) == -1) 702 return (-1); 703 RB_FOREACH_SAFE(psi, prefixset_tree, &ps->psitems, npsi) { 704 RB_REMOVE(prefixset_tree, &ps->psitems, psi); 705 if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIX_SET_ITEM, 706 0, 0, -1, psi, sizeof(*psi)) == -1) 707 return (-1); 708 free(psi); 709 } 710 free(ps); 711 } 712 713 /* originsets for filters in the RDE */ 714 while ((ps = SIMPLEQ_FIRST(&conf->originsets)) != NULL) { 715 SIMPLEQ_REMOVE_HEAD(&conf->originsets, entry); 716 if (imsg_compose(ibuf_rde, IMSG_RECONF_ORIGIN_SET, 0, 0, -1, 717 ps->name, sizeof(ps->name)) == -1) 718 return (-1); 719 RB_FOREACH(roa, roa_tree, &ps->roaitems) { 720 if (imsg_compose(ibuf_rde, IMSG_RECONF_ROA_ITEM, 0, 0, 721 -1, roa, sizeof(*roa)) == -1) 722 return (-1); 723 } 724 free_roatree(&ps->roaitems); 725 free(ps); 726 } 727 728 /* roa table, aspa table and rtr config are sent to the RTR engine */ 729 RB_FOREACH(roa, roa_tree, &conf->roa) { 730 if (imsg_compose(ibuf_rtr, IMSG_RECONF_ROA_ITEM, 0, 0, 731 -1, roa, sizeof(*roa)) == -1) 732 return (-1); 733 } 734 free_roatree(&conf->roa); 735 RB_FOREACH(aspa, aspa_tree, &conf->aspa) { 736 if (imsg_compose(ibuf_rtr, IMSG_RECONF_ASPA, 0, 0, 737 -1, aspa, offsetof(struct aspa_set, tas)) == -1) 738 return (-1); 739 if (imsg_compose(ibuf_rtr, IMSG_RECONF_ASPA_TAS, 0, 0, 740 -1, aspa->tas, aspa->num * sizeof(*aspa->tas)) == -1) 741 return (-1); 742 if (imsg_compose(ibuf_rtr, IMSG_RECONF_ASPA_DONE, 0, 0, -1, 743 NULL, 0) == -1) 744 return -1; 745 } 746 free_aspatree(&conf->aspa); 747 SIMPLEQ_FOREACH(rtr, &conf->rtrs, entry) { 748 struct rtr_config_msg rtrconf = { 0 }; 749 750 strlcpy(rtrconf.descr, rtr->descr, sizeof(rtrconf.descr)); 751 rtrconf.min_version = rtr->min_version; 752 if (imsg_compose(ibuf_rtr, IMSG_RECONF_RTR_CONFIG, rtr->id, 753 0, -1, &rtrconf, sizeof(rtrconf)) == -1) 754 return (-1); 755 } 756 757 /* as-sets for filters in the RDE */ 758 while ((aset = SIMPLEQ_FIRST(&conf->as_sets)) != NULL) { 759 struct ibuf *wbuf; 760 uint32_t *as; 761 size_t i, l, n; 762 763 SIMPLEQ_REMOVE_HEAD(&conf->as_sets, entry); 764 765 as = set_get(aset->set, &n); 766 if ((wbuf = imsg_create(ibuf_rde, IMSG_RECONF_AS_SET, 0, 0, 767 sizeof(n) + sizeof(aset->name))) == NULL) 768 return -1; 769 if (imsg_add(wbuf, &n, sizeof(n)) == -1 || 770 imsg_add(wbuf, aset->name, sizeof(aset->name)) == -1) 771 return -1; 772 imsg_close(ibuf_rde, wbuf); 773 774 for (i = 0; i < n; i += l) { 775 l = (n - i > 1024 ? 1024 : n - i); 776 if (imsg_compose(ibuf_rde, IMSG_RECONF_AS_SET_ITEMS, 777 0, 0, -1, as + i, l * sizeof(*as)) == -1) 778 return -1; 779 } 780 781 if (imsg_compose(ibuf_rde, IMSG_RECONF_AS_SET_DONE, 0, 0, -1, 782 NULL, 0) == -1) 783 return -1; 784 785 set_free(aset->set); 786 free(aset); 787 } 788 789 /* filters for the RDE */ 790 while ((r = TAILQ_FIRST(conf->filters)) != NULL) { 791 TAILQ_REMOVE(conf->filters, r, entry); 792 if (send_filterset(ibuf_rde, &r->set) == -1) 793 return (-1); 794 if (imsg_compose(ibuf_rde, IMSG_RECONF_FILTER, 0, 0, -1, 795 r, sizeof(struct filter_rule)) == -1) 796 return (-1); 797 filterset_free(&r->set); 798 free(r); 799 } 800 801 while ((vpn = SIMPLEQ_FIRST(&conf->l3vpns)) != NULL) { 802 SIMPLEQ_REMOVE_HEAD(&conf->l3vpns, entry); 803 if (ktable_update(vpn->rtableid, vpn->descr, vpn->flags) == 804 -1) { 805 log_warnx("failed to load routing table %d", 806 vpn->rtableid); 807 return (-1); 808 } 809 /* networks go via kroute to the RDE */ 810 kr_net_reload(vpn->rtableid, vpn->rd, &vpn->net_l); 811 812 if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN, 0, 0, -1, 813 vpn, sizeof(*vpn)) == -1) 814 return (-1); 815 816 /* export targets */ 817 if (send_filterset(ibuf_rde, &vpn->export) == -1) 818 return (-1); 819 if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN_EXPORT, 0, 0, 820 -1, NULL, 0) == -1) 821 return (-1); 822 filterset_free(&vpn->export); 823 824 /* import targets */ 825 if (send_filterset(ibuf_rde, &vpn->import) == -1) 826 return (-1); 827 if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN_IMPORT, 0, 0, 828 -1, NULL, 0) == -1) 829 return (-1); 830 filterset_free(&vpn->import); 831 832 if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN_DONE, 0, 0, 833 -1, NULL, 0) == -1) 834 return (-1); 835 836 free(vpn); 837 } 838 839 /* send a drain message to know when all messages where processed */ 840 if (imsg_compose(ibuf_se, IMSG_RECONF_DRAIN, 0, 0, -1, NULL, 0) == -1) 841 return (-1); 842 if (imsg_compose(ibuf_rde, IMSG_RECONF_DRAIN, 0, 0, -1, NULL, 0) == -1) 843 return (-1); 844 if (imsg_compose(ibuf_rtr, IMSG_RECONF_DRAIN, 0, 0, -1, NULL, 0) == -1) 845 return (-1); 846 847 /* mrt changes can be sent out of bound */ 848 mrt_reconfigure(conf->mrt); 849 return (0); 850 } 851 852 int 853 dispatch_imsg(struct imsgbuf *imsgbuf, int idx, struct bgpd_config *conf) 854 { 855 struct imsg imsg; 856 struct peer *p; 857 struct rtr_config *r; 858 struct kroute_full kf; 859 struct bgpd_addr addr; 860 struct pftable_msg pfmsg; 861 struct demote_msg demote; 862 char reason[REASON_LEN], ifname[IFNAMSIZ]; 863 ssize_t n; 864 u_int rtableid; 865 int rv, verbose; 866 867 rv = 0; 868 while (imsgbuf) { 869 if ((n = imsg_get(imsgbuf, &imsg)) == -1) 870 return (-1); 871 872 if (n == 0) 873 break; 874 875 switch (imsg_get_type(&imsg)) { 876 case IMSG_KROUTE_CHANGE: 877 if (idx != PFD_PIPE_RDE) 878 log_warnx("route request not from RDE"); 879 else if (imsg_get_data(&imsg, &kf, sizeof(kf)) == -1) 880 log_warn("wrong imsg len"); 881 else if (kr_change(imsg_get_id(&imsg), &kf)) 882 rv = -1; 883 break; 884 case IMSG_KROUTE_DELETE: 885 if (idx != PFD_PIPE_RDE) 886 log_warnx("route request not from RDE"); 887 else if (imsg_get_data(&imsg, &kf, sizeof(kf)) == -1) 888 log_warn("wrong imsg len"); 889 else if (kr_delete(imsg_get_id(&imsg), &kf)) 890 rv = -1; 891 break; 892 case IMSG_KROUTE_FLUSH: 893 if (idx != PFD_PIPE_RDE) 894 log_warnx("route request not from RDE"); 895 else if (kr_flush(imsg_get_id(&imsg))) 896 rv = -1; 897 break; 898 case IMSG_NEXTHOP_ADD: 899 if (idx != PFD_PIPE_RDE) 900 log_warnx("nexthop request not from RDE"); 901 else if (imsg_get_data(&imsg, &addr, sizeof(addr)) == 902 -1) 903 log_warn("wrong imsg len"); 904 else { 905 rtableid = conf->default_tableid; 906 if (kr_nexthop_add(rtableid, &addr) == -1) 907 rv = -1; 908 } 909 break; 910 case IMSG_NEXTHOP_REMOVE: 911 if (idx != PFD_PIPE_RDE) 912 log_warnx("nexthop request not from RDE"); 913 else if (imsg_get_data(&imsg, &addr, sizeof(addr)) == 914 -1) 915 log_warn("wrong imsg len"); 916 else { 917 rtableid = conf->default_tableid; 918 kr_nexthop_delete(rtableid, &addr); 919 } 920 break; 921 case IMSG_PFTABLE_ADD: 922 if (idx != PFD_PIPE_RDE) 923 log_warnx("pftable request not from RDE"); 924 else if (imsg_get_data(&imsg, &pfmsg, sizeof(pfmsg)) == 925 -1) 926 log_warn("wrong imsg len"); 927 else if (pftable_addr_add(&pfmsg) != 0) 928 rv = -1; 929 break; 930 case IMSG_PFTABLE_REMOVE: 931 if (idx != PFD_PIPE_RDE) 932 log_warnx("pftable request not from RDE"); 933 else if (imsg_get_data(&imsg, &pfmsg, sizeof(pfmsg)) == 934 -1) 935 log_warn("wrong imsg len"); 936 else if (pftable_addr_remove(&pfmsg) != 0) 937 rv = -1; 938 break; 939 case IMSG_PFTABLE_COMMIT: 940 if (idx != PFD_PIPE_RDE) 941 log_warnx("pftable request not from RDE"); 942 else if (pftable_commit() != 0) 943 rv = -1; 944 break; 945 case IMSG_PFKEY_RELOAD: 946 if (idx != PFD_PIPE_SESSION) { 947 log_warnx("pfkey reload request not from SE"); 948 break; 949 } 950 p = getpeerbyid(conf, imsg_get_id(&imsg)); 951 if (p != NULL) { 952 if (pfkey_establish(&p->auth_state, 953 &p->auth_conf, session_localaddr(p), 954 &p->conf.remote_addr) == -1) 955 log_peer_warnx(&p->conf, 956 "pfkey setup failed"); 957 } 958 break; 959 case IMSG_CTL_RELOAD: 960 if (idx != PFD_PIPE_SESSION) 961 log_warnx("reload request not from SE"); 962 else { 963 reconfig = 1; 964 reconfpid = imsg_get_pid(&imsg); 965 if (imsg_get_data(&imsg, reason, 966 sizeof(reason)) == 0 && reason[0] != '\0') 967 log_info("reload due to: %s", 968 log_reason(reason)); 969 } 970 break; 971 case IMSG_CTL_FIB_COUPLE: 972 if (idx != PFD_PIPE_SESSION) 973 log_warnx("couple request not from SE"); 974 else 975 kr_fib_couple(imsg_get_id(&imsg)); 976 break; 977 case IMSG_CTL_FIB_DECOUPLE: 978 if (idx != PFD_PIPE_SESSION) 979 log_warnx("decouple request not from SE"); 980 else 981 kr_fib_decouple(imsg_get_id(&imsg)); 982 break; 983 case IMSG_CTL_KROUTE: 984 case IMSG_CTL_KROUTE_ADDR: 985 case IMSG_CTL_SHOW_NEXTHOP: 986 case IMSG_CTL_SHOW_INTERFACE: 987 case IMSG_CTL_SHOW_FIB_TABLES: 988 if (idx != PFD_PIPE_SESSION) 989 log_warnx("kroute request not from SE"); 990 else 991 kr_show_route(&imsg); 992 break; 993 case IMSG_SESSION_DEPENDON: 994 if (idx != PFD_PIPE_SESSION) 995 log_warnx("DEPENDON request not from SE"); 996 else if (imsg_get_data(&imsg, ifname, sizeof(ifname)) == 997 -1) 998 log_warn("wrong imsg len"); 999 else 1000 kr_ifinfo(ifname); 1001 break; 1002 case IMSG_DEMOTE: 1003 if (idx != PFD_PIPE_SESSION) 1004 log_warnx("demote request not from SE"); 1005 else if (imsg_get_data(&imsg, &demote, sizeof(demote)) 1006 == -1) 1007 log_warn("wrong imsg len"); 1008 else 1009 carp_demote_set(demote.demote_group, 1010 demote.level); 1011 break; 1012 case IMSG_CTL_LOG_VERBOSE: 1013 /* already checked by SE */ 1014 if (imsg_get_data(&imsg, &verbose, sizeof(verbose)) == 1015 -1) 1016 log_warn("wrong imsg len"); 1017 else 1018 log_setverbose(verbose); 1019 break; 1020 case IMSG_RECONF_DONE: 1021 if (reconfpending == 0) { 1022 log_warnx("unexpected RECONF_DONE received"); 1023 break; 1024 } 1025 if (idx == PFD_PIPE_SESSION) { 1026 /* RDE and RTR engine can reload concurrently */ 1027 imsg_compose(ibuf_rtr, IMSG_RECONF_DONE, 0, 1028 0, -1, NULL, 0); 1029 imsg_compose(ibuf_rde, IMSG_RECONF_DONE, 0, 1030 0, -1, NULL, 0); 1031 1032 /* finally fix kroute information */ 1033 ktable_postload(); 1034 1035 /* redistribute list needs to be reloaded too */ 1036 kr_reload(); 1037 1038 /* also remove old peers */ 1039 free_deleted_peers(conf); 1040 } 1041 reconfpending--; 1042 break; 1043 case IMSG_RECONF_DRAIN: 1044 if (reconfpending == 0) { 1045 log_warnx("unexpected RECONF_DRAIN received"); 1046 break; 1047 } 1048 reconfpending--; 1049 if (reconfpending == 0) { 1050 /* 1051 * SE goes first to bring templated neighbors 1052 * in sync. 1053 */ 1054 imsg_compose(ibuf_se, IMSG_RECONF_DONE, 0, 1055 0, -1, NULL, 0); 1056 reconfpending = 3; /* expecting 2 DONE msg */ 1057 } 1058 break; 1059 case IMSG_SOCKET_SETUP: 1060 if (idx != PFD_PIPE_RTR) { 1061 log_warnx("connect request not from RTR"); 1062 } else { 1063 uint32_t rtrid = imsg_get_id(&imsg); 1064 SIMPLEQ_FOREACH(r, &conf->rtrs, entry) { 1065 if (rtrid == r->id) 1066 break; 1067 } 1068 if (r == NULL) 1069 log_warnx("unknown rtr id %d", rtrid); 1070 else 1071 bgpd_rtr_conn_setup(r); 1072 } 1073 break; 1074 case IMSG_SOCKET_TEARDOWN: 1075 if (idx != PFD_PIPE_RTR) { 1076 log_warnx("connect request not from RTR"); 1077 } else { 1078 uint32_t rtrid = imsg_get_id(&imsg); 1079 bgpd_rtr_conn_teardown(rtrid); 1080 } 1081 break; 1082 case IMSG_CTL_SHOW_RTR: 1083 if (idx == PFD_PIPE_SESSION) { 1084 SIMPLEQ_FOREACH(r, &conf->rtrs, entry) { 1085 imsg_compose(ibuf_rtr, 1086 IMSG_CTL_SHOW_RTR, r->id, 1087 imsg_get_pid(&imsg), -1, NULL, 0); 1088 } 1089 imsg_compose(ibuf_rtr, IMSG_CTL_END, 1090 0, imsg_get_pid(&imsg), -1, NULL, 0); 1091 } else if (idx == PFD_PIPE_RTR) { 1092 struct ctl_show_rtr rtr; 1093 if (imsg_get_data(&imsg, &rtr, sizeof(rtr)) == 1094 -1) { 1095 log_warn("wrong imsg len"); 1096 break; 1097 } 1098 1099 SIMPLEQ_FOREACH(r, &conf->rtrs, entry) { 1100 if (imsg_get_id(&imsg) == r->id) 1101 break; 1102 } 1103 if (r != NULL) { 1104 strlcpy(rtr.descr, r->descr, 1105 sizeof(rtr.descr)); 1106 rtr.local_addr = r->local_addr; 1107 rtr.remote_addr = r->remote_addr; 1108 rtr.remote_port = r->remote_port; 1109 1110 imsg_compose(ibuf_se, IMSG_CTL_SHOW_RTR, 1111 imsg_get_id(&imsg), 1112 imsg_get_pid(&imsg), -1, 1113 &rtr, sizeof(rtr)); 1114 } 1115 } 1116 break; 1117 case IMSG_CTL_END: 1118 case IMSG_CTL_SHOW_TIMER: 1119 if (idx != PFD_PIPE_RTR) { 1120 log_warnx("connect request not from RTR"); 1121 break; 1122 } 1123 imsg_forward(ibuf_se, &imsg); 1124 break; 1125 default: 1126 break; 1127 } 1128 imsg_free(&imsg); 1129 if (rv != 0) 1130 return (rv); 1131 } 1132 return (0); 1133 } 1134 1135 void 1136 send_nexthop_update(struct kroute_nexthop *msg) 1137 { 1138 char *gw = NULL; 1139 1140 if (msg->gateway.aid) 1141 if (asprintf(&gw, ": via %s", 1142 log_addr(&msg->gateway)) == -1) { 1143 log_warn("send_nexthop_update"); 1144 quit = 1; 1145 } 1146 1147 log_debug("nexthop %s now %s%s%s", log_addr(&msg->nexthop), 1148 msg->valid ? "valid" : "invalid", 1149 msg->connected ? ": directly connected" : "", 1150 msg->gateway.aid ? gw : ""); 1151 1152 free(gw); 1153 1154 if (imsg_compose(ibuf_rde, IMSG_NEXTHOP_UPDATE, 0, 0, -1, 1155 msg, sizeof(struct kroute_nexthop)) == -1) 1156 quit = 1; 1157 } 1158 1159 void 1160 send_imsg_session(int type, pid_t pid, void *data, uint16_t datalen) 1161 { 1162 imsg_compose(ibuf_se, type, 0, pid, -1, data, datalen); 1163 } 1164 1165 int 1166 send_network(int type, struct network_config *net, struct filter_set_head *h) 1167 { 1168 if (quit) 1169 return (0); 1170 if (imsg_compose(ibuf_rde, type, 0, 0, -1, net, 1171 sizeof(struct network_config)) == -1) 1172 return (-1); 1173 /* networks that get deleted don't need to send the filter set */ 1174 if (type == IMSG_NETWORK_REMOVE) 1175 return (0); 1176 if (send_filterset(ibuf_rde, h) == -1) 1177 return (-1); 1178 if (imsg_compose(ibuf_rde, IMSG_NETWORK_DONE, 0, 0, -1, NULL, 0) == -1) 1179 return (-1); 1180 1181 return (0); 1182 } 1183 1184 /* 1185 * Return true if a route can be used for nexthop resolution. 1186 */ 1187 int 1188 bgpd_oknexthop(struct kroute_full *kf) 1189 { 1190 if (kf->flags & F_BGPD) 1191 return ((cflags & BGPD_FLAG_NEXTHOP_BGP) != 0); 1192 1193 if (kf->prefixlen == 0) 1194 return ((cflags & BGPD_FLAG_NEXTHOP_DEFAULT) != 0); 1195 1196 /* any other route is fine */ 1197 return (1); 1198 } 1199 1200 int 1201 bgpd_has_bgpnh(void) 1202 { 1203 return ((cflags & BGPD_FLAG_NEXTHOP_BGP) != 0); 1204 } 1205 1206 int 1207 control_setup(struct bgpd_config *conf) 1208 { 1209 int fd, restricted; 1210 1211 /* control socket is outside chroot */ 1212 if (!cname || strcmp(cname, conf->csock)) { 1213 if (cname) { 1214 free(cname); 1215 } 1216 if ((cname = strdup(conf->csock)) == NULL) 1217 fatal("strdup"); 1218 if (control_check(cname) == -1) 1219 return (-1); 1220 if ((fd = control_init(0, cname)) == -1) 1221 fatalx("control socket setup failed"); 1222 if (control_listen(fd) == -1) 1223 fatalx("control socket setup failed"); 1224 restricted = 0; 1225 if (imsg_compose(ibuf_se, IMSG_RECONF_CTRL, 0, 0, fd, 1226 &restricted, sizeof(restricted)) == -1) 1227 return (-1); 1228 } 1229 if (!conf->rcsock) { 1230 /* remove restricted socket */ 1231 free(rcname); 1232 rcname = NULL; 1233 } else if (!rcname || strcmp(rcname, conf->rcsock)) { 1234 if (rcname) { 1235 free(rcname); 1236 } 1237 if ((rcname = strdup(conf->rcsock)) == NULL) 1238 fatal("strdup"); 1239 if (control_check(rcname) == -1) 1240 return (-1); 1241 if ((fd = control_init(1, rcname)) == -1) 1242 fatalx("control socket setup failed"); 1243 if (control_listen(fd) == -1) 1244 fatalx("control socket setup failed"); 1245 restricted = 1; 1246 if (imsg_compose(ibuf_se, IMSG_RECONF_CTRL, 0, 0, fd, 1247 &restricted, sizeof(restricted)) == -1) 1248 return (-1); 1249 } 1250 return (0); 1251 } 1252 1253 void 1254 set_pollfd(struct pollfd *pfd, struct imsgbuf *i) 1255 { 1256 if (i == NULL || i->fd == -1) { 1257 pfd->fd = -1; 1258 return; 1259 } 1260 pfd->fd = i->fd; 1261 pfd->events = POLLIN; 1262 if (imsgbuf_queuelen(i) > 0) 1263 pfd->events |= POLLOUT; 1264 } 1265 1266 int 1267 handle_pollfd(struct pollfd *pfd, struct imsgbuf *i) 1268 { 1269 ssize_t n; 1270 1271 if (i == NULL) 1272 return (0); 1273 1274 if (pfd->revents & POLLOUT) 1275 if (imsgbuf_write(i) == -1) { 1276 log_warn("imsg write error"); 1277 close(i->fd); 1278 i->fd = -1; 1279 return (-1); 1280 } 1281 1282 if (pfd->revents & POLLIN) { 1283 if ((n = imsgbuf_read(i)) == -1) { 1284 log_warn("imsg read error"); 1285 close(i->fd); 1286 i->fd = -1; 1287 return (-1); 1288 } 1289 if (n == 0) { 1290 log_warnx("peer closed imsg connection"); 1291 close(i->fd); 1292 i->fd = -1; 1293 return (-1); 1294 } 1295 } 1296 return (0); 1297 } 1298 1299 static void 1300 getsockpair(int pipe[2]) 1301 { 1302 int bsize, i; 1303 1304 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 1305 PF_UNSPEC, pipe) == -1) 1306 fatal("socketpair"); 1307 1308 for (i = 0; i < 2; i++) { 1309 bsize = MAX_SOCK_BUF; 1310 if (setsockopt(pipe[i], SOL_SOCKET, SO_RCVBUF, 1311 &bsize, sizeof(bsize)) == -1) { 1312 if (errno != ENOBUFS) 1313 fatal("setsockopt(SO_RCVBUF, %d)", 1314 bsize); 1315 log_warn("setsockopt(SO_RCVBUF, %d)", bsize); 1316 } 1317 } 1318 for (i = 0; i < 2; i++) { 1319 bsize = MAX_SOCK_BUF; 1320 if (setsockopt(pipe[i], SOL_SOCKET, SO_SNDBUF, 1321 &bsize, sizeof(bsize)) == -1) { 1322 if (errno != ENOBUFS) 1323 fatal("setsockopt(SO_SNDBUF, %d)", 1324 bsize); 1325 log_warn("setsockopt(SO_SNDBUF, %d)", bsize); 1326 } 1327 } 1328 } 1329 1330 int 1331 imsg_send_sockets(struct imsgbuf *se, struct imsgbuf *rde, struct imsgbuf *rtr) 1332 { 1333 int pipe_s2r[2]; 1334 int pipe_s2r_ctl[2]; 1335 int pipe_r2r[2]; 1336 1337 getsockpair(pipe_s2r); 1338 getsockpair(pipe_s2r_ctl); 1339 getsockpair(pipe_r2r); 1340 1341 if (imsg_compose(se, IMSG_SOCKET_CONN, 0, 0, pipe_s2r[0], 1342 NULL, 0) == -1) 1343 return (-1); 1344 if (imsg_compose(rde, IMSG_SOCKET_CONN, 0, 0, pipe_s2r[1], 1345 NULL, 0) == -1) 1346 return (-1); 1347 1348 if (imsg_compose(se, IMSG_SOCKET_CONN_CTL, 0, 0, pipe_s2r_ctl[0], 1349 NULL, 0) == -1) 1350 return (-1); 1351 if (imsg_compose(rde, IMSG_SOCKET_CONN_CTL, 0, 0, pipe_s2r_ctl[1], 1352 NULL, 0) == -1) 1353 return (-1); 1354 1355 if (imsg_compose(rtr, IMSG_SOCKET_CONN_RTR, 0, 0, pipe_r2r[0], 1356 NULL, 0) == -1) 1357 return (-1); 1358 if (imsg_compose(rde, IMSG_SOCKET_CONN_RTR, 0, 0, pipe_r2r[1], 1359 NULL, 0) == -1) 1360 return (-1); 1361 1362 return (0); 1363 } 1364 1365 void 1366 bgpd_rtr_conn_setup(struct rtr_config *r) 1367 { 1368 struct connect_elm *ce; 1369 struct sockaddr *sa; 1370 socklen_t len; 1371 int nodelay = 1; 1372 int pre = IPTOS_PREC_INTERNETCONTROL; 1373 1374 if (connect_cnt >= MAX_CONNECT_CNT) { 1375 log_warnx("rtr %s: too many concurrent connection requests", 1376 r->descr); 1377 return; 1378 } 1379 1380 if ((ce = calloc(1, sizeof(*ce))) == NULL) { 1381 log_warn("rtr %s", r->descr); 1382 return; 1383 } 1384 1385 if (pfkey_establish(&ce->auth_state, &r->auth, 1386 &r->local_addr, &r->remote_addr) == -1) 1387 log_warnx("rtr %s: pfkey setup failed", r->descr); 1388 1389 ce->id = r->id; 1390 ce->fd = socket(aid2af(r->remote_addr.aid), 1391 SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_TCP); 1392 if (ce->fd == -1) { 1393 log_warn("rtr %s", r->descr); 1394 goto fail; 1395 } 1396 1397 switch (r->remote_addr.aid) { 1398 case AID_INET: 1399 if (setsockopt(ce->fd, IPPROTO_IP, IP_TOS, &pre, sizeof(pre)) == 1400 -1) { 1401 log_warn("rtr %s: setsockopt IP_TOS", r->descr); 1402 return; 1403 } 1404 break; 1405 case AID_INET6: 1406 if (setsockopt(ce->fd, IPPROTO_IPV6, IPV6_TCLASS, &pre, 1407 sizeof(pre)) == -1) { 1408 log_warn("rtr %s: setsockopt IP_TOS", r->descr); 1409 return; 1410 } 1411 break; 1412 } 1413 1414 if (setsockopt(ce->fd, IPPROTO_TCP, TCP_NODELAY, &nodelay, 1415 sizeof(nodelay)) == -1) { 1416 log_warn("rtr %s: setsockopt TCP_NODELAY", r->descr); 1417 return; 1418 } 1419 1420 if (tcp_md5_set(ce->fd, &r->auth, &r->remote_addr) == -1) 1421 log_warn("rtr %s: setting md5sig", r->descr); 1422 1423 if ((sa = addr2sa(&r->local_addr, 0, &len)) != NULL) { 1424 if (bind(ce->fd, sa, len) == -1) { 1425 log_warn("rtr %s: bind to %s", r->descr, 1426 log_addr(&r->local_addr)); 1427 goto fail; 1428 } 1429 } 1430 1431 sa = addr2sa(&r->remote_addr, r->remote_port, &len); 1432 if (connect(ce->fd, sa, len) == -1) { 1433 if (errno != EINPROGRESS) { 1434 log_warn("rtr %s: connect to %s:%u", r->descr, 1435 log_addr(&r->remote_addr), r->remote_port); 1436 goto fail; 1437 } 1438 TAILQ_INSERT_TAIL(&connect_queue, ce, entry); 1439 connect_cnt++; 1440 return; 1441 } 1442 1443 imsg_compose(ibuf_rtr, IMSG_SOCKET_SETUP, ce->id, 0, ce->fd, NULL, 0); 1444 TAILQ_INSERT_TAIL(&socket_queue, ce, entry); 1445 return; 1446 1447 fail: 1448 if (ce->fd != -1) 1449 close(ce->fd); 1450 free(ce); 1451 } 1452 1453 void 1454 bgpd_rtr_conn_setup_done(int fd, struct bgpd_config *conf) 1455 { 1456 struct rtr_config *r; 1457 struct connect_elm *ce; 1458 int error = 0; 1459 socklen_t len; 1460 1461 TAILQ_FOREACH(ce, &connect_queue, entry) { 1462 if (ce->fd == fd) 1463 break; 1464 } 1465 if (ce == NULL) 1466 fatalx("connect entry not found"); 1467 1468 TAILQ_REMOVE(&connect_queue, ce, entry); 1469 connect_cnt--; 1470 1471 SIMPLEQ_FOREACH(r, &conf->rtrs, entry) { 1472 if (ce->id == r->id) 1473 break; 1474 } 1475 if (r == NULL) { 1476 log_warnx("rtr id %d no longer exists", ce->id); 1477 goto fail; 1478 } 1479 1480 len = sizeof(error); 1481 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) == -1) { 1482 log_warn("rtr %s: getsockopt SO_ERROR", r->descr); 1483 goto fail; 1484 } 1485 1486 if (error != 0) { 1487 errno = error; 1488 log_warn("rtr %s: connect to %s:%u", r->descr, 1489 log_addr(&r->remote_addr), r->remote_port); 1490 goto fail; 1491 } 1492 1493 imsg_compose(ibuf_rtr, IMSG_SOCKET_SETUP, ce->id, 0, ce->fd, NULL, 0); 1494 TAILQ_INSERT_TAIL(&socket_queue, ce, entry); 1495 return; 1496 1497 fail: 1498 close(fd); 1499 free(ce); 1500 } 1501 1502 void 1503 bgpd_rtr_conn_teardown(uint32_t id) 1504 { 1505 struct connect_elm *ce; 1506 1507 TAILQ_FOREACH(ce, &socket_queue, entry) { 1508 if (ce->id == id) { 1509 pfkey_remove(&ce->auth_state); 1510 TAILQ_REMOVE(&socket_queue, ce, entry); 1511 free(ce); 1512 return; 1513 } 1514 } 1515 } 1516