Commit fd4015fa authored by Max Lv's avatar Max Lv

add unix socket

parent f2c39bd1
......@@ -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
......
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")
......
......@@ -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);
}
......@@ -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
########################################################
......@@ -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)
......@@ -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 \
......
......@@ -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;
......@@ -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();
......@@ -491,10 +494,53 @@ 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;
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, "/data/data/com.github.shadowsocks/sock_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)) {
......
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
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.
###########################################################################
# 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)
/***************************************************************************
* libancillary - black magic on Unix domain sockets
* (C) Nicolas George
* ancillary.c - public header
***************************************************************************/
/*
* 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.
*/
#ifndef ANCILLARY_H__
#define ANCILLARY_H__
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************
* Start of the readable part.
***************************************************************************/
#define ANCIL_MAX_N_FDS 960
/*
* Maximum number of fds that can be sent or received using the "esay"
* functions; this is so that all can fit in one page.
*/
extern int
ancil_send_fds_with_buffer(int, const int *, unsigned, void *);
/*
* ancil_send_fds_with_buffer(sock, n_fds, fds, buffer)
*
* Sends the file descriptors in the array pointed by fds, of length n_fds
* on the socket sock.
* buffer is a writeable memory area large enough to hold the required data
* structures.
* Returns: -1 and errno in case of error, 0 in case of success.
*/
extern int
ancil_recv_fds_with_buffer(int, int *, unsigned, void *);
/*
* ancil_recv_fds_with_buffer(sock, n_fds, fds, buffer)
*
* Receives *n_fds file descriptors into the array pointed by fds
* from the socket sock.
* buffer is a writeable memory area large enough to hold the required data
* structures.
* Returns: -1 and errno in case of error, the actual number of received fd
* in case of success
*/
#define ANCIL_FD_BUFFER(n) \
struct { \
struct cmsghdr h; \
int fd[n]; \
}
/* ANCIL_FD_BUFFER(n)
*
* A structure type suitable to be used as buffer for n file descriptors.
* Requires <sys/socket.h>.
* Example:
* ANCIL_FD_BUFFER(42) buffer;
* ancil_recv_fds_with_buffer(sock, 42, my_fds, &buffer);
*/
extern int
ancil_send_fds(int, const int *, unsigned);
/*
* ancil_send_fds(sock, n_fds, fds)
*
* Sends the file descriptors in the array pointed by fds, of length n_fds
* on the socket sock.
* n_fds must not be greater than ANCIL_MAX_N_FDS.
* Returns: -1 and errno in case of error, 0 in case of success.
*/
extern int
ancil_recv_fds(int, int *, unsigned);
/*
* ancil_recv_fds(sock, n_fds, fds)
*
* Receives *n_fds file descriptors into the array pointed by fds
* from the socket sock.
* *n_fds must not be greater than ANCIL_MAX_N_FDS.
* Returns: -1 and errno in case of error, the actual number of received fd
* in case of success.
*/
extern int
ancil_send_fd(int, int);
/* ancil_recv_fd(sock, fd);
*
* Sends the file descriptor fd on the socket sock.
* Returns : -1 and errno in case of error, 0 in case of success.
*/
extern int
ancil_recv_fd(int, int *);
/* ancil_send_fd(sock, &fd);
*
* Receives the file descriptor fd from the socket sock.
* Returns : -1 and errno in case of error, 0 in case of success.
*/
#ifdef __cplusplus
}
#endif
#endif /* ANCILLARY_H__ */
/***************************************************************************
* libancillary - black magic on Unix domain sockets
* (C) Nicolas George
* fd_send.c - receiving file descriptors
***************************************************************************/
/*
* 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.
*/
#ifndef _XPG4_2 /* Solaris sucks */
# define _XPG4_2
#endif
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <assert.h>
#if defined(__FreeBSD__)
# include <sys/param.h> /* FreeBSD sucks */
#endif
#include "ancillary.h"
int
ancil_recv_fds_with_buffer(int sock, int *fds, unsigned n_fds, void *buffer)
{
struct msghdr msghdr;
char nothing;
struct iovec nothing_ptr;
struct cmsghdr *cmsg;
int i;
nothing_ptr.iov_base = &nothing;
nothing_ptr.iov_len = 1;
msghdr.msg_name = NULL;
msghdr.msg_namelen = 0;
msghdr.msg_iov = &nothing_ptr;
msghdr.msg_iovlen = 1;
msghdr.msg_flags = 0;
msghdr.msg_control = buffer;
msghdr.msg_controllen = sizeof(struct cmsghdr) + sizeof(int) * n_fds;
cmsg = CMSG_FIRSTHDR(&msghdr);
cmsg->cmsg_len = msghdr.msg_controllen;
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
for(i = 0; i < n_fds; i++)
((int *)CMSG_DATA(cmsg))[i] = -1;
if(recvmsg(sock, &msghdr, 0) < 0)
return(-1);
for(i = 0; i < n_fds; i++)
fds[i] = ((int *)CMSG_DATA(cmsg))[i];
n_fds = (msghdr.msg_controllen - sizeof(struct cmsghdr)) / sizeof(int);
return(n_fds);
}
#ifndef SPARE_RECV_FDS
int
ancil_recv_fds(int sock, int *fd, unsigned n_fds)
{
ANCIL_FD_BUFFER(ANCIL_MAX_N_FDS) buffer;
assert(n_fds <= ANCIL_MAX_N_FDS);
return(ancil_recv_fds_with_buffer(sock, fd, n_fds, &buffer));
}
#endif /* SPARE_RECV_FDS */
#ifndef SPARE_RECV_FD
int
ancil_recv_fd(int sock, int *fd)
{
ANCIL_FD_BUFFER(1) buffer;
return(ancil_recv_fds_with_buffer(sock, fd, 1, &buffer) == 1 ? 0 : -1);
}
#endif /* SPARE_RECV_FD */
/***************************************************************************
* libancillary - black magic on Unix domain sockets
* (C) Nicolas George
* fd_send.c - sending file descriptors
***************************************************************************/
/*
* 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.
*/
#ifndef _XPG4_2 /* Solaris sucks */
# define _XPG4_2
#endif
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <assert.h>
#if defined(__FreeBSD__)
# include <sys/param.h> /* FreeBSD sucks */
#endif
#include "ancillary.h"
int
ancil_send_fds_with_buffer(int sock, const int *fds, unsigned n_fds, void *buffer)
{
struct msghdr msghdr;
char nothing = '!';
struct iovec nothing_ptr;
struct cmsghdr *cmsg;
int i;
nothing_ptr.iov_base = &nothing;
nothing_ptr.iov_len = 1;
msghdr.msg_name = NULL;
msghdr.msg_namelen = 0;
msghdr.msg_iov = &nothing_ptr;
msghdr.msg_iovlen = 1;
msghdr.msg_flags = 0;
msghdr.msg_control = buffer;
msghdr.msg_controllen = sizeof(struct cmsghdr) + sizeof(int) * n_fds;
cmsg = CMSG_FIRSTHDR(&msghdr);
cmsg->cmsg_len = msghdr.msg_controllen;
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
for(i = 0; i < n_fds; i++)
((int *)CMSG_DATA(cmsg))[i] = fds[i];
return(sendmsg(sock, &msghdr, 0) >= 0 ? 0 : -1);
}
#ifndef SPARE_SEND_FDS
int
ancil_send_fds(int sock, const int *fds, unsigned n_fds)
{
ANCIL_FD_BUFFER(ANCIL_MAX_N_FDS) buffer;
assert(n_fds <= ANCIL_MAX_N_FDS);
return(ancil_send_fds_with_buffer(sock, fds, n_fds, &buffer));
}
#endif /* SPARE_SEND_FDS */
#ifndef SPARE_SEND_FD
int
ancil_send_fd(int sock, int fd)
{
ANCIL_FD_BUFFER(1) buffer;
return(ancil_send_fds_with_buffer(sock, &fd, 1, &buffer));
}
#endif /* SPARE_SEND_FD */
/***************************************************************************
* libancillary - black magic on Unix domain sockets
* (C) Nicolas George
* test.c - testing and example program
***************************************************************************/
/*
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include "ancillary.h"
void child_process(int sock)
{
int fd;
int fds[3], nfds;
char b[] = "This is on the received fd!\n";
if(ancil_recv_fd(sock, &fd)) {
perror("ancil_recv_fd");
exit(1);
} else {
printf("Received fd: %d\n", fd);
}
write(fd, b, sizeof(b));
close(fd);
sleep(2);
nfds = ancil_recv_fds(sock, fds, 3);
if(nfds < 0) {
perror("ancil_recv_fds");
exit(1);
} else {
printf("Received %d/3 fds : %d %d %d.\n", nfds,
fds[0], fds[1], fds[2]);
}
}
void parent_process(int sock)
{
int fds[2] = { 1, 2 };
if(ancil_send_fd(sock, 1)) {
perror("ancil_send_fd");
exit(1);
} else {
printf("Sent fd.\n");
}
sleep(1);
if(ancil_send_fds(sock, fds, 2)) {
perror("ancil_send_fds");
exit(1);
} else {
printf("Sent two fds.\n");
}
}
int main(void)
{
int sock[2];
if(socketpair(PF_UNIX, SOCK_STREAM, 0, sock)) {
perror("socketpair");
exit(1);
} else {
printf("Established socket pair: (%d, %d)\n", sock[0], sock[1]);
}
switch(fork()) {
case 0:
close(sock[0]);
child_process(sock[1]);
break;
case -1:
perror("fork");
exit(1);
default:
close(sock[1]);
parent_process(sock[0]);
wait(NULL);
break;
}
return(0);
}
......@@ -5,8 +5,15 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <cpu-features.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <ancillary.h>
#define LOGI(...) do { __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__); } while(0)
#define LOGW(...) do { __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__); } while(0)
#define LOGE(...) do { __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__); } while(0)
......@@ -36,9 +43,40 @@ void Java_com_github_shadowsocks_system_exec(JNIEnv *env, jobject thiz, jstring
env->ReleaseStringUTFChars(cmd, str);
}
jint Java_com_github_shadowsocks_system_sendfd(JNIEnv *env, jobject thiz, jint tun_fd) {
int fd;
struct sockaddr_un addr;
if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
LOGE("socket() failed: %s (socket fd = %d)\n", strerror(errno), fd);
return (jint)-1;
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, "/data/data/com.github.shadowsocks/sock_path", sizeof(addr.sun_path)-1);
if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
LOGE("connect() failed: %s (fd = %d)\n", strerror(errno), fd);
close(fd);
return (jint)-1;
}
if (ancil_send_fd(fd, tun_fd)) {
LOGE("ancil_send_fd: %s", strerror(errno));
close(fd);
return (jint)-1;
}
close(fd);
return 0;
}
static const char *classPathName = "com/github/shadowsocks/System";
static JNINativeMethod method_table[] = {
{ "sendfd", "(I)I",
(void*) Java_com_github_shadowsocks_system_sendfd },
{ "exec", "(Ljava/lang/String;)V",
(void*) Java_com_github_shadowsocks_system_exec },
{ "getABI", "()Ljava/lang/String;",
......
......@@ -184,7 +184,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
version
}
def startVpn() {
def startVpn(): Int = {
val builder = new Builder()
builder
......@@ -310,7 +310,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
if (conn == null) {
stopRunner()
return
return -1
}
val fd = conn.getFd
......@@ -336,7 +336,9 @@ class ShadowsocksVpnService extends VpnService with BaseService {
if (BuildConfig.DEBUG) Log.d(TAG, cmd)
System.exec(cmd)
Console.runCommand(cmd.mkString(" "))
return fd;
}
/** Called when the activity is first created. */
......@@ -346,9 +348,20 @@ class ShadowsocksVpnService extends VpnService with BaseService {
startDnsDaemon()
startDnsTunnel()
}
startVpn()
val fd = startVpn()
if (fd == -1) {
false
} else {
Thread.sleep(1000)
if (System.sendfd(fd) == -1) {
false
} else {
true
}
}
}
override def onBind(intent: Intent): IBinder = {
val action = intent.getAction
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment