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