1*f1b790a5Sclaudio /* $OpenBSD: ldpe.c,v 1.88 2024/11/21 13:38:14 claudio Exp $ */ 2ab0c2486Smichele 3ab0c2486Smichele /* 45dc9330aSrenato * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> 5ab0c2486Smichele * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 6ab0c2486Smichele * Copyright (c) 2004, 2008 Esben Norby <norby@openbsd.org> 7ab0c2486Smichele * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 8ab0c2486Smichele * 9ab0c2486Smichele * Permission to use, copy, modify, and distribute this software for any 10ab0c2486Smichele * purpose with or without fee is hereby granted, provided that the above 11ab0c2486Smichele * copyright notice and this permission notice appear in all copies. 12ab0c2486Smichele * 13ab0c2486Smichele * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14ab0c2486Smichele * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15ab0c2486Smichele * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16ab0c2486Smichele * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17ab0c2486Smichele * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18ab0c2486Smichele * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19ab0c2486Smichele * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20ab0c2486Smichele */ 21ab0c2486Smichele 22ab0c2486Smichele #include <sys/types.h> 23ab0c2486Smichele #include <stdlib.h> 24ab0c2486Smichele #include <signal.h> 25ab0c2486Smichele #include <string.h> 26ab0c2486Smichele #include <pwd.h> 27ab0c2486Smichele #include <unistd.h> 28a8c39dc0Srenato #include <arpa/inet.h> 29ab0c2486Smichele #include <errno.h> 30ab0c2486Smichele 31ab0c2486Smichele #include "ldpd.h" 32ab0c2486Smichele #include "ldpe.h" 33ab0c2486Smichele #include "lde.h" 34ab0c2486Smichele #include "control.h" 35ab0c2486Smichele #include "log.h" 36ab0c2486Smichele 37c28a25a1Srenato static void ldpe_sig_handler(int, short, void *); 38d5e026a8Srenato static __dead void ldpe_shutdown(void); 39c28a25a1Srenato static void ldpe_dispatch_main(int, short, void *); 40c28a25a1Srenato static void ldpe_dispatch_lde(int, short, void *); 41c28a25a1Srenato static void ldpe_dispatch_pfkey(int, short, void *); 42c28a25a1Srenato static void ldpe_setup_sockets(int, int, int, int); 43c28a25a1Srenato static void ldpe_close_sockets(int); 44c28a25a1Srenato static void ldpe_iface_af_ctl(struct ctl_conn *, int, unsigned int); 45ab0c2486Smichele 46c28a25a1Srenato struct ldpd_conf *leconf; 47627846caSrenato struct ldpd_sysdep sysdep; 48ab0c2486Smichele 49c28a25a1Srenato static struct imsgev *iev_main; 50c28a25a1Srenato static struct imsgev *iev_lde; 51c28a25a1Srenato static struct event pfkey_ev; 52c28a25a1Srenato 53c28a25a1Srenato static void 54ab0c2486Smichele ldpe_sig_handler(int sig, short event, void *bula) 55ab0c2486Smichele { 56ab0c2486Smichele switch (sig) { 57ab0c2486Smichele case SIGINT: 58ab0c2486Smichele case SIGTERM: 59ab0c2486Smichele ldpe_shutdown(); 60ab0c2486Smichele /* NOTREACHED */ 61ab0c2486Smichele default: 62ab0c2486Smichele fatalx("unexpected signal"); 63ab0c2486Smichele } 64ab0c2486Smichele } 65ab0c2486Smichele 66ab0c2486Smichele /* label distribution protocol engine */ 67e21b401eSrenato void 68dcaf1165Srenato ldpe(int debug, int verbose, char *sockname) 69ab0c2486Smichele { 70ab0c2486Smichele struct passwd *pw; 71ab0c2486Smichele struct event ev_sigint, ev_sigterm; 72ab0c2486Smichele 7316040b47Srenato leconf = config_new_empty(); 74ab0c2486Smichele 7516040b47Srenato log_init(debug); 7616040b47Srenato log_verbose(verbose); 771b8ec09cSclaudio 781b8ec09cSclaudio setproctitle("ldp engine"); 791b8ec09cSclaudio ldpd_process = PROC_LDP_ENGINE; 802b80d179Sclaudio log_procname = "ldpe"; 811b8ec09cSclaudio 82ab0c2486Smichele /* create ldpd control socket outside chroot */ 83dcaf1165Srenato global.csock = sockname; 84dcaf1165Srenato if (control_init(global.csock) == -1) 85ab0c2486Smichele fatalx("control socket setup failed"); 86ab0c2486Smichele 873de94509Srenato LIST_INIT(&global.addr_list); 88a8c39dc0Srenato LIST_INIT(&global.adj_list); 893de94509Srenato TAILQ_INIT(&global.pending_conns); 90a8c39dc0Srenato if (inet_pton(AF_INET, AllRouters_v4, &global.mcast_addr_v4) != 1) 91a8c39dc0Srenato fatal("inet_pton"); 92a8c39dc0Srenato if (inet_pton(AF_INET6, AllRouters_v6, &global.mcast_addr_v6) != 1) 93a8c39dc0Srenato fatal("inet_pton"); 94c28a25a1Srenato global.pfkeysock = pfkey_init(); 957416d201Srenato 96ab0c2486Smichele if ((pw = getpwnam(LDPD_USER)) == NULL) 97ab0c2486Smichele fatal("getpwnam"); 98ab0c2486Smichele 99ab0c2486Smichele if (chroot(pw->pw_dir) == -1) 100ab0c2486Smichele fatal("chroot"); 101ab0c2486Smichele if (chdir("/") == -1) 102ab0c2486Smichele fatal("chdir(\"/\")"); 103ab0c2486Smichele 104ab0c2486Smichele if (setgroups(1, &pw->pw_gid) || 105ab0c2486Smichele setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 106ab0c2486Smichele setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 107ab0c2486Smichele fatal("can't drop privileges"); 108ab0c2486Smichele 10944e5c375Smestre if (pledge("stdio inet mcast recvfd", NULL) == -1) 11076c6280cSrenato fatal("pledge"); 11176c6280cSrenato 112ab0c2486Smichele event_init(); 1134dda87d0Sclaudio accept_init(); 114ab0c2486Smichele 115ab0c2486Smichele /* setup signal handler */ 116ab0c2486Smichele signal_set(&ev_sigint, SIGINT, ldpe_sig_handler, NULL); 117ab0c2486Smichele signal_set(&ev_sigterm, SIGTERM, ldpe_sig_handler, NULL); 118ab0c2486Smichele signal_add(&ev_sigint, NULL); 119ab0c2486Smichele signal_add(&ev_sigterm, NULL); 120ab0c2486Smichele signal(SIGPIPE, SIG_IGN); 121ab0c2486Smichele signal(SIGHUP, SIG_IGN); 122ab0c2486Smichele 12316040b47Srenato /* setup pipe and event handler to the parent process */ 12416040b47Srenato if ((iev_main = malloc(sizeof(struct imsgev))) == NULL) 125ab0c2486Smichele fatal(NULL); 126*f1b790a5Sclaudio if (imsgbuf_init(&iev_main->ibuf, 3) == -1) 127*f1b790a5Sclaudio fatal(NULL); 128*f1b790a5Sclaudio imsgbuf_allow_fdpass(&iev_main->ibuf); 129cb77742aSpyr iev_main->handler = ldpe_dispatch_main; 130cb77742aSpyr iev_main->events = EV_READ; 131cb77742aSpyr event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events, 132cb77742aSpyr iev_main->handler, iev_main); 133cb77742aSpyr event_add(&iev_main->ev, NULL); 134ab0c2486Smichele 135d810d05aSrenato if (sysdep.no_pfkey == 0) { 1363de94509Srenato event_set(&pfkey_ev, global.pfkeysock, EV_READ | EV_PERSIST, 137627846caSrenato ldpe_dispatch_pfkey, NULL); 138627846caSrenato event_add(&pfkey_ev, NULL); 139d810d05aSrenato } 140627846caSrenato 141b5921293Srenato /* mark sockets as closed */ 142a8c39dc0Srenato global.ipv4.ldp_disc_socket = -1; 143a8c39dc0Srenato global.ipv4.ldp_edisc_socket = -1; 144a8c39dc0Srenato global.ipv4.ldp_session_socket = -1; 145a8c39dc0Srenato global.ipv6.ldp_disc_socket = -1; 146a8c39dc0Srenato global.ipv6.ldp_edisc_socket = -1; 147a8c39dc0Srenato global.ipv6.ldp_session_socket = -1; 148ab0c2486Smichele 149ab0c2486Smichele /* listen on ldpd control socket */ 150ab0c2486Smichele control_listen(); 151ab0c2486Smichele 152ab0c2486Smichele event_dispatch(); 153ab0c2486Smichele 154ab0c2486Smichele ldpe_shutdown(); 155ab0c2486Smichele } 156ab0c2486Smichele 157d5e026a8Srenato static __dead void 158ab0c2486Smichele ldpe_shutdown(void) 159ab0c2486Smichele { 160b9b5a6c8Srenato struct if_addr *if_addr; 161a8c39dc0Srenato struct adj *adj; 16217cc0810Srenato 163d5e026a8Srenato /* close pipes */ 164dd7efffeSclaudio imsgbuf_write(&iev_lde->ibuf); 1659cbf9e90Sclaudio imsgbuf_clear(&iev_lde->ibuf); 166d5e026a8Srenato close(iev_lde->ibuf.fd); 167dd7efffeSclaudio imsgbuf_write(&iev_main->ibuf); 1689cbf9e90Sclaudio imsgbuf_clear(&iev_main->ibuf); 169d5e026a8Srenato close(iev_main->ibuf.fd); 170d5e026a8Srenato 171b0e92afdSmestre control_cleanup(); 1723df4d07bSrenato config_clear(leconf); 173dbbaa7d2Srenato 174d810d05aSrenato if (sysdep.no_pfkey == 0) { 1757416d201Srenato event_del(&pfkey_ev); 1763de94509Srenato close(global.pfkeysock); 177d810d05aSrenato } 178a8c39dc0Srenato ldpe_close_sockets(AF_INET); 179a8c39dc0Srenato ldpe_close_sockets(AF_INET6); 180ab0c2486Smichele 181b9b5a6c8Srenato /* remove addresses from global list */ 1823de94509Srenato while ((if_addr = LIST_FIRST(&global.addr_list)) != NULL) { 183b9b5a6c8Srenato LIST_REMOVE(if_addr, entry); 184b9b5a6c8Srenato free(if_addr); 185b9b5a6c8Srenato } 186a8c39dc0Srenato while ((adj = LIST_FIRST(&global.adj_list)) != NULL) 187e373a269Srenato adj_del(adj, S_SHUTDOWN); 188b9b5a6c8Srenato 189ab0c2486Smichele /* clean up */ 190cb77742aSpyr free(iev_lde); 191cb77742aSpyr free(iev_main); 192ab0c2486Smichele 193ab0c2486Smichele log_info("ldp engine exiting"); 194220e0715Srenato exit(0); 195ab0c2486Smichele } 196ab0c2486Smichele 197ab0c2486Smichele /* imesg */ 198ab0c2486Smichele int 1993de94509Srenato ldpe_imsg_compose_parent(int type, pid_t pid, void *data, uint16_t datalen) 200ab0c2486Smichele { 201cb77742aSpyr return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen)); 202ab0c2486Smichele } 203ab0c2486Smichele 204ab0c2486Smichele int 2053de94509Srenato ldpe_imsg_compose_lde(int type, uint32_t peerid, pid_t pid, void *data, 2063de94509Srenato uint16_t datalen) 207ab0c2486Smichele { 208cb77742aSpyr return (imsg_compose_event(iev_lde, type, peerid, pid, -1, 209cb77742aSpyr data, datalen)); 210ab0c2486Smichele } 211ab0c2486Smichele 212c28a25a1Srenato static void 213ab0c2486Smichele ldpe_dispatch_main(int fd, short event, void *bula) 214ab0c2486Smichele { 215c28a25a1Srenato static struct ldpd_conf *nconf; 216be87e4d3Srenato struct iface *niface; 217be87e4d3Srenato struct tnbr *ntnbr; 218be87e4d3Srenato struct nbr_params *nnbrp; 21938e65088Srenato static struct l2vpn *l2vpn, *nl2vpn; 22038e65088Srenato struct l2vpn_if *lif = NULL, *nlif; 2216399cec1Srenato struct l2vpn_pw *npw; 222ab0c2486Smichele struct imsg imsg; 223cb77742aSpyr struct imsgev *iev = bula; 224cb77742aSpyr struct imsgbuf *ibuf = &iev->ibuf; 225ab0c2486Smichele struct iface *iface = NULL; 226ab0c2486Smichele struct kif *kif; 227a8c39dc0Srenato int af; 228b5921293Srenato enum socket_type *socket_type; 229b5921293Srenato static int disc_socket = -1; 230b5921293Srenato static int edisc_socket = -1; 231b5921293Srenato static int session_socket = -1; 2325a7df819Srenato struct nbr *nbr; 233814e607dSclaudio int n, shut = 0; 234ab0c2486Smichele 235ab0c2486Smichele if (event & EV_READ) { 236668e5ba9Sclaudio if ((n = imsgbuf_read(ibuf)) == -1) 237dd7efffeSclaudio fatal("imsgbuf_read error"); 238ab0c2486Smichele if (n == 0) /* connection closed */ 239ab0c2486Smichele shut = 1; 240ab0c2486Smichele } 241ab0c2486Smichele if (event & EV_WRITE) { 242dd7efffeSclaudio if (imsgbuf_write(ibuf) == -1) { 243c1aa9554Sclaudio if (errno == EPIPE) /* connection closed */ 2441203692fSkrw shut = 1; 245c1aa9554Sclaudio else 246dd7efffeSclaudio fatal("imsgbuf_write"); 247c1aa9554Sclaudio } 248ab0c2486Smichele } 249ab0c2486Smichele 250ab0c2486Smichele for (;;) { 251ab0c2486Smichele if ((n = imsg_get(ibuf, &imsg)) == -1) 252ae7f1740Sclaudio fatal("ldpe_dispatch_main: imsg_get error"); 253ab0c2486Smichele if (n == 0) 254ab0c2486Smichele break; 255ab0c2486Smichele 256ab0c2486Smichele switch (imsg.hdr.type) { 257814e607dSclaudio case IMSG_IFSTATUS: 258ab0c2486Smichele if (imsg.hdr.len != IMSG_HEADER_SIZE + 259ab0c2486Smichele sizeof(struct kif)) 260b9b5a6c8Srenato fatalx("IFSTATUS imsg with wrong len"); 261814e607dSclaudio kif = imsg.data; 26219fce358Srenato 263be87e4d3Srenato iface = if_lookup(leconf, kif->ifindex); 26438e65088Srenato if (iface) { 265ab0c2486Smichele iface->flags = kif->flags; 266ab0c2486Smichele iface->linkstate = kif->link_state; 267a8c39dc0Srenato if_update(iface, AF_UNSPEC); 268814e607dSclaudio break; 26938e65088Srenato } 27038e65088Srenato 27138e65088Srenato LIST_FOREACH(l2vpn, &leconf->l2vpn_list, entry) { 27238e65088Srenato lif = l2vpn_if_find(l2vpn, kif->ifindex); 27338e65088Srenato if (lif) { 27438e65088Srenato lif->flags = kif->flags; 27538e65088Srenato lif->linkstate = kif->link_state; 27638e65088Srenato memcpy(lif->mac, kif->mac, 27738e65088Srenato sizeof(lif->mac)); 27838e65088Srenato l2vpn_if_update(lif); 27938e65088Srenato break; 28038e65088Srenato } 28138e65088Srenato } 28238e65088Srenato break; 283814e607dSclaudio case IMSG_NEWADDR: 284814e607dSclaudio if (imsg.hdr.len != IMSG_HEADER_SIZE + 285814e607dSclaudio sizeof(struct kaddr)) 286814e607dSclaudio fatalx("NEWADDR imsg with wrong len"); 287814e607dSclaudio 2883de94509Srenato if_addr_add(imsg.data); 289ab0c2486Smichele break; 290814e607dSclaudio case IMSG_DELADDR: 291814e607dSclaudio if (imsg.hdr.len != IMSG_HEADER_SIZE + 292814e607dSclaudio sizeof(struct kaddr)) 293814e607dSclaudio fatalx("DELADDR imsg with wrong len"); 294814e607dSclaudio 2953de94509Srenato if_addr_del(imsg.data); 296814e607dSclaudio break; 29716040b47Srenato case IMSG_SOCKET_IPC: 29816040b47Srenato if (iev_lde) { 29916040b47Srenato log_warnx("%s: received unexpected imsg fd " 30016040b47Srenato "to lde", __func__); 30116040b47Srenato break; 30216040b47Srenato } 3034bba3f27Sclaudio if ((fd = imsg_get_fd(&imsg)) == -1) { 30416040b47Srenato log_warnx("%s: expected to receive imsg fd to " 30516040b47Srenato "lde but didn't receive any", __func__); 30616040b47Srenato break; 30716040b47Srenato } 30816040b47Srenato 30916040b47Srenato if ((iev_lde = malloc(sizeof(struct imsgev))) == NULL) 31016040b47Srenato fatal(NULL); 311*f1b790a5Sclaudio if (imsgbuf_init(&iev_lde->ibuf, fd) == -1) 312*f1b790a5Sclaudio fatal(NULL); 31316040b47Srenato iev_lde->handler = ldpe_dispatch_lde; 31416040b47Srenato iev_lde->events = EV_READ; 31516040b47Srenato event_set(&iev_lde->ev, iev_lde->ibuf.fd, 31616040b47Srenato iev_lde->events, iev_lde->handler, iev_lde); 31716040b47Srenato event_add(&iev_lde->ev, NULL); 31816040b47Srenato break; 319b5921293Srenato case IMSG_CLOSE_SOCKETS: 320a8c39dc0Srenato af = imsg.hdr.peerid; 321a8c39dc0Srenato 3225a7df819Srenato RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) { 3235a7df819Srenato if (nbr->af != af) 3245a7df819Srenato continue; 3255a7df819Srenato session_shutdown(nbr, S_SHUTDOWN, 0, 0); 3265a7df819Srenato pfkey_remove(nbr); 3275a7df819Srenato } 328a8c39dc0Srenato ldpe_close_sockets(af); 329a8c39dc0Srenato if_update_all(af); 330a8c39dc0Srenato tnbr_update_all(af); 331b5921293Srenato 332b5921293Srenato disc_socket = -1; 333b5921293Srenato edisc_socket = -1; 334b5921293Srenato session_socket = -1; 33572b2a41bSrenato if ((ldp_af_conf_get(leconf, af))->flags & 33672b2a41bSrenato F_LDPD_AF_ENABLED) 33772b2a41bSrenato ldpe_imsg_compose_parent(IMSG_REQUEST_SOCKETS, 33872b2a41bSrenato af, NULL, 0); 339b5921293Srenato break; 340b5921293Srenato case IMSG_SOCKET_NET: 341b5921293Srenato if (imsg.hdr.len != IMSG_HEADER_SIZE + 342b5921293Srenato sizeof(enum socket_type)) 343b5921293Srenato fatalx("SOCKET_NET imsg with wrong len"); 344b5921293Srenato socket_type = imsg.data; 345b5921293Srenato 346b5921293Srenato switch (*socket_type) { 347b5921293Srenato case LDP_SOCKET_DISC: 3484bba3f27Sclaudio disc_socket = imsg_get_fd(&imsg); 349b5921293Srenato break; 350b5921293Srenato case LDP_SOCKET_EDISC: 3514bba3f27Sclaudio edisc_socket = imsg_get_fd(&imsg); 352b5921293Srenato break; 353b5921293Srenato case LDP_SOCKET_SESSION: 3544bba3f27Sclaudio session_socket = imsg_get_fd(&imsg); 355b5921293Srenato break; 356b5921293Srenato } 357b5921293Srenato break; 358b5921293Srenato case IMSG_SETUP_SOCKETS: 359a8c39dc0Srenato af = imsg.hdr.peerid; 360b5921293Srenato if (disc_socket == -1 || edisc_socket == -1 || 361b5921293Srenato session_socket == -1) { 362b5921293Srenato if (disc_socket != -1) 363b5921293Srenato close(disc_socket); 364b5921293Srenato if (edisc_socket != -1) 365b5921293Srenato close(edisc_socket); 366b5921293Srenato if (session_socket != -1) 367b5921293Srenato close(session_socket); 368b5921293Srenato break; 369b5921293Srenato } 370b5921293Srenato 371a8c39dc0Srenato ldpe_setup_sockets(af, disc_socket, edisc_socket, 372b5921293Srenato session_socket); 373a8c39dc0Srenato if_update_all(af); 374a8c39dc0Srenato tnbr_update_all(af); 3755a7df819Srenato RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) { 3765a7df819Srenato if (nbr->af != af) 3775a7df819Srenato continue; 3785a7df819Srenato nbr->laddr = (ldp_af_conf_get(leconf, 3795a7df819Srenato af))->trans_addr; 3807ee91690Sdlg if (pfkey_establish(nconf, nbr) == -1) 3815a7df819Srenato fatalx("pfkey setup failed"); 3825a7df819Srenato if (nbr_session_active_role(nbr)) 3835a7df819Srenato nbr_establish_connection(nbr); 3845a7df819Srenato } 385b5921293Srenato break; 386ab0c2486Smichele case IMSG_RECONF_CONF: 387be87e4d3Srenato if ((nconf = malloc(sizeof(struct ldpd_conf))) == 388be87e4d3Srenato NULL) 389be87e4d3Srenato fatal(NULL); 390be87e4d3Srenato memcpy(nconf, imsg.data, sizeof(struct ldpd_conf)); 391be87e4d3Srenato 392be87e4d3Srenato LIST_INIT(&nconf->iface_list); 393be87e4d3Srenato LIST_INIT(&nconf->tnbr_list); 394be87e4d3Srenato LIST_INIT(&nconf->nbrp_list); 3956399cec1Srenato LIST_INIT(&nconf->l2vpn_list); 3967ee91690Sdlg LIST_INIT(&nconf->auth_list); 397ab0c2486Smichele break; 398ab0c2486Smichele case IMSG_RECONF_IFACE: 399be87e4d3Srenato if ((niface = malloc(sizeof(struct iface))) == NULL) 400be87e4d3Srenato fatal(NULL); 401be87e4d3Srenato memcpy(niface, imsg.data, sizeof(struct iface)); 402be87e4d3Srenato 403be87e4d3Srenato LIST_INIT(&niface->addr_list); 404a8c39dc0Srenato LIST_INIT(&niface->ipv4.adj_list); 405a8c39dc0Srenato LIST_INIT(&niface->ipv6.adj_list); 406a8c39dc0Srenato niface->ipv4.iface = niface; 407a8c39dc0Srenato niface->ipv6.iface = niface; 408be87e4d3Srenato 409be87e4d3Srenato LIST_INSERT_HEAD(&nconf->iface_list, niface, entry); 410be87e4d3Srenato break; 411be87e4d3Srenato case IMSG_RECONF_TNBR: 412be87e4d3Srenato if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL) 413be87e4d3Srenato fatal(NULL); 414be87e4d3Srenato memcpy(ntnbr, imsg.data, sizeof(struct tnbr)); 415be87e4d3Srenato 416be87e4d3Srenato LIST_INSERT_HEAD(&nconf->tnbr_list, ntnbr, entry); 417be87e4d3Srenato break; 418be87e4d3Srenato case IMSG_RECONF_NBRP: 419be87e4d3Srenato if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL) 420be87e4d3Srenato fatal(NULL); 421be87e4d3Srenato memcpy(nnbrp, imsg.data, sizeof(struct nbr_params)); 422be87e4d3Srenato 423be87e4d3Srenato LIST_INSERT_HEAD(&nconf->nbrp_list, nnbrp, entry); 424ab0c2486Smichele break; 4256399cec1Srenato case IMSG_RECONF_L2VPN: 4266399cec1Srenato if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL) 4276399cec1Srenato fatal(NULL); 4286399cec1Srenato memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn)); 4296399cec1Srenato 4306399cec1Srenato LIST_INIT(&nl2vpn->if_list); 4316399cec1Srenato LIST_INIT(&nl2vpn->pw_list); 4326399cec1Srenato 4336399cec1Srenato LIST_INSERT_HEAD(&nconf->l2vpn_list, nl2vpn, entry); 4346399cec1Srenato break; 4356399cec1Srenato case IMSG_RECONF_L2VPN_IF: 4366399cec1Srenato if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL) 4376399cec1Srenato fatal(NULL); 4386399cec1Srenato memcpy(nlif, imsg.data, sizeof(struct l2vpn_if)); 4396399cec1Srenato 4406399cec1Srenato nlif->l2vpn = nl2vpn; 4416399cec1Srenato LIST_INSERT_HEAD(&nl2vpn->if_list, nlif, entry); 4426399cec1Srenato break; 4436399cec1Srenato case IMSG_RECONF_L2VPN_PW: 4446399cec1Srenato if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL) 4456399cec1Srenato fatal(NULL); 4466399cec1Srenato memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); 4476399cec1Srenato 4486399cec1Srenato npw->l2vpn = nl2vpn; 4496399cec1Srenato LIST_INSERT_HEAD(&nl2vpn->pw_list, npw, entry); 4506399cec1Srenato break; 4517ee91690Sdlg case IMSG_RECONF_CONF_AUTH: { 4527ee91690Sdlg struct ldp_auth *auth; 4537ee91690Sdlg 4547ee91690Sdlg auth = malloc(sizeof(*auth)); 4557ee91690Sdlg if (auth == NULL) 4567ee91690Sdlg fatal(NULL); 4577ee91690Sdlg 4587ee91690Sdlg memcpy(auth, imsg.data, sizeof(*auth)); 4597ee91690Sdlg 4607ee91690Sdlg LIST_INSERT_HEAD(&nconf->auth_list, auth, entry); 4617ee91690Sdlg break; 4627ee91690Sdlg } 4637ee91690Sdlg 464ab0c2486Smichele case IMSG_RECONF_END: 465be87e4d3Srenato merge_config(leconf, nconf); 466be87e4d3Srenato nconf = NULL; 4670e35860dSrenato global.conf_seqnum++; 468ab0c2486Smichele break; 469ab0c2486Smichele case IMSG_CTL_KROUTE: 470ab0c2486Smichele case IMSG_CTL_KROUTE_ADDR: 471ab0c2486Smichele case IMSG_CTL_IFINFO: 472ab0c2486Smichele case IMSG_CTL_END: 473ab0c2486Smichele control_imsg_relay(&imsg); 474ab0c2486Smichele break; 475ab0c2486Smichele default: 476ab0c2486Smichele log_debug("ldpe_dispatch_main: error handling imsg %d", 477ab0c2486Smichele imsg.hdr.type); 478ab0c2486Smichele break; 479ab0c2486Smichele } 480ab0c2486Smichele imsg_free(&imsg); 481ab0c2486Smichele } 482ab0c2486Smichele if (!shut) 483cb77742aSpyr imsg_event_add(iev); 484ab0c2486Smichele else { 485ab0c2486Smichele /* this pipe is dead, so remove the event handler */ 486cb77742aSpyr event_del(&iev->ev); 487ab0c2486Smichele event_loopexit(NULL); 488ab0c2486Smichele } 489ab0c2486Smichele } 490ab0c2486Smichele 491c28a25a1Srenato static void 492ab0c2486Smichele ldpe_dispatch_lde(int fd, short event, void *bula) 493ab0c2486Smichele { 494cb77742aSpyr struct imsgev *iev = bula; 495cb77742aSpyr struct imsgbuf *ibuf = &iev->ibuf; 496ab0c2486Smichele struct imsg imsg; 497ab0c2486Smichele struct map map; 4987d508fe8Smichele struct notify_msg nm; 499ab0c2486Smichele int n, shut = 0; 500ab0c2486Smichele struct nbr *nbr = NULL; 501ab0c2486Smichele 502ab0c2486Smichele if (event & EV_READ) { 503668e5ba9Sclaudio if ((n = imsgbuf_read(ibuf)) == -1) 504dd7efffeSclaudio fatal("imsgbuf_read error"); 505ab0c2486Smichele if (n == 0) /* connection closed */ 506ab0c2486Smichele shut = 1; 507ab0c2486Smichele } 508ab0c2486Smichele if (event & EV_WRITE) { 509dd7efffeSclaudio if (imsgbuf_write(ibuf) == -1) { 510c1aa9554Sclaudio if (errno == EPIPE) /* connection closed */ 5111203692fSkrw shut = 1; 512c1aa9554Sclaudio else 513dd7efffeSclaudio fatal("imsgbuf_write"); 514c1aa9554Sclaudio } 515ab0c2486Smichele } 516ab0c2486Smichele 517ab0c2486Smichele for (;;) { 518ab0c2486Smichele if ((n = imsg_get(ibuf, &imsg)) == -1) 519ae7f1740Sclaudio fatal("ldpe_dispatch_lde: imsg_get error"); 520ab0c2486Smichele if (n == 0) 521ab0c2486Smichele break; 522ab0c2486Smichele 523ab0c2486Smichele switch (imsg.hdr.type) { 524ab0c2486Smichele case IMSG_MAPPING_ADD: 52532415746Sclaudio case IMSG_RELEASE_ADD: 52632415746Sclaudio case IMSG_REQUEST_ADD: 527cf483f25Srenato case IMSG_WITHDRAW_ADD: 528ab0c2486Smichele if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(map)) 52932415746Sclaudio fatalx("invalid size of map request"); 530ab0c2486Smichele memcpy(&map, imsg.data, sizeof(map)); 531ab0c2486Smichele 532ab0c2486Smichele nbr = nbr_find_peerid(imsg.hdr.peerid); 533ab0c2486Smichele if (nbr == NULL) { 534ab0c2486Smichele log_debug("ldpe_dispatch_lde: cannot find " 535ab0c2486Smichele "neighbor"); 53612da3e3bSrenato break; 537ab0c2486Smichele } 53853e24948Sclaudio if (nbr->state != NBR_STA_OPER) 53912da3e3bSrenato break; 540ab0c2486Smichele 54132415746Sclaudio switch (imsg.hdr.type) { 54232415746Sclaudio case IMSG_MAPPING_ADD: 5438d99d653Srenato mapping_list_add(&nbr->mapping_list, &map); 544ab0c2486Smichele break; 545ab0c2486Smichele case IMSG_RELEASE_ADD: 5468d99d653Srenato mapping_list_add(&nbr->release_list, &map); 547ab0c2486Smichele break; 54832415746Sclaudio case IMSG_REQUEST_ADD: 5498d99d653Srenato mapping_list_add(&nbr->request_list, &map); 55032415746Sclaudio break; 551cf483f25Srenato case IMSG_WITHDRAW_ADD: 5528d99d653Srenato mapping_list_add(&nbr->withdraw_list, &map); 553cf483f25Srenato break; 55432415746Sclaudio } 55532415746Sclaudio break; 55632415746Sclaudio case IMSG_MAPPING_ADD_END: 557ab0c2486Smichele case IMSG_RELEASE_ADD_END: 55832415746Sclaudio case IMSG_REQUEST_ADD_END: 559cf483f25Srenato case IMSG_WITHDRAW_ADD_END: 560ab0c2486Smichele nbr = nbr_find_peerid(imsg.hdr.peerid); 561ab0c2486Smichele if (nbr == NULL) { 562ab0c2486Smichele log_debug("ldpe_dispatch_lde: cannot find " 563ab0c2486Smichele "neighbor"); 56412da3e3bSrenato break; 565ab0c2486Smichele } 56653e24948Sclaudio if (nbr->state != NBR_STA_OPER) 56712da3e3bSrenato break; 56832415746Sclaudio 56932415746Sclaudio switch (imsg.hdr.type) { 57032415746Sclaudio case IMSG_MAPPING_ADD_END: 571bb21b33cSrenato send_labelmessage(nbr, MSG_TYPE_LABELMAPPING, 572bb21b33cSrenato &nbr->mapping_list); 57332415746Sclaudio break; 57432415746Sclaudio case IMSG_RELEASE_ADD_END: 575bb21b33cSrenato send_labelmessage(nbr, MSG_TYPE_LABELRELEASE, 576bb21b33cSrenato &nbr->release_list); 577ab0c2486Smichele break; 57832415746Sclaudio case IMSG_REQUEST_ADD_END: 579bb21b33cSrenato send_labelmessage(nbr, MSG_TYPE_LABELREQUEST, 580bb21b33cSrenato &nbr->request_list); 58132415746Sclaudio break; 582cf483f25Srenato case IMSG_WITHDRAW_ADD_END: 583cf483f25Srenato send_labelmessage(nbr, MSG_TYPE_LABELWITHDRAW, 584cf483f25Srenato &nbr->withdraw_list); 585cf483f25Srenato break; 58632415746Sclaudio } 58732415746Sclaudio break; 588ab0c2486Smichele case IMSG_NOTIFICATION_SEND: 5897d508fe8Smichele if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(nm)) 590ab0c2486Smichele fatalx("invalid size of OE request"); 5917d508fe8Smichele memcpy(&nm, imsg.data, sizeof(nm)); 592ab0c2486Smichele 593ab0c2486Smichele nbr = nbr_find_peerid(imsg.hdr.peerid); 594ab0c2486Smichele if (nbr == NULL) { 595ab0c2486Smichele log_debug("ldpe_dispatch_lde: cannot find " 596ab0c2486Smichele "neighbor"); 59712da3e3bSrenato break; 598ab0c2486Smichele } 59953e24948Sclaudio if (nbr->state != NBR_STA_OPER) 60012da3e3bSrenato break; 601ab0c2486Smichele 6026399cec1Srenato send_notification_full(nbr->tcp, &nm); 603ab0c2486Smichele break; 604ab0c2486Smichele case IMSG_CTL_END: 605ab0c2486Smichele case IMSG_CTL_SHOW_LIB: 6066399cec1Srenato case IMSG_CTL_SHOW_L2VPN_PW: 6076399cec1Srenato case IMSG_CTL_SHOW_L2VPN_BINDING: 608ab0c2486Smichele control_imsg_relay(&imsg); 609ab0c2486Smichele break; 610ab0c2486Smichele default: 611ab0c2486Smichele log_debug("ldpe_dispatch_lde: error handling imsg %d", 612ab0c2486Smichele imsg.hdr.type); 613ab0c2486Smichele break; 614ab0c2486Smichele } 615ab0c2486Smichele imsg_free(&imsg); 616ab0c2486Smichele } 617ab0c2486Smichele if (!shut) 618cb77742aSpyr imsg_event_add(iev); 619ab0c2486Smichele else { 620ab0c2486Smichele /* this pipe is dead, so remove the event handler */ 621cb77742aSpyr event_del(&iev->ev); 622ab0c2486Smichele event_loopexit(NULL); 623ab0c2486Smichele } 624ab0c2486Smichele } 625ab0c2486Smichele 626c28a25a1Srenato static void 627627846caSrenato ldpe_dispatch_pfkey(int fd, short event, void *bula) 628627846caSrenato { 629627846caSrenato if (event & EV_READ) { 630627846caSrenato if (pfkey_read(fd, NULL) == -1) { 631627846caSrenato fatal("pfkey_read failed, exiting..."); 632627846caSrenato } 633627846caSrenato } 634627846caSrenato } 635627846caSrenato 636c28a25a1Srenato static void 637c28a25a1Srenato ldpe_setup_sockets(int af, int disc_socket, int edisc_socket, 638c28a25a1Srenato int session_socket) 639b5921293Srenato { 640a8c39dc0Srenato struct ldpd_af_global *af_global; 641a8c39dc0Srenato 642a8c39dc0Srenato af_global = ldp_af_global_get(&global, af); 643a8c39dc0Srenato 644b5921293Srenato /* discovery socket */ 645a8c39dc0Srenato af_global->ldp_disc_socket = disc_socket; 646a8c39dc0Srenato event_set(&af_global->disc_ev, af_global->ldp_disc_socket, 647b5921293Srenato EV_READ|EV_PERSIST, disc_recv_packet, NULL); 648a8c39dc0Srenato event_add(&af_global->disc_ev, NULL); 649b5921293Srenato 650b5921293Srenato /* extended discovery socket */ 651a8c39dc0Srenato af_global->ldp_edisc_socket = edisc_socket; 652a8c39dc0Srenato event_set(&af_global->edisc_ev, af_global->ldp_edisc_socket, 653b5921293Srenato EV_READ|EV_PERSIST, disc_recv_packet, NULL); 654a8c39dc0Srenato event_add(&af_global->edisc_ev, NULL); 655b5921293Srenato 656b5921293Srenato /* session socket */ 657a8c39dc0Srenato af_global->ldp_session_socket = session_socket; 658a8c39dc0Srenato accept_add(af_global->ldp_session_socket, session_accept, NULL); 659b5921293Srenato } 660b5921293Srenato 661c28a25a1Srenato static void 662a8c39dc0Srenato ldpe_close_sockets(int af) 663b5921293Srenato { 664a8c39dc0Srenato struct ldpd_af_global *af_global; 665a8c39dc0Srenato 666a8c39dc0Srenato af_global = ldp_af_global_get(&global, af); 667a8c39dc0Srenato 668b5921293Srenato /* discovery socket */ 669a8c39dc0Srenato if (event_initialized(&af_global->disc_ev)) 670a8c39dc0Srenato event_del(&af_global->disc_ev); 671a8c39dc0Srenato if (af_global->ldp_disc_socket != -1) { 672a8c39dc0Srenato close(af_global->ldp_disc_socket); 673a8c39dc0Srenato af_global->ldp_disc_socket = -1; 674b5921293Srenato } 675b5921293Srenato 676b5921293Srenato /* extended discovery socket */ 677a8c39dc0Srenato if (event_initialized(&af_global->edisc_ev)) 678a8c39dc0Srenato event_del(&af_global->edisc_ev); 679a8c39dc0Srenato if (af_global->ldp_edisc_socket != -1) { 680a8c39dc0Srenato close(af_global->ldp_edisc_socket); 681a8c39dc0Srenato af_global->ldp_edisc_socket = -1; 682b5921293Srenato } 683b5921293Srenato 684b5921293Srenato /* session socket */ 685a8c39dc0Srenato if (af_global->ldp_session_socket != -1) { 686a8c39dc0Srenato accept_del(af_global->ldp_session_socket); 687a8c39dc0Srenato close(af_global->ldp_session_socket); 688a8c39dc0Srenato af_global->ldp_session_socket = -1; 689b5921293Srenato } 690b5921293Srenato } 691b5921293Srenato 692b5921293Srenato void 693a8c39dc0Srenato ldpe_reset_nbrs(int af) 69408964f31Srenato { 69508964f31Srenato struct nbr *nbr; 69608964f31Srenato 697a8c39dc0Srenato RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) { 698a8c39dc0Srenato if (nbr->af == af) 69908964f31Srenato session_shutdown(nbr, S_SHUTDOWN, 0, 0); 70008964f31Srenato } 701a8c39dc0Srenato } 70208964f31Srenato 70308964f31Srenato void 704a8c39dc0Srenato ldpe_reset_ds_nbrs(void) 705a8c39dc0Srenato { 706a8c39dc0Srenato struct nbr *nbr; 707a8c39dc0Srenato 708a8c39dc0Srenato RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) { 709a8c39dc0Srenato if (nbr->ds_tlv) 710a8c39dc0Srenato session_shutdown(nbr, S_SHUTDOWN, 0, 0); 711a8c39dc0Srenato } 712a8c39dc0Srenato } 713a8c39dc0Srenato 714a8c39dc0Srenato void 715a8c39dc0Srenato ldpe_remove_dynamic_tnbrs(int af) 7162cba3533Srenato { 7172cba3533Srenato struct tnbr *tnbr, *safe; 7182cba3533Srenato 7192cba3533Srenato LIST_FOREACH_SAFE(tnbr, &leconf->tnbr_list, entry, safe) { 720a8c39dc0Srenato if (tnbr->af != af) 721a8c39dc0Srenato continue; 722a8c39dc0Srenato 7232cba3533Srenato tnbr->flags &= ~F_TNBR_DYNAMIC; 7242cba3533Srenato tnbr_check(tnbr); 7252cba3533Srenato } 7262cba3533Srenato } 7272cba3533Srenato 7282cba3533Srenato void 729a8c39dc0Srenato ldpe_stop_init_backoff(int af) 7302cba3533Srenato { 7312cba3533Srenato struct nbr *nbr; 7322cba3533Srenato 7332cba3533Srenato RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) { 734a8c39dc0Srenato if (nbr->af == af && nbr_pending_idtimer(nbr)) { 7352cba3533Srenato nbr_stop_idtimer(nbr); 7362cba3533Srenato nbr_establish_connection(nbr); 7372cba3533Srenato } 7382cba3533Srenato } 7392cba3533Srenato } 7402cba3533Srenato 741c28a25a1Srenato static void 742a8c39dc0Srenato ldpe_iface_af_ctl(struct ctl_conn *c, int af, unsigned int idx) 74333f6ccfeSrenato { 74433f6ccfeSrenato struct iface *iface; 745a8c39dc0Srenato struct iface_af *ia; 74633f6ccfeSrenato struct ctl_iface *ictl; 74733f6ccfeSrenato 74833f6ccfeSrenato LIST_FOREACH(iface, &leconf->iface_list, entry) { 74933f6ccfeSrenato if (idx == 0 || idx == iface->ifindex) { 750a8c39dc0Srenato ia = iface_af_get(iface, af); 751a8c39dc0Srenato if (!ia->enabled) 752a8c39dc0Srenato continue; 753a8c39dc0Srenato 754a8c39dc0Srenato ictl = if_to_ctl(ia); 75502a212eeSrenato imsg_compose_event(&c->iev, IMSG_CTL_SHOW_INTERFACE, 75633f6ccfeSrenato 0, 0, -1, ictl, sizeof(struct ctl_iface)); 75733f6ccfeSrenato } 75833f6ccfeSrenato } 75933f6ccfeSrenato } 76033f6ccfeSrenato 76133f6ccfeSrenato void 762a8c39dc0Srenato ldpe_iface_ctl(struct ctl_conn *c, unsigned int idx) 763a8c39dc0Srenato { 764a8c39dc0Srenato ldpe_iface_af_ctl(c, AF_INET, idx); 765a8c39dc0Srenato ldpe_iface_af_ctl(c, AF_INET6, idx); 766a8c39dc0Srenato } 767a8c39dc0Srenato 768a8c39dc0Srenato void 76933f6ccfeSrenato ldpe_adj_ctl(struct ctl_conn *c) 77033f6ccfeSrenato { 771a8c39dc0Srenato struct nbr *nbr; 77233f6ccfeSrenato struct adj *adj; 77333f6ccfeSrenato struct ctl_adj *actl; 77433f6ccfeSrenato 775a8c39dc0Srenato RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) { 776a8c39dc0Srenato LIST_FOREACH(adj, &nbr->adj_list, nbr_entry) { 77733f6ccfeSrenato actl = adj_to_ctl(adj); 77833f6ccfeSrenato imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 77933f6ccfeSrenato 0, 0, -1, actl, sizeof(struct ctl_adj)); 78033f6ccfeSrenato } 781a8c39dc0Srenato } 782a8c39dc0Srenato /* show adjacencies not associated with any neighbor */ 783a8c39dc0Srenato LIST_FOREACH(adj, &global.adj_list, global_entry) { 784a8c39dc0Srenato if (adj->nbr != NULL) 785a8c39dc0Srenato continue; 78633f6ccfeSrenato 787a8c39dc0Srenato actl = adj_to_ctl(adj); 788a8c39dc0Srenato imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0, 789a8c39dc0Srenato -1, actl, sizeof(struct ctl_adj)); 79033f6ccfeSrenato } 79133f6ccfeSrenato 79233f6ccfeSrenato imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0); 79333f6ccfeSrenato } 79433f6ccfeSrenato 79533f6ccfeSrenato void 79633f6ccfeSrenato ldpe_nbr_ctl(struct ctl_conn *c) 79733f6ccfeSrenato { 79833f6ccfeSrenato struct nbr *nbr; 79933f6ccfeSrenato struct ctl_nbr *nctl; 80033f6ccfeSrenato 801a8c39dc0Srenato RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) { 80233f6ccfeSrenato nctl = nbr_to_ctl(nbr); 80333f6ccfeSrenato imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl, 80433f6ccfeSrenato sizeof(struct ctl_nbr)); 80533f6ccfeSrenato } 80633f6ccfeSrenato imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0); 80733f6ccfeSrenato } 80833f6ccfeSrenato 80933f6ccfeSrenato void 8108d99d653Srenato mapping_list_add(struct mapping_head *mh, struct map *map) 8118d99d653Srenato { 8128d99d653Srenato struct mapping_entry *me; 8138d99d653Srenato 8148d99d653Srenato me = calloc(1, sizeof(*me)); 8158d99d653Srenato if (me == NULL) 816b7b4db73Srenato fatal(__func__); 8178d99d653Srenato me->map = *map; 8188d99d653Srenato 8198d99d653Srenato TAILQ_INSERT_TAIL(mh, me, entry); 8208d99d653Srenato } 8218d99d653Srenato 8228d99d653Srenato void 8238d99d653Srenato mapping_list_clr(struct mapping_head *mh) 8248d99d653Srenato { 8258d99d653Srenato struct mapping_entry *me; 8268d99d653Srenato 8278d99d653Srenato while ((me = TAILQ_FIRST(mh)) != NULL) { 8288d99d653Srenato TAILQ_REMOVE(mh, me, entry); 8298d99d653Srenato free(me); 8308d99d653Srenato } 8318d99d653Srenato } 832