1 /* Copyright (C) 2007-2016 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  * \author Gurvinder Singh <gurvindersinghdahiya@gmail.com>
23  *
24  * TCP stream tracking and reassembly engine.
25  *
26  * \todo - 4WHS: what if after the 2nd SYN we turn out to be normal 3WHS anyway?
27  */
28 
29 #include "suricata-common.h"
30 #include "suricata.h"
31 
32 #include "decode.h"
33 #include "debug.h"
34 #include "detect.h"
35 
36 #include "flow.h"
37 #include "flow-util.h"
38 
39 #include "conf.h"
40 #include "conf-yaml-loader.h"
41 
42 #include "threads.h"
43 #include "threadvars.h"
44 #include "tm-threads.h"
45 
46 #include "util-pool.h"
47 #include "util-pool-thread.h"
48 #include "util-checksum.h"
49 #include "util-unittest.h"
50 #include "util-print.h"
51 #include "util-debug.h"
52 #include "util-device.h"
53 
54 #include "stream-tcp-private.h"
55 #include "stream-tcp-reassemble.h"
56 #include "stream-tcp.h"
57 #include "stream-tcp-inline.h"
58 #include "stream-tcp-sack.h"
59 #include "stream-tcp-util.h"
60 #include "stream.h"
61 
62 #include "pkt-var.h"
63 #include "host.h"
64 
65 #include "app-layer.h"
66 #include "app-layer-parser.h"
67 #include "app-layer-protos.h"
68 #include "app-layer-htp-mem.h"
69 
70 #include "util-host-os-info.h"
71 #include "util-privs.h"
72 #include "util-profiling.h"
73 #include "util-misc.h"
74 #include "util-validate.h"
75 #include "util-runmodes.h"
76 #include "util-random.h"
77 
78 #include "source-pcap-file.h"
79 
80 //#define DEBUG
81 
82 #define STREAMTCP_DEFAULT_PREALLOC              2048
83 #define STREAMTCP_DEFAULT_MEMCAP                (64 * 1024 * 1024)  /* 64mb */
84 #define STREAMTCP_DEFAULT_REASSEMBLY_MEMCAP     (256 * 1024 * 1024) /* 256mb */
85 #define STREAMTCP_DEFAULT_TOSERVER_CHUNK_SIZE   2560
86 #define STREAMTCP_DEFAULT_TOCLIENT_CHUNK_SIZE   2560
87 #define STREAMTCP_DEFAULT_MAX_SYNACK_QUEUED     5
88 
89 #define STREAMTCP_NEW_TIMEOUT                   60
90 #define STREAMTCP_EST_TIMEOUT                   3600
91 #define STREAMTCP_CLOSED_TIMEOUT                120
92 
93 #define STREAMTCP_EMERG_NEW_TIMEOUT             10
94 #define STREAMTCP_EMERG_EST_TIMEOUT             300
95 #define STREAMTCP_EMERG_CLOSED_TIMEOUT          20
96 
97 static int StreamTcpHandleFin(ThreadVars *tv, StreamTcpThread *, TcpSession *, Packet *, PacketQueueNoLock *);
98 void StreamTcpReturnStreamSegments (TcpStream *);
99 void StreamTcpInitConfig(char);
100 int StreamTcpGetFlowState(void *);
101 void StreamTcpSetOSPolicy(TcpStream*, Packet*);
102 
103 static int StreamTcpValidateTimestamp(TcpSession * , Packet *);
104 static int StreamTcpHandleTimestamp(TcpSession * , Packet *);
105 static int StreamTcpValidateRst(TcpSession * , Packet *);
106 static inline int StreamTcpValidateAck(TcpSession *ssn, TcpStream *, Packet *);
107 static int StreamTcpStateDispatch(ThreadVars *tv, Packet *p,
108         StreamTcpThread *stt, TcpSession *ssn, PacketQueueNoLock *pq,
109         uint8_t state);
110 
111 extern int g_detect_disabled;
112 
113 static PoolThread *ssn_pool = NULL;
114 static SCMutex ssn_pool_mutex = SCMUTEX_INITIALIZER; /**< init only, protect initializing and growing pool */
115 #ifdef DEBUG
116 static uint64_t ssn_pool_cnt = 0; /** counts ssns, protected by ssn_pool_mutex */
117 #endif
118 
119 TcpStreamCnf stream_config;
120 uint64_t StreamTcpReassembleMemuseGlobalCounter(void);
121 SC_ATOMIC_DECLARE(uint64_t, st_memuse);
122 
StreamTcpInitMemuse(void)123 void StreamTcpInitMemuse(void)
124 {
125     SC_ATOMIC_INIT(st_memuse);
126 }
127 
StreamTcpIncrMemuse(uint64_t size)128 void StreamTcpIncrMemuse(uint64_t size)
129 {
130     (void) SC_ATOMIC_ADD(st_memuse, size);
131     SCLogDebug("STREAM %"PRIu64", incr %"PRIu64, StreamTcpMemuseCounter(), size);
132     return;
133 }
134 
StreamTcpDecrMemuse(uint64_t size)135 void StreamTcpDecrMemuse(uint64_t size)
136 {
137 #ifdef DEBUG_VALIDATION
138     uint64_t presize = SC_ATOMIC_GET(st_memuse);
139     if (RunmodeIsUnittests()) {
140         BUG_ON(presize > UINT_MAX);
141     }
142 #endif
143 
144     (void) SC_ATOMIC_SUB(st_memuse, size);
145 
146 #ifdef DEBUG_VALIDATION
147     if (RunmodeIsUnittests()) {
148         uint64_t postsize = SC_ATOMIC_GET(st_memuse);
149         BUG_ON(postsize > presize);
150     }
151 #endif
152     SCLogDebug("STREAM %"PRIu64", decr %"PRIu64, StreamTcpMemuseCounter(), size);
153     return;
154 }
155 
StreamTcpMemuseCounter(void)156 uint64_t StreamTcpMemuseCounter(void)
157 {
158     uint64_t memusecopy = SC_ATOMIC_GET(st_memuse);
159     return memusecopy;
160 }
161 
162 /**
163  *  \brief Check if alloc'ing "size" would mean we're over memcap
164  *
165  *  \retval 1 if in bounds
166  *  \retval 0 if not in bounds
167  */
StreamTcpCheckMemcap(uint64_t size)168 int StreamTcpCheckMemcap(uint64_t size)
169 {
170     uint64_t memcapcopy = SC_ATOMIC_GET(stream_config.memcap);
171     if (memcapcopy == 0 || size + SC_ATOMIC_GET(st_memuse) <= memcapcopy)
172         return 1;
173     return 0;
174 }
175 
176 /**
177  *  \brief Update memcap value
178  *
179  *  \param size new memcap value
180  */
StreamTcpSetMemcap(uint64_t size)181 int StreamTcpSetMemcap(uint64_t size)
182 {
183     if (size == 0 || (uint64_t)SC_ATOMIC_GET(st_memuse) < size) {
184         SC_ATOMIC_SET(stream_config.memcap, size);
185         return 1;
186     }
187 
188     return 0;
189 }
190 
191 /**
192  *  \brief Return memcap value
193  *
194  *  \param memcap memcap value
195  */
StreamTcpGetMemcap(void)196 uint64_t StreamTcpGetMemcap(void)
197 {
198     uint64_t memcapcopy = SC_ATOMIC_GET(stream_config.memcap);
199     return memcapcopy;
200 }
201 
StreamTcpStreamCleanup(TcpStream * stream)202 void StreamTcpStreamCleanup(TcpStream *stream)
203 {
204     if (stream != NULL) {
205         StreamTcpSackFreeList(stream);
206         StreamTcpReturnStreamSegments(stream);
207         StreamingBufferClear(&stream->sb);
208     }
209 }
210 
211 /**
212  *  \brief Session cleanup function. Does not free the ssn.
213  *  \param ssn tcp session
214  */
StreamTcpSessionCleanup(TcpSession * ssn)215 void StreamTcpSessionCleanup(TcpSession *ssn)
216 {
217     SCEnter();
218     TcpStateQueue *q, *q_next;
219 
220     if (ssn == NULL)
221         return;
222 
223     StreamTcpStreamCleanup(&ssn->client);
224     StreamTcpStreamCleanup(&ssn->server);
225 
226     q = ssn->queue;
227     while (q != NULL) {
228         q_next = q->next;
229         SCFree(q);
230         q = q_next;
231         StreamTcpDecrMemuse((uint64_t)sizeof(TcpStateQueue));
232     }
233     ssn->queue = NULL;
234     ssn->queue_len = 0;
235 
236     SCReturn;
237 }
238 
239 /**
240  *  \brief Function to return the stream back to the pool. It returns the
241  *         segments in the stream to the segment pool.
242  *
243  *  This function is called when the flow is destroyed, so it should free
244  *  *everything* related to the tcp session. So including the app layer
245  *  data. We are guaranteed to only get here when the flow's use_cnt is 0.
246  *
247  *  \param ssn Void ptr to the ssn.
248  */
StreamTcpSessionClear(void * ssnptr)249 void StreamTcpSessionClear(void *ssnptr)
250 {
251     SCEnter();
252     TcpSession *ssn = (TcpSession *)ssnptr;
253     if (ssn == NULL)
254         return;
255 
256     StreamTcpSessionCleanup(ssn);
257 
258     /* HACK: don't loose track of thread id */
259     PoolThreadReserved a = ssn->res;
260     memset(ssn, 0, sizeof(TcpSession));
261     ssn->res = a;
262 
263     PoolThreadReturn(ssn_pool, ssn);
264 #ifdef DEBUG
265     SCMutexLock(&ssn_pool_mutex);
266     ssn_pool_cnt--;
267     SCMutexUnlock(&ssn_pool_mutex);
268 #endif
269 
270     SCReturn;
271 }
272 
273 /**
274  *  \brief Function to return the stream segments back to the pool.
275  *
276  *  We don't clear out the app layer storage here as that is under protection
277  *  of the "use_cnt" reference counter in the flow. This function is called
278  *  when the use_cnt is always at least 1 (this pkt has incremented the flow
279  *  use_cnt itself), so we don't bother.
280  *
281  *  \param p Packet used to identify the stream.
282  */
StreamTcpSessionPktFree(Packet * p)283 void StreamTcpSessionPktFree (Packet *p)
284 {
285     SCEnter();
286 
287     TcpSession *ssn = (TcpSession *)p->flow->protoctx;
288     if (ssn == NULL)
289         SCReturn;
290 
291     StreamTcpReturnStreamSegments(&ssn->client);
292     StreamTcpReturnStreamSegments(&ssn->server);
293 
294     SCReturn;
295 }
296 
297 /** \brief Stream alloc function for the Pool
298  *  \retval ptr void ptr to TcpSession structure with all vars set to 0/NULL
299  */
StreamTcpSessionPoolAlloc(void)300 static void *StreamTcpSessionPoolAlloc(void)
301 {
302     void *ptr = NULL;
303 
304     if (StreamTcpCheckMemcap((uint32_t)sizeof(TcpSession)) == 0)
305         return NULL;
306 
307     ptr = SCMalloc(sizeof(TcpSession));
308     if (unlikely(ptr == NULL))
309         return NULL;
310 
311     return ptr;
312 }
313 
StreamTcpSessionPoolInit(void * data,void * initdata)314 static int StreamTcpSessionPoolInit(void *data, void* initdata)
315 {
316     memset(data, 0, sizeof(TcpSession));
317     StreamTcpIncrMemuse((uint64_t)sizeof(TcpSession));
318 
319     return 1;
320 }
321 
322 /** \brief Pool cleanup function
323  *  \param s Void ptr to TcpSession memory */
StreamTcpSessionPoolCleanup(void * s)324 static void StreamTcpSessionPoolCleanup(void *s)
325 {
326     if (s != NULL) {
327         StreamTcpSessionCleanup(s);
328         /** \todo not very clean, as the memory is not freed here */
329         StreamTcpDecrMemuse((uint64_t)sizeof(TcpSession));
330     }
331 }
332 
333 /**
334  *  \brief See if stream engine is dropping invalid packet in inline mode
335  *
336  *  \retval 0 no
337  *  \retval 1 yes
338  */
StreamTcpInlineDropInvalid(void)339 int StreamTcpInlineDropInvalid(void)
340 {
341     return ((stream_config.flags & STREAMTCP_INIT_FLAG_INLINE)
342             && (stream_config.flags & STREAMTCP_INIT_FLAG_DROP_INVALID));
343 }
344 
345 /* hack: stream random range code expects random values in range of 0-RAND_MAX,
346  * but we can get both <0 and >RAND_MAX values from RandomGet
347  */
RandomGetWrap(void)348 static int RandomGetWrap(void)
349 {
350     unsigned long r;
351 
352     do {
353         r = RandomGet();
354     } while(r >= ULONG_MAX - (ULONG_MAX % RAND_MAX));
355 
356     return r % RAND_MAX;
357 }
358 
359 /** \brief          To initialize the stream global configuration data
360  *
361  *  \param  quiet   It tells the mode of operation, if it is TRUE nothing will
362  *                  be get printed.
363  */
364 
StreamTcpInitConfig(char quiet)365 void StreamTcpInitConfig(char quiet)
366 {
367     intmax_t value = 0;
368     uint16_t rdrange = 10;
369 
370     SCLogDebug("Initializing Stream");
371 
372     memset(&stream_config,  0, sizeof(stream_config));
373 
374     SC_ATOMIC_INIT(stream_config.memcap);
375     SC_ATOMIC_INIT(stream_config.reassembly_memcap);
376 
377     if ((ConfGetInt("stream.max-sessions", &value)) == 1) {
378         SCLogWarning(SC_WARN_OPTION_OBSOLETE, "max-sessions is obsolete. "
379             "Number of concurrent sessions is now only limited by Flow and "
380             "TCP stream engine memcaps.");
381     }
382 
383     if ((ConfGetInt("stream.prealloc-sessions", &value)) == 1) {
384         stream_config.prealloc_sessions = (uint32_t)value;
385     } else {
386         if (RunmodeIsUnittests()) {
387             stream_config.prealloc_sessions = 128;
388         } else {
389             stream_config.prealloc_sessions = STREAMTCP_DEFAULT_PREALLOC;
390             if (ConfGetNode("stream.prealloc-sessions") != NULL) {
391                 WarnInvalidConfEntry("stream.prealloc_sessions",
392                                      "%"PRIu32,
393                                      stream_config.prealloc_sessions);
394             }
395         }
396     }
397     if (!quiet) {
398         SCLogConfig("stream \"prealloc-sessions\": %"PRIu32" (per thread)",
399                 stream_config.prealloc_sessions);
400     }
401 
402     const char *temp_stream_memcap_str;
403     if (ConfGetValue("stream.memcap", &temp_stream_memcap_str) == 1) {
404         uint64_t stream_memcap_copy;
405         if (ParseSizeStringU64(temp_stream_memcap_str, &stream_memcap_copy) < 0) {
406             SCLogError(SC_ERR_SIZE_PARSE, "Error parsing stream.memcap "
407                        "from conf file - %s.  Killing engine",
408                        temp_stream_memcap_str);
409             exit(EXIT_FAILURE);
410         } else {
411             SC_ATOMIC_SET(stream_config.memcap, stream_memcap_copy);
412         }
413     } else {
414         SC_ATOMIC_SET(stream_config.memcap, STREAMTCP_DEFAULT_MEMCAP);
415     }
416 
417     if (!quiet) {
418         SCLogConfig("stream \"memcap\": %"PRIu64, SC_ATOMIC_GET(stream_config.memcap));
419     }
420 
421     ConfGetBool("stream.midstream", &stream_config.midstream);
422 
423     if (!quiet) {
424         SCLogConfig("stream \"midstream\" session pickups: %s", stream_config.midstream ? "enabled" : "disabled");
425     }
426 
427     ConfGetBool("stream.async-oneside", &stream_config.async_oneside);
428 
429     if (!quiet) {
430         SCLogConfig("stream \"async-oneside\": %s", stream_config.async_oneside ? "enabled" : "disabled");
431     }
432 
433     int csum = 0;
434 
435     if ((ConfGetBool("stream.checksum-validation", &csum)) == 1) {
436         if (csum == 1) {
437             stream_config.flags |= STREAMTCP_INIT_FLAG_CHECKSUM_VALIDATION;
438         }
439     /* Default is that we validate the checksum of all the packets */
440     } else {
441         stream_config.flags |= STREAMTCP_INIT_FLAG_CHECKSUM_VALIDATION;
442     }
443 
444     if (!quiet) {
445         SCLogConfig("stream \"checksum-validation\": %s",
446                 stream_config.flags & STREAMTCP_INIT_FLAG_CHECKSUM_VALIDATION ?
447                 "enabled" : "disabled");
448     }
449 
450     const char *temp_stream_inline_str;
451     if (ConfGetValue("stream.inline", &temp_stream_inline_str) == 1) {
452         int inl = 0;
453 
454         /* checking for "auto" and falling back to boolean to provide
455          * backward compatibility */
456         if (strcmp(temp_stream_inline_str, "auto") == 0) {
457             if (EngineModeIsIPS()) {
458                 stream_config.flags |= STREAMTCP_INIT_FLAG_INLINE;
459             }
460         } else if (ConfGetBool("stream.inline", &inl) == 1) {
461             if (inl) {
462                 stream_config.flags |= STREAMTCP_INIT_FLAG_INLINE;
463             }
464         }
465     } else {
466         /* default to 'auto' */
467         if (EngineModeIsIPS()) {
468             stream_config.flags |= STREAMTCP_INIT_FLAG_INLINE;
469         }
470     }
471 
472     if (!quiet) {
473         SCLogConfig("stream.\"inline\": %s",
474                     stream_config.flags & STREAMTCP_INIT_FLAG_INLINE
475                     ? "enabled" : "disabled");
476     }
477 
478     int bypass = 0;
479     if ((ConfGetBool("stream.bypass", &bypass)) == 1) {
480         if (bypass == 1) {
481             stream_config.flags |= STREAMTCP_INIT_FLAG_BYPASS;
482         }
483     }
484 
485     if (!quiet) {
486         SCLogConfig("stream \"bypass\": %s",
487                     (stream_config.flags & STREAMTCP_INIT_FLAG_BYPASS)
488                     ? "enabled" : "disabled");
489     }
490 
491     int drop_invalid = 0;
492     if ((ConfGetBool("stream.drop-invalid", &drop_invalid)) == 1) {
493         if (drop_invalid == 1) {
494             stream_config.flags |= STREAMTCP_INIT_FLAG_DROP_INVALID;
495         }
496     } else {
497         stream_config.flags |= STREAMTCP_INIT_FLAG_DROP_INVALID;
498     }
499 
500     if ((ConfGetInt("stream.max-synack-queued", &value)) == 1) {
501         if (value >= 0 && value <= 255) {
502             stream_config.max_synack_queued = (uint8_t)value;
503         } else {
504             stream_config.max_synack_queued = (uint8_t)STREAMTCP_DEFAULT_MAX_SYNACK_QUEUED;
505         }
506     } else {
507         stream_config.max_synack_queued = (uint8_t)STREAMTCP_DEFAULT_MAX_SYNACK_QUEUED;
508     }
509     if (!quiet) {
510         SCLogConfig("stream \"max-synack-queued\": %"PRIu8, stream_config.max_synack_queued);
511     }
512 
513     const char *temp_stream_reassembly_memcap_str;
514     if (ConfGetValue("stream.reassembly.memcap", &temp_stream_reassembly_memcap_str) == 1) {
515         uint64_t stream_reassembly_memcap_copy;
516         if (ParseSizeStringU64(temp_stream_reassembly_memcap_str,
517                                &stream_reassembly_memcap_copy) < 0) {
518             SCLogError(SC_ERR_SIZE_PARSE, "Error parsing "
519                        "stream.reassembly.memcap "
520                        "from conf file - %s.  Killing engine",
521                        temp_stream_reassembly_memcap_str);
522             exit(EXIT_FAILURE);
523         } else {
524             SC_ATOMIC_SET(stream_config.reassembly_memcap, stream_reassembly_memcap_copy);
525         }
526     } else {
527         SC_ATOMIC_SET(stream_config.reassembly_memcap , STREAMTCP_DEFAULT_REASSEMBLY_MEMCAP);
528     }
529 
530     if (!quiet) {
531         SCLogConfig("stream.reassembly \"memcap\": %"PRIu64"",
532                     SC_ATOMIC_GET(stream_config.reassembly_memcap));
533     }
534 
535     const char *temp_stream_reassembly_depth_str;
536     if (ConfGetValue("stream.reassembly.depth", &temp_stream_reassembly_depth_str) == 1) {
537         if (ParseSizeStringU32(temp_stream_reassembly_depth_str,
538                                &stream_config.reassembly_depth) < 0) {
539             SCLogError(SC_ERR_SIZE_PARSE, "Error parsing "
540                        "stream.reassembly.depth "
541                        "from conf file - %s.  Killing engine",
542                        temp_stream_reassembly_depth_str);
543             exit(EXIT_FAILURE);
544         }
545     } else {
546         stream_config.reassembly_depth = 0;
547     }
548 
549     if (!quiet) {
550         SCLogConfig("stream.reassembly \"depth\": %"PRIu32"", stream_config.reassembly_depth);
551     }
552 
553     int randomize = 0;
554     if ((ConfGetBool("stream.reassembly.randomize-chunk-size", &randomize)) == 0) {
555         /* randomize by default if value not set
556          * In ut mode we disable, to get predictible test results */
557         if (!(RunmodeIsUnittests()))
558             randomize = 1;
559     }
560 
561     if (randomize) {
562         const char *temp_rdrange;
563         if (ConfGetValue("stream.reassembly.randomize-chunk-range",
564                     &temp_rdrange) == 1) {
565             if (ParseSizeStringU16(temp_rdrange, &rdrange) < 0) {
566                 SCLogError(SC_ERR_SIZE_PARSE, "Error parsing "
567                         "stream.reassembly.randomize-chunk-range "
568                         "from conf file - %s.  Killing engine",
569                         temp_rdrange);
570                 exit(EXIT_FAILURE);
571             } else if (rdrange >= 100) {
572                            FatalError(SC_ERR_FATAL,
573                                       "stream.reassembly.randomize-chunk-range "
574                                       "must be lower than 100");
575             }
576         }
577     }
578 
579     const char *temp_stream_reassembly_toserver_chunk_size_str;
580     if (ConfGetValue("stream.reassembly.toserver-chunk-size",
581                 &temp_stream_reassembly_toserver_chunk_size_str) == 1) {
582         if (ParseSizeStringU16(temp_stream_reassembly_toserver_chunk_size_str,
583                                &stream_config.reassembly_toserver_chunk_size) < 0) {
584             SCLogError(SC_ERR_SIZE_PARSE, "Error parsing "
585                        "stream.reassembly.toserver-chunk-size "
586                        "from conf file - %s.  Killing engine",
587                        temp_stream_reassembly_toserver_chunk_size_str);
588             exit(EXIT_FAILURE);
589         }
590     } else {
591         stream_config.reassembly_toserver_chunk_size =
592             STREAMTCP_DEFAULT_TOSERVER_CHUNK_SIZE;
593     }
594 
595     if (randomize) {
596         long int r = RandomGetWrap();
597         stream_config.reassembly_toserver_chunk_size +=
598             (int) (stream_config.reassembly_toserver_chunk_size *
599                    (r * 1.0 / RAND_MAX - 0.5) * rdrange / 100);
600     }
601     const char *temp_stream_reassembly_toclient_chunk_size_str;
602     if (ConfGetValue("stream.reassembly.toclient-chunk-size",
603                 &temp_stream_reassembly_toclient_chunk_size_str) == 1) {
604         if (ParseSizeStringU16(temp_stream_reassembly_toclient_chunk_size_str,
605                                &stream_config.reassembly_toclient_chunk_size) < 0) {
606             SCLogError(SC_ERR_SIZE_PARSE, "Error parsing "
607                        "stream.reassembly.toclient-chunk-size "
608                        "from conf file - %s.  Killing engine",
609                        temp_stream_reassembly_toclient_chunk_size_str);
610             exit(EXIT_FAILURE);
611         }
612     } else {
613         stream_config.reassembly_toclient_chunk_size =
614             STREAMTCP_DEFAULT_TOCLIENT_CHUNK_SIZE;
615     }
616 
617     if (randomize) {
618         long int r = RandomGetWrap();
619         stream_config.reassembly_toclient_chunk_size +=
620             (int) (stream_config.reassembly_toclient_chunk_size *
621                    (r * 1.0 / RAND_MAX - 0.5) * rdrange / 100);
622     }
623     if (!quiet) {
624         SCLogConfig("stream.reassembly \"toserver-chunk-size\": %"PRIu16,
625             stream_config.reassembly_toserver_chunk_size);
626         SCLogConfig("stream.reassembly \"toclient-chunk-size\": %"PRIu16,
627             stream_config.reassembly_toclient_chunk_size);
628     }
629 
630     int enable_raw = 1;
631     if (ConfGetBool("stream.reassembly.raw", &enable_raw) == 1) {
632         if (!enable_raw) {
633             stream_config.stream_init_flags = STREAMTCP_STREAM_FLAG_DISABLE_RAW;
634         }
635     } else {
636         enable_raw = 1;
637     }
638     if (!quiet)
639         SCLogConfig("stream.reassembly.raw: %s", enable_raw ? "enabled" : "disabled");
640 
641     /* init the memcap/use tracking */
642     StreamTcpInitMemuse();
643     StatsRegisterGlobalCounter("tcp.memuse", StreamTcpMemuseCounter);
644 
645     StreamTcpReassembleInit(quiet);
646 
647     /* set the default free function and flow state function
648      * values. */
649     FlowSetProtoFreeFunc(IPPROTO_TCP, StreamTcpSessionClear);
650 
651 #ifdef UNITTESTS
652     if (RunmodeIsUnittests()) {
653         SCMutexLock(&ssn_pool_mutex);
654         if (ssn_pool == NULL) {
655             ssn_pool = PoolThreadInit(1, /* thread */
656                     0, /* unlimited */
657                     stream_config.prealloc_sessions,
658                     sizeof(TcpSession),
659                     StreamTcpSessionPoolAlloc,
660                     StreamTcpSessionPoolInit, NULL,
661                     StreamTcpSessionPoolCleanup, NULL);
662         }
663         SCMutexUnlock(&ssn_pool_mutex);
664     }
665 #endif
666 }
667 
StreamTcpFreeConfig(char quiet)668 void StreamTcpFreeConfig(char quiet)
669 {
670     StreamTcpReassembleFree(quiet);
671 
672     SCMutexLock(&ssn_pool_mutex);
673     if (ssn_pool != NULL) {
674         PoolThreadFree(ssn_pool);
675         ssn_pool = NULL;
676     }
677     SCMutexUnlock(&ssn_pool_mutex);
678     SCMutexDestroy(&ssn_pool_mutex);
679 
680     SCLogDebug("ssn_pool_cnt %"PRIu64"", ssn_pool_cnt);
681 }
682 
683 /** \internal
684  *  \brief The function is used to to fetch a TCP session from the
685  *         ssn_pool, when a TCP SYN is received.
686  *
687  *  \param p packet starting the new TCP session.
688  *  \param id thread pool id
689  *
690  *  \retval ssn new TCP session.
691  */
StreamTcpNewSession(Packet * p,int id)692 static TcpSession *StreamTcpNewSession (Packet *p, int id)
693 {
694     TcpSession *ssn = (TcpSession *)p->flow->protoctx;
695 
696     if (ssn == NULL) {
697         p->flow->protoctx = PoolThreadGetById(ssn_pool, id);
698 #ifdef DEBUG
699         SCMutexLock(&ssn_pool_mutex);
700         if (p->flow->protoctx != NULL)
701             ssn_pool_cnt++;
702         SCMutexUnlock(&ssn_pool_mutex);
703 #endif
704 
705         ssn = (TcpSession *)p->flow->protoctx;
706         if (ssn == NULL) {
707             SCLogDebug("ssn_pool is empty");
708             return NULL;
709         }
710 
711         ssn->state = TCP_NONE;
712         ssn->reassembly_depth = stream_config.reassembly_depth;
713         ssn->tcp_packet_flags = p->tcph ? p->tcph->th_flags : 0;
714         ssn->server.flags = stream_config.stream_init_flags;
715         ssn->client.flags = stream_config.stream_init_flags;
716 
717         StreamingBuffer x = STREAMING_BUFFER_INITIALIZER(&stream_config.sbcnf);
718         ssn->client.sb = x;
719         ssn->server.sb = x;
720 
721         if (PKT_IS_TOSERVER(p)) {
722             ssn->client.tcp_flags = p->tcph ? p->tcph->th_flags : 0;
723             ssn->server.tcp_flags = 0;
724         } else if (PKT_IS_TOCLIENT(p)) {
725             ssn->server.tcp_flags = p->tcph ? p->tcph->th_flags : 0;
726             ssn->client.tcp_flags = 0;
727         }
728     }
729 
730     return ssn;
731 }
732 
StreamTcpPacketSetState(Packet * p,TcpSession * ssn,uint8_t state)733 static void StreamTcpPacketSetState(Packet *p, TcpSession *ssn,
734                                            uint8_t state)
735 {
736     if (state == ssn->state || PKT_IS_PSEUDOPKT(p))
737         return;
738 
739     ssn->pstate = ssn->state;
740     ssn->state = state;
741 
742     /* update the flow state */
743     switch(ssn->state) {
744         case TCP_ESTABLISHED:
745         case TCP_FIN_WAIT1:
746         case TCP_FIN_WAIT2:
747         case TCP_CLOSING:
748         case TCP_CLOSE_WAIT:
749             FlowUpdateState(p->flow, FLOW_STATE_ESTABLISHED);
750             break;
751         case TCP_LAST_ACK:
752         case TCP_TIME_WAIT:
753         case TCP_CLOSED:
754             FlowUpdateState(p->flow, FLOW_STATE_CLOSED);
755             break;
756     }
757 }
758 
759 /**
760  *  \brief  Function to set the OS policy for the given stream based on the
761  *          destination of the received packet.
762  *
763  *  \param  stream  TcpStream of which os_policy needs to set
764  *  \param  p       Packet which is used to set the os policy
765  */
StreamTcpSetOSPolicy(TcpStream * stream,Packet * p)766 void StreamTcpSetOSPolicy(TcpStream *stream, Packet *p)
767 {
768     int ret = 0;
769 
770     if (PKT_IS_IPV4(p)) {
771         /* Get the OS policy based on destination IP address, as destination
772            OS will decide how to react on the anomalies of newly received
773            packets */
774         ret = SCHInfoGetIPv4HostOSFlavour((uint8_t *)GET_IPV4_DST_ADDR_PTR(p));
775         if (ret > 0)
776             stream->os_policy = ret;
777         else
778             stream->os_policy = OS_POLICY_DEFAULT;
779 
780     } else if (PKT_IS_IPV6(p)) {
781         /* Get the OS policy based on destination IP address, as destination
782            OS will decide how to react on the anomalies of newly received
783            packets */
784         ret = SCHInfoGetIPv6HostOSFlavour((uint8_t *)GET_IPV6_DST_ADDR(p));
785         if (ret > 0)
786             stream->os_policy = ret;
787         else
788             stream->os_policy = OS_POLICY_DEFAULT;
789     }
790 
791     if (stream->os_policy == OS_POLICY_BSD_RIGHT)
792         stream->os_policy = OS_POLICY_BSD;
793     else if (stream->os_policy == OS_POLICY_OLD_SOLARIS)
794         stream->os_policy = OS_POLICY_SOLARIS;
795 
796     SCLogDebug("Policy is %"PRIu8"", stream->os_policy);
797 
798 }
799 
800 /**
801  *  \brief macro to update last_ack only if the new value is higher
802  *
803  *  \param ssn session
804  *  \param stream stream to update
805  *  \param ack ACK value to test and set
806  */
807 #define StreamTcpUpdateLastAck(ssn, stream, ack) { \
808     if (SEQ_GT((ack), (stream)->last_ack)) \
809     { \
810         SCLogDebug("ssn %p: last_ack set to %"PRIu32", moved %u forward", (ssn), (ack), (ack) - (stream)->last_ack); \
811         if ((SEQ_LEQ((stream)->last_ack, (stream)->next_seq) && SEQ_GT((ack),(stream)->next_seq))) { \
812             SCLogDebug("last_ack just passed next_seq: %u (was %u) > %u", (ack), (stream)->last_ack, (stream)->next_seq); \
813         } else { \
814             SCLogDebug("next_seq (%u) <> last_ack now %d", (stream)->next_seq, (int)(stream)->next_seq - (ack)); \
815         }\
816         (stream)->last_ack = (ack); \
817         StreamTcpSackPruneList((stream)); \
818     } else { \
819         SCLogDebug("ssn %p: no update: ack %u, last_ack %"PRIu32", next_seq %u (state %u)", \
820                     (ssn), (ack), (stream)->last_ack, (stream)->next_seq, (ssn)->state); \
821     }\
822 }
823 
824 #define StreamTcpAsyncLastAckUpdate(ssn, stream) {                              \
825     if ((ssn)->flags & STREAMTCP_FLAG_ASYNC) {                                  \
826         if (SEQ_GT((stream)->next_seq, (stream)->last_ack)) {                   \
827             uint32_t ack_diff = (stream)->next_seq - (stream)->last_ack;        \
828             (stream)->last_ack += ack_diff;                                     \
829             SCLogDebug("ssn %p: ASYNC last_ack set to %"PRIu32", moved %u forward",     \
830                     (ssn), (stream)->next_seq, ack_diff);                               \
831         }                                                                       \
832     }                                                                           \
833 }
834 
835 #define StreamTcpUpdateNextSeq(ssn, stream, seq) {                      \
836     (stream)->next_seq = seq;                                           \
837     SCLogDebug("ssn %p: next_seq %" PRIu32, (ssn), (stream)->next_seq); \
838     StreamTcpAsyncLastAckUpdate((ssn), (stream));                       \
839 }
840 
841 /**
842  *  \brief macro to update next_win only if the new value is higher
843  *
844  *  \param ssn session
845  *  \param stream stream to update
846  *  \param win window value to test and set
847  */
848 #define StreamTcpUpdateNextWin(ssn, stream, win) { \
849     uint32_t sacked_size__ = StreamTcpSackedSize((stream)); \
850     if (SEQ_GT(((win) + sacked_size__), (stream)->next_win)) { \
851         (stream)->next_win = ((win) + sacked_size__); \
852         SCLogDebug("ssn %p: next_win set to %"PRIu32, (ssn), (stream)->next_win); \
853     } \
854 }
855 
StreamTcpCloseSsnWithReset(Packet * p,TcpSession * ssn)856 static inline void StreamTcpCloseSsnWithReset(Packet *p, TcpSession *ssn)
857 {
858     ssn->flags |= STREAMTCP_FLAG_CLOSED_BY_RST;
859     StreamTcpPacketSetState(p, ssn, TCP_CLOSED);
860     SCLogDebug("ssn %p: (state: %s) Reset received and state changed to "
861             "TCP_CLOSED", ssn, StreamTcpStateAsString(ssn->state));
862 }
863 
StreamTcpPacketIsRetransmission(TcpStream * stream,Packet * p)864 static int StreamTcpPacketIsRetransmission(TcpStream *stream, Packet *p)
865 {
866     if (p->payload_len == 0)
867         SCReturnInt(0);
868 
869     /* retransmission of already partially ack'd data */
870     if (SEQ_LT(TCP_GET_SEQ(p), stream->last_ack) && SEQ_GT((TCP_GET_SEQ(p) + p->payload_len), stream->last_ack))
871     {
872         StreamTcpSetEvent(p, STREAM_PKT_RETRANSMISSION);
873         SCReturnInt(1);
874     }
875 
876     /* retransmission of already ack'd data */
877     if (SEQ_LEQ((TCP_GET_SEQ(p) + p->payload_len), stream->last_ack)) {
878         StreamTcpSetEvent(p, STREAM_PKT_RETRANSMISSION);
879         SCReturnInt(1);
880     }
881 
882     /* retransmission of in flight data */
883     if (SEQ_LEQ((TCP_GET_SEQ(p) + p->payload_len), stream->next_seq)) {
884         StreamTcpSetEvent(p, STREAM_PKT_RETRANSMISSION);
885         SCReturnInt(2);
886     }
887 
888     SCLogDebug("seq %u payload_len %u => %u, last_ack %u, next_seq %u", TCP_GET_SEQ(p),
889             p->payload_len, (TCP_GET_SEQ(p) + p->payload_len), stream->last_ack, stream->next_seq);
890     SCReturnInt(0);
891 }
892 
893 /**
894  *  \internal
895  *  \brief  Function to handle the TCP_CLOSED or NONE state. The function handles
896  *          packets while the session state is None which means a newly
897  *          initialized structure, or a fully closed session.
898  *
899  *  \param  tv      Thread Variable containig  input/output queue, cpu affinity
900  *  \param  p       Packet which has to be handled in this TCP state.
901  *  \param  stt     Strean Thread module registered to handle the stream handling
902  *
903  *  \retval 0 ok
904  *  \retval -1 error
905  */
StreamTcpPacketStateNone(ThreadVars * tv,Packet * p,StreamTcpThread * stt,TcpSession * ssn,PacketQueueNoLock * pq)906 static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p,
907         StreamTcpThread *stt, TcpSession *ssn,
908         PacketQueueNoLock *pq)
909 {
910     if (p->tcph->th_flags & TH_RST) {
911         StreamTcpSetEvent(p, STREAM_RST_BUT_NO_SESSION);
912         SCLogDebug("RST packet received, no session setup");
913         return -1;
914 
915     } else if (p->tcph->th_flags & TH_FIN) {
916         StreamTcpSetEvent(p, STREAM_FIN_BUT_NO_SESSION);
917         SCLogDebug("FIN packet received, no session setup");
918         return -1;
919 
920     /* SYN/ACK */
921     } else if ((p->tcph->th_flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) {
922         if (stream_config.midstream == FALSE &&
923                 stream_config.async_oneside == FALSE)
924             return 0;
925 
926         if (ssn == NULL) {
927             ssn = StreamTcpNewSession(p, stt->ssn_pool_id);
928             if (ssn == NULL) {
929                 StatsIncr(tv, stt->counter_tcp_ssn_memcap);
930                 return -1;
931             }
932             StatsIncr(tv, stt->counter_tcp_sessions);
933             StatsIncr(tv, stt->counter_tcp_midstream_pickups);
934         }
935 
936         /* reverse packet and flow */
937         SCLogDebug("reversing flow and packet");
938         PacketSwap(p);
939         FlowSwap(p->flow);
940 
941         /* set the state */
942         StreamTcpPacketSetState(p, ssn, TCP_SYN_RECV);
943         SCLogDebug("ssn %p: =~ midstream picked ssn state is now "
944                 "TCP_SYN_RECV", ssn);
945         ssn->flags |= STREAMTCP_FLAG_MIDSTREAM;
946         /* Flag used to change the direct in the later stage in the session */
947         ssn->flags |= STREAMTCP_FLAG_MIDSTREAM_SYNACK;
948         if (stream_config.async_oneside) {
949             SCLogDebug("ssn %p: =~ ASYNC", ssn);
950             ssn->flags |= STREAMTCP_FLAG_ASYNC;
951         }
952 
953         /* sequence number & window */
954         ssn->server.isn = TCP_GET_SEQ(p);
955         STREAMTCP_SET_RA_BASE_SEQ(&ssn->server, ssn->server.isn);
956         ssn->server.next_seq = ssn->server.isn + 1;
957         ssn->server.window = TCP_GET_WINDOW(p);
958         SCLogDebug("ssn %p: server window %u", ssn, ssn->server.window);
959 
960         ssn->client.isn = TCP_GET_ACK(p) - 1;
961         STREAMTCP_SET_RA_BASE_SEQ(&ssn->client, ssn->client.isn);
962         ssn->client.next_seq = ssn->client.isn + 1;
963 
964         ssn->client.last_ack = TCP_GET_ACK(p);
965         ssn->server.last_ack = TCP_GET_SEQ(p);
966 
967         ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
968 
969         /** If the client has a wscale option the server had it too,
970          *  so set the wscale for the server to max. Otherwise none
971          *  will have the wscale opt just like it should. */
972         if (TCP_HAS_WSCALE(p)) {
973             ssn->client.wscale = TCP_GET_WSCALE(p);
974             ssn->server.wscale = TCP_WSCALE_MAX;
975             SCLogDebug("ssn %p: wscale enabled. client %u server %u",
976                     ssn, ssn->client.wscale, ssn->server.wscale);
977         }
978 
979         SCLogDebug("ssn %p: ssn->client.isn %"PRIu32", ssn->client.next_seq"
980                 " %"PRIu32", ssn->client.last_ack %"PRIu32"", ssn,
981                 ssn->client.isn, ssn->client.next_seq,
982                 ssn->client.last_ack);
983         SCLogDebug("ssn %p: ssn->server.isn %"PRIu32", ssn->server.next_seq"
984                 " %"PRIu32", ssn->server.last_ack %"PRIu32"", ssn,
985                 ssn->server.isn, ssn->server.next_seq,
986                 ssn->server.last_ack);
987 
988         /* Set the timestamp value for both streams, if packet has timestamp
989          * option enabled.*/
990         if (TCP_HAS_TS(p)) {
991             ssn->server.last_ts = TCP_GET_TSVAL(p);
992             ssn->client.last_ts = TCP_GET_TSECR(p);
993             SCLogDebug("ssn %p: ssn->server.last_ts %" PRIu32" "
994                     "ssn->client.last_ts %" PRIu32"", ssn,
995                     ssn->server.last_ts, ssn->client.last_ts);
996 
997             ssn->flags |= STREAMTCP_FLAG_TIMESTAMP;
998 
999             ssn->server.last_pkt_ts = p->ts.tv_sec;
1000             if (ssn->server.last_ts == 0)
1001                 ssn->server.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
1002             if (ssn->client.last_ts == 0)
1003                 ssn->client.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
1004 
1005         } else {
1006             ssn->server.last_ts = 0;
1007             ssn->client.last_ts = 0;
1008         }
1009 
1010         if (TCP_GET_SACKOK(p) == 1) {
1011             ssn->flags |= STREAMTCP_FLAG_SACKOK;
1012             SCLogDebug("ssn %p: SYN/ACK with SACK permitted, assuming "
1013                     "SACK permitted for both sides", ssn);
1014         }
1015         return 0;
1016 
1017     } else if (p->tcph->th_flags & TH_SYN) {
1018         if (ssn == NULL) {
1019             ssn = StreamTcpNewSession(p, stt->ssn_pool_id);
1020             if (ssn == NULL) {
1021                 StatsIncr(tv, stt->counter_tcp_ssn_memcap);
1022                 return -1;
1023             }
1024 
1025             StatsIncr(tv, stt->counter_tcp_sessions);
1026         }
1027 
1028         /* set the state */
1029         StreamTcpPacketSetState(p, ssn, TCP_SYN_SENT);
1030         SCLogDebug("ssn %p: =~ ssn state is now TCP_SYN_SENT", ssn);
1031 
1032         if (stream_config.async_oneside) {
1033             SCLogDebug("ssn %p: =~ ASYNC", ssn);
1034             ssn->flags |= STREAMTCP_FLAG_ASYNC;
1035         }
1036 
1037         /* set the sequence numbers and window */
1038         ssn->client.isn = TCP_GET_SEQ(p);
1039         STREAMTCP_SET_RA_BASE_SEQ(&ssn->client, ssn->client.isn);
1040         ssn->client.next_seq = ssn->client.isn + 1;
1041 
1042         /* Set the stream timestamp value, if packet has timestamp option
1043          * enabled. */
1044         if (TCP_HAS_TS(p)) {
1045             ssn->client.last_ts = TCP_GET_TSVAL(p);
1046             SCLogDebug("ssn %p: %02x", ssn, ssn->client.last_ts);
1047 
1048             if (ssn->client.last_ts == 0)
1049                 ssn->client.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
1050 
1051             ssn->client.last_pkt_ts = p->ts.tv_sec;
1052             ssn->client.flags |= STREAMTCP_STREAM_FLAG_TIMESTAMP;
1053         }
1054 
1055         ssn->server.window = TCP_GET_WINDOW(p);
1056         if (TCP_HAS_WSCALE(p)) {
1057             ssn->flags |= STREAMTCP_FLAG_SERVER_WSCALE;
1058             ssn->server.wscale = TCP_GET_WSCALE(p);
1059         }
1060 
1061         if (TCP_GET_SACKOK(p) == 1) {
1062             ssn->flags |= STREAMTCP_FLAG_CLIENT_SACKOK;
1063             SCLogDebug("ssn %p: SACK permitted on SYN packet", ssn);
1064         }
1065 
1066         if (TCP_HAS_TFO(p)) {
1067             ssn->flags |= STREAMTCP_FLAG_TCP_FAST_OPEN;
1068             if (p->payload_len) {
1069                 StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
1070                 SCLogDebug("ssn: %p (TFO) [len: %d] isn %u base_seq %u next_seq %u payload len %u",
1071                         ssn, p->tcpvars.tfo.len, ssn->client.isn, ssn->client.base_seq, ssn->client.next_seq, p->payload_len);
1072                 StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p, pq);
1073             }
1074         }
1075 
1076         SCLogDebug("ssn %p: ssn->client.isn %" PRIu32 ", "
1077                 "ssn->client.next_seq %" PRIu32 ", ssn->client.last_ack "
1078                 "%"PRIu32"", ssn, ssn->client.isn, ssn->client.next_seq,
1079                 ssn->client.last_ack);
1080 
1081     } else if (p->tcph->th_flags & TH_ACK) {
1082         if (stream_config.midstream == FALSE)
1083             return 0;
1084 
1085         if (ssn == NULL) {
1086             ssn = StreamTcpNewSession(p, stt->ssn_pool_id);
1087             if (ssn == NULL) {
1088                 StatsIncr(tv, stt->counter_tcp_ssn_memcap);
1089                 return -1;
1090             }
1091             StatsIncr(tv, stt->counter_tcp_sessions);
1092             StatsIncr(tv, stt->counter_tcp_midstream_pickups);
1093         }
1094         /* set the state */
1095         StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
1096         SCLogDebug("ssn %p: =~ midstream picked ssn state is now "
1097                 "TCP_ESTABLISHED", ssn);
1098 
1099         ssn->flags = STREAMTCP_FLAG_MIDSTREAM;
1100         ssn->flags |= STREAMTCP_FLAG_MIDSTREAM_ESTABLISHED;
1101         if (stream_config.async_oneside) {
1102             SCLogDebug("ssn %p: =~ ASYNC", ssn);
1103             ssn->flags |= STREAMTCP_FLAG_ASYNC;
1104         }
1105 
1106         /** window scaling for midstream pickups, we can't do much other
1107          *  than assume that it's set to the max value: 14 */
1108         ssn->client.wscale = TCP_WSCALE_MAX;
1109         ssn->server.wscale = TCP_WSCALE_MAX;
1110 
1111         /* set the sequence numbers and window */
1112         ssn->client.isn = TCP_GET_SEQ(p) - 1;
1113         STREAMTCP_SET_RA_BASE_SEQ(&ssn->client, ssn->client.isn);
1114         ssn->client.next_seq = TCP_GET_SEQ(p) + p->payload_len;
1115         ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
1116         ssn->client.last_ack = TCP_GET_SEQ(p);
1117         ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
1118         SCLogDebug("ssn %p: ssn->client.isn %u, ssn->client.next_seq %u",
1119                 ssn, ssn->client.isn, ssn->client.next_seq);
1120 
1121         ssn->server.isn = TCP_GET_ACK(p) - 1;
1122         STREAMTCP_SET_RA_BASE_SEQ(&ssn->server, ssn->server.isn);
1123         ssn->server.next_seq = ssn->server.isn + 1;
1124         ssn->server.last_ack = TCP_GET_ACK(p);
1125         ssn->server.next_win = ssn->server.last_ack;
1126 
1127         SCLogDebug("ssn %p: ssn->client.next_win %"PRIu32", "
1128                 "ssn->server.next_win %"PRIu32"", ssn,
1129                 ssn->client.next_win, ssn->server.next_win);
1130         SCLogDebug("ssn %p: ssn->client.last_ack %"PRIu32", "
1131                 "ssn->server.last_ack %"PRIu32"", ssn,
1132                 ssn->client.last_ack, ssn->server.last_ack);
1133 
1134         /* Set the timestamp value for both streams, if packet has timestamp
1135          * option enabled.*/
1136         if (TCP_HAS_TS(p)) {
1137             ssn->client.last_ts = TCP_GET_TSVAL(p);
1138             ssn->server.last_ts = TCP_GET_TSECR(p);
1139             SCLogDebug("ssn %p: ssn->server.last_ts %" PRIu32" "
1140                     "ssn->client.last_ts %" PRIu32"", ssn,
1141                     ssn->server.last_ts, ssn->client.last_ts);
1142 
1143             ssn->flags |= STREAMTCP_FLAG_TIMESTAMP;
1144 
1145             ssn->client.last_pkt_ts = p->ts.tv_sec;
1146             if (ssn->server.last_ts == 0)
1147                 ssn->server.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
1148             if (ssn->client.last_ts == 0)
1149                 ssn->client.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
1150 
1151         } else {
1152             ssn->server.last_ts = 0;
1153             ssn->client.last_ts = 0;
1154         }
1155 
1156         StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p, pq);
1157 
1158         ssn->flags |= STREAMTCP_FLAG_SACKOK;
1159         SCLogDebug("ssn %p: assuming SACK permitted for both sides", ssn);
1160 
1161     } else {
1162         SCLogDebug("default case");
1163     }
1164 
1165     return 0;
1166 }
1167 
1168 /** \internal
1169  *  \brief Setup TcpStateQueue based on SYN/ACK packet
1170  */
StreamTcp3whsSynAckToStateQueue(Packet * p,TcpStateQueue * q)1171 static inline void StreamTcp3whsSynAckToStateQueue(Packet *p, TcpStateQueue *q)
1172 {
1173     q->flags = 0;
1174     q->wscale = 0;
1175     q->ts = 0;
1176     q->win = TCP_GET_WINDOW(p);
1177     q->seq = TCP_GET_SEQ(p);
1178     q->ack = TCP_GET_ACK(p);
1179     q->pkt_ts = p->ts.tv_sec;
1180 
1181     if (TCP_GET_SACKOK(p) == 1)
1182         q->flags |= STREAMTCP_QUEUE_FLAG_SACK;
1183 
1184     if (TCP_HAS_WSCALE(p)) {
1185         q->flags |= STREAMTCP_QUEUE_FLAG_WS;
1186         q->wscale = TCP_GET_WSCALE(p);
1187     }
1188     if (TCP_HAS_TS(p)) {
1189         q->flags |= STREAMTCP_QUEUE_FLAG_TS;
1190         q->ts = TCP_GET_TSVAL(p);
1191     }
1192 }
1193 
1194 /** \internal
1195  *  \brief Find the Queued SYN/ACK that is the same as this SYN/ACK
1196  *  \retval q or NULL */
StreamTcp3whsFindSynAckBySynAck(TcpSession * ssn,Packet * p)1197 static TcpStateQueue *StreamTcp3whsFindSynAckBySynAck(TcpSession *ssn, Packet *p)
1198 {
1199     TcpStateQueue *q = ssn->queue;
1200     TcpStateQueue search;
1201 
1202     StreamTcp3whsSynAckToStateQueue(p, &search);
1203 
1204     while (q != NULL) {
1205         if (search.flags == q->flags &&
1206             search.wscale == q->wscale &&
1207             search.win == q->win &&
1208             search.seq == q->seq &&
1209             search.ack == q->ack &&
1210             search.ts == q->ts) {
1211             return q;
1212         }
1213 
1214         q = q->next;
1215     }
1216 
1217     return q;
1218 }
1219 
StreamTcp3whsQueueSynAck(TcpSession * ssn,Packet * p)1220 static int StreamTcp3whsQueueSynAck(TcpSession *ssn, Packet *p)
1221 {
1222     /* first see if this is already in our list */
1223     if (StreamTcp3whsFindSynAckBySynAck(ssn, p) != NULL)
1224         return 0;
1225 
1226     if (ssn->queue_len == stream_config.max_synack_queued) {
1227         SCLogDebug("ssn %p: =~ SYN/ACK queue limit reached", ssn);
1228         StreamTcpSetEvent(p, STREAM_3WHS_SYNACK_FLOOD);
1229         return -1;
1230     }
1231 
1232     if (StreamTcpCheckMemcap((uint32_t)sizeof(TcpStateQueue)) == 0) {
1233         SCLogDebug("ssn %p: =~ SYN/ACK queue failed: stream memcap reached", ssn);
1234         return -1;
1235     }
1236 
1237     TcpStateQueue *q = SCMalloc(sizeof(*q));
1238     if (unlikely(q == NULL)) {
1239         SCLogDebug("ssn %p: =~ SYN/ACK queue failed: alloc failed", ssn);
1240         return -1;
1241     }
1242     memset(q, 0x00, sizeof(*q));
1243     StreamTcpIncrMemuse((uint64_t)sizeof(TcpStateQueue));
1244 
1245     StreamTcp3whsSynAckToStateQueue(p, q);
1246 
1247     /* put in list */
1248     q->next = ssn->queue;
1249     ssn->queue = q;
1250     ssn->queue_len++;
1251     return 0;
1252 }
1253 
1254 /** \internal
1255  *  \brief Find the Queued SYN/ACK that goes with this ACK
1256  *  \retval q or NULL */
StreamTcp3whsFindSynAckByAck(TcpSession * ssn,Packet * p)1257 static TcpStateQueue *StreamTcp3whsFindSynAckByAck(TcpSession *ssn, Packet *p)
1258 {
1259     uint32_t ack = TCP_GET_SEQ(p);
1260     uint32_t seq = TCP_GET_ACK(p) - 1;
1261     TcpStateQueue *q = ssn->queue;
1262 
1263     while (q != NULL) {
1264         if (seq == q->seq &&
1265             ack == q->ack) {
1266             return q;
1267         }
1268 
1269         q = q->next;
1270     }
1271 
1272     return NULL;
1273 }
1274 
1275 /** \internal
1276  *  \brief Update SSN after receiving a valid SYN/ACK
1277  *
1278  *  Normally we update the SSN from the SYN/ACK packet. But in case
1279  *  of queued SYN/ACKs, we can use one of those.
1280  *
1281  *  \param ssn TCP session
1282  *  \param p Packet
1283  *  \param q queued state if used, NULL otherwise
1284  *
1285  *  To make sure all SYN/ACK based state updates are in one place,
1286  *  this function can updated based on Packet or TcpStateQueue, where
1287  *  the latter takes precedence.
1288  */
StreamTcp3whsSynAckUpdate(TcpSession * ssn,Packet * p,TcpStateQueue * q)1289 static void StreamTcp3whsSynAckUpdate(TcpSession *ssn, Packet *p, TcpStateQueue *q)
1290 {
1291     TcpStateQueue update;
1292     if (likely(q == NULL)) {
1293         StreamTcp3whsSynAckToStateQueue(p, &update);
1294         q = &update;
1295     }
1296 
1297     if (ssn->state != TCP_SYN_RECV) {
1298         /* update state */
1299         StreamTcpPacketSetState(p, ssn, TCP_SYN_RECV);
1300         SCLogDebug("ssn %p: =~ ssn state is now TCP_SYN_RECV", ssn);
1301     }
1302     /* sequence number & window */
1303     ssn->server.isn = q->seq;
1304     STREAMTCP_SET_RA_BASE_SEQ(&ssn->server, ssn->server.isn);
1305     ssn->server.next_seq = ssn->server.isn + 1;
1306 
1307     ssn->client.window = q->win;
1308     SCLogDebug("ssn %p: window %" PRIu32 "", ssn, ssn->server.window);
1309 
1310     /* Set the timestamp values used to validate the timestamp of
1311      * received packets.*/
1312     if ((q->flags & STREAMTCP_QUEUE_FLAG_TS) &&
1313             (ssn->client.flags & STREAMTCP_STREAM_FLAG_TIMESTAMP))
1314     {
1315         ssn->server.last_ts = q->ts;
1316         SCLogDebug("ssn %p: ssn->server.last_ts %" PRIu32" "
1317                 "ssn->client.last_ts %" PRIu32"", ssn,
1318                 ssn->server.last_ts, ssn->client.last_ts);
1319         ssn->flags |= STREAMTCP_FLAG_TIMESTAMP;
1320         ssn->server.last_pkt_ts = q->pkt_ts;
1321         if (ssn->server.last_ts == 0)
1322             ssn->server.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
1323     } else {
1324         ssn->client.last_ts = 0;
1325         ssn->server.last_ts = 0;
1326         ssn->client.flags &= ~STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
1327     }
1328 
1329     ssn->client.last_ack = q->ack;
1330     ssn->server.last_ack = ssn->server.isn + 1;
1331 
1332     /** check for the presense of the ws ptr to determine if we
1333      *  support wscale at all */
1334     if ((ssn->flags & STREAMTCP_FLAG_SERVER_WSCALE) &&
1335             (q->flags & STREAMTCP_QUEUE_FLAG_WS))
1336     {
1337         ssn->client.wscale = q->wscale;
1338     } else {
1339         ssn->client.wscale = 0;
1340     }
1341 
1342     if ((ssn->flags & STREAMTCP_FLAG_CLIENT_SACKOK) &&
1343             (q->flags & STREAMTCP_QUEUE_FLAG_SACK)) {
1344         ssn->flags |= STREAMTCP_FLAG_SACKOK;
1345         SCLogDebug("ssn %p: SACK permitted for session", ssn);
1346     } else {
1347         ssn->flags &= ~STREAMTCP_FLAG_SACKOK;
1348     }
1349 
1350     ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
1351     ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
1352     SCLogDebug("ssn %p: ssn->server.next_win %" PRIu32 "", ssn,
1353             ssn->server.next_win);
1354     SCLogDebug("ssn %p: ssn->client.next_win %" PRIu32 "", ssn,
1355             ssn->client.next_win);
1356     SCLogDebug("ssn %p: ssn->server.isn %" PRIu32 ", "
1357             "ssn->server.next_seq %" PRIu32 ", "
1358             "ssn->server.last_ack %" PRIu32 " "
1359             "(ssn->client.last_ack %" PRIu32 ")", ssn,
1360             ssn->server.isn, ssn->server.next_seq,
1361             ssn->server.last_ack, ssn->client.last_ack);
1362 
1363     /* unset the 4WHS flag as we received this SYN/ACK as part of a
1364      * (so far) valid 3WHS */
1365     if (ssn->flags & STREAMTCP_FLAG_4WHS)
1366         SCLogDebug("ssn %p: STREAMTCP_FLAG_4WHS unset, normal SYN/ACK"
1367                 " so considering 3WHS", ssn);
1368 
1369     ssn->flags &=~ STREAMTCP_FLAG_4WHS;
1370 }
1371 
1372 /** \internal
1373  *  \brief detect timestamp anomalies when processing responses to the
1374  *         SYN packet.
1375  *  \retval true packet is ok
1376  *  \retval false packet is bad
1377  */
StateSynSentValidateTimestamp(TcpSession * ssn,Packet * p)1378 static inline bool StateSynSentValidateTimestamp(TcpSession *ssn, Packet *p)
1379 {
1380     /* we only care about evil server here, so skip TS packets */
1381     if (PKT_IS_TOSERVER(p) || !(TCP_HAS_TS(p))) {
1382         return true;
1383     }
1384 
1385     TcpStream *receiver_stream = &ssn->client;
1386     uint32_t ts_echo = TCP_GET_TSECR(p);
1387     if ((receiver_stream->flags & STREAMTCP_STREAM_FLAG_TIMESTAMP) != 0) {
1388         if (receiver_stream->last_ts != 0 && ts_echo != 0 &&
1389             ts_echo != receiver_stream->last_ts)
1390         {
1391             SCLogDebug("ssn %p: BAD TSECR echo %u recv %u", ssn,
1392                     ts_echo, receiver_stream->last_ts);
1393             return false;
1394         }
1395     } else {
1396         if (receiver_stream->last_ts == 0 && ts_echo != 0) {
1397             SCLogDebug("ssn %p: BAD TSECR echo %u recv %u", ssn,
1398                     ts_echo, receiver_stream->last_ts);
1399             return false;
1400         }
1401     }
1402     return true;
1403 }
1404 
1405 /**
1406  *  \brief  Function to handle the TCP_SYN_SENT state. The function handles
1407  *          SYN, SYN/ACK, RST packets and correspondingly changes the connection
1408  *          state.
1409  *
1410  *  \param  tv      Thread Variable containig  input/output queue, cpu affinity
1411  *  \param  p       Packet which has to be handled in this TCP state.
1412  *  \param  stt     Strean Thread module registered to handle the stream handling
1413  */
1414 
StreamTcpPacketStateSynSent(ThreadVars * tv,Packet * p,StreamTcpThread * stt,TcpSession * ssn,PacketQueueNoLock * pq)1415 static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p,
1416         StreamTcpThread *stt, TcpSession *ssn,
1417         PacketQueueNoLock *pq)
1418 {
1419     if (ssn == NULL)
1420         return -1;
1421 
1422     SCLogDebug("ssn %p: pkt received: %s", ssn, PKT_IS_TOCLIENT(p) ?
1423                "toclient":"toserver");
1424 
1425     /* check for bad responses */
1426     if (StateSynSentValidateTimestamp(ssn, p) == false)
1427         return -1;
1428 
1429     /* RST */
1430     if (p->tcph->th_flags & TH_RST) {
1431         if (!StreamTcpValidateRst(ssn, p))
1432             return -1;
1433 
1434         if (PKT_IS_TOSERVER(p)) {
1435             if (SEQ_EQ(TCP_GET_SEQ(p), ssn->client.isn) &&
1436                     SEQ_EQ(TCP_GET_WINDOW(p), 0) &&
1437                     SEQ_EQ(TCP_GET_ACK(p), (ssn->client.isn + 1)))
1438             {
1439                 SCLogDebug("ssn->server.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
1440                 ssn->server.flags |= STREAMTCP_STREAM_FLAG_RST_RECV;
1441                 StreamTcpCloseSsnWithReset(p, ssn);
1442             }
1443         } else {
1444             ssn->client.flags |= STREAMTCP_STREAM_FLAG_RST_RECV;
1445             SCLogDebug("ssn->client.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
1446             StreamTcpCloseSsnWithReset(p, ssn);
1447         }
1448 
1449     /* FIN */
1450     } else if (p->tcph->th_flags & TH_FIN) {
1451         /** \todo */
1452 
1453     /* SYN/ACK */
1454     } else if ((p->tcph->th_flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) {
1455         if ((ssn->flags & STREAMTCP_FLAG_4WHS) && PKT_IS_TOSERVER(p)) {
1456             SCLogDebug("ssn %p: SYN/ACK received on 4WHS session", ssn);
1457 
1458             /* Check if the SYN/ACK packet ack's the earlier
1459              * received SYN packet. */
1460             if (!(SEQ_EQ(TCP_GET_ACK(p), ssn->server.isn + 1))) {
1461                 StreamTcpSetEvent(p, STREAM_4WHS_SYNACK_WITH_WRONG_ACK);
1462 
1463                 SCLogDebug("ssn %p: 4WHS ACK mismatch, packet ACK %"PRIu32""
1464                         " != %" PRIu32 " from stream", ssn,
1465                         TCP_GET_ACK(p), ssn->server.isn + 1);
1466                 return -1;
1467             }
1468 
1469             /* Check if the SYN/ACK packet SEQ's the *FIRST* received SYN
1470              * packet. */
1471             if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->client.isn))) {
1472                 StreamTcpSetEvent(p, STREAM_4WHS_SYNACK_WITH_WRONG_SYN);
1473 
1474                 SCLogDebug("ssn %p: 4WHS SEQ mismatch, packet SEQ %"PRIu32""
1475                         " != %" PRIu32 " from *first* SYN pkt", ssn,
1476                         TCP_GET_SEQ(p), ssn->client.isn);
1477                 return -1;
1478             }
1479 
1480 
1481             /* update state */
1482             StreamTcpPacketSetState(p, ssn, TCP_SYN_RECV);
1483             SCLogDebug("ssn %p: =~ 4WHS ssn state is now TCP_SYN_RECV", ssn);
1484 
1485             /* sequence number & window */
1486             ssn->client.isn = TCP_GET_SEQ(p);
1487             STREAMTCP_SET_RA_BASE_SEQ(&ssn->client, ssn->client.isn);
1488             ssn->client.next_seq = ssn->client.isn + 1;
1489 
1490             ssn->server.window = TCP_GET_WINDOW(p);
1491             SCLogDebug("ssn %p: 4WHS window %" PRIu32 "", ssn,
1492                     ssn->client.window);
1493 
1494             /* Set the timestamp values used to validate the timestamp of
1495              * received packets. */
1496             if ((TCP_HAS_TS(p)) &&
1497                     (ssn->server.flags & STREAMTCP_STREAM_FLAG_TIMESTAMP))
1498             {
1499                 ssn->client.last_ts = TCP_GET_TSVAL(p);
1500                 SCLogDebug("ssn %p: 4WHS ssn->client.last_ts %" PRIu32" "
1501                         "ssn->server.last_ts %" PRIu32"", ssn,
1502                         ssn->client.last_ts, ssn->server.last_ts);
1503                 ssn->flags |= STREAMTCP_FLAG_TIMESTAMP;
1504                 ssn->client.last_pkt_ts = p->ts.tv_sec;
1505                 if (ssn->client.last_ts == 0)
1506                     ssn->client.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
1507             } else {
1508                 ssn->server.last_ts = 0;
1509                 ssn->client.last_ts = 0;
1510                 ssn->server.flags &= ~STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
1511             }
1512 
1513             ssn->server.last_ack = TCP_GET_ACK(p);
1514             ssn->client.last_ack = ssn->client.isn + 1;
1515 
1516             /** check for the presense of the ws ptr to determine if we
1517              *  support wscale at all */
1518             if ((ssn->flags & STREAMTCP_FLAG_SERVER_WSCALE) &&
1519                     (TCP_HAS_WSCALE(p)))
1520             {
1521                 ssn->server.wscale = TCP_GET_WSCALE(p);
1522             } else {
1523                 ssn->server.wscale = 0;
1524             }
1525 
1526             if ((ssn->flags & STREAMTCP_FLAG_CLIENT_SACKOK) &&
1527                     TCP_GET_SACKOK(p) == 1) {
1528                 ssn->flags |= STREAMTCP_FLAG_SACKOK;
1529                 SCLogDebug("ssn %p: SACK permitted for 4WHS session", ssn);
1530             }
1531 
1532             ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
1533             ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
1534             SCLogDebug("ssn %p: 4WHS ssn->client.next_win %" PRIu32 "", ssn,
1535                     ssn->client.next_win);
1536             SCLogDebug("ssn %p: 4WHS ssn->server.next_win %" PRIu32 "", ssn,
1537                     ssn->server.next_win);
1538             SCLogDebug("ssn %p: 4WHS ssn->client.isn %" PRIu32 ", "
1539                     "ssn->client.next_seq %" PRIu32 ", "
1540                     "ssn->client.last_ack %" PRIu32 " "
1541                     "(ssn->server.last_ack %" PRIu32 ")", ssn,
1542                     ssn->client.isn, ssn->client.next_seq,
1543                     ssn->client.last_ack, ssn->server.last_ack);
1544 
1545             /* done here */
1546             return 0;
1547         }
1548 
1549         if (PKT_IS_TOSERVER(p)) {
1550             StreamTcpSetEvent(p, STREAM_3WHS_SYNACK_IN_WRONG_DIRECTION);
1551             SCLogDebug("ssn %p: SYN/ACK received in the wrong direction", ssn);
1552             return -1;
1553         }
1554 
1555         if (!(TCP_HAS_TFO(p) || (ssn->flags & STREAMTCP_FLAG_TCP_FAST_OPEN))) {
1556             /* Check if the SYN/ACK packet ack's the earlier
1557              * received SYN packet. */
1558             if (!(SEQ_EQ(TCP_GET_ACK(p), ssn->client.isn + 1))) {
1559                 StreamTcpSetEvent(p, STREAM_3WHS_SYNACK_WITH_WRONG_ACK);
1560                 SCLogDebug("ssn %p: ACK mismatch, packet ACK %" PRIu32 " != "
1561                         "%" PRIu32 " from stream", ssn, TCP_GET_ACK(p),
1562                         ssn->client.isn + 1);
1563                 return -1;
1564             }
1565         } else {
1566             if (!(SEQ_EQ(TCP_GET_ACK(p), ssn->client.next_seq))) {
1567                 StreamTcpSetEvent(p, STREAM_3WHS_SYNACK_WITH_WRONG_ACK);
1568                 SCLogDebug("ssn %p: (TFO) ACK mismatch, packet ACK %" PRIu32 " != "
1569                         "%" PRIu32 " from stream", ssn, TCP_GET_ACK(p),
1570                         ssn->client.next_seq);
1571                 return -1;
1572             }
1573             SCLogDebug("ssn %p: (TFO) ACK match, packet ACK %" PRIu32 " == "
1574                     "%" PRIu32 " from stream", ssn, TCP_GET_ACK(p),
1575                     ssn->client.next_seq);
1576 
1577             ssn->flags |= STREAMTCP_FLAG_TCP_FAST_OPEN;
1578             StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
1579         }
1580         StreamTcp3whsSynAckUpdate(ssn, p, /* no queue override */NULL);
1581 
1582     } else if (p->tcph->th_flags & TH_SYN) {
1583         SCLogDebug("ssn %p: SYN packet on state SYN_SENT... resent", ssn);
1584         if (ssn->flags & STREAMTCP_FLAG_4WHS) {
1585             SCLogDebug("ssn %p: SYN packet on state SYN_SENT... resent of "
1586                     "4WHS SYN", ssn);
1587         }
1588 
1589         if (PKT_IS_TOCLIENT(p)) {
1590             /** a SYN only packet in the opposite direction could be:
1591              *  http://www.breakingpointsystems.com/community/blog/tcp-
1592              *  portals-the-three-way-handshake-is-a-lie
1593              *
1594              * \todo improve resetting the session */
1595 
1596             /* indicate that we're dealing with 4WHS here */
1597             ssn->flags |= STREAMTCP_FLAG_4WHS;
1598             SCLogDebug("ssn %p: STREAMTCP_FLAG_4WHS flag set", ssn);
1599 
1600             /* set the sequence numbers and window for server
1601              * We leave the ssn->client.isn in place as we will
1602              * check the SYN/ACK pkt with that.
1603              */
1604             ssn->server.isn = TCP_GET_SEQ(p);
1605             STREAMTCP_SET_RA_BASE_SEQ(&ssn->server, ssn->server.isn);
1606             ssn->server.next_seq = ssn->server.isn + 1;
1607 
1608             /* Set the stream timestamp value, if packet has timestamp
1609              * option enabled. */
1610             if (TCP_HAS_TS(p)) {
1611                 ssn->server.last_ts = TCP_GET_TSVAL(p);
1612                 SCLogDebug("ssn %p: %02x", ssn, ssn->server.last_ts);
1613 
1614                 if (ssn->server.last_ts == 0)
1615                     ssn->server.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
1616                 ssn->server.last_pkt_ts = p->ts.tv_sec;
1617                 ssn->server.flags |= STREAMTCP_STREAM_FLAG_TIMESTAMP;
1618             }
1619 
1620             ssn->server.window = TCP_GET_WINDOW(p);
1621             if (TCP_HAS_WSCALE(p)) {
1622                 ssn->flags |= STREAMTCP_FLAG_SERVER_WSCALE;
1623                 ssn->server.wscale = TCP_GET_WSCALE(p);
1624             } else {
1625                 ssn->flags &= ~STREAMTCP_FLAG_SERVER_WSCALE;
1626                 ssn->server.wscale = 0;
1627             }
1628 
1629             if (TCP_GET_SACKOK(p) == 1) {
1630                 ssn->flags |= STREAMTCP_FLAG_CLIENT_SACKOK;
1631             } else {
1632                 ssn->flags &= ~STREAMTCP_FLAG_CLIENT_SACKOK;
1633             }
1634 
1635             SCLogDebug("ssn %p: 4WHS ssn->server.isn %" PRIu32 ", "
1636                     "ssn->server.next_seq %" PRIu32 ", "
1637                     "ssn->server.last_ack %"PRIu32"", ssn,
1638                     ssn->server.isn, ssn->server.next_seq,
1639                     ssn->server.last_ack);
1640             SCLogDebug("ssn %p: 4WHS ssn->client.isn %" PRIu32 ", "
1641                     "ssn->client.next_seq %" PRIu32 ", "
1642                     "ssn->client.last_ack %"PRIu32"", ssn,
1643                     ssn->client.isn, ssn->client.next_seq,
1644                     ssn->client.last_ack);
1645         }
1646 
1647         /** \todo check if it's correct or set event */
1648 
1649     } else if (p->tcph->th_flags & TH_ACK) {
1650         /* Handle the asynchronous stream, when we receive a  SYN packet
1651            and now istead of receving a SYN/ACK we receive a ACK from the
1652            same host, which sent the SYN, this suggests the ASNYC streams.*/
1653         if (stream_config.async_oneside == FALSE)
1654             return 0;
1655 
1656         /* we are in AYNC (one side) mode now. */
1657 
1658         /* one side async means we won't see a SYN/ACK, so we can
1659          * only check the SYN. */
1660         if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->client.next_seq))) {
1661             StreamTcpSetEvent(p, STREAM_3WHS_ASYNC_WRONG_SEQ);
1662 
1663             SCLogDebug("ssn %p: SEQ mismatch, packet SEQ %" PRIu32 " != "
1664                     "%" PRIu32 " from stream",ssn, TCP_GET_SEQ(p),
1665                     ssn->client.next_seq);
1666             return -1;
1667         }
1668 
1669         ssn->flags |= STREAMTCP_FLAG_ASYNC;
1670         StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
1671         SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
1672 
1673         ssn->client.window = TCP_GET_WINDOW(p);
1674         ssn->client.last_ack = TCP_GET_SEQ(p);
1675         ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
1676 
1677         /* Set the server side parameters */
1678         ssn->server.isn = TCP_GET_ACK(p) - 1;
1679         STREAMTCP_SET_RA_BASE_SEQ(&ssn->server, ssn->server.isn);
1680         ssn->server.next_seq = ssn->server.isn + 1;
1681         ssn->server.last_ack = ssn->server.next_seq;
1682         ssn->server.next_win = ssn->server.last_ack;
1683 
1684         SCLogDebug("ssn %p: synsent => Asynchronous stream, packet SEQ"
1685                 " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "), "
1686                 "ssn->client.next_seq %" PRIu32 ""
1687                 ,ssn, TCP_GET_SEQ(p), p->payload_len, TCP_GET_SEQ(p)
1688                 + p->payload_len, ssn->client.next_seq);
1689 
1690         /* if SYN had wscale, assume it to be supported. Otherwise
1691          * we know it not to be supported. */
1692         if (ssn->flags & STREAMTCP_FLAG_SERVER_WSCALE) {
1693             ssn->client.wscale = TCP_WSCALE_MAX;
1694         }
1695 
1696         /* Set the timestamp values used to validate the timestamp of
1697          * received packets.*/
1698         if (TCP_HAS_TS(p) &&
1699                 (ssn->client.flags & STREAMTCP_STREAM_FLAG_TIMESTAMP))
1700         {
1701             ssn->flags |= STREAMTCP_FLAG_TIMESTAMP;
1702             ssn->client.flags &= ~STREAMTCP_STREAM_FLAG_TIMESTAMP;
1703             ssn->client.last_pkt_ts = p->ts.tv_sec;
1704         } else {
1705             ssn->client.last_ts = 0;
1706             ssn->client.flags &= ~STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
1707         }
1708 
1709         if (ssn->flags & STREAMTCP_FLAG_CLIENT_SACKOK) {
1710             ssn->flags |= STREAMTCP_FLAG_SACKOK;
1711         }
1712 
1713         StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
1714                 &ssn->client, p, pq);
1715 
1716     } else {
1717         SCLogDebug("ssn %p: default case", ssn);
1718     }
1719 
1720     return 0;
1721 }
1722 
1723 /**
1724  *  \brief  Function to handle the TCP_SYN_RECV state. The function handles
1725  *          SYN, SYN/ACK, ACK, FIN, RST packets and correspondingly changes
1726  *          the connection state.
1727  *
1728  *  \param  tv      Thread Variable containig  input/output queue, cpu affinity
1729  *  \param  p       Packet which has to be handled in this TCP state.
1730  *  \param  stt     Strean Thread module registered to handle the stream handling
1731  *
1732  *  \retval  0 ok
1733  *  \retval -1 error
1734  */
1735 
StreamTcpPacketStateSynRecv(ThreadVars * tv,Packet * p,StreamTcpThread * stt,TcpSession * ssn,PacketQueueNoLock * pq)1736 static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p,
1737         StreamTcpThread *stt, TcpSession *ssn,
1738         PacketQueueNoLock *pq)
1739 {
1740     if (ssn == NULL)
1741         return -1;
1742 
1743     if (p->tcph->th_flags & TH_RST) {
1744         if (!StreamTcpValidateRst(ssn, p))
1745             return -1;
1746 
1747         uint8_t reset = TRUE;
1748         /* After receiveing the RST in SYN_RECV state and if detection
1749            evasion flags has been set, then the following operating
1750            systems will not closed the connection. As they consider the
1751            packet as stray packet and not belonging to the current
1752            session, for more information check
1753            http://www.packetstan.com/2010/06/recently-ive-been-on-campaign-to-make.html */
1754         if (ssn->flags & STREAMTCP_FLAG_DETECTION_EVASION_ATTEMPT) {
1755             if (PKT_IS_TOSERVER(p)) {
1756                 if ((ssn->server.os_policy == OS_POLICY_LINUX) ||
1757                         (ssn->server.os_policy == OS_POLICY_OLD_LINUX) ||
1758                         (ssn->server.os_policy == OS_POLICY_SOLARIS))
1759                 {
1760                     reset = FALSE;
1761                     SCLogDebug("Detection evasion has been attempted, so"
1762                             " not resetting the connection !!");
1763                 }
1764             } else {
1765                 if ((ssn->client.os_policy == OS_POLICY_LINUX) ||
1766                         (ssn->client.os_policy == OS_POLICY_OLD_LINUX) ||
1767                         (ssn->client.os_policy == OS_POLICY_SOLARIS))
1768                 {
1769                     reset = FALSE;
1770                     SCLogDebug("Detection evasion has been attempted, so"
1771                             " not resetting the connection !!");
1772                 }
1773             }
1774         }
1775 
1776         if (reset == TRUE) {
1777             StreamTcpCloseSsnWithReset(p, ssn);
1778 
1779             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
1780                 StreamTcpHandleTimestamp(ssn, p);
1781             }
1782         }
1783 
1784     } else if (p->tcph->th_flags & TH_FIN) {
1785         /* FIN is handled in the same way as in TCP_ESTABLISHED case */;
1786         if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
1787             if (!StreamTcpValidateTimestamp(ssn, p))
1788                 return -1;
1789         }
1790 
1791         if ((StreamTcpHandleFin(tv, stt, ssn, p, pq)) == -1)
1792             return -1;
1793 
1794     /* SYN/ACK */
1795     } else if ((p->tcph->th_flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) {
1796         SCLogDebug("ssn %p: SYN/ACK packet on state SYN_RECV. resent", ssn);
1797 
1798         if (PKT_IS_TOSERVER(p)) {
1799             SCLogDebug("ssn %p: SYN/ACK-pkt to server in SYN_RECV state", ssn);
1800 
1801             StreamTcpSetEvent(p, STREAM_3WHS_SYNACK_TOSERVER_ON_SYN_RECV);
1802             return -1;
1803         }
1804 
1805         /* Check if the SYN/ACK packets ACK matches the earlier
1806          * received SYN/ACK packet. */
1807         if (!(SEQ_EQ(TCP_GET_ACK(p), ssn->client.last_ack))) {
1808             SCLogDebug("ssn %p: ACK mismatch, packet ACK %" PRIu32 " != "
1809                     "%" PRIu32 " from stream", ssn, TCP_GET_ACK(p),
1810                     ssn->client.isn + 1);
1811 
1812             StreamTcpSetEvent(p, STREAM_3WHS_SYNACK_RESEND_WITH_DIFFERENT_ACK);
1813             return -1;
1814         }
1815 
1816         /* Check if the SYN/ACK packet SEQ the earlier
1817          * received SYN/ACK packet, server resend with different ISN. */
1818         if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->server.isn))) {
1819             SCLogDebug("ssn %p: SEQ mismatch, packet SEQ %" PRIu32 " != "
1820                     "%" PRIu32 " from stream", ssn, TCP_GET_SEQ(p),
1821                     ssn->client.isn);
1822 
1823             if (StreamTcp3whsQueueSynAck(ssn, p) == -1)
1824                 return -1;
1825             SCLogDebug("ssn %p: queued different SYN/ACK", ssn);
1826         }
1827 
1828     } else if (p->tcph->th_flags & TH_SYN) {
1829         SCLogDebug("ssn %p: SYN packet on state SYN_RECV... resent", ssn);
1830 
1831         if (PKT_IS_TOCLIENT(p)) {
1832             SCLogDebug("ssn %p: SYN-pkt to client in SYN_RECV state", ssn);
1833 
1834             StreamTcpSetEvent(p, STREAM_3WHS_SYN_TOCLIENT_ON_SYN_RECV);
1835             return -1;
1836         }
1837 
1838         if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->client.isn))) {
1839             SCLogDebug("ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
1840 
1841             StreamTcpSetEvent(p, STREAM_3WHS_SYN_RESEND_DIFF_SEQ_ON_SYN_RECV);
1842             return -1;
1843         }
1844 
1845     } else if (p->tcph->th_flags & TH_ACK) {
1846         if (ssn->queue_len) {
1847             SCLogDebug("ssn %p: checking ACK against queued SYN/ACKs", ssn);
1848             TcpStateQueue *q = StreamTcp3whsFindSynAckByAck(ssn, p);
1849             if (q != NULL) {
1850                 SCLogDebug("ssn %p: here we update state against queued SYN/ACK", ssn);
1851                 StreamTcp3whsSynAckUpdate(ssn, p, /* using queue to update state */q);
1852             } else {
1853                 SCLogDebug("ssn %p: none found, now checking ACK against original SYN/ACK (state)", ssn);
1854             }
1855         }
1856 
1857 
1858         /* If the timestamp option is enabled for both the streams, then
1859          * validate the received packet timestamp value against the
1860          * stream->last_ts. If the timestamp is valid then process the
1861          * packet normally otherwise the drop the packet (RFC 1323)*/
1862         if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
1863             if (!(StreamTcpValidateTimestamp(ssn, p))) {
1864                 return -1;
1865             }
1866         }
1867 
1868         if ((ssn->flags & STREAMTCP_FLAG_4WHS) && PKT_IS_TOCLIENT(p)) {
1869             SCLogDebug("ssn %p: ACK received on 4WHS session",ssn);
1870 
1871             if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq))) {
1872                 SCLogDebug("ssn %p: 4WHS wrong seq nr on packet", ssn);
1873                 StreamTcpSetEvent(p, STREAM_4WHS_WRONG_SEQ);
1874                 return -1;
1875             }
1876 
1877             if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
1878                 SCLogDebug("ssn %p: 4WHS invalid ack nr on packet", ssn);
1879                 StreamTcpSetEvent(p, STREAM_4WHS_INVALID_ACK);
1880                 return -1;
1881             }
1882 
1883             SCLogDebug("4WHS normal pkt");
1884             SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
1885                     "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
1886                     TCP_GET_SEQ(p), TCP_GET_ACK(p));
1887 
1888             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
1889                 StreamTcpHandleTimestamp(ssn, p);
1890             }
1891 
1892             StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
1893             StreamTcpUpdateNextSeq(ssn, &ssn->server, (ssn->server.next_seq + p->payload_len));
1894             ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
1895             ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
1896 
1897             StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
1898             SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
1899 
1900             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
1901                     &ssn->server, p, pq);
1902 
1903             SCLogDebug("ssn %p: ssn->client.next_win %" PRIu32 ", "
1904                     "ssn->client.last_ack %"PRIu32"", ssn,
1905                     ssn->client.next_win, ssn->client.last_ack);
1906             return 0;
1907         }
1908 
1909         bool ack_indicates_missed_3whs_ack_packet = false;
1910         /* Check if the ACK received is in right direction. But when we have
1911          * picked up a mid stream session after missing the initial SYN pkt,
1912          * in this case the ACK packet can arrive from either client (normal
1913          * case) or from server itself (asynchronous streams). Therefore
1914          *  the check has been avoided in this case */
1915         if (PKT_IS_TOCLIENT(p)) {
1916             /* special case, handle 4WHS, so SYN/ACK in the opposite
1917              * direction */
1918             if (ssn->flags & STREAMTCP_FLAG_MIDSTREAM_SYNACK) {
1919                 SCLogDebug("ssn %p: ACK received on midstream SYN/ACK "
1920                         "pickup session",ssn);
1921                 /* fall through */
1922             } else if (ssn->flags & STREAMTCP_FLAG_TCP_FAST_OPEN) {
1923                 SCLogDebug("ssn %p: ACK received on TFO session",ssn);
1924                 /* fall through */
1925 
1926             } else {
1927                 /* if we missed traffic between the S/SA and the current
1928                  * 'wrong direction' ACK, we could end up here. In IPS
1929                  * reject it. But in IDS mode we continue.
1930                  *
1931                  * IPS rejects as it should see all packets, so pktloss
1932                  * should lead to retransmissions. As this can also be
1933                  * pattern for MOTS/MITM injection attacks, we need to be
1934                  * careful.
1935                  */
1936                 if (StreamTcpInlineMode()) {
1937                     if (p->payload_len > 0 &&
1938                             SEQ_EQ(TCP_GET_ACK(p), ssn->client.last_ack) &&
1939                             SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq)) {
1940                         /* packet loss is possible but unlikely here */
1941                         SCLogDebug("ssn %p: possible data injection", ssn);
1942                         StreamTcpSetEvent(p, STREAM_3WHS_ACK_DATA_INJECT);
1943                         return -1;
1944                     }
1945 
1946                     SCLogDebug("ssn %p: ACK received in the wrong direction",
1947                             ssn);
1948                     StreamTcpSetEvent(p, STREAM_3WHS_ACK_IN_WRONG_DIR);
1949                     return -1;
1950                 }
1951                 ack_indicates_missed_3whs_ack_packet = true;
1952             }
1953         }
1954 
1955         SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ %" PRIu32 ""
1956                 ", ACK %" PRIu32 "", ssn, p->payload_len, TCP_GET_SEQ(p),
1957                 TCP_GET_ACK(p));
1958 
1959         /* Check both seq and ack number before accepting the packet and
1960            changing to ESTABLISHED state */
1961         if ((SEQ_EQ(TCP_GET_SEQ(p), ssn->client.next_seq)) &&
1962                 SEQ_EQ(TCP_GET_ACK(p), ssn->server.next_seq)) {
1963             SCLogDebug("normal pkt");
1964 
1965             /* process the packet normal, No Async streams :) */
1966 
1967             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
1968                 StreamTcpHandleTimestamp(ssn, p);
1969             }
1970 
1971             StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
1972             StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
1973             ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
1974 
1975             ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
1976 
1977             if (ssn->flags & STREAMTCP_FLAG_MIDSTREAM) {
1978                 ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
1979                 ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
1980                 ssn->server.next_win = ssn->server.last_ack +
1981                     ssn->server.window;
1982                 if (!(ssn->flags & STREAMTCP_FLAG_MIDSTREAM_SYNACK)) {
1983                     /* window scaling for midstream pickups, we can't do much
1984                      * other than assume that it's set to the max value: 14 */
1985                     ssn->server.wscale = TCP_WSCALE_MAX;
1986                     ssn->client.wscale = TCP_WSCALE_MAX;
1987                     ssn->flags |= STREAMTCP_FLAG_SACKOK;
1988                 }
1989             }
1990 
1991             StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
1992             SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
1993 
1994             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
1995                     &ssn->client, p, pq);
1996 
1997             /* If asynchronous stream handling is allowed then set the session,
1998                if packet's seq number is equal the expected seq no.*/
1999         } else if (stream_config.async_oneside == TRUE &&
2000                 (SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq)))
2001         {
2002             /*set the ASYNC flag used to indicate the session as async stream
2003               and helps in relaxing the windows checks.*/
2004             ssn->flags |= STREAMTCP_FLAG_ASYNC;
2005             ssn->server.next_seq += p->payload_len;
2006             ssn->server.last_ack = TCP_GET_SEQ(p);
2007 
2008             ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
2009             ssn->client.last_ack = TCP_GET_ACK(p);
2010 
2011             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2012                 StreamTcpHandleTimestamp(ssn, p);
2013             }
2014 
2015             if (ssn->flags & STREAMTCP_FLAG_MIDSTREAM) {
2016                 ssn->server.window = TCP_GET_WINDOW(p);
2017                 ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
2018                 /* window scaling for midstream pickups, we can't do much
2019                  * other than assume that it's set to the max value: 14 */
2020                 ssn->server.wscale = TCP_WSCALE_MAX;
2021                 ssn->client.wscale = TCP_WSCALE_MAX;
2022                 ssn->flags |= STREAMTCP_FLAG_SACKOK;
2023             }
2024 
2025             SCLogDebug("ssn %p: synrecv => Asynchronous stream, packet SEQ"
2026                     " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "), "
2027                     "ssn->server.next_seq %" PRIu32
2028                     , ssn, TCP_GET_SEQ(p), p->payload_len, TCP_GET_SEQ(p)
2029                     + p->payload_len, ssn->server.next_seq);
2030 
2031             StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
2032             SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2033 
2034             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
2035                     &ssn->server, p, pq);
2036             /* Upon receiving the packet with correct seq number and wrong
2037                ACK number, it causes the other end to send RST. But some target
2038                system (Linux & solaris) does not RST the connection, so it is
2039                likely to avoid the detection */
2040         } else if (SEQ_EQ(TCP_GET_SEQ(p), ssn->client.next_seq)){
2041             ssn->flags |= STREAMTCP_FLAG_DETECTION_EVASION_ATTEMPT;
2042             SCLogDebug("ssn %p: wrong ack nr on packet, possible evasion!!",
2043                     ssn);
2044 
2045             StreamTcpSetEvent(p, STREAM_3WHS_RIGHT_SEQ_WRONG_ACK_EVASION);
2046             return -1;
2047 
2048             /* SYN/ACK followed by more TOCLIENT suggesting packet loss */
2049         } else if (PKT_IS_TOCLIENT(p) && !StreamTcpInlineMode() &&
2050                    SEQ_GT(TCP_GET_SEQ(p), ssn->client.next_seq) &&
2051                    SEQ_GT(TCP_GET_ACK(p), ssn->client.last_ack)) {
2052             SCLogDebug("ssn %p: ACK for missing data", ssn);
2053 
2054             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2055                 StreamTcpHandleTimestamp(ssn, p);
2056             }
2057 
2058             StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
2059 
2060             ssn->server.next_seq = TCP_GET_SEQ(p) + p->payload_len;
2061             SCLogDebug("ssn %p: ACK for missing data: ssn->server.next_seq %u", ssn,
2062                     ssn->server.next_seq);
2063             ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
2064 
2065             ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
2066 
2067             ssn->client.window = TCP_GET_WINDOW(p);
2068             ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
2069 
2070             StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
2071             SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2072 
2073             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p, pq);
2074 
2075             /* if we get a packet with a proper ack, but a seq that is beyond
2076              * next_seq but in-window, we probably missed some packets */
2077         } else if (SEQ_GT(TCP_GET_SEQ(p), ssn->client.next_seq) &&
2078                    SEQ_LEQ(TCP_GET_SEQ(p), ssn->client.next_win) &&
2079                    SEQ_EQ(TCP_GET_ACK(p), ssn->server.next_seq)) {
2080             SCLogDebug("ssn %p: ACK for missing data", ssn);
2081 
2082             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2083                 StreamTcpHandleTimestamp(ssn, p);
2084             }
2085 
2086             StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
2087 
2088             ssn->client.next_seq = TCP_GET_SEQ(p) + p->payload_len;
2089             SCLogDebug("ssn %p: ACK for missing data: ssn->client.next_seq %u", ssn, ssn->client.next_seq);
2090             ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
2091 
2092             ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
2093 
2094             if (ssn->flags & STREAMTCP_FLAG_MIDSTREAM) {
2095                 ssn->client.window = TCP_GET_WINDOW(p);
2096                 ssn->server.next_win = ssn->server.last_ack +
2097                     ssn->server.window;
2098                 /* window scaling for midstream pickups, we can't do much
2099                  * other than assume that it's set to the max value: 14 */
2100                 ssn->server.wscale = TCP_WSCALE_MAX;
2101                 ssn->client.wscale = TCP_WSCALE_MAX;
2102                 ssn->flags |= STREAMTCP_FLAG_SACKOK;
2103             }
2104 
2105             StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
2106             SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2107 
2108             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
2109                     &ssn->client, p, pq);
2110 
2111         /* toclient packet: after having missed the 3whs's final ACK */
2112         } else if ((ack_indicates_missed_3whs_ack_packet ||
2113                            (ssn->flags & STREAMTCP_FLAG_TCP_FAST_OPEN)) &&
2114                    SEQ_EQ(TCP_GET_ACK(p), ssn->client.last_ack) &&
2115                    SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq)) {
2116             if (ack_indicates_missed_3whs_ack_packet) {
2117                 SCLogDebug("ssn %p: packet fits perfectly after a missed 3whs-ACK", ssn);
2118             } else {
2119                 SCLogDebug("ssn %p: (TFO) expected packet fits perfectly after SYN/ACK", ssn);
2120             }
2121 
2122             StreamTcpUpdateNextSeq(ssn, &ssn->server, (TCP_GET_SEQ(p) + p->payload_len));
2123 
2124             ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
2125             ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
2126 
2127             StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
2128             SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2129 
2130             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
2131                     &ssn->server, p, pq);
2132 
2133         } else {
2134             SCLogDebug("ssn %p: wrong seq nr on packet", ssn);
2135 
2136             StreamTcpSetEvent(p, STREAM_3WHS_WRONG_SEQ_WRONG_ACK);
2137             return -1;
2138         }
2139 
2140         SCLogDebug("ssn %p: ssn->server.next_win %" PRIu32 ", "
2141                 "ssn->server.last_ack %"PRIu32"", ssn,
2142                 ssn->server.next_win, ssn->server.last_ack);
2143     } else {
2144         SCLogDebug("ssn %p: default case", ssn);
2145     }
2146 
2147     return 0;
2148 }
2149 
2150 /**
2151  *  \brief  Function to handle the TCP_ESTABLISHED state packets, which are
2152  *          sent by the client to server. The function handles
2153  *          ACK packets and call StreamTcpReassembleHandleSegment() to handle
2154  *          the reassembly.
2155  *
2156  *  Timestamp has already been checked at this point.
2157  *
2158  *  \param  tv      Thread Variable containig  input/output queue, cpu affinity etc.
2159  *  \param  ssn     Pointer to the current TCP session
2160  *  \param  p       Packet which has to be handled in this TCP state.
2161  *  \param  stt     Strean Thread module registered to handle the stream handling
2162  */
HandleEstablishedPacketToServer(ThreadVars * tv,TcpSession * ssn,Packet * p,StreamTcpThread * stt,PacketQueueNoLock * pq)2163 static int HandleEstablishedPacketToServer(ThreadVars *tv, TcpSession *ssn, Packet *p,
2164                         StreamTcpThread *stt, PacketQueueNoLock *pq)
2165 {
2166     SCLogDebug("ssn %p: =+ pkt (%" PRIu32 ") is to server: SEQ %" PRIu32 ","
2167                "ACK %" PRIu32 ", WIN %"PRIu16"", ssn, p->payload_len,
2168                 TCP_GET_SEQ(p), TCP_GET_ACK(p), TCP_GET_WINDOW(p));
2169 
2170     if (StreamTcpValidateAck(ssn, &(ssn->server), p) == -1) {
2171         SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
2172         StreamTcpSetEvent(p, STREAM_EST_INVALID_ACK);
2173         return -1;
2174     }
2175 
2176     /* check for Keep Alive */
2177     if ((p->payload_len == 0 || p->payload_len == 1) &&
2178             (TCP_GET_SEQ(p) == (ssn->client.next_seq - 1))) {
2179         SCLogDebug("ssn %p: pkt is keep alive", ssn);
2180 
2181     /* normal pkt */
2182     } else if (!(SEQ_GEQ((TCP_GET_SEQ(p)+p->payload_len), ssn->client.last_ack))) {
2183         if (ssn->flags & STREAMTCP_FLAG_ASYNC) {
2184             SCLogDebug("ssn %p: server => Asynchrouns stream, packet SEQ"
2185                     " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "),"
2186                     " ssn->client.last_ack %" PRIu32 ", ssn->client.next_win"
2187                     "%" PRIu32"(%"PRIu32")", ssn, TCP_GET_SEQ(p),
2188                     p->payload_len, TCP_GET_SEQ(p) + p->payload_len,
2189                     ssn->client.last_ack, ssn->client.next_win,
2190                     TCP_GET_SEQ(p) + p->payload_len - ssn->client.next_win);
2191 
2192             /* update the last_ack to current seq number as the session is
2193              * async and other stream is not updating it anymore :( */
2194             StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_SEQ(p));
2195 
2196         } else if (SEQ_EQ(ssn->client.next_seq, TCP_GET_SEQ(p)) &&
2197                 (stream_config.async_oneside == TRUE) &&
2198                 (ssn->flags & STREAMTCP_FLAG_MIDSTREAM)) {
2199             SCLogDebug("ssn %p: server => Asynchronous stream, packet SEQ."
2200                     " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "), "
2201                     "ssn->client.last_ack %" PRIu32 ", ssn->client.next_win "
2202                     "%" PRIu32 "(%"PRIu32")", ssn, TCP_GET_SEQ(p),
2203                     p->payload_len, TCP_GET_SEQ(p) + p->payload_len,
2204                     ssn->client.last_ack, ssn->client.next_win,
2205                     TCP_GET_SEQ(p) + p->payload_len - ssn->client.next_win);
2206 
2207             /* it seems we missed SYN and SYN/ACK packets of this session.
2208              * Update the last_ack to current seq number as the session
2209              * is async and other stream is not updating it anymore :( */
2210             StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_SEQ(p));
2211             ssn->flags |= STREAMTCP_FLAG_ASYNC;
2212 
2213         } else if (SEQ_EQ(ssn->client.last_ack, (ssn->client.isn + 1)) &&
2214                 (stream_config.async_oneside == TRUE) &&
2215                 (ssn->flags & STREAMTCP_FLAG_MIDSTREAM)) {
2216             SCLogDebug("ssn %p: server => Asynchronous stream, packet SEQ"
2217                     " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "), "
2218                     "ssn->client.last_ack %" PRIu32 ", ssn->client.next_win "
2219                     "%" PRIu32 "(%"PRIu32")", ssn, TCP_GET_SEQ(p),
2220                     p->payload_len, TCP_GET_SEQ(p) + p->payload_len,
2221                     ssn->client.last_ack, ssn->client.next_win,
2222                     TCP_GET_SEQ(p) + p->payload_len - ssn->client.next_win);
2223 
2224             /* it seems we missed SYN and SYN/ACK packets of this session.
2225              * Update the last_ack to current seq number as the session
2226              * is async and other stream is not updating it anymore :(*/
2227             StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_SEQ(p));
2228             ssn->flags |= STREAMTCP_FLAG_ASYNC;
2229 
2230         /* if last ack is beyond next_seq, we have accepted ack's for missing data.
2231          * In this case we do accept the data before last_ack if it is (partly)
2232          * beyond next seq */
2233         } else if (SEQ_GT(ssn->client.last_ack, ssn->client.next_seq) &&
2234                    SEQ_GT((TCP_GET_SEQ(p)+p->payload_len),ssn->client.next_seq))
2235         {
2236             SCLogDebug("ssn %p: PKT SEQ %"PRIu32" payload_len %"PRIu16
2237                     " before last_ack %"PRIu32", after next_seq %"PRIu32":"
2238                     " acked data that we haven't seen before",
2239                     ssn, TCP_GET_SEQ(p), p->payload_len, ssn->client.last_ack, ssn->client.next_seq);
2240             if (SEQ_EQ(TCP_GET_SEQ(p),ssn->client.next_seq)) {
2241                 StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
2242             }
2243         } else {
2244             SCLogDebug("ssn %p: server => SEQ before last_ack, packet SEQ"
2245                     " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "), "
2246                     "ssn->client.last_ack %" PRIu32 ", ssn->client.next_win "
2247                     "%" PRIu32 "(%"PRIu32")", ssn, TCP_GET_SEQ(p),
2248                     p->payload_len, TCP_GET_SEQ(p) + p->payload_len,
2249                     ssn->client.last_ack, ssn->client.next_win,
2250                     TCP_GET_SEQ(p) + p->payload_len - ssn->client.next_win);
2251 
2252             SCLogDebug("ssn %p: rejecting because pkt before last_ack", ssn);
2253             StreamTcpSetEvent(p, STREAM_EST_PKT_BEFORE_LAST_ACK);
2254             return -1;
2255         }
2256     }
2257 
2258     int zerowindowprobe = 0;
2259     /* zero window probe */
2260     if (p->payload_len == 1 && TCP_GET_SEQ(p) == ssn->client.next_seq && ssn->client.window == 0) {
2261         SCLogDebug("ssn %p: zero window probe", ssn);
2262         zerowindowprobe = 1;
2263 
2264     /* expected packet */
2265     } else if (SEQ_EQ(ssn->client.next_seq, TCP_GET_SEQ(p))) {
2266         StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
2267 
2268     /* not completely as expected, but valid */
2269     } else if (SEQ_LT(TCP_GET_SEQ(p),ssn->client.next_seq) &&
2270                SEQ_GT((TCP_GET_SEQ(p)+p->payload_len), ssn->client.next_seq))
2271     {
2272         StreamTcpUpdateNextSeq(ssn, &ssn->client, (TCP_GET_SEQ(p) + p->payload_len));
2273         SCLogDebug("ssn %p: ssn->client.next_seq %"PRIu32
2274                    " (started before next_seq, ended after)",
2275                    ssn, ssn->client.next_seq);
2276 
2277     /* if next_seq has fallen behind last_ack, we got some catching up to do */
2278     } else if (SEQ_LT(ssn->client.next_seq, ssn->client.last_ack)) {
2279         StreamTcpUpdateNextSeq(ssn, &ssn->client, (TCP_GET_SEQ(p) + p->payload_len));
2280         SCLogDebug("ssn %p: ssn->client.next_seq %"PRIu32
2281                    " (next_seq had fallen behind last_ack)",
2282                    ssn, ssn->client.next_seq);
2283 
2284     } else {
2285         SCLogDebug("ssn %p: no update to ssn->client.next_seq %"PRIu32
2286                    " SEQ %u SEQ+ %u last_ack %u",
2287                    ssn, ssn->client.next_seq,
2288                    TCP_GET_SEQ(p), TCP_GET_SEQ(p)+p->payload_len, ssn->client.last_ack);
2289     }
2290 
2291     /* in window check */
2292     if (zerowindowprobe) {
2293         SCLogDebug("ssn %p: zero window probe, skipping oow check", ssn);
2294     } else if (SEQ_LEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->client.next_win) ||
2295             (ssn->flags & (STREAMTCP_FLAG_MIDSTREAM|STREAMTCP_FLAG_ASYNC)))
2296     {
2297         SCLogDebug("ssn %p: seq %"PRIu32" in window, ssn->client.next_win "
2298                    "%" PRIu32 "", ssn, TCP_GET_SEQ(p), ssn->client.next_win);
2299 
2300         ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
2301         SCLogDebug("ssn %p: ssn->server.window %"PRIu32"", ssn,
2302                     ssn->server.window);
2303 
2304         /* Check if the ACK value is sane and inside the window limit */
2305         StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
2306         SCLogDebug("ack %u last_ack %u next_seq %u", TCP_GET_ACK(p), ssn->server.last_ack, ssn->server.next_seq);
2307 
2308         if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2309             StreamTcpHandleTimestamp(ssn, p);
2310         }
2311 
2312         StreamTcpSackUpdatePacket(&ssn->server, p);
2313 
2314         /* update next_win */
2315         StreamTcpUpdateNextWin(ssn, &ssn->server, (ssn->server.last_ack + ssn->server.window));
2316 
2317         /* handle data (if any) */
2318         StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p, pq);
2319 
2320     } else {
2321         SCLogDebug("ssn %p: toserver => SEQ out of window, packet SEQ "
2322                 "%" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "),"
2323                 "ssn->client.last_ack %" PRIu32 ", ssn->client.next_win "
2324                 "%" PRIu32 "(%"PRIu32")", ssn, TCP_GET_SEQ(p),
2325                 p->payload_len, TCP_GET_SEQ(p) + p->payload_len,
2326                 ssn->client.last_ack, ssn->client.next_win,
2327                 (TCP_GET_SEQ(p) + p->payload_len) - ssn->client.next_win);
2328         SCLogDebug("ssn %p: window %u sacked %u", ssn, ssn->client.window,
2329                 StreamTcpSackedSize(&ssn->client));
2330         StreamTcpSetEvent(p, STREAM_EST_PACKET_OUT_OF_WINDOW);
2331         return -1;
2332     }
2333     return 0;
2334 }
2335 
2336 /**
2337  *  \brief  Function to handle the TCP_ESTABLISHED state packets, which are
2338  *          sent by the server to client. The function handles
2339  *          ACK packets and call StreamTcpReassembleHandleSegment() to handle
2340  *          the reassembly
2341  *
2342  *  Timestamp has already been checked at this point.
2343  *
2344  *  \param  tv      Thread Variable containig  input/output queue, cpu affinity etc.
2345  *  \param  ssn     Pointer to the current TCP session
2346  *  \param  p       Packet which has to be handled in this TCP state.
2347  *  \param  stt     Strean Thread module registered to handle the stream handling
2348  */
HandleEstablishedPacketToClient(ThreadVars * tv,TcpSession * ssn,Packet * p,StreamTcpThread * stt,PacketQueueNoLock * pq)2349 static int HandleEstablishedPacketToClient(ThreadVars *tv, TcpSession *ssn, Packet *p,
2350                         StreamTcpThread *stt, PacketQueueNoLock *pq)
2351 {
2352     SCLogDebug("ssn %p: =+ pkt (%" PRIu32 ") is to client: SEQ %" PRIu32 ","
2353                " ACK %" PRIu32 ", WIN %"PRIu16"", ssn, p->payload_len,
2354                 TCP_GET_SEQ(p), TCP_GET_ACK(p), TCP_GET_WINDOW(p));
2355 
2356     if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
2357         SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
2358         StreamTcpSetEvent(p, STREAM_EST_INVALID_ACK);
2359         return -1;
2360     }
2361 
2362     /* To get the server window value from the servers packet, when connection
2363        is picked up as midstream */
2364     if ((ssn->flags & STREAMTCP_FLAG_MIDSTREAM) &&
2365             (ssn->flags & STREAMTCP_FLAG_MIDSTREAM_ESTABLISHED))
2366     {
2367         ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
2368         ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
2369         ssn->flags &= ~STREAMTCP_FLAG_MIDSTREAM_ESTABLISHED;
2370         SCLogDebug("ssn %p: adjusted midstream ssn->server.next_win to "
2371                 "%" PRIu32 "", ssn, ssn->server.next_win);
2372     }
2373 
2374     /* check for Keep Alive */
2375     if ((p->payload_len == 0 || p->payload_len == 1) &&
2376             (TCP_GET_SEQ(p) == (ssn->server.next_seq - 1))) {
2377         SCLogDebug("ssn %p: pkt is keep alive", ssn);
2378 
2379     /* normal pkt */
2380     } else if (!(SEQ_GEQ((TCP_GET_SEQ(p)+p->payload_len), ssn->server.last_ack))) {
2381         if (ssn->flags & STREAMTCP_FLAG_ASYNC) {
2382 
2383             SCLogDebug("ssn %p: client => Asynchrouns stream, packet SEQ"
2384                     " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "),"
2385                     " ssn->client.last_ack %" PRIu32 ", ssn->client.next_win"
2386                     " %"PRIu32"(%"PRIu32")", ssn, TCP_GET_SEQ(p),
2387                     p->payload_len, TCP_GET_SEQ(p) + p->payload_len,
2388                     ssn->server.last_ack, ssn->server.next_win,
2389                     TCP_GET_SEQ(p) + p->payload_len - ssn->server.next_win);
2390 
2391             ssn->server.last_ack = TCP_GET_SEQ(p);
2392 
2393         /* if last ack is beyond next_seq, we have accepted ack's for missing data.
2394          * In this case we do accept the data before last_ack if it is (partly)
2395          * beyond next seq */
2396         } else if (SEQ_GT(ssn->server.last_ack, ssn->server.next_seq) &&
2397                    SEQ_GT((TCP_GET_SEQ(p)+p->payload_len),ssn->server.next_seq))
2398         {
2399             SCLogDebug("ssn %p: PKT SEQ %"PRIu32" payload_len %"PRIu16
2400                     " before last_ack %"PRIu32", after next_seq %"PRIu32":"
2401                     " acked data that we haven't seen before",
2402                     ssn, TCP_GET_SEQ(p), p->payload_len, ssn->server.last_ack, ssn->server.next_seq);
2403             if (SEQ_EQ(TCP_GET_SEQ(p),ssn->server.next_seq)) {
2404                 StreamTcpUpdateNextSeq(ssn, &ssn->server, (ssn->server.next_seq + p->payload_len));
2405             }
2406         } else {
2407             SCLogDebug("ssn %p: PKT SEQ %"PRIu32" payload_len %"PRIu16
2408                     " before last_ack %"PRIu32". next_seq %"PRIu32,
2409                     ssn, TCP_GET_SEQ(p), p->payload_len, ssn->server.last_ack, ssn->server.next_seq);
2410             StreamTcpSetEvent(p, STREAM_EST_PKT_BEFORE_LAST_ACK);
2411             return -1;
2412         }
2413     }
2414 
2415     int zerowindowprobe = 0;
2416     /* zero window probe */
2417     if (p->payload_len == 1 && TCP_GET_SEQ(p) == ssn->server.next_seq && ssn->server.window == 0) {
2418         SCLogDebug("ssn %p: zero window probe", ssn);
2419         zerowindowprobe = 1;
2420 
2421     /* expected packet */
2422     } else if (SEQ_EQ(ssn->server.next_seq, TCP_GET_SEQ(p))) {
2423         StreamTcpUpdateNextSeq(ssn, &ssn->server, (ssn->server.next_seq + p->payload_len));
2424 
2425     /* not completely as expected, but valid */
2426     } else if (SEQ_LT(TCP_GET_SEQ(p),ssn->server.next_seq) &&
2427                SEQ_GT((TCP_GET_SEQ(p)+p->payload_len), ssn->server.next_seq))
2428     {
2429         StreamTcpUpdateNextSeq(ssn, &ssn->server, (TCP_GET_SEQ(p) + p->payload_len));
2430         SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32
2431                    " (started before next_seq, ended after)",
2432                    ssn, ssn->server.next_seq);
2433 
2434     /* if next_seq has fallen behind last_ack, we got some catching up to do */
2435     } else if (SEQ_LT(ssn->server.next_seq, ssn->server.last_ack)) {
2436         StreamTcpUpdateNextSeq(ssn, &ssn->server, (TCP_GET_SEQ(p) + p->payload_len));
2437         SCLogDebug("ssn %p: ssn->server.next_seq %"PRIu32
2438                    " (next_seq had fallen behind last_ack)",
2439                    ssn, ssn->server.next_seq);
2440 
2441     } else {
2442         SCLogDebug("ssn %p: no update to ssn->server.next_seq %"PRIu32
2443                    " SEQ %u SEQ+ %u last_ack %u",
2444                    ssn, ssn->server.next_seq,
2445                    TCP_GET_SEQ(p), TCP_GET_SEQ(p)+p->payload_len, ssn->server.last_ack);
2446     }
2447 
2448     if (zerowindowprobe) {
2449         SCLogDebug("ssn %p: zero window probe, skipping oow check", ssn);
2450     } else if (SEQ_LEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->server.next_win) ||
2451             (ssn->flags & (STREAMTCP_FLAG_MIDSTREAM|STREAMTCP_FLAG_ASYNC)))
2452     {
2453         SCLogDebug("ssn %p: seq %"PRIu32" in window, ssn->server.next_win "
2454                 "%" PRIu32 "", ssn, TCP_GET_SEQ(p), ssn->server.next_win);
2455         ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
2456         SCLogDebug("ssn %p: ssn->client.window %"PRIu32"", ssn,
2457                     ssn->client.window);
2458 
2459         StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
2460 
2461         if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2462             StreamTcpHandleTimestamp(ssn, p);
2463         }
2464 
2465         StreamTcpSackUpdatePacket(&ssn->client, p);
2466 
2467         StreamTcpUpdateNextWin(ssn, &ssn->client, (ssn->client.last_ack + ssn->client.window));
2468 
2469         StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p, pq);
2470     } else {
2471         SCLogDebug("ssn %p: client => SEQ out of window, packet SEQ"
2472                    "%" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "),"
2473                    " ssn->server.last_ack %" PRIu32 ", ssn->server.next_win "
2474                    "%" PRIu32 "(%"PRIu32")", ssn, TCP_GET_SEQ(p),
2475                    p->payload_len, TCP_GET_SEQ(p) + p->payload_len,
2476                    ssn->server.last_ack, ssn->server.next_win,
2477                    TCP_GET_SEQ(p) + p->payload_len - ssn->server.next_win);
2478         StreamTcpSetEvent(p, STREAM_EST_PACKET_OUT_OF_WINDOW);
2479         return -1;
2480     }
2481     return 0;
2482 }
2483 
2484 /**
2485  *  \internal
2486  *
2487  *  \brief Find the highest sequence number needed to consider all segments as ACK'd
2488  *
2489  *  Used to treat all segments as ACK'd upon receiving a valid RST.
2490  *
2491  *  \param stream stream to inspect the segments from
2492  *  \param seq sequence number to check against
2493  *
2494  *  \retval ack highest ack we need to set
2495  */
StreamTcpResetGetMaxAck(TcpStream * stream,uint32_t seq)2496 static inline uint32_t StreamTcpResetGetMaxAck(TcpStream *stream, uint32_t seq)
2497 {
2498     uint32_t ack = seq;
2499 
2500     if (STREAM_HAS_SEEN_DATA(stream)) {
2501         const uint32_t tail_seq = STREAM_SEQ_RIGHT_EDGE(stream);
2502         if (SEQ_GT(tail_seq, ack)) {
2503             ack = tail_seq;
2504         }
2505     }
2506 
2507     SCReturnUInt(ack);
2508 }
2509 
2510 /**
2511  *  \brief  Function to handle the TCP_ESTABLISHED state. The function handles
2512  *          ACK, FIN, RST packets and correspondingly changes the connection
2513  *          state. The function handles the data inside packets and call
2514  *          StreamTcpReassembleHandleSegment(tv, ) to handle the reassembling.
2515  *
2516  *  \param  tv      Thread Variable containig  input/output queue, cpu affinity etc.
2517  *  \param  p       Packet which has to be handled in this TCP state.
2518  *  \param  stt     Strean Thread module registered to handle the stream handling
2519  */
2520 
StreamTcpPacketStateEstablished(ThreadVars * tv,Packet * p,StreamTcpThread * stt,TcpSession * ssn,PacketQueueNoLock * pq)2521 static int StreamTcpPacketStateEstablished(ThreadVars *tv, Packet *p,
2522         StreamTcpThread *stt, TcpSession *ssn, PacketQueueNoLock *pq)
2523 {
2524     if (ssn == NULL)
2525         return -1;
2526 
2527     if (p->tcph->th_flags & TH_RST) {
2528         if (!StreamTcpValidateRst(ssn, p))
2529             return -1;
2530 
2531         if (PKT_IS_TOSERVER(p)) {
2532             StreamTcpCloseSsnWithReset(p, ssn);
2533 
2534             ssn->server.next_seq = TCP_GET_ACK(p);
2535             ssn->client.next_seq = TCP_GET_SEQ(p) + p->payload_len;
2536             SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "", ssn,
2537                     ssn->server.next_seq);
2538             ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
2539 
2540             if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
2541                 StreamTcpUpdateLastAck(ssn, &ssn->server,
2542                         StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
2543 
2544             StreamTcpUpdateLastAck(ssn, &ssn->client,
2545                     StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p)));
2546 
2547             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2548                 StreamTcpHandleTimestamp(ssn, p);
2549             }
2550 
2551             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
2552                     &ssn->client, p, pq);
2553             SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
2554                     "%" PRIu32 "", ssn, ssn->client.next_seq,
2555                     ssn->server.last_ack);
2556 
2557             /* don't return packets to pools here just yet, the pseudo
2558              * packet will take care, otherwise the normal session
2559              * cleanup. */
2560         } else {
2561             StreamTcpCloseSsnWithReset(p, ssn);
2562 
2563             ssn->server.next_seq = TCP_GET_SEQ(p) + p->payload_len + 1;
2564             ssn->client.next_seq = TCP_GET_ACK(p);
2565 
2566             SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "", ssn,
2567                     ssn->server.next_seq);
2568             ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
2569 
2570             if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
2571                 StreamTcpUpdateLastAck(ssn, &ssn->client,
2572                         StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
2573 
2574             StreamTcpUpdateLastAck(ssn, &ssn->server,
2575                     StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p)));
2576 
2577             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2578                 StreamTcpHandleTimestamp(ssn, p);
2579             }
2580 
2581             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
2582                     &ssn->server, p, pq);
2583             SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
2584                     "%" PRIu32 "", ssn, ssn->server.next_seq,
2585                     ssn->client.last_ack);
2586 
2587             /* don't return packets to pools here just yet, the pseudo
2588              * packet will take care, otherwise the normal session
2589              * cleanup. */
2590         }
2591 
2592     } else if (p->tcph->th_flags & TH_FIN) {
2593         if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2594             if (!StreamTcpValidateTimestamp(ssn, p))
2595                 return -1;
2596         }
2597 
2598         SCLogDebug("ssn (%p: FIN received SEQ"
2599                 " %" PRIu32 ", last ACK %" PRIu32 ", next win %"PRIu32","
2600                 " win %" PRIu32 "", ssn, ssn->server.next_seq,
2601                 ssn->client.last_ack, ssn->server.next_win,
2602                 ssn->server.window);
2603 
2604         if ((StreamTcpHandleFin(tv, stt, ssn, p, pq)) == -1)
2605             return -1;
2606 
2607     /* SYN/ACK */
2608     } else if ((p->tcph->th_flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) {
2609         SCLogDebug("ssn %p: SYN/ACK packet on state ESTABLISHED... resent",
2610                 ssn);
2611 
2612         if (PKT_IS_TOSERVER(p)) {
2613             SCLogDebug("ssn %p: SYN/ACK-pkt to server in ESTABLISHED state", ssn);
2614 
2615             StreamTcpSetEvent(p, STREAM_EST_SYNACK_TOSERVER);
2616             return -1;
2617         }
2618 
2619         /* Check if the SYN/ACK packets ACK matches the earlier
2620          * received SYN/ACK packet. */
2621         if (!(SEQ_EQ(TCP_GET_ACK(p), ssn->client.last_ack))) {
2622             SCLogDebug("ssn %p: ACK mismatch, packet ACK %" PRIu32 " != "
2623                     "%" PRIu32 " from stream", ssn, TCP_GET_ACK(p),
2624                     ssn->client.isn + 1);
2625 
2626             StreamTcpSetEvent(p, STREAM_EST_SYNACK_RESEND_WITH_DIFFERENT_ACK);
2627             return -1;
2628         }
2629 
2630         /* Check if the SYN/ACK packet SEQ the earlier
2631          * received SYN packet. */
2632         if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->server.isn))) {
2633             SCLogDebug("ssn %p: SEQ mismatch, packet SEQ %" PRIu32 " != "
2634                     "%" PRIu32 " from stream", ssn, TCP_GET_ACK(p),
2635                     ssn->client.isn + 1);
2636 
2637             StreamTcpSetEvent(p, STREAM_EST_SYNACK_RESEND_WITH_DIFF_SEQ);
2638             return -1;
2639         }
2640 
2641         if (ssn->flags & STREAMTCP_FLAG_3WHS_CONFIRMED) {
2642             /* a resend of a SYN while we are established already -- fishy */
2643             StreamTcpSetEvent(p, STREAM_EST_SYNACK_RESEND);
2644             return -1;
2645         }
2646 
2647         SCLogDebug("ssn %p: SYN/ACK packet on state ESTABLISHED... resent. "
2648                 "Likely due server not receiving final ACK in 3whs", ssn);
2649         return 0;
2650 
2651     } else if (p->tcph->th_flags & TH_SYN) {
2652         SCLogDebug("ssn %p: SYN packet on state ESTABLISHED... resent", ssn);
2653         if (PKT_IS_TOCLIENT(p)) {
2654             SCLogDebug("ssn %p: SYN-pkt to client in EST state", ssn);
2655 
2656             StreamTcpSetEvent(p, STREAM_EST_SYN_TOCLIENT);
2657             return -1;
2658         }
2659 
2660         if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->client.isn))) {
2661             SCLogDebug("ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
2662 
2663             StreamTcpSetEvent(p, STREAM_EST_SYN_RESEND_DIFF_SEQ);
2664             return -1;
2665         }
2666 
2667         /* a resend of a SYN while we are established already -- fishy */
2668         StreamTcpSetEvent(p, STREAM_EST_SYN_RESEND);
2669         return -1;
2670 
2671     } else if (p->tcph->th_flags & TH_ACK) {
2672         /* Urgent pointer size can be more than the payload size, as it tells
2673          * the future coming data from the sender will be handled urgently
2674          * until data of size equal to urgent offset has been processed
2675          * (RFC 2147) */
2676 
2677         /* If the timestamp option is enabled for both the streams, then
2678          * validate the received packet timestamp value against the
2679          * stream->last_ts. If the timestamp is valid then process the
2680          * packet normally otherwise the drop the packet (RFC 1323) */
2681         if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2682             if (!StreamTcpValidateTimestamp(ssn, p))
2683                 return -1;
2684         }
2685 
2686         if (PKT_IS_TOSERVER(p)) {
2687             /* Process the received packet to server */
2688             HandleEstablishedPacketToServer(tv, ssn, p, stt, pq);
2689 
2690             SCLogDebug("ssn %p: next SEQ %" PRIu32 ", last ACK %" PRIu32 ","
2691                     " next win %" PRIu32 ", win %" PRIu32 "", ssn,
2692                     ssn->client.next_seq, ssn->server.last_ack
2693                     ,ssn->client.next_win, ssn->client.window);
2694 
2695         } else { /* implied to client */
2696             if (!(ssn->flags & STREAMTCP_FLAG_3WHS_CONFIRMED)) {
2697                 ssn->flags |= STREAMTCP_FLAG_3WHS_CONFIRMED;
2698                 SCLogDebug("3whs is now confirmed by server");
2699             }
2700 
2701             /* Process the received packet to client */
2702             HandleEstablishedPacketToClient(tv, ssn, p, stt, pq);
2703 
2704             SCLogDebug("ssn %p: next SEQ %" PRIu32 ", last ACK %" PRIu32 ","
2705                     " next win %" PRIu32 ", win %" PRIu32 "", ssn,
2706                     ssn->server.next_seq, ssn->client.last_ack,
2707                     ssn->server.next_win, ssn->server.window);
2708         }
2709     } else {
2710         SCLogDebug("ssn %p: default case", ssn);
2711     }
2712 
2713     return 0;
2714 }
2715 
2716 /**
2717  *  \brief  Function to handle the FIN packets for states TCP_SYN_RECV and
2718  *          TCP_ESTABLISHED and changes to another TCP state as required.
2719  *
2720  *  \param  tv      Thread Variable containig  input/output queue, cpu affinity
2721  *  \param  p       Packet which has to be handled in this TCP state.
2722  *  \param  stt     Strean Thread module registered to handle the stream handling
2723  *
2724  *  \retval 0 success
2725  *  \retval -1 something wrong with the packet
2726  */
2727 
StreamTcpHandleFin(ThreadVars * tv,StreamTcpThread * stt,TcpSession * ssn,Packet * p,PacketQueueNoLock * pq)2728 static int StreamTcpHandleFin(ThreadVars *tv, StreamTcpThread *stt,
2729                                 TcpSession *ssn, Packet *p, PacketQueueNoLock *pq)
2730 {
2731     if (PKT_IS_TOSERVER(p)) {
2732         SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ %" PRIu32 ","
2733                 " ACK %" PRIu32 "", ssn, p->payload_len, TCP_GET_SEQ(p),
2734                 TCP_GET_ACK(p));
2735 
2736         if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
2737             SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
2738             StreamTcpSetEvent(p, STREAM_FIN_INVALID_ACK);
2739             return -1;
2740         }
2741 
2742         if (SEQ_LT(TCP_GET_SEQ(p), ssn->client.next_seq) ||
2743             SEQ_GT(TCP_GET_SEQ(p), (ssn->client.last_ack + ssn->client.window)))
2744         {
2745             SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != "
2746                     "%" PRIu32 " from stream", ssn, TCP_GET_SEQ(p),
2747                     ssn->client.next_seq);
2748 
2749             StreamTcpSetEvent(p, STREAM_FIN_OUT_OF_WINDOW);
2750             return -1;
2751         }
2752 
2753         if (p->tcph->th_flags & TH_SYN) {
2754             SCLogDebug("ssn %p: FIN+SYN", ssn);
2755             StreamTcpSetEvent(p, STREAM_FIN_SYN);
2756             return -1;
2757         }
2758         StreamTcpPacketSetState(p, ssn, TCP_CLOSE_WAIT);
2759         SCLogDebug("ssn %p: state changed to TCP_CLOSE_WAIT", ssn);
2760 
2761         if (SEQ_EQ(TCP_GET_SEQ(p), ssn->client.next_seq))
2762             ssn->client.next_seq = TCP_GET_SEQ(p) + p->payload_len;
2763 
2764         SCLogDebug("ssn %p: ssn->client.next_seq %" PRIu32 "", ssn,
2765                     ssn->client.next_seq);
2766         ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
2767 
2768         StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
2769 
2770         if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2771             StreamTcpHandleTimestamp(ssn, p);
2772         }
2773 
2774         /* Update the next_seq, in case if we have missed the client packet
2775            and server has already received and acked it */
2776         if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
2777             ssn->server.next_seq = TCP_GET_ACK(p);
2778 
2779         StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p, pq);
2780 
2781         SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK %" PRIu32 "",
2782                 ssn, ssn->client.next_seq, ssn->server.last_ack);
2783     } else { /* implied to client */
2784         SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ %" PRIu32 ", "
2785                    "ACK %" PRIu32 "", ssn, p->payload_len, TCP_GET_SEQ(p),
2786                     TCP_GET_ACK(p));
2787 
2788         if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
2789             SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
2790             StreamTcpSetEvent(p, STREAM_FIN_INVALID_ACK);
2791             return -1;
2792         }
2793 
2794         if (SEQ_LT(TCP_GET_SEQ(p), ssn->server.next_seq) ||
2795                 SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + ssn->server.window)))
2796         {
2797             SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != "
2798                     "%" PRIu32 " from stream (last_ack %u win %u = %u)", ssn, TCP_GET_SEQ(p),
2799                     ssn->server.next_seq, ssn->server.last_ack, ssn->server.window, (ssn->server.last_ack + ssn->server.window));
2800 
2801             StreamTcpSetEvent(p, STREAM_FIN_OUT_OF_WINDOW);
2802             return -1;
2803         }
2804 
2805         StreamTcpPacketSetState(p, ssn, TCP_FIN_WAIT1);
2806         SCLogDebug("ssn %p: state changed to TCP_FIN_WAIT1", ssn);
2807 
2808         if (SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq))
2809             ssn->server.next_seq = TCP_GET_SEQ(p) + p->payload_len;
2810 
2811         SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "", ssn,
2812                     ssn->server.next_seq);
2813         ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
2814 
2815         StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
2816 
2817         if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2818             StreamTcpHandleTimestamp(ssn, p);
2819         }
2820 
2821         /* Update the next_seq, in case if we have missed the client packet
2822            and server has already received and acked it */
2823         if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
2824             ssn->client.next_seq = TCP_GET_ACK(p);
2825 
2826         StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p, pq);
2827 
2828         SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK %" PRIu32 "",
2829                 ssn, ssn->server.next_seq, ssn->client.last_ack);
2830     }
2831 
2832     return 0;
2833 }
2834 
2835 /**
2836  *  \brief  Function to handle the TCP_FIN_WAIT1 state. The function handles
2837  *          ACK, FIN, RST packets and correspondingly changes the connection
2838  *          state.
2839  *
2840  *  \param  tv      Thread Variable containig  input/output queue, cpu affinity
2841  *  \param  p       Packet which has to be handled in this TCP state.
2842  *  \param  stt     Strean Thread module registered to handle the stream handling
2843  *
2844  *  \retval 0 success
2845  *  \retval -1 something wrong with the packet
2846  */
2847 
StreamTcpPacketStateFinWait1(ThreadVars * tv,Packet * p,StreamTcpThread * stt,TcpSession * ssn,PacketQueueNoLock * pq)2848 static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p,
2849         StreamTcpThread *stt, TcpSession *ssn, PacketQueueNoLock *pq)
2850 {
2851     if (ssn == NULL)
2852         return -1;
2853 
2854     if (p->tcph->th_flags & TH_RST) {
2855         if (!StreamTcpValidateRst(ssn, p))
2856             return -1;
2857 
2858         StreamTcpCloseSsnWithReset(p, ssn);
2859 
2860         if (PKT_IS_TOSERVER(p)) {
2861             if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
2862                 StreamTcpUpdateLastAck(ssn, &ssn->server,
2863                         StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
2864 
2865             StreamTcpUpdateLastAck(ssn, &ssn->client,
2866                     StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p)));
2867 
2868             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2869                 StreamTcpHandleTimestamp(ssn, p);
2870             }
2871 
2872             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
2873                     &ssn->client, p, pq);
2874         } else {
2875             if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
2876                 StreamTcpUpdateLastAck(ssn, &ssn->client,
2877                         StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
2878 
2879             StreamTcpUpdateLastAck(ssn, &ssn->server,
2880                     StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p)));
2881 
2882             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2883                 StreamTcpHandleTimestamp(ssn, p);
2884             }
2885 
2886             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
2887                     &ssn->server, p, pq);
2888         }
2889 
2890     } else if ((p->tcph->th_flags & (TH_FIN|TH_ACK)) == (TH_FIN|TH_ACK)) {
2891         if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2892             if (!StreamTcpValidateTimestamp(ssn, p))
2893                 return -1;
2894         }
2895 
2896         if (PKT_IS_TOSERVER(p)) {
2897             SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
2898                     "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
2899                     TCP_GET_SEQ(p), TCP_GET_ACK(p));
2900             int retransmission = 0;
2901 
2902             if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
2903                 SCLogDebug("ssn %p: packet is retransmission", ssn);
2904                 retransmission = 1;
2905 
2906             } else if (SEQ_LT(TCP_GET_SEQ(p), ssn->client.next_seq) ||
2907                     SEQ_GT(TCP_GET_SEQ(p), (ssn->client.last_ack + ssn->client.window)))
2908             {
2909                 SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
2910                         " != %" PRIu32 " from stream", ssn,
2911                         TCP_GET_SEQ(p), ssn->client.next_seq);
2912                 StreamTcpSetEvent(p, STREAM_FIN1_FIN_WRONG_SEQ);
2913                 return -1;
2914             }
2915 
2916             if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
2917                 SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
2918                 StreamTcpSetEvent(p, STREAM_FIN1_INVALID_ACK);
2919                 return -1;
2920             }
2921 
2922             if (!retransmission) {
2923                 StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
2924                 SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
2925 
2926                 ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
2927             }
2928 
2929             StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
2930 
2931             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2932                 StreamTcpHandleTimestamp(ssn, p);
2933             }
2934 
2935             /* Update the next_seq, in case if we have missed the client
2936                packet and server has already received and acked it */
2937             if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
2938                 ssn->server.next_seq = TCP_GET_ACK(p);
2939 
2940             if (SEQ_EQ(ssn->client.next_seq, TCP_GET_SEQ(p))) {
2941                 StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
2942             }
2943 
2944             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
2945                     &ssn->client, p, pq);
2946 
2947             SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
2948                     "%" PRIu32 "", ssn, ssn->client.next_seq,
2949                     ssn->server.last_ack);
2950         } else { /* implied to client */
2951             SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
2952                     "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
2953                     TCP_GET_SEQ(p), TCP_GET_ACK(p));
2954             int retransmission = 0;
2955 
2956             if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
2957                 SCLogDebug("ssn %p: packet is retransmission", ssn);
2958                 retransmission = 1;
2959             } else if (SEQ_EQ(ssn->server.next_seq, TCP_GET_SEQ(p)) &&
2960                        SEQ_EQ(ssn->client.last_ack, TCP_GET_ACK(p))) {
2961                 SCLogDebug("ssn %p: packet is retransmission", ssn);
2962                 retransmission = 1;
2963 
2964             } else if (SEQ_LT(TCP_GET_SEQ(p), ssn->server.next_seq) ||
2965                        SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + ssn->server.window))) {
2966                 SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
2967                         " != %" PRIu32 " from stream", ssn,
2968                         TCP_GET_SEQ(p), ssn->server.next_seq);
2969                 StreamTcpSetEvent(p, STREAM_FIN1_FIN_WRONG_SEQ);
2970                 return -1;
2971             }
2972 
2973             if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
2974                 SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
2975                 StreamTcpSetEvent(p, STREAM_FIN1_INVALID_ACK);
2976                 return -1;
2977             }
2978 
2979             if (!retransmission) {
2980                 StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
2981                 SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
2982 
2983                 ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
2984             }
2985 
2986             StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
2987 
2988             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2989                 StreamTcpHandleTimestamp(ssn, p);
2990             }
2991 
2992             /* Update the next_seq, in case if we have missed the client
2993                packet and server has already received and acked it */
2994             if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
2995                 ssn->client.next_seq = TCP_GET_ACK(p);
2996 
2997             if (SEQ_EQ(ssn->server.next_seq, TCP_GET_SEQ(p))) {
2998                 StreamTcpUpdateNextSeq(ssn, &ssn->server, (ssn->server.next_seq + p->payload_len));
2999             }
3000 
3001             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
3002                     &ssn->server, p, pq);
3003 
3004             SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3005                     "%" PRIu32 "", ssn, ssn->server.next_seq,
3006                     ssn->client.last_ack);
3007         }
3008 
3009     } else if (p->tcph->th_flags & TH_FIN) {
3010         if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3011             if (!StreamTcpValidateTimestamp(ssn, p))
3012                 return -1;
3013         }
3014 
3015         if (PKT_IS_TOSERVER(p)) {
3016             SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
3017                     "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3018                     TCP_GET_SEQ(p), TCP_GET_ACK(p));
3019             int retransmission = 0;
3020 
3021             if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
3022                 SCLogDebug("ssn %p: packet is retransmission", ssn);
3023                 retransmission = 1;
3024 
3025             } else if (SEQ_LT(TCP_GET_SEQ(p), ssn->client.next_seq) ||
3026                     SEQ_GT(TCP_GET_SEQ(p), (ssn->client.last_ack + ssn->client.window)))
3027             {
3028                 SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
3029                         " != %" PRIu32 " from stream", ssn,
3030                         TCP_GET_SEQ(p), ssn->client.next_seq);
3031                 StreamTcpSetEvent(p, STREAM_FIN1_FIN_WRONG_SEQ);
3032                 return -1;
3033             }
3034 
3035             if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
3036                 SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3037                 StreamTcpSetEvent(p, STREAM_FIN1_INVALID_ACK);
3038                 return -1;
3039             }
3040 
3041             if (!retransmission) {
3042                 StreamTcpPacketSetState(p, ssn, TCP_CLOSING);
3043                 SCLogDebug("ssn %p: state changed to TCP_CLOSING", ssn);
3044 
3045                 ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
3046             }
3047 
3048             StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
3049 
3050             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3051                 StreamTcpHandleTimestamp(ssn, p);
3052             }
3053 
3054             /* Update the next_seq, in case if we have missed the client
3055                packet and server has already received and acked it */
3056             if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
3057                 ssn->server.next_seq = TCP_GET_ACK(p);
3058 
3059             if (SEQ_EQ(ssn->client.next_seq, TCP_GET_SEQ(p))) {
3060                 StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
3061             }
3062 
3063             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
3064                     &ssn->client, p, pq);
3065 
3066             SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3067                     "%" PRIu32 "", ssn, ssn->client.next_seq,
3068                     ssn->server.last_ack);
3069         } else { /* implied to client */
3070             SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
3071                     "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3072                     TCP_GET_SEQ(p), TCP_GET_ACK(p));
3073 
3074             int retransmission = 0;
3075 
3076             if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
3077                 SCLogDebug("ssn %p: packet is retransmission", ssn);
3078                 retransmission = 1;
3079 
3080             } else if (SEQ_LT(TCP_GET_SEQ(p), ssn->server.next_seq) ||
3081                     SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + ssn->server.window)))
3082             {
3083                 SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
3084                         " != %" PRIu32 " from stream", ssn,
3085                         TCP_GET_SEQ(p), ssn->server.next_seq);
3086                 StreamTcpSetEvent(p, STREAM_FIN1_FIN_WRONG_SEQ);
3087                 return -1;
3088             }
3089 
3090             if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
3091                 SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3092                 StreamTcpSetEvent(p, STREAM_FIN1_INVALID_ACK);
3093                 return -1;
3094             }
3095 
3096             if (!retransmission) {
3097                 StreamTcpPacketSetState(p, ssn, TCP_CLOSING);
3098                 SCLogDebug("ssn %p: state changed to TCP_CLOSING", ssn);
3099 
3100                 ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
3101             }
3102 
3103             StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
3104 
3105             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3106                 StreamTcpHandleTimestamp(ssn, p);
3107             }
3108 
3109             /* Update the next_seq, in case if we have missed the client
3110                packet and server has already received and acked it */
3111             if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
3112                 ssn->client.next_seq = TCP_GET_ACK(p);
3113 
3114             if (SEQ_EQ(ssn->server.next_seq, TCP_GET_SEQ(p))) {
3115                 StreamTcpUpdateNextSeq(ssn, &ssn->server, (ssn->server.next_seq + p->payload_len));
3116             }
3117 
3118             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
3119                     &ssn->server, p, pq);
3120 
3121             SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3122                     "%" PRIu32 "", ssn, ssn->server.next_seq,
3123                     ssn->client.last_ack);
3124         }
3125     } else if (p->tcph->th_flags & TH_SYN) {
3126         SCLogDebug("ssn (%p): SYN pkt on FinWait1", ssn);
3127         StreamTcpSetEvent(p, STREAM_SHUTDOWN_SYN_RESEND);
3128         return -1;
3129 
3130     } else if (p->tcph->th_flags & TH_ACK) {
3131         if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3132             if (!StreamTcpValidateTimestamp(ssn, p))
3133                 return -1;
3134         }
3135 
3136         if (PKT_IS_TOSERVER(p)) {
3137             SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
3138                     "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3139                     TCP_GET_SEQ(p), TCP_GET_ACK(p));
3140             int retransmission = 0;
3141 
3142             if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
3143                 SCLogDebug("ssn %p: packet is retransmission", ssn);
3144                 retransmission = 1;
3145             }
3146 
3147             if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
3148                 SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3149                 StreamTcpSetEvent(p, STREAM_FIN1_INVALID_ACK);
3150                 return -1;
3151             }
3152 
3153             if (!retransmission) {
3154                 if (SEQ_LEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->client.next_win) ||
3155                         (ssn->flags & (STREAMTCP_FLAG_MIDSTREAM|STREAMTCP_FLAG_ASYNC)))
3156                 {
3157                     SCLogDebug("ssn %p: seq %"PRIu32" in window, ssn->client.next_win "
3158                             "%" PRIu32 "", ssn, TCP_GET_SEQ(p), ssn->client.next_win);
3159 
3160                     if (TCP_GET_SEQ(p) == ssn->client.next_seq) {
3161                         StreamTcpPacketSetState(p, ssn, TCP_FIN_WAIT2);
3162                         SCLogDebug("ssn %p: state changed to TCP_FIN_WAIT2", ssn);
3163                     }
3164                 } else {
3165                     SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
3166                             " != %" PRIu32 " from stream", ssn,
3167                             TCP_GET_SEQ(p), ssn->client.next_seq);
3168 
3169                     StreamTcpSetEvent(p, STREAM_FIN1_ACK_WRONG_SEQ);
3170                     return -1;
3171                 }
3172 
3173                 ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
3174             }
3175 
3176             StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
3177 
3178             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3179                 StreamTcpHandleTimestamp(ssn, p);
3180             }
3181 
3182             /* Update the next_seq, in case if we have missed the client
3183                packet and server has already received and acked it */
3184             if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
3185                 ssn->server.next_seq = TCP_GET_ACK(p);
3186 
3187             if (SEQ_EQ(ssn->client.next_seq, TCP_GET_SEQ(p))) {
3188                 StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
3189             }
3190 
3191             StreamTcpSackUpdatePacket(&ssn->server, p);
3192 
3193             /* update next_win */
3194             StreamTcpUpdateNextWin(ssn, &ssn->server, (ssn->server.last_ack + ssn->server.window));
3195 
3196             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
3197                     &ssn->client, p, pq);
3198 
3199             SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3200                     "%" PRIu32 "", ssn, ssn->client.next_seq,
3201                     ssn->server.last_ack);
3202 
3203         } else { /* implied to client */
3204 
3205             SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
3206                     "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3207                     TCP_GET_SEQ(p), TCP_GET_ACK(p));
3208 
3209             int retransmission = 0;
3210 
3211             if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
3212                 SCLogDebug("ssn %p: packet is retransmission", ssn);
3213                 retransmission = 1;
3214             }
3215 
3216             if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
3217                 SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3218                 StreamTcpSetEvent(p, STREAM_FIN1_INVALID_ACK);
3219                 return -1;
3220             }
3221 
3222             if (!retransmission) {
3223                 if (SEQ_LEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->server.next_win) ||
3224                         (ssn->flags & (STREAMTCP_FLAG_MIDSTREAM|STREAMTCP_FLAG_ASYNC)))
3225                 {
3226                     SCLogDebug("ssn %p: seq %"PRIu32" in window, ssn->server.next_win "
3227                             "%" PRIu32 "", ssn, TCP_GET_SEQ(p), ssn->server.next_win);
3228 
3229                     if (TCP_GET_SEQ(p) == ssn->server.next_seq) {
3230                         StreamTcpPacketSetState(p, ssn, TCP_FIN_WAIT2);
3231                         SCLogDebug("ssn %p: state changed to TCP_FIN_WAIT2", ssn);
3232                     }
3233                 } else {
3234                     SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
3235                             " != %" PRIu32 " from stream", ssn,
3236                             TCP_GET_SEQ(p), ssn->server.next_seq);
3237                     StreamTcpSetEvent(p, STREAM_FIN1_ACK_WRONG_SEQ);
3238                     return -1;
3239                 }
3240 
3241                 ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
3242             }
3243 
3244             StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
3245 
3246             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3247                 StreamTcpHandleTimestamp(ssn, p);
3248             }
3249 
3250             /* Update the next_seq, in case if we have missed the client
3251                packet and server has already received and acked it */
3252             if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
3253                 ssn->client.next_seq = TCP_GET_ACK(p);
3254 
3255             if (SEQ_EQ(ssn->server.next_seq, TCP_GET_SEQ(p))) {
3256                 StreamTcpUpdateNextSeq(ssn, &ssn->server, (ssn->server.next_seq + p->payload_len));
3257             }
3258 
3259             StreamTcpSackUpdatePacket(&ssn->client, p);
3260 
3261             /* update next_win */
3262             StreamTcpUpdateNextWin(ssn, &ssn->client, (ssn->client.last_ack + ssn->client.window));
3263 
3264             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
3265                     &ssn->server, p, pq);
3266 
3267             SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3268                     "%" PRIu32 "", ssn, ssn->server.next_seq,
3269                     ssn->client.last_ack);
3270         }
3271     } else {
3272         SCLogDebug("ssn (%p): default case", ssn);
3273     }
3274 
3275     return 0;
3276 }
3277 
3278 /**
3279  *  \brief  Function to handle the TCP_FIN_WAIT2 state. The function handles
3280  *          ACK, RST, FIN packets and correspondingly changes the connection
3281  *          state.
3282  *
3283  *  \param  tv      Thread Variable containig  input/output queue, cpu affinity
3284  *  \param  p       Packet which has to be handled in this TCP state.
3285  *  \param  stt     Strean Thread module registered to handle the stream handling
3286  */
3287 
StreamTcpPacketStateFinWait2(ThreadVars * tv,Packet * p,StreamTcpThread * stt,TcpSession * ssn,PacketQueueNoLock * pq)3288 static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p,
3289         StreamTcpThread *stt, TcpSession *ssn, PacketQueueNoLock *pq)
3290 {
3291     if (ssn == NULL)
3292         return -1;
3293 
3294     if (p->tcph->th_flags & TH_RST) {
3295         if (!StreamTcpValidateRst(ssn, p))
3296             return -1;
3297 
3298         StreamTcpCloseSsnWithReset(p, ssn);
3299 
3300         if (PKT_IS_TOSERVER(p)) {
3301             if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
3302                 StreamTcpUpdateLastAck(ssn, &ssn->server,
3303                         StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
3304 
3305             StreamTcpUpdateLastAck(ssn, &ssn->client,
3306                     StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p)));
3307 
3308             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3309                 StreamTcpHandleTimestamp(ssn, p);
3310             }
3311 
3312             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
3313                     &ssn->client, p, pq);
3314         } else {
3315             if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
3316                 StreamTcpUpdateLastAck(ssn, &ssn->client,
3317                         StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
3318 
3319             StreamTcpUpdateLastAck(ssn, &ssn->server,
3320                     StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p)));
3321 
3322             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3323                 StreamTcpHandleTimestamp(ssn, p);
3324             }
3325 
3326             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
3327                     &ssn->server, p, pq);
3328         }
3329 
3330     } else if (p->tcph->th_flags & TH_FIN) {
3331         if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3332             if (!StreamTcpValidateTimestamp(ssn, p))
3333                 return -1;
3334         }
3335 
3336         if (PKT_IS_TOSERVER(p)) {
3337             SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
3338                     "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3339                     TCP_GET_SEQ(p), TCP_GET_ACK(p));
3340             int retransmission = 0;
3341 
3342             if (SEQ_EQ(TCP_GET_SEQ(p), ssn->client.next_seq - 1) &&
3343                 SEQ_EQ(TCP_GET_ACK(p), ssn->server.last_ack)) {
3344                 SCLogDebug("ssn %p: retransmission", ssn);
3345                 retransmission = 1;
3346             } else if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
3347                 SCLogDebug("ssn %p: packet is retransmission", ssn);
3348                 retransmission = 1;
3349 
3350             } else if (SEQ_LT(TCP_GET_SEQ(p), ssn->client.next_seq) ||
3351                     SEQ_GT(TCP_GET_SEQ(p), (ssn->client.last_ack + ssn->client.window)))
3352             {
3353                 SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ "
3354                         "%" PRIu32 " != %" PRIu32 " from stream", ssn,
3355                         TCP_GET_SEQ(p), ssn->client.next_seq);
3356                 StreamTcpSetEvent(p, STREAM_FIN2_FIN_WRONG_SEQ);
3357                 return -1;
3358             }
3359 
3360             if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
3361                 SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3362                 StreamTcpSetEvent(p, STREAM_FIN2_INVALID_ACK);
3363                 return -1;
3364             }
3365 
3366             if (!retransmission) {
3367                 StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
3368                 SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
3369 
3370                 if (SEQ_EQ(ssn->client.next_seq, TCP_GET_SEQ(p))) {
3371                     StreamTcpUpdateNextSeq(
3372                             ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
3373                 }
3374                 ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
3375             }
3376 
3377             StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
3378 
3379             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3380                 StreamTcpHandleTimestamp(ssn, p);
3381             }
3382 
3383             /* Update the next_seq, in case if we have missed the client
3384                packet and server has already received and acked it */
3385             if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
3386                 ssn->server.next_seq = TCP_GET_ACK(p);
3387 
3388             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
3389                     &ssn->client, p, pq);
3390 
3391             SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3392                     "%" PRIu32 "", ssn, ssn->client.next_seq,
3393                     ssn->server.last_ack);
3394         } else { /* implied to client */
3395             SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
3396                     "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3397                     TCP_GET_SEQ(p), TCP_GET_ACK(p));
3398             int retransmission = 0;
3399 
3400             if (SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq - 1) &&
3401                 SEQ_EQ(TCP_GET_ACK(p), ssn->client.last_ack)) {
3402                 SCLogDebug("ssn %p: retransmission", ssn);
3403                 retransmission = 1;
3404             } else if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
3405                 SCLogDebug("ssn %p: packet is retransmission", ssn);
3406                 retransmission = 1;
3407 
3408             } else if (SEQ_LT(TCP_GET_SEQ(p), ssn->server.next_seq) ||
3409                     SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + ssn->server.window)))
3410             {
3411                 SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ "
3412                         "%" PRIu32 " != %" PRIu32 " from stream", ssn,
3413                         TCP_GET_SEQ(p), ssn->server.next_seq);
3414                 StreamTcpSetEvent(p, STREAM_FIN2_FIN_WRONG_SEQ);
3415                 return -1;
3416             }
3417 
3418             if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
3419                 SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3420                 StreamTcpSetEvent(p, STREAM_FIN2_INVALID_ACK);
3421                 return -1;
3422             }
3423 
3424             if (!retransmission) {
3425                 StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
3426                 SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
3427 
3428                 ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
3429             }
3430 
3431             StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
3432 
3433             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3434                 StreamTcpHandleTimestamp(ssn, p);
3435             }
3436 
3437             /* Update the next_seq, in case if we have missed the client
3438                packet and server has already received and acked it */
3439             if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
3440                 ssn->client.next_seq = TCP_GET_ACK(p);
3441 
3442             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
3443                     &ssn->server, p, pq);
3444             SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3445                     "%" PRIu32 "", ssn, ssn->server.next_seq,
3446                     ssn->client.last_ack);
3447         }
3448 
3449     } else if (p->tcph->th_flags & TH_SYN) {
3450         SCLogDebug("ssn (%p): SYN pkt on FinWait2", ssn);
3451         StreamTcpSetEvent(p, STREAM_SHUTDOWN_SYN_RESEND);
3452         return -1;
3453 
3454     } else if (p->tcph->th_flags & TH_ACK) {
3455         if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3456             if (!StreamTcpValidateTimestamp(ssn, p))
3457                 return -1;
3458         }
3459 
3460         if (PKT_IS_TOSERVER(p)) {
3461             SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
3462                     "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3463                     TCP_GET_SEQ(p), TCP_GET_ACK(p));
3464             int retransmission = 0;
3465 
3466             if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
3467                 SCLogDebug("ssn %p: packet is retransmission", ssn);
3468                 retransmission = 1;
3469             }
3470 
3471             if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
3472                 SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3473                 StreamTcpSetEvent(p, STREAM_FIN2_INVALID_ACK);
3474                 return -1;
3475             }
3476 
3477             if (!retransmission) {
3478                 if (SEQ_LEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->client.next_win) ||
3479                         (ssn->flags & (STREAMTCP_FLAG_MIDSTREAM|STREAMTCP_FLAG_ASYNC)))
3480                 {
3481                     SCLogDebug("ssn %p: seq %"PRIu32" in window, ssn->client.next_win "
3482                             "%" PRIu32 "", ssn, TCP_GET_SEQ(p), ssn->client.next_win);
3483 
3484                 } else {
3485                     SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
3486                             " != %" PRIu32 " from stream", ssn,
3487                             TCP_GET_SEQ(p), ssn->client.next_seq);
3488                     StreamTcpSetEvent(p, STREAM_FIN2_ACK_WRONG_SEQ);
3489                     return -1;
3490                 }
3491 
3492                 ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
3493             }
3494 
3495             StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
3496 
3497             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3498                 StreamTcpHandleTimestamp(ssn, p);
3499             }
3500 
3501             if (SEQ_EQ(ssn->client.next_seq, TCP_GET_SEQ(p))) {
3502                 StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
3503             }
3504 
3505             StreamTcpSackUpdatePacket(&ssn->server, p);
3506 
3507             /* update next_win */
3508             StreamTcpUpdateNextWin(ssn, &ssn->server, (ssn->server.last_ack + ssn->server.window));
3509 
3510             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
3511                     &ssn->client, p, pq);
3512 
3513             SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3514                     "%" PRIu32 "", ssn, ssn->client.next_seq,
3515                     ssn->server.last_ack);
3516         } else { /* implied to client */
3517             SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
3518                     "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3519                     TCP_GET_SEQ(p), TCP_GET_ACK(p));
3520             int retransmission = 0;
3521 
3522             if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
3523                 SCLogDebug("ssn %p: packet is retransmission", ssn);
3524                 retransmission = 1;
3525             }
3526 
3527             if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
3528                 SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3529                 StreamTcpSetEvent(p, STREAM_FIN2_INVALID_ACK);
3530                 return -1;
3531             }
3532 
3533             if (!retransmission) {
3534                 if (SEQ_LEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->server.next_win) ||
3535                         (ssn->flags & (STREAMTCP_FLAG_MIDSTREAM|STREAMTCP_FLAG_ASYNC)))
3536                 {
3537                     SCLogDebug("ssn %p: seq %"PRIu32" in window, ssn->server.next_win "
3538                             "%" PRIu32 "", ssn, TCP_GET_SEQ(p), ssn->server.next_win);
3539                 } else {
3540                     SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
3541                             " != %" PRIu32 " from stream", ssn,
3542                             TCP_GET_SEQ(p), ssn->server.next_seq);
3543                     StreamTcpSetEvent(p, STREAM_FIN2_ACK_WRONG_SEQ);
3544                     return -1;
3545                 }
3546 
3547                 ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
3548             }
3549 
3550             StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
3551 
3552             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3553                 StreamTcpHandleTimestamp(ssn, p);
3554             }
3555 
3556             if (SEQ_EQ(ssn->server.next_seq, TCP_GET_SEQ(p))) {
3557                 StreamTcpUpdateNextSeq(ssn, &ssn->server, (ssn->server.next_seq + p->payload_len));
3558             }
3559 
3560             StreamTcpSackUpdatePacket(&ssn->client, p);
3561 
3562             /* update next_win */
3563             StreamTcpUpdateNextWin(ssn, &ssn->client, (ssn->client.last_ack + ssn->client.window));
3564 
3565             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
3566                     &ssn->server, p, pq);
3567 
3568             SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3569                     "%" PRIu32 "", ssn, ssn->server.next_seq,
3570                     ssn->client.last_ack);
3571         }
3572     } else {
3573         SCLogDebug("ssn %p: default case", ssn);
3574     }
3575 
3576     return 0;
3577 }
3578 
3579 /**
3580  *  \brief  Function to handle the TCP_CLOSING state. Upon arrival of ACK
3581  *          the connection goes to TCP_TIME_WAIT state. The state has been
3582  *          reached as both end application has been closed.
3583  *
3584  *  \param  tv      Thread Variable containig  input/output queue, cpu affinity
3585  *  \param  p       Packet which has to be handled in this TCP state.
3586  *  \param  stt     Strean Thread module registered to handle the stream handling
3587  */
3588 
StreamTcpPacketStateClosing(ThreadVars * tv,Packet * p,StreamTcpThread * stt,TcpSession * ssn,PacketQueueNoLock * pq)3589 static int StreamTcpPacketStateClosing(ThreadVars *tv, Packet *p,
3590         StreamTcpThread *stt, TcpSession *ssn, PacketQueueNoLock *pq)
3591 {
3592     if (ssn == NULL)
3593         return -1;
3594 
3595     if (p->tcph->th_flags & TH_RST) {
3596         if (!StreamTcpValidateRst(ssn, p))
3597             return -1;
3598 
3599         StreamTcpCloseSsnWithReset(p, ssn);
3600 
3601         if (PKT_IS_TOSERVER(p)) {
3602             if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
3603                 StreamTcpUpdateLastAck(ssn, &ssn->server,
3604                         StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
3605 
3606             StreamTcpUpdateLastAck(ssn, &ssn->client,
3607                     StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p)));
3608 
3609             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3610                 StreamTcpHandleTimestamp(ssn, p);
3611             }
3612 
3613             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
3614                     &ssn->client, p, pq);
3615         } else {
3616             if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
3617                 StreamTcpUpdateLastAck(ssn, &ssn->client,
3618                         StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
3619 
3620             StreamTcpUpdateLastAck(ssn, &ssn->server,
3621                     StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p)));
3622 
3623             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3624                 StreamTcpHandleTimestamp(ssn, p);
3625             }
3626 
3627             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
3628                     &ssn->server, p, pq);
3629         }
3630 
3631     } else if (p->tcph->th_flags & TH_SYN) {
3632         SCLogDebug("ssn (%p): SYN pkt on Closing", ssn);
3633         StreamTcpSetEvent(p, STREAM_SHUTDOWN_SYN_RESEND);
3634         return -1;
3635 
3636     } else if (p->tcph->th_flags & TH_ACK) {
3637         if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3638             if (!StreamTcpValidateTimestamp(ssn, p))
3639                 return -1;
3640         }
3641 
3642         if (PKT_IS_TOSERVER(p)) {
3643             SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
3644                     "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3645                     TCP_GET_SEQ(p), TCP_GET_ACK(p));
3646             int retransmission = 0;
3647             if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
3648                 SCLogDebug("ssn %p: packet is retransmission", ssn);
3649                 retransmission = 1;
3650             }
3651 
3652             if (TCP_GET_SEQ(p) != ssn->client.next_seq) {
3653                 SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
3654                         " != %" PRIu32 " from stream", ssn,
3655                         TCP_GET_SEQ(p), ssn->client.next_seq);
3656                 StreamTcpSetEvent(p, STREAM_CLOSING_ACK_WRONG_SEQ);
3657                 return -1;
3658             }
3659 
3660             if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
3661                 SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3662                 StreamTcpSetEvent(p, STREAM_CLOSING_INVALID_ACK);
3663                 return -1;
3664             }
3665 
3666             if (!retransmission) {
3667                 StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
3668                 SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
3669 
3670                 ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
3671             }
3672 
3673             StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
3674 
3675             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3676                 StreamTcpHandleTimestamp(ssn, p);
3677             }
3678             /* Update the next_seq, in case if we have missed the client
3679                packet and server has already received and acked it */
3680             if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
3681                 ssn->server.next_seq = TCP_GET_ACK(p);
3682 
3683             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
3684                     &ssn->client, p, pq);
3685             SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3686                     "%" PRIu32 "", ssn, ssn->client.next_seq,
3687                     ssn->server.last_ack);
3688         } else { /* implied to client */
3689             SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
3690                     "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3691                     TCP_GET_SEQ(p), TCP_GET_ACK(p));
3692             int retransmission = 0;
3693             if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
3694                 SCLogDebug("ssn %p: packet is retransmission", ssn);
3695                 retransmission = 1;
3696             }
3697 
3698             if (TCP_GET_SEQ(p) != ssn->server.next_seq) {
3699                 SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
3700                         " != %" PRIu32 " from stream", ssn,
3701                         TCP_GET_SEQ(p), ssn->server.next_seq);
3702                 StreamTcpSetEvent(p, STREAM_CLOSING_ACK_WRONG_SEQ);
3703                 return -1;
3704             }
3705 
3706             if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
3707                 SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3708                 StreamTcpSetEvent(p, STREAM_CLOSING_INVALID_ACK);
3709                 return -1;
3710             }
3711 
3712             if (!retransmission) {
3713                 StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
3714                 SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
3715 
3716                 ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
3717             }
3718 
3719             StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
3720 
3721             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3722                 StreamTcpHandleTimestamp(ssn, p);
3723             }
3724 
3725             /* Update the next_seq, in case if we have missed the client
3726                packet and server has already received and acked it */
3727             if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
3728                 ssn->client.next_seq = TCP_GET_ACK(p);
3729 
3730             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
3731                     &ssn->server, p, pq);
3732             SCLogDebug("StreamTcpPacketStateClosing (%p): =+ next SEQ "
3733                     "%" PRIu32 ", last ACK %" PRIu32 "", ssn,
3734                     ssn->server.next_seq, ssn->client.last_ack);
3735         }
3736     } else {
3737         SCLogDebug("ssn %p: default case", ssn);
3738     }
3739 
3740     return 0;
3741 }
3742 
3743 /**
3744  *  \brief  Function to handle the TCP_CLOSE_WAIT state. Upon arrival of FIN
3745  *          packet from server the connection goes to TCP_LAST_ACK state.
3746  *          The state is possible only for server host.
3747  *
3748  *  \param  tv      Thread Variable containig  input/output queue, cpu affinity
3749  *  \param  p       Packet which has to be handled in this TCP state.
3750  *  \param  stt     Strean Thread module registered to handle the stream handling
3751  */
3752 
StreamTcpPacketStateCloseWait(ThreadVars * tv,Packet * p,StreamTcpThread * stt,TcpSession * ssn,PacketQueueNoLock * pq)3753 static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p,
3754         StreamTcpThread *stt, TcpSession *ssn, PacketQueueNoLock *pq)
3755 {
3756     SCEnter();
3757 
3758     if (ssn == NULL) {
3759         SCReturnInt(-1);
3760     }
3761 
3762     if (PKT_IS_TOCLIENT(p)) {
3763         SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
3764                 "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3765                 TCP_GET_SEQ(p), TCP_GET_ACK(p));
3766     } else {
3767         SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
3768                 "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3769                 TCP_GET_SEQ(p), TCP_GET_ACK(p));
3770     }
3771 
3772     if (p->tcph->th_flags & TH_RST) {
3773         if (!StreamTcpValidateRst(ssn, p))
3774             return -1;
3775 
3776         StreamTcpCloseSsnWithReset(p, ssn);
3777 
3778         if (PKT_IS_TOSERVER(p)) {
3779             if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
3780                 StreamTcpUpdateLastAck(ssn, &ssn->server,
3781                         StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
3782 
3783             StreamTcpUpdateLastAck(ssn, &ssn->client,
3784                     StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p)));
3785 
3786             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3787                 StreamTcpHandleTimestamp(ssn, p);
3788             }
3789 
3790             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
3791                     &ssn->client, p, pq);
3792         } else {
3793             if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
3794                 StreamTcpUpdateLastAck(ssn, &ssn->client,
3795                         StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
3796 
3797             StreamTcpUpdateLastAck(ssn, &ssn->server,
3798                     StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p)));
3799 
3800             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3801                 StreamTcpHandleTimestamp(ssn, p);
3802             }
3803 
3804             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
3805                     &ssn->server, p, pq);
3806         }
3807 
3808     } else if (p->tcph->th_flags & TH_FIN) {
3809         if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3810             if (!StreamTcpValidateTimestamp(ssn, p))
3811                 SCReturnInt(-1);
3812         }
3813 
3814         if (PKT_IS_TOSERVER(p)) {
3815             SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
3816                     "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3817                     TCP_GET_SEQ(p), TCP_GET_ACK(p));
3818 
3819             int retransmission = 0;
3820             if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
3821                 SCLogDebug("ssn %p: packet is retransmission", ssn);
3822                 retransmission = 1;
3823             }
3824 
3825             if (!retransmission) {
3826                 if (SEQ_LT(TCP_GET_SEQ(p), ssn->client.next_seq) ||
3827                         SEQ_GT(TCP_GET_SEQ(p), (ssn->client.last_ack + ssn->client.window)))
3828                 {
3829                     SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
3830                             " != %" PRIu32 " from stream", ssn,
3831                             TCP_GET_SEQ(p), ssn->client.next_seq);
3832                     StreamTcpSetEvent(p, STREAM_CLOSEWAIT_FIN_OUT_OF_WINDOW);
3833                     SCReturnInt(-1);
3834                 }
3835             }
3836 
3837             if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
3838                 SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3839                 StreamTcpSetEvent(p, STREAM_CLOSEWAIT_INVALID_ACK);
3840                 SCReturnInt(-1);
3841             }
3842 
3843             /* don't update to LAST_ACK here as we want a toclient FIN for that */
3844 
3845             if (!retransmission)
3846                 ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
3847 
3848             StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
3849 
3850             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3851                 StreamTcpHandleTimestamp(ssn, p);
3852             }
3853 
3854             /* Update the next_seq, in case if we have missed the client
3855                packet and server has already received and acked it */
3856             if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
3857                 ssn->server.next_seq = TCP_GET_ACK(p);
3858 
3859             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
3860                     &ssn->client, p, pq);
3861             SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3862                     "%" PRIu32 "", ssn, ssn->client.next_seq,
3863                     ssn->server.last_ack);
3864         } else {
3865             SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
3866                     "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3867                     TCP_GET_SEQ(p), TCP_GET_ACK(p));
3868 
3869             int retransmission = 0;
3870             if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
3871                 SCLogDebug("ssn %p: packet is retransmission", ssn);
3872                 retransmission = 1;
3873             }
3874 
3875             if (!retransmission) {
3876                 if (SEQ_LT(TCP_GET_SEQ(p), ssn->server.next_seq) ||
3877                         SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + ssn->server.window)))
3878                 {
3879                     SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
3880                             " != %" PRIu32 " from stream", ssn,
3881                             TCP_GET_SEQ(p), ssn->server.next_seq);
3882                     StreamTcpSetEvent(p, STREAM_CLOSEWAIT_FIN_OUT_OF_WINDOW);
3883                     SCReturnInt(-1);
3884                 }
3885             }
3886 
3887             if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
3888                 SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3889                 StreamTcpSetEvent(p, STREAM_CLOSEWAIT_INVALID_ACK);
3890                 SCReturnInt(-1);
3891             }
3892 
3893             if (!retransmission) {
3894                 StreamTcpPacketSetState(p, ssn, TCP_LAST_ACK);
3895                 SCLogDebug("ssn %p: state changed to TCP_LAST_ACK", ssn);
3896 
3897                 ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
3898             }
3899 
3900             StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
3901 
3902             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3903                 StreamTcpHandleTimestamp(ssn, p);
3904             }
3905 
3906             /* Update the next_seq, in case if we have missed the client
3907                packet and server has already received and acked it */
3908             if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
3909                 ssn->client.next_seq = TCP_GET_ACK(p);
3910 
3911             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
3912                     &ssn->server, p, pq);
3913             SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3914                     "%" PRIu32 "", ssn, ssn->server.next_seq,
3915                     ssn->client.last_ack);
3916         }
3917 
3918     } else if (p->tcph->th_flags & TH_SYN) {
3919         SCLogDebug("ssn (%p): SYN pkt on CloseWait", ssn);
3920         StreamTcpSetEvent(p, STREAM_SHUTDOWN_SYN_RESEND);
3921         SCReturnInt(-1);
3922 
3923     } else if (p->tcph->th_flags & TH_ACK) {
3924         if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3925             if (!StreamTcpValidateTimestamp(ssn, p))
3926                 SCReturnInt(-1);
3927         }
3928 
3929         if (PKT_IS_TOSERVER(p)) {
3930             SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
3931                     "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3932                     TCP_GET_SEQ(p), TCP_GET_ACK(p));
3933 
3934             int retransmission = 0;
3935             if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
3936                 SCLogDebug("ssn %p: packet is retransmission", ssn);
3937                 retransmission = 1;
3938             }
3939 
3940             if (p->payload_len > 0 && (SEQ_LEQ((TCP_GET_SEQ(p) + p->payload_len), ssn->client.last_ack))) {
3941                 SCLogDebug("ssn %p: -> retransmission", ssn);
3942                 StreamTcpSetEvent(p, STREAM_CLOSEWAIT_PKT_BEFORE_LAST_ACK);
3943                 SCReturnInt(-1);
3944 
3945             } else if (SEQ_GT(TCP_GET_SEQ(p), (ssn->client.last_ack + ssn->client.window)))
3946             {
3947                 SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
3948                         " != %" PRIu32 " from stream", ssn,
3949                         TCP_GET_SEQ(p), ssn->client.next_seq);
3950                 StreamTcpSetEvent(p, STREAM_CLOSEWAIT_ACK_OUT_OF_WINDOW);
3951                 SCReturnInt(-1);
3952             }
3953 
3954             if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
3955                 SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3956                 StreamTcpSetEvent(p, STREAM_CLOSEWAIT_INVALID_ACK);
3957                 SCReturnInt(-1);
3958             }
3959 
3960             if (!retransmission) {
3961                 ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
3962             }
3963 
3964             StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
3965 
3966             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3967                 StreamTcpHandleTimestamp(ssn, p);
3968             }
3969 
3970             /* Update the next_seq, in case if we have missed the client
3971                packet and server has already received and acked it */
3972             if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
3973                 ssn->server.next_seq = TCP_GET_ACK(p);
3974 
3975             if (SEQ_EQ(TCP_GET_SEQ(p),ssn->client.next_seq))
3976                 StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
3977 
3978             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
3979                     &ssn->client, p, pq);
3980             SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3981                     "%" PRIu32 "", ssn, ssn->client.next_seq,
3982                     ssn->server.last_ack);
3983         } else {
3984             SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
3985                     "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3986                     TCP_GET_SEQ(p), TCP_GET_ACK(p));
3987             int retransmission = 0;
3988             if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
3989                 SCLogDebug("ssn %p: packet is retransmission", ssn);
3990                 retransmission = 1;
3991             }
3992 
3993             if (p->payload_len > 0 && (SEQ_LEQ((TCP_GET_SEQ(p) + p->payload_len), ssn->server.last_ack))) {
3994                 SCLogDebug("ssn %p: -> retransmission", ssn);
3995                 StreamTcpSetEvent(p, STREAM_CLOSEWAIT_PKT_BEFORE_LAST_ACK);
3996                 SCReturnInt(-1);
3997 
3998             } else if (SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + ssn->server.window)))
3999             {
4000                 SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
4001                         " != %" PRIu32 " from stream", ssn,
4002                         TCP_GET_SEQ(p), ssn->server.next_seq);
4003                 StreamTcpSetEvent(p, STREAM_CLOSEWAIT_ACK_OUT_OF_WINDOW);
4004                 SCReturnInt(-1);
4005             }
4006 
4007             if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
4008                 SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4009                 StreamTcpSetEvent(p, STREAM_CLOSEWAIT_INVALID_ACK);
4010                 SCReturnInt(-1);
4011             }
4012 
4013             if (!retransmission) {
4014                 ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
4015             }
4016 
4017             StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
4018 
4019             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4020                 StreamTcpHandleTimestamp(ssn, p);
4021             }
4022 
4023             /* Update the next_seq, in case if we have missed the client
4024                packet and server has already received and acked it */
4025             if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
4026                 ssn->client.next_seq = TCP_GET_ACK(p);
4027 
4028             if (SEQ_EQ(TCP_GET_SEQ(p),ssn->server.next_seq))
4029                 StreamTcpUpdateNextSeq(ssn, &ssn->server, (ssn->server.next_seq + p->payload_len));
4030 
4031             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
4032                     &ssn->server, p, pq);
4033             SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
4034                     "%" PRIu32 "", ssn, ssn->server.next_seq,
4035                     ssn->client.last_ack);
4036         }
4037 
4038     } else {
4039         SCLogDebug("ssn %p: default case", ssn);
4040     }
4041     SCReturnInt(0);
4042 }
4043 
4044 /**
4045  *  \brief  Function to handle the TCP_LAST_ACK state. Upon arrival of ACK
4046  *          the connection goes to TCP_CLOSED state and stream memory is
4047  *          returned back to pool. The state is possible only for server host.
4048  *
4049  *  \param  tv      Thread Variable containig  input/output queue, cpu affinity
4050  *  \param  p       Packet which has to be handled in this TCP state.
4051  *  \param  stt     Strean Thread module registered to handle the stream handling
4052  */
4053 
StreamTcpPacketStateLastAck(ThreadVars * tv,Packet * p,StreamTcpThread * stt,TcpSession * ssn,PacketQueueNoLock * pq)4054 static int StreamTcpPacketStateLastAck(ThreadVars *tv, Packet *p,
4055         StreamTcpThread *stt, TcpSession *ssn, PacketQueueNoLock *pq)
4056 {
4057     if (ssn == NULL)
4058         return -1;
4059 
4060     if (p->tcph->th_flags & TH_RST) {
4061         if (!StreamTcpValidateRst(ssn, p))
4062             return -1;
4063 
4064         StreamTcpCloseSsnWithReset(p, ssn);
4065 
4066         if (PKT_IS_TOSERVER(p)) {
4067             if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
4068                 StreamTcpUpdateLastAck(ssn, &ssn->server,
4069                         StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
4070 
4071             StreamTcpUpdateLastAck(ssn, &ssn->client,
4072                     StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p)));
4073 
4074             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4075                 StreamTcpHandleTimestamp(ssn, p);
4076             }
4077 
4078             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
4079                     &ssn->client, p, pq);
4080         } else {
4081             if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
4082                 StreamTcpUpdateLastAck(ssn, &ssn->client,
4083                         StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
4084 
4085             StreamTcpUpdateLastAck(ssn, &ssn->server,
4086                     StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p)));
4087 
4088             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4089                 StreamTcpHandleTimestamp(ssn, p);
4090             }
4091 
4092             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
4093                     &ssn->server, p, pq);
4094         }
4095 
4096     } else if (p->tcph->th_flags & TH_FIN) {
4097         /** \todo */
4098         SCLogDebug("ssn (%p): FIN pkt on LastAck", ssn);
4099 
4100     } else if (p->tcph->th_flags & TH_SYN) {
4101         SCLogDebug("ssn (%p): SYN pkt on LastAck", ssn);
4102         StreamTcpSetEvent(p, STREAM_SHUTDOWN_SYN_RESEND);
4103         return -1;
4104 
4105     } else if (p->tcph->th_flags & TH_ACK) {
4106         if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4107             if (!StreamTcpValidateTimestamp(ssn, p))
4108                 return -1;
4109         }
4110 
4111         if (PKT_IS_TOSERVER(p)) {
4112             SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
4113                     "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
4114                     TCP_GET_SEQ(p), TCP_GET_ACK(p));
4115 
4116             int retransmission = 0;
4117             if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
4118                 SCLogDebug("ssn %p: packet is retransmission", ssn);
4119                 retransmission = 1;
4120             }
4121 
4122             if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
4123                 SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4124                 StreamTcpSetEvent(p, STREAM_LASTACK_INVALID_ACK);
4125                 SCReturnInt(-1);
4126             }
4127 
4128             if (!retransmission) {
4129                 if (SEQ_LT(TCP_GET_SEQ(p), ssn->client.next_seq)) {
4130                     SCLogDebug("ssn %p: not updating state as packet is before next_seq", ssn);
4131                 } else if (TCP_GET_SEQ(p) != ssn->client.next_seq && TCP_GET_SEQ(p) != ssn->client.next_seq + 1) {
4132                     SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
4133                             " != %" PRIu32 " from stream", ssn,
4134                             TCP_GET_SEQ(p), ssn->client.next_seq);
4135                     StreamTcpSetEvent(p, STREAM_LASTACK_ACK_WRONG_SEQ);
4136                     return -1;
4137                 } else {
4138                     StreamTcpPacketSetState(p, ssn, TCP_CLOSED);
4139                     SCLogDebug("ssn %p: state changed to TCP_CLOSED", ssn);
4140 
4141                 }
4142                 ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
4143             }
4144 
4145             StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
4146 
4147             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4148                 StreamTcpHandleTimestamp(ssn, p);
4149             }
4150 
4151             /* Update the next_seq, in case if we have missed the client
4152                packet and server has already received and acked it */
4153             if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
4154                 ssn->server.next_seq = TCP_GET_ACK(p);
4155 
4156             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
4157                     &ssn->client, p, pq);
4158             SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
4159                     "%" PRIu32 "", ssn, ssn->client.next_seq,
4160                     ssn->server.last_ack);
4161         }
4162     } else {
4163         SCLogDebug("ssn %p: default case", ssn);
4164     }
4165 
4166     return 0;
4167 }
4168 
4169 /**
4170  *  \brief  Function to handle the TCP_TIME_WAIT state. Upon arrival of ACK
4171  *          the connection goes to TCP_CLOSED state and stream memory is
4172  *          returned back to pool.
4173  *
4174  *  \param  tv      Thread Variable containig  input/output queue, cpu affinity
4175  *  \param  p       Packet which has to be handled in this TCP state.
4176  *  \param  stt     Strean Thread module registered to handle the stream handling
4177  */
4178 
StreamTcpPacketStateTimeWait(ThreadVars * tv,Packet * p,StreamTcpThread * stt,TcpSession * ssn,PacketQueueNoLock * pq)4179 static int StreamTcpPacketStateTimeWait(ThreadVars *tv, Packet *p,
4180         StreamTcpThread *stt, TcpSession *ssn, PacketQueueNoLock *pq)
4181 {
4182     if (ssn == NULL)
4183         return -1;
4184 
4185     if (p->tcph->th_flags & TH_RST) {
4186         if (!StreamTcpValidateRst(ssn, p))
4187             return -1;
4188 
4189         StreamTcpCloseSsnWithReset(p, ssn);
4190 
4191         if (PKT_IS_TOSERVER(p)) {
4192             if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
4193                 StreamTcpUpdateLastAck(ssn, &ssn->server,
4194                         StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
4195 
4196             StreamTcpUpdateLastAck(ssn, &ssn->client,
4197                     StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p)));
4198 
4199             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4200                 StreamTcpHandleTimestamp(ssn, p);
4201             }
4202 
4203             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
4204                     &ssn->client, p, pq);
4205         } else {
4206             if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
4207                 StreamTcpUpdateLastAck(ssn, &ssn->client,
4208                         StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
4209 
4210             StreamTcpUpdateLastAck(ssn, &ssn->server,
4211                     StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p)));
4212 
4213             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4214                 StreamTcpHandleTimestamp(ssn, p);
4215             }
4216 
4217             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
4218                     &ssn->server, p, pq);
4219         }
4220 
4221     } else if (p->tcph->th_flags & TH_FIN) {
4222         /** \todo */
4223 
4224     } else if (p->tcph->th_flags & TH_SYN) {
4225         SCLogDebug("ssn (%p): SYN pkt on TimeWait", ssn);
4226         StreamTcpSetEvent(p, STREAM_SHUTDOWN_SYN_RESEND);
4227         return -1;
4228 
4229     } else if (p->tcph->th_flags & TH_ACK) {
4230         if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4231             if (!StreamTcpValidateTimestamp(ssn, p))
4232                 return -1;
4233         }
4234 
4235         if (PKT_IS_TOSERVER(p)) {
4236             SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
4237                     "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
4238                     TCP_GET_SEQ(p), TCP_GET_ACK(p));
4239             int retransmission = 0;
4240             if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
4241                 SCLogDebug("ssn %p: packet is retransmission", ssn);
4242                 retransmission = 1;
4243 
4244             } else if (TCP_GET_SEQ(p) != ssn->client.next_seq && TCP_GET_SEQ(p) != ssn->client.next_seq+1) {
4245                 SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
4246                         " != %" PRIu32 " from stream", ssn,
4247                         TCP_GET_SEQ(p), ssn->client.next_seq);
4248                 StreamTcpSetEvent(p, STREAM_TIMEWAIT_ACK_WRONG_SEQ);
4249                 return -1;
4250             }
4251 
4252             if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
4253                 SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4254                 StreamTcpSetEvent(p, STREAM_TIMEWAIT_INVALID_ACK);
4255                 SCReturnInt(-1);
4256             }
4257 
4258             if (!retransmission) {
4259                 StreamTcpPacketSetState(p, ssn, TCP_CLOSED);
4260                 SCLogDebug("ssn %p: state changed to TCP_CLOSED", ssn);
4261 
4262                 ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
4263             }
4264 
4265             StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
4266 
4267             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4268                 StreamTcpHandleTimestamp(ssn, p);
4269             }
4270 
4271             /* Update the next_seq, in case if we have missed the client
4272                packet and server has already received and acked it */
4273             if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
4274                 ssn->server.next_seq = TCP_GET_ACK(p);
4275 
4276             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
4277                     &ssn->client, p, pq);
4278             SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
4279                     "%" PRIu32 "", ssn, ssn->client.next_seq,
4280                     ssn->server.last_ack);
4281         } else {
4282             SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
4283                     "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
4284                     TCP_GET_SEQ(p), TCP_GET_ACK(p));
4285             int retransmission = 0;
4286             if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
4287                 SCLogDebug("ssn %p: packet is retransmission", ssn);
4288                 retransmission = 1;
4289             } else if (TCP_GET_SEQ(p) != ssn->server.next_seq && TCP_GET_SEQ(p) != ssn->server.next_seq+1) {
4290                 if (p->payload_len > 0 && TCP_GET_SEQ(p) == ssn->server.last_ack) {
4291                     SCLogDebug("ssn %p: -> retransmission", ssn);
4292                     SCReturnInt(0);
4293                 } else {
4294                     SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
4295                             " != %" PRIu32 " from stream", ssn,
4296                             TCP_GET_SEQ(p), ssn->server.next_seq);
4297                     StreamTcpSetEvent(p, STREAM_TIMEWAIT_ACK_WRONG_SEQ);
4298                     return -1;
4299                 }
4300             }
4301 
4302             if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
4303                 SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4304                 StreamTcpSetEvent(p, STREAM_TIMEWAIT_INVALID_ACK);
4305                 SCReturnInt(-1);
4306             }
4307 
4308             if (!retransmission) {
4309                 StreamTcpPacketSetState(p, ssn, TCP_CLOSED);
4310                 SCLogDebug("ssn %p: state changed to TCP_CLOSED", ssn);
4311 
4312                 ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
4313             }
4314 
4315             StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
4316 
4317             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4318                 StreamTcpHandleTimestamp(ssn, p);
4319             }
4320 
4321             /* Update the next_seq, in case if we have missed the client
4322                packet and server has already received and acked it */
4323             if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
4324                 ssn->client.next_seq = TCP_GET_ACK(p);
4325 
4326             StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
4327                     &ssn->server, p, pq);
4328             SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
4329                     "%" PRIu32 "", ssn, ssn->server.next_seq,
4330                     ssn->client.last_ack);
4331         }
4332 
4333     } else {
4334         SCLogDebug("ssn %p: default case", ssn);
4335     }
4336 
4337     return 0;
4338 }
4339 
StreamTcpPacketStateClosed(ThreadVars * tv,Packet * p,StreamTcpThread * stt,TcpSession * ssn,PacketQueueNoLock * pq)4340 static int StreamTcpPacketStateClosed(ThreadVars *tv, Packet *p,
4341         StreamTcpThread *stt, TcpSession *ssn, PacketQueueNoLock *pq)
4342 {
4343     if (ssn == NULL)
4344         return -1;
4345 
4346     if (p->tcph->th_flags & TH_RST) {
4347         SCLogDebug("RST on closed state");
4348         return 0;
4349     }
4350 
4351     TcpStream *stream = NULL, *ostream = NULL;
4352     if (PKT_IS_TOSERVER(p)) {
4353         stream = &ssn->client;
4354         ostream = &ssn->server;
4355     } else {
4356         stream = &ssn->server;
4357         ostream = &ssn->client;
4358     }
4359 
4360     SCLogDebug("stream %s ostream %s",
4361             stream->flags & STREAMTCP_STREAM_FLAG_RST_RECV?"true":"false",
4362             ostream->flags & STREAMTCP_STREAM_FLAG_RST_RECV ? "true":"false");
4363 
4364     /* if we've seen a RST on our direction, but not on the other
4365      * see if we perhaps need to continue processing anyway. */
4366     if ((stream->flags & STREAMTCP_STREAM_FLAG_RST_RECV) == 0) {
4367         if (ostream->flags & STREAMTCP_STREAM_FLAG_RST_RECV) {
4368             if (StreamTcpStateDispatch(tv, p, stt, ssn, &stt->pseudo_queue, ssn->pstate) < 0)
4369                 return -1;
4370             /* if state is still "closed", it wasn't updated by our dispatch. */
4371             if (ssn->state == TCP_CLOSED)
4372                 ssn->state = ssn->pstate;
4373         }
4374     }
4375     return 0;
4376 }
4377 
StreamTcpPacketCheckPostRst(TcpSession * ssn,Packet * p)4378 static void StreamTcpPacketCheckPostRst(TcpSession *ssn, Packet *p)
4379 {
4380     if (p->flags & PKT_PSEUDO_STREAM_END) {
4381         return;
4382     }
4383     /* more RSTs are not unusual */
4384     if ((p->tcph->th_flags & (TH_RST)) != 0) {
4385         return;
4386     }
4387 
4388     TcpStream *ostream = NULL;
4389     if (PKT_IS_TOSERVER(p)) {
4390         ostream = &ssn->server;
4391     } else {
4392         ostream = &ssn->client;
4393     }
4394 
4395     if (ostream->flags & STREAMTCP_STREAM_FLAG_RST_RECV) {
4396         SCLogDebug("regular packet %"PRIu64" from same sender as "
4397                 "the previous RST. Looks like it injected!", p->pcap_cnt);
4398         ostream->flags &= ~STREAMTCP_STREAM_FLAG_RST_RECV;
4399         ssn->flags &= ~STREAMTCP_FLAG_CLOSED_BY_RST;
4400         StreamTcpSetEvent(p, STREAM_SUSPECTED_RST_INJECT);
4401         return;
4402     }
4403     return;
4404 }
4405 
4406 /**
4407  *  \retval 1 packet is a keep alive pkt
4408  *  \retval 0 packet is not a keep alive pkt
4409  */
StreamTcpPacketIsKeepAlive(TcpSession * ssn,Packet * p)4410 static int StreamTcpPacketIsKeepAlive(TcpSession *ssn, Packet *p)
4411 {
4412     TcpStream *stream = NULL, *ostream = NULL;
4413     uint32_t seq;
4414     uint32_t ack;
4415 
4416     if (p->flags & PKT_PSEUDO_STREAM_END)
4417         return 0;
4418 
4419     /*
4420        rfc 1122:
4421        An implementation SHOULD send a keep-alive segment with no
4422        data; however, it MAY be configurable to send a keep-alive
4423        segment containing one garbage octet, for compatibility with
4424        erroneous TCP implementations.
4425      */
4426     if (p->payload_len > 1)
4427         return 0;
4428 
4429     if ((p->tcph->th_flags & (TH_SYN|TH_FIN|TH_RST)) != 0) {
4430         return 0;
4431     }
4432 
4433     if (PKT_IS_TOSERVER(p)) {
4434         stream = &ssn->client;
4435         ostream = &ssn->server;
4436     } else {
4437         stream = &ssn->server;
4438         ostream = &ssn->client;
4439     }
4440 
4441     seq = TCP_GET_SEQ(p);
4442     ack = TCP_GET_ACK(p);
4443 
4444     if (ack == ostream->last_ack && seq == (stream->next_seq - 1)) {
4445         SCLogDebug("packet is TCP keep-alive: %"PRIu64, p->pcap_cnt);
4446         stream->flags |= STREAMTCP_STREAM_FLAG_KEEPALIVE;
4447         return 1;
4448     }
4449     SCLogDebug("seq %u (%u), ack %u (%u)", seq,  (stream->next_seq - 1), ack, ostream->last_ack);
4450     return 0;
4451 }
4452 
4453 /**
4454  *  \retval 1 packet is a keep alive ACK pkt
4455  *  \retval 0 packet is not a keep alive ACK pkt
4456  */
StreamTcpPacketIsKeepAliveACK(TcpSession * ssn,Packet * p)4457 static int StreamTcpPacketIsKeepAliveACK(TcpSession *ssn, Packet *p)
4458 {
4459     TcpStream *stream = NULL, *ostream = NULL;
4460     uint32_t seq;
4461     uint32_t ack;
4462     uint32_t pkt_win;
4463 
4464     if (p->flags & PKT_PSEUDO_STREAM_END)
4465         return 0;
4466     /* should get a normal ACK to a Keep Alive */
4467     if (p->payload_len > 0)
4468         return 0;
4469 
4470     if ((p->tcph->th_flags & (TH_SYN|TH_FIN|TH_RST)) != 0)
4471         return 0;
4472 
4473     if (TCP_GET_WINDOW(p) == 0)
4474         return 0;
4475 
4476     if (PKT_IS_TOSERVER(p)) {
4477         stream = &ssn->client;
4478         ostream = &ssn->server;
4479     } else {
4480         stream = &ssn->server;
4481         ostream = &ssn->client;
4482     }
4483 
4484     seq = TCP_GET_SEQ(p);
4485     ack = TCP_GET_ACK(p);
4486 
4487     pkt_win = TCP_GET_WINDOW(p) << ostream->wscale;
4488     if (pkt_win != ostream->window)
4489         return 0;
4490 
4491     if ((ostream->flags & STREAMTCP_STREAM_FLAG_KEEPALIVE) && ack == ostream->last_ack && seq == stream->next_seq) {
4492         SCLogDebug("packet is TCP keep-aliveACK: %"PRIu64, p->pcap_cnt);
4493         ostream->flags &= ~STREAMTCP_STREAM_FLAG_KEEPALIVE;
4494         return 1;
4495     }
4496     SCLogDebug("seq %u (%u), ack %u (%u) FLAG_KEEPALIVE: %s", seq, stream->next_seq, ack, ostream->last_ack,
4497             ostream->flags & STREAMTCP_STREAM_FLAG_KEEPALIVE ? "set" : "not set");
4498     return 0;
4499 }
4500 
StreamTcpClearKeepAliveFlag(TcpSession * ssn,Packet * p)4501 static void StreamTcpClearKeepAliveFlag(TcpSession *ssn, Packet *p)
4502 {
4503     TcpStream *stream = NULL;
4504 
4505     if (p->flags & PKT_PSEUDO_STREAM_END)
4506         return;
4507 
4508     if (PKT_IS_TOSERVER(p)) {
4509         stream = &ssn->client;
4510     } else {
4511         stream = &ssn->server;
4512     }
4513 
4514     if (stream->flags & STREAMTCP_STREAM_FLAG_KEEPALIVE) {
4515         stream->flags &= ~STREAMTCP_STREAM_FLAG_KEEPALIVE;
4516         SCLogDebug("FLAG_KEEPALIVE cleared");
4517     }
4518 }
4519 
4520 /**
4521  *  \retval 1 packet is a window update pkt
4522  *  \retval 0 packet is not a window update pkt
4523  */
StreamTcpPacketIsWindowUpdate(TcpSession * ssn,Packet * p)4524 static int StreamTcpPacketIsWindowUpdate(TcpSession *ssn, Packet *p)
4525 {
4526     TcpStream *stream = NULL, *ostream = NULL;
4527     uint32_t seq;
4528     uint32_t ack;
4529     uint32_t pkt_win;
4530 
4531     if (p->flags & PKT_PSEUDO_STREAM_END)
4532         return 0;
4533 
4534     if (ssn->state < TCP_ESTABLISHED)
4535         return 0;
4536 
4537     if (p->payload_len > 0)
4538         return 0;
4539 
4540     if ((p->tcph->th_flags & (TH_SYN|TH_FIN|TH_RST)) != 0)
4541         return 0;
4542 
4543     if (TCP_GET_WINDOW(p) == 0)
4544         return 0;
4545 
4546     if (PKT_IS_TOSERVER(p)) {
4547         stream = &ssn->client;
4548         ostream = &ssn->server;
4549     } else {
4550         stream = &ssn->server;
4551         ostream = &ssn->client;
4552     }
4553 
4554     seq = TCP_GET_SEQ(p);
4555     ack = TCP_GET_ACK(p);
4556 
4557     pkt_win = TCP_GET_WINDOW(p) << ostream->wscale;
4558     if (pkt_win == ostream->window)
4559         return 0;
4560 
4561     if (ack == ostream->last_ack && seq == stream->next_seq) {
4562         SCLogDebug("packet is TCP window update: %"PRIu64, p->pcap_cnt);
4563         return 1;
4564     }
4565     SCLogDebug("seq %u (%u), ack %u (%u)", seq, stream->next_seq, ack, ostream->last_ack);
4566     return 0;
4567 }
4568 
4569 /**
4570  *  Try to detect whether a packet is a valid FIN 4whs final ack.
4571  *
4572  */
StreamTcpPacketIsFinShutdownAck(TcpSession * ssn,Packet * p)4573 static int StreamTcpPacketIsFinShutdownAck(TcpSession *ssn, Packet *p)
4574 {
4575     TcpStream *stream = NULL, *ostream = NULL;
4576     uint32_t seq;
4577     uint32_t ack;
4578 
4579     if (p->flags & PKT_PSEUDO_STREAM_END)
4580         return 0;
4581     if (!(ssn->state == TCP_TIME_WAIT || ssn->state == TCP_CLOSE_WAIT || ssn->state == TCP_LAST_ACK))
4582         return 0;
4583     if (p->tcph->th_flags != TH_ACK)
4584         return 0;
4585     if (p->payload_len != 0)
4586         return 0;
4587 
4588     if (PKT_IS_TOSERVER(p)) {
4589         stream = &ssn->client;
4590         ostream = &ssn->server;
4591     } else {
4592         stream = &ssn->server;
4593         ostream = &ssn->client;
4594     }
4595 
4596     seq = TCP_GET_SEQ(p);
4597     ack = TCP_GET_ACK(p);
4598 
4599     SCLogDebug("%"PRIu64", seq %u ack %u stream->next_seq %u ostream->next_seq %u",
4600             p->pcap_cnt, seq, ack, stream->next_seq, ostream->next_seq);
4601 
4602     if (SEQ_EQ(stream->next_seq + 1, seq) && SEQ_EQ(ack, ostream->next_seq + 1)) {
4603         return 1;
4604     }
4605     return 0;
4606 }
4607 
4608 /**
4609  *  Try to detect packets doing bad window updates
4610  *
4611  *  See bug 1238.
4612  *
4613  *  Find packets that are unexpected, and shrink the window to the point
4614  *  where the packets we do expect are rejected for being out of window.
4615  *
4616  *  The logic we use here is:
4617  *  - packet seq > next_seq
4618  *  - packet ack > next_seq (packet acks unseen data)
4619  *  - packet shrinks window more than it's own data size
4620  *  - packet shrinks window more than the diff between it's ack and the
4621  *    last_ack value
4622  *
4623  *  Packets coming in after packet loss can look quite a bit like this.
4624  */
StreamTcpPacketIsBadWindowUpdate(TcpSession * ssn,Packet * p)4625 static int StreamTcpPacketIsBadWindowUpdate(TcpSession *ssn, Packet *p)
4626 {
4627     TcpStream *stream = NULL, *ostream = NULL;
4628     uint32_t seq;
4629     uint32_t ack;
4630     uint32_t pkt_win;
4631 
4632     if (p->flags & PKT_PSEUDO_STREAM_END)
4633         return 0;
4634 
4635     if (ssn->state < TCP_ESTABLISHED || ssn->state == TCP_CLOSED)
4636         return 0;
4637 
4638     if ((p->tcph->th_flags & (TH_SYN|TH_FIN|TH_RST)) != 0)
4639         return 0;
4640 
4641     if (PKT_IS_TOSERVER(p)) {
4642         stream = &ssn->client;
4643         ostream = &ssn->server;
4644     } else {
4645         stream = &ssn->server;
4646         ostream = &ssn->client;
4647     }
4648 
4649     seq = TCP_GET_SEQ(p);
4650     ack = TCP_GET_ACK(p);
4651 
4652     pkt_win = TCP_GET_WINDOW(p) << ostream->wscale;
4653 
4654     if (pkt_win < ostream->window) {
4655         uint32_t diff = ostream->window - pkt_win;
4656         if (diff > p->payload_len &&
4657                 SEQ_GT(ack, ostream->next_seq) &&
4658                 SEQ_GT(seq, stream->next_seq))
4659         {
4660             SCLogDebug("%"PRIu64", pkt_win %u, stream win %u, diff %u, dsize %u",
4661                 p->pcap_cnt, pkt_win, ostream->window, diff, p->payload_len);
4662             SCLogDebug("%"PRIu64", pkt_win %u, stream win %u",
4663                 p->pcap_cnt, pkt_win, ostream->window);
4664             SCLogDebug("%"PRIu64", seq %u ack %u ostream->next_seq %u ostream->last_ack %u, ostream->next_win %u, diff %u (%u)",
4665                     p->pcap_cnt, seq, ack, ostream->next_seq, ostream->last_ack, ostream->next_win,
4666                     ostream->next_seq - ostream->last_ack, stream->next_seq - stream->last_ack);
4667 
4668             /* get the expected window shrinking from looking at ack vs last_ack.
4669              * Observed a lot of just a little overrunning that value. So added some
4670              * margin that is still ok. To make sure this isn't a loophole to still
4671              * close the window, this is limited to windows above 1024. Both values
4672              * are rather arbitrary. */
4673             uint32_t adiff = ack - ostream->last_ack;
4674             if (((pkt_win > 1024) && (diff > (adiff + 32))) ||
4675                 ((pkt_win <= 1024) && (diff > adiff)))
4676             {
4677                 SCLogDebug("pkt ACK %u is %u bytes beyond last_ack %u, shrinks window by %u "
4678                         "(allowing 32 bytes extra): pkt WIN %u", ack, adiff, ostream->last_ack, diff, pkt_win);
4679                 SCLogDebug("%u - %u = %u (state %u)", diff, adiff, diff - adiff, ssn->state);
4680                 StreamTcpSetEvent(p, STREAM_PKT_BAD_WINDOW_UPDATE);
4681                 return 1;
4682             }
4683         }
4684 
4685     }
4686     SCLogDebug("seq %u (%u), ack %u (%u)", seq, stream->next_seq, ack, ostream->last_ack);
4687     return 0;
4688 }
4689 
4690 /** \internal
4691  *  \brief call packet handling function for 'state'
4692  *  \param state current TCP state
4693  */
StreamTcpStateDispatch(ThreadVars * tv,Packet * p,StreamTcpThread * stt,TcpSession * ssn,PacketQueueNoLock * pq,const uint8_t state)4694 static inline int StreamTcpStateDispatch(ThreadVars *tv, Packet *p,
4695         StreamTcpThread *stt, TcpSession *ssn, PacketQueueNoLock *pq,
4696         const uint8_t state)
4697 {
4698     SCLogDebug("ssn: %p", ssn);
4699     switch (state) {
4700         case TCP_SYN_SENT:
4701             if (StreamTcpPacketStateSynSent(tv, p, stt, ssn, pq)) {
4702                 return -1;
4703             }
4704             break;
4705         case TCP_SYN_RECV:
4706             if (StreamTcpPacketStateSynRecv(tv, p, stt, ssn, pq)) {
4707                 return -1;
4708             }
4709             break;
4710         case TCP_ESTABLISHED:
4711             if (StreamTcpPacketStateEstablished(tv, p, stt, ssn, pq)) {
4712                 return -1;
4713             }
4714             break;
4715         case TCP_FIN_WAIT1:
4716             SCLogDebug("packet received on TCP_FIN_WAIT1 state");
4717             if (StreamTcpPacketStateFinWait1(tv, p, stt, ssn, pq)) {
4718                 return -1;
4719             }
4720             break;
4721         case TCP_FIN_WAIT2:
4722             SCLogDebug("packet received on TCP_FIN_WAIT2 state");
4723             if (StreamTcpPacketStateFinWait2(tv, p, stt, ssn, pq)) {
4724                 return -1;
4725             }
4726             break;
4727         case TCP_CLOSING:
4728             SCLogDebug("packet received on TCP_CLOSING state");
4729             if (StreamTcpPacketStateClosing(tv, p, stt, ssn, pq)) {
4730                 return -1;
4731             }
4732             break;
4733         case TCP_CLOSE_WAIT:
4734             SCLogDebug("packet received on TCP_CLOSE_WAIT state");
4735             if (StreamTcpPacketStateCloseWait(tv, p, stt, ssn, pq)) {
4736                 return -1;
4737             }
4738             break;
4739         case TCP_LAST_ACK:
4740             SCLogDebug("packet received on TCP_LAST_ACK state");
4741             if (StreamTcpPacketStateLastAck(tv, p, stt, ssn, pq)) {
4742                 return -1;
4743             }
4744             break;
4745         case TCP_TIME_WAIT:
4746             SCLogDebug("packet received on TCP_TIME_WAIT state");
4747             if (StreamTcpPacketStateTimeWait(tv, p, stt, ssn, pq)) {
4748                 return -1;
4749             }
4750             break;
4751         case TCP_CLOSED:
4752             /* TCP session memory is not returned to pool until timeout. */
4753             SCLogDebug("packet received on closed state");
4754 
4755             if (StreamTcpPacketStateClosed(tv, p, stt, ssn, pq)) {
4756                 return -1;
4757             }
4758 
4759             break;
4760         default:
4761             SCLogDebug("packet received on default state");
4762             break;
4763     }
4764     return 0;
4765 }
4766 
HandleThreadId(ThreadVars * tv,Packet * p,StreamTcpThread * stt)4767 static inline void HandleThreadId(ThreadVars *tv, Packet *p, StreamTcpThread *stt)
4768 {
4769     const int idx = (!(PKT_IS_TOSERVER(p)));
4770 
4771     /* assign the thread id to the flow */
4772     if (unlikely(p->flow->thread_id[idx] == 0)) {
4773         p->flow->thread_id[idx] = (FlowThreadId)tv->id;
4774     } else if (unlikely((FlowThreadId)tv->id != p->flow->thread_id[idx])) {
4775         SCLogDebug("wrong thread: flow has %u, we are %d", p->flow->thread_id[idx], tv->id);
4776         if (p->pkt_src == PKT_SRC_WIRE) {
4777             StatsIncr(tv, stt->counter_tcp_wrong_thread);
4778             if ((p->flow->flags & FLOW_WRONG_THREAD) == 0) {
4779                 p->flow->flags |= FLOW_WRONG_THREAD;
4780                 StreamTcpSetEvent(p, STREAM_WRONG_THREAD);
4781             }
4782         }
4783     }
4784 }
4785 
4786 /* flow is and stays locked */
StreamTcpPacket(ThreadVars * tv,Packet * p,StreamTcpThread * stt,PacketQueueNoLock * pq)4787 int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt,
4788                      PacketQueueNoLock *pq)
4789 {
4790     SCEnter();
4791 
4792     DEBUG_ASSERT_FLOW_LOCKED(p->flow);
4793 
4794     SCLogDebug("p->pcap_cnt %"PRIu64, p->pcap_cnt);
4795 
4796     HandleThreadId(tv, p, stt);
4797 
4798     TcpSession *ssn = (TcpSession *)p->flow->protoctx;
4799 
4800     /* track TCP flags */
4801     if (ssn != NULL) {
4802         ssn->tcp_packet_flags |= p->tcph->th_flags;
4803         if (PKT_IS_TOSERVER(p))
4804             ssn->client.tcp_flags |= p->tcph->th_flags;
4805         else if (PKT_IS_TOCLIENT(p))
4806             ssn->server.tcp_flags |= p->tcph->th_flags;
4807 
4808         /* check if we need to unset the ASYNC flag */
4809         if (ssn->flags & STREAMTCP_FLAG_ASYNC &&
4810             ssn->client.tcp_flags != 0 &&
4811             ssn->server.tcp_flags != 0)
4812         {
4813             SCLogDebug("ssn %p: removing ASYNC flag as we have packets on both sides", ssn);
4814             ssn->flags &= ~STREAMTCP_FLAG_ASYNC;
4815         }
4816     }
4817 
4818     /* update counters */
4819     if ((p->tcph->th_flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) {
4820         StatsIncr(tv, stt->counter_tcp_synack);
4821     } else if (p->tcph->th_flags & (TH_SYN)) {
4822         StatsIncr(tv, stt->counter_tcp_syn);
4823     }
4824     if (p->tcph->th_flags & (TH_RST)) {
4825         StatsIncr(tv, stt->counter_tcp_rst);
4826     }
4827 
4828     /* broken TCP http://ask.wireshark.org/questions/3183/acknowledgment-number-broken-tcp-the-acknowledge-field-is-nonzero-while-the-ack-flag-is-not-set */
4829     if (!(p->tcph->th_flags & TH_ACK) && TCP_GET_ACK(p) != 0) {
4830         StreamTcpSetEvent(p, STREAM_PKT_BROKEN_ACK);
4831         if (!(p->tcph->th_flags & TH_SYN))
4832             goto error;
4833     }
4834 
4835     /* If we are on IPS mode, and got a drop action triggered from
4836      * the IP only module, or from a reassembled msg and/or from an
4837      * applayer detection, then drop the rest of the packets of the
4838      * same stream and avoid inspecting it any further */
4839     if (StreamTcpCheckFlowDrops(p) == 1) {
4840         SCLogDebug("This flow/stream triggered a drop rule");
4841         FlowSetNoPacketInspectionFlag(p->flow);
4842         DecodeSetNoPacketInspectionFlag(p);
4843         StreamTcpDisableAppLayer(p->flow);
4844         PACKET_DROP(p);
4845         /* return the segments to the pool */
4846         StreamTcpSessionPktFree(p);
4847         SCReturnInt(0);
4848     }
4849 
4850     if (ssn == NULL || ssn->state == TCP_NONE) {
4851         if (StreamTcpPacketStateNone(tv, p, stt, ssn, &stt->pseudo_queue) == -1) {
4852             goto error;
4853         }
4854 
4855         if (ssn != NULL)
4856             SCLogDebug("ssn->alproto %"PRIu16"", p->flow->alproto);
4857     } else {
4858         /* special case for PKT_PSEUDO_STREAM_END packets:
4859          * bypass the state handling and various packet checks,
4860          * we care about reassembly here. */
4861         if (p->flags & PKT_PSEUDO_STREAM_END) {
4862             if (PKT_IS_TOCLIENT(p)) {
4863                 ssn->client.last_ack = TCP_GET_ACK(p);
4864                 StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
4865                         &ssn->server, p, pq);
4866             } else {
4867                 ssn->server.last_ack = TCP_GET_ACK(p);
4868                 StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
4869                         &ssn->client, p, pq);
4870             }
4871             /* straight to 'skip' as we already handled reassembly */
4872             goto skip;
4873         }
4874 
4875         if (p->flow->flags & FLOW_WRONG_THREAD) {
4876             /* Stream and/or session in known bad condition. Block events
4877              * from being set. */
4878             p->flags |= PKT_STREAM_NO_EVENTS;
4879         }
4880 
4881         if (StreamTcpPacketIsKeepAlive(ssn, p) == 1) {
4882             goto skip;
4883         }
4884         if (StreamTcpPacketIsKeepAliveACK(ssn, p) == 1) {
4885             StreamTcpClearKeepAliveFlag(ssn, p);
4886             goto skip;
4887         }
4888         StreamTcpClearKeepAliveFlag(ssn, p);
4889 
4890         /* if packet is not a valid window update, check if it is perhaps
4891          * a bad window update that we should ignore (and alert on) */
4892         if (StreamTcpPacketIsFinShutdownAck(ssn, p) == 0)
4893             if (StreamTcpPacketIsWindowUpdate(ssn, p) == 0)
4894                 if (StreamTcpPacketIsBadWindowUpdate(ssn,p))
4895                     goto skip;
4896 
4897         /* handle the per 'state' logic */
4898         if (StreamTcpStateDispatch(tv, p, stt, ssn, &stt->pseudo_queue, ssn->state) < 0)
4899             goto error;
4900 
4901     skip:
4902         StreamTcpPacketCheckPostRst(ssn, p);
4903 
4904         if (ssn->state >= TCP_ESTABLISHED) {
4905             p->flags |= PKT_STREAM_EST;
4906         }
4907     }
4908 
4909     /* deal with a pseudo packet that is created upon receiving a RST
4910      * segment. To be sure we process both sides of the connection, we
4911      * inject a fake packet into the system, forcing reassembly of the
4912      * opposing direction.
4913      * There should be only one, but to be sure we do a while loop. */
4914     if (ssn != NULL) {
4915         while (stt->pseudo_queue.len > 0) {
4916             SCLogDebug("processing pseudo packet / stream end");
4917             Packet *np = PacketDequeueNoLock(&stt->pseudo_queue);
4918             if (np != NULL) {
4919                 /* process the opposing direction of the original packet */
4920                 if (PKT_IS_TOSERVER(np)) {
4921                     SCLogDebug("pseudo packet is to server");
4922                     StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
4923                             &ssn->client, np, NULL);
4924                 } else {
4925                     SCLogDebug("pseudo packet is to client");
4926                     StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
4927                             &ssn->server, np, NULL);
4928                 }
4929 
4930                 /* enqueue this packet so we inspect it in detect etc */
4931                 PacketEnqueueNoLock(pq, np);
4932             }
4933             SCLogDebug("processing pseudo packet / stream end done");
4934         }
4935 
4936         /* recalc the csum on the packet if it was modified */
4937         if (p->flags & PKT_STREAM_MODIFIED) {
4938             ReCalculateChecksum(p);
4939         }
4940         /* check for conditions that may make us not want to log this packet */
4941 
4942         /* streams that hit depth */
4943         if ((ssn->client.flags & STREAMTCP_STREAM_FLAG_DEPTH_REACHED) ||
4944              (ssn->server.flags & STREAMTCP_STREAM_FLAG_DEPTH_REACHED))
4945         {
4946             /* we can call bypass callback, if enabled */
4947             if (StreamTcpBypassEnabled()) {
4948                 PacketBypassCallback(p);
4949             }
4950         }
4951 
4952         if ((ssn->client.flags & STREAMTCP_STREAM_FLAG_DEPTH_REACHED) ||
4953              (ssn->server.flags & STREAMTCP_STREAM_FLAG_DEPTH_REACHED))
4954         {
4955             p->flags |= PKT_STREAM_NOPCAPLOG;
4956         }
4957 
4958         /* encrypted packets */
4959         if ((PKT_IS_TOSERVER(p) && (ssn->client.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY)) ||
4960             (PKT_IS_TOCLIENT(p) && (ssn->server.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY)))
4961         {
4962             p->flags |= PKT_STREAM_NOPCAPLOG;
4963         }
4964 
4965         if (ssn->flags & STREAMTCP_FLAG_BYPASS) {
4966             /* we can call bypass callback, if enabled */
4967             if (StreamTcpBypassEnabled()) {
4968                 PacketBypassCallback(p);
4969             }
4970 
4971         /* if stream is dead and we have no detect engine at all, bypass. */
4972         } else if (g_detect_disabled &&
4973                 (ssn->client.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY) &&
4974                 (ssn->server.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY) &&
4975                 StreamTcpBypassEnabled())
4976         {
4977             SCLogDebug("bypass as stream is dead and we have no rules");
4978             PacketBypassCallback(p);
4979         }
4980     }
4981 
4982     SCReturnInt(0);
4983 
4984 error:
4985     /* make sure we don't leave packets in our pseudo queue */
4986     while (stt->pseudo_queue.len > 0) {
4987         Packet *np = PacketDequeueNoLock(&stt->pseudo_queue);
4988         if (np != NULL) {
4989             PacketEnqueueNoLock(pq, np);
4990         }
4991     }
4992 
4993     /* recalc the csum on the packet if it was modified */
4994     if (p->flags & PKT_STREAM_MODIFIED) {
4995         ReCalculateChecksum(p);
4996     }
4997 
4998     if (StreamTcpInlineDropInvalid()) {
4999         /* disable payload inspection as we're dropping this packet
5000          * anyway. Doesn't disable all detection, so we can still
5001          * match on the stream event that was set. */
5002         DecodeSetNoPayloadInspectionFlag(p);
5003         PACKET_DROP(p);
5004     }
5005     SCReturnInt(-1);
5006 }
5007 
5008 /**
5009  *  \brief  Function to validate the checksum of the received packet. If the
5010  *          checksum is invalid, packet will be dropped, as the end system will
5011  *          also drop the packet.
5012  *
5013  *  \param  p       Packet of which checksum has to be validated
5014  *  \retval  1 if the checksum is valid, otherwise 0
5015  */
StreamTcpValidateChecksum(Packet * p)5016 static inline int StreamTcpValidateChecksum(Packet *p)
5017 {
5018     int ret = 1;
5019 
5020     if (p->flags & PKT_IGNORE_CHECKSUM)
5021         return ret;
5022 
5023     if (p->level4_comp_csum == -1) {
5024         if (PKT_IS_IPV4(p)) {
5025             p->level4_comp_csum = TCPChecksum(p->ip4h->s_ip_addrs,
5026                                               (uint16_t *)p->tcph,
5027                                               (p->payload_len +
5028                                                   TCP_GET_HLEN(p)),
5029                                               p->tcph->th_sum);
5030         } else if (PKT_IS_IPV6(p)) {
5031             p->level4_comp_csum = TCPV6Checksum(p->ip6h->s_ip6_addrs,
5032                                                 (uint16_t *)p->tcph,
5033                                                 (p->payload_len +
5034                                                     TCP_GET_HLEN(p)),
5035                                                 p->tcph->th_sum);
5036         }
5037     }
5038 
5039     if (p->level4_comp_csum != 0) {
5040         ret = 0;
5041         if (p->livedev) {
5042             (void) SC_ATOMIC_ADD(p->livedev->invalid_checksums, 1);
5043         } else if (p->pcap_cnt) {
5044             PcapIncreaseInvalidChecksum();
5045         }
5046     }
5047 
5048     return ret;
5049 }
5050 
5051 /** \internal
5052  *  \brief check if a packet is a valid stream started
5053  *  \retval bool true/false */
TcpSessionPacketIsStreamStarter(const Packet * p)5054 static int TcpSessionPacketIsStreamStarter(const Packet *p)
5055 {
5056     if (p->tcph->th_flags == TH_SYN) {
5057         SCLogDebug("packet %"PRIu64" is a stream starter: %02x", p->pcap_cnt, p->tcph->th_flags);
5058         return 1;
5059     }
5060 
5061     if (stream_config.midstream == TRUE || stream_config.async_oneside == TRUE) {
5062         if (p->tcph->th_flags == (TH_SYN|TH_ACK)) {
5063             SCLogDebug("packet %"PRIu64" is a midstream stream starter: %02x", p->pcap_cnt, p->tcph->th_flags);
5064             return 1;
5065         }
5066     }
5067     return 0;
5068 }
5069 
5070 /** \internal
5071  *  \brief Check if Flow and TCP SSN allow this flow/tuple to be reused
5072  *  \retval bool true yes reuse, false no keep tracking old ssn */
TcpSessionReuseDoneEnoughSyn(const Packet * p,const Flow * f,const TcpSession * ssn)5073 static int TcpSessionReuseDoneEnoughSyn(const Packet *p, const Flow *f, const TcpSession *ssn)
5074 {
5075     if (FlowGetPacketDirection(f, p) == TOSERVER) {
5076         if (ssn == NULL) {
5077             SCLogDebug("steam starter packet %"PRIu64", ssn %p null. No reuse.", p->pcap_cnt, ssn);
5078             return 0;
5079         }
5080         if (SEQ_EQ(ssn->client.isn, TCP_GET_SEQ(p))) {
5081             SCLogDebug("steam starter packet %"PRIu64", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.", p->pcap_cnt, ssn);
5082             return 0;
5083         }
5084         if (ssn->state >= TCP_LAST_ACK) {
5085             SCLogDebug("steam starter packet %"PRIu64", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->pcap_cnt, ssn, ssn->state);
5086             return 1;
5087         }
5088         if (ssn->state == TCP_NONE) {
5089             SCLogDebug("steam starter packet %"PRIu64", ssn %p state == TCP_NONE (%u). Reuse.", p->pcap_cnt, ssn, ssn->state);
5090             return 1;
5091         }
5092         if (ssn->state < TCP_LAST_ACK) {
5093             SCLogDebug("steam starter packet %"PRIu64", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->pcap_cnt, ssn, ssn->state);
5094             return 0;
5095         }
5096 
5097     } else {
5098         if (ssn == NULL) {
5099             SCLogDebug("steam starter packet %"PRIu64", ssn %p null. Reuse.", p->pcap_cnt, ssn);
5100             return 1;
5101         }
5102         if (ssn->state >= TCP_LAST_ACK) {
5103             SCLogDebug("steam starter packet %"PRIu64", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->pcap_cnt, ssn, ssn->state);
5104             return 1;
5105         }
5106         if (ssn->state == TCP_NONE) {
5107             SCLogDebug("steam starter packet %"PRIu64", ssn %p state == TCP_NONE (%u). Reuse.", p->pcap_cnt, ssn, ssn->state);
5108             return 1;
5109         }
5110         if (ssn->state < TCP_LAST_ACK) {
5111             SCLogDebug("steam starter packet %"PRIu64", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->pcap_cnt, ssn, ssn->state);
5112             return 0;
5113         }
5114     }
5115 
5116     SCLogDebug("default: how did we get here?");
5117     return 0;
5118 }
5119 
5120 /** \internal
5121  *  \brief check if ssn is done enough for reuse by syn/ack
5122  *  \note should only be called if midstream is enabled
5123  */
TcpSessionReuseDoneEnoughSynAck(const Packet * p,const Flow * f,const TcpSession * ssn)5124 static int TcpSessionReuseDoneEnoughSynAck(const Packet *p, const Flow *f, const TcpSession *ssn)
5125 {
5126     if (FlowGetPacketDirection(f, p) == TOCLIENT) {
5127         if (ssn == NULL) {
5128             SCLogDebug("steam starter packet %"PRIu64", ssn %p null. No reuse.", p->pcap_cnt, ssn);
5129             return 0;
5130         }
5131         if (SEQ_EQ(ssn->server.isn, TCP_GET_SEQ(p))) {
5132             SCLogDebug("steam starter packet %"PRIu64", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.", p->pcap_cnt, ssn);
5133             return 0;
5134         }
5135         if (ssn->state >= TCP_LAST_ACK) {
5136             SCLogDebug("steam starter packet %"PRIu64", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->pcap_cnt, ssn, ssn->state);
5137             return 1;
5138         }
5139         if (ssn->state == TCP_NONE) {
5140             SCLogDebug("steam starter packet %"PRIu64", ssn %p state == TCP_NONE (%u). Reuse.", p->pcap_cnt, ssn, ssn->state);
5141             return 1;
5142         }
5143         if (ssn->state < TCP_LAST_ACK) {
5144             SCLogDebug("steam starter packet %"PRIu64", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->pcap_cnt, ssn, ssn->state);
5145             return 0;
5146         }
5147 
5148     } else {
5149         if (ssn == NULL) {
5150             SCLogDebug("steam starter packet %"PRIu64", ssn %p null. Reuse.", p->pcap_cnt, ssn);
5151             return 1;
5152         }
5153         if (ssn->state >= TCP_LAST_ACK) {
5154             SCLogDebug("steam starter packet %"PRIu64", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->pcap_cnt, ssn, ssn->state);
5155             return 1;
5156         }
5157         if (ssn->state == TCP_NONE) {
5158             SCLogDebug("steam starter packet %"PRIu64", ssn %p state == TCP_NONE (%u). Reuse.", p->pcap_cnt, ssn, ssn->state);
5159             return 1;
5160         }
5161         if (ssn->state < TCP_LAST_ACK) {
5162             SCLogDebug("steam starter packet %"PRIu64", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->pcap_cnt, ssn, ssn->state);
5163             return 0;
5164         }
5165     }
5166 
5167     SCLogDebug("default: how did we get here?");
5168     return 0;
5169 }
5170 
5171 /** \brief Check if SSN is done enough for reuse
5172  *
5173  *  Reuse means a new TCP session reuses the tuple (flow in suri)
5174  *
5175  *  \retval bool true if ssn can be reused, false if not */
TcpSessionReuseDoneEnough(const Packet * p,const Flow * f,const TcpSession * ssn)5176 static int TcpSessionReuseDoneEnough(const Packet *p, const Flow *f, const TcpSession *ssn)
5177 {
5178     if (p->tcph->th_flags == TH_SYN) {
5179         return TcpSessionReuseDoneEnoughSyn(p, f, ssn);
5180     }
5181 
5182     if (stream_config.midstream == TRUE || stream_config.async_oneside == TRUE) {
5183         if (p->tcph->th_flags == (TH_SYN|TH_ACK)) {
5184             return TcpSessionReuseDoneEnoughSynAck(p, f, ssn);
5185         }
5186     }
5187 
5188     return 0;
5189 }
5190 
TcpSessionPacketSsnReuse(const Packet * p,const Flow * f,const void * tcp_ssn)5191 int TcpSessionPacketSsnReuse(const Packet *p, const Flow *f, const void *tcp_ssn)
5192 {
5193     if (p->proto == IPPROTO_TCP && p->tcph != NULL) {
5194         if (TcpSessionPacketIsStreamStarter(p) == 1) {
5195             if (TcpSessionReuseDoneEnough(p, f, tcp_ssn) == 1) {
5196                 return 1;
5197             }
5198         }
5199     }
5200     return 0;
5201 }
5202 
StreamTcp(ThreadVars * tv,Packet * p,void * data,PacketQueueNoLock * pq)5203 TmEcode StreamTcp (ThreadVars *tv, Packet *p, void *data, PacketQueueNoLock *pq)
5204 {
5205     StreamTcpThread *stt = (StreamTcpThread *)data;
5206 
5207     SCLogDebug("p->pcap_cnt %"PRIu64, p->pcap_cnt);
5208 
5209     if (!(PKT_IS_TCP(p))) {
5210         return TM_ECODE_OK;
5211     }
5212 
5213     if (p->flow == NULL) {
5214         StatsIncr(tv, stt->counter_tcp_no_flow);
5215         return TM_ECODE_OK;
5216     }
5217 
5218     /* only TCP packets with a flow from here */
5219 
5220     if (!(p->flags & PKT_PSEUDO_STREAM_END)) {
5221         if (stream_config.flags & STREAMTCP_INIT_FLAG_CHECKSUM_VALIDATION) {
5222             if (StreamTcpValidateChecksum(p) == 0) {
5223                 StatsIncr(tv, stt->counter_tcp_invalid_checksum);
5224                 return TM_ECODE_OK;
5225             }
5226         } else {
5227             p->flags |= PKT_IGNORE_CHECKSUM;
5228         }
5229     } else {
5230         p->flags |= PKT_IGNORE_CHECKSUM; //TODO check that this is set at creation
5231     }
5232     AppLayerProfilingReset(stt->ra_ctx->app_tctx);
5233 
5234     (void)StreamTcpPacket(tv, p, stt, pq);
5235 
5236     return TM_ECODE_OK;
5237 }
5238 
StreamTcpThreadInit(ThreadVars * tv,void * initdata,void ** data)5239 TmEcode StreamTcpThreadInit(ThreadVars *tv, void *initdata, void **data)
5240 {
5241     SCEnter();
5242     StreamTcpThread *stt = SCMalloc(sizeof(StreamTcpThread));
5243     if (unlikely(stt == NULL))
5244         SCReturnInt(TM_ECODE_FAILED);
5245     memset(stt, 0, sizeof(StreamTcpThread));
5246     stt->ssn_pool_id = -1;
5247 
5248     *data = (void *)stt;
5249 
5250     stt->counter_tcp_sessions = StatsRegisterCounter("tcp.sessions", tv);
5251     stt->counter_tcp_ssn_memcap = StatsRegisterCounter("tcp.ssn_memcap_drop", tv);
5252     stt->counter_tcp_pseudo = StatsRegisterCounter("tcp.pseudo", tv);
5253     stt->counter_tcp_pseudo_failed = StatsRegisterCounter("tcp.pseudo_failed", tv);
5254     stt->counter_tcp_invalid_checksum = StatsRegisterCounter("tcp.invalid_checksum", tv);
5255     stt->counter_tcp_no_flow = StatsRegisterCounter("tcp.no_flow", tv);
5256     stt->counter_tcp_syn = StatsRegisterCounter("tcp.syn", tv);
5257     stt->counter_tcp_synack = StatsRegisterCounter("tcp.synack", tv);
5258     stt->counter_tcp_rst = StatsRegisterCounter("tcp.rst", tv);
5259     stt->counter_tcp_midstream_pickups = StatsRegisterCounter("tcp.midstream_pickups", tv);
5260     stt->counter_tcp_wrong_thread = StatsRegisterCounter("tcp.pkt_on_wrong_thread", tv);
5261 
5262     /* init reassembly ctx */
5263     stt->ra_ctx = StreamTcpReassembleInitThreadCtx(tv);
5264     if (stt->ra_ctx == NULL)
5265         SCReturnInt(TM_ECODE_FAILED);
5266 
5267     stt->ra_ctx->counter_tcp_segment_memcap = StatsRegisterCounter("tcp.segment_memcap_drop", tv);
5268     stt->ra_ctx->counter_tcp_stream_depth = StatsRegisterCounter("tcp.stream_depth_reached", tv);
5269     stt->ra_ctx->counter_tcp_reass_gap = StatsRegisterCounter("tcp.reassembly_gap", tv);
5270     stt->ra_ctx->counter_tcp_reass_overlap = StatsRegisterCounter("tcp.overlap", tv);
5271     stt->ra_ctx->counter_tcp_reass_overlap_diff_data = StatsRegisterCounter("tcp.overlap_diff_data", tv);
5272 
5273     stt->ra_ctx->counter_tcp_reass_data_normal_fail = StatsRegisterCounter("tcp.insert_data_normal_fail", tv);
5274     stt->ra_ctx->counter_tcp_reass_data_overlap_fail = StatsRegisterCounter("tcp.insert_data_overlap_fail", tv);
5275     stt->ra_ctx->counter_tcp_reass_list_fail = StatsRegisterCounter("tcp.insert_list_fail", tv);
5276 
5277 
5278     SCLogDebug("StreamTcp thread specific ctx online at %p, reassembly ctx %p",
5279                 stt, stt->ra_ctx);
5280 
5281     SCMutexLock(&ssn_pool_mutex);
5282     if (ssn_pool == NULL) {
5283         ssn_pool = PoolThreadInit(1, /* thread */
5284                 0, /* unlimited */
5285                 stream_config.prealloc_sessions,
5286                 sizeof(TcpSession),
5287                 StreamTcpSessionPoolAlloc,
5288                 StreamTcpSessionPoolInit, NULL,
5289                 StreamTcpSessionPoolCleanup, NULL);
5290         stt->ssn_pool_id = 0;
5291         SCLogDebug("pool size %d, thread ssn_pool_id %d", PoolThreadSize(ssn_pool), stt->ssn_pool_id);
5292     } else {
5293         /* grow ssn_pool until we have a element for our thread id */
5294         stt->ssn_pool_id = PoolThreadExpand(ssn_pool);
5295         SCLogDebug("pool size %d, thread ssn_pool_id %d", PoolThreadSize(ssn_pool), stt->ssn_pool_id);
5296     }
5297     SCMutexUnlock(&ssn_pool_mutex);
5298     if (stt->ssn_pool_id < 0 || ssn_pool == NULL) {
5299         SCLogError(SC_ERR_MEM_ALLOC, "failed to setup/expand stream session pool. Expand stream.memcap?");
5300         SCReturnInt(TM_ECODE_FAILED);
5301     }
5302 
5303     SCReturnInt(TM_ECODE_OK);
5304 }
5305 
StreamTcpThreadDeinit(ThreadVars * tv,void * data)5306 TmEcode StreamTcpThreadDeinit(ThreadVars *tv, void *data)
5307 {
5308     SCEnter();
5309     StreamTcpThread *stt = (StreamTcpThread *)data;
5310     if (stt == NULL) {
5311         return TM_ECODE_OK;
5312     }
5313 
5314     /* XXX */
5315 
5316     /* free reassembly ctx */
5317     StreamTcpReassembleFreeThreadCtx(stt->ra_ctx);
5318 
5319     /* clear memory */
5320     memset(stt, 0, sizeof(StreamTcpThread));
5321 
5322     SCFree(stt);
5323     SCReturnInt(TM_ECODE_OK);
5324 }
5325 
5326 /**
5327  *  \brief   Function to check the validity of the RST packets based on the
5328  *           target OS of the given packet.
5329  *
5330  *  \param   ssn    TCP session to which the given packet belongs
5331  *  \param   p      Packet which has to be checked for its validity
5332  *
5333  *  \retval 0 unacceptable RST
5334  *  \retval 1 acceptable RST
5335  *
5336  *  WebSense sends RST packets that are:
5337  *  - RST flag, win 0, ack 0, seq = nextseq
5338  *
5339  */
5340 
StreamTcpValidateRst(TcpSession * ssn,Packet * p)5341 static int StreamTcpValidateRst(TcpSession *ssn, Packet *p)
5342 {
5343     uint8_t os_policy;
5344 
5345     if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
5346         if (!StreamTcpValidateTimestamp(ssn, p)) {
5347             SCReturnInt(0);
5348         }
5349     }
5350 
5351     /* Set up the os_policy to be used in validating the RST packets based on
5352        target system */
5353     if (PKT_IS_TOSERVER(p)) {
5354         if (ssn->server.os_policy == 0)
5355             StreamTcpSetOSPolicy(&ssn->server, p);
5356 
5357         os_policy = ssn->server.os_policy;
5358 
5359         if (p->tcph->th_flags & TH_ACK &&
5360                 TCP_GET_ACK(p) && StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
5361             SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
5362             StreamTcpSetEvent(p, STREAM_RST_INVALID_ACK);
5363             SCReturnInt(0);
5364         }
5365 
5366     } else {
5367         if (ssn->client.os_policy == 0)
5368             StreamTcpSetOSPolicy(&ssn->client, p);
5369 
5370         os_policy = ssn->client.os_policy;
5371 
5372         if (p->tcph->th_flags & TH_ACK &&
5373                 TCP_GET_ACK(p) && StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
5374             SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
5375             StreamTcpSetEvent(p, STREAM_RST_INVALID_ACK);
5376             SCReturnInt(0);
5377         }
5378     }
5379 
5380     /* RFC 2385 md5 signature header or RFC 5925 TCP AO headerpresent. Since we can't
5381      * validate these (requires key that is set/transfered out of band), we can't know
5382      * if the RST will be accepted or rejected by the end host. We accept it, but keep
5383      * tracking if the sender of it ignores it, which would be a sign of injection. */
5384     if (p->tcpvars.md5_option_present || p->tcpvars.ao_option_present) {
5385         TcpStream *receiver_stream;
5386         if (PKT_IS_TOSERVER(p)) {
5387             receiver_stream = &ssn->server;
5388         } else {
5389             receiver_stream = &ssn->client;
5390         }
5391         SCLogDebug("ssn %p: setting STREAMTCP_STREAM_FLAG_RST_RECV on receiver stream", ssn);
5392         receiver_stream->flags |= STREAMTCP_STREAM_FLAG_RST_RECV;
5393     }
5394 
5395     if (ssn->flags & STREAMTCP_FLAG_ASYNC) {
5396         if (PKT_IS_TOSERVER(p)) {
5397             if (SEQ_GEQ(TCP_GET_SEQ(p), ssn->client.next_seq)) {
5398                 SCLogDebug("ssn %p: ASYNC accept RST", ssn);
5399                 return 1;
5400             }
5401         } else {
5402             if (SEQ_GEQ(TCP_GET_SEQ(p), ssn->server.next_seq)) {
5403                 SCLogDebug("ssn %p: ASYNC accept RST", ssn);
5404                 return 1;
5405             }
5406         }
5407         SCLogDebug("ssn %p: ASYNC reject RST", ssn);
5408         return 0;
5409     }
5410 
5411     switch (os_policy) {
5412         case OS_POLICY_HPUX11:
5413             if(PKT_IS_TOSERVER(p)){
5414                 if(SEQ_GEQ(TCP_GET_SEQ(p), ssn->client.next_seq)) {
5415                     SCLogDebug("reset is Valid! Packet SEQ: %" PRIu32 "",
5416                                 TCP_GET_SEQ(p));
5417                     return 1;
5418                 } else {
5419                     SCLogDebug("reset is not Valid! Packet SEQ: %" PRIu32 " "
5420                                "and server SEQ: %" PRIu32 "", TCP_GET_SEQ(p),
5421                                 ssn->client.next_seq);
5422                     return 0;
5423                 }
5424             } else { /* implied to client */
5425                 if(SEQ_GEQ(TCP_GET_SEQ(p), ssn->server.next_seq)) {
5426                     SCLogDebug("reset is valid! Packet SEQ: %" PRIu32 "",
5427                                 TCP_GET_SEQ(p));
5428                     return 1;
5429                 } else {
5430                     SCLogDebug("reset is not valid! Packet SEQ: %" PRIu32 " "
5431                                "and client SEQ: %" PRIu32 "", TCP_GET_SEQ(p),
5432                                 ssn->server.next_seq);
5433                     return 0;
5434                 }
5435             }
5436             break;
5437         case OS_POLICY_OLD_LINUX:
5438         case OS_POLICY_LINUX:
5439         case OS_POLICY_SOLARIS:
5440             if(PKT_IS_TOSERVER(p)){
5441                 if(SEQ_GEQ((TCP_GET_SEQ(p)+p->payload_len),
5442                             ssn->client.last_ack))
5443                 { /*window base is needed !!*/
5444                     if(SEQ_LT(TCP_GET_SEQ(p),
5445                               (ssn->client.next_seq + ssn->client.window)))
5446                     {
5447                         SCLogDebug("reset is Valid! Packet SEQ: %" PRIu32 "",
5448                                     TCP_GET_SEQ(p));
5449                         return 1;
5450                     }
5451                 } else {
5452                     SCLogDebug("reset is not valid! Packet SEQ: %" PRIu32 " and"
5453                                " server SEQ: %" PRIu32 "", TCP_GET_SEQ(p),
5454                                 ssn->client.next_seq);
5455                     return 0;
5456                 }
5457             } else { /* implied to client */
5458                 if(SEQ_GEQ((TCP_GET_SEQ(p) + p->payload_len),
5459                             ssn->server.last_ack))
5460                 { /*window base is needed !!*/
5461                     if(SEQ_LT(TCP_GET_SEQ(p),
5462                                 (ssn->server.next_seq + ssn->server.window)))
5463                     {
5464                         SCLogDebug("reset is Valid! Packet SEQ: %" PRIu32 "",
5465                                     TCP_GET_SEQ(p));
5466                         return 1;
5467                     }
5468                 } else {
5469                     SCLogDebug("reset is not valid! Packet SEQ: %" PRIu32 " and"
5470                                " client SEQ: %" PRIu32 "", TCP_GET_SEQ(p),
5471                                  ssn->server.next_seq);
5472                     return 0;
5473                 }
5474             }
5475             break;
5476         default:
5477         case OS_POLICY_BSD:
5478         case OS_POLICY_FIRST:
5479         case OS_POLICY_HPUX10:
5480         case OS_POLICY_IRIX:
5481         case OS_POLICY_MACOS:
5482         case OS_POLICY_LAST:
5483         case OS_POLICY_WINDOWS:
5484         case OS_POLICY_WINDOWS2K3:
5485         case OS_POLICY_VISTA:
5486             if(PKT_IS_TOSERVER(p)) {
5487                 if(SEQ_EQ(TCP_GET_SEQ(p), ssn->client.next_seq)) {
5488                     SCLogDebug("reset is valid! Packet SEQ: %" PRIu32 "",
5489                                TCP_GET_SEQ(p));
5490                     return 1;
5491                 } else {
5492                     SCLogDebug("reset is not valid! Packet SEQ: %" PRIu32 " "
5493                                "and server SEQ: %" PRIu32 "", TCP_GET_SEQ(p),
5494                                ssn->client.next_seq);
5495                     return 0;
5496                 }
5497             } else { /* implied to client */
5498                 if (SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq)) {
5499                     SCLogDebug("reset is valid! Packet SEQ: %" PRIu32 " Stream %u",
5500                                 TCP_GET_SEQ(p), ssn->server.next_seq);
5501                     return 1;
5502                 } else {
5503                     SCLogDebug("reset is not valid! Packet SEQ: %" PRIu32 " and"
5504                                " client SEQ: %" PRIu32 "",
5505                                TCP_GET_SEQ(p), ssn->server.next_seq);
5506                     return 0;
5507                 }
5508             }
5509             break;
5510     }
5511     return 0;
5512 }
5513 
5514 /**
5515  *  \brief Function to check the validity of the received timestamp based on
5516  *         the target OS of the given stream.
5517  *
5518  *  It's passive except for:
5519  *  1. it sets the os policy on the stream if necessary
5520  *  2. it sets an event in the packet if necessary
5521  *
5522  *  \param ssn TCP session to which the given packet belongs
5523  *  \param p Packet which has to be checked for its validity
5524  *
5525  *  \retval 1 if the timestamp is valid
5526  *  \retval 0 if the timestamp is invalid
5527  */
StreamTcpValidateTimestamp(TcpSession * ssn,Packet * p)5528 static int StreamTcpValidateTimestamp (TcpSession *ssn, Packet *p)
5529 {
5530     SCEnter();
5531 
5532     TcpStream *sender_stream;
5533     TcpStream *receiver_stream;
5534     uint8_t ret = 1;
5535     uint8_t check_ts = 1;
5536 
5537     if (PKT_IS_TOSERVER(p)) {
5538         sender_stream = &ssn->client;
5539         receiver_stream = &ssn->server;
5540     } else {
5541         sender_stream = &ssn->server;
5542         receiver_stream = &ssn->client;
5543     }
5544 
5545     /* Set up the os_policy to be used in validating the timestamps based on
5546        the target system */
5547     if (receiver_stream->os_policy == 0) {
5548         StreamTcpSetOSPolicy(receiver_stream, p);
5549     }
5550 
5551     if (TCP_HAS_TS(p)) {
5552         uint32_t ts = TCP_GET_TSVAL(p);
5553         uint32_t last_pkt_ts = sender_stream->last_pkt_ts;
5554         uint32_t last_ts = sender_stream->last_ts;
5555 
5556         if (sender_stream->flags & STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP) {
5557             /* The 3whs used the timestamp with 0 value. */
5558             switch (receiver_stream->os_policy) {
5559                 case OS_POLICY_LINUX:
5560                 case OS_POLICY_WINDOWS2K3:
5561                     /* Linux and windows 2003 does not allow the use of 0 as
5562                      * timestamp in the 3whs. */
5563                     check_ts = 0;
5564                     break;
5565 
5566                 case OS_POLICY_OLD_LINUX:
5567                 case OS_POLICY_WINDOWS:
5568                 case OS_POLICY_VISTA:
5569                     if (SEQ_EQ(sender_stream->next_seq, TCP_GET_SEQ(p))) {
5570                         last_ts = ts;
5571                         check_ts = 0; /*next packet will be checked for validity
5572                                         and stream TS has been updated with this
5573                                         one.*/
5574                     }
5575                     break;
5576             }
5577         }
5578 
5579         if (receiver_stream->os_policy == OS_POLICY_HPUX11) {
5580             /* HPUX11 igoners the timestamp of out of order packets */
5581             if (!SEQ_EQ(sender_stream->next_seq, TCP_GET_SEQ(p)))
5582                 check_ts = 0;
5583         }
5584 
5585         if (ts == 0) {
5586             switch (receiver_stream->os_policy) {
5587                 case OS_POLICY_OLD_LINUX:
5588                 case OS_POLICY_WINDOWS:
5589                 case OS_POLICY_WINDOWS2K3:
5590                 case OS_POLICY_VISTA:
5591                 case OS_POLICY_SOLARIS:
5592                     /* Old Linux and windows allowed packet with 0 timestamp. */
5593                     break;
5594                 default:
5595                     /* other OS simply drop the pakcet with 0 timestamp, when
5596                      * 3whs has valid timestamp*/
5597                     goto invalid;
5598             }
5599         }
5600 
5601         if (check_ts) {
5602             int32_t result = 0;
5603 
5604             SCLogDebug("ts %"PRIu32", last_ts %"PRIu32"", ts, last_ts);
5605 
5606             if (receiver_stream->os_policy == OS_POLICY_LINUX) {
5607                 /* Linux accepts TS which are off by one.*/
5608                 result = (int32_t) ((ts - last_ts) + 1);
5609             } else {
5610                 result = (int32_t) (ts - last_ts);
5611             }
5612 
5613             SCLogDebug("result %"PRIi32", p->ts.tv_sec %"PRIuMAX"", result, (uintmax_t)p->ts.tv_sec);
5614 
5615             if (last_pkt_ts == 0 &&
5616                     (ssn->flags & STREAMTCP_FLAG_MIDSTREAM))
5617             {
5618                 last_pkt_ts = p->ts.tv_sec;
5619             }
5620 
5621             if (result < 0) {
5622                 SCLogDebug("timestamp is not valid last_ts "
5623                            "%" PRIu32 " p->tcpvars->ts %" PRIu32 " result "
5624                            "%" PRId32 "", last_ts, ts, result);
5625                 /* candidate for rejection */
5626                 ret = 0;
5627             } else if ((sender_stream->last_ts != 0) &&
5628                         (((uint32_t) p->ts.tv_sec) >
5629                             last_pkt_ts + PAWS_24DAYS))
5630             {
5631                 SCLogDebug("packet is not valid last_pkt_ts "
5632                            "%" PRIu32 " p->ts.tv_sec %" PRIu32 "",
5633                             last_pkt_ts, (uint32_t) p->ts.tv_sec);
5634                 /* candidate for rejection */
5635                 ret = 0;
5636             }
5637 
5638             if (ret == 0) {
5639                 /* if the timestamp of packet is not valid then, check if the
5640                  * current stream timestamp is not so old. if so then we need to
5641                  * accept the packet and update the stream->last_ts (RFC 1323)*/
5642                 if ((SEQ_EQ(sender_stream->next_seq, TCP_GET_SEQ(p))) &&
5643                         (((uint32_t) p->ts.tv_sec > (last_pkt_ts + PAWS_24DAYS))))
5644                 {
5645                     SCLogDebug("timestamp considered valid anyway");
5646                 } else {
5647                     goto invalid;
5648                 }
5649             }
5650         }
5651     }
5652 
5653     SCReturnInt(1);
5654 
5655 invalid:
5656     StreamTcpSetEvent(p, STREAM_PKT_INVALID_TIMESTAMP);
5657     SCReturnInt(0);
5658 }
5659 
5660 /**
5661  *  \brief Function to check the validity of the received timestamp based on
5662  *         the target OS of the given stream and update the session.
5663  *
5664  *  \param ssn TCP session to which the given packet belongs
5665  *  \param p Packet which has to be checked for its validity
5666  *
5667  *  \retval 1 if the timestamp is valid
5668  *  \retval 0 if the timestamp is invalid
5669  */
StreamTcpHandleTimestamp(TcpSession * ssn,Packet * p)5670 static int StreamTcpHandleTimestamp (TcpSession *ssn, Packet *p)
5671 {
5672     SCEnter();
5673 
5674     TcpStream *sender_stream;
5675     TcpStream *receiver_stream;
5676     uint8_t ret = 1;
5677     uint8_t check_ts = 1;
5678 
5679     if (PKT_IS_TOSERVER(p)) {
5680         sender_stream = &ssn->client;
5681         receiver_stream = &ssn->server;
5682     } else {
5683         sender_stream = &ssn->server;
5684         receiver_stream = &ssn->client;
5685     }
5686 
5687     /* Set up the os_policy to be used in validating the timestamps based on
5688        the target system */
5689     if (receiver_stream->os_policy == 0) {
5690         StreamTcpSetOSPolicy(receiver_stream, p);
5691     }
5692 
5693     if (TCP_HAS_TS(p)) {
5694         uint32_t ts = TCP_GET_TSVAL(p);
5695 
5696         if (sender_stream->flags & STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP) {
5697             /* The 3whs used the timestamp with 0 value. */
5698             switch (receiver_stream->os_policy) {
5699                 case OS_POLICY_LINUX:
5700                 case OS_POLICY_WINDOWS2K3:
5701                     /* Linux and windows 2003 does not allow the use of 0 as
5702                      * timestamp in the 3whs. */
5703                     ssn->flags &= ~STREAMTCP_FLAG_TIMESTAMP;
5704                     check_ts = 0;
5705                     break;
5706 
5707                 case OS_POLICY_OLD_LINUX:
5708                 case OS_POLICY_WINDOWS:
5709                 case OS_POLICY_VISTA:
5710                     sender_stream->flags &= ~STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
5711                     if (SEQ_EQ(sender_stream->next_seq, TCP_GET_SEQ(p))) {
5712                         sender_stream->last_ts = ts;
5713                         check_ts = 0; /*next packet will be checked for validity
5714                                         and stream TS has been updated with this
5715                                         one.*/
5716                     }
5717                     break;
5718                 default:
5719                     break;
5720             }
5721         }
5722 
5723         if (receiver_stream->os_policy == OS_POLICY_HPUX11) {
5724             /*HPUX11 igoners the timestamp of out of order packets*/
5725             if (!SEQ_EQ(sender_stream->next_seq, TCP_GET_SEQ(p)))
5726                 check_ts = 0;
5727         }
5728 
5729         if (ts == 0) {
5730             switch (receiver_stream->os_policy) {
5731                 case OS_POLICY_OLD_LINUX:
5732                 case OS_POLICY_WINDOWS:
5733                 case OS_POLICY_WINDOWS2K3:
5734                 case OS_POLICY_VISTA:
5735                 case OS_POLICY_SOLARIS:
5736                     /* Old Linux and windows allowed packet with 0 timestamp. */
5737                     break;
5738                 default:
5739                     /* other OS simply drop the pakcet with 0 timestamp, when
5740                      * 3whs has valid timestamp*/
5741                     goto invalid;
5742             }
5743         }
5744 
5745         if (check_ts) {
5746             int32_t result = 0;
5747 
5748             SCLogDebug("ts %"PRIu32", last_ts %"PRIu32"", ts, sender_stream->last_ts);
5749 
5750             if (receiver_stream->os_policy == OS_POLICY_LINUX) {
5751                 /* Linux accepts TS which are off by one.*/
5752                 result = (int32_t) ((ts - sender_stream->last_ts) + 1);
5753             } else {
5754                 result = (int32_t) (ts - sender_stream->last_ts);
5755             }
5756 
5757             SCLogDebug("result %"PRIi32", p->ts.tv_sec %"PRIuMAX"", result, (uintmax_t)p->ts.tv_sec);
5758 
5759             if (sender_stream->last_pkt_ts == 0 &&
5760                     (ssn->flags & STREAMTCP_FLAG_MIDSTREAM))
5761             {
5762                 sender_stream->last_pkt_ts = p->ts.tv_sec;
5763             }
5764 
5765             if (result < 0) {
5766                 SCLogDebug("timestamp is not valid sender_stream->last_ts "
5767                            "%" PRIu32 " p->tcpvars->ts %" PRIu32 " result "
5768                            "%" PRId32 "", sender_stream->last_ts, ts, result);
5769                 /* candidate for rejection */
5770                 ret = 0;
5771             } else if ((sender_stream->last_ts != 0) &&
5772                         (((uint32_t) p->ts.tv_sec) >
5773                             sender_stream->last_pkt_ts + PAWS_24DAYS))
5774             {
5775                 SCLogDebug("packet is not valid sender_stream->last_pkt_ts "
5776                            "%" PRIu32 " p->ts.tv_sec %" PRIu32 "",
5777                             sender_stream->last_pkt_ts, (uint32_t) p->ts.tv_sec);
5778                 /* candidate for rejection */
5779                 ret = 0;
5780             }
5781 
5782             if (ret == 1) {
5783                 /* Update the timestamp and last seen packet time for this
5784                  * stream */
5785                 if (SEQ_EQ(sender_stream->next_seq, TCP_GET_SEQ(p)))
5786                     sender_stream->last_ts = ts;
5787 
5788                 sender_stream->last_pkt_ts = p->ts.tv_sec;
5789 
5790             } else if (ret == 0) {
5791                 /* if the timestamp of packet is not valid then, check if the
5792                  * current stream timestamp is not so old. if so then we need to
5793                  * accept the packet and update the stream->last_ts (RFC 1323)*/
5794                 if ((SEQ_EQ(sender_stream->next_seq, TCP_GET_SEQ(p))) &&
5795                         (((uint32_t) p->ts.tv_sec > (sender_stream->last_pkt_ts + PAWS_24DAYS))))
5796                 {
5797                     sender_stream->last_ts = ts;
5798                     sender_stream->last_pkt_ts = p->ts.tv_sec;
5799 
5800                     SCLogDebug("timestamp considered valid anyway");
5801                 } else {
5802                     goto invalid;
5803                 }
5804             }
5805         }
5806     } else {
5807         /* Solaris stops using timestamps if a packet is received
5808            without a timestamp and timestamps were used on that stream. */
5809         if (receiver_stream->os_policy == OS_POLICY_SOLARIS)
5810             ssn->flags &= ~STREAMTCP_FLAG_TIMESTAMP;
5811     }
5812 
5813     SCReturnInt(1);
5814 
5815 invalid:
5816     StreamTcpSetEvent(p, STREAM_PKT_INVALID_TIMESTAMP);
5817     SCReturnInt(0);
5818 }
5819 
5820 /**
5821  *  \brief  Function to test the received ACK values against the stream window
5822  *          and previous ack value. ACK values should be higher than previous
5823  *          ACK value and less than the next_win value.
5824  *
5825  *  \param  ssn     TcpSession for state access
5826  *  \param  stream  TcpStream of which last_ack needs to be tested
5827  *  \param  p       Packet which is used to test the last_ack
5828  *
5829  *  \retval 0  ACK is valid, last_ack is updated if ACK was higher
5830  *  \retval -1 ACK is invalid
5831  */
StreamTcpValidateAck(TcpSession * ssn,TcpStream * stream,Packet * p)5832 static inline int StreamTcpValidateAck(TcpSession *ssn, TcpStream *stream, Packet *p)
5833 {
5834     SCEnter();
5835 
5836     uint32_t ack = TCP_GET_ACK(p);
5837 
5838     /* fast track */
5839     if (SEQ_GT(ack, stream->last_ack) && SEQ_LEQ(ack, stream->next_win))
5840     {
5841         SCLogDebug("ACK in bounds");
5842         SCReturnInt(0);
5843     }
5844     /* fast track */
5845     else if (SEQ_EQ(ack, stream->last_ack)) {
5846         SCLogDebug("pkt ACK %"PRIu32" == stream last ACK %"PRIu32, TCP_GET_ACK(p), stream->last_ack);
5847         SCReturnInt(0);
5848     }
5849 
5850     /* exception handling */
5851     if (SEQ_LT(ack, stream->last_ack)) {
5852         SCLogDebug("pkt ACK %"PRIu32" < stream last ACK %"PRIu32, TCP_GET_ACK(p), stream->last_ack);
5853 
5854         /* This is an attempt to get a 'left edge' value that we can check against.
5855          * It doesn't work when the window is 0, need to think of a better way. */
5856 
5857         if (stream->window != 0 && SEQ_LT(ack, (stream->last_ack - stream->window))) {
5858             SCLogDebug("ACK %"PRIu32" is before last_ack %"PRIu32" - window "
5859                     "%"PRIu32" = %"PRIu32, ack, stream->last_ack,
5860                     stream->window, stream->last_ack - stream->window);
5861             goto invalid;
5862         }
5863 
5864         SCReturnInt(0);
5865     }
5866 
5867     /* no further checks possible for ASYNC */
5868     if ((ssn->flags & STREAMTCP_FLAG_ASYNC) != 0) {
5869         SCReturnInt(0);
5870     }
5871 
5872     if (ssn->state > TCP_SYN_SENT && SEQ_GT(ack, stream->next_win)) {
5873         SCLogDebug("ACK %"PRIu32" is after next_win %"PRIu32, ack, stream->next_win);
5874         goto invalid;
5875     /* a toclient RST as a reponse to SYN, next_win is 0, ack will be isn+1, just like
5876      * the syn ack */
5877     } else if (ssn->state == TCP_SYN_SENT && PKT_IS_TOCLIENT(p) &&
5878             p->tcph->th_flags & TH_RST &&
5879             SEQ_EQ(ack, stream->isn + 1)) {
5880         SCReturnInt(0);
5881     }
5882 
5883     SCLogDebug("default path leading to invalid: ACK %"PRIu32", last_ack %"PRIu32
5884         " next_win %"PRIu32, ack, stream->last_ack, stream->next_win);
5885 invalid:
5886     StreamTcpSetEvent(p, STREAM_PKT_INVALID_ACK);
5887     SCReturnInt(-1);
5888 }
5889 
5890 /** \brief update reassembly progress
5891 
5892  * \param ssn TCP Session
5893  * \param direction direction to set the flag in: 0 toserver, 1 toclient
5894  */
StreamTcpUpdateAppLayerProgress(TcpSession * ssn,char direction,const uint32_t progress)5895 void StreamTcpUpdateAppLayerProgress(TcpSession *ssn, char direction,
5896         const uint32_t progress)
5897 {
5898     if (direction) {
5899         ssn->server.app_progress_rel += progress;
5900     } else {
5901         ssn->client.app_progress_rel += progress;
5902     }
5903 }
5904 
5905 /** \brief disable reassembly
5906 
5907  *  Disable app layer and set raw inspect to no longer accept new data.
5908  *  Stream engine will then fully disable raw after last inspection.
5909  *
5910  * \param ssn TCP Session to set the flag in
5911  * \param direction direction to set the flag in: 0 toserver, 1 toclient
5912  */
StreamTcpSetSessionNoReassemblyFlag(TcpSession * ssn,char direction)5913 void StreamTcpSetSessionNoReassemblyFlag(TcpSession *ssn, char direction)
5914 {
5915     ssn->flags |= STREAMTCP_FLAG_APP_LAYER_DISABLED;
5916     if (direction) {
5917         ssn->server.flags |= STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED;
5918     } else {
5919         ssn->client.flags |= STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED;
5920     }
5921 }
5922 
5923 /** \brief  Set the No reassembly flag for the given direction in given TCP
5924  *          session.
5925  *
5926  * \param ssn TCP Session to set the flag in
5927  * \param direction direction to set the flag in: 0 toserver, 1 toclient
5928  */
StreamTcpSetDisableRawReassemblyFlag(TcpSession * ssn,char direction)5929 void StreamTcpSetDisableRawReassemblyFlag(TcpSession *ssn, char direction)
5930 {
5931     direction ? (ssn->server.flags |= STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED) :
5932                 (ssn->client.flags |= STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED);
5933 }
5934 
5935 /** \brief enable bypass
5936  *
5937  * \param ssn TCP Session to set the flag in
5938  * \param direction direction to set the flag in: 0 toserver, 1 toclient
5939  */
StreamTcpSetSessionBypassFlag(TcpSession * ssn)5940 void StreamTcpSetSessionBypassFlag(TcpSession *ssn)
5941 {
5942     ssn->flags |= STREAMTCP_FLAG_BYPASS;
5943 }
5944 
5945 #define PSEUDO_PKT_SET_IPV4HDR(nipv4h,ipv4h) do { \
5946         IPV4_SET_RAW_VER(nipv4h, IPV4_GET_RAW_VER(ipv4h)); \
5947         IPV4_SET_RAW_HLEN(nipv4h, IPV4_GET_RAW_HLEN(ipv4h)); \
5948         IPV4_SET_RAW_IPLEN(nipv4h, IPV4_GET_RAW_IPLEN(ipv4h)); \
5949         IPV4_SET_RAW_IPTOS(nipv4h, IPV4_GET_RAW_IPTOS(ipv4h)); \
5950         IPV4_SET_RAW_IPPROTO(nipv4h, IPV4_GET_RAW_IPPROTO(ipv4h)); \
5951         (nipv4h)->s_ip_src = IPV4_GET_RAW_IPDST(ipv4h); \
5952         (nipv4h)->s_ip_dst = IPV4_GET_RAW_IPSRC(ipv4h); \
5953     } while (0)
5954 
5955 #define PSEUDO_PKT_SET_IPV6HDR(nipv6h,ipv6h) do { \
5956         (nipv6h)->s_ip6_src[0] = (ipv6h)->s_ip6_dst[0]; \
5957         (nipv6h)->s_ip6_src[1] = (ipv6h)->s_ip6_dst[1]; \
5958         (nipv6h)->s_ip6_src[2] = (ipv6h)->s_ip6_dst[2]; \
5959         (nipv6h)->s_ip6_src[3] = (ipv6h)->s_ip6_dst[3]; \
5960         (nipv6h)->s_ip6_dst[0] = (ipv6h)->s_ip6_src[0]; \
5961         (nipv6h)->s_ip6_dst[1] = (ipv6h)->s_ip6_src[1]; \
5962         (nipv6h)->s_ip6_dst[2] = (ipv6h)->s_ip6_src[2]; \
5963         (nipv6h)->s_ip6_dst[3] = (ipv6h)->s_ip6_src[3]; \
5964         IPV6_SET_RAW_NH(nipv6h, IPV6_GET_RAW_NH(ipv6h));    \
5965     } while (0)
5966 
5967 #define PSEUDO_PKT_SET_TCPHDR(ntcph,tcph) do { \
5968         COPY_PORT((tcph)->th_dport, (ntcph)->th_sport); \
5969         COPY_PORT((tcph)->th_sport, (ntcph)->th_dport); \
5970         (ntcph)->th_seq = (tcph)->th_ack; \
5971         (ntcph)->th_ack = (tcph)->th_seq; \
5972     } while (0)
5973 
5974 /**
5975  * \brief   Function to fetch a packet from the packet allocation queue for
5976  *          creation of the pseudo packet from the reassembled stream.
5977  *
5978  * @param parent    Pointer to the parent of the pseudo packet
5979  * @param pkt       pointer to the raw packet of the parent
5980  * @param len       length of the packet
5981  * @return          upon success returns the pointer to the new pseudo packet
5982  *                  otherwise NULL
5983  */
StreamTcpPseudoSetup(Packet * parent,uint8_t * pkt,uint32_t len)5984 Packet *StreamTcpPseudoSetup(Packet *parent, uint8_t *pkt, uint32_t len)
5985 {
5986     SCEnter();
5987 
5988     if (len == 0) {
5989         SCReturnPtr(NULL, "Packet");
5990     }
5991 
5992     Packet *p = PacketGetFromQueueOrAlloc();
5993     if (p == NULL) {
5994         SCReturnPtr(NULL, "Packet");
5995     }
5996 
5997     /* set the root ptr to the lowest layer */
5998     if (parent->root != NULL)
5999         p->root = parent->root;
6000     else
6001         p->root = parent;
6002 
6003     /* copy packet and set lenght, proto */
6004     p->proto = parent->proto;
6005     p->datalink = parent->datalink;
6006 
6007     PacketCopyData(p, pkt, len);
6008     p->recursion_level = parent->recursion_level + 1;
6009     p->ts.tv_sec = parent->ts.tv_sec;
6010     p->ts.tv_usec = parent->ts.tv_usec;
6011 
6012     FlowReference(&p->flow, parent->flow);
6013     /* set tunnel flags */
6014 
6015     /* tell new packet it's part of a tunnel */
6016     SET_TUNNEL_PKT(p);
6017     /* tell parent packet it's part of a tunnel */
6018     SET_TUNNEL_PKT(parent);
6019 
6020     /* increment tunnel packet refcnt in the root packet */
6021     TUNNEL_INCR_PKT_TPR(p);
6022 
6023     return p;
6024 }
6025 
6026 /** \brief Create a pseudo packet injected into the engine to signal the
6027  *         opposing direction of this stream trigger detection/logging.
6028  *
6029  *  \param parent real packet
6030  *  \param pq packet queue to store the new pseudo packet in
6031  *  \param dir 0 ts 1 tc
6032  */
StreamTcpPseudoPacketCreateDetectLogFlush(ThreadVars * tv,StreamTcpThread * stt,Packet * parent,TcpSession * ssn,PacketQueueNoLock * pq,int dir)6033 static void StreamTcpPseudoPacketCreateDetectLogFlush(ThreadVars *tv,
6034         StreamTcpThread *stt, Packet *parent,
6035         TcpSession *ssn, PacketQueueNoLock *pq, int dir)
6036 {
6037     SCEnter();
6038     Flow *f = parent->flow;
6039 
6040     if (parent->flags & PKT_PSEUDO_DETECTLOG_FLUSH) {
6041         SCReturn;
6042     }
6043 
6044     Packet *np = PacketPoolGetPacket();
6045     if (np == NULL) {
6046         SCReturn;
6047     }
6048     PKT_SET_SRC(np, PKT_SRC_STREAM_TCP_DETECTLOG_FLUSH);
6049 
6050     np->tenant_id = f->tenant_id;
6051     np->datalink = DLT_RAW;
6052     np->proto = IPPROTO_TCP;
6053     FlowReference(&np->flow, f);
6054     np->flags |= PKT_STREAM_EST;
6055     np->flags |= PKT_HAS_FLOW;
6056     np->flags |= PKT_IGNORE_CHECKSUM;
6057     np->flags |= PKT_PSEUDO_DETECTLOG_FLUSH;
6058     np->vlan_id[0] = f->vlan_id[0];
6059     np->vlan_id[1] = f->vlan_id[1];
6060     np->vlan_idx = f->vlan_idx;
6061     np->livedev = (struct LiveDevice_ *)f->livedev;
6062 
6063     if (f->flags & FLOW_NOPACKET_INSPECTION) {
6064         DecodeSetNoPacketInspectionFlag(np);
6065     }
6066     if (f->flags & FLOW_NOPAYLOAD_INSPECTION) {
6067         DecodeSetNoPayloadInspectionFlag(np);
6068     }
6069 
6070     if (dir == 0) {
6071         SCLogDebug("pseudo is to_server");
6072         np->flowflags |= FLOW_PKT_TOSERVER;
6073     } else {
6074         SCLogDebug("pseudo is to_client");
6075         np->flowflags |= FLOW_PKT_TOCLIENT;
6076     }
6077     np->flowflags |= FLOW_PKT_ESTABLISHED;
6078     np->payload = NULL;
6079     np->payload_len = 0;
6080 
6081     if (FLOW_IS_IPV4(f)) {
6082         if (dir == 0) {
6083             FLOW_COPY_IPV4_ADDR_TO_PACKET(&f->src, &np->src);
6084             FLOW_COPY_IPV4_ADDR_TO_PACKET(&f->dst, &np->dst);
6085             np->sp = f->sp;
6086             np->dp = f->dp;
6087         } else {
6088             FLOW_COPY_IPV4_ADDR_TO_PACKET(&f->src, &np->dst);
6089             FLOW_COPY_IPV4_ADDR_TO_PACKET(&f->dst, &np->src);
6090             np->sp = f->dp;
6091             np->dp = f->sp;
6092         }
6093 
6094         /* Check if we have enough room in direct data. We need ipv4 hdr + tcp hdr.
6095          * Force an allocation if it is not the case.
6096          */
6097         if (GET_PKT_DIRECT_MAX_SIZE(np) <  40) {
6098             if (PacketCallocExtPkt(np, 40) == -1) {
6099                 goto error;
6100             }
6101         }
6102         /* set the ip header */
6103         np->ip4h = (IPV4Hdr *)GET_PKT_DATA(np);
6104         /* version 4 and length 20 bytes for the tcp header */
6105         np->ip4h->ip_verhl = 0x45;
6106         np->ip4h->ip_tos = 0;
6107         np->ip4h->ip_len = htons(40);
6108         np->ip4h->ip_id = 0;
6109         np->ip4h->ip_off = 0;
6110         np->ip4h->ip_ttl = 64;
6111         np->ip4h->ip_proto = IPPROTO_TCP;
6112         if (dir == 0) {
6113             np->ip4h->s_ip_src.s_addr = f->src.addr_data32[0];
6114             np->ip4h->s_ip_dst.s_addr = f->dst.addr_data32[0];
6115         } else {
6116             np->ip4h->s_ip_src.s_addr = f->dst.addr_data32[0];
6117             np->ip4h->s_ip_dst.s_addr = f->src.addr_data32[0];
6118         }
6119 
6120         /* set the tcp header */
6121         np->tcph = (TCPHdr *)((uint8_t *)GET_PKT_DATA(np) + 20);
6122 
6123         SET_PKT_LEN(np, 40); /* ipv4 hdr + tcp hdr */
6124 
6125     } else if (FLOW_IS_IPV6(f)) {
6126         if (dir == 0) {
6127             FLOW_COPY_IPV6_ADDR_TO_PACKET(&f->src, &np->src);
6128             FLOW_COPY_IPV6_ADDR_TO_PACKET(&f->dst, &np->dst);
6129             np->sp = f->sp;
6130             np->dp = f->dp;
6131         } else {
6132             FLOW_COPY_IPV6_ADDR_TO_PACKET(&f->src, &np->dst);
6133             FLOW_COPY_IPV6_ADDR_TO_PACKET(&f->dst, &np->src);
6134             np->sp = f->dp;
6135             np->dp = f->sp;
6136         }
6137 
6138         /* Check if we have enough room in direct data. We need ipv6 hdr + tcp hdr.
6139          * Force an allocation if it is not the case.
6140          */
6141         if (GET_PKT_DIRECT_MAX_SIZE(np) <  60) {
6142             if (PacketCallocExtPkt(np, 60) == -1) {
6143                 goto error;
6144             }
6145         }
6146         /* set the ip header */
6147         np->ip6h = (IPV6Hdr *)GET_PKT_DATA(np);
6148         /* version 6 */
6149         np->ip6h->s_ip6_vfc = 0x60;
6150         np->ip6h->s_ip6_flow = 0;
6151         np->ip6h->s_ip6_nxt = IPPROTO_TCP;
6152         np->ip6h->s_ip6_plen = htons(20);
6153         np->ip6h->s_ip6_hlim = 64;
6154         if (dir == 0) {
6155             np->ip6h->s_ip6_src[0] = f->src.addr_data32[0];
6156             np->ip6h->s_ip6_src[1] = f->src.addr_data32[1];
6157             np->ip6h->s_ip6_src[2] = f->src.addr_data32[2];
6158             np->ip6h->s_ip6_src[3] = f->src.addr_data32[3];
6159             np->ip6h->s_ip6_dst[0] = f->dst.addr_data32[0];
6160             np->ip6h->s_ip6_dst[1] = f->dst.addr_data32[1];
6161             np->ip6h->s_ip6_dst[2] = f->dst.addr_data32[2];
6162             np->ip6h->s_ip6_dst[3] = f->dst.addr_data32[3];
6163         } else {
6164             np->ip6h->s_ip6_src[0] = f->dst.addr_data32[0];
6165             np->ip6h->s_ip6_src[1] = f->dst.addr_data32[1];
6166             np->ip6h->s_ip6_src[2] = f->dst.addr_data32[2];
6167             np->ip6h->s_ip6_src[3] = f->dst.addr_data32[3];
6168             np->ip6h->s_ip6_dst[0] = f->src.addr_data32[0];
6169             np->ip6h->s_ip6_dst[1] = f->src.addr_data32[1];
6170             np->ip6h->s_ip6_dst[2] = f->src.addr_data32[2];
6171             np->ip6h->s_ip6_dst[3] = f->src.addr_data32[3];
6172         }
6173 
6174         /* set the tcp header */
6175         np->tcph = (TCPHdr *)((uint8_t *)GET_PKT_DATA(np) + 40);
6176 
6177         SET_PKT_LEN(np, 60); /* ipv6 hdr + tcp hdr */
6178     }
6179 
6180     np->tcph->th_offx2 = 0x50;
6181     np->tcph->th_flags |= TH_ACK;
6182     np->tcph->th_win = 10;
6183     np->tcph->th_urp = 0;
6184 
6185     /* to server */
6186     if (dir == 0) {
6187         np->tcph->th_sport = htons(f->sp);
6188         np->tcph->th_dport = htons(f->dp);
6189 
6190         np->tcph->th_seq = htonl(ssn->client.next_seq);
6191         np->tcph->th_ack = htonl(ssn->server.last_ack);
6192 
6193     /* to client */
6194     } else {
6195         np->tcph->th_sport = htons(f->dp);
6196         np->tcph->th_dport = htons(f->sp);
6197 
6198         np->tcph->th_seq = htonl(ssn->server.next_seq);
6199         np->tcph->th_ack = htonl(ssn->client.last_ack);
6200     }
6201 
6202     /* use parent time stamp */
6203     memcpy(&np->ts, &parent->ts, sizeof(struct timeval));
6204 
6205     SCLogDebug("np %p", np);
6206     PacketEnqueueNoLock(pq, np);
6207 
6208     StatsIncr(tv, stt->counter_tcp_pseudo);
6209     SCReturn;
6210 error:
6211     FlowDeReference(&np->flow);
6212     SCReturn;
6213 }
6214 
6215 /** \brief create packets in both directions to flush out logging
6216  *         and detection before switching protocols.
6217  *         In IDS mode, create first in packet dir, 2nd in opposing
6218  *         In IPS mode, do the reverse.
6219  *         Flag TCP engine that data needs to be inspected regardless
6220  *         of how far we are wrt inspect limits.
6221  */
StreamTcpDetectLogFlush(ThreadVars * tv,StreamTcpThread * stt,Flow * f,Packet * p,PacketQueueNoLock * pq)6222 void StreamTcpDetectLogFlush(ThreadVars *tv, StreamTcpThread *stt, Flow *f, Packet *p,
6223         PacketQueueNoLock *pq)
6224 {
6225     TcpSession *ssn = f->protoctx;
6226     ssn->client.flags |= STREAMTCP_STREAM_FLAG_TRIGGER_RAW;
6227     ssn->server.flags |= STREAMTCP_STREAM_FLAG_TRIGGER_RAW;
6228     bool ts = PKT_IS_TOSERVER(p) ? true : false;
6229     ts ^= StreamTcpInlineMode();
6230     StreamTcpPseudoPacketCreateDetectLogFlush(tv, stt, p, ssn, pq, ts^0);
6231     StreamTcpPseudoPacketCreateDetectLogFlush(tv, stt, p, ssn, pq, ts^1);
6232 }
6233 
6234 /**
6235  * \brief Run callback function on each TCP segment
6236  *
6237  * \note when stream engine is running in inline mode all segments are used,
6238  *       in IDS/non-inline mode only ack'd segments are iterated.
6239  *
6240  * \note Must be called under flow lock.
6241  *
6242  * \return -1 in case of error, the number of segment in case of success
6243  *
6244  */
StreamTcpSegmentForEach(const Packet * p,uint8_t flag,StreamSegmentCallback CallbackFunc,void * data)6245 int StreamTcpSegmentForEach(const Packet *p, uint8_t flag, StreamSegmentCallback CallbackFunc, void *data)
6246 {
6247     TcpSession *ssn = NULL;
6248     TcpStream *stream = NULL;
6249     int ret = 0;
6250     int cnt = 0;
6251 
6252     if (p->flow == NULL)
6253         return 0;
6254 
6255     ssn = (TcpSession *)p->flow->protoctx;
6256 
6257     if (ssn == NULL) {
6258         return 0;
6259     }
6260 
6261     if (flag & FLOW_PKT_TOSERVER) {
6262         stream = &(ssn->server);
6263     } else {
6264         stream = &(ssn->client);
6265     }
6266 
6267     /* for IDS, return ack'd segments. For IPS all. */
6268     TcpSegment *seg;
6269     RB_FOREACH(seg, TCPSEG, &stream->seg_tree) {
6270         if (!((stream_config.flags & STREAMTCP_INIT_FLAG_INLINE)
6271                     || SEQ_LT(seg->seq, stream->last_ack)))
6272             break;
6273 
6274         const uint8_t *seg_data;
6275         uint32_t seg_datalen;
6276         StreamingBufferSegmentGetData(&stream->sb, &seg->sbseg, &seg_data, &seg_datalen);
6277 
6278         ret = CallbackFunc(p, data, seg_data, seg_datalen);
6279         if (ret != 1) {
6280             SCLogDebug("Callback function has failed");
6281             return -1;
6282         }
6283 
6284         cnt++;
6285     }
6286     return cnt;
6287 }
6288 
StreamTcpBypassEnabled(void)6289 int StreamTcpBypassEnabled(void)
6290 {
6291     return (stream_config.flags & STREAMTCP_INIT_FLAG_BYPASS);
6292 }
6293 
6294 /**
6295  *  \brief See if stream engine is operating in inline mode
6296  *
6297  *  \retval 0 no
6298  *  \retval 1 yes
6299  */
StreamTcpInlineMode(void)6300 int StreamTcpInlineMode(void)
6301 {
6302     return (stream_config.flags & STREAMTCP_INIT_FLAG_INLINE) ? 1 : 0;
6303 }
6304 
6305 
TcpSessionSetReassemblyDepth(TcpSession * ssn,uint32_t size)6306 void TcpSessionSetReassemblyDepth(TcpSession *ssn, uint32_t size)
6307 {
6308     if (size > ssn->reassembly_depth || size == 0) {
6309         ssn->reassembly_depth = size;
6310     }
6311 
6312     return;
6313 }
6314 
StreamTcpStateAsString(const enum TcpState state)6315 const char *StreamTcpStateAsString(const enum TcpState state)
6316 {
6317     const char *tcp_state = NULL;
6318     switch (state) {
6319         case TCP_NONE:
6320             tcp_state = "none";
6321             break;
6322         case TCP_LISTEN:
6323             tcp_state = "listen";
6324             break;
6325         case TCP_SYN_SENT:
6326             tcp_state = "syn_sent";
6327             break;
6328         case TCP_SYN_RECV:
6329             tcp_state = "syn_recv";
6330             break;
6331         case TCP_ESTABLISHED:
6332             tcp_state = "established";
6333             break;
6334         case TCP_FIN_WAIT1:
6335             tcp_state = "fin_wait1";
6336             break;
6337         case TCP_FIN_WAIT2:
6338             tcp_state = "fin_wait2";
6339             break;
6340         case TCP_TIME_WAIT:
6341             tcp_state = "time_wait";
6342             break;
6343         case TCP_LAST_ACK:
6344             tcp_state = "last_ack";
6345             break;
6346         case TCP_CLOSE_WAIT:
6347             tcp_state = "close_wait";
6348             break;
6349         case TCP_CLOSING:
6350             tcp_state = "closing";
6351             break;
6352         case TCP_CLOSED:
6353             tcp_state = "closed";
6354             break;
6355     }
6356     return tcp_state;
6357 }
6358 
StreamTcpSsnStateAsString(const TcpSession * ssn)6359 const char *StreamTcpSsnStateAsString(const TcpSession *ssn)
6360 {
6361     if (ssn == NULL)
6362         return NULL;
6363     return StreamTcpStateAsString(ssn->state);
6364 }
6365 
6366 #ifdef UNITTESTS
6367 
6368 #define SET_ISN(stream, setseq)             \
6369     (stream)->isn = (setseq);               \
6370     (stream)->base_seq = (setseq) + 1
6371 
6372 /**
6373  *  \test   Test the allocation of TCP session for a given packet from the
6374  *          ssn_pool.
6375  *
6376  *  \retval On success it returns 1 and on failure 0.
6377  */
6378 
StreamTcpTest01(void)6379 static int StreamTcpTest01 (void)
6380 {
6381     StreamTcpThread stt;
6382     Packet *p = SCMalloc(SIZE_OF_PACKET);
6383     if (unlikely(p == NULL))
6384         return 0;
6385     Flow f;
6386     memset(p, 0, SIZE_OF_PACKET);
6387     memset (&f, 0, sizeof(Flow));
6388     FLOW_INITIALIZE(&f);
6389     p->flow = &f;
6390     int ret = 0;
6391 
6392     StreamTcpUTInit(&stt.ra_ctx);
6393 
6394     TcpSession *ssn = StreamTcpNewSession(p, 0);
6395     if (ssn == NULL) {
6396         printf("Session can not be allocated: ");
6397         goto end;
6398     }
6399     f.protoctx = ssn;
6400 
6401     if (f.alparser != NULL) {
6402         printf("AppLayer field not set to NULL: ");
6403         goto end;
6404     }
6405     if (ssn->state != 0) {
6406         printf("TCP state field not set to 0: ");
6407         goto end;
6408     }
6409 
6410     StreamTcpSessionClear(p->flow->protoctx);
6411 
6412     ret = 1;
6413 end:
6414     SCFree(p);
6415     FLOW_DESTROY(&f);
6416     StreamTcpUTDeinit(stt.ra_ctx);
6417     return ret;
6418 }
6419 
6420 /**
6421  *  \test   Test the deallocation of TCP session for a given packet and return
6422  *          the memory back to ssn_pool and corresponding segments to segment
6423  *          pool.
6424  *
6425  *  \retval On success it returns 1 and on failure 0.
6426  */
6427 
StreamTcpTest02(void)6428 static int StreamTcpTest02 (void)
6429 {
6430     Packet *p = SCMalloc(SIZE_OF_PACKET);
6431     FAIL_IF(unlikely(p == NULL));
6432     Flow f;
6433     ThreadVars tv;
6434     StreamTcpThread stt;
6435     uint8_t payload[4];
6436     TCPHdr tcph;
6437     PacketQueueNoLock pq;
6438     memset(&pq,0,sizeof(pq));
6439     memset(p, 0, SIZE_OF_PACKET);
6440     memset (&f, 0, sizeof(Flow));
6441     memset(&tv, 0, sizeof (ThreadVars));
6442     memset(&stt, 0, sizeof (StreamTcpThread));
6443     memset(&tcph, 0, sizeof (TCPHdr));
6444 
6445     FLOW_INITIALIZE(&f);
6446     p->flow = &f;
6447     tcph.th_win = htons(5480);
6448     tcph.th_flags = TH_SYN;
6449     p->tcph = &tcph;
6450     p->flowflags = FLOW_PKT_TOSERVER;
6451 
6452     StreamTcpUTInit(&stt.ra_ctx);
6453 
6454     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
6455 
6456     p->tcph->th_ack = htonl(1);
6457     p->tcph->th_flags = TH_SYN | TH_ACK;
6458     p->flowflags = FLOW_PKT_TOCLIENT;
6459 
6460     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
6461 
6462     p->tcph->th_ack = htonl(1);
6463     p->tcph->th_seq = htonl(1);
6464     p->tcph->th_flags = TH_ACK;
6465     p->flowflags = FLOW_PKT_TOSERVER;
6466 
6467     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
6468 
6469     p->tcph->th_ack = htonl(1);
6470     p->tcph->th_seq = htonl(2);
6471     p->tcph->th_flags = TH_PUSH | TH_ACK;
6472     p->flowflags = FLOW_PKT_TOSERVER;
6473 
6474     StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
6475     p->payload = payload;
6476     p->payload_len = 3;
6477 
6478     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
6479 
6480     p->flowflags = FLOW_PKT_TOCLIENT;
6481     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
6482 
6483     p->tcph->th_ack = htonl(1);
6484     p->tcph->th_seq = htonl(6);
6485     p->tcph->th_flags = TH_PUSH | TH_ACK;
6486     p->flowflags = FLOW_PKT_TOSERVER;
6487 
6488     StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
6489     p->payload = payload;
6490     p->payload_len = 3;
6491 
6492     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
6493 
6494     p->flowflags = FLOW_PKT_TOCLIENT;
6495     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
6496 
6497     StreamTcpSessionClear(p->flow->protoctx);
6498     //StreamTcpUTClearSession(p->flow->protoctx);
6499 
6500     SCFree(p);
6501     FLOW_DESTROY(&f);
6502     StreamTcpUTDeinit(stt.ra_ctx);
6503     PASS;
6504 }
6505 
6506 /**
6507  *  \test   Test the setting up a TCP session when we missed the intial
6508  *          SYN packet of the session. The session is setup only if midstream
6509  *          sessions are allowed to setup.
6510  *
6511  *  \retval On success it returns 1 and on failure 0.
6512  */
6513 
StreamTcpTest03(void)6514 static int StreamTcpTest03 (void)
6515 {
6516     Packet *p = SCMalloc(SIZE_OF_PACKET);
6517     if (unlikely(p == NULL))
6518         return 0;
6519     Flow f;
6520     ThreadVars tv;
6521     StreamTcpThread stt;
6522     TCPHdr tcph;
6523     memset(p, 0, SIZE_OF_PACKET);
6524     PacketQueueNoLock pq;
6525     memset(&pq,0,sizeof(pq));
6526     memset (&f, 0, sizeof(Flow));
6527     memset(&tv, 0, sizeof (ThreadVars));
6528     memset(&stt, 0, sizeof (StreamTcpThread));
6529     memset(&tcph, 0, sizeof (TCPHdr));
6530     FLOW_INITIALIZE(&f);
6531     p->flow = &f;
6532 
6533     StreamTcpUTInit(&stt.ra_ctx);
6534 
6535     tcph.th_win = htons(5480);
6536     tcph.th_seq = htonl(10);
6537     tcph.th_ack = htonl(20);
6538     tcph.th_flags = TH_SYN|TH_ACK;
6539     p->tcph = &tcph;
6540     int ret = 0;
6541 
6542     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
6543         goto end;
6544 
6545     p->tcph->th_seq = htonl(20);
6546     p->tcph->th_ack = htonl(11);
6547     p->tcph->th_flags = TH_ACK;
6548     p->flowflags = FLOW_PKT_TOSERVER;
6549 
6550     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
6551         goto end;
6552 
6553     p->tcph->th_seq = htonl(19);
6554     p->tcph->th_ack = htonl(11);
6555     p->tcph->th_flags = TH_ACK|TH_PUSH;
6556     p->flowflags = FLOW_PKT_TOSERVER;
6557 
6558     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
6559         goto end;
6560 
6561     if (stream_config.midstream != TRUE) {
6562         ret = 1;
6563         goto end;
6564     }
6565     if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED)
6566         goto end;
6567 
6568     if (((TcpSession *)(p->flow->protoctx))->client.next_seq != 20 &&
6569             ((TcpSession *)(p->flow->protoctx))->server.next_seq != 11)
6570         goto end;
6571 
6572     StreamTcpSessionClear(p->flow->protoctx);
6573 
6574     ret = 1;
6575 end:
6576     SCFree(p);
6577     FLOW_DESTROY(&f);
6578     StreamTcpUTDeinit(stt.ra_ctx);
6579     return ret;
6580 }
6581 
6582 /**
6583  *  \test   Test the setting up a TCP session when we missed the intial
6584  *          SYN/ACK packet of the session. The session is setup only if
6585  *          midstream sessions are allowed to setup.
6586  *
6587  *  \retval On success it returns 1 and on failure 0.
6588  */
6589 
StreamTcpTest04(void)6590 static int StreamTcpTest04 (void)
6591 {
6592     Packet *p = SCMalloc(SIZE_OF_PACKET);
6593     if (unlikely(p == NULL))
6594         return 0;
6595     Flow f;
6596     ThreadVars tv;
6597     StreamTcpThread stt;
6598     TCPHdr tcph;
6599     memset(p, 0, SIZE_OF_PACKET);
6600     PacketQueueNoLock pq;
6601     memset(&pq,0,sizeof(pq));
6602     memset (&f, 0, sizeof(Flow));
6603     memset(&tv, 0, sizeof (ThreadVars));
6604     memset(&stt, 0, sizeof (StreamTcpThread));
6605     memset(&tcph, 0, sizeof (TCPHdr));
6606     FLOW_INITIALIZE(&f);
6607     p->flow = &f;
6608 
6609     StreamTcpUTInit(&stt.ra_ctx);
6610 
6611     tcph.th_win = htons(5480);
6612     tcph.th_seq = htonl(10);
6613     tcph.th_ack = htonl(20);
6614     tcph.th_flags = TH_ACK;
6615     p->tcph = &tcph;
6616 
6617     int ret = 0;
6618 
6619     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
6620         goto end;
6621 
6622     p->tcph->th_seq = htonl(9);
6623     p->tcph->th_ack = htonl(19);
6624     p->tcph->th_flags = TH_ACK|TH_PUSH;
6625     p->flowflags = FLOW_PKT_TOSERVER;
6626 
6627     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
6628         goto end;
6629 
6630     if (stream_config.midstream != TRUE) {
6631         ret = 1;
6632         goto end;
6633     }
6634     if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED)
6635         goto end;
6636 
6637     if (((TcpSession *)(p->flow->protoctx))->client.next_seq != 10 &&
6638             ((TcpSession *)(p->flow->protoctx))->server.next_seq != 20)
6639         goto end;
6640 
6641     StreamTcpSessionClear(p->flow->protoctx);
6642 
6643     ret = 1;
6644 end:
6645     SCFree(p);
6646     FLOW_DESTROY(&f);
6647     StreamTcpUTDeinit(stt.ra_ctx);
6648     return ret;
6649 }
6650 
6651 /**
6652  *  \test   Test the setting up a TCP session when we missed the intial
6653  *          3WHS packet of the session. The session is setup only if
6654  *          midstream sessions are allowed to setup.
6655  *
6656  *  \retval On success it returns 1 and on failure 0.
6657  */
6658 
StreamTcpTest05(void)6659 static int StreamTcpTest05 (void)
6660 {
6661     Packet *p = SCMalloc(SIZE_OF_PACKET);
6662     if (unlikely(p == NULL))
6663         return 0;
6664     Flow f;
6665     ThreadVars tv;
6666     StreamTcpThread stt;
6667     TCPHdr tcph;
6668     uint8_t payload[4];
6669     memset(p, 0, SIZE_OF_PACKET);
6670     PacketQueueNoLock pq;
6671     memset(&pq,0,sizeof(PacketQueueNoLock));
6672     memset (&f, 0, sizeof(Flow));
6673     memset(&tv, 0, sizeof (ThreadVars));
6674     memset(&stt, 0, sizeof (StreamTcpThread));
6675     memset(&tcph, 0, sizeof (TCPHdr));
6676     FLOW_INITIALIZE(&f);
6677     p->flow = &f;
6678     int ret = 0;
6679 
6680     StreamTcpUTInit(&stt.ra_ctx);
6681     tcph.th_win = htons(5480);
6682     tcph.th_seq = htonl(10);
6683     tcph.th_ack = htonl(20);
6684     tcph.th_flags = TH_ACK|TH_PUSH;
6685     p->tcph = &tcph;
6686 
6687     StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
6688     p->payload = payload;
6689     p->payload_len = 3;
6690 
6691     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
6692         goto end;
6693 
6694     p->tcph->th_seq = htonl(20);
6695     p->tcph->th_ack = htonl(13);
6696     p->tcph->th_flags = TH_ACK|TH_PUSH;
6697     p->flowflags = FLOW_PKT_TOCLIENT;
6698 
6699     StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
6700     p->payload = payload;
6701     p->payload_len = 3;
6702 
6703     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
6704         goto end;
6705 
6706     p->tcph->th_seq = htonl(13);
6707     p->tcph->th_ack = htonl(23);
6708     p->tcph->th_flags = TH_ACK|TH_PUSH;
6709     p->flowflags = FLOW_PKT_TOSERVER;
6710 
6711     StreamTcpCreateTestPacket(payload, 0x43, 3, 4); /*CCC*/
6712     p->payload = payload;
6713     p->payload_len = 3;
6714 
6715     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
6716         goto end;
6717 
6718     p->tcph->th_seq = htonl(19);
6719     p->tcph->th_ack = htonl(16);
6720     p->tcph->th_flags = TH_ACK|TH_PUSH;
6721     p->flowflags = FLOW_PKT_TOCLIENT;
6722 
6723     StreamTcpCreateTestPacket(payload, 0x44, 3, 4); /*DDD*/
6724     p->payload = payload;
6725     p->payload_len = 3;
6726 
6727     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
6728         goto end;
6729 
6730     if (stream_config.midstream != TRUE) {
6731         ret = 1;
6732         goto end;
6733     }
6734     if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED)
6735         goto end;
6736 
6737     if (((TcpSession *)(p->flow->protoctx))->client.next_seq != 16 &&
6738             ((TcpSession *)(p->flow->protoctx))->server.next_seq != 23)
6739         goto end;
6740 
6741     StreamTcpSessionClear(p->flow->protoctx);
6742 
6743     ret = 1;
6744 end:
6745     SCFree(p);
6746     FLOW_DESTROY(&f);
6747     StreamTcpUTDeinit(stt.ra_ctx);
6748     return ret;
6749 }
6750 
6751 /**
6752  *  \test   Test the setting up a TCP session when we have seen only the
6753  *          FIN, RST packets packet of the session. The session is setup only if
6754  *          midstream sessions are allowed to setup.
6755  *
6756  *  \retval On success it returns 1 and on failure 0.
6757  */
6758 
StreamTcpTest06(void)6759 static int StreamTcpTest06 (void)
6760 {
6761     Packet *p = SCMalloc(SIZE_OF_PACKET);
6762     if (unlikely(p == NULL))
6763         return 0;
6764     Flow f;
6765     TcpSession ssn;
6766     ThreadVars tv;
6767     StreamTcpThread stt;
6768     TCPHdr tcph;
6769     memset(p, 0, SIZE_OF_PACKET);
6770     PacketQueueNoLock pq;
6771     memset(&pq,0,sizeof(PacketQueueNoLock));
6772     memset (&f, 0, sizeof(Flow));
6773     memset(&ssn, 0, sizeof (TcpSession));
6774     memset(&tv, 0, sizeof (ThreadVars));
6775     memset(&stt, 0, sizeof (StreamTcpThread));
6776     memset(&tcph, 0, sizeof (TCPHdr));
6777     FLOW_INITIALIZE(&f);
6778     p->flow = &f;
6779     int ret = 0;
6780 
6781     StreamTcpUTInit(&stt.ra_ctx);
6782 
6783     tcph.th_flags = TH_FIN;
6784     p->tcph = &tcph;
6785 
6786     /* StreamTcpPacket returns -1 on unsolicited FIN */
6787     if (StreamTcpPacket(&tv, p, &stt, &pq) != -1) {
6788         printf("StreamTcpPacket failed: ");
6789         goto end;
6790     }
6791 
6792     if (((TcpSession *)(p->flow->protoctx)) != NULL) {
6793         printf("we have a ssn while we shouldn't: ");
6794         goto end;
6795     }
6796 
6797     p->tcph->th_flags = TH_RST;
6798     /* StreamTcpPacket returns -1 on unsolicited RST */
6799     if (StreamTcpPacket(&tv, p, &stt, &pq) != -1) {
6800         printf("StreamTcpPacket failed (2): ");
6801         goto end;
6802     }
6803 
6804     if (((TcpSession *)(p->flow->protoctx)) != NULL) {
6805         printf("we have a ssn while we shouldn't (2): ");
6806         goto end;
6807     }
6808 
6809     ret = 1;
6810 end:
6811     SCFree(p);
6812     FLOW_DESTROY(&f);
6813     StreamTcpUTDeinit(stt.ra_ctx);
6814     return ret;
6815 }
6816 
6817 /**
6818  *  \test   Test the working on PAWS. The packet will be dropped by stream, as
6819  *          its timestamp is old, although the segment is in the window.
6820  */
6821 
StreamTcpTest07(void)6822 static int StreamTcpTest07 (void)
6823 {
6824     Packet *p = SCMalloc(SIZE_OF_PACKET);
6825     FAIL_IF(unlikely(p == NULL));
6826     Flow f;
6827     ThreadVars tv;
6828     StreamTcpThread stt;
6829     TCPHdr tcph;
6830     uint8_t payload[1] = {0x42};
6831     PacketQueueNoLock pq;
6832 
6833     memset(p, 0, SIZE_OF_PACKET);
6834     memset(&pq,0,sizeof(PacketQueueNoLock));
6835     memset (&f, 0, sizeof(Flow));
6836     memset(&tv, 0, sizeof (ThreadVars));
6837     memset(&stt, 0, sizeof(StreamTcpThread));
6838     memset(&tcph, 0, sizeof(TCPHdr));
6839 
6840     FLOW_INITIALIZE(&f);
6841     p->flow = &f;
6842 
6843     StreamTcpUTInit(&stt.ra_ctx);
6844     stream_config.midstream = TRUE;
6845 
6846     tcph.th_win = htons(5480);
6847     tcph.th_seq = htonl(10);
6848     tcph.th_ack = htonl(20);
6849     tcph.th_flags = TH_ACK|TH_PUSH;
6850     p->tcph = &tcph;
6851 
6852     p->tcpvars.ts_set = TRUE;
6853     p->tcpvars.ts_val = 10;
6854     p->tcpvars.ts_ecr = 11;
6855 
6856     p->payload = payload;
6857     p->payload_len = 1;
6858 
6859     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
6860 
6861     p->tcph->th_seq = htonl(11);
6862     p->tcph->th_ack = htonl(23);
6863     p->tcph->th_flags = TH_ACK|TH_PUSH;
6864     p->flowflags = FLOW_PKT_TOSERVER;
6865 
6866     p->tcpvars.ts_val = 2;
6867 
6868     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) != -1);
6869 
6870     FAIL_IF(((TcpSession *) (p->flow->protoctx))->client.next_seq != 11);
6871 
6872     StreamTcpSessionClear(p->flow->protoctx);
6873     SCFree(p);
6874     FLOW_DESTROY(&f);
6875     StreamTcpUTDeinit(stt.ra_ctx);
6876     PASS;
6877 }
6878 
6879 /**
6880  *  \test   Test the working on PAWS. The packet will be accpeted by engine as
6881  *          the timestamp is valid and it is in window.
6882  */
6883 
StreamTcpTest08(void)6884 static int StreamTcpTest08 (void)
6885 {
6886     Packet *p = SCMalloc(SIZE_OF_PACKET);
6887     FAIL_IF(unlikely(p == NULL));
6888     Flow f;
6889     ThreadVars tv;
6890     StreamTcpThread stt;
6891     TCPHdr tcph;
6892     uint8_t payload[1] = {0x42};
6893 
6894     memset(p, 0, SIZE_OF_PACKET);
6895     PacketQueueNoLock pq;
6896     memset(&pq,0,sizeof(PacketQueueNoLock));
6897     memset (&f, 0, sizeof(Flow));
6898     memset(&tv, 0, sizeof (ThreadVars));
6899     memset(&stt, 0, sizeof(StreamTcpThread));
6900     memset(&tcph, 0, sizeof(TCPHdr));
6901 
6902     FLOW_INITIALIZE(&f);
6903     p->flow = &f;
6904 
6905     StreamTcpUTInit(&stt.ra_ctx);
6906     stream_config.midstream = TRUE;
6907 
6908     tcph.th_win = htons(5480);
6909     tcph.th_seq = htonl(10);
6910     tcph.th_ack = htonl(20);
6911     tcph.th_flags = TH_ACK|TH_PUSH;
6912     p->tcph = &tcph;
6913 
6914     p->tcpvars.ts_set = TRUE;
6915     p->tcpvars.ts_val = 10;
6916     p->tcpvars.ts_ecr = 11;
6917 
6918     p->payload = payload;
6919     p->payload_len = 1;
6920 
6921     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
6922 
6923     p->tcph->th_seq = htonl(11);
6924     p->tcph->th_ack = htonl(20);
6925     p->tcph->th_flags = TH_ACK|TH_PUSH;
6926     p->flowflags = FLOW_PKT_TOSERVER;
6927 
6928     p->tcpvars.ts_val = 12;
6929 
6930     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
6931 
6932     FAIL_IF(((TcpSession *) (p->flow->protoctx))->client.next_seq != 12);
6933 
6934     StreamTcpSessionClear(p->flow->protoctx);
6935 
6936     SCFree(p);
6937     FLOW_DESTROY(&f);
6938     StreamTcpUTDeinit(stt.ra_ctx);
6939     PASS;
6940 }
6941 
6942 /**
6943  *  \test   Test the working of No stream reassembly flag. The stream will not
6944  *          reassemble the segment if the flag is set.
6945  */
6946 
StreamTcpTest09(void)6947 static int StreamTcpTest09 (void)
6948 {
6949     Packet *p = SCMalloc(SIZE_OF_PACKET);
6950     FAIL_IF(unlikely(p == NULL));
6951     Flow f;
6952     ThreadVars tv;
6953     StreamTcpThread stt;
6954     TCPHdr tcph;
6955     uint8_t payload[1] = {0x42};
6956 
6957     memset(p, 0, SIZE_OF_PACKET);
6958     PacketQueueNoLock pq;
6959     memset(&pq,0,sizeof(PacketQueueNoLock));
6960     memset (&f, 0, sizeof(Flow));
6961     memset(&tv, 0, sizeof (ThreadVars));
6962     memset(&stt, 0, sizeof(StreamTcpThread));
6963     memset(&tcph, 0, sizeof(TCPHdr));
6964 
6965     FLOW_INITIALIZE(&f);
6966     p->flow = &f;
6967 
6968     StreamTcpUTInit(&stt.ra_ctx);
6969     stream_config.midstream = TRUE;
6970 
6971     tcph.th_win = htons(5480);
6972     tcph.th_seq = htonl(10);
6973     tcph.th_ack = htonl(20);
6974     tcph.th_flags = TH_ACK|TH_PUSH;
6975     p->tcph = &tcph;
6976 
6977     p->payload = payload;
6978     p->payload_len = 1;
6979 
6980     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
6981 
6982     p->tcph->th_seq = htonl(12);
6983     p->tcph->th_ack = htonl(23);
6984     p->tcph->th_flags = TH_ACK|TH_PUSH;
6985     p->flowflags = FLOW_PKT_TOSERVER;
6986 
6987     FAIL_IF(p->flow->protoctx == NULL);
6988 
6989     StreamTcpSetSessionNoReassemblyFlag(((TcpSession *)(p->flow->protoctx)), 0);
6990 
6991     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
6992 
6993     p->tcph->th_seq = htonl(11);
6994     p->tcph->th_ack = htonl(23);
6995     p->tcph->th_flags = TH_ACK|TH_PUSH;
6996     p->flowflags = FLOW_PKT_TOSERVER;
6997 
6998     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
6999 
7000     TcpSession *ssn = p->flow->protoctx;
7001     FAIL_IF_NULL(ssn);
7002     TcpSegment *seg = RB_MIN(TCPSEG, &ssn->client.seg_tree);
7003     FAIL_IF_NULL(seg);
7004     FAIL_IF(TCPSEG_RB_NEXT(seg) != NULL);
7005 
7006     StreamTcpSessionClear(p->flow->protoctx);
7007     SCFree(p);
7008     FLOW_DESTROY(&f);
7009     StreamTcpUTDeinit(stt.ra_ctx);
7010     PASS;
7011 }
7012 
7013 /**
7014  *  \test   Test the setting up a TCP session when we are seeing asynchronous
7015  *          stream, while we see all the packets in that stream from start.
7016  */
7017 
StreamTcpTest10(void)7018 static int StreamTcpTest10 (void)
7019 {
7020     Packet *p = SCMalloc(SIZE_OF_PACKET);
7021     FAIL_IF(unlikely(p == NULL));
7022     Flow f;
7023     ThreadVars tv;
7024     StreamTcpThread stt;
7025     TCPHdr tcph;
7026     uint8_t payload[4];
7027     memset(p, 0, SIZE_OF_PACKET);
7028     PacketQueueNoLock pq;
7029     memset(&pq,0,sizeof(PacketQueueNoLock));
7030     memset (&f, 0, sizeof(Flow));
7031     memset(&tv, 0, sizeof (ThreadVars));
7032     memset(&stt, 0, sizeof (StreamTcpThread));
7033     memset(&tcph, 0, sizeof (TCPHdr));
7034     FLOW_INITIALIZE(&f);
7035     p->flow = &f;
7036 
7037     StreamTcpUTInit(&stt.ra_ctx);
7038     stream_config.async_oneside = TRUE;
7039 
7040     tcph.th_win = htons(5480);
7041     tcph.th_seq = htonl(10);
7042     tcph.th_ack = 0;
7043     tcph.th_flags = TH_SYN;
7044     p->tcph = &tcph;
7045 
7046     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
7047 
7048     p->tcph->th_seq = htonl(11);
7049     p->tcph->th_ack = htonl(11);
7050     p->tcph->th_flags = TH_ACK;
7051     p->flowflags = FLOW_PKT_TOSERVER;
7052 
7053     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
7054 
7055     p->tcph->th_seq = htonl(11);
7056     p->tcph->th_ack = htonl(11);
7057     p->tcph->th_flags = TH_ACK|TH_PUSH;
7058     p->flowflags = FLOW_PKT_TOSERVER;
7059 
7060     StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
7061     p->payload = payload;
7062     p->payload_len = 3;
7063 
7064     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
7065 
7066     p->tcph->th_seq = htonl(6);
7067     p->tcph->th_ack = htonl(11);
7068     p->tcph->th_flags = TH_ACK|TH_PUSH;
7069     p->flowflags = FLOW_PKT_TOSERVER;
7070 
7071     StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
7072     p->payload = payload;
7073     p->payload_len = 3;
7074 
7075     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
7076 
7077     FAIL_IF(((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED);
7078 
7079     FAIL_IF(! (((TcpSession *)(p->flow->protoctx))->flags & STREAMTCP_FLAG_ASYNC));
7080 
7081     FAIL_IF(((TcpSession *)(p->flow->protoctx))->client.last_ack != 6 &&
7082             ((TcpSession *)(p->flow->protoctx))->server.next_seq != 11);
7083 
7084     StreamTcpSessionClear(p->flow->protoctx);
7085 
7086     SCFree(p);
7087     FLOW_DESTROY(&f);
7088     StreamTcpUTDeinit(stt.ra_ctx);
7089     PASS;
7090 }
7091 
7092 /**
7093  *  \test   Test the setting up a TCP session when we are seeing asynchronous
7094  *          stream, while we missed the SYN packet of that stream.
7095  */
7096 
StreamTcpTest11(void)7097 static int StreamTcpTest11 (void)
7098 {
7099     Packet *p = SCMalloc(SIZE_OF_PACKET);
7100     FAIL_IF(unlikely(p == NULL));
7101     Flow f;
7102     ThreadVars tv;
7103     StreamTcpThread stt;
7104     TCPHdr tcph;
7105     uint8_t payload[4];
7106     memset(p, 0, SIZE_OF_PACKET);
7107     PacketQueueNoLock pq;
7108     memset(&pq,0,sizeof(PacketQueueNoLock));
7109     memset (&f, 0, sizeof(Flow));
7110     memset(&tv, 0, sizeof (ThreadVars));
7111     memset(&stt, 0, sizeof (StreamTcpThread));
7112     memset(&tcph, 0, sizeof (TCPHdr));
7113     FLOW_INITIALIZE(&f);
7114     p->flow = &f;
7115 
7116     StreamTcpUTInit(&stt.ra_ctx);
7117     stream_config.async_oneside = TRUE;
7118 
7119     tcph.th_win = htons(5480);
7120     tcph.th_seq = htonl(10);
7121     tcph.th_ack = htonl(1);
7122     tcph.th_flags = TH_SYN|TH_ACK;
7123     p->tcph = &tcph;
7124 
7125     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
7126 
7127     p->tcph->th_seq = htonl(11);
7128     p->tcph->th_ack = htonl(1);
7129     p->tcph->th_flags = TH_ACK;
7130     p->flowflags = FLOW_PKT_TOSERVER;
7131 
7132     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
7133 
7134     p->tcph->th_seq = htonl(11);
7135     p->tcph->th_ack = htonl(1);
7136     p->tcph->th_flags = TH_ACK|TH_PUSH;
7137     p->flowflags = FLOW_PKT_TOSERVER;
7138 
7139     StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
7140     p->payload = payload;
7141     p->payload_len = 3;
7142 
7143     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
7144 
7145     p->tcph->th_seq = htonl(2);
7146     p->tcph->th_ack = htonl(1);
7147     p->tcph->th_flags = TH_ACK|TH_PUSH;
7148     p->flowflags = FLOW_PKT_TOSERVER;
7149 
7150     StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
7151     p->payload = payload;
7152     p->payload_len = 3;
7153 
7154     FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
7155 
7156     FAIL_IF(! (((TcpSession *)(p->flow->protoctx))->flags & STREAMTCP_FLAG_ASYNC));
7157 
7158     FAIL_IF(((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED);
7159 
7160     FAIL_IF(((TcpSession *)(p->flow->protoctx))->server.last_ack != 2 &&
7161             ((TcpSession *)(p->flow->protoctx))->client.next_seq != 1);
7162 
7163     StreamTcpSessionClear(p->flow->protoctx);
7164     SCFree(p);
7165     FLOW_DESTROY(&f);
7166     StreamTcpUTDeinit(stt.ra_ctx);
7167     PASS;
7168 }
7169 
7170 /**
7171  *  \test   Test the setting up a TCP session when we are seeing asynchronous
7172  *          stream, while we missed the SYN and SYN/ACK packets in that stream.
7173  *
7174  *  \retval On success it returns 1 and on failure 0.
7175  */
7176 
StreamTcpTest12(void)7177 static int StreamTcpTest12 (void)
7178 {
7179     Packet *p = SCMalloc(SIZE_OF_PACKET);
7180     if (unlikely(p == NULL))
7181         return 0;
7182     Flow f;
7183     ThreadVars tv;
7184     StreamTcpThread stt;
7185     TCPHdr tcph;
7186     uint8_t payload[4];
7187     memset(p, 0, SIZE_OF_PACKET);
7188     PacketQueueNoLock pq;
7189     memset(&pq,0,sizeof(PacketQueueNoLock));
7190     memset (&f, 0, sizeof(Flow));
7191     memset(&tv, 0, sizeof (ThreadVars));
7192     memset(&stt, 0, sizeof (StreamTcpThread));
7193     memset(&tcph, 0, sizeof (TCPHdr));
7194     FLOW_INITIALIZE(&f);
7195     p->flow = &f;
7196 
7197     StreamTcpUTInit(&stt.ra_ctx);
7198 
7199     tcph.th_win = htons(5480);
7200     tcph.th_seq = htonl(10);
7201     tcph.th_ack = htonl(11);
7202     tcph.th_flags = TH_ACK;
7203     p->tcph = &tcph;
7204     int ret = 0;
7205 
7206     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7207         goto end;
7208 
7209     p->tcph->th_seq = htonl(10);
7210     p->tcph->th_ack = htonl(11);
7211     p->tcph->th_flags = TH_ACK|TH_PUSH;
7212     p->flowflags = FLOW_PKT_TOSERVER;
7213 
7214     StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
7215     p->payload = payload;
7216     p->payload_len = 3;
7217 
7218     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7219         goto end;
7220 
7221     p->tcph->th_seq = htonl(6);
7222     p->tcph->th_ack = htonl(11);
7223     p->tcph->th_flags = TH_ACK|TH_PUSH;
7224     p->flowflags = FLOW_PKT_TOSERVER;
7225 
7226     StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
7227     p->payload = payload;
7228     p->payload_len = 3;
7229 
7230     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7231         goto end;
7232 
7233     if (stream_config.async_oneside != TRUE) {
7234         ret = 1;
7235         goto end;
7236     }
7237 
7238     if (! (((TcpSession *)(p->flow->protoctx))->flags & STREAMTCP_FLAG_ASYNC)) {
7239         printf("failed in setting asynchronous session\n");
7240         goto end;
7241     }
7242 
7243     if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED) {
7244         printf("failed in setting state\n");
7245         goto end;
7246     }
7247 
7248     if (((TcpSession *)(p->flow->protoctx))->client.last_ack != 6 &&
7249             ((TcpSession *)(p->flow->protoctx))->server.next_seq != 11) {
7250         printf("failed in seq %"PRIu32" match\n",
7251                 ((TcpSession *)(p->flow->protoctx))->client.last_ack);
7252         goto end;
7253     }
7254 
7255     StreamTcpSessionClear(p->flow->protoctx);
7256 
7257     ret = 1;
7258 end:
7259     SCFree(p);
7260     FLOW_DESTROY(&f);
7261     StreamTcpUTDeinit(stt.ra_ctx);
7262     return ret;
7263 }
7264 
7265 /**
7266  *  \test   Test the setting up a TCP session when we are seeing asynchronous
7267  *          stream, while we missed the SYN and SYN/ACK packets in that stream.
7268  *          Later, we start to receive the packet from other end stream too.
7269  *
7270  *  \retval On success it returns 1 and on failure 0.
7271  */
7272 
StreamTcpTest13(void)7273 static int StreamTcpTest13 (void)
7274 {
7275     Packet *p = SCMalloc(SIZE_OF_PACKET);
7276     if (unlikely(p == NULL))
7277         return 0;
7278     Flow f;
7279     ThreadVars tv;
7280     StreamTcpThread stt;
7281     TCPHdr tcph;
7282     uint8_t payload[4];
7283     memset(p, 0, SIZE_OF_PACKET);
7284     PacketQueueNoLock pq;
7285     memset(&pq,0,sizeof(PacketQueueNoLock));
7286     memset (&f, 0, sizeof(Flow));
7287     memset(&tv, 0, sizeof (ThreadVars));
7288     memset(&stt, 0, sizeof (StreamTcpThread));
7289     memset(&tcph, 0, sizeof (TCPHdr));
7290     FLOW_INITIALIZE(&f);
7291     p->flow = &f;
7292 
7293     StreamTcpUTInit(&stt.ra_ctx);
7294 
7295     tcph.th_win = htons(5480);
7296     tcph.th_seq = htonl(10);
7297     tcph.th_ack = htonl(11);
7298     tcph.th_flags = TH_ACK;
7299     p->tcph = &tcph;
7300     int ret = 0;
7301 
7302     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7303         goto end;
7304 
7305     p->tcph->th_seq = htonl(10);
7306     p->tcph->th_ack = htonl(11);
7307     p->tcph->th_flags = TH_ACK|TH_PUSH;
7308     p->flowflags = FLOW_PKT_TOSERVER;
7309 
7310     StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
7311     p->payload = payload;
7312     p->payload_len = 3;
7313 
7314     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7315         goto end;
7316 
7317     p->tcph->th_seq = htonl(6);
7318     p->tcph->th_ack = htonl(11);
7319     p->tcph->th_flags = TH_ACK|TH_PUSH;
7320     p->flowflags = FLOW_PKT_TOSERVER;
7321 
7322     StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
7323     p->payload = payload;
7324     p->payload_len = 3;
7325 
7326     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7327         goto end;
7328 
7329     if (stream_config.async_oneside != TRUE) {
7330         ret = 1;
7331         goto end;
7332     }
7333 
7334     if (! (((TcpSession *)(p->flow->protoctx))->flags & STREAMTCP_FLAG_ASYNC)) {
7335         printf("failed in setting asynchronous session\n");
7336         goto end;
7337     }
7338 
7339     if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED) {
7340         printf("failed in setting state\n");
7341         goto end;
7342     }
7343 
7344     p->tcph->th_seq = htonl(11);
7345     p->tcph->th_ack = htonl(9);
7346     p->tcph->th_flags = TH_ACK|TH_PUSH;
7347     p->flowflags = FLOW_PKT_TOCLIENT;
7348 
7349     StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
7350     p->payload = payload;
7351     p->payload_len = 3;
7352 
7353     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7354         goto end;
7355 
7356     if (((TcpSession *)(p->flow->protoctx))->client.last_ack != 9 &&
7357             ((TcpSession *)(p->flow->protoctx))->server.next_seq != 14) {
7358         printf("failed in seq %"PRIu32" match\n",
7359                 ((TcpSession *)(p->flow->protoctx))->client.last_ack);
7360         goto end;
7361     }
7362 
7363     StreamTcpSessionPktFree(p);
7364 
7365     ret = 1;
7366 end:
7367     SCFree(p);
7368     FLOW_DESTROY(&f);
7369     StreamTcpUTDeinit(stt.ra_ctx);
7370     return ret;
7371 }
7372 
7373 /* Dummy conf string to setup the OS policy for unit testing */
7374 static const char *dummy_conf_string =
7375     "%YAML 1.1\n"
7376     "---\n"
7377     "\n"
7378     "default-log-dir: /var/log/eidps\n"
7379     "\n"
7380     "logging:\n"
7381     "\n"
7382     "  default-log-level: debug\n"
7383     "\n"
7384     "  default-format: \"<%t> - <%l>\"\n"
7385     "\n"
7386     "  default-startup-message: Your IDS has started.\n"
7387     "\n"
7388     "  default-output-filter:\n"
7389     "\n"
7390     "host-os-policy:\n"
7391     "\n"
7392     " windows: 192.168.0.1\n"
7393     "\n"
7394     " linux: 192.168.0.2\n"
7395     "\n";
7396 /* Dummy conf string to setup the OS policy for unit testing */
7397 static const char *dummy_conf_string1 =
7398     "%YAML 1.1\n"
7399     "---\n"
7400     "\n"
7401     "default-log-dir: /var/log/eidps\n"
7402     "\n"
7403     "logging:\n"
7404     "\n"
7405     "  default-log-level: debug\n"
7406     "\n"
7407     "  default-format: \"<%t> - <%l>\"\n"
7408     "\n"
7409     "  default-startup-message: Your IDS has started.\n"
7410     "\n"
7411     "  default-output-filter:\n"
7412     "\n"
7413     "host-os-policy:\n"
7414     "\n"
7415     " windows: 192.168.0.0/24," "192.168.1.1\n"
7416     "\n"
7417     " linux: 192.168.1.0/24," "192.168.0.1\n"
7418     "\n";
7419 
7420 /**
7421  *  \brief  Function to parse the dummy conf string and get the value of IP
7422  *          address for the corresponding OS policy type.
7423  *
7424  *  \param  conf_val_name   Name of the OS policy type
7425  *  \retval returns IP address as string on success and NULL on failure
7426  */
StreamTcpParseOSPolicy(char * conf_var_name)7427 static const char *StreamTcpParseOSPolicy (char *conf_var_name)
7428 {
7429     SCEnter();
7430     char conf_var_type_name[15] = "host-os-policy";
7431     char *conf_var_full_name = NULL;
7432     const char *conf_var_value = NULL;
7433 
7434     if (conf_var_name == NULL)
7435         goto end;
7436 
7437     /* the + 2 is for the '.' and the string termination character '\0' */
7438     conf_var_full_name = (char *)SCMalloc(strlen(conf_var_type_name) +
7439                                         strlen(conf_var_name) + 2);
7440     if (conf_var_full_name == NULL)
7441         goto end;
7442 
7443     if (snprintf(conf_var_full_name,
7444                  strlen(conf_var_type_name) + strlen(conf_var_name) + 2, "%s.%s",
7445                  conf_var_type_name, conf_var_name) < 0) {
7446         SCLogError(SC_ERR_INVALID_VALUE, "Error in making the conf full name");
7447         goto end;
7448     }
7449 
7450     if (ConfGet(conf_var_full_name, &conf_var_value) != 1) {
7451         SCLogError(SC_ERR_UNKNOWN_VALUE, "Error in getting conf value for conf name %s",
7452                     conf_var_full_name);
7453         goto end;
7454     }
7455 
7456     SCLogDebug("Value obtained from the yaml conf file, for the var "
7457                "\"%s\" is \"%s\"", conf_var_name, conf_var_value);
7458 
7459  end:
7460     if (conf_var_full_name != NULL)
7461         SCFree(conf_var_full_name);
7462     SCReturnCharPtr(conf_var_value);
7463 
7464 
7465 }
7466 /**
7467  *  \test   Test the setting up a OS policy. Te OS policy values are defined in
7468  *          the config string "dummy_conf_string"
7469  *
7470  *  \retval On success it returns 1 and on failure 0
7471  */
7472 
StreamTcpTest14(void)7473 static int StreamTcpTest14 (void)
7474 {
7475     Packet *p = SCMalloc(SIZE_OF_PACKET);
7476     if (unlikely(p == NULL))
7477         return 0;
7478     Flow f;
7479     ThreadVars tv;
7480     StreamTcpThread stt;
7481     TCPHdr tcph;
7482     uint8_t payload[4];
7483     struct in_addr addr;
7484     IPV4Hdr ipv4h;
7485     char os_policy_name[10] = "windows";
7486     const char *ip_addr;
7487     PacketQueueNoLock pq;
7488     memset(&pq,0,sizeof(PacketQueueNoLock));
7489 
7490     memset(p, 0, SIZE_OF_PACKET);
7491     memset (&f, 0, sizeof(Flow));
7492     memset(&tv, 0, sizeof (ThreadVars));
7493     memset(&stt, 0, sizeof (StreamTcpThread));
7494     memset(&tcph, 0, sizeof (TCPHdr));
7495     memset(&addr, 0, sizeof(addr));
7496     memset(&ipv4h, 0, sizeof(ipv4h));
7497     FLOW_INITIALIZE(&f);
7498     p->flow = &f;
7499     int ret = 0;
7500 
7501     StreamTcpUTInit(&stt.ra_ctx);
7502 
7503     /* Load the config string in to parser */
7504     ConfCreateContextBackup();
7505     ConfInit();
7506     ConfYamlLoadString(dummy_conf_string, strlen(dummy_conf_string));
7507 
7508     /* Get the IP address as string and add it to Host info tree for lookups */
7509     ip_addr = StreamTcpParseOSPolicy(os_policy_name);
7510     SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
7511     strlcpy(os_policy_name, "linux\0", sizeof(os_policy_name));
7512     ip_addr = StreamTcpParseOSPolicy(os_policy_name);
7513     SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
7514     addr.s_addr = inet_addr("192.168.0.1");
7515     tcph.th_win = htons(5480);
7516     tcph.th_seq = htonl(10);
7517     tcph.th_ack = htonl(20);
7518     tcph.th_flags = TH_ACK|TH_PUSH;
7519     p->tcph = &tcph;
7520     p->dst.family = AF_INET;
7521     p->dst.address.address_un_data32[0] = addr.s_addr;
7522     p->ip4h = &ipv4h;
7523 
7524     StreamTcpCreateTestPacket(payload, 0x41, 3, sizeof(payload)); /*AAA*/
7525     p->payload = payload;
7526     p->payload_len = 3;
7527 
7528     FLOWLOCK_WRLOCK(&f);
7529     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7530         goto end;
7531 
7532     p->tcph->th_seq = htonl(20);
7533     p->tcph->th_ack = htonl(13);
7534     p->tcph->th_flags = TH_ACK|TH_PUSH;
7535     p->flowflags = FLOW_PKT_TOCLIENT;
7536 
7537     StreamTcpCreateTestPacket(payload, 0x42, 3, sizeof(payload)); /*BBB*/
7538     p->payload = payload;
7539     p->payload_len = 3;
7540 
7541     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7542         goto end;
7543 
7544     p->tcph->th_seq = htonl(15);
7545     p->tcph->th_ack = htonl(23);
7546     p->tcph->th_flags = TH_ACK|TH_PUSH;
7547     p->flowflags = FLOW_PKT_TOSERVER;
7548 
7549     StreamTcpCreateTestPacket(payload, 0x43, 3, sizeof(payload)); /*CCC*/
7550     p->payload = payload;
7551     p->payload_len = 3;
7552 
7553     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7554         goto end;
7555 
7556     p->tcph->th_seq = htonl(14);
7557     p->tcph->th_ack = htonl(23);
7558     p->tcph->th_flags = TH_ACK|TH_PUSH;
7559     p->flowflags = FLOW_PKT_TOSERVER;
7560 
7561     StreamTcpCreateTestPacket(payload, 0x43, 3, sizeof(payload)); /*CCC*/
7562     p->payload = payload;
7563     p->payload_len = 3;
7564 
7565     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7566         goto end;
7567 
7568     addr.s_addr = inet_addr("192.168.0.2");
7569     p->tcph->th_seq = htonl(25);
7570     p->tcph->th_ack = htonl(13);
7571     p->tcph->th_flags = TH_ACK|TH_PUSH;
7572     p->flowflags = FLOW_PKT_TOCLIENT;
7573     p->dst.address.address_un_data32[0] = addr.s_addr;
7574 
7575     StreamTcpCreateTestPacket(payload, 0x44, 3, sizeof(payload)); /*DDD*/
7576     p->payload = payload;
7577     p->payload_len = 3;
7578 
7579     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7580         goto end;
7581 
7582     p->tcph->th_seq = htonl(24);
7583     p->tcph->th_ack = htonl(13);
7584     p->tcph->th_flags = TH_ACK|TH_PUSH;
7585     p->flowflags = FLOW_PKT_TOCLIENT;
7586 
7587     StreamTcpCreateTestPacket(payload, 0x44, 3, sizeof(payload)); /*DDD*/
7588     p->payload = payload;
7589     p->payload_len = 3;
7590 
7591     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7592         goto end;
7593 
7594     if (stream_config.midstream != TRUE) {
7595         ret = 1;
7596         goto end;
7597     }
7598     if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED)
7599         goto end;
7600 
7601     if (((TcpSession *)(p->flow->protoctx))->client.next_seq != 13 &&
7602             ((TcpSession *)(p->flow->protoctx))->server.next_seq != 23) {
7603         printf("failed in next_seq match client.next_seq %"PRIu32""
7604                 " server.next_seq %"PRIu32"\n",
7605                 ((TcpSession *)(p->flow->protoctx))->client.next_seq,
7606                 ((TcpSession *)(p->flow->protoctx))->server.next_seq);
7607         goto end;
7608     }
7609 
7610     if (((TcpSession *)(p->flow->protoctx))->client.os_policy !=
7611             OS_POLICY_WINDOWS && ((TcpSession *)
7612             (p->flow->protoctx))->server.os_policy != OS_POLICY_LINUX)
7613     {
7614         printf("failed in setting up OS policy, client.os_policy: %"PRIu8""
7615                 " should be %"PRIu8" and server.os_policy: %"PRIu8""
7616                 " should be %"PRIu8"\n", ((TcpSession *)
7617                 (p->flow->protoctx))->client.os_policy, (uint8_t)OS_POLICY_WINDOWS,
7618                 ((TcpSession *)(p->flow->protoctx))->server.os_policy,
7619                 (uint8_t)OS_POLICY_LINUX);
7620         goto end;
7621     }
7622     StreamTcpSessionClear(p->flow->protoctx);
7623 
7624     ret = 1;
7625 end:
7626     ConfDeInit();
7627     ConfRestoreContextBackup();
7628     FLOWLOCK_UNLOCK(&f);
7629     SCFree(p);
7630     FLOW_DESTROY(&f);
7631     StreamTcpUTDeinit(stt.ra_ctx);
7632     return ret;
7633 }
7634 
7635 /**
7636  *  \test   Test the setting up a TCP session using the 4WHS:
7637  *          SYN, SYN, SYN/ACK, ACK
7638  *
7639  *  \retval On success it returns 1 and on failure 0.
7640  */
7641 
StreamTcp4WHSTest01(void)7642 static int StreamTcp4WHSTest01 (void)
7643 {
7644     int ret = 0;
7645     Packet *p = SCMalloc(SIZE_OF_PACKET);
7646     if (unlikely(p == NULL))
7647         return 0;
7648     Flow f;
7649     ThreadVars tv;
7650     StreamTcpThread stt;
7651     TCPHdr tcph;
7652     memset(p, 0, SIZE_OF_PACKET);
7653     PacketQueueNoLock pq;
7654     memset(&pq,0,sizeof(PacketQueueNoLock));
7655     memset (&f, 0, sizeof(Flow));
7656     memset(&tv, 0, sizeof (ThreadVars));
7657     memset(&stt, 0, sizeof (StreamTcpThread));
7658     memset(&tcph, 0, sizeof (TCPHdr));
7659     FLOW_INITIALIZE(&f);
7660     p->flow = &f;
7661 
7662     StreamTcpUTInit(&stt.ra_ctx);
7663 
7664     tcph.th_win = htons(5480);
7665     tcph.th_seq = htonl(10);
7666     tcph.th_ack = 0;
7667     tcph.th_flags = TH_SYN;
7668     p->tcph = &tcph;
7669 
7670     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7671         goto end;
7672 
7673     p->tcph->th_seq = htonl(20);
7674     p->tcph->th_ack = 0;
7675     p->tcph->th_flags = TH_SYN;
7676     p->flowflags = FLOW_PKT_TOCLIENT;
7677 
7678     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7679         goto end;
7680 
7681     if ((!(((TcpSession *)(p->flow->protoctx))->flags & STREAMTCP_FLAG_4WHS))) {
7682         printf("STREAMTCP_FLAG_4WHS flag not set: ");
7683         goto end;
7684     }
7685 
7686     p->tcph->th_seq = htonl(10);
7687     p->tcph->th_ack = htonl(21); /* the SYN/ACK uses the SEQ from the first SYN pkt */
7688     p->tcph->th_flags = TH_SYN|TH_ACK;
7689     p->flowflags = FLOW_PKT_TOSERVER;
7690 
7691     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7692         goto end;
7693 
7694     p->tcph->th_seq = htonl(21);
7695     p->tcph->th_ack = htonl(10);
7696     p->tcph->th_flags = TH_ACK;
7697     p->flowflags = FLOW_PKT_TOCLIENT;
7698 
7699     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7700         goto end;
7701 
7702     if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED) {
7703         printf("state is not ESTABLISHED: ");
7704         goto end;
7705     }
7706 
7707     ret = 1;
7708 end:
7709     StreamTcpSessionClear(p->flow->protoctx);
7710     SCFree(p);
7711     FLOW_DESTROY(&f);
7712     StreamTcpUTDeinit(stt.ra_ctx);
7713     return ret;
7714 }
7715 
7716 /**
7717  *  \test   set up a TCP session using the 4WHS:
7718  *          SYN, SYN, SYN/ACK, ACK, but the SYN/ACK does
7719  *          not have the right SEQ
7720  *
7721  *  \retval On success it returns 1 and on failure 0.
7722  */
7723 
StreamTcp4WHSTest02(void)7724 static int StreamTcp4WHSTest02 (void)
7725 {
7726     int ret = 0;
7727     Packet *p = SCMalloc(SIZE_OF_PACKET);
7728     if (unlikely(p == NULL))
7729         return 0;
7730     Flow f;
7731     ThreadVars tv;
7732     StreamTcpThread stt;
7733     TCPHdr tcph;
7734     memset(p, 0, SIZE_OF_PACKET);
7735     PacketQueueNoLock pq;
7736     memset(&pq,0,sizeof(PacketQueueNoLock));
7737     memset (&f, 0, sizeof(Flow));
7738     memset(&tv, 0, sizeof (ThreadVars));
7739     memset(&stt, 0, sizeof (StreamTcpThread));
7740     memset(&tcph, 0, sizeof (TCPHdr));
7741     FLOW_INITIALIZE(&f);
7742     p->flow = &f;
7743 
7744     StreamTcpUTInit(&stt.ra_ctx);
7745 
7746     tcph.th_win = htons(5480);
7747     tcph.th_seq = htonl(10);
7748     tcph.th_ack = 0;
7749     tcph.th_flags = TH_SYN;
7750     p->tcph = &tcph;
7751 
7752     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7753         goto end;
7754 
7755     p->tcph->th_seq = htonl(20);
7756     p->tcph->th_ack = 0;
7757     p->tcph->th_flags = TH_SYN;
7758     p->flowflags = FLOW_PKT_TOCLIENT;
7759 
7760     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7761         goto end;
7762 
7763     if ((!(((TcpSession *)(p->flow->protoctx))->flags & STREAMTCP_FLAG_4WHS))) {
7764         printf("STREAMTCP_FLAG_4WHS flag not set: ");
7765         goto end;
7766     }
7767 
7768     p->tcph->th_seq = htonl(30);
7769     p->tcph->th_ack = htonl(21); /* the SYN/ACK uses the SEQ from the first SYN pkt */
7770     p->tcph->th_flags = TH_SYN|TH_ACK;
7771     p->flowflags = FLOW_PKT_TOSERVER;
7772 
7773     if (StreamTcpPacket(&tv, p, &stt, &pq) != -1) {
7774         printf("SYN/ACK pkt not rejected but it should have: ");
7775         goto end;
7776     }
7777 
7778     ret = 1;
7779 end:
7780     StreamTcpSessionClear(p->flow->protoctx);
7781     SCFree(p);
7782     FLOW_DESTROY(&f);
7783     StreamTcpUTDeinit(stt.ra_ctx);
7784     return ret;
7785 }
7786 
7787 /**
7788  *  \test   set up a TCP session using the 4WHS:
7789  *          SYN, SYN, SYN/ACK, ACK: however the SYN/ACK and ACK
7790  *          are part of a normal 3WHS
7791  *
7792  *  \retval On success it returns 1 and on failure 0.
7793  */
7794 
StreamTcp4WHSTest03(void)7795 static int StreamTcp4WHSTest03 (void)
7796 {
7797     int ret = 0;
7798     Packet *p = SCMalloc(SIZE_OF_PACKET);
7799     FAIL_IF(unlikely(p == NULL));
7800     Flow f;
7801     ThreadVars tv;
7802     StreamTcpThread stt;
7803     TCPHdr tcph;
7804     memset(p, 0, SIZE_OF_PACKET);
7805     PacketQueueNoLock pq;
7806     memset(&pq,0,sizeof(PacketQueueNoLock));
7807     memset (&f, 0, sizeof(Flow));
7808     memset(&tv, 0, sizeof (ThreadVars));
7809     memset(&stt, 0, sizeof (StreamTcpThread));
7810     memset(&tcph, 0, sizeof (TCPHdr));
7811     FLOW_INITIALIZE(&f);
7812     p->flow = &f;
7813 
7814     StreamTcpUTInit(&stt.ra_ctx);
7815 
7816     tcph.th_win = htons(5480);
7817     tcph.th_seq = htonl(10);
7818     tcph.th_ack = 0;
7819     tcph.th_flags = TH_SYN;
7820     p->tcph = &tcph;
7821 
7822     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7823         goto end;
7824 
7825     p->tcph->th_seq = htonl(20);
7826     p->tcph->th_ack = 0;
7827     p->tcph->th_flags = TH_SYN;
7828     p->flowflags = FLOW_PKT_TOCLIENT;
7829 
7830     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7831         goto end;
7832 
7833     if ((!(((TcpSession *)(p->flow->protoctx))->flags & STREAMTCP_FLAG_4WHS))) {
7834         printf("STREAMTCP_FLAG_4WHS flag not set: ");
7835         goto end;
7836     }
7837 
7838     p->tcph->th_seq = htonl(30);
7839     p->tcph->th_ack = htonl(11);
7840     p->tcph->th_flags = TH_SYN|TH_ACK;
7841     p->flowflags = FLOW_PKT_TOCLIENT;
7842 
7843     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7844         goto end;
7845 
7846     p->tcph->th_seq = htonl(11);
7847     p->tcph->th_ack = htonl(31);
7848     p->tcph->th_flags = TH_ACK;
7849     p->flowflags = FLOW_PKT_TOSERVER;
7850 
7851     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7852         goto end;
7853 
7854     if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED) {
7855         printf("state is not ESTABLISHED: ");
7856         goto end;
7857     }
7858 
7859     ret = 1;
7860 end:
7861     StreamTcpSessionClear(p->flow->protoctx);
7862     SCFree(p);
7863     FLOW_DESTROY(&f);
7864     StreamTcpUTDeinit(stt.ra_ctx);
7865     return ret;
7866 }
7867 
7868 /**
7869  *  \test   Test the setting up a OS policy. Te OS policy values are defined in
7870  *          the config string "dummy_conf_string1"
7871  *
7872  *  \retval On success it returns 1 and on failure 0
7873  */
7874 
StreamTcpTest15(void)7875 static int StreamTcpTest15 (void)
7876 {
7877     Packet *p = SCMalloc(SIZE_OF_PACKET);
7878     if (unlikely(p == NULL))
7879         return 0;
7880     Flow f;
7881     ThreadVars tv;
7882     StreamTcpThread stt;
7883     TCPHdr tcph;
7884     uint8_t payload[4];
7885     struct in_addr addr;
7886     IPV4Hdr ipv4h;
7887     char os_policy_name[10] = "windows";
7888     const char *ip_addr;
7889     PacketQueueNoLock pq;
7890     memset(&pq,0,sizeof(PacketQueueNoLock));
7891 
7892     memset(p, 0, SIZE_OF_PACKET);
7893     memset (&f, 0, sizeof(Flow));
7894     memset(&tv, 0, sizeof (ThreadVars));
7895     memset(&stt, 0, sizeof (StreamTcpThread));
7896     memset(&tcph, 0, sizeof (TCPHdr));
7897     memset(&addr, 0, sizeof(addr));
7898     memset(&ipv4h, 0, sizeof(ipv4h));
7899     FLOW_INITIALIZE(&f);
7900     p->flow = &f;
7901     int ret = 0;
7902 
7903     StreamTcpUTInit(&stt.ra_ctx);
7904 
7905     /* Load the config string in to parser */
7906     ConfCreateContextBackup();
7907     ConfInit();
7908     ConfYamlLoadString(dummy_conf_string1, strlen(dummy_conf_string1));
7909 
7910     /* Get the IP address as string and add it to Host info tree for lookups */
7911     ip_addr = StreamTcpParseOSPolicy(os_policy_name);
7912     SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
7913     strlcpy(os_policy_name, "linux\0", sizeof(os_policy_name));
7914     ip_addr = StreamTcpParseOSPolicy(os_policy_name);
7915     SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
7916     addr.s_addr = inet_addr("192.168.0.20");
7917     tcph.th_win = htons(5480);
7918     tcph.th_seq = htonl(10);
7919     tcph.th_ack = htonl(20);
7920     tcph.th_flags = TH_ACK|TH_PUSH;
7921     p->tcph = &tcph;
7922     p->dst.family = AF_INET;
7923     p->dst.address.address_un_data32[0] = addr.s_addr;
7924     p->ip4h = &ipv4h;
7925 
7926     StreamTcpCreateTestPacket(payload, 0x41, 3, sizeof(payload)); /*AAA*/
7927     p->payload = payload;
7928     p->payload_len = 3;
7929 
7930     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7931         goto end;
7932 
7933     p->tcph->th_seq = htonl(20);
7934     p->tcph->th_ack = htonl(13);
7935     p->tcph->th_flags = TH_ACK|TH_PUSH;
7936     p->flowflags = FLOW_PKT_TOCLIENT;
7937 
7938     StreamTcpCreateTestPacket(payload, 0x42, 3, sizeof(payload)); /*BBB*/
7939     p->payload = payload;
7940     p->payload_len = 3;
7941 
7942     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7943         goto end;
7944 
7945     p->tcph->th_seq = htonl(15);
7946     p->tcph->th_ack = htonl(23);
7947     p->tcph->th_flags = TH_ACK|TH_PUSH;
7948     p->flowflags = FLOW_PKT_TOSERVER;
7949 
7950     StreamTcpCreateTestPacket(payload, 0x43, 3, sizeof(payload)); /*CCC*/
7951     p->payload = payload;
7952     p->payload_len = 3;
7953 
7954     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7955         goto end;
7956 
7957     p->tcph->th_seq = htonl(14);
7958     p->tcph->th_ack = htonl(23);
7959     p->tcph->th_flags = TH_ACK|TH_PUSH;
7960     p->flowflags = FLOW_PKT_TOSERVER;
7961 
7962     StreamTcpCreateTestPacket(payload, 0x43, 3, sizeof(payload)); /*CCC*/
7963     p->payload = payload;
7964     p->payload_len = 3;
7965 
7966     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7967         goto end;
7968 
7969     addr.s_addr = inet_addr("192.168.1.20");
7970     p->tcph->th_seq = htonl(25);
7971     p->tcph->th_ack = htonl(13);
7972     p->tcph->th_flags = TH_ACK|TH_PUSH;
7973     p->flowflags = FLOW_PKT_TOCLIENT;
7974     p->dst.address.address_un_data32[0] = addr.s_addr;
7975 
7976     StreamTcpCreateTestPacket(payload, 0x44, 3, sizeof(payload)); /*DDD*/
7977     p->payload = payload;
7978     p->payload_len = 3;
7979 
7980     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7981         goto end;
7982 
7983     p->tcph->th_seq = htonl(24);
7984     p->tcph->th_ack = htonl(13);
7985     p->tcph->th_flags = TH_ACK|TH_PUSH;
7986     p->flowflags = FLOW_PKT_TOCLIENT;
7987 
7988     StreamTcpCreateTestPacket(payload, 0x44, 3, sizeof(payload)); /*DDD*/
7989     p->payload = payload;
7990     p->payload_len = 3;
7991 
7992     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
7993         goto end;
7994 
7995     if (stream_config.midstream != TRUE) {
7996         ret = 1;
7997         goto end;
7998     }
7999     if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED)
8000         goto end;
8001 
8002     if (((TcpSession *)(p->flow->protoctx))->client.next_seq != 13 &&
8003             ((TcpSession *)(p->flow->protoctx))->server.next_seq != 23) {
8004         printf("failed in next_seq match client.next_seq %"PRIu32""
8005                 " server.next_seq %"PRIu32"\n",
8006                 ((TcpSession *)(p->flow->protoctx))->client.next_seq,
8007                 ((TcpSession *)(p->flow->protoctx))->server.next_seq);
8008         goto end;
8009     }
8010 
8011     if (((TcpSession *)(p->flow->protoctx))->client.os_policy !=
8012             OS_POLICY_WINDOWS && ((TcpSession *)
8013             (p->flow->protoctx))->server.os_policy != OS_POLICY_LINUX)
8014     {
8015         printf("failed in setting up OS policy, client.os_policy: %"PRIu8""
8016                 " should be %"PRIu8" and server.os_policy: %"PRIu8""
8017                 " should be %"PRIu8"\n", ((TcpSession *)
8018                 (p->flow->protoctx))->client.os_policy, (uint8_t)OS_POLICY_WINDOWS,
8019                 ((TcpSession *)(p->flow->protoctx))->server.os_policy,
8020                 (uint8_t)OS_POLICY_LINUX);
8021         goto end;
8022     }
8023     StreamTcpSessionPktFree(p);
8024 
8025     ret = 1;
8026 end:
8027     ConfDeInit();
8028     ConfRestoreContextBackup();
8029     SCFree(p);
8030     FLOW_DESTROY(&f);
8031     StreamTcpUTDeinit(stt.ra_ctx);
8032     return ret;
8033 }
8034 
8035 /**
8036  *  \test   Test the setting up a OS policy. Te OS policy values are defined in
8037  *          the config string "dummy_conf_string1"
8038  *
8039  *  \retval On success it returns 1 and on failure 0
8040  */
8041 
StreamTcpTest16(void)8042 static int StreamTcpTest16 (void)
8043 {
8044     Packet *p = SCMalloc(SIZE_OF_PACKET);
8045     if (unlikely(p == NULL))
8046         return 0;
8047     Flow f;
8048     ThreadVars tv;
8049     StreamTcpThread stt;
8050     TCPHdr tcph;
8051     uint8_t payload[4];
8052     struct in_addr addr;
8053     IPV4Hdr ipv4h;
8054     char os_policy_name[10] = "windows";
8055     const char *ip_addr;
8056     PacketQueueNoLock pq;
8057     memset(&pq,0,sizeof(PacketQueueNoLock));
8058 
8059     memset(p, 0, SIZE_OF_PACKET);
8060     memset (&f, 0, sizeof(Flow));
8061     memset(&tv, 0, sizeof (ThreadVars));
8062     memset(&stt, 0, sizeof (StreamTcpThread));
8063     memset(&tcph, 0, sizeof (TCPHdr));
8064     memset(&addr, 0, sizeof(addr));
8065     memset(&ipv4h, 0, sizeof(ipv4h));
8066     FLOW_INITIALIZE(&f);
8067     p->flow = &f;
8068     int ret = 0;
8069 
8070     StreamTcpUTInit(&stt.ra_ctx);
8071 
8072     /* Load the config string in to parser */
8073     ConfCreateContextBackup();
8074     ConfInit();
8075     ConfYamlLoadString(dummy_conf_string1, strlen(dummy_conf_string1));
8076 
8077     /* Get the IP address as string and add it to Host info tree for lookups */
8078     ip_addr = StreamTcpParseOSPolicy(os_policy_name);
8079     SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
8080     strlcpy(os_policy_name, "linux\0", sizeof(os_policy_name));
8081     ip_addr = StreamTcpParseOSPolicy(os_policy_name);
8082     SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
8083     addr.s_addr = inet_addr("192.168.0.1");
8084     tcph.th_win = htons(5480);
8085     tcph.th_seq = htonl(10);
8086     tcph.th_ack = htonl(20);
8087     tcph.th_flags = TH_ACK|TH_PUSH;
8088     p->tcph = &tcph;
8089     p->dst.family = AF_INET;
8090     p->dst.address.address_un_data32[0] = addr.s_addr;
8091     p->ip4h = &ipv4h;
8092 
8093     StreamTcpCreateTestPacket(payload, 0x41, 3, sizeof(payload)); /*AAA*/
8094     p->payload = payload;
8095     p->payload_len = 3;
8096 
8097     FLOWLOCK_WRLOCK(&f);
8098     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
8099         goto end;
8100 
8101     p->tcph->th_seq = htonl(20);
8102     p->tcph->th_ack = htonl(13);
8103     p->tcph->th_flags = TH_ACK|TH_PUSH;
8104     p->flowflags = FLOW_PKT_TOCLIENT;
8105 
8106     StreamTcpCreateTestPacket(payload, 0x42, 3, sizeof(payload)); /*BBB*/
8107     p->payload = payload;
8108     p->payload_len = 3;
8109 
8110     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
8111         goto end;
8112 
8113     p->tcph->th_seq = htonl(15);
8114     p->tcph->th_ack = htonl(23);
8115     p->tcph->th_flags = TH_ACK|TH_PUSH;
8116     p->flowflags = FLOW_PKT_TOSERVER;
8117 
8118     StreamTcpCreateTestPacket(payload, 0x43, 3, sizeof(payload)); /*CCC*/
8119     p->payload = payload;
8120     p->payload_len = 3;
8121 
8122     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
8123         goto end;
8124 
8125     p->tcph->th_seq = htonl(14);
8126     p->tcph->th_ack = htonl(23);
8127     p->tcph->th_flags = TH_ACK|TH_PUSH;
8128     p->flowflags = FLOW_PKT_TOSERVER;
8129 
8130     StreamTcpCreateTestPacket(payload, 0x43, 3, sizeof(payload)); /*CCC*/
8131     p->payload = payload;
8132     p->payload_len = 3;
8133 
8134     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
8135         goto end;
8136 
8137     addr.s_addr = inet_addr("192.168.1.1");
8138     p->tcph->th_seq = htonl(25);
8139     p->tcph->th_ack = htonl(13);
8140     p->tcph->th_flags = TH_ACK|TH_PUSH;
8141     p->flowflags = FLOW_PKT_TOCLIENT;
8142     p->dst.address.address_un_data32[0] = addr.s_addr;
8143 
8144     StreamTcpCreateTestPacket(payload, 0x44, 3, sizeof(payload)); /*DDD*/
8145     p->payload = payload;
8146     p->payload_len = 3;
8147 
8148     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
8149         goto end;
8150 
8151     p->tcph->th_seq = htonl(24);
8152     p->tcph->th_ack = htonl(13);
8153     p->tcph->th_flags = TH_ACK|TH_PUSH;
8154     p->flowflags = FLOW_PKT_TOCLIENT;
8155 
8156     StreamTcpCreateTestPacket(payload, 0x44, 3, sizeof(payload)); /*DDD*/
8157     p->payload = payload;
8158     p->payload_len = 3;
8159 
8160     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
8161         goto end;
8162 
8163     if (stream_config.midstream != TRUE) {
8164         ret = 1;
8165         goto end;
8166     }
8167     if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED)
8168         goto end;
8169 
8170     if (((TcpSession *)(p->flow->protoctx))->client.next_seq != 13 &&
8171             ((TcpSession *)(p->flow->protoctx))->server.next_seq != 23) {
8172         printf("failed in next_seq match client.next_seq %"PRIu32""
8173                 " server.next_seq %"PRIu32"\n",
8174                 ((TcpSession *)(p->flow->protoctx))->client.next_seq,
8175                 ((TcpSession *)(p->flow->protoctx))->server.next_seq);
8176         goto end;
8177     }
8178 
8179     if (((TcpSession *)(p->flow->protoctx))->client.os_policy !=
8180             OS_POLICY_LINUX && ((TcpSession *)
8181             (p->flow->protoctx))->server.os_policy != OS_POLICY_WINDOWS)
8182     {
8183         printf("failed in setting up OS policy, client.os_policy: %"PRIu8""
8184                 " should be %"PRIu8" and server.os_policy: %"PRIu8""
8185                 " should be %"PRIu8"\n", ((TcpSession *)
8186                 (p->flow->protoctx))->client.os_policy, (uint8_t)OS_POLICY_LINUX,
8187                 ((TcpSession *)(p->flow->protoctx))->server.os_policy,
8188                 (uint8_t)OS_POLICY_WINDOWS);
8189         goto end;
8190     }
8191     StreamTcpSessionPktFree(p);
8192 
8193     ret = 1;
8194 end:
8195     ConfDeInit();
8196     ConfRestoreContextBackup();
8197     FLOWLOCK_UNLOCK(&f);
8198     SCFree(p);
8199     FLOW_DESTROY(&f);
8200     StreamTcpUTDeinit(stt.ra_ctx);
8201     return ret;
8202 }
8203 
8204 /**
8205  *  \test   Test the setting up a OS policy. Te OS policy values are defined in
8206  *          the config string "dummy_conf_string1". To check the setting of
8207  *          Default os policy
8208  *
8209  *  \retval On success it returns 1 and on failure 0
8210  */
8211 
StreamTcpTest17(void)8212 static int StreamTcpTest17 (void)
8213 {
8214     Packet *p = SCMalloc(SIZE_OF_PACKET);
8215     if (unlikely(p == NULL))
8216         return 0;
8217     Flow f;
8218     ThreadVars tv;
8219     StreamTcpThread stt;
8220     TCPHdr tcph;
8221     uint8_t payload[4];
8222     struct in_addr addr;
8223     IPV4Hdr ipv4h;
8224     char os_policy_name[10] = "windows";
8225     const char *ip_addr;
8226     PacketQueueNoLock pq;
8227     memset(&pq,0,sizeof(PacketQueueNoLock));
8228 
8229     memset(p, 0, SIZE_OF_PACKET);
8230     memset (&f, 0, sizeof(Flow));
8231     memset(&tv, 0, sizeof (ThreadVars));
8232     memset(&stt, 0, sizeof (StreamTcpThread));
8233     memset(&tcph, 0, sizeof (TCPHdr));
8234     memset(&addr, 0, sizeof(addr));
8235     memset(&ipv4h, 0, sizeof(ipv4h));
8236     FLOW_INITIALIZE(&f);
8237     p->flow = &f;
8238     int ret = 0;
8239 
8240     StreamTcpUTInit(&stt.ra_ctx);
8241 
8242     /* Load the config string in to parser */
8243     ConfCreateContextBackup();
8244     ConfInit();
8245     ConfYamlLoadString(dummy_conf_string1, strlen(dummy_conf_string1));
8246 
8247     /* Get the IP address as string and add it to Host info tree for lookups */
8248     ip_addr = StreamTcpParseOSPolicy(os_policy_name);
8249     SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
8250     strlcpy(os_policy_name, "linux\0", sizeof(os_policy_name));
8251     ip_addr = StreamTcpParseOSPolicy(os_policy_name);
8252     SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
8253     addr.s_addr = inet_addr("192.168.0.1");
8254     tcph.th_win = htons(5480);
8255     tcph.th_seq = htonl(10);
8256     tcph.th_ack = htonl(20);
8257     tcph.th_flags = TH_ACK|TH_PUSH;
8258     p->tcph = &tcph;
8259     p->dst.family = AF_INET;
8260     p->dst.address.address_un_data32[0] = addr.s_addr;
8261     p->ip4h = &ipv4h;
8262 
8263     StreamTcpCreateTestPacket(payload, 0x41, 3, sizeof(payload)); /*AAA*/
8264     p->payload = payload;
8265     p->payload_len = 3;
8266 
8267     FLOWLOCK_WRLOCK(&f);
8268     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
8269         goto end;
8270 
8271     p->tcph->th_seq = htonl(20);
8272     p->tcph->th_ack = htonl(13);
8273     p->tcph->th_flags = TH_ACK|TH_PUSH;
8274     p->flowflags = FLOW_PKT_TOCLIENT;
8275 
8276     StreamTcpCreateTestPacket(payload, 0x42, 3, sizeof(payload)); /*BBB*/
8277     p->payload = payload;
8278     p->payload_len = 3;
8279 
8280     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
8281         goto end;
8282 
8283     p->tcph->th_seq = htonl(15);
8284     p->tcph->th_ack = htonl(23);
8285     p->tcph->th_flags = TH_ACK|TH_PUSH;
8286     p->flowflags = FLOW_PKT_TOSERVER;
8287 
8288     StreamTcpCreateTestPacket(payload, 0x43, 3, sizeof(payload)); /*CCC*/
8289     p->payload = payload;
8290     p->payload_len = 3;
8291 
8292     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
8293         goto end;
8294 
8295     p->tcph->th_seq = htonl(14);
8296     p->tcph->th_ack = htonl(23);
8297     p->tcph->th_flags = TH_ACK|TH_PUSH;
8298     p->flowflags = FLOW_PKT_TOSERVER;
8299 
8300     StreamTcpCreateTestPacket(payload, 0x43, 3, sizeof(payload)); /*CCC*/
8301     p->payload = payload;
8302     p->payload_len = 3;
8303 
8304     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
8305         goto end;
8306 
8307     addr.s_addr = inet_addr("10.1.1.1");
8308     p->tcph->th_seq = htonl(25);
8309     p->tcph->th_ack = htonl(13);
8310     p->tcph->th_flags = TH_ACK|TH_PUSH;
8311     p->flowflags = FLOW_PKT_TOCLIENT;
8312     p->dst.address.address_un_data32[0] = addr.s_addr;
8313 
8314     StreamTcpCreateTestPacket(payload, 0x44, 3, sizeof(payload)); /*DDD*/
8315     p->payload = payload;
8316     p->payload_len = 3;
8317 
8318     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
8319         goto end;
8320 
8321     p->tcph->th_seq = htonl(24);
8322     p->tcph->th_ack = htonl(13);
8323     p->tcph->th_flags = TH_ACK|TH_PUSH;
8324     p->flowflags = FLOW_PKT_TOCLIENT;
8325 
8326     StreamTcpCreateTestPacket(payload, 0x44, 3, sizeof(payload)); /*DDD*/
8327     p->payload = payload;
8328     p->payload_len = 3;
8329 
8330     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
8331         goto end;
8332 
8333     if (stream_config.midstream != TRUE) {
8334         ret = 1;
8335         goto end;
8336     }
8337     if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED)
8338         goto end;
8339 
8340     if (((TcpSession *)(p->flow->protoctx))->client.next_seq != 13 &&
8341             ((TcpSession *)(p->flow->protoctx))->server.next_seq != 23) {
8342         printf("failed in next_seq match client.next_seq %"PRIu32""
8343                 " server.next_seq %"PRIu32"\n",
8344                 ((TcpSession *)(p->flow->protoctx))->client.next_seq,
8345                 ((TcpSession *)(p->flow->protoctx))->server.next_seq);
8346         goto end;
8347     }
8348 
8349     if (((TcpSession *)(p->flow->protoctx))->client.os_policy !=
8350             OS_POLICY_LINUX && ((TcpSession *)
8351             (p->flow->protoctx))->server.os_policy != OS_POLICY_DEFAULT)
8352     {
8353         printf("failed in setting up OS policy, client.os_policy: %"PRIu8""
8354                 " should be %"PRIu8" and server.os_policy: %"PRIu8""
8355                 " should be %"PRIu8"\n", ((TcpSession *)
8356                 (p->flow->protoctx))->client.os_policy, (uint8_t)OS_POLICY_LINUX,
8357                 ((TcpSession *)(p->flow->protoctx))->server.os_policy,
8358                 (uint8_t)OS_POLICY_DEFAULT);
8359         goto end;
8360     }
8361     StreamTcpSessionPktFree(p);
8362 
8363     ret = 1;
8364 end:
8365     ConfDeInit();
8366     ConfRestoreContextBackup();
8367     FLOWLOCK_UNLOCK(&f);
8368     SCFree(p);
8369     FLOW_DESTROY(&f);
8370     StreamTcpUTDeinit(stt.ra_ctx);
8371     return ret;
8372 }
8373 
8374 /** \test   Test the various OS policies based on different IP addresses from
8375             confuguration defined in 'dummy_conf_string1' */
StreamTcpTest18(void)8376 static int StreamTcpTest18 (void)
8377 {
8378     StreamTcpThread stt;
8379     struct in_addr addr;
8380     char os_policy_name[10] = "windows";
8381     const char *ip_addr;
8382     TcpStream stream;
8383     Packet *p = SCMalloc(SIZE_OF_PACKET);
8384     if (unlikely(p == NULL))
8385         return 0;
8386     IPV4Hdr ipv4h;
8387     int ret = 0;
8388 
8389     memset(&addr, 0, sizeof(addr));
8390     memset(&stream, 0, sizeof(stream));
8391     memset(p, 0, SIZE_OF_PACKET);
8392     memset(&ipv4h, 0, sizeof(ipv4h));
8393 
8394     StreamTcpUTInit(&stt.ra_ctx);
8395     SCHInfoCleanResources();
8396 
8397     /* Load the config string in to parser */
8398     ConfCreateContextBackup();
8399     ConfInit();
8400     ConfYamlLoadString(dummy_conf_string1, strlen(dummy_conf_string1));
8401 
8402     /* Get the IP address as string and add it to Host info tree for lookups */
8403     ip_addr = StreamTcpParseOSPolicy(os_policy_name);
8404     SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
8405 
8406     p->dst.family = AF_INET;
8407     p->ip4h = &ipv4h;
8408     addr.s_addr = inet_addr("192.168.1.1");
8409     p->dst.address.address_un_data32[0] = addr.s_addr;
8410     StreamTcpSetOSPolicy(&stream, p);
8411 
8412     if (stream.os_policy != OS_POLICY_WINDOWS)
8413         goto end;
8414 
8415     ret = 1;
8416 end:
8417     ConfDeInit();
8418     ConfRestoreContextBackup();
8419     SCFree(p);
8420     StreamTcpUTDeinit(stt.ra_ctx);
8421     return ret;
8422 }
8423 /** \test   Test the various OS policies based on different IP addresses from
8424             confuguration defined in 'dummy_conf_string1' */
StreamTcpTest19(void)8425 static int StreamTcpTest19 (void)
8426 {
8427     StreamTcpThread stt;
8428     struct in_addr addr;
8429     char os_policy_name[10] = "windows";
8430     const char *ip_addr;
8431     TcpStream stream;
8432     Packet *p = SCMalloc(SIZE_OF_PACKET);
8433     if (unlikely(p == NULL))
8434         return 0;
8435     IPV4Hdr ipv4h;
8436     int ret = 0;
8437 
8438     memset(&addr, 0, sizeof(addr));
8439     memset(&stream, 0, sizeof(stream));
8440     memset(p, 0, SIZE_OF_PACKET);
8441     memset(&ipv4h, 0, sizeof(ipv4h));
8442 
8443     StreamTcpUTInit(&stt.ra_ctx);
8444     SCHInfoCleanResources();
8445 
8446     /* Load the config string in to parser */
8447     ConfCreateContextBackup();
8448     ConfInit();
8449     ConfYamlLoadString(dummy_conf_string1, strlen(dummy_conf_string1));
8450 
8451     /* Get the IP address as string and add it to Host info tree for lookups */
8452     ip_addr = StreamTcpParseOSPolicy(os_policy_name);
8453     SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
8454 
8455     p->dst.family = AF_INET;
8456     p->ip4h = &ipv4h;
8457     addr.s_addr = inet_addr("192.168.0.30");
8458     p->dst.address.address_un_data32[0] = addr.s_addr;
8459     StreamTcpSetOSPolicy(&stream, p);
8460 
8461     if (stream.os_policy != OS_POLICY_WINDOWS) {
8462         printf("expected os_policy: %"PRIu8" but received %"PRIu8": ",
8463                 (uint8_t)OS_POLICY_WINDOWS, stream.os_policy);
8464         goto end;
8465     }
8466 
8467     ret = 1;
8468 end:
8469     ConfDeInit();
8470     ConfRestoreContextBackup();
8471     SCFree(p);
8472     StreamTcpUTDeinit(stt.ra_ctx);
8473     return ret;
8474 }
8475 /** \test   Test the various OS policies based on different IP addresses from
8476             confuguration defined in 'dummy_conf_string1' */
StreamTcpTest20(void)8477 static int StreamTcpTest20 (void)
8478 {
8479     StreamTcpThread stt;
8480     struct in_addr addr;
8481     char os_policy_name[10] = "linux";
8482     const char *ip_addr;
8483     TcpStream stream;
8484     Packet *p = SCMalloc(SIZE_OF_PACKET);
8485     if (unlikely(p == NULL))
8486         return 0;
8487     IPV4Hdr ipv4h;
8488     int ret = 0;
8489 
8490     memset(&addr, 0, sizeof(addr));
8491     memset(&stream, 0, sizeof(stream));
8492     memset(p, 0, SIZE_OF_PACKET);
8493     memset(&ipv4h, 0, sizeof(ipv4h));
8494 
8495     StreamTcpUTInit(&stt.ra_ctx);
8496     SCHInfoCleanResources();
8497 
8498     /* Load the config string in to parser */
8499     ConfCreateContextBackup();
8500     ConfInit();
8501     ConfYamlLoadString(dummy_conf_string1, strlen(dummy_conf_string1));
8502 
8503     /* Get the IP address as string and add it to Host info tree for lookups */
8504     ip_addr = StreamTcpParseOSPolicy(os_policy_name);
8505     SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
8506 
8507     p->dst.family = AF_INET;
8508     p->ip4h = &ipv4h;
8509     addr.s_addr = inet_addr("192.168.0.1");
8510     p->dst.address.address_un_data32[0] = addr.s_addr;
8511     StreamTcpSetOSPolicy(&stream, p);
8512 
8513     if (stream.os_policy != OS_POLICY_LINUX) {
8514         printf("expected os_policy: %"PRIu8" but received %"PRIu8"\n",
8515                 (uint8_t)OS_POLICY_LINUX, stream.os_policy);
8516         goto end;
8517     }
8518 
8519     ret = 1;
8520 end:
8521     ConfDeInit();
8522     ConfRestoreContextBackup();
8523     SCFree(p);
8524     StreamTcpUTDeinit(stt.ra_ctx);
8525     return ret;
8526 }
8527 /** \test   Test the various OS policies based on different IP addresses from
8528             confuguration defined in 'dummy_conf_string1' */
StreamTcpTest21(void)8529 static int StreamTcpTest21 (void)
8530 {
8531     StreamTcpThread stt;
8532     struct in_addr addr;
8533     char os_policy_name[10] = "linux";
8534     const char *ip_addr;
8535     TcpStream stream;
8536     Packet *p = SCMalloc(SIZE_OF_PACKET);
8537     if (unlikely(p == NULL))
8538         return 0;
8539     IPV4Hdr ipv4h;
8540     int ret = 0;
8541 
8542     memset(&addr, 0, sizeof(addr));
8543     memset(&stream, 0, sizeof(stream));
8544     memset(p, 0, SIZE_OF_PACKET);
8545     memset(&ipv4h, 0, sizeof(ipv4h));
8546 
8547     StreamTcpUTInit(&stt.ra_ctx);
8548     SCHInfoCleanResources();
8549 
8550     /* Load the config string in to parser */
8551     ConfCreateContextBackup();
8552     ConfInit();
8553     ConfYamlLoadString(dummy_conf_string1, strlen(dummy_conf_string1));
8554 
8555     /* Get the IP address as string and add it to Host info tree for lookups */
8556     ip_addr = StreamTcpParseOSPolicy(os_policy_name);
8557     SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
8558 
8559     p->dst.family = AF_INET;
8560     p->ip4h = &ipv4h;
8561     addr.s_addr = inet_addr("192.168.1.30");
8562     p->dst.address.address_un_data32[0] = addr.s_addr;
8563     StreamTcpSetOSPolicy(&stream, p);
8564 
8565     if (stream.os_policy != OS_POLICY_LINUX) {
8566         printf("expected os_policy: %"PRIu8" but received %"PRIu8"\n",
8567                 (uint8_t)OS_POLICY_LINUX, stream.os_policy);
8568         goto end;
8569     }
8570 
8571     ret = 1;
8572 end:
8573     ConfDeInit();
8574     ConfRestoreContextBackup();
8575     SCFree(p);
8576     StreamTcpUTDeinit(stt.ra_ctx);
8577     return ret;
8578 }
8579 /** \test   Test the various OS policies based on different IP addresses from
8580             confuguration defined in 'dummy_conf_string1' */
StreamTcpTest22(void)8581 static int StreamTcpTest22 (void)
8582 {
8583     StreamTcpThread stt;
8584     struct in_addr addr;
8585     char os_policy_name[10] = "windows";
8586     const char *ip_addr;
8587     TcpStream stream;
8588     Packet *p = SCMalloc(SIZE_OF_PACKET);
8589     if (unlikely(p == NULL))
8590         return 0;
8591     IPV4Hdr ipv4h;
8592     int ret = 0;
8593 
8594     memset(&addr, 0, sizeof(addr));
8595     memset(&stream, 0, sizeof(stream));
8596     memset(p, 0, SIZE_OF_PACKET);
8597     memset(&ipv4h, 0, sizeof(ipv4h));
8598 
8599     StreamTcpUTInit(&stt.ra_ctx);
8600     SCHInfoCleanResources();
8601 
8602     /* Load the config string in to parser */
8603     ConfCreateContextBackup();
8604     ConfInit();
8605     ConfYamlLoadString(dummy_conf_string1, strlen(dummy_conf_string1));
8606 
8607     /* Get the IP address as string and add it to Host info tree for lookups */
8608     ip_addr = StreamTcpParseOSPolicy(os_policy_name);
8609     SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
8610 
8611     p->dst.family = AF_INET;
8612     p->ip4h = &ipv4h;
8613     addr.s_addr = inet_addr("123.231.2.1");
8614     p->dst.address.address_un_data32[0] = addr.s_addr;
8615     StreamTcpSetOSPolicy(&stream, p);
8616 
8617     if (stream.os_policy != OS_POLICY_DEFAULT) {
8618         printf("expected os_policy: %"PRIu8" but received %"PRIu8"\n",
8619                 (uint8_t)OS_POLICY_DEFAULT, stream.os_policy);
8620         goto end;
8621     }
8622 
8623     ret = 1;
8624 end:
8625     ConfDeInit();
8626     ConfRestoreContextBackup();
8627     SCFree(p);
8628     StreamTcpUTDeinit(stt.ra_ctx);
8629     return ret;
8630 }
8631 
8632 /** \test   Test the stream mem leaks conditions. */
StreamTcpTest23(void)8633 static int StreamTcpTest23(void)
8634 {
8635     StreamTcpThread stt;
8636     TcpSession ssn;
8637     Flow f;
8638     TCPHdr tcph;
8639     uint8_t packet[1460] = "";
8640     ThreadVars tv;
8641     PacketQueueNoLock pq;
8642 
8643     Packet *p = SCMalloc(SIZE_OF_PACKET);
8644     FAIL_IF(p == NULL);
8645 
8646     memset(&pq,0,sizeof(PacketQueueNoLock));
8647     memset(p, 0, SIZE_OF_PACKET);
8648     memset(&f, 0, sizeof (Flow));
8649     memset(&tcph, 0, sizeof (TCPHdr));
8650     memset(&tv, 0, sizeof (ThreadVars));
8651 
8652     StreamTcpUTInit(&stt.ra_ctx);
8653     StreamTcpUTSetupSession(&ssn);
8654     FLOW_INITIALIZE(&f);
8655     ssn.client.os_policy = OS_POLICY_BSD;
8656     f.protoctx = &ssn;
8657     p->src.family = AF_INET;
8658     p->dst.family = AF_INET;
8659     p->proto = IPPROTO_TCP;
8660     p->flow = &f;
8661     tcph.th_win = 5480;
8662     tcph.th_flags = TH_PUSH | TH_ACK;
8663     p->tcph = &tcph;
8664     p->flowflags = FLOW_PKT_TOSERVER;
8665     p->payload = packet;
8666     SET_ISN(&ssn.client, 3184324452UL);
8667 
8668     p->tcph->th_seq = htonl(3184324453UL);
8669     p->tcph->th_ack = htonl(3373419609UL);
8670     p->payload_len = 2;
8671 
8672     FAIL_IF(StreamTcpReassembleHandleSegment(&tv, stt.ra_ctx, &ssn, &ssn.client, p, &pq) == -1);
8673 
8674     p->tcph->th_seq = htonl(3184324455UL);
8675     p->tcph->th_ack = htonl(3373419621UL);
8676     p->payload_len = 2;
8677 
8678     FAIL_IF(StreamTcpReassembleHandleSegment(&tv, stt.ra_ctx, &ssn, &ssn.client, p, &pq) == -1);
8679 
8680     p->tcph->th_seq = htonl(3184324453UL);
8681     p->tcph->th_ack = htonl(3373419621UL);
8682     p->payload_len = 6;
8683 
8684     FAIL_IF(StreamTcpReassembleHandleSegment(&tv, stt.ra_ctx, &ssn, &ssn.client, p, &pq) == -1);
8685 
8686     TcpSegment *seg = RB_MAX(TCPSEG, &ssn.client.seg_tree);
8687     FAIL_IF_NULL(seg);
8688     FAIL_IF(TCP_SEG_LEN(seg) != 2);
8689 
8690     StreamTcpUTClearSession(&ssn);
8691     SCFree(p);
8692     FLOW_DESTROY(&f);
8693     StreamTcpUTDeinit(stt.ra_ctx);
8694     FAIL_IF(SC_ATOMIC_GET(st_memuse) > 0);
8695     PASS;
8696 }
8697 
8698 /** \test   Test the stream mem leaks conditions. */
StreamTcpTest24(void)8699 static int StreamTcpTest24(void)
8700 {
8701     StreamTcpThread stt;
8702     TcpSession ssn;
8703     Packet *p = SCMalloc(SIZE_OF_PACKET);
8704     FAIL_IF (p == NULL);
8705     Flow f;
8706     TCPHdr tcph;
8707     uint8_t packet[1460] = "";
8708     ThreadVars tv;
8709     memset(&tv, 0, sizeof (ThreadVars));
8710     PacketQueueNoLock pq;
8711     memset(&pq,0,sizeof(PacketQueueNoLock));
8712 
8713     StreamTcpUTInit(&stt.ra_ctx);
8714     StreamTcpUTSetupSession(&ssn);
8715 
8716     memset(p, 0, SIZE_OF_PACKET);
8717     memset(&f, 0, sizeof (Flow));
8718     memset(&tcph, 0, sizeof (TCPHdr));
8719     FLOW_INITIALIZE(&f);
8720     ssn.client.os_policy = OS_POLICY_BSD;
8721     f.protoctx = &ssn;
8722     p->src.family = AF_INET;
8723     p->dst.family = AF_INET;
8724     p->proto = IPPROTO_TCP;
8725     p->flow = &f;
8726     tcph.th_win = 5480;
8727     tcph.th_flags = TH_PUSH | TH_ACK;
8728     p->tcph = &tcph;
8729     p->flowflags = FLOW_PKT_TOSERVER;
8730     p->payload = packet;
8731     //ssn.client.ra_app_base_seq = ssn.client.ra_raw_base_seq = ssn.client.last_ack = 3184324453UL;
8732     SET_ISN(&ssn.client, 3184324453UL);
8733 
8734     p->tcph->th_seq = htonl(3184324455UL);
8735     p->tcph->th_ack = htonl(3373419621UL);
8736     p->payload_len = 4;
8737 
8738     FAIL_IF (StreamTcpReassembleHandleSegment(&tv, stt.ra_ctx, &ssn, &ssn.client, p, &pq) == -1);
8739 
8740     p->tcph->th_seq = htonl(3184324459UL);
8741     p->tcph->th_ack = htonl(3373419633UL);
8742     p->payload_len = 2;
8743 
8744     FAIL_IF(StreamTcpReassembleHandleSegment(&tv, stt.ra_ctx, &ssn, &ssn.client, p, &pq) == -1);
8745 
8746     p->tcph->th_seq = htonl(3184324459UL);
8747     p->tcph->th_ack = htonl(3373419657UL);
8748     p->payload_len = 4;
8749 
8750     FAIL_IF(StreamTcpReassembleHandleSegment(&tv, stt.ra_ctx, &ssn, &ssn.client, p, &pq) == -1);
8751 
8752     TcpSegment *seg = RB_MAX(TCPSEG, &ssn.client.seg_tree);
8753     FAIL_IF_NULL(seg);
8754     FAIL_IF(TCP_SEG_LEN(seg) != 4);
8755 
8756     StreamTcpUTClearSession(&ssn);
8757     SCFree(p);
8758     FLOW_DESTROY(&f);
8759     StreamTcpUTDeinit(stt.ra_ctx);
8760     FAIL_IF(SC_ATOMIC_GET(st_memuse) > 0);
8761     PASS;
8762 }
8763 
8764 /**
8765  *  \test   Test the initialization of tcp streams with congestion flags
8766  *
8767  *  \retval On success it returns 1 and on failure 0.
8768  */
StreamTcpTest25(void)8769 static int StreamTcpTest25(void)
8770 {
8771     Packet *p = SCMalloc(SIZE_OF_PACKET);
8772     if (unlikely(p == NULL))
8773         return 0;
8774     Flow f;
8775     ThreadVars tv;
8776     StreamTcpThread stt;
8777     uint8_t payload[4];
8778     TCPHdr tcph;
8779     int ret = 0;
8780     PacketQueueNoLock pq;
8781     memset(&pq,0,sizeof(PacketQueueNoLock));
8782 
8783     memset(p, 0, SIZE_OF_PACKET);
8784     memset (&f, 0, sizeof(Flow));
8785     memset(&tv, 0, sizeof (ThreadVars));
8786     memset(&stt, 0, sizeof (StreamTcpThread));
8787     memset(&tcph, 0, sizeof (TCPHdr));
8788 
8789     FLOW_INITIALIZE(&f);
8790     p->flow = &f;
8791     tcph.th_win = htons(5480);
8792     tcph.th_flags = TH_SYN | TH_CWR;
8793     p->tcph = &tcph;
8794     p->flowflags = FLOW_PKT_TOSERVER;
8795     StreamTcpUTInit(&stt.ra_ctx);
8796 
8797     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
8798         goto end;
8799 
8800     p->tcph->th_ack = htonl(1);
8801     p->tcph->th_flags = TH_SYN | TH_ACK;
8802     p->flowflags = FLOW_PKT_TOCLIENT;
8803 
8804     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
8805         goto end;
8806 
8807     p->tcph->th_ack = htonl(1);
8808     p->tcph->th_seq = htonl(1);
8809     p->tcph->th_flags = TH_ACK;
8810     p->flowflags = FLOW_PKT_TOSERVER;
8811 
8812     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
8813         goto end;
8814 
8815     p->tcph->th_ack = htonl(1);
8816     p->tcph->th_seq = htonl(2);
8817     p->tcph->th_flags = TH_PUSH | TH_ACK;
8818     p->flowflags = FLOW_PKT_TOSERVER;
8819 
8820     StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
8821     p->payload = payload;
8822     p->payload_len = 3;
8823 
8824     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
8825         goto end;
8826 
8827     p->flowflags = FLOW_PKT_TOCLIENT;
8828     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
8829         goto end;
8830 
8831     p->tcph->th_ack = htonl(1);
8832     p->tcph->th_seq = htonl(6);
8833     p->tcph->th_flags = TH_PUSH | TH_ACK;
8834     p->flowflags = FLOW_PKT_TOSERVER;
8835 
8836     StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
8837     p->payload = payload;
8838     p->payload_len = 3;
8839 
8840     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
8841         goto end;
8842 
8843     p->flowflags = FLOW_PKT_TOCLIENT;
8844     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
8845         goto end;
8846 
8847     StreamTcpSessionClear(p->flow->protoctx);
8848 
8849     ret = 1;
8850 end:
8851     SCFree(p);
8852     FLOW_DESTROY(&f);
8853     StreamTcpUTDeinit(stt.ra_ctx);
8854     return ret;
8855 }
8856 
8857 /**
8858  *  \test   Test the initialization of tcp streams with congestion flags
8859  *
8860  *  \retval On success it returns 1 and on failure 0.
8861  */
StreamTcpTest26(void)8862 static int StreamTcpTest26(void)
8863 {
8864     Packet *p = SCMalloc(SIZE_OF_PACKET);
8865     if (unlikely(p == NULL))
8866         return 0;
8867     Flow f;
8868     ThreadVars tv;
8869     StreamTcpThread stt;
8870     uint8_t payload[4];
8871     TCPHdr tcph;
8872     int ret = 0;
8873     PacketQueueNoLock pq;
8874     memset(&pq,0,sizeof(PacketQueueNoLock));
8875 
8876     memset(p, 0, SIZE_OF_PACKET);
8877     memset (&f, 0, sizeof(Flow));
8878     memset(&tv, 0, sizeof (ThreadVars));
8879     memset(&stt, 0, sizeof (StreamTcpThread));
8880     memset(&tcph, 0, sizeof (TCPHdr));
8881 
8882     FLOW_INITIALIZE(&f);
8883     p->flow = &f;
8884     tcph.th_win = htons(5480);
8885     tcph.th_flags = TH_SYN | TH_ECN;
8886     p->tcph = &tcph;
8887     p->flowflags = FLOW_PKT_TOSERVER;
8888 
8889     StreamTcpUTInit(&stt.ra_ctx);
8890 
8891     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
8892         goto end;
8893 
8894     p->tcph->th_ack = htonl(1);
8895     p->tcph->th_flags = TH_SYN | TH_ACK;
8896     p->flowflags = FLOW_PKT_TOCLIENT;
8897 
8898     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
8899         goto end;
8900 
8901     p->tcph->th_ack = htonl(1);
8902     p->tcph->th_seq = htonl(1);
8903     p->tcph->th_flags = TH_ACK;
8904     p->flowflags = FLOW_PKT_TOSERVER;
8905 
8906     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
8907         goto end;
8908 
8909     p->tcph->th_ack = htonl(1);
8910     p->tcph->th_seq = htonl(2);
8911     p->tcph->th_flags = TH_PUSH | TH_ACK;
8912     p->flowflags = FLOW_PKT_TOSERVER;
8913 
8914     StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
8915     p->payload = payload;
8916     p->payload_len = 3;
8917 
8918     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
8919         goto end;
8920 
8921     p->flowflags = FLOW_PKT_TOCLIENT;
8922     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
8923         goto end;
8924 
8925     p->tcph->th_ack = htonl(1);
8926     p->tcph->th_seq = htonl(6);
8927     p->tcph->th_flags = TH_PUSH | TH_ACK;
8928     p->flowflags = FLOW_PKT_TOSERVER;
8929 
8930     StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
8931     p->payload = payload;
8932     p->payload_len = 3;
8933 
8934     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
8935         goto end;
8936 
8937     p->flowflags = FLOW_PKT_TOCLIENT;
8938     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
8939         goto end;
8940 
8941     StreamTcpSessionClear(p->flow->protoctx);
8942 
8943     ret = 1;
8944 end:
8945     SCFree(p);
8946     FLOW_DESTROY(&f);
8947     StreamTcpUTDeinit(stt.ra_ctx);
8948     return ret;
8949 }
8950 
8951 /**
8952  *  \test   Test the initialization of tcp streams with congestion flags
8953  *
8954  *  \retval On success it returns 1 and on failure 0.
8955  */
StreamTcpTest27(void)8956 static int StreamTcpTest27(void)
8957 {
8958     Packet *p = SCMalloc(SIZE_OF_PACKET);
8959     if (unlikely(p == NULL))
8960         return 0;
8961     Flow f;
8962     ThreadVars tv;
8963     StreamTcpThread stt;
8964     uint8_t payload[4];
8965     TCPHdr tcph;
8966     int ret = 0;
8967     PacketQueueNoLock pq;
8968     memset(&pq,0,sizeof(PacketQueueNoLock));
8969 
8970     memset(p, 0, SIZE_OF_PACKET);
8971     memset (&f, 0, sizeof(Flow));
8972     memset(&tv, 0, sizeof (ThreadVars));
8973     memset(&stt, 0, sizeof (StreamTcpThread));
8974     memset(&tcph, 0, sizeof (TCPHdr));
8975 
8976     FLOW_INITIALIZE(&f);
8977     p->flow = &f;
8978     tcph.th_win = htons(5480);
8979     tcph.th_flags = TH_SYN | TH_CWR | TH_ECN;
8980     p->tcph = &tcph;
8981     p->flowflags = FLOW_PKT_TOSERVER;
8982 
8983     StreamTcpUTInit(&stt.ra_ctx);
8984 
8985     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
8986         goto end;
8987 
8988     p->tcph->th_ack = htonl(1);
8989     p->tcph->th_flags = TH_SYN | TH_ACK;
8990     p->flowflags = FLOW_PKT_TOCLIENT;
8991 
8992     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
8993         goto end;
8994 
8995     p->tcph->th_ack = htonl(1);
8996     p->tcph->th_seq = htonl(1);
8997     p->tcph->th_flags = TH_ACK;
8998     p->flowflags = FLOW_PKT_TOSERVER;
8999 
9000     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
9001         goto end;
9002 
9003     p->tcph->th_ack = htonl(1);
9004     p->tcph->th_seq = htonl(2);
9005     p->tcph->th_flags = TH_PUSH | TH_ACK;
9006     p->flowflags = FLOW_PKT_TOSERVER;
9007 
9008     StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
9009     p->payload = payload;
9010     p->payload_len = 3;
9011 
9012     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
9013         goto end;
9014 
9015     p->flowflags = FLOW_PKT_TOCLIENT;
9016     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
9017         goto end;
9018 
9019     p->tcph->th_ack = htonl(1);
9020     p->tcph->th_seq = htonl(6);
9021     p->tcph->th_flags = TH_PUSH | TH_ACK;
9022     p->flowflags = FLOW_PKT_TOSERVER;
9023 
9024     StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
9025     p->payload = payload;
9026     p->payload_len = 3;
9027 
9028     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
9029         goto end;
9030 
9031     p->flowflags = FLOW_PKT_TOCLIENT;
9032     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
9033         goto end;
9034 
9035     StreamTcpSessionClear(p->flow->protoctx);
9036 
9037     ret = 1;
9038 end:
9039     SCFree(p);
9040     FLOW_DESTROY(&f);
9041     StreamTcpUTDeinit(stt.ra_ctx);
9042     return ret;
9043 }
9044 
9045 /** \test   Test the memcap incrementing/decrementing and memcap check */
StreamTcpTest28(void)9046 static int StreamTcpTest28(void)
9047 {
9048     StreamTcpThread stt;
9049     StreamTcpUTInit(&stt.ra_ctx);
9050 
9051     uint32_t memuse = SC_ATOMIC_GET(st_memuse);
9052 
9053     StreamTcpIncrMemuse(500);
9054     FAIL_IF(SC_ATOMIC_GET(st_memuse) != (memuse+500));
9055 
9056     StreamTcpDecrMemuse(500);
9057     FAIL_IF(SC_ATOMIC_GET(st_memuse) != memuse);
9058 
9059     FAIL_IF(StreamTcpCheckMemcap(500) != 1);
9060 
9061     FAIL_IF(StreamTcpCheckMemcap((memuse + SC_ATOMIC_GET(stream_config.memcap))) != 0);
9062 
9063     StreamTcpUTDeinit(stt.ra_ctx);
9064 
9065     FAIL_IF(SC_ATOMIC_GET(st_memuse) != 0);
9066     PASS;
9067 }
9068 
9069 #if 0
9070 /**
9071  *  \test   Test the resetting of the sesison with bad checksum packet and later
9072  *          send the malicious contents on the session. Engine should drop the
9073  *          packet with the bad checksum.
9074  *
9075  *  \retval On success it returns 1 and on failure 0.
9076  */
9077 static int StreamTcpTest29(void)
9078 {
9079     Packet p;
9080     Flow f;
9081     ThreadVars tv;
9082     StreamTcpThread stt;
9083     TCPHdr tcph;
9084     TcpSession ssn;
9085     IPV4Hdr ipv4h;
9086     struct in_addr addr;
9087     struct in_addr addr1;
9088     TCPCache tcpc;
9089     TCPVars tcpvars;
9090     TcpStream server;
9091     TcpStream client;
9092 
9093     memset (&p, 0, SIZE_OF_PACKET);
9094     memset (&f, 0, sizeof(Flow));
9095     memset(&tv, 0, sizeof (ThreadVars));
9096     memset(&stt, 0, sizeof (StreamTcpThread));
9097     memset(&tcph, 0, sizeof (TCPHdr));
9098     memset (&ipv4h, 0, sizeof(IPV4Hdr));
9099     memset (&addr, 0, sizeof(addr));
9100     memset (&addr1, 0, sizeof(addr1));
9101     memset (&tcpc, 0, sizeof(tcpc));
9102     memset (&tcpvars, 0, sizeof(tcpvars));
9103     memset(&ssn, 0, sizeof (TcpSession));
9104     memset(&server, 0, sizeof (TcpStream));
9105     memset(&client, 0, sizeof (TcpStream));
9106     uint8_t packet[1460] = "";
9107     int result = 1;
9108 
9109     FLOW_INITIALIZE(&f);
9110     StreamTcpInitConfig(TRUE);
9111 
9112     /* prevent L7 from kicking in */
9113 
9114     ssn.client.os_policy = OS_POLICY_BSD;
9115     p.src.family = AF_INET;
9116     p.dst.family = AF_INET;
9117     p.proto = IPPROTO_TCP;
9118     p.flow = &f;
9119     tcph.th_win = 5480;
9120     p.tcph = &tcph;
9121     p.payload = packet;
9122     p.ip4h = &ipv4h;
9123     p.tcpc = tcpc;
9124     p.tcpc.level4_comp_csum = -1;
9125     tcpvars.hlen = 20;
9126     p.tcpvars = tcpvars;
9127     ssn.state = TCP_ESTABLISHED;
9128     addr.s_addr = inet_addr("10.1.3.53");
9129     p.dst.address.address_un_data32[0] = addr.s_addr;
9130     addr1.s_addr = inet_addr("10.1.3.7");
9131     p.src.address.address_un_data32[0] = addr1.s_addr;
9132     f.protoctx = &ssn;
9133     stt.ra_ctx = ra_ctx;
9134     ssn.server = server;
9135     ssn.client = client;
9136     ssn.client.isn = 10;
9137     ssn.client.window = 5184;
9138     ssn.client.last_ack = 10;
9139     ssn.client.ra_base_seq = 10;
9140     ssn.client.next_win = 5184;
9141     ssn.server.isn = 119197101;
9142     ssn.server.window = 5184;
9143     ssn.server.next_win = 5184;
9144     ssn.server.last_ack = 119197101;
9145     ssn.server.ra_base_seq = 119197101;
9146 
9147     tcph.th_flags = TH_PUSH | TH_ACK;
9148     p.flowflags = FLOW_PKT_TOSERVER;
9149     p.tcph->th_seq = htonl(11);
9150     p.tcph->th_ack = htonl(119197102);
9151     p.payload_len = 4;
9152     p.ip4h->ip_src = addr1;
9153     p.tcph->th_sum = TCPCalculateChecksum((uint16_t *)&(p.ip4h->ip_src),
9154                                           (uint16_t *)p.tcph,
9155                                           (p.payload_len +
9156                                            p.tcpvars.hlen) );
9157 
9158     if (StreamTcp(&tv, &p, (void *)&stt, NULL, NULL) != TM_ECODE_OK) {
9159         printf("failed in segment reassmebling\n");
9160         result &= 0;
9161         goto end;
9162     }
9163 
9164     tcph.th_flags = TH_ACK;
9165     p.flowflags = FLOW_PKT_TOCLIENT;
9166     p.tcph->th_seq = htonl(119197102);
9167     p.tcph->th_ack = htonl(15);
9168     p.payload_len = 0;
9169     p.ip4h->ip_src = addr;
9170     p.tcph->th_sum = TCPCalculateChecksum((uint16_t *)&(p.ip4h->ip_src),
9171                                                  (uint16_t *)p.tcph,
9172                                                  (p.payload_len +
9173                                                   p.tcpvars.hlen) );
9174 
9175     if (StreamTcp(&tv, &p, (void *)&stt, NULL, NULL) != TM_ECODE_OK) {
9176         printf("failed in segment reassmebling\n");
9177         result &= 0;
9178         goto end;
9179     }
9180 
9181     tcph.th_flags = TH_RST | TH_ACK;
9182     p.flowflags = FLOW_PKT_TOSERVER;
9183     p.tcph->th_seq = htonl(15);
9184     p.tcph->th_ack = htonl(119197102);
9185     p.payload_len = 0;
9186     p.ip4h->ip_src = addr1;
9187     p.tcph->th_sum = 12345;
9188 
9189     if (StreamTcp(&tv, &p, (void *)&stt, NULL, NULL) != TM_ECODE_OK) {
9190         printf("failed in segment reassmebling\n");
9191         result &= 0;
9192         goto end;
9193     }
9194 
9195     if (ssn.state != TCP_ESTABLISHED) {
9196         printf("the ssn.state should be TCP_ESTABLISHED(%"PRIu8"), not %"PRIu8""
9197                 "\n", TCP_ESTABLISHED, ssn.state);
9198         result &= 0;
9199         goto end;
9200     }
9201 
9202 end:
9203     StreamTcpReturnStreamSegments(&ssn.client);
9204     StreamTcpFreeConfig(TRUE);
9205     return result;
9206 }
9207 
9208 /**
9209  *  \test   Test the overlapping of the packet with bad checksum packet and later
9210  *          send the malicious contents on the session. Engine should drop the
9211  *          packet with the bad checksum.
9212  *
9213  *  \retval On success it returns 1 and on failure 0.
9214  */
9215 static int StreamTcpTest30(void)
9216 {
9217     Packet p;
9218     Flow f;
9219     ThreadVars tv;
9220     StreamTcpThread stt;
9221     TCPHdr tcph;
9222     TcpSession ssn;
9223     IPV4Hdr ipv4h;
9224     struct in_addr addr;
9225     struct in_addr addr1;
9226     TCPCache tcpc;
9227     TCPVars tcpvars;
9228     TcpStream server;
9229     TcpStream client;
9230 
9231     memset (&p, 0, SIZE_OF_PACKET);
9232     memset (&f, 0, sizeof(Flow));
9233     memset(&tv, 0, sizeof (ThreadVars));
9234     memset(&stt, 0, sizeof (StreamTcpThread));
9235     memset(&tcph, 0, sizeof (TCPHdr));
9236     memset (&ipv4h, 0, sizeof(IPV4Hdr));
9237     memset (&addr, 0, sizeof(addr));
9238     memset (&addr1, 0, sizeof(addr1));
9239     memset (&tcpc, 0, sizeof(tcpc));
9240     memset (&tcpvars, 0, sizeof(tcpvars));
9241     memset(&ssn, 0, sizeof (TcpSession));
9242     memset(&server, 0, sizeof (TcpStream));
9243     memset(&client, 0, sizeof (TcpStream));
9244     uint8_t payload[9] = "AAAAAAAAA";
9245     uint8_t payload1[9] = "GET /EVIL";
9246     uint8_t expected_content[9] = { 0x47, 0x45, 0x54, 0x20, 0x2f, 0x45, 0x56,
9247                                     0x49, 0x4c };
9248     int result = 1;
9249 
9250     FLOW_INITIALIZE(&f);
9251     StreamTcpInitConfig(TRUE);
9252 
9253     /* prevent L7 from kicking in */
9254 
9255     ssn.client.os_policy = OS_POLICY_BSD;
9256     p.src.family = AF_INET;
9257     p.dst.family = AF_INET;
9258     p.proto = IPPROTO_TCP;
9259     p.flow = &f;
9260     tcph.th_win = 5480;
9261     p.tcph = &tcph;
9262     p.payload = payload;
9263     p.ip4h = &ipv4h;
9264     p.tcpc = tcpc;
9265     p.tcpc.level4_comp_csum = -1;
9266     p.tcpvars = tcpvars;
9267     ssn.state = TCP_ESTABLISHED;
9268     addr.s_addr = inet_addr("10.1.3.53");
9269     p.dst.address.address_un_data32[0] = addr.s_addr;
9270     addr1.s_addr = inet_addr("10.1.3.7");
9271     p.src.address.address_un_data32[0] = addr1.s_addr;
9272     f.protoctx = &ssn;
9273     stt.ra_ctx = ra_ctx;
9274     ssn.server = server;
9275     ssn.client = client;
9276     ssn.client.isn = 10;
9277     ssn.client.window = 5184;
9278     ssn.client.last_ack = 10;
9279     ssn.client.ra_base_seq = 10;
9280     ssn.client.next_win = 5184;
9281     ssn.server.isn = 1351079940;
9282     ssn.server.window = 5184;
9283     ssn.server.next_win = 1351088132;
9284     ssn.server.last_ack = 1351079940;
9285     ssn.server.ra_base_seq = 1351079940;
9286 
9287     tcph.th_flags = TH_PUSH | TH_ACK;
9288     p.flowflags = FLOW_PKT_TOSERVER;
9289     p.tcph->th_seq = htonl(11);
9290     p.tcph->th_ack = htonl(1351079940);
9291     p.payload_len = 9;
9292     p.ip4h->ip_src = addr1;
9293     p.tcph->th_sum = 12345;
9294 
9295     if (StreamTcp(&tv, &p, (void *)&stt, NULL, NULL) != TM_ECODE_OK) {
9296         printf("failed in segment reassmebling\n");
9297         result &= 0;
9298         goto end;
9299     }
9300 
9301     tcph.th_flags = TH_PUSH | TH_ACK;
9302     p.flowflags = FLOW_PKT_TOSERVER;
9303     p.tcph->th_seq = htonl(11);
9304     p.tcph->th_ack = htonl(1351079940);
9305     p.payload = payload1;
9306     p.payload_len = 9;
9307     p.ip4h->ip_src = addr1;
9308     p.tcph->th_sum = TCPCalculateChecksum((uint16_t *)&(p.ip4h->ip_src),
9309                                                  (uint16_t *)p.tcph,
9310                                                  (p.payload_len +
9311                                                   p.tcpvars.hlen) );
9312 
9313     if (StreamTcp(&tv, &p, (void *)&stt, NULL, NULL) != TM_ECODE_OK) {
9314         printf("failed in segment reassmebling\n");
9315         result &= 0;
9316         goto end;
9317     }
9318 
9319     tcph.th_flags = TH_ACK;
9320     p.flowflags = FLOW_PKT_TOCLIENT;
9321     p.tcph->th_seq = htonl(1351079940);
9322     p.tcph->th_ack = htonl(20);
9323     p.payload_len = 0;
9324     p.ip4h->ip_src = addr;
9325     p.tcph->th_sum = TCPCalculateChecksum((uint16_t *)&(p.ip4h->ip_src),
9326                                                  (uint16_t *)p.tcph,
9327                                                  (p.payload_len +
9328                                                   p.tcpvars.hlen) );
9329 
9330     if (StreamTcp(&tv, &p, (void *)&stt, NULL, NULL) != TM_ECODE_OK) {
9331         printf("failed in segment reassmebling\n");
9332         result &= 0;
9333         goto end;
9334     }
9335 
9336     if (StreamTcpCheckStreamContents(expected_content, 9, &ssn.client) != 1) {
9337         printf("the contents are not as expected(GET /EVIL), contents are: ");
9338         PrintRawDataFp(stdout, ssn.client.seg_list->payload, 9);
9339         result &= 0;
9340         goto end;
9341     }
9342 
9343 end:
9344     StreamTcpReturnStreamSegments(&ssn.client);
9345     StreamTcpFreeConfig(TRUE);
9346     return result;
9347 }
9348 
9349 /**
9350  *  \test   Test the multiple SYN packet handling with bad checksum and timestamp
9351  *          value. Engine should drop the bad checksum packet and establish
9352  *          TCP session correctly.
9353  *
9354  *  \retval On success it returns 1 and on failure 0.
9355  */
9356 static int StreamTcpTest31(void)
9357 {
9358     Packet p;
9359     Flow f;
9360     ThreadVars tv;
9361     StreamTcpThread stt;
9362     TCPHdr tcph;
9363     TcpSession ssn;
9364     IPV4Hdr ipv4h;
9365     TcpReassemblyThreadCtx *ra_ctx = StreamTcpReassembleInitThreadCtx(NULL);
9366     struct in_addr addr;
9367     struct in_addr addr1;
9368     TCPCache tcpc;
9369     TCPVars tcpvars;
9370     TcpStream server;
9371     TcpStream client;
9372     TCPOpt tcpopt;
9373 
9374     memset (&p, 0, SIZE_OF_PACKET);
9375     memset (&f, 0, sizeof(Flow));
9376     memset(&tv, 0, sizeof (ThreadVars));
9377     memset(&stt, 0, sizeof (StreamTcpThread));
9378     memset(&tcph, 0, sizeof (TCPHdr));
9379     memset (&ipv4h, 0, sizeof(IPV4Hdr));
9380     memset (&addr, 0, sizeof(addr));
9381     memset (&addr1, 0, sizeof(addr1));
9382     memset (&tcpc, 0, sizeof(tcpc));
9383     memset (&tcpvars, 0, sizeof(tcpvars));
9384     memset(&ssn, 0, sizeof (TcpSession));
9385     memset(&server, 0, sizeof (TcpStream));
9386     memset(&client, 0, sizeof (TcpStream));
9387     memset(&tcpopt, 0, sizeof (TCPOpt));
9388     int result = 1;
9389 
9390     StreamTcpInitConfig(TRUE);
9391 
9392     FLOW_INITIALIZE(&f);
9393     /* prevent L7 from kicking in */
9394 
9395     ssn.client.os_policy = OS_POLICY_LINUX;
9396     p.src.family = AF_INET;
9397     p.dst.family = AF_INET;
9398     p.proto = IPPROTO_TCP;
9399     p.flow = &f;
9400     tcph.th_win = 5480;
9401     p.tcph = &tcph;
9402     p.ip4h = &ipv4h;
9403     p.tcpc = tcpc;
9404     p.tcpc.level4_comp_csum = -1;
9405     p.tcpvars = tcpvars;
9406     p.tcpvars.ts = &tcpopt;
9407     addr.s_addr = inet_addr("10.1.3.53");
9408     p.dst.address.address_un_data32[0] = addr.s_addr;
9409     addr1.s_addr = inet_addr("10.1.3.7");
9410     p.src.address.address_un_data32[0] = addr1.s_addr;
9411     f.protoctx = &ssn;
9412     stt.ra_ctx = ra_ctx;
9413     ssn.server = server;
9414     ssn.client = client;
9415     ssn.client.isn = 10;
9416     ssn.client.window = 5184;
9417     ssn.client.last_ack = 10;
9418     ssn.client.ra_base_seq = 10;
9419     ssn.client.next_win = 5184;
9420     ssn.server.isn = 1351079940;
9421     ssn.server.window = 5184;
9422     ssn.server.next_win = 1351088132;
9423     ssn.server.last_ack = 1351079940;
9424     ssn.server.ra_base_seq = 1351079940;
9425 
9426     tcph.th_flags = TH_SYN;
9427     p.flowflags = FLOW_PKT_TOSERVER;
9428     p.tcph->th_seq = htonl(10);
9429     p.payload_len = 0;
9430     p.ip4h->ip_src = addr1;
9431     p.tcpc.ts1 = 100;
9432     p.tcph->th_sum = 12345;
9433 
9434     if (StreamTcp(&tv, &p, (void *)&stt, NULL, NULL) != TM_ECODE_OK) {
9435         printf("failed in segment reassmebling\n");
9436         result &= 0;
9437         goto end;
9438     }
9439 
9440     tcph.th_flags = TH_SYN;
9441     p.flowflags = FLOW_PKT_TOSERVER;
9442     p.tcph->th_seq = htonl(10);
9443     p.payload_len = 0;
9444     p.ip4h->ip_src = addr1;
9445     p.tcpc.ts1 = 10;
9446     p.tcpc.level4_comp_csum = -1;
9447     p.tcph->th_sum = TCPCalculateChecksum((uint16_t *)&(p.ip4h->ip_src),
9448                                           (uint16_t *)p.tcph,
9449                                           (p.payload_len +
9450                                            p.tcpvars.hlen) );
9451 
9452     if (StreamTcp(&tv, &p, (void *)&stt, NULL, NULL) != TM_ECODE_OK) {
9453         printf("failed in segment reassmebling\n");
9454         result &= 0;
9455         goto end;
9456     }
9457 
9458     ssn.flags |= STREAMTCP_FLAG_TIMESTAMP;
9459     tcph.th_flags = TH_SYN | TH_ACK;
9460     p.flowflags = FLOW_PKT_TOCLIENT;
9461     p.tcph->th_seq = htonl(1351079940);
9462     p.tcph->th_ack = htonl(11);
9463     p.payload_len = 0;
9464     p.tcpc.ts1 = 10;
9465     p.ip4h->ip_src = addr;
9466     p.tcpc.level4_comp_csum = -1;
9467     p.tcph->th_sum = TCPCalculateChecksum((uint16_t *)&(p.ip4h->ip_src),
9468                                           (uint16_t *)p.tcph,
9469                                           (p.payload_len +
9470                                            p.tcpvars.hlen) );
9471 
9472     if (StreamTcp(&tv, &p, (void *)&stt, NULL, NULL) != TM_ECODE_OK) {
9473         printf("failed in segment reassmebling\n");
9474         result &= 0;
9475         goto end;
9476     }
9477 
9478     tcph.th_flags = TH_ACK;
9479     p.flowflags = FLOW_PKT_TOSERVER;
9480     p.tcph->th_seq = htonl(11);
9481     p.tcph->th_ack = htonl(1351079941);
9482     p.payload_len = 0;
9483     p.tcpc.ts1 = 10;
9484     p.ip4h->ip_src = addr1;
9485     p.tcpc.level4_comp_csum = -1;
9486     p.tcph->th_sum = TCPCalculateChecksum((uint16_t *)&(p.ip4h->ip_src),
9487                                           (uint16_t *)p.tcph,
9488                                           (p.payload_len +
9489                                            p.tcpvars.hlen) );
9490 
9491     if (StreamTcp(&tv, &p, (void *)&stt, NULL, NULL) != TM_ECODE_OK) {
9492         printf("failed in segment reassmebling\n");
9493         result &= 0;
9494         goto end;
9495     }
9496 
9497     if (ssn.state != TCP_ESTABLISHED) {
9498         printf("the should have been changed to TCP_ESTABLISHED!!\n ");
9499         result &= 0;
9500         goto end;
9501     }
9502 
9503 end:
9504     StreamTcpReturnStreamSegments(&ssn.client);
9505     StreamTcpFreeConfig(TRUE);
9506     return result;
9507 }
9508 
9509 /**
9510  *  \test   Test the initialization of tcp streams with ECN & CWR flags
9511  *
9512  *  \retval On success it returns 1 and on failure 0.
9513  */
9514 static int StreamTcpTest32(void)
9515 {
9516     Packet p;
9517     Flow f;
9518     ThreadVars tv;
9519     StreamTcpThread stt;
9520     uint8_t payload[4];
9521     TCPHdr tcph;
9522     TcpReassemblyThreadCtx *ra_ctx = StreamTcpReassembleInitThreadCtx(NULL);
9523     int ret = 0;
9524     PacketQueueNoLock pq;
9525     memset(&pq,0,sizeof(PacketQueueNoLock));
9526 
9527     memset (&p, 0, SIZE_OF_PACKET);
9528     memset (&f, 0, sizeof(Flow));
9529     memset(&tv, 0, sizeof (ThreadVars));
9530     memset(&stt, 0, sizeof (StreamTcpThread));
9531     memset(&tcph, 0, sizeof (TCPHdr));
9532 
9533     FLOW_INITIALIZE(&f);
9534     stt.ra_ctx = ra_ctx;
9535     p.flow = &f;
9536     tcph.th_win = htons(5480);
9537     tcph.th_flags = TH_SYN | TH_CWR | TH_ECN;
9538     p.tcph = &tcph;
9539     p.flowflags = FLOW_PKT_TOSERVER;
9540 
9541     StreamTcpInitConfig(TRUE);
9542 
9543     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1)
9544         goto end;
9545 
9546     p.tcph->th_ack = htonl(1);
9547     p.tcph->th_flags = TH_SYN | TH_ACK | TH_ECN;
9548     p.flowflags = FLOW_PKT_TOCLIENT;
9549 
9550     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1 || (TcpSession *)p.flow->protoctx == NULL) {
9551         printf("failed in processing packet\n");
9552         goto end;
9553     }
9554 
9555     p.tcph->th_ack = htonl(1);
9556     p.tcph->th_seq = htonl(1);
9557     p.tcph->th_flags = TH_ACK | TH_ECN | TH_CWR;
9558     p.flowflags = FLOW_PKT_TOSERVER;
9559 
9560     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1 || (TcpSession *)p.flow->protoctx == NULL) {
9561         printf("failed in processing packet\n");
9562         goto end;
9563     }
9564 
9565     p.tcph->th_ack = htonl(1);
9566     p.tcph->th_seq = htonl(2);
9567     p.tcph->th_flags = TH_PUSH | TH_ACK | TH_ECN | TH_CWR;
9568     p.flowflags = FLOW_PKT_TOSERVER;
9569 
9570     StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
9571     p.payload = payload;
9572     p.payload_len = 3;
9573 
9574     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1 || (TcpSession *)p.flow->protoctx == NULL) {
9575         printf("failed in processing packet\n");
9576         goto end;
9577     }
9578 
9579     p.flowflags = FLOW_PKT_TOCLIENT;
9580     p.tcph->th_flags = TH_ACK;
9581     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1 || (TcpSession *)p.flow->protoctx == NULL) {
9582         printf("failed in processing packet\n");
9583         goto end;
9584     }
9585 
9586     if (((TcpSession *)p.flow->protoctx)->state != TCP_ESTABLISHED) {
9587         printf("the TCP state should be TCP_ESTABLISEHD\n");
9588         goto end;
9589     }
9590     StreamTcpSessionClear(p.flow->protoctx);
9591 
9592     ret = 1;
9593 end:
9594     StreamTcpFreeConfig(TRUE);
9595     return ret;
9596 }
9597 
9598 /**
9599  *  \test   Test the allocation of TCP session for a given packet when the same
9600  *          ports have been used to start the new session after resetting the
9601  *          previous session.
9602  *
9603  *  \retval On success it returns 1 and on failure 0.
9604  */
9605 
9606 static int StreamTcpTest33 (void)
9607 {
9608     Packet p;
9609     Flow f;
9610     ThreadVars tv;
9611     StreamTcpThread stt;
9612     TCPHdr tcph;
9613     TcpReassemblyThreadCtx ra_ctx;
9614     PacketQueueNoLock pq;
9615     memset(&pq,0,sizeof(PacketQueueNoLock));
9616     memset(&ra_ctx, 0, sizeof(TcpReassemblyThreadCtx));
9617     memset (&p, 0, SIZE_OF_PACKET);
9618     memset (&f, 0, sizeof(Flow));
9619     memset(&tv, 0, sizeof (ThreadVars));
9620     memset(&stt, 0, sizeof (StreamTcpThread));
9621     memset(&tcph, 0, sizeof (TCPHdr));
9622 
9623     FLOW_INITIALIZE(&f);
9624     p.flow = &f;
9625     tcph.th_win = htons(5480);
9626     tcph.th_flags = TH_SYN;
9627     p.tcph = &tcph;
9628     p.flowflags = FLOW_PKT_TOSERVER;
9629     int ret = 0;
9630     stt.ra_ctx = &ra_ctx;
9631 
9632     StreamTcpInitConfig(TRUE);
9633 
9634     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1)
9635         goto end;
9636 
9637     p.tcph->th_ack = htonl(1);
9638     p.tcph->th_flags = TH_SYN | TH_ACK;
9639     p.flowflags = FLOW_PKT_TOCLIENT;
9640 
9641     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1)
9642         goto end;
9643 
9644     p.tcph->th_ack = htonl(1);
9645     p.tcph->th_seq = htonl(1);
9646     p.tcph->th_flags = TH_ACK;
9647     p.flowflags = FLOW_PKT_TOSERVER;
9648 
9649     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1)
9650         goto end;
9651 
9652     p.tcph->th_ack = htonl(1);
9653     p.tcph->th_seq = htonl(1);
9654     p.tcph->th_flags = TH_RST | TH_ACK;
9655     p.flowflags = FLOW_PKT_TOSERVER;
9656 
9657     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1)
9658         goto end;
9659 
9660     if (((TcpSession *)(p.flow->protoctx))->state != TCP_CLOSED) {
9661         printf("Tcp session should have been closed\n");
9662         goto end;
9663     }
9664 
9665     p.tcph->th_seq = htonl(1);
9666     p.tcph->th_flags = TH_SYN;
9667     p.flowflags = FLOW_PKT_TOSERVER;
9668 
9669     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1)
9670         goto end;
9671 
9672     p.tcph->th_seq = htonl(1);
9673     p.tcph->th_ack = htonl(2);
9674     p.tcph->th_flags = TH_SYN | TH_ACK;
9675     p.flowflags = FLOW_PKT_TOCLIENT;
9676 
9677     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1)
9678         goto end;
9679 
9680     p.tcph->th_ack = htonl(2);
9681     p.tcph->th_seq = htonl(2);
9682     p.tcph->th_flags = TH_ACK;
9683     p.flowflags = FLOW_PKT_TOSERVER;
9684 
9685     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1)
9686         goto end;
9687 
9688     if (((TcpSession *)(p.flow->protoctx))->state != TCP_ESTABLISHED) {
9689         printf("Tcp session should have been ESTABLISHED\n");
9690         goto end;
9691     }
9692 
9693     ret = 1;
9694 end:
9695     StreamTcpSessionClear(p.flow->protoctx);
9696     StreamTcpFreeConfig(TRUE);
9697     return ret;
9698 }
9699 
9700 /**
9701  *  \test   Test the allocation of TCP session for a given packet when the SYN
9702  *          packet is sent with the PUSH flag set.
9703  *
9704  *  \retval On success it returns 1 and on failure 0.
9705  */
9706 
9707 static int StreamTcpTest34 (void)
9708 {
9709     Packet p;
9710     Flow f;
9711     ThreadVars tv;
9712     StreamTcpThread stt;
9713     TCPHdr tcph;
9714     TcpReassemblyThreadCtx ra_ctx;
9715     PacketQueueNoLock pq;
9716     memset(&pq,0,sizeof(PacketQueueNoLock));
9717     memset(&ra_ctx, 0, sizeof(TcpReassemblyThreadCtx));
9718     memset (&p, 0, SIZE_OF_PACKET);
9719     memset (&f, 0, sizeof(Flow));
9720     memset(&tv, 0, sizeof (ThreadVars));
9721     memset(&stt, 0, sizeof (StreamTcpThread));
9722     memset(&tcph, 0, sizeof (TCPHdr));
9723 
9724     FLOW_INITIALIZE(&f);
9725     p.flow = &f;
9726     tcph.th_win = htons(5480);
9727     tcph.th_flags = TH_SYN|TH_PUSH;
9728     p.tcph = &tcph;
9729     p.flowflags = FLOW_PKT_TOSERVER;
9730     int ret = 0;
9731     stt.ra_ctx = &ra_ctx;
9732 
9733     StreamTcpInitConfig(TRUE);
9734 
9735     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1)
9736         goto end;
9737 
9738     p.tcph->th_ack = htonl(1);
9739     p.tcph->th_flags = TH_SYN | TH_ACK;
9740     p.flowflags = FLOW_PKT_TOCLIENT;
9741 
9742     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1)
9743         goto end;
9744 
9745     p.tcph->th_ack = htonl(1);
9746     p.tcph->th_seq = htonl(1);
9747     p.tcph->th_flags = TH_ACK;
9748     p.flowflags = FLOW_PKT_TOSERVER;
9749 
9750     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1)
9751         goto end;
9752 
9753     if (((TcpSession *)(p.flow->protoctx))->state != TCP_ESTABLISHED) {
9754         printf("Tcp session should have been establisehd\n");
9755         goto end;
9756     }
9757 
9758     ret = 1;
9759 end:
9760     StreamTcpSessionClear(p.flow->protoctx);
9761     StreamTcpFreeConfig(TRUE);
9762     return ret;
9763 }
9764 
9765 /**
9766  *  \test   Test the allocation of TCP session for a given packet when the SYN
9767  *          packet is sent with the URG flag set.
9768  *
9769  *  \retval On success it returns 1 and on failure 0.
9770  */
9771 
9772 static int StreamTcpTest35 (void)
9773 {
9774     Packet p;
9775     Flow f;
9776     ThreadVars tv;
9777     StreamTcpThread stt;
9778     TCPHdr tcph;
9779     TcpReassemblyThreadCtx ra_ctx;
9780     PacketQueueNoLock pq;
9781     memset(&pq,0,sizeof(PacketQueueNoLock));
9782     memset(&ra_ctx, 0, sizeof(TcpReassemblyThreadCtx));
9783     memset (&p, 0, SIZE_OF_PACKET);
9784     memset (&f, 0, sizeof(Flow));
9785     memset(&tv, 0, sizeof (ThreadVars));
9786     memset(&stt, 0, sizeof (StreamTcpThread));
9787     memset(&tcph, 0, sizeof (TCPHdr));
9788 
9789     FLOW_INITIALIZE(&f);
9790     p.flow = &f;
9791     tcph.th_win = htons(5480);
9792     tcph.th_flags = TH_SYN|TH_URG;
9793     p.tcph = &tcph;
9794     p.flowflags = FLOW_PKT_TOSERVER;
9795     int ret = 0;
9796     stt.ra_ctx = &ra_ctx;
9797 
9798     StreamTcpInitConfig(TRUE);
9799 
9800     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1)
9801         goto end;
9802 
9803     p.tcph->th_ack = htonl(1);
9804     p.tcph->th_flags = TH_SYN | TH_ACK;
9805     p.flowflags = FLOW_PKT_TOCLIENT;
9806 
9807     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1)
9808         goto end;
9809 
9810     p.tcph->th_ack = htonl(1);
9811     p.tcph->th_seq = htonl(1);
9812     p.tcph->th_flags = TH_ACK;
9813     p.flowflags = FLOW_PKT_TOSERVER;
9814 
9815     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1)
9816         goto end;
9817 
9818     if (((TcpSession *)(p.flow->protoctx))->state != TCP_ESTABLISHED) {
9819         printf("Tcp session should have been establisehd\n");
9820         goto end;
9821     }
9822 
9823     ret = 1;
9824 end:
9825     StreamTcpSessionClear(p.flow->protoctx);
9826     StreamTcpFreeConfig(TRUE);
9827     return ret;
9828 }
9829 
9830 /**
9831  *  \test   Test the processing of PSH and URG flag in tcp session.
9832  *
9833  *  \retval On success it returns 1 and on failure 0.
9834  */
9835 static int StreamTcpTest36(void)
9836 {
9837     Packet p;
9838     Flow f;
9839     ThreadVars tv;
9840     StreamTcpThread stt;
9841     uint8_t payload[4];
9842     TCPHdr tcph;
9843     TcpReassemblyThreadCtx *ra_ctx = StreamTcpReassembleInitThreadCtx(NULL);
9844     int ret = 0;
9845     PacketQueueNoLock pq;
9846     memset(&pq,0,sizeof(PacketQueueNoLock));
9847 
9848     memset (&p, 0, SIZE_OF_PACKET);
9849     memset (&f, 0, sizeof(Flow));
9850     memset(&tv, 0, sizeof (ThreadVars));
9851     memset(&stt, 0, sizeof (StreamTcpThread));
9852     memset(&tcph, 0, sizeof (TCPHdr));
9853 
9854     FLOW_INITIALIZE(&f);
9855     stt.ra_ctx = ra_ctx;
9856     p.flow = &f;
9857     tcph.th_win = htons(5480);
9858     tcph.th_flags = TH_SYN;
9859     p.tcph = &tcph;
9860     p.flowflags = FLOW_PKT_TOSERVER;
9861 
9862     StreamTcpInitConfig(TRUE);
9863 
9864     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1) {
9865         printf("failed in processing packet\n");
9866         goto end;
9867     }
9868 
9869     p.tcph->th_ack = htonl(1);
9870     p.tcph->th_flags = TH_SYN | TH_ACK;
9871     p.flowflags = FLOW_PKT_TOCLIENT;
9872 
9873     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1 || (TcpSession *)p.flow->protoctx == NULL) {
9874         printf("failed in processing packet\n");
9875         goto end;
9876     }
9877 
9878     p.tcph->th_ack = htonl(1);
9879     p.tcph->th_seq = htonl(1);
9880     p.tcph->th_flags = TH_ACK;
9881     p.flowflags = FLOW_PKT_TOSERVER;
9882 
9883     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1 || (TcpSession *)p.flow->protoctx == NULL) {
9884         printf("failed in processing packet\n");
9885         goto end;
9886     }
9887 
9888     if (((TcpSession *)p.flow->protoctx)->state != TCP_ESTABLISHED) {
9889         printf("the TCP state should be TCP_ESTABLISEHD\n");
9890         goto end;
9891     }
9892 
9893     p.tcph->th_ack = htonl(2);
9894     p.tcph->th_seq = htonl(1);
9895     p.tcph->th_flags = TH_PUSH | TH_ACK | TH_URG;
9896     p.flowflags = FLOW_PKT_TOSERVER;
9897 
9898     StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
9899     p.payload = payload;
9900     p.payload_len = 3;
9901 
9902     if (StreamTcpPacket(&tv, &p, &stt, &pq) == -1 || (TcpSession *)p.flow->protoctx == NULL) {
9903         printf("failed in processing packet\n");
9904         goto end;
9905     }
9906 
9907     if (((TcpSession *)p.flow->protoctx)->client.next_seq != 4) {
9908         printf("the ssn->client.next_seq should be 4, but it is %"PRIu32"\n",
9909                 ((TcpSession *)p.flow->protoctx)->client.next_seq);
9910         goto end;
9911     }
9912 
9913     StreamTcpSessionClear(p.flow->protoctx);
9914 
9915     ret = 1;
9916 end:
9917     StreamTcpFreeConfig(TRUE);
9918     return ret;
9919 }
9920 #endif
9921 
9922 /**
9923  *  \test   Test the processing of out of order FIN packets in tcp session.
9924  *
9925  *  \retval On success it returns 1 and on failure 0.
9926  */
StreamTcpTest37(void)9927 static int StreamTcpTest37(void)
9928 {
9929     Packet *p = SCMalloc(SIZE_OF_PACKET);
9930     if (unlikely(p == NULL))
9931         return 0;
9932     Flow f;
9933     ThreadVars tv;
9934     StreamTcpThread stt;
9935     uint8_t payload[4];
9936     TCPHdr tcph;
9937     int ret = 0;
9938     PacketQueueNoLock pq;
9939     memset(&pq,0,sizeof(PacketQueueNoLock));
9940 
9941     memset(p, 0, SIZE_OF_PACKET);
9942     memset (&f, 0, sizeof(Flow));
9943     memset(&tv, 0, sizeof (ThreadVars));
9944     memset(&stt, 0, sizeof (StreamTcpThread));
9945     memset(&tcph, 0, sizeof (TCPHdr));
9946 
9947     FLOW_INITIALIZE(&f);
9948 
9949     p->flow = &f;
9950     tcph.th_win = htons(5480);
9951     tcph.th_flags = TH_SYN;
9952     p->tcph = &tcph;
9953     p->flowflags = FLOW_PKT_TOSERVER;
9954 
9955     StreamTcpUTInit(&stt.ra_ctx);
9956 
9957     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
9958         printf("failed in processing packet\n");
9959         goto end;
9960     }
9961 
9962     p->tcph->th_ack = htonl(1);
9963     p->tcph->th_flags = TH_SYN | TH_ACK;
9964     p->flowflags = FLOW_PKT_TOCLIENT;
9965 
9966     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL) {
9967         printf("failed in processing packet\n");
9968         goto end;
9969     }
9970 
9971     p->tcph->th_ack = htonl(1);
9972     p->tcph->th_seq = htonl(1);
9973     p->tcph->th_flags = TH_ACK;
9974     p->flowflags = FLOW_PKT_TOSERVER;
9975 
9976     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL) {
9977         printf("failed in processing packet\n");
9978         goto end;
9979     }
9980 
9981     if (((TcpSession *)p->flow->protoctx)->state != TCP_ESTABLISHED) {
9982         printf("the TCP state should be TCP_ESTABLISEHD\n");
9983         goto end;
9984     }
9985 
9986     p->tcph->th_ack = htonl(2);
9987     p->tcph->th_seq = htonl(4);
9988     p->tcph->th_flags = TH_ACK|TH_FIN;
9989     p->flowflags = FLOW_PKT_TOSERVER;
9990 
9991     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL) {
9992         printf("failed in processing packet\n");
9993         goto end;
9994     }
9995 
9996     if (((TcpSession *)p->flow->protoctx)->state != TCP_CLOSE_WAIT) {
9997         printf("the TCP state should be TCP_CLOSE_WAIT\n");
9998         goto end;
9999     }
10000 
10001     p->tcph->th_ack = htonl(1);
10002     p->tcph->th_seq = htonl(1);
10003     p->tcph->th_flags = TH_PUSH | TH_ACK;
10004     p->flowflags = FLOW_PKT_TOSERVER;
10005 
10006     StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
10007     p->payload = payload;
10008     p->payload_len = 3;
10009 
10010     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL) {
10011         printf("failed in processing packet\n");
10012         goto end;
10013     }
10014 
10015     p->tcph->th_ack = htonl(4);
10016     p->tcph->th_seq = htonl(2);
10017     p->tcph->th_flags = TH_ACK;
10018     p->payload_len = 0;
10019     p->flowflags = FLOW_PKT_TOCLIENT;
10020 
10021     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL) {
10022         printf("failed in processing packet\n");
10023         goto end;
10024     }
10025 
10026     TcpStream *stream = &(((TcpSession *)p->flow->protoctx)->client);
10027     FAIL_IF(STREAM_RAW_PROGRESS(stream) != 0); // no detect no progress update
10028 
10029     StreamTcpSessionClear(p->flow->protoctx);
10030 
10031     ret = 1;
10032 end:
10033     SCFree(p);
10034     FLOW_DESTROY(&f);
10035     StreamTcpUTDeinit(stt.ra_ctx);
10036     return ret;
10037 }
10038 
10039 /**
10040  *  \test   Test the validation of the ACK number before setting up the
10041  *          stream.last_ack.
10042  *
10043  *  \retval On success it returns 1 and on failure 0.
10044  */
10045 
StreamTcpTest38(void)10046 static int StreamTcpTest38 (void)
10047 {
10048     int ret = 0;
10049     Flow f;
10050     ThreadVars tv;
10051     StreamTcpThread stt;
10052     uint8_t payload[128];
10053     TCPHdr tcph;
10054     PacketQueueNoLock pq;
10055 
10056     memset (&f, 0, sizeof(Flow));
10057     memset(&tv, 0, sizeof (ThreadVars));
10058     memset(&stt, 0, sizeof (StreamTcpThread));
10059     memset(&tcph, 0, sizeof (TCPHdr));
10060     memset(&pq,0,sizeof(PacketQueueNoLock));
10061 
10062     Packet *p = SCMalloc(SIZE_OF_PACKET);
10063     if (unlikely(p == NULL))
10064         return 0;
10065     memset(p, 0, SIZE_OF_PACKET);
10066 
10067     FLOW_INITIALIZE(&f);
10068     p->flow = &f;
10069     tcph.th_win = htons(5480);
10070     tcph.th_flags = TH_SYN;
10071     p->tcph = &tcph;
10072     p->flowflags = FLOW_PKT_TOSERVER;
10073 
10074     StreamTcpUTInit(&stt.ra_ctx);
10075     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
10076         printf("failed in processing packet in StreamTcpPacket\n");
10077         goto end;
10078     }
10079 
10080     p->tcph->th_ack = htonl(1);
10081     p->tcph->th_flags = TH_SYN | TH_ACK;
10082     p->flowflags = FLOW_PKT_TOCLIENT;
10083 
10084     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
10085         printf("failed in processing packet in StreamTcpPacket\n");
10086         goto end;
10087     }
10088 
10089     p->tcph->th_ack = htonl(1);
10090     p->tcph->th_seq = htonl(1);
10091     p->tcph->th_flags = TH_ACK;
10092     p->flowflags = FLOW_PKT_TOSERVER;
10093 
10094     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
10095         printf("failed in processing packet in StreamTcpPacket\n");
10096         goto end;
10097     }
10098 
10099     p->tcph->th_ack = htonl(29847);
10100     p->tcph->th_seq = htonl(2);
10101     p->tcph->th_flags = TH_PUSH | TH_ACK;
10102     p->flowflags = FLOW_PKT_TOSERVER;
10103 
10104     StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
10105     p->payload = payload;
10106     p->payload_len = 3;
10107 
10108     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
10109         printf("failed in processing packet in StreamTcpPacket\n");
10110         goto end;
10111     }
10112 
10113     /* last_ack value should be 1 as the previous sent ACK value is out of
10114        window */
10115     if (((TcpSession *)(p->flow->protoctx))->server.last_ack != 1) {
10116         printf("the server.last_ack should be 1, but it is %"PRIu32"\n",
10117                 ((TcpSession *)(p->flow->protoctx))->server.last_ack);
10118         goto end;
10119     }
10120 
10121     p->tcph->th_ack = htonl(1);
10122     p->tcph->th_seq = htonl(1);
10123     p->tcph->th_flags = TH_PUSH | TH_ACK;
10124     p->flowflags = FLOW_PKT_TOCLIENT;
10125 
10126     StreamTcpCreateTestPacket(payload, 0x41, 127, 128); /*AAA*/
10127     p->payload = payload;
10128     p->payload_len = 127;
10129 
10130     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
10131         printf("failed in processing packet in StreamTcpPacket\n");
10132         goto end;
10133     }
10134 
10135     if (((TcpSession *)(p->flow->protoctx))->server.next_seq != 128) {
10136         printf("the server.next_seq should be 128, but it is %"PRIu32"\n",
10137                 ((TcpSession *)(p->flow->protoctx))->server.next_seq);
10138         goto end;
10139     }
10140 
10141     p->tcph->th_ack = htonl(256); // in window, but beyond next_seq
10142     p->tcph->th_seq = htonl(5);
10143     p->tcph->th_flags = TH_PUSH | TH_ACK;
10144     p->flowflags = FLOW_PKT_TOSERVER;
10145 
10146     StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
10147     p->payload = payload;
10148     p->payload_len = 3;
10149 
10150     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
10151         printf("failed in processing packet in StreamTcpPacket\n");
10152         goto end;
10153     }
10154 
10155     /* last_ack value should be 256, as the previous sent ACK value
10156        is inside window */
10157     if (((TcpSession *)(p->flow->protoctx))->server.last_ack != 256) {
10158         printf("the server.last_ack should be 1, but it is %"PRIu32"\n",
10159                 ((TcpSession *)(p->flow->protoctx))->server.last_ack);
10160         goto end;
10161     }
10162 
10163     p->tcph->th_ack = htonl(128);
10164     p->tcph->th_seq = htonl(8);
10165     p->tcph->th_flags = TH_PUSH | TH_ACK;
10166     p->flowflags = FLOW_PKT_TOSERVER;
10167 
10168     StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
10169     p->payload = payload;
10170     p->payload_len = 3;
10171 
10172     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
10173         printf("failed in processing packet in StreamTcpPacket\n");
10174         goto end;
10175     }
10176 
10177     /* last_ack value should be 256 as the previous sent ACK value is inside
10178        window */
10179     if (((TcpSession *)(p->flow->protoctx))->server.last_ack != 256) {
10180         printf("the server.last_ack should be 256, but it is %"PRIu32"\n",
10181                 ((TcpSession *)(p->flow->protoctx))->server.last_ack);
10182         goto end;
10183     }
10184 
10185     ret = 1;
10186 
10187 end:
10188     StreamTcpSessionClear(p->flow->protoctx);
10189     SCFree(p);
10190     FLOW_DESTROY(&f);
10191     StreamTcpUTDeinit(stt.ra_ctx);
10192     return ret;
10193 }
10194 
10195 /**
10196  *  \test   Test the validation of the ACK number before setting up the
10197  *          stream.last_ack and update the next_seq after loosing the .
10198  *
10199  *  \retval On success it returns 1 and on failure 0.
10200  */
10201 
StreamTcpTest39(void)10202 static int StreamTcpTest39 (void)
10203 {
10204     Flow f;
10205     ThreadVars tv;
10206     StreamTcpThread stt;
10207     uint8_t payload[4];
10208     TCPHdr tcph;
10209     PacketQueueNoLock pq;
10210 
10211     memset (&f, 0, sizeof(Flow));
10212     memset(&tv, 0, sizeof (ThreadVars));
10213     memset(&stt, 0, sizeof (StreamTcpThread));
10214     memset(&tcph, 0, sizeof (TCPHdr));
10215     memset(&pq,0,sizeof(PacketQueueNoLock));
10216 
10217     Packet *p = SCMalloc(SIZE_OF_PACKET);
10218     if (unlikely(p == NULL))
10219         return 0;
10220     memset(p, 0, SIZE_OF_PACKET);
10221 
10222     FLOW_INITIALIZE(&f);
10223     p->flow = &f;
10224     tcph.th_win = htons(5480);
10225     tcph.th_flags = TH_SYN;
10226     p->tcph = &tcph;
10227     p->flowflags = FLOW_PKT_TOSERVER;
10228     int ret = 0;
10229 
10230     StreamTcpUTInit(&stt.ra_ctx);
10231 
10232     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
10233         printf("failed in processing packet in StreamTcpPacket\n");
10234         goto end;
10235     }
10236 
10237     p->tcph->th_ack = htonl(1);
10238     p->tcph->th_flags = TH_SYN | TH_ACK;
10239     p->flowflags = FLOW_PKT_TOCLIENT;
10240 
10241     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
10242         printf("failed in processing packet in StreamTcpPacket\n");
10243         goto end;
10244     }
10245 
10246     p->tcph->th_ack = htonl(1);
10247     p->tcph->th_seq = htonl(1);
10248     p->tcph->th_flags = TH_ACK;
10249     p->flowflags = FLOW_PKT_TOSERVER;
10250 
10251     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
10252         printf("failed in processing packet in StreamTcpPacket\n");
10253         goto end;
10254     }
10255 
10256     p->tcph->th_ack = htonl(1);
10257     p->tcph->th_seq = htonl(1);
10258     p->tcph->th_flags = TH_PUSH | TH_ACK;
10259     p->flowflags = FLOW_PKT_TOCLIENT;
10260 
10261     StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
10262     p->payload = payload;
10263     p->payload_len = 3;
10264 
10265     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
10266         printf("failed in processing packet in StreamTcpPacket\n");
10267         goto end;
10268     }
10269 
10270     if (((TcpSession *)(p->flow->protoctx))->server.next_seq != 4) {
10271         printf("the server.next_seq should be 4, but it is %"PRIu32"\n",
10272                 ((TcpSession *)(p->flow->protoctx))->server.next_seq);
10273         goto end;
10274     }
10275 
10276     p->tcph->th_ack = htonl(4);
10277     p->tcph->th_seq = htonl(2);
10278     p->tcph->th_flags = TH_PUSH | TH_ACK;
10279     p->flowflags = FLOW_PKT_TOSERVER;
10280 
10281     StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
10282     p->payload = payload;
10283     p->payload_len = 3;
10284 
10285     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
10286         printf("failed in processing packet in StreamTcpPacket\n");
10287         goto end;
10288     }
10289 
10290     /* last_ack value should be 4 as the previous sent ACK value is inside
10291        window */
10292     if (((TcpSession *)(p->flow->protoctx))->server.last_ack != 4) {
10293         printf("the server.last_ack should be 4, but it is %"PRIu32"\n",
10294                 ((TcpSession *)(p->flow->protoctx))->server.last_ack);
10295         goto end;
10296     }
10297 
10298     p->tcph->th_seq = htonl(4);
10299     p->tcph->th_ack = htonl(5);
10300     p->tcph->th_flags = TH_PUSH | TH_ACK;
10301     p->flowflags = FLOW_PKT_TOCLIENT;
10302 
10303     StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
10304     p->payload = payload;
10305     p->payload_len = 3;
10306 
10307     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
10308         printf("failed in processing packet in StreamTcpPacket\n");
10309         goto end;
10310     }
10311 
10312     /* next_seq value should be 2987 as the previous sent ACK value is inside
10313        window */
10314     if (((TcpSession *)(p->flow->protoctx))->server.next_seq != 7) {
10315         printf("the server.next_seq should be 7, but it is %"PRIu32"\n",
10316                 ((TcpSession *)(p->flow->protoctx))->server.next_seq);
10317         goto end;
10318     }
10319 
10320     ret = 1;
10321 
10322 end:
10323     StreamTcpSessionClear(p->flow->protoctx);
10324     SCFree(p);
10325     FLOW_DESTROY(&f);
10326     StreamTcpUTDeinit(stt.ra_ctx);
10327     return ret;
10328 }
10329 
10330 /** \test multiple different SYN/ACK, pick first */
StreamTcpTest42(void)10331 static int StreamTcpTest42 (void)
10332 {
10333     int ret = 0;
10334     Flow f;
10335     ThreadVars tv;
10336     StreamTcpThread stt;
10337     TCPHdr tcph;
10338     PacketQueueNoLock pq;
10339     Packet *p = SCMalloc(SIZE_OF_PACKET);
10340     TcpSession *ssn;
10341 
10342     if (unlikely(p == NULL))
10343         return 0;
10344     memset(p, 0, SIZE_OF_PACKET);
10345 
10346     memset(&pq,0,sizeof(PacketQueueNoLock));
10347     memset (&f, 0, sizeof(Flow));
10348     memset(&tv, 0, sizeof (ThreadVars));
10349     memset(&stt, 0, sizeof (StreamTcpThread));
10350     memset(&tcph, 0, sizeof (TCPHdr));
10351 
10352     StreamTcpUTInit(&stt.ra_ctx);
10353 
10354     FLOW_INITIALIZE(&f);
10355     p->tcph = &tcph;
10356     tcph.th_win = htons(5480);
10357     p->flow = &f;
10358 
10359     /* SYN pkt */
10360     tcph.th_flags = TH_SYN;
10361     tcph.th_seq = htonl(100);
10362     p->flowflags = FLOW_PKT_TOSERVER;
10363 
10364     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
10365         goto end;
10366 
10367     /* SYN/ACK */
10368     p->tcph->th_seq = htonl(500);
10369     p->tcph->th_ack = htonl(101);
10370     p->tcph->th_flags = TH_SYN | TH_ACK;
10371     p->flowflags = FLOW_PKT_TOCLIENT;
10372 
10373     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
10374         goto end;
10375 
10376     /* SYN/ACK */
10377     p->tcph->th_seq = htonl(1000);
10378     p->tcph->th_ack = htonl(101);
10379     p->tcph->th_flags = TH_SYN | TH_ACK;
10380     p->flowflags = FLOW_PKT_TOCLIENT;
10381 
10382     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
10383         goto end;
10384 
10385     /* ACK */
10386     p->tcph->th_ack = htonl(501);
10387     p->tcph->th_seq = htonl(101);
10388     p->tcph->th_flags = TH_ACK;
10389     p->flowflags = FLOW_PKT_TOSERVER;
10390 
10391     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
10392         goto end;
10393 
10394     ssn = p->flow->protoctx;
10395 
10396     if (ssn->state != TCP_ESTABLISHED) {
10397         printf("state not TCP_ESTABLISHED: ");
10398         goto end;
10399     }
10400 
10401     if (ssn->server.isn != 500) {
10402         SCLogDebug("ssn->server.isn %"PRIu32" != %"PRIu32"",
10403             ssn->server.isn, 500);
10404         goto end;
10405     }
10406     if (ssn->client.isn != 100) {
10407         SCLogDebug("ssn->client.isn %"PRIu32" != %"PRIu32"",
10408             ssn->client.isn, 100);
10409         goto end;
10410     }
10411 
10412     StreamTcpSessionClear(p->flow->protoctx);
10413 
10414     ret = 1;
10415 end:
10416     SCFree(p);
10417     FLOW_DESTROY(&f);
10418     StreamTcpUTDeinit(stt.ra_ctx);
10419     return ret;
10420 }
10421 
10422 /** \test multiple different SYN/ACK, pick second */
StreamTcpTest43(void)10423 static int StreamTcpTest43 (void)
10424 {
10425     int ret = 0;
10426     Flow f;
10427     ThreadVars tv;
10428     StreamTcpThread stt;
10429     TCPHdr tcph;
10430     PacketQueueNoLock pq;
10431     Packet *p = SCMalloc(SIZE_OF_PACKET);
10432     TcpSession *ssn;
10433 
10434     if (unlikely(p == NULL))
10435         return 0;
10436     memset(p, 0, SIZE_OF_PACKET);
10437 
10438     memset(&pq,0,sizeof(PacketQueueNoLock));
10439     memset (&f, 0, sizeof(Flow));
10440     memset(&tv, 0, sizeof (ThreadVars));
10441     memset(&stt, 0, sizeof (StreamTcpThread));
10442     memset(&tcph, 0, sizeof (TCPHdr));
10443 
10444     StreamTcpUTInit(&stt.ra_ctx);
10445 
10446     FLOW_INITIALIZE(&f);
10447     p->tcph = &tcph;
10448     tcph.th_win = htons(5480);
10449     p->flow = &f;
10450 
10451     /* SYN pkt */
10452     tcph.th_flags = TH_SYN;
10453     tcph.th_seq = htonl(100);
10454     p->flowflags = FLOW_PKT_TOSERVER;
10455 
10456     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
10457         goto end;
10458 
10459     /* SYN/ACK */
10460     p->tcph->th_seq = htonl(500);
10461     p->tcph->th_ack = htonl(101);
10462     p->tcph->th_flags = TH_SYN | TH_ACK;
10463     p->flowflags = FLOW_PKT_TOCLIENT;
10464 
10465     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
10466         goto end;
10467 
10468     /* SYN/ACK */
10469     p->tcph->th_seq = htonl(1000);
10470     p->tcph->th_ack = htonl(101);
10471     p->tcph->th_flags = TH_SYN | TH_ACK;
10472     p->flowflags = FLOW_PKT_TOCLIENT;
10473 
10474     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
10475         goto end;
10476 
10477     /* ACK */
10478     p->tcph->th_ack = htonl(1001);
10479     p->tcph->th_seq = htonl(101);
10480     p->tcph->th_flags = TH_ACK;
10481     p->flowflags = FLOW_PKT_TOSERVER;
10482 
10483     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
10484         goto end;
10485 
10486     ssn = p->flow->protoctx;
10487 
10488     if (ssn->state != TCP_ESTABLISHED) {
10489         printf("state not TCP_ESTABLISHED: ");
10490         goto end;
10491     }
10492 
10493     if (ssn->server.isn != 1000) {
10494         SCLogDebug("ssn->server.isn %"PRIu32" != %"PRIu32"",
10495             ssn->server.isn, 1000);
10496         goto end;
10497     }
10498     if (ssn->client.isn != 100) {
10499         SCLogDebug("ssn->client.isn %"PRIu32" != %"PRIu32"",
10500             ssn->client.isn, 100);
10501         goto end;
10502     }
10503 
10504     StreamTcpSessionClear(p->flow->protoctx);
10505 
10506     ret = 1;
10507 end:
10508     SCFree(p);
10509     FLOW_DESTROY(&f);
10510     StreamTcpUTDeinit(stt.ra_ctx);
10511     return ret;
10512 }
10513 
10514 /** \test multiple different SYN/ACK, pick neither */
StreamTcpTest44(void)10515 static int StreamTcpTest44 (void)
10516 {
10517     int ret = 0;
10518     Flow f;
10519     ThreadVars tv;
10520     StreamTcpThread stt;
10521     TCPHdr tcph;
10522     PacketQueueNoLock pq;
10523     Packet *p = SCMalloc(SIZE_OF_PACKET);
10524     TcpSession *ssn;
10525 
10526     if (unlikely(p == NULL))
10527         return 0;
10528     memset(p, 0, SIZE_OF_PACKET);
10529 
10530     memset(&pq,0,sizeof(PacketQueueNoLock));
10531     memset (&f, 0, sizeof(Flow));
10532     memset(&tv, 0, sizeof (ThreadVars));
10533     memset(&stt, 0, sizeof (StreamTcpThread));
10534     memset(&tcph, 0, sizeof (TCPHdr));
10535 
10536     StreamTcpUTInit(&stt.ra_ctx);
10537 
10538     FLOW_INITIALIZE(&f);
10539     p->tcph = &tcph;
10540     tcph.th_win = htons(5480);
10541     p->flow = &f;
10542 
10543     /* SYN pkt */
10544     tcph.th_flags = TH_SYN;
10545     tcph.th_seq = htonl(100);
10546     p->flowflags = FLOW_PKT_TOSERVER;
10547 
10548     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
10549         goto end;
10550 
10551     /* SYN/ACK */
10552     p->tcph->th_seq = htonl(500);
10553     p->tcph->th_ack = htonl(101);
10554     p->tcph->th_flags = TH_SYN | TH_ACK;
10555     p->flowflags = FLOW_PKT_TOCLIENT;
10556 
10557     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
10558         goto end;
10559 
10560     /* SYN/ACK */
10561     p->tcph->th_seq = htonl(1000);
10562     p->tcph->th_ack = htonl(101);
10563     p->tcph->th_flags = TH_SYN | TH_ACK;
10564     p->flowflags = FLOW_PKT_TOCLIENT;
10565 
10566     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
10567         goto end;
10568 
10569     /* ACK */
10570     p->tcph->th_ack = htonl(3001);
10571     p->tcph->th_seq = htonl(101);
10572     p->tcph->th_flags = TH_ACK;
10573     p->flowflags = FLOW_PKT_TOSERVER;
10574 
10575     if (StreamTcpPacket(&tv, p, &stt, &pq) != -1)
10576         goto end;
10577 
10578     ssn = p->flow->protoctx;
10579 
10580     if (ssn->state != TCP_SYN_RECV) {
10581         SCLogDebug("state not TCP_SYN_RECV");
10582         goto end;
10583     }
10584 
10585     if (ssn->client.isn != 100) {
10586         SCLogDebug("ssn->client.isn %"PRIu32" != %"PRIu32"",
10587             ssn->client.isn, 100);
10588         goto end;
10589     }
10590 
10591     StreamTcpSessionClear(p->flow->protoctx);
10592 
10593     ret = 1;
10594 end:
10595     SCFree(p);
10596     FLOW_DESTROY(&f);
10597     StreamTcpUTDeinit(stt.ra_ctx);
10598     return ret;
10599 }
10600 
10601 /** \test multiple different SYN/ACK, over the limit */
StreamTcpTest45(void)10602 static int StreamTcpTest45 (void)
10603 {
10604     int ret = 0;
10605     Flow f;
10606     ThreadVars tv;
10607     StreamTcpThread stt;
10608     TCPHdr tcph;
10609     PacketQueueNoLock pq;
10610     Packet *p = SCMalloc(SIZE_OF_PACKET);
10611     TcpSession *ssn;
10612 
10613     if (unlikely(p == NULL))
10614         return 0;
10615     memset(p, 0, SIZE_OF_PACKET);
10616 
10617     memset(&pq,0,sizeof(PacketQueueNoLock));
10618     memset (&f, 0, sizeof(Flow));
10619     memset(&tv, 0, sizeof (ThreadVars));
10620     memset(&stt, 0, sizeof (StreamTcpThread));
10621     memset(&tcph, 0, sizeof (TCPHdr));
10622 
10623     StreamTcpUTInit(&stt.ra_ctx);
10624     stream_config.max_synack_queued = 2;
10625 
10626     FLOW_INITIALIZE(&f);
10627     p->tcph = &tcph;
10628     tcph.th_win = htons(5480);
10629     p->flow = &f;
10630 
10631     /* SYN pkt */
10632     tcph.th_flags = TH_SYN;
10633     tcph.th_seq = htonl(100);
10634     p->flowflags = FLOW_PKT_TOSERVER;
10635 
10636     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
10637         goto end;
10638 
10639     /* SYN/ACK */
10640     p->tcph->th_seq = htonl(500);
10641     p->tcph->th_ack = htonl(101);
10642     p->tcph->th_flags = TH_SYN | TH_ACK;
10643     p->flowflags = FLOW_PKT_TOCLIENT;
10644 
10645     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
10646         goto end;
10647 
10648     /* SYN/ACK */
10649     p->tcph->th_seq = htonl(1000);
10650     p->tcph->th_ack = htonl(101);
10651     p->tcph->th_flags = TH_SYN | TH_ACK;
10652     p->flowflags = FLOW_PKT_TOCLIENT;
10653 
10654     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
10655         goto end;
10656 
10657     /* SYN/ACK */
10658     p->tcph->th_seq = htonl(2000);
10659     p->tcph->th_ack = htonl(101);
10660     p->tcph->th_flags = TH_SYN | TH_ACK;
10661     p->flowflags = FLOW_PKT_TOCLIENT;
10662 
10663     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
10664         goto end;
10665 
10666     /* SYN/ACK */
10667     p->tcph->th_seq = htonl(3000);
10668     p->tcph->th_ack = htonl(101);
10669     p->tcph->th_flags = TH_SYN | TH_ACK;
10670     p->flowflags = FLOW_PKT_TOCLIENT;
10671 
10672     if (StreamTcpPacket(&tv, p, &stt, &pq) != -1)
10673         goto end;
10674 
10675     /* ACK */
10676     p->tcph->th_ack = htonl(1001);
10677     p->tcph->th_seq = htonl(101);
10678     p->tcph->th_flags = TH_ACK;
10679     p->flowflags = FLOW_PKT_TOSERVER;
10680 
10681     if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
10682         goto end;
10683 
10684     ssn = p->flow->protoctx;
10685 
10686     if (ssn->state != TCP_ESTABLISHED) {
10687         printf("state not TCP_ESTABLISHED: ");
10688         goto end;
10689     }
10690 
10691     if (ssn->server.isn != 1000) {
10692         SCLogDebug("ssn->server.isn %"PRIu32" != %"PRIu32"",
10693             ssn->server.isn, 1000);
10694         goto end;
10695     }
10696     if (ssn->client.isn != 100) {
10697         SCLogDebug("ssn->client.isn %"PRIu32" != %"PRIu32"",
10698             ssn->client.isn, 100);
10699         goto end;
10700     }
10701 
10702     StreamTcpSessionClear(p->flow->protoctx);
10703 
10704     ret = 1;
10705 end:
10706     SCFree(p);
10707     StreamTcpUTDeinit(stt.ra_ctx);
10708     return ret;
10709 }
10710 
10711 #endif /* UNITTESTS */
10712 
StreamTcpRegisterTests(void)10713 void StreamTcpRegisterTests (void)
10714 {
10715 #ifdef UNITTESTS
10716     UtRegisterTest("StreamTcpTest01 -- TCP session allocation",
10717                    StreamTcpTest01);
10718     UtRegisterTest("StreamTcpTest02 -- TCP session deallocation",
10719                    StreamTcpTest02);
10720     UtRegisterTest("StreamTcpTest03 -- SYN missed MidStream session",
10721                    StreamTcpTest03);
10722     UtRegisterTest("StreamTcpTest04 -- SYN/ACK missed MidStream session",
10723                    StreamTcpTest04);
10724     UtRegisterTest("StreamTcpTest05 -- 3WHS missed MidStream session",
10725                    StreamTcpTest05);
10726     UtRegisterTest("StreamTcpTest06 -- FIN, RST message MidStream session",
10727                    StreamTcpTest06);
10728     UtRegisterTest("StreamTcpTest07 -- PAWS invalid timestamp",
10729                    StreamTcpTest07);
10730     UtRegisterTest("StreamTcpTest08 -- PAWS valid timestamp", StreamTcpTest08);
10731     UtRegisterTest("StreamTcpTest09 -- No Client Reassembly", StreamTcpTest09);
10732     UtRegisterTest("StreamTcpTest10 -- No missed packet Async stream",
10733                    StreamTcpTest10);
10734     UtRegisterTest("StreamTcpTest11 -- SYN missed Async stream",
10735                    StreamTcpTest11);
10736     UtRegisterTest("StreamTcpTest12 -- SYN/ACK missed Async stream",
10737                    StreamTcpTest12);
10738     UtRegisterTest("StreamTcpTest13 -- opposite stream packets for Async " "stream",
10739                    StreamTcpTest13);
10740     UtRegisterTest("StreamTcp4WHSTest01", StreamTcp4WHSTest01);
10741     UtRegisterTest("StreamTcp4WHSTest02", StreamTcp4WHSTest02);
10742     UtRegisterTest("StreamTcp4WHSTest03", StreamTcp4WHSTest03);
10743     UtRegisterTest("StreamTcpTest14 -- setup OS policy", StreamTcpTest14);
10744     UtRegisterTest("StreamTcpTest15 -- setup OS policy", StreamTcpTest15);
10745     UtRegisterTest("StreamTcpTest16 -- setup OS policy", StreamTcpTest16);
10746     UtRegisterTest("StreamTcpTest17 -- setup OS policy", StreamTcpTest17);
10747     UtRegisterTest("StreamTcpTest18 -- setup OS policy", StreamTcpTest18);
10748     UtRegisterTest("StreamTcpTest19 -- setup OS policy", StreamTcpTest19);
10749     UtRegisterTest("StreamTcpTest20 -- setup OS policy", StreamTcpTest20);
10750     UtRegisterTest("StreamTcpTest21 -- setup OS policy", StreamTcpTest21);
10751     UtRegisterTest("StreamTcpTest22 -- setup OS policy", StreamTcpTest22);
10752     UtRegisterTest("StreamTcpTest23 -- stream memory leaks", StreamTcpTest23);
10753     UtRegisterTest("StreamTcpTest24 -- stream memory leaks", StreamTcpTest24);
10754     UtRegisterTest("StreamTcpTest25 -- test ecn/cwr sessions",
10755                    StreamTcpTest25);
10756     UtRegisterTest("StreamTcpTest26 -- test ecn/cwr sessions",
10757                    StreamTcpTest26);
10758     UtRegisterTest("StreamTcpTest27 -- test ecn/cwr sessions",
10759                    StreamTcpTest27);
10760     UtRegisterTest("StreamTcpTest28 -- Memcap Test", StreamTcpTest28);
10761 
10762 #if 0 /* VJ 2010/09/01 disabled since they blow up on Fedora and Fedora is
10763        * right about blowing up. The checksum functions are not used properly
10764        * in the tests. */
10765     UtRegisterTest("StreamTcpTest29 -- Badchecksum Reset Test", StreamTcpTest29, 1);
10766     UtRegisterTest("StreamTcpTest30 -- Badchecksum Overlap Test", StreamTcpTest30, 1);
10767     UtRegisterTest("StreamTcpTest31 -- MultipleSyns Test", StreamTcpTest31, 1);
10768     UtRegisterTest("StreamTcpTest32 -- Bogus CWR Test", StreamTcpTest32, 1);
10769     UtRegisterTest("StreamTcpTest33 -- RST-SYN Again Test", StreamTcpTest33, 1);
10770     UtRegisterTest("StreamTcpTest34 -- SYN-PUSH Test", StreamTcpTest34, 1);
10771     UtRegisterTest("StreamTcpTest35 -- SYN-URG Test", StreamTcpTest35, 1);
10772     UtRegisterTest("StreamTcpTest36 -- PUSH-URG Test", StreamTcpTest36, 1);
10773 #endif
10774     UtRegisterTest("StreamTcpTest37 -- Out of order FIN Test",
10775                    StreamTcpTest37);
10776 
10777     UtRegisterTest("StreamTcpTest38 -- validate ACK", StreamTcpTest38);
10778     UtRegisterTest("StreamTcpTest39 -- update next_seq", StreamTcpTest39);
10779 
10780     UtRegisterTest("StreamTcpTest42 -- SYN/ACK queue", StreamTcpTest42);
10781     UtRegisterTest("StreamTcpTest43 -- SYN/ACK queue", StreamTcpTest43);
10782     UtRegisterTest("StreamTcpTest44 -- SYN/ACK queue", StreamTcpTest44);
10783     UtRegisterTest("StreamTcpTest45 -- SYN/ACK queue", StreamTcpTest45);
10784 
10785     /* set up the reassembly tests as well */
10786     StreamTcpReassembleRegisterTests();
10787 
10788     StreamTcpSackRegisterTests ();
10789 #endif /* UNITTESTS */
10790 }
10791