github.com/gopacket/gopacket@v1.1.0/layertype.go (about)

     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  	"strconv"
    12  )
    13  
    14  // LayerType is a unique identifier for each type of layer.  This enumeration
    15  // does not match with any externally available numbering scheme... it's solely
    16  // usable/useful within this library as a means for requesting layer types
    17  // (see Packet.Layer) and determining which types of layers have been decoded.
    18  //
    19  // New LayerTypes may be created by calling gopacket.RegisterLayerType.
    20  type LayerType int64
    21  
    22  // LayerTypeMetadata contains metadata associated with each LayerType.
    23  type LayerTypeMetadata struct {
    24  	// Name is the string returned by each layer type's String method.
    25  	Name string
    26  	// Decoder is the decoder to use when the layer type is passed in as a
    27  	// Decoder.
    28  	Decoder Decoder
    29  }
    30  
    31  type layerTypeMetadata struct {
    32  	inUse bool
    33  	LayerTypeMetadata
    34  }
    35  
    36  // DecodersByLayerName maps layer names to decoders for those layers.
    37  // This allows users to specify decoders by name to a program and have that
    38  // program pick the correct decoder accordingly.
    39  var DecodersByLayerName = map[string]Decoder{}
    40  
    41  const maxLayerType = 2000
    42  
    43  var ltMeta [maxLayerType]layerTypeMetadata
    44  var ltMetaMap = map[LayerType]layerTypeMetadata{}
    45  
    46  // RegisterLayerType creates a new layer type and registers it globally.
    47  // The number passed in must be unique, or a runtime panic will occur.  Numbers
    48  // 0-999 are reserved for the gopacket library.  Numbers 1000-1999 should be
    49  // used for common application-specific types, and are very fast.  Any other
    50  // number (negative or >= 2000) may be used for uncommon application-specific
    51  // types, and are somewhat slower (they require a map lookup over an array
    52  // index).
    53  func RegisterLayerType(num int, meta LayerTypeMetadata) LayerType {
    54  	if 0 <= num && num < maxLayerType {
    55  		if ltMeta[num].inUse {
    56  			panic("Layer type already exists")
    57  		}
    58  	} else {
    59  		if ltMetaMap[LayerType(num)].inUse {
    60  			panic("Layer type already exists")
    61  		}
    62  	}
    63  	return OverrideLayerType(num, meta)
    64  }
    65  
    66  // OverrideLayerType acts like RegisterLayerType, except that if the layer type
    67  // has already been registered, it overrides the metadata with the passed-in
    68  // metadata intead of panicing.
    69  func OverrideLayerType(num int, meta LayerTypeMetadata) LayerType {
    70  	if 0 <= num && num < maxLayerType {
    71  		ltMeta[num] = layerTypeMetadata{
    72  			inUse:             true,
    73  			LayerTypeMetadata: meta,
    74  		}
    75  	} else {
    76  		ltMetaMap[LayerType(num)] = layerTypeMetadata{
    77  			inUse:             true,
    78  			LayerTypeMetadata: meta,
    79  		}
    80  	}
    81  	DecodersByLayerName[meta.Name] = meta.Decoder
    82  	return LayerType(num)
    83  }
    84  
    85  // Decode decodes the given data using the decoder registered with the layer
    86  // type.
    87  func (t LayerType) Decode(data []byte, c PacketBuilder) error {
    88  	var d Decoder
    89  	if 0 <= int(t) && int(t) < maxLayerType {
    90  		d = ltMeta[int(t)].Decoder
    91  	} else {
    92  		d = ltMetaMap[t].Decoder
    93  	}
    94  	if d != nil {
    95  		return d.Decode(data, c)
    96  	}
    97  	return fmt.Errorf("Layer type %v has no associated decoder", t)
    98  }
    99  
   100  // String returns the string associated with this layer type.
   101  func (t LayerType) String() (s string) {
   102  	if 0 <= int(t) && int(t) < maxLayerType {
   103  		s = ltMeta[int(t)].Name
   104  	} else {
   105  		s = ltMetaMap[t].Name
   106  	}
   107  	if s == "" {
   108  		s = strconv.Itoa(int(t))
   109  	}
   110  	return
   111  }