github.com/flowerwrong/netstack@v0.0.0-20191009141956-e5848263af28/tcpip/link/tun/tun_unsafe.go (about)

     1  // Copyright 2018 The gVisor 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  
    15  // +build linux
    16  
    17  // Package tun contains methods to open TAP and TUN devices.
    18  package tun
    19  
    20  import (
    21  	"syscall"
    22  	"unsafe"
    23  )
    24  
    25  // Open opens the specified TUN device, sets it to non-blocking mode, and
    26  // returns its file descriptor.
    27  func Open(name string) (int, error) {
    28  	return open(name, syscall.IFF_TUN|syscall.IFF_NO_PI)
    29  }
    30  
    31  // OpenTAP opens the specified TAP device, sets it to non-blocking mode, and
    32  // returns its file descriptor.
    33  func OpenTAP(name string) (int, error) {
    34  	return open(name, syscall.IFF_TAP|syscall.IFF_NO_PI)
    35  }
    36  
    37  func open(name string, flags uint16) (int, error) {
    38  	fd, err := syscall.Open("/dev/net/tun", syscall.O_RDWR, 0)
    39  	if err != nil {
    40  		return -1, err
    41  	}
    42  
    43  	var ifr struct {
    44  		name  [16]byte
    45  		flags uint16
    46  		_     [22]byte
    47  	}
    48  
    49  	copy(ifr.name[:], name)
    50  	ifr.flags = flags
    51  	_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.TUNSETIFF, uintptr(unsafe.Pointer(&ifr)))
    52  	if errno != 0 {
    53  		syscall.Close(fd)
    54  		return -1, errno
    55  	}
    56  
    57  	if err = syscall.SetNonblock(fd, true); err != nil {
    58  		syscall.Close(fd)
    59  		return -1, err
    60  	}
    61  
    62  	return fd, nil
    63  }