-
Notifications
You must be signed in to change notification settings - Fork 5
/
packet.go
90 lines (76 loc) · 2.24 KB
/
packet.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
package pcap
import (
"compress/gzip"
"errors"
"io"
"os"
"strings"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcapgo"
"github.com/google/gopacket/tcpassembly"
)
// ExtractStreamsFromFile opens a pcap file from disk and reads it into streams.
func ExtractStreamsFromFile(filename string) ([]*Stream, error) {
cap, err := openPcapFile(filename)
if err != nil {
return nil, err
}
return ExtractStreams(cap)
}
func openPcapFile(filename string) (gopacket.PacketDataSource, error) {
var cap gopacket.PacketDataSource
var r io.Reader
r, err := os.Open(filename)
if err != nil {
return nil, err
}
// Wrap in Gzip reader if necessary.
// (Pcapng reader doesn't do this automatically, pcap reader does.)
if strings.HasSuffix(filename, ".gz") {
r, err = gzip.NewReader(r)
if err != nil {
return nil, err
}
filename = filename[:len(filename)-3]
}
// Call appropriate packet loader.
if strings.HasSuffix(filename, ".pcap") {
cap, err = pcapgo.NewReader(r)
if err != nil {
return nil, err
}
} else if strings.HasSuffix(filename, ".pcapng") {
cap, err = pcapgo.NewNgReader(r, pcapgo.NgReaderOptions{WantMixedLinkType: true})
if err != nil {
return nil, err
}
} else {
return nil, errors.New("no handler for file " + filename)
}
return cap, nil
}
// ExtractStreams extracts streams out of a packet dump.
func ExtractStreams(source gopacket.PacketDataSource) ([]*Stream, error) {
streamFactory := newTCPStreamFactory()
streamPool := tcpassembly.NewStreamPool(streamFactory)
assembler := tcpassembly.NewAssembler(streamPool)
for {
data, in, err := source.ReadPacketData()
if err == io.EOF {
break
} else if err != nil {
return nil, err
}
packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.Default)
if packet.NetworkLayer() == nil {
packet = gopacket.NewPacket(data, layers.LayerTypeLoopback, gopacket.Default)
}
if packet.NetworkLayer() == nil || packet.TransportLayer() == nil || packet.TransportLayer().LayerType() != layers.LayerTypeTCP {
continue
}
tcp := packet.TransportLayer().(*layers.TCP)
assembler.AssembleWithTimestamp(packet.NetworkLayer().NetworkFlow(), tcp, in.Timestamp)
}
return streamFactory.streams, nil
}