From 5262237c3b6b8dcfd01851ad05de7a20067fcc18 Mon Sep 17 00:00:00 2001 From: Ryan Denniston Date: Fri, 18 Jan 2019 13:50:22 -0800 Subject: [PATCH] Add linux netfilter NFLOG capture functionality initial commit modified GetLinkHeaderSize to support link type modified ProcessLayer2 to support NFLOG packets expecting out of the box support from libpcap hacking my way around bpf, bpf is not supported in libpcap (would be easy to implement) but at the moment, throw a warn if applying a filter and short circuit bpf code. want to ensure this works... commenting out error states. Fixed SetFilter to properly detect m_matches_anything, which is used by the DLT_NFLOG type to short circuit bpf filters. Added NFLOG parsing to zeek source, added m_matches_anything flag check for bpf functionality (NFLOG is bpf incompatible, but shouldn't be) --- src/iosource/BPF_Program.cc | 7 ++++++ src/iosource/Packet.cc | 44 +++++++++++++++++++++++++++++++++++++ src/iosource/pcap/Source.cc | 5 +++++ 3 files changed, 56 insertions(+) diff --git a/src/iosource/BPF_Program.cc b/src/iosource/BPF_Program.cc index 451a74bed3..e284720fad 100644 --- a/src/iosource/BPF_Program.cc +++ b/src/iosource/BPF_Program.cc @@ -104,6 +104,13 @@ bool BPF_Program::Compile(int snaplen, int linktype, const char* filter, { FreeCode(); + if ( linktype == DLT_NFLOG ) //hacky way to support nflog but not bpf + { + m_compiled = true; + m_matches_anything = true; + return true; + } + #ifdef LIBPCAP_PCAP_COMPILE_NOPCAP_HAS_ERROR_PARAMETER char my_error[PCAP_ERRBUF_SIZE]; diff --git a/src/iosource/Packet.cc b/src/iosource/Packet.cc index a5c2622ecf..99f1017bdc 100644 --- a/src/iosource/Packet.cc +++ b/src/iosource/Packet.cc @@ -92,6 +92,9 @@ int Packet::GetLinkHeaderSize(int link_type) case DLT_IEEE802_11_RADIO: // 802.11 plus RadioTap return 59; + case DLT_NFLOG: //Linux netlink NETLINK NFLOG socket log messages + return 8; //base l2 header up to TLV values + case DLT_RAW: return 0; } @@ -395,6 +398,47 @@ void Packet::ProcessLayer2() break; } + case DLT_NFLOG: + { + + int protocol = pdata[0]; //https://www.tcpdump.org/linktypes/LINKTYPE_NFLOG.html + if ( protocol == AF_INET ) + l3_proto = L3_IPV4; + else if ( protocol == AF_INET6 ) + l3_proto = L3_IPV6; + //skip header to tlv structs + pdata += 4; + + int tlv_len; + int tlv_type; + + while(1){ + if ( pdata >= end_of_data ) + { + Weird("nflog_no_pcap_payload"); + return; + } + + tlv_len = (pdata[1] << 8 )+ pdata[0]; //lil' endian + tlv_type = (pdata[3] << 8) + pdata[2]; + + //tlv's are in groups of 8 bytes min padding apparently + if (tlv_len < 8){ + tlv_len = 8; + } + //if 9, then raw packet is straight away after. + if (tlv_type == 9){ //type nflog payload + pdata += 4; //skip the tlv type and length to put the payload at the front of the buffer. + break; + }else{ + pdata += tlv_len; + } + + } + break; + + } + default: { // Assume we're pointing at IP. Just figure out which version. diff --git a/src/iosource/pcap/Source.cc b/src/iosource/pcap/Source.cc index 0a0633ece0..ac4e801ae3 100644 --- a/src/iosource/pcap/Source.cc +++ b/src/iosource/pcap/Source.cc @@ -247,6 +247,11 @@ bool PcapSource::SetFilter(int index) return false; } + //if the filter matches anything, return true + if ( code->MatchesAnything() ) + { + return true; + } if ( pcap_setfilter(pd, code->GetProgram()) < 0 ) { PcapError();