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  }