if (ipv6::is_res_set(ip6frag_hdr))
p->decode_flags |= DECODE__RF;
-
- p->frag_offset = IP6F_OFFSET(ip6frag_hdr);
+ // three least signifigant bits are all flags
+ p->frag_offset = ntohs(ip6frag_hdr->get_off()) >> 3;
if (p->frag_offset || (p->decode_flags & DECODE__MF))
{
p->decode_flags |= DECODE__FRAG;
if (raw_len >= 1 && raw_pkt[0] == 0x11)
{
- if (p->ip_options_data != NULL) {
- if (p->ip_options_len >= 2) {
- if (*(p->ip_options_data) == 0 && *(p->ip_options_data+1) == 0)
+ const uint8_t* ip_opt_data = p->ip_api.get_ip_opt_data();
+
+ if (ip_opt_data != nullptr) {
+ if (p->ip_api.get_ip_opt_len() >= 2) {
+ if (*(ip_opt_data) == 0 && *(ip_opt_data+1) == 0)
{
codec_events::decoder_event(p, DECODE_IGMP_OPTIONS_DOS);
return false;
/* lay the IP struct over the raw data */
IPHdr* iph = reinterpret_cast<IPHdr*>(const_cast<uint8_t *>(raw_pkt));
- p->ip_api.set(iph);
/*
* with datalink DLT_RAW it's impossible to differ ARP datagrams from IP.
return false;
}
+ // set the api now since this layer has been verified as valid
+ p->ip_api.set(iph);
+
/*
* IP Header tests: Land attack, and Loop back test
*/
}
/* test for IP options */
- p->ip_options_len = (uint16_t)(hlen - ip::IP4_HEADER_LEN);
+ uint16_t ip_opt_len = (uint16_t)(hlen - ip::IP4_HEADER_LEN);
- if(p->ip_options_len > 0)
+ if(ip_opt_len > 0)
{
- p->ip_options_data = raw_pkt + ip::IP4_HEADER_LEN;
- DecodeIPOptions((raw_pkt + ip::IP4_HEADER_LEN), p->ip_options_len, p);
+ DecodeIPOptions((raw_pkt + ip::IP4_HEADER_LEN), ip_opt_len, p);
}
else
{
* Zero these options so they aren't associated with this inner IP
* since p->iph will be pointing to this inner IP
*/
- if (p->encapsulations)
- {
- p->ip_options_data = NULL;
- p->ip_options_len = 0;
- }
p->ip_option_count = 0;
}
ip_len -= hlen;
/* check for fragmented packets */
- p->frag_offset = ntohs(iph->get_off());
+ uint16_t frag_off = ntohs(iph->get_off());
/*
* get the values of the reserved, more
* fragments and don't fragment flags
*/
- if (p->frag_offset & 0x8000)
+ if (frag_off & 0x8000)
p->decode_flags |= DECODE__RF;
- if (p->frag_offset & 0x4000)
+ if (frag_off & 0x4000)
p->decode_flags |= DECODE__DF;
- if (p->frag_offset & 0x2000)
+ if (frag_off & 0x2000)
p->decode_flags |= DECODE__MF;
/* mask off the high bits in the fragment offset field */
- p->frag_offset &= 0x1FFF;
+ frag_off &= 0x1FFF;
- if ((p->decode_flags & DECODE__DF) && p->frag_offset )
+ if ((p->decode_flags & DECODE__DF) && frag_off )
codec_events::decoder_event(p, DECODE_IP4_DF_OFFSET);
- if ( p->frag_offset + ip_len > IP_MAXPACKET )
+ if ( frag_off + ip_len > IP_MAXPACKET )
codec_events::decoder_event(p, DECODE_IP4_LEN_OFFSET);
- if(p->frag_offset || (p->decode_flags & DECODE__MF))
+ if(frag_off || (p->decode_flags & DECODE__MF))
{
if ( !ip_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);
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) && (p->frag_offset == 0) &&
+ ((p->decode_flags & DECODE__FRAG) && (frag_off == 0) &&
(iph->get_proto() == IPPROTO_UDP)))
{
DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "IP header length: %lu\n",
/* Remove outer IP options */
- if (p->encapsulations)
- {
- p->ip_options_data = NULL;
- p->ip_options_len = 0;
- }
p->ip_option_count = 0;
/* set the real IP length for logging */
bool TcpCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
Packet *p, uint16_t &lyr_len, uint16_t& /*next_prot_id*/)
{
- if(raw_len < tcp::hdr_len())
+ if(raw_len < tcp::TCP_HEADER_LEN)
{
DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
"TCP packet (len = %d) cannot contain " "20 byte header\n", raw_len););
}
/* lay TCP on top of the data cause there is enough of it! */
- p->tcph = reinterpret_cast<tcp::TCPHdr*>(const_cast<uint8_t*>(raw_pkt));
+ tcp::TCPHdr* tcph = reinterpret_cast<tcp::TCPHdr*>(const_cast<uint8_t*>(raw_pkt));
+ p->tcph = tcph;
/* multiply the payload offset value by 4 */
- lyr_len = TCP_OFFSET(p->tcph) << 2;
+ 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););
- if(lyr_len < tcp::hdr_len())
+ if(lyr_len < tcp::TCP_HEADER_LEN)
{
DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
"TCP Data Offset (%d) < lyr_len (%d) \n",
p->dp = ntohs(p->tcph->th_dport);
- DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "tcp header starts at: %p\n", p->tcph););
-
/* if options are present, decode them */
- p->tcp_options_len = (uint16_t)(lyr_len - tcp::hdr_len());
+ uint16_t tcp_opt_len = (uint16_t)(tcph->hdr_len() - tcp::TCP_HEADER_LEN);
- if(p->tcp_options_len > 0)
+ if(tcp_opt_len > 0)
{
DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "%lu bytes of tcp options....\n",
- (unsigned long)(p->tcp_options_len)););
+ (unsigned long)(tcp_opt_len)););
- p->tcp_options_data = raw_pkt + tcp::hdr_len();
- DecodeTCPOptions((uint8_t *) (raw_pkt + tcp::hdr_len()), p->tcp_options_len, p);
+ p->tcp_options_data = raw_pkt + tcp::TCP_HEADER_LEN;
+ DecodeTCPOptions((uint8_t *) (raw_pkt + tcp::TCP_HEADER_LEN), tcp_opt_len, p);
}
else
{
* 4) increment option code ptr
*
* TCP_OPTLENMAX = 40 because of
- * (((2^4) - 1) * 4 - tcp::hdr_len)
+ * (((2^4) - 1) * 4 - tcp::TCP_HEADER_LEN
*
*/
{
tcp::TCPHdr* h = reinterpret_cast<tcp::TCPHdr*>(lyr->start);
- *len += tcp::get_tcp_hdr_len(h) + p->dsize;
+ *len += h->hdr_len() + p->dsize;
if ( !PacketWasCooked(p) || (p->packet_flags & PKT_REBUILT_FRAG) )
{
/* PPPoEHdr Header; eth::EtherHdr plus the PPPoE Header */
struct PPPoEHdr
{
- unsigned char ver_type; /* pppoe version/type */
- unsigned char code; /* pppoe code CODE_* */
- unsigned short session; /* session id */
- unsigned short length; /* payload length */
+ uint8_t ver_type; /* pppoe version/type */
+ uint8_t code; /* pppoe code CODE_* */
+ uint16_t session; /* session id */
+ uint16_t length; /* payload length */
/* payload follows */
};
typedef uint32_t EncodeFlags;
-const uint32_t ENC_FLAG_FWD = 0x80000000; // send in forward direction
-const uint32_t ENC_FLAG_SEQ = 0x40000000; // VAL bits contain seq adj
-const uint32_t ENC_FLAG_ID = 0x20000000; // use randomized IP ID
-const uint32_t ENC_FLAG_NET = 0x10000000; // stop after innermost network (ip4/6) layer
-const uint32_t ENC_FLAG_DEF = 0x08000000; // stop before innermost ip4 opts or ip6 frag header
-const uint32_t ENC_FLAG_RAW = 0x04000000; // don't encode outer eth header (this is raw ip)
-const uint32_t ENC_FLAG_RES = 0x03000000; // bits reserved for future use
-const uint32_t ENC_FLAG_VAL = 0x00FFFFFF; // bits for adjusting seq and/or ack
+constexpr uint32_t ENC_FLAG_FWD = 0x80000000; // send in forward direction
+constexpr uint32_t ENC_FLAG_SEQ = 0x40000000; // VAL bits contain seq adj
+constexpr uint32_t ENC_FLAG_ID = 0x20000000; // use randomized IP ID
+constexpr uint32_t ENC_FLAG_NET = 0x10000000; // stop after innermost network (ip4/6) layer
+constexpr uint32_t ENC_FLAG_DEF = 0x08000000; // stop before innermost ip4 opts or ip6 frag header
+constexpr uint32_t ENC_FLAG_RAW = 0x04000000; // don't encode outer eth header (this is raw ip)
+constexpr uint32_t ENC_FLAG_RES = 0x03000000; // bits reserved for future use
+constexpr uint32_t ENC_FLAG_VAL = 0x00FFFFFF; // bits for adjusting seq and/or ack
struct EncState{
if ( !p->proto_bits )
p->proto_bits = PROTO_BIT__OTHER;
- // FIXIT required until decoders are fixed
- else if ( !p->family && (p->proto_bits & PROTO_BIT__IP) )
- p->proto_bits &= ~PROTO_BIT__IP;
-
set_policy(p);
p->user_policy_id = get_ips_policy()->user_policy_id;
if ( p->num_layers == LAYER_MAX )
{
codec_events::decoder_event(p, DECODE_TOO_MANY_LAYERS);
+ p->dsize = (uint16_t)len;
+ p->data = pkt;
MODULE_PROFILE_END(decodePerfStats);
return /*false */;
}
ipv6_util::CheckIPv6ExtensionOrder(p);
s_stats[mapped_prot + stat_offset]++;
+
+ /*
+ * NOTE: NEVER RETURN BEFORE SETTING THESE TWO VARIABLES!!
+ * they are no longer zeroed above, which means if they
+ * unset, undefined behavior will ensure
+ */
p->dsize = (uint16_t)len;
p->data = pkt;
sfBase.iPegs[PERF_COUNT_TCP_URG]++;
changes++;
}
- if ( p->tcp_options_len > 0 )
+
+ uint8_t tcp_options_len = p->tcph->options_len();
+ if ( tcp_options_len > 0 )
{
- uint8_t* opts = p->layers[layer].start + TCP_HEADER_LEN;
+ uint8_t* opts = p->layers[layer].start + tcp::TCP_HEADER_LEN;
if ( Norm_IsEnabled(c, NORM_TCP_OPT) )
{
- changes = Norm_TCPOptions(c, opts, p->tcp_options_len,
+ changes = Norm_TCPOptions(c, opts, tcp_options_len,
h, p->tcp_option_count, changes);
}
else
{
- changes = Norm_TCPPadding(opts, p->tcp_options_len,
+ changes = Norm_TCPPadding(opts, tcp_options_len,
p->tcp_option_count, changes);
}
}
return ip4h->get_id();
// ensure we have an ipv6 frag
- if (p->ip6_extension_count == 0 || p->ip_frag_start == 0)
+ if (p->ip6_extension_count == 0 || p->ip_frag_start == 0 || !ip6h )
return 0;
const IP6Frag* const frag_hdr = reinterpret_cast<const IP6Frag* const>(
return ip4h->get_id();
// ensure we have an ipv6 frag
- if (p->ip6_extension_count == 0 || p->ip_frag_start == 0)
+ if (p->ip6_extension_count == 0 || p->ip_frag_start == 0 || !ip6h)
return 0;
const IP6Frag* const frag_hdr = reinterpret_cast<const IP6Frag* const>(
inline uint32_t get_ip4_dst() const
{ return ip4h ? ip4h->get_dst() : 0; }
+ // only relevent to IP4.
+ inline uint8_t get_ip_opt_len() const
+ { return ip4h ? ip4h->get_opt_len() : 0; }
+
+ // only relevent to IP4.
+ inline const uint8_t* get_ip_opt_data() const
+ { return ip4h ? reinterpret_cast<const uint8_t*>(ip4h + IP4_HEADER_LEN) : nullptr; }
+
inline const ipv6::snort_in6_addr* get_ip6_src() const
{ return ip6h ? ip6h->get_src() : nullptr; }
inline uint32_t get_dst() const
{ return ip_dst; }
+ inline uint8_t get_opt_len() const
+ { return (get_hlen() << 2) - IP4_HEADER_LEN; }
+
/* booleans */
inline bool is_src_broadcast() const
{ return ip_src == detail::IP4_BROADCAST; }
(ntohl(p_rawiph->ip6_vtf) >> 28)
-#define IP6F_OFFSET_MASK 0xfff8 /* mask out offset from _offlg */
#define IP6F_MF_MASK 0x0001 /* more-fragments flag */
-#define IP6F_OFFSET(fh) ((ntohs((fh)->ip6f_offlg) & IP6F_OFFSET_MASK) >> 3)
enum class MulticastScope : uint8_t
struct Packet
{
- //vvv------------------------------------------------
- // TODO convenience stuff to be refactored for layers
- //^^^------------------------------------------------
-
- //vvv-----------------------------
-
+ /* these four pounters are each referenced literally
+ * hundreds of times. NOTHING else should be added!!
+ */
const tcp::TCPHdr* tcph;
const udp::UDPHdr* udph;
const ICMPHdr* icmph;
-
- //^^^-----------------------------
-
Flow* flow; /* for session tracking */
- //vvv-----------------------------
- int family;
- //^^^-----------------------------
+
uint32_t packet_flags; /* special flags for the packet */
uint32_t xtradata_mask;
+ uint16_t proto_bits; /* protocols contained within this packet */
+ int16_t application_protocol_ordinal;
- uint16_t proto_bits;
- //vvv-----------------------------
- const uint8_t* data; /* packet payload pointer */
- uint16_t dsize; /* packet payload size */
uint16_t alt_dsize; /* the dsize of a packet before munging (used for log)*/
- //^^^-----------------------------
+ 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;
- uint16_t ip_options_len;
- uint16_t tcp_options_len;
- //vvv-----------------------------
- uint16_t sp; /* source port (TCP/UDP) */
- uint16_t dp; /* dest port (TCP/UDP) */
- //^^^-----------------------------
- // and so on ...
- int16_t application_protocol_ordinal;
uint8_t ip_option_count; /* number of options in this packet */
uint8_t tcp_option_count;
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 */
- uint8_t encapsulations; /* thh curent number of encapsulations */
+ uint8_t encapsulations; /* the curent number of encapsulations */
// nothing after this point is zeroed ...
const DAQ_PktHdr_t *pkth; // packet meta data
const uint8_t *pkt; // raw packet data
+ // These are both set before PacketManager::decode() returns
+ 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 */
IP6Option ip6_extensions[IP6_EXTMAX]; /* IPv6 Extension References */
const uint8_t *ip_frag_start;
- const uint8_t *ip_options_data;
const uint8_t *tcp_options_data;
Layer layers[LAYER_MAX]; /* decoded encapsulations */
ip::IpApi ip_api;
-
mpls::MplsHdr mplsHdr;
PseudoPacketType pseudo_type; // valid only when PKT_PSEUDO is set
p->xtradata_mask |= BIT(xid);
}
-static inline bool is_ip4(const Packet *p)
-{
- return p->family == AF_INET;
-}
-
-static inline bool is_ip6(const Packet *p)
-{
- return p->family == AF_INET6;
-}
-
static inline uint16_t EXTRACT_16BITS(const uint8_t* p)
{
return ntohs(*(uint16_t*)(p));
namespace tcp
{
-namespace detail
-{
-
-constexpr uint8_t TCP_HEADER_LEN = 20;
-
-} // namespace detail
+constexpr uint8_t TCP_HEADER_LEN = 20; // this is actually the minimal TCP header lenght
+constexpr int OPT_TRUNC = -1;
+constexpr int OPT_BADLEN = -2;
struct TCPHdr
{
uint16_t th_win; /* window */
uint16_t th_sum; /* checksum */
uint16_t th_urp; /* urgent pointer */
+
+ inline uint8_t hdr_len() const
+ { return (th_offx2 & 0xf0) >> 2; }
+
+ inline uint8_t off() const
+ { return th_offx2 >> 4; }
+
+ inline uint8_t options_len() const
+ { return hdr_len() - TCP_HEADER_LEN; }
};
-const int OPT_TRUNC = -1;
-const int OPT_BADLEN = -2;
+#if 0
inline uint8_t hdr_len()
{
return detail::TCP_HEADER_LEN;
}
+#endif
inline uint8_t get_tcp_hdr_len(const TCPHdr *h)
{
#define TCP_ISFLAGSET(tcph, flags) (((tcph)->th_flags & (flags)) == (flags))
-} // namespace Tcp
+} // namespace tcp
#define TCPOPT_AUTH 29 /* [RFC5925] - The TCP Authentication Option
Intended to replace MD5 Signature Option [RFC2385] */
-#define TCP_HEADER_LEN tcp::hdr_len()
-
-
#endif /* TCP_H */
};
-
-// because we can --- and this is leftover from Snort which we're stuck with
-#ifdef inet_ntoa
-#undef inet_ntoa
-#endif
-
-char *sfip_to_str(const sfip_t *ip);
-#define sfip_ntoa(x) sfip_to_str(x)
-#define inet_ntoa sfip_ntoa
-
-
/*
- * Implementing these functions rather than opeators since
+ * Implementing these functions rather than implenting opeators since
* the Google style guide recomends staying away from
* operators. Most of these are a copy and paste from sf_ip.h
*/
+// because we can --- and this is leftover from Snort which we're stuck with
+#ifdef inet_ntoa
+#undef inet_ntoa
+#endif
+
+char *sfip_to_str(const sfip_t *ip);
+#define sfip_ntoa(x) sfip_to_str(x)
+#define inet_ntoa sfip_ntoa
+
+
/* Returns 1 if the IP is non-zero. 0 otherwise *
* XXX This is a performance critical function,
* need to determine if it's safe to not check these pointers
* This is the first packet. If it has IP options,
* save them off, so we can set them on the reassembled packet.
*/
- if (p->ip_options_len)
+ uint16_t ip_options_len = p->ip_api.get_ip_opt_len();
+ if (ip_options_len)
{
if (ft->ip_options_data)
{
else
{
/* Allocate and copy in the options */
- ft->ip_options_data = (uint8_t*)SnortAlloc(p->ip_options_len);
- memcpy(ft->ip_options_data, p->ip_options_data, p->ip_options_len);
- ft->ip_options_len = p->ip_options_len;
+ 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;
}
}