mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-11-04 17:36:57 +00:00
support binding to specific interface
This commit is contained in:
+27
-2
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user