From b40d0e2982b66bcaaaf19b2b72037abb78c382c1 Mon Sep 17 00:00:00 2001 From: david Date: Fri, 16 Nov 2012 21:02:59 +0000 Subject: [PATCH] Pad the device name of SO_BINDTODEVICE up to sizeof(int). An apparent kernel bug in Linux 2.6.20 and earlier causes the SO_BINDTODEVICE setsockopt to return EINVAL if the device name is too short. Pad with null characters to avoid this. http://article.gmane.org/gmane.linux.network/71887 http://article.gmane.org/gmane.linux.network/72216 --- nbase/nbase_misc.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/nbase/nbase_misc.c b/nbase/nbase_misc.c index 14c6a27d2..5faae5d4e 100644 --- a/nbase/nbase_misc.c +++ b/nbase/nbase_misc.c @@ -284,6 +284,20 @@ int block_socket(int sd) { /* Use the SO_BINDTODEVICE sockopt to bind with a specific interface (Linux only). Pass NULL or an empty string to remove device binding. */ int socket_bindtodevice(int sd, const char *device) { + char padded[sizeof(int)]; + + /* In Linux 2.6.20 and earlier, there is a bug in SO_BINDTODEVICE that causes + EINVAL to be returned if the optlen < sizeof(int); this happens for example + with the interface names "" and "lo". Pad the string with null characters + so it is above this limit if necessary. + http://article.gmane.org/gmane.linux.network/71887 + http://article.gmane.org/gmane.linux.network/72216 */ + if (strlen(device) + 1 < sizeof(padded)) { + /* We rely on strncpy padding with nulls here. */ + strncpy(padded, device, sizeof(padded)); + device = padded; + } + #ifdef SO_BINDTODEVICE /* Linux-specific sockopt asking to use a specific interface. See socket(7). */ if (setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1) < 0)