mirror of
https://github.com/SagerNet/sing-tun.git
synced 2025-03-31 10:27:39 +03:00
90 lines
2.1 KiB
Go
90 lines
2.1 KiB
Go
//go:build linux
|
|
|
|
package tun
|
|
|
|
import (
|
|
"os"
|
|
"syscall"
|
|
"unsafe"
|
|
|
|
E "github.com/sagernet/sing/common/exceptions"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
const (
|
|
// TODO: support TSO with ECN bits
|
|
tunTCPOffloads = unix.TUN_F_CSUM | unix.TUN_F_TSO4 | unix.TUN_F_TSO6
|
|
tunUDPOffloads = unix.TUN_F_USO4 | unix.TUN_F_USO6
|
|
)
|
|
|
|
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 {
|
|
err := unix.IoctlSetInt(fd, unix.TUNSETOFFLOAD, tunTCPOffloads)
|
|
if err != nil {
|
|
return E.Cause(os.NewSyscallError("TUNSETOFFLOAD", err), "enable offload")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func setUDPOffload(fd int) error {
|
|
return unix.IoctlSetInt(fd, unix.TUNSETOFFLOAD, tunTCPOffloads|tunUDPOffloads)
|
|
}
|
|
|
|
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
|
|
}
|