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