X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=tap.go;h=6fbba6d3a32749e5d065dcb1281b06a78aaca5ba;hb=refs%2Fheads%2Fdevelop;hp=85926d7df9d1c4d290f85c77408251de0e50f417;hpb=6813fd50141426b87128f88126e2ce84df0925be;p=govpn.git diff --git a/tap.go b/tap.go index 85926d7..6fbba6d 100644 --- a/tap.go +++ b/tap.go @@ -1,11 +1,10 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2015 Sergey Matveev +Copyright (C) 2014-2020 Sergey Matveev This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. +the Free Software Foundation, version 3 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -20,49 +19,65 @@ package govpn import ( "io" - "log" - - "golang.org/x/crypto/poly1305" ) type TAP struct { - Name string - dev io.ReadWriter - buf []byte - sink chan []byte - ready chan struct{} + Name string + Sink chan []byte + dev io.ReadWriter } -func NewTAP(ifaceName string) (*TAP, error) { - maxIfacePktSize := MTU - poly1305.TagSize - NonceSize +var ( + taps = make(map[string]*TAP) +) + +func NewTAP(ifaceName string, mtu int) (*TAP, error) { tapRaw, err := newTAPer(ifaceName) if err != nil { return nil, err } tap := TAP{ - Name: ifaceName, - dev: tapRaw, - buf: make([]byte, maxIfacePktSize), - sink: make(chan []byte), - ready: make(chan struct{}), + Name: ifaceName, + dev: tapRaw, + Sink: make(chan []byte), } go func() { var n int var err error + var buf []byte + buf0 := make([]byte, mtu) + buf1 := make([]byte, mtu) + bufZ := false for { - <-tap.ready - n, err = tap.dev.Read(tap.buf) + if bufZ { + buf = buf0 + } else { + buf = buf1 + } + bufZ = !bufZ + n, err = tap.dev.Read(buf) if err != nil { - panic(err) + panic("Reading TUN/TAP:" + err.Error()) } - tap.sink <- tap.buf[:n] + tap.Sink <- buf[:n] } }() return &tap, nil } -func (t *TAP) Write(data []byte) { - if _, err := t.dev.Write(data); err != nil { - log.Println("Error writing to iface: ", err) +func (t *TAP) Write(data []byte) (n int, err error) { + return t.dev.Write(data) +} + +func TAPListen(ifaceName string, mtu int) (*TAP, error) { + tap, exists := taps[ifaceName] + if exists { + return tap, nil + } + tap, err := NewTAP(ifaceName, mtu) + if err != nil { + return nil, err } + taps[ifaceName] = tap + return tap, nil }