Skip to content

Stop using String names for LinkLayer/DLT types #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 12, 2021
Merged
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
58 changes: 58 additions & 0 deletions cmd/dlt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package main

import (
"runtime"

"github.com/google/gopacket/layers"
)

/*
* These are not defined as layers.LinkType values, but ARE defined as
* layers for decoding purposes: https://github.com/google/gopacket/blob/master/layers/enums.go#L378
*
* But only one of these are actually valid at runtime based on your OS.
* More context: https://www.tcpdump.org/linktypes.html
*
* Anyways, the RAW values per libpcap's pcap/dlt.h should be 12 or 14
* based on your OS and nothing should have a value of 101. No idea what
* the gopacket people were thinking.
*/
const (
LinkTypeRawOpenBSD layers.LinkType = 14 // Raw DLT on OpenBSD
LinkTypeRawOthers layers.LinkType = 12 // Raw DLT everywhere else
)

// Returns if the provided layertype is valid
func isValidLayerType(layertype layers.LinkType) bool {
/*
* List of Data Link Types (DLT) we support in sendPacket()
* not to be confused with LINKTYPE_ values which are mostly, but not always
* compatible: https://www.tcpdump.org/linktypes.html
*
* Specifically, DLT_RAW is 12 or 14 depending on your OS, but
* LinkTypeRaw is 101 which causes lots of problems. :-/
*/
var validLinkTypes = []layers.LinkType{
layers.LinkTypeLoop,
layers.LinkTypeEthernet,
layers.LinkTypeNull,
layers.LinkTypeRaw,
}

// Look for standardized values
for _, b := range validLinkTypes {
if layertype == b {
return true
}
}

// Look for Raw value based on our running OS due to above mentioned issue
if runtime.GOOS == "openbsd" && layertype == LinkTypeRawOpenBSD {
return true
}
if runtime.GOOS != "openbsd" && layertype == LinkTypeRawOthers {
return true
}

return false
}
57 changes: 57 additions & 0 deletions cmd/dlt_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package main

import (
"github.com/google/gopacket/layers"
"runtime"
"testing"
)

func TestIsValidLayerType(t *testing.T) {
// These are valid
if !isValidLayerType(layers.LinkTypeEthernet) {
t.Errorf("Expected that Ethernet was valid")
}
// Test all the Raw types because they are special
if !isValidLayerType(layers.LinkTypeRaw) {
t.Errorf("Expected that Raw was valid")
}

if runtime.GOOS == "openbsd" {
if !isValidLayerType(LinkTypeRawOpenBSD) {
t.Errorf("Expected that LinkTypeRawOpenBSD was valid")
}
if isValidLayerType(LinkTypeRawOthers) {
t.Errorf("Expected that LinkTypeRawOthers was invalid")
}
} else {
if !isValidLayerType(LinkTypeRawOthers) {
t.Errorf("Expected that LinkTypeRawOthers was valid")
}
if isValidLayerType(LinkTypeRawOpenBSD) {
t.Errorf("Expected that LinkTypeRawOpenBSD was invalid")
}
}

// not valid
if isValidLayerType(layers.LinkTypeLinuxSLL) {
t.Errorf("Did not expect that Linux SLL was valid")
}
}

func TestLayerTypeRaw(t *testing.T) {
if runtime.GOOS == "openbsd" {
if LinkTypeRawOpenBSD.String() != "Raw" {
t.Errorf("RawOpenBSD should be known as 'Raw': %s", LinkTypeRawOpenBSD.String())
}
if LinkTypeRawOthers.String() == "Raw" {
t.Errorf("RawOthers should not be known as 'Raw': %s", LinkTypeRawOthers.String())
}
} else {
if LinkTypeRawOthers.String() != "Raw" {
t.Errorf("RawOthers should be known as 'Raw': %s", LinkTypeRawOthers.String())
}
if LinkTypeRawOpenBSD.String() == "Raw" {
t.Errorf("RawOpenBSD should not be known as 'Raw': %s", LinkTypeRawOpenBSD.String())
}
}
}
3 changes: 2 additions & 1 deletion cmd/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ func initializeInterface(l *Listen) {
}

if !isValidLayerType(l.handle.LinkType()) {
log.Fatalf("%s: has an invalid layer type: %s", l.iname, l.handle.LinkType().String())
log.Fatalf("%s: has an invalid layer type: %s [%d]",
l.iname, l.handle.LinkType().String(), l.handle.LinkType())
}

// set our BPF filter
Expand Down
52 changes: 18 additions & 34 deletions cmd/listen.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"encoding/binary"
"encoding/hex"
"net"
"strings"
"sync"
"time"

Expand All @@ -30,14 +29,6 @@ type Listen struct {
clients map[string]time.Time // keep track of clients for non-promisc interfaces
}

// List of LayerTypes we support in sendPacket()
var validLinkTypes = []layers.LinkType{
layers.LinkTypeLoop,
layers.LinkTypeEthernet,
layers.LinkTypeNull,
layers.LinkTypeRaw,
}

// Creates a Listen struct for the given interface, promisc mode, udp sniff ports and timeout
func newListener(netif *net.Interface, promisc bool, ports []int32, to time.Duration, fixed_ip []string) Listen {
log.Debugf("%s: ifIndex: %d", netif.Name, netif.Index)
Expand Down Expand Up @@ -152,15 +143,16 @@ func (l *Listen) sendPackets(sndpkt Send) {

log.Debugf("processing packet from %s on %s", sndpkt.srcif, l.iname)

switch sndpkt.linkType.String() {
case layers.LinkTypeNull.String(), layers.LinkTypeLoop.String():
switch sndpkt.linkType {
case layers.LinkTypeNull, layers.LinkTypeLoop:
parser = gopacket.NewDecodingLayerParser(layers.LayerTypeLoopback, &loop, &ip4, &udp, &payload)
case layers.LinkTypeEthernet.String():
case layers.LinkTypeEthernet:
parser = gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, &eth, &ip4, &udp, &payload)
case layers.LinkTypeRaw.String():
case layers.LinkTypeRaw, LinkTypeRawOthers, LinkTypeRawOpenBSD:
parser = gopacket.NewDecodingLayerParser(layers.LayerTypeIPv4, &ip4, &udp, &payload)
default:
log.Fatalf("Unsupported source linktype: %s", sndpkt.linkType.String())
log.Fatalf("Unsupported source linktype: %s [%d]",
sndpkt.linkType.String(), sndpkt.linkType)
}

// try decoding our packet
Expand Down Expand Up @@ -261,15 +253,15 @@ func (l *Listen) sendPacket(dstip net.IP, eth layers.Ethernet, loop layers.Loopb
}

// Add our L2 header to the buffer
switch l.handle.LinkType().String() {
case layers.LinkTypeNull.String(), layers.LinkTypeLoop.String():
switch l.handle.LinkType() {
case layers.LinkTypeNull, layers.LinkTypeLoop:
loop := layers.Loopback{
Family: layers.ProtocolFamilyIPv4,
}
if err := loop.SerializeTo(buffer, opts); err != nil {
log.Fatalf("can't serialize Loop header: %v", loop)
}
case layers.LinkTypeEthernet.String():
case layers.LinkTypeEthernet:
// build a new ethernet header
new_eth := layers.Ethernet{
BaseLayer: layers.BaseLayer{},
Expand All @@ -280,10 +272,11 @@ func (l *Listen) sendPacket(dstip net.IP, eth layers.Ethernet, loop layers.Loopb
if err := new_eth.SerializeTo(buffer, opts); err != nil {
log.Fatalf("can't serialize Eth header: %v", new_eth)
}
case layers.LinkTypeRaw.String():
case layers.LinkTypeRaw, LinkTypeRawOthers, LinkTypeRawOpenBSD:
// no L2 header
default:
log.Warnf("Unsupported linktype: %s", l.handle.LinkType().String())
log.Warnf("Unsupported linktype: %s [%d]",
l.handle.LinkType().String(), l.handle.LinkType())
}

outgoingPacket := buffer.Bytes()
Expand All @@ -300,15 +293,16 @@ func (l *Listen) learnClientIP(packet gopacket.Packet) {
var payload gopacket.Payload
var parser *gopacket.DecodingLayerParser

switch l.handle.LinkType().String() {
case layers.LinkTypeNull.String(), layers.LinkTypeLoop.String():
switch l.handle.LinkType() {
case layers.LinkTypeNull, layers.LinkTypeLoop:
parser = gopacket.NewDecodingLayerParser(layers.LayerTypeLoopback, &loop, &ip4, &udp, &payload)
case layers.LinkTypeEthernet.String():
case layers.LinkTypeEthernet:
parser = gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, &eth, &ip4, &udp, &payload)
case layers.LinkTypeRaw.String():
case layers.LinkTypeRaw, LinkTypeRawOthers, LinkTypeRawOpenBSD:
parser = gopacket.NewDecodingLayerParser(layers.LayerTypeIPv4, &ip4, &udp, &payload)
default:
log.Fatalf("Unsupported source linktype: %s", l.handle.LinkType().String())
log.Fatalf("Unsupported source linktype: %s [%d]",
l.handle.LinkType().String(), l.handle.LinkType())
}

decoded := []gopacket.LayerType{}
Expand All @@ -333,13 +327,3 @@ func (l *Listen) learnClientIP(packet gopacket.Packet) {
}
}
}

// Returns if the provided layertype is valid
func isValidLayerType(layertype layers.LinkType) bool {
for _, b := range validLinkTypes {
if strings.Compare(b.String(), layertype.String()) == 0 {
return true
}
}
return false
}