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