ODPM 266: Go-libmemif + 2 examples.
[govpp.git] / vendor / github.com / google / gopacket / parser.go
1 // 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
7 package gopacket
8
9 import (
10         "fmt"
11 )
12
13 // DecodingLayer is an interface for packet layers that can decode themselves.
14 //
15 // The important part of DecodingLayer is that they decode themselves in-place.
16 // Calling DecodeFromBytes on a DecodingLayer totally resets the entire layer to
17 // the new state defined by the data passed in.  A returned error leaves the
18 // DecodingLayer in an unknown intermediate state, thus its fields should not be
19 // trusted.
20 //
21 // Because the DecodingLayer is resetting its own fields, a call to
22 // DecodeFromBytes should normally not require any memory allocation.
23 type DecodingLayer interface {
24         // DecodeFromBytes resets the internal state of this layer to the state
25         // defined by the passed-in bytes.  Slices in the DecodingLayer may
26         // reference the passed-in data, so care should be taken to copy it
27         // first should later modification of data be required before the
28         // DecodingLayer is discarded.
29         DecodeFromBytes(data []byte, df DecodeFeedback) error
30         // CanDecode returns the set of LayerTypes this DecodingLayer can
31         // decode.  For Layers that are also DecodingLayers, this will most
32         // often be that Layer's LayerType().
33         CanDecode() LayerClass
34         // NextLayerType returns the LayerType which should be used to decode
35         // the LayerPayload.
36         NextLayerType() LayerType
37         // LayerPayload is the set of bytes remaining to decode after a call to
38         // DecodeFromBytes.
39         LayerPayload() []byte
40 }
41
42 // DecodingLayerParser parses a given set of layer types.  See DecodeLayers for
43 // more information on how DecodingLayerParser should be used.
44 type DecodingLayerParser struct {
45         // DecodingLayerParserOptions is the set of options available to the
46         // user to define the parser's behavior.
47         DecodingLayerParserOptions
48         first    LayerType
49         decoders map[LayerType]DecodingLayer
50         df       DecodeFeedback
51         // Truncated is set when a decode layer detects that the packet has been
52         // truncated.
53         Truncated bool
54 }
55
56 // AddDecodingLayer adds a decoding layer to the parser.  This adds support for
57 // the decoding layer's CanDecode layers to the parser... should they be
58 // encountered, they'll be parsed.
59 func (l *DecodingLayerParser) AddDecodingLayer(d DecodingLayer) {
60         for _, typ := range d.CanDecode().LayerTypes() {
61                 l.decoders[typ] = d
62         }
63 }
64
65 // SetTruncated is used by DecodingLayers to set the Truncated boolean in the
66 // DecodingLayerParser.  Users should simply read Truncated after calling
67 // DecodeLayers.
68 func (l *DecodingLayerParser) SetTruncated() {
69         l.Truncated = true
70 }
71
72 // NewDecodingLayerParser creates a new DecodingLayerParser and adds in all
73 // of the given DecodingLayers with AddDecodingLayer.
74 //
75 // Each call to DecodeLayers will attempt to decode the given bytes first by
76 // treating them as a 'first'-type layer, then by using NextLayerType on
77 // subsequently decoded layers to find the next relevant decoder.  Should a
78 // deoder not be available for the layer type returned by NextLayerType,
79 // decoding will stop.
80 func NewDecodingLayerParser(first LayerType, decoders ...DecodingLayer) *DecodingLayerParser {
81         dlp := &DecodingLayerParser{
82                 decoders: make(map[LayerType]DecodingLayer),
83                 first:    first,
84         }
85         dlp.df = dlp // Cast this once to the interface
86         for _, d := range decoders {
87                 dlp.AddDecodingLayer(d)
88         }
89         return dlp
90 }
91
92 // DecodeLayers decodes as many layers as possible from the given data.  It
93 // initially treats the data as layer type 'typ', then uses NextLayerType on
94 // each subsequent decoded layer until it gets to a layer type it doesn't know
95 // how to parse.
96 //
97 // For each layer successfully decoded, DecodeLayers appends the layer type to
98 // the decoded slice.  DecodeLayers truncates the 'decoded' slice initially, so
99 // there's no need to empty it yourself.
100 //
101 // This decoding method is about an order of magnitude faster than packet
102 // decoding, because it only decodes known layers that have already been
103 // allocated.  This means it doesn't need to allocate each layer it returns...
104 // instead it overwrites the layers that already exist.
105 //
106 // Example usage:
107 //    func main() {
108 //      var eth layers.Ethernet
109 //      var ip4 layers.IPv4
110 //      var ip6 layers.IPv6
111 //      var tcp layers.TCP
112 //      var udp layers.UDP
113 //      var payload gopacket.Payload
114 //      parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, &eth, &ip4, &ip6, &tcp, &udp, &payload)
115 //      var source gopacket.PacketDataSource = getMyDataSource()
116 //      decodedLayers := make([]gopacket.LayerType, 0, 10)
117 //      for {
118 //        data, _, err := source.ReadPacketData()
119 //        if err == nil {
120 //          fmt.Println("Error reading packet data: ", err)
121 //          continue
122 //        }
123 //        fmt.Println("Decoding packet")
124 //        err = parser.DecodeLayers(data, &decodedLayers)
125 //        for _, typ := range decodedLayers {
126 //          fmt.Println("  Successfully decoded layer type", typ)
127 //          switch typ {
128 //            case layers.LayerTypeEthernet:
129 //              fmt.Println("    Eth ", eth.SrcMAC, eth.DstMAC)
130 //            case layers.LayerTypeIPv4:
131 //              fmt.Println("    IP4 ", ip4.SrcIP, ip4.DstIP)
132 //            case layers.LayerTypeIPv6:
133 //              fmt.Println("    IP6 ", ip6.SrcIP, ip6.DstIP)
134 //            case layers.LayerTypeTCP:
135 //              fmt.Println("    TCP ", tcp.SrcPort, tcp.DstPort)
136 //            case layers.LayerTypeUDP:
137 //              fmt.Println("    UDP ", udp.SrcPort, udp.DstPort)
138 //          }
139 //        }
140 //        if decodedLayers.Truncated {
141 //          fmt.Println("  Packet has been truncated")
142 //        }
143 //        if err != nil {
144 //          fmt.Println("  Error encountered:", err)
145 //        }
146 //      }
147 //    }
148 //
149 // If DecodeLayers is unable to decode the next layer type, it will return the
150 // error UnsupportedLayerType.
151 func (l *DecodingLayerParser) DecodeLayers(data []byte, decoded *[]LayerType) (err error) {
152         l.Truncated = false
153         if !l.IgnorePanic {
154                 defer panicToError(&err)
155         }
156         typ := l.first
157         *decoded = (*decoded)[:0] // Truncated decoded layers.
158         for len(data) > 0 {
159                 decoder, ok := l.decoders[typ]
160                 if !ok {
161                         return UnsupportedLayerType(typ)
162                 } else if err = decoder.DecodeFromBytes(data, l.df); err != nil {
163                         return err
164                 }
165                 *decoded = append(*decoded, typ)
166                 typ = decoder.NextLayerType()
167                 data = decoder.LayerPayload()
168         }
169         return nil
170 }
171
172 // UnsupportedLayerType is returned by DecodingLayerParser if DecodeLayers
173 // encounters a layer type that the DecodingLayerParser has no decoder for.
174 type UnsupportedLayerType LayerType
175
176 // Error implements the error interface, returning a string to say that the
177 // given layer type is unsupported.
178 func (e UnsupportedLayerType) Error() string {
179         return fmt.Sprintf("No decoder for layer type %v", LayerType(e))
180 }
181
182 func panicToError(e *error) {
183         if r := recover(); r != nil {
184                 *e = fmt.Errorf("panic: %v", r)
185         }
186 }
187
188 // DecodingLayerParserOptions provides options to affect the behavior of a given
189 // DecodingLayerParser.
190 type DecodingLayerParserOptions struct {
191         // IgnorePanic determines whether a DecodingLayerParser should stop
192         // panics on its own (by returning them as an error from DecodeLayers)
193         // or should allow them to raise up the stack.  Handling errors does add
194         // latency to the process of decoding layers, but is much safer for
195         // callers.  IgnorePanic defaults to false, thus if the caller does
196         // nothing decode panics will be returned as errors.
197         IgnorePanic bool
198 }