1 /* $OpenBSD: ospfe.c,v 1.71 2023/12/13 15:34:43 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 <netinet/in.h> 25 #include <arpa/inet.h> 26 #include <net/if_types.h> 27 #include <stdlib.h> 28 #include <signal.h> 29 #include <string.h> 30 #include <fcntl.h> 31 #include <pwd.h> 32 #include <unistd.h> 33 #include <event.h> 34 #include <err.h> 35 #include <errno.h> 36 #include <stdio.h> 37 38 #include "ospf6.h" 39 #include "ospf6d.h" 40 #include "ospfe.h" 41 #include "rde.h" 42 #include "control.h" 43 #include "log.h" 44 45 void ospfe_sig_handler(int, short, void *); 46 __dead void ospfe_shutdown(void); 47 void orig_rtr_lsa_all(struct area *); 48 struct iface *find_vlink(struct abr_rtr *); 49 50 struct ospfd_conf *oeconf = NULL, *noeconf; 51 static struct imsgev *iev_main; 52 static struct imsgev *iev_rde; 53 int oe_nofib; 54 55 void 56 ospfe_sig_handler(int sig, short event, void *bula) 57 { 58 switch (sig) { 59 case SIGINT: 60 case SIGTERM: 61 ospfe_shutdown(); 62 /* NOTREACHED */ 63 default: 64 fatalx("unexpected signal"); 65 } 66 } 67 68 /* ospf engine */ 69 pid_t 70 ospfe(struct ospfd_conf *xconf, int pipe_parent2ospfe[2], int pipe_ospfe2rde[2], 71 int pipe_parent2rde[2]) 72 { 73 struct area *area; 74 struct iface *iface; 75 struct passwd *pw; 76 struct event ev_sigint, ev_sigterm; 77 pid_t pid; 78 79 switch (pid = fork()) { 80 case -1: 81 fatal("cannot fork"); 82 case 0: 83 break; 84 default: 85 return (pid); 86 } 87 88 /* create the raw ip socket */ 89 if ((xconf->ospf_socket = socket(AF_INET6, 90 SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_OSPF)) == -1) 91 fatal("error creating raw socket"); 92 93 /* set some defaults */ 94 if (if_set_mcast_loop(xconf->ospf_socket) == -1) 95 fatal("if_set_mcast_loop"); 96 if (if_set_ipv6_checksum(xconf->ospf_socket) == -1) 97 fatal("if_set_ipv6_checksum"); 98 if (if_set_ipv6_pktinfo(xconf->ospf_socket, 1) == -1) 99 fatal("if_set_ipv6_pktinfo"); 100 if_set_sockbuf(xconf->ospf_socket); 101 102 oeconf = xconf; 103 if (oeconf->flags & OSPFD_FLAG_NO_FIB_UPDATE) 104 oe_nofib = 1; 105 106 if ((pw = getpwnam(OSPF6D_USER)) == NULL) 107 fatal("getpwnam"); 108 109 if (chroot(pw->pw_dir) == -1) 110 fatal("chroot"); 111 if (chdir("/") == -1) 112 fatal("chdir(\"/\")"); 113 114 setproctitle("ospf engine"); 115 /* 116 * XXX needed with fork+exec 117 * log_init(debug, LOG_DAEMON); 118 * log_setverbose(verbose); 119 */ 120 121 ospfd_process = PROC_OSPF_ENGINE; 122 log_procinit(log_procnames[ospfd_process]); 123 124 if (setgroups(1, &pw->pw_gid) || 125 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 126 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 127 fatal("can't drop privileges"); 128 129 if (pledge("stdio inet mcast recvfd", NULL) == -1) 130 fatal("pledge"); 131 132 event_init(); 133 nbr_init(NBR_HASHSIZE); 134 lsa_cache_init(LSA_HASHSIZE); 135 136 /* setup signal handler */ 137 signal_set(&ev_sigint, SIGINT, ospfe_sig_handler, NULL); 138 signal_set(&ev_sigterm, SIGTERM, ospfe_sig_handler, NULL); 139 signal_add(&ev_sigint, NULL); 140 signal_add(&ev_sigterm, NULL); 141 signal(SIGPIPE, SIG_IGN); 142 signal(SIGHUP, SIG_IGN); 143 144 /* setup pipes */ 145 close(pipe_parent2ospfe[0]); 146 close(pipe_ospfe2rde[1]); 147 close(pipe_parent2rde[0]); 148 close(pipe_parent2rde[1]); 149 150 if ((iev_rde = malloc(sizeof(struct imsgev))) == NULL || 151 (iev_main = malloc(sizeof(struct imsgev))) == NULL) 152 fatal(NULL); 153 imsg_init(&iev_rde->ibuf, pipe_ospfe2rde[0]); 154 iev_rde->handler = ospfe_dispatch_rde; 155 imsg_init(&iev_main->ibuf, pipe_parent2ospfe[1]); 156 iev_main->handler = ospfe_dispatch_main; 157 158 /* setup event handler */ 159 iev_rde->events = EV_READ; 160 event_set(&iev_rde->ev, iev_rde->ibuf.fd, iev_rde->events, 161 iev_rde->handler, iev_rde); 162 event_add(&iev_rde->ev, NULL); 163 164 iev_main->events = EV_READ; 165 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events, 166 iev_main->handler, iev_main); 167 event_add(&iev_main->ev, NULL); 168 169 event_set(&oeconf->ev, oeconf->ospf_socket, EV_READ|EV_PERSIST, 170 recv_packet, oeconf); 171 event_add(&oeconf->ev, NULL); 172 173 /* remove unneeded config stuff */ 174 conf_clear_redist_list(&oeconf->redist_list); 175 176 /* start interfaces */ 177 LIST_FOREACH(area, &oeconf->area_list, entry) { 178 ospfe_demote_area(area, 0); 179 LIST_FOREACH(iface, &area->iface_list, entry) 180 if_start(xconf, iface); 181 } 182 183 event_dispatch(); 184 185 ospfe_shutdown(); 186 /* NOTREACHED */ 187 return (0); 188 } 189 190 __dead void 191 ospfe_shutdown(void) 192 { 193 struct area *area; 194 struct iface *iface; 195 196 /* close pipes */ 197 msgbuf_write(&iev_rde->ibuf.w); 198 msgbuf_clear(&iev_rde->ibuf.w); 199 close(iev_rde->ibuf.fd); 200 msgbuf_write(&iev_main->ibuf.w); 201 msgbuf_clear(&iev_main->ibuf.w); 202 close(iev_main->ibuf.fd); 203 204 /* stop all interfaces and remove all areas */ 205 while ((area = LIST_FIRST(&oeconf->area_list)) != NULL) { 206 LIST_FOREACH(iface, &area->iface_list, entry) { 207 if (if_fsm(iface, IF_EVT_DOWN)) { 208 log_debug("error stopping interface %s", 209 iface->name); 210 } 211 } 212 LIST_REMOVE(area, entry); 213 area_del(area); 214 } 215 216 close(oeconf->ospf_socket); 217 218 /* clean up */ 219 free(iev_rde); 220 free(iev_main); 221 free(oeconf); 222 223 log_info("ospf engine exiting"); 224 _exit(0); 225 } 226 227 /* imesg */ 228 int 229 ospfe_imsg_compose_parent(int type, pid_t pid, void *data, u_int16_t datalen) 230 { 231 return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen)); 232 } 233 234 int 235 ospfe_imsg_compose_rde(int type, u_int32_t peerid, pid_t pid, 236 void *data, u_int16_t datalen) 237 { 238 return (imsg_compose_event(iev_rde, type, peerid, pid, -1, 239 data, datalen)); 240 } 241 242 void 243 ospfe_dispatch_main(int fd, short event, void *bula) 244 { 245 static struct area *narea; 246 struct area *area; 247 struct iface *iface, *ifp, *i; 248 struct ifaddrchange *ifc; 249 struct iface_addr *ia, *nia; 250 struct imsg imsg; 251 struct imsgev *iev = bula; 252 struct imsgbuf *ibuf = &iev->ibuf; 253 int n, stub_changed, shut = 0, isvalid, wasvalid; 254 255 if (event & EV_READ) { 256 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 257 fatal("imsg_read error"); 258 if (n == 0) /* connection closed */ 259 shut = 1; 260 } 261 if (event & EV_WRITE) { 262 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 263 fatal("msgbuf_write"); 264 if (n == 0) /* connection closed */ 265 shut = 1; 266 } 267 268 for (;;) { 269 if ((n = imsg_get(ibuf, &imsg)) == -1) 270 fatal("ospfe_dispatch_main: imsg_get error"); 271 if (n == 0) 272 break; 273 274 switch (imsg.hdr.type) { 275 case IMSG_IFINFO: 276 if (imsg.hdr.len != IMSG_HEADER_SIZE + 277 sizeof(struct iface)) 278 fatalx("IFINFO imsg with wrong len"); 279 ifp = imsg.data; 280 281 LIST_FOREACH(area, &oeconf->area_list, entry) { 282 LIST_FOREACH(i, &area->iface_list, entry) { 283 if (strcmp(i->dependon, 284 ifp->name) == 0) { 285 log_warnx("interface %s" 286 " changed state, %s" 287 " depends on it", 288 ifp->name, i->name); 289 i->depend_ok = 290 ifstate_is_up(ifp); 291 if (ifstate_is_up(i)) 292 orig_rtr_lsa(i->area); 293 } 294 } 295 } 296 297 if (!(ifp->cflags & F_IFACE_CONFIGURED)) 298 break; 299 iface = if_find(ifp->ifindex); 300 if (iface == NULL) 301 fatalx("interface lost in ospfe"); 302 303 wasvalid = (iface->flags & IFF_UP) && 304 LINK_STATE_IS_UP(iface->linkstate); 305 306 if_update(iface, ifp->mtu, ifp->flags, ifp->if_type, 307 ifp->linkstate, ifp->baudrate, ifp->rdomain); 308 309 isvalid = (iface->flags & IFF_UP) && 310 LINK_STATE_IS_UP(iface->linkstate); 311 312 if (wasvalid == isvalid) 313 break; 314 315 if (isvalid) { 316 if_fsm(iface, IF_EVT_UP); 317 log_warnx("interface %s up", iface->name); 318 } else { 319 if_fsm(iface, IF_EVT_DOWN); 320 log_warnx("interface %s down", iface->name); 321 } 322 break; 323 case IMSG_IFADDRNEW: 324 if (imsg.hdr.len != IMSG_HEADER_SIZE + 325 sizeof(struct ifaddrchange)) 326 fatalx("IFADDRNEW imsg with wrong len"); 327 ifc = imsg.data; 328 329 iface = if_find(ifc->ifindex); 330 if (iface == NULL) 331 fatalx("IFADDRNEW interface lost in ospfe"); 332 333 if ((ia = calloc(1, sizeof(struct iface_addr))) == 334 NULL) 335 fatal("ospfe_dispatch_main IFADDRNEW"); 336 ia->addr = ifc->addr; 337 ia->dstbrd = ifc->dstbrd; 338 ia->prefixlen = ifc->prefixlen; 339 340 TAILQ_INSERT_TAIL(&iface->ifa_list, ia, entry); 341 orig_link_lsa(iface); 342 break; 343 case IMSG_IFADDRDEL: 344 if (imsg.hdr.len != IMSG_HEADER_SIZE + 345 sizeof(struct ifaddrchange)) 346 fatalx("IFADDRDEL imsg with wrong len"); 347 ifc = imsg.data; 348 349 iface = if_find(ifc->ifindex); 350 if (iface == NULL) 351 fatalx("IFADDRDEL interface lost in ospfe"); 352 353 for (ia = TAILQ_FIRST(&iface->ifa_list); ia != NULL; 354 ia = nia) { 355 nia = TAILQ_NEXT(ia, entry); 356 357 if (IN6_ARE_ADDR_EQUAL(&ia->addr, 358 &ifc->addr)) { 359 TAILQ_REMOVE(&iface->ifa_list, ia, 360 entry); 361 free(ia); 362 break; 363 } 364 } 365 orig_link_lsa(iface); 366 break; 367 case IMSG_RECONF_CONF: 368 if ((noeconf = malloc(sizeof(struct ospfd_conf))) == 369 NULL) 370 fatal(NULL); 371 memcpy(noeconf, imsg.data, sizeof(struct ospfd_conf)); 372 373 LIST_INIT(&noeconf->area_list); 374 LIST_INIT(&noeconf->cand_list); 375 break; 376 case IMSG_RECONF_AREA: 377 if ((narea = area_new()) == NULL) 378 fatal(NULL); 379 memcpy(narea, imsg.data, sizeof(struct area)); 380 381 LIST_INIT(&narea->iface_list); 382 LIST_INIT(&narea->nbr_list); 383 RB_INIT(&narea->lsa_tree); 384 385 LIST_INSERT_HEAD(&noeconf->area_list, narea, entry); 386 break; 387 case IMSG_RECONF_END: 388 if ((oeconf->flags & OSPFD_FLAG_STUB_ROUTER) != 389 (noeconf->flags & OSPFD_FLAG_STUB_ROUTER)) 390 stub_changed = 1; 391 else 392 stub_changed = 0; 393 merge_config(oeconf, noeconf); 394 noeconf = NULL; 395 if (stub_changed) 396 orig_rtr_lsa_all(NULL); 397 break; 398 case IMSG_CTL_KROUTE: 399 case IMSG_CTL_KROUTE_ADDR: 400 case IMSG_CTL_END: 401 control_imsg_relay(&imsg); 402 break; 403 case IMSG_CONTROLFD: 404 if ((fd = imsg_get_fd(&imsg)) == -1) 405 fatalx("%s: expected to receive imsg control" 406 "fd but didn't receive any", __func__); 407 /* Listen on control socket. */ 408 control_listen(fd); 409 if (pledge("stdio inet mcast", NULL) == -1) 410 fatal("pledge"); 411 break; 412 default: 413 log_debug("ospfe_dispatch_main: error handling imsg %d", 414 imsg.hdr.type); 415 break; 416 } 417 imsg_free(&imsg); 418 } 419 if (!shut) 420 imsg_event_add(iev); 421 else { 422 /* this pipe is dead, so remove the event handler */ 423 event_del(&iev->ev); 424 event_loopexit(NULL); 425 } 426 } 427 428 void 429 ospfe_dispatch_rde(int fd, short event, void *bula) 430 { 431 struct lsa_hdr lsa_hdr; 432 struct lsa_link lsa_link; 433 struct imsgev *iev = bula; 434 struct imsgbuf *ibuf = &iev->ibuf; 435 struct nbr *nbr; 436 struct lsa_hdr *lhp; 437 struct lsa_ref *ref; 438 struct area *area; 439 struct iface *iface; 440 struct lsa_entry *le; 441 struct imsg imsg; 442 struct abr_rtr ar; 443 int n, noack = 0, shut = 0; 444 u_int16_t l, age; 445 446 if (event & EV_READ) { 447 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 448 fatal("imsg_read error"); 449 if (n == 0) /* connection closed */ 450 shut = 1; 451 } 452 if (event & EV_WRITE) { 453 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 454 fatal("msgbuf_write"); 455 if (n == 0) /* connection closed */ 456 shut = 1; 457 } 458 459 for (;;) { 460 if ((n = imsg_get(ibuf, &imsg)) == -1) 461 fatal("ospfe_dispatch_rde: imsg_get error"); 462 if (n == 0) 463 break; 464 465 switch (imsg.hdr.type) { 466 case IMSG_DD: 467 nbr = nbr_find_peerid(imsg.hdr.peerid); 468 if (nbr == NULL) 469 break; 470 471 /* put these on my ls_req_list for retrieval */ 472 lhp = lsa_hdr_new(); 473 memcpy(lhp, imsg.data, sizeof(*lhp)); 474 ls_req_list_add(nbr, lhp); 475 break; 476 case IMSG_DD_END: 477 nbr = nbr_find_peerid(imsg.hdr.peerid); 478 if (nbr == NULL) 479 break; 480 481 nbr->dd_pending--; 482 if (nbr->dd_pending == 0 && nbr->state & NBR_STA_LOAD) { 483 if (ls_req_list_empty(nbr)) 484 nbr_fsm(nbr, NBR_EVT_LOAD_DONE); 485 else 486 start_ls_req_tx_timer(nbr); 487 } 488 break; 489 case IMSG_DB_SNAPSHOT: 490 nbr = nbr_find_peerid(imsg.hdr.peerid); 491 if (nbr == NULL) 492 break; 493 if (nbr->state != NBR_STA_SNAP) /* discard */ 494 break; 495 496 /* add LSA header to the neighbor db_sum_list */ 497 lhp = lsa_hdr_new(); 498 memcpy(lhp, imsg.data, sizeof(*lhp)); 499 db_sum_list_add(nbr, lhp); 500 break; 501 case IMSG_DB_END: 502 nbr = nbr_find_peerid(imsg.hdr.peerid); 503 if (nbr == NULL) 504 break; 505 506 nbr->dd_snapshot = 0; 507 if (nbr->state != NBR_STA_SNAP) 508 break; 509 510 /* snapshot done, start tx of dd packets */ 511 nbr_fsm(nbr, NBR_EVT_SNAP_DONE); 512 break; 513 case IMSG_LS_FLOOD: 514 nbr = nbr_find_peerid(imsg.hdr.peerid); 515 if (nbr == NULL) 516 break; 517 518 l = imsg.hdr.len - IMSG_HEADER_SIZE; 519 if (l < sizeof(lsa_hdr)) 520 fatalx("ospfe_dispatch_rde: " 521 "bad imsg size"); 522 memcpy(&lsa_hdr, imsg.data, sizeof(lsa_hdr)); 523 524 ref = lsa_cache_add(imsg.data, l); 525 526 if (lsa_hdr.type == htons(LSA_TYPE_EXTERNAL)) { 527 /* 528 * flood on all areas but stub areas and 529 * virtual links 530 */ 531 LIST_FOREACH(area, &oeconf->area_list, entry) { 532 if (area->stub) 533 continue; 534 LIST_FOREACH(iface, &area->iface_list, 535 entry) { 536 noack += lsa_flood(iface, nbr, 537 &lsa_hdr, imsg.data); 538 } 539 } 540 } else if (lsa_hdr.type == htons(LSA_TYPE_LINK)) { 541 /* 542 * Save link-LSA options of neighbor. 543 * This is needed to originate network-LSA. 544 */ 545 if (l - sizeof(lsa_hdr) < sizeof(lsa_link)) 546 fatalx("ospfe_dispatch_rde: " 547 "bad imsg link size"); 548 memcpy(&lsa_link, (char *)imsg.data + 549 sizeof(lsa_hdr), sizeof(lsa_link)); 550 nbr->link_options = lsa_link.opts & 551 htonl(LSA_24_MASK); 552 553 /* 554 * flood on interface only 555 */ 556 noack += lsa_flood(nbr->iface, nbr, 557 &lsa_hdr, imsg.data); 558 } else { 559 /* 560 * flood on all area interfaces on 561 * area 0.0.0.0 include also virtual links. 562 */ 563 LIST_FOREACH(iface, 564 &nbr->iface->area->iface_list, entry) { 565 noack += lsa_flood(iface, nbr, 566 &lsa_hdr, imsg.data); 567 } 568 /* XXX virtual links */ 569 } 570 571 /* remove from ls_req_list */ 572 le = ls_req_list_get(nbr, &lsa_hdr); 573 if (!(nbr->state & NBR_STA_FULL) && le != NULL) { 574 ls_req_list_free(nbr, le); 575 /* 576 * XXX no need to ack requested lsa 577 * the problem is that the RFC is very 578 * unclear about this. 579 */ 580 noack = 1; 581 } 582 583 if (!noack && nbr->iface != NULL && 584 nbr->iface->self != nbr) { 585 if (!(nbr->iface->state & IF_STA_BACKUP) || 586 nbr->iface->dr == nbr) { 587 /* delayed ack */ 588 lhp = lsa_hdr_new(); 589 memcpy(lhp, &lsa_hdr, sizeof(*lhp)); 590 ls_ack_list_add(nbr->iface, lhp); 591 } 592 } 593 594 lsa_cache_put(ref, nbr); 595 break; 596 case IMSG_LS_UPD: 597 case IMSG_LS_SNAP: 598 /* 599 * IMSG_LS_UPD is used in two cases: 600 * 1. as response to ls requests 601 * 2. as response to ls updates where the DB 602 * is newer then the sent LSA 603 * IMSG_LS_SNAP is used in one case: 604 * in EXSTART when the LSA has age MaxAge 605 */ 606 l = imsg.hdr.len - IMSG_HEADER_SIZE; 607 if (l < sizeof(lsa_hdr)) 608 fatalx("ospfe_dispatch_rde: " 609 "bad imsg size"); 610 611 nbr = nbr_find_peerid(imsg.hdr.peerid); 612 if (nbr == NULL) 613 break; 614 615 if (nbr->iface->self == nbr) 616 break; 617 618 if (imsg.hdr.type == IMSG_LS_SNAP && 619 nbr->state != NBR_STA_SNAP) 620 break; 621 622 memcpy(&age, imsg.data, sizeof(age)); 623 ref = lsa_cache_add(imsg.data, l); 624 if (ntohs(age) >= MAX_AGE) 625 /* add to retransmit list */ 626 ls_retrans_list_add(nbr, imsg.data, 0, 0); 627 else 628 ls_retrans_list_add(nbr, imsg.data, 0, 1); 629 630 lsa_cache_put(ref, nbr); 631 break; 632 case IMSG_LS_ACK: 633 /* 634 * IMSG_LS_ACK is used in two cases: 635 * 1. LSA was a duplicate 636 * 2. LS age is MaxAge and there is no current 637 * instance in the DB plus no neighbor in state 638 * Exchange or Loading 639 */ 640 nbr = nbr_find_peerid(imsg.hdr.peerid); 641 if (nbr == NULL) 642 break; 643 644 if (nbr->iface->self == nbr) 645 break; 646 647 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(lsa_hdr)) 648 fatalx("ospfe_dispatch_rde: bad imsg size"); 649 memcpy(&lsa_hdr, imsg.data, sizeof(lsa_hdr)); 650 651 /* for case one check for implied acks */ 652 if (nbr->iface->state & IF_STA_DROTHER) 653 if (ls_retrans_list_del(nbr->iface->self, 654 &lsa_hdr) == 0) 655 break; 656 if (ls_retrans_list_del(nbr, &lsa_hdr) == 0) 657 break; 658 659 /* send a direct acknowledgement */ 660 send_direct_ack(nbr->iface, nbr->addr, imsg.data, 661 imsg.hdr.len - IMSG_HEADER_SIZE); 662 663 break; 664 case IMSG_LS_BADREQ: 665 nbr = nbr_find_peerid(imsg.hdr.peerid); 666 if (nbr == NULL) 667 break; 668 669 if (nbr->iface->self == nbr) 670 fatalx("ospfe_dispatch_rde: " 671 "dummy neighbor got BADREQ"); 672 673 nbr_fsm(nbr, NBR_EVT_BAD_LS_REQ); 674 break; 675 case IMSG_ABR_UP: 676 memcpy(&ar, imsg.data, sizeof(ar)); 677 678 if ((iface = find_vlink(&ar)) != NULL && 679 iface->state == IF_STA_DOWN) 680 if (if_fsm(iface, IF_EVT_UP)) { 681 log_debug("error starting interface %s", 682 iface->name); 683 } 684 break; 685 case IMSG_ABR_DOWN: 686 memcpy(&ar, imsg.data, sizeof(ar)); 687 688 if ((iface = find_vlink(&ar)) != NULL && 689 iface->state == IF_STA_POINTTOPOINT) 690 if (if_fsm(iface, IF_EVT_DOWN)) { 691 log_debug("error stopping interface %s", 692 iface->name); 693 } 694 break; 695 case IMSG_CTL_AREA: 696 case IMSG_CTL_IFACE: 697 case IMSG_CTL_END: 698 case IMSG_CTL_SHOW_DATABASE: 699 case IMSG_CTL_SHOW_DB_EXT: 700 case IMSG_CTL_SHOW_DB_LINK: 701 case IMSG_CTL_SHOW_DB_NET: 702 case IMSG_CTL_SHOW_DB_RTR: 703 case IMSG_CTL_SHOW_DB_INTRA: 704 case IMSG_CTL_SHOW_DB_SELF: 705 case IMSG_CTL_SHOW_DB_SUM: 706 case IMSG_CTL_SHOW_DB_ASBR: 707 case IMSG_CTL_SHOW_RIB: 708 case IMSG_CTL_SHOW_SUM: 709 case IMSG_CTL_SHOW_SUM_AREA: 710 control_imsg_relay(&imsg); 711 break; 712 default: 713 log_debug("ospfe_dispatch_rde: error handling imsg %d", 714 imsg.hdr.type); 715 break; 716 } 717 imsg_free(&imsg); 718 } 719 if (!shut) 720 imsg_event_add(iev); 721 else { 722 /* this pipe is dead, so remove the event handler */ 723 event_del(&iev->ev); 724 event_loopexit(NULL); 725 } 726 } 727 728 struct iface * 729 find_vlink(struct abr_rtr *ar) 730 { 731 struct area *area; 732 struct iface *iface = NULL; 733 734 LIST_FOREACH(area, &oeconf->area_list, entry) 735 LIST_FOREACH(iface, &area->iface_list, entry) 736 if (iface->abr_id.s_addr == ar->abr_id.s_addr && 737 iface->type == IF_TYPE_VIRTUALLINK && 738 iface->area->id.s_addr == ar->area.s_addr) { 739 iface->dst = ar->dst_ip; 740 iface->addr = ar->addr; 741 iface->metric = ar->metric; 742 743 return (iface); 744 } 745 746 return (iface); 747 } 748 749 void 750 orig_rtr_lsa_all(struct area *area) 751 { 752 struct area *a; 753 754 /* 755 * update all router LSA in all areas except area itself, 756 * as this update is already running. 757 */ 758 LIST_FOREACH(a, &oeconf->area_list, entry) 759 if (a != area) 760 orig_rtr_lsa(a); 761 } 762 763 void 764 orig_rtr_lsa(struct area *area) 765 { 766 struct lsa_hdr lsa_hdr; 767 struct lsa_rtr lsa_rtr; 768 struct lsa_rtr_link rtr_link; 769 struct iface *iface; 770 struct ibuf *buf; 771 struct nbr *nbr, *self = NULL; 772 u_int32_t flags; 773 u_int16_t chksum; 774 u_int8_t border, virtual = 0; 775 776 log_debug("orig_rtr_lsa: area %s", inet_ntoa(area->id)); 777 778 /* XXX IBUF_READ_SIZE */ 779 if ((buf = ibuf_dynamic(sizeof(lsa_hdr), IBUF_READ_SIZE)) == NULL) 780 fatal("orig_rtr_lsa"); 781 782 /* reserve space for LSA header and LSA Router header */ 783 if (ibuf_add_zero(buf, sizeof(lsa_hdr)) == -1) 784 fatal("orig_rtr_lsa: ibuf_add_zero failed"); 785 786 if (ibuf_add_zero(buf, sizeof(lsa_rtr)) == -1) 787 fatal("orig_rtr_lsa: ibuf_add_zero failed"); 788 789 /* links */ 790 LIST_FOREACH(iface, &area->iface_list, entry) { 791 if (self == NULL && iface->self != NULL) 792 self = iface->self; 793 794 bzero(&rtr_link, sizeof(rtr_link)); 795 796 switch (iface->type) { 797 case IF_TYPE_POINTOPOINT: 798 LIST_FOREACH(nbr, &iface->nbr_list, entry) 799 if (nbr != iface->self && 800 nbr->state & NBR_STA_FULL) 801 break; 802 if (nbr && iface->state & IF_STA_POINTTOPOINT) { 803 log_debug("orig_rtr_lsa: point-to-point, " 804 "interface %s", iface->name); 805 rtr_link.type = LINK_TYPE_POINTTOPOINT; 806 if (iface->dependon[0] != '\0' && 807 iface->depend_ok == 0) 808 rtr_link.metric = MAX_METRIC; 809 else 810 rtr_link.metric = htons(iface->metric); 811 rtr_link.iface_id = htonl(iface->ifindex); 812 rtr_link.nbr_iface_id = htonl(nbr->iface_id); 813 rtr_link.nbr_rtr_id = nbr->id.s_addr; 814 if (ibuf_add(buf, &rtr_link, sizeof(rtr_link))) 815 fatalx("orig_rtr_lsa: ibuf_add failed"); 816 } 817 continue; 818 case IF_TYPE_BROADCAST: 819 case IF_TYPE_NBMA: 820 if ((iface->state & IF_STA_MULTI)) { 821 if (iface->dr == iface->self) { 822 LIST_FOREACH(nbr, &iface->nbr_list, 823 entry) 824 if (nbr != iface->self && 825 nbr->state & NBR_STA_FULL) 826 break; 827 } else 828 nbr = iface->dr; 829 830 if (nbr && nbr->state & NBR_STA_FULL) { 831 log_debug("orig_rtr_lsa: transit net, " 832 "interface %s", iface->name); 833 834 rtr_link.type = LINK_TYPE_TRANSIT_NET; 835 if (iface->dependon[0] != '\0' && 836 iface->depend_ok == 0) 837 rtr_link.metric = MAX_METRIC; 838 else 839 rtr_link.metric = 840 htons(iface->metric); 841 rtr_link.iface_id = htonl(iface->ifindex); 842 rtr_link.nbr_iface_id = htonl(iface->dr->iface_id); 843 rtr_link.nbr_rtr_id = iface->dr->id.s_addr; 844 if (ibuf_add(buf, &rtr_link, 845 sizeof(rtr_link))) 846 fatalx("orig_rtr_lsa: " 847 "ibuf_add failed"); 848 break; 849 } 850 } 851 break; 852 #if 0 /* TODO virtualllink/pointtomulti */ 853 case IF_TYPE_VIRTUALLINK: 854 LIST_FOREACH(nbr, &iface->nbr_list, entry) { 855 if (nbr != iface->self && 856 nbr->state & NBR_STA_FULL) 857 break; 858 } 859 if (nbr) { 860 rtr_link.id = nbr->id.s_addr; 861 //XXX rtr_link.data = iface->addr.s_addr; 862 rtr_link.type = LINK_TYPE_VIRTUAL; 863 /* RFC 3137: stub router support */ 864 if (oeconf->flags & OSPFD_FLAG_STUB_ROUTER || 865 oe_nofib) 866 rtr_link.metric = 0xffff; 867 else 868 rtr_link.metric = htons(iface->metric); 869 virtual = 1; 870 if (ibuf_add(buf, &rtr_link, sizeof(rtr_link))) 871 fatalx("orig_rtr_lsa: ibuf_add failed"); 872 873 log_debug("orig_rtr_lsa: virtual link, " 874 "interface %s", iface->name); 875 } 876 continue; 877 case IF_TYPE_POINTOMULTIPOINT: 878 log_debug("orig_rtr_lsa: stub net, " 879 "interface %s", iface->name); 880 //XXX rtr_link.id = iface->addr.s_addr; 881 rtr_link.data = 0xffffffff; 882 rtr_link.type = LINK_TYPE_STUB_NET; 883 rtr_link.metric = htons(iface->metric); 884 if (ibuf_add(buf, &rtr_link, sizeof(rtr_link))) 885 fatalx("orig_rtr_lsa: ibuf_add failed"); 886 887 LIST_FOREACH(nbr, &iface->nbr_list, entry) { 888 if (nbr != iface->self && 889 nbr->state & NBR_STA_FULL) { 890 bzero(&rtr_link, sizeof(rtr_link)); 891 log_debug("orig_rtr_lsa: " 892 "point-to-multipoint, interface %s", 893 iface->name); 894 //XXX rtr_link.id = nbr->addr.s_addr; 895 //XXX rtr_link.data = iface->addr.s_addr; 896 rtr_link.type = LINK_TYPE_POINTTOPOINT; 897 /* RFC 3137: stub router support */ 898 if (oe_nofib || oeconf->flags & 899 OSPFD_FLAG_STUB_ROUTER) 900 rtr_link.metric = MAX_METRIC; 901 else if (iface->dependon[0] != '\0' && 902 iface->dependon_ok == 0) 903 rtr_link.metric = MAX_METRIC; 904 else 905 rtr_link.metric = 906 htons(iface->metric); 907 if (ibuf_add(buf, &rtr_link, 908 sizeof(rtr_link))) 909 fatalx("orig_rtr_lsa: " 910 "ibuf_add failed"); 911 } 912 } 913 continue; 914 #endif /* TODO virtualllink/pointtomulti */ 915 default: 916 fatalx("orig_rtr_lsa: unknown interface type"); 917 } 918 } 919 920 /* LSA router header */ 921 lsa_rtr.opts = 0; 922 flags = 0; 923 924 /* 925 * Set the E bit as soon as an as-ext lsa may be redistributed, only 926 * setting it in case we redistribute something is not worth the fuss. 927 */ 928 if (oeconf->redistribute && !area->stub) 929 flags |= OSPF_RTR_E; 930 931 border = (area_border_router(oeconf) != 0); 932 if (border != oeconf->border) { 933 oeconf->border = border; 934 orig_rtr_lsa_all(area); 935 } 936 937 if (oeconf->border) 938 flags |= OSPF_RTR_B; 939 /* TODO set V flag if a active virtual link ends here and the 940 * area is the transit area for this link. */ 941 if (virtual) 942 flags |= OSPF_RTR_V; 943 944 LSA_24_SETLO(lsa_rtr.opts, area_ospf_options(area)); 945 LSA_24_SETHI(lsa_rtr.opts, flags); 946 lsa_rtr.opts = htonl(lsa_rtr.opts); 947 if (ibuf_set(buf, sizeof(lsa_hdr), &lsa_rtr, sizeof(lsa_rtr)) == -1) 948 fatal("orig_rtr_lsa: ibuf_set failed"); 949 950 /* LSA header */ 951 lsa_hdr.age = htons(DEFAULT_AGE); 952 lsa_hdr.type = htons(LSA_TYPE_ROUTER); 953 /* XXX needs to be fixed if multiple router-lsa need to be announced */ 954 lsa_hdr.ls_id = 0; 955 lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr; 956 lsa_hdr.seq_num = htonl(INIT_SEQ_NUM); 957 lsa_hdr.len = htons(ibuf_size(buf)); 958 lsa_hdr.ls_chksum = 0; /* updated later */ 959 if (ibuf_set(buf, 0, &lsa_hdr, sizeof(lsa_hdr)) == -1) 960 fatal("orig_rtr_lsa: ibuf_set failed"); 961 962 chksum = iso_cksum(ibuf_data(buf), ibuf_size(buf), LS_CKSUM_OFFSET); 963 if (ibuf_set_n16(buf, LS_CKSUM_OFFSET, chksum) == -1) 964 fatal("orig_rtr_lsa: ibuf_set_n16 failed"); 965 966 if (self) 967 imsg_compose_event(iev_rde, IMSG_LS_UPD, self->peerid, 0, 968 -1, ibuf_data(buf), ibuf_size(buf)); 969 else 970 log_warnx("orig_rtr_lsa: empty area %s", 971 inet_ntoa(area->id)); 972 973 ibuf_free(buf); 974 } 975 976 void 977 orig_net_lsa(struct iface *iface) 978 { 979 struct lsa_hdr lsa_hdr; 980 struct nbr *nbr; 981 struct ibuf *buf; 982 struct lsa_net lsa_net; 983 int num_rtr = 0; 984 u_int16_t chksum; 985 986 /* XXX IBUF_READ_SIZE */ 987 if ((buf = ibuf_dynamic(sizeof(lsa_hdr), IBUF_READ_SIZE)) == NULL) 988 fatal("orig_net_lsa"); 989 990 /* reserve space for LSA header and options field */ 991 if (ibuf_add_zero(buf, sizeof(lsa_hdr) + sizeof(lsa_net)) == -1) 992 fatal("orig_net_lsa: ibuf_add_zero failed"); 993 994 lsa_net.opts = 0; 995 /* fully adjacent neighbors + self */ 996 LIST_FOREACH(nbr, &iface->nbr_list, entry) 997 if (nbr->state & NBR_STA_FULL) { 998 if (ibuf_add(buf, &nbr->id, sizeof(nbr->id))) 999 fatal("orig_net_lsa: ibuf_add failed"); 1000 lsa_net.opts |= nbr->link_options; 1001 num_rtr++; 1002 } 1003 1004 if (num_rtr == 1) { 1005 /* non transit net therefore no need to generate a net lsa */ 1006 ibuf_free(buf); 1007 return; 1008 } 1009 1010 /* LSA header */ 1011 if (iface->state & IF_STA_DR) 1012 lsa_hdr.age = htons(DEFAULT_AGE); 1013 else 1014 lsa_hdr.age = htons(MAX_AGE); 1015 1016 lsa_hdr.type = htons(LSA_TYPE_NETWORK); 1017 /* for network LSAs, the link state ID equals the interface ID */ 1018 lsa_hdr.ls_id = htonl(iface->ifindex); 1019 lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr; 1020 lsa_hdr.seq_num = htonl(INIT_SEQ_NUM); 1021 lsa_hdr.len = htons(ibuf_size(buf)); 1022 lsa_hdr.ls_chksum = 0; /* updated later */ 1023 if (ibuf_set(buf, 0, &lsa_hdr, sizeof(lsa_hdr)) == -1) 1024 fatal("orig_net_lsa: ibuf_set failed"); 1025 1026 lsa_net.opts &= lsa_net.opts & htonl(LSA_24_MASK); 1027 if (ibuf_set(buf, sizeof(lsa_hdr), &lsa_net, sizeof(lsa_net)) == -1) 1028 fatal("orig_net_lsa: ibuf_set failed"); 1029 1030 chksum = iso_cksum(ibuf_data(buf), ibuf_size(buf), LS_CKSUM_OFFSET); 1031 if (ibuf_set_n16(buf, LS_CKSUM_OFFSET, chksum) == -1) 1032 fatal("orig_net_lsa: ibuf_set_n16 failed"); 1033 1034 imsg_compose_event(iev_rde, IMSG_LS_UPD, iface->self->peerid, 0, 1035 -1, ibuf_data(buf), ibuf_size(buf)); 1036 1037 ibuf_free(buf); 1038 } 1039 1040 void 1041 orig_link_lsa(struct iface *iface) 1042 { 1043 struct lsa_hdr lsa_hdr; 1044 struct lsa_link lsa_link; 1045 struct lsa_prefix lsa_prefix; 1046 struct ibuf *buf; 1047 struct iface_addr *ia; 1048 struct in6_addr prefix; 1049 unsigned int num_prefix = 0; 1050 u_int16_t chksum; 1051 u_int32_t options; 1052 1053 log_debug("orig_link_lsa: interface %s", iface->name); 1054 1055 switch (iface->type) { 1056 case IF_TYPE_VIRTUALLINK: /* forbidden by rfc5340 */ 1057 return; 1058 case IF_TYPE_BROADCAST: 1059 case IF_TYPE_NBMA: 1060 if ((iface->state & IF_STA_MULTI) == 0) 1061 return; 1062 break; 1063 case IF_TYPE_POINTOPOINT: 1064 case IF_TYPE_POINTOMULTIPOINT: 1065 if ((iface->state & IF_STA_POINTTOPOINT) == 0) 1066 return; 1067 break; 1068 default: 1069 fatalx("orig_link_lsa: unknown interface type"); 1070 } 1071 1072 /* XXX IBUF_READ_SIZE */ 1073 if ((buf = ibuf_dynamic(sizeof(lsa_hdr) + sizeof(lsa_link), 1074 IBUF_READ_SIZE)) == NULL) 1075 fatal("orig_link_lsa"); 1076 1077 /* reserve space for LSA header and LSA link header */ 1078 if (ibuf_add_zero(buf, sizeof(lsa_hdr) + sizeof(lsa_link)) == -1) 1079 fatal("orig_link_lsa: ibuf_add_zero failed"); 1080 1081 /* link-local address, and all prefixes configured on interface */ 1082 TAILQ_FOREACH(ia, &iface->ifa_list, entry) { 1083 if (IN6_IS_ADDR_LINKLOCAL(&ia->addr)) { 1084 log_debug("orig_link_lsa: link local address %s", 1085 log_in6addr(&ia->addr)); 1086 lsa_link.lladdr = ia->addr; 1087 continue; 1088 } 1089 1090 lsa_prefix.prefixlen = ia->prefixlen; 1091 lsa_prefix.options = 0; 1092 lsa_prefix.metric = 0; 1093 inet6applymask(&prefix, &ia->addr, ia->prefixlen); 1094 log_debug("orig_link_lsa: prefix %s", log_in6addr(&prefix)); 1095 if (ibuf_add(buf, &lsa_prefix, sizeof(lsa_prefix))) 1096 fatal("orig_link_lsa: ibuf_add failed"); 1097 if (ibuf_add(buf, &prefix.s6_addr[0], 1098 LSA_PREFIXSIZE(ia->prefixlen))) 1099 fatal("orig_link_lsa: ibuf_add failed"); 1100 num_prefix++; 1101 } 1102 1103 /* LSA link header (lladdr has already been filled in above) */ 1104 LSA_24_SETHI(lsa_link.opts, iface->priority); 1105 options = area_ospf_options(iface->area); 1106 LSA_24_SETLO(lsa_link.opts, options); 1107 lsa_link.opts = htonl(lsa_link.opts); 1108 lsa_link.numprefix = htonl(num_prefix); 1109 if (ibuf_set(buf, sizeof(lsa_hdr), &lsa_link, sizeof(lsa_link)) == -1) 1110 fatal("orig_link_lsa: ibuf_set failed"); 1111 1112 /* LSA header */ 1113 lsa_hdr.age = htons(DEFAULT_AGE); 1114 lsa_hdr.type = htons(LSA_TYPE_LINK); 1115 /* for link LSAs, the link state ID equals the interface ID */ 1116 lsa_hdr.ls_id = htonl(iface->ifindex); 1117 lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr; 1118 lsa_hdr.seq_num = htonl(INIT_SEQ_NUM); 1119 lsa_hdr.len = htons(ibuf_size(buf)); 1120 lsa_hdr.ls_chksum = 0; /* updated later */ 1121 if (ibuf_set(buf, 0, &lsa_hdr, sizeof(lsa_hdr)) == -1) 1122 fatal("orig_link_lsa: ibuf_set failed"); 1123 1124 chksum = iso_cksum(ibuf_data(buf), ibuf_size(buf), LS_CKSUM_OFFSET); 1125 if (ibuf_set_n16(buf, LS_CKSUM_OFFSET, chksum) == -1) 1126 fatal("orig_link_lsa: ibuf_set_n16 failed"); 1127 1128 imsg_compose_event(iev_rde, IMSG_LS_UPD, iface->self->peerid, 0, 1129 -1, ibuf_data(buf), ibuf_size(buf)); 1130 1131 ibuf_free(buf); 1132 } 1133 1134 u_int32_t 1135 ospfe_router_id(void) 1136 { 1137 return (oeconf->rtr_id.s_addr); 1138 } 1139 1140 void 1141 ospfe_fib_update(int type) 1142 { 1143 int old = oe_nofib; 1144 1145 if (type == IMSG_CTL_FIB_COUPLE) 1146 oe_nofib = 0; 1147 if (type == IMSG_CTL_FIB_DECOUPLE) 1148 oe_nofib = 1; 1149 if (old != oe_nofib) 1150 orig_rtr_lsa_all(NULL); 1151 } 1152 1153 void 1154 ospfe_iface_ctl(struct ctl_conn *c, unsigned int idx) 1155 { 1156 struct area *area; 1157 struct iface *iface; 1158 struct ctl_iface *ictl; 1159 1160 LIST_FOREACH(area, &oeconf->area_list, entry) 1161 LIST_FOREACH(iface, &area->iface_list, entry) 1162 if (idx == 0 || idx == iface->ifindex) { 1163 ictl = if_to_ctl(iface); 1164 imsg_compose_event(&c->iev, 1165 IMSG_CTL_SHOW_INTERFACE, 0, 0, -1, 1166 ictl, sizeof(struct ctl_iface)); 1167 } 1168 } 1169 1170 void 1171 ospfe_nbr_ctl(struct ctl_conn *c) 1172 { 1173 struct area *area; 1174 struct iface *iface; 1175 struct nbr *nbr; 1176 struct ctl_nbr *nctl; 1177 1178 LIST_FOREACH(area, &oeconf->area_list, entry) 1179 LIST_FOREACH(iface, &area->iface_list, entry) 1180 LIST_FOREACH(nbr, &iface->nbr_list, entry) { 1181 if (iface->self != nbr) { 1182 nctl = nbr_to_ctl(nbr); 1183 imsg_compose_event(&c->iev, 1184 IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl, 1185 sizeof(struct ctl_nbr)); 1186 } 1187 } 1188 1189 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0); 1190 } 1191 1192 void 1193 ospfe_demote_area(struct area *area, int active) 1194 { 1195 struct demote_msg dmsg; 1196 1197 if (ospfd_process != PROC_OSPF_ENGINE || 1198 area->demote_group[0] == '\0') 1199 return; 1200 1201 bzero(&dmsg, sizeof(dmsg)); 1202 strlcpy(dmsg.demote_group, area->demote_group, 1203 sizeof(dmsg.demote_group)); 1204 dmsg.level = area->demote_level; 1205 if (active) 1206 dmsg.level = -dmsg.level; 1207 1208 ospfe_imsg_compose_parent(IMSG_DEMOTE, 0, &dmsg, sizeof(dmsg)); 1209 } 1210 1211 void 1212 ospfe_demote_iface(struct iface *iface, int active) 1213 { 1214 struct demote_msg dmsg; 1215 1216 if (ospfd_process != PROC_OSPF_ENGINE || 1217 iface->demote_group[0] == '\0') 1218 return; 1219 1220 bzero(&dmsg, sizeof(dmsg)); 1221 strlcpy(dmsg.demote_group, iface->demote_group, 1222 sizeof(dmsg.demote_group)); 1223 if (active) 1224 dmsg.level = -1; 1225 else 1226 dmsg.level = 1; 1227 1228 log_warnx("ospfe_demote_iface: group %s level %d", dmsg.demote_group, 1229 dmsg.level); 1230 1231 ospfe_imsg_compose_parent(IMSG_DEMOTE, 0, &dmsg, sizeof(dmsg)); 1232 } 1233