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