suricata
stream-tcp.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2023 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 #include "packet.h"
32 #include "decode.h"
33 #include "detect.h"
34 
35 #include "flow.h"
36 #include "flow-util.h"
37 
38 #include "conf.h"
39 #include "conf-yaml-loader.h"
40 
41 #include "threads.h"
42 #include "threadvars.h"
43 #include "tm-threads.h"
44 
45 #include "util-pool.h"
46 #include "util-pool-thread.h"
47 #include "util-checksum.h"
48 #include "util-unittest.h"
49 #include "util-print.h"
50 #include "util-debug.h"
51 #include "util-device.h"
52 
53 #include "stream-tcp-private.h"
54 #include "stream-tcp.h"
55 #include "stream-tcp-cache.h"
56 #include "stream-tcp-inline.h"
57 #include "stream-tcp-reassemble.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 #include "util-exception-policy.h"
78 #include "util-time.h"
79 
80 #include "source-pcap-file.h"
81 #include "action-globals.h"
82 
83 //#define DEBUG
84 
85 #define STREAMTCP_DEFAULT_PREALLOC 2048
86 #define STREAMTCP_DEFAULT_MEMCAP (64 * 1024 * 1024) /* 64mb */
87 #define STREAMTCP_DEFAULT_REASSEMBLY_MEMCAP (256 * 1024 * 1024) /* 256mb */
88 #define STREAMTCP_DEFAULT_TOSERVER_CHUNK_SIZE 2560
89 #define STREAMTCP_DEFAULT_TOCLIENT_CHUNK_SIZE 2560
90 #define STREAMTCP_DEFAULT_MAX_SYN_QUEUED 10
91 #define STREAMTCP_DEFAULT_MAX_SYNACK_QUEUED 5
92 
93 static int StreamTcpHandleFin(ThreadVars *tv, StreamTcpThread *, TcpSession *, Packet *);
95 void StreamTcpInitConfig(bool);
98 
99 static int StreamTcpValidateTimestamp(TcpSession * , Packet *);
100 static int StreamTcpHandleTimestamp(TcpSession * , Packet *);
101 static int StreamTcpValidateRst(TcpSession * , Packet *);
102 static inline int StreamTcpValidateAck(TcpSession *ssn, TcpStream *, Packet *);
103 static int StreamTcpStateDispatch(
104  ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn, const uint8_t state);
105 
106 extern thread_local uint64_t t_pcapcnt;
107 extern int g_detect_disabled;
108 
110 static SCMutex ssn_pool_mutex = SCMUTEX_INITIALIZER; /**< init only, protect initializing and growing pool */
111 #ifdef DEBUG
112 static uint64_t ssn_pool_cnt = 0; /** counts ssns, protected by ssn_pool_mutex */
113 #endif
114 
117 SC_ATOMIC_DECLARE(uint64_t, st_memuse);
118 
120 {
121  SC_ATOMIC_INIT(st_memuse);
122 }
123 
124 void StreamTcpIncrMemuse(uint64_t size)
125 {
126  (void) SC_ATOMIC_ADD(st_memuse, size);
127  SCLogDebug("STREAM %"PRIu64", incr %"PRIu64, StreamTcpMemuseCounter(), size);
128  return;
129 }
130 
131 void StreamTcpDecrMemuse(uint64_t size)
132 {
133 #if defined(DEBUG_VALIDATION) && defined(UNITTESTS)
134  uint64_t presize = SC_ATOMIC_GET(st_memuse);
135  if (RunmodeIsUnittests()) {
136  BUG_ON(presize > UINT_MAX);
137  }
138 #endif
139 
140  (void) SC_ATOMIC_SUB(st_memuse, size);
141 
142 #if defined(DEBUG_VALIDATION) && defined(UNITTESTS)
143  if (RunmodeIsUnittests()) {
144  uint64_t postsize = SC_ATOMIC_GET(st_memuse);
145  BUG_ON(postsize > presize);
146  }
147 #endif
148  SCLogDebug("STREAM %"PRIu64", decr %"PRIu64, StreamTcpMemuseCounter(), size);
149  return;
150 }
151 
153 {
154  uint64_t memusecopy = SC_ATOMIC_GET(st_memuse);
155  return memusecopy;
156 }
157 
158 /**
159  * \brief Check if alloc'ing "size" would mean we're over memcap
160  *
161  * \retval 1 if in bounds
162  * \retval 0 if not in bounds
163  */
164 int StreamTcpCheckMemcap(uint64_t size)
165 {
166  uint64_t memcapcopy = SC_ATOMIC_GET(stream_config.memcap);
167  if (memcapcopy == 0 || size + SC_ATOMIC_GET(st_memuse) <= memcapcopy)
168  return 1;
169  return 0;
170 }
171 
172 /**
173  * \brief Update memcap value
174  *
175  * \param size new memcap value
176  */
177 int StreamTcpSetMemcap(uint64_t size)
178 {
179  if (size == 0 || (uint64_t)SC_ATOMIC_GET(st_memuse) < size) {
180  SC_ATOMIC_SET(stream_config.memcap, size);
181  return 1;
182  }
183 
184  return 0;
185 }
186 
187 /**
188  * \brief Return memcap value
189  *
190  * \param memcap memcap value
191  */
192 uint64_t StreamTcpGetMemcap(void)
193 {
194  uint64_t memcapcopy = SC_ATOMIC_GET(stream_config.memcap);
195  return memcapcopy;
196 }
197 
199 {
200  if (stream != NULL) {
201  StreamTcpSackFreeList(stream);
204  }
205 }
206 
207 static void StreamTcp3wsFreeQueue(TcpSession *ssn)
208 {
209  TcpStateQueue *q, *q_next;
210  q = ssn->queue;
211  while (q != NULL) {
212  q_next = q->next;
213  SCFree(q);
214  q = q_next;
215  StreamTcpDecrMemuse((uint64_t)sizeof(TcpStateQueue));
216  }
217  ssn->queue = NULL;
218  ssn->queue_len = 0;
219 }
220 
221 /**
222  * \brief Session cleanup function. Does not free the ssn.
223  * \param ssn tcp session
224  */
226 {
227  SCEnter();
228 
229  if (ssn == NULL)
230  return;
231 
234  StreamTcp3wsFreeQueue(ssn);
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.
246  *
247  * \param ssn Void ptr to the ssn.
248  */
249 void StreamTcpSessionClear(void *ssnptr)
250 {
251  SCEnter();
252  TcpSession *ssn = (TcpSession *)ssnptr;
253  if (ssn == NULL)
254  return;
255 
257 
258  /* HACK: don't loose track of thread id */
260  memset(ssn, 0, sizeof(TcpSession));
261  ssn->pool_id = pool_id;
262 
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  * \param p Packet used to identify the stream.
277  */
279 {
280  SCEnter();
281 
282  TcpSession *ssn = (TcpSession *)p->flow->protoctx;
283  if (ssn == NULL)
284  SCReturn;
285 
288 
289  SCReturn;
290 }
291 
292 /** \brief Stream alloc function for the Pool
293  * \retval ptr void ptr to TcpSession structure with all vars set to 0/NULL
294  */
295 static void *StreamTcpSessionPoolAlloc(void)
296 {
297  void *ptr = NULL;
298 
299  if (StreamTcpCheckMemcap((uint32_t)sizeof(TcpSession)) == 0)
300  return NULL;
301 
302  ptr = SCMalloc(sizeof(TcpSession));
303  if (unlikely(ptr == NULL))
304  return NULL;
305 
306  return ptr;
307 }
308 
309 static int StreamTcpSessionPoolInit(void *data, void* initdata)
310 {
311  memset(data, 0, sizeof(TcpSession));
312  StreamTcpIncrMemuse((uint64_t)sizeof(TcpSession));
313 
314  return 1;
315 }
316 
317 /** \brief Pool cleanup function
318  * \param s Void ptr to TcpSession memory */
319 static void StreamTcpSessionPoolCleanup(void *s)
320 {
321  if (s != NULL) {
323  /** \todo not very clean, as the memory is not freed here */
324  StreamTcpDecrMemuse((uint64_t)sizeof(TcpSession));
325  }
326 }
327 
328 /** \internal
329  * \brief See if stream engine is dropping invalid packet in inline mode
330  * \retval false no
331  * \retval true yes
332  */
333 static inline bool StreamTcpInlineDropInvalid(void)
334 {
337 }
338 
339 /* hack: stream random range code expects random values in range of 0-RAND_MAX,
340  * but we can get both <0 and >RAND_MAX values from RandomGet
341  */
342 static int RandomGetWrap(void)
343 {
344  unsigned long r;
345 
346  do {
347  r = RandomGet();
348  } while(r >= ULONG_MAX - (ULONG_MAX % RAND_MAX));
349 
350  return r % RAND_MAX;
351 }
352 
353 /** \brief To initialize the stream global configuration data
354  *
355  * \param quiet It tells the mode of operation, if it is true nothing will
356  * be get printed.
357  */
358 
359 void StreamTcpInitConfig(bool quiet)
360 {
361  intmax_t value = 0;
362  uint16_t rdrange = 10;
363 
364  SCLogDebug("Initializing Stream");
365 
366  memset(&stream_config, 0, sizeof(stream_config));
367 
369  SC_ATOMIC_INIT(stream_config.reassembly_memcap);
370 
371  if ((ConfGetInt("stream.max-sessions", &value)) == 1) {
372  SCLogWarning("max-sessions is obsolete. "
373  "Number of concurrent sessions is now only limited by Flow and "
374  "TCP stream engine memcaps.");
375  }
376 
377  if ((ConfGetInt("stream.prealloc-sessions", &value)) == 1) {
378  stream_config.prealloc_sessions = (uint32_t)value;
379  } else {
380  if (RunmodeIsUnittests()) {
382  } else {
384  if (ConfGetNode("stream.prealloc-sessions") != NULL) {
385  WarnInvalidConfEntry("stream.prealloc_sessions",
386  "%"PRIu32,
388  }
389  }
390  }
391  if (!quiet) {
392  SCLogConfig("stream \"prealloc-sessions\": %"PRIu32" (per thread)",
394  }
395 
396  const char *temp_stream_memcap_str;
397  if (ConfGet("stream.memcap", &temp_stream_memcap_str) == 1) {
398  uint64_t stream_memcap_copy;
399  if (ParseSizeStringU64(temp_stream_memcap_str, &stream_memcap_copy) < 0) {
400  SCLogError("Error parsing stream.memcap "
401  "from conf file - %s. Killing engine",
402  temp_stream_memcap_str);
403  exit(EXIT_FAILURE);
404  } else {
405  SC_ATOMIC_SET(stream_config.memcap, stream_memcap_copy);
406  }
407  } else {
409  }
410 
411  if (!quiet) {
412  SCLogConfig("stream \"memcap\": %"PRIu64, SC_ATOMIC_GET(stream_config.memcap));
413  }
414 
415  int imidstream;
416  (void)ConfGetBool("stream.midstream", &imidstream);
417  stream_config.midstream = imidstream != 0;
418 
419  if (!quiet) {
420  SCLogConfig("stream \"midstream\" session pickups: %s", stream_config.midstream ? "enabled" : "disabled");
421  }
422 
423  int async_oneside;
424  (void)ConfGetBool("stream.async-oneside", &async_oneside);
425  stream_config.async_oneside = async_oneside != 0;
426 
427  if (!quiet) {
428  SCLogConfig("stream \"async-oneside\": %s", stream_config.async_oneside ? "enabled" : "disabled");
429  }
430 
431  int csum = 0;
432 
433  if ((ConfGetBool("stream.checksum-validation", &csum)) == 1) {
434  if (csum == 1) {
436  }
437  /* Default is that we validate the checksum of all the packets */
438  } else {
440  }
441 
442  if (!quiet) {
443  SCLogConfig("stream \"checksum-validation\": %s",
445  "enabled" : "disabled");
446  }
447 
448  const char *temp_stream_inline_str;
449  if (ConfGet("stream.inline", &temp_stream_inline_str) == 1) {
450  int inl = 0;
451 
452  /* checking for "auto" and falling back to boolean to provide
453  * backward compatibility */
454  if (strcmp(temp_stream_inline_str, "auto") == 0) {
455  if (EngineModeIsIPS()) {
457  }
458  } else if (ConfGetBool("stream.inline", &inl) == 1) {
459  if (inl) {
461  }
462  }
463  } else {
464  /* default to 'auto' */
465  if (EngineModeIsIPS()) {
467  }
468  }
469  stream_config.ssn_memcap_policy = ExceptionPolicyParse("stream.memcap-policy", true);
471  ExceptionPolicyParse("stream.reassembly.memcap-policy", true);
473 
474  if (!quiet) {
475  SCLogConfig("stream.\"inline\": %s",
477  ? "enabled" : "disabled");
478  }
479 
480  int bypass = 0;
481  if ((ConfGetBool("stream.bypass", &bypass)) == 1) {
482  if (bypass == 1) {
484  }
485  }
486 
487  if (!quiet) {
488  SCLogConfig("stream \"bypass\": %s",
490  ? "enabled" : "disabled");
491  }
492 
493  int drop_invalid = 0;
494  if ((ConfGetBool("stream.drop-invalid", &drop_invalid)) == 1) {
495  if (drop_invalid == 1) {
497  }
498  } else {
500  }
501 
502  if ((ConfGetInt("stream.max-syn-queued", &value)) == 1) {
503  if (value >= 0 && value <= 255) {
504  stream_config.max_syn_queued = (uint8_t)value;
505  } else {
507  }
508  } else {
510  }
511  if (!quiet) {
512  SCLogConfig("stream \"max-syn-queued\": %" PRIu8, stream_config.max_syn_queued);
513  }
514 
515  if ((ConfGetInt("stream.max-synack-queued", &value)) == 1) {
516  if (value >= 0 && value <= 255) {
517  stream_config.max_synack_queued = (uint8_t)value;
518  } else {
520  }
521  } else {
523  }
524  if (!quiet) {
525  SCLogConfig("stream \"max-synack-queued\": %"PRIu8, stream_config.max_synack_queued);
526  }
527 
528  const char *temp_stream_reassembly_memcap_str;
529  if (ConfGet("stream.reassembly.memcap", &temp_stream_reassembly_memcap_str) == 1) {
530  uint64_t stream_reassembly_memcap_copy;
531  if (ParseSizeStringU64(temp_stream_reassembly_memcap_str,
532  &stream_reassembly_memcap_copy) < 0) {
533  SCLogError("Error parsing "
534  "stream.reassembly.memcap "
535  "from conf file - %s. Killing engine",
536  temp_stream_reassembly_memcap_str);
537  exit(EXIT_FAILURE);
538  } else {
539  SC_ATOMIC_SET(stream_config.reassembly_memcap, stream_reassembly_memcap_copy);
540  }
541  } else {
543  }
544 
545  if (!quiet) {
546  SCLogConfig("stream.reassembly \"memcap\": %"PRIu64"",
547  SC_ATOMIC_GET(stream_config.reassembly_memcap));
548  }
549 
550  const char *temp_stream_reassembly_depth_str;
551  if (ConfGet("stream.reassembly.depth", &temp_stream_reassembly_depth_str) == 1) {
552  if (ParseSizeStringU32(temp_stream_reassembly_depth_str,
554  SCLogError("Error parsing "
555  "stream.reassembly.depth "
556  "from conf file - %s. Killing engine",
557  temp_stream_reassembly_depth_str);
558  exit(EXIT_FAILURE);
559  }
560  } else {
562  }
563 
564  if (!quiet) {
565  SCLogConfig("stream.reassembly \"depth\": %"PRIu32"", stream_config.reassembly_depth);
566  }
567 
568  int randomize = 0;
569  if ((ConfGetBool("stream.reassembly.randomize-chunk-size", &randomize)) == 0) {
570  /* randomize by default if value not set
571  * In ut mode we disable, to get predictable test results */
572  if (!(RunmodeIsUnittests()))
573  randomize = 1;
574  }
575 
576  if (randomize) {
577  const char *temp_rdrange;
578  if (ConfGet("stream.reassembly.randomize-chunk-range", &temp_rdrange) == 1) {
579  if (ParseSizeStringU16(temp_rdrange, &rdrange) < 0) {
580  SCLogError("Error parsing "
581  "stream.reassembly.randomize-chunk-range "
582  "from conf file - %s. Killing engine",
583  temp_rdrange);
584  exit(EXIT_FAILURE);
585  } else if (rdrange >= 100) {
586  FatalError("stream.reassembly.randomize-chunk-range "
587  "must be lower than 100");
588  }
589  }
590  }
591 
592  const char *temp_stream_reassembly_toserver_chunk_size_str;
593  if (ConfGet("stream.reassembly.toserver-chunk-size",
594  &temp_stream_reassembly_toserver_chunk_size_str) == 1) {
595  if (ParseSizeStringU16(temp_stream_reassembly_toserver_chunk_size_str,
597  SCLogError("Error parsing "
598  "stream.reassembly.toserver-chunk-size "
599  "from conf file - %s. Killing engine",
600  temp_stream_reassembly_toserver_chunk_size_str);
601  exit(EXIT_FAILURE);
602  }
603  } else {
606  }
607 
608  if (randomize) {
609  long int r = RandomGetWrap();
611  (int)(stream_config.reassembly_toserver_chunk_size * ((double)r / RAND_MAX - 0.5) *
612  rdrange / 100);
613  }
614  const char *temp_stream_reassembly_toclient_chunk_size_str;
615  if (ConfGet("stream.reassembly.toclient-chunk-size",
616  &temp_stream_reassembly_toclient_chunk_size_str) == 1) {
617  if (ParseSizeStringU16(temp_stream_reassembly_toclient_chunk_size_str,
619  SCLogError("Error parsing "
620  "stream.reassembly.toclient-chunk-size "
621  "from conf file - %s. Killing engine",
622  temp_stream_reassembly_toclient_chunk_size_str);
623  exit(EXIT_FAILURE);
624  }
625  } else {
628  }
629 
630  if (randomize) {
631  long int r = RandomGetWrap();
633  (int)(stream_config.reassembly_toclient_chunk_size * ((double)r / RAND_MAX - 0.5) *
634  rdrange / 100);
635  }
636  if (!quiet) {
637  SCLogConfig("stream.reassembly \"toserver-chunk-size\": %"PRIu16,
639  SCLogConfig("stream.reassembly \"toclient-chunk-size\": %"PRIu16,
641  }
642 
643  int enable_raw = 1;
644  if (ConfGetBool("stream.reassembly.raw", &enable_raw) == 1) {
645  if (!enable_raw) {
647  }
648  } else {
649  enable_raw = 1;
650  }
651  if (!quiet)
652  SCLogConfig("stream.reassembly.raw: %s", enable_raw ? "enabled" : "disabled");
653 
654  /* default to true. Not many ppl (correctly) set up host-os policies, so be permissive. */
656  int liberal_timestamps = 0;
657  if (ConfGetBool("stream.liberal-timestamps", &liberal_timestamps) == 1) {
658  stream_config.liberal_timestamps = liberal_timestamps;
659  }
660  if (!quiet)
661  SCLogConfig("stream.liberal-timestamps: %s", liberal_timestamps ? "enabled" : "disabled");
662 
663  /* init the memcap/use tracking */
666 
668 
669  /* set the default free function and flow state function
670  * values. */
672 
673 #ifdef UNITTESTS
674  if (RunmodeIsUnittests()) {
675  SCMutexLock(&ssn_pool_mutex);
676  if (ssn_pool == NULL) {
677  ssn_pool = PoolThreadInit(1, /* thread */
678  0, /* unlimited */
680  sizeof(TcpSession),
681  StreamTcpSessionPoolAlloc,
682  StreamTcpSessionPoolInit, NULL,
683  StreamTcpSessionPoolCleanup, NULL);
684  }
685  SCMutexUnlock(&ssn_pool_mutex);
686  }
687 #endif
688 }
689 
690 void StreamTcpFreeConfig(bool quiet)
691 {
693 
694  SCMutexLock(&ssn_pool_mutex);
695  if (ssn_pool != NULL) {
697  ssn_pool = NULL;
698  }
699  SCMutexUnlock(&ssn_pool_mutex);
700  SCMutexDestroy(&ssn_pool_mutex);
701 
702  SCLogDebug("ssn_pool_cnt %"PRIu64"", ssn_pool_cnt);
703 }
704 
705 /** \internal
706  * \brief The function is used to fetch a TCP session from the
707  * ssn_pool, when a TCP SYN is received.
708  *
709  * \param p packet starting the new TCP session.
710  * \param id thread pool id
711  *
712  * \retval ssn new TCP session.
713  */
714 static TcpSession *StreamTcpNewSession(ThreadVars *tv, StreamTcpThread *stt, Packet *p, int id)
715 {
716  TcpSession *ssn = (TcpSession *)p->flow->protoctx;
717 
718  if (ssn == NULL) {
719  DEBUG_VALIDATE_BUG_ON(id < 0 || id > UINT16_MAX);
721  if (p->flow->protoctx != NULL) {
722 #ifdef UNITTESTS
723  if (tv)
724 #endif
726  } else {
727  p->flow->protoctx = PoolThreadGetById(ssn_pool, (uint16_t)id);
728  if (p->flow->protoctx != NULL)
729 #ifdef UNITTESTS
730  if (tv)
731 #endif
733  }
734 #ifdef DEBUG
735  SCMutexLock(&ssn_pool_mutex);
736  if (p->flow->protoctx != NULL)
737  ssn_pool_cnt++;
738  SCMutexUnlock(&ssn_pool_mutex);
739 
740  if (unlikely((g_eps_stream_ssn_memcap != UINT64_MAX &&
741  g_eps_stream_ssn_memcap == t_pcapcnt))) {
742  SCLogNotice("simulating memcap reached condition for packet %" PRIu64, t_pcapcnt);
744  return NULL;
745  }
746 #endif
747  ssn = (TcpSession *)p->flow->protoctx;
748  if (ssn == NULL) {
749  SCLogDebug("ssn_pool is empty");
751  return NULL;
752  }
753 
754  ssn->state = TCP_NONE;
756  ssn->tcp_packet_flags = p->tcph ? p->tcph->th_flags : 0;
759 
761  ssn->client.sb = x;
762  ssn->server.sb = x;
763 
764  if (PKT_IS_TOSERVER(p)) {
765  ssn->client.tcp_flags = p->tcph ? p->tcph->th_flags : 0;
766  ssn->server.tcp_flags = 0;
767  } else if (PKT_IS_TOCLIENT(p)) {
768  ssn->server.tcp_flags = p->tcph ? p->tcph->th_flags : 0;
769  ssn->client.tcp_flags = 0;
770  }
771  }
772 
773  return ssn;
774 }
775 
776 static void StreamTcpPacketSetState(Packet *p, TcpSession *ssn,
777  uint8_t state)
778 {
779  if (state == ssn->state || PKT_IS_PSEUDOPKT(p))
780  return;
781 
782  ssn->pstate = ssn->state;
783  ssn->state = state;
785 
786  /* update the flow state */
787  switch(ssn->state) {
788  case TCP_ESTABLISHED:
789  case TCP_FIN_WAIT1:
790  case TCP_FIN_WAIT2:
791  case TCP_CLOSING:
792  case TCP_CLOSE_WAIT:
794  break;
795  case TCP_LAST_ACK:
796  case TCP_TIME_WAIT:
797  case TCP_CLOSED:
799  break;
800  }
801 }
802 
803 /**
804  * \brief Function to set the OS policy for the given stream based on the
805  * destination of the received packet.
806  *
807  * \param stream TcpStream of which os_policy needs to set
808  * \param p Packet which is used to set the os policy
809  */
811 {
812  if (PKT_IS_IPV4(p)) {
813  /* Get the OS policy based on destination IP address, as destination
814  OS will decide how to react on the anomalies of newly received
815  packets */
816  int ret = SCHInfoGetIPv4HostOSFlavour((uint8_t *)GET_IPV4_DST_ADDR_PTR(p));
817  if (ret > 0)
818  stream->os_policy = (uint8_t)ret;
819  else
820  stream->os_policy = OS_POLICY_DEFAULT;
821 
822  } else if (PKT_IS_IPV6(p)) {
823  /* Get the OS policy based on destination IP address, as destination
824  OS will decide how to react on the anomalies of newly received
825  packets */
826  int ret = SCHInfoGetIPv6HostOSFlavour((uint8_t *)GET_IPV6_DST_ADDR(p));
827  if (ret > 0)
828  stream->os_policy = (uint8_t)ret;
829  else
830  stream->os_policy = OS_POLICY_DEFAULT;
831  }
832 
833  if (stream->os_policy == OS_POLICY_BSD_RIGHT)
834  stream->os_policy = OS_POLICY_BSD;
835  else if (stream->os_policy == OS_POLICY_OLD_SOLARIS)
836  stream->os_policy = OS_POLICY_SOLARIS;
837 
838  SCLogDebug("Policy is %"PRIu8"", stream->os_policy);
839 
840 }
841 
842 /**
843  * \brief macro to update last_ack only if the new value is higher
844  *
845  * \param ssn session
846  * \param stream stream to update
847  * \param ack ACK value to test and set
848  */
849 #define StreamTcpUpdateLastAck(ssn, stream, ack) { \
850  if (SEQ_GT((ack), (stream)->last_ack)) \
851  { \
852  SCLogDebug("ssn %p: last_ack set to %"PRIu32", moved %u forward", (ssn), (ack), (ack) - (stream)->last_ack); \
853  if ((SEQ_LEQ((stream)->last_ack, (stream)->next_seq) && SEQ_GT((ack),(stream)->next_seq))) { \
854  SCLogDebug("last_ack just passed next_seq: %u (was %u) > %u", (ack), (stream)->last_ack, (stream)->next_seq); \
855  } else { \
856  SCLogDebug("next_seq (%u) <> last_ack now %d", (stream)->next_seq, (int)(stream)->next_seq - (ack)); \
857  }\
858  (stream)->last_ack = (ack); \
859  StreamTcpSackPruneList((stream)); \
860  } else { \
861  SCLogDebug("ssn %p: no update: ack %u, last_ack %"PRIu32", next_seq %u (state %u)", \
862  (ssn), (ack), (stream)->last_ack, (stream)->next_seq, (ssn)->state); \
863  }\
864 }
865 
866 #define StreamTcpAsyncLastAckUpdate(ssn, stream) { \
867  if ((ssn)->flags & STREAMTCP_FLAG_ASYNC) { \
868  if (SEQ_GT((stream)->next_seq, (stream)->last_ack)) { \
869  uint32_t ack_diff = (stream)->next_seq - (stream)->last_ack; \
870  (stream)->last_ack += ack_diff; \
871  SCLogDebug("ssn %p: ASYNC last_ack set to %"PRIu32", moved %u forward", \
872  (ssn), (stream)->next_seq, ack_diff); \
873  } \
874  } \
875 }
876 
877 #define StreamTcpUpdateNextSeq(ssn, stream, seq) { \
878  (stream)->next_seq = seq; \
879  SCLogDebug("ssn %p: next_seq %" PRIu32, (ssn), (stream)->next_seq); \
880  StreamTcpAsyncLastAckUpdate((ssn), (stream)); \
881 }
882 
883 /**
884  * \brief macro to update next_win only if the new value is higher
885  *
886  * \param ssn session
887  * \param stream stream to update
888  * \param win window value to test and set
889  */
890 #define StreamTcpUpdateNextWin(ssn, stream, win) { \
891  uint32_t sacked_size__ = StreamTcpSackedSize((stream)); \
892  if (SEQ_GT(((win) + sacked_size__), (stream)->next_win)) { \
893  (stream)->next_win = ((win) + sacked_size__); \
894  SCLogDebug("ssn %p: next_win set to %"PRIu32, (ssn), (stream)->next_win); \
895  } \
896 }
897 
898 static inline void StreamTcpCloseSsnWithReset(Packet *p, TcpSession *ssn)
899 {
901  StreamTcpPacketSetState(p, ssn, TCP_CLOSED);
902  SCLogDebug("ssn %p: (state: %s) Reset received and state changed to "
903  "TCP_CLOSED", ssn, StreamTcpStateAsString(ssn->state));
904 }
905 
906 static int StreamTcpPacketIsRetransmission(TcpStream *stream, Packet *p)
907 {
908  if (p->payload_len == 0)
909  SCReturnInt(0);
910 
911  /* retransmission of already partially ack'd data */
912  if (SEQ_LT(TCP_GET_SEQ(p), stream->last_ack) && SEQ_GT((TCP_GET_SEQ(p) + p->payload_len), stream->last_ack))
913  {
915  SCReturnInt(1);
916  }
917 
918  /* retransmission of already ack'd data */
919  if (SEQ_LEQ((TCP_GET_SEQ(p) + p->payload_len), stream->last_ack)) {
921  SCReturnInt(1);
922  }
923 
924  /* retransmission of in flight data */
925  if (SEQ_LEQ((TCP_GET_SEQ(p) + p->payload_len), stream->next_seq)) {
927  SCReturnInt(2);
928  }
929 
930  SCLogDebug("seq %u payload_len %u => %u, last_ack %u, next_seq %u", TCP_GET_SEQ(p),
931  p->payload_len, (TCP_GET_SEQ(p) + p->payload_len), stream->last_ack, stream->next_seq);
932  SCReturnInt(0);
933 }
934 
935 /**
936  * \internal
937  * \brief Function to handle the TCP_CLOSED or NONE state. The function handles
938  * packets while the session state is None which means a newly
939  * initialized structure, or a fully closed session.
940  *
941  * \param tv Thread Variable containing input/output queue, cpu affinity
942  * \param p Packet which has to be handled in this TCP state.
943  * \param stt Stream Thread module registered to handle the stream handling
944  *
945  * \retval 0 ok
946  * \retval -1 error
947  */
948 static int StreamTcpPacketStateNone(
949  ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn)
950 {
951  if (p->tcph->th_flags & TH_RST) {
953  SCLogDebug("RST packet received, no session setup");
954  return -1;
955 
956  } else if (p->tcph->th_flags & TH_FIN) {
957  /* Drop reason will only be used if midstream policy is set to fail closed */
959 
960  if (!stream_config.midstream || p->payload_len == 0) {
962  SCLogDebug("FIN packet received, no session setup");
963  return -1;
964  }
968  SCLogDebug("FIN packet received, no session setup");
969  return -1;
970  }
971  SCLogDebug("midstream picked up");
972 
973  if (ssn == NULL) {
974  ssn = StreamTcpNewSession(tv, stt, p, stt->ssn_pool_id);
975  if (ssn == NULL) {
977  return -1;
978  }
982  }
983  /* set the state */
984  StreamTcpPacketSetState(p, ssn, TCP_FIN_WAIT1);
985  SCLogDebug("ssn %p: =~ midstream picked ssn state is now "
986  "TCP_FIN_WAIT1",
987  ssn);
988 
992  SCLogDebug("ssn %p: =~ ASYNC", ssn);
993  ssn->flags |= STREAMTCP_FLAG_ASYNC;
994  }
995 
996  /** window scaling for midstream pickups, we can't do much other
997  * than assume that it's set to the max value: 14 */
1000 
1001  /* set the sequence numbers and window */
1002  ssn->client.isn = TCP_GET_SEQ(p) - 1;
1004  ssn->client.next_seq = TCP_GET_SEQ(p) + p->payload_len + 1;
1005  ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
1006  ssn->client.last_ack = TCP_GET_SEQ(p);
1007  ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
1008  SCLogDebug("ssn %p: ssn->client.isn %u, ssn->client.next_seq %u", ssn, ssn->client.isn,
1009  ssn->client.next_seq);
1010 
1011  ssn->server.isn = TCP_GET_ACK(p) - 1;
1013  ssn->server.next_seq = ssn->server.isn + 1;
1014  ssn->server.last_ack = TCP_GET_ACK(p);
1015  ssn->server.next_win = ssn->server.last_ack;
1016 
1017  SCLogDebug("ssn %p: ssn->client.next_win %" PRIu32 ", "
1018  "ssn->server.next_win %" PRIu32 "",
1019  ssn, ssn->client.next_win, ssn->server.next_win);
1020  SCLogDebug("ssn %p: ssn->client.last_ack %" PRIu32 ", "
1021  "ssn->server.last_ack %" PRIu32 "",
1022  ssn, ssn->client.last_ack, ssn->server.last_ack);
1023 
1024  /* Set the timestamp value for both streams, if packet has timestamp
1025  * option enabled.*/
1026  if (TCP_HAS_TS(p)) {
1027  ssn->client.last_ts = TCP_GET_TSVAL(p);
1028  ssn->server.last_ts = TCP_GET_TSECR(p);
1029  SCLogDebug("ssn %p: ssn->server.last_ts %" PRIu32 " "
1030  "ssn->client.last_ts %" PRIu32 "",
1031  ssn, ssn->server.last_ts, ssn->client.last_ts);
1032 
1034 
1035  ssn->client.last_pkt_ts = SCTIME_SECS(p->ts);
1036  if (ssn->server.last_ts == 0)
1038  if (ssn->client.last_ts == 0)
1040 
1041  } else {
1042  ssn->server.last_ts = 0;
1043  ssn->client.last_ts = 0;
1044  }
1045 
1046  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
1047 
1048  ssn->flags |= STREAMTCP_FLAG_SACKOK;
1049  SCLogDebug("ssn %p: assuming SACK permitted for both sides", ssn);
1050 
1051  /* SYN/ACK */
1052  } else if ((p->tcph->th_flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK)) {
1053  /* Drop reason will only be used if midstream policy is set to fail closed */
1055 
1057  SCLogDebug("Midstream not enabled, so won't pick up a session");
1058  return 0;
1059  }
1062  SCLogDebug("Midstream policy not permissive, so won't pick up a session");
1063  return 0;
1064  }
1065  SCLogDebug("midstream picked up");
1066 
1067  if (ssn == NULL) {
1068  ssn = StreamTcpNewSession(tv, stt, p, stt->ssn_pool_id);
1069  if (ssn == NULL) {
1071  return -1;
1072  }
1076  }
1077 
1078  /* reverse packet and flow */
1079  SCLogDebug("reversing flow and packet");
1080  PacketSwap(p);
1081  FlowSwap(p->flow);
1082 
1083  /* set the state */
1084  StreamTcpPacketSetState(p, ssn, TCP_SYN_RECV);
1085  SCLogDebug("ssn %p: =~ midstream picked ssn state is now "
1086  "TCP_SYN_RECV", ssn);
1088  /* Flag used to change the direct in the later stage in the session */
1091  SCLogDebug("ssn %p: =~ ASYNC", ssn);
1092  ssn->flags |= STREAMTCP_FLAG_ASYNC;
1093  }
1094 
1095  /* sequence number & window */
1096  ssn->server.isn = TCP_GET_SEQ(p);
1098  ssn->server.next_seq = ssn->server.isn + 1;
1099  ssn->server.window = TCP_GET_WINDOW(p);
1100  SCLogDebug("ssn %p: server window %u", ssn, ssn->server.window);
1101 
1102  ssn->client.isn = TCP_GET_ACK(p) - 1;
1104  ssn->client.next_seq = ssn->client.isn + 1;
1105 
1106  ssn->client.last_ack = TCP_GET_ACK(p);
1107  ssn->server.last_ack = TCP_GET_SEQ(p);
1108 
1109  ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
1110 
1111  /** If the client has a wscale option the server had it too,
1112  * so set the wscale for the server to max. Otherwise none
1113  * will have the wscale opt just like it should. */
1114  if (TCP_HAS_WSCALE(p)) {
1115  ssn->client.wscale = TCP_GET_WSCALE(p);
1116  ssn->server.wscale = TCP_WSCALE_MAX;
1117  SCLogDebug("ssn %p: wscale enabled. client %u server %u",
1118  ssn, ssn->client.wscale, ssn->server.wscale);
1119  }
1120 
1121  SCLogDebug("ssn %p: ssn->client.isn %"PRIu32", ssn->client.next_seq"
1122  " %"PRIu32", ssn->client.last_ack %"PRIu32"", ssn,
1123  ssn->client.isn, ssn->client.next_seq,
1124  ssn->client.last_ack);
1125  SCLogDebug("ssn %p: ssn->server.isn %"PRIu32", ssn->server.next_seq"
1126  " %"PRIu32", ssn->server.last_ack %"PRIu32"", ssn,
1127  ssn->server.isn, ssn->server.next_seq,
1128  ssn->server.last_ack);
1129 
1130  /* Set the timestamp value for both streams, if packet has timestamp
1131  * option enabled.*/
1132  if (TCP_HAS_TS(p)) {
1133  ssn->server.last_ts = TCP_GET_TSVAL(p);
1134  ssn->client.last_ts = TCP_GET_TSECR(p);
1135  SCLogDebug("ssn %p: ssn->server.last_ts %" PRIu32" "
1136  "ssn->client.last_ts %" PRIu32"", ssn,
1137  ssn->server.last_ts, ssn->client.last_ts);
1138 
1140 
1141  ssn->server.last_pkt_ts = SCTIME_SECS(p->ts);
1142  if (ssn->server.last_ts == 0)
1144  if (ssn->client.last_ts == 0)
1146 
1147  } else {
1148  ssn->server.last_ts = 0;
1149  ssn->client.last_ts = 0;
1150  }
1151 
1152  if (TCP_GET_SACKOK(p) == 1) {
1153  ssn->flags |= STREAMTCP_FLAG_SACKOK;
1154  SCLogDebug("ssn %p: SYN/ACK with SACK permitted, assuming "
1155  "SACK permitted for both sides", ssn);
1156  }
1157  return 0;
1158 
1159  } else if (p->tcph->th_flags & TH_SYN) {
1160  if (ssn == NULL) {
1161  ssn = StreamTcpNewSession(tv, stt, p, stt->ssn_pool_id);
1162  if (ssn == NULL) {
1164  return -1;
1165  }
1166 
1169  }
1170 
1171  /* set the state */
1172  StreamTcpPacketSetState(p, ssn, TCP_SYN_SENT);
1173  SCLogDebug("ssn %p: =~ ssn state is now TCP_SYN_SENT", ssn);
1174 
1176  SCLogDebug("ssn %p: =~ ASYNC", ssn);
1177  ssn->flags |= STREAMTCP_FLAG_ASYNC;
1178  }
1179 
1180  /* set the sequence numbers and window */
1181  ssn->client.isn = TCP_GET_SEQ(p);
1183  ssn->client.next_seq = ssn->client.isn + 1;
1184 
1185  /* Set the stream timestamp value, if packet has timestamp option
1186  * enabled. */
1187  if (TCP_HAS_TS(p)) {
1188  ssn->client.last_ts = TCP_GET_TSVAL(p);
1189  SCLogDebug("ssn %p: %02x", ssn, ssn->client.last_ts);
1190 
1191  if (ssn->client.last_ts == 0)
1193 
1194  ssn->client.last_pkt_ts = SCTIME_SECS(p->ts);
1196  }
1197 
1198  ssn->server.window = TCP_GET_WINDOW(p);
1199  if (TCP_HAS_WSCALE(p)) {
1201  ssn->server.wscale = TCP_GET_WSCALE(p);
1202  }
1203 
1204  if (TCP_GET_SACKOK(p) == 1) {
1206  SCLogDebug("ssn %p: SACK permitted on SYN packet", ssn);
1207  }
1208 
1209  if (TCP_HAS_TFO(p)) {
1211  if (p->payload_len) {
1212  StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
1213  SCLogDebug("ssn: %p (TFO) [len: %d] isn %u base_seq %u next_seq %u payload len %u",
1214  ssn, p->tcpvars.tfo.len, ssn->client.isn, ssn->client.base_seq, ssn->client.next_seq, p->payload_len);
1215  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
1216  }
1217  }
1218 
1219  SCLogDebug("ssn %p: ssn->client.isn %" PRIu32 ", "
1220  "ssn->client.next_seq %" PRIu32 ", ssn->client.last_ack "
1221  "%"PRIu32"", ssn, ssn->client.isn, ssn->client.next_seq,
1222  ssn->client.last_ack);
1223 
1224  } else if (p->tcph->th_flags & TH_ACK) {
1225  /* Drop reason will only be used if midstream policy is set to fail closed */
1227 
1228  if (!stream_config.midstream) {
1229  SCLogDebug("Midstream not enabled, so won't pick up a session");
1230  return 0;
1231  }
1234  SCLogDebug("Midstream policy not permissive, so won't pick up a session");
1235  return 0;
1236  }
1237  SCLogDebug("midstream picked up");
1238 
1239  if (ssn == NULL) {
1240  ssn = StreamTcpNewSession(tv, stt, p, stt->ssn_pool_id);
1241  if (ssn == NULL) {
1243  return -1;
1244  }
1248  }
1249  /* set the state */
1250  StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
1251  SCLogDebug("ssn %p: =~ midstream picked ssn state is now "
1252  "TCP_ESTABLISHED", ssn);
1253 
1257  SCLogDebug("ssn %p: =~ ASYNC", ssn);
1258  ssn->flags |= STREAMTCP_FLAG_ASYNC;
1259  }
1260 
1261  /** window scaling for midstream pickups, we can't do much other
1262  * than assume that it's set to the max value: 14 */
1263  ssn->client.wscale = TCP_WSCALE_MAX;
1264  ssn->server.wscale = TCP_WSCALE_MAX;
1265 
1266  /* set the sequence numbers and window */
1267  ssn->client.isn = TCP_GET_SEQ(p) - 1;
1269  ssn->client.next_seq = TCP_GET_SEQ(p) + p->payload_len;
1270  ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
1271  ssn->client.last_ack = TCP_GET_SEQ(p);
1272  ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
1273  SCLogDebug("ssn %p: ssn->client.isn %u, ssn->client.next_seq %u",
1274  ssn, ssn->client.isn, ssn->client.next_seq);
1275 
1276  ssn->server.isn = TCP_GET_ACK(p) - 1;
1278  ssn->server.next_seq = ssn->server.isn + 1;
1279  ssn->server.last_ack = TCP_GET_ACK(p);
1280  ssn->server.next_win = ssn->server.last_ack;
1281 
1282  SCLogDebug("ssn %p: ssn->client.next_win %"PRIu32", "
1283  "ssn->server.next_win %"PRIu32"", ssn,
1284  ssn->client.next_win, ssn->server.next_win);
1285  SCLogDebug("ssn %p: ssn->client.last_ack %"PRIu32", "
1286  "ssn->server.last_ack %"PRIu32"", ssn,
1287  ssn->client.last_ack, ssn->server.last_ack);
1288 
1289  /* Set the timestamp value for both streams, if packet has timestamp
1290  * option enabled.*/
1291  if (TCP_HAS_TS(p)) {
1292  ssn->client.last_ts = TCP_GET_TSVAL(p);
1293  ssn->server.last_ts = TCP_GET_TSECR(p);
1294  SCLogDebug("ssn %p: ssn->server.last_ts %" PRIu32" "
1295  "ssn->client.last_ts %" PRIu32"", ssn,
1296  ssn->server.last_ts, ssn->client.last_ts);
1297 
1299 
1300  ssn->client.last_pkt_ts = SCTIME_SECS(p->ts);
1301  if (ssn->server.last_ts == 0)
1303  if (ssn->client.last_ts == 0)
1305 
1306  } else {
1307  ssn->server.last_ts = 0;
1308  ssn->client.last_ts = 0;
1309  }
1310 
1311  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
1312 
1313  ssn->flags |= STREAMTCP_FLAG_SACKOK;
1314  SCLogDebug("ssn %p: assuming SACK permitted for both sides", ssn);
1315 
1316  } else {
1317  SCLogDebug("default case");
1318  }
1319 
1320  return 0;
1321 }
1322 
1323 /** \internal
1324  * \brief Setup TcpStateQueue based on SYN/ACK packet
1325  */
1326 static inline void StreamTcp3whsSynAckToStateQueue(Packet *p, TcpStateQueue *q)
1327 {
1328  q->flags = 0;
1329  q->wscale = 0;
1330  q->ts = 0;
1331  q->win = TCP_GET_WINDOW(p);
1332  q->seq = TCP_GET_SEQ(p);
1333  q->ack = TCP_GET_ACK(p);
1334  q->pkt_ts = SCTIME_SECS(p->ts);
1335 
1336  if (TCP_GET_SACKOK(p) == 1)
1338 
1339  if (TCP_HAS_WSCALE(p)) {
1341  q->wscale = TCP_GET_WSCALE(p);
1342  }
1343  if (TCP_HAS_TS(p)) {
1345  q->ts = TCP_GET_TSVAL(p);
1346  }
1347 }
1348 
1349 /** \internal
1350  * \brief Find the Queued SYN/ACK that is the same as this SYN/ACK
1351  * \retval q or NULL */
1352 static TcpStateQueue *StreamTcp3whsFindSynAckBySynAck(TcpSession *ssn, Packet *p)
1353 {
1354  TcpStateQueue *q = ssn->queue;
1355  TcpStateQueue search;
1356 
1357  StreamTcp3whsSynAckToStateQueue(p, &search);
1358 
1359  while (q != NULL) {
1360  if (search.flags == q->flags &&
1361  search.wscale == q->wscale &&
1362  search.win == q->win &&
1363  search.seq == q->seq &&
1364  search.ack == q->ack &&
1365  search.ts == q->ts) {
1366  return q;
1367  }
1368 
1369  q = q->next;
1370  }
1371 
1372  return q;
1373 }
1374 
1375 static int StreamTcp3whsQueueSynAck(TcpSession *ssn, Packet *p)
1376 {
1377  /* first see if this is already in our list */
1378  if (StreamTcp3whsFindSynAckBySynAck(ssn, p) != NULL)
1379  return 0;
1380 
1382  SCLogDebug("ssn %p: =~ SYN/ACK queue limit reached", ssn);
1384  return -1;
1385  }
1386 
1387  if (StreamTcpCheckMemcap((uint32_t)sizeof(TcpStateQueue)) == 0) {
1388  SCLogDebug("ssn %p: =~ SYN/ACK queue failed: stream memcap reached", ssn);
1389  return -1;
1390  }
1391 
1392  TcpStateQueue *q = SCCalloc(1, sizeof(*q));
1393  if (unlikely(q == NULL)) {
1394  SCLogDebug("ssn %p: =~ SYN/ACK queue failed: alloc failed", ssn);
1395  return -1;
1396  }
1397  StreamTcpIncrMemuse((uint64_t)sizeof(TcpStateQueue));
1398 
1399  StreamTcp3whsSynAckToStateQueue(p, q);
1400 
1401  /* put in list */
1402  q->next = ssn->queue;
1403  ssn->queue = q;
1404  ssn->queue_len++;
1405  return 0;
1406 }
1407 
1408 /** \internal
1409  * \brief Find the Queued SYN/ACK that goes with this ACK
1410  * \retval q or NULL */
1411 static TcpStateQueue *StreamTcp3whsFindSynAckByAck(TcpSession *ssn, Packet *p)
1412 {
1413  uint32_t ack = TCP_GET_SEQ(p);
1414  uint32_t seq = TCP_GET_ACK(p) - 1;
1415  TcpStateQueue *q = ssn->queue;
1416 
1417  while (q != NULL) {
1418  if (seq == q->seq &&
1419  ack == q->ack) {
1420  return q;
1421  }
1422 
1423  q = q->next;
1424  }
1425 
1426  return NULL;
1427 }
1428 
1429 /** \internal
1430  * \brief Update SSN after receiving a valid SYN/ACK
1431  *
1432  * Normally we update the SSN from the SYN/ACK packet. But in case
1433  * of queued SYN/ACKs, we can use one of those.
1434  *
1435  * \param ssn TCP session
1436  * \param p Packet
1437  * \param q queued state if used, NULL otherwise
1438  *
1439  * To make sure all SYN/ACK based state updates are in one place,
1440  * this function can updated based on Packet or TcpStateQueue, where
1441  * the latter takes precedence.
1442  */
1443 static void StreamTcp3whsSynAckUpdate(TcpSession *ssn, Packet *p, TcpStateQueue *q)
1444 {
1445  TcpStateQueue update;
1446  if (likely(q == NULL)) {
1447  StreamTcp3whsSynAckToStateQueue(p, &update);
1448  q = &update;
1449  }
1450 
1451  if (ssn->state != TCP_SYN_RECV) {
1452  /* update state */
1453  StreamTcpPacketSetState(p, ssn, TCP_SYN_RECV);
1454  SCLogDebug("ssn %p: =~ ssn state is now TCP_SYN_RECV", ssn);
1455  }
1456  /* sequence number & window */
1457  ssn->server.isn = q->seq;
1459  ssn->server.next_seq = ssn->server.isn + 1;
1460 
1461  ssn->client.window = q->win;
1462  SCLogDebug("ssn %p: window %" PRIu32 "", ssn, ssn->server.window);
1463 
1464  /* Set the timestamp values used to validate the timestamp of
1465  * received packets.*/
1466  if ((q->flags & STREAMTCP_QUEUE_FLAG_TS) &&
1468  {
1469  ssn->server.last_ts = q->ts;
1470  SCLogDebug("ssn %p: ssn->server.last_ts %" PRIu32" "
1471  "ssn->client.last_ts %" PRIu32"", ssn,
1472  ssn->server.last_ts, ssn->client.last_ts);
1474  ssn->server.last_pkt_ts = q->pkt_ts;
1475  if (ssn->server.last_ts == 0)
1477  } else {
1478  ssn->client.last_ts = 0;
1479  ssn->server.last_ts = 0;
1481  }
1482 
1483  ssn->client.last_ack = q->ack;
1484  ssn->server.last_ack = ssn->server.isn + 1;
1485 
1486  /** check for the presence of the ws ptr to determine if we
1487  * support wscale at all */
1488  if ((ssn->flags & STREAMTCP_FLAG_SERVER_WSCALE) &&
1490  {
1491  ssn->client.wscale = q->wscale;
1492  } else {
1493  ssn->client.wscale = 0;
1494  }
1495 
1496  if ((ssn->flags & STREAMTCP_FLAG_CLIENT_SACKOK) &&
1498  ssn->flags |= STREAMTCP_FLAG_SACKOK;
1499  SCLogDebug("ssn %p: SACK permitted for session", ssn);
1500  } else {
1501  ssn->flags &= ~STREAMTCP_FLAG_SACKOK;
1502  }
1503 
1504  ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
1505  ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
1506  SCLogDebug("ssn %p: ssn->server.next_win %" PRIu32 "", ssn,
1507  ssn->server.next_win);
1508  SCLogDebug("ssn %p: ssn->client.next_win %" PRIu32 "", ssn,
1509  ssn->client.next_win);
1510  SCLogDebug("ssn %p: ssn->server.isn %" PRIu32 ", "
1511  "ssn->server.next_seq %" PRIu32 ", "
1512  "ssn->server.last_ack %" PRIu32 " "
1513  "(ssn->client.last_ack %" PRIu32 ")", ssn,
1514  ssn->server.isn, ssn->server.next_seq,
1515  ssn->server.last_ack, ssn->client.last_ack);
1516 
1517  /* unset the 4WHS flag as we received this SYN/ACK as part of a
1518  * (so far) valid 3WHS */
1519  if (ssn->flags & STREAMTCP_FLAG_4WHS)
1520  SCLogDebug("ssn %p: STREAMTCP_FLAG_4WHS unset, normal SYN/ACK"
1521  " so considering 3WHS", ssn);
1522 
1523  ssn->flags &=~ STREAMTCP_FLAG_4WHS;
1524 }
1525 
1526 /** \internal
1527  * \brief detect timestamp anomalies when processing responses to the
1528  * SYN packet.
1529  * \retval true packet is ok
1530  * \retval false packet is bad
1531  */
1532 static inline bool StateSynSentValidateTimestamp(TcpSession *ssn, Packet *p)
1533 {
1534  /* we only care about evil server here, so skip TS packets */
1535  if (PKT_IS_TOSERVER(p) || !(TCP_HAS_TS(p))) {
1536  return true;
1537  }
1538 
1539  TcpStream *receiver_stream = &ssn->client;
1540  const uint32_t ts_echo = TCP_GET_TSECR(p);
1541  if ((receiver_stream->flags & STREAMTCP_STREAM_FLAG_TIMESTAMP) != 0) {
1542  if (receiver_stream->last_ts != 0 && ts_echo != 0 &&
1543  ts_echo != receiver_stream->last_ts)
1544  {
1545  SCLogDebug("ssn %p: BAD TSECR echo %u recv %u", ssn,
1546  ts_echo, receiver_stream->last_ts);
1547  return false;
1548  }
1549  } else {
1550  if (receiver_stream->last_ts == 0 && ts_echo != 0) {
1551  SCLogDebug("ssn %p: BAD TSECR echo %u recv %u", ssn,
1552  ts_echo, receiver_stream->last_ts);
1553  return false;
1554  }
1555  }
1556  return true;
1557 }
1558 
1559 static void TcpStateQueueInitFromSsnSyn(const TcpSession *ssn, TcpStateQueue *q)
1560 {
1561  BUG_ON(ssn->state != TCP_SYN_SENT); // TODO
1562  memset(q, 0, sizeof(*q));
1563 
1564  /* SYN won't use wscale yet. So window should be limited to 16 bits. */
1565  DEBUG_VALIDATE_BUG_ON(ssn->server.window > UINT16_MAX);
1566  q->win = (uint16_t)ssn->server.window;
1567 
1568  q->pkt_ts = ssn->client.last_pkt_ts;
1569 
1570  if (ssn->flags & STREAMTCP_FLAG_CLIENT_SACKOK) {
1572  }
1573  if (ssn->flags & STREAMTCP_FLAG_SERVER_WSCALE) {
1575  q->wscale = ssn->server.wscale;
1576  }
1579  q->ts = ssn->client.last_ts;
1580  }
1581 
1582  SCLogDebug("ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->seq, q->win,
1584 }
1585 
1586 static void TcpStateQueueInitFromPktSyn(const Packet *p, TcpStateQueue *q)
1587 {
1588 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1589  const TcpSession *ssn = p->flow->protoctx;
1590  BUG_ON(ssn->state != TCP_SYN_SENT);
1591 #endif
1592  memset(q, 0, sizeof(*q));
1593 
1594  q->win = TCP_GET_WINDOW(p);
1595  q->pkt_ts = SCTIME_SECS(p->ts);
1596 
1597  if (TCP_GET_SACKOK(p) == 1) {
1599  }
1600  if (TCP_HAS_WSCALE(p)) {
1602  q->wscale = TCP_GET_WSCALE(p);
1603  }
1604  if (TCP_HAS_TS(p)) {
1606  q->ts = TCP_GET_TSVAL(p);
1607  }
1608 
1609 #if defined(DEBUG)
1610  SCLogDebug("ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->seq, q->win,
1612 #endif
1613 }
1614 
1615 static void TcpStateQueueInitFromPktSynAck(const Packet *p, TcpStateQueue *q)
1616 {
1617 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1618  const TcpSession *ssn = p->flow->protoctx;
1619  if ((ssn->flags & STREAMTCP_FLAG_TCP_FAST_OPEN) == 0)
1620  BUG_ON(ssn->state != TCP_SYN_SENT);
1621  else
1622  BUG_ON(ssn->state != TCP_ESTABLISHED);
1623 #endif
1624  memset(q, 0, sizeof(*q));
1625 
1626  q->win = TCP_GET_WINDOW(p);
1627  q->pkt_ts = SCTIME_SECS(p->ts);
1628 
1629  if (TCP_GET_SACKOK(p) == 1) {
1631  }
1632  if (TCP_HAS_WSCALE(p)) {
1634  q->wscale = TCP_GET_WSCALE(p);
1635  }
1636  if (TCP_HAS_TS(p)) {
1638  q->ts = TCP_GET_TSECR(p);
1639  }
1640 
1641 #if defined(DEBUG)
1642  SCLogDebug("ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->seq, q->win,
1644 #endif
1645 }
1646 
1647 /** \internal
1648  * \brief Find the Queued SYN that is the same as this SYN/ACK
1649  * \retval q or NULL */
1650 static const TcpStateQueue *StreamTcp3whsFindSyn(const TcpSession *ssn, TcpStateQueue *s)
1651 {
1652  SCLogDebug("ssn %p: search state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, s, s->seq, s->win,
1654 
1655  for (const TcpStateQueue *q = ssn->queue; q != NULL; q = q->next) {
1656  SCLogDebug("ssn %p: queue state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->seq,
1657  q->win, BOOL2STR(q->flags & STREAMTCP_QUEUE_FLAG_TS), q->ts);
1659  s->ts == q->ts) {
1660  return q;
1661  }
1662  }
1663  return NULL;
1664 }
1665 
1666 /** \note the SEQ values *must* be the same */
1667 static int StreamTcp3whsStoreSyn(TcpSession *ssn, Packet *p)
1668 {
1669  TcpStateQueue search;
1670  TcpStateQueueInitFromSsnSyn(ssn, &search);
1671 
1672  /* first see if this is already in our list */
1673  if (ssn->queue != NULL && StreamTcp3whsFindSyn(ssn, &search) != NULL)
1674  return 0;
1675 
1676  if (ssn->queue_len == stream_config.max_syn_queued) {
1677  SCLogDebug("ssn %p: =~ SYN queue limit reached", ssn);
1679  return -1;
1680  }
1681 
1682  if (StreamTcpCheckMemcap((uint32_t)sizeof(TcpStateQueue)) == 0) {
1683  SCLogDebug("ssn %p: =~ SYN queue failed: stream memcap reached", ssn);
1684  return -1;
1685  }
1686 
1687  TcpStateQueue *q = SCCalloc(1, sizeof(*q));
1688  if (unlikely(q == NULL)) {
1689  SCLogDebug("ssn %p: =~ SYN queue failed: alloc failed", ssn);
1690  return -1;
1691  }
1692  StreamTcpIncrMemuse((uint64_t)sizeof(TcpStateQueue));
1693 
1694  *q = search;
1695  /* put in list */
1696  q->next = ssn->queue;
1697  ssn->queue = q;
1698  ssn->queue_len++;
1699  return 0;
1700 }
1701 
1702 static inline void StreamTcp3whsStoreSynApplyToSsn(TcpSession *ssn, const TcpStateQueue *q)
1703 {
1704  if (q->flags & STREAMTCP_QUEUE_FLAG_TS) {
1705  ssn->client.last_pkt_ts = q->pkt_ts;
1706  ssn->client.last_ts = q->ts;
1708  SCLogDebug("ssn: %p client.last_ts updated to %u", ssn, ssn->client.last_ts);
1709  }
1710  if (q->flags & STREAMTCP_QUEUE_FLAG_WS) {
1712  ssn->server.wscale = q->wscale;
1713  } else {
1715  ssn->server.wscale = 0;
1716  }
1717  ssn->server.window = q->win;
1718 
1719  if (q->flags & STREAMTCP_QUEUE_FLAG_SACK) {
1721  } else {
1723  }
1724 }
1725 
1726 /**
1727  * \brief Function to handle the TCP_SYN_SENT state. The function handles
1728  * SYN, SYN/ACK, RST packets and correspondingly changes the connection
1729  * state.
1730  *
1731  * \param tv Thread Variable containing input/output queue, cpu affinity
1732  * \param p Packet which has to be handled in this TCP state.
1733  * \param stt Stream Thread module registered to handle the stream handling
1734  */
1735 
1736 static int StreamTcpPacketStateSynSent(
1737  ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn)
1738 {
1739  DEBUG_VALIDATE_BUG_ON(ssn == NULL);
1740 
1741  SCLogDebug("ssn %p: pkt received: %s", ssn, PKT_IS_TOCLIENT(p) ? "toclient" : "toserver");
1742 
1743  /* common case: SYN/ACK from server to client */
1744  if ((p->tcph->th_flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK) && PKT_IS_TOCLIENT(p)) {
1745  SCLogDebug("ssn %p: SYN/ACK on SYN_SENT state for packet %" PRIu64, ssn, p->pcap_cnt);
1746 
1747  if (!(TCP_HAS_TFO(p) || (ssn->flags & STREAMTCP_FLAG_TCP_FAST_OPEN))) {
1748  /* Check if the SYN/ACK packet ack's the earlier
1749  * received SYN packet. */
1750  if (!(SEQ_EQ(TCP_GET_ACK(p), ssn->client.isn + 1))) {
1752  SCLogDebug("ssn %p: ACK mismatch, packet ACK %" PRIu32 " != "
1753  "%" PRIu32 " from stream", ssn, TCP_GET_ACK(p),
1754  ssn->client.isn + 1);
1755  return -1;
1756  }
1757  } else {
1758  if (SEQ_EQ(TCP_GET_ACK(p), ssn->client.next_seq)) {
1759  SCLogDebug("ssn %p: (TFO) ACK matches next_seq, packet ACK %" PRIu32 " == "
1760  "%" PRIu32 " from stream",
1761  ssn, TCP_GET_ACK(p), ssn->client.next_seq);
1762  } else if (SEQ_EQ(TCP_GET_ACK(p), ssn->client.isn + 1)) {
1763  SCLogDebug("ssn %p: (TFO) ACK matches ISN+1, packet ACK %" PRIu32 " == "
1764  "%" PRIu32 " from stream",
1765  ssn, TCP_GET_ACK(p), ssn->client.isn + 1);
1766  ssn->client.next_seq = ssn->client.isn; // reset to ISN
1767  SCLogDebug("ssn %p: (TFO) next_seq reset to isn (%u)", ssn, ssn->client.next_seq);
1770  } else {
1772  SCLogDebug("ssn %p: (TFO) ACK mismatch, packet ACK %" PRIu32 " != "
1773  "%" PRIu32 " from stream", ssn, TCP_GET_ACK(p),
1774  ssn->client.next_seq);
1775  return -1;
1776  }
1778  StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
1779  }
1780 
1781  const bool ts_mismatch = !StateSynSentValidateTimestamp(ssn, p);
1782  if (ts_mismatch) {
1783  SCLogDebug("ssn %p: ts_mismatch:%s", ssn, BOOL2STR(ts_mismatch));
1784  if (ssn->queue) {
1785  TcpStateQueue search;
1786  TcpStateQueueInitFromPktSynAck(p, &search);
1787 
1788  const TcpStateQueue *q = StreamTcp3whsFindSyn(ssn, &search);
1789  if (q == NULL) {
1790  SCLogDebug("not found: mismatch");
1792  return -1;
1793  }
1794  SCLogDebug("ssn %p: found queued SYN state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u",
1795  ssn, q, q->seq, q->win, BOOL2STR(q->flags & STREAMTCP_QUEUE_FLAG_TS),
1796  q->ts);
1797 
1798  StreamTcp3whsStoreSynApplyToSsn(ssn, q);
1799 
1800  } else {
1801  SCLogDebug("not found: no queue");
1803  return -1;
1804  }
1805  }
1806 
1807  /* clear ssn->queue on state change: TcpSession can be reused by SYN/ACK */
1808  StreamTcp3wsFreeQueue(ssn);
1809 
1810  StreamTcp3whsSynAckUpdate(ssn, p, /* no queue override */NULL);
1811  return 0;
1812 
1813  } else if ((p->tcph->th_flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK) && PKT_IS_TOSERVER(p)) {
1814 
1815  if (!(ssn->flags & STREAMTCP_FLAG_4WHS)) {
1817  SCLogDebug("ssn %p: SYN/ACK received in the wrong direction", ssn);
1818  return -1;
1819  }
1820 
1821  SCLogDebug("ssn %p: SYN/ACK received on 4WHS session", ssn);
1822 
1823  /* Check if the SYN/ACK packet ack's the earlier
1824  * received SYN packet. */
1825  if (!(SEQ_EQ(TCP_GET_ACK(p), ssn->server.isn + 1))) {
1827 
1828  SCLogDebug("ssn %p: 4WHS ACK mismatch, packet ACK %" PRIu32 ""
1829  " != %" PRIu32 " from stream",
1830  ssn, TCP_GET_ACK(p), ssn->server.isn + 1);
1831  return -1;
1832  }
1833 
1834  /* Check if the SYN/ACK packet SEQ's the *FIRST* received SYN
1835  * packet. */
1836  if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->client.isn))) {
1838 
1839  SCLogDebug("ssn %p: 4WHS SEQ mismatch, packet SEQ %" PRIu32 ""
1840  " != %" PRIu32 " from *first* SYN pkt",
1841  ssn, TCP_GET_SEQ(p), ssn->client.isn);
1842  return -1;
1843  }
1844 
1845  /* update state */
1846  StreamTcpPacketSetState(p, ssn, TCP_SYN_RECV);
1847  SCLogDebug("ssn %p: =~ 4WHS ssn state is now TCP_SYN_RECV", ssn);
1848 
1849  /* sequence number & window */
1850  ssn->client.isn = TCP_GET_SEQ(p);
1852  ssn->client.next_seq = ssn->client.isn + 1;
1853 
1854  ssn->server.window = TCP_GET_WINDOW(p);
1855  SCLogDebug("ssn %p: 4WHS window %" PRIu32 "", ssn, ssn->client.window);
1856 
1857  /* Set the timestamp values used to validate the timestamp of
1858  * received packets. */
1859  if ((TCP_HAS_TS(p)) && (ssn->server.flags & STREAMTCP_STREAM_FLAG_TIMESTAMP)) {
1860  ssn->client.last_ts = TCP_GET_TSVAL(p);
1861  SCLogDebug("ssn %p: 4WHS ssn->client.last_ts %" PRIu32 " "
1862  "ssn->server.last_ts %" PRIu32 "",
1863  ssn, ssn->client.last_ts, ssn->server.last_ts);
1865  ssn->client.last_pkt_ts = SCTIME_SECS(p->ts);
1866  if (ssn->client.last_ts == 0)
1868  } else {
1869  ssn->server.last_ts = 0;
1870  ssn->client.last_ts = 0;
1872  }
1873 
1874  ssn->server.last_ack = TCP_GET_ACK(p);
1875  ssn->client.last_ack = ssn->client.isn + 1;
1876 
1877  /** check for the presense of the ws ptr to determine if we
1878  * support wscale at all */
1879  if ((ssn->flags & STREAMTCP_FLAG_SERVER_WSCALE) && (TCP_HAS_WSCALE(p))) {
1880  ssn->server.wscale = TCP_GET_WSCALE(p);
1881  } else {
1882  ssn->server.wscale = 0;
1883  }
1884 
1885  if ((ssn->flags & STREAMTCP_FLAG_CLIENT_SACKOK) && TCP_GET_SACKOK(p) == 1) {
1886  ssn->flags |= STREAMTCP_FLAG_SACKOK;
1887  SCLogDebug("ssn %p: SACK permitted for 4WHS session", ssn);
1888  }
1889 
1890  ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
1891  ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
1892  SCLogDebug("ssn %p: 4WHS ssn->client.next_win %" PRIu32 "", ssn, ssn->client.next_win);
1893  SCLogDebug("ssn %p: 4WHS ssn->server.next_win %" PRIu32 "", ssn, ssn->server.next_win);
1894  SCLogDebug("ssn %p: 4WHS ssn->client.isn %" PRIu32 ", "
1895  "ssn->client.next_seq %" PRIu32 ", "
1896  "ssn->client.last_ack %" PRIu32 " "
1897  "(ssn->server.last_ack %" PRIu32 ")",
1898  ssn, ssn->client.isn, ssn->client.next_seq, ssn->client.last_ack,
1899  ssn->server.last_ack);
1900 
1901  /* done here */
1902  return 0;
1903  }
1904 
1905  /* check for bad responses */
1906  if (StateSynSentValidateTimestamp(ssn, p) == false) {
1908  return -1;
1909  }
1910 
1911  /* RST */
1912  if (p->tcph->th_flags & TH_RST) {
1913 
1914  if (!StreamTcpValidateRst(ssn, p))
1915  return -1;
1916 
1917  if (PKT_IS_TOSERVER(p)) {
1918  if (SEQ_EQ(TCP_GET_SEQ(p), ssn->client.isn) && SEQ_EQ(TCP_GET_WINDOW(p), 0) &&
1919  SEQ_EQ(TCP_GET_ACK(p), (ssn->client.isn + 1))) {
1920  SCLogDebug("ssn->server.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
1922  StreamTcpCloseSsnWithReset(p, ssn);
1923  StreamTcp3wsFreeQueue(ssn);
1924  }
1925  } else {
1927  SCLogDebug("ssn->client.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
1928  StreamTcpCloseSsnWithReset(p, ssn);
1929  StreamTcp3wsFreeQueue(ssn);
1930  }
1931 
1932  /* FIN */
1933  } else if (p->tcph->th_flags & TH_FIN) {
1934  /** \todo */
1935 
1936  } else if (p->tcph->th_flags & TH_SYN) {
1937  SCLogDebug("ssn %p: SYN packet on state SYN_SENT... resent", ssn);
1938  if (ssn->flags & STREAMTCP_FLAG_4WHS) {
1939  SCLogDebug("ssn %p: SYN packet on state SYN_SENT... resent of "
1940  "4WHS SYN", ssn);
1941  }
1942 
1943  if (PKT_IS_TOCLIENT(p)) {
1944  /** a SYN only packet in the opposite direction could be:
1945  * http://www.breakingpointsystems.com/community/blog/tcp-
1946  * portals-the-three-way-handshake-is-a-lie
1947  *
1948  * \todo improve resetting the session */
1949 
1950  /* indicate that we're dealing with 4WHS here */
1951  ssn->flags |= STREAMTCP_FLAG_4WHS;
1952  SCLogDebug("ssn %p: STREAMTCP_FLAG_4WHS flag set", ssn);
1953 
1954  /* set the sequence numbers and window for server
1955  * We leave the ssn->client.isn in place as we will
1956  * check the SYN/ACK pkt with that.
1957  */
1958  ssn->server.isn = TCP_GET_SEQ(p);
1960  ssn->server.next_seq = ssn->server.isn + 1;
1961 
1962  /* Set the stream timestamp value, if packet has timestamp
1963  * option enabled. */
1964  if (TCP_HAS_TS(p)) {
1965  ssn->server.last_ts = TCP_GET_TSVAL(p);
1966  SCLogDebug("ssn %p: %02x", ssn, ssn->server.last_ts);
1967 
1968  if (ssn->server.last_ts == 0)
1970  ssn->server.last_pkt_ts = SCTIME_SECS(p->ts);
1972  }
1973 
1974  ssn->server.window = TCP_GET_WINDOW(p);
1975  if (TCP_HAS_WSCALE(p)) {
1977  ssn->server.wscale = TCP_GET_WSCALE(p);
1978  } else {
1980  ssn->server.wscale = 0;
1981  }
1982 
1983  if (TCP_GET_SACKOK(p) == 1) {
1985  } else {
1987  }
1988 
1989  SCLogDebug("ssn %p: 4WHS ssn->server.isn %" PRIu32 ", "
1990  "ssn->server.next_seq %" PRIu32 ", "
1991  "ssn->server.last_ack %"PRIu32"", ssn,
1992  ssn->server.isn, ssn->server.next_seq,
1993  ssn->server.last_ack);
1994  SCLogDebug("ssn %p: 4WHS ssn->client.isn %" PRIu32 ", "
1995  "ssn->client.next_seq %" PRIu32 ", "
1996  "ssn->client.last_ack %"PRIu32"", ssn,
1997  ssn->client.isn, ssn->client.next_seq,
1998  ssn->client.last_ack);
1999  } else if (PKT_IS_TOSERVER(p)) {
2000  /* on a SYN resend we queue up the SYN's until a SYN/ACK moves the state
2001  * to SYN_RECV. We update the ssn to the most recent, as it is most likely
2002  * to be correct. */
2003 
2004  TcpStateQueue syn_pkt, syn_ssn;
2005  TcpStateQueueInitFromPktSyn(p, &syn_pkt);
2006  TcpStateQueueInitFromSsnSyn(ssn, &syn_ssn);
2007 
2008  if (memcmp(&syn_pkt, &syn_ssn, sizeof(TcpStateQueue)) != 0) {
2009  /* store the old session settings */
2010  StreamTcp3whsStoreSyn(ssn, p);
2011  SCLogDebug("ssn %p: Retransmitted SYN. Updating ssn from packet %" PRIu64
2012  ". Stored previous state",
2013  ssn, p->pcap_cnt);
2014  }
2015  StreamTcp3whsStoreSynApplyToSsn(ssn, &syn_pkt);
2016  }
2017  } else if (p->tcph->th_flags & TH_ACK) {
2018  /* Handle the asynchronous stream, when we receive a SYN packet
2019  and now instead of receiving a SYN/ACK we receive a ACK from the
2020  same host, which sent the SYN, this suggests the ASYNC streams.*/
2022  return 0;
2023 
2024  /* we are in ASYNC (one side) mode now. */
2025 
2026  /* one side async means we won't see a SYN/ACK, so we can
2027  * only check the SYN. */
2028  if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->client.next_seq))) {
2030 
2031  SCLogDebug("ssn %p: SEQ mismatch, packet SEQ %" PRIu32 " != "
2032  "%" PRIu32 " from stream",ssn, TCP_GET_SEQ(p),
2033  ssn->client.next_seq);
2034  return -1;
2035  }
2036 
2037  ssn->flags |= STREAMTCP_FLAG_ASYNC;
2038  StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
2039  SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2040  StreamTcp3wsFreeQueue(ssn);
2041 
2042  ssn->client.window = TCP_GET_WINDOW(p);
2043  ssn->client.last_ack = TCP_GET_SEQ(p);
2044  ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
2045 
2046  /* Set the server side parameters */
2047  ssn->server.isn = TCP_GET_ACK(p) - 1;
2049  ssn->server.next_seq = ssn->server.isn + 1;
2050  ssn->server.last_ack = ssn->server.next_seq;
2051  ssn->server.next_win = ssn->server.last_ack;
2052 
2053  SCLogDebug("ssn %p: synsent => Asynchronous stream, packet SEQ"
2054  " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "), "
2055  "ssn->client.next_seq %" PRIu32 ""
2056  ,ssn, TCP_GET_SEQ(p), p->payload_len, TCP_GET_SEQ(p)
2057  + p->payload_len, ssn->client.next_seq);
2058 
2059  /* if SYN had wscale, assume it to be supported. Otherwise
2060  * we know it not to be supported. */
2061  if (ssn->flags & STREAMTCP_FLAG_SERVER_WSCALE) {
2062  ssn->client.wscale = TCP_WSCALE_MAX;
2063  }
2064 
2065  /* Set the timestamp values used to validate the timestamp of
2066  * received packets.*/
2067  if (TCP_HAS_TS(p) &&
2069  {
2072  ssn->client.last_pkt_ts = SCTIME_SECS(p->ts);
2073  } else {
2074  ssn->client.last_ts = 0;
2076  }
2077 
2078  if (ssn->flags & STREAMTCP_FLAG_CLIENT_SACKOK) {
2079  ssn->flags |= STREAMTCP_FLAG_SACKOK;
2080  }
2081 
2082  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
2083 
2084  } else {
2085  SCLogDebug("ssn %p: default case", ssn);
2086  }
2087 
2088  return 0;
2089 }
2090 
2091 /**
2092  * \brief Function to handle the TCP_SYN_RECV state. The function handles
2093  * SYN, SYN/ACK, ACK, FIN, RST packets and correspondingly changes
2094  * the connection state.
2095  *
2096  * \param tv Thread Variable containing input/output queue, cpu affinity
2097  * \param p Packet which has to be handled in this TCP state.
2098  * \param stt Stream Thread module registered to handle the stream handling
2099  *
2100  * \retval 0 ok
2101  * \retval -1 error
2102  */
2103 
2104 static int StreamTcpPacketStateSynRecv(
2105  ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn)
2106 {
2107  DEBUG_VALIDATE_BUG_ON(ssn == NULL);
2108 
2109  if (p->tcph->th_flags & TH_RST) {
2110  if (!StreamTcpValidateRst(ssn, p))
2111  return -1;
2112 
2113  bool reset = true;
2114  /* After receiving the RST in SYN_RECV state and if detection
2115  evasion flags has been set, then the following operating
2116  systems will not closed the connection. As they consider the
2117  packet as stray packet and not belonging to the current
2118  session, for more information check
2119  http://www.packetstan.com/2010/06/recently-ive-been-on-campaign-to-make.html */
2121  if (PKT_IS_TOSERVER(p)) {
2122  if ((ssn->server.os_policy == OS_POLICY_LINUX) ||
2123  (ssn->server.os_policy == OS_POLICY_OLD_LINUX) ||
2125  {
2126  reset = false;
2127  SCLogDebug("Detection evasion has been attempted, so"
2128  " not resetting the connection !!");
2129  }
2130  } else {
2131  if ((ssn->client.os_policy == OS_POLICY_LINUX) ||
2132  (ssn->client.os_policy == OS_POLICY_OLD_LINUX) ||
2134  {
2135  reset = false;
2136  SCLogDebug("Detection evasion has been attempted, so"
2137  " not resetting the connection !!");
2138  }
2139  }
2140  }
2141 
2142  if (reset) {
2143  StreamTcpCloseSsnWithReset(p, ssn);
2144 
2145  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2146  StreamTcpHandleTimestamp(ssn, p);
2147  }
2148  }
2149 
2150  } else if (p->tcph->th_flags & TH_FIN) {
2151  /* FIN is handled in the same way as in TCP_ESTABLISHED case */;
2152  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2153  if (!StreamTcpValidateTimestamp(ssn, p))
2154  return -1;
2155  }
2156 
2157  if ((StreamTcpHandleFin(tv, stt, ssn, p)) == -1)
2158  return -1;
2159 
2160  /* SYN/ACK */
2161  } else if ((p->tcph->th_flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) {
2162  SCLogDebug("ssn %p: SYN/ACK packet on state SYN_RECV. resent", ssn);
2163 
2164  if (PKT_IS_TOSERVER(p)) {
2165  SCLogDebug("ssn %p: SYN/ACK-pkt to server in SYN_RECV state", ssn);
2166 
2168  return -1;
2169  }
2170 
2171  /* Check if the SYN/ACK packets ACK matches the earlier
2172  * received SYN/ACK packet. */
2173  if (!(SEQ_EQ(TCP_GET_ACK(p), ssn->client.last_ack))) {
2174  SCLogDebug("ssn %p: ACK mismatch, packet ACK %" PRIu32 " != "
2175  "%" PRIu32 " from stream", ssn, TCP_GET_ACK(p),
2176  ssn->client.isn + 1);
2177 
2179  return -1;
2180  }
2181 
2182  /* Check if the SYN/ACK packet SEQ the earlier
2183  * received SYN/ACK packet, server resend with different ISN. */
2184  if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->server.isn))) {
2185  SCLogDebug("ssn %p: SEQ mismatch, packet SEQ %" PRIu32 " != "
2186  "%" PRIu32 " from stream", ssn, TCP_GET_SEQ(p),
2187  ssn->client.isn);
2188 
2189  if (StreamTcp3whsQueueSynAck(ssn, p) == -1)
2190  return -1;
2191  SCLogDebug("ssn %p: queued different SYN/ACK", ssn);
2192  }
2193 
2194  } else if (p->tcph->th_flags & TH_SYN) {
2195  SCLogDebug("ssn %p: SYN packet on state SYN_RECV... resent", ssn);
2196 
2197  if (PKT_IS_TOCLIENT(p)) {
2198  SCLogDebug("ssn %p: SYN-pkt to client in SYN_RECV state", ssn);
2199 
2201  return -1;
2202  }
2203 
2204  if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->client.isn))) {
2205  SCLogDebug("ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
2206 
2208  return -1;
2209  }
2210 
2211  } else if (p->tcph->th_flags & TH_ACK) {
2212  if (ssn->queue_len) {
2213  SCLogDebug("ssn %p: checking ACK against queued SYN/ACKs", ssn);
2214  TcpStateQueue *q = StreamTcp3whsFindSynAckByAck(ssn, p);
2215  if (q != NULL) {
2216  SCLogDebug("ssn %p: here we update state against queued SYN/ACK", ssn);
2217  StreamTcp3whsSynAckUpdate(ssn, p, /* using queue to update state */q);
2218  } else {
2219  SCLogDebug("ssn %p: none found, now checking ACK against original SYN/ACK (state)", ssn);
2220  }
2221  }
2222 
2223 
2224  /* If the timestamp option is enabled for both the streams, then
2225  * validate the received packet timestamp value against the
2226  * stream->last_ts. If the timestamp is valid then process the
2227  * packet normally otherwise the drop the packet (RFC 1323)*/
2228  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2229  if (!(StreamTcpValidateTimestamp(ssn, p))) {
2230  return -1;
2231  }
2232  }
2233 
2234  if ((ssn->flags & STREAMTCP_FLAG_4WHS) && PKT_IS_TOCLIENT(p)) {
2235  SCLogDebug("ssn %p: ACK received on 4WHS session",ssn);
2236 
2237  if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq))) {
2238  SCLogDebug("ssn %p: 4WHS wrong seq nr on packet", ssn);
2240  return -1;
2241  }
2242 
2243  if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
2244  SCLogDebug("ssn %p: 4WHS invalid ack nr on packet", ssn);
2246  return -1;
2247  }
2248 
2249  SCLogDebug("4WHS normal pkt");
2250  SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
2251  "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
2252  TCP_GET_SEQ(p), TCP_GET_ACK(p));
2253 
2254  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2255  StreamTcpHandleTimestamp(ssn, p);
2256  }
2257 
2258  StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
2259  StreamTcpUpdateNextSeq(ssn, &ssn->server, (ssn->server.next_seq + p->payload_len));
2260  ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
2261  ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
2262 
2263  StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
2264  SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2265 
2266  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
2267 
2268  SCLogDebug("ssn %p: ssn->client.next_win %" PRIu32 ", "
2269  "ssn->client.last_ack %"PRIu32"", ssn,
2270  ssn->client.next_win, ssn->client.last_ack);
2271  return 0;
2272  }
2273 
2274  bool ack_indicates_missed_3whs_ack_packet = false;
2275  /* Check if the ACK received is in right direction. But when we have
2276  * picked up a mid stream session after missing the initial SYN pkt,
2277  * in this case the ACK packet can arrive from either client (normal
2278  * case) or from server itself (asynchronous streams). Therefore
2279  * the check has been avoided in this case */
2280  if (PKT_IS_TOCLIENT(p)) {
2281  /* special case, handle 4WHS, so SYN/ACK in the opposite
2282  * direction */
2284  SCLogDebug("ssn %p: ACK received on midstream SYN/ACK "
2285  "pickup session",ssn);
2286  /* fall through */
2287  } else if (ssn->flags & STREAMTCP_FLAG_TCP_FAST_OPEN) {
2288  SCLogDebug("ssn %p: ACK received on TFO session",ssn);
2289  /* fall through */
2290 
2291  } else {
2292  /* if we missed traffic between the S/SA and the current
2293  * 'wrong direction' ACK, we could end up here. In IPS
2294  * reject it. But in IDS mode we continue.
2295  *
2296  * IPS rejects as it should see all packets, so pktloss
2297  * should lead to retransmissions. As this can also be
2298  * pattern for MOTS/MITM injection attacks, we need to be
2299  * careful.
2300  */
2301  if (StreamTcpInlineMode()) {
2302  if (p->payload_len > 0 &&
2303  SEQ_EQ(TCP_GET_ACK(p), ssn->client.last_ack) &&
2304  SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq)) {
2305  /* packet loss is possible but unlikely here */
2306  SCLogDebug("ssn %p: possible data injection", ssn);
2308  return -1;
2309  }
2310 
2311  SCLogDebug("ssn %p: ACK received in the wrong direction",
2312  ssn);
2314  return -1;
2315  }
2316  ack_indicates_missed_3whs_ack_packet = true;
2317  }
2318  }
2319 
2320  SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ %" PRIu32 ""
2321  ", ACK %" PRIu32 "", ssn, p->payload_len, TCP_GET_SEQ(p),
2322  TCP_GET_ACK(p));
2323 
2324  /* Check both seq and ack number before accepting the packet and
2325  changing to ESTABLISHED state */
2326  if ((SEQ_EQ(TCP_GET_SEQ(p), ssn->client.next_seq)) &&
2327  SEQ_EQ(TCP_GET_ACK(p), ssn->server.next_seq)) {
2328  SCLogDebug("normal pkt");
2329 
2330  /* process the packet normal, No Async streams :) */
2331 
2332  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2333  StreamTcpHandleTimestamp(ssn, p);
2334  }
2335 
2336  StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
2337  StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
2338  ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
2339 
2340  ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
2341 
2342  if (ssn->flags & STREAMTCP_FLAG_MIDSTREAM) {
2343  ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
2344  ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
2345  ssn->server.next_win = ssn->server.last_ack +
2346  ssn->server.window;
2347  if (!(ssn->flags & STREAMTCP_FLAG_MIDSTREAM_SYNACK)) {
2348  /* window scaling for midstream pickups, we can't do much
2349  * other than assume that it's set to the max value: 14 */
2350  ssn->server.wscale = TCP_WSCALE_MAX;
2351  ssn->client.wscale = TCP_WSCALE_MAX;
2352  ssn->flags |= STREAMTCP_FLAG_SACKOK;
2353  }
2354  }
2355 
2356  StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
2357  SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2358 
2359  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
2360 
2361  /* If asynchronous stream handling is allowed then set the session,
2362  if packet's seq number is equal the expected seq no.*/
2363  } else if (stream_config.async_oneside && (SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq))) {
2364  /*set the ASYNC flag used to indicate the session as async stream
2365  and helps in relaxing the windows checks.*/
2366  ssn->flags |= STREAMTCP_FLAG_ASYNC;
2367  ssn->server.next_seq += p->payload_len;
2368  ssn->server.last_ack = TCP_GET_SEQ(p);
2369 
2370  ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
2371  ssn->client.last_ack = TCP_GET_ACK(p);
2372 
2373  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2374  StreamTcpHandleTimestamp(ssn, p);
2375  }
2376 
2377  if (ssn->flags & STREAMTCP_FLAG_MIDSTREAM) {
2378  ssn->server.window = TCP_GET_WINDOW(p);
2379  ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
2380  /* window scaling for midstream pickups, we can't do much
2381  * other than assume that it's set to the max value: 14 */
2382  ssn->server.wscale = TCP_WSCALE_MAX;
2383  ssn->client.wscale = TCP_WSCALE_MAX;
2384  ssn->flags |= STREAMTCP_FLAG_SACKOK;
2385  }
2386 
2387  SCLogDebug("ssn %p: synrecv => Asynchronous stream, packet SEQ"
2388  " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "), "
2389  "ssn->server.next_seq %" PRIu32
2390  , ssn, TCP_GET_SEQ(p), p->payload_len, TCP_GET_SEQ(p)
2391  + p->payload_len, ssn->server.next_seq);
2392 
2393  StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
2394  SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2395 
2396  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
2397  /* Upon receiving the packet with correct seq number and wrong
2398  ACK number, it causes the other end to send RST. But some target
2399  system (Linux & solaris) does not RST the connection, so it is
2400  likely to avoid the detection */
2401  } else if (SEQ_EQ(TCP_GET_SEQ(p), ssn->client.next_seq)) {
2403  SCLogDebug("ssn %p: wrong ack nr on packet, possible evasion!!",
2404  ssn);
2405 
2407  return -1;
2408 
2409  /* SYN/ACK followed by more TOCLIENT suggesting packet loss */
2410  } else if (PKT_IS_TOCLIENT(p) && !StreamTcpInlineMode() &&
2411  SEQ_GT(TCP_GET_SEQ(p), ssn->client.next_seq) &&
2412  SEQ_GT(TCP_GET_ACK(p), ssn->client.last_ack)) {
2413  SCLogDebug("ssn %p: ACK for missing data", ssn);
2414 
2415  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2416  StreamTcpHandleTimestamp(ssn, p);
2417  }
2418 
2419  StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
2420 
2421  ssn->server.next_seq = TCP_GET_SEQ(p) + p->payload_len;
2422  SCLogDebug("ssn %p: ACK for missing data: ssn->server.next_seq %u", ssn,
2423  ssn->server.next_seq);
2424  ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
2425 
2426  ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
2427 
2428  ssn->client.window = TCP_GET_WINDOW(p);
2429  ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
2430 
2431  StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
2432  SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2433 
2434  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
2435 
2436  /* if we get a packet with a proper ack, but a seq that is beyond
2437  * next_seq but in-window, we probably missed some packets */
2438  } else if (SEQ_GT(TCP_GET_SEQ(p), ssn->client.next_seq) &&
2439  SEQ_LEQ(TCP_GET_SEQ(p), ssn->client.next_win) &&
2440  SEQ_EQ(TCP_GET_ACK(p), ssn->server.next_seq)) {
2441  SCLogDebug("ssn %p: ACK for missing data", ssn);
2442 
2443  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2444  StreamTcpHandleTimestamp(ssn, p);
2445  }
2446 
2447  ssn->client.next_seq = TCP_GET_SEQ(p) + p->payload_len;
2448  StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
2449 
2450  SCLogDebug("ssn %p: ACK for missing data: ssn->client.next_seq %u", ssn, ssn->client.next_seq);
2451  ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
2452  ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
2453 
2454  if (ssn->flags & STREAMTCP_FLAG_MIDSTREAM) {
2455  ssn->client.window = TCP_GET_WINDOW(p);
2456  ssn->server.next_win = ssn->server.last_ack +
2457  ssn->server.window;
2458  /* window scaling for midstream pickups, we can't do much
2459  * other than assume that it's set to the max value: 14 */
2460  ssn->server.wscale = TCP_WSCALE_MAX;
2461  ssn->client.wscale = TCP_WSCALE_MAX;
2462  ssn->flags |= STREAMTCP_FLAG_SACKOK;
2463  }
2464 
2465  StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
2466  SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2467 
2468  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
2469 
2470  /* toclient packet: after having missed the 3whs's final ACK */
2471  } else if ((ack_indicates_missed_3whs_ack_packet ||
2472  (ssn->flags & STREAMTCP_FLAG_TCP_FAST_OPEN)) &&
2473  SEQ_EQ(TCP_GET_ACK(p), ssn->client.last_ack) &&
2474  SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq)) {
2475  if (ack_indicates_missed_3whs_ack_packet) {
2476  SCLogDebug("ssn %p: packet fits perfectly after a missed 3whs-ACK", ssn);
2477  } else {
2478  SCLogDebug("ssn %p: (TFO) expected packet fits perfectly after SYN/ACK", ssn);
2479  }
2480 
2481  StreamTcpUpdateNextSeq(ssn, &ssn->server, (TCP_GET_SEQ(p) + p->payload_len));
2482 
2483  ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
2484  ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
2485 
2486  StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
2487  SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2488 
2489  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
2490 
2491  } else {
2492  SCLogDebug("ssn %p: wrong seq nr on packet", ssn);
2493 
2495  return -1;
2496  }
2497 
2498  SCLogDebug("ssn %p: ssn->server.next_win %" PRIu32 ", "
2499  "ssn->server.last_ack %"PRIu32"", ssn,
2500  ssn->server.next_win, ssn->server.last_ack);
2501  } else {
2502  SCLogDebug("ssn %p: default case", ssn);
2503  }
2504 
2505  return 0;
2506 }
2507 
2508 /**
2509  * \brief Function to handle the TCP_ESTABLISHED state packets, which are
2510  * sent by the client to server. The function handles
2511  * ACK packets and call StreamTcpReassembleHandleSegment() to handle
2512  * the reassembly.
2513  *
2514  * Timestamp has already been checked at this point.
2515  *
2516  * \param tv Thread Variable containing input/output queue, cpu affinity etc.
2517  * \param ssn Pointer to the current TCP session
2518  * \param p Packet which has to be handled in this TCP state.
2519  * \param stt Stream Thread module registered to handle the stream handling
2520  */
2521 static int HandleEstablishedPacketToServer(
2522  ThreadVars *tv, TcpSession *ssn, Packet *p, StreamTcpThread *stt)
2523 {
2524  SCLogDebug("ssn %p: =+ pkt (%" PRIu32 ") is to server: SEQ %" PRIu32 ","
2525  "ACK %" PRIu32 ", WIN %"PRIu16"", ssn, p->payload_len,
2527 
2528  const bool has_ack = (p->tcph->th_flags & TH_ACK) != 0;
2529  if (has_ack) {
2530  if ((ssn->flags & STREAMTCP_FLAG_ZWP_TC) && TCP_GET_ACK(p) == ssn->server.next_seq + 1) {
2531  SCLogDebug("ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
2533 
2534  } else if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
2535  SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
2537  return -1;
2538  }
2539  }
2540 
2541  /* check for Keep Alive */
2542  if ((p->payload_len == 0 || p->payload_len == 1) &&
2543  (TCP_GET_SEQ(p) == (ssn->client.next_seq - 1))) {
2544  SCLogDebug("ssn %p: pkt is keep alive", ssn);
2545 
2546  /* normal pkt */
2547  } else if (!(SEQ_GEQ((TCP_GET_SEQ(p)+p->payload_len), ssn->client.last_ack))) {
2548  if (ssn->flags & STREAMTCP_FLAG_ASYNC) {
2549  SCLogDebug("ssn %p: server => Asynchronous stream, packet SEQ"
2550  " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "),"
2551  " ssn->client.last_ack %" PRIu32 ", ssn->client.next_win"
2552  "%" PRIu32 "(%" PRIu32 ")",
2553  ssn, TCP_GET_SEQ(p), p->payload_len, TCP_GET_SEQ(p) + p->payload_len,
2554  ssn->client.last_ack, ssn->client.next_win,
2555  TCP_GET_SEQ(p) + p->payload_len - ssn->client.next_win);
2556 
2557  /* update the last_ack to current seq number as the session is
2558  * async and other stream is not updating it anymore :( */
2559  StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_SEQ(p));
2560 
2561  } else if (SEQ_EQ(ssn->client.next_seq, TCP_GET_SEQ(p)) && stream_config.async_oneside &&
2562  (ssn->flags & STREAMTCP_FLAG_MIDSTREAM)) {
2563  SCLogDebug("ssn %p: server => Asynchronous stream, packet SEQ."
2564  " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "), "
2565  "ssn->client.last_ack %" PRIu32 ", ssn->client.next_win "
2566  "%" PRIu32 "(%"PRIu32")", ssn, TCP_GET_SEQ(p),
2567  p->payload_len, TCP_GET_SEQ(p) + p->payload_len,
2568  ssn->client.last_ack, ssn->client.next_win,
2569  TCP_GET_SEQ(p) + p->payload_len - ssn->client.next_win);
2570 
2571  /* it seems we missed SYN and SYN/ACK packets of this session.
2572  * Update the last_ack to current seq number as the session
2573  * is async and other stream is not updating it anymore :( */
2574  StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_SEQ(p));
2575  ssn->flags |= STREAMTCP_FLAG_ASYNC;
2576 
2577  } else if (SEQ_EQ(ssn->client.last_ack, (ssn->client.isn + 1)) &&
2579  SCLogDebug("ssn %p: server => Asynchronous stream, packet SEQ"
2580  " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "), "
2581  "ssn->client.last_ack %" PRIu32 ", ssn->client.next_win "
2582  "%" PRIu32 "(%"PRIu32")", ssn, TCP_GET_SEQ(p),
2583  p->payload_len, TCP_GET_SEQ(p) + p->payload_len,
2584  ssn->client.last_ack, ssn->client.next_win,
2585  TCP_GET_SEQ(p) + p->payload_len - ssn->client.next_win);
2586 
2587  /* it seems we missed SYN and SYN/ACK packets of this session.
2588  * Update the last_ack to current seq number as the session
2589  * is async and other stream is not updating it anymore :(*/
2590  StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_SEQ(p));
2591  ssn->flags |= STREAMTCP_FLAG_ASYNC;
2592 
2593  /* if last ack is beyond next_seq, we have accepted ack's for missing data.
2594  * In this case we do accept the data before last_ack if it is (partly)
2595  * beyond next seq */
2596  } else if (SEQ_GT(ssn->client.last_ack, ssn->client.next_seq) &&
2597  SEQ_GT((TCP_GET_SEQ(p) + p->payload_len), ssn->client.next_seq)) {
2598  SCLogDebug("ssn %p: PKT SEQ %" PRIu32 " payload_len %" PRIu16
2599  " before last_ack %" PRIu32 ", after next_seq %" PRIu32 ":"
2600  " acked data that we haven't seen before",
2601  ssn, TCP_GET_SEQ(p), p->payload_len, ssn->client.last_ack,
2602  ssn->client.next_seq);
2603  } else {
2604  SCLogDebug("ssn %p: server => SEQ before last_ack, packet SEQ"
2605  " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "), "
2606  "ssn->client.last_ack %" PRIu32 ", ssn->client.next_win "
2607  "%" PRIu32 "(%"PRIu32")", ssn, TCP_GET_SEQ(p),
2608  p->payload_len, TCP_GET_SEQ(p) + p->payload_len,
2609  ssn->client.last_ack, ssn->client.next_win,
2610  TCP_GET_SEQ(p) + p->payload_len - ssn->client.next_win);
2611 
2612  SCLogDebug("ssn %p: rejecting because pkt before last_ack", ssn);
2614  return -1;
2615  }
2616  }
2617 
2618  int zerowindowprobe = 0;
2619  /* zero window probe */
2620  if (p->payload_len == 1 && TCP_GET_SEQ(p) == ssn->client.next_seq && ssn->client.window == 0) {
2621  SCLogDebug("ssn %p: zero window probe", ssn);
2622  zerowindowprobe = 1;
2624  ssn->flags |= STREAMTCP_FLAG_ZWP_TS;
2625  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
2626 
2627  } else if (SEQ_GEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->client.next_seq)) {
2628  StreamTcpUpdateNextSeq(ssn, &ssn->client, (TCP_GET_SEQ(p) + p->payload_len));
2629  }
2630 
2631  /* in window check */
2632  if (zerowindowprobe) {
2633  SCLogDebug("ssn %p: zero window probe, skipping oow check", ssn);
2634  } else if (SEQ_LEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->client.next_win) ||
2636  {
2637  SCLogDebug("ssn %p: seq %"PRIu32" in window, ssn->client.next_win "
2638  "%" PRIu32 "", ssn, TCP_GET_SEQ(p), ssn->client.next_win);
2639 
2640  ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
2641  SCLogDebug("ssn %p: ssn->server.window %"PRIu32"", ssn,
2642  ssn->server.window);
2643 
2644  /* Check if the ACK value is sane and inside the window limit */
2645  if (p->tcph->th_flags & TH_ACK) {
2646  StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
2647  if ((ssn->flags & STREAMTCP_FLAG_ASYNC) == 0 &&
2648  SEQ_GT(ssn->server.last_ack, ssn->server.next_seq)) {
2651  }
2652  }
2653 
2654  SCLogDebug("ack %u last_ack %u next_seq %u", TCP_GET_ACK(p), ssn->server.last_ack, ssn->server.next_seq);
2655 
2656  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2657  StreamTcpHandleTimestamp(ssn, p);
2658  }
2659 
2661 
2662  /* update next_win */
2663  StreamTcpUpdateNextWin(ssn, &ssn->server, (ssn->server.last_ack + ssn->server.window));
2664 
2665  /* handle data (if any) */
2666  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
2667 
2668  } else {
2669  SCLogDebug("ssn %p: toserver => SEQ out of window, packet SEQ "
2670  "%" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "),"
2671  "ssn->client.last_ack %" PRIu32 ", ssn->client.next_win "
2672  "%" PRIu32 "(%"PRIu32")", ssn, TCP_GET_SEQ(p),
2673  p->payload_len, TCP_GET_SEQ(p) + p->payload_len,
2674  ssn->client.last_ack, ssn->client.next_win,
2675  (TCP_GET_SEQ(p) + p->payload_len) - ssn->client.next_win);
2676  SCLogDebug("ssn %p: window %u sacked %u", ssn, ssn->client.window,
2677  StreamTcpSackedSize(&ssn->client));
2679  return -1;
2680  }
2681  return 0;
2682 }
2683 
2684 /**
2685  * \brief Function to handle the TCP_ESTABLISHED state packets, which are
2686  * sent by the server to client. The function handles
2687  * ACK packets and call StreamTcpReassembleHandleSegment() to handle
2688  * the reassembly
2689  *
2690  * Timestamp has already been checked at this point.
2691  *
2692  * \param tv Thread Variable containing input/output queue, cpu affinity etc.
2693  * \param ssn Pointer to the current TCP session
2694  * \param p Packet which has to be handled in this TCP state.
2695  * \param stt Stream Thread module registered to handle the stream handling
2696  */
2697 static int HandleEstablishedPacketToClient(
2698  ThreadVars *tv, TcpSession *ssn, Packet *p, StreamTcpThread *stt)
2699 {
2700  SCLogDebug("ssn %p: =+ pkt (%" PRIu32 ") is to client: SEQ %" PRIu32 ","
2701  " ACK %" PRIu32 ", WIN %"PRIu16"", ssn, p->payload_len,
2703 
2704  const bool has_ack = (p->tcph->th_flags & TH_ACK) != 0;
2705  if (has_ack) {
2706  if ((ssn->flags & STREAMTCP_FLAG_ZWP_TS) && TCP_GET_ACK(p) == ssn->client.next_seq + 1) {
2707  SCLogDebug("ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
2709 
2710  } else if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
2711  SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
2713  return -1;
2714  }
2715  }
2716 
2717  /* To get the server window value from the servers packet, when connection
2718  is picked up as midstream */
2719  if ((ssn->flags & STREAMTCP_FLAG_MIDSTREAM) &&
2721  {
2722  ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
2723  ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
2725  SCLogDebug("ssn %p: adjusted midstream ssn->server.next_win to "
2726  "%" PRIu32 "", ssn, ssn->server.next_win);
2727  }
2728 
2729  /* check for Keep Alive */
2730  if ((p->payload_len == 0 || p->payload_len == 1) &&
2731  (TCP_GET_SEQ(p) == (ssn->server.next_seq - 1))) {
2732  SCLogDebug("ssn %p: pkt is keep alive", ssn);
2733 
2734  /* normal pkt */
2735  } else if (!(SEQ_GEQ((TCP_GET_SEQ(p)+p->payload_len), ssn->server.last_ack))) {
2736  if (ssn->flags & STREAMTCP_FLAG_ASYNC) {
2737 
2738  SCLogDebug("ssn %p: client => Asynchronous stream, packet SEQ"
2739  " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "),"
2740  " ssn->client.last_ack %" PRIu32 ", ssn->client.next_win"
2741  " %" PRIu32 "(%" PRIu32 ")",
2742  ssn, TCP_GET_SEQ(p), p->payload_len, TCP_GET_SEQ(p) + p->payload_len,
2743  ssn->server.last_ack, ssn->server.next_win,
2744  TCP_GET_SEQ(p) + p->payload_len - ssn->server.next_win);
2745 
2746  ssn->server.last_ack = TCP_GET_SEQ(p);
2747 
2748  /* if last ack is beyond next_seq, we have accepted ack's for missing data.
2749  * In this case we do accept the data before last_ack if it is (partly)
2750  * beyond next seq */
2751  } else if (SEQ_GT(ssn->server.last_ack, ssn->server.next_seq) &&
2753  {
2754  SCLogDebug("ssn %p: PKT SEQ %" PRIu32 " payload_len %" PRIu16
2755  " before last_ack %" PRIu32 ", after next_seq %" PRIu32 ":"
2756  " acked data that we haven't seen before",
2757  ssn, TCP_GET_SEQ(p), p->payload_len, ssn->server.last_ack,
2758  ssn->server.next_seq);
2759  } else {
2760  SCLogDebug("ssn %p: PKT SEQ %"PRIu32" payload_len %"PRIu16
2761  " before last_ack %"PRIu32". next_seq %"PRIu32,
2762  ssn, TCP_GET_SEQ(p), p->payload_len, ssn->server.last_ack, ssn->server.next_seq);
2764  return -1;
2765  }
2766  }
2767 
2768  int zerowindowprobe = 0;
2769  /* zero window probe */
2770  if (p->payload_len == 1 && TCP_GET_SEQ(p) == ssn->server.next_seq && ssn->server.window == 0) {
2771  SCLogDebug("ssn %p: zero window probe", ssn);
2772  zerowindowprobe = 1;
2774  ssn->flags |= STREAMTCP_FLAG_ZWP_TC;
2775 
2776  /* accept the segment */
2777  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
2778 
2779  } else if (SEQ_GEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->server.next_seq)) {
2780  StreamTcpUpdateNextSeq(ssn, &ssn->server, (TCP_GET_SEQ(p) + p->payload_len));
2781  }
2782 
2783  if (zerowindowprobe) {
2784  SCLogDebug("ssn %p: zero window probe, skipping oow check", ssn);
2785  } else if (SEQ_LEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->server.next_win) ||
2787  {
2788  SCLogDebug("ssn %p: seq %"PRIu32" in window, ssn->server.next_win "
2789  "%" PRIu32 "", ssn, TCP_GET_SEQ(p), ssn->server.next_win);
2790  ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
2791  SCLogDebug("ssn %p: ssn->client.window %"PRIu32"", ssn,
2792  ssn->client.window);
2793 
2794  if (p->tcph->th_flags & TH_ACK) {
2795  StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
2796  if ((ssn->flags & STREAMTCP_FLAG_ASYNC) == 0 &&
2797  SEQ_GT(ssn->client.last_ack, ssn->client.next_seq)) {
2800  }
2801  }
2802 
2803  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2804  StreamTcpHandleTimestamp(ssn, p);
2805  }
2806 
2808 
2809  StreamTcpUpdateNextWin(ssn, &ssn->client, (ssn->client.last_ack + ssn->client.window));
2810 
2811  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
2812  } else {
2813  SCLogDebug("ssn %p: client => SEQ out of window, packet SEQ"
2814  "%" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "),"
2815  " ssn->server.last_ack %" PRIu32 ", ssn->server.next_win "
2816  "%" PRIu32 "(%"PRIu32")", ssn, TCP_GET_SEQ(p),
2817  p->payload_len, TCP_GET_SEQ(p) + p->payload_len,
2818  ssn->server.last_ack, ssn->server.next_win,
2819  TCP_GET_SEQ(p) + p->payload_len - ssn->server.next_win);
2821  return -1;
2822  }
2823  return 0;
2824 }
2825 
2826 /**
2827  * \internal
2828  *
2829  * \brief Find the highest sequence number needed to consider all segments as ACK'd
2830  *
2831  * Used to treat all segments as ACK'd upon receiving a valid RST.
2832  *
2833  * \param stream stream to inspect the segments from
2834  * \param seq sequence number to check against
2835  *
2836  * \retval ack highest ack we need to set
2837  */
2838 static inline uint32_t StreamTcpResetGetMaxAck(TcpStream *stream, uint32_t seq)
2839 {
2840  uint32_t ack = seq;
2841 
2842  if (STREAM_HAS_SEEN_DATA(stream)) {
2843  const uint32_t tail_seq = STREAM_SEQ_RIGHT_EDGE(stream);
2844  if (SEQ_GT(tail_seq, ack)) {
2845  ack = tail_seq;
2846  }
2847  }
2848 
2849  SCReturnUInt(ack);
2850 }
2851 
2852 static bool StreamTcpPacketIsZeroWindowProbeAck(const TcpSession *ssn, const Packet *p)
2853 {
2854  if (ssn->state < TCP_ESTABLISHED)
2855  return false;
2856  if (p->payload_len != 0)
2857  return false;
2858  if ((p->tcph->th_flags & (TH_ACK | TH_SYN | TH_FIN | TH_RST)) != TH_ACK)
2859  return false;
2860 
2861  const TcpStream *snd, *rcv;
2862  if (PKT_IS_TOCLIENT(p)) {
2863  snd = &ssn->server;
2864  rcv = &ssn->client;
2865  if (!(ssn->flags & STREAMTCP_FLAG_ZWP_TS))
2866  return false;
2867  } else {
2868  snd = &ssn->client;
2869  rcv = &ssn->server;
2870  if (!(ssn->flags & STREAMTCP_FLAG_ZWP_TC))
2871  return false;
2872  }
2873 
2874  const uint32_t pkt_win = TCP_GET_WINDOW(p) << snd->wscale;
2875  if (pkt_win != 0)
2876  return false;
2877  if (pkt_win != rcv->window)
2878  return false;
2879 
2880  if (TCP_GET_SEQ(p) != snd->next_seq)
2881  return false;
2882  if (TCP_GET_ACK(p) != rcv->last_ack)
2883  return false;
2884  SCLogDebug("ssn %p: packet %" PRIu64 " is a Zero Window Probe ACK", ssn, p->pcap_cnt);
2885  return true;
2886 }
2887 
2888 /** \internal
2889  * \brief check if an ACK packet is a dup-ACK
2890  */
2891 static bool StreamTcpPacketIsDupAck(const TcpSession *ssn, const Packet *p)
2892 {
2893  if (ssn->state < TCP_ESTABLISHED)
2894  return false;
2895  if (p->payload_len != 0)
2896  return false;
2897  if ((p->tcph->th_flags & (TH_ACK | TH_SYN | TH_FIN | TH_RST)) != TH_ACK)
2898  return false;
2899 
2900  const TcpStream *snd, *rcv;
2901  if (PKT_IS_TOCLIENT(p)) {
2902  snd = &ssn->server;
2903  rcv = &ssn->client;
2904  } else {
2905  snd = &ssn->client;
2906  rcv = &ssn->server;
2907  }
2908 
2909  const uint32_t pkt_win = TCP_GET_WINDOW(p) << snd->wscale;
2910  if (pkt_win == 0 || rcv->window == 0)
2911  return false;
2912  if (pkt_win != rcv->window)
2913  return false;
2914 
2915  if (TCP_GET_SEQ(p) != snd->next_seq)
2916  return false;
2917  if (TCP_GET_ACK(p) != rcv->last_ack)
2918  return false;
2919 
2920  SCLogDebug("ssn %p: packet:%" PRIu64 " seq:%u ack:%u win:%u snd %u:%u:%u rcv %u:%u:%u", ssn,
2921  p->pcap_cnt, TCP_GET_SEQ(p), TCP_GET_ACK(p), pkt_win, snd->next_seq, snd->last_ack,
2922  rcv->window, snd->next_seq, rcv->last_ack, rcv->window);
2923  return true;
2924 }
2925 
2926 /** \internal
2927  * \brief check if a ACK packet is outdated so processing can be fast tracked
2928  *
2929  * Consider a packet outdated ack if:
2930  * - state is >= ESTABLISHED
2931  * - ACK < last_ACK
2932  * - SACK acks nothing new
2933  * - packet has no data
2934  * - SEQ == next_SEQ
2935  * - flags has ACK set but don't contain SYN/FIN/RST
2936  *
2937  * \todo the most likely explanation for this packet is that we already
2938  * accepted a "newer" ACK. We will not consider an outdated timestamp
2939  * option an issue for this packet, but we should probably still
2940  * check if the ts isn't too far off.
2941  */
2942 static bool StreamTcpPacketIsOutdatedAck(TcpSession *ssn, Packet *p)
2943 {
2944  if (ssn->state < TCP_ESTABLISHED)
2945  return false;
2946  if (p->payload_len != 0)
2947  return false;
2948  if ((p->tcph->th_flags & (TH_ACK | TH_SYN | TH_FIN | TH_RST)) != TH_ACK)
2949  return false;
2950 
2951  /* lets see if this is a packet that is entirely eclipsed by earlier ACKs */
2952  if (PKT_IS_TOSERVER(p)) {
2953  if (SEQ_EQ(TCP_GET_SEQ(p), ssn->client.next_seq) &&
2954  SEQ_LT(TCP_GET_ACK(p), ssn->server.last_ack)) {
2955  if (!TCP_HAS_SACK(p)) {
2956  SCLogDebug("outdated ACK (no SACK, SEQ %u vs next_seq %u)", TCP_GET_SEQ(p),
2957  ssn->client.next_seq);
2958  return true;
2959  }
2960 
2961  if (StreamTcpSackPacketIsOutdated(&ssn->server, p)) {
2962  SCLogDebug("outdated ACK (have SACK, SEQ %u vs next_seq %u)", TCP_GET_SEQ(p),
2963  ssn->client.next_seq);
2964  return true;
2965  }
2966  }
2967  } else {
2968  if (SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq) &&
2969  SEQ_LT(TCP_GET_ACK(p), ssn->client.last_ack)) {
2970  if (!TCP_HAS_SACK(p)) {
2971  SCLogDebug("outdated ACK (no SACK, SEQ %u vs next_seq %u)", TCP_GET_SEQ(p),
2972  ssn->client.next_seq);
2973  return true;
2974  }
2975 
2976  if (StreamTcpSackPacketIsOutdated(&ssn->client, p)) {
2977  SCLogDebug("outdated ACK (have SACK, SEQ %u vs next_seq %u)", TCP_GET_SEQ(p),
2978  ssn->client.next_seq);
2979  return true;
2980  }
2981  }
2982  }
2983  return false;
2984 }
2985 
2986 /** \internal
2987  * \brief check if packet is before ack'd windows
2988  * If packet is before last ack, we will not accept it
2989  *
2990  * \retval 0 not spurious retransmission
2991  * \retval 1 before last_ack, after base_seq
2992  * \retval 2 before last_ack and base_seq
2993  */
2994 static int StreamTcpPacketIsSpuriousRetransmission(const TcpSession *ssn, Packet *p)
2995 {
2996  const TcpStream *stream;
2997  if (PKT_IS_TOCLIENT(p)) {
2998  stream = &ssn->server;
2999  } else {
3000  stream = &ssn->client;
3001  }
3002  if (p->payload_len == 0)
3003  return 0;
3004 
3005  /* take base_seq into account to avoid edge cases where last_ack might be
3006  * too far ahead during heavy packet loss */
3007  if (!(stream->flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY)) {
3008  if ((SEQ_LEQ(TCP_GET_SEQ(p) + p->payload_len, stream->base_seq))) {
3009  SCLogDebug(
3010  "ssn %p: spurious retransmission; packet entirely before base_seq: SEQ %u(%u) "
3011  "last_ack %u base_seq %u",
3012  ssn, TCP_GET_SEQ(p), TCP_GET_SEQ(p) + p->payload_len, stream->last_ack,
3013  stream->base_seq);
3015  return 2;
3016  }
3017  }
3018 
3019  if ((SEQ_LEQ(TCP_GET_SEQ(p) + p->payload_len, stream->last_ack))) {
3020  SCLogDebug("ssn %p: spurious retransmission; packet entirely before last_ack: SEQ %u(%u) "
3021  "last_ack %u",
3022  ssn, TCP_GET_SEQ(p), TCP_GET_SEQ(p) + p->payload_len, stream->last_ack);
3024  return 1;
3025  }
3026 
3027  SCLogDebug("ssn %p: NOT spurious retransmission; packet NOT entirely before last_ack: SEQ "
3028  "%u(%u) last_ack %u, base_seq %u",
3029  ssn, TCP_GET_SEQ(p), TCP_GET_SEQ(p) + p->payload_len, stream->last_ack,
3030  stream->base_seq);
3031  return 0;
3032 }
3033 
3034 /**
3035  * \brief Function to handle the TCP_ESTABLISHED state. The function handles
3036  * ACK, FIN, RST packets and correspondingly changes the connection
3037  * state. The function handles the data inside packets and call
3038  * StreamTcpReassembleHandleSegment(tv, ) to handle the reassembling.
3039  *
3040  * \param tv Thread Variable containing input/output queue, cpu affinity etc.
3041  * \param p Packet which has to be handled in this TCP state.
3042  * \param stt Stream Thread module registered to handle the stream handling
3043  */
3044 
3045 static int StreamTcpPacketStateEstablished(
3046  ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn)
3047 {
3048  DEBUG_VALIDATE_BUG_ON(ssn == NULL);
3049 
3050  if (p->tcph->th_flags & TH_RST) {
3051  if (!StreamTcpValidateRst(ssn, p))
3052  return -1;
3053 
3054  if (PKT_IS_TOSERVER(p)) {
3055  StreamTcpCloseSsnWithReset(p, ssn);
3056 
3057  ssn->server.next_seq = TCP_GET_ACK(p);
3058  ssn->client.next_seq = TCP_GET_SEQ(p) + p->payload_len;
3059  SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "", ssn,
3060  ssn->server.next_seq);
3061  ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
3062 
3063  if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
3064  StreamTcpUpdateLastAck(ssn, &ssn->server,
3065  StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
3066 
3067  StreamTcpUpdateLastAck(ssn, &ssn->client,
3068  StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p)));
3069 
3070  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3071  StreamTcpHandleTimestamp(ssn, p);
3072  }
3073 
3074  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
3075  SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3076  "%" PRIu32 "", ssn, ssn->client.next_seq,
3077  ssn->server.last_ack);
3078 
3079  /* don't return packets to pools here just yet, the pseudo
3080  * packet will take care, otherwise the normal session
3081  * cleanup. */
3082  } else {
3083  StreamTcpCloseSsnWithReset(p, ssn);
3084 
3085  ssn->server.next_seq = TCP_GET_SEQ(p) + p->payload_len + 1;
3086  ssn->client.next_seq = TCP_GET_ACK(p);
3087 
3088  SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "", ssn,
3089  ssn->server.next_seq);
3090  ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
3091 
3092  if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
3093  StreamTcpUpdateLastAck(ssn, &ssn->client,
3094  StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
3095 
3096  StreamTcpUpdateLastAck(ssn, &ssn->server,
3097  StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p)));
3098 
3099  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3100  StreamTcpHandleTimestamp(ssn, p);
3101  }
3102 
3103  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
3104  SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3105  "%" PRIu32 "", ssn, ssn->server.next_seq,
3106  ssn->client.last_ack);
3107 
3108  /* don't return packets to pools here just yet, the pseudo
3109  * packet will take care, otherwise the normal session
3110  * cleanup. */
3111  }
3112 
3113  } else if (p->tcph->th_flags & TH_FIN) {
3114  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3115  if (!StreamTcpValidateTimestamp(ssn, p))
3116  return -1;
3117  }
3118 
3119  SCLogDebug("ssn (%p: FIN received SEQ"
3120  " %" PRIu32 ", last ACK %" PRIu32 ", next win %"PRIu32","
3121  " win %" PRIu32 "", ssn, ssn->server.next_seq,
3122  ssn->client.last_ack, ssn->server.next_win,
3123  ssn->server.window);
3124 
3125  if ((StreamTcpHandleFin(tv, stt, ssn, p)) == -1)
3126  return -1;
3127 
3128  /* SYN/ACK */
3129  } else if ((p->tcph->th_flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) {
3130  SCLogDebug("ssn %p: SYN/ACK packet on state ESTABLISHED... resent",
3131  ssn);
3132 
3133  if (PKT_IS_TOSERVER(p)) {
3134  SCLogDebug("ssn %p: SYN/ACK-pkt to server in ESTABLISHED state", ssn);
3135 
3137  return -1;
3138  }
3139 
3140  /* Check if the SYN/ACK packets ACK matches the earlier
3141  * received SYN/ACK packet. */
3142  if (!(SEQ_EQ(TCP_GET_ACK(p), ssn->client.last_ack))) {
3143  SCLogDebug("ssn %p: ACK mismatch, packet ACK %" PRIu32 " != "
3144  "%" PRIu32 " from stream", ssn, TCP_GET_ACK(p),
3145  ssn->client.isn + 1);
3146 
3148  return -1;
3149  }
3150 
3151  /* Check if the SYN/ACK packet SEQ the earlier
3152  * received SYN packet. */
3153  if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->server.isn))) {
3154  SCLogDebug("ssn %p: SEQ mismatch, packet SEQ %" PRIu32 " != "
3155  "%" PRIu32 " from stream", ssn, TCP_GET_ACK(p),
3156  ssn->client.isn + 1);
3157 
3159  return -1;
3160  }
3161 
3162  if (ssn->flags & STREAMTCP_FLAG_3WHS_CONFIRMED) {
3163  /* a resend of a SYN while we are established already -- fishy */
3165  return -1;
3166  }
3167 
3168  SCLogDebug("ssn %p: SYN/ACK packet on state ESTABLISHED... resent. "
3169  "Likely due server not receiving final ACK in 3whs", ssn);
3170  return 0;
3171 
3172  } else if (p->tcph->th_flags & TH_SYN) {
3173  SCLogDebug("ssn %p: SYN packet on state ESTABLISHED... resent", ssn);
3174  if (PKT_IS_TOCLIENT(p)) {
3175  SCLogDebug("ssn %p: SYN-pkt to client in EST state", ssn);
3176 
3178  return -1;
3179  }
3180 
3181  if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->client.isn))) {
3182  SCLogDebug("ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
3183 
3185  return -1;
3186  }
3187 
3188  /* a resend of a SYN while we are established already -- fishy */
3190  return -1;
3191 
3192  } else if (p->tcph->th_flags & TH_ACK) {
3193  /* Urgent pointer size can be more than the payload size, as it tells
3194  * the future coming data from the sender will be handled urgently
3195  * until data of size equal to urgent offset has been processed
3196  * (RFC 2147) */
3197 
3198  /* If the timestamp option is enabled for both the streams, then
3199  * validate the received packet timestamp value against the
3200  * stream->last_ts. If the timestamp is valid then process the
3201  * packet normally otherwise the drop the packet (RFC 1323) */
3202  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3203  if (!StreamTcpValidateTimestamp(ssn, p))
3204  return -1;
3205  }
3206 
3207  if (PKT_IS_TOSERVER(p)) {
3208  /* Process the received packet to server */
3209  HandleEstablishedPacketToServer(tv, ssn, p, stt);
3210 
3211  SCLogDebug("ssn %p: next SEQ %" PRIu32 ", last ACK %" PRIu32 ","
3212  " next win %" PRIu32 ", win %" PRIu32 "", ssn,
3213  ssn->client.next_seq, ssn->server.last_ack
3214  ,ssn->client.next_win, ssn->client.window);
3215 
3216  } else { /* implied to client */
3217  if (!(ssn->flags & STREAMTCP_FLAG_3WHS_CONFIRMED)) {
3219  SCLogDebug("3whs is now confirmed by server");
3220  }
3221 
3222  /* Process the received packet to client */
3223  HandleEstablishedPacketToClient(tv, ssn, p, stt);
3224 
3225  SCLogDebug("ssn %p: next SEQ %" PRIu32 ", last ACK %" PRIu32 ","
3226  " next win %" PRIu32 ", win %" PRIu32 "", ssn,
3227  ssn->server.next_seq, ssn->client.last_ack,
3228  ssn->server.next_win, ssn->server.window);
3229  }
3230  } else {
3231  SCLogDebug("ssn %p: default case", ssn);
3232  }
3233 
3234  return 0;
3235 }
3236 
3237 /**
3238  * \brief Function to handle the FIN packets for states TCP_SYN_RECV and
3239  * TCP_ESTABLISHED and changes to another TCP state as required.
3240  *
3241  * \param tv Thread Variable containing input/output queue, cpu affinity
3242  * \param p Packet which has to be handled in this TCP state.
3243  * \param stt Stream Thread module registered to handle the stream handling
3244  *
3245  * \retval 0 success
3246  * \retval -1 something wrong with the packet
3247  */
3248 
3249 static int StreamTcpHandleFin(ThreadVars *tv, StreamTcpThread *stt, TcpSession *ssn, Packet *p)
3250 {
3251  if (PKT_IS_TOSERVER(p)) {
3252  SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ %" PRIu32 ","
3253  " ACK %" PRIu32 "", ssn, p->payload_len, TCP_GET_SEQ(p),
3254  TCP_GET_ACK(p));
3255 
3256  if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
3257  SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3259  return -1;
3260  }
3261 
3262  const uint32_t pkt_re = TCP_GET_SEQ(p) + p->payload_len;
3263  SCLogDebug("ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn, TCP_GET_SEQ(p), pkt_re,
3264  ssn->client.last_ack, ssn->client.next_win);
3265  if (SEQ_GEQ(TCP_GET_SEQ(p), ssn->client.last_ack) &&
3266  SEQ_LEQ(pkt_re, ssn->client.next_win)) {
3267  // within expectations
3268  } else {
3269  SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != "
3270  "%" PRIu32 " from stream", ssn, TCP_GET_SEQ(p),
3271  ssn->client.next_seq);
3272 
3274  return -1;
3275  }
3276 
3277  if (p->tcph->th_flags & TH_SYN) {
3278  SCLogDebug("ssn %p: FIN+SYN", ssn);
3280  return -1;
3281  }
3282  StreamTcpPacketSetState(p, ssn, TCP_CLOSE_WAIT);
3283  SCLogDebug("ssn %p: state changed to TCP_CLOSE_WAIT", ssn);
3284 
3285  /* if we accept the FIN, next_seq needs to reflect the FIN */
3286  ssn->client.next_seq = TCP_GET_SEQ(p) + p->payload_len;
3287 
3288  SCLogDebug("ssn %p: ssn->client.next_seq %" PRIu32 "", ssn,
3289  ssn->client.next_seq);
3290  ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
3291 
3292  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3293  StreamTcpHandleTimestamp(ssn, p);
3294  }
3295 
3296  /* Update the next_seq, in case if we have missed the client packet
3297  and server has already received and acked it */
3298  if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
3299  ssn->server.next_seq = TCP_GET_ACK(p);
3300 
3301  if (p->tcph->th_flags & TH_ACK)
3302  StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
3303 
3304  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
3305 
3306  SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK %" PRIu32 "",
3307  ssn, ssn->client.next_seq, ssn->server.last_ack);
3308  } else { /* implied to client */
3309  SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ %" PRIu32 ", "
3310  "ACK %" PRIu32 "", ssn, p->payload_len, TCP_GET_SEQ(p),
3311  TCP_GET_ACK(p));
3312 
3313  if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
3314  SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3316  return -1;
3317  }
3318 
3319  const uint32_t pkt_re = TCP_GET_SEQ(p) + p->payload_len;
3320  SCLogDebug("ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn, TCP_GET_SEQ(p), pkt_re,
3321  ssn->server.last_ack, ssn->server.next_win);
3322  if (SEQ_GEQ(TCP_GET_SEQ(p), ssn->server.last_ack) &&
3323  SEQ_LEQ(pkt_re, ssn->server.next_win)) {
3324  // within expectations
3325  } else {
3326  SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != "
3327  "%" PRIu32 " from stream (last_ack %u win %u = %u)", ssn, TCP_GET_SEQ(p),
3328  ssn->server.next_seq, ssn->server.last_ack, ssn->server.window, (ssn->server.last_ack + ssn->server.window));
3329 
3331  return -1;
3332  }
3333 
3334  StreamTcpPacketSetState(p, ssn, TCP_FIN_WAIT1);
3335  SCLogDebug("ssn %p: state changed to TCP_FIN_WAIT1", ssn);
3336 
3337  /* if we accept the FIN, next_seq needs to reflect the FIN */
3338  ssn->server.next_seq = TCP_GET_SEQ(p) + p->payload_len + 1;
3339  SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 " updated", ssn, ssn->server.next_seq);
3340 
3341  ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
3342 
3343  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3344  StreamTcpHandleTimestamp(ssn, p);
3345  }
3346 
3347  /* Update the next_seq, in case if we have missed the client packet
3348  and server has already received and acked it */
3349  if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
3350  ssn->client.next_seq = TCP_GET_ACK(p);
3351 
3352  if (p->tcph->th_flags & TH_ACK)
3353  StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
3354 
3355  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
3356 
3357  SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK %" PRIu32 "",
3358  ssn, ssn->server.next_seq, ssn->client.last_ack);
3359  }
3360 
3361  return 0;
3362 }
3363 
3364 /**
3365  * \brief Function to handle the TCP_FIN_WAIT1 state. The function handles
3366  * ACK, FIN, RST packets and correspondingly changes the connection
3367  * state.
3368  *
3369  * \param tv Thread Variable containing input/output queue, cpu affinity
3370  * \param p Packet which has to be handled in this TCP state.
3371  * \param stt Stream Thread module registered to handle the stream handling
3372  *
3373  * \retval 0 success
3374  * \retval -1 something wrong with the packet
3375  */
3376 
3377 static int StreamTcpPacketStateFinWait1(
3378  ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn)
3379 {
3380  DEBUG_VALIDATE_BUG_ON(ssn == NULL);
3381 
3382  if (p->tcph->th_flags & TH_RST) {
3383  if (!StreamTcpValidateRst(ssn, p))
3384  return -1;
3385 
3386  StreamTcpCloseSsnWithReset(p, ssn);
3387 
3388  if (PKT_IS_TOSERVER(p)) {
3389  if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
3390  StreamTcpUpdateLastAck(ssn, &ssn->server,
3391  StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
3392 
3393  StreamTcpUpdateLastAck(ssn, &ssn->client,
3394  StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p)));
3395 
3396  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3397  StreamTcpHandleTimestamp(ssn, p);
3398  }
3399 
3400  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
3401  } else {
3402  if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
3403  StreamTcpUpdateLastAck(ssn, &ssn->client,
3404  StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
3405 
3406  StreamTcpUpdateLastAck(ssn, &ssn->server,
3407  StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p)));
3408 
3409  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3410  StreamTcpHandleTimestamp(ssn, p);
3411  }
3412 
3413  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
3414  }
3415 
3416  } else if ((p->tcph->th_flags & (TH_FIN|TH_ACK)) == (TH_FIN|TH_ACK)) {
3417  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3418  if (!StreamTcpValidateTimestamp(ssn, p))
3419  return -1;
3420  }
3421 
3422  if (PKT_IS_TOSERVER(p)) {
3423  SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
3424  "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3425  TCP_GET_SEQ(p), TCP_GET_ACK(p));
3426  int retransmission = 0;
3427 
3428  if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
3429  SCLogDebug("ssn %p: packet is retransmission", ssn);
3430  retransmission = 1;
3432 
3433  } else if (SEQ_LT(TCP_GET_SEQ(p), ssn->client.next_seq - 1) ||
3434  SEQ_GT(TCP_GET_SEQ(p), (ssn->client.last_ack + ssn->client.window))) {
3435  SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
3436  " != %" PRIu32 " from stream", ssn,
3437  TCP_GET_SEQ(p), ssn->client.next_seq);
3439  return -1;
3440  }
3441 
3442  if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
3443  SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3445  return -1;
3446  }
3447 
3448  if (!retransmission) {
3449  StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
3450  SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
3451 
3452  ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
3453  }
3454 
3455  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3456  StreamTcpHandleTimestamp(ssn, p);
3457  }
3458 
3459  /* Update the next_seq, in case if we have missed the client
3460  packet and server has already received and acked it */
3461  if (SEQ_LT(ssn->server.next_seq - 1, TCP_GET_ACK(p)))
3462  ssn->server.next_seq = TCP_GET_ACK(p);
3463 
3464  if (SEQ_EQ(ssn->client.next_seq, TCP_GET_SEQ(p))) {
3465  StreamTcpUpdateNextSeq(ssn, &ssn->client, (TCP_GET_SEQ(p) + p->payload_len));
3466  }
3467 
3468  StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
3469 
3470  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
3471 
3472  SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3473  "%" PRIu32 "", ssn, ssn->client.next_seq,
3474  ssn->server.last_ack);
3475  } else { /* implied to client */
3476  SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
3477  "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3478  TCP_GET_SEQ(p), TCP_GET_ACK(p));
3479  int retransmission = 0;
3480 
3481  if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
3482  SCLogDebug("ssn %p: packet is retransmission", ssn);
3483  retransmission = 1;
3485 
3486  } else if (SEQ_EQ(ssn->server.next_seq - 1, TCP_GET_SEQ(p)) &&
3487  SEQ_EQ(ssn->client.last_ack, TCP_GET_ACK(p))) {
3488  SCLogDebug("ssn %p: packet is retransmission", ssn);
3489  retransmission = 1;
3491 
3492  } else if (SEQ_LT(TCP_GET_SEQ(p), ssn->server.next_seq - 1) ||
3493  SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + ssn->server.window))) {
3494  SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
3495  " != %" PRIu32 " from stream", ssn,
3496  TCP_GET_SEQ(p), ssn->server.next_seq);
3498  return -1;
3499  }
3500 
3501  if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
3502  SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3504  return -1;
3505  }
3506 
3507  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3508  StreamTcpHandleTimestamp(ssn, p);
3509  }
3510 
3511  if (!retransmission) {
3512  StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
3513  SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
3514 
3515  ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
3516 
3517  /* Update the next_seq, in case if we have missed the client
3518  packet and server has already received and acked it */
3519  if (SEQ_LT(ssn->client.next_seq - 1, TCP_GET_ACK(p)))
3520  ssn->client.next_seq = TCP_GET_ACK(p);
3521 
3522  if (SEQ_EQ(ssn->server.next_seq - 1, TCP_GET_SEQ(p))) {
3523  StreamTcpUpdateNextSeq(ssn, &ssn->server, (TCP_GET_SEQ(p) + p->payload_len));
3524  }
3525 
3526  StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
3527  }
3528 
3529  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
3530 
3531  SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3532  "%" PRIu32 "", ssn, ssn->server.next_seq,
3533  ssn->client.last_ack);
3534  }
3535 
3536  } else if (p->tcph->th_flags & TH_FIN) {
3537  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3538  if (!StreamTcpValidateTimestamp(ssn, p))
3539  return -1;
3540  }
3541 
3542  if (PKT_IS_TOSERVER(p)) {
3543  SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
3544  "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3545  TCP_GET_SEQ(p), TCP_GET_ACK(p));
3546  int retransmission = 0;
3547 
3548  if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
3549  SCLogDebug("ssn %p: packet is retransmission", ssn);
3550  retransmission = 1;
3552 
3553  } else if (SEQ_LT(TCP_GET_SEQ(p), ssn->client.next_seq - 1) ||
3554  SEQ_GT(TCP_GET_SEQ(p), (ssn->client.last_ack + ssn->client.window))) {
3555  SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
3556  " != %" PRIu32 " from stream", ssn,
3557  TCP_GET_SEQ(p), ssn->client.next_seq);
3559  return -1;
3560  }
3561 
3562  if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
3563  SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3565  return -1;
3566  }
3567 
3568  if (!retransmission) {
3569  StreamTcpPacketSetState(p, ssn, TCP_CLOSING);
3570  SCLogDebug("ssn %p: state changed to TCP_CLOSING", ssn);
3571 
3572  ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
3573  }
3574 
3575  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3576  StreamTcpHandleTimestamp(ssn, p);
3577  }
3578 
3579  /* Update the next_seq, in case if we have missed the client
3580  packet and server has already received and acked it */
3581  if (SEQ_LT(ssn->server.next_seq - 1, TCP_GET_ACK(p)))
3582  ssn->server.next_seq = TCP_GET_ACK(p);
3583 
3584  if (SEQ_EQ(ssn->client.next_seq - 1, TCP_GET_SEQ(p))) {
3585  StreamTcpUpdateNextSeq(ssn, &ssn->client, (TCP_GET_SEQ(p) + p->payload_len));
3586  }
3587 
3588  if (p->tcph->th_flags & TH_ACK)
3589  StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
3590 
3591  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
3592 
3593  SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3594  "%" PRIu32 "", ssn, ssn->client.next_seq,
3595  ssn->server.last_ack);
3596  } else { /* implied to client */
3597  SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
3598  "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3599  TCP_GET_SEQ(p), TCP_GET_ACK(p));
3600 
3601  int retransmission = 0;
3602 
3603  if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
3604  SCLogDebug("ssn %p: packet is retransmission", ssn);
3605  retransmission = 1;
3607 
3608  } else if (SEQ_LT(TCP_GET_SEQ(p), ssn->server.next_seq - 1) ||
3609  SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + ssn->server.window))) {
3610  SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
3611  " != %" PRIu32 " from stream", ssn,
3612  TCP_GET_SEQ(p), ssn->server.next_seq);
3614  return -1;
3615  }
3616 
3617  if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
3618  SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3620  return -1;
3621  }
3622 
3623  if (!retransmission) {
3624  StreamTcpPacketSetState(p, ssn, TCP_CLOSING);
3625  SCLogDebug("ssn %p: state changed to TCP_CLOSING", ssn);
3626 
3627  ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
3628  }
3629 
3630  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3631  StreamTcpHandleTimestamp(ssn, p);
3632  }
3633 
3634  /* Update the next_seq, in case if we have missed the client
3635  packet and server has already received and acked it */
3636  if (SEQ_LT(ssn->client.next_seq - 1, TCP_GET_ACK(p)))
3637  ssn->client.next_seq = TCP_GET_ACK(p);
3638 
3639  if (SEQ_EQ(ssn->server.next_seq - 1, TCP_GET_SEQ(p))) {
3640  StreamTcpUpdateNextSeq(ssn, &ssn->server, (TCP_GET_SEQ(p) + p->payload_len));
3641  }
3642 
3643  if (p->tcph->th_flags & TH_ACK)
3644  StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
3645 
3646  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
3647 
3648  SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3649  "%" PRIu32 "", ssn, ssn->server.next_seq,
3650  ssn->client.last_ack);
3651  }
3652  } else if (p->tcph->th_flags & TH_SYN) {
3653  SCLogDebug("ssn (%p): SYN pkt on FinWait1", ssn);
3655  return -1;
3656 
3657  } else if (p->tcph->th_flags & TH_ACK) {
3658  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3659  if (!StreamTcpValidateTimestamp(ssn, p))
3660  return -1;
3661  }
3662 
3663  if (PKT_IS_TOSERVER(p)) {
3664  SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
3665  "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3666  TCP_GET_SEQ(p), TCP_GET_ACK(p));
3667  int retransmission = 0;
3668 
3669  if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
3670  SCLogDebug("ssn %p: packet is retransmission", ssn);
3671  retransmission = 1;
3673  }
3674 
3675  if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
3676  SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3678  return -1;
3679  }
3680 
3681  if (SEQ_LT(TCP_GET_ACK(p), ssn->server.next_seq)) {
3682  SCLogDebug("ssn %p: ACK's older segment as %u < %u", ssn, TCP_GET_ACK(p),
3683  ssn->server.next_seq);
3684  } else if (!retransmission) {
3685  if (SEQ_EQ(TCP_GET_ACK(p), ssn->server.next_seq)) {
3686  if (SEQ_LEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->client.next_win) ||
3688  SCLogDebug("ssn %p: seq %" PRIu32 " in window, ssn->client.next_win "
3689  "%" PRIu32 "",
3690  ssn, TCP_GET_SEQ(p), ssn->client.next_win);
3691  SCLogDebug(
3692  "seq %u client.next_seq %u", TCP_GET_SEQ(p), ssn->client.next_seq);
3693  if (TCP_GET_SEQ(p) == ssn->client.next_seq) {
3694  StreamTcpPacketSetState(p, ssn, TCP_FIN_WAIT2);
3695  SCLogDebug("ssn %p: state changed to TCP_FIN_WAIT2", ssn);
3696  }
3697  } else {
3698  SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
3699  " != %" PRIu32 " from stream",
3700  ssn, TCP_GET_SEQ(p), ssn->client.next_seq);
3701 
3703  return -1;
3704  }
3705 
3706  ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
3707  }
3708  }
3709 
3710  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3711  StreamTcpHandleTimestamp(ssn, p);
3712  }
3713 
3714  /* Update the next_seq, in case if we have missed the client
3715  packet and server has already received and acked it */
3716  if (SEQ_LT(ssn->server.next_seq - 1, TCP_GET_ACK(p)))
3717  ssn->server.next_seq = TCP_GET_ACK(p);
3718 
3719  if (SEQ_EQ(ssn->client.next_seq, TCP_GET_SEQ(p))) {
3720  StreamTcpUpdateNextSeq(ssn, &ssn->client, (TCP_GET_SEQ(p) + p->payload_len));
3721  }
3722 
3723  StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
3724 
3726 
3727  /* update next_win */
3728  StreamTcpUpdateNextWin(ssn, &ssn->server, (ssn->server.last_ack + ssn->server.window));
3729 
3730  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
3731 
3732  SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3733  "%" PRIu32 "", ssn, ssn->client.next_seq,
3734  ssn->server.last_ack);
3735 
3736  } else { /* implied to client */
3737 
3738  SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
3739  "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3740  TCP_GET_SEQ(p), TCP_GET_ACK(p));
3741 
3742  int retransmission = 0;
3743 
3744  if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
3745  SCLogDebug("ssn %p: packet is retransmission", ssn);
3746  retransmission = 1;
3748  }
3749 
3750  if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
3751  SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3753  return -1;
3754  }
3755 
3756  if (!retransmission) {
3757  if (SEQ_LEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->server.next_win) ||
3759  {
3760  SCLogDebug("ssn %p: seq %"PRIu32" in window, ssn->server.next_win "
3761  "%" PRIu32 "", ssn, TCP_GET_SEQ(p), ssn->server.next_win);
3762 
3763  if (TCP_GET_SEQ(p) == ssn->server.next_seq - 1) {
3764  StreamTcpPacketSetState(p, ssn, TCP_FIN_WAIT2);
3765  SCLogDebug("ssn %p: state changed to TCP_FIN_WAIT2", ssn);
3766  }
3767  } else {
3768  SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
3769  " != %" PRIu32 " from stream", ssn,
3770  TCP_GET_SEQ(p), ssn->server.next_seq);
3772  return -1;
3773  }
3774 
3775  ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
3776  }
3777 
3778  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3779  StreamTcpHandleTimestamp(ssn, p);
3780  }
3781 
3782  /* Update the next_seq, in case if we have missed the client
3783  packet and server has already received and acked it */
3784  if (SEQ_LT(ssn->client.next_seq - 1, TCP_GET_ACK(p)))
3785  ssn->client.next_seq = TCP_GET_ACK(p);
3786 
3787  if (SEQ_EQ(ssn->server.next_seq - 1, TCP_GET_SEQ(p))) {
3788  StreamTcpUpdateNextSeq(ssn, &ssn->server, (TCP_GET_SEQ(p) + p->payload_len));
3789  }
3790 
3791  StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
3792 
3794 
3795  /* update next_win */
3796  StreamTcpUpdateNextWin(ssn, &ssn->client, (ssn->client.last_ack + ssn->client.window));
3797 
3798  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
3799 
3800  SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3801  "%" PRIu32 "", ssn, ssn->server.next_seq,
3802  ssn->client.last_ack);
3803  }
3804  } else {
3805  SCLogDebug("ssn (%p): default case", ssn);
3806  }
3807 
3808  return 0;
3809 }
3810 
3811 /**
3812  * \brief Function to handle the TCP_FIN_WAIT2 state. The function handles
3813  * ACK, RST, FIN packets and correspondingly changes the connection
3814  * state.
3815  *
3816  * \param tv Thread Variable containing input/output queue, cpu affinity
3817  * \param p Packet which has to be handled in this TCP state.
3818  * \param stt Stream Thread module registered to handle the stream handling
3819  */
3820 
3821 static int StreamTcpPacketStateFinWait2(
3822  ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn)
3823 {
3824  DEBUG_VALIDATE_BUG_ON(ssn == NULL);
3825 
3826  if (p->tcph->th_flags & TH_RST) {
3827  if (!StreamTcpValidateRst(ssn, p))
3828  return -1;
3829 
3830  StreamTcpCloseSsnWithReset(p, ssn);
3831 
3832  if (PKT_IS_TOSERVER(p)) {
3833  if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
3834  StreamTcpUpdateLastAck(ssn, &ssn->server,
3835  StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
3836 
3837  StreamTcpUpdateLastAck(ssn, &ssn->client,
3838  StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p)));
3839 
3840  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3841  StreamTcpHandleTimestamp(ssn, p);
3842  }
3843 
3844  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
3845  } else {
3846  if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
3847  StreamTcpUpdateLastAck(ssn, &ssn->client,
3848  StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
3849 
3850  StreamTcpUpdateLastAck(ssn, &ssn->server,
3851  StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p)));
3852 
3853  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3854  StreamTcpHandleTimestamp(ssn, p);
3855  }
3856 
3857  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
3858  }
3859 
3860  } else if (p->tcph->th_flags & TH_FIN) {
3861  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3862  if (!StreamTcpValidateTimestamp(ssn, p))
3863  return -1;
3864  }
3865 
3866  if (PKT_IS_TOSERVER(p)) {
3867  SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
3868  "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3869  TCP_GET_SEQ(p), TCP_GET_ACK(p));
3870  int retransmission = 0;
3871 
3872  if (SEQ_EQ(TCP_GET_SEQ(p), ssn->client.next_seq - 1) &&
3873  SEQ_EQ(TCP_GET_ACK(p), ssn->server.last_ack)) {
3874  SCLogDebug("ssn %p: retransmission", ssn);
3875  retransmission = 1;
3877  } else if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
3878  SCLogDebug("ssn %p: packet is retransmission", ssn);
3879  retransmission = 1;
3881 
3882  } else if (SEQ_LT(TCP_GET_SEQ(p), ssn->client.next_seq) ||
3883  SEQ_GT(TCP_GET_SEQ(p), (ssn->client.last_ack + ssn->client.window)))
3884  {
3885  SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ "
3886  "%" PRIu32 " != %" PRIu32 " from stream", ssn,
3887  TCP_GET_SEQ(p), ssn->client.next_seq);
3889  return -1;
3890  }
3891 
3892  if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
3893  SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3895  return -1;
3896  }
3897 
3898  if (!retransmission) {
3899  StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
3900  SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
3901 
3902  if (SEQ_EQ(ssn->client.next_seq, TCP_GET_SEQ(p))) {
3904  ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
3905  }
3906  ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
3907  }
3908 
3909  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3910  StreamTcpHandleTimestamp(ssn, p);
3911  }
3912 
3913  /* Update the next_seq, in case if we have missed the client
3914  packet and server has already received and acked it */
3915  if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
3916  ssn->server.next_seq = TCP_GET_ACK(p);
3917 
3918  if (p->tcph->th_flags & TH_ACK)
3919  StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
3920 
3921  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
3922 
3923  SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3924  "%" PRIu32 "", ssn, ssn->client.next_seq,
3925  ssn->server.last_ack);
3926  } else { /* implied to client */
3927  SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
3928  "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3929  TCP_GET_SEQ(p), TCP_GET_ACK(p));
3930  int retransmission = 0;
3931 
3932  if (SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq - 1) &&
3933  SEQ_EQ(TCP_GET_ACK(p), ssn->client.last_ack)) {
3934  SCLogDebug("ssn %p: retransmission", ssn);
3935  retransmission = 1;
3937  } else if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
3938  SCLogDebug("ssn %p: packet is retransmission", ssn);
3939  retransmission = 1;
3941 
3942  } else if (SEQ_LT(TCP_GET_SEQ(p), ssn->server.next_seq) ||
3943  SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + ssn->server.window)))
3944  {
3945  SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ "
3946  "%" PRIu32 " != %" PRIu32 " from stream", ssn,
3947  TCP_GET_SEQ(p), ssn->server.next_seq);
3949  return -1;
3950  }
3951 
3952  if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
3953  SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3955  return -1;
3956  }
3957 
3958  if (!retransmission) {
3959  StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
3960  SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
3961 
3962  ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
3963  }
3964 
3965  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3966  StreamTcpHandleTimestamp(ssn, p);
3967  }
3968 
3969  /* Update the next_seq, in case if we have missed the client
3970  packet and server has already received and acked it */
3971  if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
3972  ssn->client.next_seq = TCP_GET_ACK(p);
3973 
3974  if (p->tcph->th_flags & TH_ACK)
3975  StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
3976 
3977  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
3978  SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3979  "%" PRIu32 "", ssn, ssn->server.next_seq,
3980  ssn->client.last_ack);
3981  }
3982 
3983  } else if (p->tcph->th_flags & TH_SYN) {
3984  SCLogDebug("ssn (%p): SYN pkt on FinWait2", ssn);
3986  return -1;
3987 
3988  } else if (p->tcph->th_flags & TH_ACK) {
3989  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3990  if (!StreamTcpValidateTimestamp(ssn, p))
3991  return -1;
3992  }
3993 
3994  if (PKT_IS_TOSERVER(p)) {
3995  SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
3996  "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
3997  TCP_GET_SEQ(p), TCP_GET_ACK(p));
3998  int retransmission = 0;
3999 
4000  if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
4001  SCLogDebug("ssn %p: packet is retransmission", ssn);
4002  retransmission = 1;
4004  }
4005 
4006  if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
4007  SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4009  return -1;
4010  }
4011 
4012  if (!retransmission) {
4013  if (SEQ_LEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->client.next_win) ||
4015  {
4016  SCLogDebug("ssn %p: seq %"PRIu32" in window, ssn->client.next_win "
4017  "%" PRIu32 "", ssn, TCP_GET_SEQ(p), ssn->client.next_win);
4018 
4019  } else {
4020  SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
4021  " != %" PRIu32 " from stream", ssn,
4022  TCP_GET_SEQ(p), ssn->client.next_seq);
4024  return -1;
4025  }
4026 
4027  ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
4028  }
4029 
4030  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4031  StreamTcpHandleTimestamp(ssn, p);
4032  }
4033 
4034  if (SEQ_EQ(ssn->client.next_seq, TCP_GET_SEQ(p))) {
4035  StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
4036  }
4037 
4038  StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
4039 
4041 
4042  /* update next_win */
4043  StreamTcpUpdateNextWin(ssn, &ssn->server, (ssn->server.last_ack + ssn->server.window));
4044 
4045  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
4046 
4047  SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
4048  "%" PRIu32 "", ssn, ssn->client.next_seq,
4049  ssn->server.last_ack);
4050  } else { /* implied to client */
4051  SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
4052  "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
4053  TCP_GET_SEQ(p), TCP_GET_ACK(p));
4054  int retransmission = 0;
4055 
4056  if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
4057  SCLogDebug("ssn %p: packet is retransmission", ssn);
4058  retransmission = 1;
4060  }
4061 
4062  if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
4063  SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4065  return -1;
4066  }
4067 
4068  if (!retransmission) {
4069  if (SEQ_LEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->server.next_win) ||
4071  {
4072  SCLogDebug("ssn %p: seq %"PRIu32" in window, ssn->server.next_win "
4073  "%" PRIu32 "", ssn, TCP_GET_SEQ(p), ssn->server.next_win);
4074  } else {
4075  SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
4076  " != %" PRIu32 " from stream", ssn,
4077  TCP_GET_SEQ(p), ssn->server.next_seq);
4079  return -1;
4080  }
4081 
4082  ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
4083  }
4084 
4085  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4086  StreamTcpHandleTimestamp(ssn, p);
4087  }
4088 
4089  if (SEQ_EQ(ssn->server.next_seq, TCP_GET_SEQ(p))) {
4090  StreamTcpUpdateNextSeq(ssn, &ssn->server, (ssn->server.next_seq + p->payload_len));
4091  }
4092 
4093  StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
4094 
4096 
4097  /* update next_win */
4098  StreamTcpUpdateNextWin(ssn, &ssn->client, (ssn->client.last_ack + ssn->client.window));
4099 
4100  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
4101 
4102  SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
4103  "%" PRIu32 "", ssn, ssn->server.next_seq,
4104  ssn->client.last_ack);
4105  }
4106  } else {
4107  SCLogDebug("ssn %p: default case", ssn);
4108  }
4109 
4110  return 0;
4111 }
4112 
4113 /**
4114  * \brief Function to handle the TCP_CLOSING state. Upon arrival of ACK
4115  * the connection goes to TCP_TIME_WAIT state. The state has been
4116  * reached as both end application has been closed.
4117  *
4118  * \param tv Thread Variable containing input/output queue, cpu affinity
4119  * \param p Packet which has to be handled in this TCP state.
4120  * \param stt Stream Thread module registered to handle the stream handling
4121  */
4122 
4123 static int StreamTcpPacketStateClosing(
4124  ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn)
4125 {
4126  DEBUG_VALIDATE_BUG_ON(ssn == NULL);
4127 
4128  if (p->tcph->th_flags & TH_RST) {
4129  if (!StreamTcpValidateRst(ssn, p))
4130  return -1;
4131 
4132  StreamTcpCloseSsnWithReset(p, ssn);
4133 
4134  if (PKT_IS_TOSERVER(p)) {
4135  if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
4136  StreamTcpUpdateLastAck(ssn, &ssn->server,
4137  StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
4138 
4139  StreamTcpUpdateLastAck(ssn, &ssn->client,
4140  StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p)));
4141 
4142  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4143  StreamTcpHandleTimestamp(ssn, p);
4144  }
4145 
4146  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
4147  } else {
4148  if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
4149  StreamTcpUpdateLastAck(ssn, &ssn->client,
4150  StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
4151 
4152  StreamTcpUpdateLastAck(ssn, &ssn->server,
4153  StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p)));
4154 
4155  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4156  StreamTcpHandleTimestamp(ssn, p);
4157  }
4158 
4159  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
4160  }
4161 
4162  } else if (p->tcph->th_flags & TH_SYN) {
4163  SCLogDebug("ssn (%p): SYN pkt on Closing", ssn);
4165  return -1;
4166 
4167  } else if (p->tcph->th_flags & TH_ACK) {
4168  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4169  if (!StreamTcpValidateTimestamp(ssn, p))
4170  return -1;
4171  }
4172 
4173  if (PKT_IS_TOSERVER(p)) {
4174  SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
4175  "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
4176  TCP_GET_SEQ(p), TCP_GET_ACK(p));
4177  int retransmission = 0;
4178  if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
4179  SCLogDebug("ssn %p: packet is retransmission", ssn);
4180  retransmission = 1;
4182  }
4183 
4184  if (TCP_GET_SEQ(p) != ssn->client.next_seq) {
4185  SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
4186  " != %" PRIu32 " from stream", ssn,
4187  TCP_GET_SEQ(p), ssn->client.next_seq);
4189  return -1;
4190  }
4191 
4192  if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
4193  SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4195  return -1;
4196  }
4197 
4198  if (!retransmission) {
4199  StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
4200  SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
4201 
4202  ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
4203  }
4204 
4205  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4206  StreamTcpHandleTimestamp(ssn, p);
4207  }
4208  /* Update the next_seq, in case if we have missed the client
4209  packet and server has already received and acked it */
4210  if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
4211  ssn->server.next_seq = TCP_GET_ACK(p);
4212 
4213  StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
4214 
4215  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
4216  SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
4217  "%" PRIu32 "", ssn, ssn->client.next_seq,
4218  ssn->server.last_ack);
4219  } else { /* implied to client */
4220  SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
4221  "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
4222  TCP_GET_SEQ(p), TCP_GET_ACK(p));
4223  int retransmission = 0;
4224  if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
4225  SCLogDebug("ssn %p: packet is retransmission", ssn);
4226  retransmission = 1;
4228  }
4229 
4230  if (TCP_GET_SEQ(p) != ssn->server.next_seq) {
4231  SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
4232  " != %" PRIu32 " from stream", ssn,
4233  TCP_GET_SEQ(p), ssn->server.next_seq);
4235  return -1;
4236  }
4237 
4238  if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
4239  SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4241  return -1;
4242  }
4243 
4244  if (!retransmission) {
4245  StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
4246  SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
4247 
4248  ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
4249  }
4250 
4251  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4252  StreamTcpHandleTimestamp(ssn, p);
4253  }
4254 
4255  /* Update the next_seq, in case if we have missed the client
4256  packet and server has already received and acked it */
4257  if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
4258  ssn->client.next_seq = TCP_GET_ACK(p);
4259 
4260  StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
4261 
4262  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
4263  SCLogDebug("StreamTcpPacketStateClosing (%p): =+ next SEQ "
4264  "%" PRIu32 ", last ACK %" PRIu32 "", ssn,
4265  ssn->server.next_seq, ssn->client.last_ack);
4266  }
4267  } else {
4268  SCLogDebug("ssn %p: default case", ssn);
4269  }
4270 
4271  return 0;
4272 }
4273 
4274 /**
4275  * \brief Function to handle the TCP_CLOSE_WAIT state. Upon arrival of FIN
4276  * packet from server the connection goes to TCP_LAST_ACK state.
4277  * The state is possible only for server host.
4278  *
4279  * \param tv Thread Variable containing input/output queue, cpu affinity
4280  * \param p Packet which has to be handled in this TCP state.
4281  * \param stt Stream Thread module registered to handle the stream handling
4282  */
4283 
4284 static int StreamTcpPacketStateCloseWait(
4285  ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn)
4286 {
4287  SCEnter();
4288 
4289  DEBUG_VALIDATE_BUG_ON(ssn == NULL);
4290 
4291  if (PKT_IS_TOCLIENT(p)) {
4292  SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
4293  "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
4294  TCP_GET_SEQ(p), TCP_GET_ACK(p));
4295  } else {
4296  SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
4297  "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
4298  TCP_GET_SEQ(p), TCP_GET_ACK(p));
4299  }
4300 
4301  if (p->tcph->th_flags & TH_RST) {
4302  if (!StreamTcpValidateRst(ssn, p))
4303  return -1;
4304 
4305  StreamTcpCloseSsnWithReset(p, ssn);
4306 
4307  if (PKT_IS_TOSERVER(p)) {
4308  if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
4309  StreamTcpUpdateLastAck(ssn, &ssn->server,
4310  StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
4311 
4312  StreamTcpUpdateLastAck(ssn, &ssn->client,
4313  StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p)));
4314 
4315  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4316  StreamTcpHandleTimestamp(ssn, p);
4317  }
4318 
4319  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
4320  } else {
4321  if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
4322  StreamTcpUpdateLastAck(ssn, &ssn->client,
4323  StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
4324 
4325  StreamTcpUpdateLastAck(ssn, &ssn->server,
4326  StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p)));
4327 
4328  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4329  StreamTcpHandleTimestamp(ssn, p);
4330  }
4331 
4332  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
4333  }
4334 
4335  } else if (p->tcph->th_flags & TH_FIN) {
4336  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4337  if (!StreamTcpValidateTimestamp(ssn, p))
4338  SCReturnInt(-1);
4339  }
4340 
4341  if (PKT_IS_TOSERVER(p)) {
4342  SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
4343  "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
4344  TCP_GET_SEQ(p), TCP_GET_ACK(p));
4345 
4346  int retransmission = 0;
4347  if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
4348  SCLogDebug("ssn %p: packet is retransmission", ssn);
4349  retransmission = 1;
4351  }
4352 
4353  if (!retransmission) {
4354  if (SEQ_LT(TCP_GET_SEQ(p), ssn->client.next_seq) ||
4355  SEQ_GT(TCP_GET_SEQ(p), (ssn->client.last_ack + ssn->client.window)))
4356  {
4357  SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
4358  " != %" PRIu32 " from stream", ssn,
4359  TCP_GET_SEQ(p), ssn->client.next_seq);
4361  SCReturnInt(-1);
4362  }
4363  }
4364 
4365  if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
4366  SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4368  SCReturnInt(-1);
4369  }
4370 
4371  /* don't update to LAST_ACK here as we want a toclient FIN for that */
4372 
4373  if (!retransmission)
4374  ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
4375 
4376  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4377  StreamTcpHandleTimestamp(ssn, p);
4378  }
4379 
4380  /* Update the next_seq, in case if we have missed the client
4381  packet and server has already received and acked it */
4382  if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
4383  ssn->server.next_seq = TCP_GET_ACK(p);
4384 
4385  if (p->tcph->th_flags & TH_ACK)
4386  StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
4387 
4388  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
4389  SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
4390  "%" PRIu32 "", ssn, ssn->client.next_seq,
4391  ssn->server.last_ack);
4392  } else {
4393  SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
4394  "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
4395  TCP_GET_SEQ(p), TCP_GET_ACK(p));
4396 
4397  int retransmission = 0;
4398  if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
4399  SCLogDebug("ssn %p: packet is retransmission", ssn);
4400  retransmission = 1;
4402  }
4403 
4404  if (!retransmission) {
4405  if (SEQ_LT(TCP_GET_SEQ(p), ssn->server.next_seq) ||
4406  SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + ssn->server.window)))
4407  {
4408  SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
4409  " != %" PRIu32 " from stream", ssn,
4410  TCP_GET_SEQ(p), ssn->server.next_seq);
4412  SCReturnInt(-1);
4413  }
4414  }
4415 
4416  if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
4417  SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4419  SCReturnInt(-1);
4420  }
4421 
4422  if (!retransmission) {
4423  StreamTcpPacketSetState(p, ssn, TCP_LAST_ACK);
4424  SCLogDebug("ssn %p: state changed to TCP_LAST_ACK", ssn);
4425 
4426  ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
4427  }
4428 
4429  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4430  StreamTcpHandleTimestamp(ssn, p);
4431  }
4432 
4433  /* Update the next_seq, in case if we have missed the client
4434  packet and server has already received and acked it */
4435  if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
4436  ssn->client.next_seq = TCP_GET_ACK(p);
4437 
4438  if (p->tcph->th_flags & TH_ACK)
4439  StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
4440 
4441  StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
4442  SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
4443  "%" PRIu32 "", ssn, ssn->server.next_seq,
4444  ssn->client.last_ack);
4445  }
4446 
4447  } else if (p->tcph->th_flags & TH_SYN) {
4448  SCLogDebug("ssn (%p): SYN pkt on CloseWait", ssn);
4450  SCReturnInt(-1);
4451 
4452  } else if (p->tcph->th_flags & TH_ACK) {
4453  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4454  if (!StreamTcpValidateTimestamp(ssn, p))
4455  SCReturnInt(-1);
4456  }
4457 
4458  if (PKT_IS_TOSERVER(p)) {
4459  SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
4460  "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
4461  TCP_GET_SEQ(p), TCP_GET_ACK(p));
4462 
4463  int retransmission = 0;
4464  if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
4465  SCLogDebug("ssn %p: packet is retransmission", ssn);
4466  retransmission = 1;
4468  }
4469 
4470  if (p->payload_len > 0 && (SEQ_LEQ((TCP_GET_SEQ(p) + p->payload_len), ssn->client.last_ack))) {
4471  SCLogDebug("ssn %p: -> retransmission", ssn);
4473  SCReturnInt(-1);
4474 
4475  } else if (SEQ_GT(TCP_GET_SEQ(p), (ssn->client.last_ack + ssn->client.window)))
4476  {
4477  SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
4478  " != %" PRIu32 " from stream", ssn,
4479  TCP_GET_SEQ(p), ssn->client.next_seq);
4481  SCReturnInt(-1);
4482  }
4483 
4484  if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
4485  SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4487  SCReturnInt(-1);
4488  }
4489 
4490  if (!retransmission) {
4491  ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
4492  }
4493 
4494  if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4495  StreamTcpHandleTimestamp(ssn, p);
4496  }
4497 
4498  /* Update the next_seq, in case if we have missed the client
4499  packet and server has already received and acked it */
4500  if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK