aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/suricata/src/decode.h
diff options
context:
space:
mode:
authorAshlee Young <ashlee@onosfw.com>2015-09-09 22:21:41 -0700
committerAshlee Young <ashlee@onosfw.com>2015-09-09 22:21:41 -0700
commit8879b125d26e8db1a5633de5a9c692eb2d1c4f83 (patch)
treec7259d85a991b83dfa85ab2e339360669fc1f58e /framework/src/suricata/src/decode.h
parent13d05bc8458758ee39cb829098241e89616717ee (diff)
suricata checkin based on commit id a4bce14770beee46a537eda3c3f6e8e8565d5d0a
Change-Id: I9a214fa0ee95e58fc640e50bd604dac7f42db48f
Diffstat (limited to 'framework/src/suricata/src/decode.h')
-rw-r--r--framework/src/suricata/src/decode.h1048
1 files changed, 1048 insertions, 0 deletions
diff --git a/framework/src/suricata/src/decode.h b/framework/src/suricata/src/decode.h
new file mode 100644
index 00000000..2f322a02
--- /dev/null
+++ b/framework/src/suricata/src/decode.h
@@ -0,0 +1,1048 @@
+/* Copyright (C) 2007-2013 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * 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
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * \file
+ *
+ * \author Victor Julien <victor@inliniac.net>
+ */
+
+#ifndef __DECODE_H__
+#define __DECODE_H__
+
+//#define DBG_THREADS
+#define COUNTERS
+
+#include "suricata-common.h"
+#include "threadvars.h"
+#include "decode-events.h"
+
+#ifdef __SC_CUDA_SUPPORT__
+#include "util-cuda-buffer.h"
+#include "util-cuda-vars.h"
+#endif /* __SC_CUDA_SUPPORT__ */
+
+typedef enum {
+ CHECKSUM_VALIDATION_DISABLE,
+ CHECKSUM_VALIDATION_ENABLE,
+ CHECKSUM_VALIDATION_AUTO,
+ CHECKSUM_VALIDATION_RXONLY,
+ CHECKSUM_VALIDATION_KERNEL,
+} ChecksumValidationMode;
+
+enum PktSrcEnum {
+ PKT_SRC_WIRE = 1,
+ PKT_SRC_DECODER_GRE,
+ PKT_SRC_DECODER_IPV4,
+ PKT_SRC_DECODER_IPV6,
+ PKT_SRC_DECODER_TEREDO,
+ PKT_SRC_DEFRAG,
+ PKT_SRC_STREAM_TCP_STREAM_END_PSEUDO,
+ PKT_SRC_FFR,
+};
+
+#include "source-nflog.h"
+#include "source-nfq.h"
+#include "source-ipfw.h"
+#include "source-pcap.h"
+#include "source-af-packet.h"
+#include "source-mpipe.h"
+#include "source-netmap.h"
+
+#include "action-globals.h"
+
+#include "decode-erspan.h"
+#include "decode-ethernet.h"
+#include "decode-gre.h"
+#include "decode-ppp.h"
+#include "decode-pppoe.h"
+#include "decode-sll.h"
+#include "decode-ipv4.h"
+#include "decode-ipv6.h"
+#include "decode-icmpv4.h"
+#include "decode-icmpv6.h"
+#include "decode-tcp.h"
+#include "decode-udp.h"
+#include "decode-sctp.h"
+#include "decode-raw.h"
+#include "decode-null.h"
+#include "decode-vlan.h"
+#include "decode-mpls.h"
+
+#include "detect-reference.h"
+
+#include "app-layer-protos.h"
+
+/* forward declarations */
+struct DetectionEngineThreadCtx_;
+typedef struct AppLayerThreadCtx_ AppLayerThreadCtx;
+
+struct PktPool_;
+
+/* declare these here as they are called from the
+ * PACKET_RECYCLE and PACKET_CLEANUP macro's. */
+typedef struct AppLayerDecoderEvents_ AppLayerDecoderEvents;
+void AppLayerDecoderEventsResetEvents(AppLayerDecoderEvents *events);
+void AppLayerDecoderEventsFreeEvents(AppLayerDecoderEvents **events);
+
+/* Address */
+typedef struct Address_ {
+ char family;
+ union {
+ uint32_t address_un_data32[4]; /* type-specific field */
+ uint16_t address_un_data16[8]; /* type-specific field */
+ uint8_t address_un_data8[16]; /* type-specific field */
+ } address;
+} Address;
+
+#define addr_data32 address.address_un_data32
+#define addr_data16 address.address_un_data16
+#define addr_data8 address.address_un_data8
+
+#define COPY_ADDRESS(a, b) do { \
+ (b)->family = (a)->family; \
+ (b)->addr_data32[0] = (a)->addr_data32[0]; \
+ (b)->addr_data32[1] = (a)->addr_data32[1]; \
+ (b)->addr_data32[2] = (a)->addr_data32[2]; \
+ (b)->addr_data32[3] = (a)->addr_data32[3]; \
+ } while (0)
+
+/* Set the IPv4 addresses into the Addrs of the Packet.
+ * Make sure p->ip4h is initialized and validated.
+ *
+ * We set the rest of the struct to 0 so we can
+ * prevent using memset. */
+#define SET_IPV4_SRC_ADDR(p, a) do { \
+ (a)->family = AF_INET; \
+ (a)->addr_data32[0] = (uint32_t)(p)->ip4h->s_ip_src.s_addr; \
+ (a)->addr_data32[1] = 0; \
+ (a)->addr_data32[2] = 0; \
+ (a)->addr_data32[3] = 0; \
+ } while (0)
+
+#define SET_IPV4_DST_ADDR(p, a) do { \
+ (a)->family = AF_INET; \
+ (a)->addr_data32[0] = (uint32_t)(p)->ip4h->s_ip_dst.s_addr; \
+ (a)->addr_data32[1] = 0; \
+ (a)->addr_data32[2] = 0; \
+ (a)->addr_data32[3] = 0; \
+ } while (0)
+
+/* clear the address structure by setting all fields to 0 */
+#define CLEAR_ADDR(a) do { \
+ (a)->family = 0; \
+ (a)->addr_data32[0] = 0; \
+ (a)->addr_data32[1] = 0; \
+ (a)->addr_data32[2] = 0; \
+ (a)->addr_data32[3] = 0; \
+ } while (0)
+
+/* Set the IPv6 addressesinto the Addrs of the Packet.
+ * Make sure p->ip6h is initialized and validated. */
+#define SET_IPV6_SRC_ADDR(p, a) do { \
+ (a)->family = AF_INET6; \
+ (a)->addr_data32[0] = (p)->ip6h->s_ip6_src[0]; \
+ (a)->addr_data32[1] = (p)->ip6h->s_ip6_src[1]; \
+ (a)->addr_data32[2] = (p)->ip6h->s_ip6_src[2]; \
+ (a)->addr_data32[3] = (p)->ip6h->s_ip6_src[3]; \
+ } while (0)
+
+#define SET_IPV6_DST_ADDR(p, a) do { \
+ (a)->family = AF_INET6; \
+ (a)->addr_data32[0] = (p)->ip6h->s_ip6_dst[0]; \
+ (a)->addr_data32[1] = (p)->ip6h->s_ip6_dst[1]; \
+ (a)->addr_data32[2] = (p)->ip6h->s_ip6_dst[2]; \
+ (a)->addr_data32[3] = (p)->ip6h->s_ip6_dst[3]; \
+ } while (0)
+
+/* Set the TCP ports into the Ports of the Packet.
+ * Make sure p->tcph is initialized and validated. */
+#define SET_TCP_SRC_PORT(pkt, prt) do { \
+ SET_PORT(TCP_GET_SRC_PORT((pkt)), *(prt)); \
+ } while (0)
+
+#define SET_TCP_DST_PORT(pkt, prt) do { \
+ SET_PORT(TCP_GET_DST_PORT((pkt)), *(prt)); \
+ } while (0)
+
+/* Set the UDP ports into the Ports of the Packet.
+ * Make sure p->udph is initialized and validated. */
+#define SET_UDP_SRC_PORT(pkt, prt) do { \
+ SET_PORT(UDP_GET_SRC_PORT((pkt)), *(prt)); \
+ } while (0)
+#define SET_UDP_DST_PORT(pkt, prt) do { \
+ SET_PORT(UDP_GET_DST_PORT((pkt)), *(prt)); \
+ } while (0)
+
+/* Set the SCTP ports into the Ports of the Packet.
+ * Make sure p->sctph is initialized and validated. */
+#define SET_SCTP_SRC_PORT(pkt, prt) do { \
+ SET_PORT(SCTP_GET_SRC_PORT((pkt)), *(prt)); \
+ } while (0)
+
+#define SET_SCTP_DST_PORT(pkt, prt) do { \
+ SET_PORT(SCTP_GET_DST_PORT((pkt)), *(prt)); \
+ } while (0)
+
+
+
+#define GET_IPV4_SRC_ADDR_U32(p) ((p)->src.addr_data32[0])
+#define GET_IPV4_DST_ADDR_U32(p) ((p)->dst.addr_data32[0])
+#define GET_IPV4_SRC_ADDR_PTR(p) ((p)->src.addr_data32)
+#define GET_IPV4_DST_ADDR_PTR(p) ((p)->dst.addr_data32)
+
+#define GET_IPV6_SRC_ADDR(p) ((p)->src.addr_data32)
+#define GET_IPV6_DST_ADDR(p) ((p)->dst.addr_data32)
+#define GET_TCP_SRC_PORT(p) ((p)->sp)
+#define GET_TCP_DST_PORT(p) ((p)->dp)
+
+#define GET_PKT_LEN(p) ((p)->pktlen)
+#define GET_PKT_DATA(p) ((((p)->ext_pkt) == NULL ) ? (uint8_t *)((p) + 1) : (p)->ext_pkt)
+#define GET_PKT_DIRECT_DATA(p) (uint8_t *)((p) + 1)
+#define GET_PKT_DIRECT_MAX_SIZE(p) (default_packet_size)
+
+#define SET_PKT_LEN(p, len) do { \
+ (p)->pktlen = (len); \
+ } while (0)
+
+
+/* Port is just a uint16_t */
+typedef uint16_t Port;
+#define SET_PORT(v, p) ((p) = (v))
+#define COPY_PORT(a,b) ((b) = (a))
+
+#define CMP_ADDR(a1, a2) \
+ (((a1)->addr_data32[3] == (a2)->addr_data32[3] && \
+ (a1)->addr_data32[2] == (a2)->addr_data32[2] && \
+ (a1)->addr_data32[1] == (a2)->addr_data32[1] && \
+ (a1)->addr_data32[0] == (a2)->addr_data32[0]))
+#define CMP_PORT(p1, p2) \
+ ((p1) == (p2))
+
+/*Given a packet pkt offset to the start of the ip header in a packet
+ *We determine the ip version. */
+#define IP_GET_RAW_VER(pkt) ((((pkt)[0] & 0xf0) >> 4))
+
+#define PKT_IS_IPV4(p) (((p)->ip4h != NULL))
+#define PKT_IS_IPV6(p) (((p)->ip6h != NULL))
+#define PKT_IS_TCP(p) (((p)->tcph != NULL))
+#define PKT_IS_UDP(p) (((p)->udph != NULL))
+#define PKT_IS_ICMPV4(p) (((p)->icmpv4h != NULL))
+#define PKT_IS_ICMPV6(p) (((p)->icmpv6h != NULL))
+#define PKT_IS_TOSERVER(p) (((p)->flowflags & FLOW_PKT_TOSERVER))
+#define PKT_IS_TOCLIENT(p) (((p)->flowflags & FLOW_PKT_TOCLIENT))
+
+#define IPH_IS_VALID(p) (PKT_IS_IPV4((p)) || PKT_IS_IPV6((p)))
+
+/* Retrieve proto regardless of IP version */
+#define IP_GET_IPPROTO(p) \
+ (p->proto ? p->proto : \
+ (PKT_IS_IPV4((p))? IPV4_GET_IPPROTO((p)) : (PKT_IS_IPV6((p))? IPV6_GET_L4PROTO((p)) : 0)))
+
+/* structure to store the sids/gids/etc the detection engine
+ * found in this packet */
+typedef struct PacketAlert_ {
+ SigIntId num; /* Internal num, used for sorting */
+ uint8_t action; /* Internal num, used for sorting */
+ uint8_t flags;
+ struct Signature_ *s;
+ uint64_t tx_id;
+} PacketAlert;
+
+/** After processing an alert by the thresholding module, if at
+ * last it gets triggered, we might want to stick the drop action to
+ * the flow on IPS mode */
+#define PACKET_ALERT_FLAG_DROP_FLOW 0x01
+/** alert was generated based on state */
+#define PACKET_ALERT_FLAG_STATE_MATCH 0x02
+/** alert was generated based on stream */
+#define PACKET_ALERT_FLAG_STREAM_MATCH 0x04
+/** alert is in a tx, tx_id set */
+#define PACKET_ALERT_FLAG_TX 0x08
+
+#define PACKET_ALERT_MAX 15
+
+typedef struct PacketAlerts_ {
+ uint16_t cnt;
+ PacketAlert alerts[PACKET_ALERT_MAX];
+ /* single pa used when we're dropping,
+ * so we can log it out in the drop log. */
+ PacketAlert drop;
+} PacketAlerts;
+
+/** number of decoder events we support per packet. Power of 2 minus 1
+ * for memory layout */
+#define PACKET_ENGINE_EVENT_MAX 15
+
+/** data structure to store decoder, defrag and stream events */
+typedef struct PacketEngineEvents_ {
+ uint8_t cnt; /**< number of events */
+ uint8_t events[PACKET_ENGINE_EVENT_MAX]; /**< array of events */
+} PacketEngineEvents;
+
+typedef struct PktVar_ {
+ char *name;
+ struct PktVar_ *next; /* right now just implement this as a list,
+ * in the long run we have thing of something
+ * faster. */
+ uint8_t *value;
+ uint16_t value_len;
+} PktVar;
+
+#ifdef PROFILING
+
+/** \brief Per TMM stats storage */
+typedef struct PktProfilingTmmData_ {
+ uint64_t ticks_start;
+ uint64_t ticks_end;
+#ifdef PROFILE_LOCKING
+ uint64_t mutex_lock_cnt;
+ uint64_t mutex_lock_wait_ticks;
+ uint64_t mutex_lock_contention;
+ uint64_t spin_lock_cnt;
+ uint64_t spin_lock_wait_ticks;
+ uint64_t spin_lock_contention;
+ uint64_t rww_lock_cnt;
+ uint64_t rww_lock_wait_ticks;
+ uint64_t rww_lock_contention;
+ uint64_t rwr_lock_cnt;
+ uint64_t rwr_lock_wait_ticks;
+ uint64_t rwr_lock_contention;
+#endif
+} PktProfilingTmmData;
+
+typedef struct PktProfilingDetectData_ {
+ uint64_t ticks_start;
+ uint64_t ticks_end;
+ uint64_t ticks_spent;
+} PktProfilingDetectData;
+
+typedef struct PktProfilingAppData_ {
+ uint64_t ticks_spent;
+} PktProfilingAppData;
+
+/** \brief Per pkt stats storage */
+typedef struct PktProfiling_ {
+ uint64_t ticks_start;
+ uint64_t ticks_end;
+
+ PktProfilingTmmData tmm[TMM_SIZE];
+ PktProfilingAppData app[ALPROTO_MAX];
+ PktProfilingDetectData detect[PROF_DETECT_SIZE];
+ uint64_t proto_detect;
+} PktProfiling;
+
+#endif /* PROFILING */
+
+/* forward declartion since Packet struct definition requires this */
+struct PacketQueue_;
+
+/* sizes of the members:
+ * src: 17 bytes
+ * dst: 17 bytes
+ * sp/type: 1 byte
+ * dp/code: 1 byte
+ * proto: 1 byte
+ * recurs: 1 byte
+ *
+ * sum of above: 38 bytes
+ *
+ * flow ptr: 4/8 bytes
+ * flags: 1 byte
+ * flowflags: 1 byte
+ *
+ * sum of above 44/48 bytes
+ */
+typedef struct Packet_
+{
+ /* Addresses, Ports and protocol
+ * these are on top so we can use
+ * the Packet as a hash key */
+ Address src;
+ Address dst;
+ union {
+ Port sp;
+ uint8_t type;
+ };
+ union {
+ Port dp;
+ uint8_t code;
+ };
+ uint8_t proto;
+ /* make sure we can't be attacked on when the tunneled packet
+ * has the exact same tuple as the lower levels */
+ uint8_t recursion_level;
+
+ uint16_t vlan_id[2];
+ uint8_t vlan_idx;
+
+ /* flow */
+ uint8_t flowflags;
+ /* coccinelle: Packet:flowflags:FLOW_PKT_ */
+
+ /* Pkt Flags */
+ uint32_t flags;
+
+ struct Flow_ *flow;
+
+ struct timeval ts;
+
+ union {
+ /* nfq stuff */
+#ifdef HAVE_NFLOG
+ NFLOGPacketVars nflog_v;
+#endif /* HAVE_NFLOG */
+#ifdef NFQ
+ NFQPacketVars nfq_v;
+#endif /* NFQ */
+#ifdef IPFW
+ IPFWPacketVars ipfw_v;
+#endif /* IPFW */
+#ifdef AF_PACKET
+ AFPPacketVars afp_v;
+#endif
+#ifdef HAVE_MPIPE
+ /* tilegx mpipe stuff */
+ MpipePacketVars mpipe_v;
+#endif
+#ifdef HAVE_NETMAP
+ NetmapPacketVars netmap_v;
+#endif
+
+ /** libpcap vars: shared by Pcap Live mode and Pcap File mode */
+ PcapPacketVars pcap_v;
+ };
+
+ /** The release function for packet structure and data */
+ void (*ReleasePacket)(struct Packet_ *);
+
+ /* pkt vars */
+ PktVar *pktvar;
+
+ /* header pointers */
+ EthernetHdr *ethh;
+
+ /* Checksum for IP packets. */
+ int32_t level3_comp_csum;
+ /* Check sum for TCP, UDP or ICMP packets */
+ int32_t level4_comp_csum;
+
+ IPV4Hdr *ip4h;
+
+ IPV6Hdr *ip6h;
+
+ /* IPv4 and IPv6 are mutually exclusive */
+ union {
+ IPV4Vars ip4vars;
+ struct {
+ IPV6Vars ip6vars;
+ IPV6ExtHdrs ip6eh;
+ };
+ };
+ /* Can only be one of TCP, UDP, ICMP at any given time */
+ union {
+ TCPVars tcpvars;
+ UDPVars udpvars;
+ ICMPV4Vars icmpv4vars;
+ ICMPV6Vars icmpv6vars;
+ };
+
+ TCPHdr *tcph;
+
+ UDPHdr *udph;
+
+ SCTPHdr *sctph;
+
+ ICMPV4Hdr *icmpv4h;
+
+ ICMPV6Hdr *icmpv6h;
+
+ PPPHdr *ppph;
+ PPPOESessionHdr *pppoesh;
+ PPPOEDiscoveryHdr *pppoedh;
+
+ GREHdr *greh;
+
+ VLANHdr *vlanh[2];
+
+ /* ptr to the payload of the packet
+ * with it's length. */
+ uint8_t *payload;
+ uint16_t payload_len;
+
+ /* IPS action to take */
+ uint8_t action;
+
+ uint8_t pkt_src;
+
+ /* storage: set to pointer to heap and extended via allocation if necessary */
+ uint32_t pktlen;
+ uint8_t *ext_pkt;
+
+ /* Incoming interface */
+ struct LiveDevice_ *livedev;
+
+ PacketAlerts alerts;
+
+ struct Host_ *host_src;
+ struct Host_ *host_dst;
+
+ /** packet number in the pcap file, matches wireshark */
+ uint64_t pcap_cnt;
+
+
+ /* engine events */
+ PacketEngineEvents events;
+
+ AppLayerDecoderEvents *app_layer_events;
+
+ /* double linked list ptrs */
+ struct Packet_ *next;
+ struct Packet_ *prev;
+
+ /** data linktype in host order */
+ int datalink;
+
+ /* used to hold flowbits only if debuglog is enabled */
+ int debuglog_flowbits_names_len;
+ const char **debuglog_flowbits_names;
+
+ /* tunnel/encapsulation handling */
+ struct Packet_ *root; /* in case of tunnel this is a ptr
+ * to the 'real' packet, the one we
+ * need to set the verdict on --
+ * It should always point to the lowest
+ * packet in a encapsulated packet */
+
+ /** mutex to protect access to:
+ * - tunnel_rtv_cnt
+ * - tunnel_tpr_cnt
+ */
+ SCMutex tunnel_mutex;
+ /* ready to set verdict counter, only set in root */
+ uint16_t tunnel_rtv_cnt;
+ /* tunnel packet ref count */
+ uint16_t tunnel_tpr_cnt;
+
+ /** tenant id for this packet, if any. If 0 then no tenant was assigned. */
+ uint32_t tenant_id;
+
+ /* The Packet pool from which this packet was allocated. Used when returning
+ * the packet to its owner's stack. If NULL, then allocated with malloc.
+ */
+ struct PktPool_ *pool;
+
+#ifdef PROFILING
+ PktProfiling *profile;
+#endif
+#ifdef __SC_CUDA_SUPPORT__
+ CudaPacketVars cuda_pkt_vars;
+#endif
+}
+#ifdef HAVE_MPIPE
+ /* mPIPE requires packet buffers to be aligned to 128 byte boundaries. */
+ __attribute__((aligned(128)))
+#endif
+Packet;
+
+#define DEFAULT_PACKET_SIZE (1500 + ETHERNET_HEADER_LEN)
+/* storage: maximum ip packet size + link header */
+#define MAX_PAYLOAD_SIZE (IPV6_HEADER_LEN + 65536 + 28)
+uint32_t default_packet_size;
+#define SIZE_OF_PACKET (default_packet_size + sizeof(Packet))
+
+typedef struct PacketQueue_ {
+ Packet *top;
+ Packet *bot;
+ uint32_t len;
+#ifdef DBG_PERF
+ uint32_t dbg_maxlen;
+#endif /* DBG_PERF */
+ SCMutex mutex_q;
+ SCCondT cond_q;
+} PacketQueue;
+
+/** \brief Structure to hold thread specific data for all decode modules */
+typedef struct DecodeThreadVars_
+{
+ /** Specific context for udp protocol detection (here atm) */
+ AppLayerThreadCtx *app_tctx;
+
+ int vlan_disabled;
+
+ /** stats/counters */
+ uint16_t counter_pkts;
+ uint16_t counter_bytes;
+ uint16_t counter_avg_pkt_size;
+ uint16_t counter_max_pkt_size;
+
+ uint16_t counter_invalid;
+
+ uint16_t counter_eth;
+ uint16_t counter_ipv4;
+ uint16_t counter_ipv6;
+ uint16_t counter_tcp;
+ uint16_t counter_udp;
+ uint16_t counter_icmpv4;
+ uint16_t counter_icmpv6;
+
+ uint16_t counter_sll;
+ uint16_t counter_raw;
+ uint16_t counter_null;
+ uint16_t counter_sctp;
+ uint16_t counter_ppp;
+ uint16_t counter_gre;
+ uint16_t counter_vlan;
+ uint16_t counter_vlan_qinq;
+ uint16_t counter_pppoe;
+ uint16_t counter_teredo;
+ uint16_t counter_mpls;
+ uint16_t counter_ipv4inipv6;
+ uint16_t counter_ipv6inipv6;
+ uint16_t counter_erspan;
+
+ /** frag stats - defrag runs in the context of the decoder. */
+ uint16_t counter_defrag_ipv4_fragments;
+ uint16_t counter_defrag_ipv4_reassembled;
+ uint16_t counter_defrag_ipv4_timeouts;
+ uint16_t counter_defrag_ipv6_fragments;
+ uint16_t counter_defrag_ipv6_reassembled;
+ uint16_t counter_defrag_ipv6_timeouts;
+ uint16_t counter_defrag_max_hit;
+
+ /* thread data for flow logging api: only used at forced
+ * flow recycle during lookups */
+ void *output_flow_thread_data;
+
+#ifdef __SC_CUDA_SUPPORT__
+ CudaThreadVars cuda_vars;
+#endif
+} DecodeThreadVars;
+
+typedef struct CaptureStats_ {
+
+ uint16_t counter_ips_accepted;
+ uint16_t counter_ips_blocked;
+ uint16_t counter_ips_rejected;
+ uint16_t counter_ips_replaced;
+
+} CaptureStats;
+
+void CaptureStatsUpdate(ThreadVars *tv, CaptureStats *s, const Packet *p);
+void CaptureStatsSetup(ThreadVars *tv, CaptureStats *s);
+
+/**
+ * \brief reset these to -1(indicates that the packet is fresh from the queue)
+ */
+#define PACKET_RESET_CHECKSUMS(p) do { \
+ (p)->level3_comp_csum = -1; \
+ (p)->level4_comp_csum = -1; \
+ } while (0)
+
+/* if p uses extended data, free them */
+#define PACKET_FREE_EXTDATA(p) do { \
+ if ((p)->ext_pkt) { \
+ if (!((p)->flags & PKT_ZERO_COPY)) { \
+ SCFree((p)->ext_pkt); \
+ } \
+ (p)->ext_pkt = NULL; \
+ } \
+ } while(0)
+
+/**
+ * \brief Initialize a packet structure for use.
+ */
+#ifdef __SC_CUDA_SUPPORT__
+#include "util-cuda-handlers.h"
+#include "util-mpm.h"
+
+#define PACKET_INITIALIZE(p) do { \
+ memset((p), 0x00, SIZE_OF_PACKET); \
+ SCMutexInit(&(p)->tunnel_mutex, NULL); \
+ PACKET_RESET_CHECKSUMS((p)); \
+ (p)->livedev = NULL; \
+ SCMutexInit(&(p)->cuda_pkt_vars.cuda_mutex, NULL); \
+ SCCondInit(&(p)->cuda_pkt_vars.cuda_cond, NULL); \
+ } while (0)
+#else
+#define PACKET_INITIALIZE(p) { \
+ SCMutexInit(&(p)->tunnel_mutex, NULL); \
+ PACKET_RESET_CHECKSUMS((p)); \
+ (p)->livedev = NULL; \
+}
+#endif
+
+#define PACKET_RELEASE_REFS(p) do { \
+ FlowDeReference(&((p)->flow)); \
+ HostDeReference(&((p)->host_src)); \
+ HostDeReference(&((p)->host_dst)); \
+ } while (0)
+
+/**
+ * \brief Recycle a packet structure for reuse.
+ */
+#define PACKET_REINIT(p) do { \
+ CLEAR_ADDR(&(p)->src); \
+ CLEAR_ADDR(&(p)->dst); \
+ (p)->sp = 0; \
+ (p)->dp = 0; \
+ (p)->proto = 0; \
+ (p)->recursion_level = 0; \
+ PACKET_FREE_EXTDATA((p)); \
+ (p)->flags = (p)->flags & PKT_ALLOC; \
+ (p)->flowflags = 0; \
+ (p)->pkt_src = 0; \
+ (p)->vlan_id[0] = 0; \
+ (p)->vlan_id[1] = 0; \
+ (p)->vlan_idx = 0; \
+ (p)->ts.tv_sec = 0; \
+ (p)->ts.tv_usec = 0; \
+ (p)->datalink = 0; \
+ (p)->action = 0; \
+ if ((p)->pktvar != NULL) { \
+ PktVarFree((p)->pktvar); \
+ (p)->pktvar = NULL; \
+ } \
+ (p)->ethh = NULL; \
+ if ((p)->ip4h != NULL) { \
+ CLEAR_IPV4_PACKET((p)); \
+ } \
+ if ((p)->ip6h != NULL) { \
+ CLEAR_IPV6_PACKET((p)); \
+ } \
+ if ((p)->tcph != NULL) { \
+ CLEAR_TCP_PACKET((p)); \
+ } \
+ if ((p)->udph != NULL) { \
+ CLEAR_UDP_PACKET((p)); \
+ } \
+ if ((p)->sctph != NULL) { \
+ CLEAR_SCTP_PACKET((p)); \
+ } \
+ if ((p)->icmpv4h != NULL) { \
+ CLEAR_ICMPV4_PACKET((p)); \
+ } \
+ if ((p)->icmpv6h != NULL) { \
+ CLEAR_ICMPV6_PACKET((p)); \
+ } \
+ (p)->ppph = NULL; \
+ (p)->pppoesh = NULL; \
+ (p)->pppoedh = NULL; \
+ (p)->greh = NULL; \
+ (p)->vlanh[0] = NULL; \
+ (p)->vlanh[1] = NULL; \
+ (p)->payload = NULL; \
+ (p)->payload_len = 0; \
+ (p)->pktlen = 0; \
+ (p)->alerts.cnt = 0; \
+ (p)->alerts.drop.action = 0; \
+ (p)->pcap_cnt = 0; \
+ (p)->tunnel_rtv_cnt = 0; \
+ (p)->tunnel_tpr_cnt = 0; \
+ (p)->events.cnt = 0; \
+ AppLayerDecoderEventsResetEvents((p)->app_layer_events); \
+ (p)->next = NULL; \
+ (p)->prev = NULL; \
+ (p)->root = NULL; \
+ (p)->livedev = NULL; \
+ PACKET_RESET_CHECKSUMS((p)); \
+ PACKET_PROFILING_RESET((p)); \
+ p->tenant_id = 0; \
+ } while (0)
+
+#define PACKET_RECYCLE(p) do { \
+ PACKET_RELEASE_REFS((p)); \
+ PACKET_REINIT((p)); \
+ } while (0)
+
+/**
+ * \brief Cleanup a packet so that we can free it. No memset needed..
+ */
+#define PACKET_DESTRUCTOR(p) do { \
+ if ((p)->pktvar != NULL) { \
+ PktVarFree((p)->pktvar); \
+ } \
+ PACKET_FREE_EXTDATA((p)); \
+ SCMutexDestroy(&(p)->tunnel_mutex); \
+ AppLayerDecoderEventsFreeEvents(&(p)->app_layer_events); \
+ PACKET_PROFILING_RESET((p)); \
+ } while (0)
+
+
+/* macro's for setting the action
+ * handle the case of a root packet
+ * for tunnels */
+
+#define PACKET_SET_ACTION(p, a) do { \
+ ((p)->root ? \
+ ((p)->root->action = a) : \
+ ((p)->action = a)); \
+} while (0)
+
+#define PACKET_ALERT(p) PACKET_SET_ACTION(p, ACTION_ALERT)
+
+#define PACKET_ACCEPT(p) PACKET_SET_ACTION(p, ACTION_ACCEPT)
+
+#define PACKET_DROP(p) PACKET_SET_ACTION(p, ACTION_DROP)
+
+#define PACKET_REJECT(p) PACKET_SET_ACTION(p, (ACTION_REJECT|ACTION_DROP))
+
+#define PACKET_REJECT_DST(p) PACKET_SET_ACTION(p, (ACTION_REJECT_DST|ACTION_DROP))
+
+#define PACKET_REJECT_BOTH(p) PACKET_SET_ACTION(p, (ACTION_REJECT_BOTH|ACTION_DROP))
+
+#define PACKET_PASS(p) PACKET_SET_ACTION(p, ACTION_PASS)
+
+#define PACKET_TEST_ACTION(p, a) \
+ ((p)->root ? \
+ ((p)->root->action & a) : \
+ ((p)->action & a))
+
+#define PACKET_UPDATE_ACTION(p, a) do { \
+ ((p)->root ? \
+ ((p)->root->action |= a) : \
+ ((p)->action |= a)); \
+} while (0)
+
+#define TUNNEL_INCR_PKT_RTV(p) do { \
+ SCMutexLock((p)->root ? &(p)->root->tunnel_mutex : &(p)->tunnel_mutex); \
+ ((p)->root ? (p)->root->tunnel_rtv_cnt++ : (p)->tunnel_rtv_cnt++); \
+ SCMutexUnlock((p)->root ? &(p)->root->tunnel_mutex : &(p)->tunnel_mutex); \
+ } while (0)
+
+#define TUNNEL_INCR_PKT_TPR(p) do { \
+ SCMutexLock((p)->root ? &(p)->root->tunnel_mutex : &(p)->tunnel_mutex); \
+ ((p)->root ? (p)->root->tunnel_tpr_cnt++ : (p)->tunnel_tpr_cnt++); \
+ SCMutexUnlock((p)->root ? &(p)->root->tunnel_mutex : &(p)->tunnel_mutex); \
+ } while (0)
+
+#define TUNNEL_DECR_PKT_TPR(p) do { \
+ SCMutexLock((p)->root ? &(p)->root->tunnel_mutex : &(p)->tunnel_mutex); \
+ ((p)->root ? (p)->root->tunnel_tpr_cnt-- : (p)->tunnel_tpr_cnt--); \
+ SCMutexUnlock((p)->root ? &(p)->root->tunnel_mutex : &(p)->tunnel_mutex); \
+ } while (0)
+
+#define TUNNEL_DECR_PKT_TPR_NOLOCK(p) do { \
+ ((p)->root ? (p)->root->tunnel_tpr_cnt-- : (p)->tunnel_tpr_cnt--); \
+ } while (0)
+
+#define TUNNEL_PKT_RTV(p) ((p)->root ? (p)->root->tunnel_rtv_cnt : (p)->tunnel_rtv_cnt)
+#define TUNNEL_PKT_TPR(p) ((p)->root ? (p)->root->tunnel_tpr_cnt : (p)->tunnel_tpr_cnt)
+
+#define IS_TUNNEL_PKT(p) (((p)->flags & PKT_TUNNEL))
+#define SET_TUNNEL_PKT(p) ((p)->flags |= PKT_TUNNEL)
+#define UNSET_TUNNEL_PKT(p) ((p)->flags &= ~PKT_TUNNEL)
+#define IS_TUNNEL_ROOT_PKT(p) (IS_TUNNEL_PKT(p) && (p)->root == NULL)
+
+#define IS_TUNNEL_PKT_VERDICTED(p) (((p)->flags & PKT_TUNNEL_VERDICTED))
+#define SET_TUNNEL_PKT_VERDICTED(p) ((p)->flags |= PKT_TUNNEL_VERDICTED)
+
+enum DecodeTunnelProto {
+ DECODE_TUNNEL_ETHERNET,
+ DECODE_TUNNEL_ERSPAN,
+ DECODE_TUNNEL_VLAN,
+ DECODE_TUNNEL_IPV4,
+ DECODE_TUNNEL_IPV6,
+ DECODE_TUNNEL_PPP,
+};
+
+Packet *PacketTunnelPktSetup(ThreadVars *tv, DecodeThreadVars *dtv, Packet *parent,
+ uint8_t *pkt, uint16_t len, enum DecodeTunnelProto proto, PacketQueue *pq);
+Packet *PacketDefragPktSetup(Packet *parent, uint8_t *pkt, uint16_t len, uint8_t proto);
+void PacketDefragPktSetupParent(Packet *parent);
+void DecodeRegisterPerfCounters(DecodeThreadVars *, ThreadVars *);
+Packet *PacketGetFromQueueOrAlloc(void);
+Packet *PacketGetFromAlloc(void);
+void PacketDecodeFinalize(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p);
+void PacketFree(Packet *p);
+void PacketFreeOrRelease(Packet *p);
+int PacketCallocExtPkt(Packet *p, int datalen);
+int PacketCopyData(Packet *p, uint8_t *pktdata, int pktlen);
+int PacketSetData(Packet *p, uint8_t *pktdata, int pktlen);
+int PacketCopyDataOffset(Packet *p, int offset, uint8_t *data, int datalen);
+const char *PktSrcToString(enum PktSrcEnum pkt_src);
+
+DecodeThreadVars *DecodeThreadVarsAlloc(ThreadVars *);
+void DecodeThreadVarsFree(ThreadVars *, DecodeThreadVars *);
+void DecodeUpdatePacketCounters(ThreadVars *tv,
+ const DecodeThreadVars *dtv, const Packet *p);
+
+/* decoder functions */
+int DecodeEthernet(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *);
+int DecodeSll(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *);
+int DecodePPP(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *);
+int DecodePPPOESession(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *);
+int DecodePPPOEDiscovery(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *);
+int DecodeTunnel(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *, enum DecodeTunnelProto) __attribute__ ((warn_unused_result));
+int DecodeNull(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *);
+int DecodeRaw(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *);
+int DecodeIPV4(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *);
+int DecodeIPV6(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *);
+int DecodeICMPV4(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *);
+int DecodeICMPV6(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *);
+int DecodeTCP(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *);
+int DecodeUDP(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *);
+int DecodeSCTP(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *);
+int DecodeGRE(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *);
+int DecodeVLAN(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *);
+int DecodeMPLS(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *);
+int DecodeERSPAN(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *);
+
+void AddressDebugPrint(Address *);
+
+/** \brief Set the No payload inspection Flag for the packet.
+ *
+ * \param p Packet to set the flag in
+ */
+#define DecodeSetNoPayloadInspectionFlag(p) do { \
+ (p)->flags |= PKT_NOPAYLOAD_INSPECTION; \
+ } while (0)
+
+#define DecodeUnsetNoPayloadInspectionFlag(p) do { \
+ (p)->flags &= ~PKT_NOPAYLOAD_INSPECTION; \
+ } while (0)
+
+/** \brief Set the No packet inspection Flag for the packet.
+ *
+ * \param p Packet to set the flag in
+ */
+#define DecodeSetNoPacketInspectionFlag(p) do { \
+ (p)->flags |= PKT_NOPACKET_INSPECTION; \
+ } while (0)
+#define DecodeUnsetNoPacketInspectionFlag(p) do { \
+ (p)->flags &= ~PKT_NOPACKET_INSPECTION; \
+ } while (0)
+
+
+#define ENGINE_SET_EVENT(p, e) do { \
+ SCLogDebug("p %p event %d", (p), e); \
+ if ((p)->events.cnt < PACKET_ENGINE_EVENT_MAX) { \
+ (p)->events.events[(p)->events.cnt] = e; \
+ (p)->events.cnt++; \
+ } \
+} while(0)
+
+#define ENGINE_SET_INVALID_EVENT(p, e) do { \
+ p->flags |= PKT_IS_INVALID; \
+ ENGINE_SET_EVENT(p, e); \
+} while(0)
+
+
+
+#define ENGINE_ISSET_EVENT(p, e) ({ \
+ int r = 0; \
+ uint8_t u; \
+ for (u = 0; u < (p)->events.cnt; u++) { \
+ if ((p)->events.events[u] == (e)) { \
+ r = 1; \
+ break; \
+ } \
+ } \
+ r; \
+})
+
+/* older libcs don't contain a def for IPPROTO_DCCP
+ * inside of <netinet/in.h>
+ * if it isn't defined let's define it here.
+ */
+#ifndef IPPROTO_DCCP
+#define IPPROTO_DCCP 33
+#endif
+
+/* older libcs don't contain a def for IPPROTO_SCTP
+ * inside of <netinet/in.h>
+ * if it isn't defined let's define it here.
+ */
+#ifndef IPPROTO_SCTP
+#define IPPROTO_SCTP 132
+#endif
+
+#ifndef IPPROTO_MH
+#define IPPROTO_MH 135
+#endif
+
+/* Host Identity Protocol (rfc 5201) */
+#ifndef IPPROTO_HIP
+#define IPPROTO_HIP 139
+#endif
+
+#ifndef IPPROTO_SHIM6
+#define IPPROTO_SHIM6 140
+#endif
+
+/* pcap provides this, but we don't want to depend on libpcap */
+#ifndef DLT_EN10MB
+#define DLT_EN10MB 1
+#endif
+
+/* taken from pcap's bpf.h */
+#ifndef DLT_RAW
+#ifdef __OpenBSD__
+#define DLT_RAW 14 /* raw IP */
+#else
+#define DLT_RAW 12 /* raw IP */
+#endif
+#endif
+
+#ifndef DLT_NULL
+#define DLT_NULL 0
+#endif
+
+/** libpcap shows us the way to linktype codes
+ * \todo we need more & maybe put them in a separate file? */
+#define LINKTYPE_NULL DLT_NULL
+#define LINKTYPE_ETHERNET DLT_EN10MB
+#define LINKTYPE_LINUX_SLL 113
+#define LINKTYPE_PPP 9
+#define LINKTYPE_RAW DLT_RAW
+#define PPP_OVER_GRE 11
+#define VLAN_OVER_GRE 13
+
+/*Packet Flags*/
+#define PKT_NOPACKET_INSPECTION (1) /**< Flag to indicate that packet header or contents should not be inspected*/
+#define PKT_NOPAYLOAD_INSPECTION (1<<2) /**< Flag to indicate that packet contents should not be inspected*/
+#define PKT_ALLOC (1<<3) /**< Packet was alloc'd this run, needs to be freed */
+#define PKT_HAS_TAG (1<<4) /**< Packet has matched a tag */
+#define PKT_STREAM_ADD (1<<5) /**< Packet payload was added to reassembled stream */
+#define PKT_STREAM_EST (1<<6) /**< Packet is part of establised stream */
+#define PKT_STREAM_EOF (1<<7) /**< Stream is in eof state */
+#define PKT_HAS_FLOW (1<<8)
+#define PKT_PSEUDO_STREAM_END (1<<9) /**< Pseudo packet to end the stream */
+#define PKT_STREAM_MODIFIED (1<<10) /**< Packet is modified by the stream engine, we need to recalc the csum and reinject/replace */
+#define PKT_MARK_MODIFIED (1<<11) /**< Packet mark is modified */
+#define PKT_STREAM_NOPCAPLOG (1<<12) /**< Exclude packet from pcap logging as it's part of a stream that has reassembly depth reached. */
+
+#define PKT_TUNNEL (1<<13)
+#define PKT_TUNNEL_VERDICTED (1<<14)
+
+#define PKT_IGNORE_CHECKSUM (1<<15) /**< Packet checksum is not computed (TX packet for example) */
+#define PKT_ZERO_COPY (1<<16) /**< Packet comes from zero copy (ext_pkt must not be freed) */
+
+#define PKT_HOST_SRC_LOOKED_UP (1<<17)
+#define PKT_HOST_DST_LOOKED_UP (1<<18)
+
+#define PKT_IS_FRAGMENT (1<<19) /**< Packet is a fragment */
+#define PKT_IS_INVALID (1<<20)
+#define PKT_PROFILE (1<<21)
+
+/** \brief return 1 if the packet is a pseudo packet */
+#define PKT_IS_PSEUDOPKT(p) ((p)->flags & PKT_PSEUDO_STREAM_END)
+
+#define PKT_SET_SRC(p, src_val) ((p)->pkt_src = src_val)
+
+#endif /* __DECODE_H__ */
+