aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/google/gopacket/layertype.go
blob: 3abfee1e9bada2fa1c8d5cee5209cdedec81fd55 (plain)
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
// 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
}