1 /* $OpenBSD: lde.c,v 1.29 2014/07/12 20:16:38 krw Exp $ */ 2 3 /* 4 * Copyright (c) 2004, 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 <netmpls/mpls.h> 26 #include <arpa/inet.h> 27 #include <err.h> 28 #include <errno.h> 29 #include <stdlib.h> 30 #include <signal.h> 31 #include <string.h> 32 #include <pwd.h> 33 #include <unistd.h> 34 #include <event.h> 35 36 #include "ldp.h" 37 #include "ldpd.h" 38 #include "ldpe.h" 39 #include "log.h" 40 #include "lde.h" 41 42 void lde_sig_handler(int sig, short, void *); 43 void lde_shutdown(void); 44 void lde_dispatch_imsg(int, short, void *); 45 void lde_dispatch_parent(int, short, void *); 46 47 struct lde_nbr *lde_nbr_find(u_int32_t); 48 struct lde_nbr *lde_nbr_new(u_int32_t, struct in_addr *); 49 void lde_nbr_del(struct lde_nbr *); 50 void lde_nbr_clear(void); 51 52 void lde_map_free(void *); 53 void lde_address_list_free(struct lde_nbr *); 54 55 struct ldpd_conf *ldeconf = NULL, *nconf = NULL; 56 struct imsgev *iev_ldpe; 57 struct imsgev *iev_main; 58 59 /* ARGSUSED */ 60 void 61 lde_sig_handler(int sig, short event, void *arg) 62 { 63 /* 64 * signal handler rules don't apply, libevent decouples for us 65 */ 66 67 switch (sig) { 68 case SIGINT: 69 case SIGTERM: 70 lde_shutdown(); 71 /* NOTREACHED */ 72 default: 73 fatalx("unexpected signal"); 74 } 75 } 76 77 /* label decision engine */ 78 pid_t 79 lde(struct ldpd_conf *xconf, int pipe_parent2lde[2], int pipe_ldpe2lde[2], 80 int pipe_parent2ldpe[2]) 81 { 82 struct event ev_sigint, ev_sigterm; 83 struct timeval now; 84 struct passwd *pw; 85 pid_t pid; 86 87 switch (pid = fork()) { 88 case -1: 89 fatal("cannot fork"); 90 /* NOTREACHED */ 91 case 0: 92 break; 93 default: 94 return (pid); 95 } 96 97 ldeconf = xconf; 98 99 setproctitle("label decision engine"); 100 ldpd_process = PROC_LDE_ENGINE; 101 102 if ((pw = getpwnam(LDPD_USER)) == NULL) 103 fatal("getpwnam"); 104 105 if (chroot(pw->pw_dir) == -1) 106 fatal("chroot"); 107 if (chdir("/") == -1) 108 fatal("chdir(\"/\")"); 109 110 if (setgroups(1, &pw->pw_gid) || 111 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 112 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 113 fatal("can't drop privileges"); 114 115 event_init(); 116 117 /* setup signal handler */ 118 signal_set(&ev_sigint, SIGINT, lde_sig_handler, NULL); 119 signal_set(&ev_sigterm, SIGTERM, lde_sig_handler, NULL); 120 signal_add(&ev_sigint, NULL); 121 signal_add(&ev_sigterm, NULL); 122 signal(SIGPIPE, SIG_IGN); 123 signal(SIGHUP, SIG_IGN); 124 125 /* setup pipes */ 126 close(pipe_ldpe2lde[0]); 127 close(pipe_parent2lde[0]); 128 close(pipe_parent2ldpe[0]); 129 close(pipe_parent2ldpe[1]); 130 131 if ((iev_ldpe = malloc(sizeof(struct imsgev))) == NULL || 132 (iev_main = malloc(sizeof(struct imsgev))) == NULL) 133 fatal(NULL); 134 imsg_init(&iev_ldpe->ibuf, pipe_ldpe2lde[1]); 135 iev_ldpe->handler = lde_dispatch_imsg; 136 imsg_init(&iev_main->ibuf, pipe_parent2lde[1]); 137 iev_main->handler = lde_dispatch_parent; 138 139 /* setup event handler */ 140 iev_ldpe->events = EV_READ; 141 event_set(&iev_ldpe->ev, iev_ldpe->ibuf.fd, iev_ldpe->events, 142 iev_ldpe->handler, iev_ldpe); 143 event_add(&iev_ldpe->ev, NULL); 144 145 iev_main->events = EV_READ; 146 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events, 147 iev_main->handler, iev_main); 148 event_add(&iev_main->ev, NULL); 149 150 gettimeofday(&now, NULL); 151 ldeconf->uptime = now.tv_sec; 152 153 event_dispatch(); 154 155 lde_shutdown(); 156 /* NOTREACHED */ 157 158 return (0); 159 } 160 161 void 162 lde_shutdown(void) 163 { 164 lde_nbr_clear(); 165 rt_clear(); 166 167 msgbuf_clear(&iev_ldpe->ibuf.w); 168 free(iev_ldpe); 169 msgbuf_clear(&iev_main->ibuf.w); 170 free(iev_main); 171 free(ldeconf); 172 173 log_info("label decision engine exiting"); 174 _exit(0); 175 } 176 177 /* imesg */ 178 int 179 lde_imsg_compose_parent(int type, pid_t pid, void *data, u_int16_t datalen) 180 { 181 return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen)); 182 } 183 184 int 185 lde_imsg_compose_ldpe(int type, u_int32_t peerid, pid_t pid, void *data, 186 u_int16_t datalen) 187 { 188 return (imsg_compose_event(iev_ldpe, type, peerid, pid, 189 -1, data, datalen)); 190 } 191 192 /* ARGSUSED */ 193 void 194 lde_dispatch_imsg(int fd, short event, void *bula) 195 { 196 struct imsgev *iev = bula; 197 struct imsgbuf *ibuf = &iev->ibuf; 198 struct imsg imsg; 199 struct lde_nbr *nbr; 200 struct map map; 201 struct timespec tp; 202 struct in_addr addr; 203 ssize_t n; 204 time_t now; 205 int shut = 0, verbose; 206 207 if (event & EV_READ) { 208 if ((n = imsg_read(ibuf)) == -1) 209 fatal("imsg_read error"); 210 if (n == 0) /* connection closed */ 211 shut = 1; 212 } 213 if (event & EV_WRITE) { 214 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 215 fatal("msgbuf_write"); 216 if (n == 0) /* connection closed */ 217 shut = 1; 218 } 219 220 clock_gettime(CLOCK_MONOTONIC, &tp); 221 now = tp.tv_sec; 222 223 for (;;) { 224 if ((n = imsg_get(ibuf, &imsg)) == -1) 225 fatal("lde_dispatch_imsg: imsg_read error"); 226 if (n == 0) 227 break; 228 229 switch (imsg.hdr.type) { 230 case IMSG_LABEL_MAPPING_FULL: 231 nbr = lde_nbr_find(imsg.hdr.peerid); 232 if (nbr == NULL) { 233 log_debug("lde_dispatch_imsg: cannot find " 234 "lde neighbor"); 235 return; 236 } 237 238 rt_snap(nbr); 239 lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, 240 imsg.hdr.peerid, 0, NULL, 0); 241 break; 242 case IMSG_LABEL_MAPPING: 243 case IMSG_LABEL_REQUEST: 244 case IMSG_LABEL_RELEASE: 245 case IMSG_LABEL_WITHDRAW: 246 case IMSG_LABEL_ABORT: 247 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(map)) 248 fatalx("invalid size of OE request"); 249 memcpy(&map, imsg.data, sizeof(map)); 250 251 nbr = lde_nbr_find(imsg.hdr.peerid); 252 if (nbr == NULL) { 253 log_debug("lde_dispatch_imsg: cannot find " 254 "lde neighbor"); 255 return; 256 } 257 258 switch (imsg.hdr.type) { 259 case IMSG_LABEL_MAPPING: 260 lde_check_mapping(&map, nbr); 261 break; 262 case IMSG_LABEL_REQUEST: 263 lde_check_request(&map, nbr); 264 break; 265 case IMSG_LABEL_RELEASE: 266 lde_check_release(&map, nbr); 267 break; 268 case IMSG_LABEL_WITHDRAW: 269 lde_check_withdraw(&map, nbr); 270 break; 271 default: 272 log_warnx("type %d not yet handled. nbr %s", 273 imsg.hdr.type, inet_ntoa(nbr->id)); 274 } 275 break; 276 case IMSG_ADDRESS_ADD: 277 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(addr)) 278 fatalx("invalid size of OE request"); 279 memcpy(&addr, imsg.data, sizeof(addr)); 280 281 nbr = lde_nbr_find(imsg.hdr.peerid); 282 if (nbr == NULL) { 283 log_debug("lde_dispatch_imsg: cannot find " 284 "lde neighbor"); 285 return; 286 } 287 288 if (lde_address_add(nbr, &addr) < 0) { 289 log_debug("lde_dispatch_imsg: cannot add " 290 "address %s, it already exists", 291 inet_ntoa(addr)); 292 } 293 294 break; 295 case IMSG_ADDRESS_DEL: 296 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(addr)) 297 fatalx("invalid size of OE request"); 298 memcpy(&addr, imsg.data, sizeof(addr)); 299 300 nbr = lde_nbr_find(imsg.hdr.peerid); 301 if (nbr == NULL) { 302 log_debug("lde_dispatch_imsg: cannot find " 303 "lde neighbor"); 304 return; 305 } 306 307 if (lde_address_del(nbr, &addr) < 0) { 308 log_debug("lde_dispatch_imsg: cannot delete " 309 "address %s, it does not exists", 310 inet_ntoa(addr)); 311 } 312 313 break; 314 case IMSG_NEIGHBOR_UP: 315 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(addr)) 316 fatalx("invalid size of OE request"); 317 memcpy(&addr, imsg.data, sizeof(addr)); 318 319 if (lde_nbr_find(imsg.hdr.peerid)) 320 fatalx("lde_dispatch_imsg: " 321 "neighbor already exists"); 322 lde_nbr_new(imsg.hdr.peerid, &addr); 323 break; 324 case IMSG_NEIGHBOR_DOWN: 325 lde_nbr_del(lde_nbr_find(imsg.hdr.peerid)); 326 break; 327 case IMSG_CTL_SHOW_LIB: 328 rt_dump(imsg.hdr.pid); 329 330 lde_imsg_compose_ldpe(IMSG_CTL_END, 0, 331 imsg.hdr.pid, NULL, 0); 332 break; 333 case IMSG_CTL_LOG_VERBOSE: 334 /* already checked by ldpe */ 335 memcpy(&verbose, imsg.data, sizeof(verbose)); 336 log_verbose(verbose); 337 break; 338 default: 339 log_debug("lde_dispatch_imsg: unexpected imsg %d", 340 imsg.hdr.type); 341 break; 342 } 343 imsg_free(&imsg); 344 } 345 if (!shut) 346 imsg_event_add(iev); 347 else { 348 /* this pipe is dead, so remove the event handler */ 349 event_del(&iev->ev); 350 event_loopexit(NULL); 351 } 352 } 353 354 /* ARGSUSED */ 355 void 356 lde_dispatch_parent(int fd, short event, void *bula) 357 { 358 struct imsg imsg; 359 struct kroute kr; 360 struct imsgev *iev = bula; 361 struct imsgbuf *ibuf = &iev->ibuf; 362 ssize_t n; 363 int shut = 0; 364 365 if (event & EV_READ) { 366 if ((n = imsg_read(ibuf)) == -1) 367 fatal("imsg_read error"); 368 if (n == 0) /* connection closed */ 369 shut = 1; 370 } 371 if (event & EV_WRITE) { 372 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 373 fatal("msgbuf_write"); 374 if (n == 0) /* connection closed */ 375 shut = 1; 376 } 377 378 for (;;) { 379 if ((n = imsg_get(ibuf, &imsg)) == -1) 380 fatal("lde_dispatch_parent: imsg_read error"); 381 if (n == 0) 382 break; 383 384 switch (imsg.hdr.type) { 385 case IMSG_NETWORK_ADD: 386 if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(kr)) { 387 log_warnx("lde_dispatch_parent: " 388 "wrong imsg len"); 389 break; 390 } 391 memcpy(&kr, imsg.data, sizeof(kr)); 392 393 lde_kernel_insert(&kr); 394 break; 395 case IMSG_NETWORK_DEL: 396 if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(kr)) { 397 log_warnx("lde_dispatch_parent: " 398 "wrong imsg len"); 399 break; 400 } 401 memcpy(&kr, imsg.data, sizeof(kr)); 402 403 lde_kernel_remove(&kr); 404 break; 405 case IMSG_RECONF_CONF: 406 if ((nconf = malloc(sizeof(struct ldpd_conf))) == 407 NULL) 408 fatal(NULL); 409 memcpy(nconf, imsg.data, sizeof(struct ldpd_conf)); 410 411 break; 412 case IMSG_RECONF_IFACE: 413 break; 414 case IMSG_RECONF_END: 415 break; 416 default: 417 log_debug("lde_dispatch_parent: unexpected imsg %d", 418 imsg.hdr.type); 419 break; 420 } 421 imsg_free(&imsg); 422 } 423 if (!shut) 424 imsg_event_add(iev); 425 else { 426 /* this pipe is dead, so remove the event handler */ 427 event_del(&iev->ev); 428 event_loopexit(NULL); 429 } 430 } 431 432 u_int32_t 433 lde_assign_label(void) 434 { 435 static u_int32_t label = MPLS_LABEL_RESERVED_MAX; 436 437 /* XXX some checks needed */ 438 label++; 439 return label; 440 } 441 442 void 443 lde_send_change_klabel(struct rt_node *rr, struct rt_lsp *rl) 444 { 445 struct kroute kr; 446 447 bzero(&kr, sizeof(kr)); 448 kr.prefix.s_addr = rr->fec.prefix.s_addr; 449 kr.prefixlen = rr->fec.prefixlen; 450 kr.local_label = rr->local_label; 451 452 kr.nexthop.s_addr = rl->nexthop.s_addr; 453 kr.remote_label = rl->remote_label; 454 455 lde_imsg_compose_parent(IMSG_KLABEL_CHANGE, 0, &kr, sizeof(kr)); 456 } 457 458 void 459 lde_send_delete_klabel(struct rt_node *rr, struct rt_lsp *rl) 460 { 461 struct kroute kr; 462 463 bzero(&kr, sizeof(kr)); 464 kr.prefix.s_addr = rr->fec.prefix.s_addr; 465 kr.prefixlen = rr->fec.prefixlen; 466 kr.local_label = rr->local_label; 467 468 kr.nexthop.s_addr = rl->nexthop.s_addr; 469 kr.remote_label = rl->remote_label; 470 471 lde_imsg_compose_parent(IMSG_KLABEL_DELETE, 0, &kr, sizeof(kr)); 472 } 473 474 void 475 lde_send_labelrequest(struct lde_nbr *ln, struct rt_node *rn) 476 { 477 struct map map; 478 479 /* TODO check if status of peer is OK to send requests (SLRq.2 & 6) 480 * For now assume no peer will send no-label-resource notifications */ 481 482 /* check if request is already pending */ 483 if (fec_find(&ln->sent_req, &rn->fec) != NULL) 484 return; 485 /* and try to add request to pending list */ 486 lde_req_add(ln, &rn->fec, 1); 487 /* msgid does not matter since only one req can be pending */ 488 489 bzero(&map, sizeof(map)); 490 map.prefix = rn->fec.prefix; 491 map.prefixlen = rn->fec.prefixlen; 492 493 lde_imsg_compose_ldpe(IMSG_REQUEST_ADD, ln->peerid, 0, 494 &map, sizeof(map)); 495 lde_imsg_compose_ldpe(IMSG_REQUEST_ADD_END, ln->peerid, 0, 496 NULL, 0); 497 } 498 499 void 500 lde_send_labelmapping(struct lde_nbr *ln, struct rt_node *rn) 501 { 502 struct lde_req *lre; 503 struct lde_map *me; 504 struct map map; 505 506 /* 507 * This function skips SL.1 - 3 and SL.9 - 14 because the lable 508 * allocation is done way earlier (because of the merging nature of 509 * ldpd). 510 */ 511 512 bzero(&map, sizeof(map)); 513 map.label = rn->local_label; 514 map.prefix = rn->fec.prefix; 515 map.prefixlen = rn->fec.prefixlen; 516 517 /* is there a pending request for this mapping? */ 518 lre = (struct lde_req *)fec_find(&ln->recv_req, &rn->fec); 519 if (lre) { 520 /* set label request msg id in the mapping response. */ 521 map.requestid = lre->msgid; 522 map.flags = F_MAP_REQ_ID; 523 lde_req_del(ln, lre, 0); 524 } 525 526 me = (struct lde_map *)fec_find(&ln->sent_map, &rn->fec); 527 if (me == NULL) 528 me = lde_map_add(ln, rn, 1); 529 me->label = map.label; 530 531 lde_imsg_compose_ldpe(IMSG_MAPPING_ADD, ln->peerid, 0, 532 &map, sizeof(map)); 533 lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, ln->peerid, 0, 534 NULL, 0); 535 } 536 537 void 538 lde_send_labelrelease(struct lde_nbr *ln, struct rt_node *rn, u_int32_t label) 539 { 540 struct map map; 541 542 bzero(&map, sizeof(map)); 543 map.prefix = rn->fec.prefix; 544 map.prefixlen = rn->fec.prefixlen; 545 if (label != NO_LABEL) { 546 map.flags = F_MAP_OPTLABEL; 547 map.label = label; 548 } 549 550 lde_imsg_compose_ldpe(IMSG_RELEASE_ADD, ln->peerid, 0, 551 &map, sizeof(map)); 552 lde_imsg_compose_ldpe(IMSG_RELEASE_ADD_END, ln->peerid, 0, 553 NULL, 0); 554 } 555 556 void 557 lde_send_notification(u_int32_t peerid, u_int32_t code, u_int32_t msgid, 558 u_int32_t type) 559 { 560 struct notify_msg nm; 561 562 bzero(&nm, sizeof(nm)); 563 564 /* Every field is in host byte order, to keep things clear */ 565 nm.status = code; 566 nm.messageid = ntohl(msgid); 567 nm.type = type; 568 569 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, peerid, 0, 570 &nm, sizeof(nm)); 571 } 572 573 static __inline int lde_nbr_compare(struct lde_nbr *, struct lde_nbr *); 574 575 RB_HEAD(nbr_tree, lde_nbr); 576 RB_PROTOTYPE(nbr_tree, lde_nbr, entry, lde_nbr_compare) 577 RB_GENERATE(nbr_tree, lde_nbr, entry, lde_nbr_compare) 578 579 struct nbr_tree lde_nbrs = RB_INITIALIZER(&lde_nbrs); 580 581 static __inline int 582 lde_nbr_compare(struct lde_nbr *a, struct lde_nbr *b) 583 { 584 return (a->peerid - b->peerid); 585 } 586 587 struct lde_nbr * 588 lde_nbr_find(u_int32_t peerid) 589 { 590 struct lde_nbr n; 591 592 n.peerid = peerid; 593 594 return (RB_FIND(nbr_tree, &lde_nbrs, &n)); 595 } 596 597 struct lde_nbr * 598 lde_nbr_new(u_int32_t peerid, struct in_addr *id) 599 { 600 struct lde_nbr *nbr; 601 602 if ((nbr = calloc(1, sizeof(*nbr))) == NULL) 603 fatal("lde_nbr_new"); 604 605 nbr->id.s_addr = id->s_addr; 606 nbr->peerid = peerid; 607 fec_init(&nbr->recv_map); 608 fec_init(&nbr->sent_map); 609 fec_init(&nbr->recv_req); 610 fec_init(&nbr->sent_req); 611 fec_init(&nbr->sent_wdraw); 612 613 TAILQ_INIT(&nbr->addr_list); 614 615 if (RB_INSERT(nbr_tree, &lde_nbrs, nbr) != NULL) 616 fatalx("lde_nbr_new: RB_INSERT failed"); 617 618 return (nbr); 619 } 620 621 void 622 lde_nbr_del(struct lde_nbr *nbr) 623 { 624 if (nbr == NULL) 625 return; 626 627 lde_address_list_free(nbr); 628 629 fec_clear(&nbr->recv_map, lde_map_free); 630 fec_clear(&nbr->sent_map, lde_map_free); 631 fec_clear(&nbr->recv_req, free); 632 fec_clear(&nbr->sent_req, free); 633 fec_clear(&nbr->sent_wdraw, free); 634 635 RB_REMOVE(nbr_tree, &lde_nbrs, nbr); 636 637 free(nbr); 638 } 639 640 void 641 lde_nbr_clear(void) 642 { 643 struct lde_nbr *nbr; 644 645 while ((nbr = RB_ROOT(&lde_nbrs)) != NULL) 646 lde_nbr_del(nbr); 647 } 648 649 void 650 lde_nbr_do_mappings(struct rt_node *rn) 651 { 652 struct lde_nbr *ln; 653 struct lde_map *me; 654 struct lde_req *lre; 655 656 /* This handles LMp.17-31 for lde_check_mapping() */ 657 658 RB_FOREACH(ln, nbr_tree, &lde_nbrs) { 659 /* LMp.18 Did we already send a mapping to this peer? */ 660 me = (struct lde_map *)fec_find(&ln->sent_map, &rn->fec); 661 if (me && me->label == rn->local_label) 662 /* same mapping already sent, skip */ 663 /* TODO LMp.22-27 Loop detection check */ 664 continue; 665 666 /* LMp.28 Is this from a pending request? */ 667 lre = (struct lde_req *)fec_find(&ln->recv_req, &rn->fec); 668 669 /* Check for the only case where no mapping should be sent. 670 * This is the On Demand case of LMp.29 */ 671 if (ldeconf->mode & MODE_ADV_ONDEMAND && lre == NULL) 672 /* adv. on demand but no req pending, skip */ 673 continue; 674 675 lde_send_labelmapping(ln, rn); 676 /* LMp.30 & 31 are not needed because labels are always added */ 677 } 678 } 679 680 struct lde_map * 681 lde_map_add(struct lde_nbr *ln, struct rt_node *rn, int sent) 682 { 683 struct lde_map *me; 684 685 me = calloc(1, sizeof(*me)); 686 if (me == NULL) 687 fatal("lde_map_add"); 688 689 me->fec = rn->fec; 690 me->nexthop = ln; 691 692 if (sent) { 693 LIST_INSERT_HEAD(&rn->upstream, me, entry); 694 if (fec_insert(&ln->sent_map, &me->fec)) 695 log_warnx("failed to add %s/%u to sent map", 696 inet_ntoa(me->fec.prefix), me->fec.prefixlen); 697 /* XXX on failure more cleanup is needed */ 698 } else { 699 LIST_INSERT_HEAD(&rn->downstream, me, entry); 700 if (fec_insert(&ln->recv_map, &me->fec)) 701 log_warnx("failed to add %s/%u to recv map", 702 inet_ntoa(me->fec.prefix), me->fec.prefixlen); 703 } 704 705 return (me); 706 } 707 708 void 709 lde_map_del(struct lde_nbr *ln, struct lde_map *me, int sent) 710 { 711 if (sent) 712 fec_remove(&ln->sent_map, &me->fec); 713 else 714 fec_remove(&ln->recv_map, &me->fec); 715 716 lde_map_free(me); 717 } 718 719 void 720 lde_map_free(void *ptr) 721 { 722 struct lde_map *map = ptr; 723 724 LIST_REMOVE(map, entry); 725 free(map); 726 } 727 728 struct lde_req * 729 lde_req_add(struct lde_nbr *ln, struct fec *fec, int sent) 730 { 731 struct fec_tree *ft; 732 struct lde_req *lre; 733 734 ft = sent ? &ln->sent_req : &ln->recv_req; 735 736 lre = calloc(1, sizeof(*lre)); 737 if (lre != NULL) { 738 lre->fec = *fec; 739 740 if (fec_insert(ft, &lre->fec)) { 741 log_warnx("failed to add %s/%u to %s req", 742 inet_ntoa(lre->fec.prefix), lre->fec.prefixlen, 743 sent ? "sent" : "recv"); 744 free(lre); 745 return (NULL); 746 } 747 } 748 749 return (lre); 750 } 751 752 void 753 lde_req_del(struct lde_nbr *ln, struct lde_req *lre, int sent) 754 { 755 if (sent) 756 fec_remove(&ln->sent_req, &lre->fec); 757 else 758 fec_remove(&ln->recv_req, &lre->fec); 759 760 free(lre); 761 } 762 763 int 764 lde_address_add(struct lde_nbr *lr, struct in_addr *addr) 765 { 766 struct lde_nbr_address *address; 767 768 if (lde_address_find(lr, addr) != NULL) 769 return (-1); 770 771 if ((address = calloc(1, sizeof(*address))) == NULL) 772 fatal("lde_address_add"); 773 774 address->addr.s_addr = addr->s_addr; 775 776 TAILQ_INSERT_TAIL(&lr->addr_list, address, entry); 777 778 log_debug("lde_address_add: added %s", inet_ntoa(*addr)); 779 780 return (0); 781 } 782 783 struct lde_nbr_address * 784 lde_address_find(struct lde_nbr *lr, struct in_addr *addr) 785 { 786 struct lde_nbr_address *address = NULL; 787 788 TAILQ_FOREACH(address, &lr->addr_list, entry) { 789 if (address->addr.s_addr == addr->s_addr) 790 return (address); 791 } 792 793 return (NULL); 794 } 795 796 int 797 lde_address_del(struct lde_nbr *lr, struct in_addr *addr) 798 { 799 struct lde_nbr_address *address; 800 801 address = lde_address_find(lr, addr); 802 if (address == NULL) 803 return (-1); 804 805 TAILQ_REMOVE(&lr->addr_list, address, entry); 806 807 free(address); 808 809 log_debug("lde_address_del: deleted %s", inet_ntoa(*addr)); 810 811 return (0); 812 } 813 814 void 815 lde_address_list_free(struct lde_nbr *nbr) 816 { 817 struct lde_nbr_address *addr; 818 819 while ((addr = TAILQ_FIRST(&nbr->addr_list)) != NULL) { 820 TAILQ_REMOVE(&nbr->addr_list, addr, entry); 821 free(addr); 822 } 823 } 824 825 struct lde_nbr * 826 lde_find_address(struct in_addr address) 827 { 828 struct lde_nbr *ln; 829 830 RB_FOREACH(ln, nbr_tree, &lde_nbrs) { 831 if (lde_address_find(ln, &address) != NULL) 832 return (ln); 833 } 834 835 return (NULL); 836 } 837