forked from Lukasa/gopcap
-
Notifications
You must be signed in to change notification settings - Fork 0
/
parse.go
117 lines (95 loc) · 2.92 KB
/
parse.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
package gopcap
import (
"bytes"
"encoding/binary"
"io"
"io/ioutil"
"time"
)
var magic = []byte{0xa1, 0xb2, 0xc3, 0xd4}
var magic_reverse = []byte{0xd4, 0xc3, 0xb2, 0xa1}
// checkMagicNum checks the first four bytes of a pcap file, searching for the magic number
// and checking the byte order. Returns three values: whether the file is a pcap file, whether
// the byte order needs flipping, and any error that was encountered. If error is returned,
// the other values are invalid.
func checkMagicNum(src io.Reader) (bool, binary.ByteOrder, error) {
// These magic numbers form the header of a pcap file.
buffer := make([]byte, len(magic))
readCount, err := src.Read(buffer)
switch {
case readCount != len(magic):
// Failed to read enough bytes for the magic number
return false, nil, InsufficientLength
case err != nil && err != io.EOF:
// Unexpected error
return false, nil, err
case bytes.Equal(buffer, magic):
// Big endian
return true, binary.BigEndian, nil
case bytes.Equal(buffer, magic_reverse):
// Little endian
return true, binary.LittleEndian, nil
default:
// Unrecognised magic number
return false, nil, NotAPcapFile
}
}
func (pkt *Packet) ReadFrom(src io.Reader, order binary.ByteOrder, linkType Link) error {
err := pkt.readPacketHeader(src, order)
if err != nil {
return err
}
packetReader := io.LimitReader(src, int64(pkt.IncludedLen))
pkt.Data, err = readLinkData(packetReader, order, linkType)
// Read any remaining data in the packet that wasn't parsed.
ioutil.ReadAll(packetReader)
if err != nil {
return err
}
return nil
}
// readFileHeader reads the next 20 bytes out of the .pcap file and uses it to populate the
// PcapFile structure.
func (file *PcapFile) readFileHeader(src io.Reader, order binary.ByteOrder) error {
return readFields(src, order, []interface{}{
&file.MajorVersion,
&file.MinorVersion,
&file.TZCorrection,
&file.SigFigs,
&file.MaxLen,
&file.LinkType,
})
}
// readPacketHeader reads the next 16 bytes out of the file and builds it into a
// packet header.
func (pkt *Packet) readPacketHeader(src io.Reader, order binary.ByteOrder) error {
var ts_seconds, ts_micros uint32
err := readFields(src, order, []interface{}{
&ts_seconds,
&ts_micros,
&pkt.IncludedLen,
&pkt.ActualLen,
})
if err == io.ErrUnexpectedEOF {
return InsufficientLength
}
if err != nil {
return err
}
// Construct the timestamp
pkt.Timestamp = (time.Duration(ts_seconds) * time.Second) + (time.Duration(ts_micros) * time.Microsecond)
return err
}
// readLinkData takes the data buffer containing the full link-layer packet (or equivalent, e.g.
// Ethernet frame) and builds an appropriate in-memory representation.
func readLinkData(src io.Reader, order binary.ByteOrder, linkType Link) (LinkLayer, error) {
var pkt LinkLayer
switch linkType {
case ETHERNET:
pkt = new(EthernetFrame)
default:
pkt = new(UnknownLink)
}
err := pkt.ReadFrom(src)
return pkt, err
}