-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtcpassembly.go
87 lines (73 loc) · 1.85 KB
/
tcpassembly.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
package netutils
import (
"bytes"
"io"
"time"
"github.com/google/gopacket"
"github.com/google/gopacket/tcpassembly"
)
type DNSStreamFactory struct {
// Channel to send reassembled DNS data
Reassembled chan DNSPacket
IPDefragmented bool
}
func (s *DNSStreamFactory) New(net, transport gopacket.Flow) tcpassembly.Stream {
return &stream{
net: net,
transport: transport,
data: make([]byte, 0),
reassembled: s.Reassembled,
ipDefragmented: s.IPDefragmented,
}
}
type stream struct {
net, transport gopacket.Flow
data []byte
lenDNS int
LastSeen time.Time
reassembled chan DNSPacket
tcpReassembled bool
ipDefragmented bool
}
func (s *stream) Reassembled(rs []tcpassembly.Reassembly) {
for _, r := range rs {
if r.Skip > 0 {
continue
}
// Append the reassembled data to the existing data
s.data = append(s.data, r.Bytes...)
// If the length of the DNS message has not been read yet, try to read it from the TCP stream
if s.lenDNS == 0 {
lenBuf := make([]byte, 2)
reader := bytes.NewReader(s.data)
nRead, err := io.ReadFull(reader, lenBuf)
if err != nil {
continue
}
if nRead < 2 {
continue
}
// Convert the length of the DNS message from the buffer to a uint
s.lenDNS = int(uint(lenBuf[0])<<8 | uint(lenBuf[1]))
s.tcpReassembled = false
}
if len(s.data) == s.lenDNS+2 {
s.LastSeen = r.Seen
// send the reassembled data to the channel
s.reassembled <- DNSPacket{
Payload: s.data[2 : s.lenDNS+2],
IPLayer: s.net,
TransportLayer: s.transport,
Timestamp: s.LastSeen,
IPDefragmented: s.ipDefragmented,
TCPReassembled: s.tcpReassembled,
}
// Reset the buffer.
s.data = s.data[s.lenDNS+2:]
s.lenDNS = 0
} else {
s.tcpReassembled = true
}
}
}
func (s *stream) ReassemblyComplete() {}