Large update to the detection engine. Greatly improve initialization speed and memory usage.

remotes/origin/master-1.0.x
Victor Julien 18 years ago
parent b1a13c89bd
commit eb1c4e4987

@ -11,6 +11,7 @@
#include "util-unittest.h"
#include "detect-address.h"
#include "detect-siggroup.h"
int DetectAddressCmpIPv4(DetectAddressData *a, DetectAddressData *b) {
u_int32_t a_ip1 = ntohl(a->ip[0]);
@ -30,13 +31,13 @@ int DetectAddressCmpIPv4(DetectAddressData *a, DetectAddressData *b) {
} else if (a_ip1 <= b_ip1 && a_ip2 >= b_ip2) {
//printf("ADDRESS_EB\n");
return ADDRESS_EB;
} else if (a_ip1 < b_ip1 && a_ip2 < b_ip2 && a_ip2 > b_ip1) {
} else if (a_ip1 < b_ip1 && a_ip2 < b_ip2 && a_ip2 >= b_ip1) {
//printf("ADDRESS_LE\n");
return ADDRESS_LE;
} else if (a_ip1 < b_ip1 && a_ip2 < b_ip2) {
//printf("ADDRESS_LT\n");
return ADDRESS_LT;
} else if (a_ip1 > b_ip1 && a_ip1 < b_ip2 && a_ip2 > b_ip2) {
} else if (a_ip1 > b_ip1 && a_ip1 <= b_ip2 && a_ip2 > b_ip2) {
//printf("ADDRESS_GE\n");
return ADDRESS_GE;
} else if (a_ip1 > b_ip2) {
@ -44,12 +45,359 @@ int DetectAddressCmpIPv4(DetectAddressData *a, DetectAddressData *b) {
return ADDRESS_GT;
} else {
/* should be unreachable */
printf("Internal Error: should be unreachable\n");
//printf("Internal Error: should be unreachable\n");
}
return ADDRESS_ER;
}
//#define DBG
/* Cut groups and merge sigs
*
* a = 1.2.3.4, b = 1.2.3.4-1.2.3.5
* must result in: a == 1.2.3.4, b == 1.2.3.5, c == NULL
*
* a = 1.2.3.4, b = 1.2.3.3-1.2.3.5
* must result in: a == 1.2.3.3, b == 1.2.3.4, c == 1.2.3.5
*
* a = 1.2.3.0/24 b = 1.2.3.128-1.2.4.10
* must result in: a == 1.2.3.0/24, b == 1.2.4.0-1.2.4.10, c == NULL
*
* a = 1.2.3.4, b = 1.2.3.0/24
* must result in: a == 1.2.3.0-1.2.3.3, b == 1.2.3.4, c == 1.2.3.5-1.2.3.255
*/
int DetectAddressGroupCutIPv4(DetectAddressGroup *a, DetectAddressGroup *b, DetectAddressGroup **c) {
u_int32_t a_ip1 = ntohl(a->ad->ip[0]);
u_int32_t a_ip2 = ntohl(a->ad->ip2[0]);
u_int32_t b_ip1 = ntohl(b->ad->ip[0]);
u_int32_t b_ip2 = ntohl(b->ad->ip2[0]);
/* default to NULL */
*c = NULL;
#ifdef DBG
printf("a "); DetectAddressDataPrint(a->ad); printf("\n");
printf("b "); DetectAddressDataPrint(b->ad); printf("\n");
printf("a sigs: ");
SigGroupContainer *sgc = a->sh ? a->sh->head : NULL;
for ( ; sgc != NULL; sgc = sgc->next) printf("%u ",sgc->s->id);
printf("\nb sigs: ");
sgc = b->sh ? b->sh->head : NULL;
for ( ; sgc != NULL; sgc = sgc->next) printf("%u ",sgc->s->id);
printf("\n");
#endif
int r = DetectAddressCmpIPv4(a->ad,b->ad);
if (r != ADDRESS_ES && r != ADDRESS_EB && r != ADDRESS_LE && r != ADDRESS_GE) {
printf("we shouldn't be here\n");
goto error;
}
/* get a place to temporary put sigs lists */
DetectAddressGroup *tmp;
tmp = DetectAddressGroupInit();
if (tmp == NULL) {
goto error;
}
memset(tmp,0,sizeof(DetectAddressGroup));
/* we have 3 parts: [aaa[abab]bbb]
* part a: a_ip1 <-> b_ip1 - 1
* part b: b_ip1 <-> a_ip2
* part c: a_ip2 + 1 <-> b_ip2
*/
if (r == ADDRESS_LE) {
#ifdef DBG
printf("cut r == ADDRESS_LE\n");
#endif
a->ad->ip[0] = htonl(a_ip1);
a->ad->ip2[0] = htonl(b_ip1 - 1);
b->ad->ip[0] = htonl(b_ip1);
b->ad->ip2[0] = htonl(a_ip2);
DetectAddressGroup *tmp_c;
tmp_c = DetectAddressGroupInit();
if (tmp_c == NULL) {
goto error;
}
tmp_c->ad = DetectAddressDataInit();
if (tmp_c->ad == NULL) {
goto error;
}
tmp_c->ad->family = AF_INET;
tmp_c->ad->ip[0] = htonl(a_ip2 + 1);
tmp_c->ad->ip2[0] = htonl(b_ip2);
*c = tmp_c;
SigGroupListCopyAppend(b,tmp_c); /* copy old b to c */
SigGroupListCopyPrepend(a,b); /* copy old b to a */
#ifdef DBG
SigGroupContainer *sg;
printf("A "); DetectAddressDataPrint(a->ad); printf(" ");
for(sg = a->sh ? a->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u ", sg->s->id); printf("\n");
printf("B "); DetectAddressDataPrint(b->ad); printf(" ");
for(sg = b->sh ? b->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u ", sg->s->id); printf("\n");
printf("C "); DetectAddressDataPrint(tmp_c->ad); printf(" ");
for(sg = tmp_c->sh ? b->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u ", sg->s->id); printf("\n\n");
#endif
/* we have 3 parts: [bbb[baba]aaa]
* part a: b_ip1 <-> a_ip1 - 1
* part b: a_ip1 <-> b_ip2
* part c: b_ip2 + 1 <-> a_ip2
*/
} else if (r == ADDRESS_GE) {
#ifdef DBG
printf("cut r == ADDRESS_GE\n");
#endif
a->ad->ip[0] = htonl(b_ip1);
a->ad->ip2[0] = htonl(a_ip1 - 1);
b->ad->ip[0] = htonl(a_ip1);
b->ad->ip2[0] = htonl(b_ip2);
DetectAddressGroup *tmp_c;
tmp_c = DetectAddressGroupInit();
if (tmp_c == NULL) {
goto error;
}
tmp_c->ad = DetectAddressDataInit();
if (tmp_c->ad == NULL) {
goto error;
}
tmp_c->ad->family = AF_INET;
tmp_c->ad->ip[0] = htonl(b_ip2 + 1);
tmp_c->ad->ip2[0] = htonl(a_ip2);
*c = tmp_c;
/* 'a' gets clean and then 'b' sigs
* 'b' gets clean, then 'a' then 'b' sigs
* 'c' gets 'a' sigs */
SigGroupListCopyAppend(a,tmp); /* store old a list */
SigGroupListClean(a->sh); /* clean a list */
SigGroupListCopyAppend(tmp,tmp_c); /* copy old b to c */
SigGroupListCopyAppend(b,a); /* copy old b to a */
SigGroupListCopyPrepend(tmp,b); /* prepend old a before b */
SigGroupListClean(tmp->sh); /* clean tmp list */
/* we have 2 or three parts:
*
* 2 part: [[abab]bbb] or [bbb[baba]]
* part a: a_ip1 <-> a_ip2
* part b: a_ip2 + 1 <-> b_ip2
*
* part a: b_ip1 <-> a_ip1 - 1
* part b: a_ip1 <-> a_ip2
*
* 3 part [bbb[aaa]bbb]
* becomes[aaa[bbb]ccc]
*
* part a: b_ip1 <-> a_ip1 - 1
* part b: a_ip1 <-> a_ip2
* part c: a_ip2 + 1 <-> b_ip2
*/
} else if (r == ADDRESS_ES) {
#ifdef DBG
printf("cut r == ADDRESS_ES\n");
#endif
if (a_ip1 == b_ip1) {
#ifdef DBG
printf("1\n");
#endif
a->ad->ip[0] = htonl(a_ip1);
a->ad->ip2[0] = htonl(a_ip2);
b->ad->ip[0] = htonl(a_ip2 + 1);
b->ad->ip2[0] = htonl(b_ip2);
/* 'b' overlaps 'a' so 'a' needs the 'b' sigs */
SigGroupListCopyAppend(b,a);
#ifdef DBG
SigGroupContainer *sg;
printf("A "); DetectAddressDataPrint(a->ad); printf(" ");
for(sg = a->sh ? a->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u ", sg->s->id); printf("\n");
printf("B "); DetectAddressDataPrint(b->ad); printf(" ");
for(sg = b->sh ? b->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u ", sg->s->id); printf("\n\n");
#endif
} else if (a_ip2 == b_ip2) {
#ifdef DBG
printf("2\n");
#endif
a->ad->ip[0] = htonl(b_ip1);
a->ad->ip2[0] = htonl(a_ip1 - 1);
b->ad->ip[0] = htonl(a_ip1);
b->ad->ip2[0] = htonl(a_ip2);
/* 'a' overlaps 'b' so a needs the 'a' sigs */
SigGroupListCopyPrepend(a,b);
#ifdef DBG
SigGroupContainer *sg;
printf("A "); DetectAddressDataPrint(a->ad); printf(" ");
for(sg = a->sh ? a->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u ", sg->s->id); printf("\n");
printf("B "); DetectAddressDataPrint(b->ad); printf(" ");
for(sg = b->sh ? b->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u ", sg->s->id); printf("\n\n");
#endif
} else {
#ifdef DBG
printf("3\n");
#endif
a->ad->ip[0] = htonl(b_ip1);
a->ad->ip2[0] = htonl(a_ip1 - 1);
b->ad->ip[0] = htonl(a_ip1);
b->ad->ip2[0] = htonl(a_ip2);
DetectAddressGroup *tmp_c;
tmp_c = DetectAddressGroupInit();
if (tmp_c == NULL) {
goto error;
}
tmp_c->ad = DetectAddressDataInit();
if (tmp_c->ad == NULL) {
goto error;
}
tmp_c->ad->family = AF_INET;
tmp_c->ad->ip[0] = htonl(a_ip2 + 1);
tmp_c->ad->ip2[0] = htonl(b_ip2);
*c = tmp_c;
/* 'a' gets clean and then 'b' sigs
* 'b' gets clean, then 'a' then 'b' sigs
* 'c' gets 'b' sigs */
SigGroupListCopyAppend(a,tmp); /* store old a list */
SigGroupListClean(a->sh); /* clean a list */
SigGroupListCopyAppend(b,tmp_c); /* copy old b to c */
SigGroupListCopyAppend(b,a); /* copy old b to a */
SigGroupListCopyPrepend(tmp,b); /* prepend old a before b */
SigGroupListClean(tmp->sh); /* clean tmp list */
#ifdef DBG
SigGroupContainer *sg;
printf("A "); DetectAddressDataPrint(a->ad); printf(" ");
for(sg = a->sh ? a->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u ", sg->s->id); printf("\n");
printf("B "); DetectAddressDataPrint(b->ad); printf(" ");
for(sg = b->sh ? b->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u ", sg->s->id); printf("\n");
printf("C "); DetectAddressDataPrint(tmp_c->ad); printf(" ");
for(sg = tmp_c->sh ? b->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u ", sg->s->id); printf("\n\n");
#endif
}
/* we have 2 or three parts:
*
* 2 part: [[baba]aaa] or [aaa[abab]]
* part a: b_ip1 <-> b_ip2
* part b: b_ip2 + 1 <-> a_ip2
*
* part a: a_ip1 <-> b_ip1 - 1
* part b: b_ip1 <-> b_ip2
*
* 3 part [aaa[bbb]aaa]
* becomes[aaa[bbb]ccc]
*
* part a: a_ip1 <-> b_ip2 - 1
* part b: b_ip1 <-> b_ip2
* part c: b_ip2 + 1 <-> a_ip2
*/
} else if (r == ADDRESS_EB) {
#ifdef DBG
printf("cut r == ADDRESS_EB\n");
#endif
if (a_ip1 == b_ip1) {
#ifdef DBG
printf("1\n");
#endif
a->ad->ip[0] = htonl(b_ip1);
a->ad->ip2[0] = htonl(b_ip2);
b->ad->ip[0] = htonl(b_ip2 + 1);
b->ad->ip2[0] = htonl(a_ip2);
/* 'b' overlaps 'a' so a needs the 'b' sigs */
SigGroupListCopyAppend(b,tmp);
SigGroupListClean(b->sh);
SigGroupListCopyAppend(a,b);
SigGroupListCopyAppend(tmp,a);
SigGroupListClean(tmp->sh);
#ifdef DBG
SigGroupContainer *sg;
printf("A "); DetectAddressDataPrint(a->ad); printf(" ");
for(sg = a->sh ? a->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u ", sg->s->id); printf("\n");
printf("B "); DetectAddressDataPrint(b->ad); printf(" ");
for(sg = b->sh ? b->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u ", sg->s->id); printf("\n\n");
#endif
} else if (a_ip2 == b_ip2) {
#ifdef DBG
printf("2\n");
#endif
a->ad->ip[0] = htonl(a_ip1);
a->ad->ip2[0] = htonl(b_ip1 - 1);
b->ad->ip[0] = htonl(b_ip1);
b->ad->ip2[0] = htonl(b_ip2);
/* 'a' overlaps 'b' so a needs the 'a' sigs */
SigGroupListCopyPrepend(a,b);
#ifdef DBG
SigGroupContainer *sg;
printf("A "); DetectAddressDataPrint(a->ad); printf(" ");
for(sg = a->sh ? a->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u ", sg->s->id); printf("\n");
printf("B "); DetectAddressDataPrint(b->ad); printf(" ");
for(sg = b->sh ? b->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u ", sg->s->id); printf("\n\n");
#endif
} else {
#ifdef DBG
printf("3\n");
#endif
a->ad->ip[0] = htonl(a_ip1);
a->ad->ip2[0] = htonl(b_ip1 - 1);
b->ad->ip[0] = htonl(b_ip1);
b->ad->ip2[0] = htonl(b_ip2);
DetectAddressGroup *tmp_c;
tmp_c = DetectAddressGroupInit();
if (tmp_c == NULL) {
goto error;
}
tmp_c->ad = DetectAddressDataInit();
if (tmp_c->ad == NULL) {
goto error;
}
tmp_c->ad->family = AF_INET;
tmp_c->ad->ip[0] = htonl(b_ip2 + 1);
tmp_c->ad->ip2[0] = htonl(a_ip2);
*c = tmp_c;
/* 'a' stays the same wrt sigs
* 'b' keeps it's own sigs and gets a's sigs prepended
* 'c' gets 'a' sigs */
SigGroupListCopyPrepend(a,b);
SigGroupListCopyAppend(a,tmp_c);
#ifdef DBG
SigGroupContainer *sg;
printf("A "); DetectAddressDataPrint(a->ad); printf(" ");
for(sg = a->sh ? a->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u ", sg->s->id); printf("\n");
printf("B "); DetectAddressDataPrint(b->ad); printf(" ");
for(sg = b->sh ? b->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u ", sg->s->id); printf("\n");
printf("C "); DetectAddressDataPrint(tmp_c->ad); printf(" ");
for(sg = tmp_c->sh ? b->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u ", sg->s->id); printf("\n\n");
#endif
}
}
/* XXX free tmp */
DetectAddressGroupFree(tmp);
return 0;
error:
/* XXX free tmp */
DetectAddressGroupFree(tmp);
return -1;
}
/* a = 1.2.3.4, b = 1.2.3.4-1.2.3.5
* must result in: a == 1.2.3.4, b == 1.2.3.5, c == NULL
*

@ -10,5 +10,7 @@ int DetectAddressCmpIPv4(DetectAddressData *, DetectAddressData *);
int DetectAddressCutIPv4(DetectAddressData *, DetectAddressData *, DetectAddressData **);
int DetectAddressCutNotIPv4(DetectAddressData *, DetectAddressData **);
int DetectAddressGroupCutIPv4(DetectAddressGroup *, DetectAddressGroup *, DetectAddressGroup **);
#endif /* __DETECT_ADDRESS_IPV4_H__ */

@ -11,6 +11,7 @@
#include "util-unittest.h"
#include "detect-address.h"
#include "detect-siggroup.h"
/* return: 1 lt, 0 not lt */
@ -94,7 +95,7 @@ int DetectAddressCmpIPv6(DetectAddressData *a, DetectAddressData *b) {
return ADDRESS_EB;
} else if (AddressIPv6Lt(a->ip, b->ip) == 1 &&
AddressIPv6Lt(a->ip2, b->ip2) == 1 &&
AddressIPv6Gt(a->ip2, b->ip) == 1) {
AddressIPv6Ge(a->ip2, b->ip) == 1) {
//printf("ADDRESS_LE\n");
return ADDRESS_LE;
} else if (AddressIPv6Lt(a->ip, b->ip) == 1 &&
@ -102,7 +103,7 @@ int DetectAddressCmpIPv6(DetectAddressData *a, DetectAddressData *b) {
//printf("ADDRESS_LT\n");
return ADDRESS_LT;
} else if (AddressIPv6Gt(a->ip, b->ip) == 1 &&
AddressIPv6Lt(a->ip, b->ip2) == 1 &&
AddressIPv6Le(a->ip, b->ip2) == 1 &&
AddressIPv6Gt(a->ip2, b->ip2) == 1) {
//printf("ADDRESS_GE\n");
return ADDRESS_GE;
@ -186,6 +187,237 @@ static void AddressCutIPv6Copy(u_int32_t *a, u_int32_t *b) {
b[3] = htonl(a[3]);
}
int DetectAddressGroupCutIPv6(DetectAddressGroup *a, DetectAddressGroup *b, DetectAddressGroup **c) {
u_int32_t a_ip1[4] = { ntohl(a->ad->ip[0]), ntohl(a->ad->ip[1]),
ntohl(a->ad->ip[2]), ntohl(a->ad->ip[3]) };
u_int32_t a_ip2[4] = { ntohl(a->ad->ip2[0]), ntohl(a->ad->ip2[1]),
ntohl(a->ad->ip2[2]), ntohl(a->ad->ip2[3]) };
u_int32_t b_ip1[4] = { ntohl(b->ad->ip[0]), ntohl(b->ad->ip[1]),
ntohl(b->ad->ip[2]), ntohl(b->ad->ip[3]) };
u_int32_t b_ip2[4] = { ntohl(b->ad->ip2[0]), ntohl(b->ad->ip2[1]),
ntohl(b->ad->ip2[2]), ntohl(b->ad->ip2[3]) };
/* default to NULL */
*c = NULL;
int r = DetectAddressCmpIPv6(a->ad,b->ad);
if (r != ADDRESS_ES && r != ADDRESS_EB && r != ADDRESS_LE && r != ADDRESS_GE) {
goto error;
}
/* get a place to temporary put sigs lists */
DetectAddressGroup *tmp;
tmp = DetectAddressGroupInit();
if (tmp == NULL) {
goto error;
}
memset(tmp,0,sizeof(DetectAddressGroup));
/* we have 3 parts: [aaa[abab]bbb]
* part a: a_ip1 <-> b_ip1 - 1
* part b: b_ip1 <-> a_ip2
* part c: a_ip2 + 1 <-> b_ip2
*/
if (r == ADDRESS_LE) {
AddressCutIPv6Copy(a_ip1, a->ad->ip);
AddressCutIPv6CopySubOne(b_ip1, a->ad->ip2);
AddressCutIPv6Copy(b_ip1, b->ad->ip);
AddressCutIPv6Copy(a_ip2, b->ad->ip2);
DetectAddressGroup *tmp_c;
tmp_c = DetectAddressGroupInit();
if (tmp_c == NULL) {
goto error;
}
tmp_c->ad = DetectAddressDataInit();
if (tmp_c->ad == NULL) {
goto error;
}
tmp_c->ad->family = AF_INET6;
AddressCutIPv6CopyAddOne(a_ip2, tmp_c->ad->ip);
AddressCutIPv6Copy(b_ip2, tmp_c->ad->ip2);
*c = tmp_c;
SigGroupListCopyAppend(b,tmp_c); /* copy old b to c */
SigGroupListCopyPrepend(a,b); /* copy old b to a */
/* we have 3 parts: [bbb[baba]aaa]
* part a: b_ip1 <-> a_ip1 - 1
* part b: a_ip1 <-> b_ip2
* part c: b_ip2 + 1 <-> a_ip2
*/
} else if (r == ADDRESS_GE) {
AddressCutIPv6Copy(b_ip1, a->ad->ip);
AddressCutIPv6CopySubOne(a_ip1, a->ad->ip2);
AddressCutIPv6Copy(a_ip1, b->ad->ip);
AddressCutIPv6Copy(b_ip2, b->ad->ip2);
DetectAddressGroup *tmp_c;
tmp_c = DetectAddressGroupInit();
if (tmp_c == NULL) {
goto error;
}
tmp_c->ad = DetectAddressDataInit();
if (tmp_c->ad == NULL) {
goto error;
}
tmp_c->ad->family = AF_INET6;
AddressCutIPv6CopyAddOne(b_ip2, tmp_c->ad->ip);
AddressCutIPv6Copy(a_ip2, tmp_c->ad->ip2);
*c = tmp_c;
/* 'a' gets clean and then 'b' sigs
* 'b' gets clean, then 'a' then 'b' sigs
* 'c' gets 'a' sigs */
SigGroupListCopyAppend(a,tmp); /* store old a list */
SigGroupListClean(a->sh); /* clean a list */
SigGroupListCopyAppend(tmp,tmp_c); /* copy old b to c */
SigGroupListCopyAppend(b,a); /* copy old b to a */
SigGroupListCopyPrepend(tmp,b); /* prepend old a before b */
SigGroupListClean(tmp->sh); /* clean tmp list */
/* we have 2 or three parts:
*
* 2 part: [[abab]bbb] or [bbb[baba]]
* part a: a_ip1 <-> a_ip2
* part b: a_ip2 + 1 <-> b_ip2
*
* part a: b_ip1 <-> a_ip1 - 1
* part b: a_ip1 <-> a_ip2
*
* 3 part [bbb[aaa]bbb]
* part a: b_ip1 <-> a_ip1 - 1
* part b: a_ip1 <-> a_ip2
* part c: a_ip2 + 1 <-> b_ip2
*/
} else if (r == ADDRESS_ES) {
if (AddressIPv6Eq(a_ip1,b_ip1) == 1) {
AddressCutIPv6Copy(a_ip1, a->ad->ip);
AddressCutIPv6Copy(a_ip2, a->ad->ip2);
AddressCutIPv6CopyAddOne(a_ip2, b->ad->ip);
AddressCutIPv6Copy(b_ip2, b->ad->ip2);
/* 'b' overlaps 'a' so 'a' needs the 'b' sigs */
SigGroupListCopyAppend(b,a);
} else if (AddressIPv6Eq(a_ip2, b_ip2) == 1) {
AddressCutIPv6Copy(b_ip1, a->ad->ip);
AddressCutIPv6CopySubOne(a_ip1, a->ad->ip2);
AddressCutIPv6Copy(a_ip1, b->ad->ip);
AddressCutIPv6Copy(a_ip2, b->ad->ip2);
/* 'a' overlaps 'b' so a needs the 'a' sigs */
SigGroupListCopyPrepend(a,b);
} else {
AddressCutIPv6Copy(b_ip1, a->ad->ip);
AddressCutIPv6CopySubOne(a_ip1, a->ad->ip2);
AddressCutIPv6Copy(a_ip1, b->ad->ip);
AddressCutIPv6Copy(a_ip2, b->ad->ip2);
DetectAddressGroup *tmp_c;
tmp_c = DetectAddressGroupInit();
if (tmp_c == NULL) {
goto error;
}
tmp_c->ad = DetectAddressDataInit();
if (tmp_c->ad == NULL) {
goto error;
}
tmp_c->ad->family = AF_INET6;
AddressCutIPv6CopyAddOne(a_ip2, tmp_c->ad->ip);
AddressCutIPv6Copy(b_ip2, tmp_c->ad->ip2);
*c = tmp_c;
/* 'a' gets clean and then 'b' sigs
* 'b' gets clean, then 'a' then 'b' sigs
* 'c' gets 'b' sigs */
SigGroupListCopyAppend(a,tmp); /* store old a list */
SigGroupListClean(a->sh); /* clean a list */
SigGroupListCopyAppend(b,tmp_c); /* copy old b to c */
SigGroupListCopyAppend(b,a); /* copy old b to a */
SigGroupListCopyPrepend(tmp,b); /* prepend old a before b */
SigGroupListClean(tmp->sh); /* clean tmp list */
}
/* we have 2 or three parts:
*
* 2 part: [[baba]aaa] or [aaa[abab]]
* part a: b_ip1 <-> b_ip2
* part b: b_ip2 + 1 <-> a_ip2
*
* part a: a_ip1 <-> b_ip1 - 1
* part b: b_ip1 <-> b_ip2
*
* 3 part [aaa[bbb]aaa]
* part a: a_ip1 <-> b_ip2 - 1
* part b: b_ip1 <-> b_ip2
* part c: b_ip2 + 1 <-> a_ip2
*/
} else if (r == ADDRESS_EB) {
if (AddressIPv6Eq(a_ip1, b_ip1) == 1) {
AddressCutIPv6Copy(b_ip1, a->ad->ip);
AddressCutIPv6Copy(b_ip2, a->ad->ip2);
AddressCutIPv6CopyAddOne(b_ip2, b->ad->ip);
AddressCutIPv6Copy(a_ip2, b->ad->ip2);
/* 'b' overlaps 'a' so a needs the 'b' sigs */
SigGroupListCopyAppend(b,tmp);
SigGroupListClean(b->sh);
SigGroupListCopyAppend(a,b);
SigGroupListCopyAppend(tmp,a);
SigGroupListClean(tmp->sh);
} else if (AddressIPv6Eq(a_ip2, b_ip2) == 1) {
AddressCutIPv6Copy(a_ip1, a->ad->ip);
AddressCutIPv6CopySubOne(b_ip1, a->ad->ip2);
AddressCutIPv6Copy(b_ip1, b->ad->ip);
AddressCutIPv6Copy(b_ip2, b->ad->ip2);
/* 'a' overlaps 'b' so a needs the 'a' sigs */
SigGroupListCopyPrepend(a,b);
} else {
AddressCutIPv6Copy(a_ip1, a->ad->ip);
AddressCutIPv6CopySubOne(b_ip1, a->ad->ip2);
AddressCutIPv6Copy(b_ip1, b->ad->ip);
AddressCutIPv6Copy(b_ip2, b->ad->ip2);
DetectAddressGroup *tmp_c;
tmp_c = DetectAddressGroupInit();
if (tmp_c == NULL) {
goto error;
}
tmp_c->ad = DetectAddressDataInit();
if (tmp_c->ad == NULL) {
goto error;
}
tmp_c->ad->family = AF_INET6;
AddressCutIPv6CopyAddOne(b_ip2, tmp_c->ad->ip);
AddressCutIPv6Copy(a_ip2, tmp_c->ad->ip2);
*c = tmp_c;
/* 'a' stays the same wrt sigs
* 'b' keeps it's own sigs and gets a's sigs prepended
* 'c' gets 'a' sigs */
SigGroupListCopyPrepend(a,b);
SigGroupListCopyAppend(a,tmp_c);
}
}
DetectAddressGroupFree(tmp);
return 0;
error:
DetectAddressGroupFree(tmp);
return -1;
}
int DetectAddressCutIPv6(DetectAddressData *a, DetectAddressData *b, DetectAddressData **c) {
u_int32_t a_ip1[4] = { ntohl(a->ip[0]), ntohl(a->ip[1]), ntohl(a->ip[2]), ntohl(a->ip[3]) };
u_int32_t a_ip2[4] = { ntohl(a->ip2[0]), ntohl(a->ip2[1]), ntohl(a->ip2[2]), ntohl(a->ip2[3]) };

@ -16,6 +16,8 @@ int DetectAddressCutIPv6(DetectAddressData *, DetectAddressData *, DetectAddress
int DetectAddressCutNotIPv6(DetectAddressData *, DetectAddressData **);
int DetectAddressCmpIPv6(DetectAddressData *, DetectAddressData *);
int DetectAddressGroupCutIPv6(DetectAddressGroup *, DetectAddressGroup *, DetectAddressGroup **);
void DetectAddressIPv6Tests(void);
#endif /* __DETECT_ADDRESS_IPV6_H__ */

@ -11,6 +11,7 @@
#include "util-cidr.h"
#include "util-unittest.h"
#include "detect-siggroup.h"
#include "detect-address.h"
#include "detect-address-ipv4.h"
#include "detect-address-ipv6.h"
@ -30,7 +31,12 @@ void DetectAddressRegister (void) {
void DetectAddressDataPrint(DetectAddressData *);
int DetectAddressCut(DetectAddressData *, DetectAddressData *, DetectAddressData **);
int DetectAddressCutNot(DetectAddressData *, DetectAddressData **);
int DetectAddressGroupCut(DetectAddressGroup *, DetectAddressGroup *, DetectAddressGroup **);
/* memory usage counters */
static u_int32_t detect_address_group_memory = 0;
static u_int32_t detect_address_group_init_cnt = 0;
static u_int32_t detect_address_group_free_cnt = 0;
DetectAddressGroup *DetectAddressGroupInit(void) {
DetectAddressGroup *ag = malloc(sizeof(DetectAddressGroup));
@ -39,16 +45,43 @@ DetectAddressGroup *DetectAddressGroupInit(void) {
}
memset(ag,0,sizeof(DetectAddressGroup));
detect_address_group_memory += sizeof(DetectAddressGroup);
detect_address_group_init_cnt++;
return ag;
}
/* free a DetectAddressGroup object */
void DetectAddressGroupFree(DetectAddressGroup *ag) {
if (ag != NULL) {
if (ag->ad != NULL) {
DetectAddressDataFree(ag->ad);
}
free(ag);
if (ag == NULL)
return;
if (ag->ad != NULL) {
DetectAddressDataFree(ag->ad);
}
/* only free the head if we have the original */
if (ag->sh != NULL && !(ag->flags & SIG_GROUP_COPY)) {
SigGroupHeadFree(ag->sh);
}
ag->sh = NULL;
if (ag->dst_gh != NULL) {
DetectAddressGroupsHeadFree(ag->dst_gh);
}
detect_address_group_memory -= sizeof(DetectAddressGroup);
detect_address_group_free_cnt++;
free(ag);
}
void DetectAddressGroupPrintMemory(void) {
printf(" * Address group memory stats:\n");
printf(" - detect_address_group_memory %u\n", detect_address_group_memory);
printf(" - detect_address_group_init_cnt %u\n", detect_address_group_init_cnt);
printf(" - detect_address_group_free_cnt %u\n", detect_address_group_free_cnt);
printf(" - outstanding groups %u\n", detect_address_group_init_cnt - detect_address_group_free_cnt);
printf(" * Address group memory stats done\n");
}
/* used to see if the exact same address group exists in the list
@ -74,7 +107,17 @@ void DetectAddressGroupPrintList(DetectAddressGroup *head) {
if (head != NULL) {
for (cur = head; cur != NULL; cur = cur->next) {
printf("SIGS %6u ", cur->sh ? cur->sh->sig_cnt : 0);
DetectAddressDataPrint(cur->ad);
if (cur->sh != NULL) {
SigGroupContainer *sg;
for (sg = cur->sh->head; sg != NULL; sg = sg->next) {
printf(" %u", sg->s->id);
}
}
printf("\n");
}
}
printf("endlist\n");
@ -96,12 +139,29 @@ void DetectAddressGroupCleanupList (DetectAddressGroup *head) {
head = NULL;
}
int DetectAddressGroupAppend(DetectAddressGroup **head, DetectAddressGroup *ag) {
/* do a sorted insert, where the top of the list should be the biggest
* network/range.
*
* XXX current sorting only works for overlapping nets */
int DetectAddressGroupAdd(DetectAddressGroup **head, DetectAddressGroup *ag) {
DetectAddressGroup *cur, *prev_cur = NULL;
//printf("DetectAddressGroupAdd: adding "); DetectAddressDataPrint(ag->ad); printf("\n");
if (*head != NULL) {
for (cur = *head; cur != NULL; cur = cur->next) {
prev_cur = cur;
int r = DetectAddressCmp(ag->ad,cur->ad);
if (r == ADDRESS_EB) {
/* insert here */
ag->prev = cur->prev;
ag->next = cur;
if (*head == cur) {
*head = ag;
}
return 0;
}
}
ag->prev = prev_cur;
prev_cur->next = ag;
@ -112,7 +172,7 @@ int DetectAddressGroupAppend(DetectAddressGroup **head, DetectAddressGroup *ag)
return 0;
}
/* helper functions for DetectAddressGroupInsert:
/* helper functions for DetectAddress(Group)Insert:
* set & get the head ptr
*/
static int SetHeadPtr(DetectAddressGroupsHead *gh, DetectAddressGroup *newhead) {
@ -141,7 +201,173 @@ static DetectAddressGroup *GetHeadPtr(DetectAddressGroupsHead *gh, DetectAddress
return head;
}
int DetectAddressGroupInsert(DetectAddressGroupsHead *gh, DetectAddressData *new) {
//#define DBG
/* Same as DetectAddressInsert, but then for inserting a address group
* object. This also makes sure SigGroupContainer lists are handled
* correctly.
*
* returncodes
* -1: error
* 0: not inserted, memory of new is freed
* 1: inserted
* */
int DetectAddressGroupInsert(DetectAddressGroupsHead *gh, DetectAddressGroup *new) {
DetectAddressGroup *head = NULL;
#ifdef DBG
printf("DetectAddressGroupInsert: inserting (sig %u) ", new->sh?new->sh->sig_cnt:0); DetectAddressDataPrint(new->ad); printf("\n");
DetectAddressGroupPrintList(gh->ipv4_head);
#endif
/* get our head ptr based on the address we want to insert */
head = GetHeadPtr(gh,new->ad);
/* see if it already exists or overlaps with existing ag's */
if (head != NULL) {
DetectAddressGroup *cur = NULL;
int r = 0;
for (cur = head; cur != NULL; cur = cur->next) {
r = DetectAddressCmp(new->ad,cur->ad);
if (r == ADDRESS_ER) {
printf("ADDRESS_ER DetectAddressCmp compared:\n");
DetectAddressDataPrint(new->ad); printf(" vs. ");
DetectAddressDataPrint(cur->ad); printf("\n");
goto error;
}
/* if so, handle that */
if (r == ADDRESS_EQ) {
#ifdef DBG
printf("ADDRESS_EQ %p %p\n", cur, new);
#endif
/* exact overlap/match */
if (cur != new) {
SigGroupListCopyAppend(new,cur);
DetectAddressGroupFree(new);
return 0;
}
return 1;
} else if (r == ADDRESS_GT) {
#ifdef DBG
printf("ADDRESS_GT\n");
#endif
/* only add it now if we are bigger than the last
* group. Otherwise we'll handle it later. */
if (cur->next == NULL) {
#ifdef DBG
printf("adding GT\n");
#endif
/* put in the list */
new->prev = cur;
cur->next = new;
return 1;
}
} else if (r == ADDRESS_LT) {
#ifdef DBG
printf("ADDRESS_LT\n");
#endif
/* see if we need to insert the ag anywhere */
/* put in the list */
if (cur->prev != NULL)
cur->prev->next = new;
new->prev = cur->prev;
new->next = cur;
cur->prev = new;
/* update head if required */
if (head == cur) {
head = new;
if (SetHeadPtr(gh,head) < 0)
goto error;
}
return 1;
/* alright, those were the simple cases,
* lets handle the more complex ones now */
} else if (r == ADDRESS_ES) {
#ifdef DBG
printf("ADDRESS_ES\n");
#endif
DetectAddressGroup *c = NULL;
r = DetectAddressGroupCut(cur,new,&c);
DetectAddressGroupInsert(gh, new);
if (c) {
#ifdef DBG
printf("DetectAddressGroupInsert: inserting C "); DetectAddressDataPrint(c->ad); printf("\n");
#endif
DetectAddressGroupInsert(gh, c);
}
return 1;
} else if (r == ADDRESS_EB) {
#ifdef DBG
printf("ADDRESS_EB\n");
#endif
DetectAddressGroup *c = NULL;
r = DetectAddressGroupCut(cur,new,&c);
//printf("DetectAddressGroupCut returned %d\n", r);
DetectAddressGroupInsert(gh, new);
if (c) {
#ifdef DBG
printf("DetectAddressGroupInsert: inserting C "); DetectAddressDataPrint(c->ad); printf("\n");
#endif
DetectAddressGroupInsert(gh, c);
}
return 1;
} else if (r == ADDRESS_LE) {
#ifdef DBG
printf("ADDRESS_LE\n");
#endif
DetectAddressGroup *c = NULL;
r = DetectAddressGroupCut(cur,new,&c);
DetectAddressGroupInsert(gh, new);
if (c) {
#ifdef DBG
printf("DetectAddressGroupInsert: inserting C "); DetectAddressDataPrint(c->ad); printf("\n");
#endif
DetectAddressGroupInsert(gh, c);
}
return 1;
} else if (r == ADDRESS_GE) {
#ifdef DBG
printf("ADDRESS_GE\n");
#endif
DetectAddressGroup *c = NULL;
r = DetectAddressGroupCut(cur,new,&c);
DetectAddressGroupInsert(gh, new);
if (c) {
#ifdef DBG
printf("DetectAddressGroupInsert: inserting C "); DetectAddressDataPrint(c->ad); printf("\n");
#endif
DetectAddressGroupInsert(gh, c);
}
return 1;
}
}
/* head is NULL, so get a group and set head to it */
} else {
#ifdef DBG
printf("Setting new head\n");
#endif
head = new;
if (SetHeadPtr(gh,head) < 0)
goto error;
}
return 1;
error:
/* XXX */
return -1;
}
/*
* return codes:
* 1: inserted
* 0: not inserted (no error), memory is cleared
* -1: error
*/
int DetectAddressInsert(DetectAddressGroupsHead *gh, DetectAddressData *new) {
DetectAddressGroup *head = NULL;
/* get our head ptr based on the address we want to insert */
@ -164,7 +390,12 @@ int DetectAddressGroupInsert(DetectAddressGroupsHead *gh, DetectAddressData *new
if (r == ADDRESS_EQ) {
/* exact overlap/match, we don't need to do a thing
*/
return 0;
if (cur->ad != new) {
DetectAddressDataFree(new);
return 0;
}
return 1;
} else if (r == ADDRESS_GT) {
/* only add it now if we are bigger than the last
* group. Otherwise we'll handle it later. */
@ -179,7 +410,7 @@ int DetectAddressGroupInsert(DetectAddressGroupsHead *gh, DetectAddressData *new
/* put in the list */
ag->prev = cur;
cur->next = ag;
return 0;
return 1;
}
} else if (r == ADDRESS_LT) {
/* see if we need to insert the ag anywhere */
@ -204,7 +435,7 @@ int DetectAddressGroupInsert(DetectAddressGroupsHead *gh, DetectAddressData *new
if (SetHeadPtr(gh,head) < 0)
goto error;
}
return 0;
return 1;
/* alright, those were the simple cases,
* lets handle the more complex ones now */
@ -212,23 +443,27 @@ int DetectAddressGroupInsert(DetectAddressGroupsHead *gh, DetectAddressData *new
} else if (r == ADDRESS_ES) {
DetectAddressData *c = NULL;
r = DetectAddressCut(cur->ad,new,&c);
DetectAddressGroupInsert(gh, new);
if (c) DetectAddressGroupInsert(gh, c);
DetectAddressInsert(gh, new);
if (c) DetectAddressInsert(gh, c);
return 1;
} else if (r == ADDRESS_EB) {
DetectAddressData *c = NULL;
r = DetectAddressCut(cur->ad,new,&c);
DetectAddressGroupInsert(gh, new);
if (c) DetectAddressGroupInsert(gh, c);
DetectAddressInsert(gh, new);
if (c) DetectAddressInsert(gh, c);
return 1;
} else if (r == ADDRESS_LE) {
DetectAddressData *c = NULL;
r = DetectAddressCut(cur->ad,new,&c);
DetectAddressGroupInsert(gh, new);
if (c) DetectAddressGroupInsert(gh, c);
DetectAddressInsert(gh, new);
if (c) DetectAddressInsert(gh, c);
return 1;
} else if (r == ADDRESS_GE) {
DetectAddressData *c = NULL;
r = DetectAddressCut(cur->ad,new,&c);
DetectAddressGroupInsert(gh, new);
if (c) DetectAddressGroupInsert(gh, c);
DetectAddressInsert(gh, new);
if (c) DetectAddressInsert(gh, c);
return 1;
}
}
@ -244,7 +479,7 @@ int DetectAddressGroupInsert(DetectAddressGroupsHead *gh, DetectAddressData *new
goto error;
}
return 0;
return 1;
error:
/* XXX */
return -1;
@ -252,6 +487,7 @@ error:
int DetectAddressGroupSetup(DetectAddressGroupsHead *gh, char *s) {
DetectAddressData *ad = NULL;
int r = 0;
/* parse the address */
ad = DetectAddressParse(s);
@ -274,28 +510,29 @@ int DetectAddressGroupSetup(DetectAddressGroupsHead *gh, char *s) {
* of the address space (e.g. 0.0.0.0 or
* 255.255.255.255). */
if (ad2 != NULL) {
if (DetectAddressGroupInsert(gh, ad2) < 0)
if (DetectAddressInsert(gh, ad2) < 0)
goto error;
}
}
if (DetectAddressGroupInsert(gh, ad) < 0)
r = DetectAddressInsert(gh, ad);
if (r < 0)
goto error;
/* if any, insert 0.0.0.0/0 and ::/0 as well */
if (ad->flags & ADDRESS_FLAG_ANY) {
if (r == 1 && ad->flags & ADDRESS_FLAG_ANY) {
ad = DetectAddressParse("0.0.0.0/0");
if (ad == NULL)
goto error;
if (DetectAddressGroupInsert(gh, ad) < 0)
if (DetectAddressInsert(gh, ad) < 0)
goto error;
ad = DetectAddressParse("::/0");
if (ad == NULL)
goto error;
if (DetectAddressGroupInsert(gh, ad) < 0)
if (DetectAddressInsert(gh, ad) < 0)
goto error;
}
return 0;
@ -307,7 +544,7 @@ error:
}
/* XXX error handling */
int DetectAddressGroupParse2(DetectAddressGroupsHead *gh, DetectAddressGroupsHead *ghn, char *s,int negate) {
int DetectAddressParse2(DetectAddressGroupsHead *gh, DetectAddressGroupsHead *ghn, char *s,int negate) {
int i, x;
int o_set = 0, n_set = 0;
int depth = 0;
@ -332,7 +569,7 @@ int DetectAddressGroupParse2(DetectAddressGroupsHead *gh, DetectAddressGroupsHea
address[x-1] = '\0';
x = 0;
DetectAddressGroupParse2(gh,ghn,address,negate ? negate : n_set);
DetectAddressParse2(gh,ghn,address,negate ? negate : n_set);
n_set = 0;
}
depth--;
@ -398,7 +635,7 @@ int DetectAddressGroupMergeNot(DetectAddressGroupsHead *gh, DetectAddressGroupsH
if (ad == NULL) {
goto error;
}
r = DetectAddressGroupInsert(gh,ad);
r = DetectAddressInsert(gh,ad);
if (r < 0) {
goto error;
}
@ -411,7 +648,7 @@ int DetectAddressGroupMergeNot(DetectAddressGroupsHead *gh, DetectAddressGroupsH
if (ad == NULL) {
goto error;
}
r = DetectAddressGroupInsert(gh,ad);
r = DetectAddressInsert(gh,ad);
if (r < 0) {
goto error;
}
@ -465,6 +702,7 @@ error:
return -1;
}
/* XXX rename this so 'Group' is out of the name */
int DetectAddressGroupParse(DetectAddressGroupsHead *gh, char *str) {
int r;
@ -473,7 +711,7 @@ int DetectAddressGroupParse(DetectAddressGroupsHead *gh, char *str) {
goto error;
}
r = DetectAddressGroupParse2(gh,ghn,str,/* start with negate no */0);
r = DetectAddressParse2(gh,ghn,str,/* start with negate no */0);
if (r < 0) {
goto error;
}
@ -483,9 +721,6 @@ int DetectAddressGroupParse(DetectAddressGroupsHead *gh, char *str) {
goto error;
}
//DetectAddressGroupPrintList(gh->ipv4_head);
//DetectAddressGroupPrintList(gh->ipv6_head);
/* free the temp negate head */
DetectAddressGroupsHeadFree(ghn);
return 0;
@ -509,6 +744,7 @@ void DetectAddressGroupsHeadCleanup(DetectAddressGroupsHead *gh) {
DetectAddressGroupCleanupList(gh->any_head);
DetectAddressGroupCleanupList(gh->ipv4_head);
DetectAddressGroupCleanupList(gh->ipv6_head);
gh->any_head = gh->ipv4_head = gh->ipv6_head = NULL;
}
}
@ -519,6 +755,16 @@ void DetectAddressGroupsHeadFree(DetectAddressGroupsHead *gh) {
}
}
int DetectAddressGroupCut(DetectAddressGroup *a, DetectAddressGroup *b, DetectAddressGroup **c) {
if (a->ad->family == AF_INET) {
return DetectAddressGroupCutIPv4(a,b,c);
} else if (a->ad->family == AF_INET6) {
return DetectAddressGroupCutIPv6(a,b,c);
}
return -1;
}
int DetectAddressCut(DetectAddressData *a, DetectAddressData *b, DetectAddressData **c) {
if (a->family == AF_INET) {
return DetectAddressCutIPv4(a,b,c);
@ -584,6 +830,7 @@ int AddressParse(DetectAddressData *dd, char *str) {
/* first handle 'any' */
if (strcasecmp(str,"any") == 0) {
dd->flags |= ADDRESS_FLAG_ANY;
free(ipdup);
return 0;
}
@ -858,7 +1105,7 @@ void DetectAddressDataPrint(DetectAddressData *ad) {
printf("%s/", s);
memcpy(&in, &ad->ip2[0], sizeof(in));
inet_ntop(AF_INET, &in, s, sizeof(s));
printf("%s\n", s);
printf("%s", s);
} else if (ad->family == AF_INET6) {
struct in6_addr in6;
char s[66];
@ -868,7 +1115,7 @@ void DetectAddressDataPrint(DetectAddressData *ad) {
printf("%s/", s);
memcpy(&in6, &ad->ip2, sizeof(in6));
inet_ntop(AF_INET6, &in6, s, sizeof(s));
printf("%s\n", s);
printf("%s", s);
}
}

@ -33,6 +33,7 @@ typedef struct DetectAddressGroup_ {
/* signatures that belong in this group */
struct _SigGroupHead *sh;
u_int8_t flags;
/* double linked list */
struct DetectAddressGroup_ *prev;
@ -55,16 +56,18 @@ DetectAddressData *DetectAddressDataInit(void);
void DetectAddressDataFree(DetectAddressData *);
void DetectAddressDataPrint(DetectAddressData *);
DetectAddressData *DetectAddressDataCopy(DetectAddressData *);
int DetectAddressGroupInsert(DetectAddressGroupsHead *, DetectAddressData *);
int DetectAddressGroupSetup(DetectAddressGroupsHead *, char *);
int DetectAddressCmp(DetectAddressData *, DetectAddressData *);
DetectAddressData *DetectAddressParse(char *);
DetectAddressGroup *DetectAddressLookupGroup(DetectAddressGroupsHead *, Address *);
int DetectAddressGroupParse(DetectAddressGroupsHead *, char *);
DetectAddressGroup *DetectAddressGroupInit(void);
int DetectAddressGroupAppend(DetectAddressGroup **head, DetectAddressGroup *ag);
DetectAddressGroup *DetectAddressGroupLookup(DetectAddressGroup *head, DetectAddressData *ad);
int DetectAddressGroupAdd(DetectAddressGroup **, DetectAddressGroup *);
DetectAddressGroup *DetectAddressGroupLookup(DetectAddressGroup *, DetectAddressData *);
void DetectAddressGroupPrintList(DetectAddressGroup *);
void DetectAddressGroupFree(DetectAddressGroup *);
int DetectAddressGroupInsert(DetectAddressGroupsHead *, DetectAddressGroup *);
void DetectAddressGroupPrintMemory(void);
#endif /* __DETECT_ADDRESS_H__ */

@ -78,7 +78,7 @@ void DetectContentRegister (void) {
/* pass on the content_max_id */
u_int32_t DetectContentMaxId(void) {
printf("DetectContentMaxId: %u\n", content_max_id);
//printf("DetectContentMaxId: %u\n", content_max_id);
return content_max_id;
}

@ -62,7 +62,8 @@ void PatternMatchPrepare(MpmCtx *mc)
/* free the pattern matcher part of a SigGroupHead */
void PatternMatchDestroyGroup(SigGroupHead *sh) {
/* content */
if (sh->flags & SIG_GROUP_HAVECONTENT && sh->mpm_ctx != NULL) {
if (sh->flags & SIG_GROUP_HAVECONTENT && sh->mpm_ctx != NULL &&
!(sh->flags & SIG_GROUP_HEAD_MPM_COPY)) {
sh->mpm_ctx->DestroyCtx(sh->mpm_ctx);
free(sh->mpm_ctx);
@ -72,7 +73,8 @@ void PatternMatchDestroyGroup(SigGroupHead *sh) {
}
/* uricontent */
if (sh->flags & SIG_GROUP_HAVEURICONTENT && sh->mpm_uri_ctx != NULL) {
if (sh->flags & SIG_GROUP_HAVEURICONTENT && sh->mpm_uri_ctx != NULL &&
!(sh->flags & SIG_GROUP_HEAD_MPM_URI_COPY)) {
sh->mpm_uri_ctx->DestroyCtx(sh->mpm_uri_ctx);
free(sh->mpm_uri_ctx);
@ -89,6 +91,7 @@ void PatternMatchDestroyGroup(SigGroupHead *sh) {
*
*
* XXX do error checking
* XXX rewrite the COPY stuff
*/
int PatternMatchPrepareGroup(SigGroupHead *sh)
{
@ -122,14 +125,14 @@ int PatternMatchPrepareGroup(SigGroupHead *sh)
}
/* intialize contexes */
if (sh->flags & SIG_GROUP_HAVECONTENT) {
if (sh->flags & SIG_GROUP_HAVECONTENT && !(sh->flags & SIG_GROUP_HEAD_MPM_COPY)) {
sh->mpm_ctx = malloc(sizeof(MpmCtx));
if (sh->mpm_ctx == NULL)
goto error;
MpmInitCtx(sh->mpm_ctx, MPM_WUMANBER);
}
if (sh->flags & SIG_GROUP_HAVEURICONTENT) {
if (sh->flags & SIG_GROUP_HAVEURICONTENT && !(sh->flags & SIG_GROUP_HEAD_MPM_URI_COPY)) {
sh->mpm_uri_ctx = malloc(sizeof(MpmCtx));
if (sh->mpm_uri_ctx == NULL)
goto error;
@ -145,7 +148,7 @@ int PatternMatchPrepareGroup(SigGroupHead *sh)
/* find flow setting of this rule */
SigMatch *sm;
for (sm = s->match; sm != NULL; sm = sm->next) {
if (sm->type == DETECT_CONTENT) {
if (sm->type == DETECT_CONTENT && !(sh->flags & SIG_GROUP_HEAD_MPM_COPY)) {
DetectContentData *cd = (DetectContentData *)sm->ctx;
if (cd->flags & DETECT_CONTENT_NOCASE) {
@ -153,7 +156,7 @@ int PatternMatchPrepareGroup(SigGroupHead *sh)
} else {
sh->mpm_ctx->AddPattern(sh->mpm_ctx, cd->content, cd->content_len, cd->id);
}
} else if (sm->type == DETECT_URICONTENT) {
} else if (sm->type == DETECT_URICONTENT && !(sh->flags & SIG_GROUP_HEAD_MPM_URI_COPY)) {
DetectUricontentData *ud = (DetectUricontentData *)sm->ctx;
if (ud->flags & DETECT_URICONTENT_NOCASE) {
@ -166,16 +169,18 @@ int PatternMatchPrepareGroup(SigGroupHead *sh)
}
/* content */
if (sh->flags & SIG_GROUP_HAVECONTENT) {
if (sh->flags & SIG_GROUP_HAVECONTENT && !(sh->flags & SIG_GROUP_HEAD_MPM_COPY)) {
if (sh->mpm_ctx->Prepare != NULL) {
sh->mpm_ctx->Prepare(sh->mpm_ctx);
}
//sh->mpm_ctx->PrintCtx(sh->mpm_ctx);
}
/* uricontent */
if (sh->flags & SIG_GROUP_HAVEURICONTENT) {
if (sh->flags & SIG_GROUP_HAVEURICONTENT && !(sh->flags & SIG_GROUP_HEAD_MPM_URI_COPY)) {
if (sh->mpm_uri_ctx->Prepare != NULL) {
sh->mpm_uri_ctx->Prepare(sh->mpm_uri_ctx);
}
//sh->mpm_uri_ctx->PrintCtx(sh->mpm_uri_ctx);
}
//printf("Printing info...\n");

@ -12,6 +12,12 @@
int SigGroupHeadCmp(SigGroupHead *, SigGroupHead *);
static u_int32_t detect_siggroup_memory = 0;
static u_int32_t detect_siggroup_append_cnt = 0;
static u_int32_t detect_siggroup_free_cnt = 0;
/* XXX eeewww global! move to DetectionEngineCtx once we have that! */
static SigGroupHead *sgh_list = NULL;
/* return the first SigGroupHead that matches
@ -27,6 +33,116 @@ SigGroupHead* SigGroupHeadListGet(SigGroupHead *a) {
return NULL;
}
void SigGroupHeadFreeMpmArrays(void) {
SigGroupHead *b = sgh_list;
for ( ; b != NULL; b = b->next) {
if (b->content_array != NULL) {
free(b->content_array);
b->content_array = NULL;
b->content_size = 0;
}
if (b->uri_content_array != NULL) {
free(b->uri_content_array);
b->uri_content_array = NULL;
b->uri_content_size = 0;
}
}
}
int SigGroupContentCmp(SigGroupContent *a, SigGroupContent *b);
/* return the first SigGroupHead that matches
* the lookup one. */
SigGroupHead* SigGroupHeadListGetMpm(SigGroupHead *a) {
SigGroupHead *b = sgh_list;
for ( ; b != NULL; b = b->next) {
//printf("a->content_size %u, b->content_size %u\n", a->content_size, b->content_size);
if (a->content_size != b->content_size)
continue;
if (memcmp(a->content_array,b->content_array,a->content_size) == 0)
return b;
//printf("a->content_cnt %u, b->content_cnt %u\n", a->content_cnt, b->content_cnt);
#if 0
if (a->content_cnt != b->content_cnt)
continue;
//printf("a->content_head %p, b->content_head %p\n", a->content_head, b->content_head);
for (sc_a = a->content_head, sc_b = b->content_head;
sc_a != NULL && sc_b != NULL;
sc_a = sc_a->next, sc_b = sc_b->next)
{
found = 1;
if (SigGroupContentCmp(sc_a,sc_b) != 0) {
found = 0;
break;
} else if ((sc_a->next == NULL && sc_b->next != NULL) ||
(sc_a->next != NULL && sc_b->next == NULL)) {
found = 0;
break;
}
//printf("so far so good\n");
}
if (found) {
//printf("returning b %p\n", b);
return b;
}
#endif
}
return NULL;
}
/* return the first SigGroupHead that matches
* the lookup one. */
SigGroupHead* SigGroupHeadListGetMpmUri(SigGroupHead *a) {
SigGroupHead *b = sgh_list;
for ( ; b != NULL; b = b->next) {
// SigGroupUricontent *sc_a, *sc_b;
// int found = 0;
if (a->content_size != b->content_size)
continue;
if (memcmp(a->content_array,b->content_array,a->content_size) == 0)
return b;
#if 0
if (a->uri_content_cnt != b->uri_content_cnt)
continue;
//printf("a->content_head %p, b->content_head %p\n", a->content_head, b->content_head);
for (sc_a = a->uri_content_head, sc_b = b->uri_content_head;
sc_a != NULL && sc_b != NULL;
sc_a = sc_a->next, sc_b = sc_b->next)
{
found = 1;
if (SigGroupUricontentCmp(sc_a,sc_b) != 0) {
found = 0;
break;
} else if ((sc_a->next == NULL && sc_b->next != NULL) ||
(sc_a->next != NULL && sc_b->next == NULL)) {
found = 0;
break;
}
//printf("so far so good\n");
}
if (found) {
//printf("returning b %p\n", b);
return b;
}
#endif
}
return NULL;
}
/* basically just reset the prt as the list items
* themselves are removed elsewhere */
void SigGroupHeadListClean(void) {
@ -66,6 +182,9 @@ int SigGroupAppend(DetectAddressGroup *ag, Signature *s) {
}
memset(sg,0,sizeof(SigGroupContainer));
detect_siggroup_append_cnt++;
detect_siggroup_memory += sizeof(SigGroupContainer);
/* connect the signature to the container */
sg->s = s;
@ -93,30 +212,88 @@ error:
return -1;
}
/* XXX function name */
int SigGroupClean(DetectAddressGroup *ag) {
int SigGroupListClean(SigGroupHead *sh) {
SigGroupContainer *sg = NULL, *next_sg = NULL;
if (ag->sh == NULL)
if (sh == NULL)
return 0;
sg = sh->head;
while (sg != NULL) {
detect_siggroup_free_cnt++;
detect_siggroup_memory -= sizeof(SigGroupContainer);
next_sg = sg->next;
sg->s->rulegroup_refcnt--;
sg->s = NULL;
free(sg);
sh->sig_cnt--;
sg = next_sg;
}
sh->head = NULL;
sh->tail = NULL;
return 0;
}
int SigGroupListCopyPrepend(DetectAddressGroup *src, DetectAddressGroup *dst) {
SigGroupContainer *sg = NULL;
if (src->sh == NULL)
return 0;
if (!(ag->sh->flags & SIG_GROUP_COPY))
PatternMatchDestroyGroup(ag->sh);
if (dst->sh == NULL) {
dst->sh = malloc(sizeof(SigGroupHead));
if (dst->sh == NULL) {
goto error;
}
memset(dst->sh, 0, sizeof(SigGroupHead));
}
sg = ag->sh->head;
/* save the head & tail */
SigGroupContainer *dsthead = dst->sh->head;
SigGroupContainer *dsttail = dst->sh->tail;
/* reset dst head */
dst->sh->head = NULL;
dst->sh->tail = NULL;
/* append the sigs into the now cleared dst */
for (sg = src->sh->head; sg != NULL; sg = sg->next) {
SigGroupAppend(dst,sg->s);
}
while (sg != NULL) {
next_sg = sg->next;
dst->sh->tail->next = dsthead;
dst->sh->tail = dsttail;
return 0;
error:
return -1;
}
sg->s->rulegroup_refcnt--;
sg->s = NULL;
free(sg);
int SigGroupListCopyAppend(DetectAddressGroup *src, DetectAddressGroup *dst) {
SigGroupContainer *sg = NULL;
sg = next_sg;
if (src->sh == NULL)
return 0;
if (dst->sh == NULL) {
dst->sh = malloc(sizeof(SigGroupHead));
if (dst->sh == NULL) {
goto error;
}
memset(dst->sh, 0, sizeof(SigGroupHead));
}
for (sg = src->sh->head; sg != NULL; sg = sg->next) {
SigGroupAppend(dst,sg->s);
}
free(ag->sh);
return 0;
error:
return -1;
}
int SigGroupHeadCmp(SigGroupHead *a, SigGroupHead *b) {
@ -135,3 +312,154 @@ int SigGroupHeadCmp(SigGroupHead *a, SigGroupHead *b) {
return 1;
}
void SigGroupHeadFree(SigGroupHead *sh) {
if (sh == NULL)
return;
PatternMatchDestroyGroup(sh);
SigGroupListClean(sh);
free(sh);
}
void DetectSigGroupPrintMemory(void) {
printf(" * Sig group memory stats:\n");
printf(" - detect_siggroup_memory %u\n", detect_siggroup_memory);
printf(" - detect_siggroup_append_cnt %u\n", detect_siggroup_append_cnt);
printf(" - detect_siggroup_free_cnt %u\n", detect_siggroup_free_cnt);
printf(" - outstanding sig containers %u\n", detect_siggroup_append_cnt - detect_siggroup_free_cnt);
printf(" * Sig group memory stats done\n");
}
/* -1: a is smaller
* 0: equal
* 1: a is bigger
*/
int SigGroupContentCmp(SigGroupContent *a, SigGroupContent *b) {
//printf("a->content->id %u, b->content->id %u\n", a->content->id, b->content->id);
if (a->content->id < b->content->id)
return -1;
else if (a->content->id > b->content->id)
return 1;
/* implied equal */
return 0;
}
/* load all pattern id's into a single bitarray that we can memcmp
* with other bitarrays. A fast and efficient way of comparing pattern
* sets. */
int SigGroupContentLoad(SigGroupHead *sgh) {
SigGroupContainer *sgc = sgh->head;
Signature *s;
SigMatch *sm;
if (DetectContentMaxId() == 0)
return 0;
sgh->content_size = (DetectContentMaxId() / 8) + 1;
sgh->content_array = malloc(sgh->content_size * sizeof(u_int32_t));
if (sgh->content_array == NULL)
return -1;
memset(sgh->content_array,0, sgh->content_size * sizeof(u_int32_t));
for ( ; sgc != NULL; sgc = sgc->next) {
s = sgc->s;
if (s == NULL)
continue;
sm = s->match;
if (sm == NULL)
continue;
for ( ; sm != NULL; sm = sm->next) {
if (sm->type == DETECT_CONTENT) {
DetectContentData *co = (DetectContentData *)sm->ctx;
sgh->content_array[(co->id/8)] |= 1<<(co->id%8);
}
}
}
return 0;
}
int SigGroupListContentClean(SigGroupHead *sh) {
if (sh == NULL)
return 0;
if (sh->content_array != NULL) {
free(sh->content_array);
sh->content_array = NULL;
sh->content_size = 0;
}
return 0;
}
/* -1: a is smaller
* 0: equal
* 1: a is bigger
*/
int SigGroupUricontentCmp(SigGroupUricontent *a, SigGroupUricontent *b) {
//printf("a->content->id %u, b->content->id %u\n", a->content->id, b->content->id);
if (a->content->id < b->content->id)
return -1;
else if (a->content->id > b->content->id)
return 1;
/* implied equal */
return 0;
}
int SigGroupUricontentLoad(SigGroupHead *sgh) {
SigGroupContainer *sgc = sgh->head;
Signature *s;
SigMatch *sm;
if (DetectUricontentMaxId() == 0)
return 0;
sgh->uri_content_size = (DetectUricontentMaxId() / 8) + 1;
sgh->uri_content_array = malloc(sgh->uri_content_size * sizeof(u_int32_t));
if (sgh->uri_content_array == NULL)
return -1;
memset(sgh->uri_content_array,0, sgh->uri_content_size * sizeof(u_int32_t));
for ( ; sgc != NULL; sgc = sgc->next) {
s = sgc->s;
if (s == NULL)
continue;
sm = s->match;
if (sm == NULL)
continue;
for ( ; sm != NULL; sm = sm->next) {
if (sm->type == DETECT_URICONTENT) {
DetectUricontentData *co = (DetectUricontentData *)sm->ctx;
sgh->uri_content_array[(co->id/8)] |= 1<<(co->id%8);
}
}
}
return 0;
}
int SigGroupListUricontentClean(SigGroupHead *sh) {
if (sh == NULL)
return 0;
if (sh->uri_content_array != NULL) {
free(sh->uri_content_array);
sh->uri_content_array = NULL;
sh->uri_content_size = 0;
}
return 0;
}

@ -4,8 +4,27 @@
int SigGroupAppend(DetectAddressGroup *, Signature *);
int SigGroupClean(DetectAddressGroup *ag);
SigGroupHead* SigGroupHeadListGet(SigGroupHead *a);
SigGroupHead* SigGroupHeadListGetMpm(SigGroupHead *a);
SigGroupHead* SigGroupHeadListGetMpmUri(SigGroupHead *a);
void SigGroupHeadListClean(void);
void SigGroupHeadAppend(SigGroupHead *);
void SigGroupHeadFree(SigGroupHead *);
int SigGroupListCopyPrepend(DetectAddressGroup *src, DetectAddressGroup *dst);
int SigGroupListCopyAppend(DetectAddressGroup *src, DetectAddressGroup *dst);
void SigGroupHeadListClean(void);
int SigGroupListClean(SigGroupHead *sh);
void DetectSigGroupPrintMemory(void);
int SigGroupContentLoad(SigGroupHead *sgh);
int SigGroupUricontentLoad(SigGroupHead *sgh);
int SigGroupListContentClean(SigGroupHead *sh);
int SigGroupListUricontentClean(SigGroupHead *sh);
int SigGroupContentCmp(SigGroupContent *, SigGroupContent *);
int SigGroupUricontentCmp(SigGroupUricontent *, SigGroupUricontent *);
void SigGroupHeadFreeMpmArrays(void);
#endif /* __DETECT_SIGGROUP_H__ */

@ -68,7 +68,7 @@ void DetectUricontentRegister (void) {
/* pass on the uricontent_max_id */
u_int32_t DetectUricontentMaxId(void) {
printf("DetectUricontentMaxId: %u\n", uricontent_max_id);
//printf("DetectUricontentMaxId: %u\n", uricontent_max_id);
return uricontent_max_id;
}

File diff suppressed because it is too large Load Diff

@ -2,6 +2,8 @@
#define __DETECT_H__
#include "detect-address.h"
#include "detect-content.h"
#include "detect-uricontent.h"
#define SIG_FLAG_RECURSIVE 0x01
#define SIG_FLAG_SP_ANY 0x02
@ -87,44 +89,58 @@ typedef struct _SigGroupContainer {
struct _SigGroupContainer *next;
} SigGroupContainer;
typedef struct _SigGroupType {
u_int8_t type;
} SigGroupType;
/* container for content matches... we use this to compare
* group heads for contents
* XXX name */
typedef struct _SigGroupContent {
DetectContentData *content;
struct _SigGroupContent *next;
} SigGroupContent;
/* container for content matches... we use this to compare
* group heads for contents
* XXX name */
typedef struct _SigGroupUricontent {
DetectUricontentData *content;
struct _SigGroupUricontent *next;
} SigGroupUricontent;
#define SIG_GROUP_HAVECONTENT 0x1
#define SIG_GROUP_HAVEURICONTENT 0x2
/* XXX rename */
#define SIG_GROUP_INITIALIZED 0x4
#define SIG_GROUP_COPY 0x8
/* head of the list of containers, contains
* the pattern matcher context for the sigs
* that follow. */
#define SIG_GROUP_HEAD_MPM_COPY 0x4
#define SIG_GROUP_HEAD_MPM_URI_COPY 0x8
/* head of the list of containers. */
typedef struct _SigGroupHead {
u_int8_t type;
u_int8_t flags;
/* pattern matcher instance */
MpmCtx *mpm_ctx;
MpmCtx *mpm_uri_ctx;
u_int8_t flags;
/* list of content containers
* XXX move into a separate data struct
* with only a ptr to it. Saves some memory
* after initialization
* XXX use a bitarray to save 7/8 of the mem*/
u_int32_t *content_array;
u_int32_t content_size;
u_int32_t *uri_content_array;
u_int32_t uri_content_size;
/* list of signature containers */
SigGroupContainer *head;
SigGroupContainer *tail;
u_int32_t sig_cnt;
u_int32_t refcnt;
struct _SigGroupHead *next;
} SigGroupHead;
typedef struct _SigGroupAddress {
u_int8_t type;
DetectAddressGroupsHead gh;
} SigGroupAddress;
typedef struct _SigGroupEntry {
SigGroupType *next;
} SigGroupEntry;
#define SIGMATCH_NOOPT 0x01
void SigLoadSignatures (void);
@ -172,6 +188,7 @@ void SigRegisterTests(void);
void TmModuleDetectRegister (void);
int SigGroupBuild(Signature *);
int SigGroupCleanup();
#endif /* __DETECT_H__ */

@ -313,6 +313,7 @@ int main(int argc, char **argv)
SigTableRegisterTests();
SigRegisterTests();
//UtRunTests();
UtCleanup();
//exit(1);
//LoadConfig();

Loading…
Cancel
Save