Removed IFF_NO_PI from TUN linux

This change was needed for the Linux TUN status hack
to work properly (not increment the error counter).

This commit also updates the TUN interface to allow for
the construction / removal of the TUN info headers in-place.
This commit is contained in:
Mathias Hall-Andersen 2017-12-04 21:39:06 +01:00
parent 9fef0ca2fb
commit 996c7c4d8a
4 changed files with 60 additions and 18 deletions

View File

@ -243,13 +243,24 @@ func (device *Device) RoutineDecryption() {
counter := elem.packet[MessageTransportOffsetCounter:MessageTransportOffsetContent] counter := elem.packet[MessageTransportOffsetCounter:MessageTransportOffsetContent]
content := elem.packet[MessageTransportOffsetContent:] content := elem.packet[MessageTransportOffsetContent:]
// expand nonce
nonce[0x4] = counter[0x0]
nonce[0x5] = counter[0x1]
nonce[0x6] = counter[0x2]
nonce[0x7] = counter[0x3]
nonce[0x8] = counter[0x4]
nonce[0x9] = counter[0x5]
nonce[0xa] = counter[0x6]
nonce[0xb] = counter[0x7]
// decrypt and release to consumer // decrypt and release to consumer
var err error var err error
copy(nonce[4:], counter)
elem.counter = binary.LittleEndian.Uint64(counter) elem.counter = binary.LittleEndian.Uint64(counter)
elem.packet, err = elem.keyPair.receive.Open( elem.packet, err = elem.keyPair.receive.Open(
elem.buffer[:0], content[:0],
nonce[:], nonce[:],
content, content,
nil, nil,
@ -495,6 +506,7 @@ func (peer *Peer) RoutineSequentialReceiver() {
// wait for decryption // wait for decryption
elem.mutex.Lock() elem.mutex.Lock()
if elem.IsDropped() { if elem.IsDropped() {
continue continue
} }
@ -603,8 +615,11 @@ func (peer *Peer) RoutineSequentialReceiver() {
// write to tun device // write to tun device
offset := MessageTransportOffsetContent
atomic.AddUint64(&peer.stats.rxBytes, uint64(len(elem.packet))) atomic.AddUint64(&peer.stats.rxBytes, uint64(len(elem.packet)))
_, err := device.tun.device.Write(elem.packet) _, err := device.tun.device.Write(
elem.buffer[:offset+len(elem.packet)],
offset)
device.PutMessageBuffer(elem.buffer) device.PutMessageBuffer(elem.buffer)
if err != nil { if err != nil {
logError.Println("Failed to write packet to TUN device:", err) logError.Println("Failed to write packet to TUN device:", err)

View File

@ -127,8 +127,9 @@ func (device *Device) RoutineReadFromTUN() {
// read packet // read packet
elem.packet = elem.buffer[MessageTransportHeaderSize:] offset := MessageTransportHeaderSize
size, err := device.tun.device.Read(elem.packet) size, err := device.tun.device.Read(elem.buffer[:], offset)
if err != nil { if err != nil {
logError.Println("Failed to read packet from TUN device:", err) logError.Println("Failed to read packet from TUN device:", err)
device.Close() device.Close()
@ -139,7 +140,7 @@ func (device *Device) RoutineReadFromTUN() {
continue continue
} }
elem.packet = elem.packet[:size] elem.packet = elem.buffer[offset : offset+size]
// lookup peer // lookup peer

View File

@ -16,13 +16,13 @@ const (
) )
type TUNDevice interface { type TUNDevice interface {
File() *os.File // returns the file descriptor of the device File() *os.File // returns the file descriptor of the device
Read([]byte) (int, error) // read a packet from the device (without any additional headers) Read([]byte, int) (int, error) // read a packet from the device (without any additional headers)
Write([]byte) (int, error) // writes a packet to 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 MTU() (int, error) // returns the MTU of the device
Name() string // returns the current name Name() string // returns the current name
Events() chan TUNEvent // returns a constant channel of events related to the device Events() chan TUNEvent // returns a constant channel of events related to the device
Close() error // stops the device and closes the event channel Close() error // stops the device and closes the event channel
} }
func (device *Device) RoutineTUNEventReader() { func (device *Device) RoutineTUNEventReader() {

View File

@ -7,6 +7,7 @@ import (
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt" "fmt"
"golang.org/x/net/ipv6"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"net" "net"
"os" "os"
@ -249,16 +250,41 @@ func (tun *NativeTun) MTU() (int, error) {
return int(val), nil return int(val), nil
} }
func (tun *NativeTun) Write(d []byte) (int, error) { func (tun *NativeTun) Write(buff []byte, offset int) (int, error) {
return tun.fd.Write(d)
// reserve space for header
buff = buff[offset-4:]
// add packet information header
buff[0] = 0x00
buff[1] = 0x00
if buff[4] == ipv6.Version<<4 {
buff[2] = 0x86
buff[3] = 0xdd
} else {
buff[2] = 0x08
buff[3] = 0x00
}
// write
return tun.fd.Write(buff)
} }
func (tun *NativeTun) Read(d []byte) (int, error) { func (tun *NativeTun) Read(buff []byte, offset int) (int, error) {
select { select {
case err := <-tun.errors: case err := <-tun.errors:
return 0, err return 0, err
default: default:
return tun.fd.Read(d) buff := buff[offset-4:]
n, err := tun.fd.Read(buff[:])
if n < 4 {
return 0, err
}
return n - 4, err
} }
} }
@ -306,7 +332,7 @@ func CreateTUN(name string) (TUNDevice, error) {
// create new device // create new device
var ifr [IFReqSize]byte var ifr [IFReqSize]byte
var flags uint16 = unix.IFF_TUN | unix.IFF_NO_PI var flags uint16 = unix.IFF_TUN // | unix.IFF_NO_PI
nameBytes := []byte(name) nameBytes := []byte(name)
if len(nameBytes) >= unix.IFNAMSIZ { if len(nameBytes) >= unix.IFNAMSIZ {
return nil, errors.New("Interface name too long") return nil, errors.New("Interface name too long")