1 /* $OpenBSD: ospfe.c,v 1.64 2009/04/07 14:57:33 reyk 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 imsgbuf *ibuf_main; 53 struct imsgbuf *ibuf_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_recvbuf(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 ((ibuf_rde = malloc(sizeof(struct imsgbuf))) == NULL || 148 (ibuf_main = malloc(sizeof(struct imsgbuf))) == NULL) 149 fatal(NULL); 150 imsg_init(ibuf_rde, pipe_ospfe2rde[0], ospfe_dispatch_rde); 151 imsg_init(ibuf_main, pipe_parent2ospfe[1], ospfe_dispatch_main); 152 153 /* setup event handler */ 154 ibuf_rde->events = EV_READ; 155 event_set(&ibuf_rde->ev, ibuf_rde->fd, ibuf_rde->events, 156 ibuf_rde->handler, ibuf_rde); 157 event_add(&ibuf_rde->ev, NULL); 158 159 ibuf_main->events = EV_READ; 160 event_set(&ibuf_main->ev, ibuf_main->fd, ibuf_main->events, 161 ibuf_main->handler, ibuf_main); 162 event_add(&ibuf_main->ev, NULL); 163 164 event_set(&oeconf->ev, oeconf->ospf_socket, EV_READ|EV_PERSIST, 165 recv_packet, oeconf); 166 event_add(&oeconf->ev, NULL); 167 168 /* remove unneeded config stuff */ 169 while ((r = SIMPLEQ_FIRST(&oeconf->redist_list)) != NULL) { 170 SIMPLEQ_REMOVE_HEAD(&oeconf->redist_list, entry); 171 free(r); 172 } 173 LIST_FOREACH(area, &oeconf->area_list, entry) { 174 while ((r = SIMPLEQ_FIRST(&area->redist_list)) != NULL) { 175 SIMPLEQ_REMOVE_HEAD(&area->redist_list, entry); 176 free(r); 177 } 178 } 179 180 /* listen on ospfd control socket */ 181 TAILQ_INIT(&ctl_conns); 182 control_listen(); 183 184 if ((pkt_ptr = calloc(1, READ_BUF_SIZE)) == NULL) 185 fatal("ospfe"); 186 187 /* start interfaces */ 188 LIST_FOREACH(area, &oeconf->area_list, entry) { 189 ospfe_demote_area(area, 0); 190 LIST_FOREACH(iface, &area->iface_list, entry) { 191 if_init(xconf, iface); 192 if (if_fsm(iface, IF_EVT_UP)) { 193 log_debug("error starting interface %s", 194 iface->name); 195 } 196 } 197 } 198 199 event_dispatch(); 200 201 ospfe_shutdown(); 202 /* NOTREACHED */ 203 return (0); 204 } 205 206 void 207 ospfe_shutdown(void) 208 { 209 struct area *area; 210 struct iface *iface; 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 msgbuf_write(&ibuf_rde->w); 228 msgbuf_clear(&ibuf_rde->w); 229 free(ibuf_rde); 230 msgbuf_write(&ibuf_main->w); 231 msgbuf_clear(&ibuf_main->w); 232 free(ibuf_main); 233 free(oeconf); 234 free(pkt_ptr); 235 236 log_info("ospf engine exiting"); 237 _exit(0); 238 } 239 240 /* imesg */ 241 int 242 ospfe_imsg_compose_parent(int type, pid_t pid, void *data, u_int16_t datalen) 243 { 244 return (imsg_compose(ibuf_main, type, 0, pid, data, datalen)); 245 } 246 247 int 248 ospfe_imsg_compose_rde(int type, u_int32_t peerid, pid_t pid, 249 void *data, u_int16_t datalen) 250 { 251 return (imsg_compose(ibuf_rde, type, peerid, pid, data, datalen)); 252 } 253 254 /* ARGSUSED */ 255 void 256 ospfe_dispatch_main(int fd, short event, void *bula) 257 { 258 static struct area *narea; 259 static struct iface *niface; 260 struct imsg imsg; 261 struct imsgbuf *ibuf = bula; 262 struct area *area = NULL; 263 struct iface *iface = NULL; 264 struct kif *kif; 265 struct auth_md md; 266 int n, link_ok, stub_changed, shut = 0; 267 268 switch (event) { 269 case EV_READ: 270 if ((n = imsg_read(ibuf)) == -1) 271 fatal("imsg_read error"); 272 if (n == 0) /* connection closed */ 273 shut = 1; 274 break; 275 case EV_WRITE: 276 if (msgbuf_write(&ibuf->w) == -1) 277 fatal("msgbuf_write"); 278 imsg_event_add(ibuf); 279 return; 280 default: 281 fatalx("unknown event"); 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(ibuf); 390 else { 391 /* this pipe is dead, so remove the event handler */ 392 event_del(&ibuf->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 imsgbuf *ibuf = bula; 403 struct nbr *nbr; 404 struct lsa_hdr *lhp; 405 struct lsa_ref *ref; 406 struct area *area; 407 struct iface *iface; 408 struct lsa_entry *le; 409 struct imsg imsg; 410 struct abr_rtr ar; 411 int n, noack = 0, shut = 0; 412 u_int16_t l, age; 413 414 switch (event) { 415 case EV_READ: 416 if ((n = imsg_read(ibuf)) == -1) 417 fatal("imsg_read error"); 418 if (n == 0) /* connection closed */ 419 shut = 1; 420 break; 421 case EV_WRITE: 422 if (msgbuf_write(&ibuf->w) == -1) 423 fatal("msgbuf_write"); 424 imsg_event_add(ibuf); 425 return; 426 default: 427 fatalx("unknown event"); 428 } 429 430 for (;;) { 431 if ((n = imsg_get(ibuf, &imsg)) == -1) 432 fatal("ospfe_dispatch_rde: imsg_read error"); 433 if (n == 0) 434 break; 435 436 switch (imsg.hdr.type) { 437 case IMSG_DD: 438 nbr = nbr_find_peerid(imsg.hdr.peerid); 439 if (nbr == NULL) 440 break; 441 442 /* 443 * Ignore imsg when in the wrong state because a 444 * NBR_EVT_SEQ_NUM_MIS may have been issued in between. 445 * Luckily regetting the DB snapshot acts as a barrier 446 * for both state and process synchronisation. 447 */ 448 if ((nbr->state & NBR_STA_FLOOD) == 0) 449 break; 450 451 /* put these on my ls_req_list for retrieval */ 452 lhp = lsa_hdr_new(); 453 memcpy(lhp, imsg.data, sizeof(*lhp)); 454 ls_req_list_add(nbr, lhp); 455 break; 456 case IMSG_DD_END: 457 nbr = nbr_find_peerid(imsg.hdr.peerid); 458 if (nbr == NULL) 459 break; 460 461 /* see above */ 462 if ((nbr->state & NBR_STA_FLOOD) == 0) 463 break; 464 465 nbr->dd_pending--; 466 if (nbr->dd_pending == 0 && nbr->state & NBR_STA_LOAD) { 467 if (ls_req_list_empty(nbr)) 468 nbr_fsm(nbr, NBR_EVT_LOAD_DONE); 469 else 470 start_ls_req_tx_timer(nbr); 471 } 472 break; 473 case IMSG_DD_BADLSA: 474 nbr = nbr_find_peerid(imsg.hdr.peerid); 475 if (nbr == NULL) 476 break; 477 478 if (nbr->iface->self == nbr) 479 fatalx("ospfe_dispatch_rde: " 480 "dummy neighbor got BADREQ"); 481 482 nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); 483 break; 484 case IMSG_DB_SNAPSHOT: 485 nbr = nbr_find_peerid(imsg.hdr.peerid); 486 if (nbr == NULL) 487 break; 488 489 /* add LSA header to the neighbor db_sum_list */ 490 lhp = lsa_hdr_new(); 491 memcpy(lhp, imsg.data, sizeof(*lhp)); 492 db_sum_list_add(nbr, lhp); 493 break; 494 case IMSG_DB_END: 495 nbr = nbr_find_peerid(imsg.hdr.peerid); 496 if (nbr == NULL) 497 break; 498 499 /* snapshot done, start tx of dd packets */ 500 nbr_fsm(nbr, NBR_EVT_SNAP_DONE); 501 break; 502 case IMSG_LS_FLOOD: 503 nbr = nbr_find_peerid(imsg.hdr.peerid); 504 if (nbr == NULL) 505 break; 506 507 l = imsg.hdr.len - IMSG_HEADER_SIZE; 508 if (l < sizeof(lsa_hdr)) 509 fatalx("ospfe_dispatch_rde: " 510 "bad imsg size"); 511 memcpy(&lsa_hdr, imsg.data, sizeof(lsa_hdr)); 512 513 ref = lsa_cache_add(imsg.data, l); 514 515 if (lsa_hdr.type == LSA_TYPE_EXTERNAL) { 516 /* 517 * flood on all areas but stub areas and 518 * virtual links 519 */ 520 LIST_FOREACH(area, &oeconf->area_list, entry) { 521 if (area->stub) 522 continue; 523 LIST_FOREACH(iface, &area->iface_list, 524 entry) { 525 noack += lsa_flood(iface, nbr, 526 &lsa_hdr, imsg.data); 527 } 528 } 529 } else { 530 /* 531 * flood on all area interfaces on 532 * area 0.0.0.0 include also virtual links. 533 */ 534 area = nbr->iface->area; 535 LIST_FOREACH(iface, &area->iface_list, entry) { 536 noack += lsa_flood(iface, nbr, 537 &lsa_hdr, imsg.data); 538 } 539 /* XXX virtual links */ 540 } 541 542 /* remove from ls_req_list */ 543 le = ls_req_list_get(nbr, &lsa_hdr); 544 if (!(nbr->state & NBR_STA_FULL) && le != NULL) { 545 ls_req_list_free(nbr, le); 546 /* 547 * XXX no need to ack requested lsa 548 * the problem is that the RFC is very 549 * unclear about this. 550 */ 551 noack = 1; 552 } 553 554 if (!noack && nbr->iface != NULL && 555 nbr->iface->self != nbr) { 556 if (!(nbr->iface->state & IF_STA_BACKUP) || 557 nbr->iface->dr == nbr) { 558 /* delayed ack */ 559 lhp = lsa_hdr_new(); 560 memcpy(lhp, &lsa_hdr, sizeof(*lhp)); 561 ls_ack_list_add(nbr->iface, lhp); 562 } 563 } 564 565 lsa_cache_put(ref, nbr); 566 break; 567 case IMSG_LS_UPD: 568 /* 569 * IMSG_LS_UPD is used in three cases: 570 * 1. as response to ls requests 571 * 2. as response to ls updates where the DB 572 * is newer then the sent LSA 573 * 3. in EXSTART when the LSA has age MaxAge 574 */ 575 l = imsg.hdr.len - IMSG_HEADER_SIZE; 576 if (l < sizeof(lsa_hdr)) 577 fatalx("ospfe_dispatch_rde: " 578 "bad imsg size"); 579 580 nbr = nbr_find_peerid(imsg.hdr.peerid); 581 if (nbr == NULL) 582 break; 583 584 if (nbr->iface->self == nbr) 585 break; 586 587 memcpy(&age, imsg.data, sizeof(age)); 588 ref = lsa_cache_add(imsg.data, l); 589 if (ntohs(age) >= MAX_AGE) 590 /* add to retransmit list */ 591 ls_retrans_list_add(nbr, imsg.data, 0, 0); 592 else 593 ls_retrans_list_add(nbr, imsg.data, 0, 1); 594 595 lsa_cache_put(ref, nbr); 596 break; 597 case IMSG_LS_ACK: 598 /* 599 * IMSG_LS_ACK is used in two cases: 600 * 1. LSA was a duplicate 601 * 2. LS age is MaxAge and there is no current 602 * instance in the DB plus no neighbor in state 603 * Exchange or Loading 604 */ 605 nbr = nbr_find_peerid(imsg.hdr.peerid); 606 if (nbr == NULL) 607 break; 608 609 if (nbr->iface->self == nbr) 610 break; 611 612 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(lsa_hdr)) 613 fatalx("ospfe_dispatch_rde: bad imsg size"); 614 memcpy(&lsa_hdr, imsg.data, sizeof(lsa_hdr)); 615 616 /* for case one check for implied acks */ 617 if (nbr->iface->state & IF_STA_DROTHER) 618 if (ls_retrans_list_del(nbr->iface->self, 619 &lsa_hdr) == 0) 620 break; 621 if (ls_retrans_list_del(nbr, &lsa_hdr) == 0) 622 break; 623 624 /* send a direct acknowledgement */ 625 send_ls_ack(nbr->iface, nbr->addr, imsg.data, 626 imsg.hdr.len - IMSG_HEADER_SIZE); 627 628 break; 629 case IMSG_LS_BADREQ: 630 nbr = nbr_find_peerid(imsg.hdr.peerid); 631 if (nbr == NULL) 632 break; 633 634 if (nbr->iface->self == nbr) 635 fatalx("ospfe_dispatch_rde: " 636 "dummy neighbor got BADREQ"); 637 638 nbr_fsm(nbr, NBR_EVT_BAD_LS_REQ); 639 break; 640 case IMSG_ABR_UP: 641 memcpy(&ar, imsg.data, sizeof(ar)); 642 643 if ((iface = find_vlink(&ar)) != NULL && 644 iface->state == IF_STA_DOWN) 645 if (if_fsm(iface, IF_EVT_UP)) { 646 log_debug("error starting interface %s", 647 iface->name); 648 } 649 break; 650 case IMSG_ABR_DOWN: 651 memcpy(&ar, imsg.data, sizeof(ar)); 652 653 if ((iface = find_vlink(&ar)) != NULL && 654 iface->state == IF_STA_POINTTOPOINT) 655 if (if_fsm(iface, IF_EVT_DOWN)) { 656 log_debug("error stopping interface %s", 657 iface->name); 658 } 659 break; 660 case IMSG_CTL_AREA: 661 case IMSG_CTL_END: 662 case IMSG_CTL_SHOW_DATABASE: 663 case IMSG_CTL_SHOW_DB_EXT: 664 case IMSG_CTL_SHOW_DB_NET: 665 case IMSG_CTL_SHOW_DB_RTR: 666 case IMSG_CTL_SHOW_DB_SELF: 667 case IMSG_CTL_SHOW_DB_SUM: 668 case IMSG_CTL_SHOW_DB_ASBR: 669 case IMSG_CTL_SHOW_RIB: 670 case IMSG_CTL_SHOW_SUM: 671 case IMSG_CTL_SHOW_SUM_AREA: 672 control_imsg_relay(&imsg); 673 break; 674 default: 675 log_debug("ospfe_dispatch_rde: error handling imsg %d", 676 imsg.hdr.type); 677 break; 678 } 679 imsg_free(&imsg); 680 } 681 if (!shut) 682 imsg_event_add(ibuf); 683 else { 684 /* this pipe is dead, so remove the event handler */ 685 event_del(&ibuf->ev); 686 event_loopexit(NULL); 687 } 688 } 689 690 struct iface * 691 find_vlink(struct abr_rtr *ar) 692 { 693 struct area *area; 694 struct iface *iface = NULL; 695 696 LIST_FOREACH(area, &oeconf->area_list, entry) 697 LIST_FOREACH(iface, &area->iface_list, entry) 698 if (iface->abr_id.s_addr == ar->abr_id.s_addr && 699 iface->type == IF_TYPE_VIRTUALLINK && 700 iface->area->id.s_addr == ar->area.s_addr) { 701 iface->dst.s_addr = ar->dst_ip.s_addr; 702 iface->addr.s_addr = ar->addr.s_addr; 703 iface->metric = ar->metric; 704 705 return (iface); 706 } 707 708 return (iface); 709 } 710 711 void 712 orig_rtr_lsa_all(struct area *area) 713 { 714 struct area *a; 715 716 /* 717 * update all router LSA in all areas except area itself, 718 * as this update is already running. 719 */ 720 LIST_FOREACH(a, &oeconf->area_list, entry) 721 if (a != area) 722 orig_rtr_lsa(a); 723 } 724 725 void 726 orig_rtr_lsa(struct area *area) 727 { 728 struct lsa_hdr lsa_hdr; 729 struct lsa_rtr lsa_rtr; 730 struct lsa_rtr_link rtr_link; 731 struct iface *iface; 732 struct buf *buf; 733 struct nbr *nbr, *self = NULL; 734 u_int16_t num_links = 0; 735 u_int16_t chksum; 736 u_int8_t border, virtual = 0; 737 738 log_debug("orig_rtr_lsa: area %s", inet_ntoa(area->id)); 739 740 /* XXX READ_BUF_SIZE */ 741 if ((buf = buf_dynamic(sizeof(lsa_hdr), READ_BUF_SIZE)) == NULL) 742 fatal("orig_rtr_lsa"); 743 744 /* reserve space for LSA header and LSA Router header */ 745 if (buf_reserve(buf, sizeof(lsa_hdr)) == NULL) 746 fatal("orig_rtr_lsa: buf_reserve failed"); 747 748 if (buf_reserve(buf, sizeof(lsa_rtr)) == NULL) 749 fatal("orig_rtr_lsa: buf_reserve failed"); 750 751 /* links */ 752 LIST_FOREACH(iface, &area->iface_list, entry) { 753 if (self == NULL && iface->self != NULL) 754 self = iface->self; 755 756 bzero(&rtr_link, sizeof(rtr_link)); 757 758 if (iface->state & IF_STA_LOOPBACK) { 759 rtr_link.id = iface->addr.s_addr; 760 rtr_link.data = 0xffffffff; 761 rtr_link.type = LINK_TYPE_STUB_NET; 762 rtr_link.metric = htons(iface->metric); 763 num_links++; 764 if (buf_add(buf, &rtr_link, sizeof(rtr_link))) 765 fatalx("orig_rtr_lsa: buf_add failed"); 766 continue; 767 } 768 769 switch (iface->type) { 770 case IF_TYPE_POINTOPOINT: 771 LIST_FOREACH(nbr, &iface->nbr_list, entry) 772 if (nbr != iface->self && 773 nbr->state & NBR_STA_FULL) 774 break; 775 if (nbr) { 776 log_debug("orig_rtr_lsa: point-to-point, " 777 "interface %s", iface->name); 778 rtr_link.id = nbr->id.s_addr; 779 rtr_link.data = iface->addr.s_addr; 780 rtr_link.type = LINK_TYPE_POINTTOPOINT; 781 /* RFC 3137: stub router support */ 782 if (oeconf->flags & OSPFD_FLAG_STUB_ROUTER || 783 oe_nofib) 784 rtr_link.metric = 0xffff; 785 else 786 rtr_link.metric = htons(iface->metric); 787 num_links++; 788 if (buf_add(buf, &rtr_link, sizeof(rtr_link))) 789 fatalx("orig_rtr_lsa: buf_add failed"); 790 } 791 if (iface->state & IF_STA_POINTTOPOINT) { 792 log_debug("orig_rtr_lsa: stub net, " 793 "interface %s", iface->name); 794 bzero(&rtr_link, sizeof(rtr_link)); 795 if (nbr) { 796 rtr_link.id = nbr->addr.s_addr; 797 rtr_link.data = 0xffffffff; 798 } else { 799 rtr_link.id = iface->addr.s_addr; 800 rtr_link.data = iface->mask.s_addr; 801 } 802 rtr_link.type = LINK_TYPE_STUB_NET; 803 rtr_link.metric = htons(iface->metric); 804 num_links++; 805 if (buf_add(buf, &rtr_link, sizeof(rtr_link))) 806 fatalx("orig_rtr_lsa: buf_add failed"); 807 } 808 continue; 809 case IF_TYPE_BROADCAST: 810 case IF_TYPE_NBMA: 811 if ((iface->state & IF_STA_MULTI)) { 812 if (iface->dr == iface->self) { 813 LIST_FOREACH(nbr, &iface->nbr_list, 814 entry) 815 if (nbr != iface->self && 816 nbr->state & NBR_STA_FULL) 817 break; 818 } else 819 nbr = iface->dr; 820 821 if (nbr && nbr->state & NBR_STA_FULL) { 822 log_debug("orig_rtr_lsa: transit net, " 823 "interface %s", iface->name); 824 825 rtr_link.id = iface->dr->addr.s_addr; 826 rtr_link.data = iface->addr.s_addr; 827 rtr_link.type = LINK_TYPE_TRANSIT_NET; 828 break; 829 } 830 } 831 832 if ((iface->flags & IFF_UP) == 0 || 833 iface->linkstate == LINK_STATE_DOWN || 834 (!LINK_STATE_IS_UP(iface->linkstate) && 835 iface->media_type == IFT_CARP)) 836 continue; 837 838 log_debug("orig_rtr_lsa: stub net, " 839 "interface %s", iface->name); 840 841 rtr_link.id = 842 iface->addr.s_addr & iface->mask.s_addr; 843 rtr_link.data = iface->mask.s_addr; 844 rtr_link.type = LINK_TYPE_STUB_NET; 845 break; 846 case IF_TYPE_VIRTUALLINK: 847 LIST_FOREACH(nbr, &iface->nbr_list, entry) { 848 if (nbr != iface->self && 849 nbr->state & NBR_STA_FULL) 850 break; 851 } 852 if (nbr) { 853 rtr_link.id = nbr->id.s_addr; 854 rtr_link.data = iface->addr.s_addr; 855 rtr_link.type = LINK_TYPE_VIRTUAL; 856 /* RFC 3137: stub router support */ 857 if (oeconf->flags & OSPFD_FLAG_STUB_ROUTER || 858 oe_nofib) 859 rtr_link.metric = 0xffff; 860 else 861 rtr_link.metric = htons(iface->metric); 862 num_links++; 863 virtual = 1; 864 if (buf_add(buf, &rtr_link, sizeof(rtr_link))) 865 fatalx("orig_rtr_lsa: buf_add failed"); 866 867 log_debug("orig_rtr_lsa: virtual link, " 868 "interface %s", iface->name); 869 } 870 continue; 871 case IF_TYPE_POINTOMULTIPOINT: 872 log_debug("orig_rtr_lsa: stub net, " 873 "interface %s", iface->name); 874 rtr_link.id = iface->addr.s_addr; 875 rtr_link.data = 0xffffffff; 876 rtr_link.type = LINK_TYPE_STUB_NET; 877 rtr_link.metric = htons(iface->metric); 878 num_links++; 879 if (buf_add(buf, &rtr_link, sizeof(rtr_link))) 880 fatalx("orig_rtr_lsa: buf_add failed"); 881 882 LIST_FOREACH(nbr, &iface->nbr_list, entry) { 883 if (nbr != iface->self && 884 nbr->state & NBR_STA_FULL) { 885 bzero(&rtr_link, sizeof(rtr_link)); 886 log_debug("orig_rtr_lsa: " 887 "point-to-multipoint, interface %s", 888 iface->name); 889 rtr_link.id = nbr->addr.s_addr; 890 rtr_link.data = iface->addr.s_addr; 891 rtr_link.type = LINK_TYPE_POINTTOPOINT; 892 /* RFC 3137: stub router support */ 893 if (oe_nofib || oeconf->flags & 894 OSPFD_FLAG_STUB_ROUTER) 895 rtr_link.metric = 0xffff; 896 else 897 rtr_link.metric = 898 htons(iface->metric); 899 num_links++; 900 if (buf_add(buf, &rtr_link, 901 sizeof(rtr_link))) 902 fatalx("orig_rtr_lsa: " 903 "buf_add failed"); 904 } 905 } 906 continue; 907 default: 908 fatalx("orig_rtr_lsa: unknown interface type"); 909 } 910 911 rtr_link.num_tos = 0; 912 /* RFC 3137: stub router support */ 913 if ((oeconf->flags & OSPFD_FLAG_STUB_ROUTER || oe_nofib) && 914 rtr_link.type != LINK_TYPE_STUB_NET) 915 rtr_link.metric = 0xffff; 916 else 917 rtr_link.metric = htons(iface->metric); 918 num_links++; 919 if (buf_add(buf, &rtr_link, sizeof(rtr_link))) 920 fatalx("orig_rtr_lsa: buf_add failed"); 921 } 922 923 /* LSA router header */ 924 lsa_rtr.flags = 0; 925 /* 926 * Set the E bit as soon as an as-ext lsa may be redistributed, only 927 * setting it in case we redistribute something is not worth the fuss. 928 * Do not set the E bit in case of a stub area. 929 */ 930 if (oeconf->redistribute && !area->stub) 931 lsa_rtr.flags |= OSPF_RTR_E; 932 933 border = (area_border_router(oeconf) != 0); 934 if (border != oeconf->border) { 935 oeconf->border = border; 936 orig_rtr_lsa_all(area); 937 } 938 939 if (oeconf->border) 940 lsa_rtr.flags |= OSPF_RTR_B; 941 /* TODO set V flag if a active virtual link ends here and the 942 * area is the tranist area for this link. */ 943 if (virtual) 944 lsa_rtr.flags |= OSPF_RTR_V; 945 946 lsa_rtr.dummy = 0; 947 lsa_rtr.nlinks = htons(num_links); 948 memcpy(buf_seek(buf, sizeof(lsa_hdr), sizeof(lsa_rtr)), 949 &lsa_rtr, sizeof(lsa_rtr)); 950 951 /* LSA header */ 952 lsa_hdr.age = htons(DEFAULT_AGE); 953 lsa_hdr.opts = area_ospf_options(area); 954 lsa_hdr.type = LSA_TYPE_ROUTER; 955 lsa_hdr.ls_id = oeconf->rtr_id.s_addr; 956 lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr; 957 lsa_hdr.seq_num = htonl(INIT_SEQ_NUM); 958 lsa_hdr.len = htons(buf_size(buf)); 959 lsa_hdr.ls_chksum = 0; /* updated later */ 960 memcpy(buf_seek(buf, 0, sizeof(lsa_hdr)), &lsa_hdr, sizeof(lsa_hdr)); 961 962 chksum = htons(iso_cksum(buf->buf, buf_size(buf), LS_CKSUM_OFFSET)); 963 memcpy(buf_seek(buf, LS_CKSUM_OFFSET, sizeof(chksum)), 964 &chksum, sizeof(chksum)); 965 966 if (self) 967 imsg_compose(ibuf_rde, IMSG_LS_UPD, self->peerid, 0, 968 buf->buf, buf_size(buf)); 969 else 970 log_warnx("orig_rtr_lsa: empty area %s", 971 inet_ntoa(area->id)); 972 973 buf_free(buf); 974 } 975 976 void 977 orig_net_lsa(struct iface *iface) 978 { 979 struct lsa_hdr lsa_hdr; 980 struct nbr *nbr; 981 struct buf *buf; 982 int num_rtr = 0; 983 u_int16_t chksum; 984 985 /* XXX READ_BUF_SIZE */ 986 if ((buf = buf_dynamic(sizeof(lsa_hdr), READ_BUF_SIZE)) == NULL) 987 fatal("orig_net_lsa"); 988 989 /* reserve space for LSA header and LSA Router header */ 990 if (buf_reserve(buf, sizeof(lsa_hdr)) == NULL) 991 fatal("orig_net_lsa: buf_reserve failed"); 992 993 /* LSA net mask and then all fully adjacent routers */ 994 if (buf_add(buf, &iface->mask, sizeof(iface->mask))) 995 fatal("orig_net_lsa: buf_add failed"); 996 997 /* fully adjacent neighbors + self */ 998 LIST_FOREACH(nbr, &iface->nbr_list, entry) 999 if (nbr->state & NBR_STA_FULL) { 1000 if (buf_add(buf, &nbr->id, sizeof(nbr->id))) 1001 fatal("orig_net_lsa: buf_add failed"); 1002 num_rtr++; 1003 } 1004 1005 if (num_rtr == 1) { 1006 /* non transit net therefor no need to generate a net lsa */ 1007 buf_free(buf); 1008 return; 1009 } 1010 1011 /* LSA header */ 1012 if (iface->state & IF_STA_DR) 1013 lsa_hdr.age = htons(DEFAULT_AGE); 1014 else 1015 lsa_hdr.age = htons(MAX_AGE); 1016 1017 lsa_hdr.opts = area_ospf_options(iface->area); 1018 lsa_hdr.type = LSA_TYPE_NETWORK; 1019 lsa_hdr.ls_id = iface->addr.s_addr; 1020 lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr; 1021 lsa_hdr.seq_num = htonl(INIT_SEQ_NUM); 1022 lsa_hdr.len = htons(buf_size(buf)); 1023 lsa_hdr.ls_chksum = 0; /* updated later */ 1024 memcpy(buf_seek(buf, 0, sizeof(lsa_hdr)), &lsa_hdr, sizeof(lsa_hdr)); 1025 1026 chksum = htons(iso_cksum(buf->buf, buf_size(buf), LS_CKSUM_OFFSET)); 1027 memcpy(buf_seek(buf, LS_CKSUM_OFFSET, sizeof(chksum)), 1028 &chksum, sizeof(chksum)); 1029 1030 imsg_compose(ibuf_rde, IMSG_LS_UPD, iface->self->peerid, 0, 1031 buf->buf, buf_size(buf)); 1032 1033 buf_free(buf); 1034 } 1035 1036 u_int32_t 1037 ospfe_router_id(void) 1038 { 1039 return (oeconf->rtr_id.s_addr); 1040 } 1041 1042 void 1043 ospfe_fib_update(int type) 1044 { 1045 int old = oe_nofib; 1046 1047 if (type == IMSG_CTL_FIB_COUPLE) 1048 oe_nofib = 0; 1049 if (type == IMSG_CTL_FIB_DECOUPLE) 1050 oe_nofib = 1; 1051 if (old != oe_nofib) 1052 orig_rtr_lsa_all(NULL); 1053 } 1054 1055 void 1056 ospfe_iface_ctl(struct ctl_conn *c, unsigned int idx) 1057 { 1058 struct area *area; 1059 struct iface *iface; 1060 struct ctl_iface *ictl; 1061 1062 LIST_FOREACH(area, &oeconf->area_list, entry) 1063 LIST_FOREACH(iface, &area->iface_list, entry) 1064 if (idx == 0 || idx == iface->ifindex) { 1065 ictl = if_to_ctl(iface); 1066 imsg_compose(&c->ibuf, IMSG_CTL_SHOW_INTERFACE, 1067 0, 0, ictl, sizeof(struct ctl_iface)); 1068 } 1069 } 1070 1071 void 1072 ospfe_nbr_ctl(struct ctl_conn *c) 1073 { 1074 struct area *area; 1075 struct iface *iface; 1076 struct nbr *nbr; 1077 struct ctl_nbr *nctl; 1078 1079 LIST_FOREACH(area, &oeconf->area_list, entry) 1080 LIST_FOREACH(iface, &area->iface_list, entry) 1081 LIST_FOREACH(nbr, &iface->nbr_list, entry) { 1082 if (iface->self != nbr) { 1083 nctl = nbr_to_ctl(nbr); 1084 imsg_compose(&c->ibuf, 1085 IMSG_CTL_SHOW_NBR, 0, 0, nctl, 1086 sizeof(struct ctl_nbr)); 1087 } 1088 } 1089 1090 imsg_compose(&c->ibuf, IMSG_CTL_END, 0, 0, NULL, 0); 1091 } 1092 1093 void 1094 ospfe_demote_area(struct area *area, int active) 1095 { 1096 struct demote_msg dmsg; 1097 1098 if (ospfd_process != PROC_OSPF_ENGINE || 1099 area->demote_group[0] == '\0') 1100 return; 1101 1102 bzero(&dmsg, sizeof(dmsg)); 1103 strlcpy(dmsg.demote_group, area->demote_group, 1104 sizeof(dmsg.demote_group)); 1105 dmsg.level = area->demote_level; 1106 if (active) 1107 dmsg.level = -dmsg.level; 1108 1109 ospfe_imsg_compose_parent(IMSG_DEMOTE, 0, &dmsg, sizeof(dmsg)); 1110 } 1111 1112 void 1113 ospfe_demote_iface(struct iface *iface, int active) 1114 { 1115 struct demote_msg dmsg; 1116 1117 if (ospfd_process != PROC_OSPF_ENGINE || 1118 iface->demote_group[0] == '\0') 1119 return; 1120 1121 bzero(&dmsg, sizeof(dmsg)); 1122 strlcpy(dmsg.demote_group, iface->demote_group, 1123 sizeof(dmsg.demote_group)); 1124 if (active) 1125 dmsg.level = -1; 1126 else 1127 dmsg.level = 1; 1128 1129 ospfe_imsg_compose_parent(IMSG_DEMOTE, 0, &dmsg, sizeof(dmsg)); 1130 } 1131