github.com/keysonzzz/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgSys/taptun_linux.go (about) 1 package kmgSys 2 3 import ( 4 "os" 5 "strings" 6 "syscall" 7 "unsafe" 8 ) 9 10 // Interface is a TUN/TAP interface. 11 type iInterface struct { 12 deviceType DeviceType 13 file *os.File 14 name string 15 } 16 17 // Create a new TAP interface whose name is ifName. 18 // If ifName is empty, a default name (tap0, tap1, ... ) will be assigned. 19 // ifName should not exceed 16 bytes. 20 func NewTap(ifName string) (ifce TunTapInterface, err error) { 21 file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0) 22 if err != nil { 23 return nil, err 24 } 25 name, err := createInterface(file.Fd(), ifName, cIFF_TAP|cIFF_NO_PI) 26 if err != nil { 27 file.Close() 28 return nil, err 29 } 30 ifce = &iInterface{deviceType: DeviceTypeTap, file: file, name: name} 31 return 32 } 33 34 // Create a new TUN interface whose name is ifName. 35 // If ifName is empty, a default name (tap0, tap1, ... ) will be assigned. 36 // ifName should not exceed 16 bytes. 37 func NewTun(ifName string) (ifce TunTapInterface, err error) { 38 file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0) 39 if err != nil { 40 return nil, err 41 } 42 name, err := createInterface(file.Fd(), ifName, cIFF_TUN|cIFF_NO_PI) 43 if err != nil { 44 file.Close() 45 return nil, err 46 } 47 ifce = &iInterface{deviceType: DeviceTypeTun, file: file, name: name} 48 return 49 } 50 51 func NewTunNoName() (ifce TunTapInterface, err error) { 52 return NewTun("") 53 } 54 55 func (ifce *iInterface) GetDeviceType() DeviceType { 56 return ifce.deviceType 57 } 58 59 // Returns the interface name of ifce, e.g. tun0, tap1, etc.. 60 func (ifce *iInterface) Name() string { 61 return ifce.name 62 } 63 64 // Implement io.Writer interface. 65 func (ifce *iInterface) Write(p []byte) (n int, err error) { 66 return ifce.file.Write(p) 67 } 68 69 // Implement io.Reader interface. 70 func (ifce *iInterface) Read(p []byte) (n int, err error) { 71 return ifce.file.Read(p) 72 } 73 func (ifce *iInterface) Close() (err error) { 74 return ifce.file.Close() 75 } 76 77 const ( 78 cIFF_TUN = 0x0001 79 cIFF_TAP = 0x0002 80 cIFF_NO_PI = 0x1000 81 ) 82 83 type ifReq struct { 84 Name [0x10]byte 85 Flags uint16 86 pad [0x28 - 0x10 - 2]byte 87 } 88 89 func createInterface(fd uintptr, ifName string, flags uint16) (createdIFName string, err error) { 90 var req ifReq 91 req.Flags = flags 92 copy(req.Name[:], ifName) 93 _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TUNSETIFF), uintptr(unsafe.Pointer(&req))) 94 if errno != 0 { 95 err = errno 96 return 97 } 98 createdIFName = strings.Trim(string(req.Name[:]), "\x00") 99 return 100 }