From e53738558f2f1aa8cd536545479ab98b0df808c5 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Wed, 10 Dec 2008 11:12:16 +0000 Subject: [PATCH] *: fix SO_BINDTODEVICE. Kernel wants at least IFNAMSIZ bytes there. --- include/libbb.h | 1 + libbb/xconnect.c | 15 +++++++++++++++ networking/arping.c | 3 +-- networking/ping.c | 4 ++-- networking/udhcp/socket.c | 4 ++-- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 16e8f48db..e6767e39e 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -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 { diff --git a/libbb/xconnect.c b/libbb/xconnect.c index 5be83241b..d078e9811 100644 --- a/libbb/xconnect.c +++ b/libbb/xconnect.c @@ -8,6 +8,7 @@ */ #include +#include #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) { diff --git a/networking/arping.c b/networking/arping.c index e7b842f5b..915af3261 100644 --- a/networking/arping.c +++ b/networking/arping.c @@ -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) { diff --git a/networking/ping.c b/networking/ping.c index 01a9f9ac5..f2a612fde 100644 --- a/networking/ping.c +++ b/networking/ping.c @@ -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 { diff --git a/networking/udhcp/socket.c b/networking/udhcp/socket.c index 857f0a4de..fdb558db4 100644 --- a/networking/udhcp/socket.c +++ b/networking/udhcp/socket.c @@ -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;