'route sourceaddr' support is incomplete.

In particular it does not work in ping or traceroute.

The original idea of this option is to replace the default src address
allocation algorithm, with a static default, particularily on routers.
It is only working for non-bound sockets, but it should also work for
SOCK_RAW or potentially other configurations.

I believe this was implimented too cynically, as a "oh we only need to
fix these few cases", but we are better off applying the replacement
algorithm for all unbound cases, then there is only algorithm A or B,
not a mix of algorithms depending on the type of socket being used.

It is really fun when you realize ping -v uses a dummy connect() to
figure out a srcaddr to print, then the kernel chooses a different
address for the sent packets.

Alexander Bluhm <alexander.bl...@gmx.net> wrote:

> On Thu, Dec 16, 2021 at 07:20:04PM +0100, Denis Fondras wrote:
> > Raw sockets do not comply with route sourceaddr.
> > 
> > Use set address if source is not set by the caller.
> 
> Which problem do you want to solve?
> Which setups do you break?
> 
> bluhm
> 
> > Index: netinet/ip_output.c
> > ===================================================================
> > RCS file: /cvs/src/sys/netinet/ip_output.c,v
> > retrieving revision 1.377
> > diff -u -p -r1.377 ip_output.c
> > --- netinet/ip_output.c     3 Dec 2021 17:18:34 -0000       1.377
> > +++ netinet/ip_output.c     16 Dec 2021 18:12:44 -0000
> > @@ -110,6 +110,7 @@ ip_output(struct mbuf *m, struct mbuf *o
> >     struct route iproute;
> >     struct sockaddr_in *dst;
> >     struct tdb *tdb = NULL;
> > +   struct sockaddr *ip4_source = NULL;
> >     u_long mtu;
> >  #if NPF > 0
> >     u_int orig_rtableid;
> > @@ -237,8 +238,18 @@ reroute:
> >                     dst = satosin(ro->ro_rt->rt_gateway);
> >  
> >             /* Set the source IP address */
> > -           if (ip->ip_src.s_addr == INADDR_ANY && ia)
> > -                   ip->ip_src = ia->ia_addr.sin_addr;
> > +           if (ip->ip_src.s_addr == INADDR_ANY && ia) {
> > +                   ip4_source = rtable_getsource(ro->ro_tableid, AF_INET);
> > +                   if (ip4_source != NULL) {
> > +                           struct ifaddr *ifa;
> > +                           if ((ifa = ifa_ifwithaddr(ip4_source,
> > +                               ro->ro_tableid)) != NULL &&
> > +                               ISSET(ifa->ifa_ifp->if_flags, IFF_UP)) {
> > +                                   ip->ip_src = 
> > satosin(ip4_source)->sin_addr;
> > +                           }
> > +                   } else
> > +                           ip->ip_src = ia->ia_addr.sin_addr;
> > +           }
> >     }
> >  
> >  #ifdef IPSEC
> 

Reply via email to