1 /* $OpenBSD: ldpe.c,v 1.70 2016/09/02 17:10:34 renato Exp $ */ 2 3 /* 4 * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> 5 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 6 * Copyright (c) 2004, 2008 Esben Norby <norby@openbsd.org> 7 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 #include <sys/types.h> 23 #include <stdlib.h> 24 #include <signal.h> 25 #include <string.h> 26 #include <pwd.h> 27 #include <unistd.h> 28 #include <arpa/inet.h> 29 #include <errno.h> 30 31 #include "ldpd.h" 32 #include "ldpe.h" 33 #include "lde.h" 34 #include "control.h" 35 #include "log.h" 36 37 static void ldpe_sig_handler(int, short, void *); 38 static __dead void ldpe_shutdown(void); 39 static void ldpe_dispatch_main(int, short, void *); 40 static void ldpe_dispatch_lde(int, short, void *); 41 static void ldpe_dispatch_pfkey(int, short, void *); 42 static void ldpe_setup_sockets(int, int, int, int); 43 static void ldpe_close_sockets(int); 44 static void ldpe_iface_af_ctl(struct ctl_conn *, int, unsigned int); 45 46 struct ldpd_conf *leconf; 47 struct ldpd_sysdep sysdep; 48 49 static struct imsgev *iev_main; 50 static struct imsgev *iev_lde; 51 static struct event pfkey_ev; 52 53 /* ARGSUSED */ 54 static void 55 ldpe_sig_handler(int sig, short event, void *bula) 56 { 57 switch (sig) { 58 case SIGINT: 59 case SIGTERM: 60 ldpe_shutdown(); 61 /* NOTREACHED */ 62 default: 63 fatalx("unexpected signal"); 64 } 65 } 66 67 /* label distribution protocol engine */ 68 void 69 ldpe(int debug, int verbose) 70 { 71 struct passwd *pw; 72 struct event ev_sigint, ev_sigterm; 73 74 leconf = config_new_empty(); 75 76 log_init(debug); 77 log_verbose(verbose); 78 79 setproctitle("ldp engine"); 80 ldpd_process = PROC_LDP_ENGINE; 81 82 /* create ldpd control socket outside chroot */ 83 if (control_init() == -1) 84 fatalx("control socket setup failed"); 85 86 LIST_INIT(&global.addr_list); 87 LIST_INIT(&global.adj_list); 88 TAILQ_INIT(&global.pending_conns); 89 if (inet_pton(AF_INET, AllRouters_v4, &global.mcast_addr_v4) != 1) 90 fatal("inet_pton"); 91 if (inet_pton(AF_INET6, AllRouters_v6, &global.mcast_addr_v6) != 1) 92 fatal("inet_pton"); 93 global.pfkeysock = pfkey_init(); 94 95 if ((pw = getpwnam(LDPD_USER)) == NULL) 96 fatal("getpwnam"); 97 98 if (chroot(pw->pw_dir) == -1) 99 fatal("chroot"); 100 if (chdir("/") == -1) 101 fatal("chdir(\"/\")"); 102 103 if (setgroups(1, &pw->pw_gid) || 104 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 105 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 106 fatal("can't drop privileges"); 107 108 if (pledge("stdio cpath inet mcast recvfd", NULL) == -1) 109 fatal("pledge"); 110 111 event_init(); 112 accept_init(); 113 114 /* setup signal handler */ 115 signal_set(&ev_sigint, SIGINT, ldpe_sig_handler, NULL); 116 signal_set(&ev_sigterm, SIGTERM, ldpe_sig_handler, NULL); 117 signal_add(&ev_sigint, NULL); 118 signal_add(&ev_sigterm, NULL); 119 signal(SIGPIPE, SIG_IGN); 120 signal(SIGHUP, SIG_IGN); 121 122 /* setup pipe and event handler to the parent process */ 123 if ((iev_main = malloc(sizeof(struct imsgev))) == NULL) 124 fatal(NULL); 125 imsg_init(&iev_main->ibuf, 3); 126 iev_main->handler = ldpe_dispatch_main; 127 iev_main->events = EV_READ; 128 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events, 129 iev_main->handler, iev_main); 130 event_add(&iev_main->ev, NULL); 131 132 if (sysdep.no_pfkey == 0) { 133 event_set(&pfkey_ev, global.pfkeysock, EV_READ | EV_PERSIST, 134 ldpe_dispatch_pfkey, NULL); 135 event_add(&pfkey_ev, NULL); 136 } 137 138 /* mark sockets as closed */ 139 global.ipv4.ldp_disc_socket = -1; 140 global.ipv4.ldp_edisc_socket = -1; 141 global.ipv4.ldp_session_socket = -1; 142 global.ipv6.ldp_disc_socket = -1; 143 global.ipv6.ldp_edisc_socket = -1; 144 global.ipv6.ldp_session_socket = -1; 145 146 /* listen on ldpd control socket */ 147 TAILQ_INIT(&ctl_conns); 148 control_listen(); 149 150 if ((pkt_ptr = calloc(1, IBUF_READ_SIZE)) == NULL) 151 fatal(__func__); 152 153 event_dispatch(); 154 155 ldpe_shutdown(); 156 } 157 158 static __dead void 159 ldpe_shutdown(void) 160 { 161 struct if_addr *if_addr; 162 struct adj *adj; 163 164 /* close pipes */ 165 msgbuf_write(&iev_lde->ibuf.w); 166 msgbuf_clear(&iev_lde->ibuf.w); 167 close(iev_lde->ibuf.fd); 168 msgbuf_write(&iev_main->ibuf.w); 169 msgbuf_clear(&iev_main->ibuf.w); 170 close(iev_main->ibuf.fd); 171 172 control_cleanup(); 173 config_clear(leconf); 174 175 if (sysdep.no_pfkey == 0) { 176 event_del(&pfkey_ev); 177 close(global.pfkeysock); 178 } 179 ldpe_close_sockets(AF_INET); 180 ldpe_close_sockets(AF_INET6); 181 182 /* remove addresses from global list */ 183 while ((if_addr = LIST_FIRST(&global.addr_list)) != NULL) { 184 LIST_REMOVE(if_addr, entry); 185 free(if_addr); 186 } 187 while ((adj = LIST_FIRST(&global.adj_list)) != NULL) 188 adj_del(adj, S_SHUTDOWN); 189 190 /* clean up */ 191 free(iev_lde); 192 free(iev_main); 193 free(pkt_ptr); 194 195 log_info("ldp engine exiting"); 196 exit(0); 197 } 198 199 /* imesg */ 200 int 201 ldpe_imsg_compose_parent(int type, pid_t pid, void *data, uint16_t datalen) 202 { 203 return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen)); 204 } 205 206 int 207 ldpe_imsg_compose_lde(int type, uint32_t peerid, pid_t pid, void *data, 208 uint16_t datalen) 209 { 210 return (imsg_compose_event(iev_lde, type, peerid, pid, -1, 211 data, datalen)); 212 } 213 214 /* ARGSUSED */ 215 static void 216 ldpe_dispatch_main(int fd, short event, void *bula) 217 { 218 static struct ldpd_conf *nconf; 219 struct iface *niface; 220 struct tnbr *ntnbr; 221 struct nbr_params *nnbrp; 222 static struct l2vpn *nl2vpn; 223 struct l2vpn_if *nlif; 224 struct l2vpn_pw *npw; 225 struct imsg imsg; 226 struct imsgev *iev = bula; 227 struct imsgbuf *ibuf = &iev->ibuf; 228 struct iface *iface = NULL; 229 struct kif *kif; 230 int af; 231 enum socket_type *socket_type; 232 static int disc_socket = -1; 233 static int edisc_socket = -1; 234 static int session_socket = -1; 235 struct nbr *nbr; 236 struct nbr_params *nbrp; 237 int n, shut = 0; 238 239 if (event & EV_READ) { 240 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 241 fatal("imsg_read error"); 242 if (n == 0) /* connection closed */ 243 shut = 1; 244 } 245 if (event & EV_WRITE) { 246 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 247 fatal("ldpe_dispatch_main: msgbuf_write"); 248 if (n == 0) 249 shut = 1; 250 } 251 252 for (;;) { 253 if ((n = imsg_get(ibuf, &imsg)) == -1) 254 fatal("ldpe_dispatch_main: imsg_get error"); 255 if (n == 0) 256 break; 257 258 switch (imsg.hdr.type) { 259 case IMSG_IFSTATUS: 260 if (imsg.hdr.len != IMSG_HEADER_SIZE + 261 sizeof(struct kif)) 262 fatalx("IFSTATUS imsg with wrong len"); 263 kif = imsg.data; 264 265 iface = if_lookup(leconf, kif->ifindex); 266 if (!iface) 267 break; 268 269 iface->flags = kif->flags; 270 iface->linkstate = kif->link_state; 271 if_update(iface, AF_UNSPEC); 272 break; 273 case IMSG_NEWADDR: 274 if (imsg.hdr.len != IMSG_HEADER_SIZE + 275 sizeof(struct kaddr)) 276 fatalx("NEWADDR imsg with wrong len"); 277 278 if_addr_add(imsg.data); 279 break; 280 case IMSG_DELADDR: 281 if (imsg.hdr.len != IMSG_HEADER_SIZE + 282 sizeof(struct kaddr)) 283 fatalx("DELADDR imsg with wrong len"); 284 285 if_addr_del(imsg.data); 286 break; 287 case IMSG_SOCKET_IPC: 288 if (iev_lde) { 289 log_warnx("%s: received unexpected imsg fd " 290 "to lde", __func__); 291 break; 292 } 293 if ((fd = imsg.fd) == -1) { 294 log_warnx("%s: expected to receive imsg fd to " 295 "lde but didn't receive any", __func__); 296 break; 297 } 298 299 if ((iev_lde = malloc(sizeof(struct imsgev))) == NULL) 300 fatal(NULL); 301 imsg_init(&iev_lde->ibuf, fd); 302 iev_lde->handler = ldpe_dispatch_lde; 303 iev_lde->events = EV_READ; 304 event_set(&iev_lde->ev, iev_lde->ibuf.fd, 305 iev_lde->events, iev_lde->handler, iev_lde); 306 event_add(&iev_lde->ev, NULL); 307 break; 308 case IMSG_CLOSE_SOCKETS: 309 af = imsg.hdr.peerid; 310 311 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) { 312 if (nbr->af != af) 313 continue; 314 session_shutdown(nbr, S_SHUTDOWN, 0, 0); 315 pfkey_remove(nbr); 316 } 317 ldpe_close_sockets(af); 318 if_update_all(af); 319 tnbr_update_all(af); 320 321 disc_socket = -1; 322 edisc_socket = -1; 323 session_socket = -1; 324 if ((ldp_af_conf_get(leconf, af))->flags & 325 F_LDPD_AF_ENABLED) 326 ldpe_imsg_compose_parent(IMSG_REQUEST_SOCKETS, 327 af, NULL, 0); 328 break; 329 case IMSG_SOCKET_NET: 330 if (imsg.hdr.len != IMSG_HEADER_SIZE + 331 sizeof(enum socket_type)) 332 fatalx("SOCKET_NET imsg with wrong len"); 333 socket_type = imsg.data; 334 335 switch (*socket_type) { 336 case LDP_SOCKET_DISC: 337 disc_socket = imsg.fd; 338 break; 339 case LDP_SOCKET_EDISC: 340 edisc_socket = imsg.fd; 341 break; 342 case LDP_SOCKET_SESSION: 343 session_socket = imsg.fd; 344 break; 345 } 346 break; 347 case IMSG_SETUP_SOCKETS: 348 af = imsg.hdr.peerid; 349 if (disc_socket == -1 || edisc_socket == -1 || 350 session_socket == -1) { 351 if (disc_socket != -1) 352 close(disc_socket); 353 if (edisc_socket != -1) 354 close(edisc_socket); 355 if (session_socket != -1) 356 close(session_socket); 357 break; 358 } 359 360 ldpe_setup_sockets(af, disc_socket, edisc_socket, 361 session_socket); 362 if_update_all(af); 363 tnbr_update_all(af); 364 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) { 365 if (nbr->af != af) 366 continue; 367 nbr->laddr = (ldp_af_conf_get(leconf, 368 af))->trans_addr; 369 nbrp = nbr_params_find(leconf, nbr->id); 370 if (nbrp && pfkey_establish(nbr, nbrp) == -1) 371 fatalx("pfkey setup failed"); 372 if (nbr_session_active_role(nbr)) 373 nbr_establish_connection(nbr); 374 } 375 break; 376 case IMSG_RECONF_CONF: 377 if ((nconf = malloc(sizeof(struct ldpd_conf))) == 378 NULL) 379 fatal(NULL); 380 memcpy(nconf, imsg.data, sizeof(struct ldpd_conf)); 381 382 LIST_INIT(&nconf->iface_list); 383 LIST_INIT(&nconf->tnbr_list); 384 LIST_INIT(&nconf->nbrp_list); 385 LIST_INIT(&nconf->l2vpn_list); 386 break; 387 case IMSG_RECONF_IFACE: 388 if ((niface = malloc(sizeof(struct iface))) == NULL) 389 fatal(NULL); 390 memcpy(niface, imsg.data, sizeof(struct iface)); 391 392 LIST_INIT(&niface->addr_list); 393 LIST_INIT(&niface->ipv4.adj_list); 394 LIST_INIT(&niface->ipv6.adj_list); 395 niface->ipv4.iface = niface; 396 niface->ipv6.iface = niface; 397 398 LIST_INSERT_HEAD(&nconf->iface_list, niface, entry); 399 break; 400 case IMSG_RECONF_TNBR: 401 if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL) 402 fatal(NULL); 403 memcpy(ntnbr, imsg.data, sizeof(struct tnbr)); 404 405 LIST_INSERT_HEAD(&nconf->tnbr_list, ntnbr, entry); 406 break; 407 case IMSG_RECONF_NBRP: 408 if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL) 409 fatal(NULL); 410 memcpy(nnbrp, imsg.data, sizeof(struct nbr_params)); 411 412 LIST_INSERT_HEAD(&nconf->nbrp_list, nnbrp, entry); 413 break; 414 case IMSG_RECONF_L2VPN: 415 if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL) 416 fatal(NULL); 417 memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn)); 418 419 LIST_INIT(&nl2vpn->if_list); 420 LIST_INIT(&nl2vpn->pw_list); 421 422 LIST_INSERT_HEAD(&nconf->l2vpn_list, nl2vpn, entry); 423 break; 424 case IMSG_RECONF_L2VPN_IF: 425 if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL) 426 fatal(NULL); 427 memcpy(nlif, imsg.data, sizeof(struct l2vpn_if)); 428 429 nlif->l2vpn = nl2vpn; 430 LIST_INSERT_HEAD(&nl2vpn->if_list, nlif, entry); 431 break; 432 case IMSG_RECONF_L2VPN_PW: 433 if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL) 434 fatal(NULL); 435 memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); 436 437 npw->l2vpn = nl2vpn; 438 LIST_INSERT_HEAD(&nl2vpn->pw_list, npw, entry); 439 break; 440 case IMSG_RECONF_END: 441 merge_config(leconf, nconf); 442 nconf = NULL; 443 global.conf_seqnum++; 444 break; 445 case IMSG_CTL_KROUTE: 446 case IMSG_CTL_KROUTE_ADDR: 447 case IMSG_CTL_IFINFO: 448 case IMSG_CTL_END: 449 control_imsg_relay(&imsg); 450 break; 451 default: 452 log_debug("ldpe_dispatch_main: error handling imsg %d", 453 imsg.hdr.type); 454 break; 455 } 456 imsg_free(&imsg); 457 } 458 if (!shut) 459 imsg_event_add(iev); 460 else { 461 /* this pipe is dead, so remove the event handler */ 462 event_del(&iev->ev); 463 event_loopexit(NULL); 464 } 465 } 466 467 /* ARGSUSED */ 468 static void 469 ldpe_dispatch_lde(int fd, short event, void *bula) 470 { 471 struct imsgev *iev = bula; 472 struct imsgbuf *ibuf = &iev->ibuf; 473 struct imsg imsg; 474 struct map map; 475 struct notify_msg nm; 476 int n, shut = 0; 477 struct nbr *nbr = NULL; 478 479 if (event & EV_READ) { 480 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 481 fatal("imsg_read error"); 482 if (n == 0) /* connection closed */ 483 shut = 1; 484 } 485 if (event & EV_WRITE) { 486 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 487 fatal("ldpe_dispatch_lde: msgbuf_write"); 488 if (n == 0) 489 shut = 1; 490 } 491 492 for (;;) { 493 if ((n = imsg_get(ibuf, &imsg)) == -1) 494 fatal("ldpe_dispatch_lde: imsg_get error"); 495 if (n == 0) 496 break; 497 498 switch (imsg.hdr.type) { 499 case IMSG_MAPPING_ADD: 500 case IMSG_RELEASE_ADD: 501 case IMSG_REQUEST_ADD: 502 case IMSG_WITHDRAW_ADD: 503 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(map)) 504 fatalx("invalid size of map request"); 505 memcpy(&map, imsg.data, sizeof(map)); 506 507 nbr = nbr_find_peerid(imsg.hdr.peerid); 508 if (nbr == NULL) { 509 log_debug("ldpe_dispatch_lde: cannot find " 510 "neighbor"); 511 break; 512 } 513 if (nbr->state != NBR_STA_OPER) 514 break; 515 516 switch (imsg.hdr.type) { 517 case IMSG_MAPPING_ADD: 518 mapping_list_add(&nbr->mapping_list, &map); 519 break; 520 case IMSG_RELEASE_ADD: 521 mapping_list_add(&nbr->release_list, &map); 522 break; 523 case IMSG_REQUEST_ADD: 524 mapping_list_add(&nbr->request_list, &map); 525 break; 526 case IMSG_WITHDRAW_ADD: 527 mapping_list_add(&nbr->withdraw_list, &map); 528 break; 529 } 530 break; 531 case IMSG_MAPPING_ADD_END: 532 case IMSG_RELEASE_ADD_END: 533 case IMSG_REQUEST_ADD_END: 534 case IMSG_WITHDRAW_ADD_END: 535 nbr = nbr_find_peerid(imsg.hdr.peerid); 536 if (nbr == NULL) { 537 log_debug("ldpe_dispatch_lde: cannot find " 538 "neighbor"); 539 break; 540 } 541 if (nbr->state != NBR_STA_OPER) 542 break; 543 544 switch (imsg.hdr.type) { 545 case IMSG_MAPPING_ADD_END: 546 send_labelmessage(nbr, MSG_TYPE_LABELMAPPING, 547 &nbr->mapping_list); 548 break; 549 case IMSG_RELEASE_ADD_END: 550 send_labelmessage(nbr, MSG_TYPE_LABELRELEASE, 551 &nbr->release_list); 552 break; 553 case IMSG_REQUEST_ADD_END: 554 send_labelmessage(nbr, MSG_TYPE_LABELREQUEST, 555 &nbr->request_list); 556 break; 557 case IMSG_WITHDRAW_ADD_END: 558 send_labelmessage(nbr, MSG_TYPE_LABELWITHDRAW, 559 &nbr->withdraw_list); 560 break; 561 } 562 break; 563 case IMSG_NOTIFICATION_SEND: 564 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(nm)) 565 fatalx("invalid size of OE request"); 566 memcpy(&nm, imsg.data, sizeof(nm)); 567 568 nbr = nbr_find_peerid(imsg.hdr.peerid); 569 if (nbr == NULL) { 570 log_debug("ldpe_dispatch_lde: cannot find " 571 "neighbor"); 572 break; 573 } 574 if (nbr->state != NBR_STA_OPER) 575 break; 576 577 send_notification_full(nbr->tcp, &nm); 578 break; 579 case IMSG_CTL_END: 580 case IMSG_CTL_SHOW_LIB: 581 case IMSG_CTL_SHOW_L2VPN_PW: 582 case IMSG_CTL_SHOW_L2VPN_BINDING: 583 control_imsg_relay(&imsg); 584 break; 585 default: 586 log_debug("ldpe_dispatch_lde: error handling imsg %d", 587 imsg.hdr.type); 588 break; 589 } 590 imsg_free(&imsg); 591 } 592 if (!shut) 593 imsg_event_add(iev); 594 else { 595 /* this pipe is dead, so remove the event handler */ 596 event_del(&iev->ev); 597 event_loopexit(NULL); 598 } 599 } 600 601 /* ARGSUSED */ 602 static void 603 ldpe_dispatch_pfkey(int fd, short event, void *bula) 604 { 605 if (event & EV_READ) { 606 if (pfkey_read(fd, NULL) == -1) { 607 fatal("pfkey_read failed, exiting..."); 608 } 609 } 610 } 611 612 static void 613 ldpe_setup_sockets(int af, int disc_socket, int edisc_socket, 614 int session_socket) 615 { 616 struct ldpd_af_global *af_global; 617 618 af_global = ldp_af_global_get(&global, af); 619 620 /* discovery socket */ 621 af_global->ldp_disc_socket = disc_socket; 622 event_set(&af_global->disc_ev, af_global->ldp_disc_socket, 623 EV_READ|EV_PERSIST, disc_recv_packet, NULL); 624 event_add(&af_global->disc_ev, NULL); 625 626 /* extended discovery socket */ 627 af_global->ldp_edisc_socket = edisc_socket; 628 event_set(&af_global->edisc_ev, af_global->ldp_edisc_socket, 629 EV_READ|EV_PERSIST, disc_recv_packet, NULL); 630 event_add(&af_global->edisc_ev, NULL); 631 632 /* session socket */ 633 af_global->ldp_session_socket = session_socket; 634 accept_add(af_global->ldp_session_socket, session_accept, NULL); 635 } 636 637 static void 638 ldpe_close_sockets(int af) 639 { 640 struct ldpd_af_global *af_global; 641 642 af_global = ldp_af_global_get(&global, af); 643 644 /* discovery socket */ 645 if (event_initialized(&af_global->disc_ev)) 646 event_del(&af_global->disc_ev); 647 if (af_global->ldp_disc_socket != -1) { 648 close(af_global->ldp_disc_socket); 649 af_global->ldp_disc_socket = -1; 650 } 651 652 /* extended discovery socket */ 653 if (event_initialized(&af_global->edisc_ev)) 654 event_del(&af_global->edisc_ev); 655 if (af_global->ldp_edisc_socket != -1) { 656 close(af_global->ldp_edisc_socket); 657 af_global->ldp_edisc_socket = -1; 658 } 659 660 /* session socket */ 661 if (af_global->ldp_session_socket != -1) { 662 accept_del(af_global->ldp_session_socket); 663 close(af_global->ldp_session_socket); 664 af_global->ldp_session_socket = -1; 665 } 666 } 667 668 void 669 ldpe_reset_nbrs(int af) 670 { 671 struct nbr *nbr; 672 673 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) { 674 if (nbr->af == af) 675 session_shutdown(nbr, S_SHUTDOWN, 0, 0); 676 } 677 } 678 679 void 680 ldpe_reset_ds_nbrs(void) 681 { 682 struct nbr *nbr; 683 684 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) { 685 if (nbr->ds_tlv) 686 session_shutdown(nbr, S_SHUTDOWN, 0, 0); 687 } 688 } 689 690 void 691 ldpe_remove_dynamic_tnbrs(int af) 692 { 693 struct tnbr *tnbr, *safe; 694 695 LIST_FOREACH_SAFE(tnbr, &leconf->tnbr_list, entry, safe) { 696 if (tnbr->af != af) 697 continue; 698 699 tnbr->flags &= ~F_TNBR_DYNAMIC; 700 tnbr_check(tnbr); 701 } 702 } 703 704 void 705 ldpe_stop_init_backoff(int af) 706 { 707 struct nbr *nbr; 708 709 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) { 710 if (nbr->af == af && nbr_pending_idtimer(nbr)) { 711 nbr_stop_idtimer(nbr); 712 nbr_establish_connection(nbr); 713 } 714 } 715 } 716 717 static void 718 ldpe_iface_af_ctl(struct ctl_conn *c, int af, unsigned int idx) 719 { 720 struct iface *iface; 721 struct iface_af *ia; 722 struct ctl_iface *ictl; 723 724 LIST_FOREACH(iface, &leconf->iface_list, entry) { 725 if (idx == 0 || idx == iface->ifindex) { 726 ia = iface_af_get(iface, af); 727 if (!ia->enabled) 728 continue; 729 730 ictl = if_to_ctl(ia); 731 imsg_compose_event(&c->iev, 732 IMSG_CTL_SHOW_INTERFACE, 733 0, 0, -1, ictl, sizeof(struct ctl_iface)); 734 } 735 } 736 } 737 738 void 739 ldpe_iface_ctl(struct ctl_conn *c, unsigned int idx) 740 { 741 ldpe_iface_af_ctl(c, AF_INET, idx); 742 ldpe_iface_af_ctl(c, AF_INET6, idx); 743 } 744 745 void 746 ldpe_adj_ctl(struct ctl_conn *c) 747 { 748 struct nbr *nbr; 749 struct adj *adj; 750 struct ctl_adj *actl; 751 752 RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) { 753 LIST_FOREACH(adj, &nbr->adj_list, nbr_entry) { 754 actl = adj_to_ctl(adj); 755 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 756 0, 0, -1, actl, sizeof(struct ctl_adj)); 757 } 758 } 759 /* show adjacencies not associated with any neighbor */ 760 LIST_FOREACH(adj, &global.adj_list, global_entry) { 761 if (adj->nbr != NULL) 762 continue; 763 764 actl = adj_to_ctl(adj); 765 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0, 766 -1, actl, sizeof(struct ctl_adj)); 767 } 768 769 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0); 770 } 771 772 void 773 ldpe_nbr_ctl(struct ctl_conn *c) 774 { 775 struct nbr *nbr; 776 struct ctl_nbr *nctl; 777 778 RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) { 779 nctl = nbr_to_ctl(nbr); 780 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl, 781 sizeof(struct ctl_nbr)); 782 } 783 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0); 784 } 785 786 void 787 mapping_list_add(struct mapping_head *mh, struct map *map) 788 { 789 struct mapping_entry *me; 790 791 me = calloc(1, sizeof(*me)); 792 if (me == NULL) 793 fatal(__func__); 794 me->map = *map; 795 796 TAILQ_INSERT_TAIL(mh, me, entry); 797 } 798 799 void 800 mapping_list_clr(struct mapping_head *mh) 801 { 802 struct mapping_entry *me; 803 804 while ((me = TAILQ_FIRST(mh)) != NULL) { 805 TAILQ_REMOVE(mh, me, entry); 806 free(me); 807 } 808 } 809