mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-28 19:59:57 +00:00
TUN-6666: Define packet package
This package defines IP and ICMP packet, decoders, encoder and flow
This commit is contained in:
218
vendor/github.com/google/gopacket/layers/lcm.go
generated
vendored
Normal file
218
vendor/github.com/google/gopacket/layers/lcm.go
generated
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
// Copyright 2018 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 layers
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
)
|
||||
|
||||
const (
|
||||
// LCMShortHeaderMagic is the LCM small message header magic number
|
||||
LCMShortHeaderMagic uint32 = 0x4c433032
|
||||
// LCMFragmentedHeaderMagic is the LCM fragmented message header magic number
|
||||
LCMFragmentedHeaderMagic uint32 = 0x4c433033
|
||||
)
|
||||
|
||||
// LCM (Lightweight Communications and Marshalling) is a set of libraries and
|
||||
// tools for message passing and data marshalling, targeted at real-time systems
|
||||
// where high-bandwidth and low latency are critical. It provides a
|
||||
// publish/subscribe message passing model and automatic
|
||||
// marshalling/unmarshalling code generation with bindings for applications in a
|
||||
// variety of programming languages.
|
||||
//
|
||||
// References
|
||||
// https://lcm-proj.github.io/
|
||||
// https://github.com/lcm-proj/lcm
|
||||
type LCM struct {
|
||||
// Common (short & fragmented header) fields
|
||||
Magic uint32
|
||||
SequenceNumber uint32
|
||||
// Fragmented header only fields
|
||||
PayloadSize uint32
|
||||
FragmentOffset uint32
|
||||
FragmentNumber uint16
|
||||
TotalFragments uint16
|
||||
// Common field
|
||||
ChannelName string
|
||||
// Gopacket helper fields
|
||||
Fragmented bool
|
||||
fingerprint LCMFingerprint
|
||||
contents []byte
|
||||
payload []byte
|
||||
}
|
||||
|
||||
// LCMFingerprint is the type of a LCM fingerprint.
|
||||
type LCMFingerprint uint64
|
||||
|
||||
var (
|
||||
// lcmLayerTypes contains a map of all LCM fingerprints that we support and
|
||||
// their LayerType
|
||||
lcmLayerTypes = map[LCMFingerprint]gopacket.LayerType{}
|
||||
layerTypeIndex = 1001
|
||||
)
|
||||
|
||||
// RegisterLCMLayerType allows users to register decoders for the underlying
|
||||
// LCM payload. This is done based on the fingerprint that every LCM message
|
||||
// contains and which identifies it uniquely. If num is not the zero value it
|
||||
// will be used when registering with RegisterLayerType towards gopacket,
|
||||
// otherwise an incremental value starting from 1001 will be used.
|
||||
func RegisterLCMLayerType(num int, name string, fingerprint LCMFingerprint,
|
||||
decoder gopacket.Decoder) gopacket.LayerType {
|
||||
metadata := gopacket.LayerTypeMetadata{Name: name, Decoder: decoder}
|
||||
|
||||
if num == 0 {
|
||||
num = layerTypeIndex
|
||||
layerTypeIndex++
|
||||
}
|
||||
|
||||
lcmLayerTypes[fingerprint] = gopacket.RegisterLayerType(num, metadata)
|
||||
|
||||
return lcmLayerTypes[fingerprint]
|
||||
}
|
||||
|
||||
// SupportedLCMFingerprints returns a slice of all LCM fingerprints that has
|
||||
// been registered so far.
|
||||
func SupportedLCMFingerprints() []LCMFingerprint {
|
||||
fingerprints := make([]LCMFingerprint, 0, len(lcmLayerTypes))
|
||||
for fp := range lcmLayerTypes {
|
||||
fingerprints = append(fingerprints, fp)
|
||||
}
|
||||
return fingerprints
|
||||
}
|
||||
|
||||
// GetLCMLayerType returns the underlying LCM message's LayerType.
|
||||
// This LayerType has to be registered by using RegisterLCMLayerType.
|
||||
func GetLCMLayerType(fingerprint LCMFingerprint) gopacket.LayerType {
|
||||
layerType, ok := lcmLayerTypes[fingerprint]
|
||||
if !ok {
|
||||
return gopacket.LayerTypePayload
|
||||
}
|
||||
|
||||
return layerType
|
||||
}
|
||||
|
||||
func decodeLCM(data []byte, p gopacket.PacketBuilder) error {
|
||||
lcm := &LCM{}
|
||||
|
||||
err := lcm.DecodeFromBytes(data, p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.AddLayer(lcm)
|
||||
p.SetApplicationLayer(lcm)
|
||||
|
||||
return p.NextDecoder(lcm.NextLayerType())
|
||||
}
|
||||
|
||||
// DecodeFromBytes decodes the given bytes into this layer.
|
||||
func (lcm *LCM) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
if len(data) < 8 {
|
||||
df.SetTruncated()
|
||||
return errors.New("LCM < 8 bytes")
|
||||
}
|
||||
offset := 0
|
||||
|
||||
lcm.Magic = binary.BigEndian.Uint32(data[offset:4])
|
||||
offset += 4
|
||||
|
||||
if lcm.Magic != LCMShortHeaderMagic && lcm.Magic != LCMFragmentedHeaderMagic {
|
||||
return fmt.Errorf("Received LCM header magic %v does not match know "+
|
||||
"LCM magic numbers. Dropping packet.", lcm.Magic)
|
||||
}
|
||||
|
||||
lcm.SequenceNumber = binary.BigEndian.Uint32(data[offset:8])
|
||||
offset += 4
|
||||
|
||||
if lcm.Magic == LCMFragmentedHeaderMagic {
|
||||
lcm.Fragmented = true
|
||||
|
||||
lcm.PayloadSize = binary.BigEndian.Uint32(data[offset : offset+4])
|
||||
offset += 4
|
||||
|
||||
lcm.FragmentOffset = binary.BigEndian.Uint32(data[offset : offset+4])
|
||||
offset += 4
|
||||
|
||||
lcm.FragmentNumber = binary.BigEndian.Uint16(data[offset : offset+2])
|
||||
offset += 2
|
||||
|
||||
lcm.TotalFragments = binary.BigEndian.Uint16(data[offset : offset+2])
|
||||
offset += 2
|
||||
} else {
|
||||
lcm.Fragmented = false
|
||||
}
|
||||
|
||||
if !lcm.Fragmented || (lcm.Fragmented && lcm.FragmentNumber == 0) {
|
||||
buffer := make([]byte, 0)
|
||||
for _, b := range data[offset:] {
|
||||
offset++
|
||||
|
||||
if b == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
buffer = append(buffer, b)
|
||||
}
|
||||
|
||||
lcm.ChannelName = string(buffer)
|
||||
}
|
||||
|
||||
lcm.fingerprint = LCMFingerprint(
|
||||
binary.BigEndian.Uint64(data[offset : offset+8]))
|
||||
|
||||
lcm.contents = data[:offset]
|
||||
lcm.payload = data[offset:]
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CanDecode returns a set of layers that LCM objects can decode.
|
||||
// As LCM objects can only decode the LCM layer, we just return that layer.
|
||||
func (lcm LCM) CanDecode() gopacket.LayerClass {
|
||||
return LayerTypeLCM
|
||||
}
|
||||
|
||||
// NextLayerType specifies the LCM payload layer type following this header.
|
||||
// As LCM packets are serialized structs with uniq fingerprints for each uniq
|
||||
// combination of data types, lookup of correct layer type is based on that
|
||||
// fingerprint.
|
||||
func (lcm LCM) NextLayerType() gopacket.LayerType {
|
||||
if !lcm.Fragmented || (lcm.Fragmented && lcm.FragmentNumber == 0) {
|
||||
return GetLCMLayerType(lcm.fingerprint)
|
||||
}
|
||||
|
||||
return gopacket.LayerTypeFragment
|
||||
}
|
||||
|
||||
// LayerType returns LayerTypeLCM
|
||||
func (lcm LCM) LayerType() gopacket.LayerType {
|
||||
return LayerTypeLCM
|
||||
}
|
||||
|
||||
// LayerContents returns the contents of the LCM header.
|
||||
func (lcm LCM) LayerContents() []byte {
|
||||
return lcm.contents
|
||||
}
|
||||
|
||||
// LayerPayload returns the payload following this LCM header.
|
||||
func (lcm LCM) LayerPayload() []byte {
|
||||
return lcm.payload
|
||||
}
|
||||
|
||||
// Payload returns the payload following this LCM header.
|
||||
func (lcm LCM) Payload() []byte {
|
||||
return lcm.LayerPayload()
|
||||
}
|
||||
|
||||
// Fingerprint returns the LCM fingerprint of the underlying message.
|
||||
func (lcm LCM) Fingerprint() LCMFingerprint {
|
||||
return lcm.fingerprint
|
||||
}
|
Reference in New Issue
Block a user