*: fix SO_BINDTODEVICE. Kernel wants at least IFNAMSIZ bytes there.
No binary (build failed)
—
(log yok)
| @@ -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 { | |
| @@ -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) | |
| { | |
| @@ -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) { | |
| @@ -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 | |
| { | |
| @@ -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; | |