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