l2vpn.c revision 1.24
1/*	$OpenBSD: l2vpn.c,v 1.24 2017/03/04 00:21:48 renato Exp $ */
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 <sys/types.h>
23#include <stdlib.h>
24#include <string.h>
25#include <limits.h>
26
27#include "ldpd.h"
28#include "ldpe.h"
29#include "lde.h"
30#include "log.h"
31
32static void	 l2vpn_pw_fec(struct l2vpn_pw *, struct fec *);
33
34struct l2vpn *
35l2vpn_new(const char *name)
36{
37	struct l2vpn	*l2vpn;
38
39	if ((l2vpn = calloc(1, sizeof(*l2vpn))) == NULL)
40		fatal("l2vpn_new: calloc");
41
42	strlcpy(l2vpn->name, name, sizeof(l2vpn->name));
43
44	/* set default values */
45	l2vpn->mtu = DEFAULT_L2VPN_MTU;
46	l2vpn->pw_type = DEFAULT_PW_TYPE;
47
48	LIST_INIT(&l2vpn->if_list);
49	LIST_INIT(&l2vpn->pw_list);
50
51	return (l2vpn);
52}
53
54struct l2vpn *
55l2vpn_find(struct ldpd_conf *xconf, const char *name)
56{
57	struct l2vpn	*l2vpn;
58
59	LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry)
60		if (strcmp(l2vpn->name, name) == 0)
61			return (l2vpn);
62
63	return (NULL);
64}
65
66void
67l2vpn_del(struct l2vpn *l2vpn)
68{
69	struct l2vpn_if		*lif;
70	struct l2vpn_pw		*pw;
71
72	while ((lif = LIST_FIRST(&l2vpn->if_list)) != NULL) {
73		LIST_REMOVE(lif, entry);
74		free(lif);
75	}
76	while ((pw = LIST_FIRST(&l2vpn->pw_list)) != NULL) {
77		LIST_REMOVE(pw, entry);
78		free(pw);
79	}
80
81	free(l2vpn);
82}
83
84void
85l2vpn_init(struct l2vpn *l2vpn)
86{
87	struct l2vpn_pw	*pw;
88
89	LIST_FOREACH(pw, &l2vpn->pw_list, entry)
90		l2vpn_pw_init(pw);
91}
92
93void
94l2vpn_exit(struct l2vpn *l2vpn)
95{
96	struct l2vpn_pw		*pw;
97
98	LIST_FOREACH(pw, &l2vpn->pw_list, entry)
99		l2vpn_pw_exit(pw);
100}
101
102struct l2vpn_if *
103l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif)
104{
105	struct l2vpn_if	*lif;
106
107	if ((lif = calloc(1, sizeof(*lif))) == NULL)
108		fatal("l2vpn_if_new: calloc");
109
110	lif->l2vpn = l2vpn;
111	strlcpy(lif->ifname, kif->ifname, sizeof(lif->ifname));
112	lif->ifindex = kif->ifindex;
113	lif->flags = kif->flags;
114	lif->linkstate = kif->link_state;
115
116	return (lif);
117}
118
119struct l2vpn_if *
120l2vpn_if_find(struct l2vpn *l2vpn, unsigned int ifindex)
121{
122	struct l2vpn_if	*lif;
123
124	LIST_FOREACH(lif, &l2vpn->if_list, entry)
125		if (lif->ifindex == ifindex)
126			return (lif);
127
128	return (NULL);
129}
130
131void
132l2vpn_if_update(struct l2vpn_if *lif)
133{
134	struct l2vpn	*l2vpn = lif->l2vpn;
135	struct l2vpn_pw	*pw;
136	struct map	 fec;
137	struct nbr	*nbr;
138
139	if ((lif->flags & IFF_UP) && LINK_STATE_IS_UP(lif->linkstate))
140		return;
141
142	LIST_FOREACH(pw, &l2vpn->pw_list, entry) {
143		nbr = nbr_find_ldpid(pw->lsr_id.s_addr);
144		if (nbr == NULL)
145			continue;
146
147		memset(&fec, 0, sizeof(fec));
148		fec.type = MAP_TYPE_PWID;
149		fec.fec.pwid.type = l2vpn->pw_type;
150		fec.fec.pwid.group_id = 0;
151		fec.flags |= F_MAP_PW_ID;
152		fec.fec.pwid.pwid = pw->pwid;
153
154		send_mac_withdrawal(nbr, &fec, lif->mac);
155	}
156}
157
158struct l2vpn_pw *
159l2vpn_pw_new(struct l2vpn *l2vpn, struct kif *kif)
160{
161	struct l2vpn_pw	*pw;
162
163	if ((pw = calloc(1, sizeof(*pw))) == NULL)
164		fatal("l2vpn_pw_new: calloc");
165
166	pw->l2vpn = l2vpn;
167	strlcpy(pw->ifname, kif->ifname, sizeof(pw->ifname));
168	pw->ifindex = kif->ifindex;
169
170	return (pw);
171}
172
173struct l2vpn_pw *
174l2vpn_pw_find(struct l2vpn *l2vpn, unsigned int ifindex)
175{
176	struct l2vpn_pw	*pw;
177
178	LIST_FOREACH(pw, &l2vpn->pw_list, entry)
179		if (pw->ifindex == ifindex)
180			return (pw);
181
182	return (NULL);
183}
184
185void
186l2vpn_pw_init(struct l2vpn_pw *pw)
187{
188	struct fec	 fec;
189
190	l2vpn_pw_reset(pw);
191
192	l2vpn_pw_fec(pw, &fec);
193	lde_kernel_insert(&fec, AF_INET, (union ldpd_addr*)&pw->lsr_id, 0,
194	    0, (void *)pw);
195}
196
197void
198l2vpn_pw_exit(struct l2vpn_pw *pw)
199{
200	struct fec	 fec;
201
202	l2vpn_pw_fec(pw, &fec);
203	lde_kernel_remove(&fec, AF_INET, (union ldpd_addr*)&pw->lsr_id, 0);
204}
205
206static void
207l2vpn_pw_fec(struct l2vpn_pw *pw, struct fec *fec)
208{
209	memset(fec, 0, sizeof(*fec));
210	fec->type = FEC_TYPE_PWID;
211	fec->u.pwid.type = pw->l2vpn->pw_type;
212	fec->u.pwid.pwid = pw->pwid;
213	fec->u.pwid.lsr_id = pw->lsr_id;
214}
215
216void
217l2vpn_pw_reset(struct l2vpn_pw *pw)
218{
219	pw->remote_group = 0;
220	pw->remote_mtu = 0;
221	pw->remote_status = 0;
222
223	if (pw->flags & F_PW_CWORD_CONF)
224		pw->flags |= F_PW_CWORD;
225	else
226		pw->flags &= ~F_PW_CWORD;
227
228	if (pw->flags & F_PW_STATUSTLV_CONF)
229		pw->flags |= F_PW_STATUSTLV;
230	else
231		pw->flags &= ~F_PW_STATUSTLV;
232}
233
234int
235l2vpn_pw_ok(struct l2vpn_pw *pw, struct fec_nh *fnh)
236{
237	struct fec		 fec;
238	struct fec_node		*fn;
239
240	/* check for a remote label */
241	if (fnh->remote_label == NO_LABEL)
242		return (0);
243
244	/* MTUs must match */
245	if (pw->l2vpn->mtu != pw->remote_mtu)
246		return (0);
247
248	/* check pw status if applicable */
249	if ((pw->flags & F_PW_STATUSTLV) &&
250	    pw->remote_status != PW_FORWARDING)
251		return (0);
252
253	/* check for a working lsp to the nexthop */
254	memset(&fec, 0, sizeof(fec));
255	switch (pw->af) {
256	case AF_INET:
257		fec.type = FEC_TYPE_IPV4;
258		fec.u.ipv4.prefix = pw->addr.v4;
259		fec.u.ipv4.prefixlen = 32;
260		break;
261	case AF_INET6:
262		fec.type = FEC_TYPE_IPV6;
263		fec.u.ipv6.prefix = pw->addr.v6;
264		fec.u.ipv6.prefixlen = 128;
265		break;
266	default:
267		fatalx("l2vpn_pw_ok: unknown af");
268	}
269
270	fn = (struct fec_node *)fec_find(&ft, &fec);
271	if (fn == NULL || fn->local_label == NO_LABEL)
272		return (0);
273	/*
274	 * Need to ensure that there's a label binding for all nexthops.
275	 * Otherwise, ECMP for this route could render the pseudowire unusable.
276	 */
277	LIST_FOREACH(fnh, &fn->nexthops, entry)
278		if (fnh->remote_label == NO_LABEL)
279			return (0);
280
281	return (1);
282}
283
284int
285l2vpn_pw_negotiate(struct lde_nbr *ln, struct fec_node *fn, struct map *map)
286{
287	struct l2vpn_pw		*pw;
288	struct status_tlv	 st;
289
290	/* NOTE: thanks martini & friends for all this mess */
291
292	pw = (struct l2vpn_pw *) fn->data;
293	if (pw == NULL)
294		/*
295		 * pseudowire not configured, return and record
296		 * the mapping later
297		 */
298		return (0);
299
300	/* RFC4447 - Section 6.2: control word negotiation */
301	if (fec_find(&ln->sent_map, &fn->fec)) {
302		if ((map->flags & F_MAP_PW_CWORD) &&
303		    !(pw->flags & F_PW_CWORD_CONF)) {
304			/* ignore the received label mapping */
305			return (1);
306		} else if (!(map->flags & F_MAP_PW_CWORD) &&
307		    (pw->flags & F_PW_CWORD_CONF)) {
308			/* append a "Wrong C-bit" status code */
309			st.status_code = S_WRONG_CBIT;
310			st.msg_id = map->msg_id;
311			st.msg_type = htons(MSG_TYPE_LABELMAPPING);
312			lde_send_labelwithdraw(ln, fn, NULL, &st);
313
314			pw->flags &= ~F_PW_CWORD;
315			lde_send_labelmapping(ln, fn, 1);
316		}
317	} else if (map->flags & F_MAP_PW_CWORD) {
318		if (pw->flags & F_PW_CWORD_CONF)
319			pw->flags |= F_PW_CWORD;
320		else
321			/* act as if no label mapping had been received */
322			return (1);
323	} else
324		pw->flags &= ~F_PW_CWORD;
325
326	/* RFC4447 - Section 5.4.3: pseudowire status negotiation */
327	if (fec_find(&ln->recv_map, &fn->fec) == NULL &&
328	    !(map->flags & F_MAP_PW_STATUS))
329		pw->flags &= ~F_PW_STATUSTLV;
330
331	return (0);
332}
333
334void
335l2vpn_send_pw_status(struct lde_nbr *ln, uint32_t status, struct fec *fec)
336{
337	struct notify_msg	 nm;
338
339	memset(&nm, 0, sizeof(nm));
340	nm.status_code = S_PW_STATUS;
341	nm.pw_status = status;
342	nm.flags |= F_NOTIF_PW_STATUS;
343	lde_fec2map(fec, &nm.fec);
344	nm.flags |= F_NOTIF_FEC;
345
346	lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, ln->peerid, 0, &nm,
347	    sizeof(nm));
348}
349
350void
351l2vpn_send_pw_status_wcard(struct lde_nbr *ln, uint32_t status,
352    uint16_t pw_type, uint32_t group_id)
353{
354	struct notify_msg	 nm;
355
356	memset(&nm, 0, sizeof(nm));
357	nm.status_code = S_PW_STATUS;
358	nm.pw_status = status;
359	nm.flags |= F_NOTIF_PW_STATUS;
360	nm.fec.type = MAP_TYPE_PWID;
361	nm.fec.fec.pwid.type = pw_type;
362	nm.fec.fec.pwid.group_id = group_id;
363	nm.flags |= F_NOTIF_FEC;
364
365	lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, ln->peerid, 0, &nm,
366	    sizeof(nm));
367}
368
369void
370l2vpn_recv_pw_status(struct lde_nbr *ln, struct notify_msg *nm)
371{
372	struct fec		 fec;
373	struct fec_node		*fn;
374	struct fec_nh		*fnh;
375	struct l2vpn_pw		*pw;
376
377	if (nm->fec.type == MAP_TYPE_TYPED_WCARD ||
378	    !(nm->fec.flags & F_MAP_PW_ID)) {
379		l2vpn_recv_pw_status_wcard(ln, nm);
380		return;
381	}
382
383	lde_map2fec(&nm->fec, ln->id, &fec);
384	fn = (struct fec_node *)fec_find(&ft, &fec);
385	if (fn == NULL)
386		/* unknown fec */
387		return;
388
389	pw = (struct l2vpn_pw *) fn->data;
390	if (pw == NULL)
391		return;
392
393	fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *)&ln->id, 0);
394	if (fnh == NULL)
395		return;
396
397	/* remote status didn't change */
398	if (pw->remote_status == nm->pw_status)
399		return;
400	pw->remote_status = nm->pw_status;
401
402	if (l2vpn_pw_ok(pw, fnh))
403		lde_send_change_klabel(fn, fnh);
404	else
405		lde_send_delete_klabel(fn, fnh);
406}
407
408/* RFC4447 PWid group wildcard */
409void
410l2vpn_recv_pw_status_wcard(struct lde_nbr *ln, struct notify_msg *nm)
411{
412	struct fec		*f;
413	struct fec_node		*fn;
414	struct fec_nh		*fnh;
415	struct l2vpn_pw		*pw;
416	struct map		*wcard = &nm->fec;
417
418	RB_FOREACH(f, fec_tree, &ft) {
419		fn = (struct fec_node *)f;
420		if (fn->fec.type != FEC_TYPE_PWID)
421			continue;
422
423		pw = (struct l2vpn_pw *) fn->data;
424		if (pw == NULL)
425			continue;
426
427		switch (wcard->type) {
428		case MAP_TYPE_TYPED_WCARD:
429			if (wcard->fec.twcard.u.pw_type != PW_TYPE_WILDCARD &&
430			    wcard->fec.twcard.u.pw_type != fn->fec.u.pwid.type)
431				continue;
432			break;
433		case MAP_TYPE_PWID:
434			if (wcard->fec.pwid.type != fn->fec.u.pwid.type)
435				continue;
436			if (wcard->fec.pwid.group_id != pw->remote_group)
437				continue;
438			break;
439		}
440
441		fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *)&ln->id, 0);
442		if (fnh == NULL)
443			continue;
444
445		/* remote status didn't change */
446		if (pw->remote_status == nm->pw_status)
447			continue;
448		pw->remote_status = nm->pw_status;
449
450		if (l2vpn_pw_ok(pw, fnh))
451			lde_send_change_klabel(fn, fnh);
452		else
453			lde_send_delete_klabel(fn, fnh);
454	}
455}
456
457void
458l2vpn_sync_pws(int af, union ldpd_addr *addr)
459{
460	struct l2vpn		*l2vpn;
461	struct l2vpn_pw		*pw;
462	struct fec		 fec;
463	struct fec_node		*fn;
464	struct fec_nh		*fnh;
465
466	LIST_FOREACH(l2vpn, &ldeconf->l2vpn_list, entry) {
467		LIST_FOREACH(pw, &l2vpn->pw_list, entry) {
468			if (af != pw->af || ldp_addrcmp(af, &pw->addr, addr))
469				continue;
470
471			l2vpn_pw_fec(pw, &fec);
472			fn = (struct fec_node *)fec_find(&ft, &fec);
473			if (fn == NULL)
474				continue;
475			fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *)
476			    &pw->lsr_id, 0);
477			if (fnh == NULL)
478				continue;
479
480			if (l2vpn_pw_ok(pw, fnh))
481				lde_send_change_klabel(fn, fnh);
482			else
483				lde_send_delete_klabel(fn, fnh);
484		}
485	}
486}
487
488void
489l2vpn_pw_ctl(pid_t pid)
490{
491	struct l2vpn		*l2vpn;
492	struct l2vpn_pw		*pw;
493	static struct ctl_pw	 pwctl;
494
495	LIST_FOREACH(l2vpn, &ldeconf->l2vpn_list, entry)
496		LIST_FOREACH(pw, &l2vpn->pw_list, entry) {
497			memset(&pwctl, 0, sizeof(pwctl));
498			strlcpy(pwctl.ifname, pw->ifname,
499			    sizeof(pwctl.ifname));
500			pwctl.pwid = pw->pwid;
501			pwctl.lsr_id = pw->lsr_id;
502			pwctl.status = pw->flags & F_PW_STATUS_UP;
503
504			lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_PW, 0,
505			    pid, &pwctl, sizeof(pwctl));
506		}
507}
508
509void
510l2vpn_binding_ctl(pid_t pid)
511{
512	struct fec		*f;
513	struct fec_node		*fn;
514	struct lde_map		*me;
515	struct l2vpn_pw		*pw;
516	static struct ctl_pw	 pwctl;
517
518	RB_FOREACH(f, fec_tree, &ft) {
519		if (f->type != FEC_TYPE_PWID)
520			continue;
521
522		fn = (struct fec_node *)f;
523		if (fn->local_label == NO_LABEL &&
524		    LIST_EMPTY(&fn->downstream))
525			continue;
526
527		memset(&pwctl, 0, sizeof(pwctl));
528		pwctl.type = f->u.pwid.type;
529		pwctl.pwid = f->u.pwid.pwid;
530		pwctl.lsr_id = f->u.pwid.lsr_id;
531
532		pw = (struct l2vpn_pw *) fn->data;
533		if (pw) {
534			pwctl.local_label = fn->local_label;
535			pwctl.local_gid = 0;
536			pwctl.local_ifmtu = pw->l2vpn->mtu;
537		} else
538			pwctl.local_label = NO_LABEL;
539
540		LIST_FOREACH(me, &fn->downstream, entry)
541			if (f->u.pwid.lsr_id.s_addr == me->nexthop->id.s_addr)
542				break;
543
544		if (me) {
545			pwctl.remote_label = me->map.label;
546			pwctl.remote_gid = me->map.fec.pwid.group_id;
547			if (me->map.flags & F_MAP_PW_IFMTU)
548				pwctl.remote_ifmtu = me->map.fec.pwid.ifmtu;
549
550			lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING,
551			    0, pid, &pwctl, sizeof(pwctl));
552		} else if (pw) {
553			pwctl.remote_label = NO_LABEL;
554
555			lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING,
556			    0, pid, &pwctl, sizeof(pwctl));
557		}
558	}
559}
560
561/* ldpe */
562
563void
564ldpe_l2vpn_init(struct l2vpn *l2vpn)
565{
566	struct l2vpn_pw		*pw;
567
568	LIST_FOREACH(pw, &l2vpn->pw_list, entry)
569		ldpe_l2vpn_pw_init(pw);
570}
571
572void
573ldpe_l2vpn_exit(struct l2vpn *l2vpn)
574{
575	struct l2vpn_pw		*pw;
576
577	LIST_FOREACH(pw, &l2vpn->pw_list, entry)
578		ldpe_l2vpn_pw_exit(pw);
579}
580
581void
582ldpe_l2vpn_pw_init(struct l2vpn_pw *pw)
583{
584	struct tnbr		*tnbr;
585
586	tnbr = tnbr_find(leconf, pw->af, &pw->addr);
587	if (tnbr == NULL) {
588		tnbr = tnbr_new(leconf, pw->af, &pw->addr);
589		tnbr_update(tnbr);
590		LIST_INSERT_HEAD(&leconf->tnbr_list, tnbr, entry);
591	}
592
593	tnbr->pw_count++;
594}
595
596void
597ldpe_l2vpn_pw_exit(struct l2vpn_pw *pw)
598{
599	struct tnbr		*tnbr;
600
601	tnbr = tnbr_find(leconf, pw->af, &pw->addr);
602	if (tnbr) {
603		tnbr->pw_count--;
604		tnbr_check(tnbr);
605	}
606}
607