Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 3 additions & 15 deletions layers/enums.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ const (
type LinkType uint8

const (
// According to pcap-linktype(7).
// According to pcap-linktype(7) with fixes from pcap/bpf.h
LinkTypeNull LinkType = 0
LinkTypeEthernet LinkType = 1
LinkTypeTokenRing LinkType = 6
Expand All @@ -97,7 +97,7 @@ const (
LinkTypePPP LinkType = 9
LinkTypeFDDI LinkType = 10
LinkTypeATM_RFC1483 LinkType = 100
LinkTypeRaw LinkType = 101
LinkTypeRaw LinkType = 12
LinkTypePPP_HDLC LinkType = 50
LinkTypePPPEthernet LinkType = 51
LinkTypeC_HDLC LinkType = 104
Expand Down Expand Up @@ -358,18 +358,6 @@ func (a Dot11Type) LayerType() gopacket.LayerType {
return Dot11TypeMetadata[a].LayerType
}

// Decode a raw v4 or v6 IP packet.
func decodeIPv4or6(data []byte, p gopacket.PacketBuilder) error {
version := data[0] >> 4
switch version {
case 4:
return decodeIPv4(data, p)
case 6:
return decodeIPv6(data, p)
}
return fmt.Errorf("Invalid IP packet version %v", version)
}

func init() {
// Here we link up all enumerations with their respective names and decoders.
for i := 0; i < 65536; i++ {
Expand Down Expand Up @@ -479,7 +467,7 @@ func init() {
LinkTypeMetadata[LinkTypeFDDI] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeFDDI), Name: "FDDI"}
LinkTypeMetadata[LinkTypeNull] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeLoopback), Name: "Null"}
LinkTypeMetadata[LinkTypeLoop] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeLoopback), Name: "Loop"}
LinkTypeMetadata[LinkTypeRaw] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeIPv4or6), Name: "Raw"}
LinkTypeMetadata[LinkTypeRaw] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeRawIP), Name: "Raw"}
LinkTypeMetadata[LinkTypePFLog] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodePFLog), Name: "PFLog"}
LinkTypeMetadata[LinkTypeIEEE80211Radio] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeRadioTap), Name: "RadioTap"}
LinkTypeMetadata[LinkTypeLinuxUSB] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeUSB), Name: "USB"}
Expand Down
1 change: 1 addition & 0 deletions layers/layertypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ var (
LayerTypeUSBInterrupt = gopacket.RegisterLayerType(111, gopacket.LayerTypeMetadata{"USBInterrupt", gopacket.DecodeFunc(decodeUSBInterrupt)})
LayerTypeUSBBulk = gopacket.RegisterLayerType(112, gopacket.LayerTypeMetadata{"USBBulk", gopacket.DecodeFunc(decodeUSBBulk)})
LayerTypeLinuxSLL = gopacket.RegisterLayerType(113, gopacket.LayerTypeMetadata{"Linux SLL", gopacket.DecodeFunc(decodeLinuxSLL)})
LayerTypeRaw = gopacket.RegisterLayerType(114, gopacket.LayerTypeMetadata{"RAW", gopacket.DecodeFunc(decodeRawIP)})
)

var (
Expand Down
68 changes: 68 additions & 0 deletions layers/raw.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright 2012 Google, Inc. All rights reserved.
// Copyright 2009-2011 Andreas Krennmair. 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 (
"fmt"
"github.com/tsg/gopacket"
)

// RawIP (DLT_RAW) contains no header and we start with the IP header
type Raw struct {
BaseLayer
Family ProtocolFamily
}

func (r *Raw) LayerType() gopacket.LayerType { return LayerTypeRaw }

func (r *Raw) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
if len(data) < 1 {
return fmt.Errorf("Raw packet too small")
}

family, err := versionToFamily(data[0] >> 4)
if err != nil {
return err
}
r.Family = family
r.BaseLayer = BaseLayer{make([]byte, 0), data}
return nil
}

func (r *Raw) CanDecode() gopacket.LayerClass {
return LayerTypeRaw
}

func (r *Raw) NextLayerType() gopacket.LayerType {
return r.Family.LayerType()
}

func versionToFamily(version uint8) (ProtocolFamily, error) {
switch version {
case 4:
return ProtocolFamilyIPv4, nil
case 6:
return ProtocolFamilyIPv6Linux, nil
default:
return 0, fmt.Errorf("Unknown protocol version %d", version)
}
}

// Decode a raw v4 or v6 IP packet.
func decodeRawIP(data []byte, p gopacket.PacketBuilder) error {
family, err := versionToFamily(data[0] >> 4)
if err != nil {
return err
}
r := &Raw{
BaseLayer: BaseLayer{make([]byte, 0), data},
Family: family,
}
p.AddLayer(r)
return p.NextDecoder(r.Family)
}
52 changes: 52 additions & 0 deletions layers/raw_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2017 Holger Hans Peter Freyther, 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 (
"testing"

"github.com/tsg/gopacket"
)

// testPacketPacket0 is the packet:
// 12:13:21.217957 IP 10.8.254.8 > 8.8.8.8: ICMP echo request, id 20348, seq 1, length 64
// 0x0000: 4500 0054 1530 4000 4001 0d59 0a08 fe08 E..T.0@.@..Y....
// 0x0010: 0808 0808 0800 d81d 4f7c 0001 e1e5 3059 ........O|....0Y
// 0x0020: 0000 0000 fc52 0300 0000 0000 1011 1213 .....R..........
// 0x0030: 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 .............!"#
// 0x0040: 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 $%&'()*+,-./0123
// 0x0050: 3435 3637 4567
var testPacketPacket0 = []byte{
0x45, 0x00, 0x00, 0x54, 0x15, 0x30, 0x40, 0x00, 0x40, 0x01, 0x0d, 0x59, 0x0a, 0x08, 0xfe, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0xd8, 0x1d, 0x4f, 0x7c, 0x00, 0x01, 0xe1, 0xe5, 0x30, 0x59,
0x00, 0x00, 0x00, 0x00, 0xfc, 0x52, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x12, 0x13,
0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
0x34, 0x35, 0x36, 0x37,
}

func TestPacketRawIPICMPv4(t *testing.T) {
p := gopacket.NewPacket(testPacketPacket0, LinkTypeRaw, gopacket.Default)
if p.ErrorLayer() != nil {
t.Error("Failed to decode packet:", p.ErrorLayer().Error())
}
checkLayers(p, []gopacket.LayerType{LayerTypeRaw, LayerTypeIPv4, LayerTypeICMPv4, gopacket.LayerTypePayload}, t)
// If ICMPv4 is found we most likely parse at the right offset. Skip detailed tests. Just verify
// that the Contents of the BaseLayer is an empty array
if got, ok := p.Layer(LayerTypeRaw).(*Raw); ok {
if len(got.BaseLayer.Contents) != 0 {
t.Error("RAW layer not empty", len(got.BaseLayer.Contents))
}
} else {
t.Error("RAW packet processing failed to get right layer")
}
}
func BenchmarkDecodePacketRawIPICMPv4(b *testing.B) {
for i := 0; i < b.N; i++ {
gopacket.NewPacket(testPacketPacket0, LinkTypeRaw, gopacket.NoCopy)
}
}