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