SO_BINDTODEVICE is not supported on this system

Lambrecht Jürgen J.Lambrecht at TELEVIC.com
Tue Jul 23 09:23:10 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>
after reading Denys' mail, I realized that the server should also run on 
interfaces that have no address set.
> 2. bind(2) to that address.
in socket.c, udhcp_listen_socket(..), xbind is called that finally calls 
bind(..).
So it should not be done again.
IMHO, your code proposal is conceptually wrong: 
setsockopt_bindtodevice(..) is to make sure the later bind(..) binds to 
the correct interface/device, but in case there is only 1 device (and no 
SO_BINDTODEVICE support), the setsockopt_bindtodevice(..) should not 
return an error (and make the server needlessly die!), then it should 
just do nothing!
I will put the comment of my patch here (should have done it in the 
first place):

Subject: [PATCH] Fix setsockopt_bindtodevice when SO_BINDTODEVICE is not
  supported:
  - just ignore it (return 0)
  - but check if this function is only called once (from ISC DHCP 
code)   (return -1 second time)   because then only 1 network interface 
is allowed.

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