feat: add config_parser

This commit is contained in:
mzz2017
2023-01-27 02:10:27 +08:00
parent 916a55d480
commit edbce81e88
53 changed files with 6696 additions and 733 deletions

View File

@ -0,0 +1,99 @@
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
#ifndef __BPF_ENDIAN__
#define __BPF_ENDIAN__
/*
* Isolate byte #n and put it into byte #m, for __u##b type.
* E.g., moving byte #6 (nnnnnnnn) into byte #1 (mmmmmmmm) for __u64:
* 1) xxxxxxxx nnnnnnnn xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx mmmmmmmm xxxxxxxx
* 2) nnnnnnnn xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx mmmmmmmm xxxxxxxx 00000000
* 3) 00000000 00000000 00000000 00000000 00000000 00000000 00000000 nnnnnnnn
* 4) 00000000 00000000 00000000 00000000 00000000 00000000 nnnnnnnn 00000000
*/
#define ___bpf_mvb(x, b, n, m) ((__u##b)(x) << (b-(n+1)*8) >> (b-8) << (m*8))
#define ___bpf_swab16(x) ((__u16)( \
___bpf_mvb(x, 16, 0, 1) | \
___bpf_mvb(x, 16, 1, 0)))
#define ___bpf_swab32(x) ((__u32)( \
___bpf_mvb(x, 32, 0, 3) | \
___bpf_mvb(x, 32, 1, 2) | \
___bpf_mvb(x, 32, 2, 1) | \
___bpf_mvb(x, 32, 3, 0)))
#define ___bpf_swab64(x) ((__u64)( \
___bpf_mvb(x, 64, 0, 7) | \
___bpf_mvb(x, 64, 1, 6) | \
___bpf_mvb(x, 64, 2, 5) | \
___bpf_mvb(x, 64, 3, 4) | \
___bpf_mvb(x, 64, 4, 3) | \
___bpf_mvb(x, 64, 5, 2) | \
___bpf_mvb(x, 64, 6, 1) | \
___bpf_mvb(x, 64, 7, 0)))
/* LLVM's BPF target selects the endianness of the CPU
* it compiles on, or the user specifies (bpfel/bpfeb),
* respectively. The used __BYTE_ORDER__ is defined by
* the compiler, we cannot rely on __BYTE_ORDER from
* libc headers, since it doesn't reflect the actual
* requested byte order.
*
* Note, LLVM's BPF target has different __builtin_bswapX()
* semantics. It does map to BPF_ALU | BPF_END | BPF_TO_BE
* in bpfel and bpfeb case, which means below, that we map
* to cpu_to_be16(). We could use it unconditionally in BPF
* case, but better not rely on it, so that this header here
* can be used from application and BPF program side, which
* use different targets.
*/
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define __bpf_ntohs(x) __builtin_bswap16(x)
# define __bpf_htons(x) __builtin_bswap16(x)
# define __bpf_constant_ntohs(x) ___bpf_swab16(x)
# define __bpf_constant_htons(x) ___bpf_swab16(x)
# define __bpf_ntohl(x) __builtin_bswap32(x)
# define __bpf_htonl(x) __builtin_bswap32(x)
# define __bpf_constant_ntohl(x) ___bpf_swab32(x)
# define __bpf_constant_htonl(x) ___bpf_swab32(x)
# define __bpf_be64_to_cpu(x) __builtin_bswap64(x)
# define __bpf_cpu_to_be64(x) __builtin_bswap64(x)
# define __bpf_constant_be64_to_cpu(x) ___bpf_swab64(x)
# define __bpf_constant_cpu_to_be64(x) ___bpf_swab64(x)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define __bpf_ntohs(x) (x)
# define __bpf_htons(x) (x)
# define __bpf_constant_ntohs(x) (x)
# define __bpf_constant_htons(x) (x)
# define __bpf_ntohl(x) (x)
# define __bpf_htonl(x) (x)
# define __bpf_constant_ntohl(x) (x)
# define __bpf_constant_htonl(x) (x)
# define __bpf_be64_to_cpu(x) (x)
# define __bpf_cpu_to_be64(x) (x)
# define __bpf_constant_be64_to_cpu(x) (x)
# define __bpf_constant_cpu_to_be64(x) (x)
#else
# error "Fix your compiler's __BYTE_ORDER__?!"
#endif
#define bpf_htons(x) \
(__builtin_constant_p(x) ? \
__bpf_constant_htons(x) : __bpf_htons(x))
#define bpf_ntohs(x) \
(__builtin_constant_p(x) ? \
__bpf_constant_ntohs(x) : __bpf_ntohs(x))
#define bpf_htonl(x) \
(__builtin_constant_p(x) ? \
__bpf_constant_htonl(x) : __bpf_htonl(x))
#define bpf_ntohl(x) \
(__builtin_constant_p(x) ? \
__bpf_constant_ntohl(x) : __bpf_ntohl(x))
#define bpf_cpu_to_be64(x) \
(__builtin_constant_p(x) ? \
__bpf_constant_cpu_to_be64(x) : __bpf_cpu_to_be64(x))
#define bpf_be64_to_cpu(x) \
(__builtin_constant_p(x) ? \
__bpf_constant_be64_to_cpu(x) : __bpf_be64_to_cpu(x))
#endif /* __BPF_ENDIAN__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,263 @@
// Copied from https://github.com/cilium/ebpf/blob/e0ada270a5/examples/headers/bpf_helpers.h
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
#ifndef __BPF_HELPERS__
#define __BPF_HELPERS__
/*
* Note that bpf programs need to include either
* vmlinux.h (auto-generated from BTF) or linux/types.h
* in advance since bpf_helper_defs.h uses such types
* as __u64.
*/
#include "bpf_helper_defs.h"
#define __uint(name, val) int (*name)[val]
#define __type(name, val) typeof(val) *name
#define __array(name, val) typeof(val) *name[]
/*
* Helper macro to place programs, maps, license in
* different sections in elf_bpf file. Section names
* are interpreted by libbpf depending on the context (BPF programs, BPF maps,
* extern variables, etc).
* To allow use of SEC() with externs (e.g., for extern .maps declarations),
* make sure __attribute__((unused)) doesn't trigger compilation warning.
*/
#define SEC(name) \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wignored-attributes\"") \
__attribute__((section(name), used)) \
_Pragma("GCC diagnostic pop") \
/* Avoid 'linux/stddef.h' definition of '__always_inline'. */
#undef __always_inline
#define __always_inline inline __attribute__((always_inline))
#ifndef __noinline
#define __noinline __attribute__((noinline))
#endif
#ifndef __weak
#define __weak __attribute__((weak))
#endif
/*
* Use __hidden attribute to mark a non-static BPF subprogram effectively
* static for BPF verifier's verification algorithm purposes, allowing more
* extensive and permissive BPF verification process, taking into account
* subprogram's caller context.
*/
#define __hidden __attribute__((visibility("hidden")))
/* When utilizing vmlinux.h with BPF CO-RE, user BPF programs can't include
* any system-level headers (such as stddef.h, linux/version.h, etc), and
* commonly-used macros like NULL and KERNEL_VERSION aren't available through
* vmlinux.h. This just adds unnecessary hurdles and forces users to re-define
* them on their own. So as a convenience, provide such definitions here.
*/
#ifndef NULL
#define NULL ((void *)0)
#endif
#ifndef KERNEL_VERSION
#define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + ((c) > 255 ? 255 : (c)))
#endif
/*
* Helper macros to manipulate data structures
*/
#ifndef offsetof
#define offsetof(TYPE, MEMBER) ((unsigned long)&((TYPE *)0)->MEMBER)
#endif
#ifndef container_of
#define container_of(ptr, type, member) \
({ \
void *__mptr = (void *)(ptr); \
((type *)(__mptr - offsetof(type, member))); \
})
#endif
/*
* Helper macro to throw a compilation error if __bpf_unreachable() gets
* built into the resulting code. This works given BPF back end does not
* implement __builtin_trap(). This is useful to assert that certain paths
* of the program code are never used and hence eliminated by the compiler.
*
* For example, consider a switch statement that covers known cases used by
* the program. __bpf_unreachable() can then reside in the default case. If
* the program gets extended such that a case is not covered in the switch
* statement, then it will throw a build error due to the default case not
* being compiled out.
*/
#ifndef __bpf_unreachable
# define __bpf_unreachable() __builtin_trap()
#endif
/*
* Helper function to perform a tail call with a constant/immediate map slot.
*/
#if __clang_major__ >= 8 && defined(__bpf__)
static __always_inline void
bpf_tail_call_static(void *ctx, const void *map, const __u32 slot)
{
if (!__builtin_constant_p(slot))
__bpf_unreachable();
/*
* Provide a hard guarantee that LLVM won't optimize setting r2 (map
* pointer) and r3 (constant map index) from _different paths_ ending
* up at the _same_ call insn as otherwise we won't be able to use the
* jmpq/nopl retpoline-free patching by the x86-64 JIT in the kernel
* given they mismatch. See also d2e4c1e6c294 ("bpf: Constant map key
* tracking for prog array pokes") for details on verifier tracking.
*
* Note on clobber list: we need to stay in-line with BPF calling
* convention, so even if we don't end up using r0, r4, r5, we need
* to mark them as clobber so that LLVM doesn't end up using them
* before / after the call.
*/
asm volatile("r1 = %[ctx]\n\t"
"r2 = %[map]\n\t"
"r3 = %[slot]\n\t"
"call 12"
:: [ctx]"r"(ctx), [map]"r"(map), [slot]"i"(slot)
: "r0", "r1", "r2", "r3", "r4", "r5");
}
#endif
/*
* Helper structure used by eBPF C program
* to describe BPF map attributes to libbpf loader
*/
struct bpf_map_def {
unsigned int type;
unsigned int key_size;
unsigned int value_size;
unsigned int max_entries;
unsigned int map_flags;
};
enum libbpf_pin_type {
LIBBPF_PIN_NONE,
/* PIN_BY_NAME: pin maps by name (in /sys/fs/bpf by default) */
LIBBPF_PIN_BY_NAME,
};
enum libbpf_tristate {
TRI_NO = 0,
TRI_YES = 1,
TRI_MODULE = 2,
};
#define __kconfig __attribute__((section(".kconfig")))
#define __ksym __attribute__((section(".ksyms")))
#ifndef ___bpf_concat
#define ___bpf_concat(a, b) a ## b
#endif
#ifndef ___bpf_apply
#define ___bpf_apply(fn, n) ___bpf_concat(fn, n)
#endif
#ifndef ___bpf_nth
#define ___bpf_nth(_, _1, _2, _3, _4, _5, _6, _7, _8, _9, _a, _b, _c, N, ...) N
#endif
#ifndef ___bpf_narg
#define ___bpf_narg(...) \
___bpf_nth(_, ##__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#endif
#define ___bpf_fill0(arr, p, x) do {} while (0)
#define ___bpf_fill1(arr, p, x) arr[p] = x
#define ___bpf_fill2(arr, p, x, args...) arr[p] = x; ___bpf_fill1(arr, p + 1, args)
#define ___bpf_fill3(arr, p, x, args...) arr[p] = x; ___bpf_fill2(arr, p + 1, args)
#define ___bpf_fill4(arr, p, x, args...) arr[p] = x; ___bpf_fill3(arr, p + 1, args)
#define ___bpf_fill5(arr, p, x, args...) arr[p] = x; ___bpf_fill4(arr, p + 1, args)
#define ___bpf_fill6(arr, p, x, args...) arr[p] = x; ___bpf_fill5(arr, p + 1, args)
#define ___bpf_fill7(arr, p, x, args...) arr[p] = x; ___bpf_fill6(arr, p + 1, args)
#define ___bpf_fill8(arr, p, x, args...) arr[p] = x; ___bpf_fill7(arr, p + 1, args)
#define ___bpf_fill9(arr, p, x, args...) arr[p] = x; ___bpf_fill8(arr, p + 1, args)
#define ___bpf_fill10(arr, p, x, args...) arr[p] = x; ___bpf_fill9(arr, p + 1, args)
#define ___bpf_fill11(arr, p, x, args...) arr[p] = x; ___bpf_fill10(arr, p + 1, args)
#define ___bpf_fill12(arr, p, x, args...) arr[p] = x; ___bpf_fill11(arr, p + 1, args)
#define ___bpf_fill(arr, args...) \
___bpf_apply(___bpf_fill, ___bpf_narg(args))(arr, 0, args)
/*
* BPF_SEQ_PRINTF to wrap bpf_seq_printf to-be-printed values
* in a structure.
*/
#define BPF_SEQ_PRINTF(seq, fmt, args...) \
({ \
static const char ___fmt[] = fmt; \
unsigned long long ___param[___bpf_narg(args)]; \
\
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
___bpf_fill(___param, args); \
_Pragma("GCC diagnostic pop") \
\
bpf_seq_printf(seq, ___fmt, sizeof(___fmt), \
___param, sizeof(___param)); \
})
/*
* BPF_SNPRINTF wraps the bpf_snprintf helper with variadic arguments instead of
* an array of u64.
*/
#define BPF_SNPRINTF(out, out_size, fmt, args...) \
({ \
static const char ___fmt[] = fmt; \
unsigned long long ___param[___bpf_narg(args)]; \
\
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
___bpf_fill(___param, args); \
_Pragma("GCC diagnostic pop") \
\
bpf_snprintf(out, out_size, ___fmt, \
___param, sizeof(___param)); \
})
#ifdef BPF_NO_GLOBAL_DATA
#define BPF_PRINTK_FMT_MOD
#else
#define BPF_PRINTK_FMT_MOD static const
#endif
#define __bpf_printk(fmt, ...) \
({ \
BPF_PRINTK_FMT_MOD char ____fmt[] = fmt; \
bpf_trace_printk(____fmt, sizeof(____fmt), \
##__VA_ARGS__); \
})
/*
* __bpf_vprintk wraps the bpf_trace_vprintk helper with variadic arguments
* instead of an array of u64.
*/
#define __bpf_vprintk(fmt, args...) \
({ \
static const char ___fmt[] = fmt; \
unsigned long long ___param[___bpf_narg(args)]; \
\
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
___bpf_fill(___param, args); \
_Pragma("GCC diagnostic pop") \
\
bpf_trace_vprintk(___fmt, sizeof(___fmt), \
___param, sizeof(___param)); \
})
/* Use __bpf_printk when bpf_printk call has 3 or fewer fmt args
* Otherwise use __bpf_vprintk
*/
#define ___bpf_pick_printk(...) \
___bpf_nth(_, ##__VA_ARGS__, __bpf_vprintk, __bpf_vprintk, __bpf_vprintk, \
__bpf_vprintk, __bpf_vprintk, __bpf_vprintk, __bpf_vprintk, \
__bpf_vprintk, __bpf_vprintk, __bpf_printk /*3*/, __bpf_printk /*2*/,\
__bpf_printk /*1*/, __bpf_printk /*0*/)
/* Helper macro to print out debug messages */
#define bpf_printk(fmt, args...) ___bpf_pick_printk(args)(fmt, ##args)
#endif

View File

@ -1,30 +1,23 @@
// +build ignore
/*
* SPDX-License-Identifier: AGPL-3.0-only
* Copyright (c) since 2022, mzz2017 (mzz@tuta.io). All rights reserved.
*/
#include <asm-generic/errno-base.h>
#include <iproute2/bpf_elf.h>
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/kernel.h>
#include <linux/pkt_cls.h>
#include <linux/tcp.h>
#include <linux/types.h>
#include <linux/udp.h>
#include <net/if.h>
#include <stdbool.h>
#include <bpf/bpf_endian.h>
#include <bpf/bpf_helpers.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#include "bpf_endian.h"
#include "bpf_helpers.h"
// #include "addr.h"
// #define likely(x) x
// #define unlikely(x) x
@ -41,12 +34,15 @@
#define MAX_PARAM_LEN 16
#define MAX_INTERFACE_NUM 128
#define MAX_ROUTING_LEN 96
#define MAX_ROUTING_LEN (32 * 3)
#define MAX_LPM_SIZE 20480
//#define MAX_LPM_SIZE 20480
#define MAX_LPM_NUM (MAX_ROUTING_LEN + 8)
#define MAX_DEST_MAPPING_NUM (65536 * 2)
#define IPV6_MAX_EXTENSIONS 4
#define OUTBOUND_DIRECT 0
#define OUTBOUND_BLOCK 1
#define OUTBOUND_CONTROL_PLANE_DIRECT 0xFE
#define OUTBOUND_LOGICAL_AND 0xFF
@ -62,10 +58,6 @@ static const __u32 zero_key = 0;
static const __u32 tproxy_port_key = 1;
static const __u32 disable_l4_tx_checksum_key = 2;
static const __u32 disable_l4_rx_checksum_key = 3;
static const __u32 epoch_key __attribute__((unused, deprecated)) = 4;
static const __u32 routings_len_key __attribute__((unused, deprecated)) = 5;
static __be32 unspecific_ipv6[4] __attribute__((__unused__)) = {0, 0, 0, 0};
struct ip_port {
__be32 ip[4];
@ -96,7 +88,7 @@ struct {
// enough for identifier. And UDP client
// side does not care it (full-cone).
__type(value, struct ip_port_outbound); // Original target.
__uint(max_entries, 0xFF << 2);
__uint(max_entries, MAX_DEST_MAPPING_NUM);
/// NOTICE: It MUST be pinned.
__uint(pinning, LIBBPF_PIN_BY_NAME);
} dst_map SEC(".maps");
@ -132,7 +124,7 @@ struct {
__uint(max_entries, MAX_INTERFACE_NUM);
/// NOTICE: No persistence.
// __uint(pinning, LIBBPF_PIN_BY_NAME);
} ifindex_ip_map SEC(".maps");
} ifindex_tproxy_ip_map SEC(".maps");
// Array of LPM tries:
struct lpm_key {
@ -145,12 +137,12 @@ struct map_lpm_type {
__uint(max_entries, MAX_LPM_SIZE);
__uint(key_size, sizeof(struct lpm_key));
__uint(value_size, sizeof(__u32));
} unused_lpm_type SEC(".maps");
} unused_lpm_type SEC(".maps"), host_ip_lpm SEC(".maps");
struct {
__uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
__uint(key_size, sizeof(__u32));
__uint(max_entries, MAX_LPM_NUM);
__uint(pinning, LIBBPF_PIN_BY_NAME);
// __uint(pinning, LIBBPF_PIN_BY_NAME);
__array(values, struct map_lpm_type);
} lpm_array_map SEC(".maps");
@ -199,16 +191,11 @@ struct {
__type(key, __u32);
__type(value, struct routing);
__uint(max_entries, MAX_ROUTING_LEN);
__uint(pinning, LIBBPF_PIN_BY_NAME);
// __uint(pinning, LIBBPF_PIN_BY_NAME);
} routing_map SEC(".maps");
struct domain_routing {
__u32 bitmap[MAX_ROUTING_LEN / 32];
/// DEPRECATED: Epoch is the epoch at the write time. Every time the control
/// plane restarts, epoch += 1. It was deprecated because long connection will
/// keep their states by persistent dst_map (we only need to know if it is a
/// old connection).
__u32 epoch;
};
struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
@ -220,7 +207,7 @@ struct {
// Functions:
static __always_inline bool equal_ipv6(__be32 x[4], __be32 y[4]) {
static __always_inline bool equal_ipv6_format(__be32 x[4], __be32 y[4]) {
#if __clang_major__ >= 10
return ((__be64 *)x)[0] == ((__be64 *)y)[0] &&
((__be64 *)x)[1] == ((__be64 *)y)[1];
@ -248,7 +235,7 @@ static __always_inline long rewrite_ip(struct __sk_buff *skb, bool is_ipv6,
__u8 proto, __u8 ihl, __be32 old_ip[4],
__be32 new_ip[4], bool is_dest) {
// Nothing to do.
if (equal_ipv6(old_ip, new_ip)) {
if (equal_ipv6_format(old_ip, new_ip)) {
return 0;
}
// bpf_printk("%pI6->%pI6", old_ip, new_ip);
@ -486,28 +473,26 @@ parse_transport(struct __sk_buff *skb, struct ethhdr **ethh, struct iphdr **iph,
}
static __always_inline long ip_is_host(bool is_ipv6, __u32 ifindex,
__be32 ip[4],
__be32 (*first_interface_ip)[4]) {
struct if_ip *if_ip = bpf_map_lookup_elem(&ifindex_ip_map, &ifindex);
if (unlikely(!if_ip)) {
return -1;
__be32 ip[4], __be32 tproxy_ip[4]) {
if (tproxy_ip) {
struct if_ip *if_ip = bpf_map_lookup_elem(&ifindex_tproxy_ip_map, &ifindex);
if (unlikely(!if_ip)) {
return -1;
}
if (!is_ipv6 && (*if_ip).hasIp4) {
__builtin_memcpy(tproxy_ip, (*if_ip).ip4, IPV6_BYTE_LENGTH);
} else if (is_ipv6 && (*if_ip).hasIp6) {
__builtin_memcpy(tproxy_ip, (*if_ip).ip6, IPV6_BYTE_LENGTH);
} else {
// Should TC_ACT_OK outer.
return -EFAULT;
}
}
__u32 host_ip[4];
if (!is_ipv6 && (*if_ip).hasIp4) {
__builtin_memcpy(host_ip, (*if_ip).ip4, IPV6_BYTE_LENGTH);
} else if (is_ipv6 && (*if_ip).hasIp6) {
__builtin_memcpy(host_ip, (*if_ip).ip6, IPV6_BYTE_LENGTH);
} else {
// Should TC_ACT_OK outer.
return -EFAULT;
}
if (first_interface_ip) {
__builtin_memcpy(*first_interface_ip, host_ip, IPV6_BYTE_LENGTH);
}
if (equal_ipv6(ip, host_ip)) {
return 1;
}
return 0;
struct lpm_key lpm_key;
lpm_key.trie_key.prefixlen = IPV6_BYTE_LENGTH * 8;
__builtin_memcpy(lpm_key.data, ip, IPV6_BYTE_LENGTH);
return bpf_map_lookup_elem(&host_ip_lpm, &lpm_key) ? 1 : 0;
}
static __always_inline long adjust_udp_len(struct __sk_buff *skb, __u16 oldlen,
@ -597,9 +582,9 @@ static __always_inline long encap_after_udp_hdr(struct __sk_buff *skb,
__be16 iphdr_tot_len,
void *newhdr, __u32 newhdrlen) {
if (unlikely(newhdrlen % 4 != 0)) {
bpf_trace_printk("encap_after_udp_hdr: unexpected newhdrlen value %u :must "
"be a multiple of 4",
newhdrlen);
bpf_printk("encap_after_udp_hdr: unexpected newhdrlen value %u :must "
"be a multiple of 4",
newhdrlen);
return -EINVAL;
}
@ -664,10 +649,9 @@ static __always_inline int decap_after_udp_hdr(struct __sk_buff *skb,
__be16 iphdr_tot_len, void *to,
__u32 decap_hdrlen) {
if (unlikely(decap_hdrlen % 4 != 0)) {
bpf_trace_printk(
"encap_after_udp_hdr: unexpected decap_hdrlen value %u :must "
"be a multiple of 4",
decap_hdrlen);
bpf_printk("encap_after_udp_hdr: unexpected decap_hdrlen value %u :must "
"be a multiple of 4",
decap_hdrlen);
return -EINVAL;
}
long ret = 0;
@ -742,15 +726,7 @@ static long routing(__u8 flag[2], void *l4_hdr, __be32 saddr[4],
__be32 daddr[4], __be32 mac[4]) {
#define _l4proto flag[0]
#define _ipversion flag[1]
// // Get len of routings and epoch from param_map.
// __u32 *routings_len = bpf_map_lookup_elem(&param_map, &routings_len_key);
// if (!routings_len) {
// return -EINVAL;
// }
// __u32 *epoch = bpf_map_lookup_elem(&param_map, &epoch_key);
// if (!epoch) {
// return -EINVAL;
// }
// Define variables for further use.
__u16 h_dport;
__u16 h_sport;
@ -786,13 +762,6 @@ static long routing(__u8 flag[2], void *l4_hdr, __be32 saddr[4],
bool bad_rule = false;
struct domain_routing *domain_routing;
/// DEPRECATED: Epoch was deprecated and domain_routing_map was unpinned, thus
/// this branch will never hit.
// if (domain_routing && domain_routing->epoch != *epoch) {
// // Dirty (epoch dismatch) traffic should be routed by the control plane.
// return OUTBOUND_CONTROL_PLANE_DIRECT;
// }
#pragma unroll
for (__u32 key = 0; key < MAX_ROUTING_LEN; key++) {
__u32 k = key; // Clone to pass code checker.
@ -895,6 +864,7 @@ int tproxy_ingress(struct __sk_buff *skb) {
struct udphdr *udph;
__sum16 bak_cksm;
__u8 ihl;
bool tcp_state_syn;
long ret = parse_transport(skb, &ethh, &iph, &ipv6h, &tcph, &udph, &ihl);
if (ret) {
bpf_printk("parse_transport: %ld", ret);
@ -906,13 +876,7 @@ int tproxy_ingress(struct __sk_buff *skb) {
// Backup for further use.
__u8 l4_proto;
if (tcph) {
l4_proto = IPPROTO_TCP;
} else if (udph) {
l4_proto = IPPROTO_UDP;
} else {
return TC_ACT_OK;
}
__be16 ip_tot_len = 0;
// Parse saddr and daddr as ipv6 format.
__be32 saddr[4];
@ -927,6 +891,8 @@ int tproxy_ingress(struct __sk_buff *skb) {
daddr[1] = 0;
daddr[2] = bpf_htonl(0x0000ffff);
daddr[3] = iph->daddr;
ip_tot_len = iph->tot_len;
} else if (ipv6h) {
__builtin_memcpy(daddr, &ipv6h->daddr, IPV6_BYTE_LENGTH);
__builtin_memcpy(saddr, &ipv6h->saddr, IPV6_BYTE_LENGTH);
@ -935,8 +901,8 @@ int tproxy_ingress(struct __sk_buff *skb) {
}
// If this packet is sent to this host, accept it.
__u32 first_interface_ip[4];
long to_host = ip_is_host(ipv6h, skb->ifindex, daddr, &first_interface_ip);
__u32 tproxy_ip[4];
long to_host = ip_is_host(ipv6h, skb->ifindex, daddr, tproxy_ip);
if (to_host < 0) { // error
// bpf_printk("to_host: %ld", to_host);
return TC_ACT_OK;
@ -946,7 +912,6 @@ int tproxy_ingress(struct __sk_buff *skb) {
// To host:53. Process it.
} else {
// To host. Accept.
/// FIXME: all host ip.
return TC_ACT_OK;
}
}
@ -958,8 +923,9 @@ int tproxy_ingress(struct __sk_buff *skb) {
if (tcph) {
// Backup for further use.
l4_proto = IPPROTO_TCP;
bak_cksm = tcph->check;
bool tcp_state_syn = tcph->syn && !tcph->ack;
tcp_state_syn = tcph->syn && !tcph->ack;
struct ip_port_proto key_src;
__builtin_memset(&key_src, 0, sizeof(key_src));
__builtin_memcpy(key_src.ip, saddr, IPV6_BYTE_LENGTH);
@ -1003,6 +969,8 @@ int tproxy_ingress(struct __sk_buff *skb) {
bpf_printk("tcp: outbound: %u, %pI6", outbound, daddr);
if (outbound == OUTBOUND_DIRECT) {
return TC_ACT_OK;
} else if (unlikely(outbound == OUTBOUND_BLOCK)) {
return TC_ACT_SHOT;
} else {
// Rewrite to control plane.
@ -1017,8 +985,8 @@ int tproxy_ingress(struct __sk_buff *skb) {
__u32 *dst_ip = daddr;
__u16 dst_port = tcph->dest;
if ((ret = rewrite_ip(skb, ipv6h, IPPROTO_TCP, ihl, dst_ip,
first_interface_ip, true))) {
if ((ret = rewrite_ip(skb, ipv6h, IPPROTO_TCP, ihl, dst_ip, tproxy_ip,
true))) {
bpf_printk("Shot IP: %ld", ret);
return TC_ACT_SHOT;
}
@ -1031,6 +999,7 @@ int tproxy_ingress(struct __sk_buff *skb) {
} else if (udph) {
// Backup for further use.
bak_cksm = udph->check;
l4_proto = IPPROTO_UDP;
struct ip_port_outbound new_hdr;
__builtin_memset(&new_hdr, 0, sizeof(new_hdr));
__builtin_memcpy(new_hdr.ip, daddr, IPV6_BYTE_LENGTH);
@ -1059,18 +1028,19 @@ int tproxy_ingress(struct __sk_buff *skb) {
if (new_hdr.outbound == OUTBOUND_DIRECT) {
return TC_ACT_OK;
} else if (unlikely(new_hdr.outbound == OUTBOUND_BLOCK)) {
return TC_ACT_SHOT;
} else {
// Rewrite to control plane.
// Encap a header to transmit fullcone tuple.
__be16 ip_tot_len = iph ? iph->tot_len : 0;
encap_after_udp_hdr(skb, ipv6h, ihl, ip_tot_len, &new_hdr,
sizeof(new_hdr));
// Rewrite udp dst ip.
// bpf_printk("rewrite dst ip from %pI4", &ori_dst.ip);
if ((ret = rewrite_ip(skb, ipv6h, IPPROTO_UDP, ihl, new_hdr.ip,
first_interface_ip, true))) {
if ((ret = rewrite_ip(skb, ipv6h, IPPROTO_UDP, ihl, new_hdr.ip, tproxy_ip,
true))) {
bpf_printk("Shot IP: %ld", ret);
return TC_ACT_SHOT;
}
@ -1129,6 +1099,7 @@ int tproxy_egress(struct __sk_buff *skb) {
struct tcphdr *tcph;
struct udphdr *udph;
__sum16 bak_cksm;
__u8 l4_proto;
__u8 ihl;
long ret = parse_transport(skb, &ethh, &iph, &ipv6h, &tcph, &udph, &ihl);
if (ret) {
@ -1138,6 +1109,7 @@ int tproxy_egress(struct __sk_buff *skb) {
// Parse saddr and daddr as ipv6 format.
__be32 saddr[4];
__be32 daddr[4];
__be16 ip_tot_len = 0;
if (iph) {
saddr[0] = 0;
saddr[1] = 0;
@ -1148,6 +1120,8 @@ int tproxy_egress(struct __sk_buff *skb) {
daddr[1] = 0;
daddr[2] = bpf_htonl(0x0000ffff);
daddr[3] = iph->daddr;
ip_tot_len = iph->tot_len;
} else if (ipv6h) {
__builtin_memcpy(daddr, ipv6h->daddr.in6_u.u6_addr32, IPV6_BYTE_LENGTH);
__builtin_memcpy(saddr, ipv6h->saddr.in6_u.u6_addr32, IPV6_BYTE_LENGTH);
@ -1160,23 +1134,17 @@ int tproxy_egress(struct __sk_buff *skb) {
if (!tproxy_port) {
return TC_ACT_OK;
}
long from_host = ip_is_host(ipv6h, skb->ifindex, saddr, NULL);
if (!(from_host == 1)) {
// Not from localhost.
__be32 tproxy_ip[4];
ret = ip_is_host(ipv6h, skb->ifindex, saddr, tproxy_ip);
if (!(ret == 1)) {
return TC_ACT_OK;
}
if (!equal_ipv6_format(saddr, tproxy_ip)) {
return TC_ACT_OK;
}
// Backup for further use.
__u8 l4_proto;
if (tcph) {
l4_proto = IPPROTO_TCP;
} else if (udph) {
l4_proto = IPPROTO_UDP;
} else {
return TC_ACT_OK;
}
if (tcph) {
if (tcph->source != *tproxy_port) {
return TC_ACT_OK;
}
@ -1216,6 +1184,7 @@ int tproxy_egress(struct __sk_buff *skb) {
return TC_ACT_SHOT;
}
} else if (udph) {
l4_proto = IPPROTO_UDP;
if (udph->source != *tproxy_port) {
return TC_ACT_OK;
}
@ -1233,7 +1202,6 @@ int tproxy_egress(struct __sk_buff *skb) {
// Get source ip/port from our packet header.
// Decap header to get fullcone tuple.
__be16 ip_tot_len = iph ? iph->tot_len : 0;
decap_after_udp_hdr(skb, ipv6h, ihl, ip_tot_len, &ori_src, sizeof(ori_src));
// Rewrite udp src ip
@ -1274,7 +1242,7 @@ int tproxy_egress(struct __sk_buff *skb) {
if (*disable_l4_checksum == DISABLE_L4_CHECKSUM_POLICY_SET_ZERO) {
bak_cksm = 0;
}
bpf_skb_store_bytes(skb, l4_cksm_off, &bak_cksm, 2, 0);
bpf_skb_store_bytes(skb, l4_cksm_off, &bak_cksm, sizeof(bak_cksm), 0);
}
}
return TC_ACT_OK;