]> git.proxmox.com Git - mirror_frr.git/blame - ldpd/lde.c
ldpd: use red-black trees to store 'l2vpn_pw' elements
[mirror_frr.git] / ldpd / lde.c
CommitLineData
8429abe0
RW
1/* $OpenBSD$ */
2
3/*
4 * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
5 * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
6 * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
7 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 */
21
eac6e3f0 22#include <zebra.h>
8429abe0
RW
23
24#include "ldp.h"
25#include "ldpd.h"
26#include "ldpe.h"
27#include "log.h"
28#include "lde.h"
eac6e3f0 29#include "ldp_debug.h"
8429abe0 30
eac6e3f0
RW
31#include <lib/log.h>
32#include "memory.h"
33#include "privs.h"
34#include "sigevent.h"
35#include "mpls.h"
36
37static void lde_shutdown(void);
38static int lde_dispatch_imsg(struct thread *);
39static int lde_dispatch_parent(struct thread *);
8429abe0
RW
40static __inline int lde_nbr_compare(struct lde_nbr *,
41 struct lde_nbr *);
42static struct lde_nbr *lde_nbr_new(uint32_t, struct lde_nbr *);
43static void lde_nbr_del(struct lde_nbr *);
44static struct lde_nbr *lde_nbr_find(uint32_t);
45static void lde_nbr_clear(void);
46static void lde_nbr_addr_update(struct lde_nbr *,
47 struct lde_addr *, int);
d3e1887a 48static __inline int lde_map_compare(struct lde_map *, struct lde_map *);
8429abe0
RW
49static void lde_map_free(void *);
50static int lde_address_add(struct lde_nbr *, struct lde_addr *);
51static int lde_address_del(struct lde_nbr *, struct lde_addr *);
52static void lde_address_list_free(struct lde_nbr *);
53
54RB_GENERATE(nbr_tree, lde_nbr, entry, lde_nbr_compare)
d3e1887a 55RB_GENERATE(lde_map_head, lde_map, entry, lde_map_compare)
8429abe0
RW
56
57struct ldpd_conf *ldeconf;
58struct nbr_tree lde_nbrs = RB_INITIALIZER(&lde_nbrs);
59
60static struct imsgev *iev_ldpe;
61static struct imsgev *iev_main;
62
eac6e3f0
RW
63/* Master of threads. */
64struct thread_master *master;
65
66/* lde privileges */
67static zebra_capabilities_t _caps_p [] =
8429abe0 68{
eac6e3f0
RW
69 /* none */
70};
8429abe0 71
eac6e3f0
RW
72static struct zebra_privs_t lde_privs =
73{
74#if defined(QUAGGA_USER) && defined(QUAGGA_GROUP)
75 .user = QUAGGA_USER,
76 .group = QUAGGA_GROUP,
77#endif
78#if defined(VTY_GROUP)
79 .vty_group = VTY_GROUP,
80#endif
81 .caps_p = _caps_p,
82 .cap_num_p = array_size(_caps_p),
83 .cap_num_i = 0
84};
85
86/* SIGINT / SIGTERM handler. */
87static void
88sigint(void)
89{
90 lde_shutdown();
8429abe0
RW
91}
92
eac6e3f0
RW
93static struct quagga_signal_t lde_signals[] =
94{
95 {
96 .signal = SIGINT,
97 .handler = &sigint,
98 },
99 {
100 .signal = SIGTERM,
101 .handler = &sigint,
102 },
103};
104
8429abe0
RW
105/* label decision engine */
106void
eac6e3f0 107lde(const char *user, const char *group)
8429abe0 108{
eac6e3f0 109 struct thread thread;
8429abe0 110 struct timeval now;
8429abe0
RW
111
112 ldeconf = config_new_empty();
113
eac6e3f0 114#ifdef HAVE_SETPROCTITLE
8429abe0 115 setproctitle("label decision engine");
eac6e3f0 116#endif
8429abe0
RW
117 ldpd_process = PROC_LDE_ENGINE;
118
eac6e3f0
RW
119 /* drop privileges */
120 if (user)
121 lde_privs.user = user;
122 if (group)
123 lde_privs.group = group;
124 zprivs_init(&lde_privs);
8429abe0 125
eac6e3f0 126#ifdef HAVE_PLEDGE
8429abe0
RW
127 if (pledge("stdio recvfd", NULL) == -1)
128 fatal("pledge");
eac6e3f0 129#endif
8429abe0 130
eac6e3f0 131 master = thread_master_create();
8429abe0
RW
132
133 /* setup signal handler */
eac6e3f0 134 signal_init(master, array_size(lde_signals), lde_signals);
8429abe0
RW
135
136 /* setup pipe and event handler to the parent process */
137 if ((iev_main = malloc(sizeof(struct imsgev))) == NULL)
138 fatal(NULL);
139 imsg_init(&iev_main->ibuf, 3);
eac6e3f0
RW
140 iev_main->handler_read = lde_dispatch_parent;
141 iev_main->ev_read = thread_add_read(master, iev_main->handler_read,
142 iev_main, iev_main->ibuf.fd);
143 iev_main->handler_write = ldp_write_handler;
144 iev_main->ev_write = NULL;
145
146 /* start the LIB garbage collector */
8429abe0
RW
147 lde_gc_start_timer();
148
149 gettimeofday(&now, NULL);
150 global.uptime = now.tv_sec;
151
eac6e3f0
RW
152 /* Fetch next active thread. */
153 while (thread_fetch(master, &thread))
154 thread_call(&thread);
8429abe0
RW
155}
156
eac6e3f0 157static void
8429abe0
RW
158lde_shutdown(void)
159{
160 /* close pipes */
161 msgbuf_clear(&iev_ldpe->ibuf.w);
162 close(iev_ldpe->ibuf.fd);
163 msgbuf_clear(&iev_main->ibuf.w);
164 close(iev_main->ibuf.fd);
165
166 lde_gc_stop_timer();
167 lde_nbr_clear();
168 fec_tree_clear();
169
170 config_clear(ldeconf);
171
172 free(iev_ldpe);
173 free(iev_main);
174
175 log_info("label decision engine exiting");
176 exit(0);
177}
178
179/* imesg */
eac6e3f0 180int
8429abe0
RW
181lde_imsg_compose_parent(int type, pid_t pid, void *data, uint16_t datalen)
182{
183 return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
184}
185
186int
187lde_imsg_compose_ldpe(int type, uint32_t peerid, pid_t pid, void *data,
188 uint16_t datalen)
189{
190 return (imsg_compose_event(iev_ldpe, type, peerid, pid,
191 -1, data, datalen));
192}
193
194/* ARGSUSED */
eac6e3f0
RW
195static int
196lde_dispatch_imsg(struct thread *thread)
8429abe0 197{
eac6e3f0 198 struct imsgev *iev = THREAD_ARG(thread);
8429abe0
RW
199 struct imsgbuf *ibuf = &iev->ibuf;
200 struct imsg imsg;
201 struct lde_nbr *ln;
202 struct map map;
203 struct lde_addr lde_addr;
204 struct notify_msg nm;
205 ssize_t n;
eac6e3f0 206 int shut = 0;
8429abe0 207
eac6e3f0
RW
208 iev->ev_read = NULL;
209
210 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
211 fatal("imsg_read error");
212 if (n == 0) /* connection closed */
213 shut = 1;
8429abe0
RW
214
215 for (;;) {
216 if ((n = imsg_get(ibuf, &imsg)) == -1)
217 fatal("lde_dispatch_imsg: imsg_get error");
218 if (n == 0)
219 break;
220
221 switch (imsg.hdr.type) {
222 case IMSG_LABEL_MAPPING_FULL:
223 ln = lde_nbr_find(imsg.hdr.peerid);
224 if (ln == NULL) {
225 log_debug("%s: cannot find lde neighbor",
226 __func__);
227 break;
228 }
229
230 fec_snap(ln);
231 break;
232 case IMSG_LABEL_MAPPING:
233 case IMSG_LABEL_REQUEST:
234 case IMSG_LABEL_RELEASE:
235 case IMSG_LABEL_WITHDRAW:
236 case IMSG_LABEL_ABORT:
237 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(map))
238 fatalx("lde_dispatch_imsg: wrong imsg len");
239 memcpy(&map, imsg.data, sizeof(map));
240
241 ln = lde_nbr_find(imsg.hdr.peerid);
242 if (ln == NULL) {
243 log_debug("%s: cannot find lde neighbor",
244 __func__);
245 break;
246 }
247
248 switch (imsg.hdr.type) {
249 case IMSG_LABEL_MAPPING:
250 lde_check_mapping(&map, ln);
251 break;
252 case IMSG_LABEL_REQUEST:
253 lde_check_request(&map, ln);
254 break;
255 case IMSG_LABEL_RELEASE:
256 if (map.type == MAP_TYPE_WILDCARD)
257 lde_check_release_wcard(&map, ln);
258 else
259 lde_check_release(&map, ln);
260 break;
261 case IMSG_LABEL_WITHDRAW:
262 if (map.type == MAP_TYPE_WILDCARD)
263 lde_check_withdraw_wcard(&map, ln);
264 else
265 lde_check_withdraw(&map, ln);
266 break;
267 case IMSG_LABEL_ABORT:
268 /* not necessary */
269 break;
270 }
271 break;
272 case IMSG_ADDRESS_ADD:
273 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(lde_addr))
274 fatalx("lde_dispatch_imsg: wrong imsg len");
275 memcpy(&lde_addr, imsg.data, sizeof(lde_addr));
276
277 ln = lde_nbr_find(imsg.hdr.peerid);
278 if (ln == NULL) {
279 log_debug("%s: cannot find lde neighbor",
280 __func__);
281 break;
282 }
283 if (lde_address_add(ln, &lde_addr) < 0) {
284 log_debug("%s: cannot add address %s, it "
285 "already exists", __func__,
286 log_addr(lde_addr.af, &lde_addr.addr));
287 }
288 break;
289 case IMSG_ADDRESS_DEL:
290 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(lde_addr))
291 fatalx("lde_dispatch_imsg: wrong imsg len");
292 memcpy(&lde_addr, imsg.data, sizeof(lde_addr));
293
294 ln = lde_nbr_find(imsg.hdr.peerid);
295 if (ln == NULL) {
296 log_debug("%s: cannot find lde neighbor",
297 __func__);
298 break;
299 }
300 if (lde_address_del(ln, &lde_addr) < 0) {
301 log_debug("%s: cannot delete address %s, it "
302 "does not exist", __func__,
303 log_addr(lde_addr.af, &lde_addr.addr));
304 }
305 break;
306 case IMSG_NOTIFICATION:
307 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(nm))
308 fatalx("lde_dispatch_imsg: wrong imsg len");
309 memcpy(&nm, imsg.data, sizeof(nm));
310
311 ln = lde_nbr_find(imsg.hdr.peerid);
312 if (ln == NULL) {
313 log_debug("%s: cannot find lde neighbor",
314 __func__);
315 break;
316 }
317
318 switch (nm.status_code) {
319 case S_PW_STATUS:
320 l2vpn_recv_pw_status(ln, &nm);
321 break;
322 default:
323 break;
324 }
325 break;
326 case IMSG_NEIGHBOR_UP:
327 if (imsg.hdr.len - IMSG_HEADER_SIZE !=
328 sizeof(struct lde_nbr))
329 fatalx("lde_dispatch_imsg: wrong imsg len");
330
331 if (lde_nbr_find(imsg.hdr.peerid))
332 fatalx("lde_dispatch_imsg: "
333 "neighbor already exists");
334 lde_nbr_new(imsg.hdr.peerid, imsg.data);
335 break;
336 case IMSG_NEIGHBOR_DOWN:
337 lde_nbr_del(lde_nbr_find(imsg.hdr.peerid));
338 break;
339 case IMSG_CTL_SHOW_LIB:
340 rt_dump(imsg.hdr.pid);
341
342 lde_imsg_compose_ldpe(IMSG_CTL_END, 0,
343 imsg.hdr.pid, NULL, 0);
344 break;
345 case IMSG_CTL_SHOW_L2VPN_PW:
346 l2vpn_pw_ctl(imsg.hdr.pid);
347
348 lde_imsg_compose_ldpe(IMSG_CTL_END, 0,
349 imsg.hdr.pid, NULL, 0);
350 break;
351 case IMSG_CTL_SHOW_L2VPN_BINDING:
352 l2vpn_binding_ctl(imsg.hdr.pid);
353
354 lde_imsg_compose_ldpe(IMSG_CTL_END, 0,
355 imsg.hdr.pid, NULL, 0);
356 break;
8429abe0
RW
357 default:
358 log_debug("%s: unexpected imsg %d", __func__,
359 imsg.hdr.type);
360 break;
361 }
362 imsg_free(&imsg);
363 }
364 if (!shut)
365 imsg_event_add(iev);
366 else {
eac6e3f0
RW
367 /* this pipe is dead, so remove the event handlers and exit */
368 THREAD_READ_OFF(iev->ev_read);
369 THREAD_WRITE_OFF(iev->ev_write);
370 lde_shutdown();
8429abe0 371 }
eac6e3f0
RW
372
373 return (0);
8429abe0
RW
374}
375
376/* ARGSUSED */
eac6e3f0
RW
377static int
378lde_dispatch_parent(struct thread *thread)
8429abe0
RW
379{
380 static struct ldpd_conf *nconf;
381 struct iface *niface;
382 struct tnbr *ntnbr;
383 struct nbr_params *nnbrp;
384 static struct l2vpn *nl2vpn;
385 struct l2vpn_if *nlif;
386 struct l2vpn_pw *npw;
387 struct imsg imsg;
388 struct kroute kr;
eac6e3f0
RW
389 int fd = THREAD_FD(thread);
390 struct imsgev *iev = THREAD_ARG(thread);
8429abe0
RW
391 struct imsgbuf *ibuf = &iev->ibuf;
392 ssize_t n;
393 int shut = 0;
394 struct fec fec;
395
eac6e3f0
RW
396 iev->ev_read = NULL;
397
398 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
399 fatal("imsg_read error");
400 if (n == 0) /* connection closed */
401 shut = 1;
8429abe0
RW
402
403 for (;;) {
404 if ((n = imsg_get(ibuf, &imsg)) == -1)
405 fatal("lde_dispatch_parent: imsg_get error");
406 if (n == 0)
407 break;
408
409 switch (imsg.hdr.type) {
410 case IMSG_NETWORK_ADD:
134970a2 411 case IMSG_NETWORK_ADD_END:
8429abe0
RW
412 case IMSG_NETWORK_DEL:
413 if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(kr)) {
414 log_warnx("%s: wrong imsg len", __func__);
415 break;
416 }
417 memcpy(&kr, imsg.data, sizeof(kr));
418
419 switch (kr.af) {
420 case AF_INET:
421 fec.type = FEC_TYPE_IPV4;
422 fec.u.ipv4.prefix = kr.prefix.v4;
423 fec.u.ipv4.prefixlen = kr.prefixlen;
424 break;
425 case AF_INET6:
426 fec.type = FEC_TYPE_IPV6;
427 fec.u.ipv6.prefix = kr.prefix.v6;
428 fec.u.ipv6.prefixlen = kr.prefixlen;
429 break;
430 default:
431 fatalx("lde_dispatch_parent: unknown af");
432 }
433
434 switch (imsg.hdr.type) {
435 case IMSG_NETWORK_ADD:
436 lde_kernel_insert(&fec, kr.af, &kr.nexthop,
88d88a9c
RW
437 kr.ifindex, kr.priority,
438 kr.flags & F_CONNECTED, NULL);
8429abe0 439 break;
134970a2
RW
440 case IMSG_NETWORK_ADD_END:
441 lde_kernel_reevaluate(&fec);
442 break;
8429abe0
RW
443 case IMSG_NETWORK_DEL:
444 lde_kernel_remove(&fec, kr.af, &kr.nexthop,
88d88a9c 445 kr.ifindex, kr.priority);
8429abe0
RW
446 break;
447 }
448 break;
449 case IMSG_SOCKET_IPC:
450 if (iev_ldpe) {
451 log_warnx("%s: received unexpected imsg fd "
452 "to ldpe", __func__);
453 break;
454 }
455 if ((fd = imsg.fd) == -1) {
456 log_warnx("%s: expected to receive imsg fd to "
457 "ldpe but didn't receive any", __func__);
458 break;
459 }
460
461 if ((iev_ldpe = malloc(sizeof(struct imsgev))) == NULL)
462 fatal(NULL);
463 imsg_init(&iev_ldpe->ibuf, fd);
eac6e3f0
RW
464 iev_ldpe->handler_read = lde_dispatch_imsg;
465 iev_ldpe->ev_read = thread_add_read(master,
466 iev_ldpe->handler_read, iev_ldpe, iev_ldpe->ibuf.fd);
467 iev_ldpe->handler_write = ldp_write_handler;
468 iev_ldpe->ev_write = NULL;
8429abe0
RW
469 break;
470 case IMSG_RECONF_CONF:
471 if ((nconf = malloc(sizeof(struct ldpd_conf))) ==
472 NULL)
473 fatal(NULL);
474 memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
475
7d3d7491 476 RB_INIT(&nconf->iface_tree);
7989cdba 477 RB_INIT(&nconf->tnbr_tree);
76c4abd1 478 RB_INIT(&nconf->nbrp_tree);
90d7e7bd 479 RB_INIT(&nconf->l2vpn_tree);
8429abe0
RW
480 break;
481 case IMSG_RECONF_IFACE:
482 if ((niface = malloc(sizeof(struct iface))) == NULL)
483 fatal(NULL);
484 memcpy(niface, imsg.data, sizeof(struct iface));
485
486 LIST_INIT(&niface->addr_list);
487 LIST_INIT(&niface->ipv4.adj_list);
488 LIST_INIT(&niface->ipv6.adj_list);
489 niface->ipv4.iface = niface;
490 niface->ipv6.iface = niface;
491
7d3d7491 492 RB_INSERT(iface_head, &nconf->iface_tree, niface);
8429abe0
RW
493 break;
494 case IMSG_RECONF_TNBR:
495 if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL)
496 fatal(NULL);
497 memcpy(ntnbr, imsg.data, sizeof(struct tnbr));
498
7989cdba 499 RB_INSERT(tnbr_head, &nconf->tnbr_tree, ntnbr);
8429abe0
RW
500 break;
501 case IMSG_RECONF_NBRP:
502 if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL)
503 fatal(NULL);
504 memcpy(nnbrp, imsg.data, sizeof(struct nbr_params));
505
76c4abd1 506 RB_INSERT(nbrp_head, &nconf->nbrp_tree, nnbrp);
8429abe0
RW
507 break;
508 case IMSG_RECONF_L2VPN:
509 if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL)
510 fatal(NULL);
511 memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn));
512
029c1958 513 RB_INIT(&nl2vpn->if_tree);
20bacaeb
RW
514 RB_INIT(&nl2vpn->pw_tree);
515 RB_INIT(&nl2vpn->pw_inactive_tree);
8429abe0 516
90d7e7bd 517 RB_INSERT(l2vpn_head, &nconf->l2vpn_tree, nl2vpn);
8429abe0
RW
518 break;
519 case IMSG_RECONF_L2VPN_IF:
520 if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL)
521 fatal(NULL);
522 memcpy(nlif, imsg.data, sizeof(struct l2vpn_if));
523
524 nlif->l2vpn = nl2vpn;
029c1958 525 RB_INSERT(l2vpn_if_head, &nl2vpn->if_tree, nlif);
8429abe0
RW
526 break;
527 case IMSG_RECONF_L2VPN_PW:
528 if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
529 fatal(NULL);
530 memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
531
532 npw->l2vpn = nl2vpn;
20bacaeb 533 RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_tree, npw);
8429abe0 534 break;
eac6e3f0
RW
535 case IMSG_RECONF_L2VPN_IPW:
536 if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
537 fatal(NULL);
538 memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
539
540 npw->l2vpn = nl2vpn;
20bacaeb 541 RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree, npw);
eac6e3f0 542 break;
8429abe0
RW
543 case IMSG_RECONF_END:
544 merge_config(ldeconf, nconf);
545 nconf = NULL;
546 break;
eac6e3f0
RW
547 case IMSG_DEBUG_UPDATE:
548 if (imsg.hdr.len != IMSG_HEADER_SIZE +
549 sizeof(ldp_debug)) {
550 log_warnx("%s: wrong imsg len", __func__);
551 break;
552 }
553 memcpy(&ldp_debug, imsg.data, sizeof(ldp_debug));
554 break;
8429abe0
RW
555 default:
556 log_debug("%s: unexpected imsg %d", __func__,
557 imsg.hdr.type);
558 break;
559 }
560 imsg_free(&imsg);
561 }
562 if (!shut)
563 imsg_event_add(iev);
564 else {
eac6e3f0
RW
565 /* this pipe is dead, so remove the event handlers and exit */
566 THREAD_READ_OFF(iev->ev_read);
567 THREAD_WRITE_OFF(iev->ev_write);
568 lde_shutdown();
8429abe0 569 }
eac6e3f0
RW
570
571 return (0);
8429abe0
RW
572}
573
574uint32_t
575lde_assign_label(void)
576{
577 static uint32_t label = MPLS_LABEL_RESERVED_MAX;
578
eac6e3f0
RW
579 /*
580 * TODO: request label to zebra or define a range of labels for ldpd.
581 */
582
8429abe0
RW
583 label++;
584 return (label);
585}
586
587void
588lde_send_change_klabel(struct fec_node *fn, struct fec_nh *fnh)
589{
590 struct kroute kr;
591 struct kpw kpw;
592 struct l2vpn_pw *pw;
593
594 switch (fn->fec.type) {
595 case FEC_TYPE_IPV4:
596 memset(&kr, 0, sizeof(kr));
597 kr.af = AF_INET;
598 kr.prefix.v4 = fn->fec.u.ipv4.prefix;
599 kr.prefixlen = fn->fec.u.ipv4.prefixlen;
600 kr.nexthop.v4 = fnh->nexthop.v4;
88d88a9c 601 kr.ifindex = fnh->ifindex;
8429abe0
RW
602 kr.local_label = fn->local_label;
603 kr.remote_label = fnh->remote_label;
604 kr.priority = fnh->priority;
605
606 lde_imsg_compose_parent(IMSG_KLABEL_CHANGE, 0, &kr,
607 sizeof(kr));
608
609 if (fn->fec.u.ipv4.prefixlen == 32)
610 l2vpn_sync_pws(AF_INET, (union ldpd_addr *)
611 &fn->fec.u.ipv4.prefix);
612 break;
613 case FEC_TYPE_IPV6:
614 memset(&kr, 0, sizeof(kr));
615 kr.af = AF_INET6;
616 kr.prefix.v6 = fn->fec.u.ipv6.prefix;
617 kr.prefixlen = fn->fec.u.ipv6.prefixlen;
618 kr.nexthop.v6 = fnh->nexthop.v6;
88d88a9c 619 kr.ifindex = fnh->ifindex;
8429abe0
RW
620 kr.local_label = fn->local_label;
621 kr.remote_label = fnh->remote_label;
622 kr.priority = fnh->priority;
623
624 lde_imsg_compose_parent(IMSG_KLABEL_CHANGE, 0, &kr,
625 sizeof(kr));
626
627 if (fn->fec.u.ipv6.prefixlen == 128)
628 l2vpn_sync_pws(AF_INET6, (union ldpd_addr *)
629 &fn->fec.u.ipv6.prefix);
630 break;
631 case FEC_TYPE_PWID:
632 if (fn->local_label == NO_LABEL ||
633 fnh->remote_label == NO_LABEL)
634 return;
635
636 pw = (struct l2vpn_pw *) fn->data;
637 pw->flags |= F_PW_STATUS_UP;
638
639 memset(&kpw, 0, sizeof(kpw));
640 kpw.ifindex = pw->ifindex;
641 kpw.pw_type = fn->fec.u.pwid.type;
642 kpw.af = pw->af;
643 kpw.nexthop = pw->addr;
644 kpw.local_label = fn->local_label;
645 kpw.remote_label = fnh->remote_label;
646 kpw.flags = pw->flags;
647
648 lde_imsg_compose_parent(IMSG_KPWLABEL_CHANGE, 0, &kpw,
649 sizeof(kpw));
650 break;
651 }
652}
653
654void
655lde_send_delete_klabel(struct fec_node *fn, struct fec_nh *fnh)
656{
657 struct kroute kr;
658 struct kpw kpw;
659 struct l2vpn_pw *pw;
660
661 switch (fn->fec.type) {
662 case FEC_TYPE_IPV4:
663 memset(&kr, 0, sizeof(kr));
664 kr.af = AF_INET;
665 kr.prefix.v4 = fn->fec.u.ipv4.prefix;
666 kr.prefixlen = fn->fec.u.ipv4.prefixlen;
667 kr.nexthop.v4 = fnh->nexthop.v4;
88d88a9c 668 kr.ifindex = fnh->ifindex;
8429abe0
RW
669 kr.local_label = fn->local_label;
670 kr.remote_label = fnh->remote_label;
671 kr.priority = fnh->priority;
672
673 lde_imsg_compose_parent(IMSG_KLABEL_DELETE, 0, &kr,
674 sizeof(kr));
675
676 if (fn->fec.u.ipv4.prefixlen == 32)
677 l2vpn_sync_pws(AF_INET, (union ldpd_addr *)
678 &fn->fec.u.ipv4.prefix);
679 break;
680 case FEC_TYPE_IPV6:
681 memset(&kr, 0, sizeof(kr));
682 kr.af = AF_INET6;
683 kr.prefix.v6 = fn->fec.u.ipv6.prefix;
684 kr.prefixlen = fn->fec.u.ipv6.prefixlen;
685 kr.nexthop.v6 = fnh->nexthop.v6;
88d88a9c 686 kr.ifindex = fnh->ifindex;
8429abe0
RW
687 kr.local_label = fn->local_label;
688 kr.remote_label = fnh->remote_label;
689 kr.priority = fnh->priority;
690
691 lde_imsg_compose_parent(IMSG_KLABEL_DELETE, 0, &kr,
692 sizeof(kr));
693
694 if (fn->fec.u.ipv6.prefixlen == 128)
695 l2vpn_sync_pws(AF_INET6, (union ldpd_addr *)
696 &fn->fec.u.ipv6.prefix);
697 break;
698 case FEC_TYPE_PWID:
699 pw = (struct l2vpn_pw *) fn->data;
700 if (!(pw->flags & F_PW_STATUS_UP))
701 return;
702 pw->flags &= ~F_PW_STATUS_UP;
703
704 memset(&kpw, 0, sizeof(kpw));
705 kpw.ifindex = pw->ifindex;
706 kpw.pw_type = fn->fec.u.pwid.type;
707 kpw.af = pw->af;
708 kpw.nexthop = pw->addr;
709 kpw.local_label = fn->local_label;
710 kpw.remote_label = fnh->remote_label;
711 kpw.flags = pw->flags;
712
713 lde_imsg_compose_parent(IMSG_KPWLABEL_DELETE, 0, &kpw,
714 sizeof(kpw));
715 break;
716 }
717}
718
719void
720lde_fec2map(struct fec *fec, struct map *map)
721{
722 memset(map, 0, sizeof(*map));
723
724 switch (fec->type) {
725 case FEC_TYPE_IPV4:
726 map->type = MAP_TYPE_PREFIX;
727 map->fec.prefix.af = AF_INET;
728 map->fec.prefix.prefix.v4 = fec->u.ipv4.prefix;
729 map->fec.prefix.prefixlen = fec->u.ipv4.prefixlen;
730 break;
731 case FEC_TYPE_IPV6:
732 map->type = MAP_TYPE_PREFIX;
733 map->fec.prefix.af = AF_INET6;
734 map->fec.prefix.prefix.v6 = fec->u.ipv6.prefix;
735 map->fec.prefix.prefixlen = fec->u.ipv6.prefixlen;
736 break;
737 case FEC_TYPE_PWID:
738 map->type = MAP_TYPE_PWID;
739 map->fec.pwid.type = fec->u.pwid.type;
740 map->fec.pwid.group_id = 0;
741 map->flags |= F_MAP_PW_ID;
742 map->fec.pwid.pwid = fec->u.pwid.pwid;
743 break;
744 }
745}
746
747void
748lde_map2fec(struct map *map, struct in_addr lsr_id, struct fec *fec)
749{
750 memset(fec, 0, sizeof(*fec));
751
752 switch (map->type) {
753 case MAP_TYPE_PREFIX:
754 switch (map->fec.prefix.af) {
755 case AF_INET:
756 fec->type = FEC_TYPE_IPV4;
757 fec->u.ipv4.prefix = map->fec.prefix.prefix.v4;
758 fec->u.ipv4.prefixlen = map->fec.prefix.prefixlen;
759 break;
760 case AF_INET6:
761 fec->type = FEC_TYPE_IPV6;
762 fec->u.ipv6.prefix = map->fec.prefix.prefix.v6;
763 fec->u.ipv6.prefixlen = map->fec.prefix.prefixlen;
764 break;
765 default:
766 fatalx("lde_map2fec: unknown af");
767 break;
768 }
769 break;
770 case MAP_TYPE_PWID:
771 fec->type = FEC_TYPE_PWID;
772 fec->u.pwid.type = map->fec.pwid.type;
773 fec->u.pwid.pwid = map->fec.pwid.pwid;
774 fec->u.pwid.lsr_id = lsr_id;
775 break;
776 }
777}
778
779void
780lde_send_labelmapping(struct lde_nbr *ln, struct fec_node *fn, int single)
781{
782 struct lde_req *lre;
783 struct lde_map *me;
784 struct map map;
785 struct l2vpn_pw *pw;
786
787 /*
788 * This function skips SL.1 - 3 and SL.9 - 14 because the label
789 * allocation is done way earlier (because of the merging nature of
790 * ldpd).
791 */
792
793 lde_fec2map(&fn->fec, &map);
794 switch (fn->fec.type) {
795 case FEC_TYPE_IPV4:
796 if (!ln->v4_enabled)
797 return;
798 break;
799 case FEC_TYPE_IPV6:
800 if (!ln->v6_enabled)
801 return;
802 break;
803 case FEC_TYPE_PWID:
804 pw = (struct l2vpn_pw *) fn->data;
805 if (pw == NULL || pw->lsr_id.s_addr != ln->id.s_addr)
806 /* not the remote end of the pseudowire */
807 return;
808
809 map.flags |= F_MAP_PW_IFMTU;
810 map.fec.pwid.ifmtu = pw->l2vpn->mtu;
811 if (pw->flags & F_PW_CWORD)
812 map.flags |= F_MAP_PW_CWORD;
813 if (pw->flags & F_PW_STATUSTLV) {
814 map.flags |= F_MAP_PW_STATUS;
815 /* VPLS are always up */
816 map.pw_status = PW_FORWARDING;
817 }
818 break;
819 }
820 map.label = fn->local_label;
821
822 /* SL.6: is there a pending request for this mapping? */
823 lre = (struct lde_req *)fec_find(&ln->recv_req, &fn->fec);
824 if (lre) {
825 /* set label request msg id in the mapping response. */
826 map.requestid = lre->msg_id;
827 map.flags = F_MAP_REQ_ID;
828
829 /* SL.7: delete record of pending request */
830 lde_req_del(ln, lre, 0);
831 }
832
833 /* SL.4: send label mapping */
834 lde_imsg_compose_ldpe(IMSG_MAPPING_ADD, ln->peerid, 0,
835 &map, sizeof(map));
836 if (single)
837 lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, ln->peerid, 0,
838 NULL, 0);
839
840 /* SL.5: record sent label mapping */
841 me = (struct lde_map *)fec_find(&ln->sent_map, &fn->fec);
842 if (me == NULL)
843 me = lde_map_add(ln, fn, 1);
844 me->map = map;
845}
846
847void
848lde_send_labelwithdraw(struct lde_nbr *ln, struct fec_node *fn, uint32_t label,
849 struct status_tlv *st)
850{
851 struct lde_wdraw *lw;
852 struct map map;
853 struct fec *f;
854 struct l2vpn_pw *pw;
855
856 if (fn) {
857 lde_fec2map(&fn->fec, &map);
858 switch (fn->fec.type) {
859 case FEC_TYPE_IPV4:
860 if (!ln->v4_enabled)
861 return;
862 break;
863 case FEC_TYPE_IPV6:
864 if (!ln->v6_enabled)
865 return;
866 break;
867 case FEC_TYPE_PWID:
868 pw = (struct l2vpn_pw *) fn->data;
869 if (pw == NULL || pw->lsr_id.s_addr != ln->id.s_addr)
870 /* not the remote end of the pseudowire */
871 return;
872
873 if (pw->flags & F_PW_CWORD)
874 map.flags |= F_MAP_PW_CWORD;
875 break;
876 }
877 map.label = fn->local_label;
878 } else {
879 memset(&map, 0, sizeof(map));
880 map.type = MAP_TYPE_WILDCARD;
881 map.label = label;
882 }
883
884 if (st) {
885 map.st.status_code = st->status_code;
886 map.st.msg_id = st->msg_id;
887 map.st.msg_type = st->msg_type;
888 map.flags |= F_MAP_STATUS;
889 }
890
891 /* SWd.1: send label withdraw. */
892 lde_imsg_compose_ldpe(IMSG_WITHDRAW_ADD, ln->peerid, 0,
893 &map, sizeof(map));
894 lde_imsg_compose_ldpe(IMSG_WITHDRAW_ADD_END, ln->peerid, 0, NULL, 0);
895
896 /* SWd.2: record label withdraw. */
897 if (fn) {
898 lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec);
899 if (lw == NULL)
900 lw = lde_wdraw_add(ln, fn);
901 lw->label = map.label;
902 } else {
903 RB_FOREACH(f, fec_tree, &ft) {
904 fn = (struct fec_node *)f;
905
906 lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw,
907 &fn->fec);
908 if (lw == NULL)
909 lw = lde_wdraw_add(ln, fn);
910 lw->label = map.label;
911 }
912 }
913}
914
915void
916lde_send_labelwithdraw_all(struct fec_node *fn, uint32_t label)
917{
918 struct lde_nbr *ln;
919
920 RB_FOREACH(ln, nbr_tree, &lde_nbrs)
921 lde_send_labelwithdraw(ln, fn, label, NULL);
922}
923
924void
925lde_send_labelrelease(struct lde_nbr *ln, struct fec_node *fn, uint32_t label)
926{
927 struct map map;
928 struct l2vpn_pw *pw;
929
930 if (fn) {
931 lde_fec2map(&fn->fec, &map);
932 switch (fn->fec.type) {
933 case FEC_TYPE_IPV4:
934 if (!ln->v4_enabled)
935 return;
936 break;
937 case FEC_TYPE_IPV6:
938 if (!ln->v6_enabled)
939 return;
940 break;
941 case FEC_TYPE_PWID:
942 pw = (struct l2vpn_pw *) fn->data;
943 if (pw == NULL || pw->lsr_id.s_addr != ln->id.s_addr)
944 /* not the remote end of the pseudowire */
945 return;
946
947 if (pw->flags & F_PW_CWORD)
948 map.flags |= F_MAP_PW_CWORD;
949 break;
950 }
951 } else {
952 memset(&map, 0, sizeof(map));
953 map.type = MAP_TYPE_WILDCARD;
954 }
955 map.label = label;
956
957 lde_imsg_compose_ldpe(IMSG_RELEASE_ADD, ln->peerid, 0,
958 &map, sizeof(map));
959 lde_imsg_compose_ldpe(IMSG_RELEASE_ADD_END, ln->peerid, 0, NULL, 0);
960}
961
962void
963lde_send_notification(uint32_t peerid, uint32_t status_code, uint32_t msg_id,
964 uint16_t msg_type)
965{
966 struct notify_msg nm;
967
968 memset(&nm, 0, sizeof(nm));
969 nm.status_code = status_code;
970 /* 'msg_id' and 'msg_type' should be in network byte order */
971 nm.msg_id = msg_id;
972 nm.msg_type = msg_type;
973
974 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, peerid, 0,
975 &nm, sizeof(nm));
976}
977
978static __inline int
979lde_nbr_compare(struct lde_nbr *a, struct lde_nbr *b)
980{
981 return (a->peerid - b->peerid);
982}
983
984static struct lde_nbr *
985lde_nbr_new(uint32_t peerid, struct lde_nbr *new)
986{
987 struct lde_nbr *ln;
988
989 if ((ln = calloc(1, sizeof(*ln))) == NULL)
990 fatal(__func__);
991
992 ln->id = new->id;
993 ln->v4_enabled = new->v4_enabled;
994 ln->v6_enabled = new->v6_enabled;
995 ln->peerid = peerid;
996 fec_init(&ln->recv_map);
997 fec_init(&ln->sent_map);
998 fec_init(&ln->recv_req);
999 fec_init(&ln->sent_req);
1000 fec_init(&ln->sent_wdraw);
1001
1002 TAILQ_INIT(&ln->addr_list);
1003
1004 if (RB_INSERT(nbr_tree, &lde_nbrs, ln) != NULL)
1005 fatalx("lde_nbr_new: RB_INSERT failed");
1006
1007 return (ln);
1008}
1009
1010static void
1011lde_nbr_del(struct lde_nbr *ln)
1012{
1013 struct fec *f;
1014 struct fec_node *fn;
1015 struct fec_nh *fnh;
1016 struct l2vpn_pw *pw;
1017
1018 if (ln == NULL)
1019 return;
1020
1021 /* uninstall received mappings */
1022 RB_FOREACH(f, fec_tree, &ft) {
1023 fn = (struct fec_node *)f;
1024
1025 LIST_FOREACH(fnh, &fn->nexthops, entry) {
1026 switch (f->type) {
1027 case FEC_TYPE_IPV4:
1028 case FEC_TYPE_IPV6:
1029 if (!lde_address_find(ln, fnh->af,
1030 &fnh->nexthop))
1031 continue;
1032 break;
1033 case FEC_TYPE_PWID:
1034 if (f->u.pwid.lsr_id.s_addr != ln->id.s_addr)
1035 continue;
1036 pw = (struct l2vpn_pw *) fn->data;
1037 if (pw)
1038 l2vpn_pw_reset(pw);
1039 break;
1040 default:
1041 break;
1042 }
1043
1044 lde_send_delete_klabel(fn, fnh);
1045 fnh->remote_label = NO_LABEL;
1046 }
1047 }
1048
1049 lde_address_list_free(ln);
1050
1051 fec_clear(&ln->recv_map, lde_map_free);
1052 fec_clear(&ln->sent_map, lde_map_free);
1053 fec_clear(&ln->recv_req, free);
1054 fec_clear(&ln->sent_req, free);
1055 fec_clear(&ln->sent_wdraw, free);
1056
1057 RB_REMOVE(nbr_tree, &lde_nbrs, ln);
1058
1059 free(ln);
1060}
1061
1062static struct lde_nbr *
1063lde_nbr_find(uint32_t peerid)
1064{
1065 struct lde_nbr ln;
1066
1067 ln.peerid = peerid;
1068
1069 return (RB_FIND(nbr_tree, &lde_nbrs, &ln));
1070}
1071
1072struct lde_nbr *
1073lde_nbr_find_by_lsrid(struct in_addr addr)
1074{
1075 struct lde_nbr *ln;
1076
1077 RB_FOREACH(ln, nbr_tree, &lde_nbrs)
1078 if (ln->id.s_addr == addr.s_addr)
1079 return (ln);
1080
1081 return (NULL);
1082}
1083
1084struct lde_nbr *
1085lde_nbr_find_by_addr(int af, union ldpd_addr *addr)
1086{
1087 struct lde_nbr *ln;
1088
1089 RB_FOREACH(ln, nbr_tree, &lde_nbrs)
1090 if (lde_address_find(ln, af, addr) != NULL)
1091 return (ln);
1092
1093 return (NULL);
1094}
1095
1096static void
1097lde_nbr_clear(void)
1098{
1099 struct lde_nbr *ln;
1100
1101 while ((ln = RB_ROOT(&lde_nbrs)) != NULL)
1102 lde_nbr_del(ln);
1103}
1104
1105static void
1106lde_nbr_addr_update(struct lde_nbr *ln, struct lde_addr *lde_addr, int removed)
1107{
1108 struct fec *fec;
1109 struct fec_node *fn;
1110 struct fec_nh *fnh;
1111 struct lde_map *me;
1112
1113 RB_FOREACH(fec, fec_tree, &ln->recv_map) {
1114 fn = (struct fec_node *)fec_find(&ft, fec);
1115 switch (fec->type) {
1116 case FEC_TYPE_IPV4:
1117 if (lde_addr->af != AF_INET)
1118 continue;
1119 break;
1120 case FEC_TYPE_IPV6:
1121 if (lde_addr->af != AF_INET6)
1122 continue;
1123 break;
1124 default:
1125 continue;
1126 }
1127
1128 LIST_FOREACH(fnh, &fn->nexthops, entry) {
1129 if (ldp_addrcmp(fnh->af, &fnh->nexthop,
1130 &lde_addr->addr))
1131 continue;
1132
1133 if (removed) {
1134 lde_send_delete_klabel(fn, fnh);
1135 fnh->remote_label = NO_LABEL;
1136 } else {
1137 me = (struct lde_map *)fec;
1138 fnh->remote_label = me->map.label;
1139 lde_send_change_klabel(fn, fnh);
1140 }
1141 break;
1142 }
1143 }
1144}
1145
d3e1887a
RW
1146static __inline int
1147lde_map_compare(struct lde_map *a, struct lde_map *b)
1148{
1149 return (ldp_addrcmp(AF_INET, (union ldpd_addr *)&a->nexthop->id,
1150 (union ldpd_addr *)&b->nexthop->id));
1151}
1152
8429abe0
RW
1153struct lde_map *
1154lde_map_add(struct lde_nbr *ln, struct fec_node *fn, int sent)
1155{
1156 struct lde_map *me;
1157
1158 me = calloc(1, sizeof(*me));
1159 if (me == NULL)
1160 fatal(__func__);
1161
1162 me->fec = fn->fec;
1163 me->nexthop = ln;
1164
1165 if (sent) {
d3e1887a
RW
1166 RB_INSERT(lde_map_head, &fn->upstream, me);
1167 me->head = &fn->upstream;
8429abe0
RW
1168 if (fec_insert(&ln->sent_map, &me->fec))
1169 log_warnx("failed to add %s to sent map",
1170 log_fec(&me->fec));
1171 /* XXX on failure more cleanup is needed */
1172 } else {
d3e1887a
RW
1173 RB_INSERT(lde_map_head, &fn->downstream, me);
1174 me->head = &fn->downstream;
8429abe0
RW
1175 if (fec_insert(&ln->recv_map, &me->fec))
1176 log_warnx("failed to add %s to recv map",
1177 log_fec(&me->fec));
1178 }
1179
1180 return (me);
1181}
1182
1183void
1184lde_map_del(struct lde_nbr *ln, struct lde_map *me, int sent)
1185{
1186 if (sent)
1187 fec_remove(&ln->sent_map, &me->fec);
1188 else
1189 fec_remove(&ln->recv_map, &me->fec);
1190
1191 lde_map_free(me);
1192}
1193
1194static void
1195lde_map_free(void *ptr)
1196{
1197 struct lde_map *map = ptr;
1198
d3e1887a 1199 RB_REMOVE(lde_map_head, map->head, map);
8429abe0
RW
1200 free(map);
1201}
1202
1203struct lde_req *
1204lde_req_add(struct lde_nbr *ln, struct fec *fec, int sent)
1205{
1206 struct fec_tree *t;
1207 struct lde_req *lre;
1208
1209 t = sent ? &ln->sent_req : &ln->recv_req;
1210
1211 lre = calloc(1, sizeof(*lre));
1212 if (lre != NULL) {
1213 lre->fec = *fec;
1214
1215 if (fec_insert(t, &lre->fec)) {
1216 log_warnx("failed to add %s to %s req",
1217 log_fec(&lre->fec), sent ? "sent" : "recv");
1218 free(lre);
1219 return (NULL);
1220 }
1221 }
1222
1223 return (lre);
1224}
1225
1226void
1227lde_req_del(struct lde_nbr *ln, struct lde_req *lre, int sent)
1228{
1229 if (sent)
1230 fec_remove(&ln->sent_req, &lre->fec);
1231 else
1232 fec_remove(&ln->recv_req, &lre->fec);
1233
1234 free(lre);
1235}
1236
1237struct lde_wdraw *
1238lde_wdraw_add(struct lde_nbr *ln, struct fec_node *fn)
1239{
1240 struct lde_wdraw *lw;
1241
1242 lw = calloc(1, sizeof(*lw));
1243 if (lw == NULL)
1244 fatal(__func__);
1245
1246 lw->fec = fn->fec;
1247
1248 if (fec_insert(&ln->sent_wdraw, &lw->fec))
1249 log_warnx("failed to add %s to sent wdraw",
1250 log_fec(&lw->fec));
1251
1252 return (lw);
1253}
1254
1255void
1256lde_wdraw_del(struct lde_nbr *ln, struct lde_wdraw *lw)
1257{
1258 fec_remove(&ln->sent_wdraw, &lw->fec);
1259 free(lw);
1260}
1261
1262void
1263lde_change_egress_label(int af, int was_implicit)
1264{
1265 struct lde_nbr *ln;
1266 struct fec *f;
1267 struct fec_node *fn;
1268
1269 RB_FOREACH(ln, nbr_tree, &lde_nbrs) {
1270 /* explicit withdraw */
1271 if (was_implicit)
1272 lde_send_labelwithdraw(ln, NULL, MPLS_LABEL_IMPLNULL,
1273 NULL);
1274 else {
1275 if (ln->v4_enabled)
1276 lde_send_labelwithdraw(ln, NULL,
1277 MPLS_LABEL_IPV4NULL, NULL);
1278 if (ln->v6_enabled)
1279 lde_send_labelwithdraw(ln, NULL,
1280 MPLS_LABEL_IPV6NULL, NULL);
1281 }
1282
1283 /* advertise new label of connected prefixes */
1284 RB_FOREACH(f, fec_tree, &ft) {
1285 fn = (struct fec_node *)f;
1286 if (fn->local_label > MPLS_LABEL_RESERVED_MAX)
1287 continue;
1288
1289 switch (af) {
1290 case AF_INET:
1291 if (fn->fec.type != FEC_TYPE_IPV4)
1292 continue;
1293 break;
1294 case AF_INET6:
1295 if (fn->fec.type != FEC_TYPE_IPV6)
1296 continue;
1297 break;
1298 default:
1299 fatalx("lde_change_egress_label: unknown af");
1300 }
1301
1302 fn->local_label = egress_label(fn->fec.type);
1303 lde_send_labelmapping(ln, fn, 0);
1304 }
1305
1306 lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, ln->peerid, 0,
1307 NULL, 0);
1308 }
1309}
1310
1311static int
1312lde_address_add(struct lde_nbr *ln, struct lde_addr *lde_addr)
1313{
1314 struct lde_addr *new;
1315
1316 if (lde_address_find(ln, lde_addr->af, &lde_addr->addr) != NULL)
1317 return (-1);
1318
1319 if ((new = calloc(1, sizeof(*new))) == NULL)
1320 fatal(__func__);
1321
1322 new->af = lde_addr->af;
1323 new->addr = lde_addr->addr;
1324 TAILQ_INSERT_TAIL(&ln->addr_list, new, entry);
1325
1326 /* reevaluate the previously received mappings from this neighbor */
1327 lde_nbr_addr_update(ln, lde_addr, 0);
1328
1329 return (0);
1330}
1331
1332static int
1333lde_address_del(struct lde_nbr *ln, struct lde_addr *lde_addr)
1334{
1335 lde_addr = lde_address_find(ln, lde_addr->af, &lde_addr->addr);
1336 if (lde_addr == NULL)
1337 return (-1);
1338
1339 /* reevaluate the previously received mappings from this neighbor */
1340 lde_nbr_addr_update(ln, lde_addr, 1);
1341
1342 TAILQ_REMOVE(&ln->addr_list, lde_addr, entry);
1343 free(lde_addr);
1344
1345 return (0);
1346}
1347
1348struct lde_addr *
1349lde_address_find(struct lde_nbr *ln, int af, union ldpd_addr *addr)
1350{
1351 struct lde_addr *lde_addr;
1352
1353 TAILQ_FOREACH(lde_addr, &ln->addr_list, entry)
1354 if (lde_addr->af == af &&
1355 ldp_addrcmp(af, &lde_addr->addr, addr) == 0)
1356 return (lde_addr);
1357
1358 return (NULL);
1359}
1360
1361static void
1362lde_address_list_free(struct lde_nbr *ln)
1363{
1364 struct lde_addr *lde_addr;
1365
1366 while ((lde_addr = TAILQ_FIRST(&ln->addr_list)) != NULL) {
1367 TAILQ_REMOVE(&ln->addr_list, lde_addr, entry);
1368 free(lde_addr);
1369 }
1370}