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>