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