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 *
l2vpn_new(const char * name)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 *
l2vpn_find(struct ldpd_conf * xconf,const char * name)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
l2vpn_del(struct l2vpn * l2vpn)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
l2vpn_init(struct l2vpn * l2vpn)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
l2vpn_exit(struct l2vpn * l2vpn)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 *
l2vpn_if_new(struct l2vpn * l2vpn,struct kif * kif)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 *
l2vpn_if_find(struct l2vpn * l2vpn,unsigned int ifindex)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
l2vpn_if_update(struct l2vpn_if * lif)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 *
l2vpn_pw_new(struct l2vpn * l2vpn,struct kif * kif)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 *
l2vpn_pw_find(struct l2vpn * l2vpn,unsigned int ifindex)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
l2vpn_pw_init(struct l2vpn_pw * pw)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
l2vpn_pw_exit(struct l2vpn_pw * pw)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
l2vpn_pw_fec(struct l2vpn_pw * pw,struct fec * fec)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
l2vpn_pw_reset(struct l2vpn_pw * pw)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
l2vpn_pw_ok(struct l2vpn_pw * pw,struct fec_nh * fnh)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
l2vpn_pw_negotiate(struct lde_nbr * ln,struct fec_node * fn,struct map * map)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
l2vpn_send_pw_status(struct lde_nbr * ln,uint32_t status,struct fec * fec)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
l2vpn_send_pw_status_wcard(struct lde_nbr * ln,uint32_t status,uint16_t pw_type,uint32_t group_id)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
l2vpn_recv_pw_status(struct lde_nbr * ln,struct notify_msg * nm)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
l2vpn_recv_pw_status_wcard(struct lde_nbr * ln,struct notify_msg * nm)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
l2vpn_sync_pws(int af,union ldpd_addr * addr)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
l2vpn_pw_ctl(pid_t pid)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
l2vpn_binding_ctl(pid_t pid)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
ldpe_l2vpn_init(struct l2vpn * l2vpn)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
ldpe_l2vpn_exit(struct l2vpn * l2vpn)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
ldpe_l2vpn_pw_init(struct l2vpn_pw * pw)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
ldpe_l2vpn_pw_exit(struct l2vpn_pw * pw)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 }
607