From: Michael Altizer (mialtize) Date: Mon, 8 Mar 2021 21:44:27 +0000 (+0000) Subject: Merge pull request #2744 in SNORT/snort3 from ~MIALTIZE/snort3:mpls to master X-Git-Tag: 3.1.2.0~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f0d2f2b7ecb245dbd5820ebfc0eea8f0efabeaab;p=thirdparty%2Fsnort3.git Merge pull request #2744 in SNORT/snort3 from ~MIALTIZE/snort3:mpls to master Squashed commit of the following: commit ee516377468dd17dfb4b1ff370d3912c96b29274 Author: Michael Altizer Date: Thu Feb 25 16:38:35 2021 -0500 mpls: Add next layer autodetection and implement codec logging The max_mpls_stack_depth and mpls_payload_type parameters of the MPLS codec module have been renamed to max_stack_depth and payload_type respectively to cut down on redundancy. The EXP field in the MPLS header has been renamed to TC (traffic class) per RFC5462. Previously available MPLS counters have been removed due to being both inaccurate and not very valuable. commit c007bb268c0f94038e07646eb047f2f0659165a5 Author: Michael Altizer Date: Thu Feb 25 16:38:35 2021 -0500 mpls: Refactor mpls.enable_mpls_overlapping_ip into packet.mpls_agnostic commit c00686eb8b98ccca8ca61cbd3517733ffe64802a Author: Michael Altizer Date: Thu Feb 25 16:38:35 2021 -0500 mpls: Remove enable_mpls_multicast option The option was unused and MPLS multicast support is now always enabled. commit 8b4edf540f2ac597e954b6edaace9e506d0d603a Author: Michael Altizer Date: Thu Feb 25 16:38:35 2021 -0500 loggers: Fix excessive byte reordering when printing MPLS labels in CSV and JSON commit ec4488602cf3e45ed4b5f7385f7acd9099078205 Author: Michael Altizer Date: Thu Feb 25 16:38:35 2021 -0500 trans_bridge: Lift the log() implementation from the root Ethernet codec --- diff --git a/src/codecs/link/cd_mpls.cc b/src/codecs/link/cd_mpls.cc index b31ef2a1d..22a0c97ba 100644 --- a/src/codecs/link/cd_mpls.cc +++ b/src/codecs/link/cd_mpls.cc @@ -16,7 +16,7 @@ // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. //-------------------------------------------------------------------------- -// cd_mpls.cc author Josh Rosenbaum +// cd_mpls.cc author Michael Altizer #ifdef HAVE_CONFIG_H #include "config.h" @@ -25,6 +25,7 @@ #include "codecs/codec_module.h" #include "flow/flow.h" #include "framework/codec.h" +#include "log/text_log.h" #include "main/snort_config.h" #include "utils/safec.h" @@ -35,19 +36,22 @@ using namespace snort; namespace { -static const Parameter mpls_params[] = +enum MplsPayloadType : uint8_t { - { "enable_mpls_multicast", Parameter::PT_BOOL, nullptr, "false", - "enables support for MPLS multicast" }, - - { "enable_mpls_overlapping_ip", Parameter::PT_BOOL, nullptr, "false", - "enable if private network addresses overlap and must be differentiated by MPLS label(s)" }, + // Entries must align with mpls_payload_type enum parameter in mpls_params + MPLS_PAYLOADTYPE_AUTODETECT = 0, + MPLS_PAYLOADTYPE_ETHERNET, + MPLS_PAYLOADTYPE_IPV4, + MPLS_PAYLOADTYPE_IPV6 +}; - { "max_mpls_stack_depth", Parameter::PT_INT, "-1:255", "-1", - "set MPLS stack depth" }, +static const Parameter mpls_params[] = +{ + { "max_stack_depth", Parameter::PT_INT, "-1:255", "-1", + "set maximum MPLS stack depth" }, - { "mpls_payload_type", Parameter::PT_ENUM, "eth | ip4 | ip6", "ip4", - "set encapsulated payload type" }, + { "payload_type", Parameter::PT_ENUM, "auto | eth | ip4 | ip6", "auto", + "force encapsulated payload type" }, { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } }; @@ -55,29 +59,21 @@ static const Parameter mpls_params[] = static const RuleMap mpls_rules[] = { { DECODE_BAD_MPLS, "bad MPLS frame" }, - { DECODE_BAD_MPLS_LABEL0, "MPLS label 0 appears in non-bottom header" }, + { DECODE_BAD_MPLS_LABEL0, "MPLS label 0 appears in bottom header when not decoding as ip4" }, { DECODE_BAD_MPLS_LABEL1, "MPLS label 1 appears in bottom header" }, - { DECODE_BAD_MPLS_LABEL2, "MPLS label 2 appears in non-bottom header" }, + { DECODE_BAD_MPLS_LABEL2, "MPLS label 2 appears in bottom header when not decoding as ip6" }, { DECODE_BAD_MPLS_LABEL3, "MPLS label 3 appears in header" }, { DECODE_MPLS_RESERVED_LABEL, "MPLS label 4, 5,.. or 15 appears in header" }, { DECODE_MPLS_LABEL_STACK, "too many MPLS headers" }, { 0, nullptr } }; -static const PegInfo mpls_pegs[] = +struct MplsCodecConfig { - { CountType::SUM, "total_packets", "total mpls labeled packets processed" }, - { CountType::SUM, "total_bytes", "total mpls labeled bytes processed" }, - { CountType::END, nullptr, nullptr } + int stack_depth = -1; + uint8_t payload_type = MPLS_PAYLOADTYPE_AUTODETECT; }; -struct MplsStats -{ - PegCount total_packets; - PegCount total_bytes; -}; -static THREAD_LOCAL MplsStats mpls_stats; - class MplsModule : public BaseCodecModule { public: @@ -86,44 +82,33 @@ public: const RuleMap* get_rules() const override { return mpls_rules; } - bool set(const char*, Value& v, SnortConfig* sc) override + bool begin(const char*, int, SnortConfig*) override { - if ( v.is("enable_mpls_multicast") ) - { - if ( v.get_bool() ) - sc->run_flags |= RUN_FLAG__MPLS_MULTICAST; // FIXIT-L move to existing bitfield - } - else if ( v.is("enable_mpls_overlapping_ip") ) - { - if ( v.get_bool() ) - sc->run_flags |= RUN_FLAG__MPLS_OVERLAPPING_IP; // FIXIT-L move to existing - // bitfield - } - else if ( v.is("max_mpls_stack_depth") ) - { - sc->mpls_stack_depth = v.get_int16(); - } - else if ( v.is("mpls_payload_type") ) - { - sc->mpls_payload_type = v.get_uint8() + 1; - } - else - return false; + config = { }; + return true; + } + + bool set(const char*, Value& v, SnortConfig*) override + { + if ( v.is("max_stack_depth") ) + config.stack_depth = v.get_int16(); + else if ( v.is("payload_type") ) + config.payload_type = v.get_uint8(); return true; } - const PegInfo* get_pegs() const override - { return mpls_pegs; } + const MplsCodecConfig& get_data() + { return config; } - PegCount* get_counts() const override - { return (PegCount*)&mpls_stats; } +private: + MplsCodecConfig config; }; class MplsCodec : public Codec { public: - MplsCodec() : Codec(CD_MPLS_NAME) { } + MplsCodec(const MplsCodecConfig& config = { }) : Codec(CD_MPLS_NAME), config(config) { } void get_protocol_ids(std::vector& v) override; bool decode(const RawData&, CodecData&, DecodeData&) override; @@ -132,12 +117,14 @@ public: void log(TextLog* const, const uint8_t* pkt, const uint16_t len) override; private: - int checkMplsHdr(const CodecData&, uint32_t label, uint8_t bos); + bool validate_reserved_label(const CodecData&, uint32_t label, uint8_t bos); + +private: + MplsCodecConfig config; }; constexpr int MPLS_HEADER_LEN = 4; constexpr int NUM_RESERVED_LABELS = 16; -constexpr int MPLS_PAYLOADTYPE_ERROR = -1; } // namespace void MplsCodec::get_protocol_ids(std::vector& v) @@ -147,19 +134,35 @@ void MplsCodec::get_protocol_ids(std::vector& v) v.emplace_back(ProtocolId::MPLS_IP); } +static inline void decode_mpls_entry(const uint32_t* entry, uint32_t& label, uint8_t& tc, uint8_t& bos, uint8_t& ttl) +{ + // https://tools.ietf.org/html/rfc5462 + // 0 1 2 3 + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Label + // | Label | TC |S| TTL | Stack + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Entry + // + // Label: Label Value, 20 bits + // TC: Traffic Class field, 3 bits + // S: Bottom of Stack, 1 bit + // TTL: Time to Live, 8 bits + + uint32_t mpls_h = ntohl(*entry); + ttl = (uint8_t)(mpls_h & 0x000000FF); + mpls_h = mpls_h >> 8; + bos = (uint8_t)(mpls_h & 0x00000001); + tc = (uint8_t)(mpls_h & 0x0000000E); + label = (mpls_h >> 4) & 0x000FFFFF; +} + bool MplsCodec::decode(const RawData& raw, CodecData& codec, DecodeData& snort) { uint8_t bos = 0; - uint8_t chainLen = 0; + uint8_t depth = 0; uint32_t stack_len = raw.len; - int iRet = 0; - - mpls_stats.total_packets++; - mpls_stats.total_bytes += raw.len + 4; //4 bytes for CRC - - const uint32_t* tmpMplsHdr = - reinterpret_cast(raw.data); + const uint32_t* mpls_entry = reinterpret_cast(raw.data); while (!bos) { @@ -169,79 +172,87 @@ bool MplsCodec::decode(const RawData& raw, CodecData& codec, DecodeData& snort) return false; } - uint32_t mpls_h = ntohl(*tmpMplsHdr); - uint8_t ttl = (uint8_t)(mpls_h & 0x000000FF); - mpls_h = mpls_h>>8; - bos = (uint8_t)(mpls_h & 0x00000001); - uint8_t exp = (uint8_t)(mpls_h & 0x0000000E); - uint32_t label = (mpls_h>>4) & 0x000FFFFF; + uint32_t label; + uint8_t tc; + uint8_t ttl; + + decode_mpls_entry(mpls_entry, label, tc, bos, ttl); - if ((labelmpls = &(snort.mplsHdr); - **/ + codec.proto_bits |= PROTO_BIT__MPLS; - if (!iRet) - { - iRet = codec.conf->get_mpls_payload_type(); - } } - tmpMplsHdr++; + mpls_entry++; stack_len -= MPLS_HEADER_LEN; - if ((codec.conf->get_mpls_stack_depth() != -1) && - (chainLen++ >= codec.conf->get_mpls_stack_depth())) + if ((config.stack_depth != -1) && (++depth > config.stack_depth)) { codec_event(codec, DECODE_MPLS_LABEL_STACK); codec.proto_bits &= ~PROTO_BIT__MPLS; return false; } - } /* while bos not 1, peel off more labels */ + } /* peel off labels until we find the bottom of the stack */ if (codec.conf->tunnel_bypass_enabled(TUNNEL_MPLS)) codec.tunnel_bypass = true; - codec.lyr_len = (const uint8_t*)tmpMplsHdr - raw.data; + codec.lyr_len = (const uint8_t*) mpls_entry - raw.data; - switch (iRet) - { - case MPLS_PAYLOADTYPE_IPV4: + uint8_t dplt = config.payload_type; + if (snort.mplsHdr.label == 0) codec.next_prot_id = ProtocolId::ETHERTYPE_IPV4; - break; - - case MPLS_PAYLOADTYPE_IPV6: + else if (snort.mplsHdr.label == 2) codec.next_prot_id = ProtocolId::ETHERTYPE_IPV6; - break; - - case MPLS_PAYLOADTYPE_ETHERNET: + else if (dplt == MPLS_PAYLOADTYPE_IPV4) + codec.next_prot_id = ProtocolId::ETHERTYPE_IPV4; + else if (dplt == MPLS_PAYLOADTYPE_IPV6) + codec.next_prot_id = ProtocolId::ETHERTYPE_IPV6; + else if (dplt == MPLS_PAYLOADTYPE_ETHERNET) codec.next_prot_id = ProtocolId::ETHERTYPE_TRANS_ETHER_BRIDGING; - break; - - default: - break; + else + { + // Default to first nibble autodetection + // This heuristic is obviously vulnerable to corner cases where the next layer is actually + // Ethernet and the first nibble of the destination MAC address is 4 or 6. + if (codec.lyr_len == raw.len) + return false; + uint8_t first_nibble = (*(raw.data + codec.lyr_len) >> 4) & 0x0F; + switch (first_nibble) + { + case 4: + codec.next_prot_id = ProtocolId::ETHERTYPE_IPV4; + break; + case 6: + codec.next_prot_id = ProtocolId::ETHERTYPE_IPV6; + break; + default: + codec.next_prot_id = ProtocolId::ETHERTYPE_TRANS_ETHER_BRIDGING; + break; + } } return true; } + bool MplsCodec::encode(const uint8_t* const raw_in, const uint16_t raw_len, EncState& enc, Buffer& buf, Flow* pflow) { uint16_t hdr_len = raw_len; const uint8_t* hdr_start = raw_in; - if( pflow ) + if (pflow) { Layer mpls_lyr = pflow->get_mpls_layer_per_dir(enc.forward()); - if( mpls_lyr.length ) + if (mpls_lyr.length) { hdr_len = mpls_lyr.length; hdr_start = mpls_lyr.start; @@ -262,102 +273,64 @@ bool MplsCodec::encode(const uint8_t* const raw_in, const uint16_t raw_len, /* * check if reserved labels are used properly */ -int MplsCodec::checkMplsHdr(const CodecData& codec, uint32_t label, uint8_t bos) +bool MplsCodec::validate_reserved_label(const CodecData& codec, uint32_t label, uint8_t bos) { - int iRet = 0; + uint8_t plt = config.payload_type; + switch (label) { - case 0: - case 2: - //if this label is the bottom of the stack - if (bos) - { - if ( label == 0 ) - iRet = MPLS_PAYLOADTYPE_IPV4; - else if ( label == 2 ) - iRet = MPLS_PAYLOADTYPE_IPV6; - - /* when label == 2, IPv6 is expected; - * when label == 0, IPv4 is expected */ - if ( (label && ( codec.conf->get_mpls_payload_type() != MPLS_PAYLOADTYPE_IPV6) ) - || ( (!label) && (codec.conf->get_mpls_payload_type() != MPLS_PAYLOADTYPE_IPV4))) + case 0: + // Label 0 is the "IPv4 Explicit NULL Label", which indicates encapsulated IPv4 when at BoS + // RFC 3032 removed the BoS restriction for this label + if (bos && plt && plt != MPLS_PAYLOADTYPE_IPV4) + codec_event(codec, DECODE_BAD_MPLS_LABEL0); + break; + + case 1: + // Label 1 is the "Router Alert Label", which cannot occur at the bottom of the stack + if (bos) { - if ( !label ) - codec_event(codec, DECODE_BAD_MPLS_LABEL0); - else - codec_event(codec, DECODE_BAD_MPLS_LABEL2); + codec_event(codec, DECODE_BAD_MPLS_LABEL1); + return false; } break; - } - //if bos is false we are believed to NOT be at the bottom of the stack - //and if we arent at the bottom of the stack then we should NOT see - //label 0 or 2 (according to RFC 3032) - else - { - if ( label == 0 ) - codec_event(codec, DECODE_BAD_MPLS_LABEL0); - //it MUST be label 2 - else - codec_event(codec, DECODE_BAD_MPLS_LABEL2); - } -#if 0 - /* This is valid per RFC 4182. Just pop this label off, ignore it - * and move on to the next one. - */ - if ( !label ) - codec_event(codec, DECODE_BAD_MPLS_LABEL0); - else - codec_event(codec, DECODE_BAD_MPLS_LABEL2); - - p->iph = NULL; - p->family = NO_IP; - return(-1); -#endif - break; - case 1: - if (!bos) + + case 2: + // Label 2 is the "IPv6 Explicit NULL Label", which indicates encapsulated IPv6 when at BoS + // RFC 3032 removed the BoS restriction for this label + if (bos && plt && plt != MPLS_PAYLOADTYPE_IPV6) + codec_event(codec, DECODE_BAD_MPLS_LABEL2); break; - codec_event(codec, DECODE_BAD_MPLS_LABEL1); - - iRet = MPLS_PAYLOADTYPE_ERROR; - break; - - case 3: - codec_event(codec, DECODE_BAD_MPLS_LABEL3); - - iRet = MPLS_PAYLOADTYPE_ERROR; - break; - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - codec_event(codec, DECODE_MPLS_RESERVED_LABEL); - break; - default: - break; - } - if ( !iRet ) - { - iRet = codec.conf->get_mpls_payload_type(); + case 3: + // Label 3 is the "Implicit NULL Label", which should never actually appear in a stack + codec_event(codec, DECODE_BAD_MPLS_LABEL3); + return false; + + default: + // Labels 4-15 are reserved without any current special meaning + codec_event(codec, DECODE_MPLS_RESERVED_LABEL); + break; } - return iRet; + + return true; } -void MplsCodec::log(TextLog* const /*text_log*/, const uint8_t* /*raw_pkt*/, +void MplsCodec::log(TextLog* const text_log, const uint8_t* raw_pkt, const uint16_t /*lyr_len*/) { -// FIXIT-L MPLS needs to be updated throughout Snort++ -// TextLog_Print(text_log,"label:0x%05X exp:0x%X bos:0x%X ttl:0x%X\n", -// p->ptrs.mplsHdr.label, p->ptrs.mplsHdr.exp, p->ptrs.mplsHdr.bos, p->ptrs.mplsHdr.ttl); + const uint32_t* mpls_entry = reinterpret_cast(raw_pkt); + uint8_t bos = 0; + while (!bos) + { + uint32_t label; + uint8_t tc; + uint8_t ttl; + + decode_mpls_entry(mpls_entry, label, tc, bos, ttl); + TextLog_Print(text_log, "\n\tlabel:0x%05X tc:0x%hhX bos:0x%hhX ttl:0x%hhX", label, tc, bos, ttl); + mpls_entry++; + } } //------------------------------------------------------------------------- @@ -370,8 +343,15 @@ static Module* mod_ctor() static void mod_dtor(Module* m) { delete m; } -static Codec* ctor(Module*) -{ return new MplsCodec(); } +static Codec* ctor(Module* m) +{ + if (m) + { + MplsModule* mod = (MplsModule*) m; + return new MplsCodec(mod->get_data()); + } + return new MplsCodec(); +} static void dtor(Codec* cd) { delete cd; } diff --git a/src/codecs/link/cd_trans_bridge.cc b/src/codecs/link/cd_trans_bridge.cc index 681e007c2..dc0ce4b9b 100644 --- a/src/codecs/link/cd_trans_bridge.cc +++ b/src/codecs/link/cd_trans_bridge.cc @@ -23,6 +23,7 @@ #include "codecs/codec_module.h" #include "framework/codec.h" +#include "log/log_text.h" #include "protocols/eth.h" using namespace snort; @@ -39,6 +40,7 @@ public: void get_protocol_ids(std::vector& v) override; bool decode(const RawData&, CodecData&, DecodeData&) override; + void log(TextLog* const, const uint8_t* pkt, const uint16_t len) override; }; } // anonymous namespace @@ -67,6 +69,21 @@ bool TransbridgeCodec::decode(const RawData& raw, CodecData& codec, DecodeData&) return true; } +void TransbridgeCodec::log(TextLog* const text_log, const uint8_t* raw_pkt, + const uint16_t /*len*/) +{ + const eth::EtherHdr* eh = reinterpret_cast(raw_pkt); + + LogEthAddrs(text_log, eh); + + const ProtocolId prot_id = eh->ethertype(); + + if (to_utype(prot_id) <= to_utype(ProtocolId::ETHERTYPE_MINIMUM)) + TextLog_Print(text_log, " len:0x%04X", static_cast(prot_id)); + else + TextLog_Print(text_log, " type:0x%04X", static_cast(prot_id)); +} + //------------------------------------------------------------------------- // api //------------------------------------------------------------------------- diff --git a/src/codecs/root/cd_eth.cc b/src/codecs/root/cd_eth.cc index b998654d8..5e13ffa7a 100644 --- a/src/codecs/root/cd_eth.cc +++ b/src/codecs/root/cd_eth.cc @@ -26,7 +26,7 @@ #include "codecs/codec_module.h" #include "framework/codec.h" -#include "log/text_log.h" +#include "log/log_text.h" #include "main/snort_config.h" #include "protocols/eth.h" #include "protocols/packet_manager.h" @@ -125,15 +125,7 @@ void EthCodec::log(TextLog* const text_log, const uint8_t* raw_pkt, { const eth::EtherHdr* eh = reinterpret_cast(raw_pkt); - /* src addr */ - TextLog_Print(text_log, "%02X:%02X:%02X:%02X:%02X:%02X -> ", eh->ether_src[0], - eh->ether_src[1], eh->ether_src[2], eh->ether_src[3], - eh->ether_src[4], eh->ether_src[5]); - - /* dest addr */ - TextLog_Print(text_log, "%02X:%02X:%02X:%02X:%02X:%02X", eh->ether_dst[0], - eh->ether_dst[1], eh->ether_dst[2], eh->ether_dst[3], - eh->ether_dst[4], eh->ether_dst[5]); + LogEthAddrs(text_log, eh); const ProtocolId prot_id = eh->ethertype(); diff --git a/src/flow/flow_key.cc b/src/flow/flow_key.cc index a655bf988..c1aefb484 100644 --- a/src/flow/flow_key.cc +++ b/src/flow/flow_key.cc @@ -91,11 +91,8 @@ static inline void update_icmp6(const SfIp*& srcIP, uint16_t& srcPort, //------------------------------------------------------------------------- // init foo //------------------------------------------------------------------------- -inline bool FlowKey::init4( - const SnortConfig* sc, IpProtocol ip_proto, - const SfIp *srcIP, uint16_t srcPort, - const SfIp *dstIP, uint16_t dstPort, - uint32_t mplsId, bool order) +inline bool FlowKey::init4(IpProtocol ip_proto, const SfIp *srcIP, uint16_t srcPort, + const SfIp *dstIP, uint16_t dstPort, bool order) { uint32_t src; uint32_t dst; @@ -139,20 +136,12 @@ inline bool FlowKey::init4( port_h = srcPort; reversed = true; } - if (sc->mpls_overlapping_ip() && - ip::isPrivateIP(src) && ip::isPrivateIP(dst)) - mplsLabel = mplsId; - else - mplsLabel = 0; return reversed; } -inline bool FlowKey::init6( - const SnortConfig* sc, IpProtocol ip_proto, - const SfIp *srcIP, uint16_t srcPort, - const SfIp *dstIP, uint16_t dstPort, - uint32_t mplsId, bool order) +inline bool FlowKey::init6(IpProtocol ip_proto, const SfIp *srcIP, uint16_t srcPort, + const SfIp *dstIP, uint16_t dstPort, bool order) { bool reversed = false; @@ -193,11 +182,6 @@ inline bool FlowKey::init6( reversed = true; } - if (sc->mpls_overlapping_ip()) - mplsLabel = mplsId; - else - mplsLabel = 0; - return reversed; } @@ -238,7 +222,7 @@ void FlowKey::init_groups(int16_t ingress_group, int16_t egress_group, bool rev) void FlowKey::init_mpls(const SnortConfig* sc, uint32_t mplsId) { - if (sc->mpls_overlapping_ip()) + if (!sc->get_mpls_agnostic()) mplsLabel = mplsId; else mplsLabel = 0; @@ -264,12 +248,12 @@ bool FlowKey::init( if (srcIP->is_ip4() && dstIP->is_ip4()) { version = 4; - reversed = init4(sc, ip_proto, srcIP, srcPort, dstIP, dstPort, mplsId); + reversed = init4(ip_proto, srcIP, srcPort, dstIP, dstPort); } else { version = 6; - reversed = init6(sc, ip_proto, srcIP, srcPort, dstIP, dstPort, mplsId); + reversed = init6(ip_proto, srcIP, srcPort, dstIP, dstPort); } pkt_type = type; @@ -277,6 +261,7 @@ bool FlowKey::init( init_vlan(sc, vlanId); init_address_space(sc, addrSpaceId); + init_mpls(sc, mplsId); if (ingress_group == DAQ_PKTHDR_UNKNOWN or egress_group == DAQ_PKTHDR_UNKNOWN) flags.group_used = 0; @@ -308,12 +293,12 @@ bool FlowKey::init( if (srcIP->is_ip4() && dstIP->is_ip4()) { version = 4; - reversed = init4(sc, ip_proto, srcIP, srcPort, dstIP, dstPort, mplsId); + reversed = init4(ip_proto, srcIP, srcPort, dstIP, dstPort); } else { version = 6; - reversed = init6(sc, ip_proto, srcIP, srcPort, dstIP, dstPort, mplsId); + reversed = init6(ip_proto, srcIP, srcPort, dstIP, dstPort); } pkt_type = type; @@ -321,6 +306,7 @@ bool FlowKey::init( init_vlan(sc, vlanId); init_address_space(sc, pkt_hdr.address_space_id); + init_mpls(sc, mplsId); flags.group_used = ((pkt_hdr.flags & DAQ_PKT_FLAG_SIGNIFICANT_GROUPS) != 0); init_groups(pkt_hdr.ingress_group, pkt_hdr.egress_group, reversed); @@ -348,13 +334,13 @@ bool FlowKey::init( if (srcIP->is_ip4() && dstIP->is_ip4()) { version = 4; - reversed = init4(sc, ip_proto, srcIP, srcPort, dstIP, dstPort, mplsId, false); + reversed = init4(ip_proto, srcIP, srcPort, dstIP, dstPort, false); ip_protocol = (uint8_t)ip_proto; } else { version = 6; - reversed = init6(sc, ip_proto, srcIP, srcPort, dstIP, dstPort, mplsId, false); + reversed = init6(ip_proto, srcIP, srcPort, dstIP, dstPort, false); ip_protocol = 0; } @@ -362,6 +348,7 @@ bool FlowKey::init( init_vlan(sc, vlanId); init_address_space(sc, addrSpaceId); + init_mpls(sc, mplsId); if (ingress_group == DAQ_PKTHDR_UNKNOWN or egress_group == DAQ_PKTHDR_UNKNOWN) flags.group_used = 0; @@ -392,13 +379,13 @@ bool FlowKey::init( if (srcIP->is_ip4() && dstIP->is_ip4()) { version = 4; - reversed = init4(sc, ip_proto, srcIP, srcPort, dstIP, dstPort, mplsId, false); + reversed = init4(ip_proto, srcIP, srcPort, dstIP, dstPort, false); ip_protocol = (uint8_t)ip_proto; } else { version = 6; - reversed = init6(sc, ip_proto, srcIP, srcPort, dstIP, dstPort, mplsId, false); + reversed = init6(ip_proto, srcIP, srcPort, dstIP, dstPort, false); ip_protocol = 0; } @@ -406,6 +393,7 @@ bool FlowKey::init( init_vlan(sc, vlanId); init_address_space(sc, pkt_hdr.address_space_id); + init_mpls(sc, mplsId); flags.group_used = ((pkt_hdr.flags & DAQ_PKT_FLAG_SIGNIFICANT_GROUPS) != 0); init_groups(pkt_hdr.ingress_group, pkt_hdr.egress_group, reversed); diff --git a/src/flow/flow_key.h b/src/flow/flow_key.h index 3295f7d9b..f582df2d6 100644 --- a/src/flow/flow_key.h +++ b/src/flow/flow_key.h @@ -108,17 +108,11 @@ struct SO_PUBLIC FlowKey static bool is_equal(const void* k1, const void* k2, size_t); private: - bool init4( - const SnortConfig*, IpProtocol, - const snort::SfIp *srcIP, uint16_t srcPort, - const snort::SfIp *dstIP, uint16_t dstPort, - uint32_t mplsId, bool order = true); + bool init4(IpProtocol, const snort::SfIp *srcIP, uint16_t srcPort, + const snort::SfIp *dstIP, uint16_t dstPort, bool order = true); - bool init6( - const SnortConfig*, IpProtocol, - const snort::SfIp *srcIP, uint16_t srcPort, - const snort::SfIp *dstIP, uint16_t dstPort, - uint32_t mplsId, bool order = true); + bool init6(IpProtocol, const snort::SfIp *srcIP, uint16_t srcPort, + const snort::SfIp *dstIP, uint16_t dstPort, bool order = true); }; PADDING_GUARD_END diff --git a/src/log/log_text.cc b/src/log/log_text.cc index f11659830..9ff4c4ac4 100644 --- a/src/log/log_text.cc +++ b/src/log/log_text.cc @@ -104,29 +104,30 @@ bool LogAppID(TextLog* log, Packet* p) *-------------------------------------------------------------------- */ +void LogEthAddrs(TextLog* log, const eth::EtherHdr* eh) +{ + TextLog_Print(log, "%02X:%02X:%02X:%02X:%02X:%02X -> %02X:%02X:%02X:%02X:%02X:%02X", + eh->ether_src[0], eh->ether_src[1], eh->ether_src[2], eh->ether_src[3], + eh->ether_src[4], eh->ether_src[5], eh->ether_dst[0], eh->ether_dst[1], + eh->ether_dst[2], eh->ether_dst[3], eh->ether_dst[4], eh->ether_dst[5]); +} + static void LogEthHeader(TextLog* log, Packet* p) { const eth::EtherHdr* eh = layer::get_eth_layer(p); - /* src addr */ - TextLog_Print(log, "%02X:%02X:%02X:%02X:%02X:%02X -> ", eh->ether_src[0], - eh->ether_src[1], eh->ether_src[2], eh->ether_src[3], - eh->ether_src[4], eh->ether_src[5]); - - /* dest addr */ - TextLog_Print(log, "%02X:%02X:%02X:%02X:%02X:%02X ", eh->ether_dst[0], - eh->ether_dst[1], eh->ether_dst[2], eh->ether_dst[3], - eh->ether_dst[4], eh->ether_dst[5]); + /* src and dst addrs */ + LogEthAddrs(log, eh); /* protocol and pkt size */ - TextLog_Print(log, "type:0x%X len:0x%X\n", ntohs(eh->ether_type), + TextLog_Print(log, " type:0x%X len:0x%X\n", ntohs(eh->ether_type), p->pkth->pktlen); } static void LogMPLSHeader(TextLog* log, Packet* p) { - TextLog_Print(log,"label:0x%05X exp:0x%X bos:0x%X ttl:0x%X\n", - p->ptrs.mplsHdr.label, p->ptrs.mplsHdr.exp, p->ptrs.mplsHdr.bos, p->ptrs.mplsHdr.ttl); + TextLog_Print(log,"label:0x%05X tc:0x%X bos:0x%X ttl:0x%X\n", + p->ptrs.mplsHdr.label, p->ptrs.mplsHdr.tc, p->ptrs.mplsHdr.bos, p->ptrs.mplsHdr.ttl); } static void LogGREHeader(TextLog* log, Packet* p) diff --git a/src/log/log_text.h b/src/log/log_text.h index 6a887640a..dd94412ee 100644 --- a/src/log/log_text.h +++ b/src/log/log_text.h @@ -31,6 +31,7 @@ struct Event; namespace snort { struct Packet; +namespace eth { struct EtherHdr; } namespace ip { struct IP4Hdr; } namespace tcp { struct TCPHdr; } @@ -51,6 +52,7 @@ SO_PUBLIC void LogTCPHeader(TextLog*, Packet*); SO_PUBLIC void LogUDPHeader(TextLog*, Packet*); SO_PUBLIC void LogICMPHeader(TextLog*, Packet*); +SO_PUBLIC void LogEthAddrs(TextLog*, const eth::EtherHdr*); SO_PUBLIC void LogIpAddrs(TextLog*, Packet*); SO_PUBLIC void LogIPHeader(TextLog*, Packet*); diff --git a/src/loggers/alert_csv.cc b/src/loggers/alert_csv.cc index 1fbd519a6..1172f41d7 100644 --- a/src/loggers/alert_csv.cc +++ b/src/loggers/alert_csv.cc @@ -274,7 +274,7 @@ static void ff_mpls(const Args& a) else return; - TextLog_Print(csv_log, "%u", ntohl(mpls)); + TextLog_Print(csv_log, "%u", mpls); } static void ff_pkt_gen(const Args& a) diff --git a/src/loggers/alert_json.cc b/src/loggers/alert_json.cc index 1f76b13b9..0b578abd2 100644 --- a/src/loggers/alert_json.cc +++ b/src/loggers/alert_json.cc @@ -369,7 +369,7 @@ static bool ff_mpls(const Args& a) return false; print_label(a, "mpls"); - TextLog_Print(json_log, "%u", ntohl(mpls)); + TextLog_Print(json_log, "%u", mpls); return true; } diff --git a/src/main/modules.cc b/src/main/modules.cc index 501ff29b0..db0f0c82e 100644 --- a/src/main/modules.cc +++ b/src/main/modules.cc @@ -907,8 +907,11 @@ static const Parameter packets_params[] = { "skip", Parameter::PT_INT, "0:max53", "0", "number of packets to skip before before processing" }, + { "mpls_agnostic", Parameter::PT_BOOL, nullptr, "true", + "determines whether MPLS labels are used to track fragments and connections" }, + { "vlan_agnostic", Parameter::PT_BOOL, nullptr, "false", - "determines whether VLAN info is used to track fragments and connections" }, + "determines whether VLAN tags are used to track fragments and connections" }, { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } }; @@ -929,7 +932,7 @@ public: bool PacketsModule::set(const char*, Value& v, SnortConfig* sc) { if ( v.is("address_space_agnostic") ) - sc->addressspace_agnostic = v.get_bool(); + sc->asid_agnostic = v.get_bool(); else if ( v.is("bpf_file") ) sc->bpf_file = v.get_string(); @@ -937,15 +940,15 @@ bool PacketsModule::set(const char*, Value& v, SnortConfig* sc) else if ( v.is("limit") ) sc->pkt_cnt = v.get_uint64(); + else if ( v.is("mpls_agnostic") ) + sc->mpls_agnostic = v.get_bool(); + else if ( v.is("skip") ) sc->pkt_skip = v.get_uint64(); else if ( v.is("vlan_agnostic") ) sc->vlan_agnostic = v.get_bool(); - else - return false; - return true; } diff --git a/src/main/snort_config.cc b/src/main/snort_config.cc index 6cba980bd..3b2fbfb05 100644 --- a/src/main/snort_config.cc +++ b/src/main/snort_config.cc @@ -163,7 +163,6 @@ void SnortConfig::init(const SnortConfig* const other_conf, ProtocolReference* p max_attribute_services_per_host = DEFAULT_MAX_ATTRIBUTE_SERVICES_PER_HOST; max_metadata_services = DEFAULT_MAX_METADATA_SERVICES; - mpls_stack_depth = DEFAULT_LABELCHAIN_LENGTH; daq_config = new SFDAQConfig(); ActionManager::new_config(this); @@ -434,20 +433,6 @@ void SnortConfig::merge(SnortConfig* cmd_line) daq_config->overlay(cmd_line->daq_config); - if (cmd_line->mpls_stack_depth != DEFAULT_LABELCHAIN_LENGTH) - mpls_stack_depth = cmd_line->mpls_stack_depth; - - /* Set MPLS payload type here if it hasn't been defined */ - if ((cmd_line->mpls_payload_type == 0) && - (mpls_payload_type == 0)) - { - mpls_payload_type = DEFAULT_MPLS_PAYLOADTYPE; - } - else if (cmd_line->mpls_payload_type != 0) - { - mpls_payload_type = cmd_line->mpls_payload_type; - } - if (cmd_line->run_flags & RUN_FLAG__PROCESS_ALL_EVENTS) event_queue_config->process_all_events = 1; diff --git a/src/main/snort_config.h b/src/main/snort_config.h index f9d121e40..efa834503 100644 --- a/src/main/snort_config.h +++ b/src/main/snort_config.h @@ -52,33 +52,31 @@ enum RunFlag RUN_FLAG__ALERT_BEFORE_PASS = 0x00000100, RUN_FLAG__CONF_ERROR_OUT = 0x00000200, - RUN_FLAG__MPLS_MULTICAST = 0x00000400, - RUN_FLAG__MPLS_OVERLAPPING_IP = 0x00000800, + RUN_FLAG__PROCESS_ALL_EVENTS = 0x00000400, + RUN_FLAG__INLINE_TEST = 0x00000800, - RUN_FLAG__PROCESS_ALL_EVENTS = 0x00001000, - RUN_FLAG__INLINE_TEST = 0x00002000, - RUN_FLAG__PCAP_SHOW = 0x00004000, - RUN_FLAG__SHOW_FILE_CODES = 0x00008000, + RUN_FLAG__PCAP_SHOW = 0x00001000, + RUN_FLAG__SHOW_FILE_CODES = 0x00002000, + RUN_FLAG__PAUSE = 0x00004000, + RUN_FLAG__NO_PCRE = 0x00008000, - RUN_FLAG__PAUSE = 0x00010000, - RUN_FLAG__NO_PCRE = 0x00020000, /* If stream is configured, the STATEFUL flag is set. This is * somewhat misnamed and is used to assure a session is established */ - RUN_FLAG__ASSURE_EST = 0x00040000, - RUN_FLAG__DUMP_RULE_DEPS = 0x00080000, + RUN_FLAG__ASSURE_EST = 0x00010000, + RUN_FLAG__DUMP_RULE_DEPS = 0x00020000, + RUN_FLAG__TEST = 0x00040000, + RUN_FLAG__MEM_CHECK = 0x00080000, + + RUN_FLAG__TRACK_ON_SYN = 0x00100000, + RUN_FLAG__IP_FRAGS_ONLY = 0x00200000, + RUN_FLAG__DUMP_RULE_STATE = 0x00400000, - RUN_FLAG__TEST = 0x00100000, #ifdef SHELL - RUN_FLAG__SHELL = 0x00200000, + RUN_FLAG__SHELL = 0x00800000, #endif #ifdef PIGLET - RUN_FLAG__PIGLET = 0x00400000, + RUN_FLAG__PIGLET = 0x01000000, #endif - RUN_FLAG__MEM_CHECK = 0x00800000, - - RUN_FLAG__TRACK_ON_SYN = 0x01000000, - RUN_FLAG__IP_FRAGS_ONLY = 0x02000000, - RUN_FLAG__DUMP_RULE_STATE = 0x04000000, }; enum OutputFlag @@ -279,9 +277,6 @@ public: //------------------------------------------------------ // decode module stuff - int mpls_stack_depth = 0; - - uint8_t mpls_payload_type = 0; uint8_t num_layers = 0; uint8_t max_ip6_extensions = 0; uint8_t max_ip_layers = 0; @@ -308,8 +303,9 @@ public: //------------------------------------------------------ // packet module stuff + bool asid_agnostic = false; + bool mpls_agnostic = true; bool vlan_agnostic = false; - bool addressspace_agnostic = false; uint64_t pkt_cnt = 0; /* -n */ uint64_t pkt_skip = 0; @@ -484,18 +480,6 @@ public: //------------------------------------------------------ // accessor methods - long int get_mpls_stack_depth() const - { return mpls_stack_depth; } - - long int get_mpls_payload_type() const - { return mpls_payload_type; } - - bool mpls_overlapping_ip() const - { return run_flags & RUN_FLAG__MPLS_OVERLAPPING_IP; } - - bool mpls_multicast() const - { return run_flags & RUN_FLAG__MPLS_MULTICAST; } - bool esp_decoding() const { return enable_esp; } @@ -658,11 +642,14 @@ public: int get_gid() const { return group_id; } + bool get_mpls_agnostic() const + { return mpls_agnostic; } + bool get_vlan_agnostic() const { return vlan_agnostic; } bool address_space_agnostic() const - { return addressspace_agnostic; } + { return asid_agnostic; } bool change_privileges() const { return user_id != -1 || group_id != -1 || !chroot_dir.empty(); } diff --git a/src/protocols/mpls.h b/src/protocols/mpls.h index f46a2a018..8bdfcc453 100644 --- a/src/protocols/mpls.h +++ b/src/protocols/mpls.h @@ -29,16 +29,11 @@ namespace mpls struct MplsHdr { uint32_t label; - uint8_t exp; + uint8_t tc; uint8_t bos; uint8_t ttl; }; } // namespace mpls - -// FIXIT-L constexpr != const, they are orthogonal keywords -constexpr int MPLS_PAYLOADTYPE_ETHERNET = 1; -constexpr int MPLS_PAYLOADTYPE_IPV4 = 2; -constexpr int MPLS_PAYLOADTYPE_IPV6 = 3; } #endif diff --git a/src/protocols/packet.h b/src/protocols/packet.h index 33c4dbbb9..261590428 100644 --- a/src/protocols/packet.h +++ b/src/protocols/packet.h @@ -101,10 +101,6 @@ enum PseudoPacketType PSEUDO_PKT_MAX }; -/* default mpls flags */ -#define DEFAULT_MPLS_PAYLOADTYPE MPLS_PAYLOADTYPE_IPV4 -#define DEFAULT_LABELCHAIN_LENGTH (-1) - constexpr int32_t MAX_PORTS = 65536; constexpr uint16_t NUM_IP_PROTOS = 256; constexpr uint8_t TCP_OPTLENMAX = 40; /* (((2^4) - 1) * 4 - TCP_HEADER_LEN) */ diff --git a/tools/snort2lua/config_states/config_deleted.cc b/tools/snort2lua/config_states/config_deleted.cc index 45d9895f1..2ca66c579 100644 --- a/tools/snort2lua/config_states/config_deleted.cc +++ b/tools/snort2lua/config_states/config_deleted.cc @@ -599,4 +599,17 @@ static const ConvertMap no_promisc_api = const ConvertMap* no_promisc_map = &no_promisc_api; +/************************************************* + ************ enable_mpls_multicast ************ + *************************************************/ + +static const std::string enable_mpls_multicast = "enable_mpls_multicast"; +static const ConvertMap enable_mpls_multicast_api = +{ + enable_mpls_multicast, + deleted_ctor<& enable_mpls_multicast>, +}; + +const ConvertMap* enable_mpls_multicast_map = &enable_mpls_multicast_api; + } // namespace config diff --git a/tools/snort2lua/config_states/config_mpls_payload_type.cc b/tools/snort2lua/config_states/config_mpls_payload_type.cc index 50fb51383..d757ffb97 100644 --- a/tools/snort2lua/config_states/config_mpls_payload_type.cc +++ b/tools/snort2lua/config_states/config_mpls_payload_type.cc @@ -49,20 +49,20 @@ bool MplsPayloadType::convert(std::istringstream& data_stream) if (type == "ethernet") { table_api.add_diff_option_comment("config mpls_payload_type: ethernet", - "mpls_payload_type = eth"); - retval = table_api.add_option("mpls_payload_type", "eth"); + "payload_type = eth"); + retval = table_api.add_option("payload_type", "eth"); } else if (type == "ipv4") { table_api.add_diff_option_comment("config mpls_payload_type: ipv4", - "mpls_payload_type = ip4"); - retval = table_api.add_option("mpls_payload_type", "ip4"); + "payload_type = ip4"); + retval = table_api.add_option("payload_type", "ip4"); } else if (type == "ipv6") { table_api.add_diff_option_comment("config mpls_payload_type: ipv6", - "mpls_payload_type = ip6"); - retval = table_api.add_option("mpls_payload_type", "ip6"); + "payload_type = ip6"); + retval = table_api.add_option("payload_type", "ip6"); } else return false; diff --git a/tools/snort2lua/config_states/config_no_option.cc b/tools/snort2lua/config_states/config_no_option.cc index 901b6da7a..e73dd1aec 100644 --- a/tools/snort2lua/config_states/config_no_option.cc +++ b/tools/snort2lua/config_states/config_no_option.cc @@ -233,19 +233,6 @@ static const ConvertMap dump_payload_verbose_api = const ConvertMap* dump_payload_verbose_map = &dump_payload_verbose_api; -/************************************************* - ************ enable_mpls_multicast ************ - *************************************************/ - -static const std::string enable_mpls_multicast = "enable_mpls_multicast"; -static const ConvertMap enable_mpls_multicast_api = -{ - enable_mpls_multicast, - config_true_no_opt_ctor<& enable_mpls_multicast, & mpls> -}; - -const ConvertMap* enable_mpls_multicast_map = &enable_mpls_multicast_api; - /************************************************* ******** enable_deep_teredo_inspection ******** *************************************************/ @@ -267,10 +254,11 @@ const ConvertMap* enable_deep_teredo_inspection_map = &enable_deep_teredo_inspec *************************************************/ static const std::string enable_mpls_overlapping_ip = "enable_mpls_overlapping_ip"; +static const std::string mpls_agnostic = "mpls_agnostic"; static const ConvertMap enable_mpls_overlapping_ip_api = { enable_mpls_overlapping_ip, - config_true_no_opt_ctor<& enable_mpls_overlapping_ip, & mpls> + config_false_no_opt_ctor<& enable_mpls_overlapping_ip, & packets, & mpls_agnostic>, }; const ConvertMap* enable_mpls_overlapping_ip_map = &enable_mpls_overlapping_ip_api; diff --git a/tools/snort2lua/config_states/config_one_int_option.cc b/tools/snort2lua/config_states/config_one_int_option.cc index a80d7aca9..24ac8fcd4 100644 --- a/tools/snort2lua/config_states/config_one_int_option.cc +++ b/tools/snort2lua/config_states/config_one_int_option.cc @@ -191,13 +191,13 @@ const ConvertMap* max_metadata_services_map = &max_metadata_services_api; *************************************************/ static const std::string max_mpls_labelchain_len = "max_mpls_labelchain_len"; -static const std::string max_mpls_stack_depth = "max_mpls_stack_depth"; +static const std::string max_stack_depth = "max_stack_depth"; static const ConvertMap max_mpls_labelchain_len_api = { max_mpls_labelchain_len, config_int_ctor<&max_mpls_labelchain_len, &mpls, - &max_mpls_stack_depth, + &max_stack_depth, 255>, };