uricontent:"foo" --> http_uri; content:"foo"
* deleted urilen raw and norm; must use http_raw_uri and http_uri instead
* deleted unused http_encode option
-* content suboption http_* are no full option and should be place before content
+* content suboption http_* are not full option and should be place before content
* the following pcre options have been deleted: use sticky buffers instead
B, U, P, H, M, C, I, D, K, S, Y
DECODE_ERSPAN3_DGRAM_LT_HDR,
DECODE_AUTH_HDR_TRUNC,
DECODE_AUTH_HDR_BAD_LEN,
+ DECODE_TOO_MANY_LAYERS,
DECODE_INDEX_MAX
};
bool Ipv6DSTOptsCodec::update(Packet* p, Layer* lyr, uint32_t* len)
{
- if ( lyr == (p->layers + p->next_layer - 1) )
+ if ( lyr == (p->layers + p->num_layers - 1) )
*len += p->dsize;
*len += lyr->length;
return false;
}
- if (p->encapsulated)
- {
- /* discard packet - multiple GRE encapsulation */
- /* not sure if this is ever used but I am assuming it is not */
- codec_events::decoder_alert_encapsulated(p, DECODE_IP_MULTIPLE_ENCAPSULATION,
- raw_pkt, raw_len);
- return false;
- }
+ p->encapsulations++;
/* Note: Since GRE doesn't have a field to indicate header length and
* can contain a few options, we need to walk through the header to
bool Ipv6HopOptsCodec::update(Packet* p, Layer* lyr, uint32_t* len)
{
- if ( lyr == (p->layers + p->next_layer - 1) )
+ if ( lyr == (p->layers + p->num_layers - 1) )
*len += p->dsize;
*len += lyr->length;
// uint16_t orig_frag_offset;
/* lay the IP struct over the raw data */
- ipv6::IP6RawHdr* hdr = (ipv6::IP6RawHdr*)pkt;
+ const ipv6::IP6RawHdr* hdr = reinterpret_cast<const ipv6::IP6RawHdr*>(pkt);
DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "DecodeICMPEmbeddedIP6: ip header"
" starts at: %p, length is %lu\n", hdr,
return false;
}
- if (p->family != NO_IP)
+ if (p->encapsulations)
{
- if (p->encapsulated)
- {
+ if (p->encapsulations)
codec_events::decoder_alert_encapsulated(p, DECODE_IP_MULTIPLE_ENCAPSULATION,
raw_pkt, raw_len);
- return false;
- }
- else
- {
- p->encapsulated = 1;
- p->outer_iph = p->iph;
- p->outer_ip_data = p->ip_data;
- p->outer_ip_dsize = p->ip_dsize;
- }
+
+ p->encapsulations++;
+ p->outer_iph = p->iph;
+ p->outer_ip_data = p->ip_data;
+ p->outer_ip_dsize = p->ip_dsize;
+
}
/* lay the IP struct over the raw data */
* Zero these options so they aren't associated with this inner IP
* since p->iph will be pointing to this inner IP
*/
- if (p->encapsulated)
+ if (p->encapsulations)
{
p->ip_options_data = NULL;
p->ip_options_len = 0;
*len += ipv4::get_pkt_len(h);
- if ( i + 1 == p->next_layer )
+ if ( i + 1 == p->num_layers )
{
*len += p->dsize;
}
if ( f & ENC_FLAG_DEF )
{
int i = lyr - c->layers;
- if ( i + 1 == p->next_layer )
+ if ( i + 1 == p->num_layers )
{
lyr->length = sizeof(*ch);
ch->ip_len = htons(lyr->length);
// This will need to go
if (p->family != NO_IP)
{
- /* Snort currently supports only 2 IP layers. Any more will fail to be
- decoded. */
- if (p->encapsulated)
- {
-
+ if (p->encapsulations)
codec_events::decoder_alert_encapsulated(p, DECODE_IP_MULTIPLE_ENCAPSULATION,
raw_pkt, raw_len);
- goto decodeipv6_fail;
- }
- else
- {
- p->encapsulated = 1;
- p->outer_iph = p->iph;
- p->outer_ip_data = p->ip_data;
- p->outer_ip_dsize = p->ip_dsize;
- }
+
+ p->outer_iph = p->iph;
+ p->outer_ip_data = p->ip_data;
+ p->outer_ip_dsize = p->ip_dsize;
}
payload_len = ntohs(hdr->ip6plen) + ipv6::hdr_len();
sfiph_build(p, hdr, AF_INET6);
/* Remove outer IP options */
- if (p->encapsulated)
+ if (p->encapsulations)
{
p->ip_options_data = NULL;
p->ip_options_len = 0;
}
else
{
- if ( i + 1 == p->next_layer )
+ if ( i + 1 == p->num_layers )
*len += lyr->length + p->dsize;
// w/o all extension headers, can't use just the
if ( f & ENC_FLAG_DEF )
{
int i = lyr - c->layers;
- if ( i + 1 == p->next_layer )
+ if ( i + 1 == p->num_layers )
{
uint8_t* b = (uint8_t*)p->ip6_extensions[p->ip6_frag_index].data;
if ( b ) lyr->length = b - p->layers[i].start;
return false;
}
- if (p->encapsulated)
- {
- /* discard packet - multiple encapsulation */
- /* not sure if this is ever used but I am assuming it is not */
- codec_events::decoder_alert_encapsulated(p, DECODE_IP_MULTIPLE_ENCAPSULATION,
- raw_pkt, raw_len);
- return false;
- }
+ p->encapsulations++;
+
/* Check that this is in fact ERSpan Type 2.
*/
return false;
}
- if (p->encapsulated)
- {
- /* discard packet - multiple encapsulation */
- /* not sure if this is ever used but I am assuming it is not */
- codec_events::decoder_alert_encapsulated(p, DECODE_IP_MULTIPLE_ENCAPSULATION,
- raw_pkt, raw_len);
- return false;
- }
+ p->encapsulations++;
/* Check that this is in fact ERSpan Type 3.
*/
}
else
{
+ uint16_t vid = vlan::vth_vlan(vh);
+
+ // Vlan IDs 0 and 4095 are reserved.
+ if (vid == 0 || vid == 4095)
+ {
+ codec_events::decoder_event(p, DECODE_BAD_VLAN);
+
+ // TBD add decoder drop event for VLAN hdr len issue
+ p->iph = NULL;
+ p->family = NO_IP;
+ return false;
+ }
+
+
lyr_len = sizeof(vlan::VlanTagHdr);
next_prot_id = ntohs(vh->vth_proto);
-
}
p->proto_bits |= PROTO_BIT__VLAN;
uint8_t next_hdr_type;
uint8_t version;
uint8_t ip_ver;
- GTPHdr *hdr;
+ const GTPHdr *hdr;
DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Start GTP decoding.\n"););
- hdr = (GTPHdr *) raw_pkt;
+ p->encapsulations++;
+
+ hdr = reinterpret_cast<const GTPHdr *>(raw_pkt);
+
+
- if (p->GTPencapsulated)
- {
- codec_events::decoder_alert_encapsulated(p, DECODE_GTP_MULTIPLE_ENCAPSULATION,
- raw_pkt, raw_len);
- return false;
- }
- else
- {
- p->GTPencapsulated = 1;
- }
/*Check the length*/
if (raw_len < GTP_MIN_LEN)
return false;
#include "config.h"
#endif
-#include "generators.h"
-#include "protocols/packet.h"
-#include "static_include.h"
-#include "root_ppp.h"
-#include "../decoder_includes.h"
-#include "protocols/root/root_chdlc.h"
+#include "framework/codec.h"
+
+
+static int DLT_PPP = 51;
/*
{
uint32_t cap_len = pkthdr->caplen;
int hlen = 0;
- PROFILE_VARS;
-
- PREPROC_PROFILE_START(decodePerfStats);
-
- dc.total_processed++;
-
- memset(p, 0, PKT_ZERO_LEN);
-
- p->pkth = pkthdr;
- p->pkt = pkt;
-
- DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Packet!\n"););
if(cap_len < 2)
{
DecodePppPktEncapsulated(p->pkt + hlen, cap_len - hlen, p);
- PREPROC_PROFILE_END(decodePerfStats);
return;
}
EventNode* en = (EventNode*)sfeventq_event_alloc(event_queue[qIndex]);
- if ( !en )
+ if ( en )
return -1;
en->otn = otn;
switch(DAQ_GetBaseProtocol())
{
case DLT_EN10MB: /* Ethernet */
- if(p && (p->next_layer > 0))
+ if(p && (p->num_layers > 0))
LogEthHeader(log, p);
break;
#ifndef NO_NON_ETHER_DECODER
#ifdef DLT_IEEE802_11
case DLT_IEEE802_11:
- if(p && (p->next_layer > 0))
+ if(p && (p->num_layers > 0))
LogWifiHeader(log, p);
break;
#endif
case DLT_IEEE802: /* Token Ring */
- if(p && (p->next_layer > 0))
+ if(p && (p->num_layers > 0))
LogTrHeader(log, p);
break;
#ifdef DLT_LINUX_SLL
case DLT_LINUX_SLL:
- if (p && (p->next_layer > 0))
+ if (p && (p->num_layers > 0))
LogSLLHeader(log, p); /* Linux cooked sockets */
break;
#endif
orig_p->dp = p->orig_dp;
orig_p->icmph = p->orig_icmph;
orig_p->iph_api = p->orig_iph_api;
- orig_p->ip4h = p->orig_ip4h;
- orig_p->ip6h = p->orig_ip6h;
+// orig_p->ip4h = p->orig_ip4h;
+// orig_p->ip6h = p->orig_ip6h;
orig_p->family = p->orig_family;
if(orig_p->iph != NULL)
if(p && ScObfuscate() )
{
- int next_layer = p->next_layer;
- for ( i = 0; i < next_layer; i++ )
+ int num_layers = p->num_layers;
+ for ( i = 0; i < num_layers; i++ )
{
if ( p->layers[i].proto == PROTO_IP4
|| p->layers[i].proto == PROTO_IP6
else if ( v.is("react") )
sc->react_page = SnortStrdup(v.get_string());
+ else
+ return false;
+
return true;
}
{ "new_ttl", Parameter::PT_INT, "1:255", "1",
"use this value for responses and when normalizing" },
+ { "max_encapsulations", Parameter::PT_INT, "-1:32", "-1",
+ "maximum number of encapsulations per packet" },
+
{ nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
};
else if ( v.is("new_ttl") )
p->new_ttl = (uint8_t)v.get_long();
+ else if ( v.is("max_encapsulations") )
+ sc->max_encapsulations = v.get_long();
+
else
return false;
return snort_conf->so_rule_memcap;
}
-static inline bool ScTunnelBypassEnabled (uint8_t proto)
+static inline bool ScTunnelBypassEnabled(uint8_t proto)
{
return !(snort_conf->tunnel_mask & proto);
}
+static inline int8_t ScMaxEncapsulations(void)
+{
+ return snort_conf->max_encapsulations;
+}
+
#endif
uint8_t enable_gtp;
char *gtp_ports;
uint8_t enable_esp;
+ int8_t max_encapsulations;
int pkt_snaplen;
#include "protocols/ipv4.h"
#include "protocols/ipv6.h"
#include "codecs/ip/ipv6_util.h"
+#include "codecs/codec_events.h"
+#include "codecs/decode_module.h"
// Encoder FOO
#ifdef HAVE_DUMBNET_H
uint32_t len,
Codec *const cd)
{
- if ( p->next_layer < LAYER_MAX )
+ if ( p->num_layers < LAYER_MAX )
{
- Layer& lyr = p->layers[p->next_layer++];
+ Layer& lyr = p->layers[p->num_layers++];
lyr.proto = cd->get_proto_id();
lyr.prot_id = prot_id;
lyr.start = (uint8_t*)hdr_start;
}
}
-static inline uint8_t* get_inner_ip_hdr(const Packet *p)
-{
- const Layer *layers = p->layers;
-
- for (int i = p->next_layer-1; i >= 0; i--)
- {
- switch(layers[i].prot_id)
- {
- case ETHERTYPE_IPV4:
- case ETHERTYPE_IPV6:
- case IPPROTO_ID_IPIP:
- case IPPROTO_ID_IPV6:
- return layers[i].start;
- default:
- break;
- }
- }
- return nullptr;
-}
-
-static inline int get_inner_ip_lyr(const Packet *p)
-{
- const Layer *layers = p->layers;
-
- for (int i = p->next_layer-1; i >= 0; i--)
- {
- switch(layers[i].prot_id)
- {
- case ETHERTYPE_IPV4:
- case ETHERTYPE_IPV6:
- case IPPROTO_ID_IPIP:
- case IPPROTO_ID_IPV6:
- return i;
- default:
- break;
- }
- }
- return -1;
-}
/*
* Begin search from index 1. 0 is a special case in that it is the default
obuf.size = sizeof(s_pkt);
// setting convenience pointers
- enc->layer = p->next_layer;
+ enc->layer = p->num_layers;
enc->p = p;
- enc->ip_hdr = get_inner_ip_hdr(p);
+ enc->ip_hdr = p->layers[layer::get_inner_ip_lyr(p)].start;
if ( ipv4::is_ipv4(*(enc->ip_hdr)))
enc->ip_len = ipv4::get_pkt_len((IPHdr*) enc->ip_hdr);
const Layer *lyrs = p->layers;
- for(int i = p->next_layer-1; i >= 0; i--)
+ for(int i = p->num_layers-1; i >= 0; i--)
{
// lots of room for improvement
const Layer *l = &lyrs[i];
// loop until the protocol id is no longer valid
while(s_protocols[mapped_prot]->decode(pkt, len, p, lyr_len, prot_id))
{
+ // must be done here after decode and before push for case layer
+ // LAYER_MAX+1 is invalid or the default codec
+ if ( p->num_layers == LAYER_MAX )
+ {
+ codec_events::decoder_event(p, DECODE_TOO_MANY_LAYERS);
+ PREPROC_PROFILE_END(decodePerfStats);
+ return false;
+ }
+
// internal statistics and record keeping
push_layer(p, prev_prot_id, pkt, lyr_len, s_protocols[mapped_prot]);
s_stats[mapped_prot + stat_offset]++;
p->packet_flags |= PKT_TRUST;
}
+ if (ScMaxEncapsulations() != -1 &&
+ p->encapsulations > ScMaxEncapsulations())
+ {
+ codec_events::decoder_event(p, DECODE_IP_MULTIPLE_ENCAPSULATION);
+ }
+
if (p->ip6_extension_count > 0)
ipv6_util::CheckIPv6ExtensionOrder(p);
int i;
Layer* lyr;
int len;
- int num_layers = p->next_layer;
+ int num_layers = p->num_layers;
DAQ_PktHdr_t* pkth = (DAQ_PktHdr_t*)c->pkth;
uint8_t* pkt = (uint8_t*)c->pkt;
if ( f & ENC_FLAG_NET )
{
- num_layers = get_inner_ip_lyr(p) + 1;
+ num_layers = layer::get_inner_ip_lyr(p) + 1;
// TBD: is this an extraneous check?
if (num_layers == 0)
}
// setup payload info
- c->next_layer = num_layers;
+ c->num_layers = num_layers;
c->data = lyr->start + lyr->length;
len = c->data - c->pkt;
p->actual_ip_len = 0;
Layer *lyr = p->layers;
- for ( i = p->next_layer - 1; i >= 0; i-- )
+ for ( i = p->num_layers - 1; i >= 0; i-- )
{
Layer *l = lyr + i;
#include "stream/stream_splitter.h"
#include "managers/inspector_manager.h"
#include "protocols/packet.h"
+#include "protocols/vlan.h"
+#include "protocols/layer.h"
#include "stream/stream_api.h"
#include "time/profiler.h"
#include "utils/stats.h"
unsigned i, sz = bindings.size();
Port port = (p->packet_flags & PKT_FROM_CLIENT) ? p->dp : p->sp;
+ uint16_t vlan = vlan::vth_vlan(layer::get_vlan_layer(p));
for ( i = 0; i < sz; i++ )
{
// go from inner to outer
int Norm_Packet (NormalizerConfig* c, Packet* p)
{
- uint8_t lyr = p->next_layer;
+ uint8_t lyr = p->num_layers;
int changes = 0;
while ( lyr > 0 )
static inline PROTO_ID GetInnerProto (const Packet* p)
{
- if ( !p->next_layer ) return PROTO_MAX;
- return ( p->layers[p->next_layer-1].proto );
+ if ( !p->num_layers ) return PROTO_MAX;
+ return ( p->layers[p->num_layers-1].proto );
}
//--------------------------------------------------------------------
#include "protocols/packet.h"
+#include "protocols/ipv4.h"
+#include "protocols/ipv6.h"
namespace layer
{
return nullptr;
}
-const arp::EtherARP* get_arp_layer(const Packet* p)
+const arp::EtherARP* get_arp_layer(const Packet* const p)
{
- uint8_t num_layers = p->next_layer;
+ uint8_t num_layers = p->num_layers;
const Layer *lyr = p->layers;
return reinterpret_cast<const arp::EtherARP*>(
find_layer(lyr, num_layers, ETHERTYPE_ARP, ETHERTYPE_REVARP));
}
-const gre::GREHdr* get_gre_layer(const Packet* p)
+const gre::GREHdr* get_gre_layer(const Packet* const p)
{
- uint8_t num_layers = p->next_layer;
+ uint8_t num_layers = p->num_layers;
const Layer *lyr = p->layers;
return reinterpret_cast<const gre::GREHdr*>(
find_layer(lyr, num_layers, IPPROTO_ID_GRE));
}
-const eapol::EtherEapol* get_eapol_layer(const Packet* p)
+const eapol::EtherEapol* get_eapol_layer(const Packet* const p)
{
- uint8_t num_layers = p->next_layer;
+ uint8_t num_layers = p->num_layers;
const Layer *lyr = p->layers;
return reinterpret_cast<const eapol::EtherEapol*>(
find_layer(lyr, num_layers, ETHERTYPE_EAPOL));
}
-const vlan::VlanTagHdr* get_vlan_layer(const Packet* p)
+const vlan::VlanTagHdr* get_vlan_layer(const Packet* const p)
{
- uint8_t num_layers = p->next_layer;
+ uint8_t num_layers = p->num_layers;
const Layer *lyr = p->layers;
return reinterpret_cast<const vlan::VlanTagHdr*>(
find_layer(lyr, num_layers, ETHERTYPE_8021Q));
}
-const eth::EtherHdr* get_eth_layer(const Packet* p)
+const eth::EtherHdr* get_eth_layer(const Packet* const p)
{
- uint8_t num_layers = p->next_layer;
+ uint8_t num_layers = p->num_layers;
const Layer *lyr = p->layers;
// First, search for the inner eth layer (transbridging)
return eh ? eh : reinterpret_cast<const eth::EtherHdr*>(get_root_layer(p));
}
-const uint8_t* get_root_layer(const Packet* p)
+const uint8_t* get_root_layer(const Packet* const p)
{
// since token ring is the grinder, its the begining of the packet.
- if (p->next_layer > 0)
+ if (p->num_layers > 0)
return p->layers[0].start;
return nullptr;
}
+
+uint8_t get_outer_ip_next_pro(const Packet* const p)
+{
+ const Layer* layers = p->layers;
+ const int max_layers = p->num_layers;
+
+ for (int i = 0; i < max_layers; i++)
+ {
+ switch(layers[i].prot_id)
+ {
+ case ETHERTYPE_IPV4:
+ case IPPROTO_ID_IPIP:
+ return reinterpret_cast<IP4Hdr*>(layers[i].start)->ip_proto;
+ case ETHERTYPE_IPV6:
+ case IPPROTO_ID_IPV6:
+ return reinterpret_cast<IP6Hdr*>(layers[i].start)->next;
+ default:
+ break;
+ }
+ }
+}
+
+int get_inner_ip_lyr(const Packet* const p)
+{
+ const Layer* layers = p->layers;
+
+ for (int i = p->num_layers-1; i >= 0; i--)
+ {
+ switch(layers[i].prot_id)
+ {
+ case ETHERTYPE_IPV4:
+ case ETHERTYPE_IPV6:
+ case IPPROTO_ID_IPIP:
+ case IPPROTO_ID_IPV6:
+ return i;
+ default:
+ break;
+ }
+ }
+ return -1;
+}
+
} // namespace layer
}
-// code maintained in header to ensure files to not depend on this library
namespace layer
{
+// all of these functions will begin search from layer 0,
+// and will return the first function they find.
+
-// signatures. No need to go searching for the correct function
const arp::EtherARP* get_arp_layer(const Packet*);
const vlan::VlanTagHdr* get_vlan_layer(const Packet*);
const gre::GREHdr* get_gre_layer(const Packet*);
const eapol::EtherEapol* get_eapol_layer(const Packet*);
const eth::EtherHdr* get_eth_layer(const Packet*);
-const uint8_t* get_root_layer(const Packet*);
+const uint8_t* get_root_layer(const Packet* const);
+int get_inner_ip_lyr(const Packet* const p);
+uint16_t get_outer_ip_next_proto(const Packet* const);
} // namespace layer
#define PKT_FILE_EVENT_SET 0x04000000
#define PKT_ESP_LYR_PRESENT 0x08000000
+#define PKT_UNUSED_FLAGS 0xF0000000
// 0x40000000 are available
#define PKT_PDU_FULL (PKT_PDU_HEAD | PKT_PDU_TAIL)
//vvv-----------------------------
ipv4::IP4Hdr *ip4h, *orig_ip4h;
ipv6::IP6Hdr *ip6h, *orig_ip6h;
- icmp6::ICMP6Hdr *icmp6h, *orig_icmp6h;
+ icmp6::ICMP6Hdr *icmp6h;
IPH_API* iph_api;
IPH_API* orig_iph_api;
IPH_API* outer_iph_api;
- IPH_API* outer_orig_iph_api;
int family;
int orig_family;
uint8_t ip6_frag_index;
uint8_t error_flags; /* flags indicate checksum errors, bad TTLs, etc. */
- uint8_t encapsulated;
- uint8_t GTPencapsulated;
- uint8_t next_layer; /* index into layers for next encap */
+ uint8_t num_layers; /* index into layers for next encap */
+ uint8_t decode_flags; /* flags used while decoding */
+ uint8_t encapsulations; /* thh curent number of encapsulations */
// nothing after this point is zeroed ...
ipv4::IpOptions ip_options[IP_OPTMAX]; /* ip options decode structure */
/* If iph_api is already set, we've been here before.
* That means this is a nested IP. */
if (p->orig_iph_api && (p->orig_iph_api->ver == IPH_API_V4))
- {
memcpy(&p->outer_orig_ip4h, &p->inner_orig_ip4h, sizeof(IP4Hdr));
- p->outer_orig_iph_api = p->orig_iph_api;
- }
+
else if (p->orig_iph_api && (p->orig_iph_api->ver == IPH_API_V6))
- {
memcpy(&p->outer_orig_ip6h, &p->inner_orig_ip6h, sizeof(IP6Hdr));
- p->outer_orig_iph_api = p->orig_iph_api;
- }
+
_set_callbacks(p, family, CALLBACK_ICMP_ORIG);
PREPROC_PROFILE_START(fragRebuildPerfStats);
- if ( p->encapsulated )
+ if ( p->encapsulations )
dpkt = encap_defrag_pkt;
else
dpkt = defrag_pkt;