Created
August 10, 2017 08:43
-
-
Save Nyangawa/51e1cd42508494092b9fde21823c1e80 to your computer and use it in GitHub Desktop.
NFLOG support for google/gopacket
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()) | |
+} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Any reason why you didn't submit this as a PR?