Skip to content

Instantly share code, notes, and snippets.

@Nyangawa
Created August 10, 2017 08:43
Show Gist options
  • Save Nyangawa/51e1cd42508494092b9fde21823c1e80 to your computer and use it in GitHub Desktop.
Save Nyangawa/51e1cd42508494092b9fde21823c1e80 to your computer and use it in GitHub Desktop.
NFLOG support for google/gopacket
diff --git a/layers/enums.go b/layers/enums.go
index f28bcbd..85f40e2 100644
--- a/layers/enums.go
+++ b/layers/enums.go
@@ -129,6 +129,7 @@ const (
LinkTypeLinuxUSB LinkType = 220
LinkTypeIPv4 LinkType = 228
LinkTypeIPv6 LinkType = 229
+ LinkTypeNFLOG LinkType = 239
)
// PPPoECode is the PPPoE code enum, taken from http://tools.ietf.org/html/rfc2516
@@ -505,6 +506,7 @@ func init() {
LinkTypeMetadata[LinkTypeLinuxUSB] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeUSB), Name: "USB"}
LinkTypeMetadata[LinkTypeLinuxSLL] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeLinuxSLL), Name: "Linux SLL"}
LinkTypeMetadata[LinkTypePrismHeader] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodePrismHeader), Name: "Prism"}
+ LinkTypeMetadata[LinkTypeNFLOG] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeNFLOG), Name: "NFLOG"}
FDDIFrameControlMetadata[FDDIFrameControlLLC] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeLLC), Name: "LLC"}
diff --git a/layers/layertypes.go b/layers/layertypes.go
index 9b50b37..d03fbd7 100644
--- a/layers/layertypes.go
+++ b/layers/layertypes.go
@@ -122,6 +122,7 @@ var (
LayerTypeDHCPv4 = gopacket.RegisterLayerType(118, gopacket.LayerTypeMetadata{Name: "DHCPv4", Decoder: gopacket.DecodeFunc(decodeDHCPv4)})
LayerTypeVRRP = gopacket.RegisterLayerType(119, gopacket.LayerTypeMetadata{Name: "VRRP", Decoder: gopacket.DecodeFunc(decodeVRRP)})
LayerTypeGeneve = gopacket.RegisterLayerType(120, gopacket.LayerTypeMetadata{Name: "Geneve", Decoder: gopacket.DecodeFunc(decodeGeneve)})
+ LayerTypeNFLOG = gopacket.RegisterLayerType(121, gopacket.LayerTypeMetadata{Name: "NFLOG", Decoder: gopacket.DecodeFunc(decodeNFLOG)})
)
var (
diff --git a/layers/nflog.go b/layers/nflog.go
new file mode 100644
index 0000000..767ca37
--- /dev/null
+++ b/layers/nflog.go
@@ -0,0 +1,121 @@
+package layers
+
+import (
+ "encoding/binary"
+ "fmt"
+ "net"
+
+ "github.com/google/gopacket"
+)
+
+type NFLOG struct {
+ BaseLayer
+ AF uint8
+ Version uint8
+ ResourceID uint16
+ HardwareProtocol uint16
+ NetfilterHook uint8
+ Seconds uint64
+ Microseconds uint64
+ AddressLength uint16
+ Address net.HardwareAddr
+ Payload []byte
+}
+
+const (
+ NFULA_PACKET_HDR = 1 /* nflog_packet_hdr_t */
+ NFULA_MARK = 2 /* packet mark from skbuff */
+ NFULA_TIMESTAMP = 3 /* nflog_timestamp_t for skbuff's time stamp */
+ NFULA_IFINDEX_INDEV = 4 /* ifindex of device on which packet received (possibly bridge group) */
+ NFULA_IFINDEX_OUTDEV = 5 /* ifindex of device on which packet transmitted (possibly bridge group) */
+ NFULA_IFINDEX_PHYSINDEV = 6 /* ifindex of physical device on which packet received (not bridge group) */
+ NFULA_IFINDEX_PHYSOUTDEV = 7 /* ifindex of physical device on which packet transmitted (not bridge group) */
+ NFULA_HWADDR = 8 /* nflog_hwaddr_t for hardware address */
+ NFULA_PAYLOAD = 9 /* packet payload */
+ NFULA_PREFIX = 10 /* text string - null-terminated, count includes NUL */
+ NFULA_UID = 11 /* UID owning socket on which packet was sent/received */
+ NFULA_SEQ = 12 /* sequence number of packets on this NFLOG socket */
+ NFULA_SEQ_GLOBAL = 13 /* sequence number of pakets on all NFLOG sockets */
+ NFULA_GID = 14 /* GID owning socket on which packet was sent/received */
+ NFULA_HWTYPE = 15 /* ARPHRD_ type of skbuff's device */
+ NFULA_HWHEADER = 16 /* skbuff's MAC-layer header */
+ NFULA_HWLEN = 17 /* length of skbuff's MAC-layer header */
+)
+
+func (n *NFLOG) ReadTLV(data []byte, idx int) error {
+ for idx < len(data) {
+ tlvLength := int(binary.LittleEndian.Uint16(data[idx : idx+2]))
+ padding := (4 - tlvLength%4) % 4
+ tlvType := int(binary.LittleEndian.Uint16(data[idx+2 : idx+4]))
+ switch tlvType {
+ case NFULA_PACKET_HDR:
+ n.HardwareProtocol = binary.BigEndian.Uint16(data[idx+4 : idx+6])
+ n.NetfilterHook = uint8(data[idx+6])
+ case NFULA_MARK:
+ case NFULA_TIMESTAMP:
+ n.Seconds = binary.BigEndian.Uint64(data[idx+4 : idx+12])
+ n.Microseconds = binary.BigEndian.Uint64(data[idx+12 : idx+20])
+ case NFULA_IFINDEX_INDEV:
+ case NFULA_IFINDEX_OUTDEV:
+ case NFULA_IFINDEX_PHYSINDEV:
+ case NFULA_IFINDEX_PHYSOUTDEV:
+ case NFULA_HWADDR:
+ n.AddressLength = binary.BigEndian.Uint16(data[idx+4 : idx+6])
+ n.Address = net.HardwareAddr(data[idx+8 : idx+8+int(n.AddressLength)])
+ case NFULA_PAYLOAD:
+ n.Payload = data[idx+4 : idx+tlvLength]
+ case NFULA_PREFIX:
+ case NFULA_UID:
+ case NFULA_SEQ:
+ case NFULA_SEQ_GLOBAL:
+ case NFULA_GID:
+ case NFULA_HWTYPE:
+ case NFULA_HWHEADER:
+ case NFULA_HWLEN:
+ default:
+ return fmt.Errorf("Unexpected type: %v", tlvType)
+ }
+ idx = idx + tlvLength + padding
+ }
+ return nil
+}
+
+func (n *NFLOG) LayerType() gopacket.LayerType { return LayerTypeNFLOG }
+
+func (n *NFLOG) LinkFlow() gopacket.Flow {
+ return gopacket.NewFlow(EndpointMAC, n.Address, nil)
+}
+
+func (n *NFLOG) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
+ n.AF = uint8(data[0])
+ n.Version = uint8(data[1])
+ n.ResourceID = binary.BigEndian.Uint16(data[2:4])
+ n.ReadTLV(data, 4)
+ n.BaseLayer = BaseLayer{data, n.Payload}
+ return nil
+}
+
+func (n *NFLOG) CanDecode() gopacket.LayerClass {
+ return LayerTypeNFLOG
+}
+
+func (n *NFLOG) NextLayerType() gopacket.LayerType {
+ switch n.AF {
+ case 2:
+ return LayerTypeIPv4
+ case 10:
+ return LayerTypeIPv6
+ }
+ return gopacket.LayerTypePayload
+}
+
+func decodeNFLOG(data []byte, p gopacket.PacketBuilder) error {
+ nflog := &NFLOG{}
+ err := nflog.DecodeFromBytes(data, p)
+ p.AddLayer(nflog)
+ p.SetLinkLayer(nflog)
+ if err != nil {
+ return err
+ }
+ return p.NextDecoder(nflog.NextLayerType())
+}
@WGH-
Copy link

WGH- commented Dec 8, 2018

Any reason why you didn't submit this as a PR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment