| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- // 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
- }
|