support binding to specific interface

This commit is contained in:
Max Lv
2013-05-16 10:47:25 +08:00
parent d3f16c72f6
commit 85c04ef297
17 changed files with 470 additions and 294 deletions
+27 -2
View File
@@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.11.3 from Makefile.am.
# Makefile.in generated by automake 1.11.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -16,6 +16,23 @@
@SET_MAKE@
VPATH = @srcdir@
am__make_dryrun = \
{ \
am__dry=no; \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
| grep '^AM OK$$' >/dev/null || am__dry=yes;; \
*) \
for am__flg in $$MAKEFLAGS; do \
case $$am__flg in \
*=*|--*) ;; \
*n*) am__dry=yes; break;; \
esac; \
done;; \
esac; \
test $$am__dry = yes; \
}
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
@@ -87,6 +104,11 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
SOURCES = $(ss_local_SOURCES) $(ss_redir_SOURCES) $(ss_server_SOURCES)
DIST_SOURCES = $(ss_local_SOURCES) $(am__ss_redir_SOURCES_DIST) \
$(ss_server_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -262,8 +284,11 @@ $(ACLOCAL_M4): $(am__aclocal_m4_deps)
$(am__aclocal_m4_deps):
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
$(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
fi; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
while read p p1; do if test -f $$p || test -f $$p1; \
+31 -14
View File
@@ -17,14 +17,20 @@
#include <time.h>
#include <unistd.h>
#include "utils.h"
#include "local.h"
#include "socks5.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H)
#include <net/if.h>
#include <sys/ioctl.h>
#define SET_INTERFACE
#endif
#include "utils.h"
#include "local.h"
#include "socks5.h"
#ifndef EAGAIN
#define EAGAIN EWOULDBLOCK
#endif
@@ -42,6 +48,17 @@ int setnonblocking(int fd) {
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
#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 *port) {
struct addrinfo hints;
struct addrinfo *result, *rp;
@@ -557,16 +574,11 @@ static void accept_cb (EV_P_ ev_io *w, int revents) {
setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif
struct timeval timeout;
timeout.tv_sec = listener->timeout;
timeout.tv_usec = 0;
err = setsockopt(sockfd, SOL_SOCKET,
SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
if (err) ERROR("setsockopt");
err = setsockopt(sockfd, SOL_SOCKET,
SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));
if (err) ERROR("setsockopt");
// Setup
setnonblocking(sockfd);
#ifdef SET_INTERFACE
if (listener->iface) setinterface(sockfd, listener->iface);
#endif
struct server *server = new_server(serverfd);
struct remote *remote = new_remote(sockfd, listener->timeout);
@@ -589,6 +601,7 @@ int main (int argc, char **argv) {
char *method = NULL;
char *pid_path = NULL;
char *conf_path = NULL;
char *iface = NULL;
int remote_num = 0;
char *remote_host[MAX_REMOTE_NUM];
@@ -596,7 +609,7 @@ int main (int argc, char **argv) {
opterr = 0;
while ((c = getopt (argc, argv, "f:s:p:l:k:t:m:c:")) != -1) {
while ((c = getopt (argc, argv, "f:s:p:l:k:t:m:i:c:")) != -1) {
switch (c) {
case 's':
remote_host[remote_num++] = optarg;
@@ -623,6 +636,9 @@ int main (int argc, char **argv) {
case 'c':
conf_path = optarg;
break;
case 'i':
iface = optarg;
break;
}
}
@@ -688,6 +704,7 @@ int main (int argc, char **argv) {
listen_ctx.remote_port = strdup(remote_port);
listen_ctx.timeout = atoi(timeout);
listen_ctx.fd = listenfd;
listen_ctx.iface = iface;
struct ev_loop *loop = ev_default_loop(0);
if (!loop) {
+1
View File
@@ -10,6 +10,7 @@ struct listen_ctx {
char **remote_host;
int remote_num;
char *remote_port;
char *iface;
int timeout;
int fd;
struct sockaddr sock;
+32 -6
View File
@@ -17,13 +17,19 @@
#include <time.h>
#include <unistd.h>
#include "utils.h"
#include "server.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H)
#include <net/if.h>
#include <sys/ioctl.h>
#define SET_INTERFACE
#endif
#include "utils.h"
#include "server.h"
#ifndef EAGAIN
#define EAGAIN EWOULDBLOCK
#endif
@@ -45,6 +51,17 @@ int setnonblocking(int fd) {
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
#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;
struct addrinfo *result, *rp;
@@ -93,7 +110,7 @@ int create_and_bind(const char *host, const char *port) {
return listen_sock;
}
struct remote *connect_to_remote(struct addrinfo *res) {
struct remote *connect_to_remote(struct addrinfo *res, const char *iface) {
int sockfd;
int opt = 1;
@@ -114,6 +131,10 @@ struct remote *connect_to_remote(struct addrinfo *res) {
// setup remote socks
setnonblocking(sockfd);
#ifdef SET_INTERFACE
if (iface) setinterface(sockfd, iface);
#endif
connect(sockfd, res->ai_addr, res->ai_addrlen);
return remote;
@@ -401,7 +422,7 @@ static void server_resolve_cb(EV_P_ ev_timer *watcher, int revents) {
rp = result;
}
struct remote *remote = connect_to_remote(rp);
struct remote *remote = connect_to_remote(rp, server->listen_ctx->iface);
// release addrinfo
asyncns_freeaddrinfo(result);
@@ -715,6 +736,7 @@ int main (int argc, char **argv) {
char *method = NULL;
char *pid_path = NULL;
char *conf_path = NULL;
char *iface = NULL;
int server_num = 0;
char *server_host[MAX_REMOTE_NUM];
@@ -722,7 +744,7 @@ int main (int argc, char **argv) {
opterr = 0;
while ((c = getopt (argc, argv, "f:s:p:l:k:t:m:c:v")) != -1) {
while ((c = getopt (argc, argv, "f:s:p:l:k:t:m:c:i:v")) != -1) {
switch (c) {
case 's':
server_host[server_num++] = optarg;
@@ -746,6 +768,9 @@ int main (int argc, char **argv) {
case 'c':
conf_path = optarg;
break;
case 'i':
iface = optarg;
break;
case 'v':
verbose = 1;
}
@@ -820,6 +845,7 @@ int main (int argc, char **argv) {
listen_ctx.timeout = atoi(timeout);
listen_ctx.asyncns = asyncns;
listen_ctx.fd = listenfd;
listen_ctx.iface = iface;
ev_io_init (&listen_ctx.io, accept_cb, listenfd, EV_READ);
ev_io_start (loop, &listen_ctx.io);
+2 -1
View File
@@ -12,6 +12,7 @@ struct listen_ctx {
ev_io io;
int fd;
int timeout;
char *iface;
asyncns_t *asyncns;
struct sockaddr sock;
};
@@ -64,7 +65,7 @@ static void server_timeout_cb(EV_P_ ev_timer *watcher, int revents);
static void server_resolve_cb(EV_P_ ev_timer *watcher, int revents);
struct remote* new_remote(int fd);
struct remote *connect_to_remote(struct addrinfo *res);
struct remote *connect_to_remote(struct addrinfo *res, const char *iface);
void free_remote(struct remote *remote);
void close_and_free_remote(EV_P_ struct remote *remote);
struct server* new_server(int fd, struct listen_ctx *listener);