diff --git a/etc/schema.json b/etc/schema.json index 99f419fff4..7d3d2593c3 100644 --- a/etc/schema.json +++ b/etc/schema.json @@ -1088,6 +1088,9 @@ }, "urg": { "type": "boolean" + }, + "reason": { + "type": "string" } }, "additionalProperties": false diff --git a/src/decode.c b/src/decode.c index c87941ff80..d277d2beff 100644 --- a/src/decode.c +++ b/src/decode.c @@ -768,6 +768,38 @@ const char *PktSrcToString(enum PktSrcEnum pkt_src) return pkt_src_str; } +const char *PacketDropReasonToString(enum PacketDropReason r) +{ + switch (r) { + case PKT_DROP_REASON_DECODE_ERROR: + return "decode error"; + case PKT_DROP_REASON_DEFRAG_ERROR: + return "defrag error"; + case PKT_DROP_REASON_DEFRAG_MEMCAP: + return "defrag memcap"; + case PKT_DROP_REASON_FLOW_MEMCAP: + return "flow memcap"; + case PKT_DROP_REASON_FLOW_DROP: + return "flow drop"; + case PKT_DROP_REASON_STREAM_ERROR: + return "stream error"; + case PKT_DROP_REASON_STREAM_MEMCAP: + return "stream memcap"; + case PKT_DROP_REASON_APPLAYER_ERROR: + return "applayer error"; + case PKT_DROP_REASON_APPLAYER_MEMCAP: + return "applayer memcap"; + case PKT_DROP_REASON_RULES: + return "rules"; + case PKT_DROP_REASON_RULES_THRESHOLD: + return "threshold detection_filter"; + case PKT_DROP_REASON_NOT_SET: + default: + return NULL; + } +} + +/* TODO drop reason stats! */ void CaptureStatsUpdate(ThreadVars *tv, CaptureStats *s, const Packet *p) { if (unlikely(PacketTestAction(p, (ACTION_REJECT | ACTION_REJECT_DST | ACTION_REJECT_BOTH)))) { diff --git a/src/decode.h b/src/decode.h index 1b9806e748..c766695801 100644 --- a/src/decode.h +++ b/src/decode.h @@ -404,6 +404,21 @@ typedef struct PktProfiling_ { #endif /* PROFILING */ +enum PacketDropReason { + PKT_DROP_REASON_NOT_SET = 0, + PKT_DROP_REASON_DECODE_ERROR, + PKT_DROP_REASON_DEFRAG_ERROR, + PKT_DROP_REASON_DEFRAG_MEMCAP, + PKT_DROP_REASON_FLOW_MEMCAP, + PKT_DROP_REASON_FLOW_DROP, + PKT_DROP_REASON_STREAM_ERROR, + PKT_DROP_REASON_STREAM_MEMCAP, + PKT_DROP_REASON_APPLAYER_ERROR, + PKT_DROP_REASON_APPLAYER_MEMCAP, + PKT_DROP_REASON_RULES, + PKT_DROP_REASON_RULES_THRESHOLD, /**< detection_filter in action */ +}; + /* forward declaration since Packet struct definition requires this */ struct PacketQueue_; @@ -600,6 +615,14 @@ typedef struct Packet_ /** data linktype in host order */ int datalink; + /* count decoded layers of packet : too many layers + * cause issues with performance and stability (stack exhaustion) + */ + uint8_t nb_decoded_layers; + + /* enum PacketDropReason::PKT_DROP_REASON_* as uint8_t for compactness */ + uint8_t drop_reason; + /* tunnel/encapsulation handling */ struct Packet_ *root; /* in case of tunnel this is a ptr * to the 'real' packet, the one we @@ -625,11 +648,6 @@ typedef struct Packet_ */ struct PktPool_ *pool; - /* count decoded layers of packet : too many layers - * cause issues with performance and stability (stack exhaustion) - */ - uint8_t nb_decoded_layers; - #ifdef PROFILING PktProfiling *profile; #endif @@ -802,6 +820,7 @@ void CaptureStatsSetup(ThreadVars *tv, CaptureStats *s); (p)->ts.tv_sec = 0; \ (p)->ts.tv_usec = 0; \ (p)->datalink = 0; \ + (p)->drop_reason = 0; \ (p)->action = 0; \ if ((p)->pktvar != NULL) { \ PktVarFree((p)->pktvar); \ @@ -899,8 +918,6 @@ static inline void PacketSetAction(Packet *p, const uint8_t a) #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)) @@ -911,6 +928,14 @@ static inline void PacketSetAction(Packet *p, const uint8_t a) #define PACKET_TEST_ACTION(p, a) (p)->action &(a) +static inline void PacketDrop(Packet *p, enum PacketDropReason r) +{ + if (p->drop_reason == PKT_DROP_REASON_NOT_SET) + p->drop_reason = (uint8_t)r; + + PACKET_SET_ACTION(p, ACTION_DROP); +} + static inline uint8_t PacketTestAction(const Packet *p, const uint8_t a) { if (likely(p->root == NULL)) { @@ -988,6 +1013,7 @@ DecodeThreadVars *DecodeThreadVarsAlloc(ThreadVars *); void DecodeThreadVarsFree(ThreadVars *, DecodeThreadVars *); void DecodeUpdatePacketCounters(ThreadVars *tv, const DecodeThreadVars *dtv, const Packet *p); +const char *PacketDropReasonToString(enum PacketDropReason r); /* decoder functions */ int DecodeEthernet(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t); diff --git a/src/detect-engine-threshold.c b/src/detect-engine-threshold.c index 67eccd6784..878d1d91aa 100644 --- a/src/detect-engine-threshold.c +++ b/src/detect-engine-threshold.c @@ -299,7 +299,7 @@ static inline void RateFilterSetAction(Packet *p, PacketAlert *pa, uint8_t new_a pa->flags |= PACKET_ALERT_RATE_FILTER_MODIFIED; break; case TH_ACTION_DROP: - PACKET_DROP(p); + PacketDrop(p, PKT_DROP_REASON_RULES_THRESHOLD); pa->flags |= PACKET_ALERT_RATE_FILTER_MODIFIED; break; case TH_ACTION_REJECT: diff --git a/src/detect.c b/src/detect.c index 8151abef82..fdc2bd7c5b 100644 --- a/src/detect.c +++ b/src/detect.c @@ -1688,7 +1688,7 @@ static void DetectFlow(ThreadVars *tv, /* if flow is set to drop, we enforce that here */ if (p->flow->flags & FLOW_ACTION_DROP) { - PACKET_DROP(p); + PacketDrop(p, PKT_DROP_REASON_FLOW_DROP); SCReturn; } diff --git a/src/output-json-drop.c b/src/output-json-drop.c index bd10f49e33..0746e2600a 100644 --- a/src/output-json-drop.c +++ b/src/output-json-drop.c @@ -140,6 +140,10 @@ static int DropLogJSON (JsonDropLogThread *aft, const Packet *p) } break; } + if (p->drop_reason != 0) { + const char *str = PacketDropReasonToString(p->drop_reason); + jb_set_string(js, "reason", str); + } /* Close drop. */ jb_close(js); diff --git a/src/stream-tcp.c b/src/stream-tcp.c index 08d4da95c9..1ef011b1db 100644 --- a/src/stream-tcp.c +++ b/src/stream-tcp.c @@ -4929,7 +4929,7 @@ int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt, FlowSetNoPacketInspectionFlag(p->flow); DecodeSetNoPacketInspectionFlag(p); StreamTcpDisableAppLayer(p->flow); - PACKET_DROP(p); + PacketDrop(p, PKT_DROP_REASON_FLOW_DROP); /* return the segments to the pool */ StreamTcpSessionPktFree(p); SCReturnInt(0); @@ -5097,7 +5097,7 @@ error: * anyway. Doesn't disable all detection, so we can still * match on the stream event that was set. */ DecodeSetNoPayloadInspectionFlag(p); - PACKET_DROP(p); + PacketDrop(p, PKT_DROP_REASON_STREAM_ERROR); } SCReturnInt(-1); }