On Sat, Mar 19, 2022 at 10:57:18PM +1000, David Gwynne wrote:
> On Sat, Mar 19, 2022 at 12:53:54PM +0100, Claudio Jeker wrote:
> > On Sat, Mar 19, 2022 at 12:27:43PM +0100, Claudio Jeker wrote:
> > > On Sat, Mar 19, 2022 at 10:51:13AM +0000, Stuart Henderson wrote:
> > > > On 2022/03/19 19:14, David Gwynne wrote:
> > > > > On Thu, Mar 17, 2022 at 12:05:16PM -0600, Theo de Raadt wrote:
> > > > > > This should not be done in applications.  The kernel must do it.  
> > > > > > It means
> > > > > > the current kernel code is worng.
> > > > > 
> > > > > i think this is the right place for raw ipv4 sockets like what
> > > > > ping/traceroute uses.
> > > > > 
> > > > > ipv6 looks like it already does the right thing.
> > > > 
> > > > Given that this turned out so similar to the existing v6 support that
> > > > I think you didn't notice before writing the v4 version, this looks
> > > > like the right place indeed :)
> > > > 
> > > > Works for me, OK
> > >  
> > > Did someone try this on an ospf router?
> > > I think our ospfd(8) always includes the source address and uses 
> > > IP_HDRINCL
> > > but not sure about other daemons. Are there other raw IP users that expect
> > > the IP source to be set to the outgoing interface by default?
> > > Maybe IGMP proxies and routers. E.g. dvmrpd depends on IP_MULTICAST_IF to
> > > set the source IP address.
> > > 
> > > Looking at the code I think this will break the IP_MULTICAST_IF case.
> > > In ip_output() the check is like this:
> > > 
> > >         if ((IN_MULTICAST(ip->ip_dst.s_addr) ||
> > >             (ip->ip_dst.s_addr == INADDR_BROADCAST)) &&
> > >             imo != NULL && (ifp = if_get(imo->imo_ifidx)) != NULL) {
> > > 
> > >                 mtu = ifp->if_mtu;
> > >                 if (ip->ip_src.s_addr == INADDR_ANY) {
> > >                         struct in_ifaddr *ia;
> > > 
> > >                         IFP_TO_IA(ifp, ia);
> > >                         if (ia != NULL)
> > >                                 ip->ip_src = ia->ia_addr.sin_addr;
> > >                 }
> > > 
> > > Now raw_ip.c already set ip_src to something so
> > >   if (ip->ip_src.s_addr == INADDR_ANY)
> > > is never true.
> > > 
> > > It is possible to skip the in_pcbselsrc() call in rip_output() when
> > > IN_MULTICAST(ip->ip_dst.s_addr) || (ip->ip_dst.s_addr == INADDR_BROADCAST)
> > > 
> > > Is that good enough?
> > 
> > Actually in_pcbselsrc() checks the multicast options but only for the
> > IN_MULTICAST() case. I guess we could add INADDR_BROADCAST handling in
> > there as well. Seems like a sensible thing todo. Broadcast  is just a very
> > special version of multicast.
> 
> i know we talked about this off list, but for the record there are two
> kinds of IP broadcast. there's 255.255.255.255, and the broadcast
> address on subnets, eg, 192.168.1.0/24 has a broadcast address of
> 192.168.1.255. you're talking about 255.255.255.255 here.

Yes, this only matters for 255.255.255.255. The per netowrk broadcast
addresses were a stupid idea and luckily not relevant here.
 
> im honestly surprised in_pcbselsrc doesnt already do what you're talking
> about. like i said, the impression i get from stevens and other bits of
> the stack is that 255.255.255.255 is largely treated as a multicast
> address, which is why im surprised that it isnt handled already and why
> i think it makes sense. what tests do we need to feel confident with it
> though? 

I was also surprised that this code differs from the very similar code in
ip_output(). I agree that 255.255.255.255 should be treated like a
multicast address.
 
I'm fairly confident that this will be fine. It may unbreak some cases but
luckily the use of 255.255.255.255 is very limited. Apart from DHCP/BOOTP
not much depends on it.

> > Also if this is changed is there still a way to have ip->ip_src ==
> > INADDR_ANY in ip_output()?
> 
> dunno. would slapping a counter on it be useful?

Something like that. It would be nice to remove some of the code in
ip_output() which should be redundant now. But as usual I guess some other
protocol handler may still depend on this feature of ip_output.
A counter or even printf would help identify these cases.
 
> Index: in_pcb.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/in_pcb.c,v
> retrieving revision 1.261
> diff -u -p -r1.261 in_pcb.c
> --- in_pcb.c  14 Mar 2022 22:38:43 -0000      1.261
> +++ in_pcb.c  19 Mar 2022 12:54:55 -0000
> @@ -893,11 +893,13 @@ in_pcbselsrc(struct in_addr **insrc, str
>       }
>  
>       /*
> -      * If the destination address is multicast and an outgoing
> -      * interface has been set as a multicast option, use the
> -      * address of that interface as our source address.
> +      * If the destination address is multicast or limited
> +      * broadcast (255.255.255.255) and an outgoing interface has
> +      * been set as a multicast option, use the address of that
> +      * interface as our source address.
>        */
> -     if (IN_MULTICAST(sin->sin_addr.s_addr) && mopts != NULL) {
> +     if ((IN_MULTICAST(sin->sin_addr.s_addr) || 
> +         sin->sin_addr.s_addr == INADDR_BROADCAST) && mopts != NULL) {
>               struct ifnet *ifp;
>  
>               ifp = if_get(mopts->imo_ifidx);
> 

OK claudio@

-- 
:wq Claudio

Reply via email to