diff --git a/src/detect-engine-address.c b/src/detect-engine-address.c index 3c8974f491..dfa12842e9 100644 --- a/src/detect-engine-address.c +++ b/src/detect-engine-address.c @@ -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. diff --git a/src/detect-engine-address.h b/src/detect-engine-address.h index fd10cde254..ab83716a10 100644 --- a/src/detect-engine-address.h +++ b/src/detect-engine-address.h @@ -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__ */ diff --git a/src/detect-parse.c b/src/detect-parse.c index 54ceddba3f..5d28875c5f 100644 --- a/src/detect-parse.c +++ b/src/detect-parse.c @@ -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"); diff --git a/src/detect.c b/src/detect.c index 595d516149..5923331c09 100644 --- a/src/detect.c +++ b/src/detect.c @@ -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; } } diff --git a/src/detect.h b/src/detect.h index 73cb160a02..bfcdecfce8 100644 --- a/src/detect.h +++ b/src/detect.h @@ -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_ {