this is mostly about discussion at the moment, i'm not tied to this diff at all.
the problem i'm hitting is that i have a multihomed box where the service it provides listens on an IP address that's assigned to lo1. it's a host running a service, it's not a router, so the net.inet.ip.forwarding sysctl is not set to 1. because of the checks introduced in src/sys/netinet/ip_input.c r1.345, this doesnt work because a packet has to be received on the interface the IP is assigned to. however, you cannot receive traffic on an lo(4) interface (unless you're connecting from the local host), so the addresses are on lo1 are not globally accessible. i came up with this diff, which adds even more special casing for loopback interfaces. it says addreesses on loopbacks are globally reachable, even if ip forwarding is disabled. is this reasonable? or is there a way i can do this without a diff already? or is there a better diff to support this usecase? eg, would we need a flag on IPs to specify if they're globally accessible or not? also, i don't like the name "ip_laddr" for the function, but couldnt come up with something better. thoughts? for those that are interested, the multihoming is via a bunch of gre(4) interfaces so a set of frontend load balancers can route packets to these backends, even if those backends are not directly connected to the frontends because they're at different sites. Index: netinet/ip_input.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_input.c,v retrieving revision 1.351 diff -u -p -r1.351 ip_input.c --- netinet/ip_input.c 22 Aug 2020 17:55:30 -0000 1.351 +++ netinet/ip_input.c 16 Oct 2020 04:27:43 -0000 @@ -753,29 +753,42 @@ in_ouraddr(struct mbuf *m, struct ifnet break; } } - } else if (ipforwarding == 0 && rt->rt_ifidx != ifp->if_index && - !((ifp->if_flags & IFF_LOOPBACK) || (ifp->if_type == IFT_ENC) || - (m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST))) { - /* received on wrong interface. */ -#if NCARP > 0 - struct ifnet *out_if; + } else if (ipforwarding == 0 && !ip_laddr(ifp, m, rt)) { + ipstat_inc(ips_wrongif); + match = 2; + } + + return (match); +} +int +ip_laddr(struct ifnet *ifp, struct mbuf *m, struct rtentry *rt) +{ + struct ifnet *rtifp; + int match = 0; + + if (rt->rt_ifidx == ifp->if_index || + ifp->if_type == IFT_ENC || + ISSET(ifp->if_flags, IFF_LOOPBACK) || + ISSET(m->m_pkthdr.pf.flags, PF_TAG_TRANSLATE_LOCALHOST)) + return (1); + + /* received on a different interface. */ + rtifp = if_get(rt->rt_ifidx); + if (rtifp != NULL) { + if (ISSET(rtifp->if_flags, IFF_LOOPBACK)) + match = 1; +#if NCARP > 0 /* * Virtual IPs on carp interfaces need to be checked also * against the parent interface and other carp interfaces * sharing the same parent. */ - out_if = if_get(rt->rt_ifidx); - if (!(out_if && carp_strict_addr_chk(out_if, ifp))) { - ipstat_inc(ips_wrongif); - match = 2; - } - if_put(out_if); -#else - ipstat_inc(ips_wrongif); - match = 2; + else if (carp_strict_addr_chk(rtifp, ifp)) + match = 1; #endif } + if_put(rtifp); return (match); } Index: netinet/ip_var.h =================================================================== RCS file: /cvs/src/sys/netinet/ip_var.h,v retrieving revision 1.86 diff -u -p -r1.86 ip_var.h --- netinet/ip_var.h 8 Dec 2019 11:08:22 -0000 1.86 +++ netinet/ip_var.h 16 Oct 2020 04:27:43 -0000 @@ -244,6 +244,7 @@ void ip_savecontrol(struct inpcb *, str void ipintr(void); int ip_input_if(struct mbuf **, int *, int, int, struct ifnet *); int ip_deliver(struct mbuf **, int *, int, int); +int ip_laddr(struct ifnet *, struct mbuf *, struct rtentry *); void ip_forward(struct mbuf *, struct ifnet *, struct rtentry *, int); int rip_ctloutput(int, struct socket *, int, int, struct mbuf *); void rip_init(void); Index: netinet6/ip6_input.c =================================================================== RCS file: /cvs/src/sys/netinet6/ip6_input.c,v retrieving revision 1.229 diff -u -p -r1.229 ip6_input.c --- netinet6/ip6_input.c 24 Aug 2020 16:40:07 -0000 1.229 +++ netinet6/ip6_input.c 16 Oct 2020 04:27:43 -0000 @@ -425,30 +425,9 @@ ip6_input_if(struct mbuf **mp, int *offp if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_LOCAL)) { struct in6_ifaddr *ia6 = ifatoia6(rt->rt_ifa); - if (ip6_forwarding == 0 && rt->rt_ifidx != ifp->if_index && - !((ifp->if_flags & IFF_LOOPBACK) || - (ifp->if_type == IFT_ENC) || - (m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST))) { - /* received on wrong interface */ -#if NCARP > 0 - struct ifnet *out_if; - - /* - * Virtual IPs on carp interfaces need to be checked - * also against the parent interface and other carp - * interfaces sharing the same parent. - */ - out_if = if_get(rt->rt_ifidx); - if (!(out_if && carp_strict_addr_chk(out_if, ifp))) { - ip6stat_inc(ip6s_wrongif); - if_put(out_if); - goto bad; - } - if_put(out_if); -#else + if (ip6_forwarding == 0 && !ip_laddr(ifp, m, rt)) { ip6stat_inc(ip6s_wrongif); goto bad; -#endif } /* * packets to a tentative, duplicated, or somehow invalid