On Mon, Oct 19, 2020 at 07:16:46PM +1000, David Gwynne wrote:
> On Mon, Oct 19, 2020 at 10:03:29AM +0100, Stuart Henderson wrote:
> > On 2020/10/19 11:47, David Gwynne wrote:
> > > On Sun, Oct 18, 2020 at 08:57:34PM +0100, Stuart Henderson wrote:
> > > > On 2020/10/18 14:04, David Gwynne wrote:
> > > > > 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.
> > > > 
> > > > I ran into this, I just turned on the forwarding sysctl to avoid the
> > > > problem.
> > > > 
> > > > > 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.
> > > > 
> > > > I don't see why loopbacks should be special. Another place this
> > > > might show up is services running on carp addresses (I haven't updated
> > > > those machines yet but there's a fair chance they'll be affected too).
> > > > I would prefer an explicit sysctl to disable "strong host model".
> > > 
> > > loopback is already special. if a packet comes from an loopback
> > > interface, we allow it to talk to any IP on the local machine. i think
> > > this is mostly to cope with the semantic we've had where local traffic
> > > get's tied to a loopback interface instead of going anywhere near the
> > > physical ones.
> > > 
> > > carp is also special.
> > > 
> > > let me paste the ip_laddr function instead of the diff to it, it's a bit
> > > more obvious what's going on:
> > 
> > Thanks, that will already work for the machines I was thinking of then.
> > 
> > > back to loopback and receiving packets. loopback is special because it
> > > is not connected to the outside world. it is impossible to send a packet
> > > via a loopback interface from another host, so configuring a globally
> > > (externally) routable IP on it is currently pointless unless you enable
> > > forwarding. i think making loopback more special and allowing it
> > > to be globally reachable makes sense. i can't think of any downsides to
> > > this at the moment, except that the behaviour would be subtle/not
> > > obvious
> > 
> > ok, so it makes sense for this to be independent of any possible
> > separate lever.
> > 
> > > is there a need to configure a globally reachable IP on a non-loopback
> > > interface on a host (not router)? if so, then i'd be more convinced that
> > > we need a separate lever to pull.
> > 
> > I'm not using it this way, but here's a scenario.
> > 
> > Say there are a couple of webservers with addresses from a carp on
> > ethernet/vlan, with a link to their upstream router on some separate
> > interface. They announce the carp prefix into ospf.
> 
> so carp is just being used to elect a webserver as a master, and then
> the result of that election is fed upstream.
> 
> > They aren't routing themselves so the only reason to have forwarding=1
> > is to have them use "weak host model".
> > 
> > With forwarding=0 I think they'll have to use "stub router no" otherwise
> > everything will be announced high metric (rather than being dependent on
> > carp state), but ospfd explicitly handles this; it's marked in parse.y
> > with "/* allow to force non stub mode */".
> 
> so is a Big Global Lever what you want here? if you enable weak host
> mode, all IPs on the host will be addressible from all legs of the
> host. would it make more sense to configure specific interfaces as
> holding globally addressible IPs?
> 
> if my understanding of your scenario is right, you could configure
> the carp interface with the weak or globally accessible flag. in
> my situation i could configure that on lo1.

such a diff looks like this. it adds a "global" flag that you can set on
interfaces.

Index: sbin/ifconfig/ifconfig.c
===================================================================
RCS file: /cvs/src/sbin/ifconfig/ifconfig.c,v
retrieving revision 1.429
diff -u -p -r1.429 ifconfig.c
--- sbin/ifconfig/ifconfig.c    7 Oct 2020 14:38:54 -0000       1.429
+++ sbin/ifconfig/ifconfig.c    20 Oct 2020 00:12:06 -0000
@@ -468,6 +468,8 @@ const struct        cmd {
        { "-autoconfprivacy",   IFXF_INET6_NOPRIVACY,   0,      setifxflags },
        { "soii",       -IFXF_INET6_NOSOII,     0,      setifxflags },
        { "-soii",      IFXF_INET6_NOSOII,      0,      setifxflags },
+       { "global",     IFXF_GLOBAL,    0,              setifxflags },
+       { "-global",    -IFXF_GLOBAL,   0,              setifxflags },
 #ifndef SMALL
        { "hwfeatures", NEXTARG0,       0,              printifhwfeatures },
        { "metric",     NEXTARG,        0,              setifmetric },
@@ -675,7 +677,7 @@ const struct        cmd {
        "\7RUNNING\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX"    \
        "\15LINK0\16LINK1\17LINK2\20MULTICAST"                          \
        "\23INET6_NOPRIVACY\24MPLS\25WOL\26AUTOCONF6\27INET6_NOSOII"    \
-       "\30AUTOCONF4"
+       "\30AUTOCONF4" "\031GLOBAL"
 
 int    getinfo(struct ifreq *, int);
 void   getsock(int);
Index: sys/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
--- sys/netinet/ip_input.c      22 Aug 2020 17:55:30 -0000      1.351
+++ sys/netinet/ip_input.c      20 Oct 2020 00:12:06 -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_xflags, IFXF_GLOBAL))
+                       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: sys/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
--- sys/netinet/ip_var.h        8 Dec 2019 11:08:22 -0000       1.86
+++ sys/netinet/ip_var.h        20 Oct 2020 00:12:06 -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: sys/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
--- sys/netinet6/ip6_input.c    24 Aug 2020 16:40:07 -0000      1.229
+++ sys/netinet6/ip6_input.c    20 Oct 2020 00:12:06 -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