1 // SPDX-License-Identifier: ISC
5 * Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
6 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
7 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
8 * Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org>
18 static void l2vpn_pw_fec(struct l2vpn_pw
*, struct fec
*);
19 static __inline
int l2vpn_compare(const struct l2vpn
*, const struct l2vpn
*);
20 static __inline
int l2vpn_if_compare(const struct l2vpn_if
*, const struct l2vpn_if
*);
21 static __inline
int l2vpn_pw_compare(const struct l2vpn_pw
*, const struct l2vpn_pw
*);
23 RB_GENERATE(l2vpn_head
, l2vpn
, entry
, l2vpn_compare
)
24 RB_GENERATE(l2vpn_if_head
, l2vpn_if
, entry
, l2vpn_if_compare
)
25 RB_GENERATE(l2vpn_pw_head
, l2vpn_pw
, entry
, l2vpn_pw_compare
)
28 l2vpn_compare(const struct l2vpn
*a
, const struct l2vpn
*b
)
30 return (strcmp(a
->name
, b
->name
));
34 l2vpn_new(const char *name
)
38 if ((l2vpn
= calloc(1, sizeof(*l2vpn
))) == NULL
)
39 fatal("l2vpn_new: calloc");
41 strlcpy(l2vpn
->name
, name
, sizeof(l2vpn
->name
));
43 /* set default values */
44 l2vpn
->mtu
= DEFAULT_L2VPN_MTU
;
45 l2vpn
->pw_type
= DEFAULT_PW_TYPE
;
47 RB_INIT(l2vpn_if_head
, &l2vpn
->if_tree
);
48 RB_INIT(l2vpn_pw_head
, &l2vpn
->pw_tree
);
49 RB_INIT(l2vpn_pw_head
, &l2vpn
->pw_inactive_tree
);
55 l2vpn_find(struct ldpd_conf
*xconf
, const char *name
)
58 strlcpy(l2vpn
.name
, name
, sizeof(l2vpn
.name
));
59 return (RB_FIND(l2vpn_head
, &xconf
->l2vpn_tree
, &l2vpn
));
63 l2vpn_del(struct l2vpn
*l2vpn
)
68 while (!RB_EMPTY(l2vpn_if_head
, &l2vpn
->if_tree
)) {
69 lif
= RB_ROOT(l2vpn_if_head
, &l2vpn
->if_tree
);
71 RB_REMOVE(l2vpn_if_head
, &l2vpn
->if_tree
, lif
);
74 while (!RB_EMPTY(l2vpn_pw_head
, &l2vpn
->pw_tree
)) {
75 pw
= RB_ROOT(l2vpn_pw_head
, &l2vpn
->pw_tree
);
77 RB_REMOVE(l2vpn_pw_head
, &l2vpn
->pw_tree
, pw
);
80 while (!RB_EMPTY(l2vpn_pw_head
, &l2vpn
->pw_inactive_tree
)) {
81 pw
= RB_ROOT(l2vpn_pw_head
, &l2vpn
->pw_inactive_tree
);
83 RB_REMOVE(l2vpn_pw_head
, &l2vpn
->pw_inactive_tree
, pw
);
91 l2vpn_init(struct l2vpn
*l2vpn
)
95 RB_FOREACH(pw
, l2vpn_pw_head
, &l2vpn
->pw_tree
)
100 l2vpn_exit(struct l2vpn
*l2vpn
)
104 RB_FOREACH(pw
, l2vpn_pw_head
, &l2vpn
->pw_tree
)
109 l2vpn_if_compare(const struct l2vpn_if
*a
, const struct l2vpn_if
*b
)
111 return if_cmp_name_func(a
->ifname
, b
->ifname
);
115 l2vpn_if_new(struct l2vpn
*l2vpn
, const char *ifname
)
117 struct l2vpn_if
*lif
;
119 if ((lif
= calloc(1, sizeof(*lif
))) == NULL
)
120 fatal("l2vpn_if_new: calloc");
123 strlcpy(lif
->ifname
, ifname
, sizeof(lif
->ifname
));
129 l2vpn_if_find(struct l2vpn
*l2vpn
, const char *ifname
)
132 strlcpy(lif
.ifname
, ifname
, sizeof(lif
.ifname
));
133 return (RB_FIND(l2vpn_if_head
, &l2vpn
->if_tree
, &lif
));
137 l2vpn_if_update_info(struct l2vpn_if
*lif
, struct kif
*kif
)
139 lif
->ifindex
= kif
->ifindex
;
140 lif
->operative
= kif
->operative
;
141 memcpy(lif
->mac
, kif
->mac
, sizeof(lif
->mac
));
145 l2vpn_if_update(struct l2vpn_if
*lif
)
147 struct l2vpn
*l2vpn
= lif
->l2vpn
;
155 RB_FOREACH(pw
, l2vpn_pw_head
, &l2vpn
->pw_tree
) {
156 nbr
= nbr_find_ldpid(pw
->lsr_id
.s_addr
);
160 memset(&fec
, 0, sizeof(fec
));
161 fec
.type
= MAP_TYPE_PWID
;
162 fec
.fec
.pwid
.type
= l2vpn
->pw_type
;
163 fec
.fec
.pwid
.group_id
= 0;
164 fec
.flags
|= F_MAP_PW_ID
;
165 fec
.fec
.pwid
.pwid
= pw
->pwid
;
167 send_mac_withdrawal(nbr
, &fec
, lif
->mac
);
172 l2vpn_pw_compare(const struct l2vpn_pw
*a
, const struct l2vpn_pw
*b
)
174 return if_cmp_name_func(a
->ifname
, b
->ifname
);
178 l2vpn_pw_new(struct l2vpn
*l2vpn
, const char *ifname
)
182 if ((pw
= calloc(1, sizeof(*pw
))) == NULL
)
183 fatal("l2vpn_pw_new: calloc");
186 strlcpy(pw
->ifname
, ifname
, sizeof(pw
->ifname
));
192 l2vpn_pw_find(struct l2vpn
*l2vpn
, const char *ifname
)
197 strlcpy(s
.ifname
, ifname
, sizeof(s
.ifname
));
198 pw
= RB_FIND(l2vpn_pw_head
, &l2vpn
->pw_tree
, &s
);
201 return (RB_FIND(l2vpn_pw_head
, &l2vpn
->pw_inactive_tree
, &s
));
205 l2vpn_pw_find_active(struct l2vpn
*l2vpn
, const char *ifname
)
209 strlcpy(s
.ifname
, ifname
, sizeof(s
.ifname
));
210 return (RB_FIND(l2vpn_pw_head
, &l2vpn
->pw_tree
, &s
));
214 l2vpn_pw_find_inactive(struct l2vpn
*l2vpn
, const char *ifname
)
218 strlcpy(s
.ifname
, ifname
, sizeof(s
.ifname
));
219 return (RB_FIND(l2vpn_pw_head
, &l2vpn
->pw_inactive_tree
, &s
));
223 l2vpn_pw_update_info(struct l2vpn_pw
*pw
, struct kif
*kif
)
225 pw
->ifindex
= kif
->ifindex
;
229 l2vpn_pw_init(struct l2vpn_pw
*pw
)
237 lde_imsg_compose_parent(IMSG_KPW_ADD
, 0, &zpw
, sizeof(zpw
));
239 l2vpn_pw_fec(pw
, &fec
);
240 lde_kernel_insert(&fec
, AF_INET
, (union ldpd_addr
*)&pw
->lsr_id
, 0, 0,
242 lde_kernel_update(&fec
);
246 l2vpn_pw_exit(struct l2vpn_pw
*pw
)
251 l2vpn_pw_fec(pw
, &fec
);
252 lde_kernel_remove(&fec
, AF_INET
, (union ldpd_addr
*)&pw
->lsr_id
, 0, 0, 0);
253 lde_kernel_update(&fec
);
256 lde_imsg_compose_parent(IMSG_KPW_DELETE
, 0, &zpw
, sizeof(zpw
));
260 l2vpn_pw_fec(struct l2vpn_pw
*pw
, struct fec
*fec
)
262 memset(fec
, 0, sizeof(*fec
));
263 fec
->type
= FEC_TYPE_PWID
;
264 fec
->u
.pwid
.type
= pw
->l2vpn
->pw_type
;
265 fec
->u
.pwid
.pwid
= pw
->pwid
;
266 fec
->u
.pwid
.lsr_id
= pw
->lsr_id
;
270 l2vpn_pw_reset(struct l2vpn_pw
*pw
)
272 pw
->remote_group
= 0;
274 pw
->local_status
= PW_FORWARDING
;
275 pw
->remote_status
= PW_NOT_FORWARDING
;
277 if (pw
->flags
& F_PW_CWORD_CONF
)
278 pw
->flags
|= F_PW_CWORD
;
280 pw
->flags
&= ~F_PW_CWORD
;
282 if (pw
->flags
& F_PW_STATUSTLV_CONF
)
283 pw
->flags
|= F_PW_STATUSTLV
;
285 pw
->flags
&= ~F_PW_STATUSTLV
;
287 if (pw
->flags
& F_PW_STATUSTLV_CONF
) {
290 l2vpn_pw_fec(pw
, &fec
);
291 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
293 pw
->remote_status
= fn
->pw_remote_status
;
299 l2vpn_pw_ok(struct l2vpn_pw
*pw
, struct fec_nh
*fnh
)
301 /* check for a remote label */
302 if (fnh
->remote_label
== NO_LABEL
) {
303 log_warnx("%s: pseudowire %s: no remote label", __func__
,
305 pw
->reason
= F_PW_NO_REMOTE_LABEL
;
309 /* MTUs must match */
310 if (pw
->l2vpn
->mtu
!= pw
->remote_mtu
) {
311 log_warnx("%s: pseudowire %s: MTU mismatch detected", __func__
,
313 pw
->reason
= F_PW_MTU_MISMATCH
;
317 /* check pw status if applicable */
318 if ((pw
->flags
& F_PW_STATUSTLV
) &&
319 pw
->remote_status
!= PW_FORWARDING
) {
320 log_warnx("%s: pseudowire %s: remote end is down", __func__
,
322 pw
->reason
= F_PW_REMOTE_NOT_FWD
;
326 pw
->reason
= F_PW_NO_ERR
;
331 l2vpn_pw_negotiate(struct lde_nbr
*ln
, struct fec_node
*fn
, struct map
*map
)
334 struct status_tlv st
;
336 /* NOTE: thanks martini & friends for all this mess */
338 pw
= (struct l2vpn_pw
*) fn
->data
;
341 * pseudowire not configured, return and record
346 /* RFC4447 - Section 6.2: control word negotiation */
347 if (fec_find(&ln
->sent_map
, &fn
->fec
)) {
348 if ((map
->flags
& F_MAP_PW_CWORD
) &&
349 !(pw
->flags
& F_PW_CWORD_CONF
)) {
350 /* ignore the received label mapping */
352 } else if (!(map
->flags
& F_MAP_PW_CWORD
) &&
353 (pw
->flags
& F_PW_CWORD_CONF
)) {
354 /* append a "Wrong C-bit" status code */
355 st
.status_code
= S_WRONG_CBIT
;
356 st
.msg_id
= map
->msg_id
;
357 st
.msg_type
= htons(MSG_TYPE_LABELMAPPING
);
358 lde_send_labelwithdraw(ln
, fn
, NULL
, &st
);
360 pw
->flags
&= ~F_PW_CWORD
;
361 lde_send_labelmapping(ln
, fn
, 1);
363 } else if (map
->flags
& F_MAP_PW_CWORD
) {
364 if (pw
->flags
& F_PW_CWORD_CONF
)
365 pw
->flags
|= F_PW_CWORD
;
367 /* act as if no label mapping had been received */
370 pw
->flags
&= ~F_PW_CWORD
;
372 /* RFC4447 - Section 5.4.3: pseudowire status negotiation */
373 if (fec_find(&ln
->recv_map
, &fn
->fec
) == NULL
&&
374 !(map
->flags
& F_MAP_PW_STATUS
))
375 pw
->flags
&= ~F_PW_STATUSTLV
;
381 l2vpn_send_pw_status(struct lde_nbr
*ln
, uint32_t status
, struct fec
*fec
)
383 struct notify_msg nm
;
385 memset(&nm
, 0, sizeof(nm
));
386 nm
.status_code
= S_PW_STATUS
;
387 nm
.pw_status
= status
;
388 nm
.flags
|= F_NOTIF_PW_STATUS
;
389 lde_fec2map(fec
, &nm
.fec
);
390 nm
.flags
|= F_NOTIF_FEC
;
392 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND
, ln
->peerid
, 0, &nm
,
397 l2vpn_send_pw_status_wcard(struct lde_nbr
*ln
, uint32_t status
,
398 uint16_t pw_type
, uint32_t group_id
)
400 struct notify_msg nm
;
402 memset(&nm
, 0, sizeof(nm
));
403 nm
.status_code
= S_PW_STATUS
;
404 nm
.pw_status
= status
;
405 nm
.flags
|= F_NOTIF_PW_STATUS
;
406 nm
.fec
.type
= MAP_TYPE_PWID
;
407 nm
.fec
.fec
.pwid
.type
= pw_type
;
408 nm
.fec
.fec
.pwid
.group_id
= group_id
;
409 nm
.flags
|= F_NOTIF_FEC
;
411 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND
, ln
->peerid
, 0, &nm
,
416 l2vpn_recv_pw_status(struct lde_nbr
*ln
, struct notify_msg
*nm
)
423 if (nm
->fec
.type
== MAP_TYPE_TYPED_WCARD
||
424 !(nm
->fec
.flags
& F_MAP_PW_ID
)) {
425 l2vpn_recv_pw_status_wcard(ln
, nm
);
429 lde_map2fec(&nm
->fec
, ln
->id
, &fec
);
430 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
435 fn
->pw_remote_status
= nm
->pw_status
;
437 pw
= (struct l2vpn_pw
*) fn
->data
;
441 fnh
= fec_nh_find(fn
, AF_INET
, (union ldpd_addr
*)&ln
->id
, 0, 0, 0);
445 /* remote status didn't change */
446 if (pw
->remote_status
== nm
->pw_status
)
448 pw
->remote_status
= nm
->pw_status
;
450 if (l2vpn_pw_ok(pw
, fnh
))
451 lde_send_change_klabel(fn
, fnh
);
453 lde_send_delete_klabel(fn
, fnh
);
456 /* RFC4447 PWid group wildcard */
458 l2vpn_recv_pw_status_wcard(struct lde_nbr
*ln
, struct notify_msg
*nm
)
464 struct map
*wcard
= &nm
->fec
;
466 RB_FOREACH(f
, fec_tree
, &ft
) {
467 fn
= (struct fec_node
*)f
;
468 if (fn
->fec
.type
!= FEC_TYPE_PWID
)
471 pw
= (struct l2vpn_pw
*) fn
->data
;
475 switch (wcard
->type
) {
476 case MAP_TYPE_TYPED_WCARD
:
477 if (wcard
->fec
.twcard
.u
.pw_type
!= PW_TYPE_WILDCARD
&&
478 wcard
->fec
.twcard
.u
.pw_type
!= fn
->fec
.u
.pwid
.type
)
482 if (wcard
->fec
.pwid
.type
!= fn
->fec
.u
.pwid
.type
)
484 if (wcard
->fec
.pwid
.group_id
!= pw
->remote_group
)
489 fnh
= fec_nh_find(fn
, AF_INET
, (union ldpd_addr
*)&ln
->id
,
494 /* remote status didn't change */
495 if (pw
->remote_status
== nm
->pw_status
)
497 pw
->remote_status
= nm
->pw_status
;
499 if (l2vpn_pw_ok(pw
, fnh
))
500 lde_send_change_klabel(fn
, fnh
);
502 lde_send_delete_klabel(fn
, fnh
);
507 l2vpn_pw_status_update(struct zapi_pw_status
*zpw
)
510 struct l2vpn_pw
*pw
= NULL
;
513 uint32_t local_status
;
515 RB_FOREACH(l2vpn
, l2vpn_head
, &ldeconf
->l2vpn_tree
) {
516 pw
= l2vpn_pw_find(l2vpn
, zpw
->ifname
);
521 log_warnx("%s: pseudowire %s not found", __func__
, zpw
->ifname
);
525 if (zpw
->status
== PW_FORWARDING
) {
526 local_status
= PW_FORWARDING
;
527 pw
->reason
= F_PW_NO_ERR
;
529 local_status
= zpw
->status
;
530 pw
->reason
= F_PW_LOCAL_NOT_FWD
;
533 /* local status didn't change */
534 if (pw
->local_status
== local_status
)
536 pw
->local_status
= local_status
;
538 /* notify remote peer about the status update */
539 ln
= lde_nbr_find_by_lsrid(pw
->lsr_id
);
542 l2vpn_pw_fec(pw
, &fec
);
543 if (pw
->flags
& F_PW_STATUSTLV
)
544 l2vpn_send_pw_status(ln
, local_status
, &fec
);
547 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
549 if (pw
->local_status
== PW_FORWARDING
)
550 lde_send_labelmapping(ln
, fn
, 1);
552 lde_send_labelwithdraw(ln
, fn
, NULL
, NULL
);
560 l2vpn_pw_ctl(pid_t pid
)
564 static struct ctl_pw pwctl
;
566 RB_FOREACH(l2vpn
, l2vpn_head
, &ldeconf
->l2vpn_tree
)
567 RB_FOREACH(pw
, l2vpn_pw_head
, &l2vpn
->pw_tree
) {
568 memset(&pwctl
, 0, sizeof(pwctl
));
569 strlcpy(pwctl
.l2vpn_name
, pw
->l2vpn
->name
,
570 sizeof(pwctl
.l2vpn_name
));
571 strlcpy(pwctl
.ifname
, pw
->ifname
,
572 sizeof(pwctl
.ifname
));
573 pwctl
.pwid
= pw
->pwid
;
574 pwctl
.lsr_id
= pw
->lsr_id
;
575 pwctl
.status
= PW_NOT_FORWARDING
;
577 pw
->local_status
== PW_FORWARDING
&&
578 pw
->remote_status
== PW_FORWARDING
)
579 pwctl
.status
= PW_FORWARDING
;
581 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_PW
, 0,
582 pid
, &pwctl
, sizeof(pwctl
));
587 l2vpn_binding_ctl(pid_t pid
)
593 static struct ctl_pw pwctl
;
595 RB_FOREACH(f
, fec_tree
, &ft
) {
596 if (f
->type
!= FEC_TYPE_PWID
)
599 fn
= (struct fec_node
*)f
;
600 if (fn
->local_label
== NO_LABEL
&&
601 RB_EMPTY(lde_map_head
, &fn
->downstream
))
604 memset(&pwctl
, 0, sizeof(pwctl
));
605 pwctl
.type
= f
->u
.pwid
.type
;
606 pwctl
.pwid
= f
->u
.pwid
.pwid
;
607 pwctl
.lsr_id
= f
->u
.pwid
.lsr_id
;
609 pw
= (struct l2vpn_pw
*) fn
->data
;
611 pwctl
.local_label
= fn
->local_label
;
613 pwctl
.local_ifmtu
= pw
->l2vpn
->mtu
;
614 pwctl
.local_cword
= (pw
->flags
& F_PW_CWORD_CONF
) ?
616 pwctl
.reason
= pw
->reason
;
618 pwctl
.local_label
= NO_LABEL
;
620 RB_FOREACH(me
, lde_map_head
, &fn
->downstream
)
621 if (f
->u
.pwid
.lsr_id
.s_addr
== me
->nexthop
->id
.s_addr
)
625 pwctl
.remote_label
= me
->map
.label
;
626 pwctl
.remote_gid
= me
->map
.fec
.pwid
.group_id
;
627 if (me
->map
.flags
& F_MAP_PW_IFMTU
)
628 pwctl
.remote_ifmtu
= me
->map
.fec
.pwid
.ifmtu
;
630 pwctl
.remote_cword
= (pw
->flags
& F_PW_CWORD
) ?
633 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING
,
634 0, pid
, &pwctl
, sizeof(pwctl
));
636 pwctl
.remote_label
= NO_LABEL
;
638 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING
,
639 0, pid
, &pwctl
, sizeof(pwctl
));
647 ldpe_l2vpn_init(struct l2vpn
*l2vpn
)
651 RB_FOREACH(pw
, l2vpn_pw_head
, &l2vpn
->pw_tree
)
652 ldpe_l2vpn_pw_init(pw
);
656 ldpe_l2vpn_exit(struct l2vpn
*l2vpn
)
660 RB_FOREACH(pw
, l2vpn_pw_head
, &l2vpn
->pw_tree
)
661 ldpe_l2vpn_pw_exit(pw
);
665 ldpe_l2vpn_pw_init(struct l2vpn_pw
*pw
)
669 tnbr
= tnbr_find(leconf
, pw
->af
, &pw
->addr
);
671 tnbr
= tnbr_new(pw
->af
, &pw
->addr
);
673 RB_INSERT(tnbr_head
, &leconf
->tnbr_tree
, tnbr
);
680 ldpe_l2vpn_pw_exit(struct l2vpn_pw
*pw
)
684 tnbr
= tnbr_find(leconf
, pw
->af
, &pw
->addr
);
687 tnbr_check(leconf
, tnbr
);