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