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