diff --git a/shadowsocks-libev/Makefile b/shadowsocks-libev/Makefile index 6193f4543..f26946c60 100644 --- a/shadowsocks-libev/Makefile +++ b/shadowsocks-libev/Makefile @@ -94,8 +94,8 @@ define Package/shadowsocks-libev-ss-rules/install $(INSTALL_BIN) ./files/ss-rules.defaults $(1)/etc/uci-defaults $(INSTALL_DIR) $(1)/etc/sysctl.d $(INSTALL_DATA) ./files/shadowsocks.conf $(1)/etc/sysctl.d - $(INSTALL_DIR) $(1)/usr/lib/shadowsocks-libev - $(INSTALL_DATA) $(PKG_BUILD_DIR)/src/*.ebpf $(1)/usr/lib/shadowsocks-libev +# $(INSTALL_DIR) $(1)/usr/lib/shadowsocks-libev +# $(INSTALL_DATA) $(PKG_BUILD_DIR)/src/*.ebpf $(1)/usr/lib/shadowsocks-libev endef define Package/shadowsocks-libev-ss-rules/prerm diff --git a/shadowsocks-libev/files/ss-rules b/shadowsocks-libev/files/ss-rules index 83473e12d..b50eaeacd 100755 --- a/shadowsocks-libev/files/ss-rules +++ b/shadowsocks-libev/files/ss-rules @@ -121,7 +121,7 @@ ss_rules_parse_args() { ss_rules_flush() { local setname - iptables-save --counters | grep -v ss_rules_ | iptables-restore --counters + iptables-save --counters | grep -v ss_rules_ | iptables-restore -w --counters while ip rule del fwmark 1 lookup 100 2>/dev/null; do true; done ip route flush table 100 for setname in $(ipset -n list | grep "ss_rules_"); do @@ -165,7 +165,7 @@ ss_rules_iptchains_init() { } ss_rules_iptchains_init_mark() { - iptables-restore --noflush <<-EOF + iptables-restore -w --noflush <<-EOF *mangle -A PREROUTING -m set --match-set ss_rules_dst_bypass_all dst -j MARK --set-mark 0x539 COMMIT @@ -185,7 +185,7 @@ ss_rules_iptchains_init_tcp() { bypass|*) return 0;; esac - iptables-restore --noflush <<-EOF + iptables-restore -w --noflush <<-EOF *nat :ss_rules_local_out - -I OUTPUT 1 -p tcp -j ss_rules_local_out @@ -240,7 +240,7 @@ ss_rules_iptchains_init_() { forward) dst_default_target=ss_rules_forward ;; bypass|*) dst_default_target=RETURN ;; esac - sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | iptables-restore --noflush + sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | iptables-restore -w --noflush *$table :ss_rules_pre_src - :ss_rules_src - diff --git a/shadowsocks-libev/files/ss-rules6 b/shadowsocks-libev/files/ss-rules6 index f6f595cb8..3c78e9a73 100755 --- a/shadowsocks-libev/files/ss-rules6 +++ b/shadowsocks-libev/files/ss-rules6 @@ -103,7 +103,7 @@ ss_rules6_parse_args() { ss_rules6_flush() { local setname - ip6tables-save --counters | grep -v ss_rules6_ | ip6tables-restore --counters + ip6tables-save --counters | grep -v ss_rules6_ | ip6tables-restore -w --counters while ip -f inet6 rule del fwmark 1 lookup 100 2>/dev/null; do true; done ip -f inet6 route flush table 100 for setname in $(ipset -n list | grep "ss_rules6_"); do @@ -147,7 +147,7 @@ ss_rules6_iptchains_init() { } ss_rules6_iptchains_init_mark() { - ip6tables-restore --noflush <<-EOF + ip6tables-restore -w --noflush <<-EOF *mangle -A PREROUTING -m set --match-set ss_rules6_dst_bypass_all dst -j MARK --set-mark 0x6539 COMMIT @@ -168,7 +168,7 @@ ss_rules6_iptchains_init_tcp() { bypass|*) return 0;; esac - ip6tables-restore --noflush <<-EOF + ip6tables-restore -w --noflush <<-EOF *nat :ss_rules6_local_out - -I OUTPUT 1 -p tcp -j ss_rules6_local_out @@ -224,7 +224,7 @@ ss_rules6_iptchains_init_() { forward) dst_default_target=ss_rules6_forward ;; bypass|*) dst_default_target=RETURN ;; esac - sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | ip6tables-restore --noflush + sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | ip6tables-restore -w --noflush *$table :ss_rules6_pre_src - :ss_rules6_src - diff --git a/shadowsocks-libev/patches/030-eBPF.patch b/shadowsocks-libev/patches/030-eBPF.patch deleted file mode 100644 index 92983a0e5..000000000 --- a/shadowsocks-libev/patches/030-eBPF.patch +++ /dev/null @@ -1,884 +0,0 @@ -diff -aurN shadowsocks-libev-nocrypto-nocrypto/configure.ac shadowsocks-libev-nocrypto-ebpf/configure.ac ---- shadowsocks-libev-nocrypto-nocrypto/configure.ac 2018-06-23 14:57:34.000000000 +0200 -+++ shadowsocks-libev-nocrypto-ebpf/configure.ac 2018-08-14 13:45:18.000000000 +0200 -@@ -245,6 +245,11 @@ - [AC_DEFINE([USE_SYSTEM_SHARED_LIB], [1], [Define if use system shared lib.])], - [AC_CONFIG_FILES([libbloom/Makefile libcork/Makefile libipset/Makefile])]) - -+AC_CHECK_HEADERS([linux/bpf.h bpf/bpf.h bpf/libbpf.h], [], -+ [AC_MSG_ERROR([Missing libbpf headers. Install libbpf from kernel library sources])]) -+ -+AC_CHECK_LIB([elf], [elf_getdata], [LIBS="-lelf $LIBS"], [AC_MSG_ERROR([Couldn't find libelf])]) -+ - AC_ARG_ENABLE(connmarktos, - [AS_HELP_STRING(--enable-connmarktos, Enable saved connmark to IP TOS QoS feature)], - [ -diff -aurN shadowsocks-libev-nocrypto-nocrypto/src/bpf_helpers.h shadowsocks-libev-nocrypto-ebpf/src/bpf_helpers.h ---- shadowsocks-libev-nocrypto-nocrypto/src/bpf_helpers.h 1970-01-01 01:00:00.000000000 +0100 -+++ shadowsocks-libev-nocrypto-ebpf/src/bpf_helpers.h 2018-08-14 13:45:18.000000000 +0200 -@@ -0,0 +1,208 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+#ifndef __BPF_HELPERS_H -+#define __BPF_HELPERS_H -+ -+/* helper macro to place programs, maps, license in -+ * different sections in elf_bpf file. Section names -+ * are interpreted by elf_bpf loader -+ */ -+#define SEC(NAME) __attribute__((section(NAME), used)) -+ -+/* helper functions called from eBPF programs written in C */ -+static void *(*bpf_map_lookup_elem)(void *map, void *key) = -+ (void *) BPF_FUNC_map_lookup_elem; -+static int (*bpf_map_update_elem)(void *map, void *key, void *value, -+ unsigned long long flags) = -+ (void *) BPF_FUNC_map_update_elem; -+static int (*bpf_map_delete_elem)(void *map, void *key) = -+ (void *) BPF_FUNC_map_delete_elem; -+static int (*bpf_probe_read)(void *dst, int size, void *unsafe_ptr) = -+ (void *) BPF_FUNC_probe_read; -+static unsigned long long (*bpf_ktime_get_ns)(void) = -+ (void *) BPF_FUNC_ktime_get_ns; -+static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) = -+ (void *) BPF_FUNC_trace_printk; -+static void (*bpf_tail_call)(void *ctx, void *map, int index) = -+ (void *) BPF_FUNC_tail_call; -+static unsigned long long (*bpf_get_smp_processor_id)(void) = -+ (void *) BPF_FUNC_get_smp_processor_id; -+static unsigned long long (*bpf_get_current_pid_tgid)(void) = -+ (void *) BPF_FUNC_get_current_pid_tgid; -+static unsigned long long (*bpf_get_current_uid_gid)(void) = -+ (void *) BPF_FUNC_get_current_uid_gid; -+static int (*bpf_get_current_comm)(void *buf, int buf_size) = -+ (void *) BPF_FUNC_get_current_comm; -+static unsigned long long (*bpf_perf_event_read)(void *map, -+ unsigned long long flags) = -+ (void *) BPF_FUNC_perf_event_read; -+static int (*bpf_clone_redirect)(void *ctx, int ifindex, int flags) = -+ (void *) BPF_FUNC_clone_redirect; -+static int (*bpf_redirect)(int ifindex, int flags) = -+ (void *) BPF_FUNC_redirect; -+static int (*bpf_redirect_map)(void *map, int key, int flags) = -+ (void *) BPF_FUNC_redirect_map; -+static int (*bpf_perf_event_output)(void *ctx, void *map, -+ unsigned long long flags, void *data, -+ int size) = -+ (void *) BPF_FUNC_perf_event_output; -+static int (*bpf_get_stackid)(void *ctx, void *map, int flags) = -+ (void *) BPF_FUNC_get_stackid; -+static int (*bpf_probe_write_user)(void *dst, void *src, int size) = -+ (void *) BPF_FUNC_probe_write_user; -+static int (*bpf_current_task_under_cgroup)(void *map, int index) = -+ (void *) BPF_FUNC_current_task_under_cgroup; -+static int (*bpf_skb_get_tunnel_key)(void *ctx, void *key, int size, int flags) = -+ (void *) BPF_FUNC_skb_get_tunnel_key; -+static int (*bpf_skb_set_tunnel_key)(void *ctx, void *key, int size, int flags) = -+ (void *) BPF_FUNC_skb_set_tunnel_key; -+static int (*bpf_skb_get_tunnel_opt)(void *ctx, void *md, int size) = -+ (void *) BPF_FUNC_skb_get_tunnel_opt; -+static int (*bpf_skb_set_tunnel_opt)(void *ctx, void *md, int size) = -+ (void *) BPF_FUNC_skb_set_tunnel_opt; -+static unsigned long long (*bpf_get_prandom_u32)(void) = -+ (void *) BPF_FUNC_get_prandom_u32; -+static int (*bpf_xdp_adjust_head)(void *ctx, int offset) = -+ (void *) BPF_FUNC_xdp_adjust_head; -+static int (*bpf_setsockopt)(void *ctx, int level, int optname, void *optval, -+ int optlen) = -+ (void *) BPF_FUNC_setsockopt; -+static int (*bpf_sk_redirect_map)(void *ctx, void *map, int key, int flags) = -+ (void *) BPF_FUNC_sk_redirect_map; -+static int (*bpf_sock_map_update)(void *map, void *key, void *value, -+ unsigned long long flags) = -+ (void *) BPF_FUNC_sock_map_update; -+ -+ -+/* llvm builtin functions that eBPF C program may use to -+ * emit BPF_LD_ABS and BPF_LD_IND instructions -+ */ -+struct sk_buff; -+unsigned long long load_byte(void *skb, -+ unsigned long long off) asm("llvm.bpf.load.byte"); -+unsigned long long load_half(void *skb, -+ unsigned long long off) asm("llvm.bpf.load.half"); -+unsigned long long load_word(void *skb, -+ unsigned long long off) asm("llvm.bpf.load.word"); -+ -+/* a helper structure used by eBPF C program -+ * to describe map attributes to elf_bpf loader -+ */ -+struct bpf_map_def { -+ unsigned int type; -+ unsigned int key_size; -+ unsigned int value_size; -+ unsigned int max_entries; -+ unsigned int map_flags; -+ unsigned int inner_map_idx; -+ unsigned int numa_node; -+}; -+ -+static int (*bpf_skb_load_bytes)(void *ctx, int off, void *to, int len) = -+ (void *) BPF_FUNC_skb_load_bytes; -+static int (*bpf_skb_store_bytes)(void *ctx, int off, void *from, int len, int flags) = -+ (void *) BPF_FUNC_skb_store_bytes; -+static int (*bpf_l3_csum_replace)(void *ctx, int off, int from, int to, int flags) = -+ (void *) BPF_FUNC_l3_csum_replace; -+static int (*bpf_l4_csum_replace)(void *ctx, int off, int from, int to, int flags) = -+ (void *) BPF_FUNC_l4_csum_replace; -+static int (*bpf_skb_under_cgroup)(void *ctx, void *map, int index) = -+ (void *) BPF_FUNC_skb_under_cgroup; -+static int (*bpf_skb_change_head)(void *, int len, int flags) = -+ (void *) BPF_FUNC_skb_change_head; -+ -+#if defined(__x86_64__) -+ -+#define PT_REGS_PARM1(x) ((x)->di) -+#define PT_REGS_PARM2(x) ((x)->si) -+#define PT_REGS_PARM3(x) ((x)->dx) -+#define PT_REGS_PARM4(x) ((x)->cx) -+#define PT_REGS_PARM5(x) ((x)->r8) -+#define PT_REGS_RET(x) ((x)->sp) -+#define PT_REGS_FP(x) ((x)->bp) -+#define PT_REGS_RC(x) ((x)->ax) -+#define PT_REGS_SP(x) ((x)->sp) -+#define PT_REGS_IP(x) ((x)->ip) -+ -+#elif defined(__s390x__) -+ -+#define PT_REGS_PARM1(x) ((x)->gprs[2]) -+#define PT_REGS_PARM2(x) ((x)->gprs[3]) -+#define PT_REGS_PARM3(x) ((x)->gprs[4]) -+#define PT_REGS_PARM4(x) ((x)->gprs[5]) -+#define PT_REGS_PARM5(x) ((x)->gprs[6]) -+#define PT_REGS_RET(x) ((x)->gprs[14]) -+#define PT_REGS_FP(x) ((x)->gprs[11]) /* Works only with CONFIG_FRAME_POINTER */ -+#define PT_REGS_RC(x) ((x)->gprs[2]) -+#define PT_REGS_SP(x) ((x)->gprs[15]) -+#define PT_REGS_IP(x) ((x)->psw.addr) -+ -+#elif defined(__aarch64__) -+ -+#define PT_REGS_PARM1(x) ((x)->regs[0]) -+#define PT_REGS_PARM2(x) ((x)->regs[1]) -+#define PT_REGS_PARM3(x) ((x)->regs[2]) -+#define PT_REGS_PARM4(x) ((x)->regs[3]) -+#define PT_REGS_PARM5(x) ((x)->regs[4]) -+#define PT_REGS_RET(x) ((x)->regs[30]) -+#define PT_REGS_FP(x) ((x)->regs[29]) /* Works only with CONFIG_FRAME_POINTER */ -+#define PT_REGS_RC(x) ((x)->regs[0]) -+#define PT_REGS_SP(x) ((x)->sp) -+#define PT_REGS_IP(x) ((x)->pc) -+ -+#elif defined(__mips__) -+ -+#define PT_REGS_PARM1(x) ((x)->regs[4]) -+#define PT_REGS_PARM2(x) ((x)->regs[5]) -+#define PT_REGS_PARM3(x) ((x)->regs[6]) -+#define PT_REGS_PARM4(x) ((x)->regs[7]) -+#define PT_REGS_PARM5(x) ((x)->regs[8]) -+#define PT_REGS_RET(x) ((x)->regs[31]) -+#define PT_REGS_FP(x) ((x)->regs[30]) /* Works only with CONFIG_FRAME_POINTER */ -+#define PT_REGS_RC(x) ((x)->regs[1]) -+#define PT_REGS_SP(x) ((x)->regs[29]) -+#define PT_REGS_IP(x) ((x)->cp0_epc) -+ -+#elif defined(__powerpc__) -+ -+#define PT_REGS_PARM1(x) ((x)->gpr[3]) -+#define PT_REGS_PARM2(x) ((x)->gpr[4]) -+#define PT_REGS_PARM3(x) ((x)->gpr[5]) -+#define PT_REGS_PARM4(x) ((x)->gpr[6]) -+#define PT_REGS_PARM5(x) ((x)->gpr[7]) -+#define PT_REGS_RC(x) ((x)->gpr[3]) -+#define PT_REGS_SP(x) ((x)->sp) -+#define PT_REGS_IP(x) ((x)->nip) -+ -+#elif defined(__sparc__) -+ -+#define PT_REGS_PARM1(x) ((x)->u_regs[UREG_I0]) -+#define PT_REGS_PARM2(x) ((x)->u_regs[UREG_I1]) -+#define PT_REGS_PARM3(x) ((x)->u_regs[UREG_I2]) -+#define PT_REGS_PARM4(x) ((x)->u_regs[UREG_I3]) -+#define PT_REGS_PARM5(x) ((x)->u_regs[UREG_I4]) -+#define PT_REGS_RET(x) ((x)->u_regs[UREG_I7]) -+#define PT_REGS_RC(x) ((x)->u_regs[UREG_I0]) -+#define PT_REGS_SP(x) ((x)->u_regs[UREG_FP]) -+#if defined(__arch64__) -+#define PT_REGS_IP(x) ((x)->tpc) -+#else -+#define PT_REGS_IP(x) ((x)->pc) -+#endif -+ -+#endif -+ -+#ifdef __powerpc__ -+#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = (ctx)->link; }) -+#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP -+#elif defined(__sparc__) -+#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = PT_REGS_RET(ctx); }) -+#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP -+#else -+#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ \ -+ bpf_probe_read(&(ip), sizeof(ip), (void *)PT_REGS_RET(ctx)); }) -+#define BPF_KRETPROBE_READ_RET_IP(ip, ctx) ({ \ -+ bpf_probe_read(&(ip), sizeof(ip), \ -+ (void *)(PT_REGS_FP(ctx) + sizeof(ip))); }) -+#endif -+ -+#endif -diff -aurN shadowsocks-libev-nocrypto-nocrypto/src/common.h shadowsocks-libev-nocrypto-ebpf/src/common.h ---- shadowsocks-libev-nocrypto-nocrypto/src/common.h 2018-06-23 14:57:34.000000000 +0200 -+++ shadowsocks-libev-nocrypto-ebpf/src/common.h 2018-08-14 13:45:18.000000000 +0200 -@@ -65,6 +65,7 @@ - GETOPT_VAL_ACL, - GETOPT_VAL_MTU, - GETOPT_VAL_MPTCP, -+ GETOPT_VAL_EBPF, - GETOPT_VAL_PLUGIN, - GETOPT_VAL_PLUGIN_OPTS, - GETOPT_VAL_PASSWORD, -diff -aurN shadowsocks-libev-nocrypto-nocrypto/src/jconf.c shadowsocks-libev-nocrypto-ebpf/src/jconf.c ---- shadowsocks-libev-nocrypto-nocrypto/src/jconf.c 2018-06-23 14:57:34.000000000 +0200 -+++ shadowsocks-libev-nocrypto-ebpf/src/jconf.c 2018-08-14 13:45:18.000000000 +0200 -@@ -309,11 +309,16 @@ - check_json_value_type(value, json_integer, - "invalid config file: option 'mtu' must be an integer"); - conf.mtu = value->u.integer; -+ } else if (strcmp(name, "ebpf") == 0) { -+ check_json_value_type(value, json_boolean, -+ "invalid config file: option 'ebpf' must be a boolean"); -+ conf.ebpf = value->u.boolean; - } else if (strcmp(name, "mptcp") == 0) { - check_json_value_type(value, json_boolean, - "invalid config file: option 'mptcp' must be a boolean"); - conf.mptcp = value->u.boolean; -- } else if (strcmp(name, "ipv6_first") == 0) { -+ } -+ else if (strcmp(name, "ipv6_first") == 0) { - check_json_value_type(value, json_boolean, - "invalid config file: option 'ipv6_first' must be a boolean"); - conf.ipv6_first = value->u.boolean; -diff -aurN shadowsocks-libev-nocrypto-nocrypto/src/jconf.h shadowsocks-libev-nocrypto-ebpf/src/jconf.h ---- shadowsocks-libev-nocrypto-nocrypto/src/jconf.h 2018-06-23 14:57:34.000000000 +0200 -+++ shadowsocks-libev-nocrypto-ebpf/src/jconf.h 2018-08-14 13:45:18.000000000 +0200 -@@ -84,6 +84,7 @@ - int mode; - int mtu; - int mptcp; -+ int ebpf; - int ipv6_first; - int no_delay; - } jconf_t; -diff -aurN shadowsocks-libev-nocrypto-nocrypto/src/Makefile.am shadowsocks-libev-nocrypto-ebpf/src/Makefile.am ---- shadowsocks-libev-nocrypto-nocrypto/src/Makefile.am 2018-06-23 14:57:34.000000000 +0200 -+++ shadowsocks-libev-nocrypto-ebpf/src/Makefile.am 2018-08-14 13:45:18.000000000 +0200 -@@ -105,6 +105,9 @@ - ss_redir_CFLAGS = $(AM_CFLAGS) -DMODULE_REDIR - ss_redir_LDADD = $(SS_COMMON_LIBS) - ss_redir_LDADD += -lcares -+ss_redir_LDADD += -lcap -+ss_redir_LDADD += -lbpf -+ss_redir_LDADD += -lelf - endif - - lib_LTLIBRARIES = libshadowsocks-libev.la -diff -aurN shadowsocks-libev-nocrypto-nocrypto/src/redir.c shadowsocks-libev-nocrypto-ebpf/src/redir.c ---- shadowsocks-libev-nocrypto-nocrypto/src/redir.c 2018-06-23 14:57:34.000000000 +0200 -+++ shadowsocks-libev-nocrypto-ebpf/src/redir.c 2018-08-14 13:45:18.000000000 +0200 -@@ -43,6 +43,10 @@ - - #include - -+#include -+#include -+#include -+ - #ifdef HAVE_CONFIG_H - #include "config.h" - #endif -@@ -69,6 +73,9 @@ - #define IP6T_SO_ORIGINAL_DST 80 - #endif - -+#define PARSE_PROG_FILENAME "/usr/lib/shadowsocks-libev/sockmap_parse.o.ebpf" -+#define VERDICT_PROG_FILENAME "/usr/lib/shadowsocks-libev/sockmap_verdict.o.ebpf" -+ - 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); -@@ -86,7 +93,10 @@ - int verbose = 0; - int reuse_port = 0; -+int ebpf = 0; - - static crypto_t *crypto; -+ebpf_conn_t *connections[65536]; -+obufs_t obufs; - - static int ipv6first = 0; - static int mode = TCP_ONLY; -@@ -128,6 +138,18 @@ - return fcntl(fd, F_SETFL, flags | O_NONBLOCK); - } - -+int -+is_open(int sock) -+{ -+ int err; -+ err = recv(sock, NULL, 0, MSG_PEEK|MSG_DONTWAIT); -+ if(err == 0) -+ return 1; -+ if(err == -1 && errno == EAGAIN) -+ return 1; -+ return 0; -+} -+ - int - create_and_bind(const char *addr, const char *port) - { -@@ -187,6 +209,316 @@ - return listen_sock; - } - -+int -+bpf_prog_load_obj_buf(void *obj_buf, int obj_buf_sz, const char *file, enum bpf_prog_type type, -+ struct bpf_object **pobj, int *prog_fd) -+{ -+ struct bpf_program *prog; -+ struct bpf_object *obj; -+ int err; -+ -+ obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, file); -+ if (libbpf_get_error(obj)) -+ return -ENOENT; -+ -+ prog = bpf_program__next(NULL, obj); -+ if (!prog) { -+ bpf_object__close(obj); -+ return -ENOENT; -+ } -+ -+ bpf_program__set_type(prog, type); -+ err = bpf_object__load(obj); -+ if (err) { -+ bpf_object__close(obj); -+ return -EINVAL; -+ } -+ -+ *pobj = obj; -+ *prog_fd = bpf_program__fd(prog); -+ return 0; -+} -+ -+int -+read_obj_file_into_buffer(char *fname, void **obj_buf, int *obj_buf_sz) -+{ -+ FILE *fileptr = NULL; -+ char *buf; -+ long file_size, readed; -+ int err; -+ -+ if(obj_buf == NULL || obj_buf_sz == NULL) { -+ LOGE("Invalid arguments for object file read\n"); -+ goto error; -+ } -+ -+ fileptr = fopen(fname, "rb"); -+ if(fileptr == NULL) { -+ ERROR("fopen"); -+ goto error; -+ } -+ err = fseek(fileptr, 0, SEEK_END); -+ if(err < 0) { -+ ERROR("fseek"); -+ goto error; -+ } -+ file_size = ftell(fileptr); -+ if(file_size < 0) { -+ ERROR("ftell"); -+ goto error; -+ } -+ rewind(fileptr); -+ -+ buf = (char *) malloc((file_size) * sizeof(char)); -+ if(buf == NULL) { -+ ERROR("malloc"); -+ goto error; -+ } -+ -+ readed = fread(buf, file_size, 1, fileptr); -+ if(readed != 1) { -+ ERROR("fread"); -+ goto cleanup; -+ } -+ -+ *obj_buf = (void *) buf; -+ *obj_buf_sz = file_size; -+ return 0; -+ -+cleanup: -+ free(buf); -+error: -+ if(fileptr != NULL) -+ fclose(fileptr); -+ return -1; -+} -+ -+int -+init_ebpf_object_buffers(obufs_t *progs) -+{ -+ char *buf; -+ int i, err; -+ -+ if(progs == NULL) { -+ printf("Invalid argument for object buffer initialization\n"); -+ goto error; -+ } -+ -+ err = read_obj_file_into_buffer(PARSE_PROG_FILENAME, -+ &progs->parse_prog, &progs->parse_prog_size); -+ if(err < 0) { -+ goto error; -+ } -+ -+ err = read_obj_file_into_buffer(VERDICT_PROG_FILENAME, -+ &progs->verdict_prog, &progs->verdict_prog_size); -+ if(err < 0) { -+ goto error; -+ } -+ -+ buf = (char *) progs->verdict_prog; -+ for(i = 0; i < progs->verdict_prog_size - 3; ++i) { -+ if(buf[i] == (char)0xfc && -+ buf[i+1] == (char)0xfc && -+ buf[i+2] == (char)0xfc && -+ buf[i+3] == (char)0xfc) { -+ -+ progs->verdict_port_p = (int *) &buf[i]; -+ } -+ } -+ -+ return 0; -+ -+error: -+ return -1; -+} -+ -+void -+free_ebpf_object_buffers(obufs_t *progs) -+{ -+ free(progs->parse_prog); -+ free(progs->verdict_prog); -+ progs->verdict_port_p = NULL; -+ progs->parse_prog_size = -1; -+ progs->verdict_prog_size = -1; -+} -+ -+int -+init_ebpf_connection(int local_sock, int remote_sock) -+{ -+ int pfd, vfd, sfd, err = -1; -+ int local_key, remote_key; -+ ebpf_conn_t *conn; -+ socklen_t sock_size; -+ struct sockaddr_in local_addr; -+ struct bpf_object *vobj, *pobj; -+ struct bpf_map *smap; -+ -+ local_key = 1; remote_key = 0; -+ -+ conn = (ebpf_conn_t *) malloc(sizeof(ebpf_conn_t)); -+ if(conn == NULL) { -+ ERROR("malloc"); -+ goto error; -+ } -+ -+ sock_size = sizeof(struct sockaddr); -+ err = getsockname(local_sock, (struct sockaddr *) &local_addr, &sock_size); -+ if(err < 0) { -+ ERROR("getsockname"); -+ goto error_cleanup; -+ } -+ //set the correct local port in the bytecode before load -+ if(obufs.verdict_port_p != NULL) -+ *obufs.verdict_port_p = ntohs(local_addr.sin_port); -+ else { -+ LOGE("Invalid memory address to save port\n."); -+ goto error_cleanup; -+ } -+ -+ err = bpf_prog_load_obj_buf(obufs.parse_prog, -+ obufs.parse_prog_size, -+ PARSE_PROG_FILENAME, BPF_PROG_TYPE_SK_SKB, -+ &pobj, &pfd); -+ if(err < 0) { -+ LOGE("Failed to load BPF object (parse)\n"); -+ goto error_cleanup; -+ } -+ -+ err = bpf_prog_load_obj_buf(obufs.verdict_prog, -+ obufs.verdict_prog_size, -+ VERDICT_PROG_FILENAME, BPF_PROG_TYPE_SK_SKB, -+ &vobj, &vfd); -+ if(err < 0) { -+ LOGE("Failed to load BPF object (verdict)\n"); -+ goto error_cleanup; -+ } -+ -+ smap = bpf_object__find_map_by_name(vobj, "redirect_map"); -+ if(smap == NULL) { -+ LOGE("Cannot find sockmap. Malformed BPF object\n"); -+ goto error_cleanup; -+ } -+ -+ sfd = bpf_map__fd(smap); -+ if(sfd < 0) { -+ LOGE("Unable to get sockmap reference fd\n"); -+ goto error_cleanup; -+ } -+ -+ err = bpf_prog_attach(pfd, sfd, BPF_SK_SKB_STREAM_PARSER, 0); -+ if(err < 0) { -+ LOGE("Failed to attach stream parser to sockmap\n"); -+ goto error_cleanup; -+ } -+ -+ err = bpf_prog_attach(vfd, sfd, BPF_SK_SKB_STREAM_VERDICT, 0); -+ if(err < 0) { -+ LOGE("Failed to attach verdict program to sockmap\n"); -+ goto error_cleanup; -+ } -+ -+ err = bpf_map_update_elem(sfd, &local_key, &local_sock, BPF_ANY); -+ if(err < 0) { -+ LOGE("Failed to put socket into sockmap\n"); -+ goto error_cleanup; -+ } -+ -+ err = bpf_map_update_elem(sfd, &remote_key, &remote_sock, BPF_ANY); -+ if(err < 0) { -+ LOGE("Failed to put socket into sockmap\n"); -+ goto error_cleanup; -+ } -+ -+ conn->sockmap_fd = sfd; -+ conn->parse_prog_fd = pfd; -+ conn->verdict_prog_fd = vfd; -+ conn->local_sock = local_sock; -+ conn->remote_sock = remote_sock; -+ -+ connections[ntohs(local_addr.sin_port)] = conn; -+ -+ free(vobj); -+ free(pobj); -+ -+ return 0; -+ -+error_cleanup: -+ free(conn); -+ free(vobj); -+ free(pobj); -+error: -+ return -1; -+} -+ -+inline void -+free_ebpf_connection(ebpf_conn_t *conn) -+{ -+ close(conn->sockmap_fd); -+ close(conn->parse_prog_fd); -+ close(conn->verdict_prog_fd); -+ -+ if(is_open(conn->local_sock)) { -+ close(conn->local_sock); -+ } -+ -+ if(is_open(conn->remote_sock)) { -+ close(conn->remote_sock); -+ } -+ -+ conn = NULL; -+} -+ -+int -+send_ebpf_handshake(int remote_sock, struct sockaddr_storage *destaddr) -+{ -+ // send destaddr -+ buffer_t ss_addr_to_send; -+ buffer_t *abuf = &ss_addr_to_send; -+ balloc(abuf, BUF_SIZE); -+ -+ if (AF_INET6 == destaddr->ss_family) { // IPv6 -+ abuf->data[abuf->len++] = 4; // Type 4 is IPv6 address -+ -+ size_t in6_addr_len = sizeof(struct in6_addr); -+ memcpy(abuf->data + abuf->len, -+ &(((struct sockaddr_in6 *) destaddr)->sin6_addr), -+ in6_addr_len); -+ abuf->len += in6_addr_len; -+ memcpy(abuf->data + abuf->len, -+ &(((struct sockaddr_in6 *) destaddr)->sin6_port), -+ 2); -+ } else { // IPv4 -+ abuf->data[abuf->len++] = 1; // Type 1 is IPv4 address -+ -+ size_t in_addr_len = sizeof(struct in_addr); -+ memcpy(abuf->data + abuf->len, -+ &((struct sockaddr_in *) destaddr)->sin_addr, in_addr_len); -+ abuf->len += in_addr_len; -+ memcpy(abuf->data + abuf->len, -+ &((struct sockaddr_in *) destaddr)->sin_port, 2); -+ } -+ -+ abuf->len += 2; -+ -+ struct sockaddr_storage addr; -+ memset(&addr, 0, sizeof(struct sockaddr_storage)); -+ socklen_t len = sizeof addr; -+ int r, tries = 100; -+ do { -+ r = getpeername(remote_sock, (struct sockaddr *)&addr, &len); -+ } while(tries && r != 0); -+ if(r < 0) { -+ return -1; -+ } -+ -+ r = send(remote_sock, abuf->data, abuf->len, 0); -+ -+ bfree(abuf); -+ -+ return r; -+} -+ - static void - server_recv_cb(EV_P_ ev_io *w, int revents) - { -@@ -310,6 +642,8 @@ - // all sent out, wait for reading - server->buf->len = 0; - server->buf->idx = 0; -+ if(ebpf && remote->recv_ctx->connected && remote->send_ctx->connected) -+ init_ebpf_connection(server->fd, remote->fd); - ev_io_stop(EV_A_ & server_send_ctx->io); - ev_io_start(EV_A_ & remote->recv_ctx->io); - } -@@ -323,17 +657,24 @@ - delayed_connect_watcher); - remote_t *remote = server->remote; - -- int r = connect(remote->fd, remote->addr, -- get_sockaddr_len(remote->addr)); -+ if(!is_open(remote->fd)) { -+ int r = connect(remote->fd, remote->addr, -+ get_sockaddr_len(remote->addr)); - -- remote->addr = NULL; -+ remote->addr = NULL; - -- if (r == -1 && errno != CONNECT_IN_PROGRESS) { -- ERROR("connect"); -- close_and_free_remote(EV_A_ remote); -- close_and_free_server(EV_A_ server); -- return; -- } else { -+ if (r == -1 && errno != CONNECT_IN_PROGRESS) { -+ ERROR("connect"); -+ close_and_free_remote(EV_A_ remote); -+ close_and_free_server(EV_A_ server); -+ return; -+ } -+ else { -+ ev_io_start(EV_A_ & remote->send_ctx->io); -+ ev_timer_start(EV_A_ & remote->send_ctx->watcher); -+ } -+ } -+ else { - // listen to remote connected event - ev_io_start(EV_A_ & remote->send_ctx->io); - ev_timer_start(EV_A_ & remote->send_ctx->watcher); -@@ -788,6 +1129,27 @@ - } - } - -+ //Initialize eBPF dataplane if enabled -+ /*if (ebpf) { -+ int r = connect(remotefd, remote_addr, get_sockaddr_len(remote_addr)); -+ if (r == -1 && errno != CONNECT_IN_PROGRESS) { -+ ERROR("connect"); -+ return; -+ } -+ -+ int err = send_ebpf_handshake(remotefd, &destaddr); -+ if(err < 0) { -+ LOGE("eBPF handshake failed"); -+ } -+ -+ err = init_ebpf_connection(remotefd, serverfd); -+ if(err < 0) { -+ LOGE("eBPF connection initialization failed"); -+ } -+ -+ return; -+ }*/ -+ - server_t *server = new_server(serverfd); - remote_t *remote = new_remote(remotefd, listener->timeout); - server->remote = remote; -@@ -799,14 +1161,18 @@ - remote->addr = remote_addr; - ev_timer_start(EV_A_ & server->delayed_connect_watcher); - } else { -- int r = connect(remotefd, remote_addr, get_sockaddr_len(remote_addr)); - -- if (r == -1 && errno != CONNECT_IN_PROGRESS) { -- ERROR("connect"); -- close_and_free_remote(EV_A_ remote); -- close_and_free_server(EV_A_ server); -- return; -+ if(!is_open(remotefd)) { -+ int r = connect(remotefd, remote_addr, get_sockaddr_len(remote_addr)); -+ -+ if (r == -1 && errno != CONNECT_IN_PROGRESS) { -+ ERROR("connect"); -+ close_and_free_remote(EV_A_ remote); -+ close_and_free_server(EV_A_ server); -+ return; -+ } - } -+ - // listen to remote connected event - ev_io_start(EV_A_ & remote->send_ctx->io); - ev_timer_start(EV_A_ & remote->send_ctx->watcher); -@@ -874,6 +1240,7 @@ - { "fast-open", no_argument, NULL, GETOPT_VAL_FAST_OPEN }, - { "mtu", required_argument, NULL, GETOPT_VAL_MTU }, - { "mptcp", no_argument, NULL, GETOPT_VAL_MPTCP }, -+ { "ebpf", no_argument, NULL, GETOPT_VAL_EBPF }, - { "plugin", required_argument, NULL, GETOPT_VAL_PLUGIN }, - { "plugin-opts", required_argument, NULL, GETOPT_VAL_PLUGIN_OPTS }, - { "reuse-port", no_argument, NULL, GETOPT_VAL_REUSE_PORT }, -@@ -902,6 +1269,10 @@ - mptcp = 1; - LOGI("enable multipath TCP"); - break; -+ case GETOPT_VAL_EBPF: -+ ebpf = 1; -+ LOGI("enable eBPF dataplane"); -+ break; - case GETOPT_VAL_NODELAY: - no_delay = 1; - LOGI("enable TCP no-delay"); -@@ -1042,6 +1413,9 @@ - if (mptcp == 0) { - mptcp = conf->mptcp; - } -+ if(ebpf == 0) { -+ ebpf = conf->ebpf; -+ } - if (no_delay == 0) { - no_delay = conf->no_delay; - } -@@ -1188,6 +1562,15 @@ - } - listen_ctx.timeout = atoi(timeout); - listen_ctx.mptcp = mptcp; -+ if(ebpf) { -+ int r = init_ebpf_object_buffers(&obufs); -+ if(r < 0) { -+ LOGE("Failed to load eBPF objects"); -+ } -+ else { -+ memset(connections, 0, 65536 * sizeof(ebpf_conn_t *)); -+ } -+ } - - struct ev_loop *loop = EV_DEFAULT; - -diff -aurN shadowsocks-libev-nocrypto-nocrypto/src/redir.h shadowsocks-libev-nocrypto-ebpf/src/redir.h ---- shadowsocks-libev-nocrypto-nocrypto/src/redir.h 2018-06-23 14:57:34.000000000 +0200 -+++ shadowsocks-libev-nocrypto-ebpf/src/redir.h 2018-08-14 13:45:18.000000000 +0200 -@@ -31,6 +31,24 @@ - #include "crypto.h" - #include "jconf.h" - -+typedef struct obufs -+{ -+ void *parse_prog; -+ void *verdict_prog; -+ int *verdict_port_p; -+ int parse_prog_size; -+ int verdict_prog_size; -+} obufs_t; -+ -+typedef struct ebpf_conn -+{ -+ int sockmap_fd; -+ int parse_prog_fd; -+ int verdict_prog_fd; -+ int local_sock; -+ int remote_sock; -+} ebpf_conn_t; -+ - typedef struct listen_ctx { - ev_io io; - int remote_num; -diff -aurN shadowsocks-libev-nocrypto-nocrypto/src/sockmap_parse.c shadowsocks-libev-nocrypto-ebpf/src/sockmap_parse.c ---- shadowsocks-libev-nocrypto-nocrypto/src/sockmap_parse.c 1970-01-01 01:00:00.000000000 +0100 -+++ shadowsocks-libev-nocrypto-ebpf/src/sockmap_parse.c 2018-08-14 13:45:18.000000000 +0200 -@@ -0,0 +1,19 @@ -+#include -+#include "bpf_helpers.h" -+ -+int _version SEC("version") = 1; -+ -+#define bpf_printk(fmt, ...) \ -+({ \ -+ char ____fmt[] = fmt; \ -+ bpf_trace_printk(____fmt, sizeof(____fmt), \ -+ ##__VA_ARGS__); \ -+}) -+ -+SEC("sk_skb_parse_prog") -+int sk_skb_parse(struct __sk_buff *skb) -+{ -+ return skb->len; -+} -+ -+char _license[] SEC("license") = "GPL"; -diff -aurN shadowsocks-libev-nocrypto-nocrypto/src/sockmap_parse.o.ebpf shadowsocks-libev-nocrypto-ebpf/src/sockmap_parse.o.ebpf ---- shadowsocks-libev-nocrypto-nocrypto/src/sockmap_parse.o.ebpf 1970-01-01 01:00:00.000000000 +0100 -+++ shadowsocks-libev-nocrypto-ebpf/src/sockmap_parse.o.ebpf 2018-08-14 13:45:18.000000000 +0200 -@@ -0,0 +1 @@ -+ELF@@a•GPL/".text_versionsk_skb_parse_progsk_skb_parse_license.strtab.symtab8¸H@@P0T@X` -\ Pas de fin de ligne à la fin du fichier -diff -aurN shadowsocks-libev-nocrypto-nocrypto/src/sockmap_verdict.c shadowsocks-libev-nocrypto-ebpf/src/sockmap_verdict.c ---- shadowsocks-libev-nocrypto-nocrypto/src/sockmap_verdict.c 1970-01-01 01:00:00.000000000 +0100 -+++ shadowsocks-libev-nocrypto-ebpf/src/sockmap_verdict.c 2018-08-14 13:45:18.000000000 +0200 -@@ -0,0 +1,22 @@ -+#include -+#include "bpf_helpers.h" -+ -+int _version SEC("version") = 1; -+ -+struct bpf_map_def SEC("maps") redirect_map = { -+ .type = BPF_MAP_TYPE_SOCKMAP, -+ .key_size = sizeof(int), -+ .value_size = sizeof(int), -+ .max_entries = 2, -+}; -+ -+SEC("sk_skb_verdict_prog") -+int sk_skb_verdict(struct __sk_buff *skb) -+{ -+ if(skb->local_port == 0xfcfcfcfc) -+ return bpf_sk_redirect_map(skb, &redirect_map, 0, 0); -+ -+ return bpf_sk_redirect_map(skb, &redirect_map, 1, 0); -+} -+ -+char _license[] SEC("license") = "GPL"; -diff -aurN shadowsocks-libev-nocrypto-nocrypto/src/sockmap_verdict.o.ebpf shadowsocks-libev-nocrypto-ebpf/src/sockmap_verdict.o.ebpf ---- shadowsocks-libev-nocrypto-nocrypto/src/sockmap_verdict.o.ebpf 1970-01-01 01:00:00.000000000 +0100 -+++ shadowsocks-libev-nocrypto-ebpf/src/sockmap_verdict.o.ebpf 2018-08-14 13:45:18.000000000 +0200 -@@ -0,0 +1 @@ -+ELF@@ aˆüüüü]2···…4•GPLi@bXI( @.textsk_skb_verdictmapsredirect_map_version.relsk_skb_verdict_prog_license.strtab.symtabLBB0_3LBB0_2R p@5@p1 € )°´JÐZب -\ Pas de fin de ligne à la fin du fichier