1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter-feeds.git synced 2025-02-13 11:01:50 +00:00
openmptcprouter-feeds/shadowsocks-libev/patches/030-eBPF.patch
2018-12-31 14:52:47 +01:00

884 lines
30 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 <libcork/core.h>
+#include <linux/bpf.h>
+#include <bpf/bpf.h>
+#include <bpf/libbpf.h>
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -69,6 +73,9 @@
#define IP6T_SO_ORIGINAL_DST 80
#endif
+#define PARSE_PROG_FILENAME "sockmap_parse.o.ebpf"
+#define VERDICT_PROG_FILENAME "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\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\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 <linux/bpf.h>
+#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<00>GPL/".text_versionsk_skb_parse_progsk_skb_parse_license.strtab.symtab8<00>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 <linux/bpf.h>
+#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<12><00><><EFBFBD><EFBFBD>]2<00><00><00><00>4<00>GPLi@bXI( @.textsk_skb_verdictmapsredirect_map_version.relsk_skb_verdict_prog_license.strtab.symtabLBB0_3LBB0_2R<00>p@5@p1 <00> )<00><00>J<00>Z<00><00>
\ Pas de fin de ligne à la fin du fichier