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