GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ldpd/l2vpn.c Lines: 0 252 0.0 %
Date: 2017-11-07 Branches: 0 164 0.0 %

Line Branch Exec Source
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
32
static void	 l2vpn_pw_fec(struct l2vpn_pw *, struct fec *);
33
34
struct l2vpn *
35
l2vpn_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
54
struct l2vpn *
55
l2vpn_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
66
void
67
l2vpn_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
84
void
85
l2vpn_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
93
void
94
l2vpn_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
102
struct l2vpn_if *
103
l2vpn_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
119
struct l2vpn_if *
120
l2vpn_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
131
void
132
l2vpn_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
158
struct l2vpn_pw *
159
l2vpn_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
173
struct l2vpn_pw *
174
l2vpn_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
185
void
186
l2vpn_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
197
void
198
l2vpn_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
206
static void
207
l2vpn_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
216
void
217
l2vpn_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
234
int
235
l2vpn_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
284
int
285
l2vpn_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
334
void
335
l2vpn_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
350
void
351
l2vpn_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
369
void
370
l2vpn_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 */
409
void
410
l2vpn_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
457
void
458
l2vpn_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
488
void
489
l2vpn_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
509
void
510
l2vpn_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
563
void
564
ldpe_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
572
void
573
ldpe_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
581
void
582
ldpe_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
596
void
597
ldpe_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
}