SO_BINDTODEVICE is not supported on this system

Lambrecht Jürgen J.Lambrecht at TELEVIC.com
Tue Jul 23 08:53:01 UTC 2013


On 07/18/2013 08:59 PM, Matthias Andree wrote:
> Am 18.07.2013 16:58, schrieb Lambrecht Jürgen:
>> On 07/18/2013 12:49 PM, Lambrecht Jürgen wrote:
>>> Hi,
>>>
>>> I am porting the busybox dhcp server to an RTOS (eCos). eCos uses the
>>> FreeBSD TCP/IP stack.
>>>
>>> I get this message: bb_error_msg("SO_BINDTODEVICE is not supported on
>>> this system");.
>>>
>>> Why not ignoring this option on systems that do not support it, as long
>>> as there is only 1 network interface?
>>>
>>> When I have fixed this, I can maybe supply a patch for systems with only
>>> 1 network interface (as in the ISC DHCPD code). Alowing to not use
>>> SO_BINDTODEVICE will improve portability.
>>>
>>> Regards,
>>> Jürgen
>>>
>> patch to solve this in attach
>> (I can also use git send-email if you prefer, but I wanted to reply to
>> this mail)
>> It also contains a small fix for calling 'alloca': it wants a size_t,
>> not an int.
> Greeting Jürgen, and everyone else on the list,
>
> I'd say that the SO_BINDTODEVICE stuff can be avoided, as sketched
> below. The plan is:
>
> 1. obtain the interface's primary address for the socket's address
> family with ioctl (socket, SIOCGIFADDR, struct ifreq *something)
> <http://www.freebsd.org/cgi/man.cgi?query=netintro&apropos=0&sektion=0&manpath=FreeBSD+8.3-RELEASE&arch=default&format=html>
>
> 2. bind(2) to that address.
This looks like a valid plan, I will try this out (when I find the time) 
to give feedback. But I'm not the expert to decide what to do best: my 
patch or try to avoid it.

Kind regards,
Jürgen
>
> Note: IPv6 stuff needs more #includes, must use SIOCGIFADDR_IN6 and read
> the address from a different-form structure.  It must also figure out
> the domain (AF_INET/AF_INET6) the socket is in... this is left as an
> exercise for the readers.
> Some is in
> http://www.freebsd.org/doc/en/books/developers-handbook/ipv6.html but I
> have not looked further from there.
>
> If IPv6-enabled, this should go into libbb/xconnect.c:
>
>
> // BEWARE: THE CODE BELOW IS ONLY GOOD FOR FREEBSD AND IPV4
>
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <sys/ioctl.h>
> #include <net/if.h>
> #include <net/route.h>
>
> /* ... */
>
> int FAST_FUNC setsockopt_bindtodevice(int sock, const char *ifname)
> {
> 	// input: int sock - a socket obtained from the socket() syscall
> 	// input: const char *ifname - interface name as C string
> 	struct ifreq ifr;
>
> 	memset(&ifr, 0, sizeof(ifr));	// see man 2 bind why needed
> 	if (strlcpy(ifr.ifr_name, ifname, IFNAMSIZ) >= IFNAMSIZ) {
> 		bb_perror_msg("interface name %s too long", ifname);
> 		return -1;
> 	}
> 	if (-1 == ioctl(sock, SIOCGIFADDR, &ifr)) {
> 		// see man 4 netintro for SIOCGIFADDR
> 		bb_perror_msg("ioctl(%d,SIOCGIFADDR,\"%s\") failed", sock, ifname);
> 		return -1;
> 	}
> 	// the next line will not compile on Linux for lack of sa_len
> 	// but you have the SO_BINDTODEVICE alternative there:
> 	if (-1 == bind(sock, &ifr.ifr_addr, ifr.ifr_addr.sa_len)) {
> 		bb_perror_msg("cannot bind socket %d to interface %s", sock, ifname);
> 		return -1;
> 	}
> 	return 0;
> }
>
>
> I am attaching demo code, to be compiled with:
>
> gcc -O2 -Wall -Wextra -std=gnu99 btd.c -DFAST_FUNC= -include string.h \
> -o try-freebsd-btd main.c  -include stdio.h -include stdlib.h \
> '-Dbb_perror_msg(...)=fprintf(stderr, __VA_ARGS__)' -include unistd.h
>
> best run as truss ./try-freebsd-btd so you see what's going on behind
> the scenes.
>
> Hope that helps.
>
> BTW, note that the FreeBSD port does not enable networking modules such
> as udhcpd.
>


-- 
Jürgen Lambrecht
R&D Associate
Mobile: +32 499 644 531
Tel: +32 (0)51 303045    Fax: +32 (0)51 310670
http://www.televic-rail.com
Televic Rail NV - Leo Bekaertlaan 1 - 8870 Izegem - Belgium
Company number 0825.539.581 - RPR Kortrijk


More information about the busybox mailing list