diff options
| author | Zhenlei Huang <zlei.huang@gmail.com> | 2021-08-22 22:28:47 +0000 |
|---|---|---|
| committer | Alexander V. Chernikov <melifaro@FreeBSD.org> | 2021-08-22 22:56:08 +0000 |
| commit | 62e1a437f3285e785d9b35a476d36a469a90028d (patch) | |
| tree | 371cf19e2cae5884ebac7bc3a864d2b056aa7f1c /sys/net | |
| parent | eccb516db8b7fec957b139c3a9a2e16175551067 (diff) | |
Diffstat (limited to 'sys/net')
| -rw-r--r-- | sys/net/debugnet.c | 1 | ||||
| -rw-r--r-- | sys/net/if_disc.c | 2 | ||||
| -rw-r--r-- | sys/net/if_ethersubr.c | 11 | ||||
| -rw-r--r-- | sys/net/if_fwsubr.c | 28 | ||||
| -rw-r--r-- | sys/net/if_gif.c | 2 | ||||
| -rw-r--r-- | sys/net/if_gre.c | 2 | ||||
| -rw-r--r-- | sys/net/if_infiniband.c | 7 | ||||
| -rw-r--r-- | sys/net/if_loop.c | 2 | ||||
| -rw-r--r-- | sys/net/if_me.c | 4 | ||||
| -rw-r--r-- | sys/net/if_spppsubr.c | 11 | ||||
| -rw-r--r-- | sys/net/if_tuntap.c | 2 | ||||
| -rw-r--r-- | sys/net/route.h | 4 | ||||
| -rw-r--r-- | sys/net/route/route_ctl.c | 30 |
13 files changed, 80 insertions, 26 deletions
diff --git a/sys/net/debugnet.c b/sys/net/debugnet.c index bb59ff33a93f..8652597c55db 100644 --- a/sys/net/debugnet.c +++ b/sys/net/debugnet.c @@ -673,6 +673,7 @@ debugnet_connect(const struct debugnet_conn_params *dcp, goto cleanup; } + /* TODO support AF_INET6 */ if (nh->gw_sa.sa_family == AF_INET) gw_sin = &nh->gw4_sa; else { diff --git a/sys/net/if_disc.c b/sys/net/if_disc.c index ac0028c42f70..14d544dfd86a 100644 --- a/sys/net/if_disc.c +++ b/sys/net/if_disc.c @@ -185,7 +185,7 @@ discoutput(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, if (dst->sa_family == AF_UNSPEC) bcopy(dst->sa_data, &af, sizeof(af)); else - af = dst->sa_family; + af = RO_GET_FAMILY(ro, dst); if (bpf_peers_present(ifp->if_bpf)) bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m); diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 6d8b79d4dd12..3209e8a82978 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -236,10 +236,11 @@ ether_resolve_addr(struct ifnet *ifp, struct mbuf *m, #endif #ifdef INET6 case AF_INET6: - if ((m->m_flags & M_MCAST) == 0) - error = nd6_resolve(ifp, LLE_SF(AF_INET6, 0), m, dst, phdr, + if ((m->m_flags & M_MCAST) == 0) { + int af = RO_GET_FAMILY(ro, dst); + error = nd6_resolve(ifp, LLE_SF(af, 0), m, dst, phdr, &lleflags, plle); - else { + } else { const struct in6_addr *a6; a6 = &(((const struct sockaddr_in6 *)dst)->sin6_addr); ETHER_MAP_IPV6_MULTICAST(a6, eh->ether_dhost); @@ -353,7 +354,7 @@ ether_output(struct ifnet *ifp, struct mbuf *m, if ((pflags & RT_L2_ME) != 0) { update_mbuf_csumflags(m, m); - return (if_simloop(ifp, m, dst->sa_family, 0)); + return (if_simloop(ifp, m, RO_GET_FAMILY(ro, dst), 0)); } loop_copy = (pflags & RT_MAY_LOOP) != 0; @@ -400,7 +401,7 @@ ether_output(struct ifnet *ifp, struct mbuf *m, */ if ((n = m_dup(m, M_NOWAIT)) != NULL) { update_mbuf_csumflags(m, n); - (void)if_simloop(ifp, n, dst->sa_family, hlen); + (void)if_simloop(ifp, n, RO_GET_FAMILY(ro, dst), hlen); } else if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); } diff --git a/sys/net/if_fwsubr.c b/sys/net/if_fwsubr.c index a6c43d4d05a4..321721737d36 100644 --- a/sys/net/if_fwsubr.c +++ b/sys/net/if_fwsubr.c @@ -94,6 +94,7 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, #if defined(INET) || defined(INET6) int is_gw = 0; #endif + int af = RO_GET_FAMILY(ro, dst); #ifdef MAC error = mac_ifnet_check_transmit(ifp, m); @@ -137,6 +138,26 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, destfw = NULL; } + switch (af) { +#ifdef INET + case AF_INET: + type = ETHERTYPE_IP; + break; + case AF_ARP: + type = ETHERTYPE_ARP; + break; +#endif +#ifdef INET6 + case AF_INET6: + type = ETHERTYPE_IPV6; + break; +#endif + default: + if_printf(ifp, "can't handle af%d\n", af); + error = EAFNOSUPPORT; + goto bad; + } + switch (dst->sa_family) { #ifdef INET case AF_INET: @@ -151,7 +172,6 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, if (error) return (error == EWOULDBLOCK ? 0 : error); } - type = ETHERTYPE_IP; break; case AF_ARP: @@ -159,7 +179,6 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, struct arphdr *ah; ah = mtod(m, struct arphdr *); ah->ar_hrd = htons(ARPHRD_IEEE1394); - type = ETHERTYPE_ARP; if (unicast) *destfw = *(struct fw_hwaddr *) ar_tha(ah); @@ -176,12 +195,11 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, #ifdef INET6 case AF_INET6: if (unicast) { - error = nd6_resolve(fc->fc_ifp, LLE_SF(AF_INET6, is_gw), - m, dst, (u_char *) destfw, NULL, NULL); + error = nd6_resolve(fc->fc_ifp, LLE_SF(af, is_gw), m, + dst, (u_char *) destfw, NULL, NULL); if (error) return (error == EWOULDBLOCK ? 0 : error); } - type = ETHERTYPE_IPV6; break; #endif diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c index 113bcb5c916e..796f427e356b 100644 --- a/sys/net/if_gif.c +++ b/sys/net/if_gif.c @@ -409,7 +409,7 @@ gif_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, if (dst->sa_family == AF_UNSPEC) bcopy(dst->sa_data, &af, sizeof(af)); else - af = dst->sa_family; + af = RO_GET_FAMILY(ro, dst); /* * Now save the af in the inbound pkt csum data, this is a cheat since * we are using the inbound csum_data field to carry the af over to diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c index 19014f9fd3de..5ad452ac38e0 100644 --- a/sys/net/if_gre.c +++ b/sys/net/if_gre.c @@ -613,7 +613,7 @@ gre_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, if (dst->sa_family == AF_UNSPEC) bcopy(dst->sa_data, &af, sizeof(af)); else - af = dst->sa_family; + af = RO_GET_FAMILY(ro, dst); /* * Now save the af in the inbound pkt csum data, this is a cheat since * we are using the inbound csum_data field to carry the af over to diff --git a/sys/net/if_infiniband.c b/sys/net/if_infiniband.c index 244b2a5ba117..4dfbd5272d15 100644 --- a/sys/net/if_infiniband.c +++ b/sys/net/if_infiniband.c @@ -253,8 +253,9 @@ infiniband_resolve_addr(struct ifnet *ifp, struct mbuf *m, #ifdef INET6 case AF_INET6: if ((m->m_flags & M_MCAST) == 0) { - error = nd6_resolve(ifp, LLE_SF(AF_INET6, 0), m, dst, - phdr, &lleflags, plle); + int af = RO_GET_FAMILY(ro, dst); + error = nd6_resolve(ifp, LLE_SF(af, 0), m, dst, phdr, + &lleflags, plle); } else { infiniband_ipv6_multicast_map( &((const struct sockaddr_in6 *)dst)->sin6_addr, @@ -371,7 +372,7 @@ infiniband_output(struct ifnet *ifp, struct mbuf *m, if ((pflags & RT_L2_ME) != 0) { update_mbuf_csumflags(m, m); - return (if_simloop(ifp, m, dst->sa_family, 0)); + return (if_simloop(ifp, m, RO_GET_FAMILY(ro, dst), 0)); } /* diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c index cbff8200806a..643ef2240fe1 100644 --- a/sys/net/if_loop.c +++ b/sys/net/if_loop.c @@ -235,7 +235,7 @@ looutput(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, if (dst->sa_family == AF_UNSPEC || dst->sa_family == pseudo_AF_HDRCMPLT) bcopy(dst->sa_data, &af, sizeof(af)); else - af = dst->sa_family; + af = RO_GET_FAMILY(ro, dst); #if 1 /* XXX */ switch (af) { diff --git a/sys/net/if_me.c b/sys/net/if_me.c index aafc07c2b203..067ab22cd84d 100644 --- a/sys/net/if_me.c +++ b/sys/net/if_me.c @@ -533,14 +533,14 @@ drop: static int me_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, - struct route *ro __unused) + struct route *ro) { uint32_t af; if (dst->sa_family == AF_UNSPEC) bcopy(dst->sa_data, &af, sizeof(af)); else - af = dst->sa_family; + af = RO_GET_FAMILY(ro, dst); m->m_pkthdr.csum_data = af; return (ifp->if_transmit(ifp, m)); } diff --git a/sys/net/if_spppsubr.c b/sys/net/if_spppsubr.c index fbf7b0ea8f4c..804367025532 100644 --- a/sys/net/if_spppsubr.c +++ b/sys/net/if_spppsubr.c @@ -780,6 +780,7 @@ sppp_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, int ipproto = PPP_IP; #endif int debug = ifp->if_flags & IFF_DEBUG; + int af = RO_GET_FAMILY(ro, dst); SPPP_LOCK(sp); @@ -805,7 +806,7 @@ sppp_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, * dialout event in case IPv6 has been * administratively disabled on that interface. */ - if (dst->sa_family == AF_INET6 && + if (af == AF_INET6 && !(sp->confflags & CONF_ENABLE_IPV6)) goto drop; #endif @@ -818,7 +819,7 @@ sppp_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, } #ifdef INET - if (dst->sa_family == AF_INET) { + if (af == AF_INET) { /* XXX Check mbuf length here? */ struct ip *ip = mtod (m, struct ip*); struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); @@ -888,14 +889,14 @@ sppp_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, #endif #ifdef INET6 - if (dst->sa_family == AF_INET6) { + if (af == AF_INET6) { /* XXX do something tricky here? */ } #endif if (sp->pp_mode == PP_FR) { /* Add frame relay header. */ - m = sppp_fr_header (sp, m, dst->sa_family); + m = sppp_fr_header (sp, m, af); if (! m) goto nobufs; goto out; @@ -926,7 +927,7 @@ nobufs: if (debug) h->control = PPP_UI; /* Unnumbered Info */ } - switch (dst->sa_family) { + switch (af) { #ifdef INET case AF_INET: /* Internet Protocol */ if (sp->pp_mode == IFF_CISCO) diff --git a/sys/net/if_tuntap.c b/sys/net/if_tuntap.c index b4b1b77ddc7c..bd9fc811d19f 100644 --- a/sys/net/if_tuntap.c +++ b/sys/net/if_tuntap.c @@ -1402,7 +1402,7 @@ tunoutput(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst, if (dst->sa_family == AF_UNSPEC) bcopy(dst->sa_data, &af, sizeof(af)); else - af = dst->sa_family; + af = RO_GET_FAMILY(ro, dst); if (bpf_peers_present(ifp->if_bpf)) bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m0); diff --git a/sys/net/route.h b/sys/net/route.h index 67217f237e0b..ec77d39b9649 100644 --- a/sys/net/route.h +++ b/sys/net/route.h @@ -394,6 +394,10 @@ struct rt_addrinfo { } \ } while (0) +#define RO_GET_FAMILY(ro, dst) ((ro) != NULL && \ + (ro)->ro_flags & RT_HAS_GW \ + ? (ro)->ro_dst.sa_family : (dst)->sa_family) + /* * Validate a cached route based on a supplied cookie. If there is an * out-of-date cache, simply free it. Update the generation number diff --git a/sys/net/route/route_ctl.c b/sys/net/route/route_ctl.c index a686d1623053..6db088102cd3 100644 --- a/sys/net/route/route_ctl.c +++ b/sys/net/route/route_ctl.c @@ -106,6 +106,14 @@ SYSCTL_UINT(_net_route, OID_AUTO, multipath, _MP_FLAGS | CTLFLAG_VNET, &VNET_NAME(rib_route_multipath), 0, "Enable route multipath"); #undef _MP_FLAGS +#if defined(INET) && defined(INET6) +FEATURE(ipv4_rfc5549_support, "Route IPv4 packets via IPv6 nexthops"); +#define V_rib_route_ipv6_nexthop VNET(rib_route_ipv6_nexthop) +VNET_DEFINE(u_int, rib_route_ipv6_nexthop) = 1; +SYSCTL_UINT(_net_route, OID_AUTO, ipv6_nexthop, CTLFLAG_RW | CTLFLAG_VNET, + &VNET_NAME(rib_route_ipv6_nexthop), 0, "Enable IPv4 route via IPv6 Next Hop address"); +#endif + /* Routing table UMA zone */ VNET_DEFINE_STATIC(uma_zone_t, rtzone); #define V_rtzone VNET(rtzone) @@ -197,6 +205,20 @@ get_rnh(uint32_t fibnum, const struct rt_addrinfo *info) return (rnh); } +#if defined(INET) && defined(INET6) +static bool +rib_can_ipv6_nexthop_address(struct rib_head *rh) +{ + int result; + + CURVNET_SET(rh->rib_vnet); + result = !!V_rib_route_ipv6_nexthop; + CURVNET_RESTORE(); + + return (result); +} +#endif + #ifdef ROUTE_MPATH static bool rib_can_multipath(struct rib_head *rh) @@ -582,7 +604,13 @@ check_gateway(struct rib_head *rnh, struct sockaddr *dst, return (true); else if (gateway->sa_family == AF_LINK) return (true); - return (false); +#if defined(INET) && defined(INET6) + else if (dst->sa_family == AF_INET && gateway->sa_family == AF_INET6 && + rib_can_ipv6_nexthop_address(rnh)) + return (true); +#endif + else + return (false); } /* |
