1*f1b790a5Sclaudio /* $OpenBSD: lde.c,v 1.84 2024/11/21 13:38:14 claudio Exp $ */ 2ab0c2486Smichele 3ab0c2486Smichele /* 45dc9330aSrenato * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> 5ab0c2486Smichele * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org> 6ab0c2486Smichele * Copyright (c) 2004 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> 235411bbb6Srenato #include <sys/time.h> 24ab0c2486Smichele #include <sys/socket.h> 25ab0c2486Smichele #include <netinet/in.h> 26e3948831Sclaudio #include <netmpls/mpls.h> 27ab0c2486Smichele #include <arpa/inet.h> 28ab0c2486Smichele #include <errno.h> 29ab0c2486Smichele #include <stdlib.h> 30ab0c2486Smichele #include <signal.h> 31ab0c2486Smichele #include <string.h> 32ab0c2486Smichele #include <pwd.h> 33ab0c2486Smichele #include <unistd.h> 345411bbb6Srenato #include <limits.h> 35ab0c2486Smichele 36ab0c2486Smichele #include "ldp.h" 37ab0c2486Smichele #include "ldpd.h" 38ab0c2486Smichele #include "ldpe.h" 39ab0c2486Smichele #include "log.h" 40ab0c2486Smichele #include "lde.h" 41ab0c2486Smichele 42c28a25a1Srenato static void lde_sig_handler(int sig, short, void *); 43d5e026a8Srenato static __dead void lde_shutdown(void); 44c28a25a1Srenato static int lde_imsg_compose_parent(int, pid_t, void *, uint16_t); 45c28a25a1Srenato static void lde_dispatch_imsg(int, short, void *); 46c28a25a1Srenato static void lde_dispatch_parent(int, short, void *); 47c28a25a1Srenato static __inline int lde_nbr_compare(struct lde_nbr *, 48c28a25a1Srenato struct lde_nbr *); 49c28a25a1Srenato static struct lde_nbr *lde_nbr_new(uint32_t, struct lde_nbr *); 50c28a25a1Srenato static void lde_nbr_del(struct lde_nbr *); 51c28a25a1Srenato static struct lde_nbr *lde_nbr_find(uint32_t); 52c28a25a1Srenato static void lde_nbr_clear(void); 53ed90b960Srenato static void lde_nbr_addr_update(struct lde_nbr *, 54ed90b960Srenato struct lde_addr *, int); 55c28a25a1Srenato static void lde_map_free(void *); 56c28a25a1Srenato static int lde_address_add(struct lde_nbr *, struct lde_addr *); 57c28a25a1Srenato static int lde_address_del(struct lde_nbr *, struct lde_addr *); 58c28a25a1Srenato static void lde_address_list_free(struct lde_nbr *); 59ab0c2486Smichele 603de94509Srenato RB_GENERATE(nbr_tree, lde_nbr, entry, lde_nbr_compare) 613de94509Srenato 62c28a25a1Srenato struct ldpd_conf *ldeconf; 633de94509Srenato struct nbr_tree lde_nbrs = RB_INITIALIZER(&lde_nbrs); 643de94509Srenato 65c28a25a1Srenato static struct imsgev *iev_ldpe; 66c28a25a1Srenato static struct imsgev *iev_main; 67c28a25a1Srenato 68c28a25a1Srenato static void 69ab0c2486Smichele lde_sig_handler(int sig, short event, void *arg) 70ab0c2486Smichele { 71ab0c2486Smichele /* 72ab0c2486Smichele * signal handler rules don't apply, libevent decouples for us 73ab0c2486Smichele */ 74ab0c2486Smichele 75ab0c2486Smichele switch (sig) { 76ab0c2486Smichele case SIGINT: 77ab0c2486Smichele case SIGTERM: 78ab0c2486Smichele lde_shutdown(); 79ab0c2486Smichele /* NOTREACHED */ 80ab0c2486Smichele default: 81ab0c2486Smichele fatalx("unexpected signal"); 82ab0c2486Smichele } 83ab0c2486Smichele } 84ab0c2486Smichele 85ab0c2486Smichele /* label decision engine */ 86e21b401eSrenato void 8716040b47Srenato lde(int debug, int verbose) 88ab0c2486Smichele { 89ab0c2486Smichele struct event ev_sigint, ev_sigterm; 90ab0c2486Smichele struct timeval now; 91ab0c2486Smichele struct passwd *pw; 92ab0c2486Smichele 9316040b47Srenato ldeconf = config_new_empty(); 94ab0c2486Smichele 9516040b47Srenato log_init(debug); 9616040b47Srenato log_verbose(verbose); 97ab0c2486Smichele 981b8ec09cSclaudio setproctitle("label decision engine"); 991b8ec09cSclaudio ldpd_process = PROC_LDE_ENGINE; 1002b80d179Sclaudio log_procname = "lde"; 1011b8ec09cSclaudio 102ab0c2486Smichele if ((pw = getpwnam(LDPD_USER)) == NULL) 103ab0c2486Smichele fatal("getpwnam"); 104ab0c2486Smichele 105ab0c2486Smichele if (chroot(pw->pw_dir) == -1) 106ab0c2486Smichele fatal("chroot"); 107ab0c2486Smichele if (chdir("/") == -1) 108ab0c2486Smichele fatal("chdir(\"/\")"); 109ab0c2486Smichele 110ab0c2486Smichele if (setgroups(1, &pw->pw_gid) || 111ab0c2486Smichele setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 112ab0c2486Smichele setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 113ab0c2486Smichele fatal("can't drop privileges"); 114ab0c2486Smichele 11516040b47Srenato if (pledge("stdio recvfd", NULL) == -1) 11678497d21Srenato fatal("pledge"); 11778497d21Srenato 118ab0c2486Smichele event_init(); 119ab0c2486Smichele 120ab0c2486Smichele /* setup signal handler */ 121ab0c2486Smichele signal_set(&ev_sigint, SIGINT, lde_sig_handler, NULL); 122ab0c2486Smichele signal_set(&ev_sigterm, SIGTERM, lde_sig_handler, NULL); 123ab0c2486Smichele signal_add(&ev_sigint, NULL); 124ab0c2486Smichele signal_add(&ev_sigterm, NULL); 125ab0c2486Smichele signal(SIGPIPE, SIG_IGN); 126ab0c2486Smichele signal(SIGHUP, SIG_IGN); 127ab0c2486Smichele 12816040b47Srenato /* setup pipe and event handler to the parent process */ 12916040b47Srenato if ((iev_main = malloc(sizeof(struct imsgev))) == NULL) 130ab0c2486Smichele fatal(NULL); 131*f1b790a5Sclaudio if (imsgbuf_init(&iev_main->ibuf, 3) == -1) 132*f1b790a5Sclaudio fatal(NULL); 133*f1b790a5Sclaudio imsgbuf_allow_fdpass(&iev_main->ibuf); 134cb77742aSpyr iev_main->handler = lde_dispatch_parent; 135cb77742aSpyr iev_main->events = EV_READ; 136cb77742aSpyr event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events, 137cb77742aSpyr iev_main->handler, iev_main); 138cb77742aSpyr event_add(&iev_main->ev, NULL); 139ab0c2486Smichele 140b79e02a8Srenato /* setup and start the LIB garbage collector */ 141b79e02a8Srenato evtimer_set(&gc_timer, lde_gc_timer, NULL); 142b79e02a8Srenato lde_gc_start_timer(); 143b79e02a8Srenato 144ab0c2486Smichele gettimeofday(&now, NULL); 1453de94509Srenato global.uptime = now.tv_sec; 146ab0c2486Smichele 147ab0c2486Smichele event_dispatch(); 148ab0c2486Smichele 149ab0c2486Smichele lde_shutdown(); 150ab0c2486Smichele } 151ab0c2486Smichele 152d5e026a8Srenato static __dead void 153ab0c2486Smichele lde_shutdown(void) 154ab0c2486Smichele { 155d5e026a8Srenato /* close pipes */ 1569cbf9e90Sclaudio imsgbuf_clear(&iev_ldpe->ibuf); 157d5e026a8Srenato close(iev_ldpe->ibuf.fd); 1589cbf9e90Sclaudio imsgbuf_clear(&iev_main->ibuf); 159d5e026a8Srenato close(iev_main->ibuf.fd); 160d5e026a8Srenato 161b79e02a8Srenato lde_gc_stop_timer(); 162e3948831Sclaudio lde_nbr_clear(); 1636106bae4Srenato fec_tree_clear(); 164ab0c2486Smichele 16517cc0810Srenato config_clear(ldeconf); 16617cc0810Srenato 167cb77742aSpyr free(iev_ldpe); 168cb77742aSpyr free(iev_main); 169ab0c2486Smichele 170ab0c2486Smichele log_info("label decision engine exiting"); 171220e0715Srenato exit(0); 172ab0c2486Smichele } 173ab0c2486Smichele 174eab950efSrenato /* imesg */ 175c28a25a1Srenato static int 1763de94509Srenato lde_imsg_compose_parent(int type, pid_t pid, void *data, uint16_t datalen) 177eab950efSrenato { 178eab950efSrenato return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen)); 179eab950efSrenato } 180eab950efSrenato 181ab0c2486Smichele int 1823de94509Srenato lde_imsg_compose_ldpe(int type, uint32_t peerid, pid_t pid, void *data, 1833de94509Srenato uint16_t datalen) 184ab0c2486Smichele { 185cb77742aSpyr return (imsg_compose_event(iev_ldpe, type, peerid, pid, 186cb77742aSpyr -1, data, datalen)); 187ab0c2486Smichele } 188ab0c2486Smichele 189c28a25a1Srenato static void 190ab0c2486Smichele lde_dispatch_imsg(int fd, short event, void *bula) 191ab0c2486Smichele { 192cb77742aSpyr struct imsgev *iev = bula; 193cb77742aSpyr struct imsgbuf *ibuf = &iev->ibuf; 194ab0c2486Smichele struct imsg imsg; 1952d825b92Srenato struct lde_nbr *ln; 196ab0c2486Smichele struct map map; 197a8c39dc0Srenato struct lde_addr lde_addr; 1986399cec1Srenato struct notify_msg nm; 199ab0c2486Smichele ssize_t n; 200d5d77daaSclaudio int shut = 0, verbose; 201ab0c2486Smichele 202ab0c2486Smichele if (event & EV_READ) { 203668e5ba9Sclaudio if ((n = imsgbuf_read(ibuf)) == -1) 204dd7efffeSclaudio fatal("imsgbuf_read error"); 205ab0c2486Smichele if (n == 0) /* connection closed */ 206ab0c2486Smichele shut = 1; 207ab0c2486Smichele } 208ab0c2486Smichele if (event & EV_WRITE) { 209dd7efffeSclaudio if (imsgbuf_write(ibuf) == -1) { 210c1aa9554Sclaudio if (errno == EPIPE) /* connection closed */ 2111203692fSkrw shut = 1; 212c1aa9554Sclaudio else 213dd7efffeSclaudio fatal("imsgbuf_write"); 214c1aa9554Sclaudio } 215ab0c2486Smichele } 216ab0c2486Smichele 217ab0c2486Smichele for (;;) { 218ab0c2486Smichele if ((n = imsg_get(ibuf, &imsg)) == -1) 219ae7f1740Sclaudio fatal("lde_dispatch_imsg: imsg_get error"); 220ab0c2486Smichele if (n == 0) 221ab0c2486Smichele break; 222ab0c2486Smichele 223ab0c2486Smichele switch (imsg.hdr.type) { 224ab0c2486Smichele case IMSG_LABEL_MAPPING_FULL: 2253de94509Srenato ln = lde_nbr_find(imsg.hdr.peerid); 2263de94509Srenato if (ln == NULL) { 227b7b4db73Srenato log_debug("%s: cannot find lde neighbor", 228b7b4db73Srenato __func__); 2293de94509Srenato break; 230510d51a3Sclaudio } 231ab0c2486Smichele 2323de94509Srenato fec_snap(ln); 233ab0c2486Smichele break; 2344d839438Sclaudio case IMSG_LABEL_MAPPING: 235ab0c2486Smichele case IMSG_LABEL_REQUEST: 2364d839438Sclaudio case IMSG_LABEL_RELEASE: 2374d839438Sclaudio case IMSG_LABEL_WITHDRAW: 2384d839438Sclaudio case IMSG_LABEL_ABORT: 239ab0c2486Smichele if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(map)) 240d99a8fc3Srenato fatalx("lde_dispatch_imsg: wrong imsg len"); 241ab0c2486Smichele memcpy(&map, imsg.data, sizeof(map)); 242ab0c2486Smichele 2432d825b92Srenato ln = lde_nbr_find(imsg.hdr.peerid); 2442d825b92Srenato if (ln == NULL) { 245b7b4db73Srenato log_debug("%s: cannot find lde neighbor", 246b7b4db73Srenato __func__); 2473de94509Srenato break; 248ab0c2486Smichele } 249ab0c2486Smichele 2504d839438Sclaudio switch (imsg.hdr.type) { 2514d839438Sclaudio case IMSG_LABEL_MAPPING: 2522d825b92Srenato lde_check_mapping(&map, ln); 2534d839438Sclaudio break; 2544d839438Sclaudio case IMSG_LABEL_REQUEST: 2552d825b92Srenato lde_check_request(&map, ln); 256ab0c2486Smichele break; 2574d839438Sclaudio case IMSG_LABEL_RELEASE: 2582d825b92Srenato lde_check_release(&map, ln); 2594d839438Sclaudio break; 260510d51a3Sclaudio case IMSG_LABEL_WITHDRAW: 2612d825b92Srenato lde_check_withdraw(&map, ln); 262510d51a3Sclaudio break; 263cf483f25Srenato case IMSG_LABEL_ABORT: 264cf483f25Srenato /* not necessary */ 265cf483f25Srenato break; 2664d839438Sclaudio } 2674d839438Sclaudio break; 268ab0c2486Smichele case IMSG_ADDRESS_ADD: 269a8c39dc0Srenato if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(lde_addr)) 270d99a8fc3Srenato fatalx("lde_dispatch_imsg: wrong imsg len"); 271a8c39dc0Srenato memcpy(&lde_addr, imsg.data, sizeof(lde_addr)); 272ab0c2486Smichele 2733de94509Srenato ln = lde_nbr_find(imsg.hdr.peerid); 2743de94509Srenato if (ln == NULL) { 275b7b4db73Srenato log_debug("%s: cannot find lde neighbor", 276b7b4db73Srenato __func__); 2773de94509Srenato break; 278ab0c2486Smichele } 279a8c39dc0Srenato if (lde_address_add(ln, &lde_addr) < 0) { 280b7b4db73Srenato log_debug("%s: cannot add address %s, it " 281b7b4db73Srenato "already exists", __func__, 282a8c39dc0Srenato log_addr(lde_addr.af, &lde_addr.addr)); 283ab0c2486Smichele } 284ab0c2486Smichele break; 285ab0c2486Smichele case IMSG_ADDRESS_DEL: 286a8c39dc0Srenato if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(lde_addr)) 287d99a8fc3Srenato fatalx("lde_dispatch_imsg: wrong imsg len"); 288a8c39dc0Srenato memcpy(&lde_addr, imsg.data, sizeof(lde_addr)); 289ab0c2486Smichele 2903de94509Srenato ln = lde_nbr_find(imsg.hdr.peerid); 2913de94509Srenato if (ln == NULL) { 292b7b4db73Srenato log_debug("%s: cannot find lde neighbor", 293b7b4db73Srenato __func__); 2943de94509Srenato break; 295ab0c2486Smichele } 296a8c39dc0Srenato if (lde_address_del(ln, &lde_addr) < 0) { 297b7b4db73Srenato log_debug("%s: cannot delete address %s, it " 298d99a8fc3Srenato "does not exist", __func__, 299a8c39dc0Srenato log_addr(lde_addr.af, &lde_addr.addr)); 300ab0c2486Smichele } 301ab0c2486Smichele break; 3026399cec1Srenato case IMSG_NOTIFICATION: 3036399cec1Srenato if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(nm)) 304d99a8fc3Srenato fatalx("lde_dispatch_imsg: wrong imsg len"); 3056399cec1Srenato memcpy(&nm, imsg.data, sizeof(nm)); 3066399cec1Srenato 3072d825b92Srenato ln = lde_nbr_find(imsg.hdr.peerid); 3082d825b92Srenato if (ln == NULL) { 309b7b4db73Srenato log_debug("%s: cannot find lde neighbor", 310b7b4db73Srenato __func__); 3113de94509Srenato break; 3126399cec1Srenato } 3136399cec1Srenato 31460e1e0e7Srenato switch (nm.status_code) { 3156399cec1Srenato case S_PW_STATUS: 3162d825b92Srenato l2vpn_recv_pw_status(ln, &nm); 3176399cec1Srenato break; 3189246985aSrenato case S_ENDOFLIB: 3199246985aSrenato /* 3209246985aSrenato * Do nothing for now. Should be useful in 3219246985aSrenato * the future when we implement LDP-IGP 3229246985aSrenato * Synchronization (RFC 5443) and Graceful 3239246985aSrenato * Restart (RFC 3478). 3249246985aSrenato */ 3256399cec1Srenato default: 3266399cec1Srenato break; 3276399cec1Srenato } 3286399cec1Srenato break; 329ab0c2486Smichele case IMSG_NEIGHBOR_UP: 330a8c39dc0Srenato if (imsg.hdr.len - IMSG_HEADER_SIZE != 331a8c39dc0Srenato sizeof(struct lde_nbr)) 332d99a8fc3Srenato fatalx("lde_dispatch_imsg: wrong imsg len"); 333ab0c2486Smichele 334ab0c2486Smichele if (lde_nbr_find(imsg.hdr.peerid)) 335ab0c2486Smichele fatalx("lde_dispatch_imsg: " 336ab0c2486Smichele "neighbor already exists"); 33719fce358Srenato lde_nbr_new(imsg.hdr.peerid, imsg.data); 338ab0c2486Smichele break; 339ab0c2486Smichele case IMSG_NEIGHBOR_DOWN: 340ab0c2486Smichele lde_nbr_del(lde_nbr_find(imsg.hdr.peerid)); 341ab0c2486Smichele break; 342ab0c2486Smichele case IMSG_CTL_SHOW_LIB: 343ab0c2486Smichele rt_dump(imsg.hdr.pid); 344ab0c2486Smichele 345eab950efSrenato lde_imsg_compose_ldpe(IMSG_CTL_END, 0, 346eab950efSrenato imsg.hdr.pid, NULL, 0); 347ab0c2486Smichele break; 3486399cec1Srenato case IMSG_CTL_SHOW_L2VPN_PW: 3496399cec1Srenato l2vpn_pw_ctl(imsg.hdr.pid); 3506399cec1Srenato 3516399cec1Srenato lde_imsg_compose_ldpe(IMSG_CTL_END, 0, 3526399cec1Srenato imsg.hdr.pid, NULL, 0); 3536399cec1Srenato break; 3546399cec1Srenato case IMSG_CTL_SHOW_L2VPN_BINDING: 3556399cec1Srenato l2vpn_binding_ctl(imsg.hdr.pid); 3566399cec1Srenato 3576399cec1Srenato lde_imsg_compose_ldpe(IMSG_CTL_END, 0, 3586399cec1Srenato imsg.hdr.pid, NULL, 0); 3596399cec1Srenato break; 3607dc5fe12Sclaudio case IMSG_CTL_LOG_VERBOSE: 3617dc5fe12Sclaudio /* already checked by ldpe */ 3627dc5fe12Sclaudio memcpy(&verbose, imsg.data, sizeof(verbose)); 3637dc5fe12Sclaudio log_verbose(verbose); 3647dc5fe12Sclaudio break; 365ab0c2486Smichele default: 366b7b4db73Srenato log_debug("%s: unexpected imsg %d", __func__, 367ab0c2486Smichele imsg.hdr.type); 368ab0c2486Smichele break; 369ab0c2486Smichele } 370ab0c2486Smichele imsg_free(&imsg); 371ab0c2486Smichele } 372ab0c2486Smichele if (!shut) 373cb77742aSpyr imsg_event_add(iev); 374ab0c2486Smichele else { 375ab0c2486Smichele /* this pipe is dead, so remove the event handler */ 376cb77742aSpyr event_del(&iev->ev); 377ab0c2486Smichele event_loopexit(NULL); 378ab0c2486Smichele } 379ab0c2486Smichele } 380ab0c2486Smichele 381c28a25a1Srenato static void 382ab0c2486Smichele lde_dispatch_parent(int fd, short event, void *bula) 383ab0c2486Smichele { 384c28a25a1Srenato static struct ldpd_conf *nconf; 385be87e4d3Srenato struct iface *niface; 386be87e4d3Srenato struct tnbr *ntnbr; 387be87e4d3Srenato struct nbr_params *nnbrp; 3886399cec1Srenato static struct l2vpn *nl2vpn; 3896399cec1Srenato struct l2vpn_if *nlif; 3906399cec1Srenato struct l2vpn_pw *npw; 391ab0c2486Smichele struct imsg imsg; 392ab0c2486Smichele struct kroute kr; 393cb77742aSpyr struct imsgev *iev = bula; 394cb77742aSpyr struct imsgbuf *ibuf = &iev->ibuf; 395ab0c2486Smichele ssize_t n; 396ab0c2486Smichele int shut = 0; 3976399cec1Srenato struct fec fec; 398ab0c2486Smichele 399ab0c2486Smichele if (event & EV_READ) { 400668e5ba9Sclaudio if ((n = imsgbuf_read(ibuf)) == -1) 401dd7efffeSclaudio fatal("imsgbuf_read error"); 402ab0c2486Smichele if (n == 0) /* connection closed */ 403ab0c2486Smichele shut = 1; 404ab0c2486Smichele } 405ab0c2486Smichele if (event & EV_WRITE) { 406dd7efffeSclaudio if (imsgbuf_write(ibuf) == -1) { 407c1aa9554Sclaudio if (errno == EPIPE) /* connection closed */ 4081203692fSkrw shut = 1; 409c1aa9554Sclaudio else 410dd7efffeSclaudio fatal("imsgbuf_write"); 411c1aa9554Sclaudio } 412ab0c2486Smichele } 413ab0c2486Smichele 414ab0c2486Smichele for (;;) { 415ab0c2486Smichele if ((n = imsg_get(ibuf, &imsg)) == -1) 416ae7f1740Sclaudio fatal("lde_dispatch_parent: imsg_get error"); 417ab0c2486Smichele if (n == 0) 418ab0c2486Smichele break; 419ab0c2486Smichele 420ab0c2486Smichele switch (imsg.hdr.type) { 421ab0c2486Smichele case IMSG_NETWORK_ADD: 422ab0c2486Smichele case IMSG_NETWORK_DEL: 423ab0c2486Smichele if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(kr)) { 424b7b4db73Srenato log_warnx("%s: wrong imsg len", __func__); 425ab0c2486Smichele break; 426ab0c2486Smichele } 427ab0c2486Smichele memcpy(&kr, imsg.data, sizeof(kr)); 428ab0c2486Smichele 429a8c39dc0Srenato switch (kr.af) { 430a8c39dc0Srenato case AF_INET: 4316399cec1Srenato fec.type = FEC_TYPE_IPV4; 432a8c39dc0Srenato fec.u.ipv4.prefix = kr.prefix.v4; 4336399cec1Srenato fec.u.ipv4.prefixlen = kr.prefixlen; 434a8c39dc0Srenato break; 435a8c39dc0Srenato case AF_INET6: 436a8c39dc0Srenato fec.type = FEC_TYPE_IPV6; 437a8c39dc0Srenato fec.u.ipv6.prefix = kr.prefix.v6; 438a8c39dc0Srenato fec.u.ipv6.prefixlen = kr.prefixlen; 439a8c39dc0Srenato break; 440a8c39dc0Srenato default: 441a8c39dc0Srenato fatalx("lde_dispatch_parent: unknown af"); 442a8c39dc0Srenato } 443a8c39dc0Srenato 444a8c39dc0Srenato switch (imsg.hdr.type) { 445a8c39dc0Srenato case IMSG_NETWORK_ADD: 446a8c39dc0Srenato lde_kernel_insert(&fec, kr.af, &kr.nexthop, 4470c0343b7Srenato kr.priority, kr.flags & F_CONNECTED, NULL); 448a8c39dc0Srenato break; 449a8c39dc0Srenato case IMSG_NETWORK_DEL: 4500c0343b7Srenato lde_kernel_remove(&fec, kr.af, &kr.nexthop, 4510c0343b7Srenato kr.priority); 452a8c39dc0Srenato break; 453a8c39dc0Srenato } 454ab0c2486Smichele break; 45516040b47Srenato case IMSG_SOCKET_IPC: 45616040b47Srenato if (iev_ldpe) { 45716040b47Srenato log_warnx("%s: received unexpected imsg fd " 45816040b47Srenato "to ldpe", __func__); 45916040b47Srenato break; 46016040b47Srenato } 4614bba3f27Sclaudio if ((fd = imsg_get_fd(&imsg)) == -1) { 46216040b47Srenato log_warnx("%s: expected to receive imsg fd to " 46316040b47Srenato "ldpe but didn't receive any", __func__); 46416040b47Srenato break; 46516040b47Srenato } 46616040b47Srenato 46716040b47Srenato if ((iev_ldpe = malloc(sizeof(struct imsgev))) == NULL) 46816040b47Srenato fatal(NULL); 469*f1b790a5Sclaudio if (imsgbuf_init(&iev_ldpe->ibuf, fd) == -1) 470*f1b790a5Sclaudio fatal(NULL); 47116040b47Srenato iev_ldpe->handler = lde_dispatch_imsg; 47216040b47Srenato iev_ldpe->events = EV_READ; 47316040b47Srenato event_set(&iev_ldpe->ev, iev_ldpe->ibuf.fd, 47416040b47Srenato iev_ldpe->events, iev_ldpe->handler, iev_ldpe); 47516040b47Srenato event_add(&iev_ldpe->ev, NULL); 47616040b47Srenato break; 477ab0c2486Smichele case IMSG_RECONF_CONF: 478ab0c2486Smichele if ((nconf = malloc(sizeof(struct ldpd_conf))) == 479ab0c2486Smichele NULL) 480ab0c2486Smichele fatal(NULL); 481ab0c2486Smichele memcpy(nconf, imsg.data, sizeof(struct ldpd_conf)); 482ab0c2486Smichele 483be87e4d3Srenato LIST_INIT(&nconf->iface_list); 484be87e4d3Srenato LIST_INIT(&nconf->tnbr_list); 485be87e4d3Srenato LIST_INIT(&nconf->nbrp_list); 4866399cec1Srenato LIST_INIT(&nconf->l2vpn_list); 4877ee91690Sdlg LIST_INIT(&nconf->auth_list); 488ab0c2486Smichele break; 489ab0c2486Smichele case IMSG_RECONF_IFACE: 490be87e4d3Srenato if ((niface = malloc(sizeof(struct iface))) == NULL) 491be87e4d3Srenato fatal(NULL); 492be87e4d3Srenato memcpy(niface, imsg.data, sizeof(struct iface)); 493be87e4d3Srenato 494be87e4d3Srenato LIST_INIT(&niface->addr_list); 495a8c39dc0Srenato LIST_INIT(&niface->ipv4.adj_list); 496a8c39dc0Srenato LIST_INIT(&niface->ipv6.adj_list); 497a8c39dc0Srenato niface->ipv4.iface = niface; 498a8c39dc0Srenato niface->ipv6.iface = niface; 499be87e4d3Srenato 500be87e4d3Srenato LIST_INSERT_HEAD(&nconf->iface_list, niface, entry); 501be87e4d3Srenato break; 502be87e4d3Srenato case IMSG_RECONF_TNBR: 503be87e4d3Srenato if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL) 504be87e4d3Srenato fatal(NULL); 505be87e4d3Srenato memcpy(ntnbr, imsg.data, sizeof(struct tnbr)); 506be87e4d3Srenato 507be87e4d3Srenato LIST_INSERT_HEAD(&nconf->tnbr_list, ntnbr, entry); 508be87e4d3Srenato break; 509be87e4d3Srenato case IMSG_RECONF_NBRP: 510be87e4d3Srenato if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL) 511be87e4d3Srenato fatal(NULL); 512be87e4d3Srenato memcpy(nnbrp, imsg.data, sizeof(struct nbr_params)); 513be87e4d3Srenato 514be87e4d3Srenato LIST_INSERT_HEAD(&nconf->nbrp_list, nnbrp, entry); 515ab0c2486Smichele break; 5166399cec1Srenato case IMSG_RECONF_L2VPN: 5176399cec1Srenato if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL) 5186399cec1Srenato fatal(NULL); 5196399cec1Srenato memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn)); 5206399cec1Srenato 5216399cec1Srenato LIST_INIT(&nl2vpn->if_list); 5226399cec1Srenato LIST_INIT(&nl2vpn->pw_list); 5236399cec1Srenato 5246399cec1Srenato LIST_INSERT_HEAD(&nconf->l2vpn_list, nl2vpn, entry); 5256399cec1Srenato break; 5266399cec1Srenato case IMSG_RECONF_L2VPN_IF: 5276399cec1Srenato if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL) 5286399cec1Srenato fatal(NULL); 5296399cec1Srenato memcpy(nlif, imsg.data, sizeof(struct l2vpn_if)); 5306399cec1Srenato 5316399cec1Srenato nlif->l2vpn = nl2vpn; 5326399cec1Srenato LIST_INSERT_HEAD(&nl2vpn->if_list, nlif, entry); 5336399cec1Srenato break; 5346399cec1Srenato case IMSG_RECONF_L2VPN_PW: 5356399cec1Srenato if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL) 5366399cec1Srenato fatal(NULL); 5376399cec1Srenato memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); 5386399cec1Srenato 5396399cec1Srenato npw->l2vpn = nl2vpn; 5406399cec1Srenato LIST_INSERT_HEAD(&nl2vpn->pw_list, npw, entry); 5416399cec1Srenato break; 5427ee91690Sdlg case IMSG_RECONF_CONF_AUTH: { 5437ee91690Sdlg struct ldp_auth *auth; 5447ee91690Sdlg 5457ee91690Sdlg auth = malloc(sizeof(*auth)); 5467ee91690Sdlg if (auth == NULL) 5477ee91690Sdlg fatal(NULL); 5487ee91690Sdlg 5497ee91690Sdlg memcpy(auth, imsg.data, sizeof(*auth)); 5507ee91690Sdlg 5517ee91690Sdlg LIST_INSERT_HEAD(&nconf->auth_list, auth, entry); 5527ee91690Sdlg break; 5537ee91690Sdlg } 554ab0c2486Smichele case IMSG_RECONF_END: 555be87e4d3Srenato merge_config(ldeconf, nconf); 556be87e4d3Srenato nconf = NULL; 557ab0c2486Smichele break; 558ab0c2486Smichele default: 559b7b4db73Srenato log_debug("%s: unexpected imsg %d", __func__, 560ab0c2486Smichele imsg.hdr.type); 561ab0c2486Smichele break; 562ab0c2486Smichele } 563ab0c2486Smichele imsg_free(&imsg); 564ab0c2486Smichele } 565ab0c2486Smichele if (!shut) 566cb77742aSpyr imsg_event_add(iev); 567ab0c2486Smichele else { 568ab0c2486Smichele /* this pipe is dead, so remove the event handler */ 569cb77742aSpyr event_del(&iev->ev); 570ab0c2486Smichele event_loopexit(NULL); 571ab0c2486Smichele } 572ab0c2486Smichele } 573ab0c2486Smichele 5743de94509Srenato uint32_t 575e3948831Sclaudio lde_assign_label(void) 576ab0c2486Smichele { 5773de94509Srenato static uint32_t label = MPLS_LABEL_RESERVED_MAX; 578e3948831Sclaudio 579e3948831Sclaudio /* XXX some checks needed */ 580e3948831Sclaudio label++; 58119fce358Srenato return (label); 582ab0c2486Smichele } 583ab0c2486Smichele 584ab0c2486Smichele void 5856106bae4Srenato lde_send_change_klabel(struct fec_node *fn, struct fec_nh *fnh) 586ab0c2486Smichele { 587ab0c2486Smichele struct kroute kr; 5886399cec1Srenato struct kpw kpw; 5896399cec1Srenato struct l2vpn_pw *pw; 590ab0c2486Smichele 5916399cec1Srenato switch (fn->fec.type) { 5926399cec1Srenato case FEC_TYPE_IPV4: 5933de94509Srenato memset(&kr, 0, sizeof(kr)); 594a8c39dc0Srenato kr.af = AF_INET; 595a8c39dc0Srenato kr.prefix.v4 = fn->fec.u.ipv4.prefix; 5966399cec1Srenato kr.prefixlen = fn->fec.u.ipv4.prefixlen; 597a8c39dc0Srenato kr.nexthop.v4 = fnh->nexthop.v4; 5986106bae4Srenato kr.local_label = fn->local_label; 5996106bae4Srenato kr.remote_label = fnh->remote_label; 6000c0343b7Srenato kr.priority = fnh->priority; 601ab0c2486Smichele 6026399cec1Srenato lde_imsg_compose_parent(IMSG_KLABEL_CHANGE, 0, &kr, 6036399cec1Srenato sizeof(kr)); 6046399cec1Srenato 605a8c39dc0Srenato if (fn->fec.u.ipv4.prefixlen == 32) 606a8c39dc0Srenato l2vpn_sync_pws(AF_INET, (union ldpd_addr *) 607a8c39dc0Srenato &fn->fec.u.ipv4.prefix); 608a8c39dc0Srenato break; 609a8c39dc0Srenato case FEC_TYPE_IPV6: 610a8c39dc0Srenato memset(&kr, 0, sizeof(kr)); 611a8c39dc0Srenato kr.af = AF_INET6; 612a8c39dc0Srenato kr.prefix.v6 = fn->fec.u.ipv6.prefix; 613a8c39dc0Srenato kr.prefixlen = fn->fec.u.ipv6.prefixlen; 614a8c39dc0Srenato kr.nexthop.v6 = fnh->nexthop.v6; 615a8c39dc0Srenato kr.local_label = fn->local_label; 616a8c39dc0Srenato kr.remote_label = fnh->remote_label; 6170c0343b7Srenato kr.priority = fnh->priority; 618a8c39dc0Srenato 619a8c39dc0Srenato lde_imsg_compose_parent(IMSG_KLABEL_CHANGE, 0, &kr, 620a8c39dc0Srenato sizeof(kr)); 621a8c39dc0Srenato 622a8c39dc0Srenato if (fn->fec.u.ipv6.prefixlen == 128) 623a8c39dc0Srenato l2vpn_sync_pws(AF_INET6, (union ldpd_addr *) 624a8c39dc0Srenato &fn->fec.u.ipv6.prefix); 6256399cec1Srenato break; 6266399cec1Srenato case FEC_TYPE_PWID: 6276399cec1Srenato if (fn->local_label == NO_LABEL || 6286399cec1Srenato fnh->remote_label == NO_LABEL) 6296399cec1Srenato return; 6306399cec1Srenato 63172bfe95eSrenato pw = (struct l2vpn_pw *) fn->data; 6326399cec1Srenato pw->flags |= F_PW_STATUS_UP; 6336399cec1Srenato 6343de94509Srenato memset(&kpw, 0, sizeof(kpw)); 6356399cec1Srenato kpw.ifindex = pw->ifindex; 6366399cec1Srenato kpw.pw_type = fn->fec.u.pwid.type; 637a8c39dc0Srenato kpw.af = pw->af; 638a8c39dc0Srenato kpw.nexthop = pw->addr; 6396399cec1Srenato kpw.local_label = fn->local_label; 6406399cec1Srenato kpw.remote_label = fnh->remote_label; 6416399cec1Srenato kpw.flags = pw->flags; 6426399cec1Srenato 6436399cec1Srenato lde_imsg_compose_parent(IMSG_KPWLABEL_CHANGE, 0, &kpw, 6446399cec1Srenato sizeof(kpw)); 6456399cec1Srenato break; 6466399cec1Srenato } 647ab0c2486Smichele } 648ab0c2486Smichele 649ab0c2486Smichele void 6506106bae4Srenato lde_send_delete_klabel(struct fec_node *fn, struct fec_nh *fnh) 651ab0c2486Smichele { 652ab0c2486Smichele struct kroute kr; 6536399cec1Srenato struct kpw kpw; 6546399cec1Srenato struct l2vpn_pw *pw; 655ab0c2486Smichele 6566399cec1Srenato switch (fn->fec.type) { 6576399cec1Srenato case FEC_TYPE_IPV4: 6583de94509Srenato memset(&kr, 0, sizeof(kr)); 659a8c39dc0Srenato kr.af = AF_INET; 660a8c39dc0Srenato kr.prefix.v4 = fn->fec.u.ipv4.prefix; 6616399cec1Srenato kr.prefixlen = fn->fec.u.ipv4.prefixlen; 662a8c39dc0Srenato kr.nexthop.v4 = fnh->nexthop.v4; 6636106bae4Srenato kr.local_label = fn->local_label; 6646106bae4Srenato kr.remote_label = fnh->remote_label; 6650c0343b7Srenato kr.priority = fnh->priority; 666ab0c2486Smichele 6676399cec1Srenato lde_imsg_compose_parent(IMSG_KLABEL_DELETE, 0, &kr, 6686399cec1Srenato sizeof(kr)); 6696399cec1Srenato 6706399cec1Srenato if (fn->fec.u.ipv4.prefixlen == 32) 671a8c39dc0Srenato l2vpn_sync_pws(AF_INET, (union ldpd_addr *) 672a8c39dc0Srenato &fn->fec.u.ipv4.prefix); 673a8c39dc0Srenato break; 674a8c39dc0Srenato case FEC_TYPE_IPV6: 675a8c39dc0Srenato memset(&kr, 0, sizeof(kr)); 676a8c39dc0Srenato kr.af = AF_INET6; 677a8c39dc0Srenato kr.prefix.v6 = fn->fec.u.ipv6.prefix; 678a8c39dc0Srenato kr.prefixlen = fn->fec.u.ipv6.prefixlen; 679a8c39dc0Srenato kr.nexthop.v6 = fnh->nexthop.v6; 680a8c39dc0Srenato kr.local_label = fn->local_label; 681a8c39dc0Srenato kr.remote_label = fnh->remote_label; 6820c0343b7Srenato kr.priority = fnh->priority; 683a8c39dc0Srenato 684a8c39dc0Srenato lde_imsg_compose_parent(IMSG_KLABEL_DELETE, 0, &kr, 685a8c39dc0Srenato sizeof(kr)); 686a8c39dc0Srenato 687a8c39dc0Srenato if (fn->fec.u.ipv6.prefixlen == 128) 688a8c39dc0Srenato l2vpn_sync_pws(AF_INET6, (union ldpd_addr *) 689a8c39dc0Srenato &fn->fec.u.ipv6.prefix); 6906399cec1Srenato break; 6916399cec1Srenato case FEC_TYPE_PWID: 69272bfe95eSrenato pw = (struct l2vpn_pw *) fn->data; 6936399cec1Srenato if (!(pw->flags & F_PW_STATUS_UP)) 6946399cec1Srenato return; 6956399cec1Srenato pw->flags &= ~F_PW_STATUS_UP; 6966399cec1Srenato 6973de94509Srenato memset(&kpw, 0, sizeof(kpw)); 6986399cec1Srenato kpw.ifindex = pw->ifindex; 6996399cec1Srenato kpw.pw_type = fn->fec.u.pwid.type; 700a8c39dc0Srenato kpw.af = pw->af; 701a8c39dc0Srenato kpw.nexthop = pw->addr; 7026399cec1Srenato kpw.local_label = fn->local_label; 7036399cec1Srenato kpw.remote_label = fnh->remote_label; 7046399cec1Srenato kpw.flags = pw->flags; 7056399cec1Srenato 7066399cec1Srenato lde_imsg_compose_parent(IMSG_KPWLABEL_DELETE, 0, &kpw, 7076399cec1Srenato sizeof(kpw)); 7086399cec1Srenato break; 7096399cec1Srenato } 710ab0c2486Smichele } 711ab0c2486Smichele 712ab0c2486Smichele void 7136399cec1Srenato lde_fec2map(struct fec *fec, struct map *map) 7146399cec1Srenato { 7153de94509Srenato memset(map, 0, sizeof(*map)); 7166399cec1Srenato 7176399cec1Srenato switch (fec->type) { 7186399cec1Srenato case FEC_TYPE_IPV4: 719cf09440fSrenato map->type = MAP_TYPE_PREFIX; 72000f5e67fSrenato map->fec.prefix.af = AF_INET; 721a8c39dc0Srenato map->fec.prefix.prefix.v4 = fec->u.ipv4.prefix; 722a8c39dc0Srenato map->fec.prefix.prefixlen = fec->u.ipv4.prefixlen; 723a8c39dc0Srenato break; 724a8c39dc0Srenato case FEC_TYPE_IPV6: 725a8c39dc0Srenato map->type = MAP_TYPE_PREFIX; 72600f5e67fSrenato map->fec.prefix.af = AF_INET6; 727a8c39dc0Srenato map->fec.prefix.prefix.v6 = fec->u.ipv6.prefix; 728a8c39dc0Srenato map->fec.prefix.prefixlen = fec->u.ipv6.prefixlen; 7296399cec1Srenato break; 7306399cec1Srenato case FEC_TYPE_PWID: 731cf09440fSrenato map->type = MAP_TYPE_PWID; 7326399cec1Srenato map->fec.pwid.type = fec->u.pwid.type; 7336399cec1Srenato map->fec.pwid.group_id = 0; 7346399cec1Srenato map->flags |= F_MAP_PW_ID; 7356399cec1Srenato map->fec.pwid.pwid = fec->u.pwid.pwid; 7366399cec1Srenato break; 7376399cec1Srenato } 7386399cec1Srenato } 7396399cec1Srenato 7406399cec1Srenato void 74172bfe95eSrenato lde_map2fec(struct map *map, struct in_addr lsr_id, struct fec *fec) 7426399cec1Srenato { 7433de94509Srenato memset(fec, 0, sizeof(*fec)); 7446399cec1Srenato 7456399cec1Srenato switch (map->type) { 746cf09440fSrenato case MAP_TYPE_PREFIX: 747a8c39dc0Srenato switch (map->fec.prefix.af) { 74800f5e67fSrenato case AF_INET: 7496399cec1Srenato fec->type = FEC_TYPE_IPV4; 750a8c39dc0Srenato fec->u.ipv4.prefix = map->fec.prefix.prefix.v4; 751a8c39dc0Srenato fec->u.ipv4.prefixlen = map->fec.prefix.prefixlen; 752a8c39dc0Srenato break; 75300f5e67fSrenato case AF_INET6: 754a8c39dc0Srenato fec->type = FEC_TYPE_IPV6; 755a8c39dc0Srenato fec->u.ipv6.prefix = map->fec.prefix.prefix.v6; 756a8c39dc0Srenato fec->u.ipv6.prefixlen = map->fec.prefix.prefixlen; 757a8c39dc0Srenato break; 758a8c39dc0Srenato default: 759a8c39dc0Srenato fatalx("lde_map2fec: unknown af"); 760a8c39dc0Srenato break; 761a8c39dc0Srenato } 7626399cec1Srenato break; 763cf09440fSrenato case MAP_TYPE_PWID: 7646399cec1Srenato fec->type = FEC_TYPE_PWID; 7656399cec1Srenato fec->u.pwid.type = map->fec.pwid.type; 7666399cec1Srenato fec->u.pwid.pwid = map->fec.pwid.pwid; 76772bfe95eSrenato fec->u.pwid.lsr_id = lsr_id; 7686399cec1Srenato break; 7696399cec1Srenato } 7706399cec1Srenato } 7716399cec1Srenato 7726399cec1Srenato void 7736399cec1Srenato lde_send_labelmapping(struct lde_nbr *ln, struct fec_node *fn, int single) 774ab0c2486Smichele { 775fb298019Sclaudio struct lde_req *lre; 776fb298019Sclaudio struct lde_map *me; 777fb298019Sclaudio struct map map; 7786399cec1Srenato struct l2vpn_pw *pw; 779fb298019Sclaudio 780fb298019Sclaudio /* 781cf483f25Srenato * This function skips SL.1 - 3 and SL.9 - 14 because the label 782fb298019Sclaudio * allocation is done way earlier (because of the merging nature of 783fb298019Sclaudio * ldpd). 784fb298019Sclaudio */ 785fb298019Sclaudio 7866399cec1Srenato lde_fec2map(&fn->fec, &map); 787a8c39dc0Srenato switch (fn->fec.type) { 788a8c39dc0Srenato case FEC_TYPE_IPV4: 789a8c39dc0Srenato if (!ln->v4_enabled) 790a8c39dc0Srenato return; 791a8c39dc0Srenato break; 792a8c39dc0Srenato case FEC_TYPE_IPV6: 793a8c39dc0Srenato if (!ln->v6_enabled) 794a8c39dc0Srenato return; 795a8c39dc0Srenato break; 796a8c39dc0Srenato case FEC_TYPE_PWID: 79772bfe95eSrenato pw = (struct l2vpn_pw *) fn->data; 79872bfe95eSrenato if (pw == NULL || pw->lsr_id.s_addr != ln->id.s_addr) 79972bfe95eSrenato /* not the remote end of the pseudowire */ 8006399cec1Srenato return; 8016399cec1Srenato 8026399cec1Srenato map.flags |= F_MAP_PW_IFMTU; 8036399cec1Srenato map.fec.pwid.ifmtu = pw->l2vpn->mtu; 8042d825b92Srenato if (pw->flags & F_PW_CWORD) 8056399cec1Srenato map.flags |= F_MAP_PW_CWORD; 8066399cec1Srenato if (pw->flags & F_PW_STATUSTLV) { 8076399cec1Srenato map.flags |= F_MAP_PW_STATUS; 8086399cec1Srenato /* VPLS are always up */ 8096399cec1Srenato map.pw_status = PW_FORWARDING; 8106399cec1Srenato } 811a8c39dc0Srenato break; 8126399cec1Srenato } 8136106bae4Srenato map.label = fn->local_label; 814fb298019Sclaudio 815cf483f25Srenato /* SL.6: is there a pending request for this mapping? */ 8166106bae4Srenato lre = (struct lde_req *)fec_find(&ln->recv_req, &fn->fec); 817fb298019Sclaudio if (lre) { 818fb298019Sclaudio /* set label request msg id in the mapping response. */ 81960e1e0e7Srenato map.requestid = lre->msg_id; 820fb298019Sclaudio map.flags = F_MAP_REQ_ID; 821cf483f25Srenato 822cf483f25Srenato /* SL.7: delete record of pending request */ 823fb298019Sclaudio lde_req_del(ln, lre, 0); 824fb298019Sclaudio } 825fb298019Sclaudio 826cf483f25Srenato /* SL.4: send label mapping */ 827cf483f25Srenato lde_imsg_compose_ldpe(IMSG_MAPPING_ADD, ln->peerid, 0, 828cf483f25Srenato &map, sizeof(map)); 8296399cec1Srenato if (single) 8306399cec1Srenato lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, ln->peerid, 0, 8316399cec1Srenato NULL, 0); 832cf483f25Srenato 833cf483f25Srenato /* SL.5: record sent label mapping */ 8346106bae4Srenato me = (struct lde_map *)fec_find(&ln->sent_map, &fn->fec); 835fb298019Sclaudio if (me == NULL) 8366106bae4Srenato me = lde_map_add(ln, fn, 1); 8377aa09c5dSrenato me->map = map; 838cf483f25Srenato } 839fb298019Sclaudio 840cf483f25Srenato void 8412c06fdf4Srenato lde_send_labelwithdraw(struct lde_nbr *ln, struct fec_node *fn, 8422c06fdf4Srenato struct map *wcard, struct status_tlv *st) 843cf483f25Srenato { 844cf483f25Srenato struct lde_wdraw *lw; 845cf483f25Srenato struct map map; 846cf483f25Srenato struct fec *f; 8476399cec1Srenato struct l2vpn_pw *pw; 8486399cec1Srenato 8496106bae4Srenato if (fn) { 8506399cec1Srenato lde_fec2map(&fn->fec, &map); 851a8c39dc0Srenato switch (fn->fec.type) { 852a8c39dc0Srenato case FEC_TYPE_IPV4: 853a8c39dc0Srenato if (!ln->v4_enabled) 854a8c39dc0Srenato return; 855a8c39dc0Srenato break; 856a8c39dc0Srenato case FEC_TYPE_IPV6: 857a8c39dc0Srenato if (!ln->v6_enabled) 858a8c39dc0Srenato return; 859a8c39dc0Srenato break; 860a8c39dc0Srenato case FEC_TYPE_PWID: 8613de94509Srenato pw = (struct l2vpn_pw *) fn->data; 8623de94509Srenato if (pw == NULL || pw->lsr_id.s_addr != ln->id.s_addr) 8633de94509Srenato /* not the remote end of the pseudowire */ 8643de94509Srenato return; 8653de94509Srenato 8662d825b92Srenato if (pw->flags & F_PW_CWORD) 8676399cec1Srenato map.flags |= F_MAP_PW_CWORD; 868a8c39dc0Srenato break; 8696399cec1Srenato } 870a8c39dc0Srenato map.label = fn->local_label; 8712c06fdf4Srenato } else 8722c06fdf4Srenato memcpy(&map, wcard, sizeof(map)); 873cf483f25Srenato 87460e1e0e7Srenato if (st) { 87560e1e0e7Srenato map.st.status_code = st->status_code; 87660e1e0e7Srenato map.st.msg_id = st->msg_id; 87760e1e0e7Srenato map.st.msg_type = st->msg_type; 8785ba85977Srenato map.flags |= F_MAP_STATUS; 8795ba85977Srenato } 8805ba85977Srenato 881cf483f25Srenato /* SWd.1: send label withdraw. */ 882cf483f25Srenato lde_imsg_compose_ldpe(IMSG_WITHDRAW_ADD, ln->peerid, 0, 883eab950efSrenato &map, sizeof(map)); 884cf483f25Srenato lde_imsg_compose_ldpe(IMSG_WITHDRAW_ADD_END, ln->peerid, 0, NULL, 0); 885cf483f25Srenato 886cf483f25Srenato /* SWd.2: record label withdraw. */ 8876106bae4Srenato if (fn) { 8886106bae4Srenato lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec); 889cf483f25Srenato if (lw == NULL) 8906106bae4Srenato lw = lde_wdraw_add(ln, fn); 891cf483f25Srenato lw->label = map.label; 892cf483f25Srenato } else { 8932c06fdf4Srenato struct lde_map *me; 8942c06fdf4Srenato 8956106bae4Srenato RB_FOREACH(f, fec_tree, &ft) { 8966106bae4Srenato fn = (struct fec_node *)f; 8972c06fdf4Srenato me = (struct lde_map *)fec_find(&ln->sent_map, &fn->fec); 8982c06fdf4Srenato if (lde_wildcard_apply(wcard, &fn->fec, me) == 0) 8992c06fdf4Srenato continue; 900cf483f25Srenato 901cf483f25Srenato lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, 9026106bae4Srenato &fn->fec); 903cf483f25Srenato if (lw == NULL) 9046106bae4Srenato lw = lde_wdraw_add(ln, fn); 905cf483f25Srenato lw->label = map.label; 906cf483f25Srenato } 907cf483f25Srenato } 908ab0c2486Smichele } 909ab0c2486Smichele 910ab0c2486Smichele void 9112c06fdf4Srenato lde_send_labelwithdraw_wcard(struct lde_nbr *ln, uint32_t label) 912ab0c2486Smichele { 9132c06fdf4Srenato struct map wcard; 9146399cec1Srenato 9152c06fdf4Srenato memset(&wcard, 0, sizeof(wcard)); 9162c06fdf4Srenato wcard.type = MAP_TYPE_WILDCARD; 9172c06fdf4Srenato wcard.label = label; 9182c06fdf4Srenato lde_send_labelwithdraw(ln, NULL, &wcard, NULL); 9196399cec1Srenato } 920fb298019Sclaudio 9213de94509Srenato void 922c7c5a728Srenato lde_send_labelwithdraw_twcard_prefix(struct lde_nbr *ln, uint16_t af, 923c7c5a728Srenato uint32_t label) 924c7c5a728Srenato { 925c7c5a728Srenato struct map wcard; 926c7c5a728Srenato 927c7c5a728Srenato memset(&wcard, 0, sizeof(wcard)); 928c7c5a728Srenato wcard.type = MAP_TYPE_TYPED_WCARD; 929c7c5a728Srenato wcard.fec.twcard.type = MAP_TYPE_PREFIX; 930c7c5a728Srenato wcard.fec.twcard.u.prefix_af = af; 931c7c5a728Srenato wcard.label = label; 932c7c5a728Srenato lde_send_labelwithdraw(ln, NULL, &wcard, NULL); 933c7c5a728Srenato } 934c7c5a728Srenato 935c7c5a728Srenato void 9366702dd25Srenato lde_send_labelwithdraw_twcard_pwid(struct lde_nbr *ln, uint16_t pw_type, 9376702dd25Srenato uint32_t label) 9386702dd25Srenato { 9396702dd25Srenato struct map wcard; 9406702dd25Srenato 9416702dd25Srenato memset(&wcard, 0, sizeof(wcard)); 9426702dd25Srenato wcard.type = MAP_TYPE_TYPED_WCARD; 9436702dd25Srenato wcard.fec.twcard.type = MAP_TYPE_PWID; 9446702dd25Srenato wcard.fec.twcard.u.pw_type = pw_type; 9456702dd25Srenato wcard.label = label; 9466702dd25Srenato lde_send_labelwithdraw(ln, NULL, &wcard, NULL); 9476702dd25Srenato } 9486702dd25Srenato 9496702dd25Srenato void 9502c06fdf4Srenato lde_send_labelwithdraw_pwid_wcard(struct lde_nbr *ln, uint16_t pw_type, 9512c06fdf4Srenato uint32_t group_id) 9522c06fdf4Srenato { 9532c06fdf4Srenato struct map wcard; 9542c06fdf4Srenato 9552c06fdf4Srenato memset(&wcard, 0, sizeof(wcard)); 9562c06fdf4Srenato wcard.type = MAP_TYPE_PWID; 9572c06fdf4Srenato wcard.fec.pwid.type = pw_type; 9582c06fdf4Srenato wcard.fec.pwid.group_id = group_id; 9592c06fdf4Srenato /* we can not append a Label TLV when using PWid group wildcards. */ 9602c06fdf4Srenato wcard.label = NO_LABEL; 9612c06fdf4Srenato lde_send_labelwithdraw(ln, NULL, &wcard, NULL); 9622c06fdf4Srenato } 9632c06fdf4Srenato 9642c06fdf4Srenato void 9652c06fdf4Srenato lde_send_labelrelease(struct lde_nbr *ln, struct fec_node *fn, 9662c06fdf4Srenato struct map *wcard, uint32_t label) 9673de94509Srenato { 9683de94509Srenato struct map map; 9693de94509Srenato struct l2vpn_pw *pw; 9703de94509Srenato 9716106bae4Srenato if (fn) { 9726399cec1Srenato lde_fec2map(&fn->fec, &map); 973a8c39dc0Srenato switch (fn->fec.type) { 974a8c39dc0Srenato case FEC_TYPE_IPV4: 975a8c39dc0Srenato if (!ln->v4_enabled) 976a8c39dc0Srenato return; 977a8c39dc0Srenato break; 978a8c39dc0Srenato case FEC_TYPE_IPV6: 979a8c39dc0Srenato if (!ln->v6_enabled) 980a8c39dc0Srenato return; 981a8c39dc0Srenato break; 982a8c39dc0Srenato case FEC_TYPE_PWID: 9833de94509Srenato pw = (struct l2vpn_pw *) fn->data; 9843de94509Srenato if (pw == NULL || pw->lsr_id.s_addr != ln->id.s_addr) 9853de94509Srenato /* not the remote end of the pseudowire */ 9863de94509Srenato return; 9873de94509Srenato 9882d825b92Srenato if (pw->flags & F_PW_CWORD) 9896399cec1Srenato map.flags |= F_MAP_PW_CWORD; 990a8c39dc0Srenato break; 9916399cec1Srenato } 9922c06fdf4Srenato } else 9932c06fdf4Srenato memcpy(&map, wcard, sizeof(map)); 994fb298019Sclaudio map.label = label; 995fb298019Sclaudio 996eab950efSrenato lde_imsg_compose_ldpe(IMSG_RELEASE_ADD, ln->peerid, 0, 997eab950efSrenato &map, sizeof(map)); 998cf483f25Srenato lde_imsg_compose_ldpe(IMSG_RELEASE_ADD_END, ln->peerid, 0, NULL, 0); 999ab0c2486Smichele } 1000ab0c2486Smichele 1001ab0c2486Smichele void 100202a212eeSrenato lde_send_notification(struct lde_nbr *ln, uint32_t status_code, uint32_t msg_id, 100360e1e0e7Srenato uint16_t msg_type) 1004ab0c2486Smichele { 10057d508fe8Smichele struct notify_msg nm; 10067d508fe8Smichele 10073de94509Srenato memset(&nm, 0, sizeof(nm)); 100860e1e0e7Srenato nm.status_code = status_code; 100960e1e0e7Srenato /* 'msg_id' and 'msg_type' should be in network byte order */ 101060e1e0e7Srenato nm.msg_id = msg_id; 101160e1e0e7Srenato nm.msg_type = msg_type; 10127d508fe8Smichele 101302a212eeSrenato lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, ln->peerid, 0, 1014eab950efSrenato &nm, sizeof(nm)); 1015ab0c2486Smichele } 1016ab0c2486Smichele 10179246985aSrenato void 10189246985aSrenato lde_send_notification_eol_prefix(struct lde_nbr *ln, int af) 10199246985aSrenato { 10209246985aSrenato struct notify_msg nm; 10219246985aSrenato 10229246985aSrenato memset(&nm, 0, sizeof(nm)); 10239246985aSrenato nm.status_code = S_ENDOFLIB; 10249246985aSrenato nm.fec.type = MAP_TYPE_TYPED_WCARD; 10259246985aSrenato nm.fec.fec.twcard.type = MAP_TYPE_PREFIX; 10269246985aSrenato nm.fec.fec.twcard.u.prefix_af = af; 10279246985aSrenato nm.flags |= F_NOTIF_FEC; 10289246985aSrenato 10299246985aSrenato lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, ln->peerid, 0, 10309246985aSrenato &nm, sizeof(nm)); 10319246985aSrenato } 10329246985aSrenato 10339246985aSrenato void 10349246985aSrenato lde_send_notification_eol_pwid(struct lde_nbr *ln, uint16_t pw_type) 10359246985aSrenato { 10369246985aSrenato struct notify_msg nm; 10379246985aSrenato 10389246985aSrenato memset(&nm, 0, sizeof(nm)); 10399246985aSrenato nm.status_code = S_ENDOFLIB; 10409246985aSrenato nm.fec.type = MAP_TYPE_TYPED_WCARD; 10419246985aSrenato nm.fec.fec.twcard.type = MAP_TYPE_PWID; 10429246985aSrenato nm.fec.fec.twcard.u.pw_type = pw_type; 10439246985aSrenato nm.flags |= F_NOTIF_FEC; 10449246985aSrenato 10459246985aSrenato lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, ln->peerid, 0, 10469246985aSrenato &nm, sizeof(nm)); 10479246985aSrenato } 10489246985aSrenato 1049e3948831Sclaudio static __inline int 1050e3948831Sclaudio lde_nbr_compare(struct lde_nbr *a, struct lde_nbr *b) 1051ab0c2486Smichele { 1052e3948831Sclaudio return (a->peerid - b->peerid); 1053ab0c2486Smichele } 1054ab0c2486Smichele 1055c28a25a1Srenato static struct lde_nbr * 1056a8c39dc0Srenato lde_nbr_new(uint32_t peerid, struct lde_nbr *new) 1057ab0c2486Smichele { 10582d825b92Srenato struct lde_nbr *ln; 1059ab0c2486Smichele 10602d825b92Srenato if ((ln = calloc(1, sizeof(*ln))) == NULL) 1061b7b4db73Srenato fatal(__func__); 1062ab0c2486Smichele 1063a8c39dc0Srenato ln->id = new->id; 1064a8c39dc0Srenato ln->v4_enabled = new->v4_enabled; 1065a8c39dc0Srenato ln->v6_enabled = new->v6_enabled; 10669246985aSrenato ln->flags = new->flags; 10672d825b92Srenato ln->peerid = peerid; 10682d825b92Srenato fec_init(&ln->recv_map); 10692d825b92Srenato fec_init(&ln->sent_map); 10702d825b92Srenato fec_init(&ln->recv_req); 10712d825b92Srenato fec_init(&ln->sent_req); 10722d825b92Srenato fec_init(&ln->sent_wdraw); 1073ab0c2486Smichele 10742d825b92Srenato TAILQ_INIT(&ln->addr_list); 1075ab0c2486Smichele 10762d825b92Srenato if (RB_INSERT(nbr_tree, &lde_nbrs, ln) != NULL) 1077e3948831Sclaudio fatalx("lde_nbr_new: RB_INSERT failed"); 1078ab0c2486Smichele 10792d825b92Srenato return (ln); 1080ab0c2486Smichele } 1081ab0c2486Smichele 1082c28a25a1Srenato static void 10832d825b92Srenato lde_nbr_del(struct lde_nbr *ln) 1084d5e40e07Sclaudio { 10855b52d092Srenato struct fec *f; 10866106bae4Srenato struct fec_node *fn; 10876106bae4Srenato struct fec_nh *fnh; 1088a2da3f43Srenato struct l2vpn_pw *pw; 10895b52d092Srenato 10902d825b92Srenato if (ln == NULL) 1091d5e40e07Sclaudio return; 1092d5e40e07Sclaudio 10935b52d092Srenato /* uninstall received mappings */ 10946106bae4Srenato RB_FOREACH(f, fec_tree, &ft) { 10956106bae4Srenato fn = (struct fec_node *)f; 10965b52d092Srenato 10976106bae4Srenato LIST_FOREACH(fnh, &fn->nexthops, entry) { 109872bfe95eSrenato switch (f->type) { 109972bfe95eSrenato case FEC_TYPE_IPV4: 1100a8c39dc0Srenato case FEC_TYPE_IPV6: 1101a8c39dc0Srenato if (!lde_address_find(ln, fnh->af, 1102a8c39dc0Srenato &fnh->nexthop)) 110372bfe95eSrenato continue; 110472bfe95eSrenato break; 110572bfe95eSrenato case FEC_TYPE_PWID: 110672bfe95eSrenato if (f->u.pwid.lsr_id.s_addr != ln->id.s_addr) 110772bfe95eSrenato continue; 1108a2da3f43Srenato pw = (struct l2vpn_pw *) fn->data; 1109a2da3f43Srenato if (pw) 1110a2da3f43Srenato l2vpn_pw_reset(pw); 111172bfe95eSrenato break; 111272bfe95eSrenato default: 111372bfe95eSrenato break; 111472bfe95eSrenato } 111572bfe95eSrenato 11166106bae4Srenato lde_send_delete_klabel(fn, fnh); 11176106bae4Srenato fnh->remote_label = NO_LABEL; 11185b52d092Srenato } 11195b52d092Srenato } 11205b52d092Srenato 11212d825b92Srenato lde_address_list_free(ln); 1122d5e40e07Sclaudio 11232d825b92Srenato fec_clear(&ln->recv_map, lde_map_free); 11242d825b92Srenato fec_clear(&ln->sent_map, lde_map_free); 11252d825b92Srenato fec_clear(&ln->recv_req, free); 11262d825b92Srenato fec_clear(&ln->sent_req, free); 11272d825b92Srenato fec_clear(&ln->sent_wdraw, free); 1128e3948831Sclaudio 11292d825b92Srenato RB_REMOVE(nbr_tree, &lde_nbrs, ln); 1130d5e40e07Sclaudio 11312d825b92Srenato free(ln); 1132d5e40e07Sclaudio } 1133d5e40e07Sclaudio 1134c28a25a1Srenato static struct lde_nbr * 113533f6ccfeSrenato lde_nbr_find(uint32_t peerid) 113633f6ccfeSrenato { 11372d825b92Srenato struct lde_nbr ln; 113833f6ccfeSrenato 11392d825b92Srenato ln.peerid = peerid; 114033f6ccfeSrenato 11412d825b92Srenato return (RB_FIND(nbr_tree, &lde_nbrs, &ln)); 114233f6ccfeSrenato } 114333f6ccfeSrenato 114472bfe95eSrenato struct lde_nbr * 114572bfe95eSrenato lde_nbr_find_by_lsrid(struct in_addr addr) 114672bfe95eSrenato { 114772bfe95eSrenato struct lde_nbr *ln; 114872bfe95eSrenato 114972bfe95eSrenato RB_FOREACH(ln, nbr_tree, &lde_nbrs) 115072bfe95eSrenato if (ln->id.s_addr == addr.s_addr) 115172bfe95eSrenato return (ln); 115272bfe95eSrenato 115372bfe95eSrenato return (NULL); 115472bfe95eSrenato } 115572bfe95eSrenato 115672bfe95eSrenato struct lde_nbr * 1157a8c39dc0Srenato lde_nbr_find_by_addr(int af, union ldpd_addr *addr) 115872bfe95eSrenato { 115972bfe95eSrenato struct lde_nbr *ln; 116072bfe95eSrenato 116172bfe95eSrenato RB_FOREACH(ln, nbr_tree, &lde_nbrs) 1162a8c39dc0Srenato if (lde_address_find(ln, af, addr) != NULL) 116372bfe95eSrenato return (ln); 116472bfe95eSrenato 116572bfe95eSrenato return (NULL); 116672bfe95eSrenato } 116772bfe95eSrenato 1168c28a25a1Srenato static void 1169e3948831Sclaudio lde_nbr_clear(void) 1170e3948831Sclaudio { 11712d825b92Srenato struct lde_nbr *ln; 1172e3948831Sclaudio 11732d825b92Srenato while ((ln = RB_ROOT(&lde_nbrs)) != NULL) 11742d825b92Srenato lde_nbr_del(ln); 1175e3948831Sclaudio } 1176e3948831Sclaudio 1177ed90b960Srenato static void 1178ed90b960Srenato lde_nbr_addr_update(struct lde_nbr *ln, struct lde_addr *lde_addr, int removed) 1179ed90b960Srenato { 1180ed90b960Srenato struct fec *fec; 1181ed90b960Srenato struct fec_node *fn; 1182ed90b960Srenato struct fec_nh *fnh; 1183ed90b960Srenato struct lde_map *me; 1184ed90b960Srenato 1185ed90b960Srenato RB_FOREACH(fec, fec_tree, &ln->recv_map) { 1186ed90b960Srenato fn = (struct fec_node *)fec_find(&ft, fec); 1187ed90b960Srenato switch (fec->type) { 1188ed90b960Srenato case FEC_TYPE_IPV4: 1189ed90b960Srenato if (lde_addr->af != AF_INET) 1190ed90b960Srenato continue; 1191ed90b960Srenato break; 1192ed90b960Srenato case FEC_TYPE_IPV6: 1193ed90b960Srenato if (lde_addr->af != AF_INET6) 1194ed90b960Srenato continue; 1195ed90b960Srenato break; 1196ed90b960Srenato default: 1197ed90b960Srenato continue; 1198ed90b960Srenato } 1199ed90b960Srenato 1200ed90b960Srenato LIST_FOREACH(fnh, &fn->nexthops, entry) { 1201ed90b960Srenato if (ldp_addrcmp(fnh->af, &fnh->nexthop, 1202ed90b960Srenato &lde_addr->addr)) 1203ed90b960Srenato continue; 1204ed90b960Srenato 1205ed90b960Srenato if (removed) { 1206ed90b960Srenato lde_send_delete_klabel(fn, fnh); 1207ed90b960Srenato fnh->remote_label = NO_LABEL; 1208ed90b960Srenato } else { 1209ed90b960Srenato me = (struct lde_map *)fec; 1210ed90b960Srenato fnh->remote_label = me->map.label; 1211ed90b960Srenato lde_send_change_klabel(fn, fnh); 1212ed90b960Srenato } 1213ed90b960Srenato break; 1214ed90b960Srenato } 1215ed90b960Srenato } 1216ed90b960Srenato } 1217ed90b960Srenato 1218a094a533Sclaudio struct lde_map * 12196106bae4Srenato lde_map_add(struct lde_nbr *ln, struct fec_node *fn, int sent) 1220a094a533Sclaudio { 1221a094a533Sclaudio struct lde_map *me; 1222a094a533Sclaudio 1223a094a533Sclaudio me = calloc(1, sizeof(*me)); 1224a094a533Sclaudio if (me == NULL) 1225b7b4db73Srenato fatal(__func__); 1226a094a533Sclaudio 12276106bae4Srenato me->fec = fn->fec; 1228a094a533Sclaudio me->nexthop = ln; 1229a094a533Sclaudio 1230a094a533Sclaudio if (sent) { 12316106bae4Srenato LIST_INSERT_HEAD(&fn->upstream, me, entry); 1232a094a533Sclaudio if (fec_insert(&ln->sent_map, &me->fec)) 12336399cec1Srenato log_warnx("failed to add %s to sent map", 12346399cec1Srenato log_fec(&me->fec)); 1235fb298019Sclaudio /* XXX on failure more cleanup is needed */ 1236a094a533Sclaudio } else { 12376106bae4Srenato LIST_INSERT_HEAD(&fn->downstream, me, entry); 1238a094a533Sclaudio if (fec_insert(&ln->recv_map, &me->fec)) 12396399cec1Srenato log_warnx("failed to add %s to recv map", 12406399cec1Srenato log_fec(&me->fec)); 1241a094a533Sclaudio } 1242a094a533Sclaudio 1243a094a533Sclaudio return (me); 1244a094a533Sclaudio } 1245a094a533Sclaudio 1246e3948831Sclaudio void 1247510d51a3Sclaudio lde_map_del(struct lde_nbr *ln, struct lde_map *me, int sent) 1248510d51a3Sclaudio { 1249510d51a3Sclaudio if (sent) 1250510d51a3Sclaudio fec_remove(&ln->sent_map, &me->fec); 1251510d51a3Sclaudio else 1252510d51a3Sclaudio fec_remove(&ln->recv_map, &me->fec); 1253510d51a3Sclaudio 1254510d51a3Sclaudio lde_map_free(me); 1255510d51a3Sclaudio } 1256510d51a3Sclaudio 1257c28a25a1Srenato static void 1258e3948831Sclaudio lde_map_free(void *ptr) 1259e3948831Sclaudio { 1260e3948831Sclaudio struct lde_map *map = ptr; 1261e3948831Sclaudio 1262e3948831Sclaudio LIST_REMOVE(map, entry); 1263e3948831Sclaudio free(map); 1264e3948831Sclaudio } 1265e3948831Sclaudio 1266fb298019Sclaudio struct lde_req * 1267fb298019Sclaudio lde_req_add(struct lde_nbr *ln, struct fec *fec, int sent) 1268fb298019Sclaudio { 12696106bae4Srenato struct fec_tree *t; 1270fb298019Sclaudio struct lde_req *lre; 1271fb298019Sclaudio 12726106bae4Srenato t = sent ? &ln->sent_req : &ln->recv_req; 1273fb298019Sclaudio 1274fb298019Sclaudio lre = calloc(1, sizeof(*lre)); 1275fb298019Sclaudio if (lre != NULL) { 1276fb298019Sclaudio lre->fec = *fec; 1277fb298019Sclaudio 12786106bae4Srenato if (fec_insert(t, &lre->fec)) { 1279a8e25944Sbenno log_warnx("failed to add %s to %s req", 12806399cec1Srenato log_fec(&lre->fec), sent ? "sent" : "recv"); 1281fb298019Sclaudio free(lre); 1282fb298019Sclaudio return (NULL); 1283fb298019Sclaudio } 1284fb298019Sclaudio } 1285fb298019Sclaudio 1286fb298019Sclaudio return (lre); 1287fb298019Sclaudio } 1288fb298019Sclaudio 1289fb298019Sclaudio void 1290fb298019Sclaudio lde_req_del(struct lde_nbr *ln, struct lde_req *lre, int sent) 1291fb298019Sclaudio { 1292fb298019Sclaudio if (sent) 1293fb298019Sclaudio fec_remove(&ln->sent_req, &lre->fec); 1294fb298019Sclaudio else 1295fb298019Sclaudio fec_remove(&ln->recv_req, &lre->fec); 1296fb298019Sclaudio 1297fb298019Sclaudio free(lre); 1298fb298019Sclaudio } 1299fb298019Sclaudio 1300cf483f25Srenato struct lde_wdraw * 13016106bae4Srenato lde_wdraw_add(struct lde_nbr *ln, struct fec_node *fn) 1302cf483f25Srenato { 1303cf483f25Srenato struct lde_wdraw *lw; 1304cf483f25Srenato 1305cf483f25Srenato lw = calloc(1, sizeof(*lw)); 1306cf483f25Srenato if (lw == NULL) 1307b7b4db73Srenato fatal(__func__); 1308cf483f25Srenato 13096106bae4Srenato lw->fec = fn->fec; 1310cf483f25Srenato 1311cf483f25Srenato if (fec_insert(&ln->sent_wdraw, &lw->fec)) 13126399cec1Srenato log_warnx("failed to add %s to sent wdraw", 13136399cec1Srenato log_fec(&lw->fec)); 1314cf483f25Srenato 1315cf483f25Srenato return (lw); 1316cf483f25Srenato } 1317cf483f25Srenato 1318cf483f25Srenato void 1319cf483f25Srenato lde_wdraw_del(struct lde_nbr *ln, struct lde_wdraw *lw) 1320cf483f25Srenato { 1321cf483f25Srenato fec_remove(&ln->sent_wdraw, &lw->fec); 1322cf483f25Srenato free(lw); 1323cf483f25Srenato } 1324cf483f25Srenato 132533f6ccfeSrenato void 1326a8c39dc0Srenato lde_change_egress_label(int af, int was_implicit) 132733f6ccfeSrenato { 132833f6ccfeSrenato struct lde_nbr *ln; 132933f6ccfeSrenato struct fec *f; 133033f6ccfeSrenato struct fec_node *fn; 133133f6ccfeSrenato 1332a8c39dc0Srenato RB_FOREACH(ln, nbr_tree, &lde_nbrs) { 133333f6ccfeSrenato /* explicit withdraw */ 133433f6ccfeSrenato if (was_implicit) 13352c06fdf4Srenato lde_send_labelwithdraw_wcard(ln, MPLS_LABEL_IMPLNULL); 1336a8c39dc0Srenato else { 1337a8c39dc0Srenato if (ln->v4_enabled) 13382c06fdf4Srenato lde_send_labelwithdraw_wcard(ln, 13392c06fdf4Srenato MPLS_LABEL_IPV4NULL); 1340a8c39dc0Srenato if (ln->v6_enabled) 13412c06fdf4Srenato lde_send_labelwithdraw_wcard(ln, 13422c06fdf4Srenato MPLS_LABEL_IPV6NULL); 1343a8c39dc0Srenato } 134433f6ccfeSrenato 1345a8c39dc0Srenato /* advertise new label of connected prefixes */ 134633f6ccfeSrenato RB_FOREACH(f, fec_tree, &ft) { 134733f6ccfeSrenato fn = (struct fec_node *)f; 134833f6ccfeSrenato if (fn->local_label > MPLS_LABEL_RESERVED_MAX) 134933f6ccfeSrenato continue; 135033f6ccfeSrenato 1351a8c39dc0Srenato switch (af) { 1352a8c39dc0Srenato case AF_INET: 1353a8c39dc0Srenato if (fn->fec.type != FEC_TYPE_IPV4) 1354a8c39dc0Srenato continue; 1355a8c39dc0Srenato break; 1356a8c39dc0Srenato case AF_INET6: 1357a8c39dc0Srenato if (fn->fec.type != FEC_TYPE_IPV6) 1358a8c39dc0Srenato continue; 1359a8c39dc0Srenato break; 1360a8c39dc0Srenato default: 1361a8c39dc0Srenato fatalx("lde_change_egress_label: unknown af"); 1362a8c39dc0Srenato } 1363a8c39dc0Srenato 136433f6ccfeSrenato fn->local_label = egress_label(fn->fec.type); 136533f6ccfeSrenato lde_send_labelmapping(ln, fn, 0); 136633f6ccfeSrenato } 136734f55a3fSrenato 136834f55a3fSrenato lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, ln->peerid, 0, 136934f55a3fSrenato NULL, 0); 137033f6ccfeSrenato } 137133f6ccfeSrenato } 137233f6ccfeSrenato 1373c28a25a1Srenato static int 1374a8c39dc0Srenato lde_address_add(struct lde_nbr *ln, struct lde_addr *lde_addr) 1375ab0c2486Smichele { 137619fce358Srenato struct lde_addr *new; 1377ab0c2486Smichele 1378a8c39dc0Srenato if (lde_address_find(ln, lde_addr->af, &lde_addr->addr) != NULL) 1379ab0c2486Smichele return (-1); 1380ab0c2486Smichele 138119fce358Srenato if ((new = calloc(1, sizeof(*new))) == NULL) 1382b7b4db73Srenato fatal(__func__); 1383ab0c2486Smichele 1384a8c39dc0Srenato new->af = lde_addr->af; 1385a8c39dc0Srenato new->addr = lde_addr->addr; 138619fce358Srenato TAILQ_INSERT_TAIL(&ln->addr_list, new, entry); 1387ab0c2486Smichele 1388ed90b960Srenato /* reevaluate the previously received mappings from this neighbor */ 1389ed90b960Srenato lde_nbr_addr_update(ln, lde_addr, 0); 1390ed90b960Srenato 1391ab0c2486Smichele return (0); 1392ab0c2486Smichele } 1393ab0c2486Smichele 1394c28a25a1Srenato static int 1395a8c39dc0Srenato lde_address_del(struct lde_nbr *ln, struct lde_addr *lde_addr) 1396ab0c2486Smichele { 1397a8c39dc0Srenato lde_addr = lde_address_find(ln, lde_addr->af, &lde_addr->addr); 139819fce358Srenato if (lde_addr == NULL) 1399ab0c2486Smichele return (-1); 1400ab0c2486Smichele 1401ed90b960Srenato /* reevaluate the previously received mappings from this neighbor */ 1402ed90b960Srenato lde_nbr_addr_update(ln, lde_addr, 1); 1403ed90b960Srenato 140419fce358Srenato TAILQ_REMOVE(&ln->addr_list, lde_addr, entry); 140519fce358Srenato free(lde_addr); 1406ab0c2486Smichele 1407ab0c2486Smichele return (0); 1408ab0c2486Smichele } 1409ab0c2486Smichele 14102d825b92Srenato struct lde_addr * 1411a8c39dc0Srenato lde_address_find(struct lde_nbr *ln, int af, union ldpd_addr *addr) 141233f6ccfeSrenato { 141319fce358Srenato struct lde_addr *lde_addr; 141433f6ccfeSrenato 141519fce358Srenato TAILQ_FOREACH(lde_addr, &ln->addr_list, entry) 1416a8c39dc0Srenato if (lde_addr->af == af && 1417a8c39dc0Srenato ldp_addrcmp(af, &lde_addr->addr, addr) == 0) 141819fce358Srenato return (lde_addr); 141933f6ccfeSrenato 142033f6ccfeSrenato return (NULL); 142133f6ccfeSrenato } 142233f6ccfeSrenato 1423c28a25a1Srenato static void 14242d825b92Srenato lde_address_list_free(struct lde_nbr *ln) 1425ab0c2486Smichele { 142619fce358Srenato struct lde_addr *lde_addr; 1427ab0c2486Smichele 142819fce358Srenato while ((lde_addr = TAILQ_FIRST(&ln->addr_list)) != NULL) { 142919fce358Srenato TAILQ_REMOVE(&ln->addr_list, lde_addr, entry); 143019fce358Srenato free(lde_addr); 1431ab0c2486Smichele } 1432ab0c2486Smichele } 1433