-
Notifications
You must be signed in to change notification settings - Fork 1
/
parser.go
350 lines (316 loc) · 12.3 KB
/
parser.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
// Copyright 2012 Google, Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree.
package gopacket
import (
"fmt"
)
// A container for single LayerType->DecodingLayer mapping.
type decodingLayerElem struct {
typ LayerType
dec DecodingLayer
}
// DecodingLayer is an interface for packet layers that can decode themselves.
//
// The important part of DecodingLayer is that they decode themselves in-place.
// Calling DecodeFromBytes on a DecodingLayer totally resets the entire layer to
// the new state defined by the data passed in. A returned error leaves the
// DecodingLayer in an unknown intermediate state, thus its fields should not be
// trusted.
//
// Because the DecodingLayer is resetting its own fields, a call to
// DecodeFromBytes should normally not require any memory allocation.
type DecodingLayer interface {
// DecodeFromBytes resets the internal state of this layer to the state
// defined by the passed-in bytes. Slices in the DecodingLayer may
// reference the passed-in data, so care should be taken to copy it
// first should later modification of data be required before the
// DecodingLayer is discarded.
DecodeFromBytes(data []byte, df DecodeFeedback) error
// CanDecode returns the set of LayerTypes this DecodingLayer can
// decode. For Layers that are also DecodingLayers, this will most
// often be that Layer's LayerType().
CanDecode() LayerClass
// NextLayerType returns the LayerType which should be used to decode
// the LayerPayload.
NextLayerType() LayerType
// LayerPayload is the set of bytes remaining to decode after a call to
// DecodeFromBytes.
LayerPayload() []byte
}
// DecodingLayerFunc decodes given packet and stores decoded LayerType
// values into specified slice. Returns either first encountered
// unsupported LayerType value or decoding error. In case of success,
// returns (LayerTypeZero, nil).
type DecodingLayerFunc func([]byte, *[]LayerType) (LayerType, error)
// DecodingLayerContainer stores all DecodingLayer-s and serves as a
// searching tool for DecodingLayerParser.
type DecodingLayerContainer interface {
// Put adds new DecodingLayer to container. The new instance of
// the same DecodingLayerContainer is returned so it may be
// implemented as a value receiver.
Put(DecodingLayer) DecodingLayerContainer
// Decoder returns DecodingLayer to decode given LayerType and
// true if it was found. If no decoder found, return false.
Decoder(LayerType) (DecodingLayer, bool)
// LayersDecoder returns DecodingLayerFunc which decodes given
// packet, starting with specified LayerType and DecodeFeedback.
LayersDecoder(first LayerType, df DecodeFeedback) DecodingLayerFunc
}
// DecodingLayerSparse is a sparse array-based implementation of
// DecodingLayerContainer. Each DecodingLayer is addressed in an
// allocated slice by LayerType value itself. Though this is the
// fastest container it may be memory-consuming if used with big
// LayerType values.
type DecodingLayerSparse []DecodingLayer
// Put implements DecodingLayerContainer interface.
func (dl DecodingLayerSparse) Put(d DecodingLayer) DecodingLayerContainer {
maxLayerType := LayerType(len(dl) - 1)
for _, typ := range d.CanDecode().LayerTypes() {
if typ > maxLayerType {
maxLayerType = typ
}
}
if extra := maxLayerType - LayerType(len(dl)) + 1; extra > 0 {
dl = append(dl, make([]DecodingLayer, extra)...)
}
for _, typ := range d.CanDecode().LayerTypes() {
dl[typ] = d
}
return dl
}
// LayersDecoder implements DecodingLayerContainer interface.
func (dl DecodingLayerSparse) LayersDecoder(first LayerType, df DecodeFeedback) DecodingLayerFunc {
return LayersDecoder(dl, first, df)
}
// Decoder implements DecodingLayerContainer interface.
func (dl DecodingLayerSparse) Decoder(typ LayerType) (DecodingLayer, bool) {
if int64(typ) < int64(len(dl)) {
decoder := dl[typ]
return decoder, decoder != nil
}
return nil, false
}
// DecodingLayerArray is an array-based implementation of
// DecodingLayerContainer. Each DecodingLayer is searched linearly in
// an allocated slice in one-by-one fashion.
type DecodingLayerArray []decodingLayerElem
// Put implements DecodingLayerContainer interface.
func (dl DecodingLayerArray) Put(d DecodingLayer) DecodingLayerContainer {
TYPES:
for _, typ := range d.CanDecode().LayerTypes() {
for i := range dl {
if dl[i].typ == typ {
dl[i].dec = d
continue TYPES
}
}
dl = append(dl, decodingLayerElem{typ, d})
}
return dl
}
// Decoder implements DecodingLayerContainer interface.
func (dl DecodingLayerArray) Decoder(typ LayerType) (DecodingLayer, bool) {
for i := range dl {
if dl[i].typ == typ {
return dl[i].dec, true
}
}
return nil, false
}
// LayersDecoder implements DecodingLayerContainer interface.
func (dl DecodingLayerArray) LayersDecoder(first LayerType, df DecodeFeedback) DecodingLayerFunc {
return LayersDecoder(dl, first, df)
}
// DecodingLayerMap is an map-based implementation of
// DecodingLayerContainer. Each DecodingLayer is searched in a map
// hashed by LayerType value.
type DecodingLayerMap map[LayerType]DecodingLayer
// Put implements DecodingLayerContainer interface.
func (dl DecodingLayerMap) Put(d DecodingLayer) DecodingLayerContainer {
for _, typ := range d.CanDecode().LayerTypes() {
if dl == nil {
dl = make(map[LayerType]DecodingLayer)
}
dl[typ] = d
}
return dl
}
// Decoder implements DecodingLayerContainer interface.
func (dl DecodingLayerMap) Decoder(typ LayerType) (DecodingLayer, bool) {
d, ok := dl[typ]
return d, ok
}
// LayersDecoder implements DecodingLayerContainer interface.
func (dl DecodingLayerMap) LayersDecoder(first LayerType, df DecodeFeedback) DecodingLayerFunc {
return LayersDecoder(dl, first, df)
}
// Static code check.
var (
_ = []DecodingLayerContainer{
DecodingLayerSparse(nil),
DecodingLayerMap(nil),
DecodingLayerArray(nil),
}
)
// DecodingLayerParser parses a given set of layer types. See DecodeLayers for
// more information on how DecodingLayerParser should be used.
type DecodingLayerParser struct {
// DecodingLayerParserOptions is the set of options available to the
// user to define the parser's behavior.
DecodingLayerParserOptions
dlc DecodingLayerContainer
first LayerType
df DecodeFeedback
decodeFunc DecodingLayerFunc
// Truncated is set when a decode layer detects that the packet has been
// truncated.
Truncated bool
}
// AddDecodingLayer adds a decoding layer to the parser. This adds support for
// the decoding layer's CanDecode layers to the parser... should they be
// encountered, they'll be parsed.
func (l *DecodingLayerParser) AddDecodingLayer(d DecodingLayer) {
l.SetDecodingLayerContainer(l.dlc.Put(d))
}
// SetTruncated is used by DecodingLayers to set the Truncated boolean in the
// DecodingLayerParser. Users should simply read Truncated after calling
// DecodeLayers.
func (l *DecodingLayerParser) SetTruncated() {
l.Truncated = true
}
// NewDecodingLayerParser creates a new DecodingLayerParser and adds in all
// of the given DecodingLayers with AddDecodingLayer.
//
// Each call to DecodeLayers will attempt to decode the given bytes first by
// treating them as a 'first'-type layer, then by using NextLayerType on
// subsequently decoded layers to find the next relevant decoder. Should a
// deoder not be available for the layer type returned by NextLayerType,
// decoding will stop.
//
// NewDecodingLayerParser uses DecodingLayerMap container by
// default.
func NewDecodingLayerParser(first LayerType, decoders ...DecodingLayer) *DecodingLayerParser {
dlp := &DecodingLayerParser{first: first}
dlp.df = dlp // Cast this once to the interface
// default container
dlc := DecodingLayerContainer(DecodingLayerMap(make(map[LayerType]DecodingLayer)))
for _, d := range decoders {
dlc = dlc.Put(d)
}
dlp.SetDecodingLayerContainer(dlc)
return dlp
}
// SetDecodingLayerContainer specifies container with decoders. This
// call replaces all decoders already registered in given instance of
// DecodingLayerParser.
func (l *DecodingLayerParser) SetDecodingLayerContainer(dlc DecodingLayerContainer) {
l.dlc = dlc
l.decodeFunc = l.dlc.LayersDecoder(l.first, l.df)
}
// DecodeLayers decodes as many layers as possible from the given data. It
// initially treats the data as layer type 'typ', then uses NextLayerType on
// each subsequent decoded layer until it gets to a layer type it doesn't know
// how to parse.
//
// For each layer successfully decoded, DecodeLayers appends the layer type to
// the decoded slice. DecodeLayers truncates the 'decoded' slice initially, so
// there's no need to empty it yourself.
//
// This decoding method is about an order of magnitude faster than packet
// decoding, because it only decodes known layers that have already been
// allocated. This means it doesn't need to allocate each layer it returns...
// instead it overwrites the layers that already exist.
//
// Example usage:
// func main() {
// var eth layers.Ethernet
// var ip4 layers.IPv4
// var ip6 layers.IPv6
// var tcp layers.TCP
// var udp layers.UDP
// var payload gopacket.Payload
// parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ð, &ip4, &ip6, &tcp, &udp, &payload)
// var source gopacket.PacketDataSource = getMyDataSource()
// decodedLayers := make([]gopacket.LayerType, 0, 10)
// for {
// data, _, err := source.ReadPacketData()
// if err != nil {
// fmt.Println("Error reading packet data: ", err)
// continue
// }
// fmt.Println("Decoding packet")
// err = parser.DecodeLayers(data, &decodedLayers)
// for _, typ := range decodedLayers {
// fmt.Println(" Successfully decoded layer type", typ)
// switch typ {
// case layers.LayerTypeEthernet:
// fmt.Println(" Eth ", eth.SrcMAC, eth.DstMAC)
// case layers.LayerTypeIPv4:
// fmt.Println(" IP4 ", ip4.SrcIP, ip4.DstIP)
// case layers.LayerTypeIPv6:
// fmt.Println(" IP6 ", ip6.SrcIP, ip6.DstIP)
// case layers.LayerTypeTCP:
// fmt.Println(" TCP ", tcp.SrcPort, tcp.DstPort)
// case layers.LayerTypeUDP:
// fmt.Println(" UDP ", udp.SrcPort, udp.DstPort)
// }
// }
// if decodedLayers.Truncated {
// fmt.Println(" Packet has been truncated")
// }
// if err != nil {
// fmt.Println(" Error encountered:", err)
// }
// }
// }
//
// If DecodeLayers is unable to decode the next layer type, it will return the
// error UnsupportedLayerType.
func (l *DecodingLayerParser) DecodeLayers(data []byte, decoded *[]LayerType) (err error) {
l.Truncated = false
if !l.IgnorePanic {
defer panicToError(&err)
}
typ, err := l.decodeFunc(data, decoded)
if typ != LayerTypeZero {
// no decoder
if l.IgnoreUnsupported {
return nil
}
return UnsupportedLayerType(typ)
}
return err
}
// UnsupportedLayerType is returned by DecodingLayerParser if DecodeLayers
// encounters a layer type that the DecodingLayerParser has no decoder for.
type UnsupportedLayerType LayerType
// Error implements the error interface, returning a string to say that the
// given layer type is unsupported.
func (e UnsupportedLayerType) Error() string {
return fmt.Sprintf("No decoder for layer type %v", LayerType(e))
}
func panicToError(e *error) {
if r := recover(); r != nil {
*e = fmt.Errorf("panic: %v", r)
}
}
// DecodingLayerParserOptions provides options to affect the behavior of a given
// DecodingLayerParser.
type DecodingLayerParserOptions struct {
// IgnorePanic determines whether a DecodingLayerParser should stop
// panics on its own (by returning them as an error from DecodeLayers)
// or should allow them to raise up the stack. Handling errors does add
// latency to the process of decoding layers, but is much safer for
// callers. IgnorePanic defaults to false, thus if the caller does
// nothing decode panics will be returned as errors.
IgnorePanic bool
// IgnoreUnsupported will stop parsing and return a nil error when it
// encounters a layer it doesn't have a parser for, instead of returning an
// UnsupportedLayerType error. If this is true, it's up to the caller to make
// sure that all expected layers have been parsed (by checking the decoded
// slice).
IgnoreUnsupported bool
}