Skip to content

Commit

Permalink
Merge pull request #330 from shadowsocks/unix-socket
Browse files Browse the repository at this point in the history
Pass the file descriptor through unix domain socket
  • Loading branch information
madeye committed Jul 22, 2015
2 parents f2c39bd + 2f7424d commit faad961
Show file tree
Hide file tree
Showing 14 changed files with 797 additions and 12 deletions.
2 changes: 1 addition & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ try pushd src/main

# Build
try $ANDROID_NDK_HOME/ndk-build clean
try $ANDROID_NDK_HOME/ndk-build
try $ANDROID_NDK_HOME/ndk-build -j8

# copy executables
rm -rf assets/armeabi-v7a
Expand Down
2 changes: 1 addition & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
resolvers += Resolver.url("scalasbt releases", new URL("http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-snapshots"))(Resolver.ivyStylePatterns)

addSbtPlugin("com.hanhuy.sbt" % "android-sdk-plugin" % "1.4.0")
addSbtPlugin("com.hanhuy.sbt" % "android-sdk-plugin" % "1.4.6")

resolvers += Resolver.sbtPluginRepo("snapshots")

Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/github/shadowsocks/System.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,5 @@ public class System {

public static native void exec(String cmd);
public static native String getABI();
public static native int sendfd(int fd);
}
25 changes: 22 additions & 3 deletions src/main/jni/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,21 @@ LOCAL_CFLAGS := -O2 -I$(LOCAL_PATH)/libevent \

include $(BUILD_STATIC_LIBRARY)

########################################################
## libancillary
########################################################

include $(CLEAR_VARS)

ANCILLARY_SOURCE := fd_recv.c fd_send.c

LOCAL_MODULE := libancillary
LOCAL_CFLAGS += -O2 -I$(LOCAL_PATH)/libancillary

LOCAL_SRC_FILES := $(addprefix libancillary/, $(ANCILLARY_SOURCE))

include $(BUILD_STATIC_LIBRARY)

########################################################
## libipset
########################################################
Expand Down Expand Up @@ -287,12 +302,13 @@ include $(CLEAR_VARS)

LOCAL_MODULE:= system

LOCAL_SRC_FILES:= \
system.cpp
LOCAL_C_INCLUDES:= $(LOCAL_PATH)/libancillary

LOCAL_SRC_FILES:= system.cpp

LOCAL_LDLIBS := -ldl -llog

LOCAL_STATIC_LIBRARIES := cpufeatures
LOCAL_STATIC_LIBRARIES := cpufeatures libancillary

include $(BUILD_SHARED_LIBRARY)

Expand All @@ -309,7 +325,10 @@ LOCAL_CFLAGS += -DBADVPN_LITTLE_ENDIAN -DBADVPN_THREAD_SAFE
LOCAL_CFLAGS += -DNDEBUG -DANDROID
# LOCAL_CFLAGS += -DTUN2SOCKS_JNI

LOCAL_STATIC_LIBRARIES := libancillary

LOCAL_C_INCLUDES:= \
$(LOCAL_PATH)/libancillary \
$(LOCAL_PATH)/badvpn/lwip/src/include/ipv4 \
$(LOCAL_PATH)/badvpn/lwip/src/include/ipv6 \
$(LOCAL_PATH)/badvpn/lwip/src/include \
Expand Down
52 changes: 50 additions & 2 deletions src/main/jni/badvpn/tun2socks/tun2socks.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,13 @@
#include <generated/blog_channel_tun2socks.h>

#ifdef ANDROID

#include <ancillary.h>

#include <sys/prctl.h>
#include <sys/un.h>
#include <structure/BAVL.h>

BAVL connections_tree;
typedef struct {
BAddr local_addr;
Expand Down Expand Up @@ -408,7 +412,6 @@ int main (int argc, char **argv)
prctl(PR_SET_NAME, "com.github.shadowsocks");
}


// handle --help and --version
if (options.help) {
print_version();
Expand Down Expand Up @@ -490,11 +493,56 @@ int main (int argc, char **argv)

#ifdef ANDROID
// use supplied file descriptor

int sock, fd;
struct sockaddr_un addr;

if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
BLog(BLOG_ERROR, "socket() failed: %s (socket sock = %d)\n", strerror(errno), sock);
goto fail2;
}

char *path = "/data/data/com.github.shadowsocks/sock_path";
unlink(path);
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, path, sizeof(addr.sun_path)-1);

if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
BLog(BLOG_ERROR, "bind() failed: %s (sock = %d)\n", strerror(errno), sock);
close(sock);
goto fail2;
}

if (listen(sock, 5) == -1) {
BLog(BLOG_ERROR, "listen() failed: %s (sock = %d)\n", strerror(errno), sock);
close(sock);
goto fail2;
}

for (;;) {
int sock2;
struct sockaddr_un remote;
int t = sizeof(remote);
if ((sock2 = accept(sock, (struct sockaddr *)&remote, &t)) == -1) {
BLog(BLOG_ERROR, "accept() failed: %s (sock = %d)\n", strerror(errno), sock);
continue;
}
if (ancil_recv_fd(sock2, &fd)) {
BLog(BLOG_ERROR, "ancil_recv_fd: %s (sock = %d)\n", strerror(errno), sock2);
close(sock2);
} else {
close(sock2);
BLog(BLOG_INFO, "received fd = %d", fd);
break;
}
}
close(sock);

struct BTap_init_data init_data;
init_data.dev_type = BTAP_DEV_TUN;
init_data.init_type = BTAP_INIT_FD;
init_data.init.fd.fd = options.tun_fd;
init_data.init.fd.fd = fd;
init_data.init.fd.mtu = options.tun_mtu;

if (!BTap_Init2(&device, &ss, init_data, device_error_handler, NULL)) {
Expand Down
139 changes: 139 additions & 0 deletions src/main/jni/libancillary/API
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
This library provide an easy interface to the black magic that can be done
on Unix domain sockets, like passing file descriptors from one process to
another.

Programs that uses this library should include the ancillary.h header file.
Nothing else is required.

All functions of this library require the following header:

#include <ancillary.h>

At this time, the only ancillary data defined by the Single Unix
Specification (v3) is file descriptors.

Passing file descriptors

int ancil_send_fd(socket, file_descriptor)
int socket: the Unix socket
int file_descriptor: the file descriptor
Return value: 0 for success, -1 for failure.

Sends one file descriptor on a socket.
In case of failure, errno is set; the possible values are the ones of the
sendmsg(2) system call.


int ancil_recv_fd(socket, file_descriptor)
int socket: the Unix socket
int *file_descriptor: pointer to the returned file descriptor
Return value: 0 for success, -1 for failure

Receives one file descriptor from a socket.
In case of success, the file descriptor is stored in the integer pointed
to by file_descriptor.
In case of failure, errno is set; the possible values are the ones of the
recvmsg(2) system call.
The behavior is undefined if the recv_fd does not match a send_fd* on the
other side.


int ancil_send_fds(socket, file_descriptors, num_file_descriptors)
int socket: the Unix socket
const int *file_descriptors: array of file descriptors
unsigned num_file_descriptors: number of file descriptors
Return value: 0 for success, -1 for failure

Sends several file descriptors on a socket.
In case of failure, errno is set; the possible values are the ones of the
sendmsg(2) system call.
The maximum number of file descriptors that can be sent using this
function is ANCIL_MAX_N_FDS; the behavior is undefined in case of
overflow, probably a stack corruption.


int ancil_recv_fds(socket, file_descriptors, num_file_descriptors)
int socket: the Unix socket
int *file_descriptors: return array of file descriptors
unsigned num_file_descriptors: number of file descriptors
Return value: number of received fd for success, -1 for failure

Receives several file descriptors from a socket, no more than
num_file_descriptors.
In case of success, the received file descriptors are stored in the array
pointed to by file_descriptors.
In case of failure, errno is set; the possible values are the ones of the
recvmsg(2) system call.
The maximum number of file descriptors that can be received using this
function is ANCIL_MAX_N_FDS; the behavior is undefined in case of
overflow, probably a stack corruption.
The behavior is undefined if the recv_fds does not match a send_fd* on
the other side, or if the number of received file descriptors is more than
num_file_descriptors.


int ancil_send_fds_with_buffer(socket, fds, num, buffer)
int socket: the Unix socket
const int *fds: array of file descriptors
unsigned num: number of file descriptors
void *buffer: buffer to hold the system data structures
Return value: 0 for success, -1 for failure

Sends several file descriptors on a socket.
In case of failure, errno is set; the possible values are the ones of the
sendmsg(2) system call.
The buffer argument must point to a memory area large enough to hold the
system data structures, see ANCIL_FD_BUFFER.


int ancil_send_fds_with_buffer(socket, fds, num, buffer)
int socket: the Unix socket
int *fds: return array of file descriptors
unsigned num: number of file descriptors
void *buffer: buffer to hold the system data structures
Return value: number of received fd for success, -1 for failure

Receives several file descriptors from a socket, no more than
num_file_descriptors.
In case of success, the received file descriptors are stored in the array
pointed to by file_descriptors.
In case of failure, errno is set; the possible values are the ones of the
recvmsg(2) system call.
The behavior is undefined if the recv_fds does not match a send_fd* on
the other side, or if the number of received file descriptors is more than
num_file_descriptors.
The buffer argument must point to a memory area large enough to hold the
system data structures, see ANCIL_FD_BUFFER.


ANCIL_MAX_N_FDS

Maximum number of file descriptors that can be sent with the sent_fds and
recv_fds functions. If you have to send more at once, use the
*_with_buffer versions. The value is enough to send "quite a few" file
descriptors.


ANCIL_FD_BUFFER(n)
int n: number of file descriptors

Expands to a structure data type large enough to hold the system data
structures for n file descriptors. So the address of a variable declared
of type ANCIL_FD_BUFFER(n) is suitable as the buffer argument for
*_with_buffer on n file descriptors.
To use this macro, you need <sys/types.h> and <sys/socket.h>. Bevare: with
Solaris, the _XPG4_2 macro must be defined before sys/socket is included.


Tuning the compilation

This library is designed to be included in projects, not installed in
/usr/lib. If your project does not use some of the functions, the
TUNE_OPTS variable in the Makefile allows not to build them. It is a list
of proprocessor options:

-DNDEBUG: turn assertions off (see assert(3))
-DSPARE_SEND_FDS: do not build ancil_send_fds
-DSPARE_SEND_FD: do not build ancil_send_fd
-DSPARE_RECV_FDS: do not build ancil_recv_fds
-DSPARE_RECV_FD: do not build ancil_recv_fd
21 changes: 21 additions & 0 deletions src/main/jni/libancillary/COPYING
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 changes: 73 additions & 0 deletions src/main/jni/libancillary/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
###########################################################################
# libancillary - black magic on Unix domain sockets
# (C) Nicolas George
# Makefile - guess what
###########################################################################

# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

CC=gcc
CFLAGS=-Wall -g -O2
LDFLAGS=
LIBS=
AR=ar
RANLIB=ranlib
RM=rm
CP=cp
MKDIR=mkdir
TAR=tar
GZIP=gzip -9

NAME=libancillary
DISTRIBUTION=API COPYING Makefile ancillary.h fd_send.c fd_recv.c test.c
VERSION=0.9.1

OBJECTS=fd_send.o fd_recv.o

TUNE_OPTS=-DNDEBUG
#TUNE_OPTS=-DNDEBUG \
-DSPARE_SEND_FDS -DSPARE_SEND_FD -DSPARE_RECV_FDS -DSPARE_RECV_FD

.c.o:
$(CC) -c $(CFLAGS) $(TUNE_OPTS) $<

all: libancillary.a

libancillary.a: $(OBJECTS)
$(AR) cr $@ $(OBJECTS)
$(RANLIB) $@

fd_send.o: ancillary.h
fd_recv.o: ancillary.h

test: test.c libancillary.a
$(CC) -o $@ $(CFLAGS) $(LDFLAGS) -L. test.c -lancillary $(LIBS)

clean:
-$(RM) -f *.o *.a test

dist:
$(MKDIR) $(NAME)-$(VERSION)
$(CP) $(DISTRIBUTION) $(NAME)-$(VERSION)
$(TAR) -cf - $(NAME)-$(VERSION) | $(GZIP) > $(NAME)-$(VERSION).tar.gz
$(RM) -rf $(NAME)-$(VERSION)
Loading

0 comments on commit faad961

Please sign in to comment.