Move tun to subpackage

This commit is contained in:
Jason A. Donenfeld 2018-05-23 02:10:54 +02:00
parent 65a74f3175
commit 0a63188afa
9 changed files with 127 additions and 131 deletions

View file

@ -8,6 +8,7 @@ package main
import ( import (
"./ratelimiter" "./ratelimiter"
"./tun"
"runtime" "runtime"
"sync" "sync"
"sync/atomic" "sync/atomic"
@ -80,7 +81,7 @@ type Device struct {
} }
tun struct { tun struct {
device TUNDevice device tun.TUNDevice
mtu int32 mtu int32
} }
} }
@ -250,7 +251,7 @@ func (device *Device) PutMessageBuffer(msg *[MaxMessageSize]byte) {
device.pool.messageBuffers.Put(msg) device.pool.messageBuffers.Put(msg)
} }
func NewDevice(tun TUNDevice, logger *Logger) *Device { func NewDevice(tunDevice tun.TUNDevice, logger *Logger) *Device {
device := new(Device) device := new(Device)
device.isUp.Set(false) device.isUp.Set(false)
@ -258,7 +259,7 @@ func NewDevice(tun TUNDevice, logger *Logger) *Device {
device.log = logger device.log = logger
device.tun.device = tun device.tun.device = tunDevice
mtu, err := device.tun.device.MTU() mtu, err := device.tun.device.MTU()
if err != nil { if err != nil {
logger.Error.Println("Trouble determining MTU, assuming default:", err) logger.Error.Println("Trouble determining MTU, assuming default:", err)

View file

@ -7,6 +7,7 @@
package main package main
import ( import (
"./tun"
"fmt" "fmt"
"os" "os"
"os/signal" "os/signal"
@ -125,10 +126,10 @@ func main() {
// open TUN device (or use supplied fd) // open TUN device (or use supplied fd)
tun, err := func() (TUNDevice, error) { tun, err := func() (tun.TUNDevice, error) {
tunFdStr := os.Getenv(ENV_WG_TUN_FD) tunFdStr := os.Getenv(ENV_WG_TUN_FD)
if tunFdStr == "" { if tunFdStr == "" {
return CreateTUN(interfaceName) return tun.CreateTUN(interfaceName, DefaultMTU)
} }
// construct tun device from supplied fd // construct tun device from supplied fd
@ -139,7 +140,7 @@ func main() {
} }
file := os.NewFile(uintptr(fd), "") file := os.NewFile(uintptr(fd), "")
return CreateTUNFromFile(file) return tun.CreateTUNFromFile(file, DefaultMTU)
}() }()
if err == nil { if err == nil {

View file

@ -41,13 +41,6 @@ func (a *AtomicBool) Set(val bool) {
atomic.StoreInt32(&a.flag, flag) atomic.StoreInt32(&a.flag, flag)
} }
/* Integer manipulation */
func toInt32(n uint32) int32 {
mask := uint32(1 << 31)
return int32(-(n & mask) + (n & ^mask))
}
func min(a, b uint) uint { func min(a, b uint) uint {
if a > b { if a > b {
return b return b

26
tun.go
View file

@ -7,30 +7,12 @@
package main package main
import ( import (
"os" "./tun"
"sync/atomic" "sync/atomic"
) )
const DefaultMTU = 1420 const DefaultMTU = 1420
type TUNEvent int
const (
TUNEventUp = 1 << iota
TUNEventDown
TUNEventMTUUpdate
)
type TUNDevice interface {
File() *os.File // returns the file descriptor of the device
Read([]byte, int) (int, error) // read a packet from the device (without any additional headers)
Write([]byte, int) (int, error) // writes a packet to the device (without any additional headers)
MTU() (int, error) // returns the MTU of the device
Name() (string, error) // fetches and returns the current name
Events() chan TUNEvent // returns a constant channel of events related to the device
Close() error // stops the device and closes the event channel
}
func (device *Device) RoutineTUNEventReader() { func (device *Device) RoutineTUNEventReader() {
setUp := false setUp := false
logDebug := device.log.Debug logDebug := device.log.Debug
@ -41,7 +23,7 @@ func (device *Device) RoutineTUNEventReader() {
device.state.starting.Done() device.state.starting.Done()
for event := range device.tun.device.Events() { for event := range device.tun.device.Events() {
if event&TUNEventMTUUpdate != 0 { if event&tun.TUNEventMTUUpdate != 0 {
mtu, err := device.tun.device.MTU() mtu, err := device.tun.device.MTU()
old := atomic.LoadInt32(&device.tun.mtu) old := atomic.LoadInt32(&device.tun.mtu)
if err != nil { if err != nil {
@ -56,13 +38,13 @@ func (device *Device) RoutineTUNEventReader() {
} }
} }
if event&TUNEventUp != 0 && !setUp { if event&tun.TUNEventUp != 0 && !setUp {
logInfo.Println("Interface set up") logInfo.Println("Interface set up")
setUp = true setUp = true
device.Up() device.Up()
} }
if event&TUNEventDown != 0 && setUp { if event&tun.TUNEventDown != 0 && setUp {
logInfo.Println("Interface set down") logInfo.Println("Interface set down")
setUp = false setUp = false
device.Down() device.Down()

27
tun/tun.go Normal file
View file

@ -0,0 +1,27 @@
/* SPDX-License-Identifier: GPL-2.0
*
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
*/
package tun
import "os"
type TUNEvent int
const (
TUNEventUp = 1 << iota
TUNEventDown
TUNEventMTUUpdate
)
type TUNDevice interface {
File() *os.File // returns the file descriptor of the device
Read([]byte, int) (int, error) // read a packet from the device (without any additional headers)
Write([]byte, int) (int, error) // writes a packet to the device (without any additional headers)
MTU() (int, error) // returns the MTU of the device
Name() (string, error) // fetches and returns the current name
Events() chan TUNEvent // returns a constant channel of events related to the device
Close() error // stops the device and closes the event channel
}

View file

@ -4,11 +4,10 @@
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>. * Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
*/ */
package main package tun
import ( import (
"./rwcancel" "../rwcancel"
"encoding/binary"
"errors" "errors"
"fmt" "fmt"
"golang.org/x/net/ipv6" "golang.org/x/net/ipv6"
@ -34,7 +33,7 @@ type sockaddrCtl struct {
scReserved [5]uint32 scReserved [5]uint32
} }
type NativeTun struct { type nativeTun struct {
name string name string
fd *os.File fd *os.File
rwcancel *rwcancel.RWCancel rwcancel *rwcancel.RWCancel
@ -45,7 +44,7 @@ type NativeTun struct {
var sockaddrCtlSize uintptr = 32 var sockaddrCtlSize uintptr = 32
func (tun *NativeTun) RoutineRouteListener(tunIfindex int) { func (tun *nativeTun) routineRouteListener(tunIfindex int) {
var ( var (
statusUp bool statusUp bool
statusMTU int statusMTU int
@ -97,7 +96,7 @@ func (tun *NativeTun) RoutineRouteListener(tunIfindex int) {
} }
} }
func CreateTUN(name string) (TUNDevice, error) { func CreateTUN(name string, mtu int) (TUNDevice, error) {
ifIndex := -1 ifIndex := -1
if name != "utun" { if name != "utun" {
_, err := fmt.Sscanf(name, "utun%d", &ifIndex) _, err := fmt.Sscanf(name, "utun%d", &ifIndex)
@ -151,21 +150,21 @@ func CreateTUN(name string) (TUNDevice, error) {
return nil, fmt.Errorf("SYS_CONNECT: %v", errno) return nil, fmt.Errorf("SYS_CONNECT: %v", errno)
} }
tun, err := CreateTUNFromFile(os.NewFile(uintptr(fd), "")) tun, err := CreateTUNFromFile(os.NewFile(uintptr(fd), ""), mtu)
if err == nil && name == "utun" { if err == nil && name == "utun" {
fname := os.Getenv("WG_TUN_NAME_FILE") fname := os.Getenv("WG_TUN_NAME_FILE")
if fname != "" { if fname != "" {
ioutil.WriteFile(fname, []byte(tun.(*NativeTun).name+"\n"), 0400) ioutil.WriteFile(fname, []byte(tun.(*nativeTun).name+"\n"), 0400)
} }
} }
return tun, err return tun, err
} }
func CreateTUNFromFile(file *os.File) (TUNDevice, error) { func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
tun := &NativeTun{ tun := &nativeTun{
fd: file, fd: file,
events: make(chan TUNEvent, 10), events: make(chan TUNEvent, 10),
errors: make(chan error, 1), errors: make(chan error, 1),
@ -201,10 +200,9 @@ func CreateTUNFromFile(file *os.File) (TUNDevice, error) {
return nil, err return nil, err
} }
go tun.RoutineRouteListener(tunIfindex) go tun.routineRouteListener(tunIfindex)
// set default MTU err = tun.setMTU(mtu)
err = tun.setMTU(DefaultMTU)
if err != nil { if err != nil {
tun.Close() tun.Close()
return nil, err return nil, err
@ -213,7 +211,7 @@ func CreateTUNFromFile(file *os.File) (TUNDevice, error) {
return tun, nil return tun, nil
} }
func (tun *NativeTun) Name() (string, error) { func (tun *nativeTun) Name() (string, error) {
var ifName struct { var ifName struct {
name [16]byte name [16]byte
@ -236,15 +234,15 @@ func (tun *NativeTun) Name() (string, error) {
return tun.name, nil return tun.name, nil
} }
func (tun *NativeTun) File() *os.File { func (tun *nativeTun) File() *os.File {
return tun.fd return tun.fd
} }
func (tun *NativeTun) Events() chan TUNEvent { func (tun *nativeTun) Events() chan TUNEvent {
return tun.events return tun.events
} }
func (tun *NativeTun) doRead(buff []byte, offset int) (int, error) { func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) {
select { select {
case err := <-tun.errors: case err := <-tun.errors:
return 0, err return 0, err
@ -258,7 +256,7 @@ func (tun *NativeTun) doRead(buff []byte, offset int) (int, error) {
} }
} }
func (tun *NativeTun) Read(buff []byte, offset int) (int, error) { func (tun *nativeTun) Read(buff []byte, offset int) (int, error) {
for { for {
n, err := tun.doRead(buff, offset) n, err := tun.doRead(buff, offset)
if err == nil || !rwcancel.ErrorIsEAGAIN(err) { if err == nil || !rwcancel.ErrorIsEAGAIN(err) {
@ -270,7 +268,7 @@ func (tun *NativeTun) Read(buff []byte, offset int) (int, error) {
} }
} }
func (tun *NativeTun) Write(buff []byte, offset int) (int, error) { func (tun *nativeTun) Write(buff []byte, offset int) (int, error) {
// reserve space for header // reserve space for header
@ -293,7 +291,7 @@ func (tun *NativeTun) Write(buff []byte, offset int) (int, error) {
return tun.fd.Write(buff) return tun.fd.Write(buff)
} }
func (tun *NativeTun) Close() error { func (tun *nativeTun) Close() error {
var err3 error var err3 error
err1 := tun.rwcancel.Cancel() err1 := tun.rwcancel.Cancel()
err2 := tun.fd.Close() err2 := tun.fd.Close()
@ -313,7 +311,7 @@ func (tun *NativeTun) Close() error {
return err3 return err3
} }
func (tun *NativeTun) setMTU(n int) error { func (tun *nativeTun) setMTU(n int) error {
// open datagram socket // open datagram socket
@ -335,7 +333,7 @@ func (tun *NativeTun) setMTU(n int) error {
var ifr [32]byte var ifr [32]byte
copy(ifr[:], tun.name) copy(ifr[:], tun.name)
binary.LittleEndian.PutUint32(ifr[16:20], uint32(n)) *(*uint32)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = uint32(n)
_, _, errno := unix.Syscall( _, _, errno := unix.Syscall(
unix.SYS_IOCTL, unix.SYS_IOCTL,
uintptr(fd), uintptr(fd),
@ -350,7 +348,7 @@ func (tun *NativeTun) setMTU(n int) error {
return nil return nil
} }
func (tun *NativeTun) MTU() (int, error) { func (tun *nativeTun) MTU() (int, error) {
// open datagram socket // open datagram socket

View file

@ -3,10 +3,10 @@
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. * Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
*/ */
package main package tun
import ( import (
"./rwcancel" "../rwcancel"
"bytes" "bytes"
"errors" "errors"
"fmt" "fmt"
@ -48,7 +48,7 @@ type ifstat struct {
Ascii [_IFSTATMAX]byte Ascii [_IFSTATMAX]byte
} }
type NativeTun struct { type nativeTun struct {
name string name string
fd *os.File fd *os.File
rwcancel *rwcancel.RWCancel rwcancel *rwcancel.RWCancel
@ -57,7 +57,7 @@ type NativeTun struct {
routeSocket int routeSocket int
} }
func (tun *NativeTun) RoutineRouteListener(tunIfindex int) { func (tun *nativeTun) routineRouteListener(tunIfindex int) {
var ( var (
statusUp bool statusUp bool
statusMTU int statusMTU int
@ -221,7 +221,7 @@ func tunDestroy(name string) error {
return nil return nil
} }
func CreateTUN(name string) (TUNDevice, error) { func CreateTUN(name string, mtu int) (TUNDevice, error) {
if len(name) > unix.IFNAMSIZ-1 { if len(name) > unix.IFNAMSIZ-1 {
return nil, errors.New("interface name too long") return nil, errors.New("interface name too long")
} }
@ -306,12 +306,12 @@ func CreateTUN(name string) (TUNDevice, error) {
return nil, fmt.Errorf("failed to rename %s to %s: %s", assignedName, name, errno.Error()) return nil, fmt.Errorf("failed to rename %s to %s: %s", assignedName, name, errno.Error())
} }
return CreateTUNFromFile(tunfile) return CreateTUNFromFile(tunfile, mtu)
} }
func CreateTUNFromFile(file *os.File) (TUNDevice, error) { func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
tun := &NativeTun{ tun := &nativeTun{
fd: file, fd: file,
events: make(chan TUNEvent, 10), events: make(chan TUNEvent, 10),
errors: make(chan error, 1), errors: make(chan error, 1),
@ -347,10 +347,9 @@ func CreateTUNFromFile(file *os.File) (TUNDevice, error) {
return nil, err return nil, err
} }
go tun.RoutineRouteListener(tunIfindex) go tun.routineRouteListener(tunIfindex)
// set default MTU err = tun.setMTU(mtu)
err = tun.setMTU(DefaultMTU)
if err != nil { if err != nil {
tun.Close() tun.Close()
return nil, err return nil, err
@ -359,7 +358,7 @@ func CreateTUNFromFile(file *os.File) (TUNDevice, error) {
return tun, nil return tun, nil
} }
func (tun *NativeTun) Name() (string, error) { func (tun *nativeTun) Name() (string, error) {
name, err := tunName(tun.fd.Fd()) name, err := tunName(tun.fd.Fd())
if err != nil { if err != nil {
return "", err return "", err
@ -368,15 +367,15 @@ func (tun *NativeTun) Name() (string, error) {
return name, nil return name, nil
} }
func (tun *NativeTun) File() *os.File { func (tun *nativeTun) File() *os.File {
return tun.fd return tun.fd
} }
func (tun *NativeTun) Events() chan TUNEvent { func (tun *nativeTun) Events() chan TUNEvent {
return tun.events return tun.events
} }
func (tun *NativeTun) doRead(buff []byte, offset int) (int, error) { func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) {
select { select {
case err := <-tun.errors: case err := <-tun.errors:
return 0, err return 0, err
@ -390,7 +389,7 @@ func (tun *NativeTun) doRead(buff []byte, offset int) (int, error) {
} }
} }
func (tun *NativeTun) Read(buff []byte, offset int) (int, error) { func (tun *nativeTun) Read(buff []byte, offset int) (int, error) {
for { for {
n, err := tun.doRead(buff, offset) n, err := tun.doRead(buff, offset)
if err == nil || !rwcancel.ErrorIsEAGAIN(err) { if err == nil || !rwcancel.ErrorIsEAGAIN(err) {
@ -402,7 +401,7 @@ func (tun *NativeTun) Read(buff []byte, offset int) (int, error) {
} }
} }
func (tun *NativeTun) Write(buff []byte, offset int) (int, error) { func (tun *nativeTun) Write(buff []byte, offset int) (int, error) {
// reserve space for header // reserve space for header
@ -425,7 +424,7 @@ func (tun *NativeTun) Write(buff []byte, offset int) (int, error) {
return tun.fd.Write(buff) return tun.fd.Write(buff)
} }
func (tun *NativeTun) Close() error { func (tun *nativeTun) Close() error {
var err4 error var err4 error
err1 := tun.rwcancel.Cancel() err1 := tun.rwcancel.Cancel()
err2 := tun.fd.Close() err2 := tun.fd.Close()
@ -449,7 +448,7 @@ func (tun *NativeTun) Close() error {
return err4 return err4
} }
func (tun *NativeTun) setMTU(n int) error { func (tun *nativeTun) setMTU(n int) error {
// open datagram socket // open datagram socket
var fd int var fd int
@ -486,7 +485,7 @@ func (tun *NativeTun) setMTU(n int) error {
return nil return nil
} }
func (tun *NativeTun) MTU() (int, error) { func (tun *nativeTun) MTU() (int, error) {
// open datagram socket // open datagram socket
fd, err := unix.Socket( fd, err := unix.Socket(

View file

@ -6,15 +6,14 @@
/* Copyright 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. */ /* Copyright 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. */
package main package tun
/* Implementation of the TUN device interface for linux /* Implementation of the TUN device interface for linux
*/ */
import ( import (
"./rwcancel" "../rwcancel"
"bytes" "bytes"
"encoding/binary"
"errors" "errors"
"fmt" "fmt"
"golang.org/x/net/ipv6" "golang.org/x/net/ipv6"
@ -32,7 +31,7 @@ const (
ifReqSize = unix.IFNAMSIZ + 64 ifReqSize = unix.IFNAMSIZ + 64
) )
type NativeTun struct { type nativeTun struct {
fd *os.File fd *os.File
fdCancel *rwcancel.RWCancel fdCancel *rwcancel.RWCancel
index int32 // if index index int32 // if index
@ -46,11 +45,11 @@ type NativeTun struct {
statusListenersShutdown chan struct{} statusListenersShutdown chan struct{}
} }
func (tun *NativeTun) File() *os.File { func (tun *nativeTun) File() *os.File {
return tun.fd return tun.fd
} }
func (tun *NativeTun) RoutineHackListener() { func (tun *nativeTun) routineHackListener() {
defer tun.hackListenerClosed.Unlock() defer tun.hackListenerClosed.Unlock()
/* This is needed for the detection to work across network namespaces /* This is needed for the detection to work across network namespaces
* If you are reading this and know a better method, please get in touch. * If you are reading this and know a better method, please get in touch.
@ -90,7 +89,7 @@ func createNetlinkSocket() (int, error) {
return sock, nil return sock, nil
} }
func (tun *NativeTun) RoutineNetlinkListener() { func (tun *nativeTun) routineNetlinkListener() {
defer func() { defer func() {
unix.Close(tun.netlinkSock) unix.Close(tun.netlinkSock)
tun.hackListenerClosed.Lock() tun.hackListenerClosed.Lock()
@ -160,7 +159,7 @@ func (tun *NativeTun) RoutineNetlinkListener() {
} }
} }
func (tun *NativeTun) isUp() (bool, error) { func (tun *nativeTun) isUp() (bool, error) {
inter, err := net.InterfaceByName(tun.name) inter, err := net.InterfaceByName(tun.name)
return inter.Flags&net.FlagUp != 0, err return inter.Flags&net.FlagUp != 0, err
} }
@ -194,11 +193,10 @@ func getIFIndex(name string) (int32, error) {
return 0, errno return 0, errno
} }
index := binary.LittleEndian.Uint32(ifr[unix.IFNAMSIZ:]) return *(*int32)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])), nil
return toInt32(index), nil
} }
func (tun *NativeTun) setMTU(n int) error { func (tun *nativeTun) setMTU(n int) error {
// open datagram socket // open datagram socket
@ -218,7 +216,7 @@ func (tun *NativeTun) setMTU(n int) error {
var ifr [ifReqSize]byte var ifr [ifReqSize]byte
copy(ifr[:], tun.name) copy(ifr[:], tun.name)
binary.LittleEndian.PutUint32(ifr[16:20], uint32(n)) *(*uint32)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = uint32(n)
_, _, errno := unix.Syscall( _, _, errno := unix.Syscall(
unix.SYS_IOCTL, unix.SYS_IOCTL,
uintptr(fd), uintptr(fd),
@ -233,7 +231,7 @@ func (tun *NativeTun) setMTU(n int) error {
return nil return nil
} }
func (tun *NativeTun) MTU() (int, error) { func (tun *nativeTun) MTU() (int, error) {
// open datagram socket // open datagram socket
@ -263,10 +261,10 @@ func (tun *NativeTun) MTU() (int, error) {
return 0, errors.New("failed to get MTU of TUN device: " + strconv.FormatInt(int64(errno), 10)) return 0, errors.New("failed to get MTU of TUN device: " + strconv.FormatInt(int64(errno), 10))
} }
return int(*(*int32)(unsafe.Pointer(&ifr[16]))), nil return int(*(*int32)(unsafe.Pointer(&ifr[unix.IFNAMSIZ]))), nil
} }
func (tun *NativeTun) Name() (string, error) { func (tun *nativeTun) Name() (string, error) {
var ifr [ifReqSize]byte var ifr [ifReqSize]byte
_, _, errno := unix.Syscall( _, _, errno := unix.Syscall(
@ -287,7 +285,7 @@ func (tun *NativeTun) Name() (string, error) {
return tun.name, nil return tun.name, nil
} }
func (tun *NativeTun) Write(buff []byte, offset int) (int, error) { func (tun *nativeTun) Write(buff []byte, offset int) (int, error) {
if tun.nopi { if tun.nopi {
buff = buff[offset:] buff = buff[offset:]
@ -315,7 +313,7 @@ func (tun *NativeTun) Write(buff []byte, offset int) (int, error) {
return tun.fd.Write(buff) return tun.fd.Write(buff)
} }
func (tun *NativeTun) doRead(buff []byte, offset int) (int, error) { func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) {
select { select {
case err := <-tun.errors: case err := <-tun.errors:
return 0, err return 0, err
@ -333,7 +331,7 @@ func (tun *NativeTun) doRead(buff []byte, offset int) (int, error) {
} }
} }
func (tun *NativeTun) Read(buff []byte, offset int) (int, error) { func (tun *nativeTun) Read(buff []byte, offset int) (int, error) {
for { for {
n, err := tun.doRead(buff, offset) n, err := tun.doRead(buff, offset)
if err == nil || !rwcancel.ErrorIsEAGAIN(err) { if err == nil || !rwcancel.ErrorIsEAGAIN(err) {
@ -345,11 +343,11 @@ func (tun *NativeTun) Read(buff []byte, offset int) (int, error) {
} }
} }
func (tun *NativeTun) Events() chan TUNEvent { func (tun *nativeTun) Events() chan TUNEvent {
return tun.events return tun.events
} }
func (tun *NativeTun) Close() error { func (tun *nativeTun) Close() error {
var err1 error var err1 error
if tun.statusListenersShutdown != nil { if tun.statusListenersShutdown != nil {
close(tun.statusListenersShutdown) close(tun.statusListenersShutdown)
@ -371,7 +369,7 @@ func (tun *NativeTun) Close() error {
return err3 return err3
} }
func CreateTUN(name string) (TUNDevice, error) { func CreateTUN(name string, mtu int) (TUNDevice, error) {
// open clone device // open clone device
@ -401,7 +399,7 @@ func CreateTUN(name string) (TUNDevice, error) {
return nil, errors.New("interface name too long") return nil, errors.New("interface name too long")
} }
copy(ifr[:], nameBytes) copy(ifr[:], nameBytes)
binary.LittleEndian.PutUint16(ifr[16:], flags) *(*uint16)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = flags
_, _, errno := unix.Syscall( _, _, errno := unix.Syscall(
unix.SYS_IOCTL, unix.SYS_IOCTL,
@ -413,12 +411,12 @@ func CreateTUN(name string) (TUNDevice, error) {
return nil, errno return nil, errno
} }
return CreateTUNFromFile(fd) return CreateTUNFromFile(fd, mtu)
} }
func CreateTUNFromFile(fd *os.File) (TUNDevice, error) { func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
tun := &NativeTun{ tun := &nativeTun{
fd: fd, fd: file,
events: make(chan TUNEvent, 5), events: make(chan TUNEvent, 5),
errors: make(chan error, 5), errors: make(chan error, 5),
statusListenersShutdown: make(chan struct{}), statusListenersShutdown: make(chan struct{}),
@ -426,7 +424,7 @@ func CreateTUNFromFile(fd *os.File) (TUNDevice, error) {
} }
var err error var err error
tun.fdCancel, err = rwcancel.NewRWCancel(int(fd.Fd())) tun.fdCancel, err = rwcancel.NewRWCancel(int(file.Fd()))
if err != nil { if err != nil {
tun.fd.Close() tun.fd.Close()
return nil, err return nil, err
@ -457,12 +455,10 @@ func CreateTUNFromFile(fd *os.File) (TUNDevice, error) {
} }
tun.hackListenerClosed.Lock() tun.hackListenerClosed.Lock()
go tun.RoutineNetlinkListener() go tun.routineNetlinkListener()
go tun.RoutineHackListener() // cross namespace go tun.routineHackListener() // cross namespace
// set default MTU err = tun.setMTU(mtu)
err = tun.setMTU(DefaultMTU)
if err != nil { if err != nil {
tun.Close() tun.Close()
return nil, err return nil, err

View file

@ -3,10 +3,10 @@
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. * Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
*/ */
package main package tun
import ( import (
"./rwcancel" "../rwcancel"
"errors" "errors"
"fmt" "fmt"
"golang.org/x/net/ipv6" "golang.org/x/net/ipv6"
@ -27,7 +27,7 @@ type ifreq_mtu struct {
const _TUNSIFMODE = 0x8004745d const _TUNSIFMODE = 0x8004745d
type NativeTun struct { type nativeTun struct {
name string name string
fd *os.File fd *os.File
rwcancel *rwcancel.RWCancel rwcancel *rwcancel.RWCancel
@ -36,7 +36,7 @@ type NativeTun struct {
routeSocket int routeSocket int
} }
func (tun *NativeTun) RoutineRouteListener(tunIfindex int) { func (tun *nativeTun) routineRouteListener(tunIfindex int) {
var ( var (
statusUp bool statusUp bool
statusMTU int statusMTU int
@ -100,7 +100,7 @@ func errorIsEBUSY(err error) bool {
return false return false
} }
func CreateTUN(name string) (TUNDevice, error) { func CreateTUN(name string, mtu int) (TUNDevice, error) {
ifIndex := -1 ifIndex := -1
if name != "tun" { if name != "tun" {
_, err := fmt.Sscanf(name, "tun%d", &ifIndex) _, err := fmt.Sscanf(name, "tun%d", &ifIndex)
@ -140,21 +140,21 @@ func CreateTUN(name string) (TUNDevice, error) {
return nil, fmt.Errorf("error %s", errno.Error()) return nil, fmt.Errorf("error %s", errno.Error())
} }
tun, err := CreateTUNFromFile(tunfile) tun, err := CreateTUNFromFile(tunfile, mtu)
if err == nil && name == "tun" { if err == nil && name == "tun" {
fname := os.Getenv("WG_TUN_NAME_FILE") fname := os.Getenv("WG_TUN_NAME_FILE")
if fname != "" { if fname != "" {
ioutil.WriteFile(fname, []byte(tun.(*NativeTun).name+"\n"), 0400) ioutil.WriteFile(fname, []byte(tun.(*nativeTun).name+"\n"), 0400)
} }
} }
return tun, err return tun, err
} }
func CreateTUNFromFile(file *os.File) (TUNDevice, error) { func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
tun := &NativeTun{ tun := &nativeTun{
fd: file, fd: file,
events: make(chan TUNEvent, 10), events: make(chan TUNEvent, 10),
errors: make(chan error, 1), errors: make(chan error, 1),
@ -190,10 +190,9 @@ func CreateTUNFromFile(file *os.File) (TUNDevice, error) {
return nil, err return nil, err
} }
go tun.RoutineRouteListener(tunIfindex) go tun.routineRouteListener(tunIfindex)
// set default MTU err = tun.setMTU(mtu)
err = tun.setMTU(DefaultMTU)
if err != nil { if err != nil {
tun.Close() tun.Close()
return nil, err return nil, err
@ -202,7 +201,7 @@ func CreateTUNFromFile(file *os.File) (TUNDevice, error) {
return tun, nil return tun, nil
} }
func (tun *NativeTun) Name() (string, error) { func (tun *nativeTun) Name() (string, error) {
gostat, err := tun.fd.Stat() gostat, err := tun.fd.Stat()
if err != nil { if err != nil {
tun.name = "" tun.name = ""
@ -213,15 +212,15 @@ func (tun *NativeTun) Name() (string, error) {
return tun.name, nil return tun.name, nil
} }
func (tun *NativeTun) File() *os.File { func (tun *nativeTun) File() *os.File {
return tun.fd return tun.fd
} }
func (tun *NativeTun) Events() chan TUNEvent { func (tun *nativeTun) Events() chan TUNEvent {
return tun.events return tun.events
} }
func (tun *NativeTun) doRead(buff []byte, offset int) (int, error) { func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) {
select { select {
case err := <-tun.errors: case err := <-tun.errors:
return 0, err return 0, err
@ -235,7 +234,7 @@ func (tun *NativeTun) doRead(buff []byte, offset int) (int, error) {
} }
} }
func (tun *NativeTun) Read(buff []byte, offset int) (int, error) { func (tun *nativeTun) Read(buff []byte, offset int) (int, error) {
for { for {
n, err := tun.doRead(buff, offset) n, err := tun.doRead(buff, offset)
if err == nil || !rwcancel.ErrorIsEAGAIN(err) { if err == nil || !rwcancel.ErrorIsEAGAIN(err) {
@ -247,7 +246,7 @@ func (tun *NativeTun) Read(buff []byte, offset int) (int, error) {
} }
} }
func (tun *NativeTun) Write(buff []byte, offset int) (int, error) { func (tun *nativeTun) Write(buff []byte, offset int) (int, error) {
// reserve space for header // reserve space for header
@ -270,7 +269,7 @@ func (tun *NativeTun) Write(buff []byte, offset int) (int, error) {
return tun.fd.Write(buff) return tun.fd.Write(buff)
} }
func (tun *NativeTun) Close() error { func (tun *nativeTun) Close() error {
var err3 error var err3 error
err1 := tun.rwcancel.Cancel() err1 := tun.rwcancel.Cancel()
err2 := tun.fd.Close() err2 := tun.fd.Close()
@ -290,7 +289,7 @@ func (tun *NativeTun) Close() error {
return err3 return err3
} }
func (tun *NativeTun) setMTU(n int) error { func (tun *nativeTun) setMTU(n int) error {
// open datagram socket // open datagram socket
var fd int var fd int
@ -327,7 +326,7 @@ func (tun *NativeTun) setMTU(n int) error {
return nil return nil
} }
func (tun *NativeTun) MTU() (int, error) { func (tun *nativeTun) MTU() (int, error) {
// open datagram socket // open datagram socket
fd, err := unix.Socket( fd, err := unix.Socket(