//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 }