]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
tcp: reduce TCP options storage in packets
authorVictor Julien <victor@inliniac.net>
Wed, 16 Dec 2015 12:10:05 +0000 (13:10 +0100)
committerVictor Julien <victor@inliniac.net>
Thu, 7 Apr 2016 13:31:55 +0000 (15:31 +0200)
Until now, the TCP options would all be stored in the Packet structure.
The commonly used ones (wscale, ts, sack, sackok and mss*) then had a
pointer to the position in the option array. Overall this option array
was large. About 360 bytes on 64bit systems. Since no part of the engine
would every access this array other than through the common short cuts,
this was actually just wasteful.

This patch changes the approach. It stores just the common ones in the
packet. The rest is gone. This shrinks the packet structure with almost
300 bytes.

* even though mss wasn't actually used

src/decode-tcp.c
src/decode-tcp.h
src/stream-tcp.c

index 428e7ae4e39079b380092ac2043ec9696dcf2db6..ae3650be11cfe07a43cf1fe765971d944f4fd57f 100644 (file)
 #include "pkt-var.h"
 #include "host.h"
 
+#define SET_OPTS(dst, src) \
+    (dst).type = (src).type; \
+    (dst).len  = (src).len; \
+    (dst).data = (src).data
+
 static int DecodeTCPOptions(Packet *p, uint8_t *pkt, uint16_t len)
 {
+    uint8_t tcp_opt_cnt = 0;
+    TCPOpt tcp_opts[TCP_OPTMAX];
+
     uint16_t plen = len;
     while (plen)
     {
@@ -68,81 +76,81 @@ static int DecodeTCPOptions(Packet *p, uint8_t *pkt, uint16_t len)
                 return -1;
             }
 
-            p->TCP_OPTS[p->TCP_OPTS_CNT].type = *pkt;
-            p->TCP_OPTS[p->TCP_OPTS_CNT].len  = *(pkt+1);
+            tcp_opts[tcp_opt_cnt].type = *pkt;
+            tcp_opts[tcp_opt_cnt].len  = *(pkt+1);
             if (plen > 2)
-                p->TCP_OPTS[p->TCP_OPTS_CNT].data = (pkt+2);
+                tcp_opts[tcp_opt_cnt].data = (pkt+2);
             else
-                p->TCP_OPTS[p->TCP_OPTS_CNT].data = NULL;
+                tcp_opts[tcp_opt_cnt].data = NULL;
 
             /* we are parsing the most commonly used opts to prevent
              * us from having to walk the opts list for these all the
              * time. */
-            switch (p->TCP_OPTS[p->TCP_OPTS_CNT].type) {
+            switch (tcp_opts[tcp_opt_cnt].type) {
                 case TCP_OPT_WS:
-                    if (p->TCP_OPTS[p->TCP_OPTS_CNT].len != TCP_OPT_WS_LEN) {
+                    if (tcp_opts[tcp_opt_cnt].len != TCP_OPT_WS_LEN) {
                         ENGINE_SET_EVENT(p,TCP_OPT_INVALID_LEN);
                     } else {
-                        if (p->tcpvars.ws != NULL) {
+                        if (p->tcpvars.ws.type != 0) {
                             ENGINE_SET_EVENT(p,TCP_OPT_DUPLICATE);
                         } else {
-                            p->tcpvars.ws = &p->TCP_OPTS[p->TCP_OPTS_CNT];
+                            SET_OPTS(p->tcpvars.ws, tcp_opts[tcp_opt_cnt]);
                         }
                     }
                     break;
                 case TCP_OPT_MSS:
-                    if (p->TCP_OPTS[p->TCP_OPTS_CNT].len != TCP_OPT_MSS_LEN) {
+                    if (tcp_opts[tcp_opt_cnt].len != TCP_OPT_MSS_LEN) {
                         ENGINE_SET_EVENT(p,TCP_OPT_INVALID_LEN);
                     } else {
-                        if (p->tcpvars.mss != NULL) {
+                        if (p->tcpvars.mss.type != 0) {
                             ENGINE_SET_EVENT(p,TCP_OPT_DUPLICATE);
                         } else {
-                            p->tcpvars.mss = &p->TCP_OPTS[p->TCP_OPTS_CNT];
+                            SET_OPTS(p->tcpvars.mss, tcp_opts[tcp_opt_cnt]);
                         }
                     }
                     break;
                 case TCP_OPT_SACKOK:
-                    if (p->TCP_OPTS[p->TCP_OPTS_CNT].len != TCP_OPT_SACKOK_LEN) {
+                    if (tcp_opts[tcp_opt_cnt].len != TCP_OPT_SACKOK_LEN) {
                         ENGINE_SET_EVENT(p,TCP_OPT_INVALID_LEN);
                     } else {
-                        if (p->tcpvars.sackok != NULL) {
+                        if (p->tcpvars.sackok.type != 0) {
                             ENGINE_SET_EVENT(p,TCP_OPT_DUPLICATE);
                         } else {
-                            p->tcpvars.sackok = &p->TCP_OPTS[p->TCP_OPTS_CNT];
+                            SET_OPTS(p->tcpvars.sackok, tcp_opts[tcp_opt_cnt]);
                         }
                     }
                     break;
                 case TCP_OPT_TS:
-                    if (p->TCP_OPTS[p->TCP_OPTS_CNT].len != TCP_OPT_TS_LEN) {
+                    if (tcp_opts[tcp_opt_cnt].len != TCP_OPT_TS_LEN) {
                         ENGINE_SET_EVENT(p,TCP_OPT_INVALID_LEN);
                     } else {
-                        if (p->tcpvars.ts != NULL) {
+                        if (p->tcpvars.ts.type != 0) {
                             ENGINE_SET_EVENT(p,TCP_OPT_DUPLICATE);
                         } else {
-                            p->tcpvars.ts = &p->TCP_OPTS[p->TCP_OPTS_CNT];
+                            SET_OPTS(p->tcpvars.ts, tcp_opts[tcp_opt_cnt]);
                         }
                     }
                     break;
                 case TCP_OPT_SACK:
-                    SCLogDebug("SACK option, len %u", p->TCP_OPTS[p->TCP_OPTS_CNT].len);
-                    if (p->TCP_OPTS[p->TCP_OPTS_CNT].len < TCP_OPT_SACK_MIN_LEN ||
-                            p->TCP_OPTS[p->TCP_OPTS_CNT].len > TCP_OPT_SACK_MAX_LEN ||
-                            !((p->TCP_OPTS[p->TCP_OPTS_CNT].len - 2) % 8 == 0))
+                    SCLogDebug("SACK option, len %u", tcp_opts[tcp_opt_cnt].len);
+                    if (tcp_opts[tcp_opt_cnt].len < TCP_OPT_SACK_MIN_LEN ||
+                            tcp_opts[tcp_opt_cnt].len > TCP_OPT_SACK_MAX_LEN ||
+                            !((tcp_opts[tcp_opt_cnt].len - 2) % 8 == 0))
                     {
                         ENGINE_SET_EVENT(p,TCP_OPT_INVALID_LEN);
                     } else {
-                        if (p->tcpvars.sack != NULL) {
+                        if (p->tcpvars.sack.type != 0) {
                             ENGINE_SET_EVENT(p,TCP_OPT_DUPLICATE);
                         } else {
-                            p->tcpvars.sack = &p->TCP_OPTS[p->TCP_OPTS_CNT];
+                            SET_OPTS(p->tcpvars.sack, tcp_opts[tcp_opt_cnt]);
                         }
                     }
                     break;
             }
 
-            pkt += p->TCP_OPTS[p->TCP_OPTS_CNT].len;
-            plen -= (p->TCP_OPTS[p->TCP_OPTS_CNT].len);
-            p->TCP_OPTS_CNT++;
+            pkt += tcp_opts[tcp_opt_cnt].len;
+            plen -= (tcp_opts[tcp_opt_cnt].len);
+            tcp_opt_cnt++;
         }
     }
     return 0;
@@ -197,9 +205,9 @@ int DecodeTCP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, ui
 #ifdef DEBUG
     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 " : "");
+        TCP_HAS_SACKOK(p) ? "SACKOK " : "", TCP_HAS_SACK(p) ? "SACK " : "",
+        TCP_HAS_WSCALE(p) ? "WS " : "", TCP_HAS_TS(p) ? "TS " : "",
+        TCP_HAS_MSS(p) ? "MSS " : "");
 #endif
 
     /* Flow is an integral part of us */
@@ -468,7 +476,7 @@ static int TCPGetSackTest01(void)
         goto end;
     }
 
-    if (p->tcpvars.sack == NULL) {
+    if (!TCP_HAS_SACK(p)) {
         printf("tcp packet sack not decoded: ");
         goto end;
     }
index 29c02dfb2feaf2d3a90f2051cc7b312e4c934527..955800e17adeacdffd7e059191ded99e5348e91e 100644 (file)
@@ -62,9 +62,6 @@
 /** Max valid wscale value. */
 #define TCP_WSCALE_MAX                       14
 
-#define TCP_OPTS                             tcpvars.tcp_opts
-#define TCP_OPTS_CNT                         tcpvars.tcp_opt_cnt
-
 #define TCP_GET_RAW_OFFSET(tcph)             (((tcph)->th_offx2 & 0xf0) >> 4)
 #define TCP_GET_RAW_X2(tcph)                 (unsigned char)((tcph)->th_offx2 & 0x0f)
 #define TCP_GET_RAW_SRC_PORT(tcph)           ntohs((tcph)->th_sport)
 /** 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) \
-    (uint32_t)ntohl((*(uint32_t *)(p)->tcpvars.ts->data))
+    (uint32_t)ntohl((*(uint32_t *)(p)->tcpvars.ts.data))
 
 /** 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) \
-    (uint32_t)ntohl((*(uint32_t *)((p)->tcpvars.ts->data+4)))
+    (uint32_t)ntohl((*(uint32_t *)((p)->tcpvars.ts.data+4)))
+
+#define TCP_HAS_WSCALE(p)                   ((p)->tcpvars.ws.type == TCP_OPT_WS)
+#define TCP_HAS_SACK(p)                     ((p)->tcpvars.sack.type == TCP_OPT_SACK)
+#define TCP_HAS_SACKOK(p)                   ((p)->tcpvars.sackok.type == TCP_OPT_SACKOK)
+#define TCP_HAS_TS(p)                       ((p)->tcpvars.ts.type == TCP_OPT_TS)
+#define TCP_HAS_MSS(p)                      ((p)->tcpvars.mss.type == TCP_OPT_MSS)
 
 /** 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)
+#define TCP_GET_WSCALE(p)                    (TCP_HAS_WSCALE((p)) ? \
+                                                (((*(uint8_t *)(p)->tcpvars.ws.data) <= TCP_WSCALE_MAX) ? \
+                                                  (*(uint8_t *)((p)->tcpvars.ws.data)) : 0) : 0)
 
-#define TCP_GET_SACKOK(p)                    ((p)->tcpvars.sackok ? 1 : 0)
-#define TCP_GET_SACK_PTR(p)                  (p)->tcpvars.sack ? (p)->tcpvars.sack->data : NULL
-#define TCP_GET_SACK_CNT(p)                  ((p)->tcpvars.sack ? (((p)->tcpvars.sack->len - 2) / 8) : 0)
+#define TCP_GET_SACKOK(p)                    (TCP_HAS_SACKOK((p)) ? 1 : 0)
+#define TCP_GET_SACK_PTR(p)                  TCP_HAS_SACK((p)) ? (p)->tcpvars.sack.data : NULL
+#define TCP_GET_SACK_CNT(p)                  (TCP_HAS_SACK((p)) ? (((p)->tcpvars.sack.len - 2) / 8) : 0)
 
 #define TCP_GET_OFFSET(p)                    TCP_GET_RAW_OFFSET((p)->tcph)
 #define TCP_GET_HLEN(p)                      (TCP_GET_OFFSET((p)) << 2)
@@ -140,26 +145,22 @@ typedef struct TCPHdr_
 
 typedef struct TCPVars_
 {
-    uint8_t tcp_opt_cnt;
-    TCPOpt tcp_opts[TCP_OPTMAX];
-
-    /* ptrs to commonly used and needed opts */
-    TCPOpt *ts;
-    TCPOpt *sack;
-    TCPOpt *sackok;
-    TCPOpt *ws;
-    TCPOpt *mss;
+    /* commonly used and needed opts */
+    TCPOpt ts;
+    TCPOpt sack;
+    TCPOpt sackok;
+    TCPOpt ws;
+    TCPOpt mss;
 } TCPVars;
 
 #define CLEAR_TCP_PACKET(p) { \
     (p)->tcph = NULL; \
     (p)->level4_comp_csum = -1; \
-    (p)->tcpvars.tcp_opt_cnt = 0; \
-    (p)->tcpvars.ts = NULL; \
-    (p)->tcpvars.sack = NULL; \
-    (p)->tcpvars.sackok = NULL; \
-    (p)->tcpvars.ws = NULL; \
-    (p)->tcpvars.mss = NULL; \
+    (p)->tcpvars.ts.type = 0; \
+    (p)->tcpvars.sack.type = 0; \
+    (p)->tcpvars.sackok.type = 0; \
+    (p)->tcpvars.ws.type = 0; \
+    (p)->tcpvars.mss.type = 0; \
 }
 
 void DecodeTCPRegisterTests(void);
index f0a3fbdac98708e96e484e6273d349da71793819..2f1a9f250d94e3591abf56a7290a7e49203ce592 100644 (file)
@@ -896,7 +896,7 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p,
         /** If the client has a wscale option the server had it too,
          *  so set the wscale for the server to max. Otherwise none
          *  will have the wscale opt just like it should. */
-        if (p->tcpvars.ws != NULL) {
+        if (TCP_HAS_WSCALE(p)) {
             ssn->client.wscale = TCP_GET_WSCALE(p);
             ssn->server.wscale = TCP_WSCALE_MAX;
         }
@@ -912,7 +912,7 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p,
 
         /* Set the timestamp value for both streams, if packet has timestamp
          * option enabled.*/
-        if (p->tcpvars.ts != NULL) {
+        if (TCP_HAS_TS(p)) {
             ssn->server.last_ts = TCP_GET_TSVAL(p);
             ssn->client.last_ts = TCP_GET_TSECR(p);
             SCLogDebug("ssn %p: ssn->server.last_ts %" PRIu32" "
@@ -963,10 +963,9 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p,
 
         /* Set the stream timestamp value, if packet has timestamp option
          * enabled. */
-        if (p->tcpvars.ts != NULL) {
+        if (TCP_HAS_TS(p)) {
             ssn->client.last_ts = TCP_GET_TSVAL(p);
-            SCLogDebug("ssn %p: p->tcpvars.ts %p, %02x", ssn, p->tcpvars.ts,
-                    ssn->client.last_ts);
+            SCLogDebug("ssn %p: %02x", ssn, ssn->client.last_ts);
 
             if (ssn->client.last_ts == 0)
                 ssn->client.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
@@ -976,7 +975,7 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p,
         }
 
         ssn->server.window = TCP_GET_WINDOW(p);
-        if (p->tcpvars.ws != NULL) {
+        if (TCP_HAS_WSCALE(p)) {
             ssn->flags |= STREAMTCP_FLAG_SERVER_WSCALE;
             ssn->server.wscale = TCP_GET_WSCALE(p);
         }
@@ -1041,7 +1040,7 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p,
 
         /* Set the timestamp value for both streams, if packet has timestamp
          * option enabled.*/
-        if (p->tcpvars.ts != NULL) {
+        if (TCP_HAS_TS(p)) {
             ssn->client.last_ts = TCP_GET_TSVAL(p);
             ssn->server.last_ts = TCP_GET_TSECR(p);
             SCLogDebug("ssn %p: ssn->server.last_ts %" PRIu32" "
@@ -1089,11 +1088,11 @@ static inline void StreamTcp3whsSynAckToStateQueue(Packet *p, TcpStateQueue *q)
     if (TCP_GET_SACKOK(p) == 1)
         q->flags |= STREAMTCP_QUEUE_FLAG_SACK;
 
-    if (p->tcpvars.ws != NULL) {
+    if (TCP_HAS_WSCALE(p)) {
         q->flags |= STREAMTCP_QUEUE_FLAG_WS;
         q->wscale = TCP_GET_WSCALE(p);
     }
-    if (p->tcpvars.ts != NULL) {
+    if (TCP_HAS_TS(p)) {
         q->flags |= STREAMTCP_QUEUE_FLAG_TS;
         q->ts = TCP_GET_TSVAL(p);
     }
@@ -1363,7 +1362,7 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p,
 
             /* Set the timestamp values used to validate the timestamp of
              * received packets. */
-            if ((p->tcpvars.ts != NULL) &&
+            if ((TCP_HAS_TS(p)) &&
                     (ssn->server.flags & STREAMTCP_STREAM_FLAG_TIMESTAMP))
             {
                 ssn->client.last_ts = TCP_GET_TSVAL(p);
@@ -1386,7 +1385,7 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p,
             /** check for the presense of the ws ptr to determine if we
              *  support wscale at all */
             if ((ssn->flags & STREAMTCP_FLAG_SERVER_WSCALE) &&
-                    (p->tcpvars.ws != NULL))
+                    (TCP_HAS_WSCALE(p)))
             {
                 ssn->server.wscale = TCP_GET_WSCALE(p);
             } else {
@@ -1462,10 +1461,9 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p,
 
             /* Set the stream timestamp value, if packet has timestamp
              * option enabled. */
-            if (p->tcpvars.ts != NULL) {
+            if (TCP_HAS_TS(p)) {
                 ssn->server.last_ts = TCP_GET_TSVAL(p);
-                SCLogDebug("ssn %p: p->tcpvars.ts %p, %02x", ssn,
-                        p->tcpvars.ts, ssn->server.last_ts);
+                SCLogDebug("ssn %p: %02x", ssn, ssn->server.last_ts);
 
                 if (ssn->server.last_ts == 0)
                     ssn->server.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
@@ -1474,7 +1472,7 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p,
             }
 
             ssn->server.window = TCP_GET_WINDOW(p);
-            if (p->tcpvars.ws != NULL) {
+            if (TCP_HAS_WSCALE(p)) {
                 ssn->flags |= STREAMTCP_FLAG_SERVER_WSCALE;
                 ssn->server.wscale = TCP_GET_WSCALE(p);
             } else {
@@ -1551,7 +1549,7 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p,
 
         /* Set the timestamp values used to validate the timestamp of
          * received packets.*/
-        if (p->tcpvars.ts != NULL &&
+        if (TCP_HAS_TS(p) &&
                 (ssn->client.flags & STREAMTCP_STREAM_FLAG_TIMESTAMP))
         {
             ssn->flags |= STREAMTCP_FLAG_TIMESTAMP;
@@ -5370,7 +5368,7 @@ static int StreamTcpValidateTimestamp (TcpSession *ssn, Packet *p)
         StreamTcpSetOSPolicy(receiver_stream, p);
     }
 
-    if (p->tcpvars.ts != NULL) {
+    if (TCP_HAS_TS(p)) {
         uint32_t ts = TCP_GET_TSVAL(p);
         uint32_t last_pkt_ts = sender_stream->last_pkt_ts;
         uint32_t last_ts = sender_stream->last_ts;
@@ -5512,7 +5510,7 @@ static int StreamTcpHandleTimestamp (TcpSession *ssn, Packet *p)
         StreamTcpSetOSPolicy(receiver_stream, p);
     }
 
-    if (p->tcpvars.ts != NULL) {
+    if (TCP_HAS_TS(p)) {
         uint32_t ts = TCP_GET_TSVAL(p);
 
         if (sender_stream->flags & STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP) {
@@ -6466,8 +6464,6 @@ static int StreamTcpTest07 (void)
     StreamTcpThread stt;
     TCPHdr tcph;
     uint8_t payload[1] = {0x42};
-    TCPVars tcpvars;
-    TCPOpt ts;
     uint32_t data[2];
     PacketQueue pq;
 
@@ -6477,8 +6473,6 @@ static int StreamTcpTest07 (void)
     memset(&tv, 0, sizeof (ThreadVars));
     memset(&stt, 0, sizeof(StreamTcpThread));
     memset(&tcph, 0, sizeof(TCPHdr));
-    memset(&tcpvars, 0, sizeof(TCPVars));
-    memset(&ts, 0, sizeof(TCPOpt));
 
     FLOW_INITIALIZE(&f);
     p->flow = &f;
@@ -6500,11 +6494,9 @@ static int StreamTcpTest07 (void)
     data[0] = htonl(10);
     data[1] = htonl(11);
 
-    ts.type = TCP_OPT_TS;
-    ts.len = 10;
-    ts.data = (uint8_t *)data;
-    tcpvars.ts = &ts;
-    p->tcpvars = tcpvars;
+    p->tcpvars.ts.type = TCP_OPT_TS;
+    p->tcpvars.ts.len = 10;
+    p->tcpvars.ts.data = (uint8_t *)data;
 
     p->payload = payload;
     p->payload_len = 1;
@@ -6519,7 +6511,7 @@ static int StreamTcpTest07 (void)
     p->flowflags = FLOW_PKT_TOSERVER;
 
     data[0] = htonl(2);
-    p->tcpvars.ts->data = (uint8_t *)data;
+    p->tcpvars.ts.data = (uint8_t *)data;
 
     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
         if (((TcpSession *) (p->flow->protoctx))->client.next_seq != 11) {
@@ -6558,8 +6550,6 @@ static int StreamTcpTest08 (void)
     StreamTcpThread stt;
     TCPHdr tcph;
     uint8_t payload[1] = {0x42};
-    TCPVars tcpvars;
-    TCPOpt ts;
     uint32_t data[2];
 
     memset(p, 0, SIZE_OF_PACKET);
@@ -6569,8 +6559,6 @@ static int StreamTcpTest08 (void)
     memset(&tv, 0, sizeof (ThreadVars));
     memset(&stt, 0, sizeof(StreamTcpThread));
     memset(&tcph, 0, sizeof(TCPHdr));
-    memset(&tcpvars, 0, sizeof(TCPVars));
-    memset(&ts, 0, sizeof(TCPOpt));
 
     FLOW_INITIALIZE(&f);
     p->flow = &f;
@@ -6592,11 +6580,9 @@ static int StreamTcpTest08 (void)
     data[0] = htonl(10);
     data[1] = htonl(11);
 
-    ts.type = TCP_OPT_TS;
-    ts.len = 10;
-    ts.data = (uint8_t *)data;
-    tcpvars.ts = &ts;
-    p->tcpvars = tcpvars;
+    p->tcpvars.ts.type = TCP_OPT_TS;
+    p->tcpvars.ts.len = 10;
+    p->tcpvars.ts.data = (uint8_t *)data;
 
     p->payload = payload;
     p->payload_len = 1;
@@ -6611,7 +6597,7 @@ static int StreamTcpTest08 (void)
     p->flowflags = FLOW_PKT_TOSERVER;
 
     data[0] = htonl(12);
-    p->tcpvars.ts->data = (uint8_t *)data;
+    p->tcpvars.ts.data = (uint8_t *)data;
 
     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
         goto end;