Page MenuHomeFreeBSD

D30398.id90724.diff
No OneTemporary

D30398.id90724.diff

diff --git a/sys/contrib/dpdk_rte_lpm/dpdk_lpm.c b/sys/contrib/dpdk_rte_lpm/dpdk_lpm.c
--- a/sys/contrib/dpdk_rte_lpm/dpdk_lpm.c
+++ b/sys/contrib/dpdk_rte_lpm/dpdk_lpm.c
@@ -141,6 +141,7 @@
rt = fib4_lookup_rt(dd->fibnum, addr, 0, NHR_UNLOCKED, &rnd);
if (rt != NULL) {
+ /* FIXME check gw_sa.sa_family */
struct in_addr addr4;
uint32_t scopeid;
int inet_plen;
diff --git a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c
--- a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c
+++ b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c
@@ -689,7 +689,9 @@
register struct mbuf *m = *mpp;
int len, off, error = 0, hlen, code;
struct ifnet *ifp, *sifp;
- struct sockaddr_in dst;
+ struct route ro;
+ struct sockaddr_in *dst;
+ const struct sockaddr *gw;
struct nhop_object *nh;
u_long fibnum = 0;
u_short ip_off;
@@ -739,10 +741,12 @@
/*
* Route packet.
*/
- bzero(&dst, sizeof (dst));
- dst.sin_family = AF_INET;
- dst.sin_addr = ip->ip_dst;
- dst.sin_len = sizeof(dst);
+ bzero(&ro, sizeof (ro));
+ dst = (struct sockaddr_in *)&ro.ro_dst;
+ dst->sin_family = AF_INET;
+ dst->sin_addr = ip->ip_dst;
+ dst->sin_len = sizeof(dst);
+ gw = (const struct sockaddr *)dst;
fr = fin->fin_fr;
if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) &&
@@ -762,11 +766,11 @@
}
if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0))
- dst.sin_addr = fdp->fd_ip;
+ dst->sin_addr = fdp->fd_ip;
fibnum = M_GETFIB(m0);
NET_EPOCH_ASSERT();
- nh = fib4_lookup(fibnum, dst.sin_addr, 0, NHR_NONE, 0);
+ nh = fib4_lookup(fibnum, dst->sin_addr, 0, NHR_NONE, 0);
if (nh == NULL) {
if (in_localaddr(ip->ip_dst))
error = EHOSTUNREACH;
@@ -777,8 +781,10 @@
if (ifp == NULL)
ifp = nh->nh_ifp;
- if (nh->nh_flags & NHF_GATEWAY)
- dst.sin_addr = nh->gw4_sa.sin_addr;
+ if (nh->nh_flags & NHF_GATEWAY) {
+ gw = &nh->gw_sa;
+ ro.ro_flags |= RT_HAS_GW;
+ }
/*
* For input packets which are being "fastrouted", they won't
@@ -822,9 +828,8 @@
if (ntohs(ip->ip_len) <= ifp->if_mtu) {
if (!ip->ip_sum)
ip->ip_sum = in_cksum(m, hlen);
- error = (*ifp->if_output)(ifp, m, (struct sockaddr *)&dst,
- NULL
- );
+ /* FIXME pass &ro conditionally ? */
+ error = (*ifp->if_output)(ifp, m, gw, &ro);
goto done;
}
/*
@@ -904,10 +909,7 @@
m0 = m->m_act;
m->m_act = 0;
if (error == 0)
- error = (*ifp->if_output)(ifp, m,
- (struct sockaddr *)&dst,
- NULL
- );
+ error = (*ifp->if_output)(ifp, m, gw, &ro);
else
FREE_MB_T(m);
}
diff --git a/sys/dev/cxgbe/tom/t4_listen.c b/sys/dev/cxgbe/tom/t4_listen.c
--- a/sys/dev/cxgbe/tom/t4_listen.c
+++ b/sys/dev/cxgbe/tom/t4_listen.c
@@ -1100,7 +1100,14 @@
if (nh->nh_ifp != ifp)
return (NULL);
if (nh->nh_flags & NHF_GATEWAY)
- ((struct sockaddr_in6 *)dst)->sin6_addr = nh->gw6_sa.sin6_addr;
+ /* FIXME check nh->gw_sa.sa_family */
+ if (nh->gw_sa.sa_family == AF_INET6)
+ ((struct sockaddr_in6 *)dst)->sin6_addr = nh->gw6_sa.sin6_addr;
+ else {
+ dst->sa_len = sizeof(struct sockaddr_in);
+ dst->sa_family = AF_INET;
+ ((struct sockaddr_in *)dst)->sin_addr = nh->gw4_sa.sin_addr;
+ }
else
((struct sockaddr_in6 *)dst)->sin6_addr = inc->inc6_faddr;
} else {
@@ -1113,7 +1120,15 @@
if (nh->nh_ifp != ifp)
return (NULL);
if (nh->nh_flags & NHF_GATEWAY)
- ((struct sockaddr_in *)dst)->sin_addr = nh->gw4_sa.sin_addr;
+ /* FIXME check nh->gw_sa.sa_family */
+ if (nh->gw_sa.sa_family == AF_INET)
+ ((struct sockaddr_in *)dst)->sin_addr = nh->gw4_sa.sin_addr;
+ else {
+ bzero(dst, sizeof(struct sockaddr_in6));
+ dst->sa_len = sizeof(struct sockaddr_in6);
+ dst->sa_family = AF_INET6;
+ ((struct sockaddr_in6 *)dst)->sin6_addr = nh->gw6_sa.sin6_addr;
+ }
else
((struct sockaddr_in *)dst)->sin_addr = inc->inc_faddr;
}
diff --git a/sys/dev/iicbus/if_ic.c b/sys/dev/iicbus/if_ic.c
--- a/sys/dev/iicbus/if_ic.c
+++ b/sys/dev/iicbus/if_ic.c
@@ -371,6 +371,8 @@
/* BPF writes need to be handled specially. */
if (dst->sa_family == AF_UNSPEC)
bcopy(dst->sa_data, &hdr, sizeof(hdr));
+ else if (ro != NULL && ro->ro_flags & RT_HAS_GW)
+ hdr = ro->ro_dst.sa_family;
else
hdr = dst->sa_family;
diff --git a/sys/net/debugnet.c b/sys/net/debugnet.c
--- a/sys/net/debugnet.c
+++ b/sys/net/debugnet.c
@@ -673,6 +673,7 @@
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
--- a/sys/net/if_disc.c
+++ b/sys/net/if_disc.c
@@ -184,6 +184,8 @@
/* BPF writes need to be handled specially. */
if (dst->sa_family == AF_UNSPEC)
bcopy(dst->sa_data, &af, sizeof(af));
+ else if (ro != NULL && ro->ro_flags & RT_HAS_GW)
+ af = ro->ro_dst.sa_family;
else
af = dst->sa_family;
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -289,6 +289,7 @@
uint32_t pflags;
struct llentry *lle = NULL;
int addref = 0;
+ int af = dst->sa_family;
phdr = NULL;
pflags = 0;
@@ -323,6 +324,8 @@
pflags = lle->r_flags;
}
}
+ if ((ro->ro_flags & RT_HAS_GW) != 0)
+ af = ro->ro_dst.sa_family;
}
#ifdef MAC
@@ -352,7 +355,7 @@
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, af, 0));
}
loop_copy = (pflags & RT_MAY_LOOP) != 0;
@@ -370,6 +373,20 @@
if ((pflags & RT_HAS_HEADER) == 0) {
eh = mtod(m, struct ether_header *);
memcpy(eh, phdr, hlen);
+ /* XXX phdr might be from lle cache, let's fix the ether_type */
+#if defined(INET) || defined(INET6)
+ uint16_t etype = 0;
+#ifdef INET
+ if (af == AF_INET)
+ etype = htons(ETHERTYPE_IP);
+#endif
+#ifdef INET6
+ if (af == AF_INET6)
+ etype = htons(ETHERTYPE_IPV6);
+#endif
+ if (etype != 0)
+ memcpy(&eh->ether_type, &etype, sizeof(etype));
+#endif
}
/*
@@ -399,7 +416,7 @@
*/
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, af, hlen);
} else
if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
}
diff --git a/sys/net/if_fwsubr.c b/sys/net/if_fwsubr.c
--- a/sys/net/if_fwsubr.c
+++ b/sys/net/if_fwsubr.c
@@ -94,6 +94,7 @@
#if defined(INET) || defined(INET6)
int is_gw = 0;
#endif
+ int af = dst->sa_family;
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
@@ -110,6 +111,8 @@
#if defined(INET) || defined(INET6)
if (ro != NULL)
is_gw = (ro->ro_flags & RT_HAS_GW) != 0;
+ if (is_gw)
+ af = ro->ro_dst.sa_family;
#endif
/*
* For unicast, we make a tag to store the lladdr of the
@@ -137,6 +140,26 @@
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 +174,6 @@
if (error)
return (error == EWOULDBLOCK ? 0 : error);
}
- type = ETHERTYPE_IP;
break;
case AF_ARP:
@@ -159,7 +181,6 @@
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);
@@ -181,7 +202,6 @@
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
--- a/sys/net/if_gif.c
+++ b/sys/net/if_gif.c
@@ -408,6 +408,8 @@
if (dst->sa_family == AF_UNSPEC)
bcopy(dst->sa_data, &af, sizeof(af));
+ else if (ro != NULL && ro->ro_flags & RT_HAS_GW)
+ af = ro->ro_dst.sa_family;
else
af = dst->sa_family;
/*
diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c
--- a/sys/net/if_gre.c
+++ b/sys/net/if_gre.c
@@ -612,6 +612,8 @@
if (dst->sa_family == AF_UNSPEC)
bcopy(dst->sa_data, &af, sizeof(af));
+ else if (ro != NULL && ro->ro_flags & RT_HAS_GW)
+ af = ro->ro_dst.sa_family;
else
af = dst->sa_family;
/*
diff --git a/sys/net/if_infiniband.c b/sys/net/if_infiniband.c
--- a/sys/net/if_infiniband.c
+++ b/sys/net/if_infiniband.c
@@ -300,6 +300,7 @@
int hlen; /* link layer header length */
uint32_t pflags;
bool addref;
+ int af = dst->sa_family;
NET_EPOCH_ASSERT();
@@ -337,6 +338,8 @@
pflags = lle->r_flags;
}
}
+ if ((ro->ro_flags & RT_HAS_GW) != 0)
+ af = ro->ro_dst.sa_family;
}
#ifdef MAC
@@ -370,7 +373,7 @@
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, af, 0));
}
/*
@@ -385,6 +388,20 @@
if ((pflags & RT_HAS_HEADER) == 0) {
ih = mtod(m, struct infiniband_header *);
memcpy(ih, phdr, hlen);
+ /* XXX phdr might be from lle cache, let's fix the ether_type */
+#if defined(INET) || defined(INET6)
+ uint16_t etype = 0;
+#ifdef INET
+ if (af == AF_INET)
+ etype = htons(ETHERTYPE_IP);
+#endif
+#ifdef INET6
+ if (af == AF_INET6)
+ etype = htons(ETHERTYPE_IPV6);
+#endif
+ if (etype != 0)
+ ih->ib_protocol = etype;
+#endif
}
/*
diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c
--- a/sys/net/if_loop.c
+++ b/sys/net/if_loop.c
@@ -234,6 +234,8 @@
/* BPF writes need to be handled specially. */
if (dst->sa_family == AF_UNSPEC || dst->sa_family == pseudo_AF_HDRCMPLT)
bcopy(dst->sa_data, &af, sizeof(af));
+ else if (ro != NULL && ro->ro_flags & RT_HAS_GW)
+ af = ro->ro_dst.sa_family;
else
af = dst->sa_family;
diff --git a/sys/net/if_me.c b/sys/net/if_me.c
--- a/sys/net/if_me.c
+++ b/sys/net/if_me.c
@@ -533,12 +533,14 @@
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 if (ro != NULL && ro->ro_flags & RT_HAS_GW)
+ af = ro->ro_dst.sa_family;
else
af = dst->sa_family;
m->m_pkthdr.csum_data = af;
diff --git a/sys/net/if_spppsubr.c b/sys/net/if_spppsubr.c
--- a/sys/net/if_spppsubr.c
+++ b/sys/net/if_spppsubr.c
@@ -805,6 +805,7 @@
* dialout event in case IPv6 has been
* administratively disabled on that interface.
*/
+ /* FIXME get af from ro->ro_dst ??? */
if (dst->sa_family == AF_INET6 &&
!(sp->confflags & CONF_ENABLE_IPV6))
goto drop;
diff --git a/sys/net/if_stf.c b/sys/net/if_stf.c
--- a/sys/net/if_stf.c
+++ b/sys/net/if_stf.c
@@ -427,6 +427,7 @@
#endif
sc = ifp->if_softc;
+ /* FIXME possible sockaddr_in gw ? */
dst6 = (const struct sockaddr_in6 *)dst;
/* just in case */
diff --git a/sys/net/if_tuntap.c b/sys/net/if_tuntap.c
--- a/sys/net/if_tuntap.c
+++ b/sys/net/if_tuntap.c
@@ -1401,6 +1401,9 @@
/* BPF writes need to be handled specially. */
if (dst->sa_family == AF_UNSPEC)
bcopy(dst->sa_data, &af, sizeof(af));
+ /* FIXME TUN is p-t-p device */
+ else if (ro != NULL && ro->ro_flags & RT_HAS_GW)
+ af = ro->ro_dst.sa_family;
else
af = dst->sa_family;
diff --git a/sys/net/route/route_ctl.c b/sys/net/route/route_ctl.c
--- a/sys/net/route/route_ctl.c
+++ b/sys/net/route/route_ctl.c
@@ -106,6 +106,18 @@
&VNET_NAME(rib_route_multipath), 0, "Enable route multipath");
#undef _MP_FLAGS
+/*
+#define V_rib_route_ipv4_nexthop VNET(rib_route_ipv4_nexthop)
+VNET_DEFINE(u_int, rib_route_ipv4_nexthop) = 1;
+SYSCTL_UINT(_net_route, OID_AUTO, ipv4_nexthop, CTLFLAG_RW | CTLFLAG_VNET,
+ &VNET_NAME(rib_route_ipv4_nexthop), 0, "Enable IPv6 route via IPv4 Next Hop address");
+*/
+
+#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");
+
/* Routing table UMA zone */
VNET_DEFINE_STATIC(uma_zone_t, rtzone);
#define V_rtzone VNET(rtzone)
@@ -197,6 +209,32 @@
return (rnh);
}
+/*
+static bool
+rib_can_ipv4_nexthop_address(struct rib_head *rh)
+{
+ int result;
+
+ CURVNET_SET(rh->rib_vnet);
+ result = !!V_rib_route_ipv4_nexthop;
+ CURVNET_RESTORE();
+
+ return (result);
+}
+*/
+
+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);
+}
+
#ifdef ROUTE_MPATH
static bool
rib_can_multipath(struct rib_head *rh)
@@ -590,8 +628,16 @@
if ((flags & RTF_GATEWAY) && !gateway)
return (EINVAL);
if (dst && gateway && (dst->sa_family != gateway->sa_family) &&
- (gateway->sa_family != AF_UNSPEC) && (gateway->sa_family != AF_LINK))
- return (EINVAL);
+ (gateway->sa_family != AF_UNSPEC) && (gateway->sa_family != AF_LINK)) {
+ if (dst->sa_family == AF_INET
+ && gateway->sa_family == AF_INET6
+ && rib_can_ipv6_nexthop_address(rnh)) {
+ } /* else if (dst->sa_family == AF_INET6
+ && gateway->sa_family == AF_INET
+ && !rib_can_ipv4_nexthop_address(rnh)) {
+ } */ else
+ return (EINVAL);
+ }
if (dst->sa_len > sizeof(((struct rtentry *)NULL)->rt_dstb))
return (EINVAL);
diff --git a/sys/netgraph/netflow/netflow.c b/sys/netgraph/netflow/netflow.c
--- a/sys/netgraph/netflow/netflow.c
+++ b/sys/netgraph/netflow/netflow.c
@@ -364,6 +364,7 @@
fle->f.fle_o_ifx = nh->nh_ifp->if_index;
if (nh->gw_sa.sa_family == AF_INET)
fle->f.next_hop = nh->gw4_sa.sin_addr;
+ /* FIXME nh->gw_sa.sa_family == AF_INET6 */
fle->f.dst_mask = plen;
}
}
@@ -381,6 +382,7 @@
rt_get_inet_prefix_plen(rt, &addr, &plen, &scopeid);
fle->f.src_mask = plen;
+ /* FIXME nh->gw_sa.sa_family == AF_INET6 */
}
}
diff --git a/sys/netgraph/ng_iface.c b/sys/netgraph/ng_iface.c
--- a/sys/netgraph/ng_iface.c
+++ b/sys/netgraph/ng_iface.c
@@ -370,6 +370,8 @@
/* BPF writes need to be handled specially. */
if (dst->sa_family == AF_UNSPEC)
bcopy(dst->sa_data, &af, sizeof(af));
+ else if (ro != NULL && ro->ro_flags & RT_HAS_GW)
+ af = ro->ro_dst.sa_family;
else
af = dst->sa_family;
diff --git a/sys/netinet/in_fib_dxr.c b/sys/netinet/in_fib_dxr.c
--- a/sys/netinet/in_fib_dxr.c
+++ b/sys/netinet/in_fib_dxr.c
@@ -338,6 +338,7 @@
rt = fib4_lookup_rt(da->fibnum, da->dst.sin_addr, 0, NHR_UNLOCKED,
&rnd);
if (rt != NULL) {
+ /* FIXME check gw_sa.sa_family ? */
struct in_addr addr;
uint32_t scopeid;
diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c
--- a/sys/netinet/ip_fastfwd.c
+++ b/sys/netinet/ip_fastfwd.c
@@ -199,7 +199,9 @@
struct ip *ip;
struct mbuf *m0 = NULL;
struct nhop_object *nh = NULL;
- struct sockaddr_in dst;
+ struct route ro;
+ struct sockaddr_in *dst;
+ const struct sockaddr *gw;
struct in_addr dest, odest, rtdest;
uint16_t ip_len, ip_off;
int error = 0;
@@ -421,19 +423,23 @@
ip_len = ntohs(ip->ip_len);
ip_off = ntohs(ip->ip_off);
- bzero(&dst, sizeof(dst));
- dst.sin_family = AF_INET;
- dst.sin_len = sizeof(dst);
- if (nh->nh_flags & NHF_GATEWAY)
- dst.sin_addr = nh->gw4_sa.sin_addr;
- else
- dst.sin_addr = dest;
+ bzero(&ro, sizeof(ro));
+ dst = (struct sockaddr_in *)&ro.ro_dst;
+ dst->sin_family = AF_INET;
+ dst->sin_len = sizeof(*dst);
+ dst->sin_addr = dest;
+ if (nh->nh_flags & NHF_GATEWAY) {
+ ro.ro_flags |= RT_HAS_GW;
+ gw = &nh->gw_sa;
+ } else
+ gw = (const struct sockaddr *)dst;
/*
* Handle redirect case.
*/
redest.s_addr = 0;
- if (V_ipsendredirects && (nh->nh_ifp == m->m_pkthdr.rcvif))
+ if (V_ipsendredirects && (nh->nh_ifp == m->m_pkthdr.rcvif) &&
+ gw->sa_family == AF_INET)
mcopy = ip_redir_alloc(m, nh, ip, &redest.s_addr);
/*
@@ -448,8 +454,8 @@
* Send off the packet via outgoing interface
*/
IP_PROBE(send, NULL, NULL, ip, nh->nh_ifp, ip, NULL);
- error = (*nh->nh_ifp->if_output)(nh->nh_ifp, m,
- (struct sockaddr *)&dst, NULL);
+ /* FIXME pass &ro conditionally ? only when RT_HAS_GW */
+ error = (*nh->nh_ifp->if_output)(nh->nh_ifp, m, gw, &ro);
} else {
/*
* Handle EMSGSIZE with icmp reply needfrag for TCP MTU discovery
@@ -484,7 +490,7 @@
mtod(m, struct ip *), nh->nh_ifp,
mtod(m, struct ip *), NULL);
error = (*nh->nh_ifp->if_output)(nh->nh_ifp, m,
- (struct sockaddr *)&dst, NULL);
+ gw, &ro);
if (error)
break;
} while ((m = m0) != NULL);
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -1065,13 +1065,17 @@
if (nh_ia != NULL &&
(src & nh_ia->ia_subnetmask) == nh_ia->ia_subnet) {
- if (nh->nh_flags & NHF_GATEWAY)
- dest.s_addr = nh->gw4_sa.sin_addr.s_addr;
- else
- dest.s_addr = ip->ip_dst.s_addr;
/* Router requirements says to only send host redirects */
type = ICMP_REDIRECT;
code = ICMP_REDIRECT_HOST;
+
+ if (nh->nh_flags & NHF_GATEWAY) {
+ if (nh->gw_sa.sa_family == AF_INET)
+ dest.s_addr = nh->gw4_sa.sin_addr.s_addr;
+ else /* Do not redirect in case gw is AF_INET6 */
+ type = 0;
+ } else
+ dest.s_addr = ip->ip_dst.s_addr;
}
}
}
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -212,7 +212,7 @@
static int
ip_output_send(struct inpcb *inp, struct ifnet *ifp, struct mbuf *m,
- const struct sockaddr_in *gw, struct route *ro, bool stamp_tag)
+ const struct sockaddr *gw, struct route *ro, bool stamp_tag)
{
#ifdef KERN_TLS
struct ktls_session *tls = NULL;
@@ -273,7 +273,7 @@
m->m_pkthdr.csum_flags |= CSUM_SND_TAG;
}
- error = (*ifp->if_output)(ifp, m, (const struct sockaddr *)gw, ro);
+ error = (*ifp->if_output)(ifp, m, gw, ro);
done:
/* Check for route change invalidating send tags. */
@@ -329,12 +329,13 @@
int mtu = 0;
int error = 0;
int vlan_pcp = -1;
- struct sockaddr_in *dst, sin;
- const struct sockaddr_in *gw;
+ struct sockaddr_in *dst;
+ const struct sockaddr *gw;
struct in_ifaddr *ia = NULL;
struct in_addr src;
int isbroadcast;
uint16_t ip_len, ip_off;
+ struct route iproute;
uint32_t fibnum;
#if defined(IPSEC) || defined(IPSEC_SUPPORT)
int no_route_but_check_spd = 0;
@@ -386,23 +387,23 @@
* therefore we need restore gw if we're redoing lookup.
*/
fibnum = (inp != NULL) ? inp->inp_inc.inc_fibnum : M_GETFIB(m);
- if (ro != NULL)
- dst = (struct sockaddr_in *)&ro->ro_dst;
- else
- dst = &sin;
- if (ro == NULL || ro->ro_nh == NULL) {
- bzero(dst, sizeof(*dst));
+ if (ro == NULL) {
+ ro = &iproute;
+ bzero(ro, sizeof (*ro));
+ }
+ dst = (struct sockaddr_in *)&ro->ro_dst;
+ if (ro->ro_nh == NULL) {
dst->sin_family = AF_INET;
dst->sin_len = sizeof(*dst);
dst->sin_addr = ip->ip_dst;
}
- gw = dst;
+ gw = (const struct sockaddr *)dst;
again:
/*
* Validate route against routing table additions;
* a better/more specific route might have been added.
*/
- if (inp != NULL && ro != NULL && ro->ro_nh != NULL)
+ if (inp != NULL && ro->ro_nh != NULL)
NH_VALIDATE(ro, &inp->inp_rt_cookie, fibnum);
/*
* If there is a cached route,
@@ -412,7 +413,7 @@
* cache with IPv6.
* Also check whether routing cache needs invalidation.
*/
- if (ro != NULL && ro->ro_nh != NULL &&
+ if (ro->ro_nh != NULL &&
((!NH_IS_VALID(ro->ro_nh)) || dst->sin_family != AF_INET ||
dst->sin_addr.s_addr != ip->ip_dst.s_addr))
RO_INVALIDATE_CACHE(ro);
@@ -469,7 +470,7 @@
src = IA_SIN(ia)->sin_addr;
else
src.s_addr = INADDR_ANY;
- } else if (ro != NULL) {
+ } else if (ro != &iproute) {
if (ro->ro_nh == NULL) {
/*
* We want to do any cloning requested by the link
@@ -500,11 +501,11 @@
counter_u64_add(ro->ro_nh->nh_pksent, 1);
rt_update_ro_flags(ro);
if (ro->ro_nh->nh_flags & NHF_GATEWAY)
- gw = &ro->ro_nh->gw4_sa;
+ gw = &ro->ro_nh->gw_sa;
if (ro->ro_nh->nh_flags & NHF_HOST)
isbroadcast = (ro->ro_nh->nh_flags & NHF_BROADCAST);
- else if (ifp->if_flags & IFF_BROADCAST)
- isbroadcast = in_ifaddr_broadcast(gw->sin_addr, ia);
+ else if ((ifp->if_flags & IFF_BROADCAST) && (gw->sa_family == AF_INET))
+ isbroadcast = in_ifaddr_broadcast(((const struct sockaddr_in *)gw)->sin_addr, ia);
else
isbroadcast = 0;
if (ro->ro_nh->nh_flags & NHF_HOST)
@@ -532,6 +533,9 @@
}
ifp = nh->nh_ifp;
mtu = nh->nh_mtu;
+ ro->ro_nh = nh;
+ rt_update_ro_flags(ro);
+ ro->ro_nh = NULL;
/*
* We are rewriting here dst to be gw actually, contradicting
* comment at the beginning of the function. However, in this
@@ -539,15 +543,15 @@
* In case if pfil(9) sends us back to beginning of the
* function, the dst would be rewritten by ip_output_pfil().
*/
- MPASS(dst == &sin);
if (nh->nh_flags & NHF_GATEWAY)
- dst->sin_addr = nh->gw4_sa.sin_addr;
+ gw = &nh->gw_sa;
ia = ifatoia(nh->nh_ifa);
src = IA_SIN(ia)->sin_addr;
isbroadcast = (((nh->nh_flags & (NHF_HOST | NHF_BROADCAST)) ==
(NHF_HOST | NHF_BROADCAST)) ||
((ifp->if_flags & IFF_BROADCAST) &&
- in_ifaddr_broadcast(dst->sin_addr, ia)));
+ (gw->sa_family == AF_INET) &&
+ in_ifaddr_broadcast(((const struct sockaddr_in *)gw)->sin_addr, ia)));
}
/* Catch a possible divide by zero later. */
@@ -562,7 +566,7 @@
* still points to the address in "ro". (It may have been
* changed to point to a gateway address, above.)
*/
- gw = dst;
+ gw = (const struct sockaddr *)dst;
/*
* See if the caller provided any multicast options
*/
@@ -722,7 +726,7 @@
RO_NHFREE(ro);
ro->ro_prepend = NULL;
}
- gw = dst;
+ gw = (const struct sockaddr *)dst;
ip = mtod(m, struct ip *);
goto again;
}
diff --git a/sys/netpfil/ipfw/ip_fw_table_algo.c b/sys/netpfil/ipfw/ip_fw_table_algo.c
--- a/sys/netpfil/ipfw/ip_fw_table_algo.c
+++ b/sys/netpfil/ipfw/ip_fw_table_algo.c
@@ -3914,6 +3914,7 @@
#ifdef INET
if (family == AF_INET) {
+ /* FIXME rt is IPv6 nexthop ? */
rt_get_inet_prefix_plen(rt, &tent->k.addr, &plen, &scopeid);
tent->masklen = plen;
tent->subtype = AF_INET;
@@ -3922,6 +3923,7 @@
#endif
#ifdef INET6
if (family == AF_INET6) {
+ /* FIXME rt is IPv4 nexthop ? */
rt_get_inet6_prefix_plen(rt, &tent->k.addr6, &plen, &scopeid);
tent->masklen = plen;
tent->subtype = AF_INET6;
diff --git a/sys/ofed/drivers/infiniband/core/ib_addr.c b/sys/ofed/drivers/infiniband/core/ib_addr.c
--- a/sys/ofed/drivers/infiniband/core/ib_addr.c
+++ b/sys/ofed/drivers/infiniband/core/ib_addr.c
@@ -396,6 +396,7 @@
} else {
bool is_gw = (nh->nh_flags & NHF_GATEWAY) != 0;
memset(edst, 0, MAX_ADDR_LEN);
+ /* FIXME should check nh->gw_sa.sa_family */
error = arpresolve(ifp, is_gw, NULL, is_gw ?
&nh->gw_sa : (const struct sockaddr *)&dst_tmp,
edst, NULL, NULL);

File Metadata

Mime Type
text/plain
Expires
Fri, May 22, 1:42 PM (17 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33421935
Default Alt Text
D30398.id90724.diff (22 KB)

Event Timeline