diff --git a/src/local.c b/src/local.c index 6d904f35..66b59dc4 100644 --- a/src/local.c +++ b/src/local.c @@ -131,19 +131,6 @@ int setnonblocking(int fd) #endif -#ifdef SET_INTERFACE -int setinterface(int socket_fd, const char *interface_name) -{ - struct ifreq interface; - memset(&interface, 0, sizeof(interface)); - strncpy(interface.ifr_name, interface_name, IFNAMSIZ); - int res = setsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE, &interface, - sizeof(struct ifreq)); - return res; -} - -#endif - int create_and_bind(const char *addr, const char *port) { struct addrinfo hints; diff --git a/src/netutils.c b/src/netutils.c index 850387ab..1bbdfd2d 100644 --- a/src/netutils.c +++ b/src/netutils.c @@ -39,6 +39,12 @@ #include #endif +#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H) && defined(__linux__) +#include +#include +#define SET_INTERFACE +#endif + #include "netutils.h" #include "utils.h" @@ -64,6 +70,36 @@ size_t get_sockaddr_len(struct sockaddr *addr) return 0; } +#ifdef SET_INTERFACE +int setinterface(int socket_fd, const char *interface_name) +{ + struct ifreq interface; + memset(&interface, 0, sizeof(interface)); + strncpy(interface.ifr_name, interface_name, IFNAMSIZ); + int res = setsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE, &interface, + sizeof(struct ifreq)); + return res; +} +#endif + +int bind_to_address(int socket_fd, const char *address) +{ + if (address != NULL) { + struct cork_ip ip; + struct sockaddr_storage addr; + if (cork_ip_init(&ip, address) != -1) { + if (ip.version == 4) { + dns_pton(AF_INET, address, &addr); + return bind(socket_fd, (struct sockaddr_in *)&addr, sizeof(struct sockaddr_in)); + } else if (ip.version == 6) { + dns_pton(AF_INET6, address, &addr); + return bind(socket_fd, (struct sockaddr_in6 *)&addr, sizeof(struct sockaddr_in6)); + } + } + } + return -1; +} + ssize_t get_sockaddr(char *host, char *port, struct sockaddr_storage *storage, int block) { struct cork_ip ip; diff --git a/src/netutils.h b/src/netutils.h index 8d61a3ba..dba0ab6a 100644 --- a/src/netutils.h +++ b/src/netutils.h @@ -32,6 +32,12 @@ size_t get_sockaddr_len(struct sockaddr *addr); ssize_t get_sockaddr(char *host, char *port, struct sockaddr_storage *storage, int block); int set_reuseport(int socket); +#ifdef SET_INTERFACE +int setinterface(int socket_fd, const char *interface_name); +#endif + +int bind_to_address(int socket_fd, const char *address); + /** * Compare two sockaddrs. Imposes an ordering on the addresses. * Compares address and port. diff --git a/src/server.c b/src/server.c index 44838763..858768b7 100644 --- a/src/server.c +++ b/src/server.c @@ -121,6 +121,7 @@ static int nofile = 0; static int remote_conn = 0; static int server_conn = 0; +static char *bind_address = NULL; static char *server_port = NULL; static char *manager_address = NULL; uint64_t tx = 0; @@ -300,19 +301,6 @@ int setnonblocking(int fd) #endif -#ifdef SET_INTERFACE -int setinterface(int socket_fd, const char *interface_name) -{ - struct ifreq interface; - memset(&interface, 0, sizeof(interface)); - strncpy(interface.ifr_name, interface_name, IFNAMSIZ); - int res = setsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE, &interface, - sizeof(struct ifreq)); - return res; -} - -#endif - int create_and_bind(const char *host, const char *port) { struct addrinfo hints; @@ -429,6 +417,7 @@ static remote_t *connect_to_remote(struct addrinfo *res, // setup remote socks setnonblocking(sockfd); + bind_to_address(sockfd, bind_address); #ifdef SET_INTERFACE if (iface) { if (setinterface(sockfd, iface) == -1) @@ -1329,7 +1318,7 @@ int main(int argc, char **argv) USE_TTY(); - while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:i:d:a:n:huUvAw6", + while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:b:c:i:d:a:n:huUvAw6", long_options, &option_index)) != -1) { switch (c) { case 0: @@ -1351,6 +1340,9 @@ int main(int argc, char **argv) server_host[server_num++] = optarg; } break; + case 'b': + bind_address = optarg; + break; case 'p': server_port = optarg; break; diff --git a/src/tunnel.c b/src/tunnel.c index 1e7cd9b1..1c2711c7 100644 --- a/src/tunnel.c +++ b/src/tunnel.c @@ -110,19 +110,6 @@ static int setnonblocking(int fd) #endif -#ifdef SET_INTERFACE -int setinterface(int socket_fd, const char *interface_name) -{ - struct ifreq interface; - memset(&interface, 0, sizeof(interface)); - strncpy(interface.ifr_name, interface_name, IFNAMSIZ); - int res = setsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE, &interface, - sizeof(struct ifreq)); - return res; -} - -#endif - int create_and_bind(const char *addr, const char *port) { struct addrinfo hints; diff --git a/src/udprelay.c b/src/udprelay.c index de6a3172..d1f61a28 100644 --- a/src/udprelay.c +++ b/src/udprelay.c @@ -116,19 +116,6 @@ static int setnonblocking(int fd) #endif -#ifdef SET_INTERFACE -static int setinterface(int socket_fd, const char *interface_name) -{ - struct ifreq interface; - memset(&interface, 0, sizeof(interface)); - strncpy(interface.ifr_name, interface_name, IFNAMSIZ); - int res = setsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE, &interface, - sizeof(struct ifreq)); - return res; -} - -#endif - #if defined(MODULE_REMOTE) && defined(SO_BROADCAST) static int set_broadcast(int socket_fd) { diff --git a/src/utils.c b/src/utils.c index af08ea60..04d0eec5 100644 --- a/src/utils.c +++ b/src/utils.c @@ -243,10 +243,8 @@ void usage() printf( " [-i ] Network interface to bind.\n"); #endif -#ifndef MODULE_REMOTE printf( " [-b ] Local address to bind.\n"); -#endif printf("\n"); printf( " [-u] Enable UDP relay,\n");