1 /*	$OpenBSD$ */
2 
3 /*
4  * Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
5  * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
6  * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
7  * Copyright (c) 2004, 2005, 2008 Esben Norby <norby@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 
22 #include <zebra.h>
23 
24 #include "ldpd.h"
25 #include "ldpe.h"
26 #include "lde.h"
27 #include "log.h"
28 
29 static void		 l2vpn_pw_fec(struct l2vpn_pw *, struct fec *);
30 static __inline int	 l2vpn_compare(const struct l2vpn *, const struct l2vpn *);
31 static __inline int	 l2vpn_if_compare(const struct l2vpn_if *, const struct l2vpn_if *);
32 static __inline int	 l2vpn_pw_compare(const struct l2vpn_pw *, const struct l2vpn_pw *);
33 
RB_GENERATE(l2vpn_head,l2vpn,entry,l2vpn_compare)34 RB_GENERATE(l2vpn_head, l2vpn, entry, l2vpn_compare)
35 RB_GENERATE(l2vpn_if_head, l2vpn_if, entry, l2vpn_if_compare)
36 RB_GENERATE(l2vpn_pw_head, l2vpn_pw, entry, l2vpn_pw_compare)
37 
38 static __inline int
39 l2vpn_compare(const struct l2vpn *a, const struct l2vpn *b)
40 {
41 	return (strcmp(a->name, b->name));
42 }
43 
44 struct l2vpn *
l2vpn_new(const char * name)45 l2vpn_new(const char *name)
46 {
47 	struct l2vpn	*l2vpn;
48 
49 	if ((l2vpn = calloc(1, sizeof(*l2vpn))) == NULL)
50 		fatal("l2vpn_new: calloc");
51 
52 	strlcpy(l2vpn->name, name, sizeof(l2vpn->name));
53 
54 	/* set default values */
55 	l2vpn->mtu = DEFAULT_L2VPN_MTU;
56 	l2vpn->pw_type = DEFAULT_PW_TYPE;
57 
58 	RB_INIT(l2vpn_if_head, &l2vpn->if_tree);
59 	RB_INIT(l2vpn_pw_head, &l2vpn->pw_tree);
60 	RB_INIT(l2vpn_pw_head, &l2vpn->pw_inactive_tree);
61 
62 	return (l2vpn);
63 }
64 
65 struct l2vpn *
l2vpn_find(struct ldpd_conf * xconf,const char * name)66 l2vpn_find(struct ldpd_conf *xconf, const char *name)
67 {
68 	struct l2vpn	 l2vpn;
69 	strlcpy(l2vpn.name, name, sizeof(l2vpn.name));
70 	return (RB_FIND(l2vpn_head, &xconf->l2vpn_tree, &l2vpn));
71 }
72 
73 void
l2vpn_del(struct l2vpn * l2vpn)74 l2vpn_del(struct l2vpn *l2vpn)
75 {
76 	struct l2vpn_if		*lif;
77 	struct l2vpn_pw		*pw;
78 
79 	while (!RB_EMPTY(l2vpn_if_head, &l2vpn->if_tree)) {
80 		lif = RB_ROOT(l2vpn_if_head, &l2vpn->if_tree);
81 
82 		RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
83 		free(lif);
84 	}
85 	while (!RB_EMPTY(l2vpn_pw_head, &l2vpn->pw_tree)) {
86 		pw = RB_ROOT(l2vpn_pw_head, &l2vpn->pw_tree);
87 
88 		RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
89 		free(pw);
90 	}
91 	while (!RB_EMPTY(l2vpn_pw_head, &l2vpn->pw_inactive_tree)) {
92 		pw = RB_ROOT(l2vpn_pw_head, &l2vpn->pw_inactive_tree);
93 
94 		RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
95 		free(pw);
96 	}
97 
98 	free(l2vpn);
99 }
100 
101 void
l2vpn_init(struct l2vpn * l2vpn)102 l2vpn_init(struct l2vpn *l2vpn)
103 {
104 	struct l2vpn_pw	*pw;
105 
106 	RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
107 		l2vpn_pw_init(pw);
108 }
109 
110 void
l2vpn_exit(struct l2vpn * l2vpn)111 l2vpn_exit(struct l2vpn *l2vpn)
112 {
113 	struct l2vpn_pw		*pw;
114 
115 	RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
116 		l2vpn_pw_exit(pw);
117 }
118 
119 static __inline int
l2vpn_if_compare(const struct l2vpn_if * a,const struct l2vpn_if * b)120 l2vpn_if_compare(const struct l2vpn_if *a, const struct l2vpn_if *b)
121 {
122 	return if_cmp_name_func(a->ifname, b->ifname);
123 }
124 
125 struct l2vpn_if *
l2vpn_if_new(struct l2vpn * l2vpn,const char * ifname)126 l2vpn_if_new(struct l2vpn *l2vpn, const char *ifname)
127 {
128 	struct l2vpn_if	*lif;
129 
130 	if ((lif = calloc(1, sizeof(*lif))) == NULL)
131 		fatal("l2vpn_if_new: calloc");
132 
133 	lif->l2vpn = l2vpn;
134 	strlcpy(lif->ifname, ifname, sizeof(lif->ifname));
135 
136 	return (lif);
137 }
138 
139 struct l2vpn_if *
l2vpn_if_find(struct l2vpn * l2vpn,const char * ifname)140 l2vpn_if_find(struct l2vpn *l2vpn, const char *ifname)
141 {
142 	struct l2vpn_if	 lif;
143 	strlcpy(lif.ifname, ifname, sizeof(lif.ifname));
144 	return (RB_FIND(l2vpn_if_head, &l2vpn->if_tree, &lif));
145 }
146 
147 void
l2vpn_if_update_info(struct l2vpn_if * lif,struct kif * kif)148 l2vpn_if_update_info(struct l2vpn_if *lif, struct kif *kif)
149 {
150 	lif->ifindex = kif->ifindex;
151 	lif->operative = kif->operative;
152 	memcpy(lif->mac, kif->mac, sizeof(lif->mac));
153 }
154 
155 void
l2vpn_if_update(struct l2vpn_if * lif)156 l2vpn_if_update(struct l2vpn_if *lif)
157 {
158 	struct l2vpn	*l2vpn = lif->l2vpn;
159 	struct l2vpn_pw	*pw;
160 	struct map	 fec;
161 	struct nbr	*nbr;
162 
163 	if (lif->operative)
164 		return;
165 
166 	RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
167 		nbr = nbr_find_ldpid(pw->lsr_id.s_addr);
168 		if (nbr == NULL)
169 			continue;
170 
171 		memset(&fec, 0, sizeof(fec));
172 		fec.type = MAP_TYPE_PWID;
173 		fec.fec.pwid.type = l2vpn->pw_type;
174 		fec.fec.pwid.group_id = 0;
175 		fec.flags |= F_MAP_PW_ID;
176 		fec.fec.pwid.pwid = pw->pwid;
177 
178 		send_mac_withdrawal(nbr, &fec, lif->mac);
179 	}
180 }
181 
182 static __inline int
l2vpn_pw_compare(const struct l2vpn_pw * a,const struct l2vpn_pw * b)183 l2vpn_pw_compare(const struct l2vpn_pw *a, const struct l2vpn_pw *b)
184 {
185 	return if_cmp_name_func(a->ifname, b->ifname);
186 }
187 
188 struct l2vpn_pw *
l2vpn_pw_new(struct l2vpn * l2vpn,const char * ifname)189 l2vpn_pw_new(struct l2vpn *l2vpn, const char *ifname)
190 {
191 	struct l2vpn_pw	*pw;
192 
193 	if ((pw = calloc(1, sizeof(*pw))) == NULL)
194 		fatal("l2vpn_pw_new: calloc");
195 
196 	pw->l2vpn = l2vpn;
197 	strlcpy(pw->ifname, ifname, sizeof(pw->ifname));
198 
199 	return (pw);
200 }
201 
202 struct l2vpn_pw *
l2vpn_pw_find(struct l2vpn * l2vpn,const char * ifname)203 l2vpn_pw_find(struct l2vpn *l2vpn, const char *ifname)
204 {
205 	struct l2vpn_pw	*pw;
206 	struct l2vpn_pw	 s;
207 
208 	strlcpy(s.ifname, ifname, sizeof(s.ifname));
209 	pw = RB_FIND(l2vpn_pw_head, &l2vpn->pw_tree, &s);
210 	if (pw)
211 		return (pw);
212 	return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_inactive_tree, &s));
213 }
214 
215 struct l2vpn_pw *
l2vpn_pw_find_active(struct l2vpn * l2vpn,const char * ifname)216 l2vpn_pw_find_active(struct l2vpn *l2vpn, const char *ifname)
217 {
218 	struct l2vpn_pw	 s;
219 
220 	strlcpy(s.ifname, ifname, sizeof(s.ifname));
221 	return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_tree, &s));
222 }
223 
224 struct l2vpn_pw *
l2vpn_pw_find_inactive(struct l2vpn * l2vpn,const char * ifname)225 l2vpn_pw_find_inactive(struct l2vpn *l2vpn, const char *ifname)
226 {
227 	struct l2vpn_pw	 s;
228 
229 	strlcpy(s.ifname, ifname, sizeof(s.ifname));
230 	return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_inactive_tree, &s));
231 }
232 
233 void
l2vpn_pw_update_info(struct l2vpn_pw * pw,struct kif * kif)234 l2vpn_pw_update_info(struct l2vpn_pw *pw, struct kif *kif)
235 {
236 	pw->ifindex = kif->ifindex;
237 }
238 
239 void
l2vpn_pw_init(struct l2vpn_pw * pw)240 l2vpn_pw_init(struct l2vpn_pw *pw)
241 {
242 	struct fec	 fec;
243 	struct zapi_pw	 zpw;
244 
245 	l2vpn_pw_reset(pw);
246 
247 	pw2zpw(pw, &zpw);
248 	lde_imsg_compose_parent(IMSG_KPW_ADD, 0, &zpw, sizeof(zpw));
249 
250 	l2vpn_pw_fec(pw, &fec);
251 	lde_kernel_insert(&fec, AF_INET, (union ldpd_addr*)&pw->lsr_id, 0, 0,
252 	    0, 0, (void *)pw);
253 	lde_kernel_update(&fec);
254 }
255 
256 void
l2vpn_pw_exit(struct l2vpn_pw * pw)257 l2vpn_pw_exit(struct l2vpn_pw *pw)
258 {
259 	struct fec	 fec;
260 	struct zapi_pw	 zpw;
261 
262 	l2vpn_pw_fec(pw, &fec);
263 	lde_kernel_remove(&fec, AF_INET, (union ldpd_addr*)&pw->lsr_id, 0, 0, 0);
264 	lde_kernel_update(&fec);
265 
266 	pw2zpw(pw, &zpw);
267 	lde_imsg_compose_parent(IMSG_KPW_DELETE, 0, &zpw, sizeof(zpw));
268 }
269 
270 static void
l2vpn_pw_fec(struct l2vpn_pw * pw,struct fec * fec)271 l2vpn_pw_fec(struct l2vpn_pw *pw, struct fec *fec)
272 {
273 	memset(fec, 0, sizeof(*fec));
274 	fec->type = FEC_TYPE_PWID;
275 	fec->u.pwid.type = pw->l2vpn->pw_type;
276 	fec->u.pwid.pwid = pw->pwid;
277 	fec->u.pwid.lsr_id = pw->lsr_id;
278 }
279 
280 void
l2vpn_pw_reset(struct l2vpn_pw * pw)281 l2vpn_pw_reset(struct l2vpn_pw *pw)
282 {
283 	pw->remote_group = 0;
284 	pw->remote_mtu = 0;
285 	pw->local_status = PW_FORWARDING;
286 	pw->remote_status = PW_NOT_FORWARDING;
287 
288 	if (pw->flags & F_PW_CWORD_CONF)
289 		pw->flags |= F_PW_CWORD;
290 	else
291 		pw->flags &= ~F_PW_CWORD;
292 
293 	if (pw->flags & F_PW_STATUSTLV_CONF)
294 		pw->flags |= F_PW_STATUSTLV;
295 	else
296 		pw->flags &= ~F_PW_STATUSTLV;
297 
298 	if (pw->flags & F_PW_STATUSTLV_CONF) {
299 		struct fec_node         *fn;
300 		struct fec fec;
301 		l2vpn_pw_fec(pw, &fec);
302 		fn = (struct fec_node *)fec_find(&ft, &fec);
303 		if (fn)
304 			pw->remote_status = fn->pw_remote_status;
305 	}
306 
307 }
308 
309 int
l2vpn_pw_ok(struct l2vpn_pw * pw,struct fec_nh * fnh)310 l2vpn_pw_ok(struct l2vpn_pw *pw, struct fec_nh *fnh)
311 {
312 	/* check for a remote label */
313 	if (fnh->remote_label == NO_LABEL) {
314 		log_warnx("%s: pseudowire %s: no remote label", __func__,
315 			  pw->ifname);
316 		pw->reason = F_PW_NO_REMOTE_LABEL;
317 		return (0);
318 	}
319 
320 	/* MTUs must match */
321 	if (pw->l2vpn->mtu != pw->remote_mtu) {
322 		log_warnx("%s: pseudowire %s: MTU mismatch detected", __func__,
323 			  pw->ifname);
324 		pw->reason = F_PW_MTU_MISMATCH;
325 		return (0);
326 	}
327 
328 	/* check pw status if applicable */
329 	if ((pw->flags & F_PW_STATUSTLV) &&
330 	    pw->remote_status != PW_FORWARDING) {
331 		log_warnx("%s: pseudowire %s: remote end is down", __func__,
332 			  pw->ifname);
333 		pw->reason = F_PW_REMOTE_NOT_FWD;
334 		return (0);
335 	}
336 
337 	pw->reason = F_PW_NO_ERR;
338 	return (1);
339 }
340 
341 int
l2vpn_pw_negotiate(struct lde_nbr * ln,struct fec_node * fn,struct map * map)342 l2vpn_pw_negotiate(struct lde_nbr *ln, struct fec_node *fn, struct map *map)
343 {
344 	struct l2vpn_pw		*pw;
345 	struct status_tlv	 st;
346 
347 	/* NOTE: thanks martini & friends for all this mess */
348 
349 	pw = (struct l2vpn_pw *) fn->data;
350 	if (pw == NULL)
351 		/*
352 		 * pseudowire not configured, return and record
353 		 * the mapping later
354 		 */
355 		return (0);
356 
357 	/* RFC4447 - Section 6.2: control word negotiation */
358 	if (fec_find(&ln->sent_map, &fn->fec)) {
359 		if ((map->flags & F_MAP_PW_CWORD) &&
360 		    !(pw->flags & F_PW_CWORD_CONF)) {
361 			/* ignore the received label mapping */
362 			return (1);
363 		} else if (!(map->flags & F_MAP_PW_CWORD) &&
364 		    (pw->flags & F_PW_CWORD_CONF)) {
365 			/* append a "Wrong C-bit" status code */
366 			st.status_code = S_WRONG_CBIT;
367 			st.msg_id = map->msg_id;
368 			st.msg_type = htons(MSG_TYPE_LABELMAPPING);
369 			lde_send_labelwithdraw(ln, fn, NULL, &st);
370 
371 			pw->flags &= ~F_PW_CWORD;
372 			lde_send_labelmapping(ln, fn, 1);
373 		}
374 	} else if (map->flags & F_MAP_PW_CWORD) {
375 		if (pw->flags & F_PW_CWORD_CONF)
376 			pw->flags |= F_PW_CWORD;
377 		else
378 			/* act as if no label mapping had been received */
379 			return (1);
380 	} else
381 		pw->flags &= ~F_PW_CWORD;
382 
383 	/* RFC4447 - Section 5.4.3: pseudowire status negotiation */
384 	if (fec_find(&ln->recv_map, &fn->fec) == NULL &&
385 	    !(map->flags & F_MAP_PW_STATUS))
386 		pw->flags &= ~F_PW_STATUSTLV;
387 
388 	return (0);
389 }
390 
391 void
l2vpn_send_pw_status(struct lde_nbr * ln,uint32_t status,struct fec * fec)392 l2vpn_send_pw_status(struct lde_nbr *ln, uint32_t status, struct fec *fec)
393 {
394 	struct notify_msg	 nm;
395 
396 	memset(&nm, 0, sizeof(nm));
397 	nm.status_code = S_PW_STATUS;
398 	nm.pw_status = status;
399 	nm.flags |= F_NOTIF_PW_STATUS;
400 	lde_fec2map(fec, &nm.fec);
401 	nm.flags |= F_NOTIF_FEC;
402 
403 	lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, ln->peerid, 0, &nm,
404 	    sizeof(nm));
405 }
406 
407 void
l2vpn_send_pw_status_wcard(struct lde_nbr * ln,uint32_t status,uint16_t pw_type,uint32_t group_id)408 l2vpn_send_pw_status_wcard(struct lde_nbr *ln, uint32_t status,
409     uint16_t pw_type, uint32_t group_id)
410 {
411 	struct notify_msg	 nm;
412 
413 	memset(&nm, 0, sizeof(nm));
414 	nm.status_code = S_PW_STATUS;
415 	nm.pw_status = status;
416 	nm.flags |= F_NOTIF_PW_STATUS;
417 	nm.fec.type = MAP_TYPE_PWID;
418 	nm.fec.fec.pwid.type = pw_type;
419 	nm.fec.fec.pwid.group_id = group_id;
420 	nm.flags |= F_NOTIF_FEC;
421 
422 	lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, ln->peerid, 0, &nm,
423 	    sizeof(nm));
424 }
425 
426 void
l2vpn_recv_pw_status(struct lde_nbr * ln,struct notify_msg * nm)427 l2vpn_recv_pw_status(struct lde_nbr *ln, struct notify_msg *nm)
428 {
429 	struct fec		 fec;
430 	struct fec_node		*fn;
431 	struct fec_nh		*fnh;
432 	struct l2vpn_pw		*pw;
433 
434 	if (nm->fec.type == MAP_TYPE_TYPED_WCARD ||
435 	    !(nm->fec.flags & F_MAP_PW_ID)) {
436 		l2vpn_recv_pw_status_wcard(ln, nm);
437 		return;
438 	}
439 
440 	lde_map2fec(&nm->fec, ln->id, &fec);
441 	fn = (struct fec_node *)fec_find(&ft, &fec);
442 	if (fn == NULL)
443 		/* unknown fec */
444 		return;
445 
446 	fn->pw_remote_status = nm->pw_status;
447 
448 	pw = (struct l2vpn_pw *) fn->data;
449 	if (pw == NULL)
450 		return;
451 
452 	fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *)&ln->id, 0, 0, 0);
453 	if (fnh == NULL)
454 		return;
455 
456 	/* remote status didn't change */
457 	if (pw->remote_status == nm->pw_status)
458 		return;
459 	pw->remote_status = nm->pw_status;
460 
461 	if (l2vpn_pw_ok(pw, fnh))
462 		lde_send_change_klabel(fn, fnh);
463 	else
464 		lde_send_delete_klabel(fn, fnh);
465 }
466 
467 /* RFC4447 PWid group wildcard */
468 void
l2vpn_recv_pw_status_wcard(struct lde_nbr * ln,struct notify_msg * nm)469 l2vpn_recv_pw_status_wcard(struct lde_nbr *ln, struct notify_msg *nm)
470 {
471 	struct fec		*f;
472 	struct fec_node		*fn;
473 	struct fec_nh		*fnh;
474 	struct l2vpn_pw		*pw;
475 	struct map		*wcard = &nm->fec;
476 
477 	RB_FOREACH(f, fec_tree, &ft) {
478 		fn = (struct fec_node *)f;
479 		if (fn->fec.type != FEC_TYPE_PWID)
480 			continue;
481 
482 		pw = (struct l2vpn_pw *) fn->data;
483 		if (pw == NULL)
484 			continue;
485 
486 		switch (wcard->type) {
487 		case MAP_TYPE_TYPED_WCARD:
488 			if (wcard->fec.twcard.u.pw_type != PW_TYPE_WILDCARD &&
489 			    wcard->fec.twcard.u.pw_type != fn->fec.u.pwid.type)
490 				continue;
491 			break;
492 		case MAP_TYPE_PWID:
493 			if (wcard->fec.pwid.type != fn->fec.u.pwid.type)
494 				continue;
495 			if (wcard->fec.pwid.group_id != pw->remote_group)
496 				continue;
497 			break;
498 		}
499 
500 		fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *)&ln->id,
501 		    0, 0, 0);
502 		if (fnh == NULL)
503 			continue;
504 
505 		/* remote status didn't change */
506 		if (pw->remote_status == nm->pw_status)
507 			continue;
508 		pw->remote_status = nm->pw_status;
509 
510 		if (l2vpn_pw_ok(pw, fnh))
511 			lde_send_change_klabel(fn, fnh);
512 		else
513 			lde_send_delete_klabel(fn, fnh);
514 	}
515 }
516 
517 int
l2vpn_pw_status_update(struct zapi_pw_status * zpw)518 l2vpn_pw_status_update(struct zapi_pw_status *zpw)
519 {
520 	struct l2vpn		*l2vpn;
521 	struct l2vpn_pw		*pw = NULL;
522 	struct lde_nbr		*ln;
523 	struct fec		 fec;
524 	uint32_t		 local_status;
525 
526 	RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree) {
527 		pw = l2vpn_pw_find(l2vpn, zpw->ifname);
528 		if (pw)
529 			break;
530 	}
531 	if (!pw) {
532 		log_warnx("%s: pseudowire %s not found", __func__, zpw->ifname);
533 		return (1);
534 	}
535 
536 	if (zpw->status == PW_FORWARDING) {
537 		local_status = PW_FORWARDING;
538 		pw->reason = F_PW_NO_ERR;
539 	} else {
540 		local_status = zpw->status;
541 		pw->reason = F_PW_LOCAL_NOT_FWD;
542 	}
543 
544 	/* local status didn't change */
545 	if (pw->local_status == local_status)
546 		return (0);
547 	pw->local_status = local_status;
548 
549 	/* notify remote peer about the status update */
550 	ln = lde_nbr_find_by_lsrid(pw->lsr_id);
551 	if (ln == NULL)
552 		return (0);
553 	l2vpn_pw_fec(pw, &fec);
554 	if (pw->flags & F_PW_STATUSTLV)
555 		l2vpn_send_pw_status(ln, local_status, &fec);
556 	else {
557 		struct fec_node *fn;
558 		fn = (struct fec_node *)fec_find(&ft, &fec);
559 		if (fn) {
560 			if (pw->local_status == PW_FORWARDING)
561 				lde_send_labelmapping(ln, fn, 1);
562 			else
563 				lde_send_labelwithdraw(ln, fn, NULL, NULL);
564 		}
565 	}
566 
567 	return (0);
568 }
569 
570 void
l2vpn_pw_ctl(pid_t pid)571 l2vpn_pw_ctl(pid_t pid)
572 {
573 	struct l2vpn		*l2vpn;
574 	struct l2vpn_pw		*pw;
575 	static struct ctl_pw	 pwctl;
576 
577 	RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree)
578 		RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
579 			memset(&pwctl, 0, sizeof(pwctl));
580 			strlcpy(pwctl.l2vpn_name, pw->l2vpn->name,
581 			    sizeof(pwctl.l2vpn_name));
582 			strlcpy(pwctl.ifname, pw->ifname,
583 			    sizeof(pwctl.ifname));
584 			pwctl.pwid = pw->pwid;
585 			pwctl.lsr_id = pw->lsr_id;
586 			pwctl.status = PW_NOT_FORWARDING;
587 			if (pw->enabled &&
588 			    pw->local_status == PW_FORWARDING &&
589 			    pw->remote_status == PW_FORWARDING)
590 				pwctl.status = PW_FORWARDING;
591 
592 			lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_PW, 0,
593 			    pid, &pwctl, sizeof(pwctl));
594 		}
595 }
596 
597 void
l2vpn_binding_ctl(pid_t pid)598 l2vpn_binding_ctl(pid_t pid)
599 {
600 	struct fec		*f;
601 	struct fec_node		*fn;
602 	struct lde_map		*me;
603 	struct l2vpn_pw		*pw;
604 	static struct ctl_pw	 pwctl;
605 
606 	RB_FOREACH(f, fec_tree, &ft) {
607 		if (f->type != FEC_TYPE_PWID)
608 			continue;
609 
610 		fn = (struct fec_node *)f;
611 		if (fn->local_label == NO_LABEL &&
612 		    RB_EMPTY(lde_map_head, &fn->downstream))
613 			continue;
614 
615 		memset(&pwctl, 0, sizeof(pwctl));
616 		pwctl.type = f->u.pwid.type;
617 		pwctl.pwid = f->u.pwid.pwid;
618 		pwctl.lsr_id = f->u.pwid.lsr_id;
619 
620 		pw = (struct l2vpn_pw *) fn->data;
621 		if (pw) {
622 			pwctl.local_label = fn->local_label;
623 			pwctl.local_gid = 0;
624 			pwctl.local_ifmtu = pw->l2vpn->mtu;
625 			pwctl.local_cword = (pw->flags & F_PW_CWORD_CONF) ?
626 			    1 : 0;
627 			pwctl.reason = pw->reason;
628 		} else
629 			pwctl.local_label = NO_LABEL;
630 
631 		RB_FOREACH(me, lde_map_head, &fn->downstream)
632 			if (f->u.pwid.lsr_id.s_addr == me->nexthop->id.s_addr)
633 				break;
634 
635 		if (me) {
636 			pwctl.remote_label = me->map.label;
637 			pwctl.remote_gid = me->map.fec.pwid.group_id;
638 			if (me->map.flags & F_MAP_PW_IFMTU)
639 				pwctl.remote_ifmtu = me->map.fec.pwid.ifmtu;
640 			if (pw)
641 				pwctl.remote_cword = (pw->flags & F_PW_CWORD) ?
642 				    1 : 0;
643 
644 			lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING,
645 			    0, pid, &pwctl, sizeof(pwctl));
646 		} else if (pw) {
647 			pwctl.remote_label = NO_LABEL;
648 
649 			lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING,
650 			    0, pid, &pwctl, sizeof(pwctl));
651 		}
652 	}
653 }
654 
655 /* ldpe */
656 
657 void
ldpe_l2vpn_init(struct l2vpn * l2vpn)658 ldpe_l2vpn_init(struct l2vpn *l2vpn)
659 {
660 	struct l2vpn_pw		*pw;
661 
662 	RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
663 		ldpe_l2vpn_pw_init(pw);
664 }
665 
666 void
ldpe_l2vpn_exit(struct l2vpn * l2vpn)667 ldpe_l2vpn_exit(struct l2vpn *l2vpn)
668 {
669 	struct l2vpn_pw		*pw;
670 
671 	RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
672 		ldpe_l2vpn_pw_exit(pw);
673 }
674 
675 void
ldpe_l2vpn_pw_init(struct l2vpn_pw * pw)676 ldpe_l2vpn_pw_init(struct l2vpn_pw *pw)
677 {
678 	struct tnbr		*tnbr;
679 
680 	tnbr = tnbr_find(leconf, pw->af, &pw->addr);
681 	if (tnbr == NULL) {
682 		tnbr = tnbr_new(pw->af, &pw->addr);
683 		tnbr_update(tnbr);
684 		RB_INSERT(tnbr_head, &leconf->tnbr_tree, tnbr);
685 	}
686 
687 	tnbr->pw_count++;
688 }
689 
690 void
ldpe_l2vpn_pw_exit(struct l2vpn_pw * pw)691 ldpe_l2vpn_pw_exit(struct l2vpn_pw *pw)
692 {
693 	struct tnbr		*tnbr;
694 
695 	tnbr = tnbr_find(leconf, pw->af, &pw->addr);
696 	if (tnbr) {
697 		tnbr->pw_count--;
698 		tnbr_check(leconf, tnbr);
699 	}
700 }
701