-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpackets.go
120 lines (100 loc) · 2.98 KB
/
packets.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
120
package main
import (
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
"github.com/prometheus/procfs"
)
// Extract connection-information and size from each packet
func ExtractPacketData(device string, pkt gopacket.Packet) *PacketData {
pckData := PacketData{}
pckData.Device = device
pckData.Timestamp = pkt.Metadata().Timestamp.UnixNano()
// decode IPv4 or IPv6 layer
if layer := pkt.Layer(layers.LayerTypeIPv4); layer != nil {
ipv4 := layer.(*layers.IPv4)
pckData.LocalAddr = ipv4.SrcIP
pckData.RemAddr = ipv4.DstIP
} else if layer := pkt.Layer(layers.LayerTypeIPv6); layer != nil {
ipv6 := layer.(*layers.IPv6)
pckData.LocalAddr = ipv6.SrcIP
pckData.RemAddr = ipv6.DstIP
}
// Decode TPC layer if present
if tcpLayer := pkt.Layer(layers.LayerTypeTCP); tcpLayer != nil {
tcp := tcpLayer.(*layers.TCP)
pckData.LocalPort = uint64(tcp.SrcPort)
pckData.RemPort = uint64(tcp.DstPort)
}
// TODO UDP or other layer
pckData.Size = len(pkt.Data())
return &pckData
}
// Emit packet-information for each device to a shared channel.
func EmitDevicePackets(packetChan chan *PacketData, device string) {
handle, err := pcap.OpenLive(device, 262144, true, pcap.BlockForever)
if err != nil {
panic(err)
}
defer handle.Close()
packets := gopacket.NewPacketSource(handle, handle.LinkType()).Packets()
for pkt := range packets {
packetChan <- ExtractPacketData(device, pkt)
}
}
// Watch for packets on each present device
func PacketWatcher(packetChan chan *PacketData, pfs *procfs.FS) {
deviceNames, _ := ListNetworkDevices(pfs)
for _, device := range deviceNames {
go EmitDevicePackets(packetChan, device)
}
}
func AssociatePacket(store MachineNetworkStorage, pidConns *[]PidSocket, pkt PacketData) {
// if the device is not set, set it!
if _, ok := store[pkt.Device]; !ok {
store[pkt.Device] = map[string]StoredConnectionData{}
}
id := pkt.GetId()
if tgt, hasConn := store[pkt.Device][id]; !hasConn {
// set the initial stored-data for this connection, with a single stored packet
packets := []StoredPacketData{}
packets = append(packets, StoredPacketData{
Timestamp: int64(pkt.Timestamp),
Size: int(pkt.Size),
})
store[pkt.Device][id] = StoredConnectionData{
LocalAddr: pkt.LocalAddr,
LocalPort: pkt.LocalPort,
RemAddr: pkt.RemAddr,
RemPort: pkt.RemPort,
Size: pkt.Size,
From: int(pkt.Timestamp),
To: int(pkt.Timestamp),
Packets: packets,
}
} else {
// update the connection
tgt.Size += pkt.Size
if tgt.From > int(pkt.Timestamp) {
tgt.From = int(pkt.Timestamp)
}
if tgt.To < int(pkt.Timestamp) {
tgt.To = int(pkt.Timestamp)
}
tgt.Packets = append(tgt.Packets, StoredPacketData{
pkt.Timestamp,
pkt.Size,
})
// for some reason I need to create a new struct?
store[pkt.Device][id] = StoredConnectionData{
tgt.LocalAddr,
tgt.LocalPort,
tgt.RemAddr,
tgt.RemPort,
tgt.Size,
tgt.From,
tgt.To,
tgt.Packets,
}
}
}