diff --git a/src/decode-ipv4.c b/src/decode-ipv4.c index fc1770ad82..608f0bc783 100644 --- a/src/decode-ipv4.c +++ b/src/decode-ipv4.c @@ -30,9 +30,11 @@ #include "decode-ipv4.h" #include "decode-events.h" #include "defrag.h" +#include "pkt-var.h" + #include "util-unittest.h" #include "util-debug.h" -#include "pkt-var.h" +#include "util-optimize.h" /* Generic validation * @@ -271,7 +273,7 @@ static int IPV4OptValidateCIPSO(Packet *p, const IPV4Opt *o) { /** * Decode/Validate IPv4 Options. */ -static int DecodeIPV4Options(ThreadVars *tv, Packet *p, uint8_t *pkt, uint16_t len) +static int DecodeIPV4Options(Packet *p, uint8_t *pkt, uint16_t len) { uint16_t plen = len; @@ -458,14 +460,14 @@ static int DecodeIPV4Options(ThreadVars *tv, Packet *p, uint8_t *pkt, uint16_t l return 0; } -static int DecodeIPV4Packet(ThreadVars *tv, Packet *p, uint8_t *pkt, uint16_t len) +static int DecodeIPV4Packet(Packet *p, uint8_t *pkt, uint16_t len) { - if (len < IPV4_HEADER_LEN) { + if (unlikely(len < IPV4_HEADER_LEN)) { DECODER_SET_EVENT(p,IPV4_PKT_TOO_SMALL); return -1; } - if (IP_GET_RAW_VER(pkt) != 4) { + if (unlikely(IP_GET_RAW_VER(pkt) != 4)) { SCLogDebug("wrong ip version %" PRIu8 "",IP_GET_RAW_VER(pkt)); DECODER_SET_EVENT(p,IPV4_WRONG_IP_VER); return -1; @@ -473,38 +475,36 @@ static int DecodeIPV4Packet(ThreadVars *tv, Packet *p, uint8_t *pkt, uint16_t le p->ip4h = (IPV4Hdr *)pkt; - if (IPV4_GET_HLEN(p) < IPV4_HEADER_LEN) { + if (unlikely(IPV4_GET_HLEN(p) < IPV4_HEADER_LEN)) { DECODER_SET_EVENT(p,IPV4_HLEN_TOO_SMALL); return -1; } - if (IPV4_GET_IPLEN(p) < IPV4_GET_HLEN(p)) { + if (unlikely(IPV4_GET_IPLEN(p) < IPV4_GET_HLEN(p))) { DECODER_SET_EVENT(p,IPV4_IPLEN_SMALLER_THAN_HLEN); return -1; } - if (len < IPV4_GET_IPLEN(p)) { + if (unlikely(len < IPV4_GET_IPLEN(p))) { DECODER_SET_EVENT(p,IPV4_TRUNC_PKT); return -1; } - /* save the options len */ - p->ip4vars.ip_opt_len = IPV4_GET_HLEN(p) - IPV4_HEADER_LEN; - if (p->ip4vars.ip_opt_len > 0) { - DecodeIPV4Options(tv, p, pkt + IPV4_HEADER_LEN, p->ip4vars.ip_opt_len); - } - /* set the address struct */ SET_IPV4_SRC_ADDR(p,&p->src); SET_IPV4_DST_ADDR(p,&p->dst); + /* save the options len */ + uint8_t ip_opt_len = IPV4_GET_HLEN(p) - IPV4_HEADER_LEN; + if (ip_opt_len > 0) { + DecodeIPV4Options(p, pkt + IPV4_HEADER_LEN, ip_opt_len); + } + return 0; } void DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) { - int ret; - SCPerfCounterIncr(dtv->counter_ipv4, tv->sc_perf_pca); /* reset the decoder cache flags */ @@ -513,15 +513,14 @@ void DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, SCLogDebug("pkt %p len %"PRIu16"", pkt, len); /* do the actual decoding */ - ret = DecodeIPV4Packet (tv, p, pkt, len); - if (ret < 0) { + if (unlikely(DecodeIPV4Packet (p, pkt, len) < 0)) { SCLogDebug("decoding IPv4 packet failed"); p->ip4h = NULL; return; } /* If a fragment, pass off for re-assembly. */ - if (IPV4_GET_IPOFFSET(p) > 0 || IPV4_GET_MF(p) == 1) { + if (unlikely(IPV4_GET_IPOFFSET(p) > 0 || IPV4_GET_MF(p) == 1)) { Packet *rp = Defrag(tv, dtv, NULL, p); if (rp != NULL) { /* Got re-assembled packet, re-run through decoder. */ @@ -547,27 +546,22 @@ void DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, /* check what next decoder to invoke */ switch (IPV4_GET_IPPROTO(p)) { - case IPPROTO_IP: - /* check PPP VJ uncompressed packets and decode tcp dummy */ - if(p->ppph != NULL && ntohs(p->ppph->protocol) == PPP_VJ_UCOMP) { - DecodeTCP(tv, dtv, p, pkt + IPV4_GET_HLEN(p), - IPV4_GET_IPLEN(p) - IPV4_GET_HLEN(p), pq); - } - break; case IPPROTO_TCP: DecodeTCP(tv, dtv, p, pkt + IPV4_GET_HLEN(p), IPV4_GET_IPLEN(p) - IPV4_GET_HLEN(p), pq); break; case IPPROTO_UDP: - //printf("DecodeIPV4: next layer is UDP\n"); DecodeUDP(tv, dtv, p, pkt + IPV4_GET_HLEN(p), IPV4_GET_IPLEN(p) - IPV4_GET_HLEN(p), pq); break; case IPPROTO_ICMP: - //printf("DecodeIPV4: next layer is ICMP\n"); DecodeICMPV4(tv, dtv, p, pkt + IPV4_GET_HLEN(p), IPV4_GET_IPLEN(p) - IPV4_GET_HLEN(p), pq); break; + case IPPROTO_GRE: + DecodeGRE(tv, dtv, p, pkt + IPV4_GET_HLEN(p), + IPV4_GET_IPLEN(p) - IPV4_GET_HLEN(p), pq); + break; case IPPROTO_SCTP: DecodeSCTP(tv, dtv, p, pkt + IPV4_GET_HLEN(p), IPV4_GET_IPLEN(p) - IPV4_GET_HLEN(p), pq); @@ -589,9 +583,12 @@ void DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, } break; } - case IPPROTO_GRE: - DecodeGRE(tv, dtv, p, pkt + IPV4_GET_HLEN(p), - IPV4_GET_IPLEN(p) - IPV4_GET_HLEN(p), pq); + case IPPROTO_IP: + /* check PPP VJ uncompressed packets and decode tcp dummy */ + if(p->ppph != NULL && ntohs(p->ppph->protocol) == PPP_VJ_UCOMP) { + DecodeTCP(tv, dtv, p, pkt + IPV4_GET_HLEN(p), + IPV4_GET_IPLEN(p) - IPV4_GET_HLEN(p), pq); + } break; } @@ -633,16 +630,14 @@ int DecodeIPV4OptionsNONETest01(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; uint8_t *data = (uint8_t *)p; uint16_t i; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); if (rc != 0) { DecodeIPV4OptionsPrint(p); SCFree(p); @@ -671,16 +666,14 @@ int DecodeIPV4OptionsEOLTest01(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; uint8_t *data = (uint8_t *)p; uint16_t i; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); if (rc != 0) { DecodeIPV4OptionsPrint(p); SCFree(p); @@ -709,16 +702,14 @@ int DecodeIPV4OptionsNOPTest01(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; uint8_t *data = (uint8_t *)p; uint16_t i; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); if (rc != 0) { DecodeIPV4OptionsPrint(p); SCFree(p); @@ -751,14 +742,12 @@ int DecodeIPV4OptionsRRTest01(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",rr=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_rr, (uintmax_t)&p.IPV4_OPTS[0]); if ( (rc == 0) && (p->IPV4_OPTS_CNT == 1) @@ -787,14 +776,12 @@ int DecodeIPV4OptionsRRTest02(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",rr=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_rr, (uintmax_t)&p.IPV4_OPTS[0]); if (rc != 0) { SCFree(p); @@ -818,14 +805,12 @@ int DecodeIPV4OptionsRRTest03(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",rr=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_rr, (uintmax_t)&p.IPV4_OPTS[0]); if (rc != 0) { SCFree(p); @@ -849,14 +834,12 @@ int DecodeIPV4OptionsRRTest04(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",rr=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_rr, (uintmax_t)&p.IPV4_OPTS[0]); if (rc != 0) { SCFree(p); @@ -876,14 +859,12 @@ int DecodeIPV4OptionsQSTest01(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",qs=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_qs, (uintmax_t)&p.IPV4_OPTS[0]); if ( (rc == 0) && (p->IPV4_OPTS_CNT == 1) @@ -908,14 +889,12 @@ int DecodeIPV4OptionsQSTest02(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",qs=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_qs, (uintmax_t)&p.IPV4_OPTS[0]); if (rc != 0) { SCFree(p); @@ -939,14 +918,12 @@ int DecodeIPV4OptionsTSTest01(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",ts=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_ts, (uintmax_t)&p.IPV4_OPTS[0]); if ( (rc == 0) && (p->IPV4_OPTS_CNT == 1) @@ -975,14 +952,12 @@ int DecodeIPV4OptionsTSTest02(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",ts=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_ts, (uintmax_t)&p.IPV4_OPTS[0]); if (rc != 0) { SCFree(p); @@ -1006,14 +981,12 @@ int DecodeIPV4OptionsTSTest03(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",ts=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_ts, (uintmax_t)&p.IPV4_OPTS[0]); if (rc != 0) { SCFree(p); @@ -1037,14 +1010,12 @@ int DecodeIPV4OptionsTSTest04(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",ts=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_ts, (uintmax_t)&p.IPV4_OPTS[0]); if (rc != 0) { SCFree(p); @@ -1065,14 +1036,12 @@ int DecodeIPV4OptionsSECTest01(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",sec=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_sec, (uintmax_t)&p.IPV4_OPTS[0]); if ( (rc == 0) && (p->IPV4_OPTS_CNT == 1) @@ -1098,14 +1067,12 @@ int DecodeIPV4OptionsSECTest02(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",sec=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_sec, (uintmax_t)&p.IPV4_OPTS[0]); if (rc != 0) { SCFree(p); @@ -1129,14 +1096,12 @@ int DecodeIPV4OptionsLSRRTest01(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",lsrr=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_lsrr, (uintmax_t)&p.IPV4_OPTS[0]); if ( (rc == 0) && (p->IPV4_OPTS_CNT == 1) @@ -1165,14 +1130,12 @@ int DecodeIPV4OptionsLSRRTest02(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",lsrr=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_lsrr, (uintmax_t)&p.IPV4_OPTS[0]); if (rc != 0) { SCFree(p); @@ -1196,14 +1159,12 @@ int DecodeIPV4OptionsLSRRTest03(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",lsrr=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_lsrr, (uintmax_t)&p.IPV4_OPTS[0]); if (rc != 0) { SCFree(p); @@ -1227,14 +1188,12 @@ int DecodeIPV4OptionsLSRRTest04(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",lsrr=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_lsrr, (uintmax_t)&p.IPV4_OPTS[0]); if (rc != 0) { SCFree(p); @@ -1256,14 +1215,12 @@ int DecodeIPV4OptionsCIPSOTest01(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",rr=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_cipso, (uintmax_t)&p.IPV4_OPTS[0]); if ( (rc == 0) && (p->IPV4_OPTS_CNT == 1) @@ -1288,14 +1245,12 @@ int DecodeIPV4OptionsSIDTest01(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",sid=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_sid, (uintmax_t)&p.IPV4_OPTS[0]); if ( (rc == 0) && (p->IPV4_OPTS_CNT == 1) @@ -1320,14 +1275,12 @@ int DecodeIPV4OptionsSIDTest02(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",sid=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_sid, (uintmax_t)&p.IPV4_OPTS[0]); if (rc != 0) { SCFree(p); @@ -1351,14 +1304,12 @@ int DecodeIPV4OptionsSSRRTest01(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",ssrr=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_ssrr, (uintmax_t)&p.IPV4_OPTS[0]); if ( (rc == 0) && (p->IPV4_OPTS_CNT == 1) @@ -1387,14 +1338,12 @@ int DecodeIPV4OptionsSSRRTest02(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",ssrr=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_ssrr, (uintmax_t)&p.IPV4_OPTS[0]); if (rc != 0) { SCFree(p); @@ -1418,14 +1367,12 @@ int DecodeIPV4OptionsSSRRTest03(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",ssrr=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_ssrr, (uintmax_t)&p.IPV4_OPTS[0]); if (rc != 0) { SCFree(p); @@ -1449,14 +1396,12 @@ int DecodeIPV4OptionsSSRRTest04(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",ssrr=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_ssrr, (uintmax_t)&p.IPV4_OPTS[0]); if (rc != 0) { SCFree(p); @@ -1476,14 +1421,12 @@ int DecodeIPV4OptionsRTRALTTest01(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",rtralt=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_rtralt, (uintmax_t)&p.IPV4_OPTS[0]); if ( (rc == 0) && (p->IPV4_OPTS_CNT == 1) @@ -1508,14 +1451,12 @@ int DecodeIPV4OptionsRTRALTTest02(void) { Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; - ThreadVars tv; int rc; - memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); - rc = DecodeIPV4Options(&tv, p, raw_opts, sizeof(raw_opts)); + rc = DecodeIPV4Options(p, raw_opts, sizeof(raw_opts)); //printf("rc=%d,cnt=%" PRIu16 ",type=%" PRIu8 ",len=%" PRIu8 ",rtralt=%" PRIuMAX "/%" PRIuMAX "\n", rc, p.IPV4_OPTS_CNT, p.IPV4_OPTS[0].type, p.IPV4_OPTS[0].len, (uintmax_t)p.ip4vars.o_rtralt, (uintmax_t)&p.IPV4_OPTS[0]); if (rc != 0) { SCFree(p); diff --git a/src/decode-ipv4.h b/src/decode-ipv4.h index 817d7d9f94..28d8a43c81 100644 --- a/src/decode-ipv4.h +++ b/src/decode-ipv4.h @@ -195,7 +195,6 @@ typedef struct IPV4Cache_ #define CLEAR_IPV4_PACKET(p) do { \ (p)->ip4h = NULL; \ - (p)->ip4vars.ip_opt_len = 0; \ (p)->ip4vars.ip_opt_cnt = 0; \ (p)->ip4vars.o_rr = NULL; \ (p)->ip4vars.o_qs = NULL; \ @@ -228,7 +227,6 @@ typedef struct IPV4Cache_ /* helper structure with parsed ipv4 info */ typedef struct IPV4Vars_ { - uint8_t ip_opt_len; IPV4Opt ip_opts[IPV4_OPTMAX]; uint8_t ip_opt_cnt; diff --git a/src/decode-tcp.c b/src/decode-tcp.c index 4f38691e16..91532ab107 100644 --- a/src/decode-tcp.c +++ b/src/decode-tcp.c @@ -32,7 +32,7 @@ #include "util-optimize.h" #include "flow.h" -static int DecodeTCPOptions(ThreadVars *tv, Packet *p, uint8_t *pkt, uint16_t len) +static int DecodeTCPOptions(Packet *p, uint8_t *pkt, uint16_t len) { uint16_t plen = len; while (plen) @@ -147,30 +147,30 @@ static int DecodeTCPPacket(ThreadVars *tv, Packet *p, uint8_t *pkt, uint16_t len p->tcph = (TCPHdr *)pkt; - p->tcpvars.hlen = TCP_GET_HLEN(p); - if (unlikely(len < p->tcpvars.hlen)) { + uint8_t hlen = TCP_GET_HLEN(p); + if (unlikely(len < hlen)) { DECODER_SET_EVENT(p, TCP_HLEN_TOO_SMALL); return -1; } - SET_TCP_SRC_PORT(p,&p->sp); - SET_TCP_DST_PORT(p,&p->dp); - - p->tcpvars.tcp_opt_len = p->tcpvars.hlen - TCP_HEADER_LEN; - if (unlikely(p->tcpvars.tcp_opt_len > TCP_OPTLENMAX)) { + uint8_t tcp_opt_len = hlen - TCP_HEADER_LEN; + if (unlikely(tcp_opt_len > TCP_OPTLENMAX)) { DECODER_SET_EVENT(p, TCP_INVALID_OPTLEN); return -1; } - if (p->tcpvars.tcp_opt_len > 0) { - DecodeTCPOptions(tv, p, pkt + TCP_HEADER_LEN, p->tcpvars.tcp_opt_len); + if (likely(tcp_opt_len > 0)) { + DecodeTCPOptions(p, pkt + TCP_HEADER_LEN, tcp_opt_len); } - p->payload = pkt + p->tcpvars.hlen; - p->payload_len = len - p->tcpvars.hlen; + SET_TCP_SRC_PORT(p,&p->sp); + SET_TCP_DST_PORT(p,&p->dp); p->proto = IPPROTO_TCP; + p->payload = pkt + hlen; + p->payload_len = len - hlen; + return 0; } @@ -185,11 +185,10 @@ void DecodeTCP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, u } #ifdef DEBUG - SCLogDebug("TCP sp: %" PRIu32 " -> dp: %" PRIu32 " - HLEN: %" PRIu32 " LEN: %" PRIu32 " %s%s%s%s", - GET_TCP_SRC_PORT(p), GET_TCP_DST_PORT(p), p->tcpvars.hlen, len, - p->tcpvars.sackok ? "SACKOK " : "", - p->tcpvars.ws ? "WS " : "", - p->tcpvars.ts ? "TS " : "", + SCLogDebug("TCP sp: %" PRIu32 " -> dp: %" PRIu32 " - HLEN: %" PRIu32 " LEN: %" PRIu32 " %s%s%s%s%s", + GET_TCP_SRC_PORT(p), GET_TCP_DST_PORT(p), TCP_GET_HLEN(p), len, + p->tcpvars.sackok ? "SACKOK " : "", p->tcpvars.sack ? "SACK " : "", + p->tcpvars.ws ? "WS " : "", p->tcpvars.ts ? "TS " : "", p->tcpvars.mss ? "MSS " : ""); #endif diff --git a/src/decode-tcp.h b/src/decode-tcp.h index 7018716b76..b0d94e5b75 100644 --- a/src/decode-tcp.h +++ b/src/decode-tcp.h @@ -81,12 +81,15 @@ /** macro for getting the first timestamp from the packet. Timestamp is in host * order and either returned from the cache or from the packet directly. */ -#define TCP_GET_TSVAL(p) ((p)->tcpc.ts1 != 0 ? \ - (p)->tcpc.ts1 : (p)->tcpvars.ts ? ((p)->tcpc.ts1 = (uint32_t)ntohl((*(uint32_t *)(p)->tcpvars.ts->data))) : 0) +#define TCP_GET_TSVAL(p) ((p)->tcpc.ts1 != 0 ? \ + (p)->tcpc.ts1 : (p)->tcpvars.ts ? \ + ((p)->tcpc.ts1 = (uint32_t)ntohl((*(uint32_t *)(p)->tcpvars.ts->data))) : 0) + /** macro for getting the second timestamp from the packet. Timestamp is in * host order and either returned from the cache or from the packet directly. */ -#define TCP_GET_TSECR(p) ((p)->tcpc.ts2 != 0 ? \ - (p)->tcpc.ts2 : (p)->tcpvars.ts ? ((p)->tcpc.ts2 = (uint32_t)ntohl((*(uint32_t *)((p)->tcpvars.ts->data+4)))) : 0) +#define TCP_GET_TSECR(p) ((p)->tcpc.ts2 != 0 ? \ + (p)->tcpc.ts2 : (p)->tcpvars.ts ? \ + ((p)->tcpc.ts2 = (uint32_t)ntohl((*(uint32_t *)((p)->tcpvars.ts->data+4)))) : 0) /** macro for getting the wscale from the packet. */ #define TCP_GET_WSCALE(p) ((p)->tcpvars.ws ? (((*(uint8_t *)(p)->tcpvars.ws->data) <= TCP_WSCALE_MAX) ? (*(uint8_t *)((p)->tcpvars.ws->data)) : 0) : 0) @@ -139,9 +142,6 @@ typedef struct TCPHdr_ typedef struct TCPVars_ { - uint8_t hlen; - - uint8_t tcp_opt_len; uint8_t tcp_opt_cnt; TCPOpt tcp_opts[TCP_OPTMAX]; diff --git a/src/detect-csum.c b/src/detect-csum.c index 14f1d2148f..98d2b7ccf1 100644 --- a/src/detect-csum.c +++ b/src/detect-csum.c @@ -326,8 +326,7 @@ int DetectTCPV4CsumMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, if (p->tcpc.comp_csum == -1) p->tcpc.comp_csum = TCPCalculateChecksum((uint16_t *)&(p->ip4h->ip_src), (uint16_t *)p->tcph, - (p->payload_len + - p->tcpvars.hlen) ); + (p->payload_len + TCP_GET_HLEN(p))); if (p->tcpc.comp_csum == p->tcph->th_sum && cd->valid == 1) return 1; @@ -418,8 +417,7 @@ int DetectTCPV6CsumMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, if (p->tcpc.comp_csum == -1) p->tcpc.comp_csum = TCPV6CalculateChecksum((uint16_t *)&(p->ip6h->ip6_src), (uint16_t *)p->tcph, - (p->payload_len + - p->tcpvars.hlen) ); + (p->payload_len + TCP_GET_HLEN(p))); if (p->tcpc.comp_csum == p->tcph->th_sum && cd->valid == 1) return 1; diff --git a/src/detect.c b/src/detect.c index 5f35042b2f..183294fc03 100644 --- a/src/detect.c +++ b/src/detect.c @@ -5997,32 +5997,29 @@ int SigTest26TCPV4Keyword(void) uint8_t valid_raw_tcp[] = { 0x00, 0x50, 0x8e, 0x16, 0x0d, 0x59, 0xcd, 0x3c, - 0xcf, 0x0d, 0x21, 0x80, 0xa0, 0x12, 0x16, 0xa0, - 0xfa, 0x03, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, + 0xcf, 0x0d, 0x21, 0x80, 0x50, 0x12, 0x16, 0xa0, + 0x4A, 0x04, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, 0x04, 0x02, 0x08, 0x0a, 0x6e, 0x18, 0x78, 0x73, 0x01, 0x71, 0x74, 0xde, 0x01, 0x03, 0x03, 0x02}; uint8_t invalid_raw_tcp[] = { 0x00, 0x50, 0x8e, 0x16, 0x0d, 0x59, 0xcd, 0x3c, - 0xcf, 0x0d, 0x21, 0x80, 0xa0, 0x12, 0x16, 0xa0, + 0xcf, 0x0d, 0x21, 0x80, 0x50, 0x12, 0x16, 0xa0, 0xfa, 0x03, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, 0x04, 0x02, 0x08, 0x0a, 0x6e, 0x18, 0x78, 0x73, 0x01, 0x71, 0x74, 0xde, 0x01, 0x03, 0x03, 0x03}; - Packet *p1 = SCMalloc(SIZE_OF_PACKET); if (p1 == NULL) return 0; + Packet *p2 = SCMalloc(SIZE_OF_PACKET); if (p2 == NULL) return 0; + ThreadVars th_v; DetectEngineThreadCtx *det_ctx; - int result = 1; - - uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0yyyyyyyyyyyyyyyy\r\n" - "\r\n\r\n"; - uint16_t buflen = strlen((char *)buf); + int result = 0; memset(&th_v, 0, sizeof(ThreadVars)); memset(p1, 0, SIZE_OF_PACKET); @@ -6030,24 +6027,32 @@ int SigTest26TCPV4Keyword(void) memset(p2, 0, SIZE_OF_PACKET); p2->pkt = (uint8_t *)(p2 + 1); + memcpy(p1->pkt, raw_ipv4, sizeof(raw_ipv4)); + p1->pktlen = sizeof(raw_ipv4); + memcpy(p1->pkt + p1->pktlen, valid_raw_tcp, sizeof(valid_raw_tcp)); + p1->pktlen += sizeof(valid_raw_tcp); + + memcpy(p2->pkt, raw_ipv4, sizeof(raw_ipv4)); + p2->pktlen = sizeof(raw_ipv4); + memcpy(p2->pkt + p2->pktlen, invalid_raw_tcp, sizeof(invalid_raw_tcp)); + p2->pktlen += sizeof(invalid_raw_tcp); + p1->tcpc.comp_csum = -1; - p1->ip4h = (IPV4Hdr *)raw_ipv4; - p1->tcph = (TCPHdr *)valid_raw_tcp; - p1->tcpvars.hlen = 0; + p1->ip4h = (IPV4Hdr *)p1->pkt; + p1->tcph = (TCPHdr *)(p1->pkt + sizeof(raw_ipv4)); p1->src.family = AF_INET; p1->dst.family = AF_INET; - p1->payload = buf; - p1->payload_len = buflen; + p1->payload = (uint8_t *)p1->pkt + sizeof(raw_ipv4) + 20; + p1->payload_len = 20; p1->proto = IPPROTO_TCP; p2->tcpc.comp_csum = -1; - p2->ip4h = (IPV4Hdr *)raw_ipv4; - p2->tcph = (TCPHdr *)invalid_raw_tcp; - p2->tcpvars.hlen = 0; + p2->ip4h = (IPV4Hdr *)p2->pkt; + p2->tcph = (TCPHdr *)(p2->pkt + sizeof(raw_ipv4)); p2->src.family = AF_INET; p2->dst.family = AF_INET; - p2->payload = buf; - p2->payload_len = buflen; + p2->payload = (uint8_t *)p2->pkt + sizeof(raw_ipv4) + 20; + p2->payload_len = 20; p2->proto = IPPROTO_TCP; DetectEngineCtx *de_ctx = DetectEngineCtxInit(); @@ -6059,20 +6064,18 @@ int SigTest26TCPV4Keyword(void) de_ctx->sig_list = SigInit(de_ctx, "alert ip any any -> any any " - "(content:\"/one/\"; tcpv4-csum:valid; " + "(content:\"|DE 01 03|\"; tcpv4-csum:valid; dsize:20; " "msg:\"tcpv4-csum keyword check(1)\"; sid:1;)"); if (de_ctx->sig_list == NULL) { - result &= 0; goto end; } de_ctx->sig_list->next = SigInit(de_ctx, "alert ip any any -> any any " - "(content:\"/one/\"; tcpv4-csum:invalid; " + "(content:\"|DE 01 03|\"; tcpv4-csum:invalid; " "msg:\"tcpv4-csum keyword check(1)\"; " "sid:2;)"); if (de_ctx->sig_list->next == NULL) { - result &= 0; goto end; } @@ -6080,22 +6083,23 @@ int SigTest26TCPV4Keyword(void) DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx); SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); - if (PacketAlertCheck(p1, 1)) - result &= 1; - else - result &= 0; + if (!(PacketAlertCheck(p1, 1))) { + printf("sig 1 didn't match: "); + goto end; + } SigMatchSignatures(&th_v, de_ctx, det_ctx, p2); - if (PacketAlertCheck(p2, 2)) - result &= 1; - else - result &= 0; + if (!(PacketAlertCheck(p2, 2))) { + printf("sig 2 didn't match: "); + goto end; + } + result = 1; +end: SigGroupCleanup(de_ctx); SigCleanSignatures(de_ctx); DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); DetectEngineCtxFree(de_ctx); -end: SCFree(p1); SCFree(p2); return result; @@ -6110,14 +6114,14 @@ int SigTest27NegativeTCPV4Keyword(void) uint8_t valid_raw_tcp[] = { 0x00, 0x50, 0x8e, 0x16, 0x0d, 0x59, 0xcd, 0x3c, - 0xcf, 0x0d, 0x21, 0x80, 0xa0, 0x12, 0x16, 0xa0, + 0xcf, 0x0d, 0x21, 0x80, 0x50, 0x12, 0x16, 0xa0, 0xfa, 0x03, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, 0x04, 0x02, 0x08, 0x0a, 0x6e, 0x18, 0x78, 0x73, 0x01, 0x71, 0x74, 0xde, 0x01, 0x03, 0x03, 0x02}; uint8_t invalid_raw_tcp[] = { 0x00, 0x50, 0x8e, 0x16, 0x0d, 0x59, 0xcd, 0x3c, - 0xcf, 0x0d, 0x21, 0x80, 0xa0, 0x12, 0x16, 0xa0, + 0xcf, 0x0d, 0x21, 0x80, 0x50, 0x12, 0x16, 0xa0, 0xfa, 0x03, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, 0x04, 0x02, 0x08, 0x0a, 0x6e, 0x18, 0x78, 0x73, 0x01, 0x71, 0x74, 0xde, 0x01, 0x03, 0x03, 0x03}; @@ -6131,11 +6135,7 @@ int SigTest27NegativeTCPV4Keyword(void) return 0; ThreadVars th_v; DetectEngineThreadCtx *det_ctx; - int result = 1; - - uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0yyyyyyyyyyyyyyyy\r\n" - "\r\n\r\n"; - uint16_t buflen = strlen((char *)buf); + int result = 0; memset(&th_v, 0, sizeof(ThreadVars)); memset(p1, 0, SIZE_OF_PACKET); @@ -6143,26 +6143,32 @@ int SigTest27NegativeTCPV4Keyword(void) memset(p2, 0, SIZE_OF_PACKET); p2->pkt = (uint8_t *)(p2 + 1); + memcpy(p1->pkt, raw_ipv4, sizeof(raw_ipv4)); + p1->pktlen = sizeof(raw_ipv4); + memcpy(p1->pkt + p1->pktlen, valid_raw_tcp, sizeof(valid_raw_tcp)); + p1->pktlen += sizeof(valid_raw_tcp); + + memcpy(p2->pkt, raw_ipv4, sizeof(raw_ipv4)); + p2->pktlen = sizeof(raw_ipv4); + memcpy(p2->pkt + p2->pktlen, invalid_raw_tcp, sizeof(invalid_raw_tcp)); + p2->pktlen += sizeof(invalid_raw_tcp); + p1->tcpc.comp_csum = -1; - p1->ip4h = (IPV4Hdr *)raw_ipv4; - p1->tcph = (TCPHdr *)valid_raw_tcp; - //p1.tcpvars.hlen = TCP_GET_HLEN((&p)); - p1->tcpvars.hlen = 0; + p1->ip4h = (IPV4Hdr *)p1->pkt; + p1->tcph = (TCPHdr *)(p1->pkt + sizeof(raw_ipv4)); p1->src.family = AF_INET; p1->dst.family = AF_INET; - p1->payload = buf; - p1->payload_len = buflen; + p1->payload = (uint8_t *)p1->pkt + sizeof(raw_ipv4) + 20; + p1->payload_len = 20; p1->proto = IPPROTO_TCP; p2->tcpc.comp_csum = -1; - p2->ip4h = (IPV4Hdr *)raw_ipv4; - p2->tcph = (TCPHdr *)invalid_raw_tcp; - //p2.tcpvars.hlen = TCP_GET_HLEN((&p)); - p2->tcpvars.hlen = 0; + p2->ip4h = (IPV4Hdr *)p2->pkt; + p2->tcph = (TCPHdr *)(p2->pkt + sizeof(raw_ipv4)); p2->src.family = AF_INET; p2->dst.family = AF_INET; - p2->payload = buf; - p2->payload_len = buflen; + p2->payload = (uint8_t *)p2->pkt + sizeof(raw_ipv4) + 20; + p2->payload_len = 20; p2->proto = IPPROTO_TCP; DetectEngineCtx *de_ctx = DetectEngineCtxInit(); @@ -6174,46 +6180,40 @@ int SigTest27NegativeTCPV4Keyword(void) de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " - "(content:\"/one/\"; tcpv4-csum:invalid; " + "(content:\"|DE 01 03|\"; tcpv4-csum:invalid; dsize:20; " "msg:\"tcpv4-csum keyword check(1)\"; sid:1;)"); if (de_ctx->sig_list == NULL) { - result &= 0; goto end; } de_ctx->sig_list->next = SigInit(de_ctx, "alert tcp any any -> any any " - "(content:\"/one/\"; tcpv4-csum:valid; " + "(content:\"|DE 01 03|\"; tcpv4-csum:valid; dsize:20; " "msg:\"tcpv4-csum keyword check(1)\"; " "sid:2;)"); if (de_ctx->sig_list->next == NULL) { - result &= 0; goto end; } SigGroupBuild(de_ctx); - //PatternMatchPrepare(mpm_ctx, MPM_B2G); DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx); SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); - if (PacketAlertCheck(p1, 1)) - result &= 0; - else - result &= 1; + if (PacketAlertCheck(p1, 1)) { + goto end; + } SigMatchSignatures(&th_v, de_ctx, det_ctx, p2); if (PacketAlertCheck(p2, 2)) { - result &= 0; + goto end; } - else - result &= 1; + result = 1; +end: SigGroupCleanup(de_ctx); SigCleanSignatures(de_ctx); DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); - //PatternMatchDestroy(mpm_ctx); DetectEngineCtxFree(de_ctx); -end: SCFree(p1); SCFree(p2); return result; @@ -6223,29 +6223,37 @@ int SigTest28TCPV6Keyword(void) { static uint8_t valid_raw_ipv6[] = { 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00, - 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, 0x60, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x06, 0x40, 0x3f, 0xfe, - 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, - 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe, - 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0, - 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0x03, 0xfe, - 0x00, 0x16, 0xd6, 0x76, 0xf5, 0x2d, 0x0c, 0x7a, - 0x08, 0x77, 0x80, 0x10, 0x21, 0x5c, 0xc2, 0xf1, - 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x00, 0x08, - 0xca, 0x5a, 0x00, 0x01, 0x69, 0x27}; + 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, + + 0x60, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0x40, + 0x3f, 0xfe, 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, + 0x02, 0x00, 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, + 0x3f, 0xfe, 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, + 0x02, 0xc0, 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, + + 0x03, 0xfe, 0x00, 0x16, 0xd6, 0x76, 0xf5, 0x2d, + 0x0c, 0x7a, 0x08, 0x77, 0x50, 0x10, 0x21, 0x5c, + 0xf2, 0xf1, 0x00, 0x00, + + 0x01, 0x01, 0x08, 0x0a, 0x00, 0x08, 0xca, 0x5a, + 0x00, 0x01, 0x69, 0x27}; static uint8_t invalid_raw_ipv6[] = { 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00, - 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, 0x60, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x06, 0x40, 0x3f, 0xfe, - 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, - 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe, - 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0, - 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0x03, 0xfe, - 0x00, 0x16, 0xd6, 0x76, 0xf5, 0x2d, 0x0c, 0x7a, - 0x08, 0x77, 0x80, 0x10, 0x21, 0x5c, 0xc2, 0xf1, - 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x00, 0x08, - 0xca, 0x5a, 0x00, 0x01, 0x69, 0x28}; + 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, + + 0x60, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0x40, + 0x3f, 0xfe, 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, + 0x02, 0x00, 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, + 0x3f, 0xfe, 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, + 0x02, 0xc0, 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, + + 0x03, 0xfe, 0x00, 0x16, 0xd6, 0x76, 0xf5, 0x2d, + 0x0c, 0x7a, 0x08, 0x77, 0x50, 0x10, 0x21, 0x5c, + 0xc2, 0xf1, 0x00, 0x00, + + 0x01, 0x01, 0x08, 0x0a, 0x00, 0x08, 0xca, 0x5a, + 0x00, 0x01, 0x69, 0x28}; Packet *p1 = SCMalloc(SIZE_OF_PACKET); if (p1 == NULL) @@ -6255,10 +6263,7 @@ int SigTest28TCPV6Keyword(void) return 0; ThreadVars th_v; DetectEngineThreadCtx *det_ctx; - int result = 1; - - uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0tttttttt\r\n" - "\r\n\r\n"; + int result = 0; memset(&th_v, 0, sizeof(ThreadVars)); memset(p1, 0, SIZE_OF_PACKET); @@ -6271,23 +6276,27 @@ int SigTest28TCPV6Keyword(void) p1->tcph = (TCPHdr *) (valid_raw_ipv6 + 54); p1->src.family = AF_INET; p1->dst.family = AF_INET; - p1->tcpvars.hlen = TCP_GET_HLEN((p1)); - p1->payload = buf; - p1->payload_len = p1->tcpvars.hlen; - p1->tcpvars.hlen = 0; + p1->payload = valid_raw_ipv6 + 54 + 20; + p1->payload_len = 12; p1->proto = IPPROTO_TCP; + if (TCP_GET_HLEN(p1) != 20) { + BUG_ON(1); + } + p2->tcpc.comp_csum = -1; p2->ip6h = (IPV6Hdr *)(invalid_raw_ipv6 + 14); p2->tcph = (TCPHdr *) (invalid_raw_ipv6 + 54); p2->src.family = AF_INET; p2->dst.family = AF_INET; - p2->tcpvars.hlen = TCP_GET_HLEN((p2)); - p2->payload = buf; - p2->payload_len = p2->tcpvars.hlen; - p2->tcpvars.hlen = 0; + p2->payload = invalid_raw_ipv6 + 54 + 20;; + p2->payload_len = 12; p2->proto = IPPROTO_TCP; + if (TCP_GET_HLEN(p2) != 20) { + BUG_ON(1); + } + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); if (de_ctx == NULL) { goto end; @@ -6297,45 +6306,38 @@ int SigTest28TCPV6Keyword(void) de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " - "(content:\"/one/\"; tcpv6-csum:valid; " + "(content:\"|00 01 69|\"; tcpv6-csum:valid; dsize:12; " "msg:\"tcpv6-csum keyword check(1)\"; sid:1;)"); if (de_ctx->sig_list == NULL) { - result &= 0; goto end; } de_ctx->sig_list->next = SigInit(de_ctx, "alert tcp any any -> any any " - "(content:\"/one/\"; tcpv6-csum:invalid; " + "(content:\"|00 01 69|\"; tcpv6-csum:invalid; dsize:12; " "msg:\"tcpv6-csum keyword check(1)\"; " "sid:2;)"); if (de_ctx->sig_list->next == NULL) { - result &= 0; goto end; } SigGroupBuild(de_ctx); - //PatternMatchPrepare(mpm_ctx, MPM_B2G); DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx); SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); - if (PacketAlertCheck(p1, 1)) - result &= 1; - else - result &= 0; + if (!(PacketAlertCheck(p1, 1))) + goto end; SigMatchSignatures(&th_v, de_ctx, det_ctx, p2); - if (PacketAlertCheck(p2, 2)) - result &= 1; - else - result &= 0; + if (!(PacketAlertCheck(p2, 2))) + goto end; + result = 1; +end: SigGroupCleanup(de_ctx); SigCleanSignatures(de_ctx); DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); - //PatternMatchDestroy(mpm_ctx); DetectEngineCtxFree(de_ctx); -end: SCFree(p1); SCFree(p2); return result; @@ -6345,29 +6347,37 @@ int SigTest29NegativeTCPV6Keyword(void) { static uint8_t valid_raw_ipv6[] = { 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00, - 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, 0x60, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x06, 0x40, 0x3f, 0xfe, - 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, - 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe, - 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0, - 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0x03, 0xfe, - 0x00, 0x16, 0xd6, 0x76, 0xf5, 0x2d, 0x0c, 0x7a, - 0x08, 0x77, 0x80, 0x10, 0x21, 0x5c, 0xc2, 0xf1, - 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x00, 0x08, - 0xca, 0x5a, 0x00, 0x01, 0x69, 0x27}; + 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, + + 0x60, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0x40, + 0x3f, 0xfe, 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, + 0x02, 0x00, 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, + 0x3f, 0xfe, 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, + 0x02, 0xc0, 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, + + 0x03, 0xfe, 0x00, 0x16, 0xd6, 0x76, 0xf5, 0x2d, + 0x0c, 0x7a, 0x08, 0x77, 0x50, 0x10, 0x21, 0x5c, + 0xf2, 0xf1, 0x00, 0x00, + + 0x01, 0x01, 0x08, 0x0a, 0x00, 0x08, 0xca, 0x5a, + 0x00, 0x01, 0x69, 0x27}; static uint8_t invalid_raw_ipv6[] = { 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00, - 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, 0x60, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x06, 0x40, 0x3f, 0xfe, - 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, - 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe, - 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0, - 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0x03, 0xfe, - 0x00, 0x16, 0xd6, 0x76, 0xf5, 0x2d, 0x0c, 0x7a, - 0x08, 0x77, 0x80, 0x10, 0x21, 0x5c, 0xc2, 0xf1, - 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x00, 0x08, - 0xca, 0x5a, 0x00, 0x01, 0x69, 0x28}; + 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, + + 0x60, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0x40, + 0x3f, 0xfe, 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, + 0x02, 0x00, 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, + 0x3f, 0xfe, 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, + 0x02, 0xc0, 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, + + 0x03, 0xfe, 0x00, 0x16, 0xd6, 0x76, 0xf5, 0x2d, + 0x0c, 0x7a, 0x08, 0x77, 0x50, 0x10, 0x21, 0x5c, + 0xc2, 0xf1, 0x00, 0x00, + + 0x01, 0x01, 0x08, 0x0a, 0x00, 0x08, 0xca, 0x5a, + 0x00, 0x01, 0x69, 0x28}; Packet *p1 = SCMalloc(SIZE_OF_PACKET); if (p1 == NULL) @@ -6377,10 +6387,7 @@ int SigTest29NegativeTCPV6Keyword(void) return 0; ThreadVars th_v; DetectEngineThreadCtx *det_ctx; - int result = 1; - - uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0tttttttt\r\n" - "\r\n\r\n"; + int result = 0; memset(&th_v, 0, sizeof(ThreadVars)); memset(p1, 0, SIZE_OF_PACKET); @@ -6393,23 +6400,27 @@ int SigTest29NegativeTCPV6Keyword(void) p1->tcph = (TCPHdr *) (valid_raw_ipv6 + 54); p1->src.family = AF_INET; p1->dst.family = AF_INET; - p1->tcpvars.hlen = TCP_GET_HLEN((p1)); - p1->payload = buf; - p1->payload_len = p1->tcpvars.hlen; - p1->tcpvars.hlen = 0; + p1->payload = valid_raw_ipv6 + 54 + 20; + p1->payload_len = 12; p1->proto = IPPROTO_TCP; + if (TCP_GET_HLEN(p1) != 20) { + BUG_ON(1); + } + p2->tcpc.comp_csum = -1; p2->ip6h = (IPV6Hdr *)(invalid_raw_ipv6 + 14); p2->tcph = (TCPHdr *) (invalid_raw_ipv6 + 54); p2->src.family = AF_INET; p2->dst.family = AF_INET; - p2->tcpvars.hlen = TCP_GET_HLEN((p2)); - p2->payload = buf; - p2->payload_len = p2->tcpvars.hlen; - p2->tcpvars.hlen = 0; + p2->payload = invalid_raw_ipv6 + 54 + 20;; + p2->payload_len = 12; p2->proto = IPPROTO_TCP; + if (TCP_GET_HLEN(p2) != 20) { + BUG_ON(1); + } + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); if (de_ctx == NULL) { goto end; @@ -6419,46 +6430,39 @@ int SigTest29NegativeTCPV6Keyword(void) de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " - "(content:\"/one/\"; tcpv6-csum:invalid; " + "(content:\"|00 01 69|\"; tcpv6-csum:invalid; dsize:12; " "msg:\"tcpv6-csum keyword check(1)\"; " "sid:1;)"); if (de_ctx->sig_list == NULL) { - result &= 0; goto end; } de_ctx->sig_list->next = SigInit(de_ctx, "alert tcp any any -> any any " - "(content:\"/one/\"; tcpv6-csum:valid; " + "(content:\"|00 01 69|\"; tcpv6-csum:valid; dsize:12; " "msg:\"tcpv6-csum keyword check(1)\"; " "sid:2;)"); if (de_ctx->sig_list->next == NULL) { - result &= 0; goto end; } SigGroupBuild(de_ctx); - //PatternMatchPrepare(mpm_ctx, MPM_B2G); DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx); SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); if (PacketAlertCheck(p1, 1)) - result &= 0; - else - result &= 1; + goto end; SigMatchSignatures(&th_v, de_ctx, det_ctx, p2); if (PacketAlertCheck(p2, 2)) - result &= 0; - else - result &= 1; + goto end; + result = 1; +end: SigGroupCleanup(de_ctx); SigCleanSignatures(de_ctx); DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); - //PatternMatchDestroy(mpm_ctx); DetectEngineCtxFree(de_ctx); -end: SCFree(p1); SCFree(p2); return result; @@ -7525,7 +7529,6 @@ int SigTest38Real(int mpm_type) p1->ethh = (EthernetHdr *)raw_eth; p1->ip4h = (IPV4Hdr *)raw_ipv4; p1->tcph = (TCPHdr *)raw_tcp; - p1->tcpvars.hlen = 0; p1->src.family = AF_INET; p1->dst.family = AF_INET; p1->payload = GET_PKT_DATA(p1) + ethlen + ipv4len + tcplen; @@ -7668,7 +7671,6 @@ int SigTest39Real(int mpm_type) p1->ethh = (EthernetHdr *)raw_eth; p1->ip4h = (IPV4Hdr *)raw_ipv4; p1->tcph = (TCPHdr *)raw_tcp; - p1->tcpvars.hlen = 0; p1->src.family = AF_INET; p1->dst.family = AF_INET; p1->payload = GET_PKT_DATA(p1) + ethlen + ipv4len + tcplen; diff --git a/src/stream-tcp-inline.c b/src/stream-tcp-inline.c index 0088a3f16a..1108bd1f5c 100644 --- a/src/stream-tcp-inline.c +++ b/src/stream-tcp-inline.c @@ -198,7 +198,7 @@ void StreamTcpInlineRecalcCsum(Packet *p) { /* TCP */ p->tcph->th_sum = 0; p->tcph->th_sum = TCPCalculateChecksum((uint16_t *)&(p->ip4h->ip_src), - (uint16_t *)p->tcph, (p->payload_len + p->tcpvars.hlen)); + (uint16_t *)p->tcph, (p->payload_len + TCP_GET_HLEN(p))); /* IPV4 */ p->ip4h->ip_csum = 0; p->ip4h->ip_csum = IPV4CalculateChecksum((uint16_t *)p->ip4h, @@ -207,7 +207,7 @@ void StreamTcpInlineRecalcCsum(Packet *p) { /* just TCP for IPV6 */ p->tcph->th_sum = 0; p->tcph->th_sum = TCPV6CalculateChecksum((uint16_t *)&(p->ip6h->ip6_src), - (uint16_t *)p->tcph, (p->payload_len + p->tcpvars.hlen)); + (uint16_t *)p->tcph, (p->payload_len + TCP_GET_HLEN(p))); } SCReturn;