Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
111 lines (99 sloc) 3.3 KB
// 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"
"strconv"
)
// LayerType is a unique identifier for each type of layer. This enumeration
// does not match with any externally available numbering scheme... it's solely
// usable/useful within this library as a means for requesting layer types
// (see Packet.Layer) and determining which types of layers have been decoded.
//
// New LayerTypes may be created by calling gopacket.RegisterLayerType.
type LayerType int64
// LayerTypeMetadata contains metadata associated with each LayerType.
type LayerTypeMetadata struct {
// Name is the string returned by each layer type's String method.
Name string
// Decoder is the decoder to use when the layer type is passed in as a
// Decoder.
Decoder Decoder
}
type layerTypeMetadata struct {
inUse bool
LayerTypeMetadata
}
// DecodersByLayerName maps layer names to decoders for those layers.
// This allows users to specify decoders by name to a program and have that
// program pick the correct decoder accordingly.
var DecodersByLayerName = map[string]Decoder{}
const maxLayerType = 2000
var ltMeta [maxLayerType]layerTypeMetadata
var ltMetaMap = map[LayerType]layerTypeMetadata{}
// RegisterLayerType creates a new layer type and registers it globally.
// The number passed in must be unique, or a runtime panic will occur. Numbers
// 0-999 are reserved for the gopacket library. Numbers 1000-1999 should be
// used for common application-specific types, and are very fast. Any other
// number (negative or >= 2000) may be used for uncommon application-specific
// types, and are somewhat slower (they require a map lookup over an array
// index).
func RegisterLayerType(num int, meta LayerTypeMetadata) LayerType {
if 0 <= num && num < maxLayerType {
if ltMeta[num].inUse {
panic("Layer type already exists")
}
} else {
if ltMetaMap[LayerType(num)].inUse {
panic("Layer type already exists")
}
}
return OverrideLayerType(num, meta)
}
// OverrideLayerType acts like RegisterLayerType, except that if the layer type
// has already been registered, it overrides the metadata with the passed-in
// metadata intead of panicing.
func OverrideLayerType(num int, meta LayerTypeMetadata) LayerType {
if 0 <= num && num < maxLayerType {
ltMeta[num] = layerTypeMetadata{
inUse: true,
LayerTypeMetadata: meta,
}
} else {
ltMetaMap[LayerType(num)] = layerTypeMetadata{
inUse: true,
LayerTypeMetadata: meta,
}
}
DecodersByLayerName[meta.Name] = meta.Decoder
return LayerType(num)
}
// Decode decodes the given data using the decoder registered with the layer
// type.
func (t LayerType) Decode(data []byte, c PacketBuilder) error {
var d Decoder
if 0 <= int(t) && int(t) < maxLayerType {
d = ltMeta[int(t)].Decoder
} else {
d = ltMetaMap[t].Decoder
}
if d != nil {
return d.Decode(data, c)
}
return fmt.Errorf("Layer type %v has no associated decoder", t)
}
// String returns the string associated with this layer type.
func (t LayerType) String() (s string) {
if 0 <= int(t) && int(t) < maxLayerType {
s = ltMeta[int(t)].Name
} else {
s = ltMetaMap[t].Name
}
if s == "" {
s = strconv.Itoa(int(t))
}
return
}
You can’t perform that action at this time.