tun.go 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. // Copyright 2015 flannel authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // +build !windows
  15. package ip
  16. import (
  17. "bytes"
  18. "fmt"
  19. "os"
  20. "syscall"
  21. "unsafe"
  22. )
  23. const (
  24. tunDevice = "/dev/net/tun"
  25. ifnameSize = 16
  26. )
  27. type ifreqFlags struct {
  28. IfrnName [ifnameSize]byte
  29. IfruFlags uint16
  30. }
  31. func ioctl(fd int, request, argp uintptr) error {
  32. _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), request, argp)
  33. if errno != 0 {
  34. return fmt.Errorf("ioctl failed with '%s'", errno)
  35. }
  36. return nil
  37. }
  38. func fromZeroTerm(s []byte) string {
  39. return string(bytes.TrimRight(s, "\000"))
  40. }
  41. func OpenTun(name string) (*os.File, string, error) {
  42. tun, err := os.OpenFile(tunDevice, os.O_RDWR, 0)
  43. if err != nil {
  44. return nil, "", err
  45. }
  46. var ifr ifreqFlags
  47. copy(ifr.IfrnName[:len(ifr.IfrnName)-1], []byte(name+"\000"))
  48. ifr.IfruFlags = syscall.IFF_TUN | syscall.IFF_NO_PI
  49. err = ioctl(int(tun.Fd()), syscall.TUNSETIFF, uintptr(unsafe.Pointer(&ifr)))
  50. if err != nil {
  51. return nil, "", err
  52. }
  53. ifname := fromZeroTerm(ifr.IfrnName[:ifnameSize])
  54. return tun, ifname, nil
  55. }