Index: sys/net/route/route_ctl.c =================================================================== --- sys/net/route/route_ctl.c +++ sys/net/route/route_ctl.c @@ -567,6 +567,24 @@ return (error); } +/* + * Checks if @dst and @gateway is valid combination. + * + * Returns true if is valid, false otherwise. + */ +static bool +check_gateway(struct rib_head *rnh, struct sockaddr *dst, + struct sockaddr *gateway) +{ + if (dst->sa_family == gateway->sa_family) + return (true); + else if (gateway->sa_family == AF_UNSPEC) + return (true); + else if (gateway->sa_family == AF_LINK) + return (true); + return (false); +} + /* * Creates rtentry and nexthop based on @info data. * Return 0 and fills in rtentry into @prt on success, @@ -589,8 +607,7 @@ 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)) + if (dst && gateway && !check_gateway(rnh, dst, gateway)) return (EINVAL); if (dst->sa_len > sizeof(((struct rtentry *)NULL)->rt_dstb)) Index: sys/netinet/ip_output.c =================================================================== --- sys/netinet/ip_output.c +++ sys/netinet/ip_output.c @@ -293,9 +293,9 @@ /* rte<>ro_flags translation */ static inline void -rt_update_ro_flags(struct route *ro) +rt_update_ro_flags(struct route *ro, const struct nhop_object *nh) { - int nh_flags = ro->ro_nh->nh_flags; + int nh_flags = nh->nh_flags; ro->ro_flags &= ~ (RT_REJECT|RT_BLACKHOLE|RT_HAS_GW); @@ -495,22 +495,21 @@ goto bad; } } - ia = ifatoia(ro->ro_nh->nh_ifa); - ifp = ro->ro_nh->nh_ifp; - 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; - if (ro->ro_nh->nh_flags & NHF_HOST) - isbroadcast = (ro->ro_nh->nh_flags & NHF_BROADCAST); + struct nhop_object *nh = ro->ro_nh; + + ia = ifatoia(nh->nh_ifa); + ifp = nh->nh_ifp; + counter_u64_add(nh->nh_pksent, 1); + rt_update_ro_flags(ro, nh); + if (nh->nh_flags & NHF_GATEWAY) + gw = &nh->gw4_sa; + if (nh->nh_flags & NHF_HOST) + isbroadcast = (nh->nh_flags & NHF_BROADCAST); else if (ifp->if_flags & IFF_BROADCAST) isbroadcast = in_ifaddr_broadcast(gw->sin_addr, ia); else isbroadcast = 0; - if (ro->ro_nh->nh_flags & NHF_HOST) - mtu = ro->ro_nh->nh_mtu; - else - mtu = ifp->if_mtu; + mtu = nh->nh_mtu; src = IA_SIN(ia)->sin_addr; } else { struct nhop_object *nh;