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
|
// 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"
)
// 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
}
// 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
first LayerType
decoders map[LayerType]DecodingLayer
df DecodeFeedback
// 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) {
for _, typ := range d.CanDecode().LayerTypes() {
l.decoders[typ] = 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.
func NewDecodingLayerParser(first LayerType, decoders ...DecodingLayer) *DecodingLayerParser {
dlp := &DecodingLayerParser{
decoders: make(map[LayerType]DecodingLayer),
first: first,
}
dlp.df = dlp // Cast this once to the interface
for _, d := range decoders {
dlp.AddDecodingLayer(d)
}
return dlp
}
// 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 := l.first
*decoded = (*decoded)[:0] // Truncated decoded layers.
for len(data) > 0 {
decoder, ok := l.decoders[typ]
if !ok {
return UnsupportedLayerType(typ)
} else if err = decoder.DecodeFromBytes(data, l.df); err != nil {
return err
}
*decoded = append(*decoded, typ)
typ = decoder.NextLayerType()
data = decoder.LayerPayload()
}
return nil
}
// 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
}
|