// 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 <jrosenba@cisco.com>
+// cd_mpls.cc author Michael Altizer <mialtize@cisco.com>
#ifdef HAVE_CONFIG_H
#include "config.h"
#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"
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 }
};
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:
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<ProtocolId>& v) override;
bool decode(const RawData&, CodecData&, DecodeData&) override;
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<ProtocolId>& 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<const uint32_t*>(raw.data);
+ const uint32_t* mpls_entry = reinterpret_cast<const uint32_t*>(raw.data);
while (!bos)
{
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 ((label<NUM_RESERVED_LABELS)&&((iRet = checkMplsHdr(codec, label, bos)) < 0))
+ if ((label < NUM_RESERVED_LABELS) && !validate_reserved_label(codec, label, bos))
return false;
- if ( bos )
+ if (bos)
{
snort.mplsHdr.label = label;
- snort.mplsHdr.exp = exp;
+ snort.mplsHdr.tc = tc;
snort.mplsHdr.bos = bos;
snort.mplsHdr.ttl = ttl;
- /**
- p->mpls = &(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;
/*
* 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<const uint32_t*>(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++;
+ }
}
//-------------------------------------------------------------------------
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; }
#include "codecs/codec_module.h"
#include "framework/codec.h"
+#include "log/log_text.h"
#include "protocols/eth.h"
using namespace snort;
void get_protocol_ids(std::vector<ProtocolId>& v) override;
bool decode(const RawData&, CodecData&, DecodeData&) override;
+ void log(TextLog* const, const uint8_t* pkt, const uint16_t len) override;
};
} // anonymous namespace
return true;
}
+void TransbridgeCodec::log(TextLog* const text_log, const uint8_t* raw_pkt,
+ const uint16_t /*len*/)
+{
+ const eth::EtherHdr* eh = reinterpret_cast<const eth::EtherHdr*>(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<uint16_t>(prot_id));
+ else
+ TextLog_Print(text_log, " type:0x%04X", static_cast<uint16_t>(prot_id));
+}
+
//-------------------------------------------------------------------------
// api
//-------------------------------------------------------------------------
#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"
{
const eth::EtherHdr* eh = reinterpret_cast<const eth::EtherHdr*>(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();
//-------------------------------------------------------------------------
// 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;
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;
reversed = true;
}
- if (sc->mpls_overlapping_ip())
- mplsLabel = mplsId;
- else
- mplsLabel = 0;
-
return reversed;
}
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;
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;
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;
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;
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);
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;
}
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;
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;
}
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);
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
*--------------------------------------------------------------------
*/
+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)
namespace snort
{
struct Packet;
+namespace eth { struct EtherHdr; }
namespace ip { struct IP4Hdr; }
namespace tcp { struct TCPHdr; }
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*);
else
return;
- TextLog_Print(csv_log, "%u", ntohl(mpls));
+ TextLog_Print(csv_log, "%u", mpls);
}
static void ff_pkt_gen(const Args& a)
return false;
print_label(a, "mpls");
- TextLog_Print(json_log, "%u", ntohl(mpls));
+ TextLog_Print(json_log, "%u", mpls);
return true;
}
{ "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 }
};
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();
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;
}
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);
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;
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
//------------------------------------------------------
// 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;
//------------------------------------------------------
// 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;
//------------------------------------------------------
// 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; }
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(); }
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
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) */
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
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;
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 ********
*************************************************/
*************************************************/
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;
*************************************************/
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>,
};