diff --git a/src/detect-address-ipv4.c b/src/detect-engine-address-ipv4.c similarity index 71% rename from src/detect-address-ipv4.c rename to src/detect-engine-address-ipv4.c index 91b7249b3a..1ea87b3c5f 100644 --- a/src/detect-address-ipv4.c +++ b/src/detect-engine-address-ipv4.c @@ -71,16 +71,17 @@ int DetectAddressGroupCutIPv4(DetectAddressGroup *a, DetectAddressGroup *b, Dete 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]); + DetectPort *port = NULL; /* default to NULL */ *c = NULL; #ifdef DBG - printf("a "); DetectAddressDataPrint(a->ad); printf("\n"); - printf("b "); DetectAddressDataPrint(b->ad); printf("\n"); - printf("a sigs: "); + printf("DetectAddressGroupCutIPv4: a "); DetectAddressDataPrint(a->ad); printf("\n"); + printf("DetectAddressGroupCutIPv4: b "); DetectAddressDataPrint(b->ad); printf("\n"); + printf("DetectAddressGroupCutIPv4: a sigs: "); SigGroupContainer *sgc = a->sh ? a->sh->head : NULL; for ( ; sgc != NULL; sgc = sgc->next) printf("%u ",sgc->s->id); - printf("\nb sigs: "); + printf("\nDetectAddressGroupCutIPv4: b sigs: "); sgc = b->sh ? b->sh->head : NULL; for ( ; sgc != NULL; sgc = sgc->next) printf("%u ",sgc->s->id); printf("\n"); @@ -92,8 +93,7 @@ int DetectAddressGroupCutIPv4(DetectAddressGroup *a, DetectAddressGroup *b, Dete } /* get a place to temporary put sigs lists */ - DetectAddressGroup *tmp; - tmp = DetectAddressGroupInit(); + DetectAddressGroup *tmp = DetectAddressGroupInit(); if (tmp == NULL) { goto error; } @@ -106,7 +106,7 @@ int DetectAddressGroupCutIPv4(DetectAddressGroup *a, DetectAddressGroup *b, Dete */ if (r == ADDRESS_LE) { #ifdef DBG - printf("cut r == ADDRESS_LE\n"); + printf("DetectAddressGroupCutIPv4: r == ADDRESS_LE\n"); #endif a->ad->ip[0] = htonl(a_ip1); a->ad->ip2[0] = htonl(b_ip1 - 1); @@ -129,16 +129,23 @@ int DetectAddressGroupCutIPv4(DetectAddressGroup *a, DetectAddressGroup *b, Dete 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 */ + SigGroupListCopy(b->sh,&tmp_c->sh); + SigGroupListCopy(a->sh,&b->sh); + + for (port = b->port; port != NULL; port = port->next) { + DetectPortInsertCopy(&tmp_c->port, port); + } + for (port = a->port; port != NULL; port = port->next) { + DetectPortInsertCopy(&b->port, port); + } #ifdef DBG SigGroupContainer *sg; -printf("A "); DetectAddressDataPrint(a->ad); printf(" "); +printf("DetectAddressGroupCutIPv4: 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(" "); +printf("DetectAddressGroupCutIPv4: 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(" "); +printf("DetectAddressGroupCutIPv4: 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] @@ -148,7 +155,7 @@ for(sg = tmp_c->sh ? b->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u " */ } else if (r == ADDRESS_GE) { #ifdef DBG - printf("cut r == ADDRESS_GE\n"); + printf("DetectAddressGroupCutIPv4: r == ADDRESS_GE\n"); #endif a->ad->ip[0] = htonl(b_ip1); a->ad->ip2[0] = htonl(a_ip1 - 1); @@ -174,13 +181,33 @@ for(sg = tmp_c->sh ? b->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u " /* '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 */ + SigGroupListCopy(a->sh,&tmp->sh); /* 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 */ - + SigGroupListCopy(tmp->sh,&tmp_c->sh); /* copy old b to c */ + SigGroupListCopy(b->sh,&a->sh); /* copy old b to a */ + SigGroupListCopy(tmp->sh,&b->sh); /* prepend old a before b */ SigGroupListClean(tmp->sh); /* clean tmp list */ + + //SigGroupListCopy(a->sh,&tmp->sh); /* store old a list */ + //SigGroupListClean(a->sh); /* clean a list */ + //SigGroupListCopy(tmp->sh,&tmp_c->sh); /* copy old b to c */ + //SigGroupListCopy(b->sh,&a->sh); /* copy old b to a */ + //SigGroupListCopy(tmp->sh,&b->sh); /* prepend old a before b */ + //SigGroupListClean(tmp->sh); /* clean tmp list */ + + for (port = a->port; port != NULL; port = port->next) { + DetectPortInsertCopy(&tmp->port, port); + } + for (port = b->port; port != NULL; port = port->next) { + DetectPortInsertCopy(&a->port, port); + } + for (port = tmp->port; port != NULL; port = port->next) { + DetectPortInsertCopy(&b->port, port); + } + for (port = tmp->port; port != NULL; port = port->next) { + DetectPortInsertCopy(&tmp_c->port, port); + } + /* we have 2 or three parts: * * 2 part: [[abab]bbb] or [bbb[baba]] @@ -199,11 +226,11 @@ for(sg = tmp_c->sh ? b->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u " */ } else if (r == ADDRESS_ES) { #ifdef DBG - printf("cut r == ADDRESS_ES\n"); + printf("DetectAddressGroupCutIPv4: r == ADDRESS_ES\n"); #endif if (a_ip1 == b_ip1) { #ifdef DBG - printf("1\n"); + printf("DetectAddressGroupCutIPv4: 1\n"); #endif a->ad->ip[0] = htonl(a_ip1); a->ad->ip2[0] = htonl(a_ip2); @@ -212,17 +239,22 @@ for(sg = tmp_c->sh ? b->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u " b->ad->ip2[0] = htonl(b_ip2); /* 'b' overlaps 'a' so 'a' needs the 'b' sigs */ - SigGroupListCopyAppend(b,a); + SigGroupListCopy(b->sh,&a->sh); + + for (port = b->port; port != NULL; port = port->next) { + DetectPortInsertCopy(&a->port, port); + } + #ifdef DBG SigGroupContainer *sg; -printf("A "); DetectAddressDataPrint(a->ad); printf(" "); +printf("DetectAddressGroupCutIPv4: 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(" "); +printf("DetectAddressGroupCutIPv4: 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"); + printf("DetectAddressGroupCutIPv4: 2\n"); #endif a->ad->ip[0] = htonl(b_ip1); a->ad->ip2[0] = htonl(a_ip1 - 1); @@ -231,12 +263,16 @@ for(sg = b->sh ? b->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u ", sg b->ad->ip2[0] = htonl(a_ip2); /* 'a' overlaps 'b' so a needs the 'a' sigs */ - SigGroupListCopyPrepend(a,b); + SigGroupListCopy(a->sh,&b->sh); + + for (port = a->port; port != NULL; port = port->next) { + DetectPortInsertCopy(&b->port, port); + } #ifdef DBG SigGroupContainer *sg; -printf("A "); DetectAddressDataPrint(a->ad); printf(" "); +printf("DetectAddressGroupCutIPv4: 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(" "); +printf("DetectAddressGroupCutIPv4: 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 { @@ -267,20 +303,39 @@ for(sg = b->sh ? b->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u ", sg /* '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 */ + SigGroupListCopy(a->sh,&tmp->sh); /* 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 */ - + SigGroupListCopy(b->sh,&tmp_c->sh); /* copy old b to c */ + SigGroupListCopy(b->sh,&a->sh); /* copy old b to a */ + SigGroupListCopy(tmp->sh,&b->sh); /* prepend old a before b */ SigGroupListClean(tmp->sh); /* clean tmp list */ + + //SigGroupListCopy(a->sh,&tmp->sh); /* store old a list */ + //SigGroupListClean(a->sh); /* clean a list */ + //SigGroupListCopy(b->sh,&tmp_c->sh); /* copy old b to c */ + //SigGroupListCopy(b->sh,&a->sh); /* copy old b to a */ + //SigGroupListCopy(tmp->sh,&b->sh); /* prepend old a before b */ + //SigGroupListClean(tmp->sh); /* clean tmp list */ + + for (port = a->port; port != NULL; port = port->next) { + DetectPortInsertCopy(&tmp->port, port); + } + for (port = b->port; port != NULL; port = port->next) { + DetectPortInsertCopy(&tmp_c->port, port); + } + for (port = b->port; port != NULL; port = port->next) { + DetectPortInsertCopy(&a->port, port); + } + for (port = tmp->port; port != NULL; port = port->next) { + DetectPortInsertCopy(&b->port, port); + } #ifdef DBG SigGroupContainer *sg; -printf("A "); DetectAddressDataPrint(a->ad); printf(" "); +printf("DetectAddressGroupCutIPv4: 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(" "); +printf("DetectAddressGroupCutIPv4: 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(" "); +printf("DetectAddressGroupCutIPv4: 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 } @@ -302,11 +357,11 @@ for(sg = tmp_c->sh ? b->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u " */ } else if (r == ADDRESS_EB) { #ifdef DBG - printf("cut r == ADDRESS_EB\n"); + printf("DetectAddressGroupCutIPv4: r == ADDRESS_EB\n"); #endif if (a_ip1 == b_ip1) { #ifdef DBG - printf("1\n"); + printf("DetectAddressGroupCutIPv4: 1\n"); #endif a->ad->ip[0] = htonl(b_ip1); a->ad->ip2[0] = htonl(b_ip2); @@ -315,21 +370,31 @@ for(sg = tmp_c->sh ? b->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u " b->ad->ip2[0] = htonl(a_ip2); /* 'b' overlaps 'a' so a needs the 'b' sigs */ - SigGroupListCopyAppend(b,tmp); + SigGroupListCopy(b->sh,&tmp->sh); SigGroupListClean(b->sh); - SigGroupListCopyAppend(a,b); - SigGroupListCopyAppend(tmp,a); + SigGroupListCopy(a->sh,&b->sh); + SigGroupListCopy(tmp->sh,&a->sh); SigGroupListClean(tmp->sh); + + for (port = b->port; port != NULL; port = port->next) { + DetectPortInsertCopy(&tmp->port, b->port); + } + for (port = a->port; port != NULL; port = port->next) { + DetectPortInsertCopy(&b->port, port); + } + for (port = tmp->port; port != NULL; port = port->next) { + DetectPortInsertCopy(&a->port, port); + } #ifdef DBG SigGroupContainer *sg; -printf("A "); DetectAddressDataPrint(a->ad); printf(" "); +printf("DetectAddressGroupCutIPv4: 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(" "); +printf("DetectAddressGroupCutIPv4: 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"); + printf("DetectAddressGroupCutIPv4: 2\n"); #endif a->ad->ip[0] = htonl(a_ip1); a->ad->ip2[0] = htonl(b_ip1 - 1); @@ -338,17 +403,21 @@ for(sg = b->sh ? b->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u ", sg b->ad->ip2[0] = htonl(b_ip2); /* 'a' overlaps 'b' so a needs the 'a' sigs */ - SigGroupListCopyPrepend(a,b); + SigGroupListCopy(a->sh,&b->sh); + + for (port = a->port; port != NULL; port = port->next) { + DetectPortInsertCopy(&b->port, port); + } #ifdef DBG SigGroupContainer *sg; -printf("A "); DetectAddressDataPrint(a->ad); printf(" "); +printf("DetectAddressGroupCutIPv4: 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(" "); +printf("DetectAddressGroupCutIPv4: 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"); + printf("DetectAddressGroupCutIPv4: 3\n"); #endif a->ad->ip[0] = htonl(a_ip1); a->ad->ip2[0] = htonl(b_ip1 - 1); @@ -374,15 +443,22 @@ for(sg = b->sh ? b->sh->head : NULL; sg != NULL; sg = sg->next) printf("%u ", sg /* '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); + SigGroupListCopy(a->sh,&b->sh); + SigGroupListCopy(a->sh,&tmp_c->sh); + + for (port = a->port; port != NULL; port = port->next) { + DetectPortInsertCopy(&b->port, port); + } + for (port = a->port; port != NULL; port = port->next) { + DetectPortInsertCopy(&tmp_c->port, port); + } #ifdef DBG SigGroupContainer *sg; -printf("A "); DetectAddressDataPrint(a->ad); printf(" "); +printf("DetectAddressGroupCutIPv4: 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(" "); +printf("DetectAddressGroupCutIPv4: 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(" "); +printf("DetectAddressGroupCutIPv4: 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 } diff --git a/src/detect-address-ipv4.h b/src/detect-engine-address-ipv4.h similarity index 100% rename from src/detect-address-ipv4.h rename to src/detect-engine-address-ipv4.h diff --git a/src/detect-address-ipv6.c b/src/detect-engine-address-ipv6.c similarity index 95% rename from src/detect-address-ipv6.c rename to src/detect-engine-address-ipv6.c index e82bf33d46..177909e3b2 100644 --- a/src/detect-address-ipv6.c +++ b/src/detect-engine-address-ipv6.c @@ -206,8 +206,7 @@ int DetectAddressGroupCutIPv6(DetectAddressGroup *a, DetectAddressGroup *b, Dete } /* get a place to temporary put sigs lists */ - DetectAddressGroup *tmp; - tmp = DetectAddressGroupInit(); + DetectAddressGroup *tmp = DetectAddressGroupInit(); if (tmp == NULL) { goto error; } @@ -239,8 +238,8 @@ int DetectAddressGroupCutIPv6(DetectAddressGroup *a, DetectAddressGroup *b, Dete 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 */ + SigGroupListCopy(b->sh,&tmp_c->sh); /* copy old b to c */ + SigGroupListCopy(a->sh,&b->sh); /* copy old b to a */ /* we have 3 parts: [bbb[baba]aaa] * part a: b_ip1 <-> a_ip1 - 1 @@ -271,11 +270,11 @@ int DetectAddressGroupCutIPv6(DetectAddressGroup *a, DetectAddressGroup *b, Dete /* '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 */ + SigGroupListCopy(a->sh,&tmp->sh); /* 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 */ + SigGroupListCopy(tmp->sh,&tmp_c->sh); /* copy old b to c */ + SigGroupListCopy(b->sh,&a->sh); /* copy old b to a */ + SigGroupListCopy(tmp->sh,&b->sh); /* prepend old a before b */ SigGroupListClean(tmp->sh); /* clean tmp list */ @@ -302,7 +301,7 @@ int DetectAddressGroupCutIPv6(DetectAddressGroup *a, DetectAddressGroup *b, Dete AddressCutIPv6Copy(b_ip2, b->ad->ip2); /* 'b' overlaps 'a' so 'a' needs the 'b' sigs */ - SigGroupListCopyAppend(b,a); + SigGroupListCopy(b->sh,&a->sh); } else if (AddressIPv6Eq(a_ip2, b_ip2) == 1) { AddressCutIPv6Copy(b_ip1, a->ad->ip); AddressCutIPv6CopySubOne(a_ip1, a->ad->ip2); @@ -311,7 +310,7 @@ int DetectAddressGroupCutIPv6(DetectAddressGroup *a, DetectAddressGroup *b, Dete AddressCutIPv6Copy(a_ip2, b->ad->ip2); /* 'a' overlaps 'b' so a needs the 'a' sigs */ - SigGroupListCopyPrepend(a,b); + SigGroupListCopy(a->sh,&b->sh); } else { AddressCutIPv6Copy(b_ip1, a->ad->ip); AddressCutIPv6CopySubOne(a_ip1, a->ad->ip2); @@ -336,11 +335,11 @@ int DetectAddressGroupCutIPv6(DetectAddressGroup *a, DetectAddressGroup *b, Dete /* '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 */ + SigGroupListCopy(a->sh,&tmp->sh); /* 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 */ + SigGroupListCopy(b->sh,&tmp_c->sh); /* copy old b to c */ + SigGroupListCopy(b->sh,&a->sh); /* copy old b to a */ + SigGroupListCopy(tmp->sh,&b->sh); /* prepend old a before b */ SigGroupListClean(tmp->sh); /* clean tmp list */ } @@ -367,10 +366,10 @@ int DetectAddressGroupCutIPv6(DetectAddressGroup *a, DetectAddressGroup *b, Dete AddressCutIPv6Copy(a_ip2, b->ad->ip2); /* 'b' overlaps 'a' so a needs the 'b' sigs */ - SigGroupListCopyAppend(b,tmp); + SigGroupListCopy(b->sh,&tmp->sh); SigGroupListClean(b->sh); - SigGroupListCopyAppend(a,b); - SigGroupListCopyAppend(tmp,a); + SigGroupListCopy(a->sh,&b->sh); + SigGroupListCopy(tmp->sh,&a->sh); SigGroupListClean(tmp->sh); } else if (AddressIPv6Eq(a_ip2, b_ip2) == 1) { AddressCutIPv6Copy(a_ip1, a->ad->ip); @@ -380,7 +379,7 @@ int DetectAddressGroupCutIPv6(DetectAddressGroup *a, DetectAddressGroup *b, Dete AddressCutIPv6Copy(b_ip2, b->ad->ip2); /* 'a' overlaps 'b' so a needs the 'a' sigs */ - SigGroupListCopyPrepend(a,b); + SigGroupListCopy(a->sh,&b->sh); } else { AddressCutIPv6Copy(a_ip1, a->ad->ip); AddressCutIPv6CopySubOne(b_ip1, a->ad->ip2); @@ -405,8 +404,8 @@ int DetectAddressGroupCutIPv6(DetectAddressGroup *a, DetectAddressGroup *b, Dete /* '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); + SigGroupListCopy(a->sh,&b->sh); + SigGroupListCopy(a->sh,&tmp_c->sh); } } diff --git a/src/detect-address-ipv6.h b/src/detect-engine-address-ipv6.h similarity index 100% rename from src/detect-address-ipv6.h rename to src/detect-engine-address-ipv6.h diff --git a/src/detect-address.c b/src/detect-engine-address.c similarity index 98% rename from src/detect-address.c rename to src/detect-engine-address.c index 49781ed5cb..2016967a17 100644 --- a/src/detect-address.c +++ b/src/detect-engine-address.c @@ -2,7 +2,11 @@ * * Copyright (c) 2008 Victor Julien * - * TODO move this out of the detection plugin structure */ + * TODO move this out of the detection plugin structure + * rename to detect-engine-address.c + * + * + */ #include "decode.h" #include "detect.h" @@ -20,7 +24,7 @@ int DetectAddressSetup (Signature *s, SigMatch *m, char *sidstr); void DetectAddressTests (void); void DetectAddressRegister (void) { - sigmatch_table[DETECT_ADDRESS].name = "address"; + sigmatch_table[DETECT_ADDRESS].name = "__address__"; sigmatch_table[DETECT_ADDRESS].Match = NULL; sigmatch_table[DETECT_ADDRESS].Setup = DetectAddressSetup; sigmatch_table[DETECT_ADDRESS].Free = NULL; @@ -69,7 +73,7 @@ void DetectAddressGroupFree(DetectAddressGroup *ag) { } /* only free the head if we have the original */ - if (ag->sh != NULL && !(ag->flags & SIG_GROUP_COPY)) { + if (ag->sh != NULL && !(ag->flags & ADDRESS_GROUP_SIGGROUPHEAD_COPY)) { SigGroupHeadFree(ag->sh); } ag->sh = NULL; @@ -78,6 +82,11 @@ void DetectAddressGroupFree(DetectAddressGroup *ag) { DetectAddressGroupsHeadFree(ag->dst_gh); } + if (ag->port != NULL && !(ag->flags & ADDRESS_GROUP_PORTS_COPY)) { + DetectPortCleanupList(ag->port); + ag->port = NULL; + } + detect_address_group_memory -= sizeof(DetectAddressGroup); detect_address_group_free_cnt++; free(ag); @@ -131,13 +140,6 @@ void DetectAddressGroupPrintList(DetectAddressGroup *head) { 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"); } } @@ -168,22 +170,28 @@ 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) { + //printf("r == EB, inserting here\n"); + /* insert here */ ag->prev = cur->prev; ag->next = cur; + cur->prev = ag; if (*head == cur) { *head = ag; + } else { + ag->prev->next = ag; } return 0; } } + //printf("default append\n"); ag->prev = prev_cur; prev_cur->next = ag; } else { @@ -234,6 +242,10 @@ static DetectAddressGroup *GetHeadPtr(DetectAddressGroupsHead *gh, DetectAddress * */ int DetectAddressGroupInsert(DetectAddressGroupsHead *gh, DetectAddressGroup *new) { DetectAddressGroup *head = NULL; + + if (new == NULL) + return 0; + #ifdef DBG printf("DetectAddressGroupInsert: inserting (sig %u) ", new->sh?new->sh->sig_cnt:0); DetectAddressDataPrint(new->ad); printf("\n"); DetectAddressGroupPrintList(gh->ipv4_head); @@ -257,24 +269,28 @@ int DetectAddressGroupInsert(DetectAddressGroupsHead *gh, DetectAddressGroup *ne /* if so, handle that */ if (r == ADDRESS_EQ) { #ifdef DBG - printf("ADDRESS_EQ %p %p\n", cur, new); + printf("DetectAddressGroupInsert: ADDRESS_EQ %p %p\n", cur, new); #endif /* exact overlap/match */ if (cur != new) { - SigGroupListCopyAppend(new,cur); + DetectPort *port = new->port; + for ( ; port != NULL; port = port->next) { + DetectPortInsertCopy(&cur->port,port); + } + SigGroupListCopy(new->sh,&cur->sh); DetectAddressGroupFree(new); return 0; } return 1; } else if (r == ADDRESS_GT) { #ifdef DBG - printf("ADDRESS_GT\n"); + printf("DetectAddressGroupInsert: 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"); + printf("DetectAddressGroupInsert: adding GT\n"); #endif /* put in the list */ new->prev = cur; @@ -283,7 +299,7 @@ int DetectAddressGroupInsert(DetectAddressGroupsHead *gh, DetectAddressGroup *ne } } else if (r == ADDRESS_LT) { #ifdef DBG - printf("ADDRESS_LT\n"); + printf("DetectAddressGroupInsert: ADDRESS_LT\n"); #endif /* see if we need to insert the ag anywhere */ /* put in the list */ @@ -307,7 +323,7 @@ int DetectAddressGroupInsert(DetectAddressGroupsHead *gh, DetectAddressGroup *ne } else if (r == ADDRESS_ES) { #ifdef DBG - printf("ADDRESS_ES\n"); + printf("DetectAddressGroupInsert: ADDRESS_ES\n"); #endif DetectAddressGroup *c = NULL; r = DetectAddressGroupCut(cur,new,&c); @@ -350,7 +366,7 @@ int DetectAddressGroupInsert(DetectAddressGroupsHead *gh, DetectAddressGroup *ne return 1; } else if (r == ADDRESS_GE) { #ifdef DBG - printf("ADDRESS_GE\n"); + printf("DetectAddressGroupInsert: ADDRESS_GE\n"); #endif DetectAddressGroup *c = NULL; r = DetectAddressGroupCut(cur,new,&c); @@ -368,10 +384,9 @@ int DetectAddressGroupInsert(DetectAddressGroupsHead *gh, DetectAddressGroup *ne /* head is NULL, so get a group and set head to it */ } else { #ifdef DBG -printf("Setting new head\n"); + printf("DetectAddressGroupInsert: Setting new head\n"); #endif head = new; - if (SetHeadPtr(gh,head) < 0) goto error; } @@ -1157,9 +1172,13 @@ DetectAddressGroup * DetectAddressLookupGroup(DetectAddressGroupsHead *gh, Address *a) { DetectAddressGroup *g; + //printf("DetectAddressLookupGroup: start %p\n", gh); + if (gh == NULL) return NULL; + //printf("DetectAddressLookupGroup: gh 4%p 6%p a%p\n", gh->ipv4_head, gh->ipv6_head, gh->any_head); + /* XXX should we really do this check every time we run * this function? */ if (a->family == AF_INET) @@ -1169,7 +1188,10 @@ DetectAddressLookupGroup(DetectAddressGroupsHead *gh, Address *a) { else g = gh->any_head; + //printf("g %p\n", g); + for ( ; g != NULL; g = g->next) { + //printf("DetectAddressLookupGroup: checking \n"); DetectAddressDataPrint(g->ad); printf("\n"); if (DetectAddressMatch(g->ad,a) == 1) { return g; } diff --git a/src/detect-address.h b/src/detect-engine-address.h similarity index 95% rename from src/detect-address.h rename to src/detect-engine-address.h index e293e6be86..61a8620df3 100644 --- a/src/detect-address.h +++ b/src/detect-engine-address.h @@ -16,6 +16,9 @@ enum { #define ADDRESS_FLAG_ANY 0x1 #define ADDRESS_FLAG_NOT 0x2 +#define ADDRESS_GROUP_SIGGROUPHEAD_COPY 0x01 +#define ADDRESS_GROUP_PORTS_COPY 0x02 + typedef struct DetectAddressData_ { /* XXX convert to use a Address datatype to replace family, ip,ip2*/ u_int8_t family; @@ -30,7 +33,7 @@ typedef struct DetectAddressGroup_ { /* XXX ptr to rules, or PortGroup or whatever */ struct DetectAddressGroupsHead_ *dst_gh; - + struct DetectPort_ *port; /* signatures that belong in this group */ struct _SigGroupHead *sh; u_int8_t flags; diff --git a/src/detect-mpm.c b/src/detect-engine-mpm.c similarity index 92% rename from src/detect-mpm.c rename to src/detect-engine-mpm.c index db97b1847c..54e677ae17 100644 --- a/src/detect-mpm.c +++ b/src/detect-engine-mpm.c @@ -41,21 +41,13 @@ void PacketPatternCleanup(ThreadVars *t, PatternMatcherThread *pmt) { /* XXX remove this once we got rid of the global mpm_ctx */ void PatternMatchDestroy(MpmCtx *mc) { - u_int8_t instance = 0; - - for (instance = 0; instance < MPM_INSTANCE_MAX; instance++) - mc[instance].DestroyCtx(&mc[instance]); + mc->DestroyCtx(mc); } /* TODO remove this when we move to the rule groups completely */ void PatternMatchPrepare(MpmCtx *mc) { - u_int8_t instance = 0; - - /* intialize contexes */ - for (instance = 0; instance < MPM_INSTANCE_MAX; instance++) { - MpmInitCtx(&mc[instance], MPM_WUMANBER); - } + MpmInitCtx(mc, MPM_WUMANBER); } @@ -93,17 +85,21 @@ void PatternMatchDestroyGroup(SigGroupHead *sh) { * XXX do error checking * XXX rewrite the COPY stuff */ -int PatternMatchPrepareGroup(SigGroupHead *sh) +int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) { Signature *s; - SigGroupContainer *sc; u_int32_t co_cnt = 0; u_int32_t ur_cnt = 0; u_int32_t cnt = 0; + u_int32_t sig; /* see if this head has content and/or uricontent */ - for (sc = sh->head; sc != NULL; sc = sc->next) { - s = sc->s; + for (sig = 0; sig < sh->sig_cnt; sig++) { + u_int32_t num = sh->match_array[sig]; + + s = de_ctx->sig_array[num]; + if (s == NULL) + continue; /* find flow setting of this rule */ SigMatch *sm; @@ -141,8 +137,13 @@ int PatternMatchPrepareGroup(SigGroupHead *sh) } /* for each signature in this group do */ - for (sc = sh->head; sc != NULL; sc = sc->next) { - s = sc->s; + for (sig = 0; sig < sh->sig_cnt; sig++) { + u_int32_t num = sh->match_array[sig]; + + s = de_ctx->sig_array[num]; + if (s == NULL) + continue; + cnt++; /* find flow setting of this rule */ diff --git a/src/detect-mpm.h b/src/detect-engine-mpm.h similarity index 84% rename from src/detect-mpm.h rename to src/detect-engine-mpm.h index 967726c256..0ef791de45 100644 --- a/src/detect-mpm.h +++ b/src/detect-engine-mpm.h @@ -1,13 +1,14 @@ #ifndef __DETECT_MPM_H__ #define __DETECT_MPM_H__ -MpmCtx mpm_ctx[MPM_INSTANCE_MAX]; +/* XXX remove once */ +MpmCtx mpm_ctx[1]; u_int32_t PacketPatternMatch(ThreadVars *, PatternMatcherThread *, Packet *); int PacketPatternScan(ThreadVars *t, Packet *p, u_int8_t mpm_instance); void PacketPatternCleanup(ThreadVars *, PatternMatcherThread *); void PatternMatchPrepare(MpmCtx *); -int PatternMatchPrepareGroup(SigGroupHead *); +int PatternMatchPrepareGroup(DetectEngineCtx *, SigGroupHead *); void PatternMatcherThreadInfo(ThreadVars *, PatternMatcherThread *); void PatternMatchDestroy(MpmCtx *); void PatternMatchDestroyGroup(SigGroupHead *); diff --git a/src/detect-engine-port.c b/src/detect-engine-port.c new file mode 100644 index 0000000000..ec913474b5 --- /dev/null +++ b/src/detect-engine-port.c @@ -0,0 +1,1294 @@ +/* Ports part of the detection engine. + * + * Copyright (c) 2008 Victor Julien + * + * TODO VJ + * - move this out of the detection plugin structure + * - more unittesting + * + * + * */ + +#include "decode.h" +#include "detect.h" +#include "flow-var.h" + +#include "util-cidr.h" +#include "util-unittest.h" + +#include "detect-engine-siggroup.h" +#include "detect-engine-port.h" + +int DetectPortSetupTmp (Signature *s, SigMatch *m, char *sidstr); +void DetectPortTests (void); + +void DetectPortRegister (void) { + sigmatch_table[DETECT_PORT].name = "__port__"; + sigmatch_table[DETECT_PORT].Match = NULL; + sigmatch_table[DETECT_PORT].Setup = DetectPortSetupTmp; + sigmatch_table[DETECT_PORT].Free = NULL; + sigmatch_table[DETECT_PORT].RegisterTests = DetectPortTests; +} + +/* prototypes */ +void DetectPortPrint(DetectPort *); +int DetectPortCut(DetectPort *, DetectPort *, DetectPort **); +int DetectPortCutNot(DetectPort *, DetectPort **); +int DetectPortCut(DetectPort *, DetectPort *, DetectPort **); +DetectPort *DetectPortCopy(DetectPort *src); +DetectPort *PortParse(char *str); +int DetectPortCmp(DetectPort *, DetectPort *); + +/* memory usage counters */ +static u_int32_t detect_port_memory = 0; +static u_int32_t detect_port_init_cnt = 0; +static u_int32_t detect_port_free_cnt = 0; + +static u_int32_t detect_port_hash_add_cnt = 0; +static u_int32_t detect_port_hash_add_coll_cnt = 0; +static u_int32_t detect_port_hash_lookup_cnt = 0; +static u_int32_t detect_port_hash_lookup_miss_cnt = 0; +static u_int32_t detect_port_hash_lookup_hit_cnt = 0; +static u_int32_t detect_port_hash_lookup_loop_cnt = 0; + +DetectPort *DetectPortInit(void) { + DetectPort *dp = malloc(sizeof(DetectPort)); + if (dp == NULL) { + return NULL; + } + memset(dp,0,sizeof(DetectPort)); + + detect_port_memory += sizeof(DetectPort); + detect_port_init_cnt++; + + return dp; +} + +/* free a DetectPort object */ +void DetectPortFree(DetectPort *dp) { + if (dp == NULL) + return; + + /* only free the head if we have the original */ + if (dp->sh != NULL && !(dp->flags & PORT_SIGGROUPHEAD_COPY)) { + SigGroupHeadFree(dp->sh); + } + dp->sh = NULL; + + detect_port_memory -= sizeof(DetectPort); + detect_port_free_cnt++; + free(dp); +} + +void DetectPortPrintMemory(void) { + printf(" * Port memory stats (DetectPort %u):\n", sizeof(DetectPort)); + printf(" - detect_port_memory %u\n", detect_port_memory); + printf(" - detect_port_init_cnt %u\n", detect_port_init_cnt); + printf(" - detect_port_free_cnt %u\n", detect_port_free_cnt); + printf(" - outstanding ports %u\n", detect_port_init_cnt - detect_port_free_cnt); + printf(" * Port memory stats done\n"); +#if 0 + printf(" x detect_port_hash_add_cnt %u\n", detect_port_hash_add_cnt); + printf(" x detect_port_hash_add_insert_cnt %u\n", detect_port_hash_add_insert_cnt); + printf(" x detect_port_hash_add_coll_cnt %u\n", detect_port_hash_add_coll_cnt); + printf(" x detect_port_hash_lookup_cnt %u\n", detect_port_hash_lookup_cnt); + printf(" x detect_port_hash_lookup_miss_cnt %u\n", detect_port_hash_lookup_miss_cnt); + printf(" x detect_port_hash_lookup_hit_cnt %u\n", detect_port_hash_lookup_hit_cnt); + printf(" x detect_port_hash_lookup_loop_cnt %u\n", detect_port_hash_lookup_loop_cnt); +#endif +} + +/* used to see if the exact same portrange exists in the list + * returns a ptr to the match, or NULL if no match + */ +DetectPort *DetectPortLookup(DetectPort *head, DetectPort *dp) { + DetectPort *cur; + + if (head != NULL) { + for (cur = head; cur != NULL; cur = cur->next) { + if (DetectPortCmp(cur, dp) == PORT_EQ) + return cur; + } + } + + return NULL; +} + +void DetectPortPrintList(DetectPort *head) { + DetectPort *cur; + u_int16_t cnt = 0; + + printf("list:\n"); + if (head != NULL) { + for (cur = head; cur != NULL; cur = cur->next) { + printf("SIGS %6u ", cur->sh ? cur->sh->sig_cnt : 0); + + DetectPortPrint(cur); + cnt++; + printf("\n"); + } + } + printf("endlist (cnt %u)\n", cnt); +} + +void DetectPortCleanupList (DetectPort *head) { + if (head == NULL) + return; + + DetectPort *cur, *next; + + for (cur = head; cur != NULL; ) { + next = cur->next; + + DetectPortFree(cur); + cur = next; + } + + head = NULL; +} + +/* do a sorted insert, where the top of the list should be the biggest + * port range. + * + * XXX current sorting only works for overlapping ranges */ +int DetectPortAdd(DetectPort **head, DetectPort *dp) { + DetectPort *cur, *prev_cur = NULL; + + //printf("DetectPortAdd: adding "); DetectPortPrint(ag); printf("\n"); + + if (*head != NULL) { + for (cur = *head; cur != NULL; cur = cur->next) { + prev_cur = cur; + int r = DetectPortCmp(dp,cur); + if (r == PORT_EB) { + /* insert here */ + dp->prev = cur->prev; + dp->next = cur; + + cur->prev = dp; + if (*head == cur) { + *head = dp; + } else { + dp->prev->next = dp; + } + return 0; + } + } + dp->prev = prev_cur; + prev_cur->next = dp; + } else { + *head = dp; + } + + return 0; +} + +int DetectPortInsertCopy(DetectPort **head, DetectPort *new) { + DetectPort *copy = DetectPortCopySingle(new); + + if (copy != NULL) { + //printf("DetectPortInsertCopy: "); DetectPortPrint(copy); printf("\n"); + } + + return DetectPortInsert(head, copy); +} + +//#define DBG +/* function for inserting a port group oject. This also makes sure + * SigGroupContainer lists are handled correctly. + * + * returncodes + * -1: error + * 0: not inserted, memory of new is freed + * 1: inserted + * */ +int DetectPortInsert(DetectPort **head, DetectPort *new) { + if (new == NULL) + return 0; + +#ifdef DBG + printf("DetectPortInsert: inserting (sig %u) ", new->sh ? new->sh->sig_cnt : 0); DetectPortPrint(new); printf("\n"); + //DetectPortPrintList(*head); +#endif + + /* see if it already exists or overlaps with existing ag's */ + if (*head != NULL) { + DetectPort *cur = NULL; + int r = 0; + + for (cur = *head; cur != NULL; cur = cur->next) { +// printf("DetectPortInsert: cur %p ",cur); DetectPortPrint(cur); printf("\n"); +// DetectPortPrintList(cur); +// printf("DetectPortInsert: cur end ========\n"); + r = DetectPortCmp(new,cur); + if (r == PORT_ER) { + printf("PORT_ER DetectPortCmp compared:\n"); + DetectPortPrint(new); printf(" vs. "); + DetectPortPrint(cur); printf("\n"); + goto error; + } + /* if so, handle that */ + if (r == PORT_EQ) { +#ifdef DBG + printf("DetectPortInsert: PORT_EQ %p %p\n", cur, new); +#endif + /* exact overlap/match */ + if (cur != new) { + SigGroupHeadCopySigs(new->sh,&cur->sh); + DetectPortFree(new); + return 0; + } + return 1; + } else if (r == PORT_GT) { +#ifdef DBG + printf("DetectPortInsert: PORT_GT (cur->next %p)\n", cur->next); +#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("DetectPortInsert: adding GT\n"); +#endif + /* put in the list */ + new->prev = cur; + cur->next = new; +/* + printf("DetectPortInsert: cur %p ",cur); DetectPortPrint(cur); printf("\n"); + DetectPortPrintList(cur); + printf("DetectPortInsert: cur end ========\n"); + printf("DetectPortInsert: new %p ",new); DetectPortPrint(new); printf("\n"); + DetectPortPrintList(new); + printf("DetectPortInsert: new end ========\n"); +*/ + return 1; + } else { + //printf("cur->next "); DetectPortPrint(cur->next); printf("\n"); + } + } else if (r == PORT_LT) { +#ifdef DBG + printf("DetectPortInsert: PORT_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; + } + return 1; + + /* alright, those were the simple cases, + * lets handle the more complex ones now */ + + } else if (r == PORT_ES) { +#ifdef DBG + printf("DetectPortInsert: PORT_ES\n"); +#endif + DetectPort *c = NULL; + r = DetectPortCut(cur,new,&c); + DetectPortInsert(head, new); + if (c) { +#ifdef DBG + printf("DetectPortInsert: inserting C (%p) ",c); DetectPortPrint(c); printf("\n"); +#endif + DetectPortInsert(head, c); + } + return 1; + } else if (r == PORT_EB) { +#ifdef DBG + printf("DetectPortInsert: PORT_EB\n"); +#endif + DetectPort *c = NULL; + r = DetectPortCut(cur,new,&c); + //printf("DetectPortCut returned %d\n", r); + DetectPortInsert(head, new); + if (c) { +#ifdef DBG + printf("DetectPortInsert: inserting C "); DetectPortPrint(c); printf("\n"); +#endif + DetectPortInsert(head, c); + } + return 1; + } else if (r == PORT_LE) { +#ifdef DBG + printf("DetectPortInsert: PORT_LE\n"); +#endif + DetectPort *c = NULL; + r = DetectPortCut(cur,new,&c); + DetectPortInsert(head, new); + if (c) { +#ifdef DBG + printf("DetectPortInsert: inserting C "); DetectPortPrint(c); printf("\n"); +#endif + DetectPortInsert(head, c); + } + return 1; + } else if (r == PORT_GE) { +#ifdef DBG + printf("DetectPortInsert: PORT_GE\n"); +#endif + DetectPort *c = NULL; + r = DetectPortCut(cur,new,&c); + DetectPortInsert(head, new); + if (c) { +#ifdef DBG + printf("DetectPortInsert: inserting C "); DetectPortPrint(c); printf("\n"); +#endif + DetectPortInsert(head, c); + } + return 1; + } + } + + /* head is NULL, so get a group and set head to it */ + } else { +#ifdef DBG + printf("DetectPortInsert: Setting new head\n"); +#endif + *head = new; + } + + return 1; +error: + /* XXX */ + return -1; +} + +int DetectPortSetup(DetectPort **head, char *s) { + DetectPort *ad = NULL; + int r = 0; + + /* parse the address */ + ad = PortParse(s); + if (ad == NULL) { + printf("PortParse error \"%s\"\n",s); + goto error; + } + + /* handle the not case, we apply the negation + * then insert the part(s) */ + if (ad->flags & PORT_FLAG_NOT) { + DetectPort *ad2 = NULL; + + if (DetectPortCutNot(ad,&ad2) < 0) { + goto error; + } + + /* normally a 'not' will result in two ad's + * unless the 'not' is on the start or end + * of the address space (e.g. 0.0.0.0 or + * 255.255.255.255). */ + if (ad2 != NULL) { + if (DetectPortInsert(head, ad2) < 0) + goto error; + } + } + + r = DetectPortInsert(head, ad); + if (r < 0) + goto error; + + /* if any, insert 0.0.0.0/0 and ::/0 as well */ + if (r == 1 && ad->flags & PORT_FLAG_ANY) { + ad = PortParse("0:65535"); + if (ad == NULL) + goto error; + + if (DetectPortInsert(head, ad) < 0) + goto error; + } + + return 0; + +error: + printf("DetectPortSetup error\n"); + /* XXX cleanup */ + return -1; +} + +/* XXX error handling */ +int DetectPortParse2(DetectPort **head, DetectPort **nhead, char *s,int negate) { + int i, x; + int o_set = 0, n_set = 0; + int depth = 0; + size_t size = strlen(s); + char address[1024] = ""; + + for (i = 0, x = 0; i < size && x < sizeof(address); i++) { + address[x] = s[i]; + x++; + + if (!o_set && s[i] == '!') { + n_set = 1; + x--; + } else if (s[i] == '[') { + if (!o_set) { + o_set = 1; + x = 0; + } + depth++; + } else if (s[i] == ']') { + if (depth == 1) { + address[x-1] = '\0'; + x = 0; + + DetectPortParse2(head,nhead,address,negate ? negate : n_set); + n_set = 0; + } + depth--; + } else if (depth == 0 && s[i] == ',') { + if (o_set == 1) { + o_set = 0; + } else { + address[x-1] = '\0'; + + if (negate == 0 && n_set == 0) { + DetectPortSetup(head,address); + } else { + DetectPortSetup(nhead,address); + } + n_set = 0; + } + x = 0; + } else if (depth == 0 && i == size-1) { + address[x] = '\0'; + x = 0; + + if (negate == 0 && n_set == 0) { + DetectPortSetup(head,address); + } else { + DetectPortSetup(nhead,address); + } + n_set = 0; + } + } + + return 0; +//error: +// return -1; +} + +int DetectPortMergeNot(DetectPort **head, DetectPort **nhead) { + DetectPort *ad; + DetectPort *ag, *ag2; + int r = 0; + + /* step 0: if the head list is empty, but the nhead list isn't + * we have a pure not thingy. In that case we add a 0:65535 + * first. */ + if (*head == NULL && *nhead != NULL) { + r = DetectPortSetup(head,"0:65535"); + if (r < 0) { + goto error; + } + } + + /* step 1: insert our ghn members into the gh list */ + for (ag = *nhead; ag != NULL; ag = ag->next) { + /* work with a copy of the ad so we can easily clean up + * the ghn group later. */ + ad = DetectPortCopy(ag); + if (ad == NULL) { + goto error; + } + r = DetectPortInsert(head,ad); + if (r < 0) { + goto error; + } + } + + /* step 2: pull the address blocks that match our 'not' blocks */ + for (ag = *nhead; ag != NULL; ag = ag->next) { + for (ag2 = *head; ag2 != NULL; ) { + r = DetectPortCmp(ag,ag2); + if (r == PORT_EQ || r == PORT_EB) { /* XXX more ??? */ + if (ag2->prev == NULL) { + *head = ag2->next; + } else { + ag2->prev->next = ag2->next; + } + + if (ag2->next != NULL) { + ag2->next->prev = ag2->prev; + } + /* store the next ptr and remove the group */ + DetectPort *next_ag2 = ag2->next; + DetectPortFree(ag2); + ag2 = next_ag2; + } else { + ag2 = ag2->next; + } + } + } + + return 0; +error: + return -1; +} + +int DetectPortParse(DetectPort **head, char *str) { + int r; + + DetectPort *nhead = NULL; + + r = DetectPortParse2(head,&nhead,str,/* start with negate no */0); + if (r < 0) { + goto error; + } + + /* merge the 'not' address groups */ + if (DetectPortMergeNot(head,&nhead) < 0) { + goto error; + } + + /* free the temp negate head */ + DetectPortFree(nhead); + return 0; +error: + DetectPortFree(nhead); + return -1; +} + +int DetectPortCut(DetectPort *a, DetectPort *b, DetectPort **c) { + u_int32_t a_port1 = a->port;//ntohl(a->port); + u_int32_t a_port2 = a->port2;//ntohl(a->port2); + u_int32_t b_port1 = b->port;//ntohl(b->port); + u_int32_t b_port2 = b->port2;//ntohl(b->port2); + + /* default to NULL */ + *c = NULL; + + int r = DetectPortCmp(a,b); + if (r != PORT_ES && r != PORT_EB && r != PORT_LE && r != PORT_GE) { + printf("DetectPortCut: we shouldn't be here\n"); + goto error; + } + + /* get a place to temporary put sigs lists */ + DetectPort *tmp = NULL; + tmp = DetectPortInit(); + if (tmp == NULL) { + goto error; + } + memset(tmp,0,sizeof(DetectPort)); + + /* we have 3 parts: [aaa[abab]bbb] + * part a: a_port1 <-> b_port1 - 1 + * part b: b_port1 <-> a_port2 + * part c: a_port2 + 1 <-> b_port2 + */ + if (r == PORT_LE) { +#ifdef DBG + printf("DetectPortCut: cut r == PORT_LE\n"); +#endif + a->port = a_port1; + a->port2 = b_port1 - 1; + + b->port = b_port1; + b->port2 = a_port2; + + DetectPort *tmp_c; + tmp_c = DetectPortInit(); + if (tmp_c == NULL) { + goto error; + } + + tmp_c->port = a_port2 + 1; + tmp_c->port2 = b_port2; + *c = tmp_c; + + SigGroupHeadCopySigs(b->sh,&tmp_c->sh); /* copy old b to c */ + SigGroupHeadCopySigs(a->sh,&b->sh); /* copy old b to a */ + + /* we have 3 parts: [bbb[baba]aaa] + * part a: b_port1 <-> a_port1 - 1 + * part b: a_port1 <-> b_port2 + * part c: b_port2 + 1 <-> a_port2 + */ + } else if (r == PORT_GE) { +#ifdef DBG + printf("DetectPortCut: cut r == PORT_GE\n"); +#endif + a->port = b_port1; + a->port2 = a_port1 - 1; + + b->port = a_port1; + b->port2 = b_port2; + + DetectPort *tmp_c; + tmp_c = DetectPortInit(); + if (tmp_c == NULL) { + goto error; + } + + tmp_c->port = b_port2 + 1; + tmp_c->port2 = a_port2; + *c = tmp_c; + + /* 'a' gets clean and then 'b' sigs + * 'b' gets clean, then 'a' then 'b' sigs + * 'c' gets 'a' sigs */ + SigGroupHeadCopySigs(a->sh,&tmp->sh); /* store old a list */ + SigGroupHeadClearSigs(a->sh); /* clean a list */ + SigGroupHeadCopySigs(tmp->sh,&tmp_c->sh); /* copy old b to c */ + SigGroupHeadCopySigs(b->sh,&a->sh); /* copy old b to a */ + SigGroupHeadCopySigs(tmp->sh,&b->sh); /* prepend old a before b */ + + SigGroupHeadClearSigs(tmp->sh); /* clean tmp list */ + /* we have 2 or three parts: + * + * 2 part: [[abab]bbb] or [bbb[baba]] + * part a: a_port1 <-> a_port2 + * part b: a_port2 + 1 <-> b_port2 + * + * part a: b_port1 <-> a_port1 - 1 + * part b: a_port1 <-> a_port2 + * + * 3 part [bbb[aaa]bbb] + * becomes[aaa[bbb]ccc] + * + * part a: b_port1 <-> a_port1 - 1 + * part b: a_port1 <-> a_port2 + * part c: a_port2 + 1 <-> b_port2 + */ + } else if (r == PORT_ES) { +#ifdef DBG + printf("DetectPortCut: cut r == PORT_ES\n"); +#endif + if (a_port1 == b_port1) { +#ifdef DBG + printf("DetectPortCut: 1\n"); +#endif + a->port = a_port1; + a->port2 = a_port2; + + b->port = a_port2 + 1; + b->port2 = b_port2; + + /* 'b' overlaps 'a' so 'a' needs the 'b' sigs */ + SigGroupHeadCopySigs(b->sh,&a->sh); + + } else if (a_port2 == b_port2) { +#ifdef DBG + printf("DetectPortCut: 2\n"); +#endif + a->port = b_port1; + a->port2 = a_port1 - 1; + + b->port = a_port1; + b->port2 = a_port2; + + /* 'a' overlaps 'b' so a needs the 'a' sigs */ + SigGroupHeadCopySigs(a->sh,&b->sh); + } else { +#ifdef DBG + printf("DetectPortCut: 3\n"); +#endif + a->port = b_port1; + a->port2 = a_port1 - 1; + + b->port = a_port1; + b->port2 = a_port2; + + DetectPort *tmp_c; + tmp_c = DetectPortInit(); + if (tmp_c == NULL) { + goto error; + } + + tmp_c->port = a_port2 + 1; + tmp_c->port2 = b_port2; + *c = tmp_c; + + /* 'a' gets clean and then 'b' sigs + * 'b' gets clean, then 'a' then 'b' sigs + * 'c' gets 'b' sigs */ + SigGroupHeadCopySigs(a->sh,&tmp->sh); /* store old a list */ + SigGroupHeadClearSigs(a->sh); /* clean a list */ + SigGroupHeadCopySigs(b->sh,&tmp_c->sh); /* copy old b to c */ + SigGroupHeadCopySigs(b->sh,&a->sh); /* copy old b to a */ + SigGroupHeadCopySigs(tmp->sh,&b->sh); /* prepend old a before b */ + + SigGroupHeadClearSigs(tmp->sh); /* clean tmp list */ + } + /* we have 2 or three parts: + * + * 2 part: [[baba]aaa] or [aaa[abab]] + * part a: b_port1 <-> b_port2 + * part b: b_port2 + 1 <-> a_port2 + * + * part a: a_port1 <-> b_port1 - 1 + * part b: b_port1 <-> b_port2 + * + * 3 part [aaa[bbb]aaa] + * becomes[aaa[bbb]ccc] + * + * part a: a_port1 <-> b_port2 - 1 + * part b: b_port1 <-> b_port2 + * part c: b_port2 + 1 <-> a_port2 + */ + } else if (r == PORT_EB) { +#ifdef DBG + printf("DetectPortCut: cut r == PORT_EB\n"); +#endif + if (a_port1 == b_port1) { +#ifdef DBG + printf("DetectPortCut: 1\n"); +#endif + a->port = b_port1; + a->port2 = b_port2; + + b->port = b_port2 + 1; + b->port2 = a_port2; + + /* 'b' overlaps 'a' so a needs the 'b' sigs */ + SigGroupHeadCopySigs(b->sh,&tmp->sh); + SigGroupHeadClearSigs(b->sh); + SigGroupHeadCopySigs(a->sh,&b->sh); + SigGroupHeadCopySigs(tmp->sh,&a->sh); + + SigGroupHeadClearSigs(tmp->sh); + } else if (a_port2 == b_port2) { +#ifdef DBG + printf("DetectPortCut: 2\n"); +#endif + a->port = a_port1; + a->port2 = b_port1 - 1; + + b->port = b_port1; + b->port2 = b_port2; + + /* 'a' overlaps 'b' so a needs the 'a' sigs */ + SigGroupHeadCopySigs(a->sh,&b->sh); + } else { +#ifdef DBG + printf("DetectPortCut: 3\n"); +#endif + a->port = a_port1; + a->port2 = b_port1 - 1; + + b->port = b_port1; + b->port2 = b_port2; + + DetectPort *tmp_c; + tmp_c = DetectPortInit(); + if (tmp_c == NULL) { + goto error; + } + + tmp_c->port = b_port2 + 1; + tmp_c->port2 = a_port2; + *c = tmp_c; + + SigGroupHeadCopySigs(a->sh,&b->sh); + SigGroupHeadCopySigs(a->sh,&tmp_c->sh); + } + } + + /* XXX free tmp */ + DetectPortFree(tmp); + return 0; + +error: + /* XXX free tmp */ + DetectPortFree(tmp); + return -1; + + return -1; +} + +int DetectPortCutNot(DetectPort *a, DetectPort **b) { + u_int16_t a_port1 = a->port; + u_int16_t a_port2 = a->port2; + + /* default to NULL */ + *b = NULL; + + if (a_port1 != 0x0000 && a_port2 != 0xFFFF) { + a->port = 0x0000; + a->port2 = a_port1 - 1; + + DetectPort *tmp_b; + tmp_b = DetectPortInit(); + if (tmp_b == NULL) { + goto error; + } + + tmp_b->port = a_port2 + 1; + tmp_b->port2 = 0xFFFF; + *b = tmp_b; + + } else if (a_port1 == 0x0000 && a_port2 != 0xFFFF) { + a->port = a_port2 + 1; + a->port2 = 0xFFFF; + + } else if (a_port1 != 0x0000 && a_port2 == 0xFFFF) { + a->port = 0x0000; + a->port2 = a_port1 - 1; + } else { + goto error; + } + + return 0; + +error: + return -1; + + return -1; +} + +int DetectPortCmp(DetectPort *a, DetectPort *b) { + /* check any */ + if (a->flags & PORT_FLAG_ANY && b->flags & PORT_FLAG_ANY) + return PORT_EQ; + if (a->flags & PORT_FLAG_ANY && !(b->flags & PORT_FLAG_ANY)) + return PORT_LT; + if (!(a->flags & PORT_FLAG_ANY) && b->flags & PORT_FLAG_ANY) + return PORT_GT; + + u_int16_t a_port1 = a->port; //ntohl(a->port); + u_int16_t a_port2 = a->port2; //ntohl(a->port2); + u_int16_t b_port1 = b->port; //ntohl(b->port); + u_int16_t b_port2 = b->port2; //ntohl(b->port2); + + /* PORT_EQ */ + if (a_port1 == b_port1 && a_port2 == b_port2) { + //printf("PORT_EQ\n"); + return PORT_EQ; + /* PORT_ES */ + } else if (a_port1 >= b_port1 && a_port1 <= b_port2 && a_port2 <= b_port2) { + //printf("PORT_ES\n"); + return PORT_ES; + /* PORT_EB */ + } else if (a_port1 <= b_port1 && a_port2 >= b_port2) { + //printf("PORT_EB\n"); + return PORT_EB; + } else if (a_port1 < b_port1 && a_port2 < b_port2 && a_port2 >= b_port1) { + //printf("PORT_LE\n"); + return PORT_LE; + } else if (a_port1 < b_port1 && a_port2 < b_port2) { + //printf("PORT_LT\n"); + return PORT_LT; + } else if (a_port1 > b_port1 && a_port1 <= b_port2 && a_port2 > b_port2) { + //printf("PORT_GE\n"); + return PORT_GE; + } else if (a_port1 > b_port2) { + //printf("PORT_GT\n"); + return PORT_GT; + } else { + /* should be unreachable */ + printf("Internal Error: should be unreachable\n"); + } + + return PORT_ER; +} + +DetectPort *PortParse(char *str) { + char *portdup = strdup(str); + char *port2 = NULL; + + DetectPort *dp = DetectPortInit(); + if (dp == NULL) + goto error; + + /* we dup so we can put a nul-termination in it later */ + char *port = portdup; + + /* handle the negation case */ + if (port[0] == '!') { + dp->flags |= PORT_FLAG_NOT; + port++; + } + + /* see if the address is an ipv4 or ipv6 address */ + if ((port2 = strchr(port, ':')) != NULL) { + /* 1.2.3.4-1.2.3.6 range format */ + port[port2 - port] = '\0'; + port2++; + dp->port = atoi(port); + if (strcmp(port2,"") != 0) + dp->port2 = atoi(port2); + else + dp->port2 = 65535; + + /* a>b is illegal, a=b is ok */ + if (dp->port > dp->port2) + goto error; + + } else { + if (strcasecmp(port,"any") == 0) { + dp->port = 0; + dp->port2 = 65535; + } else { + dp->port = dp->port2 = atoi(port); + } + } + + free(portdup); + return dp; + +error: + if (portdup) free(portdup); + return NULL; +} + +DetectPort *DetectPortCopy(DetectPort *src) { + if (src == NULL) + return NULL; + + DetectPort *dst = DetectPortInit(); + if (dst == NULL) { + goto error; + } + + memcpy(dst,src,sizeof(DetectPort)); + dst->sh = NULL; + + if (src->next != NULL) + dst->next = DetectPortCopy(src->next); + + return dst; +error: + return NULL; +} + +DetectPort *DetectPortCopySingle(DetectPort *src) { + if (src == NULL) + return NULL; + + DetectPort *dst = DetectPortInit(); + if (dst == NULL) { + goto error; + } + + memcpy(dst,src,sizeof(DetectPort)); + dst->sh = NULL; + dst->next = NULL; + dst->prev = NULL; + + SigGroupHeadCopySigs(src->sh,&dst->sh); + + return dst; +error: + return NULL; +} + +int DetectPortSetupTmp (Signature *s, SigMatch *m, char *addressstr) +{ + return 0; +} + + +int DetectPortMatch (DetectPort *dp, u_int16_t port) { + /* XXX figure out a way to not need to do this ntohl + * if we switch to Address inside DetectPort + * we can do u_int8_t checks */ + if (ntohl(port) >= ntohl(dp->port) && + ntohl(port) <= ntohl(dp->port2)) { + return 1; + } + + return 0; +} + +void DetectPortPrint(DetectPort *dp) { + if (dp == NULL) + return; + + if (dp->flags & PORT_FLAG_ANY) { + printf("ANY"); + } else { + printf("%u-%u", dp->port, dp->port2); + } +} + +/* find the group matching address in a group head */ +DetectPort * +DetectPortLookupGroup(DetectPort *dp, u_int16_t port) { + DetectPort *p = dp; + + if (dp == NULL) + return NULL; + + for ( ; p != NULL; p = p->next) { + if (DetectPortMatch(p,port) == 1) { + return p; + } + } + + return NULL; +} + + +/* XXX eeewww global! move to DetectionEngineCtx once we have that! */ +static DetectPort **port_hash; +static DetectPort *port_list; +#define HASH_SIZE 65536 + +/* XXX dynamic size based on number of sigs? */ +int DetectPortHashInit(void) { + port_hash = (DetectPort **)malloc(sizeof(DetectPort) * HASH_SIZE); + if (port_hash == NULL) { + goto error; + } + memset(port_hash,0,sizeof(DetectPort) * HASH_SIZE); + + port_list = NULL; + + return 0; +error: + return -1; +} + +void DetectPortHashFree(void) { + free(port_hash); + port_hash = NULL; +} + +void DetectPortHashReset(void) { + if (port_hash != NULL) { + memset(port_hash,0,sizeof(DetectPort) * HASH_SIZE); + } + port_list = NULL; +} + +DetectPort **DetectPortHashGetPtr(void) { + return port_hash; +} + +DetectPort *DetectPortHashGetListPtr(void) { + return port_list; +} + +u_int32_t DetectPortHashGetSize(void) { + return HASH_SIZE; +} + +static inline u_int32_t DetectPortHash(DetectPort *p) { + u_int32_t hash = p->port * p->port2; + + return (hash % HASH_SIZE); +} + +int DetectPortHashAdd(DetectPort *p) { + u_int32_t hash = DetectPortHash(p); + + //printf("DetectPortHashAdd: hash %u\n", hash); + detect_port_hash_add_cnt++; + + /* list */ + p->next = port_list; + port_list = p; + + /* easy: no collision */ + if (port_hash[hash] == NULL) { + port_hash[hash] = p; + return 0; + } + + detect_port_hash_add_coll_cnt++; + + /* harder: collision */ + DetectPort *h = port_hash[hash], *ph = NULL; + for ( ; h != NULL; h = h->hnext) { +#if 0 + if (DetectPortCmp(p,h) == PORT_EB) { + if (h == port_hash[hash]) { + p->hnext = h; + port_hash[hash] = p; + } else { + p->hnext = ph->hnext; + ph->hnext = p; + } + detect_port_hash_add_insert_cnt++; + return 0; + } +#endif + ph = h; + } + ph->hnext = p; + + return 0; +} + +static inline int DetectPortHashCmp(DetectPort *a,DetectPort *b) { + if (a->port2 == b->port2 && a->port == b->port && a->flags == b->flags) + return 1; + + return 0; +} + +DetectPort *DetectPortHashLookup(DetectPort *p) { + u_int32_t hash = DetectPortHash(p); + + //printf("DetectPortHashLookup: hash %u\n", hash); + detect_port_hash_lookup_cnt++; + + /* easy: no sgh at our hash */ + if (port_hash[hash] == NULL) { + detect_port_hash_lookup_miss_cnt++; + //printf("DetectPortHashLookup: not found\n"); + return NULL; + } + + /* see if we have the sgh we're looking for */ + DetectPort *h = port_hash[hash]; + for ( ; h != NULL; h = h->hnext) { + detect_port_hash_lookup_loop_cnt++; + if (DetectPortHashCmp(p,h) == 1) { + //printf("DetectPortHashLookup: found at %p\n", h); + detect_port_hash_lookup_hit_cnt++; + return h; + } + } + + //printf("DetectPortHashLookup: not found\n"); + return NULL; +} + +/* TESTS */ + +int PortTestParse01 (void) { + DetectPort *dd = NULL; + + int r = DetectPortParse(&dd,"80"); + if (r == 0) { + DetectPortFree(dd); + return 1; + } + + return 0; +} + +int PortTestParse02 (void) { + DetectPort *dd = NULL; + int result = 0; + + int r = DetectPortParse(&dd,"80"); + if (r == 0) { + r = DetectPortParse(&dd,"22"); + if (r == 0) { + result = 1; + } + + DetectPortCleanupList(dd); + return result; + } + + return result; +} + +int PortTestParse03 (void) { + DetectPort *dd = NULL; + int result = 0; + + int r = DetectPortParse(&dd,"80:88"); + if (r == 0) { + r = DetectPortParse(&dd,"85:100"); + if (r == 0) { + result = 1; + } + + DetectPortCleanupList(dd); + + return result; + } + + return result; +} + +int PortTestParse04 (void) { + DetectPort *dd = NULL; + + int r = DetectPortParse(&dd,"!80:81"); + if (r == 0) { + DetectPortCleanupList(dd); + return 1; + } + + return 0; +} + +int PortTestParse05 (void) { + DetectPort *dd = NULL; + int result = 0; + + int r = DetectPortParse(&dd,"!80:81"); + if (r != 0) + goto end; + + if (dd->next == NULL) + goto end; + + if (dd->port != 0 || dd->port2 != 79) + goto end; + + if (dd->next->port != 82 || dd->next->port2 != 65535) + goto end; + + DetectPortCleanupList(dd); + result = 1; +end: + return result; +} + +int PortTestParse06 (void) { + DetectPort *dd = NULL, *copy = NULL; + int result = 0; + + int r = DetectPortParse(&dd,"22"); + if (r != 0) + goto end; + + r = DetectPortParse(&dd,"80"); + if (r != 0) + goto end; + + r = DetectPortParse(&dd,"143"); + if (r != 0) + goto end; + + copy = DetectPortCopy(dd); + if (copy == NULL) + goto end; + + if (DetectPortCmp(dd,copy) != PORT_EQ) + goto end; + + if (copy->next == NULL) + goto end; + + if (DetectPortCmp(dd->next,copy->next) != PORT_EQ) + goto end; + + if (copy->next->next == NULL) + goto end; + + if (DetectPortCmp(dd->next->next,copy->next->next) != PORT_EQ) + goto end; + + if (copy->port != 22 || copy->next->port != 80 || copy->next->next->port != 143) + goto end; + + result = 1; + +end: + DetectPortCleanupList(dd); + return result; +} + + +void DetectPortTests(void) { + UtRegisterTest("PortTestParse01", PortTestParse01, 1); + UtRegisterTest("PortTestParse02", PortTestParse02, 1); + UtRegisterTest("PortTestParse03", PortTestParse03, 1); + UtRegisterTest("PortTestParse04", PortTestParse04, 1); + UtRegisterTest("PortTestParse05", PortTestParse05, 1); + UtRegisterTest("PortTestParse06", PortTestParse06, 1); +} + diff --git a/src/detect-engine-port.h b/src/detect-engine-port.h new file mode 100644 index 0000000000..7e3946af16 --- /dev/null +++ b/src/detect-engine-port.h @@ -0,0 +1,67 @@ +#ifndef __DETECT_PORT_H__ +#define __DETECT_PORT_H__ + +/* a is ... than b */ +enum { + PORT_ER = -1, /* error e.g. compare ipv4 and ipv6 */ + PORT_LT, /* smaller [aaa] [bbb] */ + PORT_LE, /* smaller with overlap [aa[bab]bb] */ + PORT_EQ, /* exactly equal [abababab] */ + PORT_ES, /* within [bb[aaa]bb] and [[abab]bbb] and [bbb[abab]] */ + PORT_EB, /* completely overlaps [aa[bbb]aa] and [[baba]aaa] and [aaa[baba]] */ + PORT_GE, /* bigger with overlap [bb[aba]aa] */ + PORT_GT, /* bigger [bbb] [aaa] */ +}; + +#define PORT_FLAG_ANY 0x1 +#define PORT_FLAG_NOT 0x2 + +#define PORT_SIGGROUPHEAD_COPY 0x04 + +typedef struct DetectPort_ { + u_int8_t flags; + + u_int16_t port; + u_int16_t port2; + + /* signatures that belong in this group */ + struct _SigGroupHead *sh; + + /* double linked list */ + union { + struct DetectPort_ *prev; + struct DetectPort_ *hnext; + }; + struct DetectPort_ *next; + +} DetectPort; + +/* prototypes */ +void DetectPortRegister (void); + +int DetectPortParse(DetectPort **head, char *str); + +DetectPort *DetectPortCopy(DetectPort *); +DetectPort *DetectPortCopySingle(DetectPort *); +int DetectPortInsertCopy(DetectPort **, DetectPort *); +int DetectPortInsert(DetectPort **, DetectPort *); +void DetectPortCleanupList (DetectPort *head); + +DetectPort *DetectPortLookup(DetectPort *head, DetectPort *dp); +int DetectPortAdd(DetectPort **head, DetectPort *dp); + +DetectPort *DetectPortLookupGroup(DetectPort *dp, u_int16_t port); + +void DetectPortPrintMemory(void); + +DetectPort *DetectPortHashLookup(DetectPort *p); +DetectPort **DetectPortHashGetPtr(void); +DetectPort *DetectPortHashGetListPtr(void); +u_int32_t DetectPortHashGetSize(void); +int DetectPortHashInit(void); +void DetectPortHashFree(void); +int DetectPortHashAdd(DetectPort *p); +void DetectPortHashReset(void); + +#endif /* __DETECT_PORT_H__ */ + diff --git a/src/detect-engine-siggroup.c b/src/detect-engine-siggroup.c new file mode 100644 index 0000000000..92710c178b --- /dev/null +++ b/src/detect-engine-siggroup.c @@ -0,0 +1,712 @@ + +#include "decode.h" +#include "detect.h" +#include "flow-var.h" + +#include "util-cidr.h" +#include "util-unittest.h" + +#include "detect.h" +#include "detect-engine-address.h" +#include "detect-mpm.h" + +/* prototypes */ +int SigGroupHeadClearSigs(SigGroupHead *); + +static u_int32_t detect_siggroup_head_memory = 0; +static u_int32_t detect_siggroup_head_init_cnt = 0; +static u_int32_t detect_siggroup_head_free_cnt = 0; +static u_int32_t detect_siggroup_sigarray_memory = 0; +static u_int32_t detect_siggroup_sigarray_init_cnt = 0; +static u_int32_t detect_siggroup_sigarray_free_cnt = 0; +static u_int32_t detect_siggroup_matcharray_memory = 0; +static u_int32_t detect_siggroup_matcharray_init_cnt = 0; +static u_int32_t detect_siggroup_matcharray_free_cnt = 0; + +/* Free a sgh */ +void SigGroupHeadFree(SigGroupHead *sh) { + if (sh == NULL) + return; + + PatternMatchDestroyGroup(sh); + SigGroupHeadClearSigs(sh); + + if (sh->sig_array != NULL) { + free(sh->sig_array); + + detect_siggroup_sigarray_free_cnt++; + detect_siggroup_sigarray_memory -= sh->sig_size; + } + + free(sh); + + detect_siggroup_head_free_cnt++; + detect_siggroup_head_memory -= sizeof(SigGroupHead); +} + +static int SigGroupHeadCmpSigArray(SigGroupHead *a, SigGroupHead *b) { + if (a->sig_size != b->sig_size) + return 0; + + if (memcmp(a->sig_array,b->sig_array,a->sig_size) != 0) + return 0; + + return 1; +} + +/* hashes */ + +/* XXX eeewww global! move to DetectionEngineCtx once we have that! */ +static SigGroupHead **sgh_port_hash; +static SigGroupHead **sgh_hash; +static SigGroupHead **sgh_mpm_hash; +static SigGroupHead **sgh_mpm_uri_hash; + +#define HASH_SIZE 65536 + +/* mpm sgh hash */ + +/* XXX dynamic size based on number of sigs? */ +int SigGroupHeadMpmHashInit(void) { + sgh_mpm_hash = (SigGroupHead **)malloc(sizeof(SigGroupHead *) * HASH_SIZE); + if (sgh_mpm_hash == NULL) { + goto error; + } + memset(sgh_mpm_hash,0,sizeof(SigGroupHead *) * HASH_SIZE); + + return 0; +error: + return -1; +} + +u_int32_t SigGroupHeadMpmHash(SigGroupHead *sgh) { + u_int32_t hash = sgh->content_size<<8; + + u_int32_t b; + for (b = 0; b < sgh->content_size; b+=1) { + hash += sgh->content_array[b]; + } + + return (hash % HASH_SIZE); +} + +int SigGroupHeadMpmHashAdd(SigGroupHead *sgh) { + u_int32_t hash = SigGroupHeadMpmHash(sgh); + + //printf("SigGroupHeadMpmHashAdd: hash %u\n", hash); + + /* easy: no collision */ + if (sgh_mpm_hash[hash] == NULL) { + sgh_mpm_hash[hash] = sgh; + return 0; + } + + /* harder: collision */ + SigGroupHead *h = sgh_mpm_hash[hash], *ph = NULL; + for ( ; h != NULL; h = h->mpm_next) { + ph = h; + } + ph->mpm_next = sgh; + + return 0; +} + +SigGroupHead *SigGroupHeadMpmHashLookup(SigGroupHead *sgh) { + u_int32_t hash = SigGroupHeadMpmHash(sgh); + + //printf("SigGroupHeadMpmHashLookup: hash %u\n", hash); + + /* easy: no sgh at our hash */ + if (sgh_mpm_hash[hash] == NULL) { + return NULL; + } + + /* see if we have the sgh we're looking for */ + SigGroupHead *h = sgh_mpm_hash[hash]; + for ( ; h != NULL; h = h->mpm_next) { + if (sgh->content_size == h->content_size && + memcmp(sgh->content_array,h->content_array,sgh->content_size) == 0) { + return h; + } + } + + return NULL; +} + +void SigGroupHeadMpmHashFree(void) { + free(sgh_mpm_hash); + sgh_mpm_hash = NULL; +} + +/* mpm uri sgh hash */ + +/* XXX dynamic size based on number of sigs? */ +int SigGroupHeadMpmUriHashInit(void) { + sgh_mpm_uri_hash = (SigGroupHead **)malloc(sizeof(SigGroupHead *) * HASH_SIZE); + if (sgh_mpm_uri_hash == NULL) { + goto error; + } + memset(sgh_mpm_uri_hash,0,sizeof(SigGroupHead *) * HASH_SIZE); + + return 0; +error: + return -1; +} + +u_int32_t SigGroupHeadMpmUriHash(SigGroupHead *sgh) { + u_int32_t hash = sgh->uri_content_size<<8; + + u_int32_t b; + for (b = 0; b < sgh->uri_content_size; b+=1) { + hash += sgh->uri_content_array[b]; + } + + return (hash % HASH_SIZE); +} + +int SigGroupHeadMpmUriHashAdd(SigGroupHead *sgh) { + u_int32_t hash = SigGroupHeadMpmUriHash(sgh); + + //printf("SigGroupHeadHashAdd: hash %u\n", hash); + + /* easy: no collision */ + if (sgh_mpm_uri_hash[hash] == NULL) { + sgh_mpm_uri_hash[hash] = sgh; + return 0; + } + + /* harder: collision */ + SigGroupHead *h = sgh_mpm_uri_hash[hash], *ph = NULL; + for ( ; h != NULL; h = h->mpm_uri_next) { + ph = h; + } + ph->mpm_uri_next = sgh; + + return 0; +} + +SigGroupHead *SigGroupHeadMpmUriHashLookup(SigGroupHead *sgh) { + u_int32_t hash = SigGroupHeadMpmUriHash(sgh); + + //printf("SigGroupHeadHashLookup: hash %u\n", hash); + + /* easy: no sgh at our hash */ + if (sgh_mpm_uri_hash[hash] == NULL) { + return NULL; + } + + /* see if we have the sgh we're looking for */ + SigGroupHead *h = sgh_mpm_uri_hash[hash]; + for ( ; h != NULL; h = h->mpm_uri_next) { + if (sgh->uri_content_size == h->uri_content_size && + memcmp(sgh->uri_content_array,h->uri_content_array,sgh->uri_content_size) == 0) { + return h; + } + } + + return NULL; +} + +void SigGroupHeadMpmUriHashFree(void) { + free(sgh_mpm_uri_hash); + sgh_mpm_uri_hash = NULL; +} + +/* non-port sgh hash */ + +/* XXX dynamic size based on number of sigs? */ +int SigGroupHeadHashInit(void) { + sgh_hash = (SigGroupHead **)malloc(sizeof(SigGroupHead *) * HASH_SIZE); + if (sgh_hash == NULL) { + goto error; + } + memset(sgh_hash,0,sizeof(SigGroupHead *) * HASH_SIZE); + + return 0; +error: + return -1; +} + +u_int32_t SigGroupHeadHash(SigGroupHead *sgh) { + u_int32_t hash = 0; + + u_int32_t b; + for (b = 0; b < sgh->content_size; b+=1) { + hash += sgh->content_array[b]; + } + + return (hash % HASH_SIZE); +} + +int SigGroupHeadHashAdd(SigGroupHead *sgh) { + u_int32_t hash = SigGroupHeadHash(sgh); + + //printf("SigGroupHeadHashAdd: hash %u\n", hash); + + /* easy: no collision */ + if (sgh_hash[hash] == NULL) { + sgh_hash[hash] = sgh; + return 0; + } + + /* harder: collision */ + SigGroupHead *h = sgh_hash[hash], *ph = NULL; + for ( ; h != NULL; h = h->next) { + ph = h; + } + ph->next = sgh; + + return 0; +} + +SigGroupHead *SigGroupHeadHashLookup(SigGroupHead *sgh) { + u_int32_t hash = SigGroupHeadHash(sgh); + + //printf("SigGroupHeadHashLookup: hash %u\n", hash); + + /* easy: no sgh at our hash */ + if (sgh_hash[hash] == NULL) { + return NULL; + } + + /* see if we have the sgh we're looking for */ + SigGroupHead *h = sgh_hash[hash]; + for ( ; h != NULL; h = h->next) { + if (SigGroupHeadCmpSigArray(sgh,h) == 1) { + return h; + } + } + + return NULL; +} + +void SigGroupHeadHashFree(void) { + free(sgh_hash); + sgh_hash = NULL; +} + + +/* port based sgh hash */ + +/* XXX dynamic size based on number of sigs? */ +int SigGroupHeadPortHashInit(void) { + sgh_port_hash = (SigGroupHead **)malloc(sizeof(SigGroupHead *) * HASH_SIZE); + if (sgh_port_hash == NULL) { + goto error; + } + memset(sgh_port_hash,0,sizeof(SigGroupHead *) * HASH_SIZE); + + return 0; +error: + return -1; +} + +int SigGroupHeadPortHashAdd(SigGroupHead *sgh) { + u_int32_t hash = SigGroupHeadHash(sgh); + + //printf("SigGroupHeadHashAdd: hash %u\n", hash); + + /* easy: no collision */ + if (sgh_port_hash[hash] == NULL) { + sgh_port_hash[hash] = sgh; + return 0; + } + + /* harder: collision */ + SigGroupHead *h = sgh_port_hash[hash], *ph = NULL; + for ( ; h != NULL; h = h->next) { + ph = h; + } + ph->next = sgh; + + return 0; +} + +SigGroupHead *SigGroupHeadPortHashLookup(SigGroupHead *sgh) { + u_int32_t hash = SigGroupHeadHash(sgh); + + //printf("SigGroupHeadHashLookup: hash %u\n", hash); + + /* easy: no sgh at our hash */ + if (sgh_port_hash[hash] == NULL) { + return NULL; + } + + /* see if we have the sgh we're looking for */ + SigGroupHead *h = sgh_port_hash[hash]; + for ( ; h != NULL; h = h->next) { + if (SigGroupHeadCmpSigArray(sgh,h) == 1) { + return h; + } + } + + return NULL; +} + +void SigGroupHeadPortHashFree(void) { + free(sgh_port_hash); + sgh_port_hash = NULL; +} + +/* end hashes */ + +void SigGroupHeadFreeHeads(void) { + SigGroupHead *b, *nb, *pb; + + u_int32_t hash = 0; + for ( ; hash < HASH_SIZE; hash++) { + b = sgh_hash[hash]; + for ( ; b != NULL; ) { + nb = b->next; + + if (b->flags & SIG_GROUP_HEAD_FREE) { +printf("SigGroupHeadFreeHeads: want to free %p\n", b); +//#if 0 + SigGroupHeadFree(b); + + /* remove from the hash as well */ + if (b == sgh_hash[hash]) { + sgh_hash[hash] = nb; + } else { + pb->next = nb; + } +//#endif + } + + pb = b; + b = nb; + } + } +} + +/* Free the sigarrays in the sgh's. Those are only + * used during the init stage. */ +void SigGroupHeadFreeSigArrays(void) { + SigGroupHead *b; + + u_int32_t hash = 0; + for ( ; hash < HASH_SIZE; hash++) { + b = sgh_hash[hash]; + for ( ; b != NULL; b = b->next) { + if (b->sig_array != NULL) { + detect_siggroup_sigarray_free_cnt++; + detect_siggroup_sigarray_memory -= b->sig_size; + + free(b->sig_array); + b->sig_array = NULL; + b->sig_size = 0; + } + } + b = sgh_port_hash[hash]; + for ( ; b != NULL; b = b->next) { + if (b->sig_array != NULL) { + detect_siggroup_sigarray_free_cnt++; + detect_siggroup_sigarray_memory -= b->sig_size; + + free(b->sig_array); + b->sig_array = NULL; + b->sig_size = 0; + } + } + } +} + +/* Free the mpm arrays that are only used during the + * init stage */ +void SigGroupHeadFreeMpmArrays(void) { + SigGroupHead *b; + + u_int32_t hash = 0; + for ( ; hash < HASH_SIZE; hash++) { + b = sgh_hash[hash]; + 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; + } + } + b = sgh_port_hash[hash]; + 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 SigGroupHeadAppendSig(SigGroupHead **sh, Signature *s) { + /* see if we have a head already */ + if (*sh == NULL) { + *sh = malloc(sizeof(SigGroupHead)); + if (*sh == NULL) { + goto error; + } + memset(*sh, 0, sizeof(SigGroupHead)); + + detect_siggroup_head_init_cnt++; + detect_siggroup_head_memory += sizeof(SigGroupHead); + + /* initialize the signature bitarray */ + (*sh)->sig_size = SigGetMaxId() / 8 + 1; + (*sh)->sig_array = malloc((*sh)->sig_size); + if ((*sh)->sig_array == NULL) + goto error; + memset((*sh)->sig_array,0,(*sh)->sig_size); + + detect_siggroup_sigarray_init_cnt++; + detect_siggroup_sigarray_memory += (*sh)->sig_size; + } + + /* enable the sig in the bitarray */ + (*sh)->sig_array[(s->num/8)] |= 1<<(s->num%8); + + return 0; +error: + return -1; +} + +int SigGroupHeadClearSigs(SigGroupHead *sh) { + if (sh == NULL) + return 0; + + if (sh->sig_array != NULL) { + memset(sh->sig_array,0,sh->sig_size); + sh->sig_cnt = 0; + } + return 0; +} + +int SigGroupHeadCopySigs(SigGroupHead *src, SigGroupHead **dst) { + if (src == NULL) + return 0; + + if (*dst == NULL) { + *dst = malloc(sizeof(SigGroupHead)); + if (*dst == NULL) { + goto error; + } + memset(*dst, 0, sizeof(SigGroupHead)); + + detect_siggroup_head_init_cnt++; + detect_siggroup_head_memory += sizeof(SigGroupHead); + + (*dst)->sig_size = SigGetMaxId() / 8 + 1; + (*dst)->sig_array = malloc((*dst)->sig_size); + if ((*dst)->sig_array == NULL) + goto error; + + memset((*dst)->sig_array,0,(*dst)->sig_size); + + detect_siggroup_sigarray_init_cnt++; + detect_siggroup_sigarray_memory += (*dst)->sig_size; + } + + /* do the copy */ + u_int32_t idx; + for (idx = 0; idx < src->sig_size; idx++) { + (*dst)->sig_array[idx] = (*dst)->sig_array[idx] | src->sig_array[idx]; + } + + return 0; +error: + return -1; +} + +void SigGroupHeadSetSigCnt(SigGroupHead *sgh, u_int32_t max_idx) { + u_int32_t sig; + + for (sig = 0; sig < max_idx+1; sig++) { + if (sgh->sig_array[(sig/8)] & (1<<(sig%8))) { + sgh->sig_cnt++; + } + } +} + +void DetectSigGroupPrintMemory(void) { + printf(" * Sig group head memory stats (SigGroupHead %u):\n", sizeof(SigGroupHead)); + printf(" - detect_siggroup_head_memory %u\n", detect_siggroup_head_memory); + printf(" - detect_siggroup_head_init_cnt %u\n", detect_siggroup_head_init_cnt); + printf(" - detect_siggroup_head_free_cnt %u\n", detect_siggroup_head_free_cnt); + printf(" - outstanding sig group heads %u\n", detect_siggroup_head_init_cnt - detect_siggroup_head_free_cnt); + printf(" * Sig group head memory stats done\n"); + printf(" * Sig group sigarray memory stats:\n"); + printf(" - detect_siggroup_sigarray_memory %u\n", detect_siggroup_sigarray_memory); + printf(" - detect_siggroup_sigarray_init_cnt %u\n", detect_siggroup_sigarray_init_cnt); + printf(" - detect_siggroup_sigarray_free_cnt %u\n", detect_siggroup_sigarray_free_cnt); + printf(" - outstanding sig group sigarrays %u\n", detect_siggroup_sigarray_init_cnt - detect_siggroup_sigarray_free_cnt); + printf(" * Sig group sigarray memory stats done\n"); + printf(" * Sig group matcharray memory stats:\n"); + printf(" - detect_siggroup_matcharray_memory %u\n", detect_siggroup_matcharray_memory); + printf(" - detect_siggroup_matcharray_init_cnt %u\n", detect_siggroup_matcharray_init_cnt); + printf(" - detect_siggroup_matcharray_free_cnt %u\n", detect_siggroup_matcharray_free_cnt); + printf(" - outstanding sig group matcharrays %u\n", detect_siggroup_matcharray_init_cnt - detect_siggroup_matcharray_free_cnt); + printf(" * Sig group sigarray memory stats done\n"); + printf(" X Total %u\n", detect_siggroup_head_memory + detect_siggroup_sigarray_memory + detect_siggroup_matcharray_memory); +} + +void SigGroupHeadPrintContent(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { + printf("SigGroupHeadPrintContent: "); + + u_int32_t sig; + for (sig = 0; sig < sgh->sig_cnt; sig++) { + u_int32_t num = sgh->match_array[sig]; + + Signature *s = de_ctx->sig_array[num]; + printf("%u ", s->id); + } + printf("\n"); +} + +/* 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 SigGroupHeadLoadContent(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { + if (sgh == NULL) + return 0; + + 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)); + + u_int32_t sig; + for (sig = 0; sig < sgh->sig_cnt; sig++) { + u_int32_t num = sgh->match_array[sig]; + + s = de_ctx->sig_array[num]; + 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 SigGroupHeadClearContent(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; +} + +int SigGroupHeadLoadUricontent(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { + if (sgh == NULL) + return 0; + + 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)); + + u_int32_t sig; + for (sig = 0; sig < sgh->sig_cnt; sig++) { + u_int32_t num = sgh->match_array[sig]; + + s = de_ctx->sig_array[num]; + 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 SigGroupHeadClearUricontent(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; +} + +int SigGroupHeadBuildMatchArray (DetectEngineCtx *de_ctx, SigGroupHead *sgh, u_int32_t max_idx) { + u_int32_t idx = 0; + u_int32_t sig = 0; + + if (sgh == NULL) + return 0; + + sgh->match_array = malloc(sgh->sig_cnt * sizeof(u_int32_t)); + if (sgh->match_array == NULL) + return -1; + + memset(sgh->match_array,0, sgh->sig_cnt * sizeof(u_int32_t)); + + detect_siggroup_matcharray_init_cnt++; + detect_siggroup_matcharray_memory += (sgh->sig_cnt * sizeof(u_int32_t)); + + for (sig = 0; sig < max_idx+1; sig++) { + if (!(sgh->sig_array[(sig/8)] & (1<<(sig%8)))) + continue; + + Signature *s = de_ctx->sig_array[sig]; + if (s == NULL) + continue; + + sgh->match_array[idx] = s->num; + idx++; + } + + return 0; +} + diff --git a/src/detect-engine-siggroup.h b/src/detect-engine-siggroup.h new file mode 100644 index 0000000000..66831efb58 --- /dev/null +++ b/src/detect-engine-siggroup.h @@ -0,0 +1,44 @@ +#ifndef __DETECT_SIGGROUP_H__ +#define __DETECT_SIGGROUP_H__ + +/* XXX cleanup */ + +int SigGroupHeadAppendSig(SigGroupHead **, Signature *); +int SigGroupHeadClearSigs(SigGroupHead *); +int SigGroupHeadCopySigs(SigGroupHead *, SigGroupHead **); + +int SigGroupHeadLoadContent(DetectEngineCtx *, SigGroupHead *); +int SigGroupHeadLoadUricontent(DetectEngineCtx *, SigGroupHead *); +int SigGroupHeadClearContent(SigGroupHead *); +int SigGroupHeadClearUricontent(SigGroupHead *); + +void SigGroupHeadFree(SigGroupHead *); + +void SigGroupHeadFreeMpmArrays(void); + +SigGroupHead *SigGroupHeadHashLookup(SigGroupHead *sgh); +SigGroupHead *SigGroupHeadPortHashLookup(SigGroupHead *sgh); +SigGroupHead *SigGroupHeadMpmHashLookup(SigGroupHead *sgh); +SigGroupHead *SigGroupHeadMpmUriHashLookup(SigGroupHead *sgh); + +int SigGroupHeadPortHashAdd(SigGroupHead *sgh); +int SigGroupHeadMpmHashAdd(SigGroupHead *sgh); +int SigGroupHeadMpmUriHashAdd(SigGroupHead *sgh); +int SigGroupHeadHashAdd(SigGroupHead *sgh); + +void SigGroupHeadHashFree(void); +void SigGroupHeadPortHashFree(void); +void SigGroupHeadMpmHashFree(void); +void SigGroupHeadMpmUriHashFree(void); + +int SigGroupHeadMpmHashInit(void); +int SigGroupHeadMpmUriHashInit(void); +int SigGroupHeadPortHashInit(void); +int SigGroupHeadHashInit(void); + +void SigGroupHeadSetSigCnt(SigGroupHead *sgh, u_int32_t max_idx); +int SigGroupHeadBuildMatchArray (DetectEngineCtx *de_ctx, SigGroupHead *sgh, u_int32_t max_idx); +void SigGroupHeadFreeSigArrays(void); + +#endif /* __DETECT_SIGGROUP_H__ */ + diff --git a/src/detect-siggroup.c b/src/detect-siggroup.c deleted file mode 100644 index d6b3bfc641..0000000000 --- a/src/detect-siggroup.c +++ /dev/null @@ -1,432 +0,0 @@ - -#include "decode.h" -#include "detect.h" -#include "flow-var.h" - -#include "util-cidr.h" -#include "util-unittest.h" - -#include "detect.h" -#include "detect-address.h" -#include "detect-mpm.h" - -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; - -static u_int32_t detect_siggroup_head_memory = 0; -static u_int32_t detect_siggroup_head_init_cnt = 0; -static u_int32_t detect_siggroup_head_free_cnt = 0; - -/* XXX eeewww global! move to DetectionEngineCtx once we have that! */ -static SigGroupHead *sgh_list = NULL; - -/* return the first SigGroupHead that matches - * the lookup one. */ -SigGroupHead* SigGroupHeadListGet(SigGroupHead *a) { - SigGroupHead *b = sgh_list; - - for ( ; b != NULL; b = b->next) { - if (SigGroupHeadCmp(a,b) == 1 && a != b) { - return b; - } - } - 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) { - if (a->content_size != b->content_size) - continue; - - if (memcmp(a->content_array,b->content_array,a->content_size) == 0) - return b; - } - 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) { - if (a->uri_content_size != b->uri_content_size) - continue; - - if (memcmp(a->uri_content_array,b->uri_content_array,a->uri_content_size) == 0) - return b; - } - return NULL; -} - -/* basically just reset the prt as the list items - * themselves are removed elsewhere */ -void SigGroupHeadListClean(void) { - sgh_list = NULL; -} - -void SigGroupHeadList(void) { - SigGroupHead *sh; - - printf("SigGroupHeadList: start\n"); - for (sh = sgh_list; sh != NULL; sh = sh->next) { - printf("%p sig_cnt %u\n", sh, sh->sig_cnt); - } - printf("SigGroupHeadList: end\n"); -} - -/* put this head in the list */ -void SigGroupHeadAppend(SigGroupHead *sh) { - if (sgh_list == NULL) { - sgh_list = sh; - } else { - SigGroupHead *list = sgh_list; - - while (list->next != NULL) - list = list->next; - - list->next = sh; - } -} - -int SigGroupAppend(DetectAddressGroup *ag, Signature *s) { - SigGroupContainer *sg = NULL, *tmp_sg = NULL; - - sg = malloc(sizeof(SigGroupContainer)); - if (sg == NULL) { - goto error; - } - memset(sg,0,sizeof(SigGroupContainer)); - - detect_siggroup_append_cnt++; - detect_siggroup_memory += sizeof(SigGroupContainer); - - /* connect the signature to the container */ - sg->s = s; - - /* see if we have a head already */ - if (ag->sh == NULL) { - ag->sh = malloc(sizeof(SigGroupHead)); - if (ag->sh == NULL) { - goto error; - } - memset(ag->sh, 0, sizeof(SigGroupHead)); - - detect_siggroup_head_init_cnt++; - detect_siggroup_head_memory += sizeof(SigGroupHead); - } - - if (ag->sh->head == NULL) { - /* put it as first in the list */ - ag->sh->head = sg; - ag->sh->tail = sg; - } else { - /* append to the list */ - tmp_sg = ag->sh->tail; - ag->sh->tail = tmp_sg->next = sg; - } - ag->sh->sig_cnt++; - return 0; -error: - return -1; -} - -int SigGroupListClean(SigGroupHead *sh) { - SigGroupContainer *sg = NULL, *next_sg = 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 (dst->sh == NULL) { - dst->sh = malloc(sizeof(SigGroupHead)); - if (dst->sh == NULL) { - goto error; - } - memset(dst->sh, 0, sizeof(SigGroupHead)); - - detect_siggroup_head_init_cnt++; - detect_siggroup_head_memory += sizeof(SigGroupHead); - } - - /* 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); - } - - dst->sh->tail->next = dsthead; - dst->sh->tail = dsttail; - return 0; -error: - return -1; -} - -int SigGroupListCopyAppend(DetectAddressGroup *src, DetectAddressGroup *dst) { - SigGroupContainer *sg = NULL; - - 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)); - - detect_siggroup_head_init_cnt++; - detect_siggroup_head_memory += sizeof(SigGroupHead); - } - - for (sg = src->sh->head; sg != NULL; sg = sg->next) { - SigGroupAppend(dst,sg->s); - } - - return 0; -error: - return -1; -} - -int SigGroupHeadCmp(SigGroupHead *a, SigGroupHead *b) { - SigGroupContainer *sg_a = NULL, *sg_b = NULL; - - if (a->sig_cnt != b->sig_cnt) - return 0; - - for (sg_a = a->head, sg_b = b->head; - sg_a != NULL && sg_b != NULL; - sg_a = sg_a->next, sg_b = sg_b->next) { - if (sg_a->s != sg_b->s) - return 0; - } - - return 1; -} - -void SigGroupHeadFree(SigGroupHead *sh) { - if (sh == NULL) - return; - - PatternMatchDestroyGroup(sh); - - SigGroupListClean(sh); - - free(sh); - - detect_siggroup_head_free_cnt++; - detect_siggroup_head_memory -= sizeof(SigGroupHead); -} - -void DetectSigGroupPrintMemory(void) { - printf(" * Sig group memory stats (SigGroupContainer %u):\n", sizeof(SigGroupContainer)); - 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"); - printf(" * Sig group head memory stats (SigGroupHead %u):\n", sizeof(SigGroupHead)); - printf(" - detect_siggroup_head_memory %u\n", detect_siggroup_head_memory); - printf(" - detect_siggroup_head_init_cnt %u\n", detect_siggroup_head_init_cnt); - printf(" - detect_siggroup_head_free_cnt %u\n", detect_siggroup_head_free_cnt); - printf(" - outstanding sig containers %u\n", detect_siggroup_head_init_cnt - detect_siggroup_head_free_cnt); - printf(" * Sig group head memory stats done\n"); - printf(" X Total %u\n", detect_siggroup_memory + detect_siggroup_head_memory); -} - - -/* -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; - u_int16_t min_depth = 65535; - u_int16_t min_offset = 65535; - - 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); - - if (co->depth < min_depth) min_depth = co->depth; - if (co->offset < min_offset) min_offset = co->offset; - } - } - } - //printf(" * min_depth %u, min_offset %u\n", min_depth, min_offset); - 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 deleted file mode 100644 index 182faa72f5..0000000000 --- a/src/detect-siggroup.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef __DETECT_SIGGROUP_H__ -#define __DETECT_SIGGROUP_H__ - -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__ */ -