/* If this is an IP Fragment, set some data... */
p->ip6_frag_index = p->num_layers;
- p->ip_frag_start = raw_pkt + sizeof(ip::IP6Frag);
-
p->decode_flags &= ~DECODE__DF;
if (ntohs(ip6frag_hdr->ip6f_offlg) & ip::IP6F_MF_MASK)
// three least signifigant bits are all flags
const uint16_t frag_offset = ntohs(ip6frag_hdr->get_off()) >> 3;
- p->frag_offset = frag_offset;
if (frag_offset || (p->decode_flags & DECODE__MF))
{
p->decode_flags |= DECODE__FRAG;
lyr_len = sizeof(ip::IP6Frag);
next_prot_id = ip6frag_hdr->ip6f_nxt;
- p->ip_frag_len = (uint16_t)(raw_len - lyr_len);
// check header ordering up thru frag header
ip_util::CheckIPv6ExtensionOrder(p, IPPROTO_ID_FRAGMENT, next_prot_id);
#include "protocols/icmp4.h"
#include "codecs/codec_events.h"
#include "codecs/ip/checksum.h"
-#include "protocols/protocol_ids.h"
-#include "protocols/packet.h"
#include "codecs/decode_module.h"
#include "codecs/sf_protocols.h"
#include "codecs/ip/ip_util.h"
+#include "protocols/protocol_ids.h"
+#include "protocols/packet.h"
+#include "protocols/ipv4_options.h"
#include "packet_io/active.h"
#include "log/text_log.h"
+#include "main/snort_debug.h"
+#include "sfip/sf_ip.h"
namespace{
if (p->icmph->type == icmp::IcmpType::ECHOREPLY)
{
- int i;
- for (i = 0; i < p->ip_option_count; i++)
+ if (p->ip_api.is_ip4())
{
- if (p->ip_options[i].is_opt_rr())
- codec_events::decoder_event(p, DECODE_ICMP_TRACEROUTE_IPOPTS);
+ ip::IpOptionIterator iter(p->ip_api.get_ip4h(), p);
+ for (const ip::IpOptions& opt : iter)
+ {
+ if (opt.code == ip::IPOptionCodes::RR)
+ codec_events::decoder_event(p, DECODE_ICMP_TRACEROUTE_IPOPTS);
+ }
}
}
#include "codecs/ip/ip_util.h"
#include "packet_io/active.h"
#include "log/text_log.h"
+#include "main/snort_debug.h"
namespace
#include "codecs/decode_module.h"
#include "codecs/codec_events.h"
#include "protocols/packet.h"
+#include "protocols/ipv4_options.h"
namespace
bool IgmpCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
Packet *p, uint16_t& /*lyr_len*/, uint16_t& /*next_prot_id*/)
{
- int i, alert = 0;
-
if (raw_len >= 1 && raw_pkt[0] == 0x11)
{
const uint8_t* ip_opt_data = p->ip_api.get_ip_opt_data();
}
}
- for(i=0; i< (int) p->ip_option_count; i++) {
+
+ ip::IpOptionIterator iter(p->ip_api.get_ip4h(), p);
+ for (const ip::IpOptions& opt : iter)
+ {
/* All IGMPv2 packets contain IP option code 148 (router alert).
This vulnerability only applies to IGMPv3, so return early. */
- if (p->ip_options[i].is_opt_rtralt()) {
+ if (opt.code == ip::IPOptionCodes::RTRALT)
+ {
return true; /* No alert. */
}
- if (p->ip_options[i].len == 1) {
- alert++;
+ if (opt.len == 3)
+ {
+ codec_events::decoder_event(p, DECODE_IGMP_OPTIONS_DOS);
+ return true;
}
}
-
- if (alert > 0)
- codec_events::decoder_event(p, DECODE_IGMP_OPTIONS_DOS);
}
return true;
}
#include "codecs/decode_module.h"
#include "codecs/sf_protocols.h"
#include "protocols/ip.h"
+#include "protocols/ipv4_options.h"
#include "log/text_log.h"
#include "log/log_text.h"
static inline void IP4AddrTests (const IP4Hdr*, const Packet* p);
-static inline void IPMiscTests(Packet *);
-static void DecodeIPOptions(const uint8_t *start, uint32_t o_len, Packet *p);
+static inline void IPMiscTests(Packet *, const IP4Hdr* const, uint16_t len);
+static void DecodeIPOptions(const uint8_t *start, uint8_t& o_len, Packet *p);
-static int OptLenValidate(const uint8_t *option_ptr,
- const uint8_t *end,
- const uint8_t *len_ptr,
- int expected_len,
- Options *tcpopt,
- uint8_t *byte_skip);
/*******************************************
************ PRIVATE FUNCTIONS ***********
}
/* test for IP options */
- uint16_t ip_opt_len = (uint16_t)(hlen - ip::IP4_HEADER_LEN);
+ uint8_t ip_opt_len = (uint8_t)(hlen - ip::IP4_HEADER_LEN);
if(ip_opt_len > 0)
- {
DecodeIPOptions((raw_pkt + ip::IP4_HEADER_LEN), ip_opt_len, p);
- }
- else
- {
- /* If delivery header for GRE encapsulated packet is IP and it
- * had options, the packet's ip options will be refering to this
- * outer IP's options
- * Zero these options so they aren't associated with this inner IP
- * since p->iph will be pointing to this inner IP
- */
- p->ip_option_count = 0;
- }
/* set the remaining packet length */
const_cast<uint32_t&>(raw_len) = ip_len;
{
/* set the packet fragment flag */
p->decode_flags |= DECODE__FRAG;
- p->ip_frag_start = raw_pkt + hlen;
- p->ip_frag_len = (uint16_t)ip_len;
}
}
else
codec_events::decoder_event(p, DECODE_BAD_FRAGBITS);
}
- p->frag_offset = frag_off;
-
/* See if there are any ip_proto only rules that match */
fpEvalIpProtoOnlyRules(snort_conf->ip_proto_only_lists, p, iph->get_proto());
p->proto_bits |= PROTO_BIT__IP;
- IPMiscTests(p);
+ IPMiscTests(p, iph, ip::IP4_HEADER_LEN + ip_opt_len);
lyr_len = hlen;
+
/* if this packet isn't a fragment
* or if it is, its a UDP packet and offset is 0 */
if(!(p->decode_flags & DECODE__FRAG) ||
- ((p->decode_flags & DECODE__FRAG) && (frag_off == 0) &&
- (iph->get_proto() == IPPROTO_UDP)))
+ ((frag_off == 0) &&
+ (iph->get_proto() == IPPROTO_UDP)))
{
- DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "IP header length: %lu\n",
- (unsigned long)hlen););
-
if (iph->get_proto() >= MIN_UNASSIGNED_IP_PROTO)
codec_events::decoder_event(p, DECODE_IP_UNASSIGNED_PROTO);
else
/* IPv4-layer decoder rules */
-static inline void IPMiscTests(Packet *p)
+static inline void IPMiscTests(Packet *p, const IP4Hdr* const ip4h, uint16_t len)
{
/* Yes, it's an ICMP-related vuln in IP options. */
- uint8_t i, length, pointer;
+ uint8_t length, pointer;
+
/* Alert on IP packets with either 0x07 (Record Route) or 0x44 (Timestamp)
options that are specially crafted. */
- for (i = 0; i < p->ip_option_count; i++)
+ ip::IpOptionIterator iter(ip4h, (uint8_t)(len - ip::IP4_HEADER_LEN));
+ for (const ip::IpOptions& opt : iter)
{
- if (p->ip_options[i].data == NULL)
- continue;
-
- if (p->ip_options[i].is_opt_rr())
+ if (opt.code == ip::IPOptionCodes::RR)
{
- length = p->ip_options[i].len;
- if (length < 1)
+ length = opt.len;
+ if (length < 3)
continue;
- pointer = p->ip_options[i].data[0];
+ pointer = opt.data[0];
/* If the pointer goes past the end of the data, then the data
is full. That's okay. */
- if (pointer >= length + 2)
+ if (pointer >= length)
continue;
/* If the remaining space in the option isn't a multiple of 4
bytes, alert. */
- if (((length + 3) - pointer) % 4)
+ if (((length + 1) - pointer) % 4)
codec_events::decoder_event(p, DECODE_ICMP_DOS_ATTEMPT);
}
- else if (p->ip_options[i].is_opt_ts())
+ else if (opt.code == ip::IPOptionCodes::TS)
{
- length = p->ip_options[i].len;
+ length = opt.get_len();
if (length < 2)
continue;
- pointer = p->ip_options[i].data[0];
+ pointer = opt.data[0];
/* If the pointer goes past the end of the data, then the data
is full. That's okay. */
- if (pointer >= length + 2)
+ if (pointer >= length)
continue;
/* If the remaining space in the option isn't a multiple of 4
bytes, alert. */
- if (((length + 3) - pointer) % 4)
+ if (((length + 1) - pointer) % 4)
codec_events::decoder_event(p, DECODE_ICMP_DOS_ATTEMPT);
/* If there is a timestamp + address, we need a multiple of 8
bytes instead. */
- if ((p->ip_options[i].data[1] & 0x01) && /* address flag */
- (((length + 3) - pointer) % 8))
+ if ((opt.data[1] & 0x01) && /* address flag */
+ (((length + 1) - pointer) % 8))
codec_events::decoder_event(p, DECODE_ICMP_DOS_ATTEMPT);
}
}
}
-
-// TODO :: delete. IN TCP
-int OptLenValidate(const uint8_t *option_ptr,
- const uint8_t *end,
- const uint8_t *len_ptr,
- int expected_len,
- Options *tcpopt,
- uint8_t *byte_skip);
-
/*
* Function: DecodeIPOptions(uint8_t *, uint32_t, Packet *)
*
*
* Returns: void function
*/
-static void DecodeIPOptions(const uint8_t *start, uint32_t o_len, Packet *p)
+static void DecodeIPOptions(const uint8_t *start, uint8_t& o_len, Packet *p)
{
- const uint8_t *option_ptr = start;
- u_char done = 0; /* have we reached IP_OPTEOL yet? */
- const uint8_t *end_ptr = start + o_len;
- uint8_t opt_count = 0; /* what option are we processing right now */
- uint8_t byte_skip;
- const uint8_t *len_ptr;
+ uint32_t tot_len = 0;
int code = 0; /* negative error codes are returned from bad options */
DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Decoding %d bytes of IP options\n", o_len););
+ const ip::IpOptions* option = reinterpret_cast<const ip::IpOptions*>(start);
- while((option_ptr < end_ptr) && (opt_count < IP_OPTMAX) && (code >= 0))
- {
- p->ip_options[opt_count].code = *option_ptr;
- if((option_ptr + 1) < end_ptr)
- {
- len_ptr = option_ptr + 1;
- }
- else
- {
- len_ptr = NULL;
- }
-
- switch(static_cast<ip::IPOptionCodes>(*option_ptr))
+ while(tot_len < o_len)
+ {
+ switch(option->code)
{
- case ip::IPOptionCodes::EOL:
- done = 1;
- // fall through
-
- case ip::IPOptionCodes::NOP:
- /* if we hit an EOL, we're done */
-
- p->ip_options[opt_count].len = 0;
- p->ip_options[opt_count].data = NULL;
- byte_skip = 1;
- break;
- default:
- /* FIXIT-L - J ip option validation should be updated. 3 of these fields are useless */
- code = OptLenValidate(option_ptr, end_ptr, len_ptr, -1,
- reinterpret_cast<Options *>(&p->ip_options[opt_count]), &byte_skip);
- }
+ case ip::IPOptionCodes::EOL:
+ /* if we hit an EOL, we're done */
+ tot_len++;
+ p->byte_skip = o_len - tot_len;
+ o_len = tot_len;
+ return;
+ // fall through
- if(code < 0)
- {
- /* Yes, we use TCP_OPT_* for the IP option decoder.
- */
- if(code == tcp::OPT_BADLEN)
- {
- codec_events::decoder_event(p, DECODE_IPV4OPT_BADLEN);
- }
- else if(code == tcp::OPT_TRUNC)
- {
- codec_events::decoder_event(p, DECODE_IPV4OPT_TRUNCATED);
- }
- return;
- }
+ case ip::IPOptionCodes::NOP:
+ tot_len++;
+ break;
- if(!done)
- opt_count++;
+ default:
- option_ptr += byte_skip;
- }
+ if((tot_len + 1) >= o_len)
+ code = tcp::OPT_TRUNC;
- p->ip_option_count = opt_count;
+ /* RFC sez that we MUST have atleast this much data */
+ else if (option->get_len() < 2)
+ code = tcp::OPT_BADLEN;
- return;
-}
+ else if (tot_len + option->get_len() > o_len)
+ /* not enough data to read in a perfect world */
+ code = tcp::OPT_TRUNC;
-static int OptLenValidate(const uint8_t *option_ptr,
- const uint8_t *end,
- const uint8_t *len_ptr,
- int expected_len,
- Options *tcpopt,
- uint8_t *byte_skip)
-{
- *byte_skip = 0;
- if(len_ptr == NULL)
- return tcp::OPT_TRUNC;
+ if(code < 0)
+ {
+ /* Yes, we use TCP_OPT_* for the IP option decoder. */
+ if(code == tcp::OPT_BADLEN)
+ codec_events::decoder_event(p, DECODE_IPV4OPT_BADLEN);
+ else if(code == tcp::OPT_TRUNC)
+ codec_events::decoder_event(p, DECODE_IPV4OPT_TRUNCATED);
+ p->byte_skip = o_len - tot_len;
+ o_len = tot_len;
+ return;
+ }
- if(*len_ptr == 0 || expected_len == 0 || expected_len == 1)
- {
- return tcp::OPT_BADLEN;
- }
- else if(expected_len > 1)
- {
- /* not enough data to read in a perfect world */
- if((option_ptr + expected_len) > end)
- return tcp::OPT_TRUNC;
+ tot_len += option->len;
+ }
- if(*len_ptr != expected_len)
- return tcp::OPT_BADLEN;
- }
- else /* expected_len < 0 (i.e. variable length) */
- {
- /* RFC sez that we MUST have atleast this much data */
- if(*len_ptr < 2)
- return tcp::OPT_BADLEN;
- /* not enough data to read in a perfect world */
- if((option_ptr + *len_ptr) > end)
- return tcp::OPT_TRUNC;
+ option = &(option->next());
}
-
- tcpopt->len = *len_ptr - 2;
-
- if(*len_ptr == 2)
- tcpopt->data = NULL;
- else
- tcpopt->data = option_ptr + 2;
-
- *byte_skip = *len_ptr;
-
- return 0;
}
+
/******************************************************************
********************* L O G G E R ******************************
*******************************************************************/
TextLog_Puts(text_log, " MF");
/* print IP options */
- if(p->ip_option_count > 0)
+ if (ip4h->has_options())
{
TextLog_Putc(text_log, '\t');
TextLog_NewLine(text_log);
- LogIpOptions(text_log, p);
+ LogIpOptions(text_log, ip4h, p);
}
}
if ( f & ENC_FLAG_DEF )
{
+ lyr->length = ip::IP4_HEADER_LEN;
+ ch->set_ip_len(htons(ip::IP4_HEADER_LEN));
+ ch->set_hlen(ip::IP4_HEADER_LEN >> 2);
+
+#if 0
+ // FIXIT-L - J why did Snort check for this?
int i = lyr - c->layers;
if ( i + 1 == p->num_layers )
{
ch->set_ip_len(htons(ip::IP4_HEADER_LEN));
ch->set_hlen(ip::IP4_HEADER_LEN >> 2);
}
+#endif
}
c->ip_api.set(ch);
#include "config.h"
#endif
+#include <limits>
#include "detection/fpdetect.h"
#include "protocols/ipv6.h"
#include "protocols/protocol_ids.h"
#include "protocols/packet_manager.h"
#include "log/text_log.h"
+#include "sfip/sf_ip.h"
namespace
{
}
-
- /* Remove outer IP options */
- p->ip_option_count = 0;
-
/* set the real IP length for logging */
p->proto_bits |= PROTO_BIT__IP;
// extra ipv6 header will be removed in PacketManager
p->ip_api.set(ip6h);
p->curr_ip6_extension_order = 0;
+ p->ip6_extension_count = 0;
+ p->ip6_frag_index = std::numeric_limits<uint8_t>::max();
p->decode_flags &= ~DECODE__ROUTING_SEEN;
IPV6MiscTests(p);
#include "config.h"
#endif
-
#include "framework/codec.h"
#include "codecs/decode_module.h"
#include "codecs/ip/checksum.h"
#include "codecs/sf_protocols.h"
#include "protocols/tcp.h"
+#include "protocols/tcp_options.h"
#include "protocols/ipv6.h"
#include "protocols/packet.h"
#include "packet_io/active.h"
#include "protocols/packet_manager.h"
+using namespace tcp;
+
namespace
{
-static int OptLenValidate(const uint8_t *option_ptr,
- const uint8_t *end,
- const uint8_t *len_ptr,
- int expected_len,
- Options *tcpopt,
- uint8_t *byte_skip);
+static int OptLenValidate(const tcp::TcpOption* const opt,
+ const uint8_t* const end,
+ const int expected_len);
static void DecodeTCPOptions(const uint8_t *, uint32_t, Packet *);
lyr_len = tcph->hdr_len();
DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "TCP th_off is %d, passed len is %lu\n",
- TCP_OFFSET(p->tcph), (unsigned long)raw_len););
+ tcph->off(), (unsigned long)raw_len););
if(lyr_len < tcp::TCP_HEADER_LEN)
{
DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
"TCP Data Offset (%d) < lyr_len (%d) \n",
- TCP_OFFSET(p->tcph), lyr_len););
+ tcph->off(), lyr_len););
codec_events::decoder_event(p, DECODE_TCP_INVALID_OFFSET);
{
DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
"TCP Data Offset(%d) < longer than payload(%d)!\n",
- TCP_OFFSET(p->tcph) << 2, raw_len););
+ tcph->off() << 2, raw_len););
codec_events::decoder_event(p, DECODE_TCP_LARGE_OFFSET);
/* if we're being "stateless" we probably don't care about the TCP
* checksum, but it's not bad to keep around for shits and giggles */
/* calculate the checksum */
- csum = checksum::tcp_cksum((uint16_t *)(p->tcph), raw_len, &ph);
+ csum = checksum::tcp_cksum((uint16_t *)(tcph), raw_len, &ph);
}
/* IPv6 traffic */
ph6.len = htons((uint16_t)raw_len);
- csum = checksum::tcp_cksum((uint16_t *)(p->tcph), raw_len, &ph6);
+ csum = checksum::tcp_cksum((uint16_t *)(tcph), raw_len, &ph6);
}
if(csum)
p->error_flags |= PKT_ERR_CKSUM_TCP;
DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Bad TCP checksum\n",
"0x%x versus 0x%x\n", csum,
- ntohs(p->tcph->th_sum)););
+ ntohs(tcph->th_sum)););
if( ScInlineMode() && ScTcpChecksumDrops() )
}
}
- if(TCP_ISFLAGSET(p->tcph, (TH_FIN|TH_PUSH|TH_URG)))
+ if(TCP_ISFLAGSET(tcph, (TH_FIN|TH_PUSH|TH_URG)))
{
- if(TCP_ISFLAGSET(p->tcph, (TH_SYN|TH_ACK|TH_RST)))
+ if(TCP_ISFLAGSET(tcph, (TH_SYN|TH_ACK|TH_RST)))
{
codec_events::decoder_event(p, DECODE_TCP_XMAS);
}
return;*/
}
- if(TCP_ISFLAGSET(p->tcph, (TH_SYN)))
+ if(TCP_ISFLAGSET(tcph, (TH_SYN)))
{
/* check if only SYN is set */
- if( p->tcph->th_flags == TH_SYN )
+ if( tcph->th_flags == TH_SYN )
{
- if( p->tcph->th_seq == 6060842 )
+ if( tcph->th_seq == 6060842 )
{
if( p->ip_api.id(p) == 413 )
{
{
codec_events::decoder_event(p, DECODE_SYN_TO_MULTICAST);
}
- if ( (p->tcph->th_flags & TH_RST) )
+ if ( (tcph->th_flags & TH_RST) )
codec_events::decoder_event(p, DECODE_TCP_SYN_RST);
- if ( (p->tcph->th_flags & TH_FIN) )
+ if ( (tcph->th_flags & TH_FIN) )
codec_events::decoder_event(p, DECODE_TCP_SYN_FIN);
}
else
{ // we already know there is no SYN
- if ( !(p->tcph->th_flags & (TH_ACK|TH_RST)) )
+ if ( !(tcph->th_flags & (TH_ACK|TH_RST)) )
codec_events::decoder_event(p, DECODE_TCP_NO_SYN_ACK_RST);
}
- if ( (p->tcph->th_flags & (TH_FIN|TH_PUSH|TH_URG)) &&
- !(p->tcph->th_flags & TH_ACK) )
+ if ( (tcph->th_flags & (TH_FIN|TH_PUSH|TH_URG)) &&
+ !(tcph->th_flags & TH_ACK) )
codec_events::decoder_event(p, DECODE_TCP_MUST_ACK);
/* stuff more data into the printout data struct */
- p->sp = ntohs(p->tcph->th_sport);
- p->dp = ntohs(p->tcph->th_dport);
+ p->sp = ntohs(tcph->th_sport);
+ p->dp = ntohs(tcph->th_dport);
/* if options are present, decode them */
uint16_t tcp_opt_len = (uint16_t)(tcph->hdr_len() - tcp::TCP_HEADER_LEN);
if(tcp_opt_len > 0)
- {
- DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "%lu bytes of tcp options....\n",
- (unsigned long)(tcp_opt_len)););
-
DecodeTCPOptions((uint8_t *) (raw_pkt + tcp::TCP_HEADER_LEN), tcp_opt_len, p);
- }
- else
- {
- p->tcp_option_count = 0;
- }
- /* set the data pointer and size */
- p->data = (uint8_t *) (raw_pkt + lyr_len);
- if(lyr_len < raw_len)
- {
- p->dsize = (uint16_t)(raw_len - lyr_len);
- }
- else
- {
- p->dsize = 0;
- }
+ int dsize = raw_len - tcph->hdr_len();
+ if (dsize < 0)
+ dsize = 0;
- if ( (p->tcph->th_flags & TH_URG) &&
- (!p->dsize || ntohs(p->tcph->th_urp) > p->dsize) )
+ if ( (tcph->th_flags & TH_URG) &&
+ ((dsize == 0) || ntohs(tcph->th_urp) > dsize) )
codec_events::decoder_event(p, DECODE_TCP_BAD_URP);
p->proto_bits |= PROTO_BIT__TCP;
TCPMiscTests(p);
-
+
return true;
}
*/
void DecodeTCPOptions(const uint8_t *start, uint32_t o_len, Packet *p)
{
- const uint8_t *option_ptr = start;
- const uint8_t *end_ptr = start + o_len; /* points to byte after last option */
- const uint8_t *len_ptr;
- uint8_t opt_count = 0;
- u_char done = 0; /* have we reached TCPOPT_EOL yet?*/
- u_char experimental_option_found = 0; /* are all options RFC compliant? */
- u_char obsolete_option_found = 0;
- u_char ttcp_found = 0;
-
+ const uint8_t* const end_ptr = start + o_len; /* points to byte after last option */
+ const tcp::TcpOption* opt = reinterpret_cast<const tcp::TcpOption*>(start);
int code = 2;
- uint8_t byte_skip;
+ uint16_t tot_len = 0;
+ bool done = false; /* have we reached TCPOPT_EOL yet?*/
+ bool experimental_option_found = false; /* are all options RFC compliant? */
+ bool obsolete_option_found = false;
+
+
/* Here's what we're doing so that when we find out what these
* other buggers of TCP option codes are, we can do something
*
* 1) get option code
* 2) check for enough space for current option code
- * 3) set option data ptr
* 4) increment option code ptr
*
* TCP_OPTLENMAX = 40 because of
*
*/
- if(o_len > TCP_OPTLENMAX)
+ while((tot_len < o_len) && !done)
{
- /* This shouldn't ever alert if we are doing our job properly
- * in the caller */
- p->tcph = NULL; /* let's just alert */
- DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
- "o_len(%u) > TCP_OPTLENMAX(%u)\n",
- o_len, TCP_OPTLENMAX));
- return;
- }
-
- while((option_ptr < end_ptr) && (opt_count < TCP_OPTLENMAX) && !done)
- {
- p->tcp_options[opt_count].code = *option_ptr;
-
- if((option_ptr + 1) < end_ptr)
+ switch(opt->code)
{
- len_ptr = option_ptr + 1;
- }
- else
- {
- len_ptr = NULL;
- }
-
- switch(*option_ptr)
- {
- case tcp::TcpOpt::EOL:
- done = 1; /* fall through to the NOP case */
- case tcp::TcpOpt::NOP:
- p->tcp_options[opt_count].len = 0;
- p->tcp_options[opt_count].data = NULL;
- byte_skip = 1;
+ case tcp::TcpOptCode::EOL:
+ done = true; /* fall through to the NOP case */
+ p->byte_skip = o_len - tot_len;
+ case tcp::TcpOptCode::NOP:
code = 0;
break;
- case tcp::TcpOpt::MAXSEG:
- code = OptLenValidate(option_ptr, end_ptr, len_ptr, TCPOLEN_MAXSEG,
- &p->tcp_options[opt_count], &byte_skip);
+
+ case tcp::TcpOptCode::MAXSEG:
+ code = OptLenValidate(opt, end_ptr, TCPOLEN_MAXSEG);
break;
- case tcp::TcpOpt::SACKOK:
- code = OptLenValidate(option_ptr, end_ptr, len_ptr, TCPOLEN_SACKOK,
- &p->tcp_options[opt_count], &byte_skip);
+
+ case tcp::TcpOptCode::SACKOK:
+ code = OptLenValidate(opt, end_ptr, TCPOLEN_SACKOK);
break;
- case tcp::TcpOpt::WSCALE:
- code = OptLenValidate(option_ptr, end_ptr, len_ptr, TCPOLEN_WSCALE,
- &p->tcp_options[opt_count], &byte_skip);
+
+ case tcp::TcpOptCode::WSCALE:
+ code = OptLenValidate(opt, end_ptr, TCPOLEN_WSCALE);
if (code == 0)
{
- if (
- ((uint16_t) p->tcp_options[opt_count].data[0] > 14))
+ if (((uint16_t) opt->data[0] > 14))
{
/* LOG INVALID WINDOWSCALE alert */
codec_events::decoder_event(p, DECODE_TCPOPT_WSCALE_INVALID);
}
}
break;
- case tcp::TcpOpt::ECHO: /* both use the same lengths */
- case tcp::TcpOpt::ECHOREPLY:
- obsolete_option_found = 1;
- code = OptLenValidate(option_ptr, end_ptr, len_ptr, TCPOLEN_ECHO,
- &p->tcp_options[opt_count], &byte_skip);
+
+ case tcp::TcpOptCode::ECHO: /* both use the same lengths */
+ case tcp::TcpOptCode::ECHOREPLY:
+ obsolete_option_found = true;
+ code = OptLenValidate(opt, end_ptr, TCPOLEN_ECHO);
break;
- case tcp::TcpOpt::MD5SIG:
+
+ case tcp::TcpOptCode::MD5SIG:
/* RFC 5925 obsoletes this option (see below) */
obsolete_option_found = 1;
- code = OptLenValidate(option_ptr, end_ptr, len_ptr, TCPOLEN_MD5SIG,
- &p->tcp_options[opt_count], &byte_skip);
+ code = OptLenValidate(opt, end_ptr, TCPOLEN_MD5SIG);
break;
- case tcp::TcpOpt::AUTH:
+
+ case tcp::TcpOptCode::AUTH:
+ code = OptLenValidate(opt, end_ptr, -1);
+
/* Has to have at least 4 bytes - see RFC 5925, Section 2.2 */
- if ((len_ptr != NULL) && (*len_ptr < 4))
+ if (code >= 0 && opt->len < 4)
code = tcp::OPT_BADLEN;
- else
- code = OptLenValidate(option_ptr, end_ptr, len_ptr, -1,
- &p->tcp_options[opt_count], &byte_skip);
break;
- case tcp::TcpOpt::SACK:
- code = OptLenValidate(option_ptr, end_ptr, len_ptr, -1,
- &p->tcp_options[opt_count], &byte_skip);
- if((code == 0) && (p->tcp_options[opt_count].data == NULL))
- code = tcp::OPT_BADLEN;
+ case tcp::TcpOptCode::SACK:
+ code = OptLenValidate(opt, end_ptr, -1);
+
+ if((code >= 0) && (opt->len < 2))
+ code = tcp::OPT_BADLEN;
break;
- case tcp::TcpOpt::CC_ECHO:
- ttcp_found = 1;
+
+ case tcp::TcpOptCode::CC_ECHO:
+ codec_events::decoder_event(p, DECODE_TCPOPT_TTCP);
/* fall through */
- case tcp::TcpOpt::CC: /* all 3 use the same lengths / T/TCP */
- case tcp::TcpOpt::CC_NEW:
- code = OptLenValidate(option_ptr, end_ptr, len_ptr, TCPOLEN_CC,
- &p->tcp_options[opt_count], &byte_skip);
+ case tcp::TcpOptCode::CC: /* all 3 use the same lengths / T/TCP */
+ case tcp::TcpOptCode::CC_NEW:
+ code = OptLenValidate(opt, end_ptr, TCPOLEN_CC);
break;
- case tcp::TcpOpt::TRAILER_CSUM:
- experimental_option_found = 1;
- code = OptLenValidate(option_ptr, end_ptr, len_ptr, TCPOLEN_TRAILER_CSUM,
- &p->tcp_options[opt_count], &byte_skip);
+
+ case tcp::TcpOptCode::TRAILER_CSUM:
+ experimental_option_found = true;
+ code = OptLenValidate(opt, end_ptr, TCPOLEN_TRAILER_CSUM);
break;
- case tcp::TcpOpt::TIMESTAMP:
- code = OptLenValidate(option_ptr, end_ptr, len_ptr, TCPOLEN_TIMESTAMP,
- &p->tcp_options[opt_count], &byte_skip);
+ case tcp::TcpOptCode::TIMESTAMP:
+ code = OptLenValidate(opt, end_ptr, TCPOLEN_TIMESTAMP);
break;
- case tcp::TcpOpt::SKEETER:
- case tcp::TcpOpt::BUBBA:
- case tcp::TcpOpt::UNASSIGNED:
- obsolete_option_found = 1;
- code = OptLenValidate(option_ptr, end_ptr, len_ptr, -1,
- &p->tcp_options[opt_count], &byte_skip);
+ case tcp::TcpOptCode::SKEETER:
+ case tcp::TcpOptCode::BUBBA:
+ case tcp::TcpOptCode::UNASSIGNED:
+ obsolete_option_found = true;
+ code = OptLenValidate(opt, end_ptr, -1);
break;
+
+ case tcp::TcpOptCode::SCPS:
+ case tcp::TcpOptCode::SELNEGACK:
+ case tcp::TcpOptCode::RECORDBOUND:
+ case tcp::TcpOptCode::CORRUPTION:
+ case tcp::TcpOptCode::PARTIAL_PERM:
+ case tcp::TcpOptCode::PARTIAL_SVC:
+ case tcp::TcpOptCode::ALTCSUM:
+ case tcp::TcpOptCode::SNAP:
default:
- case tcp::TcpOpt::SCPS:
- case tcp::TcpOpt::SELNEGACK:
- case tcp::TcpOpt::RECORDBOUND:
- case tcp::TcpOpt::CORRUPTION:
- case tcp::TcpOpt::PARTIAL_PERM:
- case tcp::TcpOpt::PARTIAL_SVC:
- case tcp::TcpOpt::ALTCSUM:
- case tcp::TcpOpt::SNAP:
- experimental_option_found = 1;
- code = OptLenValidate(option_ptr, end_ptr, len_ptr, -1,
- &p->tcp_options[opt_count], &byte_skip);
+ experimental_option_found = true;
+ code = OptLenValidate(opt, end_ptr, -1);
break;
}
* options found before this bad one
* some implementations (BSD and Linux) ignore
* the bad ones, but accept the good ones */
- p->tcp_option_count = opt_count;
+ p->byte_skip = o_len - tot_len;
return;
}
- opt_count++;
-
- option_ptr += byte_skip;
+ tot_len += ((uint8_t)opt->code <= 1) ? 1 : opt->len;
+ opt = &(opt->next());
}
- p->tcp_option_count = opt_count;
-
if (experimental_option_found)
{
codec_events::decoder_event(p, DECODE_TCPOPT_EXPERIMENTAL);
{
codec_events::decoder_event(p, DECODE_TCPOPT_OBSOLETE);
}
- else if (ttcp_found)
- {
- codec_events::decoder_event(p, DECODE_TCPOPT_TTCP);
- }
return;
}
+static int OptLenValidate(const tcp::TcpOption* const opt,
+ const uint8_t* const end,
+ const int expected_len)
+{
+ // case for pointer arithmetic
+ const uint8_t* const opt_ptr = reinterpret_cast<const uint8_t* const>(opt);
+
+
+ if(expected_len > 1)
+ {
+ /* not enough data to read in a perfect world */
+ if((opt_ptr + expected_len) > end)
+ return tcp::OPT_TRUNC;
+
+ if(opt->len != expected_len)
+ return tcp::OPT_BADLEN;
+ }
+ else /* expected_len < 0 (i.e. variable length) */
+ {
+ /* RFC sez that we MUST have atleast this much data */
+ if(opt->len < 2)
+ return tcp::OPT_BADLEN;
+
+ /* not enough data to read in a perfect world */
+ if((opt_ptr + opt->len) > end)
+ return tcp::OPT_TRUNC;
+ }
+
+ return 0;
+}
+
/* TCP-layer decoder alerts */
static inline void TCPMiscTests(Packet *p)
if (p->sp == 0 || p->dp == 0)
codec_events::decoder_event(p, DECODE_TCP_PORT_ZERO);
+
}
/******************************************************************
{
char tcpFlags[9];
- const tcp::TCPHdr* tcph = reinterpret_cast<const tcp::TCPHdr*>(raw_pkt);
+ const tcp::TCPHdr* const tcph = reinterpret_cast<const tcp::TCPHdr*>(raw_pkt);
/* print TCP flags */
CreateTCPFlagString(tcph, tcpFlags);
"Win: 0x%X TcpLen: %d",ntohs(tcph->th_sport),
ntohs(tcph->th_dport), (u_long) ntohl(tcph->th_seq),
(u_long) ntohl(tcph->th_ack),
- ntohs(tcph->th_win), TCP_OFFSET(tcph) << 2);
+ ntohs(tcph->th_win), tcph->off() << 2);
if((tcph->th_flags & TH_URG) != 0)
TextLog_Print(text_log, "UrgPtr: 0x%X", (uint16_t) ntohs(tcph->th_urp));
/* dump the TCP options */
- if(p->tcp_option_count > 0)
+ if(tcph->has_options())
{
TextLog_Puts(text_log, "\n\t");
LogTcpOptions(text_log, p);
memcpy(out->base, enc->payLoad, enc->payLen);
}
- if (!update_buffer(out, tcp::get_tcp_hdr_len(hi)))
+ if (!update_buffer(out, hi->hdr_len()))
return false;
tcp::TCPHdr* ho = reinterpret_cast<tcp::TCPHdr*>(out->base);
}
ho->th_offx2 = 0;
- tcp::set_tcp_offset(ho, (tcp::TCP_HEADER_LEN >> 2));
+ ho->set_offset(tcp::TCP_HEADER_LEN >> 2);
ho->th_win = ho->th_urp = 0;
if ( attach_payload )
}
-static int OptLenValidate(const uint8_t *option_ptr,
- const uint8_t *end,
- const uint8_t *len_ptr,
- int expected_len,
- Options *tcpopt,
- uint8_t *byte_skip)
-{
- *byte_skip = 0;
-
- if(len_ptr == NULL)
- return tcp::OPT_TRUNC;
-
-
- if(*len_ptr == 0 || expected_len == 0 || expected_len == 1)
- {
- return tcp::OPT_BADLEN;
- }
- else if(expected_len > 1)
- {
- /* not enough data to read in a perfect world */
- if((option_ptr + expected_len) > end)
- return tcp::OPT_TRUNC;
-
- if(*len_ptr != expected_len)
- return tcp::OPT_BADLEN;
- }
- else /* expected_len < 0 (i.e. variable length) */
- {
- /* RFC sez that we MUST have atleast this much data */
- if(*len_ptr < 2)
- return tcp::OPT_BADLEN;
-
- /* not enough data to read in a perfect world */
- if((option_ptr + *len_ptr) > end)
- return tcp::OPT_TRUNC;
- }
-
- tcpopt->len = *len_ptr - 2;
-
- if(*len_ptr == 2)
- tcpopt->data = NULL;
- else
- tcpopt->data = option_ptr + 2;
-
- *byte_skip = *len_ptr;
-
- return 0;
-}
-
-
-// KEEPING FOR TESTING AND PROFILING
-#if 0
-
-
-/*
- * Checksum Functions
- */
-
-/*
-* checksum tcp
-*
-* h - pseudo header - 12 bytes
-* d - tcp hdr + payload
-* dlen - length of tcp hdr + payload in bytes
-*
-*/
-static inline unsigned short in_chksum_tcp(pseudoheader *ph,
- unsigned short * d, int dlen )
-{
- uint16_t *h = (uint16_t *)ph;
- unsigned int cksum;
- unsigned short answer=0;
-
- /* PseudoHeader must have 12 bytes */
- cksum = h[0];
- cksum += h[1];
- cksum += h[2];
- cksum += h[3];
- cksum += h[4];
- cksum += h[5];
-
- /* TCP hdr must have 20 hdr bytes */
- cksum += d[0];
- cksum += d[1];
- cksum += d[2];
- cksum += d[3];
- cksum += d[4];
- cksum += d[5];
- cksum += d[6];
- cksum += d[7];
- cksum += d[8];
- cksum += d[9];
-
- dlen -= 20; /* bytes */
- d += 10; /* short's */
-
- while(dlen >=32)
- {
- cksum += d[0];
- cksum += d[1];
- cksum += d[2];
- cksum += d[3];
- cksum += d[4];
- cksum += d[5];
- cksum += d[6];
- cksum += d[7];
- cksum += d[8];
- cksum += d[9];
- cksum += d[10];
- cksum += d[11];
- cksum += d[12];
- cksum += d[13];
- cksum += d[14];
- cksum += d[15];
- d += 16;
- dlen -= 32;
- }
-
- while(dlen >=8)
- {
- cksum += d[0];
- cksum += d[1];
- cksum += d[2];
- cksum += d[3];
- d += 4;
- dlen -= 8;
- }
-
- while(dlen > 1)
- {
- cksum += *d++;
- dlen -= 2;
- }
-
- if( dlen == 1 )
- {
- /* printf("new checksum odd byte-packet\n"); */
- *(unsigned char*)(&answer) = (*(unsigned char*)d);
-
- /* cksum += (uint16_t) (*(uint8_t*)d); */
-
- cksum += answer;
- }
-
- cksum = (cksum >> 16) + (cksum & 0x0000ffff);
- cksum += (cksum >> 16);
-
- return (unsigned short)(~cksum);
-}
-/*
-* checksum tcp for IPv6.
-*
-* h - pseudo header - 12 bytes
-* d - tcp hdr + payload
-* dlen - length of tcp hdr + payload in bytes
-*
-*/
-static inline unsigned short in_chksum_tcp6(pseudoheader6 *ph,
- unsigned short * d, int dlen )
-{
- uint16_t *h = (uint16_t *)ph;
- unsigned int cksum;
- unsigned short answer=0;
-
- /* PseudoHeader must have 36 bytes */
- cksum = h[0];
- cksum += h[1];
- cksum += h[2];
- cksum += h[3];
- cksum += h[4];
- cksum += h[5];
- cksum += h[6];
- cksum += h[7];
- cksum += h[8];
- cksum += h[9];
- cksum += h[10];
- cksum += h[11];
- cksum += h[12];
- cksum += h[13];
- cksum += h[14];
- cksum += h[15];
- cksum += h[16];
- cksum += h[17];
-
- /* TCP hdr must have 20 hdr bytes */
- cksum += d[0];
- cksum += d[1];
- cksum += d[2];
- cksum += d[3];
- cksum += d[4];
- cksum += d[5];
- cksum += d[6];
- cksum += d[7];
- cksum += d[8];
- cksum += d[9];
-
- dlen -= 20; /* bytes */
- d += 10; /* short's */
-
- while(dlen >=32)
- {
- cksum += d[0];
- cksum += d[1];
- cksum += d[2];
- cksum += d[3];
- cksum += d[4];
- cksum += d[5];
- cksum += d[6];
- cksum += d[7];
- cksum += d[8];
- cksum += d[9];
- cksum += d[10];
- cksum += d[11];
- cksum += d[12];
- cksum += d[13];
- cksum += d[14];
- cksum += d[15];
- d += 16;
- dlen -= 32;
- }
-
- while(dlen >=8)
- {
- cksum += d[0];
- cksum += d[1];
- cksum += d[2];
- cksum += d[3];
- d += 4;
- dlen -= 8;
- }
-
- while(dlen > 1)
- {
- cksum += *d++;
- dlen -= 2;
- }
-
- if( dlen == 1 )
- {
- /* printf("new checksum odd byte-packet\n"); */
- *(unsigned char*)(&answer) = (*(unsigned char*)d);
-
- /* cksum += (uint16_t) (*(uint8_t*)d); */
-
- cksum += answer;
- }
-
- cksum = (cksum >> 16) + (cksum & 0x0000ffff);
- cksum += (cksum >> 16);
-
- return (unsigned short)(~cksum);
-}
-
-#endif
-
//-------------------------------------------------------------------------
// api
//-------------------------------------------------------------------------
#include "snort_config.h"
#include "parser/config_file.h"
#include "codecs/ip/ip_util.h"
+#include "main/snort_debug.h"
namespace
if(raw_len < sizeof(udp::UDPHdr))
{
- DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
- "Truncated UDP header (%d bytes)\n", raw_len););
-
codec_events::decoder_event(p, DECODE_UDP_DGRAM_LT_UDPHDR);
-
PopUdp(p);
return false;
}
*/
static inline void PopUdp (Packet* p)
{
+ //FIXIT-J-H
// required for detect.c to short-circuit preprocessing
if ( !p->dsize )
-bool UdpCodec::encode (EncState* enc, Buffer* out, const uint8_t* raw_in)
+bool UdpCodec::encode(EncState* enc, Buffer* out, const uint8_t* raw_in)
{
const ip::IpApi* const ip_api = &enc->p->ip_api;
#include "protocols/protocol_ids.h"
#include "snort.h"
#include "codecs/sf_protocols.h"
+#include "main/snort_debug.h"
namespace
{
*
*/
if(raw_len < 2)
- {
- if (ScLogVerbose())
- {
- ErrorMessage("Length not big enough for even a single "
- "header or a one byte payload\n");
- }
return false;
- }
if(raw_pkt[0] & 0x01)
//-------------------------------------------------------------------------
static Codec* ctor(Module*)
-{
- return new PppEncap();
-}
+{ return new PppEncap(); }
static void dtor(Codec *cd)
-{
- delete cd;
-}
+{ delete cd; }
static const CodecApi pppencap_api =
{
#include "protocols/packet.h"
#include "codecs/sf_protocols.h"
#include "protocols/layer.h"
+#include "main/snort_debug.h"
namespace
{
bool PPPoESessCodec::encode(EncState *enc, Buffer* out, const uint8_t* raw_in)
-{
- return pppoepkt_encode(enc, out, raw_in);
-}
+{ return pppoepkt_encode(enc, out, raw_in); }
//-------------------------------------------------------------------------
static Codec* sess_ctor(Module*)
-{
- return new PPPoESessCodec();
-}
+{ return new PPPoESessCodec(); }
static void sess_dtor(Codec *cd)
-{
- delete cd;
-}
+{ delete cd; }
static const CodecApi pppoepkt_sess_api =
ehlib_LTLIBRARIES += libcd_llc.la
libcd_llc_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO
libcd_llc_la_LDFLAGS = -export-dynamic -shared
-libcd_llc_la_SOURCES = libcd_llc.cc
+libcd_llc_la_SOURCES = cd_llc.cc
ehlib_LTLIBRARIES += libcd_gtp.la
libcd_gtp_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO
"Ack: 0x%lX Win: 0x%X TcpLen: %d",ntohs(tcph->th_sport),
ntohs(tcph->th_dport), (u_long) ntohl(tcph->th_seq),
(u_long) ntohl(tcph->th_ack),
- ntohs(tcph->th_win), TCP_OFFSET(tcph) << 2);
+ ntohs(tcph->th_win), tcph->off() << 2);
break;
}
bool NullCodec::decode(const uint8_t* /*raw_pkt*/, const uint32_t& raw_len,
Packet* /*p*/, uint16_t &lyr_len, uint16_t &next_prot_id)
{
- DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "NULL Packet!\n"); );
-
/* do a little validation */
if(raw_len < NULL_HDRLEN)
- {
- if (ScLogVerbose())
- {
- ErrorMessage("NULL header length < captured len! (%d bytes)\n",
- raw_len);
- }
return false;
- }
lyr_len = NULL_HDRLEN;
next_prot_id = ETHERTYPE_IPV4;
//-------------------------------------------------------------------------
static Codec* ctor(Module*)
-{
- return new NullCodec();
-}
+{ return new NullCodec(); }
static void dtor(Codec *cd)
-{
- delete cd;
-}
+{ delete cd; }
static const CodecApi null_api =
{
#include "codecs/codec_events.h"
#include "protocols/protocol_ids.h"
#include "main/snort.h"
+#include "log/text_log.h"
-#ifdef DEBUG_MSGS
-#include "log/log.h"
-#endif
-
namespace
{
virtual bool decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
Packet *, uint16_t &lyr_len, uint16_t &next_prot_id);
-
virtual void get_data_link_type(std::vector<int>&);
-
-};
-
-struct EthLlc
-{
- uint8_t dsap;
- uint8_t ssap;
-} ;
-
-struct EthLlcOther
-{
- uint8_t ctrl;
- uint8_t org_code[3];
- uint16_t proto_id;
+ virtual void log(TextLog* const, const uint8_t* /*raw_pkt*/,
+ const Packet* const);
};
#define MINIMAL_IEEE80211_HEADER_LEN 10 /* Ack frames and others */
bool WlanCodec::decode(const uint8_t *raw_pkt, const uint32_t &raw_len,
Packet*, uint16_t &lyr_len, uint16_t &next_prot_id)
{
- uint32_t cap_len = raw_len;
- // reinterpret the raw data into this codec's data format
-
-
/* do a little validation */
- if(cap_len < MINIMAL_IEEE80211_HEADER_LEN)
- {
- if (ScLogVerbose())
- {
- ErrorMessage("Captured data length < IEEE 802.11 header length! "
- "(%d bytes)\n", cap_len);
- }
-
+ if(raw_len < MINIMAL_IEEE80211_HEADER_LEN)
return false;
- }
/* lay the wireless structure over the packet data */
const wlan::WifiHdr *wifih = reinterpret_cast<const wlan::WifiHdr *>(raw_pkt);
- DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "%X %X\n", *wifih->addr1,
- *wifih->addr2););
/* determine frame type */
switch(wifih->frame_control & 0x00ff)
{
lyr_len = IEEE802_11_DATA_HDR_LEN;
next_prot_id = ETHERNET_LLC;
-#if 0
- if(cap_len < IEEE802_11_DATA_HDR_LEN + sizeof(EthLlc))
- {
- codec_events::decoder_event(p, DECODE_BAD_80211_ETHLLC);
- return false;
- }
-
- const EthLlc *ehllc = reinterpret_cast<const EthLlc*>(raw_pkt + IEEE802_11_DATA_HDR_LEN);
-
-#ifdef DEBUG_MSGS
- LogNetData((uint8_t*) ehllc, sizeof(EthLlc), NULL);
-
- printf("LLC Header:\n");
- printf(" DSAP: 0x%X\n", ehllc->dsap);
- printf(" SSAP: 0x%X\n", ehllc->ssap);
-#endif
- if(ehllc->dsap == ETH_DSAP_IP && ehllc->ssap == ETH_SSAP_IP)
- {
- if(cap_len < IEEE802_11_DATA_HDR_LEN +
- sizeof(EthLlc) + sizeof(EthLlcOther))
- {
- codec_events::decoder_event(p, DECODE_BAD_80211_OTHER);
- return false;
- }
-
- const EthLlcOther *ehllcother = reinterpret_cast<const EthLlcOther *>(raw_pkt + IEEE802_11_DATA_HDR_LEN + sizeof(EthLlc));
-#ifdef DEBUG_MSGS
- LogNetData((uint8_t*)ehllcother, sizeof(EthLlcOther), NULL);
-
- printf("LLC Other Header:\n");
- printf(" CTRL: 0x%X\n", ehllcother->ctrl);
- printf(" ORG: 0x%02X%02X%02X\n", ehllcother->org_code[0],
- ehllcother->org_code[1], ehllcother->org_code[2]);
- printf(" PROTO: 0x%04X\n", ntohs(ehllcother->proto_id));
-#endif
- next_prot_id = ntohs(ehllcother->proto_id);
-
- switch(ntohs(ehllcother->proto_id))
- {
- case ETHERTYPE_IPV4:
- case ETHERTYPE_ARP:
- case ETHERTYPE_REVARP:
- case ETHERTYPE_EAPOL:
- lyr_len = IEEE802_11_DATA_HDR_LEN + sizeof(EthLlc) + sizeof(EthLlcOther);
-
-
- case ETHERTYPE_8021Q:
- case ETHERTYPE_IPV6:
- lyr_len = IEEE802_11_DATA_HDR_LEN;
- default:
- return false;
- }
- }
-#endif
break;
}
default:
return true;
}
+void WlanCodec::log(TextLog* const text_log, const uint8_t* raw_pkt,
+ const Packet* const)
+{
+ const wlan::WifiHdr *wifih = reinterpret_cast<const wlan::WifiHdr *>(raw_pkt);
+
+ /* src addr */
+ TextLog_Print(text_log, "addr1(%02X:%02X:%02X:%02X:%02X:%02X) -> ",
+ wifih->addr1[0], wifih->addr1[1], wifih->addr1[2],
+ wifih->addr1[3], wifih->addr1[4], wifih->addr1[5]);
+
+ /* dest addr */
+ TextLog_Print(text_log, "%02X:%02X:%02X:%02X:%02X:%02X)",
+ wifih->addr2[0], wifih->addr2[1], wifih->addr2[2],
+ wifih->addr2[3], wifih->addr2[4], wifih->addr2[5]);
+
+ TextLog_NewLine(text_log);
+ TextLog_Putc(text_log, '\t');
+ TextLog_Print(text_log, "frame_control:%02x duration_id:%02x "
+ "seq_control:%02x", ntohs(wifih->frame_control),
+ ntohs(wifih->duration_id), ntohs(wifih->seq_control));
+}
//-------------------------------------------------------------------------
#include "actions/actions.h"
#include "protocols/packet_manager.h"
#include "managers/action_manager.h"
+#include "sfip/sf_ip.h"
/*
** Static function prototypes
#include "sfxhash.h"
#include "sfip/sfip_t.h"
+#include "sfip/sf_ip.h"
/* D E F I N E S **************************************************/
#define MAX_TAG_NODES 256
#include "packet_io/active.h"
#include "libs/file_sha256.h"
#include "managers/action_manager.h"
+#include "sfip/sf_ip.h"
/* The hash table of expected files */
static THREAD_LOCAL_TBD SFXHASH *fileHash = NULL;
#include <stdio.h>
#include <stdlib.h>
-#include "snort_types.h"
+#include "main/snort_types.h"
+#include "main/snort_debug.h"
#include "util.h"
#include "mstring.h"
-#include "parser.h"
+#include "parser/parser.h"
#include "file_lib.h"
#include "file_identifier.h"
#include "sfrf.h"
#include "snort.h"
#include "sfthd.h"
+#include "sfip/sf_ip.h"
//static int _printThresholdContext(RateFilterConfig*);
#include "time/packet_time.h"
#include "stream/stream_api.h" // FIXIT-M bad dependency
#include "zhash.h"
+#include "sfip/sf_ip.h"
/* Reasonably small, and prime */
// FIXIT-L size based on max_tcp + max_udp?
#include "utils/bitop_funcs.h"
#include "utils/util.h"
#include "protocols/packet.h"
+#include "sfip/sf_ip.h"
unsigned FlowData:: flow_id = 0;
#include "protocols/packet.h"
#include "snort.h"
#include "utils/util.h"
+#include "sfip/sf_ip.h"
//-------------------------------------------------------------------------
// init foo
struct Packet;
struct Layer;
+namespace ip
+{
+ class IpApi;
+}
+namespace tcp
+{
+ struct TCPHdr;
+}
+namespace udp
+{
+ struct UDPHdr;
+}
+namespace icmp
+{
+ struct ICMPHdr;
+}
+
+
enum EncodeType{
ENC_TCP_FIN,
ENC_TCP_RST,
}
+struct CodecData
+{
+ /* Convenience Pointers. These will be passed to the rest of Snort++ */
+ const tcp::TCPHdr* tcph;
+ const udp::UDPHdr* udph;
+ const icmp::ICMPHdr* icmph;
+ uint16_t sp; /* source port (TCP/UDP) */
+ uint16_t dp; /* dest port (TCP/UDP) */
+
+ /* Flags which will be sent to the rest of Snort++ */
+ uint32_t packet_flags; /* TODO: delete */
+ uint16_t proto_bits; /* protocols contained within this packet */
+ uint8_t error_flags; /* flags indicate checksum errors, bad TTLs, etc. */
+
+
+ uint8_t ip6_frag_index;
+ uint8_t curr_ip6_extension_order;
+ uint8_t ip6_extension_count;
+ uint8_t byte_skip; /* when decoding, there are <byte_skip> bytes between the end of the layer and the start of the next layer */
+ ip::IpApi* ip_api;
+};
+
/* Codec Class */
class SO_PUBLIC Codec
return rval;
}
+ const uint16_t frag_offset = ntohs(p->ip_api.off(p));
MODULE_PROFILE_START(fragBitsPerfStats);
DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, " <!!> CheckFragBits: ");
DebugMessage(DEBUG_PLUGIN, "[rule: 0x%X:%d pkt: 0x%X] ",
- fb->frag_bits, fb->mode, (p->ip_api.off(p)&bitmask)););
+ fb->frag_bits, fb->mode, frag_offset & bitmask););
switch(fb->mode)
{
case FB_NORMAL:
/* check if the rule bits match the bits in the packet */
- if(fb->frag_bits == (p->ip_api.off(p)&bitmask))
+ if(fb->frag_bits == (frag_offset & bitmask))
{
DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Got Normal bits match\n"););
rval = DETECTION_OPTION_MATCH;
case FB_NOT:
/* check if the rule bits don't match the bits in the packet */
- if((fb->frag_bits & (p->ip_api.off(p)&bitmask)) == 0)
+ if((fb->frag_bits & (frag_offset & bitmask)) == 0)
{
DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Got NOT bits match\n"););
rval = DETECTION_OPTION_MATCH;
case FB_ALL:
/* check if the rule bits are present in the packet */
- if((fb->frag_bits & (p->ip_api.off(p)&bitmask)) == fb->frag_bits)
+ if((fb->frag_bits & (frag_offset & bitmask)) == fb->frag_bits)
{
DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Got ALL bits match\n"););
rval = DETECTION_OPTION_MATCH;
case FB_ANY:
/* check if any of the rule bits match the bits in the packet */
- if((fb->frag_bits & (p->ip_api.off(p)&bitmask)) != 0)
+ if((fb->frag_bits & (frag_offset & bitmask)) != 0)
{
DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Got ANY bits match\n"););
rval = DETECTION_OPTION_MATCH;
int FragOffsetOption::eval(Cursor&, Packet *p)
{
- int p_offset = p->frag_offset * 8;
+ int p_offset = ntohs(p->ip_api.off(p)) * 8;
int rval = DETECTION_OPTION_NO_MATCH;
PROFILE_VARS;
#include "snort_types.h"
#include "treenodes.h"
#include "protocols/packet.h"
+#include "protocols/ipv4.h"
+#include "protocols/ipv4_options.h"
#include "parser.h"
#include "snort_debug.h"
#include "util.h"
struct IpOptionData
{
- u_char ip_option;
+ ip::IPOptionCodes ip_option;
u_char any_flag;
};
uint32_t a,b,c;
const IpOptionData *data = &config;
- a = data->ip_option;
+ a = (uint32_t)data->ip_option;
b = data->any_flag;
c = 0;
{
IpOptionData *ipOptionData = &config;
int rval = DETECTION_OPTION_NO_MATCH;
- int i;
PROFILE_VARS;
DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "CheckIpOptions:"););
- if(!p->ip_api.is_valid())
+ if(!p->ip_api.is_ip4())
return rval; /* if error occured while ip header
- * was processed, return 0 automagically. */
+ * was processed, return 0 automatically. */
MODULE_PROFILE_START(ipOptionPerfStats);
- if((ipOptionData->any_flag == 1) && (p->ip_option_count > 0))
+ const ip::IP4Hdr* const ip4h = p->ip_api.get_ip4h();
+ const uint8_t option_len = ip4h->get_opt_len();
+
+ if((ipOptionData->any_flag == 1) && (option_len > 0))
{
DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Matched any ip options!\n"););
rval = DETECTION_OPTION_MATCH;
return rval;
}
- for(i=0; i< (int) p->ip_option_count; i++)
+ ip::IpOptionIterator iter(ip4h, p);
+ for( ip::IpOptions opt : iter)
{
DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "testing pkt(%d):rule(%d)\n",
ipOptionData->ip_option,
- p->ip_options[i].code); );
+ static_cast<int>(opt.code)); );
- if(ipOptionData->ip_option == p->ip_options[i].code)
+ if(ipOptionData->ip_option == opt.code)
{
rval = DETECTION_OPTION_MATCH;
MODULE_PROFILE_END(ipOptionPerfStats);
{
if(strcasecmp(data, "rr") == 0)
{
- ds_ptr->ip_option = IPOPT_RR;
+ ds_ptr->ip_option = ip::IPOptionCodes::RR;
}
else if(strcasecmp(data, "eol") == 0)
{
- ds_ptr->ip_option = IPOPT_EOL;
+ ds_ptr->ip_option = ip::IPOptionCodes::EOL;
}
else if(strcasecmp(data, "nop") == 0)
{
- ds_ptr->ip_option = IPOPT_NOP;
+ ds_ptr->ip_option = ip::IPOptionCodes::NOP;
}
else if(strcasecmp(data, "ts") == 0)
{
- ds_ptr->ip_option = IPOPT_TS;
+ ds_ptr->ip_option = ip::IPOptionCodes::TS;
}
else if(strcasecmp(data, "esec") == 0)
{
- ds_ptr->ip_option = IPOPT_ESEC;
+ ds_ptr->ip_option = ip::IPOptionCodes::ESEC;
}
else if(strcasecmp(data, "sec") == 0)
{
- ds_ptr->ip_option = IPOPT_SECURITY;
+ ds_ptr->ip_option = ip::IPOptionCodes::SECURITY;
}
else if(strcasecmp(data, "lsrr") == 0)
{
- ds_ptr->ip_option = IPOPT_LSRR;
+ ds_ptr->ip_option = ip::IPOptionCodes::LSRR;
}
else if(strcasecmp(data, "lsrre") == 0)
{
- ds_ptr->ip_option = IPOPT_LSRR_E;
+ ds_ptr->ip_option = ip::IPOptionCodes::LSRR_E;
}
else if(strcasecmp(data, "satid") == 0)
{
- ds_ptr->ip_option = IPOPT_SATID;
+ ds_ptr->ip_option = ip::IPOptionCodes::SATID;
}
else if(strcasecmp(data, "ssrr") == 0)
{
- ds_ptr->ip_option = IPOPT_SSRR;
+ ds_ptr->ip_option = ip::IPOptionCodes::SSRR;
}
else if(strcasecmp(data, "any") == 0)
{
- ds_ptr->ip_option = 0;
+ ds_ptr->ip_option = static_cast<ip::IPOptionCodes>(0);
ds_ptr->any_flag = 1;
}
}
#include "framework/ips_option.h"
#include "framework/parameter.h"
#include "framework/module.h"
+#include "sfip/sf_ip.h"
static const char* s_name = "session";
#include "main/analyzer.h"
#include "snort.h"
#include "protocols/tcp.h"
+#include "main/snort_debug.h"
#define DEFAULT_DAEMON_ALERT_FILE "alert"
#include "protocols/wlan.h"
#include "protocols/linux_sll.h"
#include "protocols/eapol.h"
+#include "protocols/ipv4_options.h"
+#include "protocols/tcp_options.h"
/*--------------------------------------------------------------------
* utility functions
*-------------------------------------------------------------------
*/
-void LogIpOptions(TextLog* log, const Packet* const p)
+void LogIpOptions(TextLog* log, const IP4Hdr* ip4h, const Packet* const p)
{
- uint8_t i, j;
u_long init_offset;
u_long print_offset;
- const uint8_t option_count = p->ip_option_count;
+
init_offset = TextLog_Tell(log);
- TextLog_Print(log, "IP Options (%d) => ", option_count);
+ TextLog_Puts(log, "IP Options => ");
+
+ ip::IpOptionIterator options(ip4h, p);
- for(i = 0; i < option_count; i++)
+ for (auto op : options)
{
print_offset = TextLog_Tell(log);
init_offset = TextLog_Tell(log);
}
- switch(p->ip_options[i].code)
+ switch(op.code)
{
- case IPOPT_RR:
+ case ip::IPOptionCodes::RR:
TextLog_Puts(log, "RR ");
break;
- case IPOPT_EOL:
+ case ip::IPOptionCodes::EOL:
TextLog_Puts(log, "EOL ");
break;
- case IPOPT_NOP:
+ case ip::IPOptionCodes::NOP:
TextLog_Puts(log, "NOP ");
break;
- case IPOPT_TS:
+ case ip::IPOptionCodes::TS:
TextLog_Puts(log, "TS ");
break;
- case IPOPT_ESEC:
+ case ip::IPOptionCodes::ESEC:
TextLog_Puts(log, "ESEC ");
break;
- case IPOPT_SECURITY:
+ case ip::IPOptionCodes::SECURITY:
TextLog_Puts(log, "SEC ");
break;
- case IPOPT_LSRR:
- case IPOPT_LSRR_E:
+ case ip::IPOptionCodes::LSRR:
+ case ip::IPOptionCodes::LSRR_E:
TextLog_Puts(log, "LSRR ");
break;
- case IPOPT_SATID:
+ case ip::IPOptionCodes::SATID:
TextLog_Puts(log, "SID ");
break;
- case IPOPT_SSRR:
+ case ip::IPOptionCodes::SSRR:
TextLog_Puts(log, "SSRR ");
break;
- case IPOPT_RTRALT:
+ case ip::IPOptionCodes::RTRALT:
TextLog_Puts(log, "RTRALT ");
break;
default:
- TextLog_Print(log, "Opt %d: ", p->ip_options[i].code);
+ TextLog_Print(log, "Opt %d: ", (int)op.code);
- const ip::IpOptions* const ip_opt = &(p->ip_options[i]);
- const uint8_t opt_len = ip_opt->len;
+ // the only cases where len is invalid were handled aboved
+ const uint8_t opt_len = op.len;
+ int j;
- if(opt_len)
+ for(j = 0; (j + 1) < opt_len; j += 2)
{
- if (ip_opt->data)
- {
- for(j = 0; (j + 1) < opt_len; j += 2)
- {
- TextLog_Print(log, "%02X%02X ",ip_opt->data[j],
- ip_opt->data[j+1]);
- }
-
- // since we're skipping by two, if (j+1) == opt_len,
- // we will not have printed j
- if (j < opt_len)
- TextLog_Print(log, "%02X",ip_opt->data[j]);
- }
- else
- {
- for(j = 0; (j + 1) < opt_len; j += 2)
- {
- TextLog_Print(log, "%02X%02X ", 0, 0);
- }
-
- // since we're skipping by two, if (j+1) == opt_len,
- // we will not have printed j
- if (j < opt_len)
- TextLog_Print(log, "%02X",0);
- }
+ TextLog_Print(log, "%02X%02X ",op.data[j],
+ op.data[j+1]);
}
- break;
+
+ // since we're skipping by two, if (j+1) == opt_len,
+ // we will not have printed j
+ if (j < opt_len)
+ TextLog_Print(log, "%02X", op.data[j]);
+ break;
}
}
TextLog_NewLine(log);
p->ip_api.hlen() << 2,
p->ip_api.dgram_len());
+ const uint16_t frag_off = ntohs(p->ip_api.off(p));
+
/* print the reserved bit if it's set */
- if((uint8_t)((ntohs(p->ip_api.off(p)) & 0x8000) >> 15) == 1)
+ if(frag_off & 0x8000)
TextLog_Puts(log, " RB");
/* printf more frags/don't frag bits */
- if((uint8_t)((ntohs(p->ip_api.off(p)) & 0x4000) >> 14) == 1)
+ if(frag_off & 0x4000)
TextLog_Puts(log, " DF");
- if((uint8_t)((ntohs(p->ip_api.off(p)) & 0x2000) >> 13) == 1)
+ if(frag_off & 0x2000)
TextLog_Puts(log, " MF");
TextLog_NewLine(log);
/* print IP options */
- if(p->ip_option_count != 0)
+ if(p->ip_api.is_ip4())
{
- LogIpOptions(log, p);
+ const ip::IP4Hdr* const ip4h = p->ip_api.get_ip4h();
+
+ if (ip4h->has_options())
+ LogIpOptions(log, ip4h, p);
}
/* print fragment info if necessary */
if(p->decode_flags & DECODE__FRAG)
{
TextLog_Print(log, "Frag Offset: 0x%04X Frag Size: 0x%04X\n",
- (p->frag_offset & 0x1FFF),
+ (frag_off & 0x1FFF),
p->ip_api.pay_len());
}
}
static void LogOuterIPHeader(TextLog *log, Packet *p)
{
- uint8_t save_ip_option_count = p->ip_option_count;
uint8_t save_frag_flag = (p->decode_flags & DECODE__FRAG);
uint16_t save_sp, save_dp;
ip::IpApi save_ip_api = p->ip_api;
- p->ip_option_count = 0;
p->decode_flags &= ~DECODE__FRAG;
if (p->proto_bits & PROTO_BIT__TEREDO)
LogIPHeader(log, p);
p->ip_api = save_ip_api;
- p->ip_option_count = save_ip_option_count;
p->decode_flags |= save_frag_flag;
}
void LogTcpOptions(TextLog* log, const Packet* const p)
{
- uint8_t i;
- int j;
- const uint8_t option_count = p->tcp_option_count;
- const Options* const opts = p->tcp_options;
+ tcp::TcpOptIterator opt_iter(p->tcph, p);
+
- TextLog_Print(log, "TCP Options (%d) => ", option_count);
+ TextLog_Print(log, "TCP Options =>");
- for(i = 0; i < option_count; i++)
+ for (const tcp::TcpOption& opt : opt_iter)
{
#if 0
print_offset = TextLog_Tell(log);
init_offset = TextLog_Tell(log);
}
#endif
- switch(opts[i].code)
+ switch(opt.code)
{
- case TCPOPT_MAXSEG:
- {
- uint16_t val;
- TextLog_Puts(log, "MSS: ");
-
- if (opts[i].data)
- val = extract_16_bits(opts[i].data);
- else
- val = 0;
-
- TextLog_Print(log, "%u ", val);
- break;
- }
- case TCPOPT_EOL:
- TextLog_Puts(log, "EOL ");
+ case tcp::TcpOptCode::MAXSEG:
+ TextLog_Print(log, " MSS: %u", extract_16_bits(opt.data));
break;
- case TCPOPT_NOP:
- TextLog_Puts(log, "NOP ");
+ case tcp::TcpOptCode::EOL:
+ TextLog_Puts(log, " EOL");
break;
- case TCPOPT_WSCALE:
- {
- uint8_t val;
-
- if (opts[i].data)
- val = opts[i].data[0];
- else
- val = 0;
+ case tcp::TcpOptCode::NOP:
+ TextLog_Puts(log, " NOP");
+ break;
- TextLog_Print(log, "WS: %u ", val);
+ case tcp::TcpOptCode::WSCALE:
+ TextLog_Print(log, " WS: %u", opt.data[0]);
break;
- }
- case TCPOPT_SACK:
+
+ case tcp::TcpOptCode::SACK:
{
+ /* This length was not check during tcp decode */
uint16_t val1, val2;
- if (opts[i].data && (opts[i].len >= 4))
+ if (opt.len >= 4)
{
- val1 = extract_16_bits(opts[i].data);
- val2 = extract_16_bits(opts[i].data + 2);
+ val1 = extract_16_bits(opt.data);
+ val2 = extract_16_bits(opt.data + 2);
}
- else if (opts[i].data && (opts[i].len >= 2))
+ else if (opt.len >= 2)
{
- val1 = extract_16_bits(opts[i].data);
+ val1 = extract_16_bits(opt.data);
val2 = 0;
}
else
val2 = 0;
}
- TextLog_Print(log, "Sack: %u@%u", val1, val2);
+ TextLog_Print(log, " Sack: %u@%u", val1, val2);
break;
}
- case TCPOPT_SACKOK:
+ case tcp::TcpOptCode::SACKOK:
TextLog_Puts(log, "SackOK ");
break;
- case TCPOPT_ECHO:
- {
- uint32_t val;
-
- if (opts[i].data)
- val = extract_32_bits(opts[i].data);
- else
- val = 0;
-
- TextLog_Print(log, "Echo: %u ", val);
+ case tcp::TcpOptCode::ECHO:
+ TextLog_Print(log, "Echo: %u", extract_32_bits(opt.data));
break;
- }
- case TCPOPT_ECHOREPLY:
- {
- uint32_t val;
-
- if (opts[i].data)
- val = extract_32_bits(opts[i].data);
- else
- val = 0;
- TextLog_Print(log, "Echo Rep: %u ", val);
+ case tcp::TcpOptCode::ECHOREPLY:
+ TextLog_Print(log, "Echo Rep: %u", extract_32_bits(opt.data));
break;
- }
- case TCPOPT_TIMESTAMP:
- {
- uint32_t val1, val2;
- if (opts[i].data)
- {
- val1 = extract_32_bits(opts[i].data);
- val2 = extract_32_bits(opts[i].data + 4);
- }
- else
- {
- val1 = 0;
- val2 = 0;
- }
- TextLog_Print(log, "TS: %u %u ", val1, val2);
+ case tcp::TcpOptCode::TIMESTAMP:
+ TextLog_Print(log, "TS: %u %u", extract_32_bits(opt.data), opt.data + 4);
break;
- }
- case TCPOPT_CC:
- {
- uint32_t val;
- if (opts[i].data)
- val = extract_32_bits(opts[i].data);
- else
- val = 0;
-
- TextLog_Print(log, "CC %u ", val);
+ case tcp::TcpOptCode::CC:
+ TextLog_Print(log, "CC %u", extract_32_bits(opt.data));
break;
- }
- case TCPOPT_CC_NEW:
- {
- uint32_t val;
- if (opts[i].data)
- val = extract_32_bits(opts[i].data);
- else
- val = 0;
-
- TextLog_Print(log, "CCNEW: %u ", val);
+ case tcp::TcpOptCode::CC_NEW:
+ TextLog_Print(log, "CCNEW: %u", extract_32_bits(opt.data));
break;
- }
- case TCPOPT_CC_ECHO:
- {
- uint32_t val;
- if (opts[i].data)
- val = extract_32_bits(opts[i].data);
- else
- val = 0;
-
- TextLog_Print(log, "CCECHO: %u ", val);
+ case tcp::TcpOptCode::CC_ECHO:
+ TextLog_Print(log, "CCECHO: %u", extract_32_bits(opt.data));
break;
- }
+
default:
{
- const uint8_t opts_len = opts[i].len;
+ const int opt_len = opt.len - 2;
- if(opts_len)
+ if(opt_len > 0)
{
- TextLog_Print(log, "Opt %d (%d): ", opts[i].code,
- (int) opts_len);
+ TextLog_Print(log, " Opt %d (%d):", opt.code,
+ (int) opt_len);
- if (opts[i].data)
+ for (int i = 0; (i + 1) < opt_len; i += 2)
{
- for(j = 0; (j +1) < opts_len; j += 2)
- {
- TextLog_Print(log, "%02X%02X ", opts[i].data[j],
- opts[i].data[j+1]);
- }
-
- if (j < opts_len)
- TextLog_Print(log, "%02x", opts[i].data[j]);
- }
- else
- {
- for(j = 0; (j +1) < opts_len; j += 2)
- {
- TextLog_Print(log, "%02X%02X ", 0, 0);
- }
-
- if (j < opts_len)
- TextLog_Print(log, "%02x", 0);
+ TextLog_Print(log, " %02X%02X", opt.data[i],
+ opt.data[i+1]);
}
- TextLog_Putc(log, ' ');
+ // if there is an odd number of bytes
+ if (opt_len & 1)
+ TextLog_Print(log, " %02x", opt.data[opt_len - 1]);
}
else
{
- TextLog_Print(log, "Opt %d ", p->tcp_options[i].code);
+ TextLog_Print(log, " Opt %d", opt.code);
}
break;
}
void LogTCPHeader(TextLog* log, Packet * p)
{
char tcpFlags[9];
+ const tcp::TCPHdr* tcph = p->tcph;
- if(p->tcph == NULL)
+ if(tcph == NULL)
{
TextLog_Print(log, "TCP header truncated\n");
return;
}
/* print TCP flags */
- CreateTCPFlagString(p->tcph, tcpFlags);
+ CreateTCPFlagString(tcph, tcpFlags);
TextLog_Puts(log, tcpFlags); /* We don't care about the NULL */
/* print other TCP info */
TextLog_Print(log, " Seq: 0x%lX Ack: 0x%lX Win: 0x%X TcpLen: %d",
- (u_long) ntohl(p->tcph->th_seq),
- (u_long) ntohl(p->tcph->th_ack),
- ntohs(p->tcph->th_win), TCP_OFFSET(p->tcph) << 2);
+ (u_long) ntohl(tcph->th_seq),
+ (u_long) ntohl(tcph->th_ack),
+ ntohs(tcph->th_win), tcph->off() << 2);
- if((p->tcph->th_flags & TH_URG) != 0)
+ if((tcph->th_flags & TH_URG) != 0)
{
- TextLog_Print(log, " UrgPtr: 0x%X\n", (uint16_t) ntohs(p->tcph->th_urp));
+ TextLog_Print(log, " UrgPtr: 0x%X\n", (uint16_t) ntohs(tcph->th_urp));
}
else
{
}
/* dump the TCP options */
- if(p->tcp_option_count != 0)
+ if(tcph->has_options())
{
LogTcpOptions(log, p);
}
struct Packet;
struct Event;
+namespace ip
+{
+struct IP4Hdr;
+}
+typedef ip::IP4Hdr IP4Hdr;
+
void LogPriorityData(TextLog*, const Event*, bool doNewLine);
void LogXrefs(TextLog*, const Event*, bool doNewLine);
void LogTrHeader(TextLog*, Packet*);
void Log2ndHeader(TextLog*, Packet*);
void LogIpAddrs(TextLog*, Packet*);
-SO_PUBLIC void LogIpOptions(TextLog*, const Packet* const);
+void SO_PUBLIC LogIpOptions(TextLog*, const IP4Hdr*, const Packet* const);
void LogIPHeader(TextLog*, Packet*);
void LogTCPHeader(TextLog*, Packet*);
SO_PUBLIC void LogTcpOptions(TextLog*, const Packet* const);
#include "main/snort_config.h"
#include "packet_io/sfdaq.h"
#include "time/packet_time.h"
+#include "main/snort_debug.h"
+#include "sfip/sf_ip.h"
static int already_fatal = 0;
noinst_LIBRARIES = libloggers.a
libloggers_a_SOURCES = \
alert_luajit.cc \
+log_codecs.cc \
loggers.cc \
loggers.h
else if (!strcasecmp("tcp_len", type))
{
if (p->tcph != NULL)
- TextLog_Print(csv_log, "%d", TCP_OFFSET(p->tcph) << 2);
+ TextLog_Print(csv_log, "%d", (p->tcph->off()) << 2);
}
else if (!strcasecmp("tcp_win", type))
{
};
-const BaseApi* eh_codecs = &log_codecs_api.base;
+const BaseApi* log_codecs = &log_codecs_api.base;
#include "framework/logger.h"
// to ensure PacketManager::log_protocols() is built into Snort++
-extern const BaseApi* eh_codecs;
+extern const BaseApi* log_codecs;
extern const BaseApi* log_luajit;
#ifdef LINUX
eh_unified2,
#endif
// loggers
+ log_codecs,
log_luajit,
// both
- eh_codecs,
nullptr
};
#include "detection/fpcreate.h"
#include "filters/detection_filter.h"
#include "filters/sfthreshold.h"
+#include "sfip/sf_ip.h"
#if defined(DEBUG_MSGS) || defined (REG_TEST)
#include "file_api/file_api.h"
#include "framework/inspector.h"
#include "protocols/layer.h"
#include "protocols/arp.h"
+#include "sfip/sf_ip.h"
static const uint8_t bcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
#include "perf_monitor/perf.h"
#include "packet_io/sfdaq.h"
#include "protocols/ipv4.h"
+#include "protocols/ipv4_options.h"
#include "protocols/tcp.h"
+#include "protocols/tcp_options.h"
#include "stream/stream.h"
typedef enum {
uint8_t* opts = const_cast<uint8_t*>(p->layers[layer].start) + ip::IP4_HEADER_LEN;
uint8_t len = p->layers[layer].length - ip::IP4_HEADER_LEN;
// expect len > 0 because IHL yields a multiple of 4
- memset(opts, IPOPT_NOP, len);
+ memset(opts, static_cast<uint8_t>(ip::IPOptionCodes::NOP), len);
normStats[PC_IP4_OPTS]++;
sfBase.iPegs[PERF_COUNT_IP4_OPTS]++;
changes++;
static inline void NopDaOpt (uint8_t* opt, uint8_t len)
{
- memset(opt, TCPOPT_NOP, len);
+ memset(opt, (uint8_t)tcp::TcpOptCode::NOP , len);
}
#define TS_ECR_OFFSET 6
static inline int Norm_TCPOptions (
NormalizerConfig* config,
- uint8_t* opts, size_t len, const tcp::TCPHdr* h, uint8_t numOpts, int changes)
+ uint8_t* opts, size_t len, const tcp::TCPHdr* h, uint8_t validated_len, int changes)
{
size_t i = 0;
- uint8_t c = 0;
- while ( (i < len) && (opts[i] != TCPOPT_EOL) &&
- (c++ < numOpts) )
+ while ( (i < len) &&
+ (opts[i] != (uint8_t)tcp::TcpOptCode::EOL) &&
+ (i < validated_len) )
{
uint8_t olen = ( opts[i] <= 1 ) ? 1 : opts[i+1];
if ( i + olen > len)
break;
- switch ( opts[i] )
+ switch ( static_cast<tcp::TcpOptCode>(opts[i]) )
{
- case TCPOPT_NOP:
+ case tcp::TcpOptCode::NOP:
break;
- case TCPOPT_MAXSEG:
- case TCPOPT_WSCALE:
+ case tcp::TcpOptCode::MAXSEG:
+ case tcp::TcpOptCode::WSCALE:
if ( !(h->th_flags & TH_SYN) )
{
NopDaOpt(opts+i, olen);
}
break;
- case TCPOPT_TIMESTAMP:
+ case tcp::TcpOptCode::TIMESTAMP:
if ( !(h->th_flags & TH_ACK) &&
// use memcmp because opts have arbitrary alignment
memcmp(opts+i+TS_ECR_OFFSET, MAX_EOL_PAD, TS_ECR_LENGTH) )
}
static inline int Norm_TCPPadding (
- uint8_t* opts, size_t len, uint8_t numOpts, int changes)
+ uint8_t* opts, size_t len, uint8_t validated_len, int changes)
{
size_t i = 0;
- uint8_t c = 0;
- while ( (i < len) && (opts[i] != TCPOPT_EOL) && (c++ < numOpts) )
+ while ( (i < len) &&
+ (opts[i] != (uint8_t)tcp::TcpOptCode::EOL) &&
+ (i < validated_len) )
{
i += ( opts[i] <= 1 ) ? 1 : opts[i+1];
}
changes++;
}
- uint8_t tcp_options_len = p->tcph->options_len();
+ uint8_t tcp_options_len = h->options_len();
+
if ( tcp_options_len > 0 )
{
- uint8_t* opts = const_cast<uint8_t*>(p->layers[layer].start) + tcp::TCP_HEADER_LEN;
+ const Layer& lyr = p->layers[layer];
+ uint8_t* opts = const_cast<uint8_t*>(lyr.start) + tcp::TCP_HEADER_LEN;
+ // lyr.length only includes valid tcp options
+ uint8_t valid_opts_len = lyr.length - tcp::TCP_HEADER_LEN;
if ( Norm_IsEnabled(c, NORM_TCP_OPT) )
{
changes = Norm_TCPOptions(c, opts, tcp_options_len,
- h, p->tcp_option_count, changes);
+ h, valid_opts_len, changes);
}
else
{
changes = Norm_TCPPadding(opts, tcp_options_len,
- p->tcp_option_count, changes);
+ valid_opts_len, changes);
}
}
return changes;
#include "util.h"
#include "snort_types.h"
#include "perf.h"
+#include "sfip/sf_ip.h"
static void DisplayFlowStats(SFFLOW_STATS *sfFlowStats);
static void WriteFlowStats(SFFLOW_STATS *, FILE *);
#include "sfxhash.h"
#include "ipobj.h"
#include "stream/stream_api.h"
+#include "sfip/sf_ip.h"
typedef struct s_PS_HASH_KEY
{
#include "snort_debug.h"
#include "snort.h"
#include "utils/util.h"
+#include "sfip/sf_ip.h"
//------------------------------------------------------------------------------
// interface stuff
#include "target_based/sftarget_reader.h"
#include "managers/event_manager.h"
#include "detection/detect.h"
+#include "sfip/sf_ip.h"
#define LOG_NONE "none"
#define LOG_TEXT "text"
unsigned idx = 0, len = strlen(in);
negate = false;
- uint8_t hex;
- unsigned nx;
+ uint8_t hex = 0;
+ unsigned nx = 0;
bool ok = true;
while ( ok && (idx < len) )
icmp6.h
ip.h
ipv4.h
+ ipv4_options.h
ipv6.h
gre.h
layer.h
packet_manager.h
protocol_ids.h
tcp.h
+ tcp_options.h
teredo.h
token_ring.h
udp.h
${PROTOCOL_HEADERS}
layer.cc
ip.cc
+ ipv4_options.cc
+ tcp_options.cc
packet_manager.cc
)
icmp6.h \
ip.h \
ipv4.h \
+ipv4_options.h \
ipv6.h \
gre.h \
layer.h \
packet_manager.h \
protocol_ids.h \
tcp.h \
+tcp_options.h \
teredo.h \
token_ring.h \
udp.h \
libprotocols_a_SOURCES = \
layer.cc \
packet_manager.cc \
-ip.cc
+ip.cc \
+ipv4_options.cc \
+tcp_options.cc
AM_CXXFLAGS = @AM_CXXFLAGS@
// ip.cc author Josh Rosenbaum <jrosenba@cisco.com>
#include <arpa/inet.h>
+#include <limits>
#include "protocols/ip.h"
#include "protocols/packet.h"
{
ip4h = h4;
ip6h = nullptr;
- src_p = nullptr;
- dst_p = nullptr;
+
+ src.family = AF_INET;
+ src.bits = 32;
+ src.ip32[0] = *(uint32_t*)(&ip4h->ip_src);
+ std::memset(&(src.ip32[1]), 0, 12);
+ src_p = &src;
+
+ dst.family = AF_INET;
+ dst.bits = 32;
+ dst.ip32[0] = *(uint32_t*)(&ip4h->ip_dst);
+ std::memset(&(dst.ip32[1]), 0, 12);
+ dst_p = &dst;
}
void IpApi::set(const ip::IP6Hdr* h6)
{
ip6h = h6;
ip4h = nullptr;
- src_p = nullptr;
- dst_p = nullptr;
+
+ src.family = AF_INET6;
+ src.bits = 128;
+ std::memcpy(&(src.ip8), &(ip6h->ip6_src), 16);
+ src_p = &src;
+
+ dst.family = AF_INET6;
+ dst.bits = 128;
+ std::memcpy(&(dst.ip8), &(ip6h->ip6_dst), 16);
+ dst_p = &dst;
}
bool IpApi::set(const uint8_t* raw_ip_data)
return true;
}
- const ip::IP6Hdr* h6 =
- reinterpret_cast<const ip::IP6Hdr*>(raw_ip_data);
-
- if (h6->get_ver() != 6)
- return false;
-
- set(h6);
- return true;
-}
-
-const sfip_t *IpApi::get_src()
-{
- if (src_p)
- return src_p;
-
- if(ip4h)
- {
- src.family = AF_INET;
- src.bits = 32;
-
- // TODO: Make this a pointer rather than copying
- // will likely need to change Snort++
- src.ip32[0] = *(uint32_t*)(&ip4h->ip_src);
- std::memset(&(src.ip32[1]), 0, 12);
- }
- else if (ip6h)
- {
- src.family = AF_INET6;
- src.bits = 128;
-
- std::memcpy(&(src.ip8), &(ip6h->ip6_src), 16);
- }
- else
- {
- return nullptr;
- }
+ const IP6Hdr* h6 = reinterpret_cast<const IP6Hdr*>(raw_ip_data);
- src_p = &src;
- return src_p;
-}
-
-
-const sfip_t *IpApi::get_dst()
-{
- if (dst_p)
- return dst_p;
-
- if(ip4h)
- {
- dst.family = AF_INET;
- dst.bits = 32;
-
- // TODO: Make this a pointer rather than copying
- // will likely need to change Snort++
- dst.ip32[0] = *(uint32_t*)(&ip4h->ip_dst);
- std::memset(&(dst.ip32[1]), 0, 12);
- }
- else if (ip6h)
- {
- dst.family = AF_INET6;
- dst.bits = 128;
- std::memcpy(&(dst.ip8), &(ip6h->ip6_dst), 16);
- }
- else
+ if (h6->get_ver() == 6)
{
- return nullptr;
+ set(h6);
+ return true;
}
- dst_p = &dst;
- return dst_p;
-
+ return false;
}
uint32_t IpApi::id(const Packet* const p) const
return ip4h->get_id();
// ensure we have an ipv6 frag
- if (p->ip6_extension_count == 0 || p->ip_frag_start == 0 || !ip6h )
+ if (!ip6h || p->ip6_frag_index == std::numeric_limits<uint8_t>::max())
return 0;
const IP6Frag* const frag_hdr = reinterpret_cast<const IP6Frag* const>(
uint16_t IpApi::off(const Packet* const p) const
{
if (ip4h)
- return (uint32_t)ip4h->get_id();
+ return (uint32_t)ip4h->get_off();
// ensure we have an ipv6 frag
- if (p->ip6_extension_count == 0 || p->ip_frag_start == 0 || !ip6h)
+ if (!ip6h || p->ip6_frag_index == std::numeric_limits<uint8_t>::max())
return 0;
const IP6Frag* const frag_hdr = reinterpret_cast<const IP6Frag* const>(
void set(const IP6Hdr* h6);
bool set(const uint8_t* raw_ip_data);
void reset();
- const sfip_t *get_src();
- const sfip_t *get_dst();
uint32_t id(const Packet* const p) const;
uint16_t off(const Packet* const p) const;
// returns a pointer to this ip layer's data
inline const IP6Hdr* get_ip6h() const
{ return ip6h; }
+ inline const sfip_t *get_src() const
+ { return src_p; }
+
+ inline const sfip_t *get_dst() const
+ { return dst_p; }
+
inline uint16_t tos() const
{ return ip4h ? ip4h->get_tos() : ip6h ? ip6h->get_tos() : 0; }
#include "protocols/protocol_ids.h" // include ipv4 protocol numbers
-
-
#define ETHERNET_TYPE_IP 0x0800
#ifndef IP_MAXPACKET
constexpr uint8_t IP4_LOOPBACK = 0x7F; // msb
-enum class IPOptionCodes : std::uint8_t {
- EOL = 0x00,
- NOP = 0x01,
- RR = 0x07,
- TS = 0x44,
- SECURITY = 0x82,
- LSRR = 0x83,
- LSRR_E = 0x84,
- ESEC = 0x85,
- SATID = 0x88,
- SSRR = 0x89,
- RTRALT = 0x94,
- ANY = 0xff,
-};
-
-
-struct IpOptions
-{
- uint8_t code;
- uint8_t len; /* length of the data section */
- const uint8_t *data;
-
- inline bool is_opt_rtralt() const
- { return code == static_cast<uint8_t>(IPOptionCodes::RTRALT); }
-
- inline bool is_opt_ts() const
- { return code == static_cast<uint8_t>(IPOptionCodes::TS); }
-
- inline bool is_opt_rr() const
- { return code == static_cast<uint8_t>(IPOptionCodes::RR); }
-};
-
// This must be a standard layour struct!
struct IP4Hdr
inline bool is_dst_broadcast() const
{ return ip_dst == IP4_BROADCAST; }
+ inline bool has_options() const
+ { return get_hlen() > 5; }
+
/* setters */
inline void set_hlen(uint8_t value)
{ ip_verhl = (ip_verhl & 0xf0) | (value & 0x0f); }
} ;
+
static inline bool isPrivateIP(uint32_t addr)
{
switch (addr & 0xff)
} /* namespace ip */
+
+
/* tcpdump shows us the way to cross platform compatibility */
/* we need to change them as well as get them */
// TYPEDEF WHICH NEED TO BE DELETED
-
typedef ip::IP4Hdr IP4Hdr;
-constexpr uint8_t IPOPT_EOL = 0x00;
-constexpr uint8_t IPOPT_NOP = 0x01;
-constexpr uint8_t IPOPT_RR = 0x07;
-constexpr uint8_t IPOPT_TS = 0x44;
-constexpr uint8_t IPOPT_SECURITY = 0x82;
-constexpr uint8_t IPOPT_LSRR = 0x83;
-constexpr uint8_t IPOPT_LSRR_E = 0x84;
-constexpr uint8_t IPOPT_ESEC = 0x85;
-constexpr uint8_t IPOPT_SATID = 0x88;
-constexpr uint8_t IPOPT_SSRR = 0x89;
-constexpr uint8_t IPOPT_RTRALT = 0x94;
-constexpr uint8_t IPOPT_ANY = 0xff;
-
/* #define IP_HEADER_LEN ip::ip4_hdr_len() */
--- /dev/null
+/*
+** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
+** Copyright (C) 2007-2013 Sourcefire, Inc.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License Version 2 as
+** published by the Free Software Foundation. You may not use, modify or
+** distribute this program under any other version of the GNU General
+** Public License.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+// ipv4_options.cc author Josh Rosenbaum <jrosenba@cisco.com>
+
+#include "protocols/ipv4_options.h"
+#include "protocols/ipv4.h"
+#include "protocols/layer.h"
+#include "protocols/packet.h"
+
+namespace ip
+{
+
+
+IpOptionIteratorIter::IpOptionIteratorIter(const IpOptions* first_opt) : opt(first_opt)
+{ }
+
+const IpOptions& IpOptionIteratorIter::operator* () const
+{ return *opt; }
+
+
+IpOptionIterator::IpOptionIterator(const IP4Hdr* const ip4_header, const Packet* const p)
+{
+ const uint8_t* const hdr = (const uint8_t* const)ip4_header;
+ start_ptr = hdr + IP4_HEADER_LEN;
+ end_ptr = start_ptr;
+
+ for (int i = p->num_layers-1; i >= 0; --i)
+ {
+ if (p->layers[i].start == (const uint8_t*)ip4_header)
+ {
+ // the Options do not necessarily include
+ // the entire header
+ end_ptr = (hdr + p->layers[i].length);
+ return;
+ }
+ }
+}
+
+
+
+IpOptionIterator::IpOptionIterator(const IP4Hdr* const ip4_header, const uint8_t valid_hdr_len)
+{
+ const uint8_t* const hdr = (const uint8_t* const)ip4_header;
+ start_ptr = hdr + IP4_HEADER_LEN;
+
+ if (valid_hdr_len < IP4_HEADER_LEN)
+ end_ptr = start_ptr;
+ else
+ end_ptr = hdr + valid_hdr_len;
+}
+
+IpOptionIteratorIter IpOptionIterator::begin() const
+{
+ return IpOptionIteratorIter(reinterpret_cast<const IpOptions*>(start_ptr));
+}
+
+IpOptionIteratorIter IpOptionIterator::end() const
+{
+ return IpOptionIteratorIter(reinterpret_cast<const IpOptions*>(end_ptr));
+}
+
+
+} // namespace ip
--- /dev/null
+/*
+** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
+** Copyright (C) 2007-2013 Sourcefire, Inc.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License Version 2 as
+** published by the Free Software Foundation. You may not use, modify or
+** distribute this program under any other version of the GNU General
+** Public License.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+// ipv4_options.H author Josh Rosenbaum <jrosenba@cisco.com>
+
+#ifndef PROTOCOLS_IP_OPTIONS_H
+#define PROTOCOLS_IP_OPTIONS_H
+
+#include <cstdint>
+
+struct Packet;
+
+
+namespace ip
+{
+
+struct IP4Hdr;
+
+enum class IPOptionCodes : std::uint8_t {
+ EOL = 0x00,
+ NOP = 0x01,
+ RR = 0x07,
+ TS = 0x44,
+ SECURITY = 0x82,
+ LSRR = 0x83,
+ LSRR_E = 0x84,
+ ESEC = 0x85,
+ SATID = 0x88,
+ SSRR = 0x89,
+ RTRALT = 0x94,
+ ANY = 0xff,
+};
+
+
+struct IpOptions
+{
+ IPOptionCodes code;
+ uint8_t len;
+ uint8_t data[6]; // arbitrary number. choosing six to align with 64 bits
+
+ inline uint8_t get_len() const
+ { return ((uint8_t)code <= 1) ? 1 : len; }
+
+ inline const uint8_t* get_data() const
+ { return (((uint8_t)code <= 1) || (len < 2)) ? nullptr : &data[0]; }
+
+ inline const IpOptions& next() const
+ {
+
+ // because gcc requires strict aliasing.
+# if defined(__GNUC__)
+ const uint8_t tmp_len = ((uint8_t) code <= 1) ? 1 : len;
+ const uint8_t* const tmp = reinterpret_cast<const uint8_t*>(this);
+ const IpOptions* opt = reinterpret_cast<const IpOptions*>(&tmp[tmp_len]);
+ return *opt;
+
+ // ... and the legible code
+# else
+ if ( (uint8_t)code <= 1 )
+ return reinterpret_cast<const IpOptions&>(len);
+ else
+ return reinterpret_cast<const IpOptions&>(data[len -2]);
+# endif
+ }
+};
+
+/*
+ * relly creative name ... right
+ * Use IpOptionIter ... this is the placehold
+ */
+class IpOptionIteratorIter
+{
+public:
+ IpOptionIteratorIter(const IpOptions*);
+
+ bool operator== (const IpOptionIteratorIter& rhs)
+ { return opt == rhs.opt; }
+
+ bool operator!= (const IpOptionIteratorIter& rhs)
+ { return opt != rhs.opt; }
+
+ // I'd suggest just using IpOptionIterator and completley ignoring this
+ // horror of a ++ operation.
+ IpOptionIteratorIter& operator++()
+ {
+ opt = &opt->next();
+ return *this;
+ }
+
+ const IpOptions& operator* () const;
+
+private:
+ const IpOptions* opt;
+};
+
+/*
+ * relly creative name ... right
+ * Use IP ranged for loop rather than calling this directly.
+ * i.e.,
+ * IpOptionIter iter(ip4h, p)
+ * for (auto i : iter)
+ * {
+ * do_something
+ * }
+ */
+class IpOptionIterator
+{
+public:
+ /* CONSTRUCTOR VALID AFTER DECODE()
+ * Some options in the provided header may not be valid.
+ * Provide the packet struct ensures only valid options
+ * will be returned
+ */
+ IpOptionIterator(const IP4Hdr* const, const Packet* const);
+ /* If you already know the validated option length (for instance,
+ * if you are in a decode() method), then call this constructor.
+ * You MUST validate the a;; ip_options within len before
+ * using this constuctor*/
+ IpOptionIterator(const IP4Hdr* const, const uint8_t valid_hdr_len);
+ IpOptionIteratorIter begin() const;
+ IpOptionIteratorIter end() const;
+
+private:
+ const uint8_t* end_ptr;
+ const uint8_t* start_ptr;
+};
+
+} // namespace ip
+
+
+#endif /* PROTOCOLS_IP_OPTIONS_H */
return nullptr;
}
-
uint8_t get_outer_ip_next_pro(const Packet* const p)
{
const Layer* layers = p->layers;
{
case ETHERTYPE_IPV4:
case IPPROTO_ID_IPIP:
- return reinterpret_cast<const IP4Hdr*>(layers[i].start)->get_proto();
+ return reinterpret_cast<const ip::IP4Hdr*>(layers[i].start)->get_proto();
case ETHERTYPE_IPV6:
case IPPROTO_ID_IPV6:
return reinterpret_cast<const ip::IP6Hdr*>(layers[i].start)->get_next();
return -1;
}
-int get_inner_ip_lyr(const Packet* const p)
+int get_inner_ip_lyr_index(const Packet* const p)
{
const Layer* layers = p->layers;
struct Layer {
+ const uint8_t* start;
uint16_t prot_id;
- PROTO_ID proto;
uint16_t length;
- const uint8_t* start;
+// uint16_t invalid_bytes; -- Commented out since nothing uses this
+ /*
+ * Data which should not be considered part of
+ * this layer's valid data, but must be skipped
+ * before the next layer. For instance, an invalid
+ * ip option. It should not be part of length but
+ * must be skipped before the next layer.
+ *
+ * Generally calculated by
+ * (layers_entire_length) - length;
+ * (ip::IP4Hdr*) ip4h->get_hlen() * 4 - length;
+ */
+ PROTO_ID proto;
};
SO_PUBLIC const uint8_t* get_root_layer(const Packet* const);
/* return a pointer to the outermost UDP layer */
SO_PUBLIC const udp::UDPHdr* get_outer_udp_lyr(const Packet* const);
+// return the inner ip layer's index in the p->layers array
+SO_PUBLIC int get_inner_ip_lyr_index(const Packet* const p);
+
// ICMP with Embedded IP layer
// true - ip layer found and api set
// false - ip layer NOT found, api reset
SO_PUBLIC bool set_api_ip_embed_icmp(const Packet*, ip::IpApi& api);
-
// a helper function when the api to be set is inside the packet
SO_PUBLIC bool set_api_ip_embed_icmp(const Packet* p);
SO_PUBLIC const tcp::TCPHdr* get_tcp_embed_icmp(const ip::IpApi&);
SO_PUBLIC const udp::UDPHdr* get_udp_embed_icmp(const ip::IpApi&);
SO_PUBLIC const icmp::ICMPHdr* get_icmp_embed_icmp(const ip::IpApi&);
-
-
-
-SO_PUBLIC int get_inner_ip_lyr(const Packet* const p);
-
/*
* Starting from layer 'curr_layer', continuing looking at increasingly
* outermost layer for another IP protocol. If an IP protocol is found,
}
#include "main/snort_types.h"
-#include "sfip/sf_ip.h"
#include "protocols/tcp.h"
class Flow;
-struct Options
-{
- uint8_t code;
- uint8_t len; /* length of the data section */
- const uint8_t *data;
-} ;
-
-
-
struct Packet
{
uint16_t sp; /* source port (TCP/UDP) */
uint16_t dp; /* dest port (TCP/UDP) */
-
- uint16_t frag_offset; /* fragment offset number */
- uint16_t ip_frag_len;
-
-
-
- uint8_t ip_option_count; /* number of options in this packet */
- uint8_t tcp_option_count;
- uint8_t ip6_extension_count;
- uint8_t ip6_frag_index;
-
uint8_t error_flags; /* flags indicate checksum errors, bad TTLs, etc. */
uint8_t num_layers; /* index into layers for next encap */
uint8_t decode_flags; /* flags used while decoding */
const uint8_t* data; /* packet payload pointer */
uint16_t dsize; /* packet payload size */
- ip::IpOptions ip_options[IP_OPTMAX]; /* ip options decode structure */
- Options tcp_options[TCP_OPTLENMAX]; /* tcp options decode struct */
+ uint8_t ip6_frag_index;
uint8_t curr_ip6_extension_order;
-
- const uint8_t *ip_frag_start;
+ uint8_t ip6_extension_count;
+ uint8_t byte_skip; /* when decoding, there are <byte_skip> bytes between the end of the layer and the start of the next layer */
Layer layers[LAYER_MAX]; /* decoded encapsulations */
uint16_t user_policy_id;
uint32_t iplist_id;
- unsigned char iprep_layer;
uint8_t ps_proto; // Used for portscan and unified2 logging
#include "codecs/decode_module.h"
#include "utils/stats.h"
#include "log/text_log.h"
+#include "main/snort_debug.h"
#ifdef PERF_PROFILING
uint32_t len,
Codec *const cd)
{
- if ( p->num_layers < LAYER_MAX )
- {
- Layer& lyr = p->layers[p->num_layers++];
- lyr.proto = cd->get_proto_id();
- lyr.prot_id = prot_id;
- lyr.start = hdr_start;
- lyr.length = (uint16_t)len;
- }
- else
- {
- //FIXIT-M Alert when max layers maxed out.
- LogMessage("(packet_manager) WARNING: decoder has too many layers;"
- " next proto is something.\n");
- }
+
+ // We check to ensure num_layer < MAX_LAYERS before this function call
+ Layer& lyr = p->layers[p->num_layers++];
+ lyr.proto = cd->get_proto_id();
+ lyr.prot_id = prot_id;
+ lyr.start = hdr_start;
+ lyr.length = (uint16_t)len;
+// lyr.invalid_bits = p->byte_skip; -- currently unused
}
//-------------------------------------------------------------------------
mapped_prot = CodecManager::s_proto_map[prot_id];
prev_prot_id = prot_id;
+ lyr_len += p->byte_skip;
+
// set for next call
prot_id = FINISHED_DECODE;
len -= lyr_len;
pkt += lyr_len;
lyr_len = 0;
+ p->byte_skip = 0;
}
DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Codec %s (protocol_id: %hu: ip header"
if ( f & ENC_FLAG_NET )
{
- num_layers = layer::get_inner_ip_lyr(p) + 1;
+ num_layers = layer::get_inner_ip_lyr_index(p) + 1;
// TBD: is this an extraneous check?
if (num_layers == 0)
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// codec_manager.h author Josh Rosenbaum <jrosenba@cisco.com>
+// packet_manager.h author Josh Rosenbaum <jrosenba@cisco.com>
-#ifndef MANAGERS_PACKET_MANAGER_H
-#define MANAGERS_PACKET_MANAGER_H
+#ifndef PROTOCOLS_PACKET_MANAGER_H
+#define PROTOCOLS_PACKET_MANAGER_H
#include <array>
#include <list>
static Packet* encode_new(void);
// release the allocated Packet
static void encode_delete(Packet*);
+
+ // when encoding, rather than copy the destination MAC address from the
+ // inbound packet, manually set the MAC address.
+ static void encode_set_dst_mac(uint8_t* );
+ // get the MAC address which has been set using encode_set_dst_mac().
+ // Useful for root decoders setting the MAC address
+ static uint8_t *encode_get_dst_mac();
// update the packet's checksums and length variables. Call this function
// after Snort has changed any data in this packet
static void encode_update(Packet*);
static const uint8_t* encode_response(
EncodeType, EncodeFlags, const Packet* orig, uint32_t* len,
const uint8_t* payLoad, uint32_t payLen);
- // when encoding, rather than copy the destination MAC address from the
- // inbound packet, manually set the MAC address.
- static void encode_set_dst_mac(uint8_t* );
- // get the MAC address which has been set using encode_set_dst_mac().
- // Useful for root decoders setting the MAC address
- static uint8_t *encode_get_dst_mac();
// wrapper for encode response. Ensure no payload is encoded.
static inline const uint8_t* encode_reject( EncodeType type,
-
/*
* Below is a partial list of ethertypes.
* Defined at:
#include <cstdint>
-
// these are bits in th_flags:
#define TH_FIN 0x01
#define TH_SYN 0x02
#define SOL_TCP 6 /* TCP level */
-/* tcp option codes */
-#define TOPT_EOL 0x00
-#define TOPT_NOP 0x01
-#define TOPT_MSS 0x02
-#define TOPT_WS 0x03
-#define TOPT_TS 0x08
-
namespace tcp
{
inline uint8_t options_len() const
{ return hdr_len() - TCP_HEADER_LEN; }
-};
-
-
-#if 0
-inline uint8_t hdr_len()
-{
- return detail::TCP_HEADER_LEN;
-}
-#endif
-
-inline uint8_t get_tcp_hdr_len(const TCPHdr *h)
-{
- return ((h->th_offx2 & 0xf0) >> 2);
-}
-
-/* http://www.iana.org/assignments/tcp-parameters
- *
- * tcp options stuff. used to be in <netinet/tcp.h> but it breaks
- * things on AIX
- */
-// enum class TcpOpt{
-enum TcpOpt{
- EOL = 0, /* End of Option List [RFC793] */
- NOP = 1, /* No-Option [RFC793] */
- MAXSEG = 2, /* Maximum Segment Size [RFC793] */
- WSCALE = 3, /* Window scaling option [RFC1323] */
- SACKOK = 4, /* Experimental [RFC2018]*/
- SACK = 5, /* Experimental [RFC2018] variable length */
- ECHO = 6, /* Echo (obsoleted by option 8) [RFC1072] */
- ECHOREPLY = 7, /* Echo Reply (obsoleted by option 8)[RFC1072] */
- TIMESTAMP = 8, /* Timestamp [RFC1323], 10 bytes */
- PARTIAL_PERM = 9, /* Partial Order Permitted/ Experimental [RFC1693] */
- PARTIAL_SVC = 10, /* Partial Order Profile [RFC1693] */
- CC = 11, /* T/TCP Connection count [RFC1644] */
- CC_NEW = 12, /* CC.NEW [RFC1644] */
- CC_ECHO = 13, /* CC.ECHO [RFC1644] */
+ inline bool has_options() const
+ { return (th_offx2 & 0xf0) == 0x50; }
- ALTCSUM = 15, /* TCP Alternate Checksum Data [RFC1146], variable length */
- SKEETER = 16, /* Skeeter [Knowles] */
- BUBBA = 17, /* Bubba [Knowles] */
- TRAILER_CSUM = 18, /* Trailer Checksum Option [Subbu & Monroe] */
- MD5SIG = 19, /* MD5 Signature Option [RFC2385] */
+ inline bool are_flags_set(uint8_t flags) const
+ { return (th_flags & flags) == flags; }
-
- /* Space Communications Protocol Standardization */
- SCPS = 20, /* Capabilities [Scott] */
- SELNEGACK = 21, /* Selective Negative Acknowledgements [Scott] */
- RECORDBOUND = 22, /* Record Boundaries [Scott] */
- CORRUPTION = 23, /* Corruption experienced [Scott] */
- SNAP = 24, /* SNAP [Sukonnik] -- anyone have info?*/
- UNASSIGNED = 25, /* Unassigned (released 12/18/00) */
- COMPRESSION = 26, /* TCP Compression Filter [Bellovin] */
- /* http://www.research.att.com/~smb/papers/draft-bellovin-tcpcomp-00.txt*/
-
- AUTH = 29, /* [RFC5925] - The TCP Authentication Option
- Intended to replace MD5 Signature Option [RFC2385] */
+ // setters
+ inline void set_offset(uint8_t val)
+ { th_offx2 = (uint8_t)((th_offx2 & 0x0f) | (val << 4)); }
};
-inline void set_tcp_offset(TCPHdr *tcph, uint8_t value)
-{
- tcph->th_offx2 = (uint8_t)((tcph->th_offx2 & 0x0f) | (value << 4));
-}
-
-inline void set_tcp_x2(TCPHdr* tcph, uint8_t value)
-{
- tcph->th_offx2 = (tcph->th_offx2 & 0xf0) | (value & 0x0f);
-}
-
-#define TCPOLEN_EOL 1 /* Always one byte */
-#define TCPOLEN_NOP 1 /* Always one byte */
-#define TCPOLEN_MAXSEG 4 /* Always 4 bytes */
-#define TCPOLEN_WSCALE 3 /* 1 byte with logarithmic values */
-#define TCPOLEN_SACKOK 2
-#define TCPOLEN_ECHO 6 /* 6 bytes */
-#define TCPOLEN_ECHOREPLY 6 /* 6 bytes */
-#define TCPOLEN_TIMESTAMP 10
-#define TCPOLEN_PARTIAL_PERM 2 /* Partial Order Permitted/ Experimental [RFC1693] */
-#define TCPOLEN_PARTIAL_SVC 3 /* 3 bytes long -- Experimental */
-
-/* atleast decode T/TCP options... */
-#define TCPOLEN_CC 6 /* page 17 of rfc1644 */
-#define TCPOLEN_CC_NEW 6 /* page 17 of rfc1644 */
-#define TCPOLEN_CC_ECHO 6 /* page 17 of rfc1644 */
-#define TCPOLEN_TRAILER_CSUM 3
-#define TCPOLEN_MD5SIG 18
/* more macros for TCP offset */
-#define TCP_OFFSET(tcph) (((tcph)->th_offx2 & 0xf0) >> 4)
-#define TCP_X2(tcph) ((tcph)->th_offx2 & 0x0f)
-
#define TCP_ISFLAGSET(tcph, flags) (((tcph)->th_flags & (flags)) == (flags))
-/* delete everything from here to the end of the file (excluding the #endif of course) */
-
-#define TCPOPT_EOL 0 /* End of Option List [RFC793] */
-#define TCPOLEN_EOL 1 /* Always one byte */
-
-#define TCPOPT_NOP 1 /* No-Option [RFC793] */
-#define TCPOLEN_NOP 1 /* Always one byte */
-
-#define TCPOPT_MAXSEG 2 /* Maximum Segment Size [RFC793] */
-#define TCPOLEN_MAXSEG 4 /* Always 4 bytes */
-
-#define TCPOPT_WSCALE 3 /* Window scaling option [RFC1323] */
-#define TCPOLEN_WSCALE 3 /* 1 byte with logarithmic values */
-
-#define TCPOPT_SACKOK 4 /* Experimental [RFC2018]*/
-#define TCPOLEN_SACKOK 2
-
-#define TCPOPT_SACK 5 /* Experimental [RFC2018] variable length */
-
-#define TCPOPT_ECHO 6 /* Echo (obsoleted by option 8) [RFC1072] */
-#define TCPOLEN_ECHO 6 /* 6 bytes */
-
-#define TCPOPT_ECHOREPLY 7 /* Echo Reply (obsoleted by option 8)[RFC1072] */
-#define TCPOLEN_ECHOREPLY 6 /* 6 bytes */
-
-#define TCPOPT_TIMESTAMP 8 /* Timestamp [RFC1323], 10 bytes */
-#define TCPOLEN_TIMESTAMP 10
-
-#define TCPOPT_PARTIAL_PERM 9 /* Partial Order Permitted/ Experimental [RFC1693] */
-#define TCPOLEN_PARTIAL_PERM 2 /* Partial Order Permitted/ Experimental [RFC1693] */
-
-#define TCPOPT_PARTIAL_SVC 10 /* Partial Order Profile [RFC1693] */
-#define TCPOLEN_PARTIAL_SVC 3 /* 3 bytes long -- Experimental */
-
-/* atleast decode T/TCP options... */
-#define TCPOPT_CC 11 /* T/TCP Connection count [RFC1644] */
-#define TCPOPT_CC_NEW 12 /* CC.NEW [RFC1644] */
-#define TCPOPT_CC_ECHO 13 /* CC.ECHO [RFC1644] */
-#define TCPOLEN_CC 6 /* page 17 of rfc1644 */
-#define TCPOLEN_CC_NEW 6 /* page 17 of rfc1644 */
-#define TCPOLEN_CC_ECHO 6 /* page 17 of rfc1644 */
-
-#define TCPOPT_ALTCSUM 15 /* TCP Alternate Checksum Data [RFC1146], variable length */
-#define TCPOPT_SKEETER 16 /* Skeeter [Knowles] */
-#define TCPOPT_BUBBA 17 /* Bubba [Knowles] */
-
-#define TCPOPT_TRAILER_CSUM 18 /* Trailer Checksum Option [Subbu & Monroe] */
-#define TCPOLEN_TRAILER_CSUM 3
-
-#define TCPOPT_MD5SIG 19 /* MD5 Signature Option [RFC2385] */
-#define TCPOLEN_MD5SIG 18
-
-/* Space Communications Protocol Standardization */
-#define TCPOPT_SCPS 20 /* Capabilities [Scott] */
-#define TCPOPT_SELNEGACK 21 /* Selective Negative Acknowledgements [Scott] */
-#define TCPOPT_RECORDBOUND 22 /* Record Boundaries [Scott] */
-#define TCPOPT_CORRUPTION 23 /* Corruption experienced [Scott] */
-
-#define TCPOPT_SNAP 24 /* SNAP [Sukonnik] -- anyone have info?*/
-#define TCPOPT_UNASSIGNED 25 /* Unassigned (released 12/18/00) */
-#define TCPOPT_COMPRESSION 26 /* TCP Compression Filter [Bellovin] */
-/* http://www.research.att.com/~smb/papers/draft-bellovin-tcpcomp-00.txt*/
-
-#define TCPOPT_AUTH 29 /* [RFC5925] - The TCP Authentication Option
- Intended to replace MD5 Signature Option [RFC2385] */
-
#endif /* TCP_H */
--- /dev/null
+/*
+** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
+** Copyright (C) 2007-2013 Sourcefire, Inc.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License Version 2 as
+** published by the Free Software Foundation. You may not use, modify or
+** distribute this program under any other version of the GNU General
+** Public License.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+// tcp_options.cc author Josh Rosenbaum <jrosenba@cisco.com>
+
+#include "protocols/tcp_options.h"
+#include "protocols/tcp.h"
+#include "protocols/layer.h"
+#include "protocols/packet.h"
+
+namespace tcp
+{
+
+
+TcpOptIteratorIter::TcpOptIteratorIter(const TcpOption* first_opt) : opt(first_opt)
+{
+}
+
+const TcpOption& TcpOptIteratorIter::operator* () const
+{ return *opt; }
+
+
+TcpOptIterator::TcpOptIterator(const TCPHdr* const tcp_header, const Packet* const p)
+{
+ const uint8_t* const hdr = (const uint8_t* const)tcp_header;
+ start_ptr = hdr + TCP_HEADER_LEN;
+ end_ptr = start_ptr; // == begin()
+
+ for (int i = p->num_layers-1; i >= 0; --i)
+ {
+ if (p->layers[i].start == (const uint8_t*)tcp_header)
+ {
+ // the Options do not necessarily include
+ // the entire header. However, length has
+ // been validated during decode
+ end_ptr = (hdr + p->layers[i].length);
+ return;
+ }
+ }
+}
+
+
+TcpOptIterator::TcpOptIterator(const TCPHdr* const tcp_header, const uint32_t valid_hdr_len)
+{
+ const uint8_t* const hdr = (const uint8_t* const)tcp_header;
+ start_ptr = hdr + TCP_HEADER_LEN;
+
+ if (valid_hdr_len < TCP_HEADER_LEN)
+ end_ptr = start_ptr;
+ else
+ end_ptr = hdr + valid_hdr_len;
+}
+
+
+TcpOptIteratorIter TcpOptIterator::begin() const
+{
+ return TcpOptIteratorIter(reinterpret_cast<const TcpOption*>(start_ptr));
+}
+
+TcpOptIteratorIter TcpOptIterator::end() const
+{
+ return TcpOptIteratorIter(reinterpret_cast<const TcpOption*>(end_ptr));
+}
+
+
+} // namespace ip
--- /dev/null
+/*
+** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
+** Copyright (C) 2007-2013 Sourcefire, Inc.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License Version 2 as
+** published by the Free Software Foundation. You may not use, modify or
+** distribute this program under any other version of the GNU General
+** Public License.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+// tcp_options.h author Josh Rosenbaum <jrosenba@cisco.com>
+
+#ifndef PROTOCOLS_TCP_OPTIONS_H
+#define PROTOCOLS_TCP_OPTIONS_H
+
+#include <cstdint>
+
+struct Packet;
+
+
+namespace tcp
+{
+
+struct TCPHdr;
+
+/* http://www.iana.org/assignments/tcp-parameters
+ *
+ * tcp options stuff. used to be in <netinet/tcp.h> but it breaks
+ * things on AIX
+ */
+
+enum class TcpOptCode : std::uint8_t {
+ EOL = 0, /* End of Option List [RFC793] */
+ NOP = 1, /* No-Option [RFC793] */
+ MAXSEG = 2, /* Maximum Segment Size [RFC793] */
+ WSCALE = 3, /* Window scaling option [RFC1323] */
+ SACKOK = 4, /* Experimental [RFC2018]*/
+ SACK = 5, /* Experimental [RFC2018] variable length */
+ ECHO = 6, /* Echo (obsoleted by option 8) [RFC1072] */
+ ECHOREPLY = 7, /* Echo Reply (obsoleted by option 8)[RFC1072] */
+ TIMESTAMP = 8, /* Timestamp [RFC1323], 10 bytes */
+ PARTIAL_PERM = 9, /* Partial Order Permitted/ Experimental [RFC1693] */
+ PARTIAL_SVC = 10, /* Partial Order Profile [RFC1693] */
+ CC = 11, /* T/TCP Connection count [RFC1644] */
+ CC_NEW = 12, /* CC.NEW [RFC1644] */
+ CC_ECHO = 13, /* CC.ECHO [RFC1644] */
+
+ ALTCSUM = 15, /* TCP Alternate Checksum Data [RFC1146], variable length */
+ SKEETER = 16, /* Skeeter [Knowles] */
+ BUBBA = 17, /* Bubba [Knowles] */
+ TRAILER_CSUM = 18, /* Trailer Checksum Option [Subbu & Monroe] */
+ MD5SIG = 19, /* MD5 Signature Option [RFC2385] */
+
+
+ /* Space Communications Protocol Standardization */
+ SCPS = 20, /* Capabilities [Scott] */
+ SELNEGACK = 21, /* Selective Negative Acknowledgements [Scott] */
+ RECORDBOUND = 22, /* Record Boundaries [Scott] */
+ CORRUPTION = 23, /* Corruption experienced [Scott] */
+ SNAP = 24, /* SNAP [Sukonnik] -- anyone have info?*/
+ UNASSIGNED = 25, /* Unassigned (released 12/18/00) */
+ COMPRESSION = 26, /* TCP Compression Filter [Bellovin] */
+ /* http://www.research.att.com/~smb/papers/draft-bellovin-tcpcomp-00.txt*/
+
+ AUTH = 29, /* [RFC5925] - The TCP Authentication Option
+ Intended to replace MD5 Signature Option [RFC2385] */
+};
+
+/* Associated lengths */
+const uint8_t TCPOLEN_EOL = 1; /* Always one byte - [RFC793]*/
+const uint8_t TCPOLEN_NOP = 1; /* Always one byte - [RFC793]*/
+const uint8_t TCPOLEN_MAXSEG = 4; /* Always 4 bytes - [RFC793] */
+const uint8_t TCPOLEN_WSCALE = 3; /* 1 byte with logarithmic values - [RFC1323]*/
+const uint8_t TCPOLEN_SACKOK = 2; /* Experimental [RFC2018]*/
+const uint8_t TCPOLEN_ECHO = 6; /* 6 bytes - Echo (obsoleted by option 8) [RFC1072] */
+const uint8_t TCPOLEN_ECHOREPLY = 6; /* 6 bytes - Echo Reply (obsoleted by option 8)[RFC1072]*/
+const uint8_t TCPOLEN_TIMESTAMP = 10; /* Timestamp [RFC1323], 10 bytes */
+const uint8_t TCPOLEN_PARTIAL_PERM = 2; /* Partial Order Permitted/ Experimental [RFC1693] */
+const uint8_t TCPOLEN_PARTIAL_SVC = 3; /* 3 bytes long -- Experimental - [RFC1693] */
+
+/* atleast decode T/TCP options... */
+const uint8_t TCPOLEN_CC = 6; /* page 17 of rfc1644 */
+const uint8_t TCPOLEN_CC_NEW = 6; /* page 17 of rfc1644 */
+const uint8_t TCPOLEN_CC_ECHO = 6; /* page 17 of rfc1644 */
+
+const uint8_t TCPOLEN_TRAILER_CSUM = 3;
+const uint8_t TCPOLEN_MD5SIG = 18;
+
+
+struct TcpOption
+{
+ TcpOptCode code;
+ uint8_t len;
+ uint8_t data[13]; // arbitrary number. choosing 13 to align with 128 bits
+
+ inline uint8_t get_len() const
+ { return ((uint8_t)code <= 1) ? 1 : len; }
+
+ inline const uint8_t* get_data() const
+ { return ((uint8_t)code <= 1 || len < 2) ? nullptr : &data[0]; }
+
+ inline const TcpOption& next() const
+ {
+# if defined(__GNUC__)
+ const uint8_t tmp_len = ((uint8_t) code <= 1) ? 1 : len;
+ const uint8_t* const tmp = reinterpret_cast<const uint8_t*>(this);
+ const TcpOption* opt = reinterpret_cast<const TcpOption*>(&tmp[tmp_len]);
+ return *opt;
+
+ // ... and the legible code
+# else
+ if ( (uint8_t)code <= 1 )
+ return reinterpret_cast<const TcpOption&>(len);
+ else
+ return reinterpret_cast<const TcpOption&>(data[len -2]);
+# endif
+ }
+};
+
+
+/*
+ * Use TcpOptIterator ... this should NOT be called directly
+ * unless you want to an actual iterator or some buggy code.
+ */
+class TcpOptIteratorIter
+{
+public:
+ TcpOptIteratorIter(const TcpOption*);
+
+ bool operator== (const TcpOptIteratorIter& rhs)
+ { return opt == rhs.opt; }
+
+ bool operator!= (const TcpOptIteratorIter& rhs)
+ { return opt != rhs.opt; }
+
+ TcpOptIteratorIter& operator++()
+ {
+ opt = &opt->next();
+ return *this;
+ }
+
+ const TcpOption& operator* () const;
+
+private:
+ const TcpOption* opt;
+};
+
+/*
+ * Use IP ranged for loop rather than calling this directly.
+ * i.e.,
+ * IpOptionIter iter(tcph, p)
+ * for (const TcpOption& opt : iter)
+ * {
+ * do_something
+ * }
+ */
+class TcpOptIterator
+{
+public:
+ /* CONSTRUCTOR VALID AFTER DECODE()
+ * Some options in the provided header may not be valid.
+ * Provide the packet struct ensures only valid options
+ * will be returned
+ */
+ TcpOptIterator(const TCPHdr* const, const Packet* const);
+ /* If you already know the validated option length (for instance,
+ * if you are in a decode() method), then call this constructor.*/
+ TcpOptIterator(const TCPHdr* const, const uint32_t valid_hdr_len);
+ TcpOptIteratorIter begin() const;
+ TcpOptIteratorIter end() const;
+
+private:
+ const uint8_t* start_ptr;
+ const uint8_t* end_ptr;
+};
+
+
+} // namespace tcp
+
+
+#endif /* PROTOCOLS_TCP_OPTIONS_H */
#include "protocols/vlan.h"
#include "protocols/ip.h"
#include "protocols/icmp4.h"
+#include "sfip/sf_ip.h"
THREAD_LOCAL SessionStats icmpStats;
THREAD_LOCAL ProfileStats icmp_perf_stats;
*/
/* I N C L U D E S ************************************************/
-#include "ip_defrag.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#include <rpc/types.h>
#include <errno.h>
-#include "ip_session.h"
-#include "ip_module.h"
-#include "stream_ip.h"
-#include "stream/stream.h"
-#include "main/analyzer.h"
-#include "snort_bounds.h"
-#include "log_text.h"
-#include "detect.h"
-#include "protocols/packet.h"
-#include "protocols/packet_manager.h"
-#include "event.h"
-#include "util.h"
-#include "snort_debug.h"
-#include "parser.h"
-#include "mstring.h"
-#include "perf_monitor/perf.h"
-#include "timersub.h"
-#include "fpcreate.h"
-#include "utils/sflsq.h"
-#include "snort.h"
-#include "profiler.h"
+
+#include "framework/codec.h"
+#include "framework/counts.h"
+#include "flow/flow_control.h"
+#include "ip_defrag.h"
+#include "stream/ip/ip_session.h"
+#include "stream/ip/ip_module.h"
+#include "stream/ip/stream_ip.h"
#include "packet_io/active.h"
#include "packet_io/sfdaq.h"
-#include "framework/inspector.h"
-#include "flow/flow_control.h"
-#include "framework/codec.h"
+#include "protocols/layer.h"
+#include "protocols/ipv4_options.h"
+#include "protocols/packet_manager.h"
+#include "main/snort_debug.h"
+#include "main/snort.h"
+#include "time/profiler.h"
+#include "time/timersub.h"
+#include "network_inspectors/perf_monitor/perf.h"
+#include "utils/stats.h"
+#include "utils/snort_bounds.h"
/* D E F I N E S **************************************************/
/* P R O T O T Y P E S ********************************************/
static void FragRebuild(FragTracker *, Packet *);
static inline int FragIsComplete(FragTracker *);
-static int FragHandleIPOptions(FragTracker *, Packet *);
+static int FragHandleIPOptions(FragTracker *, const Packet* const);
/* deletion funcs */
static THREAD_LOCAL struct timeval *pkttime; /* packet timestamp */
*
* @return none
*/
-static inline int FragCheckFirstLast(Packet *p, FragTracker *ft)
+static inline int FragCheckFirstLast(const Packet* const p,
+ FragTracker *ft,
+ const uint16_t frag_offset)
{
uint16_t fragLength;
int retVal = FRAG_FIRSTLAST_OK;
uint16_t endOfThisFrag;
/* set the frag flag if this is the first fragment */
- if((p->decode_flags & DECODE__MF) && p->frag_offset == 0)
+ if((p->decode_flags & DECODE__MF) && frag_offset == 0)
{
ft->frag_flags |= FRAG_GOT_FIRST;
DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Got first frag\n"););
}
- else if((!(p->decode_flags & DECODE__MF)) && (p->frag_offset > 0)) /* set for last frag too */
+ else if((!(p->decode_flags & DECODE__MF)) && (frag_offset > 0)) /* set for last frag too */
{
- /* Use the actual length here, because packet may have been
- * truncated. Don't want to try to copy more than we actually
- * captured. */
- //fragLength = p->actual_ip_len - GET_IPH_HLEN(p) * 4;
- fragLength = p->ip_frag_len;
- endOfThisFrag = (p->frag_offset << 3) + fragLength;
+ /* Use the actual length here because packet may have been
+ * truncated. Don't want to try to copy more than we actually
+ * captured. Use dsize as the frag length since it is distance
+ * between the last sucesfully decoded layer (which is ip6_frag
+ * or ipv4) and the end of packet, */
+ fragLength = p->dsize;
+ endOfThisFrag = (frag_offset << 3) + fragLength;
if (ft->frag_flags & FRAG_GOT_LAST)
{
}
}
- if (p->frag_offset != 0)
+ if (frag_offset != 0)
{
ft->frag_flags |= FRAG_NO_BSD_VULN;
}
* @retval 1 on success
*/
static int FragHandleIPOptions(FragTracker *ft,
- Packet *p)
+ const Packet* const p)
{
- unsigned int i = 0; /* counter */
- if(p->frag_offset == 0)
+ // FIXIT-J pass in frag_offset as a parameter
+ const uint16_t frag_offset = ntohs(p->ip_api.off(p));
+ const uint16_t ip_options_len = p->ip_api.get_ip_opt_len();
+
+ if(frag_offset == 0)
{
/*
* This is the first packet. If it has IP options,
* save them off, so we can set them on the reassembled packet.
*/
- uint16_t ip_options_len = p->ip_api.get_ip_opt_len();
if (ip_options_len)
{
if (ft->ip_options_data)
{
/* Already seen 0 offset packet and copied some IP options */
if ((ft->frag_flags & FRAG_GOT_FIRST)
- && (ft->ip_option_count != p->ip_option_count))
+ && (ft->ip_options_len != ip_options_len))
{
EventAnomIpOpts(ft->engine);
}
ft->ip_options_data = (uint8_t*)SnortAlloc(ip_options_len);
memcpy(ft->ip_options_data, p->ip_api.get_ip_opt_data(), ip_options_len);
ft->ip_options_len = ip_options_len;
- ft->ip_option_count = p->ip_option_count;
}
}
}
/* XXX: could check each individual option here, but that
* would be performance ugly. So, we'll just check that the
- * option counts match. Alert if invalid, but still include in
+ * option sizes match. Alert if invalid, but still include in
* reassembly.
*/
- if (ft->copied_ip_option_count)
+ if (ft->copied_ip_options_len)
{
- if (ft->copied_ip_option_count != p->ip_option_count)
+ if (ft->copied_ip_options_len != ip_options_len)
{
EventAnomIpOpts(ft->engine);
}
}
else
{
- ft->copied_ip_option_count = p->ip_option_count;
- for (i = 0;i< p->ip_option_count && i < IP_OPTMAX; i++)
+ ft->copied_ip_options_len = ip_options_len;
+
+ ip::IpOptionIterator iter(p->ip_api.get_ip4h(), p);
+
+ for (ip::IpOptions opt : iter)
{
/* Is the high bit set? If not, weird anomaly. */
- if (!(p->ip_options[i].code & 0x80))
+ if (!(static_cast<uint8_t>(opt.code) & 0x80))
EventAnomIpOpts(ft->engine);
}
}
*/
static inline int checkTinyFragments(
FragEngine *engine,
- Packet *p,
+ const Packet* const p,
unsigned int trimmedLength
)
{
///detect tiny fragments before processing overlaps.
if (engine->min_fragment_length)
{
- if (p->ip_frag_len <= engine->min_fragment_length)
+ if (p->dsize <= engine->min_fragment_length)
{
DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
"Frag3: Received fragment size(%d) is not more than configured min_fragment_length (%d)\n",
- p->ip_frag_len, engine->min_fragment_length););
+ p->dsize, engine->min_fragment_length););
EventTinyFragments(engine);
return 1;
}
assert(p->ip_api.is_valid() && !(p->error_flags & PKT_ERR_CKSUM_IP));
assert(p->decode_flags & DECODE__FRAG);
+ const uint16_t frag_offset = ntohs(p->ip_api.off(p));
+
/*
* First case: if frag offset is 0 & UDP, let that packet go
* through the rest of the system. Ugly HACK to detect DNS
* Disable Inspection since we'll look at the payload in
* a rebuilt packet later. So don't process it further.
*/
- if ((p->frag_offset != 0) ||
+ if ((frag_offset != 0) ||
((p->ip_api.proto() != IPPROTO_UDP) && (p->decode_flags & DECODE__MF)))
{
DisableDetect(p);
"[0x%X->0x%X], TTL: %d " "Offset: %d Length: %d\n",
ntohl(p->ip_api.get_ip4h()->get_src()),
ntohl(p->ip_api.get_ip4h()->get_dst()),
- p->ip_api.ttl(), p->frag_offset,
+ p->ip_api.ttl(), frag_offset,
p->dsize););
EventAnomScMinTTL(fe);
case FRAG_INSERT_FAILED:
#ifdef DEBUG
LogMessage("WARNING: Insert into Fraglist failed, "
- "(offset: %u).\n", p->frag_offset);
+ "(offset: %u).\n", frag_offset);
#endif
MODULE_PROFILE_END(fragPerfStats);
return;
"Offset: %d Length: %d\n",
ntohl(p->ip_api.get_ip4h()->get_src()),
ntohl(p->ip_api.get_ip4h()->get_dst()),
- p->ip_api.ttl(), ft->ttl, p->frag_offset,
+ p->ip_api.ttl(), ft->ttl, frag_offset,
p->dsize););
t_stats.discards++;
MODULE_PROFILE_END(fragPerfStats);
case FRAG_INSERT_TIMEOUT:
#ifdef DEBUG
LogMessage("WARNING: Insert into Fraglist failed due to timeout, "
- "(offset: %u).\n", p->frag_offset);
+ "(offset: %u).\n", frag_offset);
#endif
MODULE_PROFILE_END(fragPerfStats);
return;
LogMessage("WARNING: Excessive IP fragment overlap, "
"(More: %u, offset: %u, offsetSize: %u).\n",
(p->decode_flags & DECODE__MF),
- (p->frag_offset<<3), p->ip_frag_len);
+ (frag_offset << 3), p->dsize);
#endif
t_stats.discards++;
MODULE_PROFILE_END(fragPerfStats);
{
FragRebuild(ft, p);
- if (p->frag_offset != 0 ||
+ if (frag_offset != 0 ||
(p->ip_api.proto() != IPPROTO_UDP && ft->frag_flags & FRAG_REBUILT))
{
/* Need to reset some things here because the
const uint8_t *fragStart;
int16_t fragLength;
PROFILE_VARS;
+ const uint16_t net_frag_offset = ntohs(p->ip_api.off(p));
sfBase.iFragInserts++;
MODULE_PROFILE_START(fragInsertPerfStats);
- if (p->ip_api.is_ip6() && (p->frag_offset == 0))
+ if (p->ip_api.is_ip6() && (net_frag_offset == 0))
{
ip::IP6Frag *fragHdr = (ip::IP6Frag *)p->layers[p->ip6_frag_index].start;
if (ft->protocol != fragHdr->ip6f_nxt)
* Check to see if this fragment is the first or last one and
* set the appropriate flags and values in the FragTracker
*/
- firstLastOk = FragCheckFirstLast(p, ft);
+ firstLastOk = FragCheckFirstLast(p, ft, net_frag_offset);
+
+ // if we're here, then the last layer was a fragment.
+ const Layer& lyr = p->layers[p->num_layers-1];
+ fragStart = lyr.start + lyr.length;
- fragStart = p->ip_frag_start;
- //fragStart = (uint8_t *)p->iph + GET_IPH_HLEN(p) * 4;
- /* Use the actual length here, because packet may have been
+ /* Use the actual length here because packet may have been
* truncated. Don't want to try to copy more than we actually
- * captured. */
- //len = fragLength = p->actual_ip_len - GET_IPH_HLEN(p) * 4;
- len = fragLength = p->ip_frag_len;
+ * captured. Use dsize as the frag length since it is distance
+ * between the last sucesfully decoded layer (which is ip6_frag
+ * or ipv4) and the end of packet, */
+ len = fragLength = p->dsize;
+
#ifdef DEBUG_MSGS
if (p->ip_api.actual_ip_len() != ntohs(p->ip_api.len()))
{
/*
* setup local variables for tracking this frag
*/
- orig_offset = frag_offset = p->frag_offset << 3;
+ orig_offset = frag_offset = net_frag_offset << 3;
/* Reset the offset to handle the weird Solaris case */
if (firstLastOk == FRAG_LAST_OFFSET_ADJUST)
frag_offset = (uint16_t)ft->calculated_size;
DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
"Overly large fragment %d 0x%x 0x%x %d\n",
fragLength, ntohs(p->ip_api.len()), p->ip_api.off(p),
- p->frag_offset << 3););
+ net_frag_offset << 3););
MODULE_PROFILE_END(fragInsertPerfStats);
return FRAG_INSERT_FAILED;
}
const uint8_t *fragStart;
uint16_t fragLength;
uint16_t frag_end;
+ uint16_t frag_off;
+
+ // if we're here, then the last layer was a fragment.
+ const Layer& lyr = p->layers[p->num_layers-1];
+ fragStart = lyr.start + lyr.length;
- fragStart = p->ip_frag_start;
- //fragStart = (uint8_t *)p->iph + GET_IPH_HLEN(p) * 4;
- /* Use the actual length here, because packet may have been
+ /* Use the actual length here because packet may have been
* truncated. Don't want to try to copy more than we actually
- * captured. */
- //fragLength = p->actual_ip_len - GET_IPH_HLEN(p) * 4;
- fragLength = p->ip_frag_len;
+ * captured. Use dsize as the frag length since it is distance
+ * between the last sucesfully decoded layer (which is ip6_frag
+ * or ipv4) and the end of packet, */
+ fragLength = p->dsize;
/* Just to double check */
if (fragLength > pkt_snaplen)
{
DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
- "Overly large fragment %d 0x%x 0x%x %d\n",
- fragLength, ntohs(p->ip_api.len()), p->ip_api.off(p),
- p->frag_offset << 3););
+ "Overly large fragment length:%d(0x%x) off:0x%x(%d)\n",
+ fragLength, ntohs(p->ip_api.len()), ntohs(p->ip_api.off(p)) << 3,
+ ntohs(p->ip_api.off(p)) << 3););
/* Ah, crap. Return that tracker. */
return 0;
if (p->ip_api.is_ip4())
{
ft->protocol = p->ip_api.proto();
+
+ const ip::IP4Hdr *ip4h = reinterpret_cast<const ip::IP4Hdr*>(lyr.start);
+ frag_off = ntohs(ip4h->get_off());
}
else /* IPv6 */
{
- if (p->frag_offset == 0)
- {
- ip::IP6Frag *fragHdr = (ip::IP6Frag *)p->layers[p->ip6_frag_index].start;
+ const ip::IP6Frag *fragHdr = reinterpret_cast<const ip::IP6Frag*>(lyr.start);
+ frag_off = ntohs(fragHdr->get_off());
+
+ if (frag_off == 0)
ft->protocol = fragHdr->ip6f_nxt;
- }
}
+
ft->ttl = p->ip_api.ttl(); /* store the first ttl we got */
ft->calculated_size = 0;
ft->alerted = 0;
ft->frag_time.tv_sec = p->pkth->ts.tv_sec;
ft->frag_time.tv_usec = p->pkth->ts.tv_usec;
ft->ip_options_len = 0;
- ft->ip_option_count = 0;
ft->ip_options_data = NULL;
ft->copied_ip_options_len = 0;
- ft->copied_ip_option_count = 0;
ft->ordinal = 0;
ft->frag_policy = FragGetPolicy(p, &engine);
ft->engine = &engine;
memcpy(f->fptr, fragStart, fragLength);
f->size = f->flen = fragLength;
- f->offset = p->frag_offset << 3;
+ f->offset = frag_off << 3;
frag_end = f->offset + fragLength;
f->ord = ft->ordinal++;
f->data = f->fptr; /* ptr to adjusted start position */
/*
* mark the FragTracker if this is the first/last frag
*/
- FragCheckFirstLast(p, ft);
+ FragCheckFirstLast(p, ft, frag_off);
ft->frag_bytes += fragLength;
#include "stream/stream.h"
#include "perf_monitor/perf.h"
#include "flow/flow_control.h"
+#include "sfip/sf_ip.h"
THREAD_LOCAL SessionStats ipStats;
THREAD_LOCAL ProfileStats ip_perf_stats;
int fraglist_count; /* handy dandy counter */
uint32_t ip_options_len; /* length of ip options for this set of frags */
- uint32_t ip_option_count; /* number of ip options for this set of frags */
uint8_t *ip_options_data; /* ip options from offset 0 packet */
uint32_t copied_ip_options_len; /* length of 'copied' ip options */
- uint32_t copied_ip_option_count; /* number of 'copied' ip options */
FragEngine *engine;
#include "detection/detection_defines.h"
#include "hash/sfhashfcn.h"
#include "time/profiler.h"
+#include "sfip/sf_ip.h"
enum SsodOp
{
#include "time/packet_time.h"
#include "protocols/packet.h"
#include "protocols/packet_manager.h"
+#include "protocols/tcp_options.h"
#include "log_text.h"
#include "packet_io/active.h"
#include "normalize/normalize.h"
#include "file_api/file_api.h"
#include "tcp_module.h"
#include "stream/stream_splitter.h"
+#include "sfip/sf_ip.h"
using namespace tcp;
return 0;
}
-static inline void NormalStripTimeStamp (Packet* p, int i)
+static inline void NormalStripTimeStamp (Packet* p, const TcpOption* opt)
{
- uint8_t* opt;
+ // set raw option bytes to nops
+ memset((uint8_t*)(opt), (uint8_t)tcp::TcpOptCode::NOP, TCPOLEN_TIMESTAMP);
- if ( i < 0 )
- {
- for ( i = 0; i < p->tcp_option_count; i++ )
- {
- if ( p->tcp_options[i].code == TCPOPT_TIMESTAMP )
- break;
- }
- if ( i == p->tcp_option_count )
- return;
- }
- // first set raw option bytes to nops
- opt = (uint8_t*)p->tcp_options[i].data - 2;
- memset(opt, TCPOPT_NOP, TCPOLEN_TIMESTAMP);
-
- // then nop decoded option code only
- p->tcp_options[i].code = TCPOPT_NOP;
p->packet_flags |= PKT_MODIFIED;
normStats[PC_TCP_TS_NOP]++;
static uint32_t Stream5GetTcpTimestamp(Packet *p, uint32_t *ts, int strip)
{
- unsigned int i = 0;
-
STREAM5_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
"Getting timestamp...\n"););
- while(i < p->tcp_option_count && i < TCP_OPTLENMAX)
+
+ TcpOptIterator iter(p->tcph, p);
+
+ // using const because non-const is not supported
+ for (const TcpOption& opt : iter)
{
- if(p->tcp_options[i].code == TCPOPT_TIMESTAMP)
+ if(opt.code == TcpOptCode::TIMESTAMP)
{
if ( strip && Normalize_IsEnabled(p, NORM_TCP_OPT) )
{
- NormalStripTimeStamp(p, i);
+ NormalStripTimeStamp(p, &opt);
}
else
{
- *ts = EXTRACT_32BITS(p->tcp_options[i].data);
+ *ts = EXTRACT_32BITS(opt.data);
STREAM5_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
"Found timestamp %lu\n", *ts););
return TF_TSTAMP;
}
}
- i++;
}
*ts = 0;
static uint32_t Stream5GetMss(Packet *p, uint16_t *value)
{
- unsigned int i = 0;
-
STREAM5_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
"Getting MSS...\n"););
- while(i < p->tcp_option_count && i < TCP_OPTLENMAX)
+
+ TcpOptIterator iter(p->tcph, p);
+ for (const TcpOption& opt : iter)
{
- if(p->tcp_options[i].code == TCPOPT_MAXSEG)
+ if(opt.code == TcpOptCode::MAXSEG)
{
- *value = EXTRACT_16BITS(p->tcp_options[i].data);
+ *value = EXTRACT_16BITS(opt.data);
STREAM5_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
"Found MSS %u\n", *value););
return TF_MSS;
}
-
- i++;
}
*value = 0;
static uint32_t Stream5GetWscale(Packet *p, uint16_t *value)
{
- unsigned int i = 0;
-
STREAM5_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
"Getting wscale...\n"););
- while(i < p->tcp_option_count && i < TCP_OPTLENMAX)
+
+
+ TcpOptIterator iter(p->tcph, p);
+
+ // using const because non-const is not supported
+ for (const TcpOption& opt : iter)
{
- if(p->tcp_options[i].code == TCPOPT_WSCALE)
+ if(opt.code == TcpOptCode::WSCALE)
{
- *value = (uint16_t) p->tcp_options[i].data[0];
+ *value = (uint16_t) opt.data[0];
STREAM5_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
"Found wscale %d\n", *value););
return TF_WSCALE;
}
-
- i++;
}
*value = 0;
#include "packet_io/active.h"
#include "perf_monitor/perf.h"
#include "profiler.h"
+#include "sfip/sf_ip.h"
/* sender/responder ip/port dereference */
#define udp_sender_ip flow->client_ip
#include "snort.h"
#include "snort_debug.h"
#include "utils/stats.h"
+#include "sfip/sf_ip.h"
#define ATTRIBUTE_MAP_MAX_ROWS 1024
#include "actions/actions.h"
#include "protocols/packet.h"
#include "utils/stats.h"
+#include "sfip/sf_ip.h"
#ifdef PPM_MGR
#endif
-#if __clang__
+#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc99-extensions"
#pragma clang diagnostic ignored "-Wflexible-array-extensions"
#endif
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+#endif
+
// Encoder FOO
#ifdef HAVE_DUMBNET_H
#include <dumbnet.h>
#endif
-#if __clang__
+#if defined(__clang__)
#pragma clang diagnostic pop
#endif
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
#endif