-
Notifications
You must be signed in to change notification settings - Fork 0
/
ip_stack.go
119 lines (101 loc) · 2.54 KB
/
ip_stack.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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package ftcp
import (
"math/rand"
"net"
"sync"
"golang.org/x/net/ipv4"
)
const (
ipStackMaxPacketSize = 65536
)
type IPConn interface {
ReadFromIP(b []byte) (int, *net.IPAddr, error)
WriteToIP(b []byte, addr *net.IPAddr) (int, error)
}
type IPSender interface {
SendIPPacket(b []byte, addr *net.IPAddr) error
}
type IPProtcolHandler interface {
HandleIPPacket(packet *IPPacket) error
}
type IPStack struct {
conn IPConn
listenAddr *net.IPAddr
protoHandlers map[int]IPProtcolHandler
lock sync.Mutex
}
func NewIPStack(conn IPConn, listenAddr *net.IPAddr) *IPStack {
s := &IPStack{
conn: conn,
listenAddr: listenAddr,
protoHandlers: make(map[int]IPProtcolHandler),
}
return s
}
func (s *IPStack) RegisterProtocolHandler(proto int, handler IPProtcolHandler) {
s.lock.Lock()
defer s.lock.Unlock()
if s.protoHandlers[proto] != nil {
panic("Protocol handler already registered")
}
s.protoHandlers[proto] = handler
}
func (s *IPStack) Run() error {
packetBuf := make([]byte, ipStackMaxPacketSize)
for {
n, _, err := s.conn.ReadFromIP(packetBuf)
if err != nil {
LogError("Error reading IP packet: %v", err)
return err
}
readPacket := packetBuf[:n]
ipPacket, err := MakeIPPacket(readPacket)
if err != nil {
LogWarn("Error parsing IP packet: %v", err)
continue
}
if !ipPacket.Header.Dst.Equal(s.listenAddr.IP) {
// Not listening on this address. Drop packet.
continue
}
// Verify IP checksum
calcIpChecksum := IPChecksum(readPacket[:ipPacket.Header.Len])
if uint16(ipPacket.Header.Checksum) != calcIpChecksum {
LogWarn("IP checksum 0x%04x != calculated checksum 0x%04x",
ipPacket.Header.Checksum, calcIpChecksum)
continue
}
s.lock.Lock()
handler := s.protoHandlers[ipPacket.Header.Protocol]
s.lock.Unlock()
if handler == nil {
LogDebug("No handler registered for protocol %d", ipPacket.Header.Protocol)
continue
}
err = handler.HandleIPPacket(ipPacket)
if err != nil {
LogWarn("Error handling IP packet: %v", err)
}
}
}
func (s *IPStack) SendIPPacket(b []byte, addr *net.IPAddr) error {
respIpHeader := &ipv4.Header{
Version: ipv4.Version,
Len: ipv4.HeaderLen,
TotalLen: ipv4.HeaderLen + len(b),
FragOff: 0,
TTL: 32,
Protocol: 6,
ID: rand.Int(),
Src: s.listenAddr.IP,
Dst: addr.IP,
}
packetBuf, err := respIpHeader.Marshal()
if err != nil {
panic(err)
}
IPSetChecksum(packetBuf, IPChecksum(packetBuf))
packetBuf = append(packetBuf, b...)
_, err = s.conn.WriteToIP(packetBuf, addr)
return err
}