]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
removing ip options, tcp options, and frag options from packet struct. Adding iterat...
authorJosh <jrosenba@cisco.com>
Tue, 9 Sep 2014 20:16:35 +0000 (16:16 -0400)
committerJosh <jrosenba@cisco.com>
Tue, 9 Sep 2014 20:16:35 +0000 (16:16 -0400)
69 files changed:
src/codecs/ip/cd_frag.cc
src/codecs/ip/cd_icmp4.cc
src/codecs/ip/cd_icmp6.cc
src/codecs/ip/cd_igmp.cc
src/codecs/ip/cd_ipv4.cc
src/codecs/ip/cd_ipv6.cc
src/codecs/ip/cd_tcp.cc
src/codecs/ip/cd_udp.cc
src/codecs/link/cd_ppp_encap.cc
src/codecs/link/cd_pppoe.cc
src/codecs/misc/Makefile.am
src/codecs/misc/cd_icmp4_ip.cc
src/codecs/root/cd_null.cc
src/codecs/root/cd_wlan.cc
src/detection/fpdetect.cc
src/detection/tag.cc
src/file_api/file_resume_block.cc
src/file_api/libs/file_config.cc
src/filters/rate_filter.cc
src/flow/expect_cache.cc
src/flow/flow.cc
src/flow/flow_key.cc
src/framework/codec.h
src/ips_options/ips_fragbits.cc
src/ips_options/ips_fragoffset.cc
src/ips_options/ips_ipopts.cc
src/ips_options/ips_session.cc
src/log/log.cc
src/log/log_text.cc
src/log/log_text.h
src/log/messages.cc
src/loggers/Makefile.am
src/loggers/alert_csv.cc
src/loggers/log_codecs.cc
src/loggers/loggers.cc
src/main/modules.cc
src/network_inspectors/arp_spoof/arp_spoof.cc
src/network_inspectors/normalize/norm.cc
src/network_inspectors/perf_monitor/perf_flow.cc
src/network_inspectors/port_scan/ps_detect.cc
src/packet_io/intf.cc
src/parser/config_file.cc
src/parser/parse_byte_code.cc
src/protocols/CMakeLists.txt
src/protocols/Makefile.am
src/protocols/ip.cc
src/protocols/ip.h
src/protocols/ipv4.h
src/protocols/ipv4_options.cc [new file with mode: 0644]
src/protocols/ipv4_options.h [new file with mode: 0644]
src/protocols/layer.cc
src/protocols/layer.h
src/protocols/packet.h
src/protocols/packet_manager.cc
src/protocols/packet_manager.h
src/protocols/protocol_ids.h
src/protocols/tcp.h
src/protocols/tcp_options.cc [new file with mode: 0644]
src/protocols/tcp_options.h [new file with mode: 0644]
src/stream/icmp/icmp_session.cc
src/stream/ip/ip_defrag.cc
src/stream/ip/ip_session.cc
src/stream/ip/ip_session.h
src/stream/tcp/ips_stream_size.cc
src/stream/tcp/tcp_session.cc
src/stream/udp/udp_session.cc
src/target_based/sftarget_reader.cc
src/time/ppm.cc
src/utils/dnet_header.h

index 13c38faaf5c532c16f086a7d46d8149eec3f3768..fcab7554d88acb0c34609466729fcee868957710 100644 (file)
@@ -90,8 +90,6 @@ bool Ipv6FragCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
 
     /* 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)
@@ -105,7 +103,6 @@ bool Ipv6FragCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
 
     // 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;
@@ -125,7 +122,6 @@ bool Ipv6FragCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
 
     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);
index a7b4b6dc4ea9643ccc2869ba4e51340af6ac1c86..7bfc911f5ac2122de697794dc84c9c63d35787ad 100644 (file)
 #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{
 
@@ -304,11 +307,14 @@ void Icmp4Codec::ICMP4MiscTests (Packet *p)
 
     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);
+            }
         }
     }
 
index b2a33135561654cd3e1e885e99059b4e4724b607..aa6e7a7bf1935ef4b896ca1535c90fbb11e6bd3a 100644 (file)
@@ -38,6 +38,7 @@
 #include "codecs/ip/ip_util.h"
 #include "packet_io/active.h"
 #include "log/text_log.h"
+#include "main/snort_debug.h"
 
 
 namespace
index e15d94fa57ff5fa4d007d0792d7487430695ec24..609c944eb585f7c1d21384de3ad7430c9099804e 100644 (file)
@@ -29,6 +29,7 @@
 #include "codecs/decode_module.h"
 #include "codecs/codec_events.h"
 #include "protocols/packet.h"
+#include "protocols/ipv4_options.h"
 
 
 namespace
@@ -80,8 +81,6 @@ public:
 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();
@@ -96,20 +95,23 @@ bool IgmpCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
             }
         }
 
-        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;
 }
index a8609f37bcb2fa6bfc15526f8c1d659f8560b957..32c5cec91014d17ee01a45fda4195cf78e7a4996 100644 (file)
@@ -44,6 +44,7 @@
 #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"
 
@@ -129,15 +130,9 @@ static THREAD_LOCAL std::array<uint16_t, IP_ID_COUNT> s_id_pool{{0}};
 
 
 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 ***********
@@ -325,22 +320,10 @@ bool Ipv4Codec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
     }
 
     /* 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;
@@ -386,8 +369,6 @@ bool Ipv4Codec::decode(const uint8_t *raw_pkt, const uint32_t& raw_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
@@ -400,24 +381,20 @@ bool Ipv4Codec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
         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
@@ -486,71 +463,61 @@ static inline void IP4AddrTests(const IP4Hdr* iph, const Packet* p)
 
 
 /* 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 *)
  *
@@ -562,128 +529,70 @@ int OptLenValidate(const uint8_t *option_ptr,
  *
  * 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  ******************************
 *******************************************************************/
@@ -745,11 +654,11 @@ void Ipv4Codec::log(TextLog* const text_log, const uint8_t* raw_pkt,
         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);
     }
 
 
@@ -871,6 +780,12 @@ void Ipv4Codec::format(EncodeFlags f, const Packet* p, Packet* c, Layer* lyr)
     }
     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 )
         {
@@ -878,6 +793,7 @@ void Ipv4Codec::format(EncodeFlags f, const Packet* p, Packet* c, Layer* lyr)
             ch->set_ip_len(htons(ip::IP4_HEADER_LEN));
             ch->set_hlen(ip::IP4_HEADER_LEN >> 2);
         }
+#endif
     }
 
     c->ip_api.set(ch);
index 46c5f0006a460674257986c73c0a21d5f812f860..6f6d926dc30c9a115b2efc6ce761e65158ec3388 100644 (file)
@@ -25,6 +25,7 @@
 #include "config.h"
 #endif
 
+#include <limits>
 #include "detection/fpdetect.h"
 
 #include "protocols/ipv6.h"
@@ -40,6 +41,7 @@
 #include "protocols/protocol_ids.h"
 #include "protocols/packet_manager.h"
 #include "log/text_log.h"
+#include "sfip/sf_ip.h"
 
 namespace
 {
@@ -241,10 +243,6 @@ bool Ipv6Codec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
     }
 
 
-
-    /* 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
@@ -255,6 +253,8 @@ bool Ipv6Codec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
 
     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);
index 6407c40279aa99868cacbeb30062ab7075f21258..bad73f4bc9654a7d204bd135e66586fa1276a7e2 100644 (file)
 #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"
@@ -44,6 +44,8 @@
 #include "protocols/packet_manager.h"
 
 
+using namespace tcp;
+
 namespace
 {
 
@@ -115,12 +117,9 @@ static sfip_var_t *SynToMulticastDstIp = NULL;
 
 
 
-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 *);
@@ -165,13 +164,13 @@ bool TcpCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
     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);
 
@@ -183,7 +182,7 @@ bool TcpCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
     {
         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);
 
@@ -210,7 +209,7 @@ bool TcpCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
             /* 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 */
@@ -224,7 +223,7 @@ bool TcpCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
             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)
@@ -241,7 +240,7 @@ bool TcpCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
             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() )
@@ -257,9 +256,9 @@ bool TcpCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
         }
     }
 
-    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);
         }
@@ -273,12 +272,12 @@ bool TcpCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
         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 )
                 {
@@ -291,61 +290,45 @@ bool TcpCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
         {
             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;
 }
 
@@ -401,17 +384,15 @@ bool TcpCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
  */
 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
@@ -419,7 +400,6 @@ void DecodeTCPOptions(const uint8_t *start, uint32_t o_len, Packet *p)
      *
      * 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
@@ -427,126 +407,99 @@ void DecodeTCPOptions(const uint8_t *start, uint32_t o_len, Packet *p)
      *
      */
 
-    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;
         }
 
@@ -565,18 +518,15 @@ void DecodeTCPOptions(const uint8_t *start, uint32_t o_len, Packet *p)
              * 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);
@@ -585,15 +535,42 @@ void DecodeTCPOptions(const uint8_t *start, uint32_t o_len, Packet *p)
     {
         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)
@@ -604,6 +581,7 @@ static inline void TCPMiscTests(Packet *p)
 
     if (p->sp == 0 || p->dp == 0)
         codec_events::decoder_event(p, DECODE_TCP_PORT_ZERO);
+
 }
 
 /******************************************************************
@@ -616,7 +594,7 @@ void TcpCodec::log(TextLog* const text_log, const uint8_t* raw_pkt,
 {
     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);
@@ -627,14 +605,14 @@ void TcpCodec::log(TextLog* const text_log, const uint8_t* raw_pkt,
             "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);
@@ -674,7 +652,7 @@ bool TcpCodec::encode (EncState* enc, Buffer* out, const uint8_t* raw_in)
         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);
@@ -710,7 +688,7 @@ bool TcpCodec::encode (EncState* enc, Buffer* out, const uint8_t* raw_in)
     }
 
     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 )
@@ -820,261 +798,6 @@ void TcpCodec::format(EncodeFlags f, const Packet* p, Packet* c, Layer* lyr)
 }
 
 
-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
 //-------------------------------------------------------------------------
index fb6b93c96ffd3aeb136a8d3b435117e17a90e8b1..deafc055f0555dfb88babc4b70730a1b4afde5f2 100644 (file)
@@ -43,6 +43,7 @@
 #include "snort_config.h"
 #include "parser/config_file.h"
 #include "codecs/ip/ip_util.h"
+#include "main/snort_debug.h"
 
 
 namespace
@@ -158,11 +159,7 @@ bool UdpCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
 
     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;
     }
@@ -349,6 +346,7 @@ static inline void UDPMiscTests(Packet *p)
  */
 static inline void PopUdp (Packet* p)
 {
+    //FIXIT-J-H
 
     // required for detect.c to short-circuit preprocessing
     if ( !p->dsize )
@@ -382,7 +380,7 @@ typedef struct {
 
 
 
-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;
 
index 0e949509597ba79a4c880b0a3fc013e78df8b6a6..fa23a11d7b9c741e72e51af1618df7cb52aa04ea 100644 (file)
@@ -28,6 +28,7 @@
 #include "protocols/protocol_ids.h"
 #include "snort.h"
 #include "codecs/sf_protocols.h"
+#include "main/snort_debug.h"
 
 namespace
 {
@@ -101,14 +102,7 @@ bool PppEncap::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
      *
      */
     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)
@@ -175,14 +169,10 @@ bool PppEncap::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
 //-------------------------------------------------------------------------
 
 static Codec* ctor(Module*)
-{
-    return new PppEncap();
-}
+{ return new PppEncap(); }
 
 static void dtor(Codec *cd)
-{
-    delete cd;
-}
+{ delete cd; }
 
 static const CodecApi pppencap_api =
 {
index 8e59c6e2441c05a4b1cdc0a2fa2b5f29322cfdf1..1282e9712bdbf60679f70ef4dbb656d11b53f38c 100644 (file)
@@ -27,6 +27,7 @@
 #include "protocols/packet.h"
 #include "codecs/sf_protocols.h"
 #include "protocols/layer.h"
+#include "main/snort_debug.h"
 
 namespace
 {
@@ -437,9 +438,7 @@ bool PPPoESessCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
 
 
 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); }
 
 
 //-------------------------------------------------------------------------
@@ -448,14 +447,10 @@ bool PPPoESessCodec::encode(EncState *enc, Buffer* out, const uint8_t* 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 =
index b61583e9d690f4afb7a19e1daba33b614e2bc07c..a3fe55a7c040b984cafef2a4d6d0e54c0b700994 100644 (file)
@@ -32,7 +32,7 @@ libcd_icmp6_ip_la_SOURCES = cd_icmp6_ip.cc
 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
index e769b4bd9f82c3e9c44b98a20855f618db5a3a99..49da9f925ff4aace0472e7607de3612f712a765e 100644 (file)
@@ -256,7 +256,7 @@ void Icmp4IpCodec::log(TextLog* const text_log, const uint8_t* raw_pkt,
                     "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;
         }
index 7853585bda4ef8f02f6c769420fdc68b8acd9df6..fce984252fd850e7cfe241c7e7ccff5030aebe32 100644 (file)
@@ -70,18 +70,9 @@ static const uint16_t NULL_HDRLEN = 4;
 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;
@@ -98,14 +89,10 @@ void NullCodec::get_data_link_type(std::vector<int>&v)
 //-------------------------------------------------------------------------
 
 static Codec* ctor(Module*)
-{
-    return new NullCodec();
-}
+{ return new NullCodec(); }
 
 static void dtor(Codec *cd)
-{
-    delete cd;
-}
+{ delete cd; }
 
 static const CodecApi null_api =
 {
index eed16656d94cc6c7d7bddab2fc40fa3dda832260..7fb9d423203dbc935228b845662a22afdbb70f4b 100644 (file)
 #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
 {
 
@@ -67,22 +64,9 @@ public:
 
     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 */
@@ -101,27 +85,13 @@ void WlanCodec::get_data_link_type(std::vector<int>&v)
 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)
@@ -162,61 +132,7 @@ bool WlanCodec::decode(const uint8_t *raw_pkt, const uint32_t &raw_len,
         {
             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:
@@ -226,6 +142,27 @@ bool WlanCodec::decode(const uint8_t *raw_pkt, const uint32_t &raw_len,
     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));
+}
 
 
 //-------------------------------------------------------------------------
index da3a4c82d59de24dcaa74170cbdfd63f58706022..354ed6ce2a2daa3f30fc4fa1517038db0a429987 100644 (file)
@@ -73,6 +73,7 @@
 #include "actions/actions.h"
 #include "protocols/packet_manager.h"
 #include "managers/action_manager.h"
+#include "sfip/sf_ip.h"
 
 /*
 **  Static function prototypes
index 2e9804d180e3e4a21773d191f5402aed1ad9d2c3..50756d837cdf7d43d7f9e43869af84e5a0479a59 100644 (file)
@@ -39,6 +39,7 @@
 
 #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
index 1b76857af7066dbebac4c3621d64fe36d476cdf4..959cef9a64bd31b56b2e8f11c9d4879d84a4136f 100644 (file)
@@ -36,6 +36,7 @@
 #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;
index 670daa865451d7ff19b806035661f450c2a7c488..1c892b973c6ee95e4129f082e644340546e0da65 100644 (file)
 #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"
index 34e9d5f3b55f95d7ecb61eba78a90a23db3d7734..d3beb263031a0c47894d4d84b41493235cc109e5 100644 (file)
@@ -46,6 +46,7 @@
 #include "sfrf.h"
 #include "snort.h"
 #include "sfthd.h"
+#include "sfip/sf_ip.h"
 
 //static int _printThresholdContext(RateFilterConfig*);
 
index 7e83bba1030c8b67f8729613c5d16fbc20247407..082858a9d53d9676017c615cb5145403e54e01fa 100644 (file)
@@ -25,6 +25,7 @@
 #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?
index 6274790772d2c97edd14af226920bc48d5fcd146..d2e8db92693f95a072800068c83aa75696fcf4b6 100644 (file)
@@ -31,6 +31,7 @@
 #include "utils/bitop_funcs.h"
 #include "utils/util.h"
 #include "protocols/packet.h"
+#include "sfip/sf_ip.h"
 
 unsigned FlowData:: flow_id = 0;
 
index 40ba95b07f5da36286a927333a76bf326fc47ee5..b3897f8da319a475fd89182eaf986bb5f1814bb8 100644 (file)
@@ -28,6 +28,7 @@
 #include "protocols/packet.h"
 #include "snort.h"
 #include "utils/util.h"
+#include "sfip/sf_ip.h"
 
 //-------------------------------------------------------------------------
 // init foo
index 21a96e94ec89ffe703a0409f10683c043567fb8e..c6c78b313f94a76093401c8df7ea6968279bfeda 100644 (file)
@@ -31,6 +31,24 @@ struct TextLog;
 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,
@@ -100,6 +118,28 @@ static inline bool update_buffer(Buffer* buf, size_t n)
 }
 
 
+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
index 66a4148fa0697ee6de70dc474379e2883e85ef7a..78e7b91f8fc5f6de807a7e825687d00d0cfdb738 100644 (file)
@@ -156,17 +156,18 @@ int FragBitsOption::eval(Cursor&, Packet *p)
         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;
@@ -179,7 +180,7 @@ int FragBitsOption::eval(Cursor&, Packet *p)
 
         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;
@@ -192,7 +193,7 @@ int FragBitsOption::eval(Cursor&, Packet *p)
 
         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;
@@ -205,7 +206,7 @@ int FragBitsOption::eval(Cursor&, Packet *p)
 
         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;
index 6b8fc0b1321218ada10300a00916d2b2a6b16104..4077a7a2eda61c5ddef3111deca0672077b87849 100644 (file)
@@ -90,7 +90,7 @@ bool FragOffsetOption::operator==(const IpsOption& ips) const
 
 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;
 
index 95551e96cf44be3489a21a4ead8ef0eb5b976b72..0061564179cfe23a3b3cbb8bbeb86389bed7cfd4 100644 (file)
@@ -31,6 +31,8 @@
 #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"
@@ -49,7 +51,7 @@ static THREAD_LOCAL ProfileStats ipOptionPerfStats;
 
 struct IpOptionData
 {
-    u_char ip_option;
+    ip::IPOptionCodes ip_option;
     u_char any_flag;
 
 };
@@ -82,7 +84,7 @@ uint32_t IpOptOption::hash() const
     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;
 
@@ -114,17 +116,19 @@ int IpOptOption::eval(Cursor&, Packet *p)
 {
     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;
@@ -132,13 +136,14 @@ int IpOptOption::eval(Cursor&, Packet *p)
         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);
@@ -159,47 +164,47 @@ static void ipopts_parse(const char* data, IpOptionData* ds_ptr)
 {
     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;
     }
 }
index 453bde0a13551500c8cc74f7fee8cf97bb46a49e..023bb95a39298f5e08c930a4f3dd2d9b811eb82c 100644 (file)
@@ -69,6 +69,7 @@
 #include "framework/ips_option.h"
 #include "framework/parameter.h"
 #include "framework/module.h"
+#include "sfip/sf_ip.h"
 
 static const char* s_name = "session";
 
index 0c5430b146f0aad0e48da5de43d148953b555e7a..6bbddccdf9b7541d1b0319af74e171ad9a741716 100644 (file)
@@ -39,6 +39,7 @@ using namespace std;
 #include "main/analyzer.h"
 #include "snort.h"
 #include "protocols/tcp.h"
+#include "main/snort_debug.h"
 
 #define DEFAULT_DAEMON_ALERT_FILE  "alert"
 
index 3e04c1589eee96373e3fa7dc556568a264ac6e2b..f0bbd7df13915718652458b5557c073e726d0cbc 100644 (file)
@@ -65,6 +65,8 @@
 #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
@@ -436,17 +438,18 @@ void Log2ndHeader(TextLog* log, Packet* p)
  *-------------------------------------------------------------------
  */
 
-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);
 
@@ -456,84 +459,67 @@ void LogIpOptions(TextLog*  log, const Packet* const p)
             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);
@@ -631,42 +617,45 @@ void LogIPHeader(TextLog*  log, Packet * p)
             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)
@@ -687,7 +676,6 @@ static void LogOuterIPHeader(TextLog *log, Packet *p)
         LogIPHeader(log, p);
 
     p->ip_api = save_ip_api;
-    p->ip_option_count = save_ip_option_count;
     p->decode_flags |= save_frag_flag;
 }
 
@@ -703,14 +691,12 @@ inline uint32_t extract_32_bits(const uint8_t* const buf)
 
 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);
@@ -721,53 +707,37 @@ void LogTcpOptions(TextLog*  log, const Packet* const p)
             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
@@ -776,126 +746,59 @@ void LogTcpOptions(TextLog*  log, const Packet* const p)
                     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;
             }
@@ -918,25 +821,26 @@ void LogTcpOptions(TextLog*  log, const Packet* const p)
 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
     {
@@ -944,7 +848,7 @@ void LogTCPHeader(TextLog*  log, Packet * p)
     }
 
     /* dump the TCP options */
-    if(p->tcp_option_count != 0)
+    if(tcph->has_options())
     {
         LogTcpOptions(log, p);
     }
index 71ae3055709b6b393a39b323c3c87f8328244734..91eac5ea58a35d922e2d506215cab7123514e0f2 100644 (file)
 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);
 
@@ -54,7 +60,7 @@ void LogTimeStamp(TextLog*, Packet*);
 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);
index bf5a1c2a0a20749f9ce7951f55358c56f9e3d420..33a5ffaffc7c647671a6d6675003727415aeb00e 100644 (file)
@@ -48,6 +48,8 @@
 #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;
 
index d3ac06cf79b6e73271e3ae6f09e551d9d12b16a9..b3b1d1bb59fe8e2104dcbcdf25c7d618f52ee3da 100644 (file)
@@ -3,6 +3,7 @@ AUTOMAKE_OPTIONS=foreign no-dependencies
 noinst_LIBRARIES = libloggers.a
 libloggers_a_SOURCES = \
 alert_luajit.cc \
+log_codecs.cc \
 loggers.cc \
 loggers.h
 
index 74b2fa3b9e593664c8c64a60c4b5cbaa73776c36..e4983caf954f899dac1125c84526c7bb9a95ad9c 100644 (file)
@@ -372,7 +372,7 @@ void CsvLogger::alert(Packet *p, const char *msg, Event *event)
         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))
         {
index 650f97f1073cfc2ea80a3baf806a05a95d6b5b81..6fdb167b7279739bc31d85b900d86b1c22a110e9 100644 (file)
@@ -199,4 +199,4 @@ static const LogApi log_codecs_api =
 };
 
 
-const BaseApi* eh_codecs = &log_codecs_api.base;
+const BaseApi* log_codecs = &log_codecs_api.base;
index ad0c372833d1d9e82d87a70c1121fcee71a6aaa4..dda8a989a60558af2c076d6395b94fe32cce584c 100644 (file)
@@ -27,7 +27,7 @@
 #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
@@ -68,8 +68,8 @@ const BaseApi* loggers[] =
     eh_unified2,
 #endif
     // loggers
+    log_codecs,
     log_luajit,
     // both
-    eh_codecs,
     nullptr
 };
index 4b1f7e829183a55b598cd5bdcf6933e37b18bbf8..dd7f403c1f45f3879b9fee91b60cad67fa804580 100644 (file)
@@ -54,6 +54,7 @@ using namespace std;
 #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"
index ef38581d825e5d798050486c52655c8f005e6550..9b3e8b982cc7e2483b7c617abd15fe9cb0b1ae58 100644 (file)
@@ -93,6 +93,7 @@
 #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};
 
index c6b1d1a0efd7a0e6a95e51815c7819dec6c36cbc..4b95f2f548f3a20918098f0a5b4693c4afac79e4 100644 (file)
@@ -32,7 +32,9 @@
 #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 {
@@ -226,7 +228,7 @@ static int Norm_IP4 (
         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++;
@@ -337,7 +339,7 @@ static int Norm_UDP (Packet * p, uint8_t layer, int 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
@@ -345,13 +347,13 @@ static inline void NopDaOpt (uint8_t* opt, uint8_t len)
 
 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];
 
@@ -361,13 +363,13 @@ static inline int Norm_TCPOptions (
         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);
@@ -377,7 +379,7 @@ static inline int Norm_TCPOptions (
             }
             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) )
@@ -412,12 +414,13 @@ static inline int Norm_TCPOptions (
 }
 
 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];
     }
@@ -496,20 +499,24 @@ static int Norm_TCP (
         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;
index 12718b3009ad13917c23233cc961e6789eecfc64..9fdd269698f7c6a2fbf1746d81483966155da482 100644 (file)
@@ -57,6 +57,7 @@
 #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 *);
index 695b0cdab6523536f5960275e5011b8d225f85c5..00242c301aa6fcda959b25b4f20c6643291fb268 100644 (file)
 #include "sfxhash.h"
 #include "ipobj.h"
 #include "stream/stream_api.h"
+#include "sfip/sf_ip.h"
 
 typedef struct s_PS_HASH_KEY
 {
index 2898463c0fae5bc54bd4e5ed2b064e22f1859cc7..415aea9b50517e97bae3a0844adc8ffd64e9f3fc 100644 (file)
@@ -27,6 +27,7 @@
 #include "snort_debug.h"
 #include "snort.h"
 #include "utils/util.h"
+#include "sfip/sf_ip.h"
 
 //------------------------------------------------------------------------------
 // interface stuff
index 2939bed45fd9ee91b02cea52ab41c1beed7eb07c..93f40dd11afb1dd685c436954294ef218160776f 100644 (file)
@@ -55,6 +55,7 @@
 #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"
index 535f445e515ebf2dcd82942430a2e1567447f29e..3ac9f0e48dd5d9b07164cbfb1a6bf1fafc93cd3f 100644 (file)
@@ -46,8 +46,8 @@ bool parse_byte_code(const char* in, bool& negate, std::string& out)
     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) )
index f01b188b0aa00836d091848140f238bff27366ab..766fa998dd31c9dac0406ebe8193a215dd0666d3 100644 (file)
@@ -7,6 +7,7 @@ set (PROTOCOL_HEADERS
     icmp6.h
     ip.h
     ipv4.h
+    ipv4_options.h
     ipv6.h
     gre.h
     layer.h
@@ -16,6 +17,7 @@ set (PROTOCOL_HEADERS
     packet_manager.h
     protocol_ids.h
     tcp.h
+    tcp_options.h
     teredo.h
     token_ring.h
     udp.h
@@ -27,6 +29,8 @@ add_library (protocols STATIC
     ${PROTOCOL_HEADERS}
     layer.cc
     ip.cc
+    ipv4_options.cc
+    tcp_options.cc
     packet_manager.cc
 )
 
index 5cb15db0be171e7dcae6bfd898469af48b04aa5b..4baa722c5bd9fb5b5c9339242d906588e479958c 100644 (file)
@@ -12,6 +12,7 @@ icmp4.h \
 icmp6.h \
 ip.h \
 ipv4.h \
+ipv4_options.h \
 ipv6.h \
 gre.h \
 layer.h \
@@ -20,6 +21,7 @@ packet.h \
 packet_manager.h \
 protocol_ids.h \
 tcp.h \
+tcp_options.h \
 teredo.h \
 token_ring.h \
 udp.h \
@@ -29,7 +31,9 @@ wlan.h
 libprotocols_a_SOURCES = \
 layer.cc \
 packet_manager.cc \
-ip.cc
+ip.cc \
+ipv4_options.cc \
+tcp_options.cc
 
 
 AM_CXXFLAGS = @AM_CXXFLAGS@
index 61dbffb0511342b98cff9d7821abd9eadd22a322..581e1bf0d927231e3539c93956d7ae167f629ac1 100644 (file)
@@ -20,6 +20,7 @@
 // ip.cc author Josh Rosenbaum <jrosenba@cisco.com>
 
 #include <arpa/inet.h>
+#include <limits>
 #include "protocols/ip.h"
 #include "protocols/packet.h"
 
@@ -38,16 +39,34 @@ void IpApi::set(const IP4Hdr* h4)
 {
     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)
@@ -59,77 +78,15 @@ 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
@@ -138,7 +95,7 @@ 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>(
@@ -150,10 +107,10 @@ uint32_t IpApi::id(const Packet* const p) 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>(
index 832b7ef0a550e580613020ff3a358d1b3abe5722..ad0f19747459c2779952b4729ba0f2a25caaf29d 100644 (file)
@@ -60,8 +60,6 @@ public:
     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
@@ -97,6 +95,12 @@ public:
     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; }
 
index 3fa7a08f7befa1ef24bf2085f53f74e686be70a8..7691be562809323f4c8c18f0309974f5046d09d2 100644 (file)
@@ -39,8 +39,6 @@
 #include "protocols/protocol_ids.h" // include ipv4 protocol numbers
 
 
-
-
 #define ETHERNET_TYPE_IP 0x0800
 
 #ifndef IP_MAXPACKET
@@ -59,38 +57,6 @@ constexpr uint8_t IP4_RESERVED = 0x0F;  // ms nibble
 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
@@ -150,6 +116,9 @@ 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); }
@@ -162,6 +131,7 @@ struct IP4Hdr
 } ;
 
 
+
 static inline bool isPrivateIP(uint32_t addr)
 {
     switch (addr & 0xff)
@@ -184,27 +154,15 @@ static inline bool isPrivateIP(uint32_t addr)
 
 } /* 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() */
 
 
diff --git a/src/protocols/ipv4_options.cc b/src/protocols/ipv4_options.cc
new file mode 100644 (file)
index 0000000..b57b226
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+** 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
diff --git a/src/protocols/ipv4_options.h b/src/protocols/ipv4_options.h
new file mode 100644 (file)
index 0000000..3ddd4c2
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+** 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 */
index 589306a136020affc78f904a12658803b222a91d..6f42a14cf432b69f01feb974bca017603191a12b 100644 (file)
@@ -158,7 +158,6 @@ const uint8_t* get_root_layer(const Packet* const p)
     return nullptr;
 }
 
-
 uint8_t get_outer_ip_next_pro(const Packet* const p)
 {
     const Layer* layers = p->layers;
@@ -170,7 +169,7 @@ uint8_t get_outer_ip_next_pro(const Packet* const p)
         {
             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();
@@ -181,7 +180,7 @@ uint8_t get_outer_ip_next_pro(const Packet* const p)
     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;
 
index 5cb5071b46a4c124590c02a3f1cd46232e0db35f..f8f125bd8800451e0ac3140c9db0986f276b1a7f 100644 (file)
 
 
 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;
 };
 
 
@@ -102,6 +114,9 @@ SO_PUBLIC const eth::EtherHdr* get_eth_layer(const Packet*);
 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
@@ -113,7 +128,6 @@ SO_PUBLIC const udp::UDPHdr* get_outer_udp_lyr(const Packet* const);
 //          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);
 
@@ -126,11 +140,6 @@ 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,
index 281366b022c13004aa7cda04401754fe72b0f16f..44a6c192329030b9d4502811fe559ed58e1eb538 100644 (file)
@@ -47,7 +47,6 @@ extern "C" {
 }
 
 #include "main/snort_types.h"
-#include "sfip/sf_ip.h"
 
 
 #include "protocols/tcp.h"
@@ -162,15 +161,6 @@ constexpr uint8_t LAYER_MAX = 32;
 class Flow;
 
 
-struct Options
-{
-    uint8_t code;
-    uint8_t len; /* length of the data section */
-    const uint8_t *data;
-} ;
-
-
-
 struct Packet
 {
 
@@ -194,17 +184,6 @@ 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 */
@@ -218,12 +197,11 @@ struct Packet
     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 */
 
@@ -239,7 +217,6 @@ struct Packet
     uint16_t user_policy_id;
 
     uint32_t iplist_id;
-    unsigned char iprep_layer;
 
     uint8_t ps_proto;  // Used for portscan and unified2 logging
 
index 7e2f2ea6aef22adc4d388ba9dd54eb4f30a92bfb..33fcaca63f76f5851b9405dd478fea0ad6f617e7 100644 (file)
@@ -41,6 +41,7 @@
 #include "codecs/decode_module.h"
 #include "utils/stats.h"
 #include "log/text_log.h"
+#include "main/snort_debug.h"
 
 
 #ifdef PERF_PROFILING
@@ -86,20 +87,14 @@ static inline void push_layer(Packet *p,
                                 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
 }
 
 //-------------------------------------------------------------------------
@@ -181,11 +176,14 @@ void PacketManager::decode(
         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"
@@ -360,7 +358,7 @@ int PacketManager::encode_format_with_daq_info (
 
     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)
index 1abb34483140e7c2424d738094ed7365ff3a4ab9..98096b3f6ab75ddcc43cd4821c50863f2421b2e8 100644 (file)
 ** 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>
@@ -50,6 +50,13 @@ public:
     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*);
@@ -64,12 +71,6 @@ public:
     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,
index 23aba2bc0a4a6870626cde9e229dd4aa90f884df..83150d64638bf9b70e07ffb08414af328e0100af 100644 (file)
@@ -76,7 +76,6 @@ constexpr uint16_t ETHERNET_LLC = 0x0106;
 
 
 
-
 /*
  * Below is a partial list of ethertypes.
  *  Defined at:
index c8d314d6ff0890d4ebf1e38be6dce0df72d9277b..b4fb866786a2648421338cde45409acf9c88d334 100644 (file)
@@ -24,7 +24,6 @@
 
 #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
 {
 
@@ -102,97 +94,20 @@ struct TCPHdr
 
     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))
 
 
@@ -200,70 +115,4 @@ inline void set_tcp_x2(TCPHdr* tcph, uint8_t value)
 
 
 
-/* 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 */
diff --git a/src/protocols/tcp_options.cc b/src/protocols/tcp_options.cc
new file mode 100644 (file)
index 0000000..38bb324
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+** 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
diff --git a/src/protocols/tcp_options.h b/src/protocols/tcp_options.h
new file mode 100644 (file)
index 0000000..b244289
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+** 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 */
index 8ec6db96e59a20f6f3bca70f24a40d1a3ae6dc55..f47346ad227434dc701f55bcfdaebb4f3608a406 100644 (file)
@@ -44,6 +44,7 @@
 #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;
index 80e294a42b362705ea8ea87d99976e6d5e9c477c..19d808451901ba936d1d00d255b50abc22efd539 100644 (file)
@@ -64,7 +64,6 @@
  */
 
 /*  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  **************************************************/
 
@@ -257,7 +250,7 @@ THREAD_LOCAL ProfileStats fragRebuildPerfStats;
 /*  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 */
@@ -525,27 +518,30 @@ static inline int CheckTimeout(struct timeval *current_time,
  *
  * @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)
         {
@@ -621,7 +617,7 @@ static inline int FragCheckFirstLast(Packet *p, FragTracker *ft)
         }
     }
 
-    if (p->frag_offset != 0)
+    if (frag_offset != 0)
     {
         ft->frag_flags |= FRAG_NO_BSD_VULN;
     }
@@ -644,23 +640,25 @@ static inline int FragCheckFirstLast(Packet *p, FragTracker *ft)
  * @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);
                 }
@@ -671,7 +669,6 @@ static int FragHandleIPOptions(FragTracker *ft,
                 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;
             }
         }
     }
@@ -681,23 +678,26 @@ static int FragHandleIPOptions(FragTracker *ft,
 
         /* 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);
             }
         }
@@ -749,7 +749,7 @@ int FragGetPolicy(Packet *p, FragEngine *engine)
  */
 static inline int checkTinyFragments(
         FragEngine *engine,
-        Packet *p,
+        const Packet* const p,
         unsigned int trimmedLength
         )
 {
@@ -760,11 +760,11 @@ static inline int checkTinyFragments(
         ///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;
             }
@@ -1333,6 +1333,8 @@ void Defrag::process(Packet* p, FragTracker* ft)
     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
@@ -1351,7 +1353,7 @@ void Defrag::process(Packet* p, FragTracker* ft)
      *    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);
@@ -1367,7 +1369,7 @@ void Defrag::process(Packet* p, FragTracker* ft)
                 "[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);
@@ -1429,7 +1431,7 @@ void Defrag::process(Packet* p, FragTracker* ft)
             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;
@@ -1440,7 +1442,7 @@ void Defrag::process(Packet* p, FragTracker* ft)
                         "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);
@@ -1453,7 +1455,7 @@ void Defrag::process(Packet* p, FragTracker* ft)
             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;
@@ -1462,7 +1464,7 @@ void Defrag::process(Packet* p, FragTracker* ft)
                 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);
@@ -1488,7 +1490,7 @@ void Defrag::process(Packet* p, FragTracker* ft)
         {
             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
@@ -1550,12 +1552,13 @@ int Defrag::insert(Packet *p, FragTracker *ft, FragEngine *fe)
     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)
@@ -1568,15 +1571,19 @@ int Defrag::insert(Packet *p, FragTracker *ft, FragEngine *fe)
      * 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()))
     {
@@ -1590,7 +1597,7 @@ int Defrag::insert(Packet *p, FragTracker *ft, FragEngine *fe)
     /*
      * 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;
@@ -1908,7 +1915,7 @@ left_overlap_last:
         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;
     }
@@ -2273,22 +2280,26 @@ int Defrag::new_tracker(Packet *p, FragTracker* ft)
     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;
@@ -2299,15 +2310,19 @@ int Defrag::new_tracker(Packet *p, FragTracker* ft)
     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;
@@ -2317,10 +2332,8 @@ int Defrag::new_tracker(Packet *p, FragTracker* ft)
     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;
@@ -2358,7 +2371,7 @@ int Defrag::new_tracker(Packet *p, FragTracker* ft)
     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 */
@@ -2400,7 +2413,7 @@ int Defrag::new_tracker(Packet *p, FragTracker* ft)
     /*
      * mark the FragTracker if this is the first/last frag
      */
-    FragCheckFirstLast(p, ft);
+    FragCheckFirstLast(p, ft, frag_off);
 
     ft->frag_bytes += fragLength;
 
index 006a518827bd30fdafdad109d3f626c3d3dbb9fe..17c3bf1fed2550912326e483740c5885c0961551 100644 (file)
@@ -32,6 +32,7 @@
 #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;
index 1fd57058250ec2ca7d29c97ddd3c576e58d940af..57ed055521fd673708069d8d9b8c19eac88e1029 100644 (file)
@@ -55,11 +55,9 @@ struct FragTracker
     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;
 
index 891c8e0160c8cbe5579e7bff2a5bd0b88fe210a0..94edfb778aa15ec32f52dd25f1faa176399e2585 100644 (file)
@@ -32,6 +32,7 @@
 #include "detection/detection_defines.h"
 #include "hash/sfhashfcn.h"
 #include "time/profiler.h"
+#include "sfip/sf_ip.h"
 
 enum SsodOp
 {
index ef436a1891871e05e65f0d52d80dea7953d010fd..bda1df6c95a345a9b9f516ca399b2f45c4abd53e 100644 (file)
@@ -69,6 +69,7 @@
 #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"
@@ -81,6 +82,7 @@
 #include "file_api/file_api.h"
 #include "tcp_module.h"
 #include "stream/stream_splitter.h"
+#include "sfip/sf_ip.h"
 
 using namespace tcp;
 
@@ -1024,26 +1026,11 @@ static inline int NormalDropPacketIf (Packet* p, NormFlags f)
     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]++;
@@ -2759,28 +2746,29 @@ static inline void S5TraceTCP (
 
 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;
 
@@ -2792,21 +2780,19 @@ static uint32_t Stream5GetTcpTimestamp(Packet *p, uint32_t *ts, int strip)
 
 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;
@@ -2818,15 +2804,18 @@ static uint32_t Stream5GetMss(Packet *p, uint16_t *value)
 
 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););
 
@@ -2843,8 +2832,6 @@ static uint32_t Stream5GetWscale(Packet *p, uint16_t *value)
 
             return TF_WSCALE;
         }
-
-        i++;
     }
 
     *value = 0;
index 4213d17eebe7732885c8a64c762b61e7519ad5e0..f56d5226cd8ee2dc3f5c3b78908549b4aa187c84 100644 (file)
@@ -44,6 +44,7 @@
 #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
index 53259836d951764a8592cd2fe4f6f03f25c24904..699dad2b63bd483330371520e0471ccbca2a3aa9 100644 (file)
@@ -50,6 +50,7 @@
 #include "snort.h"
 #include "snort_debug.h"
 #include "utils/stats.h"
+#include "sfip/sf_ip.h"
 
 #define ATTRIBUTE_MAP_MAX_ROWS 1024
 
index 1d28b3cbd9edc055c4f44ff7ae8e3ca546b8be18..ed5786c6caa494aadc5de396f4f1c22b95befed0 100644 (file)
@@ -75,6 +75,7 @@
 #include "actions/actions.h"
 #include "protocols/packet.h"
 #include "utils/stats.h"
+#include "sfip/sf_ip.h"
 
 #ifdef PPM_MGR
 
index 04e4b066e3a223cf520a074ecc7db4bca27b37d0..eac129932527febcf2bdac7a334440b7c806f4ae 100644 (file)
 #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