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