diff --git a/src/detect-address-ipv4.c b/src/detect-address-ipv4.c index e6dbf1c629..91b7249b3a 100644 --- a/src/detect-address-ipv4.c +++ b/src/detect-address-ipv4.c @@ -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 * diff --git a/src/detect-address-ipv4.h b/src/detect-address-ipv4.h index 352eb0feda..6564cefba8 100644 --- a/src/detect-address-ipv4.h +++ b/src/detect-address-ipv4.h @@ -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__ */ diff --git a/src/detect-address-ipv6.c b/src/detect-address-ipv6.c index ad3416d96c..e82bf33d46 100644 --- a/src/detect-address-ipv6.c +++ b/src/detect-address-ipv6.c @@ -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]) }; diff --git a/src/detect-address-ipv6.h b/src/detect-address-ipv6.h index 0fffc841b0..5a536c2eeb 100644 --- a/src/detect-address-ipv6.h +++ b/src/detect-address-ipv6.h @@ -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__ */ diff --git a/src/detect-address.c b/src/detect-address.c index 5d3131aa2d..20d468e445 100644 --- a/src/detect-address.c +++ b/src/detect-address.c @@ -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); } } diff --git a/src/detect-address.h b/src/detect-address.h index 2bf278d0d4..56129d63cb 100644 --- a/src/detect-address.h +++ b/src/detect-address.h @@ -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__ */ diff --git a/src/detect-content.c b/src/detect-content.c index 65ed01a846..8b9e1fbf65 100644 --- a/src/detect-content.c +++ b/src/detect-content.c @@ -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; } diff --git a/src/detect-mpm.c b/src/detect-mpm.c index 70325ff069..db97b1847c 100644 --- a/src/detect-mpm.c +++ b/src/detect-mpm.c @@ -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"); diff --git a/src/detect-siggroup.c b/src/detect-siggroup.c index 149d0ef6e8..85462aa897 100644 --- a/src/detect-siggroup.c +++ b/src/detect-siggroup.c @@ -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; +} + diff --git a/src/detect-siggroup.h b/src/detect-siggroup.h index 2983ee7aa5..182faa72f5 100644 --- a/src/detect-siggroup.h +++ b/src/detect-siggroup.h @@ -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__ */ diff --git a/src/detect-uricontent.c b/src/detect-uricontent.c index c5d0f4f474..0987317b81 100644 --- a/src/detect-uricontent.c +++ b/src/detect-uricontent.c @@ -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; } diff --git a/src/detect.c b/src/detect.c index b7b78bbb0d..627af946b4 100644 --- a/src/detect.c +++ b/src/detect.c @@ -86,8 +86,9 @@ void SigLoadSignatures (void) return; prevsig->next = sig; prevsig = sig; + /* - sig = SigInit("alert ip 192.168.0.0/24 any -> 80.126.224.247 any (msg:\"ViCtOr nocase test\"; sid:2000; rev:13; content:ViCtOr; nocase; depth:150;)"); + sig = SigInit("alert tcp any any -> any any (msg:\"ViCtOr nocase test\"; sid:4; rev:13; content:ViCtOr; nocase; depth:150;)"); if (sig == NULL) return; prevsig->next = sig; @@ -175,8 +176,13 @@ void SigLoadSignatures (void) int good = 0, bad = 0; FILE *fp = fopen("/etc/vips/rules/bleeding-all.rules", "r"); //FILE *fp = fopen("/home/victor/rules/vips-http.sigs", "r"); + //FILE *fp = fopen("/home/victor/rules/emerging-dshield.rules", "r"); + //FILE *fp = fopen("/home/victor/rules/emerging-web-small.rules", "r"); + //FILE *fp = fopen("/home/victor/rules/web-misc.rules", "r"); //FILE *fp = fopen("/home/victor/rules/vips-all.sigs", "r"); //FILE *fp = fopen("/home/victor/rules/all.rules", "r"); + //FILE *fp = fopen("/home/victor/rules/all_iplists.rules", "r"); + //FILE *fp = fopen("/home/victor/rules/funky.rules", "r"); //FILE *fp = fopen("/etc/vips/rules/zango.rules", "r"); //FILE *fp = fopen("/home/victor/rules/vips-vrt-all.sigs", "r"); //FILE *fp = fopen("/home/victor/rules/test-many-ips.rules", "r"); @@ -202,11 +208,20 @@ void SigLoadSignatures (void) } fclose(fp); printf("SigLoadSignatures: %d successfully loaded from file. %d sigs failed to load\n", good, bad); + + /* http_ua -- for the log-httplog module */ + sig = SigInit("alert tcp any any -> any any (msg:\"HTTP UA cap\"; flow:to_server; content:\"User-Agent:\"; depth:400; pcre:\"/^User-Agent: (?P.*)\\r\\n/m\"; noalert; sid:4;)"); + if (sig == NULL) + return; + prevsig->next = sig; + prevsig = sig; + //#endif - /* Setup the pattern matcher */ + /* Setup the signature group lookup structure and + * pattern matchers */ SigGroupBuild(sig_list); -//abort(); +abort(); } /* check if a certain sid alerted, this is used in the test functions */ @@ -261,6 +276,7 @@ int SigMatchSignatures(ThreadVars *th_v, PatternMatcherThread *pmt, Packet *p) /* point this sig list to sg */ sg = g->sh->head; + //printf("sigs %u\n", g->sh->sig_cnt); } } @@ -375,14 +391,15 @@ void SigCleanSignatures() } } + /* add all signatures to their own source address group * XXX not currently used */ -int SigAddressPrepareStage0(Signature *s) { +int SigAddressPrepareStage1(Signature *s) { Signature *tmp_s = NULL; - DetectAddressGroup *gr = NULL;//, *grnew = NULL; - //DetectAddressData *ad = NULL; + DetectAddressGroup *gr = NULL; + u_int32_t cnt = 0, sigs = 0; - printf("* Building signature grouping structure, stage 0: adding signatures to sig source addresses...\n"); + printf("* Building signature grouping structure, stage 1: adding signatures to signature source addresses...\n"); /* now for every rule add the source group */ for (tmp_s = s; tmp_s != NULL; tmp_s = tmp_s->next) { @@ -390,34 +407,39 @@ int SigAddressPrepareStage0(Signature *s) { if (SigGroupAppend(gr,tmp_s) < 0) { goto error; } + cnt++; } for (gr = tmp_s->src.ipv6_head; gr != NULL; gr = gr->next) { if (SigGroupAppend(gr,tmp_s) < 0) { goto error; } + cnt++; } for (gr = tmp_s->src.any_head; gr != NULL; gr = gr->next) { if (SigGroupAppend(gr,tmp_s) < 0) { goto error; } + cnt++; } + sigs++; } - printf("* Building signature grouping structure, stage 0: adding signatures to sig source addresses... done\n"); + //DetectSigGroupPrintMemory(); + printf("* %u signatures appended %u times to the source addresses\n", sigs, cnt); + printf("* Building signature grouping structure, stage 1: adding signatures to signature source addresses... done\n"); return 0; error: - printf("SigAddressPrepareStage0 error\n"); + printf("SigAddressPrepareStage1 error\n"); return -1; } -/* fill the global src group head, with the sigs included - * XXX WIP code, not working & not used */ -int SigAddressPrepareStage0a(Signature *s) { +/* fill the global src group head, with the sigs included */ +int SigAddressPrepareStage2(Signature *s) { Signature *tmp_s = NULL; DetectAddressGroup *gr = NULL, *lookup_gr = NULL; - //DetectAddressData *ad = NULL; + u_int32_t cnt = 0, sigs = 0, insert = 0; - printf("* Building signature grouping structure, stage 0a: building source address list\n"); + printf("* Building signature grouping structure, stage 2: building source address list\n"); g_src_gh = DetectAddressGroupsHeadInit(); if (g_src_gh == NULL) { @@ -428,16 +450,10 @@ int SigAddressPrepareStage0a(Signature *s) { goto error; } - u_int32_t i = 0; - /* now for every rule add the source group to our temp list */ - for (tmp_s = s; tmp_s != NULL; tmp_s = tmp_s->next, i++) { -// printf("* %6u: Signature %u\n", i, tmp_s->id); + for (tmp_s = s; tmp_s != NULL; tmp_s = tmp_s->next) { for (gr = tmp_s->src.ipv4_head; gr != NULL; gr = gr->next) { -// printf("Group has address: "); DetectAddressDataPrint(gr->ad); if ((lookup_gr = DetectAddressGroupLookup(g_tmp_gh->ipv4_head,gr->ad)) == NULL) { -// printf("New group, appending and inserting\n"); - DetectAddressGroup *grtmp = DetectAddressGroupInit(); if (grtmp == NULL) { goto error; @@ -447,89 +463,19 @@ int SigAddressPrepareStage0a(Signature *s) { goto error; } grtmp->ad = adtmp; - DetectAddressGroupAppend(&g_tmp_gh->ipv4_head,grtmp); + DetectAddressGroupAdd(&g_tmp_gh->ipv4_head,grtmp); SigGroupAppend(grtmp,tmp_s); + cnt++; + insert++; } else { -// printf("Existing group, not inserting but we will merge sigs with %p\n", lookup_gr); - /* our group will only have one sig, this one. So add that. */ SigGroupAppend(lookup_gr,tmp_s); + cnt++; } } - } - printf("g_tmp_gh strt\n"); - DetectAddressGroupPrintList(g_tmp_gh->ipv4_head); - printf("g_tmp_gh end\n"); - - u_int32_t cnt_any = 0, cnt_ipv4 = 0, cnt_ipv6 = 0; - - for (gr = g_src_gh->any_head; gr != NULL; gr = gr->next) { - cnt_any++; - } - for (gr = g_src_gh->ipv4_head; gr != NULL; gr = gr->next) { - cnt_ipv4++; - } - for (gr = g_src_gh->ipv6_head; gr != NULL; gr = gr->next) { - cnt_ipv6++; - } - - printf("* Source any: %u address blocks.\n", cnt_any); - printf("* Source ipv4: %u address blocks.\n", cnt_ipv4); - printf("* Source ipv6: %u address blocks.\n", cnt_ipv6); - printf("* Building signature grouping structure, stage 0a: building source address list... done\n"); - - return 0; -error: - printf("SigAddressPrepareStage0a error\n"); - return -1; -} -/* fill the global src group head */ -int SigAddressPrepareStage1(Signature *s) { - Signature *tmp_s = NULL; - DetectAddressGroup *gr = NULL; - DetectAddressData *ad = NULL; - u_int32_t i = 0; - - printf("* Building signature grouping structure, stage 1: building source address list\n"); - - /* initializet the global lookup group head for source addresses */ - g_src_gh = DetectAddressGroupsHeadInit(); - if (g_src_gh == NULL) { - goto error; - } - /* initialize a temporary group head for speeding up initialization */ - g_tmp_gh = DetectAddressGroupsHeadInit(); - if (g_tmp_gh == NULL) { - goto error; - } - - /* now for every rule add the source group */ - for (tmp_s = s; tmp_s != NULL; tmp_s = tmp_s->next, i++) { - //printf("* %6u: Signature %u\n", i, tmp_s->id); - - //for (gr = tmp_s->src.any_head; gr != NULL; gr = gr->next) { - /* the 'any' list will contain max 1, so no need to loop - * and no need to try the insertion every single time */ - if (tmp_s->src.any_head != NULL && g_src_gh->any_head == NULL) { - gr = tmp_s->src.any_head; - - ad = DetectAddressDataCopy(gr->ad); - if (ad == NULL) { - goto error; - } - - if (DetectAddressGroupInsert(g_src_gh,ad) < 0) { - goto error; - } - } - for (gr = tmp_s->src.ipv4_head; gr != NULL; gr = gr->next) { - /* For every address block we want to insert into the global - * source list, we first check if we already did this. Many - * sigs use the same blocks, and this check is a hell of a lot - * cheaper than doing the actual pointless insert. */ - if (DetectAddressGroupLookup(g_tmp_gh->ipv4_head,gr->ad) == 0) { - /* first add a copy of the group to the tmp list */ + for (gr = tmp_s->src.ipv6_head; gr != NULL; gr = gr->next) { + if ((lookup_gr = DetectAddressGroupLookup(g_tmp_gh->ipv6_head,gr->ad)) == NULL) { DetectAddressGroup *grtmp = DetectAddressGroupInit(); if (grtmp == NULL) { goto error; @@ -539,33 +485,92 @@ int SigAddressPrepareStage1(Signature *s) { goto error; } grtmp->ad = adtmp; + DetectAddressGroupAdd(&g_tmp_gh->ipv6_head,grtmp); - DetectAddressGroupAppend(&g_tmp_gh->ipv4_head,grtmp); - - /* next insert this address block */ - ad = DetectAddressDataCopy(gr->ad); - if (ad == NULL) { + SigGroupAppend(grtmp,tmp_s); + cnt++; + insert++; + } else { + /* our group will only have one sig, this one. So add that. */ + SigGroupAppend(lookup_gr,tmp_s); + cnt++; + } + } + /* XXX review 'any' usage here */ + for (gr = tmp_s->src.any_head; gr != NULL; gr = gr->next) { + if ((lookup_gr = DetectAddressGroupLookup(g_tmp_gh->any_head,gr->ad)) == NULL) { + DetectAddressGroup *grtmp = DetectAddressGroupInit(); + if (grtmp == NULL) { goto error; } - - if (DetectAddressGroupInsert(g_src_gh,ad) < 0) { + DetectAddressData *adtmp = DetectAddressDataCopy(gr->ad); + if (adtmp == NULL) { goto error; } - } - } - for (gr = tmp_s->src.ipv6_head; gr != NULL; gr = gr->next) { - /* XXX apply the same speedup trick as the ipv4 one */ - ad = DetectAddressDataCopy(gr->ad); - if (ad == NULL) { - goto error; - } + grtmp->ad = adtmp; + DetectAddressGroupAdd(&g_tmp_gh->any_head,grtmp); - if (DetectAddressGroupInsert(g_src_gh,ad) < 0) { - goto error; + SigGroupAppend(grtmp,tmp_s); + cnt++; + insert++; + } else { + /* our group will only have one sig, this one. So add that. */ + SigGroupAppend(lookup_gr,tmp_s); + cnt++; } } + sigs++; } + //DetectAddressGroupPrintMemory(); + //DetectSigGroupPrintMemory(); + + //printf("g_tmp_gh strt\n"); + //DetectAddressGroupPrintList(g_tmp_gh->ipv4_head); + //printf("g_tmp_gh end\n"); + + for (gr = g_tmp_gh->ipv4_head; gr != NULL; ) { + //printf("Inserting2'ing: "); DetectAddressDataPrint(gr->ad); + DetectAddressGroup *grnext = gr->next; + + gr->next = NULL; + if (DetectAddressGroupInsert(g_src_gh,gr) < 0) + goto error; + + gr = grnext; + } + for (gr = g_tmp_gh->ipv6_head; gr != NULL; ) { + //printf("Inserting2'ing: "); DetectAddressDataPrint(gr->ad); + DetectAddressGroup *grnext = gr->next; + + gr->next = NULL; + if (DetectAddressGroupInsert(g_src_gh,gr) < 0) + goto error; + + gr = grnext; + } + /* XXX whats the point of the any temp list if any is always just + * one object.... ??? */ + for (gr = g_tmp_gh->any_head; gr != NULL; ) { + //printf("Inserting2'ing: "); DetectAddressDataPrint(gr->ad); + DetectAddressGroup *grnext = gr->next; + + gr->next = NULL; + if (DetectAddressGroupInsert(g_src_gh,gr) < 0) + goto error; + + gr = grnext; + } + + + + //DetectAddressGroupPrintMemory(); + //DetectSigGroupPrintMemory(); + + //printf("g_src_gh strt\n"); + //DetectAddressGroupPrintList(g_src_gh->ipv4_head); + //printf("g_src_gh end\n"); + u_int32_t cnt_any = 0, cnt_ipv4 = 0, cnt_ipv6 = 0; for (gr = g_src_gh->any_head; gr != NULL; gr = gr->next) { @@ -578,652 +583,480 @@ int SigAddressPrepareStage1(Signature *s) { cnt_ipv6++; } + printf("* %u signatures, %u sigs appends, %u actual source address inserts\n", sigs,cnt,insert); + printf("* Source any: %u address blocks.\n", cnt_any); printf("* Source ipv4: %u address blocks.\n", cnt_ipv4); printf("* Source ipv6: %u address blocks.\n", cnt_ipv6); - printf("* Building signature grouping structure, stage 1: building source address list... done\n"); + printf("* Building signature grouping structure, stage 2: building source address list... done\n"); return 0; error: - printf("SigAddressPrepareStage1 error\n"); + printf("SigAddressPrepareStage2 error\n"); return -1; } -/* fill dst group heads */ -int SigAddressPrepareStage2(Signature *s) { +int SigAddressPrepareStage3(Signature *s) { Signature *tmp_s = NULL; - DetectAddressGroup *rule_src_gr = NULL, *rule_dst_gr = NULL, *global_src_gr = NULL; - DetectAddressData *ad = NULL; + DetectAddressGroup *gr = NULL, *sgr = NULL, *lookup_gr = NULL; + SigGroupContainer *sgc = NULL; + u_int32_t cnt = 0, copy = 0, real = 0, mpm_unique = 0, mpm_reuse = 0, mpm_none = 0, + mpm_uri_unique = 0, mpm_uri_reuse = 0, mpm_uri_none = 0; - printf("* Building signature grouping structure, stage 2: building destination address heads...\n"); + printf("* Building signature grouping structure, stage 3: building destination address lists...\n"); - /* for each rule, do */ - for (tmp_s = s; tmp_s != NULL; tmp_s = tmp_s->next) { - /* for each rule source, look up which global - * source matches */ - for (rule_src_gr = tmp_s->src.ipv4_head; rule_src_gr != NULL; - rule_src_gr = rule_src_gr->next) - { - //printf("Lookup "); DetectAddressDataPrint(rule_src_gr->ad); - for (global_src_gr = g_src_gh->ipv4_head; global_src_gr != NULL; - global_src_gr = global_src_gr->next) - { - int r = DetectAddressCmp(rule_src_gr->ad,global_src_gr->ad); - if (r == ADDRESS_ER) { - goto error; - } + SigGroupHeadListClean(); - if (r == ADDRESS_EQ || r == ADDRESS_EB) { - //printf("- Fits global: "); DetectAddressDataPrint(global_src_gr->ad); + /* loop through the global source address list */ + for (gr = g_src_gh->ipv4_head; gr != NULL; gr = gr->next) { + //printf(" * Source group: "); DetectAddressDataPrint(gr->ad); printf("\n"); - /* okay we need to add this sig to this src group */ - for (rule_dst_gr = tmp_s->dst.ipv4_head; rule_dst_gr != NULL; - rule_dst_gr = rule_dst_gr->next) - { - //printf("DST "); DetectAddressDataPrint(rule_dst_gr->ad); + /* use a tmp list for speeding up insertions */ + DetectAddressGroupsHead *tmp_gh = DetectAddressGroupsHeadInit(); + if (tmp_gh == NULL) { + goto error; + } - ad = DetectAddressDataCopy(rule_dst_gr->ad); - if (ad == NULL) { - goto error; - } + /* loop through all signatures in this source address group */ + for (sgc = gr->sh->head; sgc != NULL; sgc = sgc->next) { + tmp_s = sgc->s; - if (global_src_gr->dst_gh == NULL) { - global_src_gr->dst_gh = DetectAddressGroupsHeadInit(); - if (global_src_gr->dst_gh == NULL) { - goto error; - } - } - if (DetectAddressGroupInsert(global_src_gr->dst_gh,ad) < 0) { - goto error; - } + /* build the temp list */ + for (sgr = tmp_s->dst.ipv4_head; sgr != NULL; sgr = sgr->next) { + if ((lookup_gr = DetectAddressGroupLookup(tmp_gh->ipv4_head,sgr->ad)) == NULL) { + DetectAddressGroup *grtmp = DetectAddressGroupInit(); + if (grtmp == NULL) { + goto error; + } + DetectAddressData *adtmp = DetectAddressDataCopy(sgr->ad); + if (adtmp == NULL) { + goto error; } + grtmp->ad = adtmp; + DetectAddressGroupAdd(&tmp_gh->ipv4_head,grtmp); + + SigGroupAppend(grtmp,tmp_s); + } else { + /* our group will only have one sig, this one. So add that. */ + SigGroupAppend(lookup_gr,tmp_s); } } } - /* for each rule source, look up which global - * source matches */ - for (rule_src_gr = tmp_s->src.ipv6_head; rule_src_gr != NULL; - rule_src_gr = rule_src_gr->next) - { - //printf("Lookup "); DetectAddressDataPrint(rule_src_gr->ad); - for (global_src_gr = g_src_gh->ipv6_head; global_src_gr != NULL; - global_src_gr = global_src_gr->next) - { - int r = DetectAddressCmp(rule_src_gr->ad,global_src_gr->ad); - if (r == ADDRESS_ER) { - goto error; - } - if (r == ADDRESS_EQ || r == ADDRESS_EB) { - //printf("- Fits global: "); DetectAddressDataPrint(global_src_gr->ad); - - /* okay we need to add this sig to this src group */ - for (rule_dst_gr = tmp_s->dst.ipv6_head; rule_dst_gr != NULL; - rule_dst_gr = rule_dst_gr->next) - { - //printf("DST "); DetectAddressDataPrint(rule_dst_gr->ad); + /* for each address in the tmp list, insert a copy */ + for (sgr = tmp_gh->ipv4_head; sgr != NULL; sgr = sgr->next) { + DetectAddressGroup *grtmp = DetectAddressGroupInit(); + if (grtmp == NULL) { + goto error; + } + DetectAddressData *adtmp = DetectAddressDataCopy(sgr->ad); + if (adtmp == NULL) { + goto error; + } + grtmp->ad = adtmp; - ad = DetectAddressDataCopy(rule_dst_gr->ad); - if (ad == NULL) { - goto error; - } + SigGroupListCopyAppend(sgr,grtmp); - if (global_src_gr->dst_gh == NULL) { - global_src_gr->dst_gh = DetectAddressGroupsHeadInit(); - if (global_src_gr->dst_gh == NULL) { - goto error; - } - } - if (DetectAddressGroupInsert(global_src_gr->dst_gh,ad) < 0) { - goto error; - } - } - } + if (gr->dst_gh == NULL) { + gr->dst_gh = DetectAddressGroupsHeadInit(); } + + int r = DetectAddressGroupInsert(gr->dst_gh,grtmp); + if (r < 0) goto error; } - /* for each rule source, look up which global - * source matches */ - for (rule_src_gr = tmp_s->src.any_head; rule_src_gr != NULL; - rule_src_gr = rule_src_gr->next) - { - //printf("Lookup "); DetectAddressDataPrint(rule_src_gr->ad); - for (global_src_gr = g_src_gh->any_head; global_src_gr != NULL; - global_src_gr = global_src_gr->next) - { - int r = DetectAddressCmp(rule_src_gr->ad,global_src_gr->ad); - if (r == ADDRESS_ER) { - goto error; - } - if (r == ADDRESS_EQ || r == ADDRESS_EB) { - //printf("- Fits global: "); DetectAddressDataPrint(global_src_gr->ad); + /* see if the sig group head of each address group is the + * same as an earlier one. If it is, free our head and use + * a pointer to the earlier one. This saves _a lot_ of memory. + */ + for (sgr = gr->dst_gh->ipv4_head; sgr != NULL; sgr = sgr->next) { + /* Because a pattern matcher context uses quite some + * memory, we first check if we can reuse it from + * another group head. */ + SigGroupHead *sgh = SigGroupHeadListGet(sgr->sh); + if (sgh == NULL) { + /* put the contents in our head */ + SigGroupContentLoad(sgr->sh); + SigGroupUricontentLoad(sgr->sh); - /* okay we need to add this sig to this src group */ - for (rule_dst_gr = tmp_s->dst.any_head; rule_dst_gr != NULL; - rule_dst_gr = rule_dst_gr->next) - { - //printf("DST "); DetectAddressDataPrint(rule_dst_gr->ad); + //SigGroupContentListPrint(sgr->sh); + //SigGroupUricontentListPrint(sgr->sh); - ad = DetectAddressDataCopy(rule_dst_gr->ad); - if (ad == NULL) { - goto error; - } + if (sgr->sh->content_size == 0) { + mpm_none++; + } else { + /* now have a look if we can reuse a mpm ctx */ + SigGroupHead *mpmsh = SigGroupHeadListGetMpm(sgr->sh); + if (mpmsh == NULL) { + mpm_unique++; + } else { + mpm_reuse++; - if (global_src_gr->dst_gh == NULL) { - global_src_gr->dst_gh = DetectAddressGroupsHeadInit(); - if (global_src_gr->dst_gh == NULL) { - goto error; - } - } - if (DetectAddressGroupInsert(global_src_gr->dst_gh,ad) < 0) { - goto error; - } + sgr->sh->mpm_ctx = mpmsh->mpm_ctx; + sgr->sh->flags |= SIG_GROUP_HEAD_MPM_COPY; + SigGroupListContentClean(sgr->sh); } } - } - } - } - - printf("* Building signature grouping structure, stage 2: building destination address heads... done\n"); - return 0; -error: - printf("SigAddressPrepareStage2 error\n"); - return -1; -} -/* Add the signature in a siggroup to the dst groups that - * match each sig. */ -int SigAddressPrepareStage3(Signature *s) { - Signature *tmp_s = NULL; - DetectAddressGroupsHead *global_dst_gh = NULL; - DetectAddressGroup *rule_src_gr = NULL, *rule_dst_gr = NULL, - *global_src_gr = NULL, *global_dst_gr = NULL; - - printf("* Building signature grouping structure, stage 3: building destination address lists...\n"); - - /* for each rule, do */ - for (tmp_s = s; tmp_s != NULL; tmp_s = tmp_s->next) { - //printf("SIG %u\n", tmp_s->id); - - /* for each rule source, look up which global - * source matches */ - for (rule_src_gr = tmp_s->src.ipv4_head; rule_src_gr != NULL; - rule_src_gr = rule_src_gr->next) - { - //printf("RULE SRC: "); DetectAddressDataPrint(rule_src_gr->ad); + if (sgr->sh->uri_content_size == 0) { + mpm_uri_none++; + } else { + /* now have a look if we can reuse a uri mpm ctx */ + SigGroupHead *mpmsh = SigGroupHeadListGetMpmUri(sgr->sh); + if (mpmsh == NULL) { + mpm_uri_unique++; + } else { + mpm_uri_reuse++; - for (global_src_gr = g_src_gh->ipv4_head; global_src_gr != NULL; - global_src_gr = global_src_gr->next) - { - //printf("GLOBAL SRC: "); DetectAddressDataPrint(global_src_gr->ad); + sgr->sh->mpm_uri_ctx = mpmsh->mpm_uri_ctx; + sgr->sh->flags |= SIG_GROUP_HEAD_MPM_URI_COPY; + SigGroupListUricontentClean(sgr->sh); + } + } - int r = DetectAddressCmp(rule_src_gr->ad,global_src_gr->ad); - if (r == ADDRESS_ER) { + /* init the pattern matcher, this will respect the copy + * setting */ + if (PatternMatchPrepareGroup(sgr->sh) < 0) goto error; - } - if (r == ADDRESS_EQ || r == ADDRESS_EB) { - //printf("MATCH\n"); + SigGroupHeadAppend(sgr->sh); + real++; + } else { + SigGroupHeadFree(sgr->sh); + sgr->sh = sgh; + copy++; + sgr->flags |= SIG_GROUP_COPY; + } + } - /* okay we checked source, now check dst */ - for (rule_dst_gr = tmp_s->dst.ipv4_head; rule_dst_gr != NULL; - rule_dst_gr = rule_dst_gr->next) - { - //printf("RULE DST: "); DetectAddressDataPrint(rule_dst_gr->ad); + /* free the temp list */ + DetectAddressGroupsHeadFree(tmp_gh); + /* clear now unneeded sig group head */ + SigGroupHeadFree(gr->sh); + gr->sh = NULL; - global_dst_gh = global_src_gr->dst_gh; - if (global_dst_gh == NULL) - continue; + DetectAddressGroup *tgr; + for (tgr = gr->dst_gh->ipv4_head; tgr != NULL; tgr = tgr->next) { + cnt++; + } - for (global_dst_gr = global_dst_gh->ipv4_head; - global_dst_gr != NULL; - global_dst_gr = global_dst_gr->next) - { - //printf("GLOBAL DST: "); DetectAddressDataPrint(global_dst_gr->ad); + //printf(" * Source group: "); DetectAddressDataPrint(gr->ad); printf(": %d destination groups.\n", cnt); + cnt = 0; + } + for (gr = g_src_gh->ipv6_head; gr != NULL; gr = gr->next) { + //printf(" * Source group: "); DetectAddressDataPrint(gr->ad); printf("\n"); - r = DetectAddressCmp(rule_dst_gr->ad, global_dst_gr->ad); - if (r == ADDRESS_ER) { - goto error; - } + /* use a tmp list for speeding up insertions */ + DetectAddressGroupsHead *tmp_gh = DetectAddressGroupsHeadInit(); + if (tmp_gh == NULL) { + goto error; + } - /* we found a matching src group, then we found a - * dst group that matches, so add the sig to it. */ - if (r == ADDRESS_EQ || r == ADDRESS_EB) { - //printf("MATCH\n"); - if (SigGroupAppend(global_dst_gr,tmp_s) < 0) { - goto error; - } - } - } + /* loop through all signatures in this source address group */ + for (sgc = gr->sh->head; sgc != NULL; sgc = sgc->next) { + tmp_s = sgc->s; + + /* build the temp list */ + for (sgr = tmp_s->dst.ipv6_head; sgr != NULL; sgr = sgr->next) { + if ((lookup_gr = DetectAddressGroupLookup(tmp_gh->ipv6_head,sgr->ad)) == NULL) { + DetectAddressGroup *grtmp = DetectAddressGroupInit(); + if (grtmp == NULL) { + goto error; } + DetectAddressData *adtmp = DetectAddressDataCopy(sgr->ad); + if (adtmp == NULL) { + goto error; + } + grtmp->ad = adtmp; + DetectAddressGroupAdd(&tmp_gh->ipv6_head,grtmp); + + SigGroupAppend(grtmp,tmp_s); + } else { + /* our group will only have one sig, this one. So add that. */ + SigGroupAppend(lookup_gr,tmp_s); } } } - /* for each rule source, look up which global - * source matches */ - for (rule_src_gr = tmp_s->src.ipv6_head; rule_src_gr != NULL; - rule_src_gr = rule_src_gr->next) - { - //printf("RULE SRC: "); DetectAddressDataPrint(rule_src_gr->ad); - for (global_src_gr = g_src_gh->ipv6_head; global_src_gr != NULL; - global_src_gr = global_src_gr->next) - { - //printf("GLOBAL SRC: "); DetectAddressDataPrint(global_src_gr->ad); - - int r = DetectAddressCmp(rule_src_gr->ad,global_src_gr->ad); - if (r == ADDRESS_ER) { - goto error; - } + /* for each address in the tmp list, insert a copy */ + for (sgr = tmp_gh->ipv6_head; sgr != NULL; sgr = sgr->next) { + DetectAddressGroup *grtmp = DetectAddressGroupInit(); + if (grtmp == NULL) { + goto error; + } + DetectAddressData *adtmp = DetectAddressDataCopy(sgr->ad); + if (adtmp == NULL) { + goto error; + } + grtmp->ad = adtmp; - if (r == ADDRESS_EQ || r == ADDRESS_EB) { - //printf("MATCH\n"); - - /* okay we checked source, now check dst */ - for (rule_dst_gr = tmp_s->dst.ipv6_head; rule_dst_gr != NULL; - rule_dst_gr = rule_dst_gr->next) - { - global_dst_gh = global_src_gr->dst_gh; - if (global_dst_gh == NULL) - continue; - - for (global_dst_gr = global_dst_gh->ipv6_head; - global_dst_gr != NULL; - global_dst_gr = global_dst_gr->next) - { - r = DetectAddressCmp(rule_dst_gr->ad, global_dst_gr->ad); - if (r == ADDRESS_ER) { - goto error; - } + SigGroupListCopyAppend(sgr,grtmp); - /* we found a matching src group, then we found a - * dst group that matches, so add the sig to it. */ - if (r == ADDRESS_EQ || r == ADDRESS_EB) { - if (SigGroupAppend(global_dst_gr,tmp_s) < 0) { - goto error; - } - } - } - } - } + if (gr->dst_gh == NULL) { + gr->dst_gh = DetectAddressGroupsHeadInit(); } + + int r = DetectAddressGroupInsert(gr->dst_gh,grtmp); + if (r < 0) goto error; } - /* for each rule source, look up which global - * source matches */ - for (rule_src_gr = tmp_s->src.any_head; rule_src_gr != NULL; - rule_src_gr = rule_src_gr->next) - { - //printf("RULE SRC: "); DetectAddressDataPrint(rule_src_gr->ad); - for (global_src_gr = g_src_gh->any_head; global_src_gr != NULL; - global_src_gr = global_src_gr->next) - { - //printf("GLOBAL SRC: "); DetectAddressDataPrint(global_src_gr->ad); + /* see if the sig group head of each address group is the + * same as an earlier one. If it is, free our head and use + * a pointer to the earlier one. This saves _a lot_ of memory. + */ + for (sgr = gr->dst_gh->ipv6_head; sgr != NULL; sgr = sgr->next) { + /* Because a pattern matcher context uses quite some + * memory, we first check if we can reuse it from + * another group head. */ + SigGroupHead *sgh = SigGroupHeadListGet(sgr->sh); + if (sgh == NULL) { + /* put the contents in our head */ + SigGroupContentLoad(sgr->sh); + SigGroupUricontentLoad(sgr->sh); - int r = DetectAddressCmp(rule_src_gr->ad,global_src_gr->ad); - if (r == ADDRESS_ER) { - goto error; - } + //SigGroupContentListPrint(sgr->sh); + //SigGroupUricontentListPrint(sgr->sh); - if (r == ADDRESS_EQ || r == ADDRESS_EB) { - //printf("MATCH\n"); - - /* okay we checked source, now check dst */ - for (rule_dst_gr = tmp_s->dst.any_head; rule_dst_gr != NULL; - rule_dst_gr = rule_dst_gr->next) - { - global_dst_gh = global_src_gr->dst_gh; - if (global_dst_gh == NULL) - continue; - - for (global_dst_gr = global_dst_gh->any_head; - global_dst_gr != NULL; - global_dst_gr = global_dst_gr->next) - { - r = DetectAddressCmp(rule_dst_gr->ad, global_dst_gr->ad); - if (r == ADDRESS_ER) { - goto error; - } + if (sgr->sh->content_size == 0) { + mpm_none++; + } else { + /* now have a look if we can reuse a mpm ctx */ + SigGroupHead *mpmsh = SigGroupHeadListGetMpm(sgr->sh); + if (mpmsh == NULL) { + mpm_unique++; + } else { + mpm_reuse++; - /* we found a matching src group, then we found a - * dst group that matches, so add the sig to it. */ - if (r == ADDRESS_EQ || r == ADDRESS_EB) { - if (SigGroupAppend(global_dst_gr,tmp_s) < 0) { - goto error; - } - } - } + sgr->sh->mpm_ctx = mpmsh->mpm_ctx; + sgr->sh->flags |= SIG_GROUP_HEAD_MPM_COPY; + SigGroupListContentClean(sgr->sh); } } - } - } - } - u_int32_t cnt_sig = 0; - for (tmp_s = s; tmp_s != NULL; tmp_s = tmp_s->next) { - cnt_sig++; - } + if (sgr->sh->uri_content_size == 0) { + mpm_uri_none++; + } else { + /* now have a look if we can reuse a uri mpm ctx */ + SigGroupHead *mpmsh = SigGroupHeadListGetMpmUri(sgr->sh); + if (mpmsh == NULL) { + mpm_uri_unique++; + } else { + mpm_uri_reuse++; - printf("* Signatures processed: %u.\n", cnt_sig); - printf("* Building signature grouping structure, stage 3: building destination address lists... done\n"); - return 0; -error: - printf("SigAddressPrepareStage3 error\n"); - return -1; -} + sgr->sh->mpm_uri_ctx = mpmsh->mpm_uri_ctx; + sgr->sh->flags |= SIG_GROUP_HEAD_MPM_URI_COPY; + SigGroupListUricontentClean(sgr->sh); + } + } -/* initialize the pattern matcher contexts in the rule group - * heads */ -int SigAddressPrepareStage4(void) { - DetectAddressGroupsHead *global_dst_gh = NULL; - DetectAddressGroup *global_src_gr = NULL, *global_dst_gr = NULL; - u_int32_t cnt = 0; + /* init the pattern matcher, this will respect the copy + * setting */ + if (PatternMatchPrepareGroup(sgr->sh) < 0) + goto error; - printf("* Building signature grouping structure, stage 4: pattern matcher initialization...\n"); + SigGroupHeadAppend(sgr->sh); + real++; + } else { + SigGroupHeadFree(sgr->sh); + sgr->sh = sgh; + copy++; + sgr->flags |= SIG_GROUP_COPY; + } + } - SigGroupHeadListClean(); + /* free the temp list */ + DetectAddressGroupsHeadFree(tmp_gh); + /* clear now unneeded sig group head */ + SigGroupHeadFree(gr->sh); + gr->sh = NULL; - for (global_src_gr = g_src_gh->ipv4_head; global_src_gr != NULL; - global_src_gr = global_src_gr->next) - { - global_dst_gh = global_src_gr->dst_gh; - if (global_dst_gh == NULL) - continue; - - for (global_dst_gr = global_dst_gh->ipv4_head; - global_dst_gr != NULL; - global_dst_gr = global_dst_gr->next) - { + DetectAddressGroup *tgr; + for (tgr = gr->dst_gh->ipv6_head; tgr != NULL; tgr = tgr->next) { cnt++; + } - /* Because a pattern matcher context uses quite some - * memory, we first check if we can reuse it from - * another group head. */ - SigGroupHead *sgh = SigGroupHeadListGet(global_dst_gr->sh); - if (sgh == NULL) { - if (PatternMatchPrepareGroup(global_dst_gr->sh) < 0) - goto error; + //printf(" * Source group: "); DetectAddressDataPrint(gr->ad); printf(": %d destination groups.\n", cnt); + cnt = 0; + } + for (gr = g_src_gh->any_head; gr != NULL; gr = gr->next) { + //printf(" * Source group: "); DetectAddressDataPrint(gr->ad); printf("\n"); - global_dst_gr->sh->flags |= SIG_GROUP_INITIALIZED; - SigGroupHeadAppend(global_dst_gr->sh); - } else { - if (sgh->flags & SIG_GROUP_INITIALIZED) { - sgh->refcnt++; - global_dst_gr->sh->mpm_ctx = sgh->mpm_ctx; - global_dst_gr->sh->mpm_uri_ctx = sgh->mpm_uri_ctx; - global_dst_gr->sh->flags = sgh->flags; - global_dst_gr->sh->flags |= SIG_GROUP_COPY; - } - } + /* use a tmp list for speeding up insertions */ + DetectAddressGroupsHead *tmp_gh = DetectAddressGroupsHeadInit(); + if (tmp_gh == NULL) { + goto error; } - for (global_dst_gr = global_dst_gh->any_head; - global_dst_gr != NULL; - global_dst_gr = global_dst_gr->next) - { - cnt++; - /* Because a pattern matcher context uses quite some - * memory, we first check if we can reuse it from - * another group head. */ - SigGroupHead *sgh = SigGroupHeadListGet(global_dst_gr->sh); - if (sgh == NULL) { - if (PatternMatchPrepareGroup(global_dst_gr->sh) < 0) - goto error; - global_dst_gr->sh->flags |= SIG_GROUP_INITIALIZED; - SigGroupHeadAppend(global_dst_gr->sh); - } else { - if (sgh->flags & SIG_GROUP_INITIALIZED) { - sgh->refcnt++; - global_dst_gr->sh->mpm_ctx = sgh->mpm_ctx; - global_dst_gr->sh->mpm_uri_ctx = sgh->mpm_uri_ctx; - global_dst_gr->sh->flags = sgh->flags; - global_dst_gr->sh->flags |= SIG_GROUP_COPY; + /* loop through all signatures in this source address group */ + for (sgc = gr->sh->head; sgc != NULL; sgc = sgc->next) { + tmp_s = sgc->s; + + /* build the temp list */ + for (sgr = tmp_s->dst.any_head; sgr != NULL; sgr = sgr->next) { + if ((lookup_gr = DetectAddressGroupLookup(tmp_gh->any_head,sgr->ad)) == NULL) { + DetectAddressGroup *grtmp = DetectAddressGroupInit(); + if (grtmp == NULL) { + goto error; + } + DetectAddressData *adtmp = DetectAddressDataCopy(sgr->ad); + if (adtmp == NULL) { + goto error; + } + grtmp->ad = adtmp; + DetectAddressGroupAdd(&tmp_gh->any_head,grtmp); + + SigGroupAppend(grtmp,tmp_s); + } else { + /* our group will only have one sig, this one. So add that. */ + SigGroupAppend(lookup_gr,tmp_s); } } } - } - for (global_src_gr = g_src_gh->ipv6_head; global_src_gr != NULL; - global_src_gr = global_src_gr->next) - { - global_dst_gh = global_src_gr->dst_gh; - if (global_dst_gh == NULL) - continue; + /* for each address in the tmp list, insert a copy */ + for (sgr = tmp_gh->any_head; sgr != NULL; sgr = sgr->next) { + DetectAddressGroup *grtmp = DetectAddressGroupInit(); + if (grtmp == NULL) { + goto error; + } + DetectAddressData *adtmp = DetectAddressDataCopy(sgr->ad); + if (adtmp == NULL) { + goto error; + } + grtmp->ad = adtmp; - for (global_dst_gr = global_dst_gh->ipv6_head; - global_dst_gr != NULL; - global_dst_gr = global_dst_gr->next) - { - cnt++; - /* Because a pattern matcher context uses quite some - * memory, we first check if we can reuse it from - * another group head. */ - SigGroupHead *sgh = SigGroupHeadListGet(global_dst_gr->sh); - if (sgh == NULL) { - if (PatternMatchPrepareGroup(global_dst_gr->sh) < 0) - goto error; + SigGroupListCopyAppend(sgr,grtmp); - global_dst_gr->sh->flags |= SIG_GROUP_INITIALIZED; - SigGroupHeadAppend(global_dst_gr->sh); - } else { - if (sgh->flags & SIG_GROUP_INITIALIZED) { - sgh->refcnt++; - global_dst_gr->sh->mpm_ctx = sgh->mpm_ctx; - global_dst_gr->sh->mpm_uri_ctx = sgh->mpm_uri_ctx; - global_dst_gr->sh->flags = sgh->flags; - global_dst_gr->sh->flags |= SIG_GROUP_COPY; - } + if (gr->dst_gh == NULL) { + gr->dst_gh = DetectAddressGroupsHeadInit(); } + + int r = DetectAddressGroupInsert(gr->dst_gh,grtmp); + if (r < 0) goto error; } - for (global_dst_gr = global_dst_gh->any_head; - global_dst_gr != NULL; - global_dst_gr = global_dst_gr->next) - { - cnt++; + + /* see if the sig group head of each address group is the + * same as an earlier one. If it is, free our head and use + * a pointer to the earlier one. This saves _a lot_ of memory. + */ + for (sgr = gr->dst_gh->any_head; sgr != NULL; sgr = sgr->next) { /* Because a pattern matcher context uses quite some * memory, we first check if we can reuse it from * another group head. */ - SigGroupHead *sgh = SigGroupHeadListGet(global_dst_gr->sh); + SigGroupHead *sgh = SigGroupHeadListGet(sgr->sh); if (sgh == NULL) { - if (PatternMatchPrepareGroup(global_dst_gr->sh) < 0) - goto error; + /* put the contents in our head */ + SigGroupContentLoad(sgr->sh); + SigGroupUricontentLoad(sgr->sh); - global_dst_gr->sh->flags |= SIG_GROUP_INITIALIZED; - SigGroupHeadAppend(global_dst_gr->sh); - } else { - if (sgh->flags & SIG_GROUP_INITIALIZED) { - sgh->refcnt++; - global_dst_gr->sh->mpm_ctx = sgh->mpm_ctx; - global_dst_gr->sh->mpm_uri_ctx = sgh->mpm_uri_ctx; - global_dst_gr->sh->flags = sgh->flags; - global_dst_gr->sh->flags |= SIG_GROUP_COPY; - } - } - } - } + //SigGroupContentListPrint(sgr->sh); + //SigGroupUricontentListPrint(sgr->sh); - for (global_src_gr = g_src_gh->any_head; global_src_gr != NULL; - global_src_gr = global_src_gr->next) - { - global_dst_gh = global_src_gr->dst_gh; - if (global_dst_gh == NULL) - continue; + if (sgr->sh->content_size == 0) { + mpm_none++; + } else { + /* now have a look if we can reuse a mpm ctx */ + SigGroupHead *mpmsh = SigGroupHeadListGetMpm(sgr->sh); + if (mpmsh == NULL) { + mpm_unique++; + } else { + mpm_reuse++; - for (global_dst_gr = global_dst_gh->any_head; - global_dst_gr != NULL; - global_dst_gr = global_dst_gr->next) - { - cnt++; - /* Because a pattern matcher context uses quite some - * memory, we first check if we can reuse it from - * another group head. */ - SigGroupHead *sgh = SigGroupHeadListGet(global_dst_gr->sh); - if (sgh == NULL) { - if (PatternMatchPrepareGroup(global_dst_gr->sh) < 0) - goto error; + sgr->sh->mpm_ctx = mpmsh->mpm_ctx; + sgr->sh->flags |= SIG_GROUP_HEAD_MPM_COPY; + SigGroupListContentClean(sgr->sh); + } + } - global_dst_gr->sh->flags |= SIG_GROUP_INITIALIZED; - SigGroupHeadAppend(global_dst_gr->sh); - } else { - if (sgh->flags & SIG_GROUP_INITIALIZED) { - sgh->refcnt++; - global_dst_gr->sh->mpm_ctx = sgh->mpm_ctx; - global_dst_gr->sh->mpm_uri_ctx = sgh->mpm_uri_ctx; - global_dst_gr->sh->flags = sgh->flags; - global_dst_gr->sh->flags |= SIG_GROUP_COPY; + if (sgr->sh->uri_content_size == 0) { + mpm_uri_none++; + } else { + /* now have a look if we can reuse a uri mpm ctx */ + SigGroupHead *mpmsh = SigGroupHeadListGetMpmUri(sgr->sh); + if (mpmsh == NULL) { + mpm_uri_unique++; + } else { + mpm_uri_reuse++; + + sgr->sh->mpm_uri_ctx = mpmsh->mpm_uri_ctx; + sgr->sh->flags |= SIG_GROUP_HEAD_MPM_URI_COPY; + SigGroupListUricontentClean(sgr->sh); + } } - } - } - for (global_dst_gr = global_dst_gh->ipv4_head; - global_dst_gr != NULL; - global_dst_gr = global_dst_gr->next) - { - cnt++; - /* Because a pattern matcher context uses quite some - * memory, we first check if we can reuse it from - * another group head. */ - SigGroupHead *sgh = SigGroupHeadListGet(global_dst_gr->sh); - if (sgh == NULL) { - if (PatternMatchPrepareGroup(global_dst_gr->sh) < 0) + + /* init the pattern matcher, this will respect the copy + * setting */ + if (PatternMatchPrepareGroup(sgr->sh) < 0) goto error; - global_dst_gr->sh->flags |= SIG_GROUP_INITIALIZED; - SigGroupHeadAppend(global_dst_gr->sh); + SigGroupHeadAppend(sgr->sh); + real++; } else { - if (sgh->flags & SIG_GROUP_INITIALIZED) { - sgh->refcnt++; - global_dst_gr->sh->mpm_ctx = sgh->mpm_ctx; - global_dst_gr->sh->mpm_uri_ctx = sgh->mpm_uri_ctx; - global_dst_gr->sh->flags = sgh->flags; - global_dst_gr->sh->flags |= SIG_GROUP_COPY; - } + SigGroupHeadFree(sgr->sh); + sgr->sh = sgh; + copy++; + sgr->flags |= SIG_GROUP_COPY; } } - for (global_dst_gr = global_dst_gh->ipv6_head; - global_dst_gr != NULL; - global_dst_gr = global_dst_gr->next) - { - cnt++; - /* Because a pattern matcher context uses quite some - * memory, we first check if we can reuse it from - * another group head. */ - SigGroupHead *sgh = SigGroupHeadListGet(global_dst_gr->sh); - if (sgh == NULL) { - if (PatternMatchPrepareGroup(global_dst_gr->sh) < 0) - goto error; - global_dst_gr->sh->flags |= SIG_GROUP_INITIALIZED; - SigGroupHeadAppend(global_dst_gr->sh); - } else { - if (sgh->flags & SIG_GROUP_INITIALIZED) { - sgh->refcnt++; - global_dst_gr->sh->mpm_ctx = sgh->mpm_ctx; - global_dst_gr->sh->mpm_uri_ctx = sgh->mpm_uri_ctx; - global_dst_gr->sh->flags = sgh->flags; - global_dst_gr->sh->flags |= SIG_GROUP_COPY; - } - } + /* free the temp list */ + DetectAddressGroupsHeadFree(tmp_gh); + /* clear now unneeded sig group head */ + SigGroupHeadFree(gr->sh); + gr->sh = NULL; + + DetectAddressGroup *tgr; + for (tgr = gr->dst_gh->any_head; tgr != NULL; tgr = tgr->next) { + cnt++; } + + //printf(" * Source group: "); DetectAddressDataPrint(gr->ad); printf(": %d destination groups.\n", cnt); + cnt = 0; } - printf("* Pattern matcher contexts initialized: %u\n", cnt); - printf("* Building signature grouping structure, stage 4: pattern matcher initialization... done\n"); + /* XXX cleanup group head (uri)content_array's */ + SigGroupHeadFreeMpmArrays(); + + //DetectAddressGroupPrintMemory(); + //DetectSigGroupPrintMemory(); + + printf("* Signature group heads: unique %u, copies %u.\n", real,copy); + printf("* MPM instances: %u unique, copies %u (none %u).\n", mpm_unique, mpm_reuse, mpm_none); + printf("* MPM (URI) instances: %u unique, copies %u (none %u).\n", mpm_uri_unique, mpm_uri_reuse, mpm_uri_none); + printf("* Building signature grouping structure, stage 3: building destination address lists... done\n"); + return 0; error: + printf("SigAddressPrepareStage3 error\n"); return -1; } -int SigAddressCleanupStage4(void) { - DetectAddressGroupsHead *global_dst_gh = NULL; - DetectAddressGroup *global_src_gr = NULL, *global_dst_gr = NULL; - u_int32_t cnt = 0; +int SigAddressCleanupStage1(void) { + DetectAddressGroup *global_src_gr = NULL; - printf("* Cleaning up signature grouping structure, stage 4...\n"); + printf("* Cleaning up signature grouping structure, stage 1...\n"); for (global_src_gr = g_src_gh->ipv4_head; global_src_gr != NULL; global_src_gr = global_src_gr->next) { - global_dst_gh = global_src_gr->dst_gh; - if (global_dst_gh == NULL) - continue; - - for (global_dst_gr = global_dst_gh->ipv4_head; - global_dst_gr != NULL; - global_dst_gr = global_dst_gr->next) - { - cnt++; - SigGroupClean(global_dst_gr); - } - for (global_dst_gr = global_dst_gh->any_head; - global_dst_gr != NULL; - global_dst_gr = global_dst_gr->next) - { - cnt++; - SigGroupClean(global_dst_gr); - } DetectAddressGroupsHeadCleanup(global_src_gr->dst_gh); } for (global_src_gr = g_src_gh->ipv6_head; global_src_gr != NULL; global_src_gr = global_src_gr->next) { - global_dst_gh = global_src_gr->dst_gh; - if (global_dst_gh == NULL) - continue; - - for (global_dst_gr = global_dst_gh->ipv6_head; - global_dst_gr != NULL; - global_dst_gr = global_dst_gr->next) - { - cnt++; - SigGroupClean(global_dst_gr); - } - for (global_dst_gr = global_dst_gh->any_head; - global_dst_gr != NULL; - global_dst_gr = global_dst_gr->next) - { - cnt++; - SigGroupClean(global_dst_gr); - } - DetectAddressGroupsHeadCleanup(global_src_gr->dst_gh); } for (global_src_gr = g_src_gh->any_head; global_src_gr != NULL; global_src_gr = global_src_gr->next) { - global_dst_gh = global_src_gr->dst_gh; - if (global_dst_gh == NULL) - continue; - - for (global_dst_gr = global_dst_gh->any_head; - global_dst_gr != NULL; - global_dst_gr = global_dst_gr->next) - { - cnt++; - SigGroupClean(global_dst_gr); - } - for (global_dst_gr = global_dst_gh->ipv4_head; - global_dst_gr != NULL; - global_dst_gr = global_dst_gr->next) - { - cnt++; - SigGroupClean(global_dst_gr); - } - for (global_dst_gr = global_dst_gh->ipv6_head; - global_dst_gr != NULL; - global_dst_gr = global_dst_gr->next) - { - cnt++; - SigGroupClean(global_dst_gr); - } DetectAddressGroupsHeadCleanup(global_src_gr->dst_gh); } DetectAddressGroupsHeadCleanup(g_src_gh); - printf("* Pattern matcher contexts cleaned: %u\n", cnt); - printf("* Cleaning up signature grouping structure, stage 4... done\n"); + printf("* Cleaning up signature grouping structure, stage 1... done\n"); return 0; } @@ -1464,21 +1297,14 @@ int SigAddressPrepareStage5(void) { } int SigGroupBuild (Signature *s) { - //SigAddressPrepareStage0(s); - //SigAddressPrepareStage0a(s); SigAddressPrepareStage1(s); SigAddressPrepareStage2(s); SigAddressPrepareStage3(s); - SigAddressPrepareStage4(); - /* Stage 5 is just for debug output */ - //SigAddressPrepareStage5(); - return 0; } -int SigGroupCleanup (Signature *s) { - SigAddressCleanupStage4(); - +int SigGroupCleanup (void) { + SigAddressCleanupStage1(); return 0; } @@ -1593,7 +1419,7 @@ int SigTest01 (void) { result = 1; } - SigGroupCleanup(sig_list); + SigGroupCleanup(); PatternMatcherThreadDeinit(&th_v, (void *)pmt); PatternMatchDestroy(mpm_ctx); SigCleanSignatures(); @@ -1636,7 +1462,7 @@ int SigTest02 (void) { if (PacketAlertCheck(&p, 1)) result = 1; - SigGroupCleanup(sig_list); + SigGroupCleanup(); PatternMatcherThreadDeinit(&th_v, (void *)pmt); PatternMatchDestroy(mpm_ctx); SigCleanSignatures(); @@ -1680,7 +1506,7 @@ int SigTest03 (void) { if (!PacketAlertCheck(&p, 1)) result = 1; - SigGroupCleanup(sig_list); + SigGroupCleanup(); PatternMatcherThreadDeinit(&th_v, (void *)pmt); PatternMatchDestroy(mpm_ctx); SigCleanSignatures(); @@ -1724,7 +1550,7 @@ int SigTest04 (void) { if (PacketAlertCheck(&p, 1)) result = 1; - SigGroupCleanup(sig_list); + SigGroupCleanup(); PatternMatcherThreadDeinit(&th_v, (void *)pmt); PatternMatchDestroy(mpm_ctx); SigCleanSignatures(); @@ -1767,7 +1593,7 @@ int SigTest05 (void) { if (!PacketAlertCheck(&p, 1)) result = 1; - SigGroupCleanup(sig_list); + SigGroupCleanup(); PatternMatcherThreadDeinit(&th_v, (void *)pmt); PatternMatchDestroy(mpm_ctx); SigCleanSignatures(); @@ -1815,7 +1641,7 @@ int SigTest06 (void) { if (PacketAlertCheck(&p, 1) && PacketAlertCheck(&p, 2)) result = 1; - SigGroupCleanup(sig_list); + SigGroupCleanup(); PatternMatcherThreadDeinit(&th_v, (void *)pmt); PatternMatchDestroy(mpm_ctx); SigCleanSignatures(); @@ -1865,7 +1691,7 @@ int SigTest07 (void) { else result = 1; - SigGroupCleanup(sig_list); + SigGroupCleanup(); PatternMatcherThreadDeinit(&th_v, (void *)pmt); PatternMatchDestroy(mpm_ctx); SigCleanSignatures(); @@ -1913,7 +1739,7 @@ int SigTest08 (void) { if (PacketAlertCheck(&p, 1) && PacketAlertCheck(&p, 2)) result = 1; - SigGroupCleanup(sig_list); + SigGroupCleanup(); PatternMatcherThreadDeinit(&th_v, (void *)pmt); PatternMatchDestroy(mpm_ctx); SigCleanSignatures(); @@ -1963,7 +1789,7 @@ int SigTest09 (void) { else result = 1; - SigGroupCleanup(sig_list); + SigGroupCleanup(); PatternMatcherThreadDeinit(&th_v, (void *)pmt); PatternMatchDestroy(mpm_ctx); SigCleanSignatures(); diff --git a/src/detect.h b/src/detect.h index 8cd8b70bbb..19ba31b745 100644 --- a/src/detect.h +++ b/src/detect.h @@ -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__ */ diff --git a/src/vips.c b/src/vips.c index 8b6032ed31..1a9dea7eb7 100644 --- a/src/vips.c +++ b/src/vips.c @@ -313,6 +313,7 @@ int main(int argc, char **argv) SigTableRegisterTests(); SigRegisterTests(); //UtRunTests(); + UtCleanup(); //exit(1); //LoadConfig();