1 /* $OpenBSD: lde.c,v 1.22 2010/10/26 12:08:14 claudio 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 lde_nbr *); 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 if ((pw = getpwnam(LDPD_USER)) == NULL) 100 fatal("getpwnam"); 101 102 if (chroot(pw->pw_dir) == -1) 103 fatal("chroot"); 104 if (chdir("/") == -1) 105 fatal("chdir(\"/\")"); 106 107 setproctitle("label decision engine"); 108 ldpd_process = PROC_LDE_ENGINE; 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 int 178 lde_imsg_compose_ldpe(int type, u_int32_t peerid, pid_t pid, void *data, 179 u_int16_t datalen) 180 { 181 return (imsg_compose_event(iev_ldpe, type, peerid, pid, 182 -1, data, datalen)); 183 } 184 185 /* ARGSUSED */ 186 void 187 lde_dispatch_imsg(int fd, short event, void *bula) 188 { 189 struct imsgev *iev = bula; 190 struct imsgbuf *ibuf = &iev->ibuf; 191 struct imsg imsg; 192 struct lde_nbr rn, *nbr; 193 struct map map; 194 struct timespec tp; 195 struct in_addr addr; 196 ssize_t n; 197 time_t now; 198 int state, shut = 0, verbose; 199 200 if (event & EV_READ) { 201 if ((n = imsg_read(ibuf)) == -1) 202 fatal("imsg_read error"); 203 if (n == 0) /* connection closed */ 204 shut = 1; 205 } 206 if (event & EV_WRITE) { 207 if (msgbuf_write(&ibuf->w) == -1) 208 fatal("msgbuf_write"); 209 } 210 211 clock_gettime(CLOCK_MONOTONIC, &tp); 212 now = tp.tv_sec; 213 214 for (;;) { 215 if ((n = imsg_get(ibuf, &imsg)) == -1) 216 fatal("lde_dispatch_imsg: imsg_read error"); 217 if (n == 0) 218 break; 219 220 switch (imsg.hdr.type) { 221 case IMSG_LABEL_MAPPING_FULL: 222 nbr = lde_nbr_find(imsg.hdr.peerid); 223 if (nbr == NULL) { 224 log_debug("lde_dispatch_imsg: cannot find " 225 "lde neighbor"); 226 return; 227 } 228 229 rt_snap(nbr); 230 lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, 231 imsg.hdr.peerid, 0, NULL, 0); 232 break; 233 case IMSG_LABEL_MAPPING: 234 case IMSG_LABEL_REQUEST: 235 case IMSG_LABEL_RELEASE: 236 case IMSG_LABEL_WITHDRAW: 237 case IMSG_LABEL_ABORT: 238 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(map)) 239 fatalx("invalid size of OE request"); 240 memcpy(&map, imsg.data, sizeof(map)); 241 242 nbr = lde_nbr_find(imsg.hdr.peerid); 243 if (nbr == NULL) { 244 log_debug("lde_dispatch_imsg: cannot find " 245 "lde neighbor"); 246 return; 247 } 248 249 switch (imsg.hdr.type) { 250 case IMSG_LABEL_MAPPING: 251 lde_check_mapping(&map, nbr); 252 break; 253 case IMSG_LABEL_REQUEST: 254 lde_check_request(&map, nbr); 255 break; 256 case IMSG_LABEL_RELEASE: 257 lde_check_release(&map, nbr); 258 break; 259 case IMSG_LABEL_WITHDRAW: 260 lde_check_withdraw(&map, nbr); 261 break; 262 default: 263 log_warnx("type %d not yet handled. nbr %s", 264 imsg.hdr.type, inet_ntoa(nbr->id)); 265 } 266 break; 267 case IMSG_ADDRESS_ADD: 268 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(addr)) 269 fatalx("invalid size of OE request"); 270 memcpy(&addr, imsg.data, sizeof(addr)); 271 272 nbr = lde_nbr_find(imsg.hdr.peerid); 273 if (nbr == NULL) { 274 log_debug("lde_dispatch_imsg: cannot find " 275 "lde neighbor"); 276 return; 277 } 278 279 if (lde_address_add(nbr, &addr) < 0) { 280 log_debug("lde_dispatch_imsg: cannot add " 281 "address %s, it already exists", 282 inet_ntoa(addr)); 283 } 284 285 break; 286 case IMSG_ADDRESS_DEL: 287 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(addr)) 288 fatalx("invalid size of OE request"); 289 memcpy(&addr, imsg.data, sizeof(addr)); 290 291 nbr = lde_nbr_find(imsg.hdr.peerid); 292 if (nbr == NULL) { 293 log_debug("lde_dispatch_imsg: cannot find " 294 "lde neighbor"); 295 return; 296 } 297 298 if (lde_address_del(nbr, &addr) < 0) { 299 log_debug("lde_dispatch_imsg: cannot delete " 300 "address %s, it does not exists", 301 inet_ntoa(addr)); 302 } 303 304 break; 305 case IMSG_NEIGHBOR_UP: 306 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(rn)) 307 fatalx("invalid size of OE request"); 308 memcpy(&rn, imsg.data, sizeof(rn)); 309 310 if (lde_nbr_find(imsg.hdr.peerid)) 311 fatalx("lde_dispatch_imsg: " 312 "neighbor already exists"); 313 lde_nbr_new(imsg.hdr.peerid, &rn); 314 break; 315 case IMSG_NEIGHBOR_DOWN: 316 lde_nbr_del(lde_nbr_find(imsg.hdr.peerid)); 317 break; 318 case IMSG_NEIGHBOR_CHANGE: 319 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(state)) 320 fatalx("invalid size of OE request"); 321 memcpy(&state, imsg.data, sizeof(state)); 322 323 nbr = lde_nbr_find(imsg.hdr.peerid); 324 if (nbr == NULL) 325 break; 326 327 nbr->state = state; 328 break; 329 case IMSG_CTL_SHOW_LIB: 330 rt_dump(imsg.hdr.pid); 331 332 imsg_compose_event(iev_ldpe, IMSG_CTL_END, 0, 333 imsg.hdr.pid, -1, NULL, 0); 334 break; 335 case IMSG_CTL_LOG_VERBOSE: 336 /* already checked by ldpe */ 337 memcpy(&verbose, imsg.data, sizeof(verbose)); 338 log_verbose(verbose); 339 break; 340 default: 341 log_debug("lde_dispatch_imsg: unexpected imsg %d", 342 imsg.hdr.type); 343 break; 344 } 345 imsg_free(&imsg); 346 } 347 if (!shut) 348 imsg_event_add(iev); 349 else { 350 /* this pipe is dead, so remove the event handler */ 351 event_del(&iev->ev); 352 event_loopexit(NULL); 353 } 354 } 355 356 /* ARGSUSED */ 357 void 358 lde_dispatch_parent(int fd, short event, void *bula) 359 { 360 struct imsg imsg; 361 struct kroute kr; 362 struct imsgev *iev = bula; 363 struct imsgbuf *ibuf = &iev->ibuf; 364 ssize_t n; 365 int shut = 0; 366 367 if (event & EV_READ) { 368 if ((n = imsg_read(ibuf)) == -1) 369 fatal("imsg_read error"); 370 if (n == 0) /* connection closed */ 371 shut = 1; 372 } 373 if (event & EV_WRITE) { 374 if (msgbuf_write(&ibuf->w) == -1) 375 fatal("msgbuf_write"); 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 imsg_compose_event(iev_main, IMSG_KLABEL_CHANGE, 0, 0, -1, 456 &kr, sizeof(kr)); 457 } 458 459 void 460 lde_send_delete_klabel(struct rt_node *rr, struct rt_lsp *rl) 461 { 462 struct kroute kr; 463 464 bzero(&kr, sizeof(kr)); 465 kr.prefix.s_addr = rr->fec.prefix.s_addr; 466 kr.prefixlen = rr->fec.prefixlen; 467 kr.local_label = rr->local_label; 468 469 kr.nexthop.s_addr = rl->nexthop.s_addr; 470 kr.remote_label = rl->remote_label; 471 472 imsg_compose_event(iev_main, IMSG_KLABEL_DELETE, 0, 0, -1, 473 &kr, sizeof(kr)); 474 } 475 476 void 477 lde_send_labelrequest(struct lde_nbr *ln, struct rt_node *rn) 478 { 479 struct map map; 480 481 /* TODO check if status of peer is OK to send requests (SLRq.2 & 6) 482 * For now assume no peer will send no-label-resource notifications */ 483 484 /* check if request is already pending */ 485 if (fec_find(&ln->sent_req, &rn->fec) != NULL) 486 return; 487 /* and try to add request to pending list */ 488 lde_req_add(ln, &rn->fec, 1); 489 /* msgid does not matter since only one req can be pending */ 490 491 bzero(&map, sizeof(map)); 492 map.prefix = rn->fec.prefix; 493 map.prefixlen = rn->fec.prefixlen; 494 495 imsg_compose_event(iev_ldpe, IMSG_REQUEST_ADD, ln->peerid, 0, 496 -1, &map, sizeof(map)); 497 imsg_compose_event(iev_ldpe, IMSG_REQUEST_ADD_END, ln->peerid, 0, 498 -1, NULL, 0); 499 } 500 501 void 502 lde_send_labelmapping(struct lde_nbr *ln, struct rt_node *rn) 503 { 504 struct lde_req *lre; 505 struct lde_map *me; 506 struct map map; 507 508 /* 509 * This function skips SL.1 - 3 and SL.9 - 14 because the lable 510 * allocation is done way earlier (because of the merging nature of 511 * ldpd). 512 */ 513 514 bzero(&map, sizeof(map)); 515 map.label = rn->local_label; 516 map.prefix = rn->fec.prefix; 517 map.prefixlen = rn->fec.prefixlen; 518 519 /* is there a pending request for this mapping? */ 520 lre = (struct lde_req *)fec_find(&ln->recv_req, &rn->fec); 521 if (lre) { 522 /* set label request msg id in the mapping response. */ 523 map.requestid = lre->msgid; 524 map.flags = F_MAP_REQ_ID; 525 lde_req_del(ln, lre, 0); 526 } 527 528 me = (struct lde_map *)fec_find(&ln->sent_map, &rn->fec); 529 if (me == NULL) 530 me = lde_map_add(ln, rn, 1); 531 me->label = map.label; 532 533 imsg_compose_event(iev_ldpe, IMSG_MAPPING_ADD, ln->peerid, 0, 534 -1, &map, sizeof(map)); 535 imsg_compose_event(iev_ldpe, IMSG_MAPPING_ADD_END, ln->peerid, 0, 536 -1, NULL, 0); 537 } 538 539 void 540 lde_send_labelrelease(struct lde_nbr *ln, struct rt_node *rn, u_int32_t label) 541 { 542 struct map map; 543 544 bzero(&map, sizeof(map)); 545 map.prefix = rn->fec.prefix; 546 map.prefixlen = rn->fec.prefixlen; 547 if (label != NO_LABEL) { 548 map.flags = F_MAP_OPTLABEL; 549 map.label = label; 550 } 551 552 imsg_compose_event(iev_ldpe, IMSG_RELEASE_ADD, ln->peerid, 0, 553 -1, &map, sizeof(map)); 554 imsg_compose_event(iev_ldpe, IMSG_RELEASE_ADD_END, ln->peerid, 0, 555 -1, NULL, 0); 556 } 557 558 void 559 lde_send_notification(u_int32_t peerid, u_int32_t code, u_int32_t msgid, 560 u_int32_t type) 561 { 562 struct notify_msg nm; 563 564 bzero(&nm, sizeof(nm)); 565 566 /* Every field is in host byte order, to keep things clear */ 567 nm.status = code; 568 nm.messageid = ntohl(msgid); 569 nm.type = type; 570 571 imsg_compose_event(iev_ldpe, IMSG_NOTIFICATION_SEND, peerid, 0, 572 -1, &nm, sizeof(nm)); 573 } 574 575 static __inline int lde_nbr_compare(struct lde_nbr *, struct lde_nbr *); 576 577 RB_HEAD(nbr_tree, lde_nbr); 578 RB_PROTOTYPE(nbr_tree, lde_nbr, entry, lde_nbr_compare) 579 RB_GENERATE(nbr_tree, lde_nbr, entry, lde_nbr_compare) 580 581 struct nbr_tree lde_nbrs = RB_INITIALIZER(&lde_nbrs); 582 583 static __inline int 584 lde_nbr_compare(struct lde_nbr *a, struct lde_nbr *b) 585 { 586 return (a->peerid - b->peerid); 587 } 588 589 struct lde_nbr * 590 lde_nbr_find(u_int32_t peerid) 591 { 592 struct lde_nbr n; 593 594 n.peerid = peerid; 595 596 return (RB_FIND(nbr_tree, &lde_nbrs, &n)); 597 } 598 599 struct lde_nbr * 600 lde_nbr_new(u_int32_t peerid, struct lde_nbr *new) 601 { 602 struct lde_nbr *nbr; 603 604 if (lde_nbr_find(peerid)) 605 return (NULL); 606 607 if ((nbr = calloc(1, sizeof(*nbr))) == NULL) 608 fatal("lde_nbr_new"); 609 610 memcpy(nbr, new, sizeof(*nbr)); 611 nbr->peerid = peerid; 612 fec_init(&nbr->recv_map); 613 fec_init(&nbr->sent_map); 614 fec_init(&nbr->recv_req); 615 fec_init(&nbr->sent_req); 616 fec_init(&nbr->sent_wdraw); 617 618 TAILQ_INIT(&nbr->addr_list); 619 620 if (RB_INSERT(nbr_tree, &lde_nbrs, nbr) != NULL) 621 fatalx("lde_nbr_new: RB_INSERT failed"); 622 623 return (nbr); 624 } 625 626 void 627 lde_nbr_del(struct lde_nbr *nbr) 628 { 629 if (nbr == NULL) 630 return; 631 632 lde_address_list_free(nbr); 633 634 fec_clear(&nbr->recv_map, lde_map_free); 635 fec_clear(&nbr->sent_map, lde_map_free); 636 fec_clear(&nbr->recv_req, free); 637 fec_clear(&nbr->sent_req, free); 638 fec_clear(&nbr->sent_wdraw, free); 639 640 RB_REMOVE(nbr_tree, &lde_nbrs, nbr); 641 642 free(nbr); 643 } 644 645 void 646 lde_nbr_clear(void) 647 { 648 struct lde_nbr *nbr; 649 650 while ((nbr = RB_ROOT(&lde_nbrs)) != NULL) 651 lde_nbr_del(nbr); 652 } 653 654 void 655 lde_nbr_do_mappings(struct rt_node *rn) 656 { 657 struct lde_nbr *ln; 658 struct lde_map *me; 659 struct lde_req *lre; 660 661 /* This handles LMp.17-31 for lde_check_mapping() */ 662 663 RB_FOREACH(ln, nbr_tree, &lde_nbrs) { 664 /* LMp.18 Did we already send a mapping to this peer? */ 665 me = (struct lde_map *)fec_find(&ln->sent_map, &rn->fec); 666 if (me && me->label == rn->local_label) 667 /* same mapping already sent, skip */ 668 /* TODO LMp.22-27 Loop detection check */ 669 continue; 670 671 /* LMp.28 Is this from a pending request? */ 672 lre = (struct lde_req *)fec_find(&ln->recv_req, &rn->fec); 673 674 /* Check for the only case where no mapping should be sent. 675 * This is the On Demand case of LMp.29 */ 676 if (ldeconf->mode & MODE_ADV_ONDEMAND && lre == NULL) 677 /* adv. on demand but no req pending, skip */ 678 continue; 679 680 lde_send_labelmapping(ln, rn); 681 /* LMp.30 & 31 are not needed because labels are always added */ 682 } 683 } 684 685 struct lde_map * 686 lde_map_add(struct lde_nbr *ln, struct rt_node *rn, int sent) 687 { 688 struct lde_map *me; 689 690 me = calloc(1, sizeof(*me)); 691 if (me == NULL) 692 fatal("lde_map_add"); 693 694 me->fec = rn->fec; 695 me->nexthop = ln; 696 697 if (sent) { 698 LIST_INSERT_HEAD(&rn->upstream, me, entry); 699 if (fec_insert(&ln->sent_map, &me->fec)) 700 log_warnx("failed to add %s/%u to sent map", 701 inet_ntoa(me->fec.prefix), me->fec.prefixlen); 702 /* XXX on failure more cleanup is needed */ 703 } else { 704 LIST_INSERT_HEAD(&rn->downstream, me, entry); 705 if (fec_insert(&ln->recv_map, &me->fec)) 706 log_warnx("failed to add %s/%u to recv map", 707 inet_ntoa(me->fec.prefix), me->fec.prefixlen); 708 } 709 710 return (me); 711 } 712 713 void 714 lde_map_del(struct lde_nbr *ln, struct lde_map *me, int sent) 715 { 716 if (sent) 717 fec_remove(&ln->sent_map, &me->fec); 718 else 719 fec_remove(&ln->recv_map, &me->fec); 720 721 lde_map_free(me); 722 } 723 724 void 725 lde_map_free(void *ptr) 726 { 727 struct lde_map *map = ptr; 728 729 LIST_REMOVE(map, entry); 730 free(map); 731 } 732 733 struct lde_req * 734 lde_req_add(struct lde_nbr *ln, struct fec *fec, int sent) 735 { 736 struct fec_tree *ft; 737 struct lde_req *lre; 738 739 ft = sent ? &ln->sent_req : &ln->recv_req; 740 741 lre = calloc(1, sizeof(*lre)); 742 if (lre != NULL) { 743 lre->fec = *fec; 744 745 if (fec_insert(ft, &lre->fec)) { 746 log_warnx("failed to add %s/%u to %s req", 747 inet_ntoa(lre->fec.prefix), lre->fec.prefixlen, 748 sent ? "sent" : "recv"); 749 free(lre); 750 return (NULL); 751 } 752 } 753 754 return (lre); 755 } 756 757 void 758 lde_req_del(struct lde_nbr *ln, struct lde_req *lre, int sent) 759 { 760 if (sent) 761 fec_remove(&ln->sent_req, &lre->fec); 762 else 763 fec_remove(&ln->recv_req, &lre->fec); 764 765 free(lre); 766 } 767 768 int 769 lde_address_add(struct lde_nbr *lr, struct in_addr *addr) 770 { 771 struct lde_nbr_address *address; 772 773 if (lde_address_find(lr, addr) != NULL) 774 return (-1); 775 776 if ((address = calloc(1, sizeof(*address))) == NULL) 777 fatal("lde_address_add"); 778 779 address->addr.s_addr = addr->s_addr; 780 781 TAILQ_INSERT_TAIL(&lr->addr_list, address, entry); 782 783 log_debug("lde_address_add: added %s", inet_ntoa(*addr)); 784 785 return (0); 786 } 787 788 struct lde_nbr_address * 789 lde_address_find(struct lde_nbr *lr, struct in_addr *addr) 790 { 791 struct lde_nbr_address *address = NULL; 792 793 TAILQ_FOREACH(address, &lr->addr_list, entry) { 794 if (address->addr.s_addr == addr->s_addr) 795 return (address); 796 } 797 798 return (NULL); 799 } 800 801 int 802 lde_address_del(struct lde_nbr *lr, struct in_addr *addr) 803 { 804 struct lde_nbr_address *address; 805 806 address = lde_address_find(lr, addr); 807 if (address == NULL) 808 return (-1); 809 810 TAILQ_REMOVE(&lr->addr_list, address, entry); 811 812 free(address); 813 814 log_debug("lde_address_del: deleted %s", inet_ntoa(*addr)); 815 816 return (0); 817 } 818 819 void 820 lde_address_list_free(struct lde_nbr *nbr) 821 { 822 struct lde_nbr_address *addr; 823 824 while ((addr = TAILQ_FIRST(&nbr->addr_list)) != NULL) { 825 TAILQ_REMOVE(&nbr->addr_list, addr, entry); 826 free(addr); 827 } 828 } 829 830 struct lde_nbr * 831 lde_find_address(struct in_addr address) 832 { 833 struct lde_nbr *ln; 834 835 RB_FOREACH(ln, nbr_tree, &lde_nbrs) { 836 if (lde_address_find(ln, &address) != NULL) 837 return (ln); 838 } 839 840 return (NULL); 841 } 842