|
|
|
|
/* Copyright (C) 2007-2022 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
|
|
|
|
|
|
Add per packet profiling.
Per packet profiling uses tick based accounting. It has 2 outputs, a summary
and a csv file that contains per packet stats.
Stats per packet include:
1) total ticks spent
2) ticks spent per individual thread module
3) "threading overhead" which is simply calculated by subtracting (2) of (1).
A number of changes were made to integrate the new code in a clean way:
a number of generic enums are now placed in tm-threads-common.h so we can
include them from any part of the engine.
Code depends on --enable-profiling just like the rule profiling code.
New yaml parameters:
profiling:
# packet profiling
packets:
# Profiling can be disabled here, but it will still have a
# performance impact if compiled in.
enabled: yes
filename: packet_stats.log
append: yes
# per packet csv output
csv:
# Output can be disabled here, but it will still have a
# performance impact if compiled in.
enabled: no
filename: packet_stats.csv
Example output of summary stats:
IP ver Proto cnt min max avg
------ ----- ------ ------ ---------- -------
IPv4 6 19436 11448 5404365 32993
IPv4 256 4 11511 49968 30575
Per Thread module stats:
Thread Module IP ver Proto cnt min max avg
------------------------ ------ ----- ------ ------ ---------- -------
TMM_DECODEPCAPFILE IPv4 6 19434 1242 47889 1770
TMM_DETECT IPv4 6 19436 1107 137241 1504
TMM_ALERTFASTLOG IPv4 6 19436 90 1323 155
TMM_ALERTUNIFIED2ALERT IPv4 6 19436 108 1359 138
TMM_ALERTDEBUGLOG IPv4 6 19436 90 1134 154
TMM_LOGHTTPLOG IPv4 6 19436 414 5392089 7944
TMM_STREAMTCP IPv4 6 19434 828 1299159 19438
The proto 256 is a counter for handling of pseudo/tunnel packets.
Example output of csv:
pcap_cnt,ipver,ipproto,total,TMM_DECODENFQ,TMM_VERDICTNFQ,TMM_RECEIVENFQ,TMM_RECEIVEPCAP,TMM_RECEIVEPCAPFILE,TMM_DECODEPCAP,TMM_DECODEPCAPFILE,TMM_RECEIVEPFRING,TMM_DECODEPFRING,TMM_DETECT,TMM_ALERTFASTLOG,TMM_ALERTFASTLOG4,TMM_ALERTFASTLOG6,TMM_ALERTUNIFIEDLOG,TMM_ALERTUNIFIEDALERT,TMM_ALERTUNIFIED2ALERT,TMM_ALERTPRELUDE,TMM_ALERTDEBUGLOG,TMM_ALERTSYSLOG,TMM_LOGDROPLOG,TMM_ALERTSYSLOG4,TMM_ALERTSYSLOG6,TMM_RESPONDREJECT,TMM_LOGHTTPLOG,TMM_LOGHTTPLOG4,TMM_LOGHTTPLOG6,TMM_PCAPLOG,TMM_STREAMTCP,TMM_DECODEIPFW,TMM_VERDICTIPFW,TMM_RECEIVEIPFW,TMM_RECEIVEERFFILE,TMM_DECODEERFFILE,TMM_RECEIVEERFDAG,TMM_DECODEERFDAG,threading
1,4,6,172008,0,0,0,0,0,0,47889,0,0,48582,1323,0,0,0,0,1359,0,1134,0,0,0,0,0,8028,0,0,0,49356,0,0,0,0,0,0,0,14337
First line of the file contains labels.
2 example gnuplot scripts added to plot the data.
15 years ago
|
|
|
#include "suricata-common.h"
|
|
|
|
|
#include "suricata-plugin.h"
|
|
|
|
|
#include "threadvars.h"
|
|
|
|
|
#include "util-debug.h"
|
|
|
|
|
#include "decode-events.h"
|
|
|
|
|
#include "flow-worker.h"
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_NAPATECH
|
|
|
|
|
#include "util-napatech.h"
|
|
|
|
|
#endif /* HAVE_NAPATECH */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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_FFR,
|
|
|
|
|
PKT_SRC_STREAM_TCP_DETECTLOG_FLUSH,
|
|
|
|
|
PKT_SRC_DECODER_VXLAN,
|
|
|
|
|
PKT_SRC_DETECT_RELOAD_FLUSH,
|
|
|
|
|
PKT_SRC_CAPTURE_TIMEOUT,
|
|
|
|
|
PKT_SRC_DECODER_GENEVE,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#include "source-nflog.h"
|
|
|
|
|
#include "source-nfq.h"
|
|
|
|
|
#include "source-ipfw.h"
|
|
|
|
|
#include "source-pcap.h"
|
|
|
|
|
#include "source-af-packet.h"
|
|
|
|
|
#include "source-netmap.h"
|
Adds WinDivert support to Windows builds
Enables IPS functionality on Windows using the open-source
(LGPLv3/GPLv2) WinDivert driver and API.
From https://www.reqrypt.org/windivert-doc.html : "WinDivert is a
user-mode capture/sniffing/modification/blocking/re-injection package
for Windows Vista, Windows Server 2008, Windows 7, and Windows 8.
WinDivert can be used to implement user-mode packet filters, packet
sniffers, firewalls, NAT, VPNs, tunneling applications, etc., without
the need to write kernel-mode code."
- adds `--windivert [filter string]` and `--windivert-forward [filter
string]` command-line options to enable WinDivert IPS mode.
`--windivert[-forward] true` will open a filter for all traffic. See
https://www.reqrypt.org/windivert-doc.html#filter_language for more
information.
Limitation: currently limited to `autofp` runmode.
Additionally:
- `tmm_modules` now zeroed during `RegisterAllModules`
- fixed Windows Vista+ `inet_ntop` call in `PrintInet`
- fixed `GetRandom` bug (nonexistent keys) on fresh Windows installs
- fixed `RandomGetClock` building on Windows builds
- Added WMI queries for MTU
8 years ago
|
|
|
#include "source-windivert.h"
|
|
|
|
|
#ifdef HAVE_DPDK
|
|
|
|
|
#include "source-dpdk.h"
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef HAVE_PF_RING_FLOW_OFFLOAD
|
|
|
|
|
#include "source-pfring.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include "action-globals.h"
|
|
|
|
|
|
|
|
|
|
#include "decode-erspan.h"
|
|
|
|
|
#include "decode-ethernet.h"
|
|
|
|
|
#include "decode-chdlc.h"
|
|
|
|
|
#include "decode-gre.h"
|
|
|
|
|
#include "decode-geneve.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-esp.h"
|
|
|
|
|
#include "decode-raw.h"
|
|
|
|
|
#include "decode-null.h"
|
|
|
|
|
#include "decode-vlan.h"
|
|
|
|
|
#include "decode-vntag.h"
|
|
|
|
|
#include "decode-vxlan.h"
|
|
|
|
|
#include "decode-mpls.h"
|
|
|
|
|
#include "decode-nsh.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 */
|
|
|
|
|
struct in6_addr address_un_in6;
|
|
|
|
|
} address;
|
|
|
|
|
} Address;
|
|
|
|
|
|
|
|
|
|
#define addr_data32 address.address_un_data32
|
|
|
|
|
#define addr_data16 address.address_un_data16
|
|
|
|
|
#define addr_data8 address.address_un_data8
|
|
|
|
|
#define addr_in6addr address.address_un_in6
|
|
|
|
|
|
|
|
|
|
#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 addresses into 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_IN6ADDR(p) ((p)->src.addr_in6addr)
|
|
|
|
|
#define GET_IPV6_DST_IN6ADDR(p) ((p)->dst.addr_in6addr)
|
|
|
|
|
#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 thresholding */
|
|
|
|
|
uint8_t flags;
|
|
|
|
|
const struct Signature_ *s;
|
|
|
|
|
uint64_t tx_id; /* Used for sorting */
|
|
|
|
|
int64_t frame_id;
|
|
|
|
|
} PacketAlert;
|
|
|
|
|
|
|
|
|
|
/* flag to indicate the rule action (drop/pass) needs to be applied to the flow */
|
|
|
|
|
#define PACKET_ALERT_FLAG_APPLY_ACTION_TO_FLOW 0x1
|
|
|
|
|
/** 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
|
|
|
|
|
/** action was changed by rate_filter */
|
|
|
|
|
#define PACKET_ALERT_RATE_FILTER_MODIFIED 0x10
|
|
|
|
|
/** alert is in a frame, frame_id set */
|
|
|
|
|
#define PACKET_ALERT_FLAG_FRAME 0x20
|
|
|
|
|
|
|
|
|
|
extern uint16_t packet_alert_max;
|
|
|
|
|
#define PACKET_ALERT_MAX 15
|
|
|
|
|
|
|
|
|
|
typedef struct PacketAlerts_ {
|
|
|
|
|
uint16_t cnt;
|
|
|
|
|
uint16_t discarded;
|
|
|
|
|
PacketAlert *alerts;
|
|
|
|
|
/* single pa used when we're dropping,
|
|
|
|
|
* so we can log it out in the drop log. */
|
|
|
|
|
PacketAlert drop;
|
|
|
|
|
} PacketAlerts;
|
|
|
|
|
|
|
|
|
|
PacketAlert *PacketAlertCreate(void);
|
|
|
|
|
|
|
|
|
|
void PacketAlertFree(PacketAlert *pa);
|
|
|
|
|
|
|
|
|
|
/** 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_ {
|
|
|
|
|
uint32_t id;
|
|
|
|
|
struct PktVar_ *next; /* right now just implement this as a list,
|
|
|
|
|
* in the long run we have thing of something
|
|
|
|
|
* faster. */
|
|
|
|
|
uint16_t key_len;
|
|
|
|
|
uint16_t value_len;
|
|
|
|
|
uint8_t *key;
|
|
|
|
|
uint8_t *value;
|
|
|
|
|
} PktVar;
|
|
|
|
|
|
Add per packet profiling.
Per packet profiling uses tick based accounting. It has 2 outputs, a summary
and a csv file that contains per packet stats.
Stats per packet include:
1) total ticks spent
2) ticks spent per individual thread module
3) "threading overhead" which is simply calculated by subtracting (2) of (1).
A number of changes were made to integrate the new code in a clean way:
a number of generic enums are now placed in tm-threads-common.h so we can
include them from any part of the engine.
Code depends on --enable-profiling just like the rule profiling code.
New yaml parameters:
profiling:
# packet profiling
packets:
# Profiling can be disabled here, but it will still have a
# performance impact if compiled in.
enabled: yes
filename: packet_stats.log
append: yes
# per packet csv output
csv:
# Output can be disabled here, but it will still have a
# performance impact if compiled in.
enabled: no
filename: packet_stats.csv
Example output of summary stats:
IP ver Proto cnt min max avg
------ ----- ------ ------ ---------- -------
IPv4 6 19436 11448 5404365 32993
IPv4 256 4 11511 49968 30575
Per Thread module stats:
Thread Module IP ver Proto cnt min max avg
------------------------ ------ ----- ------ ------ ---------- -------
TMM_DECODEPCAPFILE IPv4 6 19434 1242 47889 1770
TMM_DETECT IPv4 6 19436 1107 137241 1504
TMM_ALERTFASTLOG IPv4 6 19436 90 1323 155
TMM_ALERTUNIFIED2ALERT IPv4 6 19436 108 1359 138
TMM_ALERTDEBUGLOG IPv4 6 19436 90 1134 154
TMM_LOGHTTPLOG IPv4 6 19436 414 5392089 7944
TMM_STREAMTCP IPv4 6 19434 828 1299159 19438
The proto 256 is a counter for handling of pseudo/tunnel packets.
Example output of csv:
pcap_cnt,ipver,ipproto,total,TMM_DECODENFQ,TMM_VERDICTNFQ,TMM_RECEIVENFQ,TMM_RECEIVEPCAP,TMM_RECEIVEPCAPFILE,TMM_DECODEPCAP,TMM_DECODEPCAPFILE,TMM_RECEIVEPFRING,TMM_DECODEPFRING,TMM_DETECT,TMM_ALERTFASTLOG,TMM_ALERTFASTLOG4,TMM_ALERTFASTLOG6,TMM_ALERTUNIFIEDLOG,TMM_ALERTUNIFIEDALERT,TMM_ALERTUNIFIED2ALERT,TMM_ALERTPRELUDE,TMM_ALERTDEBUGLOG,TMM_ALERTSYSLOG,TMM_LOGDROPLOG,TMM_ALERTSYSLOG4,TMM_ALERTSYSLOG6,TMM_RESPONDREJECT,TMM_LOGHTTPLOG,TMM_LOGHTTPLOG4,TMM_LOGHTTPLOG6,TMM_PCAPLOG,TMM_STREAMTCP,TMM_DECODEIPFW,TMM_VERDICTIPFW,TMM_RECEIVEIPFW,TMM_RECEIVEERFFILE,TMM_DECODEERFFILE,TMM_RECEIVEERFDAG,TMM_DECODEERFDAG,threading
1,4,6,172008,0,0,0,0,0,0,47889,0,0,48582,1323,0,0,0,0,1359,0,1134,0,0,0,0,0,8028,0,0,0,49356,0,0,0,0,0,0,0,14337
First line of the file contains labels.
2 example gnuplot scripts added to plot the data.
15 years ago
|
|
|
#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
|
Add per packet profiling.
Per packet profiling uses tick based accounting. It has 2 outputs, a summary
and a csv file that contains per packet stats.
Stats per packet include:
1) total ticks spent
2) ticks spent per individual thread module
3) "threading overhead" which is simply calculated by subtracting (2) of (1).
A number of changes were made to integrate the new code in a clean way:
a number of generic enums are now placed in tm-threads-common.h so we can
include them from any part of the engine.
Code depends on --enable-profiling just like the rule profiling code.
New yaml parameters:
profiling:
# packet profiling
packets:
# Profiling can be disabled here, but it will still have a
# performance impact if compiled in.
enabled: yes
filename: packet_stats.log
append: yes
# per packet csv output
csv:
# Output can be disabled here, but it will still have a
# performance impact if compiled in.
enabled: no
filename: packet_stats.csv
Example output of summary stats:
IP ver Proto cnt min max avg
------ ----- ------ ------ ---------- -------
IPv4 6 19436 11448 5404365 32993
IPv4 256 4 11511 49968 30575
Per Thread module stats:
Thread Module IP ver Proto cnt min max avg
------------------------ ------ ----- ------ ------ ---------- -------
TMM_DECODEPCAPFILE IPv4 6 19434 1242 47889 1770
TMM_DETECT IPv4 6 19436 1107 137241 1504
TMM_ALERTFASTLOG IPv4 6 19436 90 1323 155
TMM_ALERTUNIFIED2ALERT IPv4 6 19436 108 1359 138
TMM_ALERTDEBUGLOG IPv4 6 19436 90 1134 154
TMM_LOGHTTPLOG IPv4 6 19436 414 5392089 7944
TMM_STREAMTCP IPv4 6 19434 828 1299159 19438
The proto 256 is a counter for handling of pseudo/tunnel packets.
Example output of csv:
pcap_cnt,ipver,ipproto,total,TMM_DECODENFQ,TMM_VERDICTNFQ,TMM_RECEIVENFQ,TMM_RECEIVEPCAP,TMM_RECEIVEPCAPFILE,TMM_DECODEPCAP,TMM_DECODEPCAPFILE,TMM_RECEIVEPFRING,TMM_DECODEPFRING,TMM_DETECT,TMM_ALERTFASTLOG,TMM_ALERTFASTLOG4,TMM_ALERTFASTLOG6,TMM_ALERTUNIFIEDLOG,TMM_ALERTUNIFIEDALERT,TMM_ALERTUNIFIED2ALERT,TMM_ALERTPRELUDE,TMM_ALERTDEBUGLOG,TMM_ALERTSYSLOG,TMM_LOGDROPLOG,TMM_ALERTSYSLOG4,TMM_ALERTSYSLOG6,TMM_RESPONDREJECT,TMM_LOGHTTPLOG,TMM_LOGHTTPLOG4,TMM_LOGHTTPLOG6,TMM_PCAPLOG,TMM_STREAMTCP,TMM_DECODEIPFW,TMM_VERDICTIPFW,TMM_RECEIVEIPFW,TMM_RECEIVEERFFILE,TMM_DECODEERFFILE,TMM_RECEIVEERFDAG,TMM_DECODEERFDAG,threading
1,4,6,172008,0,0,0,0,0,0,47889,0,0,48582,1323,0,0,0,0,1359,0,1134,0,0,0,0,0,8028,0,0,0,49356,0,0,0,0,0,0,0,14337
First line of the file contains labels.
2 example gnuplot scripts added to plot the data.
15 years ago
|
|
|
} PktProfilingTmmData;
|
|
|
|
|
|
|
|
|
|
typedef struct PktProfilingData_ {
|
|
|
|
|
uint64_t ticks_start;
|
|
|
|
|
uint64_t ticks_end;
|
|
|
|
|
} PktProfilingData;
|
|
|
|
|
|
|
|
|
|
typedef struct PktProfilingDetectData_ {
|
|
|
|
|
uint64_t ticks_start;
|
|
|
|
|
uint64_t ticks_end;
|
|
|
|
|
uint64_t ticks_spent;
|
|
|
|
|
} PktProfilingDetectData;
|
|
|
|
|
|
|
|
|
|
typedef struct PktProfilingAppData_ {
|
|
|
|
|
uint64_t ticks_spent;
|
|
|
|
|
} PktProfilingAppData;
|
|
|
|
|
|
|
|
|
|
typedef struct PktProfilingLoggerData_ {
|
|
|
|
|
uint64_t ticks_start;
|
|
|
|
|
uint64_t ticks_end;
|
|
|
|
|
uint64_t ticks_spent;
|
|
|
|
|
} PktProfilingLoggerData;
|
|
|
|
|
|
|
|
|
|
typedef struct PktProfilingPrefilterEngine_ {
|
|
|
|
|
uint64_t ticks_spent;
|
|
|
|
|
} PktProfilingPrefilterEngine;
|
|
|
|
|
|
|
|
|
|
typedef struct PktProfilingPrefilterData_ {
|
|
|
|
|
PktProfilingPrefilterEngine *engines;
|
|
|
|
|
uint32_t size; /**< array size */
|
|
|
|
|
} PktProfilingPrefilterData;
|
|
|
|
|
|
Add per packet profiling.
Per packet profiling uses tick based accounting. It has 2 outputs, a summary
and a csv file that contains per packet stats.
Stats per packet include:
1) total ticks spent
2) ticks spent per individual thread module
3) "threading overhead" which is simply calculated by subtracting (2) of (1).
A number of changes were made to integrate the new code in a clean way:
a number of generic enums are now placed in tm-threads-common.h so we can
include them from any part of the engine.
Code depends on --enable-profiling just like the rule profiling code.
New yaml parameters:
profiling:
# packet profiling
packets:
# Profiling can be disabled here, but it will still have a
# performance impact if compiled in.
enabled: yes
filename: packet_stats.log
append: yes
# per packet csv output
csv:
# Output can be disabled here, but it will still have a
# performance impact if compiled in.
enabled: no
filename: packet_stats.csv
Example output of summary stats:
IP ver Proto cnt min max avg
------ ----- ------ ------ ---------- -------
IPv4 6 19436 11448 5404365 32993
IPv4 256 4 11511 49968 30575
Per Thread module stats:
Thread Module IP ver Proto cnt min max avg
------------------------ ------ ----- ------ ------ ---------- -------
TMM_DECODEPCAPFILE IPv4 6 19434 1242 47889 1770
TMM_DETECT IPv4 6 19436 1107 137241 1504
TMM_ALERTFASTLOG IPv4 6 19436 90 1323 155
TMM_ALERTUNIFIED2ALERT IPv4 6 19436 108 1359 138
TMM_ALERTDEBUGLOG IPv4 6 19436 90 1134 154
TMM_LOGHTTPLOG IPv4 6 19436 414 5392089 7944
TMM_STREAMTCP IPv4 6 19434 828 1299159 19438
The proto 256 is a counter for handling of pseudo/tunnel packets.
Example output of csv:
pcap_cnt,ipver,ipproto,total,TMM_DECODENFQ,TMM_VERDICTNFQ,TMM_RECEIVENFQ,TMM_RECEIVEPCAP,TMM_RECEIVEPCAPFILE,TMM_DECODEPCAP,TMM_DECODEPCAPFILE,TMM_RECEIVEPFRING,TMM_DECODEPFRING,TMM_DETECT,TMM_ALERTFASTLOG,TMM_ALERTFASTLOG4,TMM_ALERTFASTLOG6,TMM_ALERTUNIFIEDLOG,TMM_ALERTUNIFIEDALERT,TMM_ALERTUNIFIED2ALERT,TMM_ALERTPRELUDE,TMM_ALERTDEBUGLOG,TMM_ALERTSYSLOG,TMM_LOGDROPLOG,TMM_ALERTSYSLOG4,TMM_ALERTSYSLOG6,TMM_RESPONDREJECT,TMM_LOGHTTPLOG,TMM_LOGHTTPLOG4,TMM_LOGHTTPLOG6,TMM_PCAPLOG,TMM_STREAMTCP,TMM_DECODEIPFW,TMM_VERDICTIPFW,TMM_RECEIVEIPFW,TMM_RECEIVEERFFILE,TMM_DECODEERFFILE,TMM_RECEIVEERFDAG,TMM_DECODEERFDAG,threading
1,4,6,172008,0,0,0,0,0,0,47889,0,0,48582,1323,0,0,0,0,1359,0,1134,0,0,0,0,0,8028,0,0,0,49356,0,0,0,0,0,0,0,14337
First line of the file contains labels.
2 example gnuplot scripts added to plot the data.
15 years ago
|
|
|
/** \brief Per pkt stats storage */
|
|
|
|
|
typedef struct PktProfiling_ {
|
|
|
|
|
uint64_t ticks_start;
|
|
|
|
|
uint64_t ticks_end;
|
|
|
|
|
|
|
|
|
|
PktProfilingTmmData tmm[TMM_SIZE];
|
|
|
|
|
PktProfilingData flowworker[PROFILE_FLOWWORKER_SIZE];
|
|
|
|
|
PktProfilingAppData app[ALPROTO_MAX];
|
|
|
|
|
PktProfilingDetectData detect[PROF_DETECT_SIZE];
|
|
|
|
|
PktProfilingLoggerData logger[LOGGER_SIZE];
|
|
|
|
|
uint64_t proto_detect;
|
Add per packet profiling.
Per packet profiling uses tick based accounting. It has 2 outputs, a summary
and a csv file that contains per packet stats.
Stats per packet include:
1) total ticks spent
2) ticks spent per individual thread module
3) "threading overhead" which is simply calculated by subtracting (2) of (1).
A number of changes were made to integrate the new code in a clean way:
a number of generic enums are now placed in tm-threads-common.h so we can
include them from any part of the engine.
Code depends on --enable-profiling just like the rule profiling code.
New yaml parameters:
profiling:
# packet profiling
packets:
# Profiling can be disabled here, but it will still have a
# performance impact if compiled in.
enabled: yes
filename: packet_stats.log
append: yes
# per packet csv output
csv:
# Output can be disabled here, but it will still have a
# performance impact if compiled in.
enabled: no
filename: packet_stats.csv
Example output of summary stats:
IP ver Proto cnt min max avg
------ ----- ------ ------ ---------- -------
IPv4 6 19436 11448 5404365 32993
IPv4 256 4 11511 49968 30575
Per Thread module stats:
Thread Module IP ver Proto cnt min max avg
------------------------ ------ ----- ------ ------ ---------- -------
TMM_DECODEPCAPFILE IPv4 6 19434 1242 47889 1770
TMM_DETECT IPv4 6 19436 1107 137241 1504
TMM_ALERTFASTLOG IPv4 6 19436 90 1323 155
TMM_ALERTUNIFIED2ALERT IPv4 6 19436 108 1359 138
TMM_ALERTDEBUGLOG IPv4 6 19436 90 1134 154
TMM_LOGHTTPLOG IPv4 6 19436 414 5392089 7944
TMM_STREAMTCP IPv4 6 19434 828 1299159 19438
The proto 256 is a counter for handling of pseudo/tunnel packets.
Example output of csv:
pcap_cnt,ipver,ipproto,total,TMM_DECODENFQ,TMM_VERDICTNFQ,TMM_RECEIVENFQ,TMM_RECEIVEPCAP,TMM_RECEIVEPCAPFILE,TMM_DECODEPCAP,TMM_DECODEPCAPFILE,TMM_RECEIVEPFRING,TMM_DECODEPFRING,TMM_DETECT,TMM_ALERTFASTLOG,TMM_ALERTFASTLOG4,TMM_ALERTFASTLOG6,TMM_ALERTUNIFIEDLOG,TMM_ALERTUNIFIEDALERT,TMM_ALERTUNIFIED2ALERT,TMM_ALERTPRELUDE,TMM_ALERTDEBUGLOG,TMM_ALERTSYSLOG,TMM_LOGDROPLOG,TMM_ALERTSYSLOG4,TMM_ALERTSYSLOG6,TMM_RESPONDREJECT,TMM_LOGHTTPLOG,TMM_LOGHTTPLOG4,TMM_LOGHTTPLOG6,TMM_PCAPLOG,TMM_STREAMTCP,TMM_DECODEIPFW,TMM_VERDICTIPFW,TMM_RECEIVEIPFW,TMM_RECEIVEERFFILE,TMM_DECODEERFFILE,TMM_RECEIVEERFDAG,TMM_DECODEERFDAG,threading
1,4,6,172008,0,0,0,0,0,0,47889,0,0,48582,1323,0,0,0,0,1359,0,1134,0,0,0,0,0,8028,0,0,0,49356,0,0,0,0,0,0,0,14337
First line of the file contains labels.
2 example gnuplot scripts added to plot the data.
15 years ago
|
|
|
} PktProfiling;
|
|
|
|
|
|
|
|
|
|
#endif /* PROFILING */
|
|
|
|
|
|
|
|
|
|
/* forward declaration 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;
|
|
|
|
|
// icmp type and code of this packet
|
|
|
|
|
struct {
|
|
|
|
|
uint8_t type;
|
|
|
|
|
uint8_t code;
|
|
|
|
|
} icmp_s;
|
|
|
|
|
};
|
|
|
|
|
union {
|
|
|
|
|
Port dp;
|
|
|
|
|
// icmp type and code of the expected counterpart (for flows)
|
|
|
|
|
struct {
|
|
|
|
|
uint8_t type;
|
|
|
|
|
uint8_t code;
|
|
|
|
|
} icmp_d;
|
|
|
|
|
};
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
/* raw hash value for looking up the flow, will need to modulated to the
|
|
|
|
|
* hash size still */
|
|
|
|
|
uint32_t flow_hash;
|
|
|
|
|
|
|
|
|
|
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_NETMAP
|
|
|
|
|
NetmapPacketVars netmap_v;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef HAVE_PFRING
|
|
|
|
|
#ifdef HAVE_PF_RING_FLOW_OFFLOAD
|
|
|
|
|
PfringPacketVars pfring_v;
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
Adds WinDivert support to Windows builds
Enables IPS functionality on Windows using the open-source
(LGPLv3/GPLv2) WinDivert driver and API.
From https://www.reqrypt.org/windivert-doc.html : "WinDivert is a
user-mode capture/sniffing/modification/blocking/re-injection package
for Windows Vista, Windows Server 2008, Windows 7, and Windows 8.
WinDivert can be used to implement user-mode packet filters, packet
sniffers, firewalls, NAT, VPNs, tunneling applications, etc., without
the need to write kernel-mode code."
- adds `--windivert [filter string]` and `--windivert-forward [filter
string]` command-line options to enable WinDivert IPS mode.
`--windivert[-forward] true` will open a filter for all traffic. See
https://www.reqrypt.org/windivert-doc.html#filter_language for more
information.
Limitation: currently limited to `autofp` runmode.
Additionally:
- `tmm_modules` now zeroed during `RegisterAllModules`
- fixed Windows Vista+ `inet_ntop` call in `PrintInet`
- fixed `GetRandom` bug (nonexistent keys) on fresh Windows installs
- fixed `RandomGetClock` building on Windows builds
- Added WMI queries for MTU
8 years ago
|
|
|
#ifdef WINDIVERT
|
|
|
|
|
WinDivertPacketVars windivert_v;
|
|
|
|
|
#endif /* WINDIVERT */
|
|
|
|
|
#ifdef HAVE_DPDK
|
|
|
|
|
DPDKPacketVars dpdk_v;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* A chunk of memory that a plugin can use for its packet vars. */
|
|
|
|
|
uint8_t plugin_v[PLUGIN_VAR_SIZE];
|
|
|
|
|
|
|
|
|
|
/** 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_ *);
|
|
|
|
|
/** The function triggering bypass the flow in the capture method.
|
|
|
|
|
* Return 1 for success and 0 on error */
|
|
|
|
|
int (*BypassPacketsFlow)(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;
|
|
|
|
|
ICMPV4Vars icmpv4vars;
|
|
|
|
|
ICMPV6Vars icmpv6vars;
|
|
|
|
|
} l4vars;
|
|
|
|
|
#define tcpvars l4vars.tcpvars
|
|
|
|
|
#define icmpv4vars l4vars.icmpv4vars
|
|
|
|
|
#define icmpv6vars l4vars.icmpv6vars
|
|
|
|
|
|
|
|
|
|
TCPHdr *tcph;
|
|
|
|
|
|
|
|
|
|
UDPHdr *udph;
|
|
|
|
|
|
|
|
|
|
SCTPHdr *sctph;
|
|
|
|
|
|
|
|
|
|
ESPHdr *esph;
|
|
|
|
|
|
|
|
|
|
ICMPV4Hdr *icmpv4h;
|
|
|
|
|
|
|
|
|
|
ICMPV6Hdr *icmpv6h;
|
|
|
|
|
|
|
|
|
|
PPPHdr *ppph;
|
|
|
|
|
PPPOESessionHdr *pppoesh;
|
|
|
|
|
PPPOEDiscoveryHdr *pppoedh;
|
|
|
|
|
|
|
|
|
|
GREHdr *greh;
|
|
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
|
|
|
|
|
/* count decoded layers of packet : too many layers
|
|
|
|
|
* cause issues with performance and stability (stack exhaustion)
|
|
|
|
|
*/
|
|
|
|
|
uint8_t nb_decoded_layers;
|
|
|
|
|
|
Add per packet profiling.
Per packet profiling uses tick based accounting. It has 2 outputs, a summary
and a csv file that contains per packet stats.
Stats per packet include:
1) total ticks spent
2) ticks spent per individual thread module
3) "threading overhead" which is simply calculated by subtracting (2) of (1).
A number of changes were made to integrate the new code in a clean way:
a number of generic enums are now placed in tm-threads-common.h so we can
include them from any part of the engine.
Code depends on --enable-profiling just like the rule profiling code.
New yaml parameters:
profiling:
# packet profiling
packets:
# Profiling can be disabled here, but it will still have a
# performance impact if compiled in.
enabled: yes
filename: packet_stats.log
append: yes
# per packet csv output
csv:
# Output can be disabled here, but it will still have a
# performance impact if compiled in.
enabled: no
filename: packet_stats.csv
Example output of summary stats:
IP ver Proto cnt min max avg
------ ----- ------ ------ ---------- -------
IPv4 6 19436 11448 5404365 32993
IPv4 256 4 11511 49968 30575
Per Thread module stats:
Thread Module IP ver Proto cnt min max avg
------------------------ ------ ----- ------ ------ ---------- -------
TMM_DECODEPCAPFILE IPv4 6 19434 1242 47889 1770
TMM_DETECT IPv4 6 19436 1107 137241 1504
TMM_ALERTFASTLOG IPv4 6 19436 90 1323 155
TMM_ALERTUNIFIED2ALERT IPv4 6 19436 108 1359 138
TMM_ALERTDEBUGLOG IPv4 6 19436 90 1134 154
TMM_LOGHTTPLOG IPv4 6 19436 414 5392089 7944
TMM_STREAMTCP IPv4 6 19434 828 1299159 19438
The proto 256 is a counter for handling of pseudo/tunnel packets.
Example output of csv:
pcap_cnt,ipver,ipproto,total,TMM_DECODENFQ,TMM_VERDICTNFQ,TMM_RECEIVENFQ,TMM_RECEIVEPCAP,TMM_RECEIVEPCAPFILE,TMM_DECODEPCAP,TMM_DECODEPCAPFILE,TMM_RECEIVEPFRING,TMM_DECODEPFRING,TMM_DETECT,TMM_ALERTFASTLOG,TMM_ALERTFASTLOG4,TMM_ALERTFASTLOG6,TMM_ALERTUNIFIEDLOG,TMM_ALERTUNIFIEDALERT,TMM_ALERTUNIFIED2ALERT,TMM_ALERTPRELUDE,TMM_ALERTDEBUGLOG,TMM_ALERTSYSLOG,TMM_LOGDROPLOG,TMM_ALERTSYSLOG4,TMM_ALERTSYSLOG6,TMM_RESPONDREJECT,TMM_LOGHTTPLOG,TMM_LOGHTTPLOG4,TMM_LOGHTTPLOG6,TMM_PCAPLOG,TMM_STREAMTCP,TMM_DECODEIPFW,TMM_VERDICTIPFW,TMM_RECEIVEIPFW,TMM_RECEIVEERFFILE,TMM_DECODEERFFILE,TMM_RECEIVEERFDAG,TMM_DECODEERFDAG,threading
1,4,6,172008,0,0,0,0,0,0,47889,0,0,48582,1323,0,0,0,0,1359,0,1134,0,0,0,0,0,8028,0,0,0,49356,0,0,0,0,0,0,0,14337
First line of the file contains labels.
2 example gnuplot scripts added to plot the data.
15 years ago
|
|
|
#ifdef PROFILING
|
|
|
|
|
PktProfiling *profile;
|
Add per packet profiling.
Per packet profiling uses tick based accounting. It has 2 outputs, a summary
and a csv file that contains per packet stats.
Stats per packet include:
1) total ticks spent
2) ticks spent per individual thread module
3) "threading overhead" which is simply calculated by subtracting (2) of (1).
A number of changes were made to integrate the new code in a clean way:
a number of generic enums are now placed in tm-threads-common.h so we can
include them from any part of the engine.
Code depends on --enable-profiling just like the rule profiling code.
New yaml parameters:
profiling:
# packet profiling
packets:
# Profiling can be disabled here, but it will still have a
# performance impact if compiled in.
enabled: yes
filename: packet_stats.log
append: yes
# per packet csv output
csv:
# Output can be disabled here, but it will still have a
# performance impact if compiled in.
enabled: no
filename: packet_stats.csv
Example output of summary stats:
IP ver Proto cnt min max avg
------ ----- ------ ------ ---------- -------
IPv4 6 19436 11448 5404365 32993
IPv4 256 4 11511 49968 30575
Per Thread module stats:
Thread Module IP ver Proto cnt min max avg
------------------------ ------ ----- ------ ------ ---------- -------
TMM_DECODEPCAPFILE IPv4 6 19434 1242 47889 1770
TMM_DETECT IPv4 6 19436 1107 137241 1504
TMM_ALERTFASTLOG IPv4 6 19436 90 1323 155
TMM_ALERTUNIFIED2ALERT IPv4 6 19436 108 1359 138
TMM_ALERTDEBUGLOG IPv4 6 19436 90 1134 154
TMM_LOGHTTPLOG IPv4 6 19436 414 5392089 7944
TMM_STREAMTCP IPv4 6 19434 828 1299159 19438
The proto 256 is a counter for handling of pseudo/tunnel packets.
Example output of csv:
pcap_cnt,ipver,ipproto,total,TMM_DECODENFQ,TMM_VERDICTNFQ,TMM_RECEIVENFQ,TMM_RECEIVEPCAP,TMM_RECEIVEPCAPFILE,TMM_DECODEPCAP,TMM_DECODEPCAPFILE,TMM_RECEIVEPFRING,TMM_DECODEPFRING,TMM_DETECT,TMM_ALERTFASTLOG,TMM_ALERTFASTLOG4,TMM_ALERTFASTLOG6,TMM_ALERTUNIFIEDLOG,TMM_ALERTUNIFIEDALERT,TMM_ALERTUNIFIED2ALERT,TMM_ALERTPRELUDE,TMM_ALERTDEBUGLOG,TMM_ALERTSYSLOG,TMM_LOGDROPLOG,TMM_ALERTSYSLOG4,TMM_ALERTSYSLOG6,TMM_RESPONDREJECT,TMM_LOGHTTPLOG,TMM_LOGHTTPLOG4,TMM_LOGHTTPLOG6,TMM_PCAPLOG,TMM_STREAMTCP,TMM_DECODEIPFW,TMM_VERDICTIPFW,TMM_RECEIVEIPFW,TMM_RECEIVEERFFILE,TMM_DECODEERFFILE,TMM_RECEIVEERFDAG,TMM_DECODEERFDAG,threading
1,4,6,172008,0,0,0,0,0,0,47889,0,0,48582,1323,0,0,0,0,1359,0,1134,0,0,0,0,0,8028,0,0,0,49356,0,0,0,0,0,0,0,14337
First line of the file contains labels.
2 example gnuplot scripts added to plot the data.
15 years ago
|
|
|
#endif
|
|
|
|
|
#ifdef HAVE_NAPATECH
|
|
|
|
|
NapatechPacketVars ntpv;
|
|
|
|
|
#endif
|
|
|
|
|
} Packet;
|
|
|
|
|
|
|
|
|
|
/** highest mtu of the interfaces we monitor */
|
|
|
|
|
extern int g_default_mtu;
|
|
|
|
|
#define DEFAULT_MTU 1500
|
|
|
|
|
#define MINIMUM_MTU 68 /**< ipv4 minimum: rfc791 */
|
|
|
|
|
|
|
|
|
|
#define DEFAULT_PACKET_SIZE (DEFAULT_MTU + ETHERNET_HEADER_LEN)
|
|
|
|
|
/* storage: maximum ip packet size + link header */
|
|
|
|
|
#define MAX_PAYLOAD_SIZE (IPV6_HEADER_LEN + 65536 + 28)
|
|
|
|
|
extern uint32_t default_packet_size;
|
|
|
|
|
#define SIZE_OF_PACKET (default_packet_size + sizeof(Packet))
|
|
|
|
|
|
|
|
|
|
/** \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;
|
|
|
|
|
|
|
|
|
|
/** 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_max_mac_addrs_src;
|
|
|
|
|
uint16_t counter_max_mac_addrs_dst;
|
|
|
|
|
|
|
|
|
|
uint16_t counter_invalid;
|
|
|
|
|
|
|
|
|
|
uint16_t counter_eth;
|
|
|
|
|
uint16_t counter_chdlc;
|
|
|
|
|
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_esp;
|
|
|
|
|
uint16_t counter_ppp;
|
|
|
|
|
uint16_t counter_geneve;
|
|
|
|
|
uint16_t counter_gre;
|
|
|
|
|
uint16_t counter_vlan;
|
|
|
|
|
uint16_t counter_vlan_qinq;
|
|
|
|
|
uint16_t counter_vxlan;
|
|
|
|
|
uint16_t counter_vntag;
|
|
|
|
|
uint16_t counter_ieee8021ah;
|
|
|
|
|
uint16_t counter_pppoe;
|
|
|
|
|
uint16_t counter_teredo;
|
|
|
|
|
uint16_t counter_mpls;
|
|
|
|
|
uint16_t counter_ipv4inipv6;
|
|
|
|
|
uint16_t counter_ipv6inipv6;
|
|
|
|
|
uint16_t counter_erspan;
|
|
|
|
|
uint16_t counter_nsh;
|
|
|
|
|
|
|
|
|
|
/** 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;
|
|
|
|
|
|
|
|
|
|
uint16_t counter_flow_memcap;
|
|
|
|
|
|
|
|
|
|
uint16_t counter_flow_tcp;
|
|
|
|
|
uint16_t counter_flow_udp;
|
|
|
|
|
uint16_t counter_flow_icmp4;
|
|
|
|
|
uint16_t counter_flow_icmp6;
|
flow: redesign of flow timeout handling
Goals:
- reduce locking
- take advantage of 'hot' caches
- better locality
Locking reduction
New flow spare pool. The global pool is implmented as a list of blocks,
where each block has a 100 spare flows. Worker threads fetch a block at
a time, storing the block in the local thread storage.
Flow Recycler now returns flows to the pool is blocks as well.
Flow Recycler fetches all flows to be processed in one step instead of
one at a time.
Cache 'hot'ness
Worker threads now check the timeout of flows they evaluate during lookup.
The worker will have to read the flow into cache anyway, so the added
overhead of checking the timeout value is minimal. When a flow is considered
timed out, one of 2 things happens:
- if the flow is 'owned' by the thread it is handled locally. Handling means
checking if the flow needs 'timeout' work.
- otherwise, the flow is added to a special 'evicted' list in the flow
bucket where it will be picked up by the flow manager.
Flow Manager timing
By default the flow manager now tries to do passes of the flow hash in
smaller steps, where the goal is to do full pass in 8 x the lowest timeout
value it has to enforce. So if the lowest timeout value is 30s, a full pass
will take 4 minutes. The goal here is to reduce locking overhead and not
get in the way of the workers.
In emergency mode each pass is full, and lower timeouts are used.
Timing of the flow manager is also no longer relying on pthread condition
variables, as these generally cause waking up much quicker than the desired
timout. Instead a simple (u)sleep loop is used.
Both changes reduce the number of hash passes a lot.
Emergency behavior
In emergency mode there a number of changes to the workers. In this scenario
the flow memcap is fully used up and it is unavoidable that some flows won't
be tracked.
1. flow spare pool fetches are reduced to once a second. This avoids locking
overhead, while the chance of success was very low.
2. getting an active flow directly from the hash skips flows that had very
recent activity to avoid the scenario where all flows get only into the
NEW state before getting reused. Rather allow some to have a chance of
completing.
3. TCP packets that are not SYN packets will not get a used flow, unless
stream.midstream is enabled. The goal here is again to avoid evicting
active flows unnecessarily.
Better Localily
Flow Manager injects flows into the worker threads now, instead of one or
two packets. Advantage of this is that the worker threads can get packets
from their local packet pools, avoiding constant overhead of packets returning
to 'foreign' pools.
Counters
A lot of flow counters have been added and some have been renamed.
Overall the worker threads increment 'flow.wrk.*' counters, while the flow
manager increments 'flow.mgr.*'.
Additionally, none of the counters are snapshots anymore, they all increment
over time. The flow.memuse and flow.spare counters are exceptions.
Misc
FlowQueue has been split into a FlowQueuePrivate (unlocked) and FlowQueue.
Flow no longer has 'prev' pointers and used a unified 'next' pointer for
both hash and queue use.
7 years ago
|
|
|
uint16_t counter_flow_tcp_reuse;
|
|
|
|
|
uint16_t counter_flow_get_used;
|
|
|
|
|
uint16_t counter_flow_get_used_eval;
|
|
|
|
|
uint16_t counter_flow_get_used_eval_reject;
|
|
|
|
|
uint16_t counter_flow_get_used_eval_busy;
|
|
|
|
|
uint16_t counter_flow_get_used_failed;
|
|
|
|
|
|
|
|
|
|
uint16_t counter_flow_spare_sync;
|
|
|
|
|
uint16_t counter_flow_spare_sync_empty;
|
|
|
|
|
uint16_t counter_flow_spare_sync_incomplete;
|
|
|
|
|
uint16_t counter_flow_spare_sync_avg;
|
|
|
|
|
|
|
|
|
|
uint16_t counter_engine_events[DECODE_EVENT_MAX];
|
|
|
|
|
|
|
|
|
|
/* thread data for flow logging api: only used at forced
|
|
|
|
|
* flow recycle during lookups */
|
|
|
|
|
void *output_flow_thread_data;
|
|
|
|
|
|
|
|
|
|
} 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);
|
|
|
|
|
|
|
|
|
|
#define PACKET_CLEAR_L4VARS(p) do { \
|
|
|
|
|
memset(&(p)->l4vars, 0x00, sizeof((p)->l4vars)); \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \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.
|
|
|
|
|
*/
|
|
|
|
|
#define PACKET_INITIALIZE(p) \
|
|
|
|
|
{ \
|
|
|
|
|
SCMutexInit(&(p)->tunnel_mutex, NULL); \
|
|
|
|
|
(p)->alerts.alerts = PacketAlertCreate(); \
|
|
|
|
|
PACKET_RESET_CHECKSUMS((p)); \
|
|
|
|
|
(p)->livedev = NULL; \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#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)->esph != NULL) { \
|
|
|
|
|
CLEAR_ESP_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)->payload = NULL; \
|
|
|
|
|
(p)->payload_len = 0; \
|
|
|
|
|
(p)->BypassPacketsFlow = NULL; \
|
|
|
|
|
(p)->pktlen = 0; \
|
|
|
|
|
(p)->alerts.cnt = 0; \
|
|
|
|
|
(p)->alerts.discarded = 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; \
|
|
|
|
|
p->nb_decoded_layers = 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 { \
|
|
|
|
|
PACKET_RELEASE_REFS((p)); \
|
|
|
|
|
if ((p)->pktvar != NULL) { \
|
|
|
|
|
PktVarFree((p)->pktvar); \
|
|
|
|
|
} \
|
|
|
|
|
PacketAlertFree((p)->alerts.alerts); \
|
|
|
|
|
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) (p)->action = (a)
|
|
|
|
|
|
|
|
|
|
static inline void PacketSetAction(Packet *p, const uint8_t a)
|
|
|
|
|
{
|
|
|
|
|
if (likely(p->root == NULL)) {
|
|
|
|
|
PACKET_SET_ACTION(p, a);
|
|
|
|
|
} else {
|
|
|
|
|
PACKET_SET_ACTION(p->root, a);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#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)->action &(a)
|
|
|
|
|
|
|
|
|
|
static inline uint8_t PacketTestAction(const Packet *p, const uint8_t a)
|
|
|
|
|
{
|
|
|
|
|
if (likely(p->root == NULL)) {
|
|
|
|
|
return PACKET_TEST_ACTION(p, a);
|
|
|
|
|
} else {
|
|
|
|
|
return PACKET_TEST_ACTION(p->root, a);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define PACKET_UPDATE_ACTION(p, a) (p)->action |= (a)
|
|
|
|
|
static inline void PacketUpdateAction(Packet *p, const uint8_t a)
|
|
|
|
|
{
|
|
|
|
|
if (likely(p->root == NULL)) {
|
|
|
|
|
PACKET_UPDATE_ACTION(p, a);
|
|
|
|
|
} else {
|
|
|
|
|
PACKET_UPDATE_ACTION(p->root, a);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define TUNNEL_INCR_PKT_RTV_NOLOCK(p) do { \
|
|
|
|
|
((p)->root ? (p)->root->tunnel_rtv_cnt++ : (p)->tunnel_rtv_cnt++); \
|
|
|
|
|
} 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_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_ERSPANII,
|
|
|
|
|
DECODE_TUNNEL_ERSPANI,
|
|
|
|
|
DECODE_TUNNEL_VLAN,
|
|
|
|
|
DECODE_TUNNEL_IPV4,
|
|
|
|
|
DECODE_TUNNEL_IPV6,
|
|
|
|
|
DECODE_TUNNEL_IPV6_TEREDO, /**< separate protocol for stricter error handling */
|
|
|
|
|
DECODE_TUNNEL_PPP,
|
|
|
|
|
DECODE_TUNNEL_NSH,
|
|
|
|
|
DECODE_TUNNEL_UNSET
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Packet *PacketTunnelPktSetup(ThreadVars *tv, DecodeThreadVars *dtv, Packet *parent,
|
|
|
|
|
const uint8_t *pkt, uint32_t len, enum DecodeTunnelProto proto);
|
|
|
|
|
Packet *PacketDefragPktSetup(Packet *parent, const uint8_t *pkt, uint32_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 PacketUpdateEngineEventCounters(ThreadVars *tv,
|
|
|
|
|
DecodeThreadVars *dtv, Packet *p);
|
|
|
|
|
void PacketFree(Packet *p);
|
|
|
|
|
void PacketFreeOrRelease(Packet *p);
|
|
|
|
|
int PacketCallocExtPkt(Packet *p, int datalen);
|
|
|
|
|
int PacketCopyData(Packet *p, const uint8_t *pktdata, uint32_t pktlen);
|
|
|
|
|
int PacketSetData(Packet *p, const uint8_t *pktdata, uint32_t pktlen);
|
|
|
|
|
int PacketCopyDataOffset(Packet *p, uint32_t offset, const uint8_t *data, uint32_t datalen);
|
|
|
|
|
const char *PktSrcToString(enum PktSrcEnum pkt_src);
|
|
|
|
|
void PacketBypassCallback(Packet *p);
|
|
|
|
|
void PacketSwap(Packet *p);
|
|
|
|
|
|
|
|
|
|
DecodeThreadVars *DecodeThreadVarsAlloc(ThreadVars *);
|
|
|
|
|
void DecodeThreadVarsFree(ThreadVars *, DecodeThreadVars *);
|
|
|
|
|
void DecodeUpdatePacketCounters(ThreadVars *tv,
|
|
|
|
|
const DecodeThreadVars *dtv, const Packet *p);
|
|
|
|
|
|
|
|
|
|
/* decoder functions */
|
|
|
|
|
int DecodeEthernet(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
|
|
|
|
|
int DecodeSll(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
|
|
|
|
|
int DecodePPP(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
|
|
|
|
|
int DecodePPPOESession(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
|
|
|
|
|
int DecodePPPOEDiscovery(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
|
|
|
|
|
int DecodeNull(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
|
|
|
|
|
int DecodeRaw(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
|
|
|
|
|
int DecodeIPV4(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint16_t);
|
|
|
|
|
int DecodeIPV6(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint16_t);
|
|
|
|
|
int DecodeICMPV4(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
|
|
|
|
|
int DecodeICMPV6(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
|
|
|
|
|
int DecodeTCP(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint16_t);
|
|
|
|
|
int DecodeUDP(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint16_t);
|
|
|
|
|
int DecodeSCTP(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint16_t);
|
|
|
|
|
int DecodeESP(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint16_t);
|
|
|
|
|
int DecodeGRE(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
|
|
|
|
|
int DecodeVLAN(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
|
|
|
|
|
int DecodeVNTag(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
|
|
|
|
|
int DecodeIEEE8021ah(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
|
|
|
|
|
int DecodeGeneve(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
|
|
|
|
|
int DecodeVXLAN(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
|
|
|
|
|
int DecodeMPLS(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
|
|
|
|
|
int DecodeERSPAN(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
|
|
|
|
|
int DecodeERSPANTypeI(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
|
|
|
|
|
int DecodeCHDLC(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
|
|
|
|
|
int DecodeTEMPLATE(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
|
|
|
|
|
int DecodeNSH(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
|
|
|
|
|
|
|
|
|
|
#ifdef UNITTESTS
|
|
|
|
|
void DecodeIPV6FragHeader(Packet *p, const uint8_t *pkt,
|
|
|
|
|
uint16_t hdrextlen, uint16_t plen,
|
|
|
|
|
uint16_t prev_hdrextlen);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void AddressDebugPrint(Address *);
|
|
|
|
|
|
|
|
|
|
typedef int (*DecoderFunc)(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
|
|
|
|
|
const uint8_t *pkt, uint32_t len);
|
|
|
|
|
void DecodeGlobalConfig(void);
|
|
|
|
|
void PacketAlertGetMaxConfig(void);
|
|
|
|
|
void DecodeUnregisterCounters(void);
|
|
|
|
|
|
|
|
|
|
/** \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; \
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
#ifndef IPPROTO_IPIP
|
|
|
|
|
#define IPPROTO_IPIP 4
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* 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
|
|
|
|
|
|
|
|
|
|
#ifndef DLT_C_HDLC
|
|
|
|
|
#define DLT_C_HDLC 104
|
|
|
|
|
#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
|
|
|
|
|
/* http://www.tcpdump.org/linktypes.html defines DLT_RAW as 101, yet others don't.
|
|
|
|
|
* Libpcap on at least OpenBSD returns 101 as datalink type for RAW pcaps though. */
|
|
|
|
|
#define LINKTYPE_RAW2 101
|
|
|
|
|
#define LINKTYPE_IPV4 228
|
|
|
|
|
#define LINKTYPE_GRE_OVER_IP 778
|
|
|
|
|
#define LINKTYPE_CISCO_HDLC DLT_C_HDLC
|
|
|
|
|
#define PPP_OVER_GRE 11
|
|
|
|
|
#define VLAN_OVER_GRE 13
|
|
|
|
|
|
|
|
|
|
/* Packet Flags */
|
|
|
|
|
|
|
|
|
|
/** Flag to indicate that packet header or contents should not be inspected */
|
|
|
|
|
#define PKT_NOPACKET_INSPECTION BIT_U32(0)
|
|
|
|
|
// vacancy
|
|
|
|
|
|
|
|
|
|
/** Flag to indicate that packet contents should not be inspected */
|
|
|
|
|
#define PKT_NOPAYLOAD_INSPECTION BIT_U32(2)
|
|
|
|
|
/** Packet was alloc'd this run, needs to be freed */
|
|
|
|
|
#define PKT_ALLOC BIT_U32(3)
|
|
|
|
|
/** Packet has matched a tag */
|
|
|
|
|
#define PKT_HAS_TAG BIT_U32(4)
|
|
|
|
|
/** Packet payload was added to reassembled stream */
|
|
|
|
|
#define PKT_STREAM_ADD BIT_U32(5)
|
|
|
|
|
/** Packet is part of established stream */
|
|
|
|
|
#define PKT_STREAM_EST BIT_U32(6)
|
|
|
|
|
/** Stream is in eof state */
|
|
|
|
|
#define PKT_STREAM_EOF BIT_U32(7)
|
|
|
|
|
#define PKT_HAS_FLOW BIT_U32(8)
|
|
|
|
|
/** Pseudo packet to end the stream */
|
|
|
|
|
#define PKT_PSEUDO_STREAM_END BIT_U32(9)
|
|
|
|
|
/** Packet is modified by the stream engine, we need to recalc the csum and \
|
|
|
|
|
reinject/replace */
|
|
|
|
|
#define PKT_STREAM_MODIFIED BIT_U32(10)
|
|
|
|
|
/** Packet mark is modified */
|
|
|
|
|
#define PKT_MARK_MODIFIED BIT_U32(11)
|
|
|
|
|
/** Exclude packet from pcap logging as it's part of a stream that has reassembly \
|
|
|
|
|
depth reached. */
|
|
|
|
|
#define PKT_STREAM_NOPCAPLOG BIT_U32(12)
|
|
|
|
|
|
|
|
|
|
#define PKT_TUNNEL BIT_U32(13)
|
|
|
|
|
#define PKT_TUNNEL_VERDICTED BIT_U32(14)
|
|
|
|
|
|
|
|
|
|
/** Packet checksum is not computed (TX packet for example) */
|
|
|
|
|
#define PKT_IGNORE_CHECKSUM BIT_U32(15)
|
|
|
|
|
/** Packet comes from zero copy (ext_pkt must not be freed) */
|
|
|
|
|
#define PKT_ZERO_COPY BIT_U32(16)
|
|
|
|
|
|
|
|
|
|
#define PKT_HOST_SRC_LOOKED_UP BIT_U32(17)
|
|
|
|
|
#define PKT_HOST_DST_LOOKED_UP BIT_U32(18)
|
|
|
|
|
|
|
|
|
|
/** Packet is a fragment */
|
|
|
|
|
#define PKT_IS_FRAGMENT BIT_U32(19)
|
|
|
|
|
#define PKT_IS_INVALID BIT_U32(20)
|
|
|
|
|
#define PKT_PROFILE BIT_U32(21)
|
|
|
|
|
|
|
|
|
|
/** indication by decoder that it feels the packet should be handled by
|
|
|
|
|
* flow engine: Packet::flow_hash will be set */
|
|
|
|
|
#define PKT_WANTS_FLOW BIT_U32(22)
|
|
|
|
|
|
|
|
|
|
/** protocol detection done */
|
|
|
|
|
#define PKT_PROTO_DETECT_TS_DONE BIT_U32(23)
|
|
|
|
|
#define PKT_PROTO_DETECT_TC_DONE BIT_U32(24)
|
|
|
|
|
|
|
|
|
|
#define PKT_REBUILT_FRAGMENT \
|
|
|
|
|
BIT_U32(25) /**< Packet is rebuilt from \
|
|
|
|
|
* fragments. */
|
|
|
|
|
#define PKT_DETECT_HAS_STREAMDATA \
|
|
|
|
|
BIT_U32(26) /**< Set by Detect() if raw stream data is available. */
|
|
|
|
|
|
|
|
|
|
#define PKT_PSEUDO_DETECTLOG_FLUSH BIT_U32(27) /**< Detect/log flush for protocol upgrade */
|
|
|
|
|
|
|
|
|
|
/** Packet is part of stream in known bad condition (loss, wrong thread),
|
|
|
|
|
* so flag it for not setting stream events */
|
|
|
|
|
#define PKT_STREAM_NO_EVENTS BIT_U32(28)
|
|
|
|
|
|
|
|
|
|
/** \brief return 1 if the packet is a pseudo packet */
|
|
|
|
|
#define PKT_IS_PSEUDOPKT(p) \
|
|
|
|
|
((p)->flags & (PKT_PSEUDO_STREAM_END|PKT_PSEUDO_DETECTLOG_FLUSH))
|
|
|
|
|
|
|
|
|
|
#define PKT_SET_SRC(p, src_val) ((p)->pkt_src = src_val)
|
|
|
|
|
|
|
|
|
|
#define PKT_DEFAULT_MAX_DECODED_LAYERS 16
|
|
|
|
|
extern uint8_t decoder_max_layers;
|
|
|
|
|
|
|
|
|
|
static inline bool PacketIncreaseCheckLayers(Packet *p)
|
|
|
|
|
{
|
|
|
|
|
p->nb_decoded_layers++;
|
|
|
|
|
if (p->nb_decoded_layers >= decoder_max_layers) {
|
|
|
|
|
ENGINE_SET_INVALID_EVENT(p, GENERIC_TOO_MANY_LAYERS);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \brief return true if *this* packet needs to trigger a verdict.
|
|
|
|
|
*
|
|
|
|
|
* If we have the root packet, and we have none outstanding,
|
|
|
|
|
* we can verdict now.
|
|
|
|
|
*
|
|
|
|
|
* If we have a upper layer packet, it's the only one and root
|
|
|
|
|
* is already processed, we can verdict now.
|
|
|
|
|
*
|
|
|
|
|
* Otherwise, a future packet will issue the verdict.
|
|
|
|
|
*/
|
|
|
|
|
static inline bool VerdictTunnelPacket(Packet *p)
|
|
|
|
|
{
|
|
|
|
|
bool verdict = true;
|
|
|
|
|
SCMutex *m = p->root ? &p->root->tunnel_mutex : &p->tunnel_mutex;
|
|
|
|
|
SCMutexLock(m);
|
|
|
|
|
const uint16_t outstanding = TUNNEL_PKT_TPR(p) - TUNNEL_PKT_RTV(p);
|
|
|
|
|
SCLogDebug("tunnel: outstanding %u", outstanding);
|
|
|
|
|
|
|
|
|
|
/* if there are packets outstanding, we won't verdict this one */
|
|
|
|
|
if (IS_TUNNEL_ROOT_PKT(p) && !IS_TUNNEL_PKT_VERDICTED(p) && !outstanding) {
|
|
|
|
|
// verdict
|
|
|
|
|
SCLogDebug("root %p: verdict", p);
|
|
|
|
|
} else if (!IS_TUNNEL_ROOT_PKT(p) && outstanding == 1 && p->root && IS_TUNNEL_PKT_VERDICTED(p->root)) {
|
|
|
|
|
// verdict
|
|
|
|
|
SCLogDebug("tunnel %p: verdict", p);
|
|
|
|
|
} else {
|
|
|
|
|
verdict = false;
|
|
|
|
|
}
|
|
|
|
|
SCMutexUnlock(m);
|
|
|
|
|
return verdict;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void DecodeLinkLayer(ThreadVars *tv, DecodeThreadVars *dtv,
|
|
|
|
|
const int datalink, Packet *p, const uint8_t *data, const uint32_t len)
|
|
|
|
|
{
|
|
|
|
|
/* call the decoder */
|
|
|
|
|
switch (datalink) {
|
|
|
|
|
case LINKTYPE_ETHERNET:
|
|
|
|
|
DecodeEthernet(tv, dtv, p, data, len);
|
|
|
|
|
break;
|
|
|
|
|
case LINKTYPE_LINUX_SLL:
|
|
|
|
|
DecodeSll(tv, dtv, p, data, len);
|
|
|
|
|
break;
|
|
|
|
|
case LINKTYPE_PPP:
|
|
|
|
|
DecodePPP(tv, dtv, p, data, len);
|
|
|
|
|
break;
|
|
|
|
|
case LINKTYPE_RAW:
|
|
|
|
|
case LINKTYPE_GRE_OVER_IP:
|
|
|
|
|
DecodeRaw(tv, dtv, p, data, len);
|
|
|
|
|
break;
|
|
|
|
|
case LINKTYPE_NULL:
|
|
|
|
|
DecodeNull(tv, dtv, p, data, len);
|
|
|
|
|
break;
|
|
|
|
|
case LINKTYPE_CISCO_HDLC:
|
|
|
|
|
DecodeCHDLC(tv, dtv, p, data, len);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
SCLogError(SC_ERR_DATALINK_UNIMPLEMENTED, "datalink type "
|
|
|
|
|
"%"PRId32" not yet supported", datalink);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \brief decode network layer
|
|
|
|
|
* \retval bool true if successful, false if unknown */
|
|
|
|
|
static inline bool DecodeNetworkLayer(ThreadVars *tv, DecodeThreadVars *dtv,
|
|
|
|
|
const uint16_t proto, Packet *p, const uint8_t *data, const uint32_t len)
|
|
|
|
|
{
|
|
|
|
|
switch (proto) {
|
|
|
|
|
case ETHERNET_TYPE_IP: {
|
|
|
|
|
uint16_t ip_len = (len < USHRT_MAX) ? (uint16_t)len : (uint16_t)USHRT_MAX;
|
|
|
|
|
DecodeIPV4(tv, dtv, p, data, ip_len);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ETHERNET_TYPE_IPV6: {
|
|
|
|
|
uint16_t ip_len = (len < USHRT_MAX) ? (uint16_t)len : (uint16_t)USHRT_MAX;
|
|
|
|
|
DecodeIPV6(tv, dtv, p, data, ip_len);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ETHERNET_TYPE_PPPOE_SESS:
|
|
|
|
|
DecodePPPOESession(tv, dtv, p, data, len);
|
|
|
|
|
break;
|
|
|
|
|
case ETHERNET_TYPE_PPPOE_DISC:
|
|
|
|
|
DecodePPPOEDiscovery(tv, dtv, p, data, len);
|
|
|
|
|
break;
|
|
|
|
|
case ETHERNET_TYPE_VLAN:
|
|
|
|
|
case ETHERNET_TYPE_8021AD:
|
|
|
|
|
case ETHERNET_TYPE_8021QINQ:
|
|
|
|
|
if (p->vlan_idx >= 2) {
|
|
|
|
|
ENGINE_SET_EVENT(p,VLAN_HEADER_TOO_MANY_LAYERS);
|
|
|
|
|
} else {
|
|
|
|
|
DecodeVLAN(tv, dtv, p, data, len);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case ETHERNET_TYPE_8021AH:
|
|
|
|
|
DecodeIEEE8021ah(tv, dtv, p, data, len);
|
|
|
|
|
break;
|
|
|
|
|
case ETHERNET_TYPE_ARP:
|
|
|
|
|
break;
|
|
|
|
|
case ETHERNET_TYPE_MPLS_UNICAST:
|
|
|
|
|
case ETHERNET_TYPE_MPLS_MULTICAST:
|
|
|
|
|
DecodeMPLS(tv, dtv, p, data, len);
|
|
|
|
|
break;
|
|
|
|
|
case ETHERNET_TYPE_DCE:
|
|
|
|
|
if (unlikely(len < ETHERNET_DCE_HEADER_LEN)) {
|
|
|
|
|
ENGINE_SET_INVALID_EVENT(p, DCE_PKT_TOO_SMALL);
|
|
|
|
|
} else {
|
|
|
|
|
DecodeEthernet(tv, dtv, p, data, len);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case ETHERNET_TYPE_VNTAG:
|
|
|
|
|
DecodeVNTag(tv, dtv, p, data, len);
|
|
|
|
|
break;
|
|
|
|
|
case ETHERNET_TYPE_NSH:
|
|
|
|
|
DecodeNSH(tv, dtv, p, data, len);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
SCLogDebug("unknown ether type: %" PRIx16 "", proto);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif /* __DECODE_H__ */
|