forked from SagerNet/sing-tun
-
Notifications
You must be signed in to change notification settings - Fork 22
/
tun_linux_flags.go
84 lines (73 loc) · 1.97 KB
/
tun_linux_flags.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//go:build linux
package tun
import (
"os"
"syscall"
"unsafe"
E "github.com/sagernet/sing/common/exceptions"
"golang.org/x/sys/unix"
)
func checkVNETHDREnabled(fd int, name string) (bool, error) {
ifr, err := unix.NewIfreq(name)
if err != nil {
return false, err
}
err = unix.IoctlIfreq(fd, unix.TUNGETIFF, ifr)
if err != nil {
return false, os.NewSyscallError("TUNGETIFF", err)
}
return ifr.Uint16()&unix.IFF_VNET_HDR != 0, nil
}
func setTCPOffload(fd int) error {
const (
// TODO: support TSO with ECN bits
tunOffloads = unix.TUN_F_CSUM | unix.TUN_F_TSO4 | unix.TUN_F_TSO6
)
err := unix.IoctlSetInt(fd, unix.TUNSETOFFLOAD, tunOffloads)
if err != nil {
return E.Cause(os.NewSyscallError("TUNSETOFFLOAD", err), "enable offload")
}
return nil
}
type ifreqData struct {
ifrName [unix.IFNAMSIZ]byte
ifrData uintptr
}
type ethtoolValue struct {
cmd uint32
data uint32
}
//go:linkname ioctlPtr golang.org/x/sys/unix.ioctlPtr
func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error)
func checkChecksumOffload(name string, cmd uint32) (bool, error) {
fd, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, unix.IPPROTO_IP)
if err != nil {
return false, err
}
defer syscall.Close(fd)
ifr := ifreqData{}
copy(ifr.ifrName[:], name)
data := ethtoolValue{cmd: cmd}
ifr.ifrData = uintptr(unsafe.Pointer(&data))
err = ioctlPtr(fd, unix.SIOCETHTOOL, unsafe.Pointer(&ifr))
if err != nil {
return false, os.NewSyscallError("SIOCETHTOOL ETHTOOL_GTXCSUM", err)
}
return data.data == 0, nil
}
func setChecksumOffload(name string, cmd uint32) error {
fd, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, unix.IPPROTO_IP)
if err != nil {
return err
}
defer syscall.Close(fd)
ifr := ifreqData{}
copy(ifr.ifrName[:], name)
data := ethtoolValue{cmd: cmd, data: 0}
ifr.ifrData = uintptr(unsafe.Pointer(&data))
err = ioctlPtr(fd, unix.SIOCETHTOOL, unsafe.Pointer(&ifr))
if err != nil {
return os.NewSyscallError("SIOCETHTOOL ETHTOOL_STXCSUM", err)
}
return nil
}