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