Make signature address matching more cache efficient.

remotes/origin/master-1.0.x
Victor Julien 16 years ago
parent 1eec149f5e
commit 102092a89c

@ -1408,6 +1408,81 @@ int DetectAddressCmp(DetectAddress *a, DetectAddress *b)
return ADDRESS_ER;
}
/**
* \brief Match a packets address against a signatures addrs array
*
* \param addrs array of DetectMatchAddressIPv4's
* \param addrs_cnt array size in members
* \param a packets address
*
* \retval 0 no match
* \retval 1 match
*
* \note addresses in addrs are in host order
*
* \todo array should be ordered, so we can break out of the loop
*/
int DetectAddressMatchIPv4(DetectMatchAddressIPv4 *addrs, uint16_t addrs_cnt, Address *a) {
SCEnter();
if (addrs == NULL || addrs_cnt == 0) {
SCReturnInt(0);
}
uint16_t idx;
for (idx = 0; idx < addrs_cnt; idx++) {
if (ntohl(a->addr_data32[0]) >= addrs[idx].ip &&
ntohl(a->addr_data32[0]) <= addrs[idx].ip2)
{
SCReturnInt(1);
}
}
SCReturnInt(0);
}
/**
* \brief Match a packets address against a signatures addrs array
*
* \param addrs array of DetectMatchAddressIPv6's
* \param addrs_cnt array size in members
* \param a packets address
*
* \retval 0 no match
* \retval 1 match
*
* \note addresses in addrs are in host order
*
* \todo array should be ordered, so we can break out of the loop
*/
int DetectAddressMatchIPv6(DetectMatchAddressIPv6 *addrs, uint16_t addrs_cnt, Address *a) {
SCEnter();
if (addrs == NULL || addrs_cnt == 0) {
SCReturnInt(0);
}
uint16_t idx;
for (idx = 0; idx < addrs_cnt; idx++) {
if ((ntohl(a->addr_data32[0]) >= addrs[idx].ip[0] &&
ntohl(a->addr_data32[0]) <= addrs[idx].ip2[0]) &&
(ntohl(a->addr_data32[1]) >= addrs[idx].ip[1] &&
ntohl(a->addr_data32[1]) <= addrs[idx].ip2[1]) &&
(ntohl(a->addr_data32[2]) >= addrs[idx].ip[2] &&
ntohl(a->addr_data32[2]) <= addrs[idx].ip2[2]) &&
(ntohl(a->addr_data32[3]) >= addrs[idx].ip[3] &&
ntohl(a->addr_data32[3]) <= addrs[idx].ip2[3]))
{
SCReturnInt(1);
}
}
SCReturnInt(0);
}
/**
* \brief Check if a particular address(ipv4 or ipv6) matches the address
* range in the DetectAddress instance.

@ -51,4 +51,6 @@ DetectAddress *DetectAddressCopy(DetectAddress *);
void DetectAddressPrint(DetectAddress *);
int DetectAddressCmp(DetectAddress *, DetectAddress *);
int DetectAddressMatchIPv4(DetectMatchAddressIPv4 *, uint16_t, Address *);
int DetectAddressMatchIPv6(DetectMatchAddressIPv6 *, uint16_t, Address *);
#endif /* __DETECT_ADDRESS_H__ */

@ -1057,11 +1057,128 @@ void SigFree(Signature *s) {
if (s->msg != NULL)
SCFree(s->msg);
if (s->addr_src_match4 != NULL) {
SCFree(s->addr_src_match4);
}
if (s->addr_dst_match4 != NULL) {
SCFree(s->addr_dst_match4);
}
if (s->addr_src_match6 != NULL) {
SCFree(s->addr_src_match6);
}
if (s->addr_dst_match6 != NULL) {
SCFree(s->addr_dst_match6);
}
SigRefFree(s);
SCFree(s);
}
/**
* \internal
* \brief build address match array for cache efficient matching
*
* \param s the signature
*/
static void SigBuildAddressMatchArray(Signature *s) {
/* source addresses */
uint16_t cnt = 0;
uint16_t idx = 0;
DetectAddress *da = s->src.ipv4_head;
for ( ; da != NULL; da = da->next) {
cnt++;
}
if (cnt > 0) {
s->addr_src_match4 = SCMalloc(cnt * sizeof(DetectMatchAddressIPv4));
if (s->addr_src_match4 == NULL) {
exit(EXIT_FAILURE);
}
for (da = s->src.ipv4_head; da != NULL; da = da->next) {
s->addr_src_match4[idx].ip = ntohl(da->ip.addr_data32[0]);
s->addr_src_match4[idx].ip2 = ntohl(da->ip2.addr_data32[0]);
idx++;
}
s->addr_src_match4_cnt = cnt;
}
/* destination addresses */
cnt = 0;
idx = 0;
da = s->dst.ipv4_head;
for ( ; da != NULL; da = da->next) {
cnt++;
}
if (cnt > 0) {
s->addr_dst_match4 = SCMalloc(cnt * sizeof(DetectMatchAddressIPv4));
if (s->addr_dst_match4 == NULL) {
exit(EXIT_FAILURE);
}
for (da = s->dst.ipv4_head; da != NULL; da = da->next) {
s->addr_dst_match4[idx].ip = ntohl(da->ip.addr_data32[0]);
s->addr_dst_match4[idx].ip2 = ntohl(da->ip2.addr_data32[0]);
idx++;
}
s->addr_dst_match4_cnt = cnt;
}
/* source addresses IPv6 */
cnt = 0;
idx = 0;
da = s->src.ipv6_head;
for ( ; da != NULL; da = da->next) {
cnt++;
}
if (cnt > 0) {
s->addr_src_match6 = SCMalloc(cnt * sizeof(DetectMatchAddressIPv6));
if (s->addr_src_match6 == NULL) {
exit(EXIT_FAILURE);
}
for (da = s->src.ipv6_head; da != NULL; da = da->next) {
s->addr_src_match6[idx].ip[0] = ntohl(da->ip.addr_data32[0]);
s->addr_src_match6[idx].ip[1] = ntohl(da->ip.addr_data32[1]);
s->addr_src_match6[idx].ip[2] = ntohl(da->ip.addr_data32[2]);
s->addr_src_match6[idx].ip[3] = ntohl(da->ip.addr_data32[3]);
s->addr_src_match6[idx].ip2[0] = ntohl(da->ip2.addr_data32[0]);
s->addr_src_match6[idx].ip2[1] = ntohl(da->ip2.addr_data32[1]);
s->addr_src_match6[idx].ip2[2] = ntohl(da->ip2.addr_data32[2]);
s->addr_src_match6[idx].ip2[3] = ntohl(da->ip2.addr_data32[3]);
idx++;
}
s->addr_src_match6_cnt = cnt;
}
/* destination addresses IPv6 */
cnt = 0;
idx = 0;
da = s->dst.ipv6_head;
for ( ; da != NULL; da = da->next) {
cnt++;
}
if (cnt > 0) {
s->addr_dst_match6 = SCMalloc(cnt * sizeof(DetectMatchAddressIPv6));
if (s->addr_dst_match6 == NULL) {
exit(EXIT_FAILURE);
}
for (da = s->dst.ipv6_head; da != NULL; da = da->next) {
s->addr_dst_match6[idx].ip[0] = ntohl(da->ip.addr_data32[0]);
s->addr_dst_match6[idx].ip[1] = ntohl(da->ip.addr_data32[1]);
s->addr_dst_match6[idx].ip[2] = ntohl(da->ip.addr_data32[2]);
s->addr_dst_match6[idx].ip[3] = ntohl(da->ip.addr_data32[3]);
s->addr_dst_match6[idx].ip2[0] = ntohl(da->ip2.addr_data32[0]);
s->addr_dst_match6[idx].ip2[1] = ntohl(da->ip2.addr_data32[1]);
s->addr_dst_match6[idx].ip2[2] = ntohl(da->ip2.addr_data32[2]);
s->addr_dst_match6[idx].ip2[3] = ntohl(da->ip2.addr_data32[3]);
idx++;
}
s->addr_dst_match6_cnt = cnt;
}
}
/**
* \brief Parses a signature and adds it to the Detection Engine Context
* This function is going to be deprecated. Should use DetectEngineAppendSig()
@ -1179,6 +1296,8 @@ Signature *SigInit(DetectEngineCtx *de_ctx, char *sigstr) {
sig->id, sig->flags & SIG_FLAG_APPLAYER ? "set" : "not set",
sig->flags & SIG_FLAG_PACKET ? "set" : "not set");
SigBuildAddressMatchArray(sig);
SCReturnPtr(sig, "Signature");
error:
@ -1355,6 +1474,8 @@ Signature *SigInitReal(DetectEngineCtx *de_ctx, char *sigstr) {
if (sig->amatch)
sig->flags |= SIG_FLAG_AMATCH;
SigBuildAddressMatchArray(sig);
SCLogDebug("sig %"PRIu32" SIG_FLAG_APPLAYER: %s, SIG_FLAG_PACKET: %s",
sig->id, sig->flags & SIG_FLAG_APPLAYER ? "set" : "not set",
sig->flags & SIG_FLAG_PACKET ? "set" : "not set");

@ -856,18 +856,22 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
/* check the destination address */
if (!(s->flags & SIG_FLAG_DST_ANY)) {
DetectAddress *daddr = DetectAddressLookupInHead(&s->dst,&p->dst);
if (daddr == NULL) {
SCLogDebug("dst addr didn't match.");
goto next;
if (PKT_IS_IPV4(p)) {
if (DetectAddressMatchIPv4(s->addr_dst_match4, s->addr_dst_match4_cnt, &p->dst) == 0)
goto next;
} else if (PKT_IS_IPV6(p)) {
if (DetectAddressMatchIPv6(s->addr_dst_match6, s->addr_dst_match6_cnt, &p->dst) == 0)
goto next;
}
}
/* check the source address */
if (!(s->flags & SIG_FLAG_SRC_ANY)) {
DetectAddress *saddr = DetectAddressLookupInHead(&s->src,&p->src);
if (saddr == NULL) {
SCLogDebug("src addr didn't match.");
goto next;
if (PKT_IS_IPV4(p)) {
if (DetectAddressMatchIPv4(s->addr_src_match4, s->addr_src_match4_cnt, &p->src) == 0)
goto next;
} else if (PKT_IS_IPV6(p)) {
if (DetectAddressMatchIPv6(s->addr_src_match6, s->addr_src_match6_cnt, &p->src) == 0)
goto next;
}
}

@ -135,6 +135,16 @@ typedef struct DetectAddressHead_ {
DetectAddress *ipv6_head;
} DetectAddressHead;
typedef struct DetectMatchAddressIPv4_ {
uint32_t ip; /**< address in host order, start of range */
uint32_t ip2; /**< address in host order, end of range */
} DetectMatchAddressIPv4;
typedef struct DetectMatchAddressIPv6_ {
uint32_t ip[4];
uint32_t ip2[4];
} DetectMatchAddressIPv6;
/*
* DETECT PORT
*/
@ -253,8 +263,17 @@ typedef struct Signature_ {
SigIntId num; /**< signature number, internal id */
/** address settings for this signature */
DetectAddressHead src, dst;
/** ipv4 match arrays */
DetectMatchAddressIPv4 *addr_dst_match4;
uint16_t addr_dst_match4_cnt;
DetectMatchAddressIPv4 *addr_src_match4;
uint16_t addr_src_match4_cnt;
/** ipv6 match arrays */
DetectMatchAddressIPv6 *addr_dst_match6;
uint16_t addr_dst_match6_cnt;
DetectMatchAddressIPv6 *addr_src_match6;
uint16_t addr_src_match6_cnt;
/** port settings for this signature */
DetectPort *sp, *dp;
@ -321,6 +340,9 @@ typedef struct Signature_ {
#ifdef PROFILING
uint16_t profiling_id;
#endif
/** address settings for this signature */
DetectAddressHead src, dst;
} Signature;
typedef struct DetectEngineIPOnlyThreadCtx_ {

Loading…
Cancel
Save