This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
forked from titanous/go-wireguard
-
Notifications
You must be signed in to change notification settings - Fork 2
/
inside.go
88 lines (73 loc) · 2.07 KB
/
inside.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package wireguard
import (
"errors"
"log"
"net"
"runtime"
)
var ErrHostUnreachable = errors.New("Host unreachable")
// TODO: be smarter about this
const mtu = 1500
func (f *Interface) readInsidePackets() {
mtu := mtu
skip := 0
// OSX prepends the first 4 bytes received by each packet
// with the values of AF_INET/AF_INET6 to indicate the
// encapsulated IP packet. Unfortunately a Read()
// must be for the entire packet content before fetching
// subsequent packets, therefore we need to do a little
// massaging ourselves.
if runtime.GOOS == "darwin" {
mtu += 4
skip = 4
}
for {
buf := make([]byte, mtu)
log.Println("wip: f.inside.Read()\n")
n, err := f.inside.Read(buf)
log.Printf("wip: f.inside.Read() finished: (%d, %s)\n", n, err)
if err != nil {
// TODO: figure out what kind of errors can be returned
// one would be unloading the TUN driver from underneath
log.Printf("f.inside.Read() error: %s\n", err)
continue
}
f.receiveInsidePacket(buf[skip:n])
}
}
// extracts destination address from IPv4/IPv6 packet
func extractIP(buf []byte) (src net.IP, dst net.IP, err error) {
ipVer := buf[0] >> 4
if ipVer == 4 {
src = net.IP(buf[12:16])
dst = net.IP(buf[16:20])
} else if ipVer == 6 {
src = net.IP(buf[8:24])
dst = net.IP(buf[24:40])
} else {
return src, dst, errInvalidIpPacket
}
return src, dst, nil
}
func (f *Interface) receiveInsidePacket(buf []byte) error {
_, dst, err := extractIP(buf)
if err != nil {
return err
}
peer, err := f.routetable.Lookup(dst)
if err != nil {
return err
}
if peer == nil {
// we need to generate ICMP unreachable message
// but a bit time consuming to implement at the moment.
return ErrHostUnreachable
}
// in the C implementation [device.c:xmit()] the queue is first
// trimmed and then the packet is enqueued (after being segmented
// using GSO); it is unclear (but probably unlikely) we need to
// do segmentation as the underlying TUN driver will do this for us;
// (and fairly easy to test).
peer.txQueue.BoundedAppend(buf, maxQueuePackets)
return peer.sendQueue()
}