Browse Source

Merge pull request #45 from madeye/ss-tunnel

Add tunnel mode
pull/51/head
Max Lv 11 years ago
parent
commit
26f46bee1f
18 changed files with 1276 additions and 64 deletions
  1. 63
      Changes
  2. 20
      configure
  3. 2
      configure.ac
  4. 6
      debian/changelog
  5. 27
      src/Makefile.am
  6. 156
      src/Makefile.in
  7. 3
      src/include.h
  8. 15
      src/jconf.c
  9. 10
      src/jconf.h
  10. 5
      src/local.c
  11. 2
      src/local.h
  12. 5
      src/redir.c
  13. 2
      src/redir.h
  14. 884
      src/tunnel.c
  15. 76
      src/tunnel.h
  16. 48
      src/udprelay.c
  17. 3
      src/udprelay.h
  18. 13
      src/utils.c

63
Changes

@ -1,47 +1,74 @@
Changelog
---------
shadowsocks (1.4.3-1) unstable; urgency=low
1.4.2 -- Sun, 05 Jan 2014 10:05:29 +0900
* Add tunnel mode with local port forwarding feature.
-- Max Lv <max.c.lv@gmail.com> Fri, 21 Feb 2014 11:52:13 +0900
shadowsocks (1.4.2-1) unstable; urgency=high
* Fix the UDP relay issues.
* Add syslog support.
1.4.1 -- Tue, 12 Nov 2013 03:57:21 +0000
-- Max Lv <max.c.lv@gmail.com> Sun, 05 Jan 2014 10:05:29 +0900
shadowsocks (1.4.1-1) unstable; urgency=low
* Add multi-port support.
* Add PolarSSL support by @linusyang.
1.4.0 -- Sun, 08 Sep 2013 02:20:40 +0000
-- Max Lv <max.c.lv@gmail.com> Tue, 12 Nov 2013 03:57:21 +0000
shadowsocks (1.4.0-1) unstable; urgency=low
* Add standard socks5 udp support.
1.3.3 -- Fri, 21 Jun 2013 09:59:20 +0800
-- Max Lv <max.c.lv@gmail.com> Sun, 08 Sep 2013 02:20:40 +0000
shadowsocks (1.3.3-1) unstable; urgency=high
* Provide more info in verbose mode.
1.3.2 -- Sun, 09 Jun 2013 09:52:31 +0000
-- Max Lv <max.c.lv@gmail.com> Fri, 21 Jun 2013 09:59:20 +0800
shadowsocks (1.3.2-1) unstable; urgency=high
* Fix some ciphers by @linusyang.
1.3.1 -- Tue, 04 Jun 2013 00:56:17 +0000
-- Max Lv <max.c.lv@gmail.com> Sun, 09 Jun 2013 09:52:31 +0000
shadowsocks (1.3.1-1) unstable; urgency=low
* Support more cihpers: camellia, idea, rc2 and seed.
1.3 -- Thu, 16 May 2013 10:51:15 +0800
-- Max Lv <max.c.lv@gmail.com> Tue, 04 Jun 2013 00:56:17 +0000
shadowsocks (1.3-1) unstable; urgency=low
* Able to bind connections to specific interface.
* Support more ciphers: aes-128-cfb, aes-192-cfb, aes-256-cfb, bf-cfb, cast5-cfb, des-cfb.
-- Max Lv <max.c.lv@gmail.com> Thu, 16 May 2013 10:51:15 +0800
shadowsocks (1.2-2) unstable; urgency=low
* Close timeouted TCP connections.
-- Max Lv <max.c.lv@gmail.com> Tue, 07 May 2013 14:10:33 +0800
shadowsocks (1.2-1) unstable; urgency=low
* Able to bind connections to specific interface
* Support more ciphers: aes-128-cfb, aes-192-cfb, aes-256-cfb, bf-cfb, cast5-cfb, des-cfb
* Fix a high load issue.
1.2 -- Tue, 07 May 2013 14:10:33 +0800
-- Max Lv <max.c.lv@gmail.com> Thu, 18 Apr 2013 10:52:34 +0800
* Close timeouted TCP connections
* Fix a high load issue
shadowsocks (1.1-1) unstable; urgency=low
1.1 -- Wed, 10 Apr 2013 12:11:36 +0800
* Fix a IPV6 resolve issue.
* Fix a IPV6 resolve issue
-- Max Lv <max.c.lv@gmail.com> Wed, 10 Apr 2013 12:11:36 +0800
1.0 -- Sat, 06 Apr 2013 16:59:15 +0800
shadowsocks (1.0-2) unstable; urgency=low
* Initial release
* Initial release.
-- Max Lv <max.c.lv@gmail.com> Sat, 06 Apr 2013 16:59:15 +0800

20
configure

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for shadowsocks 1.4.2.
# Generated by GNU Autoconf 2.69 for shadowsocks 1.4.3.
#
# Report bugs to <max.c.lv@gmail.com>.
#
@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='shadowsocks'
PACKAGE_TARNAME='shadowsocks'
PACKAGE_VERSION='1.4.2'
PACKAGE_STRING='shadowsocks 1.4.2'
PACKAGE_VERSION='1.4.3'
PACKAGE_STRING='shadowsocks 1.4.3'
PACKAGE_BUGREPORT='max.c.lv@gmail.com'
PACKAGE_URL=''
@ -1324,7 +1324,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures shadowsocks 1.4.2 to adapt to many kinds of systems.
\`configure' configures shadowsocks 1.4.3 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1394,7 +1394,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of shadowsocks 1.4.2:";;
short | recursive ) echo "Configuration of shadowsocks 1.4.3:";;
esac
cat <<\_ACEOF
@ -1510,7 +1510,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
shadowsocks configure 1.4.2
shadowsocks configure 1.4.3
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@ -2033,7 +2033,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by shadowsocks $as_me 1.4.2, which was
It was created by shadowsocks $as_me 1.4.3, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@ -2853,7 +2853,7 @@ fi
# Define the identity of the package.
PACKAGE='shadowsocks'
VERSION='1.4.2'
VERSION='1.4.3'
cat >>confdefs.h <<_ACEOF
@ -15450,7 +15450,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by shadowsocks $as_me 1.4.2, which was
This file was extended by shadowsocks $as_me 1.4.3, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -15516,7 +15516,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
shadowsocks config.status 1.4.2
shadowsocks config.status 1.4.3
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"

2
configure.ac

@ -2,7 +2,7 @@ dnl -*- Autoconf -*-
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ([2.67])
AC_INIT([shadowsocks], [1.4.2], [max.c.lv@gmail.com])
AC_INIT([shadowsocks], [1.4.3], [max.c.lv@gmail.com])
AC_CONFIG_SRCDIR([src/encrypt.c])
AC_CONFIG_HEADERS([config.h])

6
debian/changelog

@ -1,3 +1,9 @@
shadowsocks (1.4.3-1) unstable; urgency=low
* Add tunnel mode with local port forwarding feature.
-- Max Lv <max.c.lv@gmail.com> Fri, 21 Feb 2014 11:52:13 +0900
shadowsocks (1.4.2-1) unstable; urgency=high
* Fix the UDP relay issues.

27
src/Makefile.am

@ -6,7 +6,7 @@ AM_LDFLAGS = -static
SS_COMMON_LIBS = $(top_builddir)/libev/libev.la $(INET_NTOP_LIB)
bin_PROGRAMS = ss-local
bin_PROGRAMS = ss-local ss-tunnel
if !BUILD_WINCOMPAT
bin_PROGRAMS += ss-server
@ -15,26 +15,39 @@ endif
ss_local_SOURCES = utils.c \
jconf.c \
json.c \
encrypt.c \
udprelay.c \
cache.c \
local.c
encrypt.c \
udprelay.c \
cache.c \
local.c
ss_tunnel_SOURCES = utils.c \
jconf.c \
json.c \
encrypt.c \
udprelay.c \
cache.c \
tunnel.c
ss_server_SOURCES = utils.c \
jconf.c \
json.c \
encrypt.c \
udprelay.c \
cache.c \
udprelay.c \
cache.c \
server.c
ss_local_LDADD = $(SS_COMMON_LIBS)
ss_tunnel_LDADD = $(SS_COMMON_LIBS)
ss_server_LDADD = $(SS_COMMON_LIBS)
ss_server_LDADD += $(top_builddir)/libasyncns/libasyncns.la
ss_local_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_LOCAL
ss_tunnel_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_LOCAL -DUDPRELAY_TUNNEL
ss_server_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_REMOTE
if BUILD_WINCOMPAT
ss_local_SOURCES += win32.c
ss_tunnel_SOURCES += win32.c
endif
if BUILD_REDIRECTOR

156
src/Makefile.in

@ -51,10 +51,12 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
bin_PROGRAMS = ss-local$(EXEEXT) $(am__EXEEXT_1) $(am__EXEEXT_2)
bin_PROGRAMS = ss-local$(EXEEXT) ss-tunnel$(EXEEXT) $(am__EXEEXT_1) \
$(am__EXEEXT_2)
@BUILD_WINCOMPAT_FALSE@am__append_1 = ss-server
@BUILD_WINCOMPAT_TRUE@am__append_2 = win32.c
@BUILD_REDIRECTOR_TRUE@am__append_3 = ss-redir
@BUILD_WINCOMPAT_TRUE@am__append_3 = win32.c
@BUILD_REDIRECTOR_TRUE@am__append_4 = ss-redir
subdir = src
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@ -106,6 +108,19 @@ ss_server_DEPENDENCIES = $(am__DEPENDENCIES_2) \
ss_server_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ss_server_CFLAGS) \
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
am__ss_tunnel_SOURCES_DIST = utils.c jconf.c json.c encrypt.c \
udprelay.c cache.c tunnel.c win32.c
@BUILD_WINCOMPAT_TRUE@am__objects_2 = ss_tunnel-win32.$(OBJEXT)
am_ss_tunnel_OBJECTS = ss_tunnel-utils.$(OBJEXT) \
ss_tunnel-jconf.$(OBJEXT) ss_tunnel-json.$(OBJEXT) \
ss_tunnel-encrypt.$(OBJEXT) ss_tunnel-udprelay.$(OBJEXT) \
ss_tunnel-cache.$(OBJEXT) ss_tunnel-tunnel.$(OBJEXT) \
$(am__objects_2)
ss_tunnel_OBJECTS = $(am_ss_tunnel_OBJECTS)
ss_tunnel_DEPENDENCIES = $(am__DEPENDENCIES_2)
ss_tunnel_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ss_tunnel_CFLAGS) \
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@ -119,9 +134,11 @@ CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(ss_local_SOURCES) $(ss_redir_SOURCES) $(ss_server_SOURCES)
SOURCES = $(ss_local_SOURCES) $(ss_redir_SOURCES) $(ss_server_SOURCES) \
$(ss_tunnel_SOURCES)
DIST_SOURCES = $(am__ss_local_SOURCES_DIST) \
$(am__ss_redir_SOURCES_DIST) $(ss_server_SOURCES)
$(am__ss_redir_SOURCES_DIST) $(ss_server_SOURCES) \
$(am__ss_tunnel_SOURCES_DIST)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@ -255,18 +272,22 @@ AM_LDFLAGS = -static
SS_COMMON_LIBS = $(top_builddir)/libev/libev.la $(INET_NTOP_LIB)
ss_local_SOURCES = utils.c jconf.c json.c encrypt.c udprelay.c cache.c \
local.c $(am__append_2)
ss_tunnel_SOURCES = utils.c jconf.c json.c encrypt.c udprelay.c \
cache.c tunnel.c $(am__append_3)
ss_server_SOURCES = utils.c \
jconf.c \
json.c \
encrypt.c \
udprelay.c \
cache.c \
udprelay.c \
cache.c \
server.c
ss_local_LDADD = $(SS_COMMON_LIBS)
ss_tunnel_LDADD = $(SS_COMMON_LIBS)
ss_server_LDADD = $(SS_COMMON_LIBS) \
$(top_builddir)/libasyncns/libasyncns.la
ss_local_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_LOCAL
ss_tunnel_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_LOCAL -DUDPRELAY_TUNNEL
ss_server_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_REMOTE
@BUILD_REDIRECTOR_TRUE@ss_redir_SOURCES = utils.c \
@BUILD_REDIRECTOR_TRUE@ jconf.c \
@ -364,6 +385,9 @@ ss-redir$(EXEEXT): $(ss_redir_OBJECTS) $(ss_redir_DEPENDENCIES) $(EXTRA_ss_redir
ss-server$(EXEEXT): $(ss_server_OBJECTS) $(ss_server_DEPENDENCIES) $(EXTRA_ss_server_DEPENDENCIES)
@rm -f ss-server$(EXEEXT)
$(ss_server_LINK) $(ss_server_OBJECTS) $(ss_server_LDADD) $(LIBS)
ss-tunnel$(EXEEXT): $(ss_tunnel_OBJECTS) $(ss_tunnel_DEPENDENCIES) $(EXTRA_ss_tunnel_DEPENDENCIES)
@rm -f ss-tunnel$(EXEEXT)
$(ss_tunnel_LINK) $(ss_tunnel_OBJECTS) $(ss_tunnel_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@ -390,6 +414,14 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-server.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-udprelay.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-utils.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_tunnel-cache.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_tunnel-encrypt.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_tunnel-jconf.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_tunnel-json.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_tunnel-tunnel.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_tunnel-udprelay.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_tunnel-utils.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_tunnel-win32.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@
.c.o:
@ -623,6 +655,118 @@ ss_server-server.obj: server.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-server.obj `if test -f 'server.c'; then $(CYGPATH_W) 'server.c'; else $(CYGPATH_W) '$(srcdir)/server.c'; fi`
ss_tunnel-utils.o: utils.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-utils.o -MD -MP -MF $(DEPDIR)/ss_tunnel-utils.Tpo -c -o ss_tunnel-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-utils.Tpo $(DEPDIR)/ss_tunnel-utils.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='utils.c' object='ss_tunnel-utils.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
ss_tunnel-utils.obj: utils.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-utils.obj -MD -MP -MF $(DEPDIR)/ss_tunnel-utils.Tpo -c -o ss_tunnel-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-utils.Tpo $(DEPDIR)/ss_tunnel-utils.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='utils.c' object='ss_tunnel-utils.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi`
ss_tunnel-jconf.o: jconf.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-jconf.o -MD -MP -MF $(DEPDIR)/ss_tunnel-jconf.Tpo -c -o ss_tunnel-jconf.o `test -f 'jconf.c' || echo '$(srcdir)/'`jconf.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-jconf.Tpo $(DEPDIR)/ss_tunnel-jconf.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='jconf.c' object='ss_tunnel-jconf.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-jconf.o `test -f 'jconf.c' || echo '$(srcdir)/'`jconf.c
ss_tunnel-jconf.obj: jconf.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-jconf.obj -MD -MP -MF $(DEPDIR)/ss_tunnel-jconf.Tpo -c -o ss_tunnel-jconf.obj `if test -f 'jconf.c'; then $(CYGPATH_W) 'jconf.c'; else $(CYGPATH_W) '$(srcdir)/jconf.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-jconf.Tpo $(DEPDIR)/ss_tunnel-jconf.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='jconf.c' object='ss_tunnel-jconf.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-jconf.obj `if test -f 'jconf.c'; then $(CYGPATH_W) 'jconf.c'; else $(CYGPATH_W) '$(srcdir)/jconf.c'; fi`
ss_tunnel-json.o: json.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-json.o -MD -MP -MF $(DEPDIR)/ss_tunnel-json.Tpo -c -o ss_tunnel-json.o `test -f 'json.c' || echo '$(srcdir)/'`json.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-json.Tpo $(DEPDIR)/ss_tunnel-json.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='json.c' object='ss_tunnel-json.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-json.o `test -f 'json.c' || echo '$(srcdir)/'`json.c
ss_tunnel-json.obj: json.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-json.obj -MD -MP -MF $(DEPDIR)/ss_tunnel-json.Tpo -c -o ss_tunnel-json.obj `if test -f 'json.c'; then $(CYGPATH_W) 'json.c'; else $(CYGPATH_W) '$(srcdir)/json.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-json.Tpo $(DEPDIR)/ss_tunnel-json.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='json.c' object='ss_tunnel-json.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-json.obj `if test -f 'json.c'; then $(CYGPATH_W) 'json.c'; else $(CYGPATH_W) '$(srcdir)/json.c'; fi`
ss_tunnel-encrypt.o: encrypt.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-encrypt.o -MD -MP -MF $(DEPDIR)/ss_tunnel-encrypt.Tpo -c -o ss_tunnel-encrypt.o `test -f 'encrypt.c' || echo '$(srcdir)/'`encrypt.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-encrypt.Tpo $(DEPDIR)/ss_tunnel-encrypt.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encrypt.c' object='ss_tunnel-encrypt.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-encrypt.o `test -f 'encrypt.c' || echo '$(srcdir)/'`encrypt.c
ss_tunnel-encrypt.obj: encrypt.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-encrypt.obj -MD -MP -MF $(DEPDIR)/ss_tunnel-encrypt.Tpo -c -o ss_tunnel-encrypt.obj `if test -f 'encrypt.c'; then $(CYGPATH_W) 'encrypt.c'; else $(CYGPATH_W) '$(srcdir)/encrypt.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-encrypt.Tpo $(DEPDIR)/ss_tunnel-encrypt.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encrypt.c' object='ss_tunnel-encrypt.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-encrypt.obj `if test -f 'encrypt.c'; then $(CYGPATH_W) 'encrypt.c'; else $(CYGPATH_W) '$(srcdir)/encrypt.c'; fi`
ss_tunnel-udprelay.o: udprelay.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-udprelay.o -MD -MP -MF $(DEPDIR)/ss_tunnel-udprelay.Tpo -c -o ss_tunnel-udprelay.o `test -f 'udprelay.c' || echo '$(srcdir)/'`udprelay.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-udprelay.Tpo $(DEPDIR)/ss_tunnel-udprelay.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='udprelay.c' object='ss_tunnel-udprelay.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-udprelay.o `test -f 'udprelay.c' || echo '$(srcdir)/'`udprelay.c
ss_tunnel-udprelay.obj: udprelay.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-udprelay.obj -MD -MP -MF $(DEPDIR)/ss_tunnel-udprelay.Tpo -c -o ss_tunnel-udprelay.obj `if test -f 'udprelay.c'; then $(CYGPATH_W) 'udprelay.c'; else $(CYGPATH_W) '$(srcdir)/udprelay.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-udprelay.Tpo $(DEPDIR)/ss_tunnel-udprelay.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='udprelay.c' object='ss_tunnel-udprelay.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-udprelay.obj `if test -f 'udprelay.c'; then $(CYGPATH_W) 'udprelay.c'; else $(CYGPATH_W) '$(srcdir)/udprelay.c'; fi`
ss_tunnel-cache.o: cache.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-cache.o -MD -MP -MF $(DEPDIR)/ss_tunnel-cache.Tpo -c -o ss_tunnel-cache.o `test -f 'cache.c' || echo '$(srcdir)/'`cache.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-cache.Tpo $(DEPDIR)/ss_tunnel-cache.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cache.c' object='ss_tunnel-cache.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-cache.o `test -f 'cache.c' || echo '$(srcdir)/'`cache.c
ss_tunnel-cache.obj: cache.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-cache.obj -MD -MP -MF $(DEPDIR)/ss_tunnel-cache.Tpo -c -o ss_tunnel-cache.obj `if test -f 'cache.c'; then $(CYGPATH_W) 'cache.c'; else $(CYGPATH_W) '$(srcdir)/cache.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-cache.Tpo $(DEPDIR)/ss_tunnel-cache.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cache.c' object='ss_tunnel-cache.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-cache.obj `if test -f 'cache.c'; then $(CYGPATH_W) 'cache.c'; else $(CYGPATH_W) '$(srcdir)/cache.c'; fi`
ss_tunnel-tunnel.o: tunnel.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-tunnel.o -MD -MP -MF $(DEPDIR)/ss_tunnel-tunnel.Tpo -c -o ss_tunnel-tunnel.o `test -f 'tunnel.c' || echo '$(srcdir)/'`tunnel.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-tunnel.Tpo $(DEPDIR)/ss_tunnel-tunnel.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tunnel.c' object='ss_tunnel-tunnel.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-tunnel.o `test -f 'tunnel.c' || echo '$(srcdir)/'`tunnel.c
ss_tunnel-tunnel.obj: tunnel.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-tunnel.obj -MD -MP -MF $(DEPDIR)/ss_tunnel-tunnel.Tpo -c -o ss_tunnel-tunnel.obj `if test -f 'tunnel.c'; then $(CYGPATH_W) 'tunnel.c'; else $(CYGPATH_W) '$(srcdir)/tunnel.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-tunnel.Tpo $(DEPDIR)/ss_tunnel-tunnel.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tunnel.c' object='ss_tunnel-tunnel.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-tunnel.obj `if test -f 'tunnel.c'; then $(CYGPATH_W) 'tunnel.c'; else $(CYGPATH_W) '$(srcdir)/tunnel.c'; fi`
ss_tunnel-win32.o: win32.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-win32.o -MD -MP -MF $(DEPDIR)/ss_tunnel-win32.Tpo -c -o ss_tunnel-win32.o `test -f 'win32.c' || echo '$(srcdir)/'`win32.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-win32.Tpo $(DEPDIR)/ss_tunnel-win32.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='win32.c' object='ss_tunnel-win32.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-win32.o `test -f 'win32.c' || echo '$(srcdir)/'`win32.c
ss_tunnel-win32.obj: win32.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-win32.obj -MD -MP -MF $(DEPDIR)/ss_tunnel-win32.Tpo -c -o ss_tunnel-win32.obj `if test -f 'win32.c'; then $(CYGPATH_W) 'win32.c'; else $(CYGPATH_W) '$(srcdir)/win32.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-win32.Tpo $(DEPDIR)/ss_tunnel-win32.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='win32.c' object='ss_tunnel-win32.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-win32.obj `if test -f 'win32.c'; then $(CYGPATH_W) 'win32.c'; else $(CYGPATH_W) '$(srcdir)/win32.c'; fi`
mostlyclean-libtool:
-rm -f *.lo

3
src/include.h

@ -4,6 +4,9 @@
int udprelay_init(const char *server_host, const char *server_port,
#ifdef UDPRELAY_LOCAL
const char *remote_host, const char *remote_port,
#ifdef UDPRELAY_TUNNEL
const addr_t tunnel_addr,
#endif
#endif
#ifdef UDPRELAY_REMOTE
asyncns_t *asyncns,

15
src/jconf.c

@ -35,7 +35,16 @@ static char *to_string(const json_value *value)
return 0;
}
static void parse_addr(const char *str, remote_addr_t *addr) {
void free_addr(addr_t *addr)
{
free(addr->host);
free(addr->port);
addr->host = NULL;
addr->port = NULL;
}
void parse_addr(const char *str, addr_t *addr)
{
int ret = -1, n = 0;
char *pch;
pch = strchr(str, ':');
@ -52,13 +61,13 @@ static void parse_addr(const char *str, remote_addr_t *addr) {
}
if (ret == -1)
{
addr->host = str;
addr->host = strdup(str);
addr->port = NULL;
}
else
{
addr->host = ss_strndup(str, ret);
addr->port = str + ret + 1;
addr->port = strdup(str + ret + 1);
}
}

10
src/jconf.h

@ -8,14 +8,14 @@
typedef struct
{
const char *host;
const char *port;
} remote_addr_t;
char *host;
char *port;
} addr_t;
typedef struct
{
int remote_num;
remote_addr_t remote_addr[MAX_REMOTE_NUM];
addr_t remote_addr[MAX_REMOTE_NUM];
char *remote_port;
char *local_addr;
char *local_port;
@ -25,5 +25,7 @@ typedef struct
} jconf_t;
jconf_t *read_jconf(const char* file);
void parse_addr(const char *str, addr_t *addr);
void free_addr(addr_t *addr);
#endif // _JCONF_H

5
src/local.c

@ -766,7 +766,6 @@ static void accept_cb (EV_P_ ev_io *w, int revents)
if (sockfd < 0)
{
ERROR("socket");
close(sockfd);
freeaddrinfo(res);
return;
}
@ -808,7 +807,7 @@ int main (int argc, char **argv)
char *iface = NULL;
int remote_num = 0;
remote_addr_t remote_addr[MAX_REMOTE_NUM];
addr_t remote_addr[MAX_REMOTE_NUM];
char *remote_port = NULL;
opterr = 0;
@ -929,7 +928,7 @@ int main (int argc, char **argv)
// Setup proxy context
struct listen_ctx listen_ctx;
listen_ctx.remote_num = remote_num;
listen_ctx.remote_addr = malloc(sizeof(remote_addr_t) * remote_num);
listen_ctx.remote_addr = malloc(sizeof(addr_t) * remote_num);
while (remote_num > 0)
{
int index = --remote_num;

2
src/local.h

@ -10,7 +10,7 @@
struct listen_ctx
{
ev_io io;
remote_addr_t *remote_addr;
addr_t *remote_addr;
char *iface;
int remote_num;
int method;

5
src/redir.c

@ -630,7 +630,6 @@ static void accept_cb (EV_P_ ev_io *w, int revents)
if (sockfd < 0)
{
ERROR("socket");
close(sockfd);
freeaddrinfo(res);
return;
}
@ -670,7 +669,7 @@ int main (int argc, char **argv)
char *conf_path = NULL;
int remote_num = 0;
remote_addr_t remote_addr[MAX_REMOTE_NUM];
addr_t remote_addr[MAX_REMOTE_NUM];
char *remote_port = NULL;
opterr = 0;
@ -778,7 +777,7 @@ int main (int argc, char **argv)
// Setup proxy context
struct listen_ctx listen_ctx;
listen_ctx.remote_num = remote_num;
listen_ctx.remote_addr = malloc(sizeof(remote_addr_t) * remote_num);
listen_ctx.remote_addr = malloc(sizeof(addr_t) * remote_num);
while (remote_num > 0)
{
int index = --remote_num;

2
src/redir.h

@ -8,7 +8,7 @@
struct listen_ctx
{
ev_io io;
remote_addr_t *remote_addr;
addr_t *remote_addr;
int remote_num;
int timeout;
int fd;

884
src/tunnel.c

@ -0,0 +1,884 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <locale.h>
#include <signal.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#ifndef __MINGW32__
#include <errno.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <pthread.h>
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H) && defined(__linux__)
#include <net/if.h>
#include <sys/ioctl.h>
#define SET_INTERFACE
#endif
#ifdef __MINGW32__
#include "win32.h"
#endif
#include "utils.h"
#include "tunnel.h"
#ifndef EAGAIN
#define EAGAIN EWOULDBLOCK
#endif
#ifndef EWOULDBLOCK
#define EWOULDBLOCK EAGAIN
#endif
#ifndef BUF_SIZE
#define BUF_SIZE 512
#endif
int verbose = 0;
int udprelay = 0;
#ifndef __MINGW32__
static int setnonblocking(int fd)
{
int flags;
if (-1 ==(flags = fcntl(fd, F_GETFL, 0)))
flags = 0;
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
#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;
struct addrinfo *result, *rp;
int s, listen_sock;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */
hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */
s = getaddrinfo(addr, port, &hints, &result);
if (s != 0)
{
LOGD("getaddrinfo: %s", gai_strerror(s));
return -1;
}
for (rp = result; rp != NULL; rp = rp->ai_next)
{
listen_sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (listen_sock == -1)
continue;
int opt = 1;
setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
setsockopt(listen_sock, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
#ifdef SO_NOSIGPIPE
setsockopt(listen_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif
s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);
if (s == 0)
{
/* We managed to bind successfully! */
break;
}
else
{
ERROR("bind");
}
close(listen_sock);
}
if (rp == NULL)
{
LOGE("Could not bind");
return -1;
}
freeaddrinfo(result);
return listen_sock;
}
static void server_recv_cb (EV_P_ ev_io *w, int revents)
{
struct server_ctx *server_recv_ctx = (struct server_ctx *)w;
struct server *server = server_recv_ctx->server;
struct remote *remote = server->remote;
if (remote == NULL)
{
close_and_free_server(EV_A_ server);
return;
}
ssize_t r = recv(server->fd, remote->buf, BUF_SIZE, 0);
if (r == 0)
{
// connection closed
remote->buf_len = 0;
remote->buf_idx = 0;
close_and_free_server(EV_A_ server);
if (remote != NULL)
{
ev_io_start(EV_A_ &remote->send_ctx->io);
}
return;
}
else if(r < 0)
{
if (errno == EAGAIN || errno == EWOULDBLOCK)
{
// no data
// continue to wait for recv
return;
}
else
{
ERROR("server recv");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
}
remote->buf = ss_encrypt(BUF_SIZE, remote->buf, &r, server->e_ctx);
if (remote->buf == NULL)
{
LOGE("invalid password or cipher");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
int s = send(remote->fd, remote->buf, r, 0);
if(s == -1)
{
if (errno == EAGAIN || errno == EWOULDBLOCK)
{
// no data, wait for send
remote->buf_len = r;
remote->buf_idx = 0;
ev_io_stop(EV_A_ &server_recv_ctx->io);
ev_io_start(EV_A_ &remote->send_ctx->io);
return;
}
else
{
ERROR("send");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
}
else if(s < r)
{
remote->buf_len = r - s;
remote->buf_idx = s;
ev_io_stop(EV_A_ &server_recv_ctx->io);
ev_io_start(EV_A_ &remote->send_ctx->io);
return;
}
}
static void server_send_cb (EV_P_ ev_io *w, int revents)
{
struct server_ctx *server_send_ctx = (struct server_ctx *)w;
struct server *server = server_send_ctx->server;
struct remote *remote = server->remote;
if (server->buf_len == 0)
{
// close and free
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
else
{
// has data to send
ssize_t s = send(server->fd, server->buf + server->buf_idx,
server->buf_len, 0);
if (s < 0)
{
if (errno != EAGAIN && errno != EWOULDBLOCK)
{
ERROR("send");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
}
return;
}
else if (s < server->buf_len)
{
// partly sent, move memory, wait for the next time to send
server->buf_len -= s;
server->buf_idx += s;
return;
}
else
{
// all sent out, wait for reading
server->buf_len = 0;
server->buf_idx = 0;
ev_io_stop(EV_A_ &server_send_ctx->io);
if (remote != NULL)
{
ev_io_start(EV_A_ &remote->recv_ctx->io);
}
else
{
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
}
}
}
static void remote_timeout_cb(EV_P_ ev_timer *watcher, int revents)
{
struct remote_ctx *remote_ctx = (struct remote_ctx *) (((void*)watcher)
- sizeof(ev_io));
struct remote *remote = remote_ctx->remote;
struct server *server = remote->server;
LOGD("remote timeout");
ev_timer_stop(EV_A_ watcher);
if (server == NULL)
{
close_and_free_remote(EV_A_ remote);
return;
}
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
}
static void remote_recv_cb (EV_P_ ev_io *w, int revents)
{
struct remote_ctx *remote_recv_ctx = (struct remote_ctx *)w;
struct remote *remote = remote_recv_ctx->remote;
struct server *server = remote->server;
if (server == NULL)
{
close_and_free_remote(EV_A_ remote);
return;
}
ssize_t r = recv(remote->fd, server->buf, BUF_SIZE, 0);
if (r == 0)
{
// connection closed
server->buf_len = 0;
server->buf_idx = 0;
close_and_free_remote(EV_A_ remote);
if (server != NULL)
{
ev_io_start(EV_A_ &server->send_ctx->io);
}
return;
}
else if(r < 0)
{
if (errno == EAGAIN || errno == EWOULDBLOCK)
{
// no data
// continue to wait for recv
return;
}
else
{
ERROR("remote recv");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
}
server->buf = ss_decrypt(BUF_SIZE, server->buf, &r, server->d_ctx);
if (server->buf == NULL)
{
LOGE("invalid password or cipher");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
int s = send(server->fd, server->buf, r, 0);
if (s == -1)
{
if (errno == EAGAIN || errno == EWOULDBLOCK)
{
// no data, wait for send
server->buf_len = r;
server->buf_idx = 0;
ev_io_stop(EV_A_ &remote_recv_ctx->io);
ev_io_start(EV_A_ &server->send_ctx->io);
return;
}
else
{
ERROR("send");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
}
else if (s < r)
{
server->buf_len = r - s;
server->buf_idx = s;
ev_io_stop(EV_A_ &remote_recv_ctx->io);
ev_io_start(EV_A_ &server->send_ctx->io);
return;
}
}
static void remote_send_cb (EV_P_ ev_io *w, int revents)
{
struct remote_ctx *remote_send_ctx = (struct remote_ctx *)w;
struct remote *remote = remote_send_ctx->remote;
struct server *server = remote->server;
if (!remote_send_ctx->connected)
{
struct sockaddr_storage addr;
socklen_t len = sizeof addr;
int r = getpeername(remote->fd, (struct sockaddr*)&addr, &len);
if (r == 0)
{
remote_send_ctx->connected = 1;
ev_io_stop(EV_A_ &remote_send_ctx->io);
ev_timer_stop(EV_A_ &remote_send_ctx->watcher);
// send destaddr
char *addr_to_send = malloc(BUF_SIZE);
ssize_t addr_len = 0;
struct sockaddr *sa = &server->destaddr;
addr_to_send[addr_len++] = 1;
if (sa->sa_family == AF_INET)
{
// handle IPv4
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
size_t in_addr_len = sizeof(struct in_addr);
memcpy(addr_to_send + addr_len, &sin->sin_addr, in_addr_len);
addr_len += in_addr_len;
memcpy(addr_to_send + addr_len, &sin->sin_port, 2);
addr_len += 2;
}
else if (sa->sa_family == AF_INET6)
{
// handle IPv6
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
size_t in6_addr_len = sizeof(struct in6_addr);
memcpy(addr_to_send + addr_len, &sin6->sin6_addr, in6_addr_len);
addr_len += in6_addr_len;
memcpy(addr_to_send + addr_len, &sin6->sin6_port, 2);
addr_len += 2;
}
else
{
LOGE("unsupported addr type");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
addr_to_send = ss_encrypt(BUF_SIZE, addr_to_send, &addr_len, server->e_ctx);
if (addr_to_send == NULL)
{
LOGE("invalid password or cipher");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
int s = send(remote->fd, addr_to_send, addr_len, 0);
free(addr_to_send);
if (s < addr_len)
{
LOGE("failed to send remote addr.");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
}
ev_io_start(EV_A_ &remote->recv_ctx->io);
ev_io_start(EV_A_ &server->recv_ctx->io);
return;
}
else
{
ERROR("getpeername");
// not connected
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
}
else
{
if (remote->buf_len == 0)
{
// close and free
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
else
{
// has data to send
ssize_t s = send(remote->fd, remote->buf + remote->buf_idx,
remote->buf_len, 0);
if (s < 0)
{
if (errno != EAGAIN && errno != EWOULDBLOCK)
{
ERROR("send");
// close and free
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
}
return;
}
else if (s < remote->buf_len)
{
// partly sent, move memory, wait for the next time to send
remote->buf_len -= s;
remote->buf_idx += s;
return;
}
else
{
// all sent out, wait for reading
remote->buf_len = 0;
remote->buf_idx = 0;
ev_io_stop(EV_A_ &remote_send_ctx->io);
if (server != NULL)
{
ev_io_start(EV_A_ &server->recv_ctx->io);
}
else
{
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
}
}
}
}
struct remote* new_remote(int fd, int timeout)
{
struct remote *remote;
remote = malloc(sizeof(struct remote));
remote->buf = malloc(BUF_SIZE);
remote->recv_ctx = malloc(sizeof(struct remote_ctx));
remote->send_ctx = malloc(sizeof(struct remote_ctx));
remote->fd = fd;
ev_io_init(&remote->recv_ctx->io, remote_recv_cb, fd, EV_READ);
ev_io_init(&remote->send_ctx->io, remote_send_cb, fd, EV_WRITE);
ev_timer_init(&remote->send_ctx->watcher, remote_timeout_cb, timeout, 0);
remote->recv_ctx->remote = remote;
remote->recv_ctx->connected = 0;
remote->send_ctx->remote = remote;
remote->send_ctx->connected = 0;
remote->buf_len = 0;
remote->buf_idx = 0;
return remote;
}
static void free_remote(struct remote *remote)
{
if (remote != NULL)
{
if (remote->server != NULL)
{
remote->server->remote = NULL;
}
if (remote->buf)
{
free(remote->buf);
}
free(remote->recv_ctx);
free(remote->send_ctx);
free(remote);
}
}
static void close_and_free_remote(EV_P_ struct remote *remote)
{
if (remote != NULL)
{
ev_timer_stop(EV_A_ &remote->send_ctx->watcher);
ev_io_stop(EV_A_ &remote->send_ctx->io);
ev_io_stop(EV_A_ &remote->recv_ctx->io);
close(remote->fd);
free_remote(remote);
}
}
struct server* new_server(int fd, int method)
{
struct server *server;
server = malloc(sizeof(struct server));
server->buf = malloc(BUF_SIZE);
server->recv_ctx = malloc(sizeof(struct server_ctx));
server->send_ctx = malloc(sizeof(struct server_ctx));
server->fd = fd;
ev_io_init(&server->recv_ctx->io, server_recv_cb, fd, EV_READ);
ev_io_init(&server->send_ctx->io, server_send_cb, fd, EV_WRITE);
server->recv_ctx->server = server;
server->recv_ctx->connected = 0;
server->send_ctx->server = server;
server->send_ctx->connected = 0;
if (method)
{
server->e_ctx = malloc(sizeof(struct enc_ctx));
server->d_ctx = malloc(sizeof(struct enc_ctx));
enc_ctx_init(method, server->e_ctx, 1);
enc_ctx_init(method, server->d_ctx, 0);
}
else
{
server->e_ctx = NULL;
server->d_ctx = NULL;
}
server->buf_len = 0;
server->buf_idx = 0;
return server;
}
static void free_server(struct server *server)
{
if (server != NULL)
{
if (server->remote != NULL)
{
server->remote->server = NULL;
}
if (server->e_ctx != NULL)
{
cipher_context_release(&server->e_ctx->evp);
free(server->e_ctx);
}
if (server->d_ctx != NULL)
{
cipher_context_release(&server->d_ctx->evp);
free(server->d_ctx);
}
if (server->buf)
{
free(server->buf);
}
free(server->recv_ctx);
free(server->send_ctx);
free(server);
}
}
static void close_and_free_server(EV_P_ struct server *server)
{
if (server != NULL)
{
ev_io_stop(EV_A_ &server->send_ctx->io);
ev_io_stop(EV_A_ &server->recv_ctx->io);
close(server->fd);
free_server(server);
}
}
static void accept_cb (EV_P_ ev_io *w, int revents)
{
struct listen_ctx *listener = (struct listen_ctx *)w;
int serverfd = accept(listener->fd, NULL, NULL);
if (serverfd == -1)
{
ERROR("accept");
return;
}
setnonblocking(serverfd);
int opt = 1;
setsockopt(serverfd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
#ifdef SO_NOSIGPIPE
setsockopt(serverfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif
struct addrinfo hints, *res, *dest;
int sockfd;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
int index = rand() % listener->remote_num;
if (verbose)
{
LOGD("connect to %s:%s", listener->remote_addr[index].host, listener->remote_addr[index].port);
}
int err = getaddrinfo(listener->remote_addr[index].host, listener->remote_addr[index].port, &hints, &res);
if (err)
{
ERROR("getaddrinfo");
return;
}
err = getaddrinfo(listener->tunnel_addr.host, listener->tunnel_addr.port, &hints, &dest);
if (err)
{
freeaddrinfo(res);
ERROR("getaddrinfo");
return;
}
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sockfd < 0)
{
ERROR("socket");
freeaddrinfo(res);
freeaddrinfo(dest);
return;
}
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
#ifdef SO_NOSIGPIPE
setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif
// Setup
setnonblocking(sockfd);
#ifdef SET_INTERFACE
if (listener->iface) setinterface(sockfd, listener->iface);
#endif
struct server *server = new_server(serverfd, listener->method);
struct remote *remote = new_remote(sockfd, listener->timeout);
server->destaddr = *dest->ai_addr;
server->remote = remote;
remote->server = server;
connect(sockfd, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
freeaddrinfo(dest);
// listen to remote connected event
ev_io_start(EV_A_ &remote->send_ctx->io);
ev_timer_start(EV_A_ &remote->send_ctx->watcher);
}
int main (int argc, char **argv)
{
int i, c;
int pid_flags = 0;
char *local_port = NULL;
char *local_addr = NULL;
char *password = NULL;
char *timeout = NULL;
char *method = NULL;
char *pid_path = NULL;
char *conf_path = NULL;
char *iface = NULL;
int remote_num = 0;
addr_t remote_addr[MAX_REMOTE_NUM];
char *remote_port = NULL;
addr_t tunnel_addr = {.host = NULL, .port = NULL};
char *tunnel_addr_str = NULL;
opterr = 0;
while ((c = getopt (argc, argv, "f:s:p:l:k:t:m:i:c:b:L:uv")) != -1)
{
switch (c)
{
case 's':
remote_addr[remote_num].host = optarg;
remote_addr[remote_num++].port = NULL;
break;
case 'p':
remote_port = optarg;
break;
case 'l':
local_port = optarg;
break;
case 'k':
password = optarg;
break;
case 'f':
pid_flags = 1;
pid_path = optarg;
break;
case 't':
timeout = optarg;
break;
case 'm':
method = optarg;
break;
case 'c':
conf_path = optarg;
break;
case 'i':
iface = optarg;
break;
case 'b':
local_addr = optarg;
break;
case 'u':
udprelay = 1;
break;
case 'L':
tunnel_addr_str = optarg;
break;
case 'v':
verbose = 1;
break;
}
}
if (opterr)
{
usage();
exit(EXIT_FAILURE);
}
if (conf_path != NULL)
{
jconf_t *conf = read_jconf(conf_path);
if (remote_num == 0)
{
remote_num = conf->remote_num;
for (i = 0; i < remote_num; i++)
{
remote_addr[i] = conf->remote_addr[i];
}
}
if (remote_port == NULL) remote_port = conf->remote_port;
if (local_addr == NULL) local_addr = conf->local_addr;
if (local_port == NULL) local_port = conf->local_port;
if (password == NULL) password = conf->password;
if (method == NULL) method = conf->method;
if (timeout == NULL) timeout = conf->timeout;
}
if (remote_num == 0 || remote_port == NULL || tunnel_addr_str == NULL ||
local_port == NULL || password == NULL)
{
usage();
exit(EXIT_FAILURE);
}
if (timeout == NULL) timeout = "10";
if (local_addr == NULL) local_addr = "0.0.0.0";
if (pid_flags)
{
USE_SYSLOG(argv[0]);
demonize(pid_path);
}
// parse tunnel addr
parse_addr(tunnel_addr_str, &tunnel_addr);
#ifdef __MINGW32__
winsock_init();
#else
// ignore SIGPIPE
signal(SIGPIPE, SIG_IGN);
signal(SIGABRT, SIG_IGN);
#endif
// Setup keys
LOGD("initialize ciphers... %s", method);
int m = enc_init(password, method);
// Setup socket
int listenfd;
listenfd = create_and_bind(local_addr, local_port);
if (listenfd < 0)
{
FATAL("bind() error..");
}
if (listen(listenfd, SOMAXCONN) == -1)
{
FATAL("listen() error.");
}
setnonblocking(listenfd);
LOGD("server listening at port %s.", local_port);
// Setup proxy context
struct listen_ctx listen_ctx;
listen_ctx.tunnel_addr = tunnel_addr;
listen_ctx.remote_num = remote_num;
listen_ctx.remote_addr = malloc(sizeof(addr_t) * remote_num);
while (remote_num > 0)
{
int index = --remote_num;
if (remote_addr[index].port == NULL) remote_addr[index].port = remote_port;
listen_ctx.remote_addr[index] = remote_addr[index];
}
listen_ctx.timeout = atoi(timeout);
listen_ctx.fd = listenfd;
listen_ctx.iface = iface;
listen_ctx.method = m;
struct ev_loop *loop = ev_default_loop(0);
if (!loop)
{
FATAL("ev_loop error.");
}
ev_io_init (&listen_ctx.io, accept_cb, listenfd, EV_READ);
ev_io_start (loop, &listen_ctx.io);
// Setup UDP
if (udprelay)
{
LOGD("udprelay enabled.");
udprelay_init(local_addr, local_port, remote_addr[0].host, remote_addr[0].port,
tunnel_addr, m, listen_ctx.timeout, iface);
}
ev_run (loop, 0);
#ifdef __MINGW32__
winsock_cleanup();
#endif
return 0;
}

76
src/tunnel.h

@ -0,0 +1,76 @@
#ifndef _LOCAL_H
#define _LOCAL_H
#include <ev.h>
#include "encrypt.h"
#include "jconf.h"
#include "include.h"
struct listen_ctx
{
ev_io io;
addr_t tunnel_addr;
addr_t *remote_addr;
char *iface;
int remote_num;
int method;
int timeout;
int fd;
struct sockaddr sock;
};
struct server_ctx
{
ev_io io;
int connected;
struct server *server;
};
struct server
{
int fd;
int buf_len;
int buf_idx;
char *buf; // server send from, remote recv into
struct enc_ctx *e_ctx;
struct enc_ctx *d_ctx;
struct server_ctx *recv_ctx;
struct server_ctx *send_ctx;
struct remote *remote;
struct sockaddr destaddr;
};
struct remote_ctx
{
ev_io io;
ev_timer watcher;
int connected;
struct remote *remote;
};
struct remote
{
int fd;
int buf_len;
int buf_idx;
char *buf; // remote send from, server recv into
struct remote_ctx *recv_ctx;
struct remote_ctx *send_ctx;
struct server *server;
};
static void accept_cb (EV_P_ ev_io *w, int revents);
static void server_recv_cb (EV_P_ ev_io *w, int revents);
static void server_send_cb (EV_P_ ev_io *w, int revents);
static void remote_recv_cb (EV_P_ ev_io *w, int revents);
static void remote_send_cb (EV_P_ ev_io *w, int revents);
static void free_remote(struct remote *remote);
static void close_and_free_remote(EV_P_ struct remote *remote);
static void free_server(struct server *server);
static void close_and_free_server(EV_P_ struct server *server);
struct remote* new_remote(int fd, int timeout);
struct server* new_server(int fd, int method);
#endif // _TUNNEL_H

48
src/udprelay.c

@ -473,6 +473,11 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents)
goto CLEAN_UP;
}
#ifdef UDPRELAY_TUNNEL
// Construct packet
buf_len -= addr_header_len;
memmove(buf, buf + addr_header_len, buf_len);
#else
// Construct packet
char *tmpbuf = malloc(buf_len + 3);
memset(tmpbuf, 0, 3);
@ -481,6 +486,7 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents)
buf = tmpbuf;
buf_len += 3;
#endif
#endif
#ifdef UDPRELAY_REMOTE
// Construct packet
@ -538,8 +544,10 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents)
#endif
#ifdef UDPRELAY_LOCAL
#ifndef UDPRELAY_TUNNEL
uint8_t frag = *(uint8_t*)(buf + 2);
offset += 3;
#endif
#endif
/*
@ -581,6 +589,29 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents)
*
*/
#ifdef UDPRELAY_TUNNEL
char addr_header[256] = {0};
char* host = server_ctx->tunnel_addr.host;
char* port = server_ctx->tunnel_addr.port;
int host_len = strlen(host);
uint16_t port_num = (uint16_t)atoi(port);
uint16_t port_net_num = htons(port_num);
int addr_header_len = 2 + host_len + 2;
// initialize the addr header
addr_header[0] = 3;
addr_header[1] = host_len;
memcpy(addr_header + 2, host, host_len);
memcpy(addr_header + 2 + host_len, &port_net_num, 2);
// reconstruct the buffer
char *tmp = malloc(buf_len + addr_header_len);
memcpy(tmp, addr_header, addr_header_len);
memcpy(tmp + addr_header_len, buf, buf_len);
free(buf);
buf = tmp;
#else
char host[256] = {0};
char port[64] = {0};
@ -592,6 +623,8 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents)
goto CLEAN_UP;
}
char *addr_header = buf + offset;
#endif
char *key = hash_key(addr_header, addr_header_len, &src_addr);
struct cache *conn_cache = server_ctx->conn_cache;
@ -615,11 +648,13 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents)
#ifdef UDPRELAY_LOCAL
#ifndef UDPRELAY_TUNNEL
if (frag)
{
LOGE("drop a message since frag is not 0, but %d", frag);
goto CLEAN_UP;
}
#endif
if (remote_ctx == NULL)
{
@ -675,8 +710,11 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents)
freeaddrinfo(result);
}
buf_len -= offset;
memmove(buf, buf + offset, buf_len);
if (offset > 0)
{
buf_len -= offset;
memmove(buf, buf + offset, buf_len);
}
buf = ss_encrypt_all(BUF_SIZE, buf, &buf_len, server_ctx->method);
@ -750,6 +788,9 @@ void free_cb(void *element)
int udprelay_init(const char *server_host, const char *server_port,
#ifdef UDPRELAY_LOCAL
const char *remote_host, const char *remote_port,
#ifdef UDPRELAY_TUNNEL
const addr_t tunnel_addr,
#endif
#endif
#ifdef UDPRELAY_REMOTE
asyncns_t *asyncns,
@ -783,6 +824,9 @@ int udprelay_init(const char *server_host, const char *server_port,
#ifdef UDPRELAY_LOCAL
server_ctx->remote_host = remote_host;
server_ctx->remote_port = remote_port;
#ifdef UDPRELAY_TUNNEL
server_ctx->tunnel_addr = tunnel_addr;
#endif
#endif
#ifdef UDPRELAY_REMOTE
server_ctx->asyncns = asyncns;

3
src/udprelay.h

@ -32,6 +32,9 @@ struct server_ctx
#ifdef UDPRELAY_LOCAL
const char *remote_host;
const char *remote_port;
#ifdef UDPRELAY_TUNNEL
addr_t tunnel_addr;
#endif
#endif
};

13
src/utils.c

@ -82,9 +82,10 @@ void usage()
{
printf("\n");
printf("shadowsocks-libev %s\n\n", VERSION);
printf(" maintained by Max Lv <max.c.lv@gmail.com>\n\n");
printf(" maintained by Max Lv <max.c.lv@gmail.com>\n");
printf(" and Linus Yang <laokongzi@gmail.com>\n\n");
printf(" usage:\n\n");
printf(" ss-[local|redir|server]\n");
printf(" ss-[local|redir|server|tunnel]\n");
printf(" -s <server_host> host name or ip address of your remote server\n");
printf(" -p <server_port> port number of your remote server\n");
printf(" -l <local_port> port number of your local server\n");
@ -100,11 +101,13 @@ void usage()
printf(" [-c <config_file>] json format config file\n");
printf("\n");
printf(" [-i <interface>] specific network interface to bind,\n");
printf(" only available in local and server modes\n");
printf(" not available in redir mode\n");
printf(" [-b <local_address>] specific local address to bind,\n");
printf(" only available in local and redir modes\n");
printf(" not available in server mode\n");
printf(" [-u] udprelay mode to supprot udp traffic\n");
printf(" only available in local and server modes\n");
printf(" not available in redir mode\n");
printf(" [-L <addr>:<port>] setup a local port forwarding tunnel\n");
printf(" only available in tunnel mode\n");
printf(" [-v] verbose mode, debug output in console\n");
printf("\n");
}

Loading…
Cancel
Save