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

Reply via email to