*: fix SO_BINDTODEVICE. Kernel wants at least IFNAMSIZ bytes there.
authorDenis Vlasenko <vda.linux@googlemail.com>
Wed, 10 Dec 2008 11:12:16 +0000 (11:12 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Wed, 10 Dec 2008 11:12:16 +0000 (11:12 -0000)
include/libbb.h
libbb/xconnect.c
networking/arping.c
networking/ping.c
networking/udhcp/socket.c

index 16e8f48..e6767e3 100644 (file)
@@ -437,6 +437,7 @@ ssize_t xsendto(int s, const void *buf, size_t len, const struct sockaddr *to,
  * Turn it on before you call bind(). */
 void setsockopt_reuseaddr(int fd) FAST_FUNC; /* On Linux this never fails. */
 int setsockopt_broadcast(int fd) FAST_FUNC;
+int setsockopt_bindtodevice(int fd, const char *iface) FAST_FUNC;
 /* NB: returns port in host byte order */
 unsigned bb_lookup_port(const char *port, const char *protocol, unsigned default_port) FAST_FUNC;
 typedef struct len_and_sockaddr {
index 5be8324..d078e98 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <netinet/in.h>
+#include <net/if.h>
 #include "libbb.h"
 
 void FAST_FUNC setsockopt_reuseaddr(int fd)
@@ -18,6 +19,20 @@ int FAST_FUNC setsockopt_broadcast(int fd)
 {
        return setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &const_int_1, sizeof(const_int_1));
 }
+int FAST_FUNC setsockopt_bindtodevice(int fd, const char *iface)
+{
+       int r;
+       struct ifreq ifr;
+       strncpy_IFNAMSIZ(ifr.ifr_name, iface);
+       /* Actually, ifr_name is at offset 0, and in practice
+        * just giving char[IFNAMSIZ] instead of struct ifreq works too.
+        * But just in case it's not true on some obscure arch... */
+       r = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr));
+       if (r)
+               bb_perror_msg("can't bind to interface %s", iface);
+       return r;
+}
+
 
 void FAST_FUNC xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen)
 {
index e7b842f..915af32 100644 (file)
@@ -331,8 +331,7 @@ int arping_main(int argc UNUSED_PARAM, char **argv)
                struct sockaddr_in saddr;
                int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0);
 
-               if (setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1) == -1)
-                       bb_perror_msg("cannot bind to device %s", device);
+               setsockopt_bindtodevice(probe_fd, device);
                memset(&saddr, 0, sizeof(saddr));
                saddr.sin_family = AF_INET;
                if (src.s_addr) {
index 01a9f9a..f2a612f 100644 (file)
@@ -572,7 +572,7 @@ static void ping4(len_and_sockaddr *lsa)
                xbind(pingsock, &source_lsa->u.sa, source_lsa->len);
        }
        if (str_I)
-               setsockopt(pingsock, SOL_SOCKET, SO_BINDTODEVICE, str_I, strlen(str_I) + 1);
+               setsockopt_bindtodevice(pingsock, str_I);
 
        /* enable broadcast pings */
        setsockopt_broadcast(pingsock);
@@ -622,7 +622,7 @@ static void ping6(len_and_sockaddr *lsa)
        if (source_lsa)
                xbind(pingsock, &source_lsa->u.sa, source_lsa->len);
        if (str_I)
-               setsockopt(pingsock, SOL_SOCKET, SO_BINDTODEVICE, str_I, strlen(str_I) + 1);
+               setsockopt_bindtodevice(pingsock, str_I);
 
 #ifdef ICMP6_FILTER
        {
index 857f0a4..fdb558d 100644 (file)
@@ -98,8 +98,8 @@ int FAST_FUNC udhcp_listen_socket(/*uint32_t ip,*/ int port, const char *inf)
                bb_perror_msg_and_die("SO_BROADCAST");
 
        /* NB: bug 1032 says this doesn't work on ethernet aliases (ethN:M) */
-       if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &inf, strlen(inf) + 1) == -1)
-               bb_perror_msg_and_die("SO_BINDTODEVICE");
+       if (setsockopt_bindtodevice(fd, inf))
+               xfunc_die(); /* warning is already printed */
 
        memset(&addr, 0, sizeof(addr));
        addr.sin_family = AF_INET;