]> Cypherpunks.ru repositories - govpn.git/blob - tap.go
8a19df344530ef7e181a92ce4790c68b9ad2fe44
[govpn.git] / tap.go
1 /*
2 GoVPN -- simple secure free software virtual private network daemon
3 Copyright (C) 2014-2015 Sergey Matveev <stargrave@stargrave.org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 package govpn
20
21 import (
22         "io"
23
24         "golang.org/x/crypto/poly1305"
25 )
26
27 const (
28         EtherSize = 14
29 )
30
31 type TAP struct {
32         Name   string
33         dev    io.ReadWriter
34         buf    []byte
35         sink   chan []byte
36         ready  chan struct{}
37         synced bool
38 }
39
40 func TAPMaxMTU() int {
41         return MTU - poly1305.TagSize - NonceSize - PktSizeSize - EtherSize
42 }
43
44 func NewTAP(ifaceName string) (*TAP, error) {
45         maxIfacePktSize := TAPMaxMTU() + EtherSize
46         tapRaw, err := newTAPer(ifaceName)
47         if err != nil {
48                 return nil, err
49         }
50         tap := TAP{
51                 Name:   ifaceName,
52                 dev:    tapRaw,
53                 buf:    make([]byte, maxIfacePktSize),
54                 sink:   make(chan []byte),
55                 ready:  make(chan struct{}),
56                 synced: false,
57         }
58         go func() {
59                 var n int
60                 var err error
61                 for {
62                         <-tap.ready
63                         n, err = tap.dev.Read(tap.buf)
64                         if err != nil {
65                                 panic(err)
66                         }
67                         tap.sink <- tap.buf[:n]
68                 }
69         }()
70         return &tap, nil
71 }
72
73 func (t *TAP) Write(data []byte) (n int, err error) {
74         return t.dev.Write(data)
75 }