diff --git a/nsock/include/nsock.h b/nsock/include/nsock.h index 8f2a7fa69..01cf67632 100644 --- a/nsock/include/nsock.h +++ b/nsock/include/nsock.h @@ -183,6 +183,9 @@ void nsp_settrace(nsock_pool nsp, FILE *file, int level, const struct timeval *b * sockets (value of optval will be used directly in the setsockopt() call). */ void nsp_setbroadcast(nsock_pool nsp, int optval); +/* Sets the name of the interface for new sockets to bind to. */ +void nsp_setdevice(nsock_pool nsp, const char *device); + /* Initializes an Nsock pool to create SSL connections. This sets an internal * SSL_CTX, which is like a template that sets options for all connections that * are made from it. Returns the SSL_CTX so you can set your own options. */ diff --git a/nsock/src/nsock_connect.c b/nsock/src/nsock_connect.c index e83abac85..3683cbccd 100644 --- a/nsock/src/nsock_connect.c +++ b/nsock/src/nsock_connect.c @@ -95,6 +95,15 @@ static int nsock_make_socket(mspool *ms, msiod *iod, int family, int proto) { nsock_trace(ms, "Setting of IP options failed (IOD #%li)", iod->id); } } + if (ms->device) { +#ifdef SO_BINDTODEVICE + errno = 0; + if (setsockopt(iod->sd, SOL_SOCKET, SO_BINDTODEVICE, ms->device, strlen(ms->device) + 1) == -1) { + if ((errno != EPERM && ms->tracelevel > 0) || ms->tracelevel > 5) + nsock_trace(ms, "Setting of SO_BROADCAST failed (IOD #%li)", iod->id); + } +#endif + } if (ms->broadcast) { if (setsockopt(iod->sd, SOL_SOCKET, SO_BROADCAST, (const char *)&(ms->broadcast), sizeof(int)) == -1) { if (ms->tracelevel > 0) diff --git a/nsock/src/nsock_internal.h b/nsock/src/nsock_internal.h index 8822cee35..47060b936 100644 --- a/nsock/src/nsock_internal.h +++ b/nsock/src/nsock_internal.h @@ -205,6 +205,9 @@ typedef struct { /* If true, new sockets will have SO_BROADCAST set */ int broadcast; + /* Interface to bind to; only supported on Linux with SO_BINDTODEVICE sockopt. */ + const char *device; + /* If true, exit the next iteration of nsock_loop with a status of * NSOCK_LOOP_QUIT. */ int quit; diff --git a/nsock/src/nsock_pool.c b/nsock/src/nsock_pool.c index 55ed0841d..02c41a916 100644 --- a/nsock/src/nsock_pool.c +++ b/nsock/src/nsock_pool.c @@ -147,6 +147,12 @@ void nsp_setbroadcast(nsock_pool nsp, int optval) { mt->broadcast = optval; } +/* Sets the name of the interface for new sockets to bind to. */ +void nsp_setdevice(nsock_pool nsp, const char *device) { + mspool *mt = (mspool *)nsp; + mt->device = device; +} + /* And here is how you create an nsock_pool. This allocates, initializes, and * returns an nsock_pool event aggregator. In the case of error, NULL will be * returned. If you do not wish to immediately associate any userdata, pass in @@ -192,6 +198,8 @@ nsock_pool nsp_new(void *userdata) { nsp->next_event_serial = 1; + nsp->device = NULL; + #if HAVE_OPENSSL nsp->sslctx = NULL; #endif