1 /* $OpenBSD: ospfd.c,v 1.124 2024/11/21 13:38:14 claudio Exp $ */ 2 3 /* 4 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 5 * Copyright (c) 2004 Esben Norby <norby@openbsd.org> 6 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21 #include <sys/types.h> 22 #include <sys/socket.h> 23 #include <sys/queue.h> 24 #include <sys/time.h> 25 #include <sys/stat.h> 26 #include <sys/wait.h> 27 #include <sys/sysctl.h> 28 #include <syslog.h> 29 30 #include <netinet/in.h> 31 #include <arpa/inet.h> 32 #include <net/if_types.h> 33 34 #include <event.h> 35 #include <err.h> 36 #include <errno.h> 37 #include <pwd.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <signal.h> 42 #include <unistd.h> 43 44 #include "ospfd.h" 45 #include "ospf.h" 46 #include "ospfe.h" 47 #include "control.h" 48 #include "log.h" 49 #include "rde.h" 50 51 void main_sig_handler(int, short, void *); 52 __dead void usage(void); 53 __dead void ospfd_shutdown(void); 54 55 void main_dispatch_ospfe(int, short, void *); 56 void main_dispatch_rde(int, short, void *); 57 58 int ospf_reload(void); 59 int ospf_sendboth(enum imsg_type, void *, u_int16_t); 60 int merge_interfaces(struct area *, struct area *); 61 struct iface *iface_lookup(struct area *, struct iface *); 62 63 int pipe_parent2ospfe[2]; 64 int pipe_parent2rde[2]; 65 int pipe_ospfe2rde[2]; 66 67 enum ospfd_process ospfd_process; 68 struct ospfd_conf *ospfd_conf = NULL; 69 static struct imsgev *iev_ospfe; 70 static struct imsgev *iev_rde; 71 char *conffile; 72 73 pid_t ospfe_pid = 0; 74 pid_t rde_pid = 0; 75 76 void 77 main_sig_handler(int sig, short event, void *arg) 78 { 79 /* signal handler rules don't apply, libevent decouples for us */ 80 switch (sig) { 81 case SIGTERM: 82 case SIGINT: 83 ospfd_shutdown(); 84 /* NOTREACHED */ 85 case SIGHUP: 86 if (ospf_reload() == -1) 87 log_warnx("configuration reload failed"); 88 else 89 log_debug("configuration reloaded"); 90 break; 91 default: 92 fatalx("unexpected signal"); 93 /* NOTREACHED */ 94 } 95 } 96 97 __dead void 98 usage(void) 99 { 100 extern char *__progname; 101 102 fprintf(stderr, "usage: %s [-cdnv] [-D macro=value]" 103 " [-f file] [-s socket]\n", 104 __progname); 105 exit(1); 106 } 107 108 int 109 main(int argc, char *argv[]) 110 { 111 struct event ev_sigint, ev_sigterm, ev_sighup; 112 struct area *a; 113 int ch, opts = 0; 114 int debug = 0; 115 int ipforwarding; 116 int mib[4]; 117 size_t len; 118 char *sockname = NULL; 119 int control_fd; 120 121 conffile = CONF_FILE; 122 ospfd_process = PROC_MAIN; 123 124 log_init(1, LOG_DAEMON); /* log to stderr until daemonized */ 125 log_procinit(log_procnames[ospfd_process]); 126 127 while ((ch = getopt(argc, argv, "cdD:f:ns:v")) != -1) { 128 switch (ch) { 129 case 'c': 130 opts |= OSPFD_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 opts |= OSPFD_OPT_NOACTION; 145 break; 146 case 's': 147 sockname = optarg; 148 break; 149 case 'v': 150 if (opts & OSPFD_OPT_VERBOSE) 151 opts |= OSPFD_OPT_VERBOSE2; 152 opts |= OSPFD_OPT_VERBOSE; 153 log_setverbose(1); 154 break; 155 default: 156 usage(); 157 /* NOTREACHED */ 158 } 159 } 160 161 argc -= optind; 162 argv += optind; 163 if (argc > 0) 164 usage(); 165 166 mib[0] = CTL_NET; 167 mib[1] = PF_INET; 168 mib[2] = IPPROTO_IP; 169 mib[3] = IPCTL_FORWARDING; 170 len = sizeof(ipforwarding); 171 if (sysctl(mib, 4, &ipforwarding, &len, NULL, 0) == -1) 172 err(1, "sysctl"); 173 174 if (ipforwarding != 1) { 175 log_warnx("WARNING: IP forwarding NOT enabled, " 176 "running as stub router"); 177 opts |= OSPFD_OPT_STUB_ROUTER; 178 } 179 180 /* fetch interfaces early */ 181 kif_init(); 182 183 /* parse config file */ 184 if ((ospfd_conf = parse_config(conffile, opts)) == NULL) { 185 kif_clear(); 186 exit(1); 187 } 188 if (ospfd_conf->rtr_id.s_addr == 0) 189 ospfd_conf->rtr_id.s_addr = get_rtr_id(); 190 191 if (sockname == NULL) { 192 if (asprintf(&sockname, "%s.%d", OSPFD_SOCKET, 193 ospfd_conf->rdomain) == -1) 194 err(1, "asprintf"); 195 } 196 197 ospfd_conf->csock = sockname; 198 199 if (ospfd_conf->opts & OSPFD_OPT_NOACTION) { 200 if (ospfd_conf->opts & OSPFD_OPT_VERBOSE) 201 print_config(ospfd_conf); 202 else 203 fprintf(stderr, "configuration OK\n"); 204 kif_clear(); 205 exit(0); 206 } 207 208 /* check for root privileges */ 209 if (geteuid()) 210 errx(1, "need root privileges"); 211 212 /* check for ospfd user */ 213 if (getpwnam(OSPFD_USER) == NULL) 214 errx(1, "unknown user %s", OSPFD_USER); 215 216 log_init(debug, LOG_DAEMON); 217 log_setverbose(ospfd_conf->opts & OSPFD_OPT_VERBOSE); 218 219 if ((control_check(ospfd_conf->csock)) == -1) 220 fatalx("ospfd already running"); 221 222 if (!debug) 223 daemon(1, 0); 224 225 log_info("startup"); 226 227 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 228 PF_UNSPEC, pipe_parent2ospfe) == -1) 229 fatal("socketpair"); 230 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 231 PF_UNSPEC, pipe_parent2rde) == -1) 232 fatal("socketpair"); 233 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 234 PF_UNSPEC, pipe_ospfe2rde) == -1) 235 fatal("socketpair"); 236 237 /* start children */ 238 rde_pid = rde(ospfd_conf, pipe_parent2rde, pipe_ospfe2rde, 239 pipe_parent2ospfe); 240 ospfe_pid = ospfe(ospfd_conf, pipe_parent2ospfe, pipe_ospfe2rde, 241 pipe_parent2rde); 242 243 event_init(); 244 245 /* setup signal handler */ 246 signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL); 247 signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL); 248 signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL); 249 signal_add(&ev_sigint, NULL); 250 signal_add(&ev_sigterm, NULL); 251 signal_add(&ev_sighup, NULL); 252 signal(SIGPIPE, SIG_IGN); 253 254 /* setup pipes to children */ 255 close(pipe_parent2ospfe[1]); 256 close(pipe_parent2rde[1]); 257 close(pipe_ospfe2rde[0]); 258 close(pipe_ospfe2rde[1]); 259 260 if ((iev_ospfe = malloc(sizeof(struct imsgev))) == NULL || 261 (iev_rde = malloc(sizeof(struct imsgev))) == NULL) 262 fatal(NULL); 263 if (imsgbuf_init(&iev_ospfe->ibuf, pipe_parent2ospfe[0]) == -1) 264 fatal(NULL); 265 imsgbuf_allow_fdpass(&iev_ospfe->ibuf); 266 iev_ospfe->handler = main_dispatch_ospfe; 267 if (imsgbuf_init(&iev_rde->ibuf, pipe_parent2rde[0]) == -1) 268 fatal(NULL); 269 iev_rde->handler = main_dispatch_rde; 270 271 /* setup event handler */ 272 iev_ospfe->events = EV_READ; 273 event_set(&iev_ospfe->ev, iev_ospfe->ibuf.fd, iev_ospfe->events, 274 iev_ospfe->handler, iev_ospfe); 275 event_add(&iev_ospfe->ev, NULL); 276 277 iev_rde->events = EV_READ; 278 event_set(&iev_rde->ev, iev_rde->ibuf.fd, iev_rde->events, 279 iev_rde->handler, iev_rde); 280 event_add(&iev_rde->ev, NULL); 281 282 if ((control_fd = control_init(ospfd_conf->csock)) == -1) 283 fatalx("control socket setup failed"); 284 main_imsg_compose_ospfe_fd(IMSG_CONTROLFD, 0, control_fd); 285 286 if (unveil("/", "r") == -1) 287 fatal("unveil /"); 288 if (unveil(NULL, NULL) == -1) 289 fatal("unveil"); 290 291 if (kr_init(!(ospfd_conf->flags & OSPFD_FLAG_NO_FIB_UPDATE), 292 ospfd_conf->rdomain, ospfd_conf->redist_label_or_prefix, 293 ospfd_conf->fib_priority) == -1) 294 fatalx("kr_init failed"); 295 296 /* remove unneeded stuff from config */ 297 while ((a = LIST_FIRST(&ospfd_conf->area_list)) != NULL) { 298 LIST_REMOVE(a, entry); 299 area_del(a); 300 } 301 302 event_dispatch(); 303 304 ospfd_shutdown(); 305 /* NOTREACHED */ 306 return (0); 307 } 308 309 __dead void 310 ospfd_shutdown(void) 311 { 312 pid_t pid; 313 int status; 314 struct redistribute *r; 315 316 /* close pipes */ 317 imsgbuf_clear(&iev_ospfe->ibuf); 318 close(iev_ospfe->ibuf.fd); 319 imsgbuf_clear(&iev_rde->ibuf); 320 close(iev_rde->ibuf.fd); 321 322 control_cleanup(); 323 while ((r = SIMPLEQ_FIRST(&ospfd_conf->redist_list)) != NULL) { 324 SIMPLEQ_REMOVE_HEAD(&ospfd_conf->redist_list, entry); 325 free(r); 326 } 327 kr_shutdown(); 328 carp_demote_shutdown(); 329 330 log_debug("waiting for children to terminate"); 331 do { 332 pid = wait(&status); 333 if (pid == -1) { 334 if (errno != EINTR && errno != ECHILD) 335 fatal("wait"); 336 } else if (WIFSIGNALED(status)) 337 log_warnx("%s terminated; signal %d", 338 (pid == rde_pid) ? "route decision engine" : 339 "ospf engine", WTERMSIG(status)); 340 } while (pid != -1 || (pid == -1 && errno == EINTR)); 341 342 free(iev_ospfe); 343 free(iev_rde); 344 free(ospfd_conf); 345 346 log_info("terminating"); 347 exit(0); 348 } 349 350 /* imsg handling */ 351 void 352 main_dispatch_ospfe(int fd, short event, void *bula) 353 { 354 struct imsgev *iev = bula; 355 struct imsgbuf *ibuf; 356 struct imsg imsg; 357 struct demote_msg dmsg; 358 ssize_t n; 359 int shut = 0, verbose; 360 361 ibuf = &iev->ibuf; 362 363 if (event & EV_READ) { 364 if ((n = imsgbuf_read(ibuf)) == -1) 365 fatal("imsgbuf_read error"); 366 if (n == 0) /* connection closed */ 367 shut = 1; 368 } 369 if (event & EV_WRITE) { 370 if (imsgbuf_write(ibuf) == -1) { 371 if (errno == EPIPE) /* connection closed */ 372 shut = 1; 373 else 374 fatal("imsgbuf_write"); 375 } 376 } 377 378 for (;;) { 379 if ((n = imsg_get(ibuf, &imsg)) == -1) 380 fatal("imsg_get"); 381 382 if (n == 0) 383 break; 384 385 switch (imsg.hdr.type) { 386 case IMSG_CTL_RELOAD: 387 if (ospf_reload() == -1) 388 log_warnx("configuration reload failed"); 389 else 390 log_debug("configuration reloaded"); 391 break; 392 case IMSG_CTL_FIB_COUPLE: 393 kr_fib_couple(); 394 break; 395 case IMSG_CTL_FIB_DECOUPLE: 396 kr_fib_decouple(); 397 break; 398 case IMSG_CTL_FIB_RELOAD: 399 kr_fib_reload(); 400 break; 401 case IMSG_CTL_KROUTE: 402 case IMSG_CTL_KROUTE_ADDR: 403 kr_show_route(&imsg); 404 break; 405 case IMSG_CTL_IFINFO: 406 if (imsg.hdr.len == IMSG_HEADER_SIZE) 407 kr_ifinfo(NULL, imsg.hdr.pid); 408 else if (imsg.hdr.len == IMSG_HEADER_SIZE + IFNAMSIZ) 409 kr_ifinfo(imsg.data, imsg.hdr.pid); 410 else 411 log_warnx("IFINFO request with wrong len"); 412 break; 413 case IMSG_DEMOTE: 414 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(dmsg)) 415 fatalx("invalid size of OE request"); 416 memcpy(&dmsg, imsg.data, sizeof(dmsg)); 417 carp_demote_set(dmsg.demote_group, dmsg.level); 418 break; 419 case IMSG_CTL_LOG_VERBOSE: 420 /* already checked by ospfe */ 421 memcpy(&verbose, imsg.data, sizeof(verbose)); 422 log_setverbose(verbose); 423 break; 424 default: 425 log_debug("main_dispatch_ospfe: error handling imsg %d", 426 imsg.hdr.type); 427 break; 428 } 429 imsg_free(&imsg); 430 } 431 if (!shut) 432 imsg_event_add(iev); 433 else { 434 /* this pipe is dead, so remove the event handler */ 435 event_del(&iev->ev); 436 event_loopexit(NULL); 437 } 438 } 439 440 void 441 main_dispatch_rde(int fd, short event, void *bula) 442 { 443 struct imsgev *iev = bula; 444 struct imsgbuf *ibuf; 445 struct imsg imsg; 446 ssize_t n; 447 int count, shut = 0; 448 449 ibuf = &iev->ibuf; 450 451 if (event & EV_READ) { 452 if ((n = imsgbuf_read(ibuf)) == -1) 453 fatal("imsgbuf_read error"); 454 if (n == 0) /* connection closed */ 455 shut = 1; 456 } 457 if (event & EV_WRITE) { 458 if (imsgbuf_write(ibuf) == -1) { 459 if (errno == EPIPE) /* connection closed */ 460 shut = 1; 461 else 462 fatal("imsgbuf_write"); 463 } 464 } 465 466 for (;;) { 467 if ((n = imsg_get(ibuf, &imsg)) == -1) 468 fatal("imsg_get"); 469 470 if (n == 0) 471 break; 472 473 switch (imsg.hdr.type) { 474 case IMSG_KROUTE_CHANGE: 475 count = (imsg.hdr.len - IMSG_HEADER_SIZE) / 476 sizeof(struct kroute); 477 if (kr_change(imsg.data, count)) 478 log_warn("main_dispatch_rde: error changing " 479 "route"); 480 break; 481 case IMSG_KROUTE_DELETE: 482 if (kr_delete(imsg.data)) 483 log_warn("main_dispatch_rde: error deleting " 484 "route"); 485 break; 486 default: 487 log_debug("main_dispatch_rde: error handling imsg %d", 488 imsg.hdr.type); 489 break; 490 } 491 imsg_free(&imsg); 492 } 493 if (!shut) 494 imsg_event_add(iev); 495 else { 496 /* this pipe is dead, so remove the event handler */ 497 event_del(&iev->ev); 498 event_loopexit(NULL); 499 } 500 } 501 502 void 503 main_imsg_compose_ospfe(int type, pid_t pid, void *data, u_int16_t datalen) 504 { 505 if (iev_ospfe) 506 imsg_compose_event(iev_ospfe, type, 0, pid, -1, data, datalen); 507 } 508 509 void 510 main_imsg_compose_ospfe_fd(int type, pid_t pid, int fd) 511 { 512 if (iev_ospfe) 513 imsg_compose_event(iev_ospfe, type, 0, pid, fd, NULL, 0); 514 } 515 516 void 517 main_imsg_compose_rde(int type, pid_t pid, void *data, u_int16_t datalen) 518 { 519 if (iev_rde) 520 imsg_compose_event(iev_rde, type, 0, pid, -1, data, datalen); 521 } 522 523 void 524 imsg_event_add(struct imsgev *iev) 525 { 526 iev->events = EV_READ; 527 if (imsgbuf_queuelen(&iev->ibuf) > 0) 528 iev->events |= EV_WRITE; 529 530 event_del(&iev->ev); 531 event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev); 532 event_add(&iev->ev, NULL); 533 } 534 535 int 536 imsg_compose_event(struct imsgev *iev, u_int16_t type, u_int32_t peerid, 537 pid_t pid, int fd, void *data, u_int16_t datalen) 538 { 539 int ret; 540 541 if ((ret = imsg_compose(&iev->ibuf, type, peerid, 542 pid, fd, data, datalen)) != -1) 543 imsg_event_add(iev); 544 return (ret); 545 } 546 547 int 548 ospf_redistribute(struct kroute *kr, u_int32_t *metric) 549 { 550 struct in_addr addr; 551 struct kif *kif; 552 struct redistribute *r; 553 int is_default, depend_ok; 554 555 bzero(&addr, sizeof(addr)); 556 557 /* only allow 0.0.0.0/0 via REDIST_DEFAULT */ 558 is_default = (kr->prefix.s_addr == INADDR_ANY && kr->prefixlen == 0); 559 560 SIMPLEQ_FOREACH(r, &ospfd_conf->redist_list, entry) { 561 if (r->dependon[0] != '\0') { 562 if ((kif = kif_findname(r->dependon, addr, NULL))) 563 depend_ok = ifstate_is_up(kif); 564 else 565 depend_ok = 0; 566 } else 567 depend_ok = 1; 568 569 switch (r->type & ~REDIST_NO) { 570 case REDIST_LABEL: 571 if (kr->rtlabel == r->label) { 572 *metric = depend_ok ? r->metric : 573 r->metric | MAX_METRIC; 574 return (r->type & REDIST_NO ? 0 : 1); 575 } 576 break; 577 case REDIST_STATIC: 578 /* 579 * Dynamic routes are not redistributable. Placed here 580 * so that link local addresses can be redistributed 581 * via a rtlabel. 582 */ 583 if (is_default) 584 continue; 585 if (kr->flags & F_DYNAMIC) 586 continue; 587 if (kr->flags & F_STATIC) { 588 *metric = depend_ok ? r->metric : 589 r->metric | MAX_METRIC; 590 return (r->type & REDIST_NO ? 0 : 1); 591 } 592 break; 593 case REDIST_CONNECTED: 594 if (is_default) 595 continue; 596 if (kr->flags & F_DYNAMIC) 597 continue; 598 if (kr->flags & F_CONNECTED) { 599 *metric = depend_ok ? r->metric : 600 r->metric | MAX_METRIC; 601 return (r->type & REDIST_NO ? 0 : 1); 602 } 603 break; 604 case REDIST_ADDR: 605 if (kr->flags & F_DYNAMIC) 606 continue; 607 608 if (r->addr.s_addr == INADDR_ANY && 609 r->mask.s_addr == INADDR_ANY) { 610 if (is_default) { 611 *metric = depend_ok ? r->metric : 612 r->metric | MAX_METRIC; 613 return (r->type & REDIST_NO ? 0 : 1); 614 } else 615 return (0); 616 } 617 618 if ((kr->prefix.s_addr & r->mask.s_addr) == 619 (r->addr.s_addr & r->mask.s_addr) && 620 kr->prefixlen >= mask2prefixlen(r->mask.s_addr)) { 621 *metric = depend_ok ? r->metric : 622 r->metric | MAX_METRIC; 623 return (r->type & REDIST_NO ? 0 : 1); 624 } 625 break; 626 case REDIST_DEFAULT: 627 if (is_default) { 628 *metric = depend_ok ? r->metric : 629 r->metric | MAX_METRIC; 630 return (r->type & REDIST_NO ? 0 : 1); 631 } 632 break; 633 } 634 } 635 636 return (0); 637 } 638 639 int 640 ospf_reload(void) 641 { 642 struct area *area; 643 struct iface *iface; 644 struct ospfd_conf *xconf; 645 struct redistribute *r; 646 647 if ((xconf = parse_config(conffile, ospfd_conf->opts)) == NULL) 648 return (-1); 649 650 /* No router-id was specified, keep existing value */ 651 if (xconf->rtr_id.s_addr == 0) 652 xconf->rtr_id.s_addr = ospfd_conf->rtr_id.s_addr; 653 654 /* Abort the reload if rtr_id changed */ 655 if (ospfd_conf->rtr_id.s_addr != xconf->rtr_id.s_addr) { 656 log_warnx("router-id changed: restart required"); 657 return (-1); 658 } 659 660 /* send config to childs */ 661 if (ospf_sendboth(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1) 662 return (-1); 663 664 /* send interfaces */ 665 LIST_FOREACH(area, &xconf->area_list, entry) { 666 if (ospf_sendboth(IMSG_RECONF_AREA, area, sizeof(*area)) == -1) 667 return (-1); 668 669 SIMPLEQ_FOREACH(r, &area->redist_list, entry) { 670 main_imsg_compose_rde(IMSG_RECONF_REDIST, 0, r, 671 sizeof(*r)); 672 } 673 LIST_FOREACH(iface, &area->iface_list, entry) { 674 if (ospf_sendboth(IMSG_RECONF_IFACE, iface, 675 sizeof(*iface)) == -1) 676 return (-1); 677 if (iface->auth_type == AUTH_CRYPT) 678 if (md_list_send(&iface->auth_md_list, 679 iev_ospfe) == -1) 680 return (-1); 681 } 682 } 683 684 if (ospf_sendboth(IMSG_RECONF_END, NULL, 0) == -1) 685 return (-1); 686 687 merge_config(ospfd_conf, xconf); 688 /* update redistribute lists */ 689 kr_reload(ospfd_conf->redist_label_or_prefix); 690 return (0); 691 } 692 693 int 694 ospf_sendboth(enum imsg_type type, void *buf, u_int16_t len) 695 { 696 if (imsg_compose_event(iev_ospfe, type, 0, 0, -1, buf, len) == -1) 697 return (-1); 698 if (imsg_compose_event(iev_rde, type, 0, 0, -1, buf, len) == -1) 699 return (-1); 700 return (0); 701 } 702 703 void 704 merge_config(struct ospfd_conf *conf, struct ospfd_conf *xconf) 705 { 706 struct area *a, *xa, *na; 707 struct iface *iface; 708 struct redistribute *r; 709 int rchange = 0; 710 711 conf->flags = xconf->flags; 712 conf->spf_delay = xconf->spf_delay; 713 conf->spf_hold_time = xconf->spf_hold_time; 714 if (SIMPLEQ_EMPTY(&conf->redist_list) != 715 SIMPLEQ_EMPTY(&xconf->redist_list)) 716 rchange = 1; 717 conf->rfc1583compat = xconf->rfc1583compat; 718 conf->redist_label_or_prefix = xconf->redist_label_or_prefix; 719 720 if (ospfd_process == PROC_MAIN) { 721 /* main process does neither use areas nor interfaces */ 722 while ((r = SIMPLEQ_FIRST(&conf->redist_list)) != NULL) { 723 SIMPLEQ_REMOVE_HEAD(&conf->redist_list, entry); 724 free(r); 725 } 726 SIMPLEQ_CONCAT(&conf->redist_list, &xconf->redist_list); 727 728 /* adjust FIB priority if changed */ 729 if (conf->fib_priority != xconf->fib_priority) { 730 kr_fib_decouple(); 731 kr_fib_update_prio(xconf->fib_priority); 732 conf->fib_priority = xconf->fib_priority; 733 kr_fib_couple(); 734 } 735 736 goto done; 737 } 738 739 /* merge areas and interfaces */ 740 for (a = LIST_FIRST(&conf->area_list); a != NULL; a = na) { 741 na = LIST_NEXT(a, entry); 742 /* find deleted areas */ 743 if ((xa = area_find(xconf, a->id)) == NULL) { 744 if (ospfd_process == PROC_OSPF_ENGINE) { 745 LIST_FOREACH(iface, &a->iface_list, entry) 746 if_fsm(iface, IF_EVT_DOWN); 747 } 748 LIST_REMOVE(a, entry); 749 area_del(a); 750 } 751 } 752 753 for (xa = LIST_FIRST(&xconf->area_list); xa != NULL; xa = na) { 754 na = LIST_NEXT(xa, entry); 755 if ((a = area_find(conf, xa->id)) == NULL) { 756 LIST_REMOVE(xa, entry); 757 LIST_INSERT_HEAD(&conf->area_list, xa, entry); 758 if (ospfd_process == PROC_OSPF_ENGINE) { 759 /* start interfaces */ 760 ospfe_demote_area(xa, 0); 761 LIST_FOREACH(iface, &xa->iface_list, entry) { 762 if_init(conf, iface); 763 if (if_fsm(iface, IF_EVT_UP)) { 764 log_debug("error starting " 765 "interface %s", 766 iface->name); 767 } 768 } 769 } 770 /* no need to merge interfaces */ 771 continue; 772 } 773 /* 774 * stub is not yet used but switching between stub and normal 775 * will be another painful job. 776 */ 777 if (a->stub != xa->stub && ospfd_process == PROC_OSPF_ENGINE) 778 a->dirty = 1; /* force rtr LSA update */ 779 if (xa->stub && ospfd_process == PROC_RDE_ENGINE) { 780 while ((r = SIMPLEQ_FIRST(&a->redist_list)) != NULL) { 781 SIMPLEQ_REMOVE_HEAD(&a->redist_list, entry); 782 free(r); 783 } 784 785 SIMPLEQ_CONCAT(&a->redist_list, &xa->redist_list); 786 } 787 788 a->stub = xa->stub; 789 a->stub_default_cost = xa->stub_default_cost; 790 if (ospfd_process == PROC_RDE_ENGINE) 791 a->dirty = 1; /* force SPF tree recalculation */ 792 793 /* merge interfaces */ 794 if (merge_interfaces(a, xa) && 795 ospfd_process == PROC_OSPF_ENGINE) 796 a->dirty = 1; /* force rtr LSA update */ 797 } 798 799 if (ospfd_process == PROC_OSPF_ENGINE) { 800 LIST_FOREACH(a, &conf->area_list, entry) { 801 LIST_FOREACH(iface, &a->iface_list, entry) { 802 if (iface->state == IF_STA_NEW) { 803 iface->state = IF_STA_DOWN; 804 if_init(conf, iface); 805 if (if_fsm(iface, IF_EVT_UP)) { 806 log_debug("error starting " 807 "interface %s", 808 iface->name); 809 } 810 } 811 } 812 if (a->dirty || rchange) { 813 a->dirty = 0; 814 orig_rtr_lsa(a); 815 } 816 } 817 } 818 if (ospfd_process == PROC_RDE_ENGINE) { 819 LIST_FOREACH(a, &conf->area_list, entry) { 820 if (a->dirty) { 821 start_spf_timer(); 822 break; 823 } 824 } 825 } 826 827 done: 828 while ((a = LIST_FIRST(&xconf->area_list)) != NULL) { 829 LIST_REMOVE(a, entry); 830 area_del(a); 831 } 832 free(xconf); 833 } 834 835 int 836 merge_interfaces(struct area *a, struct area *xa) 837 { 838 struct iface *i, *xi, *ni; 839 int dirty = 0; 840 841 /* problems: 842 * - new interfaces (easy) 843 * - deleted interfaces 844 * - changing passive (painful?) 845 */ 846 for (i = LIST_FIRST(&a->iface_list); i != NULL; i = ni) { 847 ni = LIST_NEXT(i, entry); 848 if (iface_lookup(xa, i) == NULL) { 849 log_debug("merge_interfaces: proc %d area %s removing " 850 "interface %s", ospfd_process, inet_ntoa(a->id), 851 i->name); 852 if (ospfd_process == PROC_OSPF_ENGINE) 853 if_fsm(i, IF_EVT_DOWN); 854 else if (ospfd_process == PROC_RDE_ENGINE) 855 rde_nbr_iface_del(i); 856 LIST_REMOVE(i, entry); 857 if_del(i); 858 dirty = 1; /* force rtr LSA update */ 859 } 860 } 861 862 for (xi = LIST_FIRST(&xa->iface_list); xi != NULL; xi = ni) { 863 ni = LIST_NEXT(xi, entry); 864 if ((i = iface_lookup(a, xi)) == NULL) { 865 /* new interface but delay initialisation */ 866 log_debug("merge_interfaces: proc %d area %s adding " 867 "interface %s", ospfd_process, inet_ntoa(a->id), 868 xi->name); 869 LIST_REMOVE(xi, entry); 870 LIST_INSERT_HEAD(&a->iface_list, xi, entry); 871 xi->area = a; 872 if (ospfd_process == PROC_OSPF_ENGINE) 873 xi->state = IF_STA_NEW; 874 continue; 875 } 876 log_debug("merge_interfaces: proc %d area %s merging " 877 "interface %s", ospfd_process, inet_ntoa(a->id), i->name); 878 i->dst = xi->dst; 879 i->abr_id = xi->abr_id; 880 i->baudrate = xi->baudrate; 881 i->dead_interval = xi->dead_interval; 882 i->mtu = xi->mtu; 883 i->transmit_delay = xi->transmit_delay; 884 i->hello_interval = xi->hello_interval; 885 i->rxmt_interval = xi->rxmt_interval; 886 if (i->metric != xi->metric) 887 dirty = 1; 888 i->metric = xi->metric; 889 i->priority = xi->priority; 890 if (i->self) 891 i->self->priority = i->priority; 892 i->flags = xi->flags; /* needed? */ 893 i->if_type = xi->if_type; /* needed? */ 894 i->linkstate = xi->linkstate; /* needed? */ 895 896 i->auth_type = xi->auth_type; 897 strncpy(i->auth_key, xi->auth_key, MAX_SIMPLE_AUTH_LEN); 898 md_list_clr(&i->auth_md_list); 899 md_list_copy(&i->auth_md_list, &xi->auth_md_list); 900 901 strlcpy(i->dependon, xi->dependon, 902 sizeof(i->dependon)); 903 i->depend_ok = xi->depend_ok; 904 905 if (i->passive != xi->passive) { 906 /* need to restart interface to cope with this change */ 907 if (ospfd_process == PROC_OSPF_ENGINE) 908 if_fsm(i, IF_EVT_DOWN); 909 i->passive = xi->passive; 910 if (ospfd_process == PROC_OSPF_ENGINE) 911 if_fsm(i, IF_EVT_UP); 912 } 913 914 if (i->type != xi->type) { 915 /* restart interface to enable or disable DR election */ 916 if (ospfd_process == PROC_OSPF_ENGINE) 917 if_fsm(i, IF_EVT_DOWN); 918 i->type = xi->type; 919 if (ospfd_process == PROC_OSPF_ENGINE) 920 if_fsm(i, IF_EVT_UP); 921 } 922 } 923 return (dirty); 924 } 925 926 struct iface * 927 iface_lookup(struct area *area, struct iface *iface) 928 { 929 struct iface *i; 930 931 LIST_FOREACH(i, &area->iface_list, entry) 932 if (i->ifindex == iface->ifindex && 933 i->addr.s_addr == iface->addr.s_addr && 934 i->mask.s_addr == iface->mask.s_addr) 935 return (i); 936 return (NULL); 937 } 938 939 int 940 ifstate_is_up(struct kif *kif) 941 { 942 if (!(kif->flags & IFF_UP)) 943 return (0); 944 if (kif->if_type == IFT_CARP && 945 kif->link_state == LINK_STATE_UNKNOWN) 946 return (0); 947 return LINK_STATE_IS_UP(kif->link_state); 948 } 949