mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-28 12:09:57 +00:00
TUN-6666: Define packet package
This package defines IP and ICMP packet, decoders, encoder and flow
This commit is contained in:
350
vendor/github.com/google/gopacket/parser.go
generated
vendored
Normal file
350
vendor/github.com/google/gopacket/parser.go
generated
vendored
Normal file
@@ -0,0 +1,350 @@
|
||||
// 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
|
||||
}
|
Reference in New Issue
Block a user