xref: /openbsd/usr.sbin/ldpd/lde_lib.c (revision 5b133f3f)
1 /*	$OpenBSD: lde_lib.c,v 1.71 2023/03/08 04:43:13 guenther Exp $ */
2 
3 /*
4  * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
5  * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <netmpls/mpls.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <limits.h>
26 
27 #include "ldpd.h"
28 #include "lde.h"
29 #include "ldpe.h"
30 #include "log.h"
31 
32 static __inline int	 fec_compare(struct fec *, struct fec *);
33 static int		 lde_nbr_is_nexthop(struct fec_node *,
34 			    struct lde_nbr *);
35 static void		 fec_free(void *);
36 static struct fec_node	*fec_add(struct fec *fec);
37 static struct fec_nh	*fec_nh_add(struct fec_node *, int, union ldpd_addr *,
38 			    uint8_t priority);
39 static void		 fec_nh_del(struct fec_nh *);
40 
41 RB_GENERATE(fec_tree, fec, entry, fec_compare)
42 
43 struct fec_tree		 ft = RB_INITIALIZER(&ft);
44 struct event		 gc_timer;
45 
46 /* FEC tree functions */
47 void
fec_init(struct fec_tree * fh)48 fec_init(struct fec_tree *fh)
49 {
50 	RB_INIT(fh);
51 }
52 
53 static __inline int
fec_compare(struct fec * a,struct fec * b)54 fec_compare(struct fec *a, struct fec *b)
55 {
56 	if (a->type < b->type)
57 		return (-1);
58 	if (a->type > b->type)
59 		return (1);
60 
61 	switch (a->type) {
62 	case FEC_TYPE_IPV4:
63 		if (ntohl(a->u.ipv4.prefix.s_addr) <
64 		    ntohl(b->u.ipv4.prefix.s_addr))
65 			return (-1);
66 		if (ntohl(a->u.ipv4.prefix.s_addr) >
67 		    ntohl(b->u.ipv4.prefix.s_addr))
68 			return (1);
69 		if (a->u.ipv4.prefixlen < b->u.ipv4.prefixlen)
70 			return (-1);
71 		if (a->u.ipv4.prefixlen > b->u.ipv4.prefixlen)
72 			return (1);
73 		return (0);
74 	case FEC_TYPE_IPV6:
75 		if (memcmp(&a->u.ipv6.prefix, &b->u.ipv6.prefix,
76 		    sizeof(struct in6_addr)) < 0)
77 			return (-1);
78 		if (memcmp(&a->u.ipv6.prefix, &b->u.ipv6.prefix,
79 		    sizeof(struct in6_addr)) > 0)
80 			return (1);
81 		if (a->u.ipv6.prefixlen < b->u.ipv6.prefixlen)
82 			return (-1);
83 		if (a->u.ipv6.prefixlen > b->u.ipv6.prefixlen)
84 			return (1);
85 		return (0);
86 	case FEC_TYPE_PWID:
87 		if (a->u.pwid.type < b->u.pwid.type)
88 			return (-1);
89 		if (a->u.pwid.type > b->u.pwid.type)
90 			return (1);
91 		if (a->u.pwid.pwid < b->u.pwid.pwid)
92 			return (-1);
93 		if (a->u.pwid.pwid > b->u.pwid.pwid)
94 			return (1);
95 		if (ntohl(a->u.pwid.lsr_id.s_addr) <
96 		    ntohl(b->u.pwid.lsr_id.s_addr))
97 			return (-1);
98 		if (ntohl(a->u.pwid.lsr_id.s_addr) >
99 		    ntohl(b->u.pwid.lsr_id.s_addr))
100 			return (1);
101 		return (0);
102 	}
103 
104 	return (-1);
105 }
106 
107 struct fec *
fec_find(struct fec_tree * fh,struct fec * f)108 fec_find(struct fec_tree *fh, struct fec *f)
109 {
110 	return (RB_FIND(fec_tree, fh, f));
111 }
112 
113 int
fec_insert(struct fec_tree * fh,struct fec * f)114 fec_insert(struct fec_tree *fh, struct fec *f)
115 {
116 	if (RB_INSERT(fec_tree, fh, f) != NULL)
117 		return (-1);
118 	return (0);
119 }
120 
121 int
fec_remove(struct fec_tree * fh,struct fec * f)122 fec_remove(struct fec_tree *fh, struct fec *f)
123 {
124 	if (RB_REMOVE(fec_tree, fh, f) == NULL) {
125 		log_warnx("%s failed for %s", __func__, log_fec(f));
126 		return (-1);
127 	}
128 	return (0);
129 }
130 
131 void
fec_clear(struct fec_tree * fh,void (* free_cb)(void *))132 fec_clear(struct fec_tree *fh, void (*free_cb)(void *))
133 {
134 	struct fec	*f;
135 
136 	while ((f = RB_ROOT(fh)) != NULL) {
137 		fec_remove(fh, f);
138 		free_cb(f);
139 	}
140 }
141 
142 /* routing table functions */
143 static int
lde_nbr_is_nexthop(struct fec_node * fn,struct lde_nbr * ln)144 lde_nbr_is_nexthop(struct fec_node *fn, struct lde_nbr *ln)
145 {
146 	struct fec_nh		*fnh;
147 
148 	LIST_FOREACH(fnh, &fn->nexthops, entry)
149 		if (lde_address_find(ln, fnh->af, &fnh->nexthop))
150 			return (1);
151 
152 	return (0);
153 }
154 
155 void
rt_dump(pid_t pid)156 rt_dump(pid_t pid)
157 {
158 	struct fec		*f;
159 	struct fec_node		*fn;
160 	struct lde_map		*me;
161 	static struct ctl_rt	 rtctl;
162 
163 	RB_FOREACH(f, fec_tree, &ft) {
164 		fn = (struct fec_node *)f;
165 		if (fn->local_label == NO_LABEL &&
166 		    LIST_EMPTY(&fn->downstream))
167 			continue;
168 
169 		switch (fn->fec.type) {
170 		case FEC_TYPE_IPV4:
171 			rtctl.af = AF_INET;
172 			rtctl.prefix.v4 = fn->fec.u.ipv4.prefix;
173 			rtctl.prefixlen = fn->fec.u.ipv4.prefixlen;
174 			break;
175 		case FEC_TYPE_IPV6:
176 			rtctl.af = AF_INET6;
177 			rtctl.prefix.v6 = fn->fec.u.ipv6.prefix;
178 			rtctl.prefixlen = fn->fec.u.ipv6.prefixlen;
179 			break;
180 		default:
181 			continue;
182 		}
183 
184 		rtctl.local_label = fn->local_label;
185 		LIST_FOREACH(me, &fn->downstream, entry) {
186 			rtctl.in_use = lde_nbr_is_nexthop(fn, me->nexthop);
187 			rtctl.nexthop = me->nexthop->id;
188 			rtctl.remote_label = me->map.label;
189 
190 			lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB, 0, pid,
191 			    &rtctl, sizeof(rtctl));
192 		}
193 		if (LIST_EMPTY(&fn->downstream)) {
194 			rtctl.in_use = 0;
195 			rtctl.nexthop.s_addr = INADDR_ANY;
196 			rtctl.remote_label = NO_LABEL;
197 
198 			lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB, 0, pid,
199 			    &rtctl, sizeof(rtctl));
200 		}
201 	}
202 }
203 
204 void
fec_snap(struct lde_nbr * ln)205 fec_snap(struct lde_nbr *ln)
206 {
207 	struct fec	*f;
208 	struct fec_node	*fn;
209 
210 	RB_FOREACH(f, fec_tree, &ft) {
211 		fn = (struct fec_node *)f;
212 		if (fn->local_label == NO_LABEL)
213 			continue;
214 
215 		lde_send_labelmapping(ln, fn, 0);
216 	}
217 
218 	lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, ln->peerid, 0, NULL, 0);
219 
220 	/*
221 	 * RFC 5919 - Section 4:
222 	 * "An LDP speaker that conforms to this specification SHOULD signal
223 	 * completion of its label advertisements to a peer by means of a
224 	 * Notification message, if its peer has advertised the Unrecognized
225 	 * Notification capability during session establishment.  The LDP
226 	 * speaker SHOULD send the Notification message (per Forwarding
227 	 * Equivalence Class (FEC) Type) to a peer even if the LDP speaker has
228 	 * zero Label bindings to advertise to that peer".
229 	 */
230 	if (ln->flags & F_NBR_CAP_UNOTIF) {
231 		lde_send_notification_eol_prefix(ln, AF_INET);
232 		lde_send_notification_eol_prefix(ln, AF_INET6);
233 		lde_send_notification_eol_pwid(ln, PW_TYPE_WILDCARD);
234 	}
235 }
236 
237 static void
fec_free(void * arg)238 fec_free(void *arg)
239 {
240 	struct fec_node	*fn = arg;
241 	struct fec_nh	*fnh;
242 
243 	while ((fnh = LIST_FIRST(&fn->nexthops)))
244 		fec_nh_del(fnh);
245 	if (!LIST_EMPTY(&fn->downstream))
246 		log_warnx("%s: fec %s downstream list not empty", __func__,
247 		    log_fec(&fn->fec));
248 	if (!LIST_EMPTY(&fn->upstream))
249 		log_warnx("%s: fec %s upstream list not empty", __func__,
250 		    log_fec(&fn->fec));
251 
252 	free(fn);
253 }
254 
255 void
fec_tree_clear(void)256 fec_tree_clear(void)
257 {
258 	fec_clear(&ft, fec_free);
259 }
260 
261 static struct fec_node *
fec_add(struct fec * fec)262 fec_add(struct fec *fec)
263 {
264 	struct fec_node	*fn;
265 
266 	fn = calloc(1, sizeof(*fn));
267 	if (fn == NULL)
268 		fatal(__func__);
269 
270 	fn->fec = *fec;
271 	fn->local_label = NO_LABEL;
272 	LIST_INIT(&fn->upstream);
273 	LIST_INIT(&fn->downstream);
274 	LIST_INIT(&fn->nexthops);
275 
276 	if (fec_insert(&ft, &fn->fec))
277 		log_warnx("failed to add %s to ft tree",
278 		    log_fec(&fn->fec));
279 
280 	return (fn);
281 }
282 
283 struct fec_nh *
fec_nh_find(struct fec_node * fn,int af,union ldpd_addr * nexthop,uint8_t priority)284 fec_nh_find(struct fec_node *fn, int af, union ldpd_addr *nexthop,
285     uint8_t priority)
286 {
287 	struct fec_nh	*fnh;
288 
289 	LIST_FOREACH(fnh, &fn->nexthops, entry)
290 		if (fnh->af == af &&
291 		    ldp_addrcmp(af, &fnh->nexthop, nexthop) == 0 &&
292 		    fnh->priority == priority)
293 			return (fnh);
294 
295 	return (NULL);
296 }
297 
298 static struct fec_nh *
fec_nh_add(struct fec_node * fn,int af,union ldpd_addr * nexthop,uint8_t priority)299 fec_nh_add(struct fec_node *fn, int af, union ldpd_addr *nexthop,
300     uint8_t priority)
301 {
302 	struct fec_nh	*fnh;
303 
304 	fnh = calloc(1, sizeof(*fnh));
305 	if (fnh == NULL)
306 		fatal(__func__);
307 
308 	fnh->af = af;
309 	fnh->nexthop = *nexthop;
310 	fnh->remote_label = NO_LABEL;
311 	fnh->priority = priority;
312 	LIST_INSERT_HEAD(&fn->nexthops, fnh, entry);
313 
314 	return (fnh);
315 }
316 
317 static void
fec_nh_del(struct fec_nh * fnh)318 fec_nh_del(struct fec_nh *fnh)
319 {
320 	LIST_REMOVE(fnh, entry);
321 	free(fnh);
322 }
323 
324 uint32_t
egress_label(enum fec_type fec_type)325 egress_label(enum fec_type fec_type)
326 {
327 	switch (fec_type) {
328 	case FEC_TYPE_IPV4:
329 		if (ldeconf->ipv4.flags & F_LDPD_AF_EXPNULL)
330 			return (MPLS_LABEL_IPV4NULL);
331 		break;
332 	case FEC_TYPE_IPV6:
333 		if (ldeconf->ipv6.flags & F_LDPD_AF_EXPNULL)
334 			return (MPLS_LABEL_IPV6NULL);
335 		break;
336 	default:
337 		fatalx("egress_label: unexpected fec type");
338 	}
339 
340 	return (MPLS_LABEL_IMPLNULL);
341 }
342 
343 void
lde_kernel_insert(struct fec * fec,int af,union ldpd_addr * nexthop,uint8_t priority,int connected,void * data)344 lde_kernel_insert(struct fec *fec, int af, union ldpd_addr *nexthop,
345     uint8_t priority, int connected, void *data)
346 {
347 	struct fec_node		*fn;
348 	struct fec_nh		*fnh;
349 	struct lde_map		*me;
350 	struct lde_nbr		*ln;
351 
352 	fn = (struct fec_node *)fec_find(&ft, fec);
353 	if (fn == NULL)
354 		fn = fec_add(fec);
355 	if (fec_nh_find(fn, af, nexthop, priority) != NULL)
356 		return;
357 
358 	log_debug("lde add fec %s nexthop %s",
359 	    log_fec(&fn->fec), log_addr(af, nexthop));
360 
361 	if (fn->fec.type == FEC_TYPE_PWID)
362 		fn->data = data;
363 
364 	if (fn->local_label == NO_LABEL) {
365 		if (connected)
366 			fn->local_label = egress_label(fn->fec.type);
367 		else
368 			fn->local_label = lde_assign_label();
369 
370 		/* FEC.1: perform lsr label distribution procedure */
371 		RB_FOREACH(ln, nbr_tree, &lde_nbrs)
372 			lde_send_labelmapping(ln, fn, 1);
373 	}
374 
375 	fnh = fec_nh_add(fn, af, nexthop, priority);
376 	lde_send_change_klabel(fn, fnh);
377 
378 	switch (fn->fec.type) {
379 	case FEC_TYPE_IPV4:
380 	case FEC_TYPE_IPV6:
381 		ln = lde_nbr_find_by_addr(af, &fnh->nexthop);
382 		break;
383 	case FEC_TYPE_PWID:
384 		ln = lde_nbr_find_by_lsrid(fn->fec.u.pwid.lsr_id);
385 		break;
386 	default:
387 		ln = NULL;
388 		break;
389 	}
390 
391 	if (ln) {
392 		/* FEC.2  */
393 		me = (struct lde_map *)fec_find(&ln->recv_map, &fn->fec);
394 		if (me)
395 			/* FEC.5 */
396 			lde_check_mapping(&me->map, ln);
397 	}
398 }
399 
400 void
lde_kernel_remove(struct fec * fec,int af,union ldpd_addr * nexthop,uint8_t priority)401 lde_kernel_remove(struct fec *fec, int af, union ldpd_addr *nexthop,
402     uint8_t priority)
403 {
404 	struct fec_node		*fn;
405 	struct fec_nh		*fnh;
406 	struct lde_nbr		*ln;
407 
408 	fn = (struct fec_node *)fec_find(&ft, fec);
409 	if (fn == NULL)
410 		/* route lost */
411 		return;
412 	fnh = fec_nh_find(fn, af, nexthop, priority);
413 	if (fnh == NULL)
414 		/* route lost */
415 		return;
416 
417 	log_debug("lde remove fec %s nexthop %s",
418 	    log_fec(&fn->fec), log_addr(af, nexthop));
419 
420 	lde_send_delete_klabel(fn, fnh);
421 	fec_nh_del(fnh);
422 	if (LIST_EMPTY(&fn->nexthops)) {
423 		RB_FOREACH(ln, nbr_tree, &lde_nbrs)
424 			lde_send_labelwithdraw(ln, fn, NULL, NULL);
425 		fn->local_label = NO_LABEL;
426 		if (fn->fec.type == FEC_TYPE_PWID)
427 			fn->data = NULL;
428 	}
429 }
430 
431 void
lde_check_mapping(struct map * map,struct lde_nbr * ln)432 lde_check_mapping(struct map *map, struct lde_nbr *ln)
433 {
434 	struct fec		 fec;
435 	struct fec_node		*fn;
436 	struct fec_nh		*fnh;
437 	struct lde_req		*lre;
438 	struct lde_map		*me;
439 	struct l2vpn_pw		*pw;
440 	int			 msgsource = 0;
441 
442 	lde_map2fec(map, ln->id, &fec);
443 	fn = (struct fec_node *)fec_find(&ft, &fec);
444 	if (fn == NULL)
445 		fn = fec_add(&fec);
446 
447 	/* LMp.1: first check if we have a pending request running */
448 	lre = (struct lde_req *)fec_find(&ln->sent_req, &fn->fec);
449 	if (lre)
450 		/* LMp.2: delete record of outstanding label request */
451 		lde_req_del(ln, lre, 1);
452 
453 	/* RFC 4447 control word and status tlv negotiation */
454 	if (map->type == MAP_TYPE_PWID && l2vpn_pw_negotiate(ln, fn, map))
455 		return;
456 
457 	/*
458 	 * LMp.3 - LMp.8: loop detection - unnecessary for frame-mode
459 	 * mpls networks.
460 	 */
461 
462 	/* LMp.9 */
463 	me = (struct lde_map *)fec_find(&ln->recv_map, &fn->fec);
464 	if (me) {
465 		/* LMp.10 */
466 		if (me->map.label != map->label && lre == NULL) {
467 			/* LMp.10a */
468 			lde_send_labelrelease(ln, fn, NULL, me->map.label);
469 
470 			/*
471 			 * Can not use lde_nbr_find_by_addr() because there's
472 			 * the possibility of multipath.
473 			 */
474 			LIST_FOREACH(fnh, &fn->nexthops, entry) {
475 				if (lde_address_find(ln, fnh->af,
476 				    &fnh->nexthop) == NULL)
477 					continue;
478 
479 				lde_send_delete_klabel(fn, fnh);
480 				fnh->remote_label = NO_LABEL;
481 			}
482 		}
483 	}
484 
485 	/*
486 	 * LMp.11 - 12: consider multiple nexthops in order to
487 	 * support multipath
488 	 */
489 	LIST_FOREACH(fnh, &fn->nexthops, entry) {
490 		/* LMp.15: install FEC in FIB */
491 		switch (fec.type) {
492 		case FEC_TYPE_IPV4:
493 		case FEC_TYPE_IPV6:
494 			if (!lde_address_find(ln, fnh->af, &fnh->nexthop))
495 				continue;
496 
497 			fnh->remote_label = map->label;
498 			lde_send_change_klabel(fn, fnh);
499 			break;
500 		case FEC_TYPE_PWID:
501 			pw = (struct l2vpn_pw *) fn->data;
502 			if (pw == NULL)
503 				continue;
504 
505 			pw->remote_group = map->fec.pwid.group_id;
506 			if (map->flags & F_MAP_PW_IFMTU)
507 				pw->remote_mtu = map->fec.pwid.ifmtu;
508 			if (map->flags & F_MAP_PW_STATUS)
509 				pw->remote_status = map->pw_status;
510 			fnh->remote_label = map->label;
511 			if (l2vpn_pw_ok(pw, fnh))
512 				lde_send_change_klabel(fn, fnh);
513 			break;
514 		default:
515 			break;
516 		}
517 
518 		msgsource = 1;
519 	}
520 	/* LMp.13 & LMp.16: Record the mapping from this peer */
521 	if (me == NULL)
522 		me = lde_map_add(ln, fn, 0);
523 	me->map = *map;
524 
525 	if (msgsource == 0)
526 		/* LMp.13: just return since we use liberal lbl retention */
527 		return;
528 
529 	/*
530 	 * LMp.17 - LMp.27 are unnecessary since we don't need to implement
531 	 * loop detection. LMp.28 - LMp.30 are unnecessary because we are
532 	 * merging capable.
533 	 */
534 }
535 
536 void
lde_check_request(struct map * map,struct lde_nbr * ln)537 lde_check_request(struct map *map, struct lde_nbr *ln)
538 {
539 	struct fec	 fec;
540 	struct lde_req	*lre;
541 	struct fec_node	*fn;
542 	struct fec_nh	*fnh;
543 
544 	/* wildcard label request */
545 	if (map->type == MAP_TYPE_TYPED_WCARD) {
546 		lde_check_request_wcard(map, ln);
547 		return;
548 	}
549 
550 	/* LRq.1: skip loop detection (not necessary) */
551 
552 	/* LRq.2: is there a next hop for fec? */
553 	lde_map2fec(map, ln->id, &fec);
554 	fn = (struct fec_node *)fec_find(&ft, &fec);
555 	if (fn == NULL || LIST_EMPTY(&fn->nexthops)) {
556 		/* LRq.5: send No Route notification */
557 		lde_send_notification(ln, S_NO_ROUTE, map->msg_id,
558 		    htons(MSG_TYPE_LABELREQUEST));
559 		return;
560 	}
561 
562 	/* LRq.3: is MsgSource the next hop? */
563 	LIST_FOREACH(fnh, &fn->nexthops, entry) {
564 		switch (fec.type) {
565 		case FEC_TYPE_IPV4:
566 		case FEC_TYPE_IPV6:
567 			if (!lde_address_find(ln, fnh->af, &fnh->nexthop))
568 				continue;
569 
570 			/* LRq.4: send Loop Detected notification */
571 			lde_send_notification(ln, S_LOOP_DETECTED, map->msg_id,
572 			    htons(MSG_TYPE_LABELREQUEST));
573 			return;
574 		default:
575 			break;
576 		}
577 	}
578 
579 	/* LRq.6: first check if we have a pending request running */
580 	lre = (struct lde_req *)fec_find(&ln->recv_req, &fn->fec);
581 	if (lre != NULL)
582 		/* LRq.7: duplicate request */
583 		return;
584 
585 	/* LRq.8: record label request */
586 	lre = lde_req_add(ln, &fn->fec, 0);
587 	if (lre != NULL)
588 		lre->msg_id = ntohl(map->msg_id);
589 
590 	/* LRq.9: perform LSR label distribution */
591 	lde_send_labelmapping(ln, fn, 1);
592 
593 	/*
594 	 * LRq.10: do nothing (Request Never) since we use liberal
595 	 * label retention.
596 	 * LRq.11 - 12 are unnecessary since we are merging capable.
597 	 */
598 }
599 
600 void
lde_check_request_wcard(struct map * map,struct lde_nbr * ln)601 lde_check_request_wcard(struct map *map, struct lde_nbr *ln)
602 {
603 	struct fec	*f;
604 	struct fec_node	*fn;
605 	struct lde_req	*lre;
606 
607 	RB_FOREACH(f, fec_tree, &ft) {
608 		fn = (struct fec_node *)f;
609 
610 		/* only a typed wildcard is possible here */
611 		if (lde_wildcard_apply(map, &fn->fec, NULL) == 0)
612 			continue;
613 
614 		/* LRq.2: is there a next hop for fec? */
615 		if (LIST_EMPTY(&fn->nexthops))
616 			continue;
617 
618 		/* LRq.6: first check if we have a pending request running */
619 		lre = (struct lde_req *)fec_find(&ln->recv_req, &fn->fec);
620 		if (lre != NULL)
621 			/* LRq.7: duplicate request */
622 			continue;
623 
624 		/* LRq.8: record label request */
625 		lre = lde_req_add(ln, &fn->fec, 0);
626 		if (lre != NULL)
627 			lre->msg_id = ntohl(map->msg_id);
628 
629 		/* LRq.9: perform LSR label distribution */
630 		lde_send_labelmapping(ln, fn, 1);
631 	}
632 
633 	/*
634 	 * RFC 5919 - Section 5.3:
635 	 * "When an LDP speaker receives a Label Request message for a Typed
636 	 * Wildcard FEC (e.g., a particular FEC Element Type) from a peer, the
637 	 * LDP speaker determines the set of bindings (as per any local
638 	 * filtering policy) to advertise to the peer for the FEC type specified
639 	 * by the request.  Assuming the peer had advertised the Unrecognized
640 	 * Notification capability at session initialization time, the speaker
641 	 * should send the peer an End-of-LIB Notification for the FEC type when
642 	 * it completes advertisement of the permitted bindings".
643 	 */
644 	if (ln->flags & F_NBR_CAP_UNOTIF) {
645 		switch (map->fec.twcard.type) {
646 		case MAP_TYPE_PREFIX:
647 			lde_send_notification_eol_prefix(ln,
648 			    map->fec.twcard.u.prefix_af);
649 			break;
650 		case MAP_TYPE_PWID:
651 			lde_send_notification_eol_pwid(ln,
652 			    map->fec.twcard.u.pw_type);
653 			break;
654 		default:
655 			break;
656 		}
657 	}
658 }
659 
660 void
lde_check_release(struct map * map,struct lde_nbr * ln)661 lde_check_release(struct map *map, struct lde_nbr *ln)
662 {
663 	struct fec		 fec;
664 	struct fec_node		*fn;
665 	struct lde_wdraw	*lw;
666 	struct lde_map		*me;
667 
668 	/* wildcard label release */
669 	if (map->type == MAP_TYPE_WILDCARD ||
670 	    map->type == MAP_TYPE_TYPED_WCARD ||
671 	    (map->type == MAP_TYPE_PWID && !(map->flags & F_MAP_PW_ID))) {
672 		lde_check_release_wcard(map, ln);
673 		return;
674 	}
675 
676 	lde_map2fec(map, ln->id, &fec);
677 	fn = (struct fec_node *)fec_find(&ft, &fec);
678 	/* LRl.1: does FEC match a known FEC? */
679 	if (fn == NULL)
680 		return;
681 
682 	/* LRl.3: first check if we have a pending withdraw running */
683 	lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec);
684 	if (lw && (map->label == NO_LABEL || map->label == lw->label)) {
685 		/* LRl.4: delete record of outstanding label withdraw */
686 		lde_wdraw_del(ln, lw);
687 	}
688 
689 	/* LRl.6: check sent map list and remove it if available */
690 	me = (struct lde_map *)fec_find(&ln->sent_map, &fn->fec);
691 	if (me && (map->label == NO_LABEL || map->label == me->map.label))
692 		lde_map_del(ln, me, 1);
693 
694 	/*
695 	 * LRl.11 - 13 are unnecessary since we remove the label from
696 	 * forwarding/switching as soon as the FEC is unreachable.
697 	 */
698 }
699 
700 void
lde_check_release_wcard(struct map * map,struct lde_nbr * ln)701 lde_check_release_wcard(struct map *map, struct lde_nbr *ln)
702 {
703 	struct fec		*f;
704 	struct fec_node		*fn;
705 	struct lde_wdraw	*lw;
706 	struct lde_map		*me;
707 
708 	RB_FOREACH(f, fec_tree, &ft) {
709 		fn = (struct fec_node *)f;
710 		me = (struct lde_map *)fec_find(&ln->sent_map, &fn->fec);
711 
712 		/* LRl.1: does FEC match a known FEC? */
713 		if (lde_wildcard_apply(map, &fn->fec, me) == 0)
714 			continue;
715 
716 		/* LRl.3: first check if we have a pending withdraw running */
717 		lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec);
718 		if (lw && (map->label == NO_LABEL || map->label == lw->label)) {
719 			/* LRl.4: delete record of outstanding lbl withdraw */
720 			lde_wdraw_del(ln, lw);
721 		}
722 
723 		/* LRl.6: check sent map list and remove it if available */
724 		if (me &&
725 		    (map->label == NO_LABEL || map->label == me->map.label))
726 			lde_map_del(ln, me, 1);
727 
728 		/*
729 		 * LRl.11 - 13 are unnecessary since we remove the label from
730 		 * forwarding/switching as soon as the FEC is unreachable.
731 		 */
732 	}
733 }
734 
735 void
lde_check_withdraw(struct map * map,struct lde_nbr * ln)736 lde_check_withdraw(struct map *map, struct lde_nbr *ln)
737 {
738 	struct fec		 fec;
739 	struct fec_node		*fn;
740 	struct fec_nh		*fnh;
741 	struct lde_map		*me;
742 	struct l2vpn_pw		*pw;
743 
744 	/* wildcard label withdraw */
745 	if (map->type == MAP_TYPE_WILDCARD ||
746 	    map->type == MAP_TYPE_TYPED_WCARD ||
747 	    (map->type == MAP_TYPE_PWID && !(map->flags & F_MAP_PW_ID))) {
748 		lde_check_withdraw_wcard(map, ln);
749 		return;
750 	}
751 
752 	lde_map2fec(map, ln->id, &fec);
753 	fn = (struct fec_node *)fec_find(&ft, &fec);
754 	if (fn == NULL)
755 		fn = fec_add(&fec);
756 
757 	/* LWd.1: remove label from forwarding/switching use */
758 	LIST_FOREACH(fnh, &fn->nexthops, entry) {
759 		switch (fec.type) {
760 		case FEC_TYPE_IPV4:
761 		case FEC_TYPE_IPV6:
762 			if (!lde_address_find(ln, fnh->af, &fnh->nexthop))
763 				continue;
764 			break;
765 		case FEC_TYPE_PWID:
766 			pw = (struct l2vpn_pw *) fn->data;
767 			if (pw == NULL)
768 				continue;
769 			break;
770 		default:
771 			break;
772 		}
773 		if (map->label != NO_LABEL && map->label != fnh->remote_label)
774 			continue;
775 
776 		lde_send_delete_klabel(fn, fnh);
777 		fnh->remote_label = NO_LABEL;
778 	}
779 
780 	/* LWd.2: send label release */
781 	lde_send_labelrelease(ln, fn, NULL, map->label);
782 
783 	/* LWd.3: check previously received label mapping */
784 	me = (struct lde_map *)fec_find(&ln->recv_map, &fn->fec);
785 	if (me && (map->label == NO_LABEL || map->label == me->map.label))
786 		/* LWd.4: remove record of previously received lbl mapping */
787 		lde_map_del(ln, me, 0);
788 }
789 
790 void
lde_check_withdraw_wcard(struct map * map,struct lde_nbr * ln)791 lde_check_withdraw_wcard(struct map *map, struct lde_nbr *ln)
792 {
793 	struct fec	*f;
794 	struct fec_node	*fn;
795 	struct fec_nh	*fnh;
796 	struct lde_map	*me;
797 
798 	/* LWd.2: send label release */
799 	lde_send_labelrelease(ln, NULL, map, map->label);
800 
801 	RB_FOREACH(f, fec_tree, &ft) {
802 		fn = (struct fec_node *)f;
803 		me = (struct lde_map *)fec_find(&ln->recv_map, &fn->fec);
804 
805 		if (lde_wildcard_apply(map, &fn->fec, me) == 0)
806 			continue;
807 
808 		/* LWd.1: remove label from forwarding/switching use */
809 		LIST_FOREACH(fnh, &fn->nexthops, entry) {
810 			switch (f->type) {
811 			case FEC_TYPE_IPV4:
812 			case FEC_TYPE_IPV6:
813 				if (!lde_address_find(ln, fnh->af,
814 				    &fnh->nexthop))
815 					continue;
816 				break;
817 			case FEC_TYPE_PWID:
818 				if (f->u.pwid.lsr_id.s_addr != ln->id.s_addr)
819 					continue;
820 				break;
821 			default:
822 				break;
823 			}
824 			if (map->label != NO_LABEL && map->label !=
825 			    fnh->remote_label)
826 				continue;
827 
828 			lde_send_delete_klabel(fn, fnh);
829 			fnh->remote_label = NO_LABEL;
830 		}
831 
832 		/* LWd.3: check previously received label mapping */
833 		if (me && (map->label == NO_LABEL ||
834 		    map->label == me->map.label))
835 			/*
836 			 * LWd.4: remove record of previously received
837 			 * label mapping
838 			 */
839 			lde_map_del(ln, me, 0);
840 	}
841 }
842 
843 int
lde_wildcard_apply(struct map * wcard,struct fec * fec,struct lde_map * me)844 lde_wildcard_apply(struct map *wcard, struct fec *fec, struct lde_map *me)
845 {
846 	switch (wcard->type) {
847 	case MAP_TYPE_WILDCARD:
848 		/* full wildcard */
849 		return (1);
850 	case MAP_TYPE_TYPED_WCARD:
851 		switch (wcard->fec.twcard.type) {
852 		case MAP_TYPE_PREFIX:
853 			if (wcard->fec.twcard.u.prefix_af == AF_INET &&
854 			    fec->type != FEC_TYPE_IPV4)
855 				return (0);
856 			if (wcard->fec.twcard.u.prefix_af == AF_INET6 &&
857 			    fec->type != FEC_TYPE_IPV6)
858 				return (0);
859 			return (1);
860 		case MAP_TYPE_PWID:
861 			if (fec->type != FEC_TYPE_PWID)
862 				return (0);
863 			if (wcard->fec.twcard.u.pw_type != PW_TYPE_WILDCARD &&
864 			    wcard->fec.twcard.u.pw_type != fec->u.pwid.type)
865 				return (0);
866 			return (1);
867 		default:
868 			fatalx("lde_wildcard_apply: unexpected fec type");
869 		}
870 		break;
871 	case MAP_TYPE_PWID:
872 		/* RFC4447 pw-id group wildcard */
873 		if (fec->type != FEC_TYPE_PWID)
874 			return (0);
875 		if (fec->u.pwid.type != wcard->fec.pwid.type)
876 			return (0);
877 		if (me == NULL || (me->map.fec.pwid.group_id !=
878 		    wcard->fec.pwid.group_id))
879 			return (0);
880 		return (1);
881 	default:
882 		fatalx("lde_wildcard_apply: unexpected fec type");
883 	}
884 }
885 
886 /* garbage collector timer: timer to remove dead entries from the LIB */
887 
888 void
lde_gc_timer(int fd,short event,void * arg)889 lde_gc_timer(int fd, short event, void *arg)
890 {
891 	struct fec	*fec, *safe;
892 	struct fec_node	*fn;
893 	int		 count = 0;
894 
895 	RB_FOREACH_SAFE(fec, fec_tree, &ft, safe) {
896 		fn = (struct fec_node *) fec;
897 
898 		if (!LIST_EMPTY(&fn->nexthops) ||
899 		    !LIST_EMPTY(&fn->downstream) ||
900 		    !LIST_EMPTY(&fn->upstream))
901 			continue;
902 
903 		fec_remove(&ft, &fn->fec);
904 		free(fn);
905 		count++;
906 	}
907 
908 	if (count > 0)
909 		log_debug("%s: %u entries removed", __func__, count);
910 
911 	lde_gc_start_timer();
912 }
913 
914 void
lde_gc_start_timer(void)915 lde_gc_start_timer(void)
916 {
917 	struct timeval	 tv;
918 
919 	timerclear(&tv);
920 	tv.tv_sec = LDE_GC_INTERVAL;
921 	if (evtimer_add(&gc_timer, &tv) == -1)
922 		fatal(__func__);
923 }
924 
925 void
lde_gc_stop_timer(void)926 lde_gc_stop_timer(void)
927 {
928 	if (evtimer_pending(&gc_timer, NULL) &&
929 	    evtimer_del(&gc_timer) == -1)
930 		fatal(__func__);
931 }
932