mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-28 20:10:00 +00:00
TUN-6666: Define packet package
This package defines IP and ICMP packet, decoders, encoder and flow
This commit is contained in:
184
vendor/github.com/google/gopacket/layers/gtp.go
generated
vendored
Normal file
184
vendor/github.com/google/gopacket/layers/gtp.go
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
// Copyright 2017 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"
|
||||
"fmt"
|
||||
"github.com/google/gopacket"
|
||||
)
|
||||
|
||||
const gtpMinimumSizeInBytes int = 8
|
||||
|
||||
// GTPExtensionHeader is used to carry extra data and enable future extensions of the GTP without the need to use another version number.
|
||||
type GTPExtensionHeader struct {
|
||||
Type uint8
|
||||
Content []byte
|
||||
}
|
||||
|
||||
// GTPv1U protocol is used to exchange user data over GTP tunnels across the Sx interfaces.
|
||||
// Defined in https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=1595
|
||||
type GTPv1U struct {
|
||||
BaseLayer
|
||||
Version uint8
|
||||
ProtocolType uint8
|
||||
Reserved uint8
|
||||
ExtensionHeaderFlag bool
|
||||
SequenceNumberFlag bool
|
||||
NPDUFlag bool
|
||||
MessageType uint8
|
||||
MessageLength uint16
|
||||
TEID uint32
|
||||
SequenceNumber uint16
|
||||
NPDU uint8
|
||||
GTPExtensionHeaders []GTPExtensionHeader
|
||||
}
|
||||
|
||||
// LayerType returns LayerTypeGTPV1U
|
||||
func (g *GTPv1U) LayerType() gopacket.LayerType { return LayerTypeGTPv1U }
|
||||
|
||||
// DecodeFromBytes analyses a byte slice and attempts to decode it as a GTPv1U packet
|
||||
func (g *GTPv1U) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
hLen := gtpMinimumSizeInBytes
|
||||
dLen := len(data)
|
||||
if dLen < hLen {
|
||||
return fmt.Errorf("GTP packet too small: %d bytes", dLen)
|
||||
}
|
||||
g.Version = (data[0] >> 5) & 0x07
|
||||
g.ProtocolType = (data[0] >> 4) & 0x01
|
||||
g.Reserved = (data[0] >> 3) & 0x01
|
||||
g.SequenceNumberFlag = ((data[0] >> 1) & 0x01) == 1
|
||||
g.NPDUFlag = (data[0] & 0x01) == 1
|
||||
g.ExtensionHeaderFlag = ((data[0] >> 2) & 0x01) == 1
|
||||
g.MessageType = data[1]
|
||||
g.MessageLength = binary.BigEndian.Uint16(data[2:4])
|
||||
pLen := 8 + g.MessageLength
|
||||
if uint16(dLen) < pLen {
|
||||
return fmt.Errorf("GTP packet too small: %d bytes", dLen)
|
||||
}
|
||||
// Field used to multiplex different connections in the same GTP tunnel.
|
||||
g.TEID = binary.BigEndian.Uint32(data[4:8])
|
||||
cIndex := uint16(hLen)
|
||||
if g.SequenceNumberFlag || g.NPDUFlag || g.ExtensionHeaderFlag {
|
||||
hLen += 4
|
||||
cIndex += 4
|
||||
if dLen < hLen {
|
||||
return fmt.Errorf("GTP packet too small: %d bytes", dLen)
|
||||
}
|
||||
if g.SequenceNumberFlag {
|
||||
g.SequenceNumber = binary.BigEndian.Uint16(data[8:10])
|
||||
}
|
||||
if g.NPDUFlag {
|
||||
g.NPDU = data[10]
|
||||
}
|
||||
if g.ExtensionHeaderFlag {
|
||||
extensionFlag := true
|
||||
for extensionFlag {
|
||||
extensionType := uint8(data[cIndex-1])
|
||||
extensionLength := uint(data[cIndex])
|
||||
if extensionLength == 0 {
|
||||
return fmt.Errorf("GTP packet with invalid extension header")
|
||||
}
|
||||
// extensionLength is in 4-octet units
|
||||
lIndex := cIndex + (uint16(extensionLength) * 4)
|
||||
if uint16(dLen) < lIndex {
|
||||
fmt.Println(dLen, lIndex)
|
||||
return fmt.Errorf("GTP packet with small extension header: %d bytes", dLen)
|
||||
}
|
||||
content := data[cIndex+1 : lIndex-1]
|
||||
eh := GTPExtensionHeader{Type: extensionType, Content: content}
|
||||
g.GTPExtensionHeaders = append(g.GTPExtensionHeaders, eh)
|
||||
cIndex = lIndex
|
||||
// Check if coming bytes are from an extension header
|
||||
extensionFlag = data[cIndex-1] != 0
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
g.BaseLayer = BaseLayer{Contents: data[:cIndex], Payload: data[cIndex:]}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// SerializeTo writes the serialized form of this layer into the
|
||||
// SerializationBuffer, implementing gopacket.SerializableLayer.
|
||||
// See the docs for gopacket.SerializableLayer for more info.
|
||||
func (g *GTPv1U) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
|
||||
data, err := b.PrependBytes(gtpMinimumSizeInBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data[0] |= (g.Version << 5)
|
||||
data[0] |= (1 << 4)
|
||||
if len(g.GTPExtensionHeaders) > 0 {
|
||||
data[0] |= 0x04
|
||||
g.ExtensionHeaderFlag = true
|
||||
}
|
||||
if g.SequenceNumberFlag {
|
||||
data[0] |= 0x02
|
||||
}
|
||||
if g.NPDUFlag {
|
||||
data[0] |= 0x01
|
||||
}
|
||||
data[1] = g.MessageType
|
||||
binary.BigEndian.PutUint16(data[2:4], g.MessageLength)
|
||||
binary.BigEndian.PutUint32(data[4:8], g.TEID)
|
||||
if g.ExtensionHeaderFlag || g.SequenceNumberFlag || g.NPDUFlag {
|
||||
data, err := b.AppendBytes(4)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
binary.BigEndian.PutUint16(data[:2], g.SequenceNumber)
|
||||
data[2] = g.NPDU
|
||||
for _, eh := range g.GTPExtensionHeaders {
|
||||
data[len(data)-1] = eh.Type
|
||||
lContent := len(eh.Content)
|
||||
// extensionLength is in 4-octet units
|
||||
extensionLength := (lContent + 2) / 4
|
||||
// Get two extra byte for the next extension header type and length
|
||||
data, err = b.AppendBytes(lContent + 2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data[0] = byte(extensionLength)
|
||||
copy(data[1:lContent+1], eh.Content)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// CanDecode returns a set of layers that GTP objects can decode.
|
||||
func (g *GTPv1U) CanDecode() gopacket.LayerClass {
|
||||
return LayerTypeGTPv1U
|
||||
}
|
||||
|
||||
// NextLayerType specifies the next layer that GoPacket should attempt to
|
||||
func (g *GTPv1U) NextLayerType() gopacket.LayerType {
|
||||
if len(g.LayerPayload()) == 0 {
|
||||
return gopacket.LayerTypeZero
|
||||
}
|
||||
version := uint8(g.LayerPayload()[0]) >> 4
|
||||
if version == 4 {
|
||||
return LayerTypeIPv4
|
||||
} else if version == 6 {
|
||||
return LayerTypeIPv6
|
||||
} else {
|
||||
return LayerTypePPP
|
||||
}
|
||||
}
|
||||
|
||||
func decodeGTPv1u(data []byte, p gopacket.PacketBuilder) error {
|
||||
gtp := >Pv1U{}
|
||||
err := gtp.DecodeFromBytes(data, p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.AddLayer(gtp)
|
||||
return p.NextDecoder(gtp.NextLayerType())
|
||||
}
|
Reference in New Issue
Block a user