1 /* $OpenBSD: ospfe.c,v 1.25 2009/03/29 19:02:58 stsp 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("IFDELETE 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 == htons(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 if (lsa_hdr.type == htons(LSA_TYPE_LINK)) { 486 /* 487 * flood on interface only 488 */ 489 noack += lsa_flood(nbr->iface, nbr, 490 &lsa_hdr, imsg.data); 491 } else { 492 /* 493 * flood on all area interfaces on 494 * area 0.0.0.0 include also virtual links. 495 */ 496 if ((area = area_find(oeconf, 497 nbr->iface->area_id)) == NULL) 498 fatalx("interface lost area"); 499 LIST_FOREACH(iface, &area->iface_list, entry) { 500 noack += lsa_flood(iface, nbr, 501 &lsa_hdr, imsg.data); 502 } 503 /* XXX virtual links */ 504 } 505 506 /* remove from ls_req_list */ 507 le = ls_req_list_get(nbr, &lsa_hdr); 508 if (!(nbr->state & NBR_STA_FULL) && le != NULL) { 509 ls_req_list_free(nbr, le); 510 /* 511 * XXX no need to ack requested lsa 512 * the problem is that the RFC is very 513 * unclear about this. 514 */ 515 noack = 1; 516 } 517 518 if (!noack && nbr->iface != NULL && 519 nbr->iface->self != nbr) { 520 if (!(nbr->iface->state & IF_STA_BACKUP) || 521 nbr->iface->dr == nbr) { 522 /* delayed ack */ 523 lhp = lsa_hdr_new(); 524 memcpy(lhp, &lsa_hdr, sizeof(*lhp)); 525 ls_ack_list_add(nbr->iface, lhp); 526 } 527 } 528 529 lsa_cache_put(ref, nbr); 530 break; 531 case IMSG_LS_UPD: 532 /* 533 * IMSG_LS_UPD is used in three cases: 534 * 1. as response to ls requests 535 * 2. as response to ls updates where the DB 536 * is newer then the sent LSA 537 * 3. in EXSTART when the LSA has age MaxAge 538 */ 539 l = imsg.hdr.len - IMSG_HEADER_SIZE; 540 if (l < sizeof(lsa_hdr)) 541 fatalx("ospfe_dispatch_rde: " 542 "bad imsg size"); 543 544 nbr = nbr_find_peerid(imsg.hdr.peerid); 545 if (nbr == NULL) 546 break; 547 548 if (nbr->iface->self == nbr) 549 break; 550 551 memcpy(&age, imsg.data, sizeof(age)); 552 ref = lsa_cache_add(imsg.data, l); 553 if (ntohs(age) >= MAX_AGE) 554 /* add to retransmit list */ 555 ls_retrans_list_add(nbr, imsg.data, 0, 0); 556 else 557 ls_retrans_list_add(nbr, imsg.data, 0, 1); 558 559 lsa_cache_put(ref, nbr); 560 break; 561 case IMSG_LS_ACK: 562 /* 563 * IMSG_LS_ACK is used in two cases: 564 * 1. LSA was a duplicate 565 * 2. LS age is MaxAge and there is no current 566 * instance in the DB plus no neighbor in state 567 * Exchange or Loading 568 */ 569 nbr = nbr_find_peerid(imsg.hdr.peerid); 570 if (nbr == NULL) 571 break; 572 573 if (nbr->iface->self == nbr) 574 break; 575 576 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(lsa_hdr)) 577 fatalx("ospfe_dispatch_rde: bad imsg size"); 578 memcpy(&lsa_hdr, imsg.data, sizeof(lsa_hdr)); 579 580 /* for case one check for implied acks */ 581 if (nbr->iface->state & IF_STA_DROTHER) 582 if (ls_retrans_list_del(nbr->iface->self, 583 &lsa_hdr) == 0) 584 break; 585 if (ls_retrans_list_del(nbr, &lsa_hdr) == 0) 586 break; 587 588 /* send a direct acknowledgement */ 589 send_ls_ack(nbr->iface, nbr->addr, imsg.data, 590 imsg.hdr.len - IMSG_HEADER_SIZE); 591 592 break; 593 case IMSG_LS_BADREQ: 594 nbr = nbr_find_peerid(imsg.hdr.peerid); 595 if (nbr == NULL) 596 break; 597 598 if (nbr->iface->self == nbr) 599 fatalx("ospfe_dispatch_rde: " 600 "dummy neighbor got BADREQ"); 601 602 nbr_fsm(nbr, NBR_EVT_BAD_LS_REQ); 603 break; 604 case IMSG_ABR_UP: 605 memcpy(&ar, imsg.data, sizeof(ar)); 606 607 if ((iface = find_vlink(&ar)) != NULL && 608 iface->state == IF_STA_DOWN) 609 if (if_fsm(iface, IF_EVT_UP)) { 610 log_debug("error starting interface %s", 611 iface->name); 612 } 613 break; 614 case IMSG_ABR_DOWN: 615 memcpy(&ar, imsg.data, sizeof(ar)); 616 617 if ((iface = find_vlink(&ar)) != NULL && 618 iface->state == IF_STA_POINTTOPOINT) 619 if (if_fsm(iface, IF_EVT_DOWN)) { 620 log_debug("error stopping interface %s", 621 iface->name); 622 } 623 break; 624 case IMSG_CTL_AREA: 625 case IMSG_CTL_IFACE: 626 case IMSG_CTL_END: 627 case IMSG_CTL_SHOW_DATABASE: 628 case IMSG_CTL_SHOW_DB_EXT: 629 case IMSG_CTL_SHOW_DB_LINK: 630 case IMSG_CTL_SHOW_DB_NET: 631 case IMSG_CTL_SHOW_DB_RTR: 632 case IMSG_CTL_SHOW_DB_INTRA: 633 case IMSG_CTL_SHOW_DB_SELF: 634 case IMSG_CTL_SHOW_DB_SUM: 635 case IMSG_CTL_SHOW_DB_ASBR: 636 case IMSG_CTL_SHOW_RIB: 637 case IMSG_CTL_SHOW_SUM: 638 case IMSG_CTL_SHOW_SUM_AREA: 639 control_imsg_relay(&imsg); 640 break; 641 default: 642 log_debug("ospfe_dispatch_rde: error handling imsg %d", 643 imsg.hdr.type); 644 break; 645 } 646 imsg_free(&imsg); 647 } 648 if (!shut) 649 imsg_event_add(ibuf); 650 else { 651 /* this pipe is dead, so remove the event handler */ 652 event_del(&ibuf->ev); 653 event_loopexit(NULL); 654 } 655 } 656 657 struct iface * 658 find_vlink(struct abr_rtr *ar) 659 { 660 struct area *area; 661 struct iface *iface = NULL; 662 663 LIST_FOREACH(area, &oeconf->area_list, entry) 664 LIST_FOREACH(iface, &area->iface_list, entry) 665 if (iface->abr_id.s_addr == ar->abr_id.s_addr && 666 iface->type == IF_TYPE_VIRTUALLINK && 667 //XXX iface->area->id.s_addr == ar->area.s_addr) { 668 iface->area_id.s_addr == ar->area.s_addr) { 669 //XXX iface->dst.s_addr = ar->dst_ip.s_addr; 670 iface->dst = ar->dst_ip; 671 //XXX iface->addr.s_addr = ar->addr.s_addr; 672 iface->addr = ar->addr; 673 iface->metric = ar->metric; 674 675 return (iface); 676 } 677 678 return (iface); 679 } 680 681 void 682 orig_rtr_lsa_all(struct area *area) 683 { 684 struct area *a; 685 686 /* 687 * update all router LSA in all areas except area itself, 688 * as this update is already running. 689 */ 690 LIST_FOREACH(a, &oeconf->area_list, entry) 691 if (a != area) 692 orig_rtr_lsa_area(a); 693 } 694 695 void 696 orig_rtr_lsa(struct iface *iface) 697 { 698 struct area *area; 699 700 if ((area = area_find(oeconf, iface->area_id)) == NULL) 701 fatalx("interface lost area"); 702 orig_rtr_lsa_area(area); 703 } 704 705 void 706 orig_rtr_lsa_area(struct area *area) 707 { 708 struct lsa_hdr lsa_hdr; 709 struct lsa_rtr lsa_rtr; 710 struct lsa_rtr_link rtr_link; 711 struct iface *iface; 712 struct buf *buf; 713 struct nbr *nbr, *self = NULL; 714 u_int32_t flags; 715 u_int16_t chksum; 716 u_int8_t border, virtual = 0; 717 718 log_debug("orig_rtr_lsa: area %s", inet_ntoa(area->id)); 719 720 /* XXX READ_BUF_SIZE */ 721 if ((buf = buf_dynamic(sizeof(lsa_hdr), READ_BUF_SIZE)) == NULL) 722 fatal("orig_rtr_lsa"); 723 724 /* reserve space for LSA header and LSA Router header */ 725 if (buf_reserve(buf, sizeof(lsa_hdr)) == NULL) 726 fatal("orig_rtr_lsa: buf_reserve failed"); 727 728 if (buf_reserve(buf, sizeof(lsa_rtr)) == NULL) 729 fatal("orig_rtr_lsa: buf_reserve failed"); 730 731 /* links */ 732 LIST_FOREACH(iface, &area->iface_list, entry) { 733 if (self == NULL && iface->self != NULL) 734 self = iface->self; 735 736 bzero(&rtr_link, sizeof(rtr_link)); 737 738 switch (iface->type) { 739 case IF_TYPE_POINTOPOINT: 740 LIST_FOREACH(nbr, &iface->nbr_list, entry) 741 if (nbr != iface->self && 742 nbr->state & NBR_STA_FULL) 743 break; 744 if (nbr && iface->state & IF_STA_POINTTOPOINT) { 745 log_debug("orig_rtr_lsa: point-to-point, " 746 "interface %s", iface->name); 747 rtr_link.type = LINK_TYPE_POINTTOPOINT; 748 rtr_link.metric = htons(iface->metric); 749 rtr_link.iface_id = htonl(iface->ifindex); 750 rtr_link.nbr_iface_id = htonl(nbr->iface_id); 751 rtr_link.nbr_rtr_id = nbr->id.s_addr; 752 if (buf_add(buf, &rtr_link, sizeof(rtr_link))) 753 fatalx("orig_rtr_lsa: buf_add failed"); 754 } 755 continue; 756 case IF_TYPE_BROADCAST: 757 case IF_TYPE_NBMA: 758 if ((iface->state & IF_STA_MULTI)) { 759 if (iface->dr == iface->self) { 760 LIST_FOREACH(nbr, &iface->nbr_list, 761 entry) 762 if (nbr != iface->self && 763 nbr->state & NBR_STA_FULL) 764 break; 765 } else 766 nbr = iface->dr; 767 768 if (nbr && nbr->state & NBR_STA_FULL) { 769 log_debug("orig_rtr_lsa: transit net, " 770 "interface %s", iface->name); 771 772 rtr_link.type = LINK_TYPE_TRANSIT_NET; 773 rtr_link.metric = htons(iface->metric); 774 rtr_link.iface_id = htonl(iface->ifindex); 775 rtr_link.nbr_iface_id = htonl(iface->dr->iface_id); 776 rtr_link.nbr_rtr_id = iface->dr->id.s_addr; 777 if (buf_add(buf, &rtr_link, 778 sizeof(rtr_link))) 779 fatalx("orig_rtr_lsa: " 780 "buf_add failed"); 781 break; 782 } 783 } 784 break; 785 #if 0 /* TODO virtualllink/pointtomulti */ 786 case IF_TYPE_VIRTUALLINK: 787 LIST_FOREACH(nbr, &iface->nbr_list, entry) { 788 if (nbr != iface->self && 789 nbr->state & NBR_STA_FULL) 790 break; 791 } 792 if (nbr) { 793 rtr_link.id = nbr->id.s_addr; 794 //XXX rtr_link.data = iface->addr.s_addr; 795 rtr_link.type = LINK_TYPE_VIRTUAL; 796 /* RFC 3137: stub router support */ 797 if (oeconf->flags & OSPFD_FLAG_STUB_ROUTER || 798 oe_nofib) 799 rtr_link.metric = 0xffff; 800 else 801 rtr_link.metric = htons(iface->metric); 802 virtual = 1; 803 if (buf_add(buf, &rtr_link, sizeof(rtr_link))) 804 fatalx("orig_rtr_lsa: buf_add failed"); 805 806 log_debug("orig_rtr_lsa: virtual link, " 807 "interface %s", iface->name); 808 } 809 continue; 810 case IF_TYPE_POINTOMULTIPOINT: 811 log_debug("orig_rtr_lsa: stub net, " 812 "interface %s", iface->name); 813 //XXX rtr_link.id = iface->addr.s_addr; 814 rtr_link.data = 0xffffffff; 815 rtr_link.type = LINK_TYPE_STUB_NET; 816 rtr_link.metric = htons(iface->metric); 817 if (buf_add(buf, &rtr_link, sizeof(rtr_link))) 818 fatalx("orig_rtr_lsa: buf_add failed"); 819 820 LIST_FOREACH(nbr, &iface->nbr_list, entry) { 821 if (nbr != iface->self && 822 nbr->state & NBR_STA_FULL) { 823 bzero(&rtr_link, sizeof(rtr_link)); 824 log_debug("orig_rtr_lsa: " 825 "point-to-multipoint, interface %s", 826 iface->name); 827 //XXX rtr_link.id = nbr->addr.s_addr; 828 //XXX rtr_link.data = iface->addr.s_addr; 829 rtr_link.type = LINK_TYPE_POINTTOPOINT; 830 /* RFC 3137: stub router support */ 831 if (oe_nofib || oeconf->flags & 832 OSPFD_FLAG_STUB_ROUTER) 833 rtr_link.metric = 0xffff; 834 else 835 rtr_link.metric = 836 htons(iface->metric); 837 if (buf_add(buf, &rtr_link, 838 sizeof(rtr_link))) 839 fatalx("orig_rtr_lsa: " 840 "buf_add failed"); 841 } 842 } 843 continue; 844 #endif /* TODO virtualllink/pointtomulti */ 845 default: 846 fatalx("orig_rtr_lsa: unknown interface type"); 847 } 848 } 849 850 /* LSA router header */ 851 lsa_rtr.opts = 0; 852 flags = 0; 853 854 /* 855 * Set the E bit as soon as an as-ext lsa may be redistributed, only 856 * setting it in case we redistribute something is not worth the fuss. 857 */ 858 if (oeconf->redistribute && !area->stub) 859 flags |= OSPF_RTR_E; 860 861 border = (area_border_router(oeconf) != 0); 862 if (border != oeconf->border) { 863 oeconf->border = border; 864 orig_rtr_lsa_all(area); 865 } 866 867 if (oeconf->border) 868 flags |= OSPF_RTR_B; 869 /* TODO set V flag if a active virtual link ends here and the 870 * area is the tranist area for this link. */ 871 if (virtual) 872 flags |= OSPF_RTR_V; 873 874 LSA_24_SETLO(lsa_rtr.opts, area_ospf_options(area)); 875 LSA_24_SETHI(lsa_rtr.opts, flags); 876 lsa_rtr.opts = htonl(lsa_rtr.opts); 877 memcpy(buf_seek(buf, sizeof(lsa_hdr), sizeof(lsa_rtr)), 878 &lsa_rtr, sizeof(lsa_rtr)); 879 880 /* LSA header */ 881 lsa_hdr.age = htons(DEFAULT_AGE); 882 lsa_hdr.type = htons(LSA_TYPE_ROUTER); 883 /* XXX needs to be fixed if multiple router-lsa need to be announced */ 884 lsa_hdr.ls_id = 0; 885 lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr; 886 lsa_hdr.seq_num = htonl(INIT_SEQ_NUM); 887 lsa_hdr.len = htons(buf->wpos); 888 lsa_hdr.ls_chksum = 0; /* updated later */ 889 memcpy(buf_seek(buf, 0, sizeof(lsa_hdr)), &lsa_hdr, sizeof(lsa_hdr)); 890 891 chksum = htons(iso_cksum(buf->buf, buf->wpos, LS_CKSUM_OFFSET)); 892 memcpy(buf_seek(buf, LS_CKSUM_OFFSET, sizeof(chksum)), 893 &chksum, sizeof(chksum)); 894 895 if (self) 896 imsg_compose(ibuf_rde, IMSG_LS_UPD, self->peerid, 0, 897 buf->buf, buf->wpos); 898 else 899 log_warnx("orig_rtr_lsa: empty area %s", 900 inet_ntoa(area->id)); 901 902 buf_free(buf); 903 } 904 905 void 906 orig_net_lsa(struct iface *iface) 907 { 908 struct lsa_hdr lsa_hdr; 909 struct nbr *nbr; 910 struct buf *buf; 911 struct lsa_net lsa_net; 912 int num_rtr = 0; 913 u_int16_t chksum; 914 915 /* XXX READ_BUF_SIZE */ 916 if ((buf = buf_dynamic(sizeof(lsa_hdr), READ_BUF_SIZE)) == NULL) 917 fatal("orig_net_lsa"); 918 919 /* reserve space for LSA header and options field */ 920 if (buf_reserve(buf, sizeof(lsa_hdr) + sizeof(lsa_net)) == NULL) 921 fatal("orig_net_lsa: buf_reserve failed"); 922 923 lsa_net.opts = 0; 924 /* fully adjacent neighbors + self */ 925 LIST_FOREACH(nbr, &iface->nbr_list, entry) 926 if (nbr->state & NBR_STA_FULL) { 927 if (buf_add(buf, &nbr->id, sizeof(nbr->id))) 928 fatal("orig_net_lsa: buf_add failed"); 929 lsa_net.opts |= nbr->options; 930 num_rtr++; 931 } 932 933 if (num_rtr == 1) { 934 /* non transit net therefor no need to generate a net lsa */ 935 buf_free(buf); 936 return; 937 } 938 939 /* LSA header */ 940 if (iface->state & IF_STA_DR) 941 lsa_hdr.age = htons(DEFAULT_AGE); 942 else 943 lsa_hdr.age = htons(MAX_AGE); 944 945 lsa_hdr.type = htons(LSA_TYPE_NETWORK); 946 /* for network LSAs, the link state ID equals the interface ID */ 947 lsa_hdr.ls_id = htonl(iface->ifindex); 948 lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr; 949 lsa_hdr.seq_num = htonl(INIT_SEQ_NUM); 950 lsa_hdr.len = htons(buf->wpos); 951 lsa_hdr.ls_chksum = 0; /* updated later */ 952 memcpy(buf_seek(buf, 0, sizeof(lsa_hdr)), &lsa_hdr, sizeof(lsa_hdr)); 953 954 lsa_net.opts &= lsa_net.opts & htonl(LSA_24_MASK); 955 memcpy(buf_seek(buf, sizeof(lsa_hdr), sizeof(lsa_net)), &lsa_net, 956 sizeof(lsa_net)); 957 958 chksum = htons(iso_cksum(buf->buf, buf->wpos, LS_CKSUM_OFFSET)); 959 memcpy(buf_seek(buf, LS_CKSUM_OFFSET, sizeof(chksum)), 960 &chksum, sizeof(chksum)); 961 962 imsg_compose(ibuf_rde, IMSG_LS_UPD, iface->self->peerid, 0, 963 buf->buf, buf->wpos); 964 965 buf_free(buf); 966 } 967 968 void 969 orig_link_lsa(struct iface *iface) 970 { 971 struct lsa_hdr lsa_hdr; 972 struct lsa_link lsa_link; 973 struct lsa_prefix lsa_prefix; 974 struct buf *buf; 975 struct iface_addr *ia; 976 struct in6_addr prefix; 977 unsigned int num_prefix = 0; 978 u_int16_t chksum; 979 u_int32_t options; 980 981 log_debug("orig_link_lsa: interface %s", iface->name); 982 983 switch (iface->type) { 984 case IF_TYPE_VIRTUALLINK: /* forbidden by rfc5340 */ 985 return; 986 case IF_TYPE_BROADCAST: 987 case IF_TYPE_NBMA: 988 if ((iface->state & IF_STA_MULTI) == 0) 989 return; 990 break; 991 case IF_TYPE_POINTOPOINT: 992 case IF_TYPE_POINTOMULTIPOINT: 993 if ((iface->state & IF_STA_POINTTOPOINT) == 0) 994 return; 995 break; 996 default: 997 fatalx("orig_link_lsa: unknown interface type"); 998 } 999 1000 /* XXX READ_BUF_SIZE */ 1001 if ((buf = buf_dynamic(sizeof(lsa_hdr) + sizeof(lsa_link), 1002 READ_BUF_SIZE)) == NULL) 1003 fatal("orig_link_lsa"); 1004 1005 /* reserve space for LSA header and LSA link header */ 1006 if (buf_reserve(buf, sizeof(lsa_hdr) + sizeof(lsa_link)) == NULL) 1007 fatal("orig_link_lsa: buf_reserve failed"); 1008 1009 /* link-local address, and all prefixes configured on interface */ 1010 TAILQ_FOREACH(ia, &iface->ifa_list, entry) { 1011 if (IN6_IS_ADDR_LINKLOCAL(&ia->addr)) { 1012 log_debug("orig_link_lsa: link local address %s", 1013 log_in6addr(&ia->addr)); 1014 lsa_link.lladdr = ia->addr; 1015 continue; 1016 } 1017 1018 lsa_prefix.prefixlen = ia->prefixlen; 1019 lsa_prefix.options = 0; 1020 lsa_prefix.metric = 0; 1021 inet6applymask(&prefix, &ia->addr, ia->prefixlen); 1022 log_debug("orig_link_lsa: prefix %s", log_in6addr(&prefix)); 1023 if (buf_add(buf, &lsa_prefix, sizeof(lsa_prefix))) 1024 fatal("orig_link_lsa: buf_add failed"); 1025 if (buf_add(buf, &prefix.s6_addr[0], 1026 LSA_PREFIXSIZE(ia->prefixlen))) 1027 fatal("orig_link_lsa: buf_add failed"); 1028 num_prefix++; 1029 } 1030 1031 /* LSA link header (lladdr has already been filled in above) */ 1032 LSA_24_SETHI(lsa_link.opts, iface->priority); 1033 options = area_ospf_options(area_find(oeconf, iface->area_id)); 1034 LSA_24_SETLO(lsa_link.opts, options); 1035 lsa_link.opts = htonl(lsa_link.opts); 1036 lsa_link.numprefix = htonl(num_prefix); 1037 memcpy(buf_seek(buf, sizeof(lsa_hdr), sizeof(lsa_link)), 1038 &lsa_link, sizeof(lsa_link)); 1039 1040 /* LSA header */ 1041 lsa_hdr.age = htons(DEFAULT_AGE); 1042 lsa_hdr.type = htons(LSA_TYPE_LINK); 1043 /* for link LSAs, the link state ID equals the interface ID */ 1044 lsa_hdr.ls_id = htonl(iface->ifindex); 1045 lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr; 1046 lsa_hdr.seq_num = htonl(INIT_SEQ_NUM); 1047 lsa_hdr.len = htons(buf->wpos); 1048 lsa_hdr.ls_chksum = 0; /* updated later */ 1049 memcpy(buf_seek(buf, 0, sizeof(lsa_hdr)), &lsa_hdr, sizeof(lsa_hdr)); 1050 1051 chksum = htons(iso_cksum(buf->buf, buf->wpos, LS_CKSUM_OFFSET)); 1052 memcpy(buf_seek(buf, LS_CKSUM_OFFSET, sizeof(chksum)), 1053 &chksum, sizeof(chksum)); 1054 1055 imsg_compose(ibuf_rde, IMSG_LS_UPD, iface->self->peerid, 0, 1056 buf->buf, buf->wpos); 1057 1058 buf_free(buf); 1059 } 1060 1061 u_int32_t 1062 ospfe_router_id(void) 1063 { 1064 return (oeconf->rtr_id.s_addr); 1065 } 1066 1067 void 1068 ospfe_fib_update(int type) 1069 { 1070 int old = oe_nofib; 1071 1072 if (type == IMSG_CTL_FIB_COUPLE) 1073 oe_nofib = 0; 1074 if (type == IMSG_CTL_FIB_DECOUPLE) 1075 oe_nofib = 1; 1076 if (old != oe_nofib) 1077 orig_rtr_lsa_all(NULL); 1078 } 1079 1080 void 1081 ospfe_iface_ctl(struct ctl_conn *c, unsigned int idx) 1082 { 1083 struct area *area; 1084 struct iface *iface; 1085 struct ctl_iface *ictl; 1086 1087 LIST_FOREACH(area, &oeconf->area_list, entry) 1088 LIST_FOREACH(iface, &area->iface_list, entry) 1089 if (idx == 0 || idx == iface->ifindex) { 1090 ictl = if_to_ctl(iface); 1091 imsg_compose(&c->ibuf, IMSG_CTL_SHOW_INTERFACE, 1092 0, 0, ictl, sizeof(struct ctl_iface)); 1093 } 1094 } 1095 1096 void 1097 ospfe_nbr_ctl(struct ctl_conn *c) 1098 { 1099 struct area *area; 1100 struct iface *iface; 1101 struct nbr *nbr; 1102 struct ctl_nbr *nctl; 1103 1104 LIST_FOREACH(area, &oeconf->area_list, entry) 1105 LIST_FOREACH(iface, &area->iface_list, entry) 1106 LIST_FOREACH(nbr, &iface->nbr_list, entry) { 1107 if (iface->self != nbr) { 1108 nctl = nbr_to_ctl(nbr); 1109 imsg_compose(&c->ibuf, 1110 IMSG_CTL_SHOW_NBR, 0, 0, nctl, 1111 sizeof(struct ctl_nbr)); 1112 } 1113 } 1114 1115 imsg_compose(&c->ibuf, IMSG_CTL_END, 0, 0, NULL, 0); 1116 } 1117 1118 void 1119 ospfe_demote_area(struct area *area, int active) 1120 { 1121 struct demote_msg dmsg; 1122 1123 if (ospfd_process != PROC_OSPF_ENGINE || 1124 area->demote_group[0] == '\0') 1125 return; 1126 1127 bzero(&dmsg, sizeof(dmsg)); 1128 strlcpy(dmsg.demote_group, area->demote_group, 1129 sizeof(dmsg.demote_group)); 1130 dmsg.level = area->demote_level; 1131 if (active) 1132 dmsg.level = -dmsg.level; 1133 1134 ospfe_imsg_compose_parent(IMSG_DEMOTE, 0, &dmsg, sizeof(dmsg)); 1135 } 1136 1137 void 1138 ospfe_demote_iface(struct iface *iface, int active) 1139 { 1140 struct demote_msg dmsg; 1141 1142 if (ospfd_process != PROC_OSPF_ENGINE || 1143 iface->demote_group[0] == '\0') 1144 return; 1145 1146 bzero(&dmsg, sizeof(dmsg)); 1147 strlcpy(dmsg.demote_group, iface->demote_group, 1148 sizeof(dmsg.demote_group)); 1149 if (active) 1150 dmsg.level = -1; 1151 else 1152 dmsg.level = 1; 1153 1154 ospfe_imsg_compose_parent(IMSG_DEMOTE, 0, &dmsg, sizeof(dmsg)); 1155 } 1156