pull/16454/merge
Jason Ish 13 hours ago committed by GitHub
commit 15466ed309
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -134,12 +134,11 @@ static void OnFlowUpdate(ThreadVars *tv, Flow *f, Packet *p, void *_data)
/* Ignore packets that have a different protocol than the
* flow. This can happen with ICMP unreachable packets. */
if (p->proto != flow_proto) {
if (SCPacketGetIPProto(p) != flow_proto) {
return;
}
uint16_t ip_len = 0;
void *ip_ptr = NULL;
uint32_t ip_len = 0;
struct NdpiThreadContext *threadctx = NdpiGetThreadContext(tv);
struct NdpiFlowContext *flowctx = NdpiGetFlowContext(f);
@ -147,19 +146,15 @@ static void OnFlowUpdate(ThreadVars *tv, Flow *f, Packet *p, void *_data)
return;
if (flowctx == NULL || flowctx->ndpi_flow == NULL)
return;
if (!(PacketIsIPv4(p) || PacketIsIPv6(p)))
return;
if (PacketIsIPv4(p)) {
const IPV4Hdr *ip4h = PacketGetIPv4(p);
ip_len = IPV4_GET_RAW_IPLEN(ip4h);
ip_ptr = (void *)PacketGetIPv4(p);
} else if (PacketIsIPv6(p)) {
const IPV6Hdr *ip6h = PacketGetIPv6(p);
ip_len = IPV6_HEADER_LEN + IPV6_GET_RAW_PLEN(ip6h);
ip_ptr = (void *)PacketGetIPv6(p);
}
const uint8_t *ip_ptr = SCPacketGetL3(p, &ip_len);
if (!flowctx->detection_completed && ip_ptr != NULL && ip_len > 0) {
uint64_t time_ms = ((uint64_t)p->ts.secs) * 1000 + p->ts.usecs / 1000;
uint64_t secs = 0, usecs = 0;
SCPacketGetTimeAsParts(p, &secs, &usecs);
uint64_t time_ms = secs * 1000 + usecs / 1000;
SCLogDebug("Performing nDPI detection...");
@ -225,7 +220,7 @@ static int DetectnDPIProtocolPacketMatch(
{
SCEnter();
const Flow *f = p->flow;
const Flow *f = SCPacketGetFlow(p);
if (f == NULL) {
SCLogDebug("packet %" PRIu64 ": no flow", PcapPacketCntGet(p));
SCReturnInt(0);
@ -321,20 +316,19 @@ static bool nDPIProtocolDataHasConflicts(
static int DetectnDPIProtocolSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
{
DetectnDPIProtocolData *data = DetectnDPIProtocolParse(arg, s->init_data->negated);
DetectnDPIProtocolData *data = DetectnDPIProtocolParse(arg, SCDetectSignatureIsNegated(s));
if (data == NULL)
goto error;
SigMatch *tsm = s->init_data->smlists[DETECT_SM_LIST_MATCH];
for (; tsm != NULL; tsm = tsm->next) {
if (tsm->type == ndpi_protocol_keyword_id) {
const DetectnDPIProtocolData *them = (const DetectnDPIProtocolData *)tsm->ctx;
const SigMatch *tsm =
SCDetectSignatureGetLastSMByType(s, DETECT_SM_LIST_MATCH, ndpi_protocol_keyword_id);
for (; tsm != NULL; tsm = SCSigMatchGetPrevByType(tsm, ndpi_protocol_keyword_id)) {
const DetectnDPIProtocolData *them = (const DetectnDPIProtocolData *)SCSigMatchGetCtx(tsm);
if (nDPIProtocolDataHasConflicts(data, them)) {
SCLogError("can't mix "
"positive ndpi-protocol match with negated");
goto error;
}
if (nDPIProtocolDataHasConflicts(data, them)) {
SCLogError("can't mix "
"positive ndpi-protocol match with negated");
goto error;
}
}
@ -360,7 +354,7 @@ static int DetectnDPIRiskPacketMatch(
{
SCEnter();
const Flow *f = p->flow;
const Flow *f = SCPacketGetFlow(p);
if (f == NULL) {
SCLogDebug("packet %" PRIu64 ": no flow", PcapPacketCntGet(p));
SCReturnInt(0);
@ -461,20 +455,19 @@ static bool nDPIRiskDataHasConflicts(const DetectnDPIRiskData *us, const Detectn
static int DetectnDPIRiskSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
{
DetectnDPIRiskData *data = DetectnDPIRiskParse(arg, s->init_data->negated);
DetectnDPIRiskData *data = DetectnDPIRiskParse(arg, SCDetectSignatureIsNegated(s));
if (data == NULL)
goto error;
SigMatch *tsm = s->init_data->smlists[DETECT_SM_LIST_MATCH];
for (; tsm != NULL; tsm = tsm->next) {
if (tsm->type == ndpi_risk_keyword_id) {
const DetectnDPIRiskData *them = (const DetectnDPIRiskData *)tsm->ctx;
const SigMatch *tsm =
SCDetectSignatureGetLastSMByType(s, DETECT_SM_LIST_MATCH, ndpi_risk_keyword_id);
for (; tsm != NULL; tsm = SCSigMatchGetPrevByType(tsm, ndpi_risk_keyword_id)) {
const DetectnDPIRiskData *them = (const DetectnDPIRiskData *)SCSigMatchGetCtx(tsm);
if (nDPIRiskDataHasConflicts(data, them)) {
SCLogError("can't mix "
"positive ndpi-risk match with negated");
goto error;
}
if (nDPIRiskDataHasConflicts(data, them)) {
SCLogError("can't mix "
"positive ndpi-risk match with negated");
goto error;
}
}
@ -538,34 +531,36 @@ static void EveCallback(ThreadVars *tv, const Packet *p, Flow *f, SCJsonBuilder
static void NdpInitRiskKeyword(void)
{
/* SCSigTableAppLiteElmt and SCDetectHelperKeywordRegister don't yet
* support all the fields required to register the nDPI keywords,
* missing the (packet) Match callback,
* so we'll just register with an empty keyword specifier to get
* the ID, then fill in the ID. */
ndpi_protocol_keyword_id = SCDetectHelperNewKeywordId();
const SCSigTableAppLiteElmt protocol_kw = {
.name = "ndpi-protocol",
.desc = "match on the detected nDPI protocol",
.url = "/rules/ndpi-protocol.html",
.flags = SIGMATCH_QUOTES_OPTIONAL | SIGMATCH_HANDLE_NEGATION,
.Setup = DetectnDPIProtocolSetup,
.Free = DetectnDPIProtocolFree,
};
ndpi_protocol_keyword_id = SCDetectHelperKeywordRegister(&protocol_kw);
if (ndpi_protocol_keyword_id == UINT16_MAX) {
FatalError("Failed to register ndpi-protocol keyword");
}
SCDetectHelperKeywordPacketMatchRegister(
ndpi_protocol_keyword_id, DetectnDPIProtocolPacketMatch);
SCLogDebug("Registered new ndpi-protocol keyword with ID %" PRIu32, ndpi_protocol_keyword_id);
sigmatch_table[ndpi_protocol_keyword_id].name = "ndpi-protocol";
sigmatch_table[ndpi_protocol_keyword_id].desc = "match on the detected nDPI protocol";
sigmatch_table[ndpi_protocol_keyword_id].url = "/rules/ndpi-protocol.html";
sigmatch_table[ndpi_protocol_keyword_id].Match = DetectnDPIProtocolPacketMatch;
sigmatch_table[ndpi_protocol_keyword_id].Setup = DetectnDPIProtocolSetup;
sigmatch_table[ndpi_protocol_keyword_id].Free = DetectnDPIProtocolFree;
sigmatch_table[ndpi_protocol_keyword_id].flags =
(SIGMATCH_QUOTES_OPTIONAL | SIGMATCH_HANDLE_NEGATION);
ndpi_risk_keyword_id = SCDetectHelperNewKeywordId();
const SCSigTableAppLiteElmt risk_kw = {
.name = "ndpi-risk",
.desc = "match on the detected nDPI risk",
.url = "/rules/ndpi-risk.html",
.flags = SIGMATCH_QUOTES_OPTIONAL | SIGMATCH_HANDLE_NEGATION,
.Setup = DetectnDPIRiskSetup,
.Free = DetectnDPIRiskFree,
};
ndpi_risk_keyword_id = SCDetectHelperKeywordRegister(&risk_kw);
if (ndpi_risk_keyword_id == UINT16_MAX) {
FatalError("Failed to register ndpi-risk keyword");
}
SCDetectHelperKeywordPacketMatchRegister(ndpi_risk_keyword_id, DetectnDPIRiskPacketMatch);
SCLogDebug("Registered new ndpi-risk keyword with ID %" PRIu32, ndpi_risk_keyword_id);
sigmatch_table[ndpi_risk_keyword_id].name = "ndpi-risk";
sigmatch_table[ndpi_risk_keyword_id].desc = "match on the detected nDPI risk";
sigmatch_table[ndpi_risk_keyword_id].url = "/rules/ndpi-risk.html";
sigmatch_table[ndpi_risk_keyword_id].Match = DetectnDPIRiskPacketMatch;
sigmatch_table[ndpi_risk_keyword_id].Setup = DetectnDPIRiskSetup;
sigmatch_table[ndpi_risk_keyword_id].Free = DetectnDPIRiskFree;
sigmatch_table[ndpi_risk_keyword_id].flags =
(SIGMATCH_QUOTES_OPTIONAL | SIGMATCH_HANDLE_NEGATION);
}
static void NdpiInit(void)

@ -158,6 +158,7 @@ if HAVE_BINDGEN
--allowlist-function 'SC.*' \
--allowlist-var 'SC.*' \
--allowlist-var 'SIGMATCH.*' \
--allowlist-type 'DetectSigmatchListEnum' \
--opaque-type 'SCConfNode' \
--allowlist-type 'ThreadVars.?' \
--opaque-type 'ThreadVars.?' \

@ -635,6 +635,23 @@ extern "C" {
tv: *mut ThreadVars, p: *const Packet, f: *mut Flow, jb: *mut SCJsonBuilder,
);
}
impl DetectSigmatchListEnum {
pub const DETECT_SM_LIST_DYNAMIC_START: DetectSigmatchListEnum =
DetectSigmatchListEnum::DETECT_SM_LIST_MAX;
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum DetectSigmatchListEnum {
DETECT_SM_LIST_MATCH = 0,
DETECT_SM_LIST_PMATCH = 1,
DETECT_SM_LIST_BASE64_DATA = 2,
DETECT_SM_LIST_POSTMATCH = 3,
#[doc = "< post-detection tagging"]
DETECT_SM_LIST_TMATCH = 4,
DETECT_SM_LIST_SUPPRESS = 5,
DETECT_SM_LIST_THRESHOLD = 6,
DETECT_SM_LIST_MAX = 7,
}
extern "C" {
pub fn SCSigTablePreRegister(
KeywordsRegister: ::std::option::Option<unsafe extern "C" fn()>,
@ -886,6 +903,19 @@ extern "C" {
extern "C" {
pub fn SCDetectHelperKeywordRegister(kw: *const SCSigTableAppLiteElmt) -> u16;
}
extern "C" {
pub fn SCDetectHelperKeywordPacketMatchRegister(
kwid: u16,
Match: ::std::option::Option<
unsafe extern "C" fn(
arg1: *mut DetectEngineThreadCtx,
arg2: *mut Packet,
arg3: *const Signature,
arg4: *const SigMatchCtx,
) -> ::std::os::raw::c_int,
>,
);
}
extern "C" {
pub fn SCDetectHelperKeywordAliasRegister(kwid: u16, alias: *const ::std::os::raw::c_char);
}
@ -1027,11 +1057,25 @@ extern "C" {
extern "C" {
pub fn SCDetectGetLastSMFromLists(s: *const Signature, ...) -> *mut SigMatch;
}
extern "C" {
pub fn SCDetectSignatureGetLastSMByType(
s: *const Signature, list_id: ::std::os::raw::c_int, type_: u16,
) -> *const SigMatch;
}
extern "C" {
pub fn SCSigMatchGetPrevByType(sm: *const SigMatch, type_: u16) -> *const SigMatch;
}
extern "C" {
pub fn SCSigMatchGetCtx(sm: *const SigMatch) -> *const SigMatchCtx;
}
extern "C" {
pub fn SCDetectSignatureSetAppProto(
s: *mut Signature, alproto: AppProto,
) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn SCDetectSignatureIsNegated(s: *const Signature) -> bool;
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum SCError {
@ -1958,6 +2002,18 @@ extern "C" {
Free: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
) -> SCFlowStorageId;
}
extern "C" {
pub fn SCPacketGetIPProto(p: *const Packet) -> u8;
}
extern "C" {
pub fn SCPacketGetL3(p: *const Packet, len: *mut u32) -> *const u8;
}
extern "C" {
pub fn SCPacketGetFlow(p: *const Packet) -> *const Flow;
}
extern "C" {
pub fn SCPacketGetTimeAsParts(p: *const Packet, secs: *mut u64, usecs: *mut u64);
}
#[doc = " \\brief Function type for thread intialization callbacks.\n\n Once registered by SCThreadRegisterInitCallback, this function will\n be called for every thread being initialized during Suricata\n startup.\n\n \\param tv The ThreadVars struct that has just been initialized.\n \\param user The user data provided when registering the callback."]
pub type SCThreadInitCallbackFn = ::std::option::Option<
unsafe extern "C" fn(tv: *mut ThreadVars, user: *mut ::std::os::raw::c_void),

@ -386,6 +386,7 @@ noinst_HEADERS = \
output-streaming.h \
output-tx.h \
output.h \
packet-bindgen.h \
packet-queue.h \
packet.h \
pkt-var.h \

@ -125,15 +125,15 @@ int AlertFastLogger(ThreadVars *tv, void *data, const Packet *p)
char proto[16] = "";
const char *protoptr;
if (SCProtoNameValid(PacketGetIPProto(p))) {
protoptr = known_proto[PacketGetIPProto(p)];
if (SCProtoNameValid(SCPacketGetIPProto(p))) {
protoptr = known_proto[SCPacketGetIPProto(p)];
} else {
snprintf(proto, sizeof(proto), "PROTO:%03" PRIu32, PacketGetIPProto(p));
snprintf(proto, sizeof(proto), "PROTO:%03" PRIu32, SCPacketGetIPProto(p));
protoptr = proto;
}
uint16_t src_port_or_icmp = p->sp;
uint16_t dst_port_or_icmp = p->dp;
if (PacketGetIPProto(p) == IPPROTO_ICMP || PacketGetIPProto(p) == IPPROTO_ICMPV6) {
if (SCPacketGetIPProto(p) == IPPROTO_ICMP || SCPacketGetIPProto(p) == IPPROTO_ICMPV6) {
src_port_or_icmp = p->icmp_s.type;
dst_port_or_icmp = p->icmp_s.code;
}

@ -64,6 +64,8 @@
#include "flow-callbacks.h"
#include "flow-storage.h"
#include "packet-bindgen.h"
#include "thread-callbacks.h"
#include "thread-storage.h"

@ -32,6 +32,7 @@
#include "threadvars.h"
#include "util-debug.h"
#include "decode-events.h"
#include "packet-bindgen.h"
#include "util-exception-policy-types.h"
#include "util-datalink.h"
#ifdef PROFILING
@ -734,21 +735,6 @@ static inline IPV4Hdr *PacketSetIPV4(Packet *p, const uint8_t *buf)
return p->l3.hdrs.ip4h;
}
/* Retrieve proto regardless of IP version */
static inline uint8_t PacketGetIPProto(const Packet *p)
{
if (p->proto != 0) {
return p->proto;
}
if (PacketIsIPv4(p)) {
const IPV4Hdr *hdr = PacketGetIPv4(p);
return IPV4_GET_RAW_IPPROTO(hdr);
} else if (PacketIsIPv6(p)) {
return IPV6_GET_L4PROTO(p);
}
return 0;
}
static inline uint8_t PacketGetIPv4IPProto(const Packet *p)
{
if (PacketGetIPv4(p)) {

@ -137,7 +137,7 @@ static void DefragTrackerInit(DefragTracker *dt, Packet *p)
dt->id = IPV6_EXTHDR_GET_FH_ID(p);
dt->af = AF_INET6;
}
dt->proto = PacketGetIPProto(p);
dt->proto = SCPacketGetIPProto(p);
memcpy(&dt->vlan_id[0], &p->vlan_id[0], sizeof(dt->vlan_id));
dt->policy = DefragGetOsPolicy(p);
dt->host_timeout = DefragPolicyGetHostTimeout(p);
@ -430,7 +430,7 @@ static inline uint32_t DefragHashGetKey(Packet *p)
#define CMP_DEFRAGTRACKER(d1, d2, id) \
(((CMP_ADDR(&(d1)->src_addr, &(d2)->src) && CMP_ADDR(&(d1)->dst_addr, &(d2)->dst)) || \
(CMP_ADDR(&(d1)->src_addr, &(d2)->dst) && CMP_ADDR(&(d1)->dst_addr, &(d2)->src))) && \
(d1)->proto == PacketGetIPProto(d2) && (d1)->id == (id) && \
(d1)->proto == SCPacketGetIPProto(d2) && (d1)->id == (id) && \
(d1)->vlan_id[0] == (d2)->vlan_id[0] && (d1)->vlan_id[1] == (d2)->vlan_id[1] && \
(d1)->vlan_id[2] == (d2)->vlan_id[2])

@ -202,6 +202,18 @@ uint16_t SCDetectHelperKeywordRegister(const SCSigTableAppLiteElmt *kw)
return (uint16_t)keyword_id;
}
/**
* \brief Register a packet match callback for an existing keyword.
*
* Must be called during keyword initialization, after successfully registering
* the keyword with SCDetectHelperKeywordRegister().
*/
void SCDetectHelperKeywordPacketMatchRegister(uint16_t kwid,
int (*Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *))
{
sigmatch_table[kwid].Match = Match;
}
void SCDetectHelperKeywordAliasRegister(uint16_t kwid, const char *alias)
{
sigmatch_table[kwid].alias = alias;

@ -29,6 +29,8 @@
// type from flow.h with only forward declarations for bindgen
typedef struct Flow_ Flow;
// type from decode.h with only a forward declaration for bindgen
typedef struct Packet_ Packet;
// types from detect.h with only forward declarations for bindgen
// could be #ifndef SURICATA_BINDGEN_H #include "detect.h" #endif
typedef struct DetectEngineCtx_ DetectEngineCtx;
@ -79,6 +81,8 @@ typedef struct SCTransformTableElmt {
int SCDetectHelperNewKeywordId(void);
uint16_t SCDetectHelperKeywordRegister(const SCSigTableAppLiteElmt *kw);
void SCDetectHelperKeywordPacketMatchRegister(uint16_t kwid,
int (*Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *));
void SCDetectHelperKeywordAliasRegister(uint16_t kwid, const char *alias);
typedef struct SCJsonBuilder SCJsonBuilder;
void SCDetectHelperKeywordJsonInfoRegister(uint16_t kwid, void (*cb)(struct SCJsonBuilder *));

@ -1054,7 +1054,7 @@ void IPOnlyMatchPacket(ThreadVars *tv, const DetectEngineCtx *de_ctx,
continue;
}
if (DetectProtoContainsProto(s->proto, PacketGetIPProto(p)) == 0) {
if (DetectProtoContainsProto(s->proto, SCPacketGetIPProto(p)) == 0) {
SCLogDebug("proto didn't match");
continue;
}

@ -298,6 +298,35 @@ enum DetectKeywordId {
DETECT_TBLSIZE_STATIC,
};
/* holds the values for different possible lists in struct Signature.
* These codes are access points to particular lists in the array
* Signature->init_data->smlists[DETECT_SM_LIST_MAX]. */
enum DetectSigmatchListEnum {
/* list for non-payload per packet matches, e.g. ttl, flow keyword */
DETECT_SM_LIST_MATCH = 0,
/* list for payload and stream match */
DETECT_SM_LIST_PMATCH,
/* base64_data keyword uses some hardcoded logic so consider
* built-in
* TODO convert to inspect engine */
DETECT_SM_LIST_BASE64_DATA,
/* list for post match actions: flowbit set, flowint increment, etc */
DETECT_SM_LIST_POSTMATCH,
DETECT_SM_LIST_TMATCH, /**< post-detection tagging */
/* lists for alert thresholding and suppression */
DETECT_SM_LIST_SUPPRESS,
DETECT_SM_LIST_THRESHOLD,
DETECT_SM_LIST_MAX,
/* start of dynamically registered lists */
DETECT_SM_LIST_DYNAMIC_START = DETECT_SM_LIST_MAX,
};
extern int DETECT_TBLSIZE;
extern int DETECT_TBLSIZE_IDX;
// step for reallocating sigmatch_table

@ -737,6 +737,57 @@ SigMatch *DetectGetLastSMByListId(const Signature *s, int list_id, ...)
return sm_last;
}
/**
* \brief Get the last SigMatch of keyword \a type in list \a list_id.
*
* Lets a keyword Setup callback inspect earlier instances of a keyword in
* the signature being set up, together with SCSigMatchGetPrevByType() and
* SCSigMatchGetCtx(), without depending on the SigMatch layout.
*
* Only the static lists from DetectSigmatchListEnum are supported. A dynamic
* buffer list can have several instances in a signature, each with its own
* SigMatch chain, so there is no single list to walk.
*
* \param s signature being set up
* \param list_id static list to search, e.g. DETECT_SM_LIST_MATCH
* \param type keyword id, as returned by SCDetectHelperKeywordRegister()
*
* \retval sm last SigMatch of \a type in the list, or NULL if there is none
* or \a list_id is not a static list
*/
const SigMatch *SCDetectSignatureGetLastSMByType(const Signature *s, int list_id, uint16_t type)
{
DEBUG_VALIDATE_BUG_ON(list_id < 0 || list_id >= DETECT_SM_LIST_MAX);
if (list_id < 0 || list_id >= DETECT_SM_LIST_MAX)
return NULL;
return DetectGetLastSMByListId(s, list_id, type, -1);
}
/**
* \brief Get the previous SigMatch of keyword \a type before \a sm.
*
* \param sm SigMatch to search before, must not be NULL
* \param type keyword id
*
* \retval sm previous SigMatch of \a type in the same list, or NULL if there
* is none
*/
const SigMatch *SCSigMatchGetPrevByType(const SigMatch *sm, uint16_t type)
{
return SigMatchGetLastSMByType(sm->prev, type);
}
/**
* \brief Get the keyword context of \a sm, as passed to
* SCSigMatchAppendSMToList() by the keyword's Setup callback.
*
* \param sm SigMatch, must not be NULL
*/
const SigMatchCtx *SCSigMatchGetCtx(const SigMatch *sm)
{
return sm->ctx;
}
/**
* \brief Returns the sm with the largest index (added latest) from this sig
*
@ -2616,6 +2667,22 @@ int DetectSignatureSetMultiAppProto(Signature *s, const AppProto *alprotos)
return 0;
}
/**
* \brief Check if the keyword option being set up was negated.
*
* Only set for keywords registered with the SIGMATCH_HANDLE_NEGATION flag,
* in which case the leading '!' is stripped from the option value before it
* is passed to the keyword's Setup callback.
*
* \param s signature being set up
*
* \retval true if the option was prefixed with '!'
*/
bool SCDetectSignatureIsNegated(const Signature *s)
{
return s->init_data->negated;
}
int SCDetectSignatureSetAppProto(Signature *s, AppProto alproto)
{
if (!AppProtoIsValid(alproto)) {

@ -84,8 +84,12 @@ SigMatch *DetectGetLastSMFromMpmLists(const DetectEngineCtx *de_ctx, const Signa
SigMatch *SCDetectGetLastSMFromLists(const Signature *s, ...);
SigMatch *DetectGetLastSMByListPtr(const Signature *s, SigMatch *sm_list, ...);
SigMatch *DetectGetLastSMByListId(const Signature *s, int list_id, ...);
const SigMatch *SCDetectSignatureGetLastSMByType(const Signature *s, int list_id, uint16_t type);
const SigMatch *SCSigMatchGetPrevByType(const SigMatch *sm, uint16_t type);
const SigMatchCtx *SCSigMatchGetCtx(const SigMatch *sm);
int WARN_UNUSED SCDetectSignatureSetAppProto(Signature *s, AppProto alproto);
bool SCDetectSignatureIsNegated(const Signature *s);
int WARN_UNUSED DetectSignatureSetMultiAppProto(Signature *s, const AppProto *alprotos);
/* parse regex setup and free util funcs */

@ -316,7 +316,7 @@ const SigGroupHead *SigMatchSignaturesGetSgh(const DetectEngineCtx *de_ctx,
/* select the flow_gh */
const int dir = (p->flowflags & FLOW_PKT_TOCLIENT) == 0;
int proto = PacketGetIPProto(p);
int proto = SCPacketGetIPProto(p);
if (proto == IPPROTO_TCP) {
DetectPort *list = de_ctx->flow_gh[dir].tcp;
SCLogDebug("tcp toserver %p, tcp toclient %p: going to use %p", de_ctx->flow_gh[1].tcp,
@ -456,7 +456,7 @@ static inline void DetectRunGetRuleGroup(
bool use_flow_sgh = false;
/* Get the stored sgh from the flow (if any). Make sure we're not using
* the sgh for icmp error packets part of the same stream. */
if (PacketGetIPProto(p) == pflow->proto) { /* filter out icmp */
if (SCPacketGetIPProto(p) == pflow->proto) { /* filter out icmp */
PACKET_PROFILING_DETECT_START(p, PROF_DETECT_GETSGH);
if ((p->flowflags & FLOW_PKT_TOSERVER) && (pflow->flags & FLOW_SGH_TOSERVER)) {
sgh = pflow->sgh_toserver;
@ -551,7 +551,7 @@ static inline bool DetectRunInspectRuleHeader(
SCLogDebug("ip version didn't match");
return false;
}
if (DetectProtoContainsProto(s->proto, PacketGetIPProto(p)) == 0) {
if (DetectProtoContainsProto(s->proto, SCPacketGetIPProto(p)) == 0) {
SCLogDebug("proto didn't match");
if (PacketIsEthernet(p) &&
(s_proto_flags & (DETECT_PROTO_ETHERNET | DETECT_PROTO_ARP))) {

@ -110,35 +110,6 @@ extern const struct SignatureProperties signature_properties[SIG_TYPE_MAX];
-- Protocol
*/
/* holds the values for different possible lists in struct Signature.
* These codes are access points to particular lists in the array
* Signature->init_data->smlists[DETECT_SM_LIST_MAX]. */
enum DetectSigmatchListEnum {
/* list for non-payload per packet matches, e.g. ttl, flow keyword */
DETECT_SM_LIST_MATCH = 0,
/* list for payload and stream match */
DETECT_SM_LIST_PMATCH,
/* base64_data keyword uses some hardcoded logic so consider
* built-in
* TODO convert to inspect engine */
DETECT_SM_LIST_BASE64_DATA,
/* list for post match actions: flowbit set, flowint increment, etc */
DETECT_SM_LIST_POSTMATCH,
DETECT_SM_LIST_TMATCH, /**< post-detection tagging */
/* lists for alert thresholding and suppression */
DETECT_SM_LIST_SUPPRESS,
DETECT_SM_LIST_THRESHOLD,
DETECT_SM_LIST_MAX,
/* start of dynamically registered lists */
DETECT_SM_LIST_DYNAMIC_START = DETECT_SM_LIST_MAX,
};
/* used for Signature->list, which indicates which list
* we're adding keywords to in cases of sticky buffers like
* file_data */

@ -557,10 +557,10 @@ void JsonAddrInfoInit(const Packet *p, enum SCOutputJsonLogDirection dir, JsonAd
break;
}
if (SCProtoNameValid(PacketGetIPProto(p))) {
strlcpy(addr->proto, known_proto[PacketGetIPProto(p)], sizeof(addr->proto));
if (SCProtoNameValid(SCPacketGetIPProto(p))) {
strlcpy(addr->proto, known_proto[SCPacketGetIPProto(p)], sizeof(addr->proto));
} else {
snprintf(addr->proto, sizeof(addr->proto), "%" PRIu32, PacketGetIPProto(p));
snprintf(addr->proto, sizeof(addr->proto), "%" PRIu32, SCPacketGetIPProto(p));
}
}

@ -0,0 +1,29 @@
/* Copyright (C) 2026 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.
*/
#ifndef SURICATA_PACKET_BINDGEN_H
#define SURICATA_PACKET_BINDGEN_H
typedef struct Packet_ Packet;
typedef struct Flow_ Flow;
uint8_t SCPacketGetIPProto(const Packet *p);
const uint8_t *SCPacketGetL3(const Packet *p, uint32_t *len);
const Flow *SCPacketGetFlow(const Packet *p);
void SCPacketGetTimeAsParts(const Packet *p, uint64_t *secs, uint64_t *usecs);
#endif /* !SURICATA_PACKET_BINDGEN_H */

@ -16,6 +16,7 @@
*/
#include "packet.h"
#include "packet-bindgen.h"
#include "pkt-var.h"
#include "flow.h"
#include "host.h"
@ -209,3 +210,76 @@ inline void SCPacketSetSource(Packet *p, enum PktSrcEnum source)
{
p->pkt_src = (uint8_t)source;
}
/**
* \brief Get IP proto regardless of IP version.
*/
inline uint8_t SCPacketGetIPProto(const Packet *p)
{
if (p->proto != 0) {
return p->proto;
}
if (PacketIsIPv4(p)) {
const IPV4Hdr *hdr = PacketGetIPv4(p);
return IPV4_GET_RAW_IPPROTO(hdr);
} else if (PacketIsIPv6(p)) {
return IPV6_GET_L4PROTO(p);
}
return 0;
}
/**
* \brief Get the L3 packet data, starting at the L3 header.
*
* The returned data is borrowed from p and is valid only while its packet
* buffer remains valid and unchanged. For IPv4 and IPv6 the length comes
* from the IP header and includes the IPv6 base header. For ARP it is the
* fixed ARP header length. Trailing padding is excluded. The decoder has
* already validated the length against the captured packet length.
*
* \param p Packet to inspect, or NULL.
* \param len Non-NULL output pointer, set to zero when no data is returned.
* \retval NULL The packet is NULL or has no decoded L3 layer.
*/
const uint8_t *SCPacketGetL3(const Packet *p, uint32_t *len)
{
*len = 0;
if (p == NULL)
return NULL;
switch (p->l3.type) {
case PACKET_L3_IPV4: {
const IPV4Hdr *ip4h = PacketGetIPv4(p);
*len = IPV4_GET_RAW_IPLEN(ip4h);
return (const uint8_t *)ip4h;
}
case PACKET_L3_IPV6: {
const IPV6Hdr *ip6h = PacketGetIPv6(p);
*len = IPV6_HEADER_LEN + IPV6_GET_RAW_PLEN(ip6h);
return (const uint8_t *)ip6h;
}
case PACKET_L3_ARP:
*len = ARP_HEADER_LEN;
return (const uint8_t *)PacketGetARP(p);
case PACKET_L3_UNKNOWN:
break;
}
return NULL;
}
/**
* \brief Get the flow associated with the packet.
*/
const Flow *SCPacketGetFlow(const Packet *p)
{
return p == NULL ? NULL : p->flow;
}
/**
* \brief Get packet timestamp as individual values.
*/
void SCPacketGetTimeAsParts(const Packet *p, uint64_t *secs, uint64_t *usecs)
{
*secs = (uint64_t)SCTIME_SECS(p->ts);
*usecs = (uint64_t)SCTIME_USECS(p->ts);
}

@ -472,7 +472,7 @@ static TmEcode DecodePcapFile(ThreadVars *tv, Packet *p, void *data)
#ifdef DEBUG
BUG_ON(p->pkt_src != PKT_SRC_WIRE && p->pkt_src != PKT_SRC_FFR);
#endif
DEBUG_VALIDATE_BUG_ON(p->proto != PacketGetIPProto(p));
DEBUG_VALIDATE_BUG_ON(p->proto != SCPacketGetIPProto(p));
PacketDecodeFinalize(tv, dtv, p);

Loading…
Cancel
Save