mirror of
https://github.com/daeuniverse/dae.git
synced 2025-07-04 15:27:55 +07:00
feat: support real process name traffic split (#6)
This commit is contained in:
@ -29,11 +29,19 @@ type _bpfPortRange struct {
|
||||
PortEnd uint16
|
||||
}
|
||||
|
||||
func (r _bpfPortRange) Encode() uint32 {
|
||||
var b [4]byte
|
||||
binary.BigEndian.PutUint16(b[:2], r.PortStart)
|
||||
binary.BigEndian.PutUint16(b[2:], r.PortEnd)
|
||||
return binary.BigEndian.Uint32(b[:])
|
||||
type _bpfMatchSet struct {
|
||||
// TODO: Need sync with C code.
|
||||
Value [16]byte
|
||||
Type uint8
|
||||
Not bool
|
||||
Outbound uint8
|
||||
_ [1]byte
|
||||
}
|
||||
|
||||
func (r _bpfPortRange) Encode() (b [16]byte) {
|
||||
binary.LittleEndian.PutUint16(b[:2], r.PortStart)
|
||||
binary.LittleEndian.PutUint16(b[2:], r.PortEnd)
|
||||
return b
|
||||
}
|
||||
|
||||
func (o *bpfObjects) newLpmMap(keys []_bpfLpmKey, values []uint32) (m *ebpf.Map, err error) {
|
||||
|
@ -69,6 +69,10 @@ func NewControlPlane(
|
||||
if kernelVersion.Less(consts.BasicFeatureVersion) {
|
||||
return nil, fmt.Errorf("your kernel version %v does not satisfy basic requirement; expect >=%v", c.kernelVersion.String(), consts.BasicFeatureVersion.String())
|
||||
}
|
||||
if len(wanInterface) > 0 && kernelVersion.Less(consts.CgSocketCookieFeatureVersion) {
|
||||
return nil, fmt.Errorf("your kernel version %v does not support bind to WAN; expect >=%v; remove wan_interface in config file and try again", kernelVersion.String(),
|
||||
consts.CgSocketCookieFeatureVersion.String())
|
||||
}
|
||||
|
||||
// Allow the current process to lock memory for eBPF resources.
|
||||
if err = rlimit.RemoveMemlock(); err != nil {
|
||||
@ -83,7 +87,8 @@ func NewControlPlane(
|
||||
var ProgramOptions ebpf.ProgramOptions
|
||||
if log.IsLevelEnabled(logrus.TraceLevel) {
|
||||
ProgramOptions = ebpf.ProgramOptions{
|
||||
LogLevel: ebpf.LogLevelInstruction | ebpf.LogLevelStats,
|
||||
LogLevel: ebpf.LogLevelBranch | ebpf.LogLevelStats,
|
||||
//LogLevel: ebpf.LogLevelInstruction | ebpf.LogLevelStats,
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,7 +97,7 @@ func NewControlPlane(
|
||||
if len(lanInterface) > 0 && len(wanInterface) == 0 {
|
||||
// Only bind LAN.
|
||||
obj = &bpfObjectsLan{}
|
||||
} else if len(wanInterface) == 0 && len(wanInterface) > 0 {
|
||||
} else if len(lanInterface) == 0 && len(wanInterface) > 0 {
|
||||
// Only bind to WAN.
|
||||
// Trick. Replace the beams with rotten timbers.
|
||||
obj = &bpfObjectsWan{}
|
||||
|
@ -164,10 +164,6 @@ func (c *ControlPlaneCore) BindLan(ifname string) error {
|
||||
}
|
||||
|
||||
func (c *ControlPlaneCore) BindWan(ifname string) error {
|
||||
if c.kernelVersion.Less(consts.BasicFeatureVersion) {
|
||||
return fmt.Errorf("your kernel version %v does not support bind to WAN; expect >=%v; remove wan_interface in config file and try again", c.kernelVersion.String(), consts.CgGetPidFeatureVersion.String())
|
||||
}
|
||||
|
||||
c.log.Infof("Bind to WAN: %v", ifname)
|
||||
link, err := netlink.LinkByName(ifname)
|
||||
if err != nil {
|
||||
|
1
component/control/kern/headers
Submodule
1
component/control/kern/headers
Submodule
Submodule component/control/kern/headers added at 372c3cc61d
@ -3,20 +3,17 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* Copyright (c) since 2022, v2rayA Organization <team@v2raya.org>
|
||||
*/
|
||||
#include <asm-generic/errno-base.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/pkt_cls.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <stdbool.h>
|
||||
#include "headers/if_ether_defs.h"
|
||||
#include "headers/pkt_cls_defs.h"
|
||||
#include "headers/socket_defs.h"
|
||||
#include "headers/vmlinux.h"
|
||||
|
||||
#include <asm-generic/errno-base.h>
|
||||
|
||||
#include <bpf/bpf_core_read.h>
|
||||
#include <bpf/bpf_endian.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
|
||||
// #define __DEBUG_ROUTING
|
||||
// #define __PRINT_ROUTING_RESULT
|
||||
@ -53,6 +50,8 @@
|
||||
#define MAX_DST_MAPPING_NUM (65536 * 2)
|
||||
#define MAX_SRC_PID_PNAME_MAPPING_NUM (65536)
|
||||
#define IPV6_MAX_EXTENSIONS 4
|
||||
#define MAX_ARG_LEN_TO_PROBE 192
|
||||
#define MAX_ARG_SCANNER_BUFFER_SIZE (TASK_COMM_LEN * 4)
|
||||
|
||||
#define OUTBOUND_DIRECT 0
|
||||
#define OUTBOUND_BLOCK 1
|
||||
@ -229,6 +228,7 @@ struct port_range {
|
||||
*/
|
||||
struct match_set {
|
||||
union {
|
||||
/// NOTICE: MUST sync with component/control/bpf_utils.go.
|
||||
__u32 __value; // Placeholder for bpf2go.
|
||||
|
||||
__u32 index;
|
||||
@ -827,13 +827,13 @@ routing(const __u32 flag[6], const void *l4_hdr, const __be32 saddr[4],
|
||||
|
||||
/// TODO: BPF_MAP_UPDATE_BATCH ?
|
||||
__u32 key = MatchType_L4Proto;
|
||||
if ((ret = bpf_map_update_elem(&l4proto_ipversion_map, &key, &_l4proto_type,
|
||||
BPF_ANY))) {
|
||||
if (unlikely((ret = bpf_map_update_elem(&l4proto_ipversion_map, &key,
|
||||
&_l4proto_type, BPF_ANY)))) {
|
||||
return ret;
|
||||
};
|
||||
key = MatchType_IpVersion;
|
||||
if ((ret = bpf_map_update_elem(&l4proto_ipversion_map, &key, &_ipversion_type,
|
||||
BPF_ANY))) {
|
||||
if (unlikely((ret = bpf_map_update_elem(&l4proto_ipversion_map, &key,
|
||||
&_ipversion_type, BPF_ANY)))) {
|
||||
return ret;
|
||||
};
|
||||
|
||||
@ -849,11 +849,13 @@ routing(const __u32 flag[6], const void *l4_hdr, const __be32 saddr[4],
|
||||
}
|
||||
|
||||
key = MatchType_SourcePort;
|
||||
if ((ret = bpf_map_update_elem(&h_port_map, &key, &h_sport, BPF_ANY))) {
|
||||
if (unlikely(
|
||||
(ret = bpf_map_update_elem(&h_port_map, &key, &h_sport, BPF_ANY)))) {
|
||||
return ret;
|
||||
};
|
||||
key = MatchType_Port;
|
||||
if ((ret = bpf_map_update_elem(&h_port_map, &key, &h_dport, BPF_ANY))) {
|
||||
if (unlikely(
|
||||
(ret = bpf_map_update_elem(&h_port_map, &key, &h_dport, BPF_ANY)))) {
|
||||
return ret;
|
||||
};
|
||||
|
||||
@ -862,7 +864,7 @@ routing(const __u32 flag[6], const void *l4_hdr, const __be32 saddr[4],
|
||||
if (h_dport == 53 && _l4proto_type == L4ProtoType_UDP) {
|
||||
struct ip_port *upstream =
|
||||
bpf_map_lookup_elem(&dns_upstream_map, &zero_key);
|
||||
if (!upstream) {
|
||||
if (unlikely(!upstream)) {
|
||||
return -EFAULT;
|
||||
}
|
||||
h_dport = bpf_ntohs(upstream->port);
|
||||
@ -875,21 +877,21 @@ routing(const __u32 flag[6], const void *l4_hdr, const __be32 saddr[4],
|
||||
__builtin_memcpy(lpm_key_instance.data, daddr, IPV6_BYTE_LENGTH);
|
||||
// bpf_printk("mac: %pI6", mac);
|
||||
key = MatchType_IpSet;
|
||||
if ((ret = bpf_map_update_elem(&lpm_key_map, &key, &lpm_key_instance,
|
||||
BPF_ANY))) {
|
||||
if (unlikely((ret = bpf_map_update_elem(&lpm_key_map, &key, &lpm_key_instance,
|
||||
BPF_ANY)))) {
|
||||
return ret;
|
||||
};
|
||||
__builtin_memcpy(lpm_key_instance.data, saddr, IPV6_BYTE_LENGTH);
|
||||
key = MatchType_SourceIpSet;
|
||||
if ((ret = bpf_map_update_elem(&lpm_key_map, &key, &lpm_key_instance,
|
||||
BPF_ANY))) {
|
||||
if (unlikely((ret = bpf_map_update_elem(&lpm_key_map, &key, &lpm_key_instance,
|
||||
BPF_ANY)))) {
|
||||
return ret;
|
||||
};
|
||||
if (!_is_wan) {
|
||||
__builtin_memcpy(lpm_key_instance.data, mac, IPV6_BYTE_LENGTH);
|
||||
key = MatchType_Mac;
|
||||
if ((ret = bpf_map_update_elem(&lpm_key_map, &key, &lpm_key_instance,
|
||||
BPF_ANY))) {
|
||||
if (unlikely((ret = bpf_map_update_elem(&lpm_key_map, &key,
|
||||
&lpm_key_instance, BPF_ANY)))) {
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
@ -909,7 +911,7 @@ routing(const __u32 flag[6], const void *l4_hdr, const __be32 saddr[4],
|
||||
for (__u32 i = 0; i < MAX_MATCH_SET_LEN; i++) {
|
||||
__u32 k = i; // Clone to pass code checker.
|
||||
match_set = bpf_map_lookup_elem(&routing_map, &k);
|
||||
if (!match_set) {
|
||||
if (unlikely(!match_set)) {
|
||||
return -EFAULT;
|
||||
}
|
||||
if (bad_rule || good_subrule) {
|
||||
@ -980,8 +982,8 @@ routing(const __u32 flag[6], const void *l4_hdr, const __be32 saddr[4],
|
||||
if ((domain_routing->bitmap[i / 32] >> (i % 32)) & 1) {
|
||||
good_subrule = true;
|
||||
}
|
||||
} else if (_is_wan && match_set->type == MatchType_ProcessName) {
|
||||
if ((equal_ipv6_format(match_set->pname, _pname))) {
|
||||
} else if (match_set->type == MatchType_ProcessName) {
|
||||
if (_is_wan && equal_ipv6_format(match_set->pname, _pname)) {
|
||||
good_subrule = true;
|
||||
}
|
||||
} else if (match_set->type == MatchType_Final) {
|
||||
@ -1298,7 +1300,7 @@ static __always_inline bool pid_is_control_plane(struct __sk_buff *skb,
|
||||
if (p) {
|
||||
*p = NULL;
|
||||
}
|
||||
if ((skb->mark & 0x80) == 0x80) {
|
||||
if ((skb->mark & 0x100) == 0x100) {
|
||||
bpf_printk("No pid_pname found. But it should not happen");
|
||||
/*
|
||||
if (l4proto == IPPROTO_TCP) {
|
||||
@ -1934,7 +1936,7 @@ int tproxy_wan_ingress(struct __sk_buff *skb) {
|
||||
}
|
||||
|
||||
static int __always_inline update_map_elem_by_cookie(const __u64 cookie) {
|
||||
if (!cookie) {
|
||||
if (unlikely(!cookie)) {
|
||||
bpf_printk("zero cookie");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -1943,15 +1945,67 @@ static int __always_inline update_map_elem_by_cookie(const __u64 cookie) {
|
||||
// Build value.
|
||||
struct pid_pname val;
|
||||
__builtin_memset(&val, 0, sizeof(struct pid_pname));
|
||||
val.pid = bpf_get_current_pid_tgid() >> 32;
|
||||
// struct task_struct *t = (void *)bpf_get_current_task();
|
||||
if ((ret = bpf_get_current_comm(val.pname, sizeof(val.pname)))) {
|
||||
return ret;
|
||||
char buf[MAX_ARG_SCANNER_BUFFER_SIZE] = {0};
|
||||
struct task_struct *current = (void *)bpf_get_current_task();
|
||||
unsigned long arg_start = BPF_CORE_READ(current, mm, arg_start);
|
||||
unsigned long arg_end = BPF_CORE_READ(current, mm, arg_end);
|
||||
unsigned long arg_len = arg_end - arg_start;
|
||||
if (arg_len > MAX_ARG_LEN_TO_PROBE) {
|
||||
arg_len = MAX_ARG_LEN_TO_PROBE;
|
||||
}
|
||||
|
||||
/**
|
||||
For string like: /usr/lib/sddm/sddm-helper --socket /tmp/sddm-auth1
|
||||
We extract "sddm-helper" from it.
|
||||
*/
|
||||
unsigned long loc, j;
|
||||
unsigned long last_slash = -1;
|
||||
#pragma unroll
|
||||
for (loc = 0, j = 0; j < MAX_ARG_LEN_TO_PROBE;
|
||||
++j, loc = ((loc + 1) & (MAX_ARG_SCANNER_BUFFER_SIZE - 1))) {
|
||||
// volatile unsigned long k = j; // Cheat to unroll.
|
||||
// if (arg_start + k >= arg_end) {
|
||||
if (unlikely(arg_start + j >= arg_end)) {
|
||||
break;
|
||||
}
|
||||
if (unlikely(loc == 0)) {
|
||||
/// WANRING: Do NOT use bpf_core_read_user_str, it will bring terminator
|
||||
/// 0.
|
||||
// __builtin_memset(&buf, 0, MAX_ARG_SCANNER_BUFFER_SIZE);
|
||||
unsigned long to_read = arg_end - (arg_start + j);
|
||||
if (to_read >= MAX_ARG_SCANNER_BUFFER_SIZE) {
|
||||
to_read = MAX_ARG_SCANNER_BUFFER_SIZE;
|
||||
} else {
|
||||
buf[to_read] = 0;
|
||||
}
|
||||
if ((ret = bpf_core_read_user(&buf, to_read, arg_start + j))) {
|
||||
bpf_printk("failed to read process name: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (unlikely(buf[loc] == '/')) {
|
||||
last_slash = j;
|
||||
} else if (unlikely(buf[loc] == ' ' || buf[loc] == 0)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
++last_slash;
|
||||
unsigned long length_cpy = j - last_slash;
|
||||
if (length_cpy > TASK_COMM_LEN) {
|
||||
length_cpy = TASK_COMM_LEN;
|
||||
}
|
||||
if ((ret = bpf_core_read_user(&val.pname, length_cpy,
|
||||
arg_start + last_slash))) {
|
||||
bpf_printk("failed to read process name: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
val.pid = BPF_CORE_READ(current, tgid);
|
||||
// bpf_printk("a start_end: %lu %lu", arg_start, arg_end);
|
||||
// bpf_printk("b start_end: %lu %lu", arg_start + last_slash, arg_start + j);
|
||||
|
||||
// Update map.
|
||||
if ((ret =
|
||||
bpf_map_update_elem(&cookie_pid_map, &cookie, &val, BPF_NOEXIST))) {
|
||||
if (unlikely(ret = bpf_map_update_elem(&cookie_pid_map, &cookie, &val,
|
||||
BPF_NOEXIST))) {
|
||||
// bpf_printk("setup_mapping_from_sk: failed update map: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
@ -1970,7 +2024,7 @@ int tproxy_wan_cg_sock_create(struct bpf_sock *sk) {
|
||||
SEC("cgroup/sock_release")
|
||||
int tproxy_wan_cg_sock_release(struct bpf_sock *sk) {
|
||||
__u64 cookie = bpf_get_socket_cookie(sk);
|
||||
if (!cookie) {
|
||||
if (unlikely(!cookie)) {
|
||||
bpf_printk("zero cookie");
|
||||
return 1;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
package control
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"github.com/cilium/ebpf"
|
||||
"github.com/v2rayA/dae/common"
|
||||
@ -14,7 +15,6 @@ import (
|
||||
"github.com/v2rayA/dae/pkg/config_parser"
|
||||
"net/netip"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type DomainSet struct {
|
||||
@ -27,7 +27,7 @@ type RoutingMatcherBuilder struct {
|
||||
*routing.DefaultMatcherBuilder
|
||||
outboundName2Id map[string]uint8
|
||||
bpf *bpfObjects
|
||||
rules []bpfMatchSet
|
||||
rules []_bpfMatchSet
|
||||
SimulatedLpmTries [][]netip.Prefix
|
||||
SimulatedDomainSet []DomainSet
|
||||
Final string
|
||||
@ -74,7 +74,7 @@ func (b *RoutingMatcherBuilder) AddDomain(f *config_parser.Function, key string,
|
||||
RuleIndex: len(b.rules),
|
||||
Domains: values,
|
||||
})
|
||||
b.rules = append(b.rules, bpfMatchSet{
|
||||
b.rules = append(b.rules, _bpfMatchSet{
|
||||
Type: uint8(consts.MatchType_DomainSet),
|
||||
Not: f.Not,
|
||||
Outbound: b.OutboundToId(outbound),
|
||||
@ -94,12 +94,14 @@ func (b *RoutingMatcherBuilder) AddSourceMac(f *config_parser.Function, macAddrs
|
||||
}
|
||||
lpmTrieIndex := len(b.SimulatedLpmTries)
|
||||
b.SimulatedLpmTries = append(b.SimulatedLpmTries, values)
|
||||
b.rules = append(b.rules, bpfMatchSet{
|
||||
set := _bpfMatchSet{
|
||||
Value: [16]byte{},
|
||||
Type: uint8(consts.MatchType_Mac),
|
||||
Value: uint32(lpmTrieIndex),
|
||||
Not: f.Not,
|
||||
Outbound: b.OutboundToId(outbound),
|
||||
})
|
||||
}
|
||||
binary.LittleEndian.PutUint32(set.Value[:], uint32(lpmTrieIndex))
|
||||
b.rules = append(b.rules, set)
|
||||
|
||||
}
|
||||
|
||||
@ -109,12 +111,14 @@ func (b *RoutingMatcherBuilder) AddIp(f *config_parser.Function, values []netip.
|
||||
}
|
||||
lpmTrieIndex := len(b.SimulatedLpmTries)
|
||||
b.SimulatedLpmTries = append(b.SimulatedLpmTries, values)
|
||||
b.rules = append(b.rules, bpfMatchSet{
|
||||
set := _bpfMatchSet{
|
||||
Value: [16]byte{},
|
||||
Type: uint8(consts.MatchType_IpSet),
|
||||
Value: uint32(lpmTrieIndex),
|
||||
Not: f.Not,
|
||||
Outbound: b.OutboundToId(outbound),
|
||||
})
|
||||
}
|
||||
binary.LittleEndian.PutUint32(set.Value[:], uint32(lpmTrieIndex))
|
||||
b.rules = append(b.rules, set)
|
||||
}
|
||||
|
||||
func (b *RoutingMatcherBuilder) AddPort(f *config_parser.Function, values [][2]uint16, _outbound string) {
|
||||
@ -123,7 +127,7 @@ func (b *RoutingMatcherBuilder) AddPort(f *config_parser.Function, values [][2]u
|
||||
if i == len(values)-1 {
|
||||
outbound = _outbound
|
||||
}
|
||||
b.rules = append(b.rules, bpfMatchSet{
|
||||
b.rules = append(b.rules, _bpfMatchSet{
|
||||
Type: uint8(consts.MatchType_Port),
|
||||
Value: _bpfPortRange{
|
||||
PortStart: value[0],
|
||||
@ -141,12 +145,14 @@ func (b *RoutingMatcherBuilder) AddSourceIp(f *config_parser.Function, values []
|
||||
}
|
||||
lpmTrieIndex := len(b.SimulatedLpmTries)
|
||||
b.SimulatedLpmTries = append(b.SimulatedLpmTries, values)
|
||||
b.rules = append(b.rules, bpfMatchSet{
|
||||
set := _bpfMatchSet{
|
||||
Value: [16]byte{},
|
||||
Type: uint8(consts.MatchType_SourceIpSet),
|
||||
Value: uint32(lpmTrieIndex),
|
||||
Not: f.Not,
|
||||
Outbound: b.OutboundToId(outbound),
|
||||
})
|
||||
}
|
||||
binary.LittleEndian.PutUint32(set.Value[:], uint32(lpmTrieIndex))
|
||||
b.rules = append(b.rules, set)
|
||||
}
|
||||
|
||||
func (b *RoutingMatcherBuilder) AddSourcePort(f *config_parser.Function, values [][2]uint16, _outbound string) {
|
||||
@ -155,7 +161,7 @@ func (b *RoutingMatcherBuilder) AddSourcePort(f *config_parser.Function, values
|
||||
if i == len(values)-1 {
|
||||
outbound = _outbound
|
||||
}
|
||||
b.rules = append(b.rules, bpfMatchSet{
|
||||
b.rules = append(b.rules, _bpfMatchSet{
|
||||
Type: uint8(consts.MatchType_SourcePort),
|
||||
Value: _bpfPortRange{
|
||||
PortStart: value[0],
|
||||
@ -171,9 +177,9 @@ func (b *RoutingMatcherBuilder) AddL4Proto(f *config_parser.Function, values con
|
||||
if b.err != nil {
|
||||
return
|
||||
}
|
||||
b.rules = append(b.rules, bpfMatchSet{
|
||||
b.rules = append(b.rules, _bpfMatchSet{
|
||||
Value: [16]byte{byte(values)},
|
||||
Type: uint8(consts.MatchType_L4Proto),
|
||||
Value: uint32(values),
|
||||
Not: f.Not,
|
||||
Outbound: b.OutboundToId(outbound),
|
||||
})
|
||||
@ -183,9 +189,9 @@ func (b *RoutingMatcherBuilder) AddIpVersion(f *config_parser.Function, values c
|
||||
if b.err != nil {
|
||||
return
|
||||
}
|
||||
b.rules = append(b.rules, bpfMatchSet{
|
||||
b.rules = append(b.rules, _bpfMatchSet{
|
||||
Value: [16]byte{byte(values)},
|
||||
Type: uint8(consts.MatchType_IpVersion),
|
||||
Value: uint32(values),
|
||||
Not: f.Not,
|
||||
Outbound: b.OutboundToId(outbound),
|
||||
})
|
||||
@ -197,12 +203,12 @@ func (b *RoutingMatcherBuilder) AddProcessName(f *config_parser.Function, values
|
||||
if i == len(values)-1 {
|
||||
outbound = _outbound
|
||||
}
|
||||
matchSet := bpfMatchSet{
|
||||
matchSet := _bpfMatchSet{
|
||||
Type: uint8(consts.MatchType_ProcessName),
|
||||
Not: f.Not,
|
||||
Outbound: b.OutboundToId(outbound),
|
||||
}
|
||||
copy((*(*[16]byte)(unsafe.Pointer(&matchSet.Value)))[:], value[:])
|
||||
copy(matchSet.Value[:], value[:])
|
||||
b.rules = append(b.rules, matchSet)
|
||||
}
|
||||
}
|
||||
@ -212,7 +218,7 @@ func (b *RoutingMatcherBuilder) AddFinal(outbound string) {
|
||||
return
|
||||
}
|
||||
b.Final = outbound
|
||||
b.rules = append(b.rules, bpfMatchSet{
|
||||
b.rules = append(b.rules, _bpfMatchSet{
|
||||
Type: uint8(consts.MatchType_Final),
|
||||
Outbound: b.OutboundToId(outbound),
|
||||
})
|
||||
|
@ -106,7 +106,7 @@ func init() {
|
||||
func SoMarkControl(c syscall.RawConn) error {
|
||||
return c.Control(func(fd uintptr) {
|
||||
//TODO: force to set 0xff. any chances to customize this value?
|
||||
err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, fwmarkIoctl, 0x80)
|
||||
err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, fwmarkIoctl, 0x100)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
Reference in New Issue
Block a user