views:

1877

answers:

3

On a Linux system with a wired and a wireless interface (e.g. 192.168.1.x and 192.168.2.x subnets) I want to send a UDP broadcast that goes out via ALL available interfaces (i.e. both through the wired and the wireless interface).

Currently I sendto() to INADDR_BROADCAST, however it seems that the broadcast only is sent through one of the interfaces (not always the same and subsequent broadcasts may use the other interface).

Is there a way that I can send a UDP broadcast that goes out through every single interface?

+2  A: 

You can't have a single sendto() generate a packet on every interface - in general (fragmentation notwithstanding) it's one packet transmitted for each sendto().

You'll need to transmit the packet once for each interface and either:

  1. use low-level (setsockopt()?) calls to select the outbound interface

  2. send to the specific broadcast address for each known interface

the latter is however not suitable if you're trying to do some sort of discovery mechanism, such that the devices you're expecting to respond aren't actually correctly configured with an IP address in the same subnet as the interface they're connected to.

Alnitak
+1  A: 

Solution: http://www.developerweb.net/forum/showthread.php?t=5085

+3  A: 

First of all, you should consider broadcast obsolete, specially INADDR_BROADCAST (255.255.255.255). Your question highlights exactly one of the reasons that broadcast is unsuitable. It should die along with IPv4 (hopefully). Note that IPv6 doesn't even have a concept of broadcast (multicast is used, instead).

INADDR_BROADCAST is limited to the local link. Nowadays, it's only visible use is for DHCP auto-configuration, since at such time, the client will not know yet in what network it is connected to.

With a single sendto(), only a single packet is generated, and the outgoing interface is determined by the operating system's routing table (ip route on linux). You can't have a single sendto() generate more than one packet, you would have to iterate over all interfaces, and either use raw sockets or bind the socket to a device using setsockopt(..., SOL_SOCKET, SO_BINDTODEVICE, "ethX") to send each packet bypassing the OS routing table (this requires root privileges). Not a good solution.

Instead, since INADDR_BROADCAST is not routed anyway, you can achieve almost the same thing by iterating over each interface, and sending the packet to its broadcast address. For example, assuming that your networks have 255.255.255.0 (/24) masks, the broadcast addresses are 192.168.1.255 and 192.168.2.255. Call sendto() once for each of these addresses and you will have accomplished your goal.


Edit: fixed information regarding to INADDR_BROADCAST, and complementing the answer with information about SO_BINDTODEVICE.

Juliano
if INADDR_BROADCAST ever did mean that it was a _very_ long time ago. I'll ask the author of RFC 1 when I see him tonight :) In recent memory it has always mapped to the local network segment's MAC address. _Directed_ broadcasts used to be handled by routers, but are now blocked for security.
Alnitak
Ok, I checked (RFC 919) and it seems that the first definition of 255.255.255.255 was "immediate neighbors". For some reason I believed that the whole internet was represented by 0.0.0.0/0, resulting in network=0.0.0.0 and brdcast=255.255.255.255. Fixed the answer.
Juliano
ok, glad that's fixed. Now, on the comment on IPv6, don't forget that a broadcast is semantically equivalent to a TTL 1 multicast, except that it doesn't use broadcast frames at layer 2.
Alnitak