github.com/labulakalia/water@v0.0.5-0.20231118024244-f351ca6784b6/syscalls_linux.go (about) 1 package water 2 3 import ( 4 "os" 5 "strings" 6 "syscall" 7 "unsafe" 8 ) 9 10 const ( 11 cIFFTUN = 0x0001 12 cIFFTAP = 0x0002 13 cIFFNOPI = 0x1000 14 cIFFMULTIQUEUE = 0x0100 15 ) 16 17 type ifReq struct { 18 Name [0x10]byte 19 Flags uint16 20 pad [0x28 - 0x10 - 2]byte 21 } 22 23 func ioctl(fd uintptr, request uintptr, argp uintptr) error { 24 _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(request), argp) 25 if errno != 0 { 26 return os.NewSyscallError("ioctl", errno) 27 } 28 return nil 29 } 30 31 func setupFd(config Config, fd uintptr) (name string, err error) { 32 var flags uint16 = cIFFNOPI 33 if config.DeviceType == TUN { 34 flags |= cIFFTUN 35 } else { 36 flags |= cIFFTAP 37 } 38 if config.PlatformSpecificParams.MultiQueue { 39 flags |= cIFFMULTIQUEUE 40 } 41 42 if name, err = createInterface(fd, config.Name, flags); err != nil { 43 return "", err 44 } 45 46 if err = setDeviceOptions(fd, config); err != nil { 47 return "", err 48 } 49 50 return name, nil 51 } 52 53 func createInterface(fd uintptr, ifName string, flags uint16) (createdIFName string, err error) { 54 var req ifReq 55 req.Flags = flags 56 copy(req.Name[:], ifName) 57 58 err = ioctl(fd, syscall.TUNSETIFF, uintptr(unsafe.Pointer(&req))) 59 if err != nil { 60 return 61 } 62 63 createdIFName = strings.Trim(string(req.Name[:]), "\x00") 64 return 65 } 66 67 func setDeviceOptions(fd uintptr, config Config) (err error) { 68 if config.Permissions != nil { 69 if err = ioctl(fd, syscall.TUNSETOWNER, uintptr(config.Permissions.Owner)); err != nil { 70 return 71 } 72 if err = ioctl(fd, syscall.TUNSETGROUP, uintptr(config.Permissions.Group)); err != nil { 73 return 74 } 75 } 76 77 // set clear the persist flag 78 value := 0 79 if config.Persist { 80 value = 1 81 } 82 return ioctl(fd, syscall.TUNSETPERSIST, uintptr(value)) 83 }