syscalls_linux.go 1.7 KB

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