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>
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.
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.
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
*);
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
)
39 l2vpn_compare(const struct l2vpn
*a
, const struct l2vpn
*b
)
41 return (strcmp(a
->name
, b
->name
));
45 l2vpn_new(const char *name
)
49 if ((l2vpn
= calloc(1, sizeof(*l2vpn
))) == NULL
)
50 fatal("l2vpn_new: calloc");
52 strlcpy(l2vpn
->name
, name
, sizeof(l2vpn
->name
));
54 /* set default values */
55 l2vpn
->mtu
= DEFAULT_L2VPN_MTU
;
56 l2vpn
->pw_type
= DEFAULT_PW_TYPE
;
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
);
66 l2vpn_find(struct ldpd_conf
*xconf
, const char *name
)
69 strlcpy(l2vpn
.name
, name
, sizeof(l2vpn
.name
));
70 return (RB_FIND(l2vpn_head
, &xconf
->l2vpn_tree
, &l2vpn
));
74 l2vpn_del(struct l2vpn
*l2vpn
)
79 while (!RB_EMPTY(l2vpn_if_head
, &l2vpn
->if_tree
)) {
80 lif
= RB_ROOT(l2vpn_if_head
, &l2vpn
->if_tree
);
82 RB_REMOVE(l2vpn_if_head
, &l2vpn
->if_tree
, lif
);
85 while (!RB_EMPTY(l2vpn_pw_head
, &l2vpn
->pw_tree
)) {
86 pw
= RB_ROOT(l2vpn_pw_head
, &l2vpn
->pw_tree
);
88 RB_REMOVE(l2vpn_pw_head
, &l2vpn
->pw_tree
, pw
);
91 while (!RB_EMPTY(l2vpn_pw_head
, &l2vpn
->pw_inactive_tree
)) {
92 pw
= RB_ROOT(l2vpn_pw_head
, &l2vpn
->pw_inactive_tree
);
94 RB_REMOVE(l2vpn_pw_head
, &l2vpn
->pw_inactive_tree
, pw
);
102 l2vpn_init(struct l2vpn
*l2vpn
)
106 RB_FOREACH(pw
, l2vpn_pw_head
, &l2vpn
->pw_tree
)
111 l2vpn_exit(struct l2vpn
*l2vpn
)
115 RB_FOREACH(pw
, l2vpn_pw_head
, &l2vpn
->pw_tree
)
120 l2vpn_if_compare(const struct l2vpn_if
*a
, const struct l2vpn_if
*b
)
122 return if_cmp_name_func(a
->ifname
, b
->ifname
);
126 l2vpn_if_new(struct l2vpn
*l2vpn
, const char *ifname
)
128 struct l2vpn_if
*lif
;
130 if ((lif
= calloc(1, sizeof(*lif
))) == NULL
)
131 fatal("l2vpn_if_new: calloc");
134 strlcpy(lif
->ifname
, ifname
, sizeof(lif
->ifname
));
140 l2vpn_if_find(struct l2vpn
*l2vpn
, const char *ifname
)
143 strlcpy(lif
.ifname
, ifname
, sizeof(lif
.ifname
));
144 return (RB_FIND(l2vpn_if_head
, &l2vpn
->if_tree
, &lif
));
148 l2vpn_if_update_info(struct l2vpn_if
*lif
, struct kif
*kif
)
150 lif
->ifindex
= kif
->ifindex
;
151 lif
->operative
= kif
->operative
;
152 memcpy(lif
->mac
, kif
->mac
, sizeof(lif
->mac
));
156 l2vpn_if_update(struct l2vpn_if
*lif
)
158 struct l2vpn
*l2vpn
= lif
->l2vpn
;
166 RB_FOREACH(pw
, l2vpn_pw_head
, &l2vpn
->pw_tree
) {
167 nbr
= nbr_find_ldpid(pw
->lsr_id
.s_addr
);
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
;
178 send_mac_withdrawal(nbr
, &fec
, lif
->mac
);
183 l2vpn_pw_compare(const struct l2vpn_pw
*a
, const struct l2vpn_pw
*b
)
185 return if_cmp_name_func(a
->ifname
, b
->ifname
);
189 l2vpn_pw_new(struct l2vpn
*l2vpn
, const char *ifname
)
193 if ((pw
= calloc(1, sizeof(*pw
))) == NULL
)
194 fatal("l2vpn_pw_new: calloc");
197 strlcpy(pw
->ifname
, ifname
, sizeof(pw
->ifname
));
203 l2vpn_pw_find(struct l2vpn
*l2vpn
, const char *ifname
)
208 strlcpy(s
.ifname
, ifname
, sizeof(s
.ifname
));
209 pw
= RB_FIND(l2vpn_pw_head
, &l2vpn
->pw_tree
, &s
);
212 return (RB_FIND(l2vpn_pw_head
, &l2vpn
->pw_inactive_tree
, &s
));
216 l2vpn_pw_find_active(struct l2vpn
*l2vpn
, const char *ifname
)
220 strlcpy(s
.ifname
, ifname
, sizeof(s
.ifname
));
221 return (RB_FIND(l2vpn_pw_head
, &l2vpn
->pw_tree
, &s
));
225 l2vpn_pw_find_inactive(struct l2vpn
*l2vpn
, const char *ifname
)
229 strlcpy(s
.ifname
, ifname
, sizeof(s
.ifname
));
230 return (RB_FIND(l2vpn_pw_head
, &l2vpn
->pw_inactive_tree
, &s
));
234 l2vpn_pw_update_info(struct l2vpn_pw
*pw
, struct kif
*kif
)
236 pw
->ifindex
= kif
->ifindex
;
240 l2vpn_pw_init(struct l2vpn_pw
*pw
)
248 lde_imsg_compose_parent(IMSG_KPW_ADD
, 0, &zpw
, sizeof(zpw
));
250 l2vpn_pw_fec(pw
, &fec
);
251 lde_kernel_insert(&fec
, AF_INET
, (union ldpd_addr
*)&pw
->lsr_id
, 0, 0,
253 lde_kernel_update(&fec
);
257 l2vpn_pw_exit(struct l2vpn_pw
*pw
)
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
);
267 lde_imsg_compose_parent(IMSG_KPW_DELETE
, 0, &zpw
, sizeof(zpw
));
271 l2vpn_pw_fec(struct l2vpn_pw
*pw
, struct fec
*fec
)
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
;
281 l2vpn_pw_reset(struct l2vpn_pw
*pw
)
283 pw
->remote_group
= 0;
285 pw
->local_status
= PW_FORWARDING
;
286 pw
->remote_status
= PW_NOT_FORWARDING
;
288 if (pw
->flags
& F_PW_CWORD_CONF
)
289 pw
->flags
|= F_PW_CWORD
;
291 pw
->flags
&= ~F_PW_CWORD
;
293 if (pw
->flags
& F_PW_STATUSTLV_CONF
)
294 pw
->flags
|= F_PW_STATUSTLV
;
296 pw
->flags
&= ~F_PW_STATUSTLV
;
298 if (pw
->flags
& F_PW_STATUSTLV_CONF
) {
301 l2vpn_pw_fec(pw
, &fec
);
302 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
304 pw
->remote_status
= fn
->pw_remote_status
;
310 l2vpn_pw_ok(struct l2vpn_pw
*pw
, struct fec_nh
*fnh
)
312 /* check for a remote label */
313 if (fnh
->remote_label
== NO_LABEL
) {
314 log_warnx("%s: pseudowire %s: no remote label", __func__
,
316 pw
->reason
= F_PW_NO_REMOTE_LABEL
;
320 /* MTUs must match */
321 if (pw
->l2vpn
->mtu
!= pw
->remote_mtu
) {
322 log_warnx("%s: pseudowire %s: MTU mismatch detected", __func__
,
324 pw
->reason
= F_PW_MTU_MISMATCH
;
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__
,
333 pw
->reason
= F_PW_REMOTE_NOT_FWD
;
337 pw
->reason
= F_PW_NO_ERR
;
342 l2vpn_pw_negotiate(struct lde_nbr
*ln
, struct fec_node
*fn
, struct map
*map
)
345 struct status_tlv st
;
347 /* NOTE: thanks martini & friends for all this mess */
349 pw
= (struct l2vpn_pw
*) fn
->data
;
352 * pseudowire not configured, return and record
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 */
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
);
371 pw
->flags
&= ~F_PW_CWORD
;
372 lde_send_labelmapping(ln
, fn
, 1);
374 } else if (map
->flags
& F_MAP_PW_CWORD
) {
375 if (pw
->flags
& F_PW_CWORD_CONF
)
376 pw
->flags
|= F_PW_CWORD
;
378 /* act as if no label mapping had been received */
381 pw
->flags
&= ~F_PW_CWORD
;
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
;
392 l2vpn_send_pw_status(struct lde_nbr
*ln
, uint32_t status
, struct fec
*fec
)
394 struct notify_msg nm
;
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
;
403 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND
, ln
->peerid
, 0, &nm
,
408 l2vpn_send_pw_status_wcard(struct lde_nbr
*ln
, uint32_t status
,
409 uint16_t pw_type
, uint32_t group_id
)
411 struct notify_msg nm
;
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
;
422 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND
, ln
->peerid
, 0, &nm
,
427 l2vpn_recv_pw_status(struct lde_nbr
*ln
, struct notify_msg
*nm
)
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
);
440 lde_map2fec(&nm
->fec
, ln
->id
, &fec
);
441 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
446 fn
->pw_remote_status
= nm
->pw_status
;
448 pw
= (struct l2vpn_pw
*) fn
->data
;
452 fnh
= fec_nh_find(fn
, AF_INET
, (union ldpd_addr
*)&ln
->id
, 0, 0, 0);
456 /* remote status didn't change */
457 if (pw
->remote_status
== nm
->pw_status
)
459 pw
->remote_status
= nm
->pw_status
;
461 if (l2vpn_pw_ok(pw
, fnh
))
462 lde_send_change_klabel(fn
, fnh
);
464 lde_send_delete_klabel(fn
, fnh
);
467 /* RFC4447 PWid group wildcard */
469 l2vpn_recv_pw_status_wcard(struct lde_nbr
*ln
, struct notify_msg
*nm
)
475 struct map
*wcard
= &nm
->fec
;
477 RB_FOREACH(f
, fec_tree
, &ft
) {
478 fn
= (struct fec_node
*)f
;
479 if (fn
->fec
.type
!= FEC_TYPE_PWID
)
482 pw
= (struct l2vpn_pw
*) fn
->data
;
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
)
493 if (wcard
->fec
.pwid
.type
!= fn
->fec
.u
.pwid
.type
)
495 if (wcard
->fec
.pwid
.group_id
!= pw
->remote_group
)
500 fnh
= fec_nh_find(fn
, AF_INET
, (union ldpd_addr
*)&ln
->id
,
505 /* remote status didn't change */
506 if (pw
->remote_status
== nm
->pw_status
)
508 pw
->remote_status
= nm
->pw_status
;
510 if (l2vpn_pw_ok(pw
, fnh
))
511 lde_send_change_klabel(fn
, fnh
);
513 lde_send_delete_klabel(fn
, fnh
);
518 l2vpn_pw_status_update(struct zapi_pw_status
*zpw
)
521 struct l2vpn_pw
*pw
= NULL
;
524 uint32_t local_status
;
526 RB_FOREACH(l2vpn
, l2vpn_head
, &ldeconf
->l2vpn_tree
) {
527 pw
= l2vpn_pw_find(l2vpn
, zpw
->ifname
);
532 log_warnx("%s: pseudowire %s not found", __func__
, zpw
->ifname
);
536 if (zpw
->status
== PW_FORWARDING
) {
537 local_status
= PW_FORWARDING
;
538 pw
->reason
= F_PW_NO_ERR
;
540 local_status
= zpw
->status
;
541 pw
->reason
= F_PW_LOCAL_NOT_FWD
;
544 /* local status didn't change */
545 if (pw
->local_status
== local_status
)
547 pw
->local_status
= local_status
;
549 /* notify remote peer about the status update */
550 ln
= lde_nbr_find_by_lsrid(pw
->lsr_id
);
553 l2vpn_pw_fec(pw
, &fec
);
554 if (pw
->flags
& F_PW_STATUSTLV
)
555 l2vpn_send_pw_status(ln
, local_status
, &fec
);
558 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
560 if (pw
->local_status
== PW_FORWARDING
)
561 lde_send_labelmapping(ln
, fn
, 1);
563 lde_send_labelwithdraw(ln
, fn
, NULL
, NULL
);
571 l2vpn_pw_ctl(pid_t pid
)
575 static struct ctl_pw pwctl
;
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
;
588 pw
->local_status
== PW_FORWARDING
&&
589 pw
->remote_status
== PW_FORWARDING
)
590 pwctl
.status
= PW_FORWARDING
;
592 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_PW
, 0,
593 pid
, &pwctl
, sizeof(pwctl
));
598 l2vpn_binding_ctl(pid_t pid
)
604 static struct ctl_pw pwctl
;
606 RB_FOREACH(f
, fec_tree
, &ft
) {
607 if (f
->type
!= FEC_TYPE_PWID
)
610 fn
= (struct fec_node
*)f
;
611 if (fn
->local_label
== NO_LABEL
&&
612 RB_EMPTY(lde_map_head
, &fn
->downstream
))
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
;
620 pw
= (struct l2vpn_pw
*) fn
->data
;
622 pwctl
.local_label
= fn
->local_label
;
624 pwctl
.local_ifmtu
= pw
->l2vpn
->mtu
;
625 pwctl
.local_cword
= (pw
->flags
& F_PW_CWORD_CONF
) ?
627 pwctl
.reason
= pw
->reason
;
629 pwctl
.local_label
= NO_LABEL
;
631 RB_FOREACH(me
, lde_map_head
, &fn
->downstream
)
632 if (f
->u
.pwid
.lsr_id
.s_addr
== me
->nexthop
->id
.s_addr
)
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
;
641 pwctl
.remote_cword
= (pw
->flags
& F_PW_CWORD
) ?
644 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING
,
645 0, pid
, &pwctl
, sizeof(pwctl
));
647 pwctl
.remote_label
= NO_LABEL
;
649 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING
,
650 0, pid
, &pwctl
, sizeof(pwctl
));
658 ldpe_l2vpn_init(struct l2vpn
*l2vpn
)
662 RB_FOREACH(pw
, l2vpn_pw_head
, &l2vpn
->pw_tree
)
663 ldpe_l2vpn_pw_init(pw
);
667 ldpe_l2vpn_exit(struct l2vpn
*l2vpn
)
671 RB_FOREACH(pw
, l2vpn_pw_head
, &l2vpn
->pw_tree
)
672 ldpe_l2vpn_pw_exit(pw
);
676 ldpe_l2vpn_pw_init(struct l2vpn_pw
*pw
)
680 tnbr
= tnbr_find(leconf
, pw
->af
, &pw
->addr
);
682 tnbr
= tnbr_new(pw
->af
, &pw
->addr
);
684 RB_INSERT(tnbr_head
, &leconf
->tnbr_tree
, tnbr
);
691 ldpe_l2vpn_pw_exit(struct l2vpn_pw
*pw
)
695 tnbr
= tnbr_find(leconf
, pw
->af
, &pw
->addr
);
698 tnbr_check(leconf
, tnbr
);