SO_BINDTODEVICE is not supported on this system

Vladislav Grishenko themiron at mail.ru
Tue Jul 23 11:20:47 UTC 2013


Hi, Lambrecht

Under FreeBSD you can use bpf device & BIOCSETIF ioctl for binding to
specific interface
Refer http://bastian.rieck.ru/howtos/bpf/ 

Best Regards, Vladislav Grishenko

> -----Original Message-----
> From: busybox-bounces at busybox.net [mailto:busybox-
> bounces at busybox.net] On Behalf Of Lambrecht Jurgen
> Sent: Tuesday, July 23, 2013 3:23 PM
> To: Matthias Andree
> Cc: busybox at busybox.net
> Subject: Re: SO_BINDTODEVICE is not supported on this system
> 
> 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
> _______________________________________________
> busybox mailing list
> busybox at busybox.net
> http://lists.busybox.net/mailman/listinfo/busybox



More information about the busybox mailing list