Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 15 Jul 2003 15:48:48 -0700
From:      Wes Peters <wes@softweyr.com>
To:        "Matthew Grooms" <mgrooms@shrew.net>, "Chuck Swiger" <cswiger@mac.com>
Cc:        "freebsd-net@freebsd.org" <freebsd-net@freebsd.org>
Subject:   Re: broadcast udp packets ...
Message-ID:  <200307151548.48778.wes@softweyr.com>
In-Reply-To: <200307151709.h6FH9UOW055742@hole.shrew.net>
References:  <200307151709.h6FH9UOW055742@hole.shrew.net>

next in thread | previous in thread | raw e-mail | index | archive | help
On Tuesday 15 July 2003 10:09, Matthew Grooms wrote:
> Hmmm,
>
> >What we observed on our embedded system is the packet gets sent on
> > all attached interfaces, with dest IP 255.255.255.255, and a src IP
> > of the local address that has the default route.  If there isn't a
> > default route, sending to 255.255.255.255 fails with "no route to
> > host."
>
> Maybe I am confused. When I use a udp socket bound to an interface,
> packets that are generated from that socket get thier dest address
> translated to a network specific broadcast address. Do I understad
> you correctly when you say that you can generate packets destined to
> 255.255.255.255? Am I doing somthing different then you are? ...
>
> int test_sock = socket( PF_INET, SOCK_DGRAM, 0 );
> if( test_sock == -1 )
>     return -1;
>
> struct ifreq ifr;
> memset( &ifr, 0, sizeof( struct ifreq ) );
> strcpy( ifr.ifr_name, config.get_service_iface() );
> if( ioctl( test_sock, SIOCGIFADDR, &ifr ) == -1 )
>     return -1;
>
> uint32_t value =  1;
> if( setsockopt( test_sock, SOL_SOCKET, SO_BROADCAST,
>     (char*) &value, sizeof( uint32_t ) ) == -1
>     return -1;
>
> struct sockaddr_in serv_addr;
> memset( &serv_addr, 0, sizeof( struct sockaddr_in ) );
> memcpy( &serv_addr, &ifr.ifr_addr, sizeof( struct sockaddr_in ) );
> serv_addr.sin_family = AF_INET;
> serv_addr.sin_port   = htons( config.get_service_port() );
>
> if( bind( test_sock, ( struct sockaddr * ) &serv_addr,
>     sizeof( struct sockaddr_in ) ) == - 1)
>     return -1;
>
> struct sockaddr_in bcast_addr;
> memset( &bcast_addr, 0, sizeof( struct sockaddr_in ) );
> bcast_addr.sin_family      = AF_INET;
> bcast_addr.sin_addr.s_addr = 0xffffffff;
> bcast_addr.sin_port        = htons( 100 );
>
> char test_buff[] = { "TEST123TEST123" };
> if( sendto( test_sock, test_buff, sizeof( test_buff ), 0,
>     ( const struct sockaddr * ) &bcast_addr,
>     sizeof( const struct sockaddr_in ) ) == -1 )
>     printf( "failed to generate broadcast packet( %d bytes )\n",
>     sizeof( test_buff ) );
> else
>     printf( "broadcast packet generated ( %d bytes )\n",
>     sizeof( test_buff ) );
>
> >This is bogus, so I propose to change it to a special case, where
> >packets sent to 255.255.255.255 will be sent on each attached
> >interface, with src IP of the interface "primary" address.
>
> When you say attached, do you mean the socket is bound to the ip
> address of that interface or do you mean all configured interfaces on
> that host? Should this be affected by the MSG_DONTROUTE flag? It
> would seem that if you were requesting the packet be routed, that it
> would be emmitted on all network interfaces. If the MSG_DONTROUTE
> were passed, that the packet would only be generated on the interface
> the socket is bound to.

It's a broadcast, the socket isn't bound to an interface.  ;^)

The idea is, we have listener on each ethernet interface listening via a 
bpf.  The listener listens for an 'appliance discovery' packet which is 
broadcast by the console application running on the admin's 
workstation.  When we receive this discovery packet, we're supposed to 
reply back with a broadcast packet that says 'here I am' so the console 
can get our MAC address.  The console application does some special 
h0h0 magic of it's own then sends us back another broadcast message 
that has IP addresses for all 3 interfaces.

It's a wonderful idea but it doesn't work.  This seems in keeping with 
the spirit of BOOTP, DHCP, et al, but is explicitly designed to assign 
a permanent address to an appliance that cannot know it's boot address 
when configured and cannot really predict which of the 3 interfaces it 
might receive an address from.

If the answer to this is 'ick, that's just not what IP broadcasting is 
supposed to do, get lost' I'm willing to accept that answer, but so far 
everyone seems to agree that what I proposed isn't that whacked out.  
Tell me if I'm wrong!  ;^)

So, in short, the IP address 255.255.255.255 is a special case that 
isn't handled as a special case by the ip_output code.  I propose to 
change the code so that a packet sent to destination address 
255.255.255.255 (aka INADDR_BROADCAST) be handled specially.  Any such 
packet will be sent to destination address 255.255.255.255 on each 
interface that is marked UP and BROADCAST, with the ip src address set 
to the currently configured primary ip address of the interface, even 
if this is 0.0.0.0.  This special case will not call rtalloc or do any 
other route lookups.

Stop me if I'm violating specifications or even just common sense 
here...  (I need to read the IP and UDP RFCs in a bit more detail, they 
seem pretty vague in this area.)  I'd like to implement this if it's a 
sensible change, but will tell the application guys to rewrite their 
send code to use the BPF if it seems this is wrong.  I don't feel the 
current implementation is right in any way, but I don't want to make it 
more wrong.

-- 
         "Where am I, and what am I doing in this handbasket?"

Wes Peters                                              wes@softweyr.com




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200307151548.48778.wes>