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