From: "Nitsche, Elia" Subject: Re: IPv4 route with IPv6 gateway To: "tech@openbsd.org" Cc: "cjeker@diehard.n-r-g.com" , "openbsd@ledeuns.net" Date: Sun, 2 Aug 2026 21:34:29 +0000 Here another go at a diff. This one uses rt->rt_dst directly (with fallback to dst) (because prob. we always want to send a v4 packet to a v4 target address) So no need to change the function header. I tested deleting the arp and ndp caches while pinging or downloading and it seems fine. This also sets the ip source address of icmp messages to 192.0.0.8, if no valid ip was found on the interface. elia Index: net/if.c =================================================================== RCS file: /cvs/src/sys/net/if.c,v diff -u -p -r1.763 if.c --- net/if.c 22 Mar 2026 23:14:00 -0000 1.763 +++ net/if.c 2 Aug 2026 15:30:46 -0000 @@ -928,8 +928,13 @@ if_output_tso(struct ifnet *ifp, struct { uint32_t ifcap; int error; + sa_family_t af; + if (rt != NULL) + af = rt_key(rt)->sa_family; + else + af = dst->sa_family; - switch (dst->sa_family) { + switch (af) { case AF_INET: ifcap = IFCAP_TSOv4; break; @@ -953,7 +958,10 @@ if_output_tso(struct ifnet *ifp, struct return error; if ((*mp)->m_pkthdr.len <= mtu) { + /* switch (dst->sa_family) { + */ + switch (af) { //dev case AF_INET: in_hdr_cksum_out(*mp, ifp); in_proto_cksum_out(*mp, ifp); Index: net/if_ethersubr.c =================================================================== RCS file: /cvs/src/sys/net/if_ethersubr.c,v diff -u -p -r1.308 if_ethersubr.c --- net/if_ethersubr.c 19 Dec 2025 02:04:13 -0000 1.308 +++ net/if_ethersubr.c 2 Aug 2026 15:30:46 -0000 @@ -220,9 +220,15 @@ ether_resolve(struct ifnet *ifp, struct struct rtentry *rt, struct ether_header *eh) { struct arpcom *ac = (struct arpcom *)ifp; - sa_family_t af = dst->sa_family; int error = 0; + sa_family_t af; + if (rt != NULL) + af = rt_key(rt)->sa_family; + else + // fallback + af = dst->sa_family; + if (!ISSET(ifp->if_flags, IFF_RUNNING)) senderr(ENETDOWN); @@ -236,13 +242,25 @@ ether_resolve(struct ifnet *ifp, struct ifp->if_rdomain, rtable_l2(m->m_pkthdr.ph_rtableid)); } #endif - + + /* packet type depends on af of rt->rt_dst (this might get overwritten later) */ switch (af) { case AF_INET: + eh->ether_type = htons(ETHERTYPE_IP); + break; +#ifdef INET6 + case AF_INET6: + eh->ether_type = htons(ETHERTYPE_IPV6); + break; +#endif + } + + /* resolve LL depending on the af of dst */ + switch (dst->sa_family) { + case AF_INET: error = arpresolve(ifp, rt, m, dst, eh->ether_dhost); if (error) return (error); - eh->ether_type = htons(ETHERTYPE_IP); /* * If broadcasting on a simplex interface, loopback a copy. @@ -265,7 +283,6 @@ ether_resolve(struct ifnet *ifp, struct error = nd6_resolve(ifp, rt, m, dst, eh->ether_dhost); if (error) return (error); - eh->ether_type = htons(ETHERTYPE_IPV6); break; #endif #ifdef MPLS Index: netinet/in.h =================================================================== RCS file: /cvs/src/sys/netinet/in.h,v diff -u -p -r1.149 in.h --- netinet/in.h 2 Mar 2025 21:28:32 -0000 1.149 +++ netinet/in.h 2 Aug 2026 21:19:18 -0000 @@ -237,6 +237,7 @@ struct in_addr { #endif /* _KERNEL */ #define INADDR_ANY __IPADDR(0x00000000) #define INADDR_LOOPBACK __IPADDR(0x7f000001) +#define INADDR_DUMMY __IPADDR(0xc0000008) /* 192.0.0.8 (RFC 7600) */ #define INADDR_BROADCAST __IPADDR(0xffffffff) /* must be masked */ #ifndef _KERNEL Index: netinet/ip_output.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_output.c,v diff -u -p -r1.419 ip_output.c --- netinet/ip_output.c 17 Jul 2026 18:51:29 -0000 1.419 +++ netinet/ip_output.c 2 Aug 2026 21:19:19 -0000 @@ -218,6 +218,10 @@ reroute: /* Set the source IP address */ if (ip->ip_src.s_addr == INADDR_ANY && ia) ip->ip_src = ia->ia_addr.sin_addr; + /* if ia has not set an address */ + if (ip->ip_src.s_addr == INADDR_ANY) { //dev + ip->ip_src.s_addr = INADDR_DUMMY; + } } #ifdef IPSEC