diff options
author | 2016-05-23 16:54:22 +0000 | |
---|---|---|
committer | 2016-05-23 16:54:22 +0000 | |
commit | 72bfe95e7900f9feb1e1e783c3d9228f96a0fd80 (patch) | |
tree | 29ff0f3f6cf067535c7a238d37e78e98fc36fddc | |
parent | Fix bug in the processing of label withdraws and releases. (diff) | |
download | wireguard-openbsd-72bfe95e7900f9feb1e1e783c3d9228f96a0fd80.tar.xz wireguard-openbsd-72bfe95e7900f9feb1e1e783c3d9228f96a0fd80.zip |
Rework L2VPN code.
-rw-r--r-- | usr.sbin/ldpd/l2vpn.c | 32 | ||||
-rw-r--r-- | usr.sbin/ldpd/lde.c | 72 | ||||
-rw-r--r-- | usr.sbin/ldpd/lde_lib.c | 104 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldpd.c | 6 | ||||
-rw-r--r-- | usr.sbin/ldpd/log.c | 4 | ||||
-rw-r--r-- | usr.sbin/ldpd/notification.c | 3 | ||||
-rw-r--r-- | usr.sbin/ldpd/parse.y | 8 | ||||
-rw-r--r-- | usr.sbin/ldpd/printconf.c | 4 |
8 files changed, 150 insertions, 83 deletions
diff --git a/usr.sbin/ldpd/l2vpn.c b/usr.sbin/ldpd/l2vpn.c index 555e7f61e56..b6186eb52f1 100644 --- a/usr.sbin/ldpd/l2vpn.c +++ b/usr.sbin/ldpd/l2vpn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: l2vpn.c,v 1.7 2016/05/23 16:37:42 renato Exp $ */ +/* $OpenBSD: l2vpn.c,v 1.8 2016/05/23 16:54:22 renato Exp $ */ /* * Copyright (c) 2015 Renato Westphal <renato@openbsd.org> @@ -161,7 +161,7 @@ l2vpn_pw_init(struct l2vpn_pw *pw) struct fec fec; l2vpn_pw_fec(pw, &fec); - lde_kernel_insert(&fec, pw->addr, 0, (void *)pw); + lde_kernel_insert(&fec, pw->lsr_id, 0, (void *)pw); } void @@ -170,7 +170,7 @@ l2vpn_pw_del(struct l2vpn_pw *pw) struct fec fec; l2vpn_pw_fec(pw, &fec); - lde_kernel_remove(&fec, pw->addr); + lde_kernel_remove(&fec, pw->lsr_id); free(pw); } @@ -181,7 +181,7 @@ l2vpn_pw_fec(struct l2vpn_pw *pw, struct fec *fec) fec->type = FEC_TYPE_PWID; fec->u.pwid.type = pw->l2vpn->pw_type; fec->u.pwid.pwid = pw->pwid; - fec->u.pwid.nexthop.s_addr = pw->addr.s_addr; + fec->u.pwid.lsr_id = pw->lsr_id; } void @@ -217,7 +217,7 @@ l2vpn_pw_ok(struct l2vpn_pw *pw, struct fec_nh *fnh) /* check for a working lsp to the nexthop */ bzero(&fec, sizeof(fec)); fec.type = FEC_TYPE_IPV4; - fec.u.ipv4.prefix.s_addr = pw->addr.s_addr; + fec.u.ipv4.prefix = pw->lsr_id; fec.u.ipv4.prefixlen = 32; fn = (struct fec_node *)fec_find(&ft, &fec); if (fn == NULL || fn->local_label == NO_LABEL) @@ -236,19 +236,17 @@ l2vpn_pw_ok(struct l2vpn_pw *pw, struct fec_nh *fnh) int l2vpn_pw_negotiate(struct lde_nbr *ln, struct fec_node *fn, struct map *map) { - struct fec_nh *fnh; struct l2vpn_pw *pw; /* NOTE: thanks martini & friends for all this mess */ - fnh = fec_nh_find(fn, ln->id); - if (fnh == NULL) + pw = (struct l2vpn_pw *) fn->data; + if (pw == NULL) /* * pseudowire not configured, return and record * the mapping later */ return (0); - pw = (struct l2vpn_pw *) fnh->data; l2vpn_pw_reset(pw); @@ -319,10 +317,13 @@ l2vpn_recv_pw_status(struct lde_nbr *ln, struct notify_msg *nm) /* unknown fec */ return; + pw = (struct l2vpn_pw *) fn->data; + if (pw == NULL) + return; + fnh = fec_nh_find(fn, ln->id); if (fnh == NULL) return; - pw = (struct l2vpn_pw *) fnh->data; /* remote status didn't change */ if (pw->remote_status == nm->pw_status) @@ -347,12 +348,12 @@ l2vpn_sync_pws(struct in_addr addr) LIST_FOREACH(l2vpn, &ldeconf->l2vpn_list, entry) { LIST_FOREACH(pw, &l2vpn->pw_list, entry) { - if (pw->addr.s_addr == addr.s_addr) { + if (pw->lsr_id.s_addr == addr.s_addr) { l2vpn_pw_fec(pw, &fec); fn = (struct fec_node *)fec_find(&ft, &fec); if (fn == NULL) continue; - fnh = fec_nh_find(fn, pw->addr); + fnh = fec_nh_find(fn, pw->lsr_id); if (fnh == NULL) continue; @@ -378,7 +379,7 @@ l2vpn_pw_ctl(pid_t pid) strlcpy(pwctl.ifname, pw->ifname, sizeof(pwctl.ifname)); pwctl.pwid = pw->pwid; - pwctl.nexthop.s_addr = pw->addr.s_addr; + pwctl.lsr_id = pw->lsr_id; pwctl.status = pw->flags & F_PW_STATUS_UP; lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_PW, 0, @@ -392,7 +393,6 @@ l2vpn_binding_ctl(pid_t pid) struct fec *f; struct fec_node *fn; struct lde_map *me; - struct fec_nh *fnh; struct l2vpn_pw *pw; static struct ctl_pw pwctl; @@ -424,7 +424,7 @@ l2vpn_binding_ctl(pid_t pid) pwctl.local_label = NO_LABEL; LIST_FOREACH(me, &fn->downstream, entry) - if (f->u.pwid.nexthop.s_addr == me->nexthop->id.s_addr) + if (f->u.pwid.lsr_id.s_addr == me->nexthop->id.s_addr) break; if (me) { @@ -479,7 +479,7 @@ ldpe_l2vpn_pw_exit(struct l2vpn_pw *pw) { struct tnbr *tnbr; - tnbr = tnbr_find(leconf, pw->addr); + tnbr = tnbr_find(leconf, pw->lsr_id); if (tnbr) { tnbr->pw_count--; tnbr_check(tnbr); diff --git a/usr.sbin/ldpd/lde.c b/usr.sbin/ldpd/lde.c index 6ecc248b0fb..fb1dbe9cf7b 100644 --- a/usr.sbin/ldpd/lde.c +++ b/usr.sbin/ldpd/lde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lde.c,v 1.47 2016/05/23 16:50:11 renato Exp $ */ +/* $OpenBSD: lde.c,v 1.48 2016/05/23 16:54:22 renato Exp $ */ /* * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org> @@ -575,7 +575,7 @@ lde_send_change_klabel(struct fec_node *fn, struct fec_nh *fnh) fnh->remote_label == NO_LABEL) return; - pw = (struct l2vpn_pw *) fnh->data; + pw = (struct l2vpn_pw *) fn->data; pw->flags |= F_PW_STATUS_UP; bzero(&kpw, sizeof(kpw)); @@ -615,7 +615,7 @@ lde_send_delete_klabel(struct fec_node *fn, struct fec_nh *fnh) l2vpn_sync_pws(fn->fec.u.ipv4.prefix); break; case FEC_TYPE_PWID: - pw = (struct l2vpn_pw *) fnh->data; + pw = (struct l2vpn_pw *) fn->data; if (!(pw->flags & F_PW_STATUS_UP)) return; pw->flags &= ~F_PW_STATUS_UP; @@ -656,7 +656,7 @@ lde_fec2map(struct fec *fec, struct map *map) } void -lde_map2fec(struct map *map, struct in_addr nbrid, struct fec *fec) +lde_map2fec(struct map *map, struct in_addr lsr_id, struct fec *fec) { bzero(fec, sizeof(*fec)); @@ -670,7 +670,7 @@ lde_map2fec(struct map *map, struct in_addr nbrid, struct fec *fec) fec->type = FEC_TYPE_PWID; fec->u.pwid.type = map->fec.pwid.type; fec->u.pwid.pwid = map->fec.pwid.pwid; - fec->u.pwid.nexthop.s_addr = nbrid.s_addr; + fec->u.pwid.lsr_id = lsr_id; break; } } @@ -681,7 +681,6 @@ lde_send_labelmapping(struct lde_nbr *ln, struct fec_node *fn, int single) struct lde_req *lre; struct lde_map *me; struct map map; - struct fec_nh *fnh; struct l2vpn_pw *pw; /* @@ -694,12 +693,11 @@ lde_send_labelmapping(struct lde_nbr *ln, struct fec_node *fn, int single) lde_fec2map(&fn->fec, &map); if (fn->fec.type == FEC_TYPE_PWID) { - fnh = fec_nh_find(fn, ln->id); - if (fnh == NULL) - /* not the other end of the pseudowire */ + pw = (struct l2vpn_pw *) fn->data; + if (pw == NULL || pw->lsr_id.s_addr != ln->id.s_addr) + /* not the remote end of the pseudowire */ return; - pw = (struct l2vpn_pw *) fnh->data; map.flags |= F_MAP_PW_IFMTU; map.fec.pwid.ifmtu = pw->l2vpn->mtu; if (pw->flags & F_PW_CWORD) @@ -904,10 +902,21 @@ lde_nbr_del(struct lde_nbr *ln) fn = (struct fec_node *)f; LIST_FOREACH(fnh, &fn->nexthops, entry) { - if (lde_address_find(ln, &fnh->nexthop)) { - lde_send_delete_klabel(fn, fnh); - fnh->remote_label = NO_LABEL; + switch (f->type) { + case FEC_TYPE_IPV4: + if (!lde_address_find(ln, &fnh->nexthop)) + continue; + break; + case FEC_TYPE_PWID: + if (f->u.pwid.lsr_id.s_addr != ln->id.s_addr) + continue; + break; + default: + break; } + + lde_send_delete_klabel(fn, fnh); + fnh->remote_label = NO_LABEL; } } @@ -934,6 +943,30 @@ lde_nbr_find(uint32_t peerid) return (RB_FIND(nbr_tree, &lde_nbrs, &ln)); } +struct lde_nbr * +lde_nbr_find_by_lsrid(struct in_addr addr) +{ + struct lde_nbr *ln; + + RB_FOREACH(ln, nbr_tree, &lde_nbrs) + if (ln->id.s_addr == addr.s_addr) + return (ln); + + return (NULL); +} + +struct lde_nbr * +lde_nbr_find_by_addr(struct in_addr addr) +{ + struct lde_nbr *ln; + + RB_FOREACH(ln, nbr_tree, &lde_nbrs) + if (lde_address_find(ln, &addr) != NULL) + return (ln); + + return (NULL); +} + void lde_nbr_clear(void) { @@ -1140,16 +1173,3 @@ lde_address_list_free(struct lde_nbr *ln) free(addr); } } - -struct lde_nbr * -lde_find_address(struct in_addr address) -{ - struct lde_nbr *ln; - - RB_FOREACH(ln, nbr_tree, &lde_nbrs) { - if (lde_address_find(ln, &address) != NULL) - return (ln); - } - - return (NULL); -} diff --git a/usr.sbin/ldpd/lde_lib.c b/usr.sbin/ldpd/lde_lib.c index ac69727a4fa..7b6520c12a7 100644 --- a/usr.sbin/ldpd/lde_lib.c +++ b/usr.sbin/ldpd/lde_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lde_lib.c,v 1.47 2016/05/23 16:52:16 renato Exp $ */ +/* $OpenBSD: lde_lib.c,v 1.48 2016/05/23 16:54:22 renato Exp $ */ /* * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org> @@ -92,11 +92,11 @@ fec_compare(struct fec *a, struct fec *b) return (-1); if (a->u.pwid.pwid > b->u.pwid.pwid) return (1); - if (ntohl(a->u.pwid.nexthop.s_addr) < - ntohl(b->u.pwid.nexthop.s_addr)) + if (ntohl(a->u.pwid.lsr_id.s_addr) < + ntohl(b->u.pwid.lsr_id.s_addr)) return (-1); - if (ntohl(a->u.pwid.nexthop.s_addr) > - ntohl(b->u.pwid.nexthop.s_addr)) + if (ntohl(a->u.pwid.lsr_id.s_addr) > + ntohl(b->u.pwid.lsr_id.s_addr)) return (1); return (0); } @@ -308,6 +308,9 @@ lde_kernel_insert(struct fec *fec, struct in_addr nexthop, int connected, if (fec_nh_find(fn, nexthop) != NULL) return; + if (fn->fec.type == FEC_TYPE_PWID) + fn->data = data; + if (LIST_EMPTY(&fn->nexthops)) { if (fn->local_label == NO_LABEL) { if (connected) @@ -339,9 +342,20 @@ lde_kernel_insert(struct fec *fec, struct in_addr nexthop, int connected, } fnh = fec_nh_add(fn, nexthop); - fnh->data = data; lde_send_change_klabel(fn, fnh); - ln = lde_find_address(fnh->nexthop); + + switch (fn->fec.type) { + case FEC_TYPE_IPV4: + ln = lde_nbr_find_by_addr(fnh->nexthop); + break; + case FEC_TYPE_PWID: + ln = lde_nbr_find_by_lsrid(fn->fec.u.pwid.lsr_id); + break; + default: + ln = NULL; + break; + } + if (ln) { /* FEC.2 */ me = (struct lde_map *)fec_find(&ln->recv_map, &fn->fec); @@ -433,28 +447,34 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln) * support multipath */ LIST_FOREACH(fnh, &fn->nexthops, entry) { - if (lde_address_find(ln, &fnh->nexthop) == NULL) - continue; - - msgsource = 1; - /* LMp.15: install FEC in FIB */ - fnh->remote_label = map->label; - switch (map->type) { - case MAP_TYPE_PREFIX: + switch (fec.type) { + case FEC_TYPE_IPV4: + if (!lde_address_find(ln, &fnh->nexthop)) + continue; + + fnh->remote_label = map->label; lde_send_change_klabel(fn, fnh); break; - case MAP_TYPE_PWID: - pw = (struct l2vpn_pw *) fnh->data; + case FEC_TYPE_PWID: + pw = (struct l2vpn_pw *) fn->data; + if (pw == NULL) + continue; + pw->remote_group = map->fec.pwid.group_id; if (map->flags & F_MAP_PW_IFMTU) pw->remote_mtu = map->fec.pwid.ifmtu; if (map->flags & F_MAP_PW_STATUS) pw->remote_status = map->pw_status; + fnh->remote_label = map->label; if (l2vpn_pw_ok(pw, fnh)) lde_send_change_klabel(fn, fnh); break; + default: + break; } + + msgsource = 1; } /* LMp.13 & LMp.16: Record the mapping from this peer */ if (me == NULL) @@ -493,10 +513,16 @@ lde_check_request(struct map *map, struct lde_nbr *ln) /* LRq.3: is MsgSource the next hop? */ LIST_FOREACH(fnh, &fn->nexthops, entry) { - if (lde_address_find(ln, &fnh->nexthop)) { + switch (fec.type) { + case FEC_TYPE_IPV4: + if (!lde_address_find(ln, &fnh->nexthop)) + continue; + lde_send_notification(ln->peerid, S_LOOP_DETECTED, map->messageid, htons(MSG_TYPE_LABELREQUEST)); return; + default: + break; } } @@ -594,10 +620,11 @@ lde_check_release_wcard(struct map *map, struct lde_nbr *ln) void lde_check_withdraw(struct map *map, struct lde_nbr *ln) { - struct fec fec; - struct fec_node *fn; - struct fec_nh *fnh; - struct lde_map *me; + struct fec fec; + struct fec_node *fn; + struct fec_nh *fnh; + struct lde_map *me; + struct l2vpn_pw *pw; /* TODO group wildcard */ if (map->type == MAP_TYPE_PWID && !(map->flags & F_MAP_PW_ID)) @@ -610,10 +637,21 @@ lde_check_withdraw(struct map *map, struct lde_nbr *ln) /* LWd.1: remove label from forwarding/switching use */ LIST_FOREACH(fnh, &fn->nexthops, entry) { - if (lde_address_find(ln, &fnh->nexthop)) { - lde_send_delete_klabel(fn, fnh); - fnh->remote_label = NO_LABEL; + switch (fec.type) { + case FEC_TYPE_IPV4: + if (!lde_address_find(ln, &fnh->nexthop)) + continue; + break; + case FEC_TYPE_PWID: + pw = (struct l2vpn_pw *) fn->data; + if (pw == NULL) + continue; + break; + default: + break; } + lde_send_delete_klabel(fn, fnh); + fnh->remote_label = NO_LABEL; } /* LWd.2: send label release */ @@ -642,10 +680,20 @@ lde_check_withdraw_wcard(struct map *map, struct lde_nbr *ln) /* LWd.1: remove label from forwarding/switching use */ LIST_FOREACH(fnh, &fn->nexthops, entry) { - if (lde_address_find(ln, &fnh->nexthop)) { - lde_send_delete_klabel(fn, fnh); - fnh->remote_label = NO_LABEL; + switch (f->type) { + case FEC_TYPE_IPV4: + if (!lde_address_find(ln, &fnh->nexthop)) + continue; + break; + case FEC_TYPE_PWID: + if (f->u.pwid.lsr_id.s_addr != ln->id.s_addr) + continue; + break; + default: + break; } + lde_send_delete_klabel(fn, fnh); + fnh->remote_label = NO_LABEL; } /* LWd.3: check previously received label mapping */ diff --git a/usr.sbin/ldpd/ldpd.c b/usr.sbin/ldpd/ldpd.c index 81a88673232..a5c0b67a946 100644 --- a/usr.sbin/ldpd/ldpd.c +++ b/usr.sbin/ldpd/ldpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ldpd.c,v 1.35 2016/05/23 16:18:51 renato Exp $ */ +/* $OpenBSD: ldpd.c,v 1.36 2016/05/23 16:54:22 renato Exp $ */ /* * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> @@ -881,7 +881,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) /* changes that require a full reset of the pseudowire */ if (l2vpn->pw_type != xl->pw_type || l2vpn->mtu != xl->mtu || - pw->addr.s_addr != xp->addr.s_addr || + pw->lsr_id.s_addr != xp->lsr_id.s_addr || pw->pwid != xp->pwid || ((pw->flags & (F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF)) != @@ -897,7 +897,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) l2vpn_pw_init(xp); break; case PROC_LDP_ENGINE: - if (pw->addr.s_addr != xp->addr.s_addr) { + if (pw->lsr_id.s_addr != xp->lsr_id.s_addr) { ldpe_l2vpn_pw_exit(pw); ldpe_l2vpn_pw_init(xp); } diff --git a/usr.sbin/ldpd/log.c b/usr.sbin/ldpd/log.c index a0a16c61d11..488d70dd30f 100644 --- a/usr.sbin/ldpd/log.c +++ b/usr.sbin/ldpd/log.c @@ -1,4 +1,4 @@ -/* $OpenBSD: log.c,v 1.20 2016/05/23 16:20:59 renato Exp $ */ +/* $OpenBSD: log.c,v 1.21 2016/05/23 16:54:22 renato Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -382,7 +382,7 @@ log_fec(struct fec *fec) if (snprintf(buf, sizeof(buf), "pwid %u (%s) - %s", fec->u.pwid.pwid, pw_type_name(fec->u.pwid.type), - inet_ntoa(fec->u.pwid.nexthop)) == -1) + inet_ntoa(fec->u.pwid.lsr_id)) == -1) return ("???"); break; default: diff --git a/usr.sbin/ldpd/notification.c b/usr.sbin/ldpd/notification.c index ef85e4f1ba2..5ee15ea8f2e 100644 --- a/usr.sbin/ldpd/notification.c +++ b/usr.sbin/ldpd/notification.c @@ -1,4 +1,4 @@ -/* $OpenBSD: notification.c,v 1.26 2016/05/23 16:29:22 renato Exp $ */ +/* $OpenBSD: notification.c,v 1.27 2016/05/23 16:54:22 renato Exp $ */ /* * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org> @@ -199,7 +199,6 @@ recv_notification(struct nbr *nbr, char *buf, u_int16_t len) switch (nm.fec.type) { case MAP_TYPE_PWID: - case MAP_TYPE_GENPWID: break; default: send_notification_nbr(nbr, S_BAD_TLV_VAL, diff --git a/usr.sbin/ldpd/parse.y b/usr.sbin/ldpd/parse.y index 36180d44107..a60d43c6a96 100644 --- a/usr.sbin/ldpd/parse.y +++ b/usr.sbin/ldpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.42 2016/05/23 16:39:47 renato Exp $ */ +/* $OpenBSD: parse.y,v 1.43 2016/05/23 16:54:22 renato Exp $ */ /* * Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org> @@ -362,7 +362,7 @@ pwopts : PWID NUMBER { } free($2); - pw->addr.s_addr = addr.s_addr; + pw->lsr_id = addr; t = tnbr_find(conf, addr); if (t == NULL) { @@ -407,7 +407,7 @@ pseudowire : PSEUDOWIRE STRING { yyerror("missing pseudowire id"); YYERROR; } - if (pw->addr.s_addr == INADDR_ANY) { + if (pw->lsr_id.s_addr == INADDR_ANY) { yyerror("missing pseudowore neighbor"); YYERROR; } @@ -416,7 +416,7 @@ pseudowire : PSEUDOWIRE STRING { LIST_FOREACH(p, &l->pw_list, entry) if (pw != p && pw->pwid == p->pwid && - pw->addr.s_addr == p->addr.s_addr) { + pw->lsr_id.s_addr == p->lsr_id.s_addr) { yyerror("pseudowire already " "configured"); YYERROR; diff --git a/usr.sbin/ldpd/printconf.c b/usr.sbin/ldpd/printconf.c index 69cc730b55a..daf3d3c719a 100644 --- a/usr.sbin/ldpd/printconf.c +++ b/usr.sbin/ldpd/printconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: printconf.c,v 1.17 2016/05/23 16:35:37 renato Exp $ */ +/* $OpenBSD: printconf.c,v 1.18 2016/05/23 16:54:22 renato Exp $ */ /* * Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org> @@ -109,7 +109,7 @@ void print_pw(struct l2vpn_pw *pw) { printf("\tpseudowire %s {\n", pw->ifname); - printf("\t\tneighbor %s\n", inet_ntoa(pw->addr)); + printf("\t\tneighbor %s\n", inet_ntoa(pw->lsr_id)); printf("\t\tpw-id %u\n", pw->pwid); if (pw->flags & F_PW_STATUSTLV_CONF) printf("\t\tstatus-tlv yes\n"); |