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