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 SET_FLAG(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 (CHECK_FLAG(pw
->flags
, F_PW_CWORD_CONF
))
278 SET_FLAG(pw
->flags
, F_PW_CWORD
);
280 UNSET_FLAG(pw
->flags
, F_PW_CWORD
);
282 if (CHECK_FLAG(pw
->flags
, F_PW_STATUSTLV_CONF
))
283 SET_FLAG(pw
->flags
, F_PW_STATUSTLV
);
285 UNSET_FLAG(pw
->flags
, F_PW_STATUSTLV
);
287 if (CHECK_FLAG(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__
, pw
->ifname
);
304 pw
->reason
= F_PW_NO_REMOTE_LABEL
;
308 /* MTUs must match */
309 if (pw
->l2vpn
->mtu
!= pw
->remote_mtu
) {
310 log_warnx("%s: pseudowire %s: MTU mismatch detected", __func__
,
312 pw
->reason
= F_PW_MTU_MISMATCH
;
316 /* check pw status if applicable */
317 if (CHECK_FLAG(pw
->flags
, F_PW_STATUSTLV
) &&
318 pw
->remote_status
!= PW_FORWARDING
) {
319 log_warnx("%s: pseudowire %s: remote end is down", __func__
, pw
->ifname
);
320 pw
->reason
= F_PW_REMOTE_NOT_FWD
;
324 pw
->reason
= F_PW_NO_ERR
;
329 l2vpn_pw_negotiate(struct lde_nbr
*ln
, struct fec_node
*fn
, struct map
*map
)
332 struct status_tlv st
;
334 /* NOTE: thanks martini & friends for all this mess */
336 pw
= (struct l2vpn_pw
*) fn
->data
;
339 * pseudowire not configured, return and record
344 /* RFC4447 - Section 6.2: control word negotiation */
345 if (fec_find(&ln
->sent_map
, &fn
->fec
)) {
346 if (CHECK_FLAG(map
->flags
, F_MAP_PW_CWORD
) &&
347 !CHECK_FLAG(pw
->flags
, F_PW_CWORD_CONF
)) {
348 /* ignore the received label mapping */
350 } else if (!CHECK_FLAG(map
->flags
, F_MAP_PW_CWORD
) &&
351 CHECK_FLAG(pw
->flags
, F_PW_CWORD_CONF
)) {
352 /* append a "Wrong C-bit" status code */
353 st
.status_code
= S_WRONG_CBIT
;
354 st
.msg_id
= map
->msg_id
;
355 st
.msg_type
= htons(MSG_TYPE_LABELMAPPING
);
356 lde_send_labelwithdraw(ln
, fn
, NULL
, &st
);
358 UNSET_FLAG(pw
->flags
, F_PW_CWORD
);
359 lde_send_labelmapping(ln
, fn
, 1);
361 } else if (CHECK_FLAG(map
->flags
, F_MAP_PW_CWORD
)) {
362 if (CHECK_FLAG(pw
->flags
, F_PW_CWORD_CONF
))
363 SET_FLAG(pw
->flags
, F_PW_CWORD
);
365 /* act as if no label mapping had been received */
368 UNSET_FLAG(pw
->flags
, F_PW_CWORD
);
370 /* RFC4447 - Section 5.4.3: pseudowire status negotiation */
371 if (fec_find(&ln
->recv_map
, &fn
->fec
) == NULL
&&
372 !CHECK_FLAG(map
->flags
, F_MAP_PW_STATUS
))
373 UNSET_FLAG(pw
->flags
, F_PW_STATUSTLV
);
379 l2vpn_send_pw_status(struct lde_nbr
*ln
, uint32_t status
, struct fec
*fec
)
381 struct notify_msg nm
;
383 memset(&nm
, 0, sizeof(nm
));
384 nm
.status_code
= S_PW_STATUS
;
385 nm
.pw_status
= status
;
386 SET_FLAG(nm
.flags
, F_NOTIF_PW_STATUS
);
387 lde_fec2map(fec
, &nm
.fec
);
388 SET_FLAG(nm
.flags
, F_NOTIF_FEC
);
390 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND
, ln
->peerid
, 0, &nm
, sizeof(nm
));
394 l2vpn_send_pw_status_wcard(struct lde_nbr
*ln
, uint32_t status
,
395 uint16_t pw_type
, uint32_t group_id
)
397 struct notify_msg nm
;
399 memset(&nm
, 0, sizeof(nm
));
400 nm
.status_code
= S_PW_STATUS
;
401 nm
.pw_status
= status
;
402 SET_FLAG(nm
.flags
, F_NOTIF_PW_STATUS
);
403 nm
.fec
.type
= MAP_TYPE_PWID
;
404 nm
.fec
.fec
.pwid
.type
= pw_type
;
405 nm
.fec
.fec
.pwid
.group_id
= group_id
;
406 SET_FLAG(nm
.flags
, F_NOTIF_FEC
);
408 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND
, ln
->peerid
, 0, &nm
, sizeof(nm
));
412 l2vpn_recv_pw_status(struct lde_nbr
*ln
, struct notify_msg
*nm
)
419 if (nm
->fec
.type
== MAP_TYPE_TYPED_WCARD
||
420 !CHECK_FLAG(nm
->fec
.flags
, F_MAP_PW_ID
)) {
421 l2vpn_recv_pw_status_wcard(ln
, nm
);
425 lde_map2fec(&nm
->fec
, ln
->id
, &fec
);
426 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
431 fn
->pw_remote_status
= nm
->pw_status
;
433 pw
= (struct l2vpn_pw
*) fn
->data
;
437 fnh
= fec_nh_find(fn
, AF_INET
, (union ldpd_addr
*)&ln
->id
, 0, 0, 0);
441 /* remote status didn't change */
442 if (pw
->remote_status
== nm
->pw_status
)
444 pw
->remote_status
= nm
->pw_status
;
446 if (l2vpn_pw_ok(pw
, fnh
))
447 lde_send_change_klabel(fn
, fnh
);
449 lde_send_delete_klabel(fn
, fnh
);
452 /* RFC4447 PWid group wildcard */
454 l2vpn_recv_pw_status_wcard(struct lde_nbr
*ln
, struct notify_msg
*nm
)
460 struct map
*wcard
= &nm
->fec
;
462 RB_FOREACH(f
, fec_tree
, &ft
) {
463 fn
= (struct fec_node
*)f
;
464 if (fn
->fec
.type
!= FEC_TYPE_PWID
)
467 pw
= (struct l2vpn_pw
*) fn
->data
;
471 switch (wcard
->type
) {
472 case MAP_TYPE_TYPED_WCARD
:
473 if (wcard
->fec
.twcard
.u
.pw_type
!= PW_TYPE_WILDCARD
&&
474 wcard
->fec
.twcard
.u
.pw_type
!= fn
->fec
.u
.pwid
.type
)
478 if (wcard
->fec
.pwid
.type
!= fn
->fec
.u
.pwid
.type
)
480 if (wcard
->fec
.pwid
.group_id
!= pw
->remote_group
)
485 fnh
= fec_nh_find(fn
, AF_INET
, (union ldpd_addr
*)&ln
->id
,
490 /* remote status didn't change */
491 if (pw
->remote_status
== nm
->pw_status
)
493 pw
->remote_status
= nm
->pw_status
;
495 if (l2vpn_pw_ok(pw
, fnh
))
496 lde_send_change_klabel(fn
, fnh
);
498 lde_send_delete_klabel(fn
, fnh
);
503 l2vpn_pw_status_update(struct zapi_pw_status
*zpw
)
506 struct l2vpn_pw
*pw
= NULL
;
509 uint32_t local_status
;
511 RB_FOREACH(l2vpn
, l2vpn_head
, &ldeconf
->l2vpn_tree
) {
512 pw
= l2vpn_pw_find(l2vpn
, zpw
->ifname
);
517 log_warnx("%s: pseudowire %s not found", __func__
, zpw
->ifname
);
521 if (zpw
->status
== PW_FORWARDING
) {
522 local_status
= PW_FORWARDING
;
523 pw
->reason
= F_PW_NO_ERR
;
525 local_status
= zpw
->status
;
526 pw
->reason
= F_PW_LOCAL_NOT_FWD
;
529 /* local status didn't change */
530 if (pw
->local_status
== local_status
)
532 pw
->local_status
= local_status
;
534 /* notify remote peer about the status update */
535 ln
= lde_nbr_find_by_lsrid(pw
->lsr_id
);
538 l2vpn_pw_fec(pw
, &fec
);
539 if (CHECK_FLAG(pw
->flags
, F_PW_STATUSTLV
))
540 l2vpn_send_pw_status(ln
, local_status
, &fec
);
543 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
545 if (pw
->local_status
== PW_FORWARDING
)
546 lde_send_labelmapping(ln
, fn
, 1);
548 lde_send_labelwithdraw(ln
, fn
, NULL
, NULL
);
556 l2vpn_pw_ctl(pid_t pid
)
560 static struct ctl_pw pwctl
;
562 RB_FOREACH(l2vpn
, l2vpn_head
, &ldeconf
->l2vpn_tree
)
563 RB_FOREACH(pw
, l2vpn_pw_head
, &l2vpn
->pw_tree
) {
564 memset(&pwctl
, 0, sizeof(pwctl
));
565 strlcpy(pwctl
.l2vpn_name
, pw
->l2vpn
->name
,
566 sizeof(pwctl
.l2vpn_name
));
567 strlcpy(pwctl
.ifname
, pw
->ifname
,
568 sizeof(pwctl
.ifname
));
569 pwctl
.pwid
= pw
->pwid
;
570 pwctl
.lsr_id
= pw
->lsr_id
;
571 pwctl
.status
= PW_NOT_FORWARDING
;
573 pw
->local_status
== PW_FORWARDING
&&
574 pw
->remote_status
== PW_FORWARDING
)
575 pwctl
.status
= PW_FORWARDING
;
577 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_PW
, 0,
578 pid
, &pwctl
, sizeof(pwctl
));
583 l2vpn_binding_ctl(pid_t pid
)
589 static struct ctl_pw pwctl
;
591 RB_FOREACH(f
, fec_tree
, &ft
) {
592 if (f
->type
!= FEC_TYPE_PWID
)
595 fn
= (struct fec_node
*)f
;
596 if (fn
->local_label
== NO_LABEL
&&
597 RB_EMPTY(lde_map_head
, &fn
->downstream
))
600 memset(&pwctl
, 0, sizeof(pwctl
));
601 pwctl
.type
= f
->u
.pwid
.type
;
602 pwctl
.pwid
= f
->u
.pwid
.pwid
;
603 pwctl
.lsr_id
= f
->u
.pwid
.lsr_id
;
605 pw
= (struct l2vpn_pw
*) fn
->data
;
607 pwctl
.local_label
= fn
->local_label
;
609 pwctl
.local_ifmtu
= pw
->l2vpn
->mtu
;
610 pwctl
.local_cword
= CHECK_FLAG(pw
->flags
, F_PW_CWORD_CONF
) ? 1 : 0;
611 pwctl
.reason
= pw
->reason
;
613 pwctl
.local_label
= NO_LABEL
;
615 RB_FOREACH(me
, lde_map_head
, &fn
->downstream
)
616 if (f
->u
.pwid
.lsr_id
.s_addr
== me
->nexthop
->id
.s_addr
)
620 pwctl
.remote_label
= me
->map
.label
;
621 pwctl
.remote_gid
= me
->map
.fec
.pwid
.group_id
;
622 if (CHECK_FLAG(me
->map
.flags
, F_MAP_PW_IFMTU
))
623 pwctl
.remote_ifmtu
= me
->map
.fec
.pwid
.ifmtu
;
625 pwctl
.remote_cword
= CHECK_FLAG(pw
->flags
, F_PW_CWORD
) ? 1 : 0;
627 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING
,
628 0, pid
, &pwctl
, sizeof(pwctl
));
630 pwctl
.remote_label
= NO_LABEL
;
632 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING
,
633 0, pid
, &pwctl
, sizeof(pwctl
));
641 ldpe_l2vpn_init(struct l2vpn
*l2vpn
)
645 RB_FOREACH(pw
, l2vpn_pw_head
, &l2vpn
->pw_tree
)
646 ldpe_l2vpn_pw_init(pw
);
650 ldpe_l2vpn_exit(struct l2vpn
*l2vpn
)
654 RB_FOREACH(pw
, l2vpn_pw_head
, &l2vpn
->pw_tree
)
655 ldpe_l2vpn_pw_exit(pw
);
659 ldpe_l2vpn_pw_init(struct l2vpn_pw
*pw
)
663 tnbr
= tnbr_find(leconf
, pw
->af
, &pw
->addr
);
665 tnbr
= tnbr_new(pw
->af
, &pw
->addr
);
667 RB_INSERT(tnbr_head
, &leconf
->tnbr_tree
, tnbr
);
674 ldpe_l2vpn_pw_exit(struct l2vpn_pw
*pw
)
678 tnbr
= tnbr_find(leconf
, pw
->af
, &pw
->addr
);
681 tnbr_check(leconf
, tnbr
);