diff --git a/src/receive.go b/src/receive.go index f650cc9..dbd2813 100644 --- a/src/receive.go +++ b/src/receive.go @@ -243,13 +243,24 @@ func (device *Device) RoutineDecryption() { counter := elem.packet[MessageTransportOffsetCounter: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 var err error - copy(nonce[4:], counter) elem.counter = binary.LittleEndian.Uint64(counter) elem.packet, err = elem.keyPair.receive.Open( - elem.buffer[:0], + content[:0], nonce[:], content, nil, @@ -495,6 +506,7 @@ func (peer *Peer) RoutineSequentialReceiver() { // wait for decryption elem.mutex.Lock() + if elem.IsDropped() { continue } @@ -603,8 +615,11 @@ func (peer *Peer) RoutineSequentialReceiver() { // write to tun device + offset := MessageTransportOffsetContent 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) if err != nil { logError.Println("Failed to write packet to TUN device:", err) diff --git a/src/send.go b/src/send.go index 2919f2e..9537f5e 100644 --- a/src/send.go +++ b/src/send.go @@ -127,8 +127,9 @@ func (device *Device) RoutineReadFromTUN() { // read packet - elem.packet = elem.buffer[MessageTransportHeaderSize:] - size, err := device.tun.device.Read(elem.packet) + offset := MessageTransportHeaderSize + size, err := device.tun.device.Read(elem.buffer[:], offset) + if err != nil { logError.Println("Failed to read packet from TUN device:", err) device.Close() @@ -139,7 +140,7 @@ func (device *Device) RoutineReadFromTUN() { continue } - elem.packet = elem.packet[:size] + elem.packet = elem.buffer[offset : offset+size] // lookup peer diff --git a/src/tun.go b/src/tun.go index 215022c..54253b4 100644 --- a/src/tun.go +++ b/src/tun.go @@ -16,13 +16,13 @@ const ( ) type TUNDevice interface { - File() *os.File // returns the file descriptor of the device - Read([]byte) (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) - MTU() (int, error) // returns the MTU of the device - Name() string // 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 + 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 // 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() { diff --git a/src/tun_linux.go b/src/tun_linux.go index 8a5d53b..daa2462 100644 --- a/src/tun_linux.go +++ b/src/tun_linux.go @@ -7,6 +7,7 @@ import ( "encoding/binary" "errors" "fmt" + "golang.org/x/net/ipv6" "golang.org/x/sys/unix" "net" "os" @@ -249,16 +250,41 @@ func (tun *NativeTun) MTU() (int, error) { return int(val), nil } -func (tun *NativeTun) Write(d []byte) (int, error) { - return tun.fd.Write(d) +func (tun *NativeTun) Write(buff []byte, offset int) (int, error) { + + // 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 { case err := <-tun.errors: return 0, err 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 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) if len(nameBytes) >= unix.IFNAMSIZ { return nil, errors.New("Interface name too long")