SO_BINDTODEVICE is not supported on this system
Matthias Andree
mandree at FreeBSD.org
Thu Jul 18 18:59:55 UTC 2013
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.
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.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: btd.c
Type: text/x-csrc
Size: 868 bytes
Desc: not available
URL: <http://lists.busybox.net/pipermail/busybox/attachments/20130718/804af91d/attachment.c>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: main.c
Type: text/x-csrc
Size: 554 bytes
Desc: not available
URL: <http://lists.busybox.net/pipermail/busybox/attachments/20130718/804af91d/attachment-0001.c>
More information about the busybox
mailing list