diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/bridgectl.c | 19 | ||||
-rw-r--r-- | sys/net/if.h | 4 | ||||
-rw-r--r-- | sys/net/if_bridge.c | 70 | ||||
-rw-r--r-- | sys/net/if_bridge.h | 22 | ||||
-rw-r--r-- | sys/net/if_switch.c | 41 | ||||
-rw-r--r-- | sys/net/if_vlan.c | 15 | ||||
-rw-r--r-- | sys/net/if_vxlan.c | 96 | ||||
-rw-r--r-- | sys/net/if_vxlan.h | 8 | ||||
-rw-r--r-- | sys/netinet/udp_usrreq.c | 22 |
9 files changed, 211 insertions, 86 deletions
diff --git a/sys/net/bridgectl.c b/sys/net/bridgectl.c index 93c638c748e..4e306927bb4 100644 --- a/sys/net/bridgectl.c +++ b/sys/net/bridgectl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bridgectl.c,v 1.2 2015/12/02 08:04:12 mpi Exp $ */ +/* $OpenBSD: bridgectl.c,v 1.3 2016/09/03 13:46:57 reyk Exp $ */ /* * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) @@ -175,13 +175,13 @@ bridge_rtupdate(struct bridge_softc *sc, struct ether_addr *ea, struct ifnet *ifp, int setflags, u_int8_t flags, struct mbuf *m) { struct bridge_rtnode *p, *q; - struct sockaddr *sa = NULL; + struct bridge_tunneltag *brtag = NULL; u_int32_t h; int dir; if (m != NULL) { /* Check if the mbuf was tagged with a tunnel endpoint addr */ - sa = bridge_tunnel(m); + brtag = bridge_tunnel(m); } h = bridge_hash(sc, ea); @@ -196,7 +196,7 @@ bridge_rtupdate(struct bridge_softc *sc, struct ether_addr *ea, bcopy(ea, &p->brt_addr, sizeof(p->brt_addr)); p->brt_if = ifp; p->brt_age = 1; - bridge_copyaddr(sa, (struct sockaddr *)&p->brt_tunnel); + bridge_copytag(brtag, &p->brt_tunnel); if (setflags) p->brt_flags = flags; @@ -223,8 +223,7 @@ bridge_rtupdate(struct bridge_softc *sc, struct ether_addr *ea, if (q->brt_if == ifp) q->brt_age = 1; ifp = q->brt_if; - bridge_copyaddr(sa, - (struct sockaddr *)&q->brt_tunnel); + bridge_copytag(brtag, &q->brt_tunnel); goto want; } @@ -239,8 +238,7 @@ bridge_rtupdate(struct bridge_softc *sc, struct ether_addr *ea, bcopy(ea, &p->brt_addr, sizeof(p->brt_addr)); p->brt_if = ifp; p->brt_age = 1; - bridge_copyaddr(sa, - (struct sockaddr *)&p->brt_tunnel); + bridge_copytag(brtag, &p->brt_tunnel); if (setflags) p->brt_flags = flags; @@ -262,8 +260,7 @@ bridge_rtupdate(struct bridge_softc *sc, struct ether_addr *ea, bcopy(ea, &p->brt_addr, sizeof(p->brt_addr)); p->brt_if = ifp; p->brt_age = 1; - bridge_copyaddr(sa, - (struct sockaddr *)&p->brt_tunnel); + bridge_copytag(brtag, &p->brt_tunnel); if (setflags) p->brt_flags = flags; @@ -490,7 +487,7 @@ bridge_rtfind(struct bridge_softc *sc, struct ifbaconf *baconf) sizeof(bareq.ifba_ifsname)); bcopy(&n->brt_addr, &bareq.ifba_dst, sizeof(bareq.ifba_dst)); - bridge_copyaddr(&n->brt_tunnel.sa, + bridge_copyaddr(&n->brt_tunnel.brtag_src.sa, (struct sockaddr *)&bareq.ifba_dstsa); bareq.ifba_age = n->brt_age; bareq.ifba_flags = n->brt_flags; diff --git a/sys/net/if.h b/sys/net/if.h index 3022b38482b..29d1cb074d9 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if.h,v 1.177 2016/06/10 20:33:29 vgross Exp $ */ +/* $OpenBSD: if.h,v 1.178 2016/09/03 13:46:57 reyk Exp $ */ /* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */ /* @@ -360,7 +360,7 @@ struct ifreq { struct sockaddr ifru_broadaddr; short ifru_flags; int ifru_metric; - uint32_t ifru_vnetid; + int64_t ifru_vnetid; uint64_t ifru_media; caddr_t ifru_data; unsigned int ifru_index; diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 80c4b7e67ec..1b01b47c295 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bridge.c,v 1.283 2016/09/02 10:01:36 goda Exp $ */ +/* $OpenBSD: if_bridge.c,v 1.284 2016/09/03 13:46:57 reyk Exp $ */ /* * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) @@ -715,6 +715,7 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa, struct bridge_rtnode *dst_p = NULL; struct ether_addr *dst; struct bridge_softc *sc; + struct bridge_tunneltag *brtag; int error; /* ifp must be a member interface of the bridge. */ @@ -811,9 +812,15 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa, } sendunicast: - if (dst_p != NULL && dst_p->brt_tunnel.sa.sa_family != AF_UNSPEC && - (sa = bridge_tunneltag(m, dst_p->brt_tunnel.sa.sa_family)) != NULL) - memcpy(sa, &dst_p->brt_tunnel.sa, dst_p->brt_tunnel.sa.sa_len); + if ((dst_p != NULL) && + (dst_p->brt_tunnel.brtag_dst.sa.sa_family != AF_UNSPEC) && + ((brtag = bridge_tunneltag(m)) != NULL)) { + memcpy(&brtag->brtag_src, &dst_p->brt_tunnel.brtag_src.sa, + dst_p->brt_tunnel.brtag_src.sa.sa_len); + memcpy(&brtag->brtag_dst, &dst_p->brt_tunnel.brtag_dst.sa, + dst_p->brt_tunnel.brtag_dst.sa.sa_len); + brtag->brtag_id = dst_p->brt_tunnel.brtag_id; + } bridge_span(sc, m); if ((dst_if->if_flags & IFF_RUNNING) == 0) { @@ -1942,7 +1949,7 @@ bridge_send_icmp_err(struct bridge_softc *sc, struct ifnet *ifp, m_freem(n); } -struct sockaddr * +struct bridge_tunneltag * bridge_tunnel(struct mbuf *m) { struct m_tag *mtag; @@ -1950,41 +1957,24 @@ bridge_tunnel(struct mbuf *m) if ((mtag = m_tag_find(m, PACKET_TAG_TUNNEL, NULL)) == NULL) return (NULL); - return ((struct sockaddr *)(mtag + 1)); + return ((struct bridge_tunneltag *)(mtag + 1)); } -struct sockaddr * -bridge_tunneltag(struct mbuf *m, int af) +struct bridge_tunneltag * +bridge_tunneltag(struct mbuf *m) { - struct m_tag *mtag; - size_t len; - struct sockaddr *sa; - - if ((mtag = m_tag_find(m, PACKET_TAG_TUNNEL, NULL)) != NULL) { - sa = (struct sockaddr *)(mtag + 1); - if (sa->sa_family != af) { - m_tag_delete(m, mtag); - mtag = NULL; - } - } - if (mtag == NULL) { - if (af == AF_INET) - len = sizeof(struct sockaddr_in); - else if (af == AF_INET6) - len = sizeof(struct sockaddr_in6); - else - return (NULL); - mtag = m_tag_get(PACKET_TAG_TUNNEL, len, M_NOWAIT); + struct m_tag *mtag; + + if ((mtag = m_tag_find(m, PACKET_TAG_TUNNEL, NULL)) == NULL) { + mtag = m_tag_get(PACKET_TAG_TUNNEL, + sizeof(struct bridge_tunneltag), M_NOWAIT); if (mtag == NULL) return (NULL); - bzero(mtag + 1, len); - sa = (struct sockaddr *)(mtag + 1); - sa->sa_family = af; - sa->sa_len = len; + bzero(mtag + 1, sizeof(struct bridge_tunneltag)); m_tag_prepend(m, mtag); } - return ((struct sockaddr *)(mtag + 1)); + return ((struct bridge_tunneltag *)(mtag + 1)); } void @@ -2000,6 +1990,20 @@ bridge_copyaddr(struct sockaddr *src, struct sockaddr *dst) { if (src != NULL && src->sa_family != AF_UNSPEC) memcpy(dst, src, src->sa_len); - else + else { dst->sa_family = AF_UNSPEC; + dst->sa_len = 0; + } +} + +void +bridge_copytag(struct bridge_tunneltag *src, struct bridge_tunneltag *dst) +{ + if (src == NULL) { + memset(dst, 0, sizeof(*dst)); + } else { + bridge_copyaddr(&src->brtag_src.sa, &dst->brtag_src.sa); + bridge_copyaddr(&src->brtag_dst.sa, &dst->brtag_dst.sa); + dst->brtag_id = src->brtag_id; + } } diff --git a/sys/net/if_bridge.h b/sys/net/if_bridge.h index df1a3b9f534..95a5144c0ca 100644 --- a/sys/net/if_bridge.h +++ b/sys/net/if_bridge.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bridge.h,v 1.50 2016/09/02 10:01:36 goda Exp $ */ +/* $OpenBSD: if_bridge.h,v 1.51 2016/09/03 13:46:57 reyk Exp $ */ /* * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) @@ -406,15 +406,24 @@ struct bridge_iflist { ((struct bridge_iflist *)_bp2)->bridge_sc) /* + * Bridge tunnel tagging + */ +struct bridge_tunneltag { + union pfsockaddr_union brtag_src; + union pfsockaddr_union brtag_dst; + u_int32_t brtag_id; +}; + +/* * Bridge route node */ struct bridge_rtnode { LIST_ENTRY(bridge_rtnode) brt_next; /* next in list */ - struct ifnet *brt_if; /* destination ifs */ + struct ifnet *brt_if; /* destination ifs */ u_int8_t brt_flags; /* address flags */ u_int8_t brt_age; /* age counter */ - struct ether_addr brt_addr; /* dst addr */ - union pfsockaddr_union brt_tunnel; /* tunnel endpoint */ + struct ether_addr brt_addr; /* dst addr */ + struct bridge_tunneltag brt_tunnel; /* tunnel endpoint */ }; #ifndef BRIDGE_RTABLE_SIZE @@ -447,10 +456,11 @@ int bridge_output(struct ifnet *, struct mbuf *, struct sockaddr *, void bridge_update(struct ifnet *, struct ether_addr *, int); void bridge_rtdelete(struct bridge_softc *, struct ifnet *, int); void bridge_rtagenode(struct ifnet *, int); -struct sockaddr *bridge_tunnel(struct mbuf *); -struct sockaddr *bridge_tunneltag(struct mbuf *, int); +struct bridge_tunneltag *bridge_tunnel(struct mbuf *); +struct bridge_tunneltag *bridge_tunneltag(struct mbuf *); void bridge_tunneluntag(struct mbuf *); void bridge_copyaddr(struct sockaddr *, struct sockaddr *); +void bridge_copytag(struct bridge_tunneltag *, struct bridge_tunneltag *); struct bstp_state *bstp_create(struct ifnet *); void bstp_destroy(struct bstp_state *); diff --git a/sys/net/if_switch.c b/sys/net/if_switch.c index 8f481583981..c0032f93749 100644 --- a/sys/net/if_switch.c +++ b/sys/net/if_switch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_switch.c,v 1.2 2016/09/02 10:01:36 goda Exp $ */ +/* $OpenBSD: if_switch.c,v 1.3 2016/09/03 13:46:57 reyk Exp $ */ /* * Copyright (c) 2016 Kazuya GODA <goda@openbsd.org> @@ -1376,6 +1376,43 @@ switch_flow_classifier_ether(struct mbuf *m, int *offset, } struct mbuf * +switch_flow_classifier_tunnel(struct mbuf *m, int *offset, + struct switch_flow_classify *swfcl) +{ + struct bridge_tunneltag *brtag; + + if ((brtag = bridge_tunnel(m)) == NULL) + goto out; + + if ((brtag->brtag_dst.sa.sa_family != AF_INET) && + (brtag->brtag_dst.sa.sa_family != AF_INET6)) + goto out; + + swfcl->swfcl_tunnel = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO); + if (swfcl->swfcl_tunnel == NULL) { + m_freem(m); + return (NULL); + } + + swfcl->swfcl_tunnel->tun_af = brtag->brtag_dst.sa.sa_family; + swfcl->swfcl_tunnel->tun_key = htobe64(brtag->brtag_id); + if (swfcl->swfcl_tunnel->tun_af == AF_INET) { + swfcl->swfcl_tunnel->tun_ipv4_src = + brtag->brtag_src.sin.sin_addr; + swfcl->swfcl_tunnel->tun_ipv4_dst = + brtag->brtag_dst.sin.sin_addr; + } else { + swfcl->swfcl_tunnel->tun_ipv6_src = + brtag->brtag_src.sin6.sin6_addr; + swfcl->swfcl_tunnel->tun_ipv6_dst = + brtag->brtag_dst.sin6.sin6_addr; + } + bridge_tunneluntag(m); + out: + return switch_flow_classifier_ether(m, offset, swfcl); +} + +struct mbuf * switch_flow_classifier(struct mbuf *m, uint32_t in_port, struct switch_flow_classify *swfcl) { @@ -1384,7 +1421,7 @@ switch_flow_classifier(struct mbuf *m, uint32_t in_port, memset(swfcl, 0, sizeof(*swfcl)); swfcl->swfcl_in_port = in_port; - return switch_flow_classifier_ether(m, &offset, swfcl); + return switch_flow_classifier_tunnel(m, &offset, swfcl); } void diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c index 0aa47d77fb0..7b23bf8dee8 100644 --- a/sys/net/if_vlan.c +++ b/sys/net/if_vlan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vlan.c,v 1.165 2016/05/18 03:46:03 dlg Exp $ */ +/* $OpenBSD: if_vlan.c,v 1.166 2016/09/03 13:46:57 reyk Exp $ */ /* * Copyright 1998 Massachusetts Institute of Technology @@ -648,15 +648,16 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCSVNETID: - tag = ifr->ifr_vnetid; - if (tag == ifv->ifv_tag) - break; - - if (tag < EVL_VLID_MIN || tag > EVL_VLID_MAX) { + if (ifr->ifr_vnetid < EVL_VLID_MIN || + ifr->ifr_vnetid > EVL_VLID_MAX) { error = EINVAL; break; } + tag = ifr->ifr_vnetid; + if (tag == ifv->ifv_tag) + break; + error = vlan_set_vnetid(ifv, tag); break; @@ -664,7 +665,7 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) if (ifv->ifv_tag == EVL_VLID_NULL) error = EADDRNOTAVAIL; else - ifr->ifr_vnetid = (uint32_t)ifv->ifv_tag; + ifr->ifr_vnetid = (int64_t)ifv->ifv_tag; break; case SIOCDVNETID: diff --git a/sys/net/if_vxlan.c b/sys/net/if_vxlan.c index 3cd59a79b5b..4050030d9ad 100644 --- a/sys/net/if_vxlan.c +++ b/sys/net/if_vxlan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vxlan.c,v 1.42 2016/08/07 14:26:26 reyk Exp $ */ +/* $OpenBSD: if_vxlan.c,v 1.43 2016/09/03 13:46:57 reyk Exp $ */ /* * Copyright (c) 2013 Reyk Floeter <reyk@openbsd.org> @@ -70,7 +70,7 @@ struct vxlan_softc { struct sockaddr_storage sc_dst; in_port_t sc_dstport; u_int sc_rdomain; - int sc_vnetid; + int64_t sc_vnetid; u_int8_t sc_ttl; LIST_ENTRY(vxlan_softc) sc_entry; @@ -103,15 +103,19 @@ u_long vxlan_tagmask; #define VXLAN_TAGHASHSIZE 32 #define VXLAN_TAGHASH(tag) ((unsigned int)tag & vxlan_tagmask) -LIST_HEAD(vxlan_taghash, vxlan_softc) *vxlan_tagh; +LIST_HEAD(vxlan_taghash, vxlan_softc) *vxlan_tagh, vxlan_any; void vxlanattach(int count) { + /* Regular vxlan interfaces with a VNI */ if ((vxlan_tagh = hashinit(VXLAN_TAGHASHSIZE, M_DEVBUF, M_NOWAIT, &vxlan_tagmask)) == NULL) panic("vxlanattach: hashinit"); + /* multipoint-to-multipoint interfaces that accept any VNI */ + LIST_INIT(&vxlan_any); + if_clone_attach(&vxlan_cloner); } @@ -316,6 +320,7 @@ vxlan_config(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst) int reset = 0, error, af; socklen_t slen; in_port_t port; + struct vxlan_taghash *tagh; if (src != NULL && dst != NULL) { if ((af = src->sa_family) != dst->sa_family) @@ -354,9 +359,17 @@ vxlan_config(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst) memcpy(&sc->sc_dst, dst, dst->sa_len); } + if (sc->sc_vnetid == VXLAN_VNI_ANY) { + /* + * If the interface accepts any VNI, put it into a separate + * list that is not part of the main hash. + */ + tagh = &vxlan_any; + } else + tagh = &vxlan_tagh[VXLAN_TAGHASH(sc->sc_vnetid)]; + LIST_REMOVE(sc, sc_entry); - LIST_INSERT_HEAD(&vxlan_tagh[VXLAN_TAGHASH(sc->sc_vnetid)], - sc, sc_entry); + LIST_INSERT_HEAD(tagh, sc, sc_entry); return (0); } @@ -454,10 +467,16 @@ vxlanioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCSVNETID: - if (ifr->ifr_vnetid > VXLAN_VNI_MAX) { + if (sc->sc_vnetid == ifr->ifr_vnetid) + break; + + if ((ifr->ifr_vnetid != VXLAN_VNI_ANY) && + (ifr->ifr_vnetid > VXLAN_VNI_MAX || + ifr->ifr_vnetid < VXLAN_VNI_MIN)) { error = EINVAL; break; } + s = splnet(); sc->sc_vnetid = (int)ifr->ifr_vnetid; (void)vxlan_config(ifp, NULL, NULL); @@ -465,11 +484,14 @@ vxlanioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCGVNETID: - if (sc->sc_vnetid == VXLAN_VNI_UNSET) { + if ((sc->sc_vnetid != VXLAN_VNI_ANY) && + (sc->sc_vnetid > VXLAN_VNI_MAX || + sc->sc_vnetid < VXLAN_VNI_MIN)) { error = EADDRNOTAVAIL; break; } - ifr->ifr_vnetid = (uint32_t)sc->sc_vnetid; + + ifr->ifr_vnetid = sc->sc_vnetid; break; case SIOCDVNETID: @@ -496,7 +518,6 @@ vxlan_media_change(struct ifnet *ifp) void vxlan_media_status(struct ifnet *ifp, struct ifmediareq *imr) { - imr->ifm_active = IFM_ETHER | IFM_AUTO; imr->ifm_status = IFM_AVALID | IFM_ACTIVE; } @@ -547,7 +568,7 @@ vxlan_sockaddr_port(struct sockaddr *sa) int vxlan_lookup(struct mbuf *m, struct udphdr *uh, int iphlen, - struct sockaddr *srcsa) + struct sockaddr *srcsa, struct sockaddr *dstsa) { struct mbuf_list ml = MBUF_LIST_INITIALIZER(); struct vxlan_softc *sc = NULL, *sc_cand = NULL; @@ -557,7 +578,7 @@ vxlan_lookup(struct mbuf *m, struct udphdr *uh, int iphlen, int skip; struct ether_header *eh; #if NBRIDGE > 0 - struct sockaddr *sa; + struct bridge_tunneltag *brtag; #endif /* XXX Should verify the UDP port first before copying the packet */ @@ -579,6 +600,7 @@ vxlan_lookup(struct mbuf *m, struct udphdr *uh, int iphlen, vni = VXLAN_VNI_UNSET; } + /* First search for a vxlan(4) interface with the packet's VNI */ LIST_FOREACH(sc, &vxlan_tagh[VXLAN_TAGHASH(vni)], sc_entry) { if ((uh->uh_dport == sc->sc_dstport) && vni == sc->sc_vnetid && @@ -590,6 +612,21 @@ vxlan_lookup(struct mbuf *m, struct udphdr *uh, int iphlen, } } + /* + * Now loop through all the vxlan(4) interfaces that are configured + * to accept any VNI and operating in multipoint-to-multipoint mode + * that is used in combination with bridge(4) or switch(4). + * If a vxlan(4) interface has been found for the packet's VNI, this + * code is not reached as the other interface is more specific. + */ + LIST_FOREACH(sc, &vxlan_any, sc_entry) { + if ((uh->uh_dport == sc->sc_dstport) && + (sc->sc_rdomain == rtable_l2(m->m_pkthdr.ph_rtableid))) { + sc_cand = sc; + goto found; + } + } + if (sc_cand) { sc = sc_cand; goto found; @@ -606,11 +643,14 @@ vxlan_lookup(struct mbuf *m, struct udphdr *uh, int iphlen, return (EINVAL); #if NBRIDGE > 0 - /* Store the peer IP address for the bridge */ - if (ifp->if_bridgeport != NULL && + /* Store the tunnel src/dst IP and vni for the bridge or switch */ + if ((ifp->if_bridgeport != NULL || ifp->if_switchport != NULL) && srcsa->sa_family != AF_UNSPEC && - (sa = bridge_tunneltag(m, srcsa->sa_family)) != NULL) - memcpy(sa, srcsa, sa->sa_len); + ((brtag = bridge_tunneltag(m)) != NULL)) { + memcpy(&brtag->brtag_src.sa, srcsa, srcsa->sa_len); + memcpy(&brtag->brtag_dst.sa, dstsa, dstsa->sa_len); + brtag->brtag_id = vni; + } #endif m->m_flags &= ~(M_MCAST|M_BCAST); @@ -712,9 +752,10 @@ vxlan_output(struct ifnet *ifp, struct mbuf *m) struct vxlanudphdr *vu; struct sockaddr *src, *dst; #if NBRIDGE > 0 - struct sockaddr *brtag; + struct bridge_tunneltag *brtag; #endif int error, af; + uint32_t tag; /* VXLAN header */ M_PREPEND(m, sizeof(*vu), M_DONTWAIT); @@ -732,10 +773,18 @@ vxlan_output(struct ifnet *ifp, struct mbuf *m) vu->vu_u.uh_dport = sc->sc_dstport; vu->vu_u.uh_ulen = htons(m->m_pkthdr.len); vu->vu_u.uh_sum = 0; + tag = sc->sc_vnetid; #if NBRIDGE > 0 if ((brtag = bridge_tunnel(m)) != NULL) { - dst = brtag; + dst = &brtag->brtag_dst.sa; + + /* If accepting any VNI, source ip address is from brtag */ + if (sc->sc_vnetid == VXLAN_VNI_ANY) { + src = &brtag->brtag_src.sa; + tag = (uint32_t)brtag->brtag_id; + af = src->sa_family; + } if (dst->sa_family != af) { ifp->if_oerrors++; @@ -750,12 +799,21 @@ vxlan_output(struct ifnet *ifp, struct mbuf *m) */ if (ifp->if_flags & IFF_LINK0) vu->vu_u.uh_dport = vxlan_sockaddr_port(dst); - } + } else #endif + if (sc->sc_vnetid == VXLAN_VNI_ANY) { + /* + * If accepting any VNI, build the vxlan header only by + * bridge_tunneltag or drop packet if the tag does not exist. + */ + ifp->if_oerrors++; + m_freem(m); + return (ENETUNREACH); + } if (sc->sc_vnetid != VXLAN_VNI_UNSET) { vu->vu_v.vxlan_flags = htonl(VXLAN_FLAGS_VNI); - vu->vu_v.vxlan_id = htonl(sc->sc_vnetid << VXLAN_VNI_S); + vu->vu_v.vxlan_id = htonl(tag << VXLAN_VNI_S); } else { vu->vu_v.vxlan_flags = htonl(0); vu->vu_v.vxlan_id = htonl(0); diff --git a/sys/net/if_vxlan.h b/sys/net/if_vxlan.h index c6ed25b8d66..33968772e4d 100644 --- a/sys/net/if_vxlan.h +++ b/sys/net/if_vxlan.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vxlan.h,v 1.10 2016/08/07 13:49:12 reyk Exp $ */ +/* $OpenBSD: if_vxlan.h,v 1.11 2016/09/03 13:46:57 reyk Exp $ */ /* * Copyright (c) 2013 Reyk Floeter <reyk@openbsd.org> @@ -34,7 +34,9 @@ struct vxlan_header { } __packed; #define VXLAN_VNI_MAX 0x00ffffff /* 24bit vnetid */ -#define VXLAN_VNI_UNSET 0xffffffff /* -1 */ +#define VXLAN_VNI_MIN 0x00000000 /* 24bit vnetid */ +#define VXLAN_VNI_UNSET 0x01ffffff /* used internally */ +#define VXLAN_VNI_ANY -1ULL /* -1 accept any vnetid */ struct vxlanudphdr { struct udphdr vu_u; @@ -45,7 +47,7 @@ struct vxlanudphdr { extern int vxlan_enable; int vxlan_lookup(struct mbuf *, struct udphdr *, int, - struct sockaddr *); + struct sockaddr *, struct sockaddr *); struct sockaddr *vxlan_tag_find(struct mbuf *); struct sockaddr *vxlan_tag_get(struct mbuf *, int); void vxlan_tag_delete(struct mbuf *); diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 01b6c5b64ef..60a7bdf41bd 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp_usrreq.c,v 1.218 2016/08/16 22:21:17 vgross Exp $ */ +/* $OpenBSD: udp_usrreq.c,v 1.219 2016/09/03 13:46:57 reyk Exp $ */ /* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */ /* @@ -173,7 +173,7 @@ udp_input(struct mbuf *m, ...) #ifdef INET6 struct sockaddr_in6 sin6; #endif /* INET6 */ - } srcsa; + } srcsa, dstsa; #ifdef INET6 struct ip6_hdr *ip6; #endif /* INET6 */ @@ -353,6 +353,12 @@ udp_input(struct mbuf *m, ...) srcsa.sin.sin_family = AF_INET; srcsa.sin.sin_port = uh->uh_sport; srcsa.sin.sin_addr = ip->ip_src; + + bzero(&dstsa, sizeof(struct sockaddr_in)); + dstsa.sin.sin_len = sizeof(struct sockaddr_in); + dstsa.sin.sin_family = AF_INET; + dstsa.sin.sin_port = uh->uh_dport; + dstsa.sin.sin_addr = ip->ip_dst; break; #ifdef INET6 case AF_INET6: @@ -365,6 +371,16 @@ udp_input(struct mbuf *m, ...) #endif /* KAME hack: recover scopeid */ in6_recoverscope(&srcsa.sin6, &ip6->ip6_src); + + bzero(&dstsa, sizeof(struct sockaddr_in6)); + dstsa.sin6.sin6_len = sizeof(struct sockaddr_in6); + dstsa.sin6.sin6_family = AF_INET6; + dstsa.sin6.sin6_port = uh->uh_dport; +#if 0 /*XXX inbound flowinfo */ + dstsa.sin6.sin6_flowinfo = htonl(0x0fffffff) & ip6->ip6_flow; +#endif + /* KAME hack: recover scopeid */ + in6_recoverscope(&dstsa.sin6, &ip6->ip6_dst); break; #endif /* INET6 */ } @@ -374,7 +390,7 @@ udp_input(struct mbuf *m, ...) #if NPF > 0 !(m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) && #endif - (error = vxlan_lookup(m, uh, iphlen, &srcsa.sa)) != 0) { + (error = vxlan_lookup(m, uh, iphlen, &srcsa.sa, &dstsa.sa)) != 0) { if (error == -1) { udpstat.udps_hdrops++; m_freem(m); |