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);