Coverage Report

Created: 2026-09-28 07:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata8/src/stream-tcp.c
Line
Count
Source
1
/* Copyright (C) 2007-2026 Open Information Security Foundation
2
 *
3
 * You can copy, redistribute or modify this Program under the terms of
4
 * the GNU General Public License version 2 as published by the Free
5
 * Software Foundation.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * version 2 along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
 * 02110-1301, USA.
16
 */
17
18
/**
19
 * \file
20
 *
21
 * \author Victor Julien <victor@inliniac.net>
22
 * \author Gurvinder Singh <gurvindersinghdahiya@gmail.com>
23
 *
24
 * TCP stream tracking and reassembly engine.
25
 *
26
 * \todo - 4WHS: what if after the 2nd SYN we turn out to be normal 3WHS anyway?
27
 */
28
29
#include "suricata-common.h"
30
#include "suricata.h"
31
#include "packet.h"
32
#include "decode.h"
33
#include "detect.h"
34
35
#include "flow.h"
36
#include "flow-util.h"
37
38
#include "conf.h"
39
#include "conf-yaml-loader.h"
40
41
#include "threads.h"
42
#include "threadvars.h"
43
#include "tm-threads.h"
44
45
#include "util-pool.h"
46
#include "util-pool-thread.h"
47
#include "util-checksum.h"
48
#include "util-unittest.h"
49
#include "util-print.h"
50
#include "util-debug.h"
51
#include "util-device-private.h"
52
53
#include "stream-tcp-private.h"
54
#include "stream-tcp.h"
55
#include "stream-tcp-cache.h"
56
#include "stream-tcp-inline.h"
57
#include "stream-tcp-reassemble.h"
58
#include "stream-tcp-sack.h"
59
#include "stream-tcp-util.h"
60
#include "stream.h"
61
62
#include "pkt-var.h"
63
#include "host.h"
64
65
#include "app-layer.h"
66
#include "app-layer-parser.h"
67
#include "app-layer-protos.h"
68
#include "app-layer-htp-mem.h"
69
70
#include "util-host-os-info.h"
71
#include "util-privs.h"
72
#include "util-profiling.h"
73
#include "util-misc.h"
74
#include "util-validate.h"
75
#include "util-runmodes.h"
76
#include "util-random.h"
77
#include "util-exception-policy.h"
78
#include "util-time.h"
79
80
#include "source-pcap-file.h"
81
#include "action-globals.h"
82
83
//#define DEBUG
84
85
78
#define STREAMTCP_DEFAULT_PREALLOC              2048
86
#define STREAMTCP_DEFAULT_MEMCAP                (64 * 1024 * 1024)  /* 64mb */
87
#define STREAMTCP_DEFAULT_REASSEMBLY_MEMCAP     (256 * 1024 * 1024) /* 256mb */
88
78
#define STREAMTCP_DEFAULT_TOSERVER_CHUNK_SIZE   2560
89
78
#define STREAMTCP_DEFAULT_TOCLIENT_CHUNK_SIZE   2560
90
78
#define STREAMTCP_DEFAULT_MAX_SYN_QUEUED        10
91
78
#define STREAMTCP_DEFAULT_MAX_SYNACK_QUEUED     5
92
93
/* Settings order as in the enum */
94
// clang-format off
95
ExceptionPolicyStatsSetts stream_memcap_eps_stats = {
96
    .valid_settings_ids = {
97
    /* EXCEPTION_POLICY_NOT_SET */      false,
98
    /* EXCEPTION_POLICY_AUTO */         false,
99
    /* EXCEPTION_POLICY_PASS_PACKET */  true,
100
    /* EXCEPTION_POLICY_PASS_FLOW */    true,
101
    /* EXCEPTION_POLICY_BYPASS_FLOW */  true,
102
    /* EXCEPTION_POLICY_DROP_PACKET */  false,
103
    /* EXCEPTION_POLICY_DROP_FLOW */    false,
104
    /* EXCEPTION_POLICY_REJECT */       true,
105
    /* EXCEPTION_POLICY_REJECT_BOTH */  true,
106
    },
107
    .valid_settings_ips = {
108
    /* EXCEPTION_POLICY_NOT_SET */      false,
109
    /* EXCEPTION_POLICY_AUTO */         false,
110
    /* EXCEPTION_POLICY_PASS_PACKET */  true,
111
    /* EXCEPTION_POLICY_PASS_FLOW */    true,
112
    /* EXCEPTION_POLICY_BYPASS_FLOW */  true,
113
    /* EXCEPTION_POLICY_DROP_PACKET */  true,
114
    /* EXCEPTION_POLICY_DROP_FLOW */    true,
115
    /* EXCEPTION_POLICY_REJECT */       true,
116
    /* EXCEPTION_POLICY_REJECT_BOTH */  true,
117
    },
118
};
119
// clang-format on
120
121
/* Settings order as in the enum */
122
// clang-format off
123
ExceptionPolicyStatsSetts stream_reassembly_memcap_eps_stats = {
124
    .valid_settings_ids = {
125
    /* EXCEPTION_POLICY_NOT_SET */      false,
126
    /* EXCEPTION_POLICY_AUTO */         false,
127
    /* EXCEPTION_POLICY_PASS_PACKET */  true,
128
    /* EXCEPTION_POLICY_PASS_FLOW */    true,
129
    /* EXCEPTION_POLICY_BYPASS_FLOW */  true,
130
    /* EXCEPTION_POLICY_DROP_PACKET */  false,
131
    /* EXCEPTION_POLICY_DROP_FLOW */    false,
132
    /* EXCEPTION_POLICY_REJECT */       true,
133
    /* EXCEPTION_POLICY_REJECT_BOTH */  true,
134
    },
135
    .valid_settings_ips = {
136
    /* EXCEPTION_POLICY_NOT_SET */      false,
137
    /* EXCEPTION_POLICY_AUTO */         false,
138
    /* EXCEPTION_POLICY_PASS_PACKET */  true,
139
    /* EXCEPTION_POLICY_PASS_FLOW */    true,
140
    /* EXCEPTION_POLICY_BYPASS_FLOW */  true,
141
    /* EXCEPTION_POLICY_DROP_PACKET */  true,
142
    /* EXCEPTION_POLICY_DROP_FLOW */    true,
143
    /* EXCEPTION_POLICY_REJECT */       true,
144
    /* EXCEPTION_POLICY_REJECT_BOTH */  true,
145
    },
146
};
147
// clang-format on
148
149
/* Settings order as in the enum */
150
// clang-format off
151
ExceptionPolicyStatsSetts stream_midstream_enabled_eps_stats = {
152
    .valid_settings_ids = {
153
    /* EXCEPTION_POLICY_NOT_SET */      false,
154
    /* EXCEPTION_POLICY_AUTO */         false,
155
    /* EXCEPTION_POLICY_PASS_PACKET */  false,
156
    /* EXCEPTION_POLICY_PASS_FLOW */    true,
157
    /* EXCEPTION_POLICY_BYPASS_FLOW */  false,
158
    /* EXCEPTION_POLICY_DROP_PACKET */  false,
159
    /* EXCEPTION_POLICY_DROP_FLOW */    false,
160
    /* EXCEPTION_POLICY_REJECT */       false,
161
    /* EXCEPTION_POLICY_REJECT_BOTH */  false,
162
    },
163
    .valid_settings_ips = {
164
    /* EXCEPTION_POLICY_NOT_SET */      false,
165
    /* EXCEPTION_POLICY_AUTO */         false,
166
    /* EXCEPTION_POLICY_PASS_PACKET */  false,
167
    /* EXCEPTION_POLICY_PASS_FLOW */    true,
168
    /* EXCEPTION_POLICY_BYPASS_FLOW */  false,
169
    /* EXCEPTION_POLICY_DROP_PACKET */  false,
170
    /* EXCEPTION_POLICY_DROP_FLOW */    false,
171
    /* EXCEPTION_POLICY_REJECT */       false,
172
    /* EXCEPTION_POLICY_REJECT_BOTH */  false,
173
    },
174
};
175
// clang-format on
176
177
/* Settings order as in the enum */
178
// clang-format off
179
ExceptionPolicyStatsSetts stream_midstream_disabled_eps_stats = {
180
    .valid_settings_ids = {
181
    /* EXCEPTION_POLICY_NOT_SET */      false,
182
    /* EXCEPTION_POLICY_AUTO */         false,
183
    /* EXCEPTION_POLICY_PASS_PACKET */  false,
184
    /* EXCEPTION_POLICY_PASS_FLOW */    true,
185
    /* EXCEPTION_POLICY_BYPASS_FLOW */  true,
186
    /* EXCEPTION_POLICY_DROP_PACKET */  false,
187
    /* EXCEPTION_POLICY_DROP_FLOW */    false,
188
    /* EXCEPTION_POLICY_REJECT */       true,
189
    /* EXCEPTION_POLICY_REJECT_BOTH */  true,
190
    },
191
    .valid_settings_ips = {
192
    /* EXCEPTION_POLICY_NOT_SET */      false,
193
    /* EXCEPTION_POLICY_AUTO */         false,
194
    /* EXCEPTION_POLICY_PASS_PACKET */  false,
195
    /* EXCEPTION_POLICY_PASS_FLOW */    true,
196
    /* EXCEPTION_POLICY_BYPASS_FLOW */  true,
197
    /* EXCEPTION_POLICY_DROP_PACKET */  false,
198
    /* EXCEPTION_POLICY_DROP_FLOW */    true,
199
    /* EXCEPTION_POLICY_REJECT */       true,
200
    /* EXCEPTION_POLICY_REJECT_BOTH */  true,
201
    },
202
};
203
// clang-format on
204
205
static int StreamTcpHandleFin(ThreadVars *tv, StreamTcpThread *, TcpSession *, Packet *);
206
void StreamTcpReturnStreamSegments (TcpStream *);
207
void StreamTcpInitConfig(bool);
208
int StreamTcpGetFlowState(void *);
209
void StreamTcpSetOSPolicy(TcpStream*, Packet*);
210
211
static int StreamTcpValidateTimestamp(TcpSession * , Packet *);
212
static int StreamTcpHandleTimestamp(TcpSession * , Packet *);
213
static int StreamTcpValidateRst(TcpSession * , Packet *);
214
static inline int StreamTcpValidateAck(TcpSession *ssn, TcpStream *, Packet *);
215
static int StreamTcpStateDispatch(
216
        ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn, const uint8_t state);
217
218
extern thread_local uint64_t t_pcapcnt;
219
extern int g_detect_disabled;
220
221
PoolThread *ssn_pool = NULL;
222
static SCMutex ssn_pool_mutex = SCMUTEX_INITIALIZER; /**< init only, protect initializing and growing pool */
223
#if defined(DEBUG) || defined(QA_SIMULATION)
224
static uint64_t ssn_pool_cnt = 0; /** counts ssns, protected by ssn_pool_mutex */
225
#endif
226
227
TcpStreamCnf stream_config;
228
uint64_t StreamTcpReassembleMemuseGlobalCounter(void);
229
SC_ATOMIC_DECLARE(uint64_t, st_memuse);
230
231
void StreamTcpInitMemuse(void)
232
78
{
233
78
    SC_ATOMIC_INIT(st_memuse);
234
78
}
235
236
void StreamTcpIncrMemuse(uint64_t size)
237
55.8k
{
238
55.8k
    (void) SC_ATOMIC_ADD(st_memuse, size);
239
55.8k
    SCLogDebug("STREAM %" PRIu64 ", incr %" PRIu64, StreamTcpMemuseCounter(), size);
240
55.8k
}
241
242
void StreamTcpDecrMemuse(uint64_t size)
243
47.6k
{
244
#if defined(DEBUG_VALIDATION) && defined(UNITTESTS)
245
    uint64_t presize = SC_ATOMIC_GET(st_memuse);
246
    if (RunmodeIsUnittests()) {
247
        BUG_ON(presize > UINT_MAX);
248
    }
249
#endif
250
251
47.6k
    (void) SC_ATOMIC_SUB(st_memuse, size);
252
253
#if defined(DEBUG_VALIDATION) && defined(UNITTESTS)
254
    if (RunmodeIsUnittests()) {
255
        uint64_t postsize = SC_ATOMIC_GET(st_memuse);
256
        BUG_ON(postsize > presize);
257
    }
258
#endif
259
47.6k
    SCLogDebug("STREAM %" PRIu64 ", decr %" PRIu64, StreamTcpMemuseCounter(), size);
260
47.6k
}
261
262
uint64_t StreamTcpMemuseCounter(void)
263
0
{
264
0
    uint64_t memusecopy = SC_ATOMIC_GET(st_memuse);
265
0
    return memusecopy;
266
0
}
267
268
/**
269
 *  \brief Check if alloc'ing "size" would mean we're over memcap
270
 *
271
 *  \retval 1 if in bounds
272
 *  \retval 0 if not in bounds
273
 */
274
int StreamTcpCheckMemcap(uint64_t size)
275
55.8k
{
276
55.8k
    uint64_t memcapcopy = SC_ATOMIC_GET(stream_config.memcap);
277
55.8k
    if (memcapcopy == 0 || size + SC_ATOMIC_GET(st_memuse) <= memcapcopy)
278
55.8k
        return 1;
279
0
    return 0;
280
55.8k
}
281
282
/**
283
 *  \brief Update memcap value
284
 *
285
 *  \param size new memcap value
286
 */
287
int StreamTcpSetMemcap(uint64_t size)
288
0
{
289
0
    if (size == 0 || (uint64_t)SC_ATOMIC_GET(st_memuse) < size) {
290
0
        SC_ATOMIC_SET(stream_config.memcap, size);
291
0
        return 1;
292
0
    }
293
294
0
    return 0;
295
0
}
296
297
/**
298
 *  \brief Return memcap value
299
 *
300
 *  \param memcap memcap value
301
 */
302
uint64_t StreamTcpGetMemcap(void)
303
0
{
304
0
    uint64_t memcapcopy = SC_ATOMIC_GET(stream_config.memcap);
305
0
    return memcapcopy;
306
0
}
307
308
void StreamTcpStreamCleanup(TcpStream *stream)
309
561k
{
310
561k
    if (stream != NULL) {
311
561k
        StreamTcpSackFreeList(stream);
312
561k
        StreamTcpReturnStreamSegments(stream);
313
561k
        StreamingBufferClear(&stream->sb, &stream_config.sbcnf);
314
561k
    }
315
561k
}
316
317
static void StreamTcp3wsFreeQueue(TcpSession *ssn)
318
347k
{
319
347k
    TcpStateQueue *q, *q_next;
320
347k
    q = ssn->queue;
321
366k
    while (q != NULL) {
322
19.5k
        q_next = q->next;
323
19.5k
        SCFree(q);
324
19.5k
        q = q_next;
325
19.5k
        StreamTcpDecrMemuse((uint64_t)sizeof(TcpStateQueue));
326
19.5k
    }
327
347k
    ssn->queue = NULL;
328
347k
    ssn->queue_len = 0;
329
347k
}
330
331
/**
332
 *  \brief Session cleanup function. Does not free the ssn.
333
 *  \param ssn tcp session
334
 */
335
void StreamTcpSessionCleanup(TcpSession *ssn)
336
280k
{
337
280k
    SCEnter();
338
339
280k
    if (ssn == NULL)
340
2
        return;
341
342
280k
    StreamTcpStreamCleanup(&ssn->client);
343
280k
    StreamTcpStreamCleanup(&ssn->server);
344
280k
    StreamTcp3wsFreeQueue(ssn);
345
346
280k
    SCReturn;
347
280k
}
348
349
/**
350
 *  \brief Function to return the stream back to the pool. It returns the
351
 *         segments in the stream to the segment pool.
352
 *
353
 *  This function is called when the flow is destroyed, so it should free
354
 *  *everything* related to the tcp session. So including the app layer
355
 *  data.
356
 *
357
 *  \param ssn Void ptr to the ssn.
358
 */
359
void StreamTcpSessionClear(void *ssnptr)
360
302k
{
361
302k
    SCEnter();
362
302k
    TcpSession *ssn = (TcpSession *)ssnptr;
363
302k
    if (ssn == NULL)
364
21.4k
        return;
365
366
280k
    StreamTcpSessionCleanup(ssn);
367
368
    /* HACK: don't loose track of thread id */
369
280k
    PoolThreadId pool_id = ssn->pool_id;
370
280k
    memset(ssn, 0, sizeof(TcpSession));
371
280k
    ssn->pool_id = pool_id;
372
373
280k
    StreamTcpThreadCacheReturnSession(ssn);
374
#ifdef DEBUG
375
    SCMutexLock(&ssn_pool_mutex);
376
    ssn_pool_cnt--;
377
    SCMutexUnlock(&ssn_pool_mutex);
378
#endif
379
380
280k
    SCReturn;
381
302k
}
382
383
/**
384
 *  \brief Function to return the stream segments back to the pool.
385
 *
386
 *  \param p Packet used to identify the stream.
387
 */
388
void StreamTcpSessionPktFree (Packet *p)
389
0
{
390
0
    SCEnter();
391
392
0
    TcpSession *ssn = (TcpSession *)p->flow->protoctx;
393
0
    if (ssn == NULL)
394
0
        SCReturn;
395
396
0
    StreamTcpReturnStreamSegments(&ssn->client);
397
0
    StreamTcpReturnStreamSegments(&ssn->server);
398
399
0
    SCReturn;
400
0
}
401
402
/** \brief Stream alloc function for the Pool
403
 *  \retval ptr void ptr to TcpSession structure with all vars set to 0/NULL
404
 */
405
static void *StreamTcpSessionPoolAlloc(void)
406
8.19k
{
407
8.19k
    void *ptr = NULL;
408
409
8.19k
    if (StreamTcpCheckMemcap((uint32_t)sizeof(TcpSession)) == 0)
410
0
        return NULL;
411
412
8.19k
    ptr = SCMalloc(sizeof(TcpSession));
413
8.19k
    if (unlikely(ptr == NULL))
414
0
        return NULL;
415
416
8.19k
    return ptr;
417
8.19k
}
418
419
static int StreamTcpSessionPoolInit(void *data, void* initdata)
420
8.19k
{
421
8.19k
    memset(data, 0, sizeof(TcpSession));
422
8.19k
    StreamTcpIncrMemuse((uint64_t)sizeof(TcpSession));
423
424
8.19k
    return 1;
425
8.19k
}
426
427
/** \brief Pool cleanup function
428
 *  \param s Void ptr to TcpSession memory */
429
static void StreamTcpSessionPoolCleanup(void *s)
430
0
{
431
0
    if (s != NULL) {
432
0
        StreamTcpSessionCleanup(s);
433
        /** \todo not very clean, as the memory is not freed here */
434
0
        StreamTcpDecrMemuse((uint64_t)sizeof(TcpSession));
435
0
    }
436
0
}
437
438
/** \internal
439
 *  \brief See if stream engine is dropping invalid packet in inline mode
440
 *  \retval false no
441
 *  \retval true yes
442
 */
443
static inline bool StreamTcpInlineDropInvalid(void)
444
981k
{
445
981k
    return ((stream_config.flags & STREAMTCP_INIT_FLAG_INLINE)
446
0
            && (stream_config.flags & STREAMTCP_INIT_FLAG_DROP_INVALID));
447
981k
}
448
449
/** \internal
450
 *  \brief See if stream engine is dropping URG packets in inline mode
451
 *  \retval false no
452
 *  \retval true yes
453
 */
454
static inline bool StreamTcpInlineDropUrg(void)
455
603k
{
456
603k
    return ((stream_config.flags & STREAMTCP_INIT_FLAG_INLINE) &&
457
0
            stream_config.urgent_policy == TCP_STREAM_URGENT_DROP);
458
603k
}
459
460
/* hack: stream random range code expects random values in range of 0-RAND_MAX,
461
 * but we can get both <0 and >RAND_MAX values from RandomGet
462
 */
463
static int RandomGetWrap(void)
464
156
{
465
156
    unsigned long r;
466
467
156
    do {
468
156
        r = RandomGet();
469
156
    } while(r >= ULONG_MAX - (ULONG_MAX % RAND_MAX));
470
471
156
    return r % RAND_MAX;
472
156
}
473
474
static const char *UrgentPolicyToString(enum TcpStreamUrgentHandling pol)
475
78
{
476
78
    switch (pol) {
477
0
        case TCP_STREAM_URGENT_OOB:
478
0
            return "oob";
479
78
        case TCP_STREAM_URGENT_INLINE:
480
78
            return "inline";
481
0
        case TCP_STREAM_URGENT_DROP:
482
0
            return "drop";
483
0
        case TCP_STREAM_URGENT_GAP:
484
0
            return "gap";
485
78
    }
486
0
    return NULL;
487
78
}
488
489
490
/** \brief          To initialize the stream global configuration data
491
 *
492
 *  \param  quiet   It tells the mode of operation, if it is true nothing will
493
 *                  be get printed.
494
 */
495
496
void StreamTcpInitConfig(bool quiet)
497
78
{
498
78
    intmax_t value = 0;
499
78
    uint16_t rdrange = 10;
500
501
78
    SCLogDebug("Initializing Stream");
502
503
78
    memset(&stream_config,  0, sizeof(stream_config));
504
505
78
    SC_ATOMIC_INIT(stream_config.memcap);
506
78
    SC_ATOMIC_INIT(stream_config.reassembly_memcap);
507
508
78
    if ((SCConfGetInt("stream.max-sessions", &value)) == 1) {
509
0
        SCLogWarning("max-sessions is obsolete. "
510
0
                     "Number of concurrent sessions is now only limited by Flow and "
511
0
                     "TCP stream engine memcaps.");
512
0
    }
513
514
78
    if ((SCConfGetInt("stream.prealloc-sessions", &value)) == 1) {
515
0
        stream_config.prealloc_sessions = (uint32_t)value;
516
78
    } else {
517
78
        if (RunmodeIsUnittests()) {
518
0
            stream_config.prealloc_sessions = 128;
519
78
        } else {
520
78
            stream_config.prealloc_sessions = STREAMTCP_DEFAULT_PREALLOC;
521
78
            if (SCConfGetNode("stream.prealloc-sessions") != NULL) {
522
0
                WarnInvalidConfEntry("stream.prealloc_sessions",
523
0
                                     "%"PRIu32,
524
0
                                     stream_config.prealloc_sessions);
525
0
            }
526
78
        }
527
78
    }
528
78
    if (!quiet) {
529
78
        SCLogConfig("stream \"prealloc-sessions\": %"PRIu32" (per thread)",
530
78
                stream_config.prealloc_sessions);
531
78
    }
532
533
78
    const char *temp_stream_memcap_str;
534
78
    if (SCConfGetNonNull("stream.memcap", &temp_stream_memcap_str) == 1) {
535
0
        uint64_t stream_memcap_copy;
536
0
        if (ParseSizeStringU64(temp_stream_memcap_str, &stream_memcap_copy) < 0) {
537
0
            SCLogError("Error parsing stream.memcap "
538
0
                       "from conf file - %s.  Killing engine",
539
0
                    temp_stream_memcap_str);
540
0
            exit(EXIT_FAILURE);
541
0
        } else {
542
0
            SC_ATOMIC_SET(stream_config.memcap, stream_memcap_copy);
543
0
        }
544
78
    } else {
545
78
        SC_ATOMIC_SET(stream_config.memcap, STREAMTCP_DEFAULT_MEMCAP);
546
78
    }
547
548
78
    if (!quiet) {
549
78
        SCLogConfig("stream \"memcap\": %"PRIu64, SC_ATOMIC_GET(stream_config.memcap));
550
78
    }
551
552
78
    int imidstream;
553
78
    (void)SCConfGetBool("stream.midstream", &imidstream);
554
78
    stream_config.midstream = imidstream != 0;
555
556
78
    if (!quiet) {
557
78
        SCLogConfig("stream \"midstream\" session pickups: %s", stream_config.midstream ? "enabled" : "disabled");
558
78
    }
559
560
78
    int async_oneside;
561
78
    (void)SCConfGetBool("stream.async-oneside", &async_oneside);
562
78
    stream_config.async_oneside = async_oneside != 0;
563
564
78
    if (!quiet) {
565
78
        SCLogConfig("stream \"async-oneside\": %s", stream_config.async_oneside ? "enabled" : "disabled");
566
78
    }
567
568
78
    int csum = 0;
569
570
78
    if ((SCConfGetBool("stream.checksum-validation", &csum)) == 1) {
571
78
        if (csum == 1) {
572
0
            stream_config.flags |= STREAMTCP_INIT_FLAG_CHECKSUM_VALIDATION;
573
0
        }
574
    /* Default is that we validate the checksum of all the packets */
575
78
    } else {
576
0
        stream_config.flags |= STREAMTCP_INIT_FLAG_CHECKSUM_VALIDATION;
577
0
    }
578
579
78
    if (!quiet) {
580
78
        SCLogConfig("stream \"checksum-validation\": %s",
581
78
                stream_config.flags & STREAMTCP_INIT_FLAG_CHECKSUM_VALIDATION ?
582
78
                "enabled" : "disabled");
583
78
    }
584
585
78
    const char *temp_stream_inline_str;
586
78
    if (SCConfGetNonNull("stream.inline", &temp_stream_inline_str) == 1) {
587
0
        int inl = 0;
588
589
        /* checking for "auto" and falling back to boolean to provide
590
         * backward compatibility */
591
0
        if (strcmp(temp_stream_inline_str, "auto") == 0) {
592
0
            if (EngineModeIsIPS()) {
593
0
                stream_config.flags |= STREAMTCP_INIT_FLAG_INLINE;
594
0
            }
595
0
        } else if (SCConfGetBool("stream.inline", &inl) == 1) {
596
0
            if (inl) {
597
0
                stream_config.flags |= STREAMTCP_INIT_FLAG_INLINE;
598
0
            }
599
0
        }
600
78
    } else {
601
        /* default to 'auto' */
602
78
        if (EngineModeIsIPS()) {
603
0
            stream_config.flags |= STREAMTCP_INIT_FLAG_INLINE;
604
0
        }
605
78
    }
606
78
    stream_config.ssn_memcap_policy = ExceptionPolicyParse("stream.memcap-policy", true);
607
78
    stream_config.reassembly_memcap_policy =
608
78
            ExceptionPolicyParse("stream.reassembly.memcap-policy", true);
609
78
    stream_config.midstream_policy = ExceptionPolicyMidstreamParse(stream_config.midstream);
610
611
78
    if (!quiet) {
612
78
        SCLogConfig("stream.\"inline\": %s",
613
78
                    stream_config.flags & STREAMTCP_INIT_FLAG_INLINE
614
78
                    ? "enabled" : "disabled");
615
78
    }
616
617
78
    int bypass = 0;
618
78
    if ((SCConfGetBool("stream.bypass", &bypass)) == 1) {
619
0
        if (bypass == 1) {
620
0
            stream_config.flags |= STREAMTCP_INIT_FLAG_BYPASS;
621
0
        }
622
0
    }
623
624
78
    if (!quiet) {
625
78
        SCLogConfig("stream \"bypass\": %s",
626
78
                    (stream_config.flags & STREAMTCP_INIT_FLAG_BYPASS)
627
78
                    ? "enabled" : "disabled");
628
78
    }
629
630
78
    int drop_invalid = 0;
631
78
    if ((SCConfGetBool("stream.drop-invalid", &drop_invalid)) == 1) {
632
0
        if (drop_invalid == 1) {
633
0
            stream_config.flags |= STREAMTCP_INIT_FLAG_DROP_INVALID;
634
0
        }
635
78
    } else {
636
78
        stream_config.flags |= STREAMTCP_INIT_FLAG_DROP_INVALID;
637
78
    }
638
639
78
    const char *temp_urgpol = NULL;
640
78
    if (SCConfGet("stream.reassembly.urgent.policy", &temp_urgpol) == 1 && temp_urgpol != NULL) {
641
0
        if (strcmp(temp_urgpol, "inline") == 0) {
642
0
            stream_config.urgent_policy = TCP_STREAM_URGENT_INLINE;
643
0
        } else if (strcmp(temp_urgpol, "drop") == 0) {
644
0
            stream_config.urgent_policy = TCP_STREAM_URGENT_DROP;
645
0
        } else if (strcmp(temp_urgpol, "oob") == 0) {
646
0
            stream_config.urgent_policy = TCP_STREAM_URGENT_OOB;
647
0
        } else if (strcmp(temp_urgpol, "gap") == 0) {
648
0
            stream_config.urgent_policy = TCP_STREAM_URGENT_GAP;
649
0
        } else {
650
0
            FatalError("stream.reassembly.urgent.policy: invalid value '%s'", temp_urgpol);
651
0
        }
652
78
    } else {
653
78
        stream_config.urgent_policy = TCP_STREAM_URGENT_DEFAULT;
654
78
    }
655
78
    if (!quiet) {
656
78
        SCLogConfig("stream.reassembly.urgent.policy\": %s", UrgentPolicyToString(stream_config.urgent_policy));
657
78
    }
658
78
    if (stream_config.urgent_policy == TCP_STREAM_URGENT_OOB) {
659
0
        const char *temp_urgoobpol = NULL;
660
0
        if (SCConfGet("stream.reassembly.urgent.oob-limit-policy", &temp_urgoobpol) == 1 &&
661
0
                temp_urgoobpol != NULL) {
662
0
            if (strcmp(temp_urgoobpol, "inline") == 0) {
663
0
                stream_config.urgent_oob_limit_policy = TCP_STREAM_URGENT_INLINE;
664
0
            } else if (strcmp(temp_urgoobpol, "drop") == 0) {
665
0
                stream_config.urgent_oob_limit_policy = TCP_STREAM_URGENT_DROP;
666
0
            } else if (strcmp(temp_urgoobpol, "gap") == 0) {
667
0
                stream_config.urgent_oob_limit_policy = TCP_STREAM_URGENT_GAP;
668
0
            } else {
669
0
                FatalError("stream.reassembly.urgent.oob-limit-policy: invalid value '%s'", temp_urgoobpol);
670
0
            }
671
0
        } else {
672
0
            stream_config.urgent_oob_limit_policy = TCP_STREAM_URGENT_DEFAULT;
673
0
        }
674
0
        if (!quiet) {
675
0
            SCLogConfig("stream.reassembly.urgent.oob-limit-policy\": %s", UrgentPolicyToString(stream_config.urgent_oob_limit_policy));
676
0
        }
677
0
    }
678
679
78
    if ((SCConfGetInt("stream.max-syn-queued", &value)) == 1) {
680
0
        if (value >= 0 && value <= 255) {
681
0
            stream_config.max_syn_queued = (uint8_t)value;
682
0
        } else {
683
0
            stream_config.max_syn_queued = (uint8_t)STREAMTCP_DEFAULT_MAX_SYN_QUEUED;
684
0
        }
685
78
    } else {
686
78
        stream_config.max_syn_queued = (uint8_t)STREAMTCP_DEFAULT_MAX_SYN_QUEUED;
687
78
    }
688
78
    if (!quiet) {
689
78
        SCLogConfig("stream \"max-syn-queued\": %" PRIu8, stream_config.max_syn_queued);
690
78
    }
691
692
78
    if ((SCConfGetInt("stream.max-synack-queued", &value)) == 1) {
693
0
        if (value >= 0 && value <= 255) {
694
0
            stream_config.max_synack_queued = (uint8_t)value;
695
0
        } else {
696
0
            stream_config.max_synack_queued = (uint8_t)STREAMTCP_DEFAULT_MAX_SYNACK_QUEUED;
697
0
        }
698
78
    } else {
699
78
        stream_config.max_synack_queued = (uint8_t)STREAMTCP_DEFAULT_MAX_SYNACK_QUEUED;
700
78
    }
701
78
    if (!quiet) {
702
78
        SCLogConfig("stream \"max-synack-queued\": %"PRIu8, stream_config.max_synack_queued);
703
78
    }
704
705
78
    const char *temp_stream_reassembly_memcap_str;
706
78
    if (SCConfGetNonNull("stream.reassembly.memcap", &temp_stream_reassembly_memcap_str) == 1) {
707
0
        uint64_t stream_reassembly_memcap_copy;
708
0
        if (ParseSizeStringU64(temp_stream_reassembly_memcap_str,
709
0
                               &stream_reassembly_memcap_copy) < 0) {
710
0
            SCLogError("Error parsing "
711
0
                       "stream.reassembly.memcap "
712
0
                       "from conf file - %s.  Killing engine",
713
0
                    temp_stream_reassembly_memcap_str);
714
0
            exit(EXIT_FAILURE);
715
0
        } else {
716
0
            SC_ATOMIC_SET(stream_config.reassembly_memcap, stream_reassembly_memcap_copy);
717
0
        }
718
78
    } else {
719
78
        SC_ATOMIC_SET(stream_config.reassembly_memcap , STREAMTCP_DEFAULT_REASSEMBLY_MEMCAP);
720
78
    }
721
722
78
    if (!quiet) {
723
78
        SCLogConfig("stream.reassembly \"memcap\": %"PRIu64"",
724
78
                    SC_ATOMIC_GET(stream_config.reassembly_memcap));
725
78
    }
726
727
78
    const char *temp_stream_reassembly_depth_str;
728
78
    if (SCConfGetNonNull("stream.reassembly.depth", &temp_stream_reassembly_depth_str) == 1) {
729
38
        if (ParseSizeStringU32(temp_stream_reassembly_depth_str,
730
38
                               &stream_config.reassembly_depth) < 0) {
731
0
            SCLogError("Error parsing "
732
0
                       "stream.reassembly.depth "
733
0
                       "from conf file - %s.  Killing engine",
734
0
                    temp_stream_reassembly_depth_str);
735
0
            exit(EXIT_FAILURE);
736
0
        }
737
40
    } else {
738
40
        SCLogNotice("stream.reassembly.depth set to unlimited by default");
739
40
        stream_config.reassembly_depth = 0;
740
40
    }
741
742
78
    if (!quiet) {
743
78
        SCLogConfig("stream.reassembly \"depth\": %"PRIu32"", stream_config.reassembly_depth);
744
78
    }
745
746
78
    int randomize = 0;
747
78
    if ((SCConfGetBool("stream.reassembly.randomize-chunk-size", &randomize)) == 0) {
748
        /* randomize by default if value not set
749
         * In ut mode we disable, to get predictable test results */
750
78
        if (!(RunmodeIsUnittests()))
751
78
            randomize = 1;
752
78
    }
753
754
78
    if (randomize) {
755
78
        const char *temp_rdrange;
756
78
        if (SCConfGetNonNull("stream.reassembly.randomize-chunk-range", &temp_rdrange) == 1) {
757
0
            if (ParseSizeStringU16(temp_rdrange, &rdrange) < 0) {
758
0
                SCLogError("Error parsing "
759
0
                           "stream.reassembly.randomize-chunk-range "
760
0
                           "from conf file - %s.  Killing engine",
761
0
                        temp_rdrange);
762
0
                exit(EXIT_FAILURE);
763
0
            } else if (rdrange >= 100) {
764
0
                FatalError("stream.reassembly.randomize-chunk-range "
765
0
                           "must be lower than 100");
766
0
            }
767
0
        }
768
78
    }
769
770
78
    const char *temp_stream_reassembly_toserver_chunk_size_str;
771
78
    if (SCConfGetNonNull("stream.reassembly.toserver-chunk-size",
772
78
                &temp_stream_reassembly_toserver_chunk_size_str) == 1) {
773
0
        if (ParseSizeStringU16(temp_stream_reassembly_toserver_chunk_size_str,
774
0
                               &stream_config.reassembly_toserver_chunk_size) < 0) {
775
0
            SCLogError("Error parsing "
776
0
                       "stream.reassembly.toserver-chunk-size "
777
0
                       "from conf file - %s.  Killing engine",
778
0
                    temp_stream_reassembly_toserver_chunk_size_str);
779
0
            exit(EXIT_FAILURE);
780
0
        }
781
78
    } else {
782
78
        stream_config.reassembly_toserver_chunk_size =
783
78
            STREAMTCP_DEFAULT_TOSERVER_CHUNK_SIZE;
784
78
    }
785
786
78
    if (randomize) {
787
78
        long int r = RandomGetWrap();
788
78
        stream_config.reassembly_toserver_chunk_size +=
789
78
                (int)(stream_config.reassembly_toserver_chunk_size * ((double)r / RAND_MAX - 0.5) *
790
78
                        rdrange / 100);
791
78
    }
792
78
    const char *temp_stream_reassembly_toclient_chunk_size_str;
793
78
    if (SCConfGetNonNull("stream.reassembly.toclient-chunk-size",
794
78
                &temp_stream_reassembly_toclient_chunk_size_str) == 1) {
795
0
        if (ParseSizeStringU16(temp_stream_reassembly_toclient_chunk_size_str,
796
0
                               &stream_config.reassembly_toclient_chunk_size) < 0) {
797
0
            SCLogError("Error parsing "
798
0
                       "stream.reassembly.toclient-chunk-size "
799
0
                       "from conf file - %s.  Killing engine",
800
0
                    temp_stream_reassembly_toclient_chunk_size_str);
801
0
            exit(EXIT_FAILURE);
802
0
        }
803
78
    } else {
804
78
        stream_config.reassembly_toclient_chunk_size =
805
78
            STREAMTCP_DEFAULT_TOCLIENT_CHUNK_SIZE;
806
78
    }
807
808
78
    if (randomize) {
809
78
        long int r = RandomGetWrap();
810
78
        stream_config.reassembly_toclient_chunk_size +=
811
78
                (int)(stream_config.reassembly_toclient_chunk_size * ((double)r / RAND_MAX - 0.5) *
812
78
                        rdrange / 100);
813
78
    }
814
78
    if (!quiet) {
815
78
        SCLogConfig("stream.reassembly \"toserver-chunk-size\": %"PRIu16,
816
78
            stream_config.reassembly_toserver_chunk_size);
817
78
        SCLogConfig("stream.reassembly \"toclient-chunk-size\": %"PRIu16,
818
78
            stream_config.reassembly_toclient_chunk_size);
819
78
    }
820
821
78
    int enable_raw = 1;
822
78
    if (SCConfGetBool("stream.reassembly.raw", &enable_raw) == 1) {
823
0
        if (!enable_raw) {
824
0
            stream_config.stream_init_flags = STREAMTCP_STREAM_FLAG_DISABLE_RAW;
825
0
        }
826
78
    } else {
827
78
        enable_raw = 1;
828
78
    }
829
78
    if (!quiet)
830
78
        SCLogConfig("stream.reassembly.raw: %s", enable_raw ? "enabled" : "disabled");
831
832
    /* default to true. Not many ppl (correctly) set up host-os policies, so be permissive. */
833
78
    stream_config.liberal_timestamps = true;
834
78
    int liberal_timestamps = 0;
835
78
    if (SCConfGetBool("stream.liberal-timestamps", &liberal_timestamps) == 1) {
836
0
        stream_config.liberal_timestamps = liberal_timestamps;
837
0
    }
838
78
    if (!quiet)
839
78
        SCLogConfig("stream.liberal-timestamps: %s", liberal_timestamps ? "enabled" : "disabled");
840
841
    /* init the memcap/use tracking */
842
78
    StreamTcpInitMemuse();
843
78
    StatsRegisterGlobalCounter("tcp.memuse", StreamTcpMemuseCounter);
844
845
78
    StreamTcpReassembleInit(quiet);
846
847
    /* set the default free function and flow state function
848
     * values. */
849
78
    FlowSetProtoFreeFunc(IPPROTO_TCP, StreamTcpSessionClear);
850
851
#ifdef UNITTESTS
852
    if (RunmodeIsUnittests()) {
853
        SCMutexLock(&ssn_pool_mutex);
854
        if (ssn_pool == NULL) {
855
            ssn_pool = PoolThreadInit(1, /* thread */
856
                    0, /* unlimited */
857
                    stream_config.prealloc_sessions,
858
                    sizeof(TcpSession),
859
                    StreamTcpSessionPoolAlloc,
860
                    StreamTcpSessionPoolInit, NULL,
861
                    StreamTcpSessionPoolCleanup, NULL);
862
        }
863
        SCMutexUnlock(&ssn_pool_mutex);
864
    }
865
#endif
866
78
}
867
868
void StreamTcpFreeConfig(bool quiet)
869
0
{
870
0
    StreamTcpReassembleFree(quiet);
871
872
0
    SCMutexLock(&ssn_pool_mutex);
873
0
    if (ssn_pool != NULL) {
874
0
        PoolThreadFree(ssn_pool);
875
0
        ssn_pool = NULL;
876
0
    }
877
0
    SCMutexUnlock(&ssn_pool_mutex);
878
0
    SCMutexDestroy(&ssn_pool_mutex);
879
880
0
    SCLogDebug("ssn_pool_cnt %"PRIu64"", ssn_pool_cnt);
881
0
}
882
883
static bool IsReassemblyMemcapExceptionPolicyStatsValid(enum ExceptionPolicy exception_policy)
884
0
{
885
0
    if (EngineModeIsIPS()) {
886
0
        return stream_reassembly_memcap_eps_stats.valid_settings_ips[exception_policy];
887
0
    }
888
0
    return stream_reassembly_memcap_eps_stats.valid_settings_ids[exception_policy];
889
0
}
890
891
static bool IsStreamTcpSessionMemcapExceptionPolicyStatsValid(enum ExceptionPolicy policy)
892
0
{
893
0
    if (EngineModeIsIPS()) {
894
0
        return stream_memcap_eps_stats.valid_settings_ips[policy];
895
0
    }
896
0
    return stream_memcap_eps_stats.valid_settings_ids[policy];
897
0
}
898
899
static void StreamTcpSsnMemcapExceptionPolicyStatsIncr(
900
        ThreadVars *tv, StreamTcpThread *stt, enum ExceptionPolicy policy)
901
0
{
902
0
    const uint16_t id = stt->counter_tcp_ssn_memcap_eps.eps_id[policy];
903
0
    if (likely(tv && id > 0)) {
904
0
        StatsIncr(tv, id);
905
0
    }
906
0
}
907
908
enum ExceptionPolicy StreamTcpSsnMemcapGetExceptionPolicy(void)
909
0
{
910
0
    return stream_config.ssn_memcap_policy;
911
0
}
912
913
enum ExceptionPolicy StreamTcpReassemblyMemcapGetExceptionPolicy(void)
914
13
{
915
13
    return stream_config.reassembly_memcap_policy;
916
13
}
917
918
enum ExceptionPolicy StreamMidstreamGetExceptionPolicy(void)
919
132k
{
920
132k
    return stream_config.midstream_policy;
921
132k
}
922
923
/** \internal
924
 *  \brief The function is used to fetch a TCP session from the
925
 *         ssn_pool, when a TCP SYN is received.
926
 *
927
 *  \param p packet starting the new TCP session.
928
 *  \param id thread pool id
929
 *
930
 *  \retval ssn new TCP session.
931
 */
932
static TcpSession *StreamTcpNewSession(ThreadVars *tv, StreamTcpThread *stt, Packet *p, int id)
933
280k
{
934
280k
    TcpSession *ssn = (TcpSession *)p->flow->protoctx;
935
936
280k
    if (ssn == NULL) {
937
280k
        DEBUG_VALIDATE_BUG_ON(id < 0 || id > UINT16_MAX);
938
280k
        p->flow->protoctx = StreamTcpThreadCacheGetSession();
939
280k
        if (p->flow->protoctx != NULL) {
940
#ifdef UNITTESTS
941
            if (tv)
942
#endif
943
279k
                StatsIncr(tv, stt->counter_tcp_ssn_from_cache);
944
279k
        } else {
945
1.40k
            p->flow->protoctx = PoolThreadGetById(ssn_pool, (uint16_t)id);
946
1.40k
            if (p->flow->protoctx != NULL)
947
#ifdef UNITTESTS
948
                if (tv)
949
#endif
950
1.40k
                    StatsIncr(tv, stt->counter_tcp_ssn_from_pool);
951
1.40k
        }
952
#if defined(DEBUG) || defined(QA_SIMULATION)
953
        SCMutexLock(&ssn_pool_mutex);
954
        if (p->flow->protoctx != NULL)
955
            ssn_pool_cnt++;
956
        SCMutexUnlock(&ssn_pool_mutex);
957
#ifdef QA_SIMULATION
958
        if (unlikely((g_eps_stream_ssn_memcap != UINT64_MAX &&
959
                      g_eps_stream_ssn_memcap == t_pcapcnt))) {
960
            SCLogNotice("simulating memcap reached condition for packet %" PRIu64, t_pcapcnt);
961
            ExceptionPolicyApply(p, stream_config.ssn_memcap_policy, PKT_DROP_REASON_STREAM_MEMCAP);
962
            StreamTcpSsnMemcapExceptionPolicyStatsIncr(tv, stt, stream_config.ssn_memcap_policy);
963
            return NULL;
964
        }
965
#endif
966
#endif
967
280k
        ssn = (TcpSession *)p->flow->protoctx;
968
280k
        if (ssn == NULL) {
969
0
            SCLogDebug("ssn_pool is empty");
970
0
            ExceptionPolicyApply(p, stream_config.ssn_memcap_policy, PKT_DROP_REASON_STREAM_MEMCAP);
971
0
            StreamTcpSsnMemcapExceptionPolicyStatsIncr(tv, stt, stream_config.ssn_memcap_policy);
972
0
            return NULL;
973
0
        }
974
975
280k
        const TCPHdr *tcph = PacketGetTCP(p);
976
280k
        ssn->state = TCP_NONE;
977
280k
        ssn->reassembly_depth = stream_config.reassembly_depth;
978
280k
        ssn->tcp_packet_flags = tcph->th_flags;
979
280k
        ssn->server.flags = stream_config.stream_init_flags;
980
280k
        ssn->client.flags = stream_config.stream_init_flags;
981
982
280k
        StreamingBuffer x = STREAMING_BUFFER_INITIALIZER;
983
280k
        ssn->client.sb = x;
984
280k
        ssn->server.sb = x;
985
986
280k
        if (PKT_IS_TOSERVER(p)) {
987
277k
            ssn->client.tcp_flags = tcph->th_flags;
988
277k
            ssn->server.tcp_flags = 0;
989
277k
        } else if (PKT_IS_TOCLIENT(p)) {
990
3.00k
            ssn->server.tcp_flags = tcph->th_flags;
991
3.00k
            ssn->client.tcp_flags = 0;
992
3.00k
        }
993
280k
    }
994
995
280k
    return ssn;
996
280k
}
997
998
static void StreamTcpPacketSetState(Packet *p, TcpSession *ssn,
999
                                           uint8_t state)
1000
637k
{
1001
637k
    if (state == ssn->state || PKT_IS_PSEUDOPKT(p))
1002
20
        return;
1003
1004
637k
    ssn->pstate = ssn->state;
1005
637k
    ssn->state = state;
1006
637k
    STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_STATE_UPDATE);
1007
1008
    /* update the flow state */
1009
637k
    switch(ssn->state) {
1010
206k
        case TCP_ESTABLISHED:
1011
259k
        case TCP_FIN_WAIT1:
1012
270k
        case TCP_FIN_WAIT2:
1013
275k
        case TCP_CLOSING:
1014
326k
        case TCP_CLOSE_WAIT:
1015
326k
            FlowUpdateState(p->flow, FLOW_STATE_ESTABLISHED);
1016
326k
            break;
1017
11.7k
        case TCP_LAST_ACK:
1018
22.1k
        case TCP_TIME_WAIT:
1019
85.9k
        case TCP_CLOSED:
1020
85.9k
            FlowUpdateState(p->flow, FLOW_STATE_CLOSED);
1021
85.9k
            break;
1022
637k
    }
1023
637k
}
1024
1025
/**
1026
 *  \brief  Function to set the OS policy for the given stream based on the
1027
 *          destination of the received packet.
1028
 *
1029
 *  \param  stream  TcpStream of which os_policy needs to set
1030
 *  \param  p       Packet which is used to set the os policy
1031
 */
1032
void StreamTcpSetOSPolicy(TcpStream *stream, Packet *p)
1033
381k
{
1034
381k
    if (PacketIsIPv4(p)) {
1035
        /* Get the OS policy based on destination IP address, as destination
1036
           OS will decide how to react on the anomalies of newly received
1037
           packets */
1038
332k
        int ret = SCHInfoGetIPv4HostOSFlavour((uint8_t *)GET_IPV4_DST_ADDR_PTR(p));
1039
332k
        if (ret > 0)
1040
0
            stream->os_policy = (uint8_t)ret;
1041
332k
        else
1042
332k
            stream->os_policy = OS_POLICY_DEFAULT;
1043
1044
332k
    } else if (PacketIsIPv6(p)) {
1045
        /* Get the OS policy based on destination IP address, as destination
1046
           OS will decide how to react on the anomalies of newly received
1047
           packets */
1048
49.2k
        int ret = SCHInfoGetIPv6HostOSFlavour((uint8_t *)GET_IPV6_DST_ADDR(p));
1049
49.2k
        if (ret > 0)
1050
0
            stream->os_policy = (uint8_t)ret;
1051
49.2k
        else
1052
49.2k
            stream->os_policy = OS_POLICY_DEFAULT;
1053
49.2k
    }
1054
1055
381k
    if (stream->os_policy == OS_POLICY_BSD_RIGHT)
1056
0
        stream->os_policy = OS_POLICY_BSD;
1057
381k
    else if (stream->os_policy == OS_POLICY_OLD_SOLARIS)
1058
0
        stream->os_policy = OS_POLICY_SOLARIS;
1059
1060
381k
    SCLogDebug("Policy is %" PRIu8 "", stream->os_policy);
1061
381k
}
1062
1063
/**
1064
 *  \brief macro to update last_ack only if the new value is higher
1065
 *
1066
 *  \param ssn session
1067
 *  \param stream stream to update
1068
 *  \param ack ACK value to test and set
1069
 */
1070
#define StreamTcpUpdateLastAck(ssn, stream, ack)                                                   \
1071
6.71M
    {                                                                                              \
1072
6.71M
        if (SEQ_GT((ack), (stream)->last_ack) && SEQ_GT(ack, (stream)->base_seq)) {                \
1073
3.03M
            SCLogDebug("ssn %p: last_ack set to %" PRIu32 ", moved %u forward", (ssn), (ack),      \
1074
3.03M
                    (ack) - (stream)->last_ack);                                                   \
1075
3.03M
            if ((SEQ_LEQ((stream)->last_ack, (stream)->next_seq) &&                                \
1076
3.03M
                        SEQ_GT((ack), (stream)->next_seq))) {                                      \
1077
58.0k
                SCLogDebug("last_ack just passed next_seq: %u (was %u) > %u", (ack),               \
1078
58.0k
                        (stream)->last_ack, (stream)->next_seq);                                   \
1079
2.97M
            } else {                                                                               \
1080
2.97M
                SCLogDebug("next_seq (%u) <> last_ack now %d", (stream)->next_seq,                 \
1081
2.97M
                        (int)(stream)->next_seq - (ack));                                          \
1082
2.97M
            }                                                                                      \
1083
3.03M
            (stream)->last_ack = (ack);                                                            \
1084
3.03M
            StreamTcpSackPruneList((stream));                                                      \
1085
3.67M
        } else {                                                                                   \
1086
3.67M
            SCLogDebug("ssn %p: no update: ack %u, last_ack %" PRIu32 ", next_seq %u (state %u)",  \
1087
3.67M
                    (ssn), (ack), (stream)->last_ack, (stream)->next_seq, (ssn)->state);           \
1088
3.67M
        }                                                                                          \
1089
6.71M
    }
1090
1091
6.07M
#define StreamTcpAsyncLastAckUpdate(ssn, stream) {                              \
1092
6.07M
    if ((ssn)->flags & STREAMTCP_FLAG_ASYNC) {                                  \
1093
0
        if (SEQ_GT((stream)->next_seq, (stream)->last_ack)) {                   \
1094
0
            uint32_t ack_diff = (stream)->next_seq - (stream)->last_ack;        \
1095
0
            (stream)->last_ack += ack_diff;                                     \
1096
0
            SCLogDebug("ssn %p: ASYNC last_ack set to %"PRIu32", moved %u forward",     \
1097
0
                    (ssn), (stream)->next_seq, ack_diff);                               \
1098
0
        }                                                                       \
1099
0
    }                                                                           \
1100
6.07M
}
1101
1102
6.07M
#define StreamTcpUpdateNextSeq(ssn, stream, seq) {                      \
1103
6.07M
    (stream)->next_seq = seq;                                           \
1104
6.07M
    SCLogDebug("ssn %p: next_seq %" PRIu32, (ssn), (stream)->next_seq); \
1105
6.07M
    StreamTcpAsyncLastAckUpdate((ssn), (stream));                       \
1106
6.07M
}
1107
1108
/**
1109
 *  \brief macro to update next_win only if the new value is higher
1110
 *
1111
 *  \param ssn session
1112
 *  \param stream stream to update
1113
 *  \param win window value to test and set
1114
 */
1115
6.18M
#define StreamTcpUpdateNextWin(ssn, stream, win) { \
1116
6.18M
    uint32_t sacked_size__ = StreamTcpSackedSize((stream)); \
1117
6.18M
    if (SEQ_GT(((win) + sacked_size__), (stream)->next_win)) { \
1118
2.51M
        (stream)->next_win = ((win) + sacked_size__); \
1119
2.51M
        SCLogDebug("ssn %p: next_win set to %"PRIu32, (ssn), (stream)->next_win); \
1120
2.51M
    } \
1121
6.18M
}
1122
1123
static inline void StreamTcpCloseSsnWithReset(Packet *p, TcpSession *ssn)
1124
52.0k
{
1125
52.0k
    ssn->flags |= STREAMTCP_FLAG_CLOSED_BY_RST;
1126
52.0k
    StreamTcpPacketSetState(p, ssn, TCP_CLOSED);
1127
52.0k
    SCLogDebug("ssn %p: (state: %s) Reset received and state changed to "
1128
52.0k
            "TCP_CLOSED", ssn, StreamTcpStateAsString(ssn->state));
1129
52.0k
}
1130
1131
static bool IsMidstreamExceptionPolicyStatsValid(enum ExceptionPolicy policy)
1132
0
{
1133
0
    if (EngineModeIsIPS()) {
1134
0
        if (stream_config.midstream) {
1135
0
            return stream_midstream_enabled_eps_stats.valid_settings_ips[policy];
1136
0
        }
1137
0
        return stream_midstream_disabled_eps_stats.valid_settings_ips[policy];
1138
0
    }
1139
0
    if (stream_config.midstream) {
1140
0
        return stream_midstream_enabled_eps_stats.valid_settings_ids[policy];
1141
0
    }
1142
0
    return stream_midstream_disabled_eps_stats.valid_settings_ids[policy];
1143
0
}
1144
1145
static void StreamTcpMidstreamExceptionPolicyStatsIncr(
1146
        ThreadVars *tv, StreamTcpThread *stt, enum ExceptionPolicy policy)
1147
224k
{
1148
224k
    const uint16_t id = stt->counter_tcp_midstream_eps.eps_id[policy];
1149
224k
    if (likely(tv && id > 0)) {
1150
0
        StatsIncr(tv, id);
1151
0
    }
1152
224k
}
1153
1154
static int StreamTcpPacketIsRetransmission(TcpStream *stream, Packet *p)
1155
1.03M
{
1156
1.03M
    if (p->payload_len == 0)
1157
412k
        SCReturnInt(0);
1158
1159
621k
    const TCPHdr *tcph = PacketGetTCP(p);
1160
621k
    const uint32_t seq = TCP_GET_RAW_SEQ(tcph);
1161
    /* retransmission of already partially ack'd data */
1162
621k
    if (SEQ_LT(seq, stream->last_ack) && SEQ_GT((seq + p->payload_len), stream->last_ack)) {
1163
7.63k
        StreamTcpSetEvent(p, STREAM_PKT_RETRANSMISSION);
1164
7.63k
        SCReturnInt(1);
1165
7.63k
    }
1166
1167
    /* retransmission of already ack'd data */
1168
614k
    if (SEQ_LEQ((seq + p->payload_len), stream->last_ack)) {
1169
256k
        StreamTcpSetEvent(p, STREAM_PKT_RETRANSMISSION);
1170
256k
        SCReturnInt(1);
1171
256k
    }
1172
1173
    /* retransmission of in flight data */
1174
357k
    if (SEQ_LEQ((seq + p->payload_len), stream->next_seq)) {
1175
151k
        StreamTcpSetEvent(p, STREAM_PKT_RETRANSMISSION);
1176
151k
        SCReturnInt(2);
1177
151k
    }
1178
1179
206k
    SCLogDebug("seq %u payload_len %u => %u, last_ack %u, next_seq %u", seq, p->payload_len,
1180
206k
            (seq + p->payload_len), stream->last_ack, stream->next_seq);
1181
206k
    SCReturnInt(0);
1182
357k
}
1183
1184
/**
1185
 *  \internal
1186
 *  \brief  Function to handle the TCP_CLOSED or NONE state. The function handles
1187
 *          packets while the session state is None which means a newly
1188
 *          initialized structure, or a fully closed session.
1189
 *
1190
 *  \param  tv      Thread Variable containing  input/output queue, cpu affinity
1191
 *  \param  p       Packet which has to be handled in this TCP state.
1192
 *  \param  stt     Stream Thread module registered to handle the stream handling
1193
 *
1194
 *  \retval 0 ok
1195
 *  \retval -1 error
1196
 */
1197
static int StreamTcpPacketStateNone(
1198
        ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn)
1199
376k
{
1200
376k
    const TCPHdr *tcph = PacketGetTCP(p);
1201
376k
    if (tcph->th_flags & TH_RST) {
1202
47.7k
        StreamTcpSetEvent(p, STREAM_RST_BUT_NO_SESSION);
1203
47.7k
        SCLogDebug("RST packet received, no session setup");
1204
47.7k
        return -1;
1205
1206
329k
    } else if (tcph->th_flags & TH_FIN) {
1207
        /* Drop reason will only be used if midstream policy is set to fail closed */
1208
46.4k
        ExceptionPolicyApply(p, stream_config.midstream_policy, PKT_DROP_REASON_STREAM_MIDSTREAM);
1209
46.4k
        StreamTcpMidstreamExceptionPolicyStatsIncr(tv, stt, stream_config.midstream_policy);
1210
1211
46.4k
        if (!stream_config.midstream || p->payload_len == 0) {
1212
31.1k
            StreamTcpSetEvent(p, STREAM_FIN_BUT_NO_SESSION);
1213
31.1k
            SCLogDebug("FIN packet received, no session setup");
1214
31.1k
            return -1;
1215
31.1k
        }
1216
15.2k
        if (!(stream_config.midstream_policy == EXCEPTION_POLICY_NOT_SET ||
1217
0
                    stream_config.midstream_policy == EXCEPTION_POLICY_PASS_FLOW)) {
1218
0
            StreamTcpSetEvent(p, STREAM_FIN_BUT_NO_SESSION);
1219
0
            SCLogDebug("FIN packet received, no session setup");
1220
0
            return -1;
1221
0
        }
1222
15.2k
        SCLogDebug("midstream picked up");
1223
1224
15.2k
        if (ssn == NULL) {
1225
15.2k
            ssn = StreamTcpNewSession(tv, stt, p, stt->ssn_pool_id);
1226
15.2k
            if (ssn == NULL) {
1227
0
                StatsIncr(tv, stt->counter_tcp_ssn_memcap);
1228
0
                return -1;
1229
0
            }
1230
15.2k
            StatsIncr(tv, stt->counter_tcp_sessions);
1231
15.2k
            StatsIncr(tv, stt->counter_tcp_active_sessions);
1232
15.2k
            StatsIncr(tv, stt->counter_tcp_midstream_pickups);
1233
15.2k
        }
1234
        /* set the state */
1235
15.2k
        StreamTcpPacketSetState(p, ssn, TCP_FIN_WAIT1);
1236
15.2k
        SCLogDebug("ssn %p: =~ midstream picked ssn state is now "
1237
15.2k
                   "TCP_FIN_WAIT1",
1238
15.2k
                ssn);
1239
1240
15.2k
        ssn->flags = STREAMTCP_FLAG_MIDSTREAM;
1241
15.2k
        ssn->flags |= STREAMTCP_FLAG_MIDSTREAM_ESTABLISHED;
1242
15.2k
        if (stream_config.async_oneside) {
1243
0
            SCLogDebug("ssn %p: =~ ASYNC", ssn);
1244
0
            ssn->flags |= STREAMTCP_FLAG_ASYNC;
1245
0
        }
1246
1247
        /** window scaling for midstream pickups, we can't do much other
1248
         *  than assume that it's set to the max value: 14 */
1249
15.2k
        ssn->client.wscale = TCP_WSCALE_MAX;
1250
15.2k
        ssn->server.wscale = TCP_WSCALE_MAX;
1251
1252
        /* set the sequence numbers and window */
1253
15.2k
        ssn->client.isn = TCP_GET_RAW_SEQ(tcph) - 1;
1254
15.2k
        STREAMTCP_SET_RA_BASE_SEQ(&ssn->client, ssn->client.isn);
1255
15.2k
        ssn->client.next_seq = TCP_GET_RAW_SEQ(tcph) + p->payload_len + 1;
1256
15.2k
        ssn->client.window = TCP_GET_RAW_WINDOW(tcph) << ssn->client.wscale;
1257
15.2k
        ssn->client.last_ack = TCP_GET_RAW_SEQ(tcph);
1258
15.2k
        ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
1259
15.2k
        SCLogDebug("ssn %p: ssn->client.isn %u, ssn->client.next_seq %u", ssn, ssn->client.isn,
1260
15.2k
                ssn->client.next_seq);
1261
1262
15.2k
        ssn->server.isn = TCP_GET_RAW_ACK(tcph) - 1;
1263
15.2k
        STREAMTCP_SET_RA_BASE_SEQ(&ssn->server, ssn->server.isn);
1264
15.2k
        ssn->server.next_seq = ssn->server.isn + 1;
1265
15.2k
        ssn->server.last_ack = TCP_GET_RAW_ACK(tcph);
1266
15.2k
        ssn->server.next_win = ssn->server.last_ack;
1267
1268
15.2k
        SCLogDebug("ssn %p: ssn->client.next_win %" PRIu32 ", "
1269
15.2k
                   "ssn->server.next_win %" PRIu32 "",
1270
15.2k
                ssn, ssn->client.next_win, ssn->server.next_win);
1271
15.2k
        SCLogDebug("ssn %p: ssn->client.last_ack %" PRIu32 ", "
1272
15.2k
                   "ssn->server.last_ack %" PRIu32 "",
1273
15.2k
                ssn, ssn->client.last_ack, ssn->server.last_ack);
1274
1275
        /* Set the timestamp value for both streams, if packet has timestamp
1276
         * option enabled.*/
1277
15.2k
        if (TCP_HAS_TS(p)) {
1278
748
            ssn->client.last_ts = TCP_GET_TSVAL(p);
1279
748
            ssn->server.last_ts = TCP_GET_TSECR(p);
1280
748
            SCLogDebug("ssn %p: ssn->server.last_ts %" PRIu32 " "
1281
748
                       "ssn->client.last_ts %" PRIu32 "",
1282
748
                    ssn, ssn->server.last_ts, ssn->client.last_ts);
1283
1284
748
            ssn->flags |= STREAMTCP_FLAG_TIMESTAMP;
1285
1286
748
            ssn->client.last_pkt_ts = (uint32_t)SCTIME_SECS(p->ts);
1287
748
            if (ssn->server.last_ts == 0)
1288
52
                ssn->server.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
1289
748
            if (ssn->client.last_ts == 0)
1290
30
                ssn->client.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
1291
1292
14.5k
        } else {
1293
14.5k
            ssn->server.last_ts = 0;
1294
14.5k
            ssn->client.last_ts = 0;
1295
14.5k
        }
1296
1297
15.2k
        StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
1298
1299
15.2k
        ssn->flags |= STREAMTCP_FLAG_SACKOK;
1300
15.2k
        SCLogDebug("ssn %p: assuming SACK permitted for both sides", ssn);
1301
1302
        /* SYN/ACK */
1303
282k
    } else if ((tcph->th_flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK)) {
1304
        /* Drop reason will only be used if midstream policy is set to fail closed */
1305
68.4k
        ExceptionPolicyApply(p, stream_config.midstream_policy, PKT_DROP_REASON_STREAM_MIDSTREAM);
1306
68.4k
        StreamTcpMidstreamExceptionPolicyStatsIncr(tv, stt, stream_config.midstream_policy);
1307
1308
68.4k
        if (!stream_config.midstream && !stream_config.async_oneside) {
1309
0
            SCLogDebug("Midstream not enabled, so won't pick up a session");
1310
0
            return 0;
1311
0
        }
1312
68.4k
        if (!(stream_config.midstream_policy == EXCEPTION_POLICY_NOT_SET ||
1313
0
                    stream_config.midstream_policy == EXCEPTION_POLICY_PASS_FLOW)) {
1314
0
            SCLogDebug("Midstream policy not permissive, so won't pick up a session");
1315
0
            return 0;
1316
0
        }
1317
68.4k
        SCLogDebug("midstream picked up");
1318
1319
68.4k
        if (ssn == NULL) {
1320
68.4k
            ssn = StreamTcpNewSession(tv, stt, p, stt->ssn_pool_id);
1321
68.4k
            if (ssn == NULL) {
1322
0
                StatsIncr(tv, stt->counter_tcp_ssn_memcap);
1323
0
                return -1;
1324
0
            }
1325
68.4k
            StatsIncr(tv, stt->counter_tcp_sessions);
1326
68.4k
            StatsIncr(tv, stt->counter_tcp_active_sessions);
1327
68.4k
            StatsIncr(tv, stt->counter_tcp_midstream_pickups);
1328
68.4k
        }
1329
1330
        /* reverse packet and flow */
1331
68.4k
        SCLogDebug("reversing flow and packet");
1332
68.4k
        PacketSwap(p);
1333
68.4k
        FlowSwap(p->flow);
1334
1335
        /* set the state */
1336
68.4k
        StreamTcpPacketSetState(p, ssn, TCP_SYN_RECV);
1337
68.4k
        SCLogDebug("ssn %p: =~ midstream picked ssn state is now "
1338
68.4k
                "TCP_SYN_RECV", ssn);
1339
68.4k
        ssn->flags |= STREAMTCP_FLAG_MIDSTREAM;
1340
        /* Flag used to change the direct in the later stage in the session */
1341
68.4k
        ssn->flags |= STREAMTCP_FLAG_MIDSTREAM_SYNACK;
1342
68.4k
        if (stream_config.async_oneside) {
1343
0
            SCLogDebug("ssn %p: =~ ASYNC", ssn);
1344
0
            ssn->flags |= STREAMTCP_FLAG_ASYNC;
1345
0
        }
1346
1347
        /* sequence number & window */
1348
68.4k
        ssn->server.isn = TCP_GET_RAW_SEQ(tcph);
1349
68.4k
        STREAMTCP_SET_RA_BASE_SEQ(&ssn->server, ssn->server.isn);
1350
68.4k
        ssn->server.next_seq = ssn->server.isn + 1;
1351
68.4k
        ssn->server.window = TCP_GET_RAW_WINDOW(tcph);
1352
68.4k
        SCLogDebug("ssn %p: server window %u", ssn, ssn->server.window);
1353
1354
68.4k
        ssn->client.isn = TCP_GET_RAW_ACK(tcph) - 1;
1355
68.4k
        STREAMTCP_SET_RA_BASE_SEQ(&ssn->client, ssn->client.isn);
1356
68.4k
        ssn->client.next_seq = ssn->client.isn + 1;
1357
1358
68.4k
        ssn->client.last_ack = TCP_GET_RAW_ACK(tcph);
1359
68.4k
        ssn->server.last_ack = TCP_GET_RAW_SEQ(tcph);
1360
1361
68.4k
        ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
1362
1363
        /** If the client has a wscale option the server had it too,
1364
         *  so set the wscale for the server to max. Otherwise none
1365
         *  will have the wscale opt just like it should. */
1366
68.4k
        if (TCP_HAS_WSCALE(p)) {
1367
31.5k
            ssn->client.wscale = TCP_GET_WSCALE(p);
1368
31.5k
            ssn->server.wscale = TCP_WSCALE_MAX;
1369
31.5k
            SCLogDebug("ssn %p: wscale enabled. client %u server %u",
1370
31.5k
                    ssn, ssn->client.wscale, ssn->server.wscale);
1371
31.5k
        }
1372
1373
68.4k
        SCLogDebug("ssn %p: ssn->client.isn %"PRIu32", ssn->client.next_seq"
1374
68.4k
                " %"PRIu32", ssn->client.last_ack %"PRIu32"", ssn,
1375
68.4k
                ssn->client.isn, ssn->client.next_seq,
1376
68.4k
                ssn->client.last_ack);
1377
68.4k
        SCLogDebug("ssn %p: ssn->server.isn %"PRIu32", ssn->server.next_seq"
1378
68.4k
                " %"PRIu32", ssn->server.last_ack %"PRIu32"", ssn,
1379
68.4k
                ssn->server.isn, ssn->server.next_seq,
1380
68.4k
                ssn->server.last_ack);
1381
1382
        /* Set the timestamp value for both streams, if packet has timestamp
1383
         * option enabled.*/
1384
68.4k
        if (TCP_HAS_TS(p)) {
1385
29.3k
            ssn->server.last_ts = TCP_GET_TSVAL(p);
1386
29.3k
            ssn->client.last_ts = TCP_GET_TSECR(p);
1387
29.3k
            SCLogDebug("ssn %p: ssn->server.last_ts %" PRIu32" "
1388
29.3k
                    "ssn->client.last_ts %" PRIu32"", ssn,
1389
29.3k
                    ssn->server.last_ts, ssn->client.last_ts);
1390
1391
29.3k
            ssn->flags |= STREAMTCP_FLAG_TIMESTAMP;
1392
1393
29.3k
            ssn->server.last_pkt_ts = (uint32_t)SCTIME_SECS(p->ts);
1394
29.3k
            if (ssn->server.last_ts == 0)
1395
329
                ssn->server.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
1396
29.3k
            if (ssn->client.last_ts == 0)
1397
561
                ssn->client.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
1398
1399
39.1k
        } else {
1400
39.1k
            ssn->server.last_ts = 0;
1401
39.1k
            ssn->client.last_ts = 0;
1402
39.1k
        }
1403
1404
68.4k
        if (TCP_GET_SACKOK(p)) {
1405
39.5k
            ssn->flags |= STREAMTCP_FLAG_SACKOK;
1406
39.5k
            SCLogDebug("ssn %p: SYN/ACK with SACK permitted, assuming "
1407
39.5k
                    "SACK permitted for both sides", ssn);
1408
39.5k
        }
1409
68.4k
        return 0;
1410
1411
214k
    } else if (tcph->th_flags & TH_SYN) {
1412
86.8k
        if (ssn == NULL) {
1413
86.8k
            ssn = StreamTcpNewSession(tv, stt, p, stt->ssn_pool_id);
1414
86.8k
            if (ssn == NULL) {
1415
0
                StatsIncr(tv, stt->counter_tcp_ssn_memcap);
1416
0
                return -1;
1417
0
            }
1418
1419
86.8k
            StatsIncr(tv, stt->counter_tcp_sessions);
1420
86.8k
            StatsIncr(tv, stt->counter_tcp_active_sessions);
1421
86.8k
        }
1422
1423
        /* set the state */
1424
86.8k
        StreamTcpPacketSetState(p, ssn, TCP_SYN_SENT);
1425
86.8k
        SCLogDebug("ssn %p: =~ ssn state is now TCP_SYN_SENT", ssn);
1426
1427
86.8k
        if (stream_config.async_oneside) {
1428
0
            SCLogDebug("ssn %p: =~ ASYNC", ssn);
1429
0
            ssn->flags |= STREAMTCP_FLAG_ASYNC;
1430
0
        }
1431
1432
        /* set the sequence numbers and window */
1433
86.8k
        ssn->client.isn = TCP_GET_RAW_SEQ(tcph);
1434
86.8k
        STREAMTCP_SET_RA_BASE_SEQ(&ssn->client, ssn->client.isn);
1435
86.8k
        ssn->client.next_seq = ssn->client.isn + 1;
1436
1437
        /* Set the stream timestamp value, if packet has timestamp option
1438
         * enabled. */
1439
86.8k
        if (TCP_HAS_TS(p)) {
1440
27.0k
            ssn->client.last_ts = TCP_GET_TSVAL(p);
1441
27.0k
            SCLogDebug("ssn %p: %02x", ssn, ssn->client.last_ts);
1442
1443
27.0k
            if (ssn->client.last_ts == 0)
1444
77
                ssn->client.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
1445
1446
27.0k
            ssn->client.last_pkt_ts = (uint32_t)SCTIME_SECS(p->ts);
1447
27.0k
            ssn->client.flags |= STREAMTCP_STREAM_FLAG_TIMESTAMP;
1448
27.0k
        }
1449
1450
86.8k
        ssn->server.window = TCP_GET_RAW_WINDOW(tcph);
1451
86.8k
        if (TCP_HAS_WSCALE(p)) {
1452
43.9k
            ssn->flags |= STREAMTCP_FLAG_SERVER_WSCALE;
1453
43.9k
            ssn->server.wscale = TCP_GET_WSCALE(p);
1454
43.9k
        }
1455
1456
86.8k
        if (TCP_GET_SACKOK(p)) {
1457
42.3k
            ssn->flags |= STREAMTCP_FLAG_CLIENT_SACKOK;
1458
42.3k
            SCLogDebug("ssn %p: SACK permitted on SYN packet", ssn);
1459
42.3k
        }
1460
1461
86.8k
        if (TCP_HAS_TFO(p)) {
1462
4.20k
            ssn->flags |= STREAMTCP_FLAG_TCP_FAST_OPEN;
1463
4.20k
            if (p->payload_len) {
1464
4.17k
                StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
1465
4.17k
                SCLogDebug("ssn: %p (TFO) isn %u base_seq %u next_seq %u payload len %u", ssn,
1466
4.17k
                        ssn->client.isn, ssn->client.base_seq, ssn->client.next_seq,
1467
4.17k
                        p->payload_len);
1468
4.17k
                StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
1469
4.17k
                p->flags |= PKT_STREAM_EST;
1470
4.17k
            }
1471
4.20k
        }
1472
1473
86.8k
        SCLogDebug("ssn %p: ssn->client.isn %" PRIu32 ", "
1474
86.8k
                "ssn->client.next_seq %" PRIu32 ", ssn->client.last_ack "
1475
86.8k
                "%"PRIu32"", ssn, ssn->client.isn, ssn->client.next_seq,
1476
86.8k
                ssn->client.last_ack);
1477
1478
127k
    } else if (tcph->th_flags & TH_ACK) {
1479
        /* Drop reason will only be used if midstream policy is set to fail closed */
1480
110k
        ExceptionPolicyApply(p, stream_config.midstream_policy, PKT_DROP_REASON_STREAM_MIDSTREAM);
1481
110k
        StreamTcpMidstreamExceptionPolicyStatsIncr(tv, stt, stream_config.midstream_policy);
1482
1483
110k
        if (!stream_config.midstream) {
1484
0
            SCLogDebug("Midstream not enabled, so won't pick up a session");
1485
0
            return 0;
1486
0
        }
1487
110k
        if (!(stream_config.midstream_policy == EXCEPTION_POLICY_NOT_SET ||
1488
0
                    stream_config.midstream_policy == EXCEPTION_POLICY_PASS_FLOW)) {
1489
0
            SCLogDebug("Midstream policy not permissive, so won't pick up a session");
1490
0
            return 0;
1491
0
        }
1492
110k
        SCLogDebug("midstream picked up");
1493
1494
110k
        if (ssn == NULL) {
1495
110k
            ssn = StreamTcpNewSession(tv, stt, p, stt->ssn_pool_id);
1496
110k
            if (ssn == NULL) {
1497
0
                StatsIncr(tv, stt->counter_tcp_ssn_memcap);
1498
0
                return -1;
1499
0
            }
1500
110k
            StatsIncr(tv, stt->counter_tcp_sessions);
1501
110k
            StatsIncr(tv, stt->counter_tcp_active_sessions);
1502
110k
            StatsIncr(tv, stt->counter_tcp_midstream_pickups);
1503
110k
        }
1504
        /* set the state */
1505
110k
        StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
1506
110k
        SCLogDebug("ssn %p: =~ midstream picked ssn state is now "
1507
110k
                "TCP_ESTABLISHED", ssn);
1508
1509
110k
        ssn->flags = STREAMTCP_FLAG_MIDSTREAM;
1510
110k
        ssn->flags |= STREAMTCP_FLAG_MIDSTREAM_ESTABLISHED;
1511
110k
        if (stream_config.async_oneside) {
1512
0
            SCLogDebug("ssn %p: =~ ASYNC", ssn);
1513
0
            ssn->flags |= STREAMTCP_FLAG_ASYNC;
1514
0
        }
1515
1516
        /** window scaling for midstream pickups, we can't do much other
1517
         *  than assume that it's set to the max value: 14 */
1518
110k
        ssn->client.wscale = TCP_WSCALE_MAX;
1519
110k
        ssn->server.wscale = TCP_WSCALE_MAX;
1520
1521
        /* set the sequence numbers and window */
1522
110k
        ssn->client.isn = TCP_GET_RAW_SEQ(tcph) - 1;
1523
110k
        STREAMTCP_SET_RA_BASE_SEQ(&ssn->client, ssn->client.isn);
1524
110k
        ssn->client.next_seq = TCP_GET_RAW_SEQ(tcph) + p->payload_len;
1525
110k
        ssn->client.window = TCP_GET_RAW_WINDOW(tcph) << ssn->client.wscale;
1526
110k
        ssn->client.last_ack = TCP_GET_RAW_SEQ(tcph);
1527
110k
        ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
1528
110k
        SCLogDebug("ssn %p: ssn->client.isn %u, ssn->client.next_seq %u",
1529
110k
                ssn, ssn->client.isn, ssn->client.next_seq);
1530
1531
110k
        ssn->server.isn = TCP_GET_RAW_ACK(tcph) - 1;
1532
110k
        STREAMTCP_SET_RA_BASE_SEQ(&ssn->server, ssn->server.isn);
1533
110k
        ssn->server.next_seq = ssn->server.isn + 1;
1534
110k
        ssn->server.last_ack = TCP_GET_RAW_ACK(tcph);
1535
110k
        ssn->server.next_win = ssn->server.last_ack;
1536
1537
110k
        SCLogDebug("ssn %p: ssn->client.next_win %"PRIu32", "
1538
110k
                "ssn->server.next_win %"PRIu32"", ssn,
1539
110k
                ssn->client.next_win, ssn->server.next_win);
1540
110k
        SCLogDebug("ssn %p: ssn->client.last_ack %"PRIu32", "
1541
110k
                "ssn->server.last_ack %"PRIu32"", ssn,
1542
110k
                ssn->client.last_ack, ssn->server.last_ack);
1543
1544
        /* Set the timestamp value for both streams, if packet has timestamp
1545
         * option enabled.*/
1546
110k
        if (TCP_HAS_TS(p)) {
1547
53.7k
            ssn->client.last_ts = TCP_GET_TSVAL(p);
1548
53.7k
            ssn->server.last_ts = TCP_GET_TSECR(p);
1549
53.7k
            SCLogDebug("ssn %p: ssn->server.last_ts %" PRIu32" "
1550
53.7k
                    "ssn->client.last_ts %" PRIu32"", ssn,
1551
53.7k
                    ssn->server.last_ts, ssn->client.last_ts);
1552
1553
53.7k
            ssn->flags |= STREAMTCP_FLAG_TIMESTAMP;
1554
1555
53.7k
            ssn->client.last_pkt_ts = (uint32_t)SCTIME_SECS(p->ts);
1556
53.7k
            if (ssn->server.last_ts == 0)
1557
144
                ssn->server.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
1558
53.7k
            if (ssn->client.last_ts == 0)
1559
414
                ssn->client.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
1560
1561
56.2k
        } else {
1562
56.2k
            ssn->server.last_ts = 0;
1563
56.2k
            ssn->client.last_ts = 0;
1564
56.2k
        }
1565
1566
110k
        StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
1567
1568
110k
        ssn->flags |= STREAMTCP_FLAG_SACKOK;
1569
110k
        SCLogDebug("ssn %p: assuming SACK permitted for both sides", ssn);
1570
1571
110k
    } else {
1572
17.2k
        SCLogDebug("default case");
1573
17.2k
    }
1574
1575
229k
    return 0;
1576
376k
}
1577
1578
/** \internal
1579
 *  \brief Setup TcpStateQueue based on SYN/ACK packet
1580
 */
1581
static inline void StreamTcp3whsSynAckToStateQueue(Packet *p, TcpStateQueue *q)
1582
83.8k
{
1583
83.8k
    const TCPHdr *tcph = PacketGetTCP(p);
1584
83.8k
    q->flags = 0;
1585
83.8k
    q->wscale = 0;
1586
83.8k
    q->ts = 0;
1587
83.8k
    q->win = TCP_GET_RAW_WINDOW(tcph);
1588
83.8k
    q->seq = TCP_GET_RAW_SEQ(tcph);
1589
83.8k
    q->ack = TCP_GET_RAW_ACK(tcph);
1590
83.8k
    q->pkt_ts = (uint32_t)SCTIME_SECS(p->ts);
1591
1592
83.8k
    if (TCP_GET_SACKOK(p))
1593
34.3k
        q->flags |= STREAMTCP_QUEUE_FLAG_SACK;
1594
1595
83.8k
    if (TCP_HAS_WSCALE(p)) {
1596
36.5k
        q->flags |= STREAMTCP_QUEUE_FLAG_WS;
1597
36.5k
        q->wscale = TCP_GET_WSCALE(p);
1598
36.5k
    }
1599
83.8k
    if (TCP_HAS_TS(p)) {
1600
22.3k
        q->flags |= STREAMTCP_QUEUE_FLAG_TS;
1601
22.3k
        q->ts = TCP_GET_TSVAL(p);
1602
22.3k
    }
1603
83.8k
}
1604
1605
/** \internal
1606
 *  \brief Find the Queued SYN/ACK that is the same as this SYN/ACK
1607
 *  \retval q or NULL */
1608
static TcpStateQueue *StreamTcp3whsFindSynAckBySynAck(TcpSession *ssn, Packet *p)
1609
14.3k
{
1610
14.3k
    TcpStateQueue *q = ssn->queue;
1611
14.3k
    TcpStateQueue search;
1612
1613
14.3k
    StreamTcp3whsSynAckToStateQueue(p, &search);
1614
1615
33.8k
    while (q != NULL) {
1616
29.6k
        if (search.flags == q->flags &&
1617
16.5k
            search.wscale == q->wscale &&
1618
15.4k
            search.win == q->win &&
1619
13.0k
            search.seq == q->seq &&
1620
10.7k
            search.ack == q->ack &&
1621
10.7k
            search.ts == q->ts) {
1622
10.1k
            return q;
1623
10.1k
        }
1624
1625
19.4k
        q = q->next;
1626
19.4k
    }
1627
1628
4.15k
    return q;
1629
14.3k
}
1630
1631
static int StreamTcp3whsQueueSynAck(TcpSession *ssn, Packet *p)
1632
14.3k
{
1633
    /* first see if this is already in our list */
1634
14.3k
    if (StreamTcp3whsFindSynAckBySynAck(ssn, p) != NULL)
1635
10.1k
        return 0;
1636
1637
4.15k
    if (ssn->queue_len == stream_config.max_synack_queued) {
1638
322
        SCLogDebug("ssn %p: =~ SYN/ACK queue limit reached", ssn);
1639
322
        StreamTcpSetEvent(p, STREAM_3WHS_SYNACK_FLOOD);
1640
322
        return -1;
1641
322
    }
1642
1643
3.83k
    if (StreamTcpCheckMemcap((uint32_t)sizeof(TcpStateQueue)) == 0) {
1644
0
        SCLogDebug("ssn %p: =~ SYN/ACK queue failed: stream memcap reached", ssn);
1645
0
        return -1;
1646
0
    }
1647
1648
3.83k
    TcpStateQueue *q = SCCalloc(1, sizeof(*q));
1649
3.83k
    if (unlikely(q == NULL)) {
1650
0
        SCLogDebug("ssn %p: =~ SYN/ACK queue failed: alloc failed", ssn);
1651
0
        return -1;
1652
0
    }
1653
3.83k
    StreamTcpIncrMemuse((uint64_t)sizeof(TcpStateQueue));
1654
1655
3.83k
    StreamTcp3whsSynAckToStateQueue(p, q);
1656
1657
    /* put in list */
1658
3.83k
    q->next = ssn->queue;
1659
3.83k
    ssn->queue = q;
1660
3.83k
    ssn->queue_len++;
1661
3.83k
    return 0;
1662
3.83k
}
1663
1664
/** \internal
1665
 *  \brief Find the Queued SYN/ACK that goes with this ACK
1666
 *  \retval q or NULL */
1667
static TcpStateQueue *StreamTcp3whsFindSynAckByAck(TcpSession *ssn, Packet *p)
1668
7.41k
{
1669
7.41k
    const TCPHdr *tcph = PacketGetTCP(p);
1670
7.41k
    const uint32_t ack = TCP_GET_RAW_SEQ(tcph);
1671
7.41k
    const uint32_t seq = TCP_GET_RAW_ACK(tcph) - 1;
1672
7.41k
    TcpStateQueue *q = ssn->queue;
1673
1674
19.1k
    while (q != NULL) {
1675
12.6k
        if (seq == q->seq &&
1676
1.14k
            ack == q->ack) {
1677
878
            return q;
1678
878
        }
1679
1680
11.7k
        q = q->next;
1681
11.7k
    }
1682
1683
6.53k
    return NULL;
1684
7.41k
}
1685
1686
/** \internal
1687
 *  \brief Update SSN after receiving a valid SYN/ACK
1688
 *
1689
 *  Normally we update the SSN from the SYN/ACK packet. But in case
1690
 *  of queued SYN/ACKs, we can use one of those.
1691
 *
1692
 *  \param ssn TCP session
1693
 *  \param p Packet
1694
 *  \param q queued state if used, NULL otherwise
1695
 *
1696
 *  To make sure all SYN/ACK based state updates are in one place,
1697
 *  this function can updated based on Packet or TcpStateQueue, where
1698
 *  the latter takes precedence.
1699
 */
1700
static void StreamTcp3whsSynAckUpdate(TcpSession *ssn, Packet *p, TcpStateQueue *q)
1701
66.5k
{
1702
66.5k
    TcpStateQueue update;
1703
66.5k
    if (likely(q == NULL)) {
1704
65.6k
        StreamTcp3whsSynAckToStateQueue(p, &update);
1705
65.6k
        q = &update;
1706
65.6k
    }
1707
1708
66.5k
    if (ssn->state != TCP_SYN_RECV) {
1709
        /* update state */
1710
65.6k
        StreamTcpPacketSetState(p, ssn, TCP_SYN_RECV);
1711
65.6k
        SCLogDebug("ssn %p: =~ ssn state is now TCP_SYN_RECV", ssn);
1712
65.6k
    }
1713
    /* sequence number & window */
1714
66.5k
    ssn->server.isn = q->seq;
1715
66.5k
    STREAMTCP_SET_RA_BASE_SEQ(&ssn->server, ssn->server.isn);
1716
66.5k
    ssn->server.next_seq = ssn->server.isn + 1;
1717
1718
66.5k
    ssn->client.window = q->win;
1719
66.5k
    SCLogDebug("ssn %p: window %" PRIu32 "", ssn, ssn->server.window);
1720
1721
    /* Set the timestamp values used to validate the timestamp of
1722
     * received packets.*/
1723
66.5k
    if ((q->flags & STREAMTCP_QUEUE_FLAG_TS) &&
1724
15.1k
            (ssn->client.flags & STREAMTCP_STREAM_FLAG_TIMESTAMP))
1725
14.1k
    {
1726
14.1k
        ssn->server.last_ts = q->ts;
1727
14.1k
        SCLogDebug("ssn %p: ssn->server.last_ts %" PRIu32" "
1728
14.1k
                "ssn->client.last_ts %" PRIu32"", ssn,
1729
14.1k
                ssn->server.last_ts, ssn->client.last_ts);
1730
14.1k
        ssn->flags |= STREAMTCP_FLAG_TIMESTAMP;
1731
14.1k
        ssn->server.last_pkt_ts = q->pkt_ts;
1732
14.1k
        if (ssn->server.last_ts == 0)
1733
4
            ssn->server.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
1734
52.3k
    } else {
1735
52.3k
        ssn->client.last_ts = 0;
1736
52.3k
        ssn->server.last_ts = 0;
1737
52.3k
        ssn->client.flags &= ~STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
1738
52.3k
    }
1739
1740
66.5k
    ssn->client.last_ack = q->ack;
1741
66.5k
    ssn->server.last_ack = ssn->server.isn + 1;
1742
1743
    /** check for the presence of the ws ptr to determine if we
1744
     *  support wscale at all */
1745
66.5k
    if ((ssn->flags & STREAMTCP_FLAG_SERVER_WSCALE) &&
1746
32.4k
            (q->flags & STREAMTCP_QUEUE_FLAG_WS))
1747
26.0k
    {
1748
26.0k
        ssn->client.wscale = q->wscale;
1749
40.4k
    } else {
1750
40.4k
        ssn->client.wscale = 0;
1751
40.4k
    }
1752
1753
66.5k
    if ((ssn->flags & STREAMTCP_FLAG_CLIENT_SACKOK) &&
1754
32.7k
            (q->flags & STREAMTCP_QUEUE_FLAG_SACK)) {
1755
25.4k
        ssn->flags |= STREAMTCP_FLAG_SACKOK;
1756
25.4k
        SCLogDebug("ssn %p: SACK permitted for session", ssn);
1757
41.1k
    } else {
1758
41.1k
        ssn->flags &= ~STREAMTCP_FLAG_SACKOK;
1759
41.1k
    }
1760
1761
66.5k
    ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
1762
66.5k
    ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
1763
66.5k
    SCLogDebug("ssn %p: ssn->server.next_win %" PRIu32 "", ssn,
1764
66.5k
            ssn->server.next_win);
1765
66.5k
    SCLogDebug("ssn %p: ssn->client.next_win %" PRIu32 "", ssn,
1766
66.5k
            ssn->client.next_win);
1767
66.5k
    SCLogDebug("ssn %p: ssn->server.isn %" PRIu32 ", "
1768
66.5k
            "ssn->server.next_seq %" PRIu32 ", "
1769
66.5k
            "ssn->server.last_ack %" PRIu32 " "
1770
66.5k
            "(ssn->client.last_ack %" PRIu32 ")", ssn,
1771
66.5k
            ssn->server.isn, ssn->server.next_seq,
1772
66.5k
            ssn->server.last_ack, ssn->client.last_ack);
1773
1774
    /* unset the 4WHS flag as we received this SYN/ACK as part of a
1775
     * (so far) valid 3WHS */
1776
66.5k
    if (ssn->flags & STREAMTCP_FLAG_4WHS)
1777
1.83k
        SCLogDebug("ssn %p: STREAMTCP_FLAG_4WHS unset, normal SYN/ACK"
1778
66.5k
                " so considering 3WHS", ssn);
1779
1780
66.5k
    ssn->flags &=~ STREAMTCP_FLAG_4WHS;
1781
66.5k
}
1782
1783
/** \internal
1784
 *  \brief detect timestamp anomalies when processing responses to the
1785
 *         SYN packet.
1786
 *  \retval true packet is ok
1787
 *  \retval false packet is bad
1788
 */
1789
static inline bool StateSynSentValidateTimestamp(TcpSession *ssn, Packet *p)
1790
167k
{
1791
    /* we only care about evil server here, so skip TS packets */
1792
167k
    if (PKT_IS_TOSERVER(p) || !(TCP_HAS_TS(p))) {
1793
137k
        return true;
1794
137k
    }
1795
1796
29.4k
    TcpStream *receiver_stream = &ssn->client;
1797
29.4k
    const uint32_t ts_echo = TCP_GET_TSECR(p);
1798
29.4k
    if ((receiver_stream->flags & STREAMTCP_STREAM_FLAG_TIMESTAMP) != 0) {
1799
15.4k
        if (receiver_stream->last_ts != 0 && ts_echo != 0 &&
1800
15.0k
            ts_echo != receiver_stream->last_ts)
1801
12.0k
        {
1802
12.0k
            SCLogDebug("%" PRIu64 ": ssn %p: BAD TSECR echo %u recv %u", p->pcap_cnt, ssn, ts_echo,
1803
12.0k
                    receiver_stream->last_ts);
1804
12.0k
            return false;
1805
12.0k
        }
1806
15.4k
    } else {
1807
13.9k
        if (receiver_stream->last_ts == 0 && ts_echo != 0) {
1808
5.93k
            SCLogDebug("%" PRIu64 ": ssn %p: BAD TSECR echo %u recv %u", p->pcap_cnt, ssn, ts_echo,
1809
5.93k
                    receiver_stream->last_ts);
1810
5.93k
            return false;
1811
5.93k
        }
1812
13.9k
    }
1813
11.4k
    return true;
1814
29.4k
}
1815
1816
static void TcpStateQueueInitFromSsnSyn(const TcpSession *ssn, TcpStateQueue *q)
1817
63.0k
{
1818
63.0k
    DEBUG_VALIDATE_BUG_ON(ssn->state != TCP_SYN_SENT); // TODO
1819
63.0k
    memset(q, 0, sizeof(*q));
1820
1821
63.0k
    q->seq = ssn->client.isn;
1822
    /* SYN won't use wscale yet. So window should be limited to 16 bits. */
1823
63.0k
    DEBUG_VALIDATE_BUG_ON(ssn->server.window > UINT16_MAX);
1824
63.0k
    q->win = (uint16_t)ssn->server.window;
1825
1826
63.0k
    q->pkt_ts = ssn->client.last_pkt_ts;
1827
1828
63.0k
    if (ssn->flags & STREAMTCP_FLAG_CLIENT_SACKOK) {
1829
36.3k
        q->flags |= STREAMTCP_QUEUE_FLAG_SACK;
1830
36.3k
    }
1831
63.0k
    if (ssn->flags & STREAMTCP_FLAG_SERVER_WSCALE) {
1832
36.6k
        q->flags |= STREAMTCP_QUEUE_FLAG_WS;
1833
36.6k
        q->wscale = ssn->server.wscale;
1834
36.6k
    }
1835
63.0k
    if (ssn->client.flags & STREAMTCP_STREAM_FLAG_TIMESTAMP) {
1836
22.9k
        q->flags |= STREAMTCP_QUEUE_FLAG_TS;
1837
22.9k
        q->ts = ssn->client.last_ts;
1838
22.9k
    }
1839
1840
63.0k
    SCLogDebug("ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->seq, q->win,
1841
63.0k
            BOOL2STR(q->flags & STREAMTCP_QUEUE_FLAG_TS), q->ts);
1842
63.0k
}
1843
1844
static void TcpStateQueueInitFromPktSyn(const Packet *p, TcpStateQueue *q)
1845
37.9k
{
1846
37.9k
#if defined(DEBUG_VALIDATION) || defined(DEBUG)
1847
37.9k
    const TcpSession *ssn = p->flow->protoctx;
1848
37.9k
    BUG_ON(ssn->state != TCP_SYN_SENT);
1849
37.9k
#endif
1850
37.9k
    memset(q, 0, sizeof(*q));
1851
37.9k
    const TCPHdr *tcph = PacketGetTCP(p);
1852
1853
37.9k
    q->seq = TCP_GET_RAW_SEQ(tcph);
1854
37.9k
    q->win = TCP_GET_RAW_WINDOW(tcph);
1855
37.9k
    q->pkt_ts = (uint32_t)SCTIME_SECS(p->ts);
1856
1857
37.9k
    if (TCP_GET_SACKOK(p)) {
1858
21.0k
        q->flags |= STREAMTCP_QUEUE_FLAG_SACK;
1859
21.0k
    }
1860
37.9k
    if (TCP_HAS_WSCALE(p)) {
1861
21.9k
        q->flags |= STREAMTCP_QUEUE_FLAG_WS;
1862
21.9k
        q->wscale = TCP_GET_WSCALE(p);
1863
21.9k
    }
1864
37.9k
    if (TCP_HAS_TS(p)) {
1865
14.4k
        q->flags |= STREAMTCP_QUEUE_FLAG_TS;
1866
14.4k
        q->ts = TCP_GET_TSVAL(p);
1867
14.4k
    }
1868
1869
#if defined(DEBUG)
1870
    SCLogDebug("ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->seq, q->win,
1871
            BOOL2STR(q->flags & STREAMTCP_QUEUE_FLAG_TS), q->ts);
1872
#endif
1873
37.9k
}
1874
1875
static void TcpStateQueueInitFromPktSynAck(const Packet *p, TcpStateQueue *q)
1876
2.64k
{
1877
2.64k
#if defined(DEBUG_VALIDATION) || defined(DEBUG)
1878
2.64k
    const TcpSession *ssn = p->flow->protoctx;
1879
2.64k
    BUG_ON(ssn->state != TCP_SYN_SENT);
1880
2.64k
#endif
1881
2.64k
    memset(q, 0, sizeof(*q));
1882
1883
2.64k
    const TCPHdr *tcph = PacketGetTCP(p);
1884
2.64k
    q->seq = TCP_GET_RAW_ACK(tcph) - 1;
1885
2.64k
    q->win = TCP_GET_RAW_WINDOW(tcph);
1886
2.64k
    q->pkt_ts = (uint32_t)SCTIME_SECS(p->ts);
1887
1888
2.64k
    if (TCP_GET_SACKOK(p)) {
1889
2.10k
        q->flags |= STREAMTCP_QUEUE_FLAG_SACK;
1890
2.10k
    }
1891
2.64k
    if (TCP_HAS_WSCALE(p)) {
1892
1.72k
        q->flags |= STREAMTCP_QUEUE_FLAG_WS;
1893
1.72k
        q->wscale = TCP_GET_WSCALE(p);
1894
1.72k
    }
1895
2.64k
    if (TCP_HAS_TS(p)) {
1896
2.17k
        q->flags |= STREAMTCP_QUEUE_FLAG_TS;
1897
2.17k
        q->ts = TCP_GET_TSECR(p);
1898
2.17k
    }
1899
1900
#if defined(DEBUG)
1901
    SCLogDebug("ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->seq, q->win,
1902
            BOOL2STR(q->flags & STREAMTCP_QUEUE_FLAG_TS), q->ts);
1903
#endif
1904
2.64k
}
1905
1906
/** \internal
1907
 *  \brief Find the Queued SYN that is the same as this SYN/ACK
1908
 *  \param[in] ignore_ts if true, ignore the timestamp
1909
 *  \retval q or NULL
1910
 *
1911
 *  \note When `ignore_ts`, the following is accepted: SYN w/o TS, SYN/ACK with TS.
1912
 *  \note When `ignore_ts` is set, `s` corresponds to the SYN/ACK packet and the
1913
 *  queue holds the stored SYN packets. */
1914
static const TcpStateQueue *StreamTcp3whsFindSyn(
1915
        const TcpSession *ssn, TcpStateQueue *s, TcpStateQueue **ret_tail, const bool ignore_ts)
1916
20.0k
{
1917
20.0k
    SCLogDebug("ssn %p: search state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, s, s->seq, s->win,
1918
20.0k
            BOOL2STR(s->flags & STREAMTCP_QUEUE_FLAG_TS), s->ts);
1919
1920
20.0k
    TcpStateQueue *last = NULL;
1921
113k
    for (TcpStateQueue *q = ssn->queue; q != NULL; q = q->next) {
1922
96.9k
        SCLogDebug("ssn %p: queue state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u (last:%s)", ssn, q,
1923
96.9k
                q->seq, q->win, BOOL2STR(q->flags & STREAMTCP_QUEUE_FLAG_TS), q->ts,
1924
96.9k
                BOOL2STR(q->next == NULL));
1925
1926
96.9k
        if (s->flags & STREAMTCP_QUEUE_FLAG_TS) {
1927
17.5k
            if ((q->flags & STREAMTCP_QUEUE_FLAG_TS) && s->ts == q->ts && s->seq == q->seq) {
1928
3.68k
                return q;
1929
3.68k
            }
1930
79.4k
        } else if (ignore_ts) {
1931
1.98k
            if (s->seq == q->seq) {
1932
19
                return q;
1933
19
            }
1934
1.98k
        }
1935
93.2k
        last = q;
1936
93.2k
    }
1937
16.3k
    if (ret_tail)
1938
13.8k
        *ret_tail = last;
1939
16.3k
    return NULL;
1940
20.0k
}
1941
1942
/** \internal
1943
 *  \brief take oldest element in the list and replace it with the new data
1944
 */
1945
static void AddAndRotate(TcpSession *ssn, TcpStateQueue *tail, TcpStateQueue *search)
1946
5.81k
{
1947
5.81k
    TcpStateQueue *old_head = ssn->queue;
1948
1949
5.81k
    if (tail == old_head) {
1950
        /* single-element list: overwrite in place */
1951
0
        *old_head = *search;
1952
0
        old_head->next = NULL;
1953
0
        return;
1954
0
    }
1955
1956
    /* multi-element list: pop head, append after tail, reuse as new tail */
1957
5.81k
    ssn->queue = old_head->next;
1958
5.81k
    tail->next = old_head;
1959
1960
5.81k
    *old_head = *search;
1961
5.81k
    old_head->next = NULL;
1962
5.81k
}
1963
1964
static int StreamTcp3whsStoreSyn(TcpSession *ssn, Packet *p)
1965
25.1k
{
1966
25.1k
    TcpStateQueue search;
1967
25.1k
    TcpStateQueueInitFromSsnSyn(ssn, &search);
1968
25.1k
    TcpStateQueue *tail = NULL;
1969
1970
    /* first see if this is already in our list */
1971
25.1k
    if (ssn->queue != NULL && StreamTcp3whsFindSyn(ssn, &search, &tail, false) != NULL)
1972
3.57k
        return 0;
1973
1974
21.5k
    if (ssn->queue != NULL && ssn->queue_len == stream_config.max_syn_queued) {
1975
5.81k
        SCLogDebug("%" PRIu64 ": ssn %p: =~ SYN queue limit reached, rotate", p->pcap_cnt, ssn);
1976
5.81k
        StreamTcpSetEvent(p, STREAM_3WHS_SYN_FLOOD);
1977
1978
        /* add to the list, evicting the oldest entry */
1979
5.81k
        AddAndRotate(ssn, tail, &search);
1980
5.81k
        return 0;
1981
5.81k
    }
1982
1983
15.7k
    if (StreamTcpCheckMemcap((uint32_t)sizeof(TcpStateQueue)) == 0) {
1984
0
        SCLogDebug("ssn %p: =~ SYN queue failed: stream memcap reached", ssn);
1985
0
        return -1;
1986
0
    }
1987
1988
15.7k
    TcpStateQueue *q = SCCalloc(1, sizeof(*q));
1989
15.7k
    if (unlikely(q == NULL)) {
1990
0
        SCLogDebug("ssn %p: =~ SYN queue failed: alloc failed", ssn);
1991
0
        return -1;
1992
0
    }
1993
15.7k
    StreamTcpIncrMemuse((uint64_t)sizeof(TcpStateQueue));
1994
1995
15.7k
    *q = search;
1996
    /* put in list */
1997
15.7k
    if (tail) {
1998
7.98k
        tail->next = q;
1999
7.98k
    } else {
2000
7.77k
        DEBUG_VALIDATE_BUG_ON(ssn->queue != NULL);
2001
7.77k
        ssn->queue = q;
2002
7.77k
    }
2003
15.7k
    ssn->queue_len++;
2004
15.7k
    SCLogDebug("%" PRIu64 ": ssn %p: =~ SYN with SEQ %u added (queue_len %u)", p->pcap_cnt, ssn,
2005
15.7k
            q->seq, ssn->queue_len);
2006
15.7k
    return 0;
2007
15.7k
}
2008
2009
static inline void StreamTcp3whsStoreSynApplyToSsn(TcpSession *ssn, const TcpStateQueue *q)
2010
38.0k
{
2011
38.0k
    if (q->flags & STREAMTCP_QUEUE_FLAG_TS) {
2012
14.5k
        ssn->client.last_pkt_ts = q->pkt_ts;
2013
14.5k
        ssn->client.last_ts = q->ts;
2014
14.5k
        ssn->client.flags |= STREAMTCP_STREAM_FLAG_TIMESTAMP;
2015
14.5k
        SCLogDebug("ssn: %p client.last_ts updated to %u", ssn, ssn->client.last_ts);
2016
14.5k
    }
2017
38.0k
    if (q->flags & STREAMTCP_QUEUE_FLAG_WS) {
2018
22.0k
        ssn->flags |= STREAMTCP_FLAG_SERVER_WSCALE;
2019
22.0k
        ssn->server.wscale = q->wscale;
2020
22.0k
    } else {
2021
16.0k
        ssn->flags &= ~STREAMTCP_FLAG_SERVER_WSCALE;
2022
16.0k
        ssn->server.wscale = 0;
2023
16.0k
    }
2024
38.0k
    ssn->server.window = q->win;
2025
2026
38.0k
    if (q->flags & STREAMTCP_QUEUE_FLAG_SACK) {
2027
21.1k
        ssn->flags |= STREAMTCP_FLAG_CLIENT_SACKOK;
2028
21.1k
    } else {
2029
16.9k
        ssn->flags &= ~STREAMTCP_FLAG_CLIENT_SACKOK;
2030
16.9k
    }
2031
38.0k
    ssn->client.isn = q->seq;
2032
38.0k
    ssn->client.base_seq = ssn->client.next_seq = ssn->client.isn + 1;
2033
38.0k
    SCLogDebug("ssn: %p client.isn updated to %u", ssn, ssn->client.isn);
2034
38.0k
}
2035
2036
/** \internal
2037
 *  \brief handle SYN/ACK on SYN_SENT state (non-TFO case)
2038
 *
2039
 *  If packet doesn't match the session, check queued states (if any)
2040
 *
2041
 *  \retval true packet is accepted
2042
 *  \retval false packet is rejected
2043
 */
2044
static inline bool StateSynSentCheckSynAck3Whs(TcpSession *ssn, Packet *p, const bool ts_mismatch)
2045
65.6k
{
2046
65.6k
    const TCPHdr *tcph = PacketGetTCP(p);
2047
65.6k
    const bool seq_match = SEQ_EQ(TCP_GET_RAW_ACK(tcph), ssn->client.isn + 1);
2048
65.6k
    if (seq_match && !ts_mismatch) {
2049
63.0k
        return true;
2050
63.0k
    }
2051
2052
    /* check the queued syns */
2053
2.64k
    if (ssn->queue == NULL) {
2054
1.36k
        goto failure;
2055
1.36k
    }
2056
2057
1.28k
    TcpStateQueue search;
2058
1.28k
    TcpStateQueueInitFromPktSynAck(p, &search);
2059
1.28k
    SCLogDebug("%" PRIu64 ": ssn %p: SYN/ACK looking for SEQ %u", p->pcap_cnt, ssn, search.seq);
2060
2061
1.28k
    const TcpStateQueue *q =
2062
1.28k
            StreamTcp3whsFindSyn(ssn, &search, NULL, stream_config.liberal_timestamps);
2063
1.28k
    if (q == NULL) {
2064
1.15k
        SCLogDebug("not found: mismatch");
2065
1.15k
        goto failure;
2066
1.15k
    }
2067
2068
128
    SCLogDebug("ssn %p: found queued SYN state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q,
2069
128
            q->seq, q->win, BOOL2STR(q->flags & STREAMTCP_QUEUE_FLAG_TS), q->ts);
2070
128
    StreamTcp3whsStoreSynApplyToSsn(ssn, q);
2071
128
    return true;
2072
2.52k
failure:
2073
2.52k
    if (!seq_match) {
2074
2.52k
        StreamTcpSetEvent(p, STREAM_3WHS_SYNACK_WITH_WRONG_ACK);
2075
2.52k
    } else if (ts_mismatch) {
2076
0
        StreamTcpSetEvent(p, STREAM_PKT_INVALID_TIMESTAMP);
2077
0
    }
2078
2.52k
    return false;
2079
1.28k
}
2080
2081
/** \internal
2082
 *  \brief handle SYN/ACK on SYN_SENT state (TFO case)
2083
 *
2084
 *  If packet doesn't match the session, check queued states (if any)
2085
 *
2086
 *  \retval true packet is accepted
2087
 *  \retval false packet is rejected
2088
 */
2089
static inline bool StateSynSentCheckSynAckTFO(TcpSession *ssn, Packet *p, const bool ts_mismatch)
2090
6.51k
{
2091
6.51k
    const TCPHdr *tcph = PacketGetTCP(p);
2092
6.51k
    const bool seq_match_tfo = SEQ_EQ(TCP_GET_RAW_ACK(tcph), ssn->client.next_seq);
2093
6.51k
    const bool seq_match_nodata = SEQ_EQ(TCP_GET_RAW_ACK(tcph), ssn->client.isn + 1);
2094
6.51k
    if (seq_match_tfo && !ts_mismatch) {
2095
        // ok
2096
4.07k
    } else if (seq_match_nodata && !ts_mismatch) {
2097
30
        ssn->client.next_seq = ssn->client.isn; // reset to ISN
2098
30
        SCLogDebug("ssn %p: (TFO) next_seq reset to isn (%u)", ssn, ssn->client.next_seq);
2099
30
        StreamTcpSetEvent(p, STREAM_3WHS_SYNACK_TFO_DATA_IGNORED);
2100
30
        ssn->flags |= STREAMTCP_FLAG_TFO_DATA_IGNORED;
2101
4.04k
    } else {
2102
        /* check the queued syns */
2103
4.04k
        if (ssn->queue == NULL) {
2104
2.67k
            goto failure;
2105
2.67k
        }
2106
2107
1.36k
        TcpStateQueue search;
2108
1.36k
        TcpStateQueueInitFromPktSynAck(p, &search);
2109
1.36k
        SCLogDebug("%" PRIu64 ": ssn %p: SYN/ACK looking for SEQ %u", p->pcap_cnt, ssn, search.seq);
2110
2111
1.36k
        const TcpStateQueue *q =
2112
1.36k
                StreamTcp3whsFindSyn(ssn, &search, NULL, stream_config.liberal_timestamps);
2113
1.36k
        if (q == NULL) {
2114
1.36k
            SCLogDebug("not found: mismatch");
2115
1.36k
            goto failure;
2116
1.36k
        }
2117
2118
0
        SCLogDebug("ssn %p: found queued SYN state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q,
2119
0
                q->seq, q->win, BOOL2STR(q->flags & STREAMTCP_QUEUE_FLAG_TS), q->ts);
2120
0
        StreamTcp3whsStoreSynApplyToSsn(ssn, q);
2121
0
    }
2122
2.47k
    ssn->flags |= STREAMTCP_FLAG_TCP_FAST_OPEN;
2123
2.47k
    return true;
2124
4.04k
failure:
2125
4.04k
    if (!seq_match_tfo && !seq_match_nodata) {
2126
4.04k
        StreamTcpSetEvent(p, STREAM_3WHS_SYNACK_WITH_WRONG_ACK);
2127
4.04k
    } else if (ts_mismatch) {
2128
0
        StreamTcpSetEvent(p, STREAM_PKT_INVALID_TIMESTAMP);
2129
0
    }
2130
4.04k
    return false;
2131
6.51k
}
2132
2133
/**
2134
 *  \brief  Function to handle the TCP_SYN_SENT state. The function handles
2135
 *          SYN, SYN/ACK, RST packets and correspondingly changes the connection
2136
 *          state.
2137
 *
2138
 *  \param  tv      Thread Variable containing  input/output queue, cpu affinity
2139
 *  \param  p       Packet which has to be handled in this TCP state.
2140
 *  \param  stt     Stream Thread module registered to handle the stream handling
2141
 */
2142
2143
static int StreamTcpPacketStateSynSent(
2144
        ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn)
2145
255k
{
2146
255k
    DEBUG_VALIDATE_BUG_ON(ssn == NULL);
2147
255k
    const TCPHdr *tcph = PacketGetTCP(p);
2148
2149
255k
    SCLogDebug("ssn %p: pkt received: %s", ssn, PKT_IS_TOCLIENT(p) ? "toclient" : "toserver");
2150
2151
    /* common case: SYN/ACK from server to client */
2152
255k
    if ((tcph->th_flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK) && PKT_IS_TOCLIENT(p)) {
2153
72.2k
        SCLogDebug("%" PRIu64 ": ssn %p: SYN/ACK on SYN_SENT state for packet %" PRIu64,
2154
72.2k
                p->pcap_cnt, ssn, p->pcap_cnt);
2155
        /* if timestamps are liberal, allow a SYN/ACK with TS even if the SYN
2156
         * had none (violates RFC 7323, see bug #4702). */
2157
72.2k
        const bool ts_mismatch =
2158
72.2k
                !(stream_config.liberal_timestamps || StateSynSentValidateTimestamp(ssn, p));
2159
72.2k
        SCLogDebug("ts_mismatch %s", BOOL2STR(ts_mismatch));
2160
2161
72.2k
        if (!(TCP_HAS_TFO(p) || (ssn->flags & STREAMTCP_FLAG_TCP_FAST_OPEN))) {
2162
65.6k
            if (StateSynSentCheckSynAck3Whs(ssn, p, ts_mismatch)) {
2163
63.1k
                SCLogDebug("ssn %p: ACK match, packet ACK %" PRIu32 " == "
2164
63.1k
                           "%" PRIu32 " from stream",
2165
63.1k
                        ssn, TCP_GET_RAW_ACK(tcph), ssn->client.isn + 1);
2166
63.1k
            } else {
2167
2.52k
                SCLogDebug("ssn %p: (3WHS) ACK mismatch, packet ACK %" PRIu32 " != "
2168
2.52k
                           "%" PRIu32 " from stream",
2169
2.52k
                        ssn, TCP_GET_RAW_ACK(tcph), ssn->client.next_seq);
2170
2.52k
                return -1;
2171
2.52k
            }
2172
65.6k
        } else {
2173
6.51k
            if (StateSynSentCheckSynAckTFO(ssn, p, ts_mismatch)) {
2174
2.47k
                SCLogDebug("ssn %p: (TFO) ACK matches next_seq, packet ACK %" PRIu32 " == "
2175
2.47k
                           "%" PRIu32 " from stream",
2176
2.47k
                        ssn, TCP_GET_RAW_ACK(tcph), ssn->client.next_seq);
2177
4.04k
            } else {
2178
4.04k
                SCLogDebug("ssn %p: (TFO) ACK mismatch, packet ACK %" PRIu32 " != "
2179
4.04k
                           "%" PRIu32 " from stream",
2180
4.04k
                        ssn, TCP_GET_RAW_ACK(tcph), ssn->client.next_seq);
2181
4.04k
                return -1;
2182
4.04k
            }
2183
6.51k
        }
2184
        /* clear ssn->queue on state change: TcpSession can be reused by SYN/ACK */
2185
65.6k
        StreamTcp3wsFreeQueue(ssn);
2186
2187
65.6k
        StreamTcp3whsSynAckUpdate(ssn, p, /* no queue override */NULL);
2188
65.6k
        SCLogDebug("%" PRIu64 ": ssn %p: SYN/ACK on SYN_SENT state: accepted", p->pcap_cnt, ssn);
2189
65.6k
        return 0;
2190
2191
183k
    } else if ((tcph->th_flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK) && PKT_IS_TOSERVER(p)) {
2192
2193
15.7k
        if (!(ssn->flags & STREAMTCP_FLAG_4WHS)) {
2194
10.4k
            StreamTcpSetEvent(p, STREAM_3WHS_SYNACK_IN_WRONG_DIRECTION);
2195
10.4k
            SCLogDebug("ssn %p: SYN/ACK received in the wrong direction", ssn);
2196
10.4k
            return -1;
2197
10.4k
        }
2198
2199
5.29k
        SCLogDebug("ssn %p: SYN/ACK received on 4WHS session", ssn);
2200
2201
        /* Check if the SYN/ACK packet ack's the earlier
2202
         * received SYN packet. */
2203
5.29k
        if (!(SEQ_EQ(TCP_GET_RAW_ACK(tcph), ssn->server.isn + 1))) {
2204
136
            StreamTcpSetEvent(p, STREAM_4WHS_SYNACK_WITH_WRONG_ACK);
2205
2206
136
            SCLogDebug("ssn %p: 4WHS ACK mismatch, packet ACK %" PRIu32 ""
2207
136
                       " != %" PRIu32 " from stream",
2208
136
                    ssn, TCP_GET_RAW_ACK(tcph), ssn->server.isn + 1);
2209
136
            return -1;
2210
136
        }
2211
2212
        /* Check if the SYN/ACK packet SEQ's the *FIRST* received SYN
2213
         * packet. */
2214
5.16k
        if (!(SEQ_EQ(TCP_GET_RAW_SEQ(tcph), ssn->client.isn))) {
2215
1.71k
            StreamTcpSetEvent(p, STREAM_4WHS_SYNACK_WITH_WRONG_SYN);
2216
2217
1.71k
            SCLogDebug("ssn %p: 4WHS SEQ mismatch, packet SEQ %" PRIu32 ""
2218
1.71k
                       " != %" PRIu32 " from *first* SYN pkt",
2219
1.71k
                    ssn, TCP_GET_RAW_SEQ(tcph), ssn->client.isn);
2220
1.71k
            return -1;
2221
1.71k
        }
2222
2223
        /* update state */
2224
3.44k
        StreamTcpPacketSetState(p, ssn, TCP_SYN_RECV);
2225
3.44k
        SCLogDebug("ssn %p: =~ 4WHS ssn state is now TCP_SYN_RECV", ssn);
2226
2227
        /* sequence number & window */
2228
3.44k
        ssn->client.isn = TCP_GET_RAW_SEQ(tcph);
2229
3.44k
        STREAMTCP_SET_RA_BASE_SEQ(&ssn->client, ssn->client.isn);
2230
3.44k
        ssn->client.next_seq = ssn->client.isn + 1;
2231
2232
3.44k
        ssn->server.window = TCP_GET_RAW_WINDOW(tcph);
2233
3.44k
        SCLogDebug("ssn %p: 4WHS window %" PRIu32 "", ssn, ssn->client.window);
2234
2235
        /* Set the timestamp values used to validate the timestamp of
2236
         * received packets. */
2237
3.44k
        if ((TCP_HAS_TS(p)) && (ssn->server.flags & STREAMTCP_STREAM_FLAG_TIMESTAMP)) {
2238
950
            ssn->client.last_ts = TCP_GET_TSVAL(p);
2239
950
            SCLogDebug("ssn %p: 4WHS ssn->client.last_ts %" PRIu32 " "
2240
950
                       "ssn->server.last_ts %" PRIu32 "",
2241
950
                    ssn, ssn->client.last_ts, ssn->server.last_ts);
2242
950
            ssn->flags |= STREAMTCP_FLAG_TIMESTAMP;
2243
950
            ssn->client.last_pkt_ts = (uint32_t)SCTIME_SECS(p->ts);
2244
950
            if (ssn->client.last_ts == 0)
2245
0
                ssn->client.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
2246
2.49k
        } else {
2247
2.49k
            ssn->server.last_ts = 0;
2248
2.49k
            ssn->client.last_ts = 0;
2249
2.49k
            ssn->server.flags &= ~STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
2250
2.49k
        }
2251
2252
3.44k
        ssn->server.last_ack = TCP_GET_RAW_ACK(tcph);
2253
3.44k
        ssn->client.last_ack = ssn->client.isn + 1;
2254
2255
        /** check for the presense of the ws ptr to determine if we
2256
         *  support wscale at all */
2257
3.44k
        if ((ssn->flags & STREAMTCP_FLAG_SERVER_WSCALE) && (TCP_HAS_WSCALE(p))) {
2258
2.92k
            ssn->server.wscale = TCP_GET_WSCALE(p);
2259
2.92k
        } else {
2260
524
            ssn->server.wscale = 0;
2261
524
        }
2262
2263
3.44k
        if ((ssn->flags & STREAMTCP_FLAG_CLIENT_SACKOK) && TCP_GET_SACKOK(p)) {
2264
1.70k
            ssn->flags |= STREAMTCP_FLAG_SACKOK;
2265
1.70k
            SCLogDebug("ssn %p: SACK permitted for 4WHS session", ssn);
2266
1.70k
        }
2267
2268
3.44k
        ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
2269
3.44k
        ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
2270
3.44k
        SCLogDebug("ssn %p: 4WHS ssn->client.next_win %" PRIu32 "", ssn, ssn->client.next_win);
2271
3.44k
        SCLogDebug("ssn %p: 4WHS ssn->server.next_win %" PRIu32 "", ssn, ssn->server.next_win);
2272
3.44k
        SCLogDebug("ssn %p: 4WHS ssn->client.isn %" PRIu32 ", "
2273
3.44k
                   "ssn->client.next_seq %" PRIu32 ", "
2274
3.44k
                   "ssn->client.last_ack %" PRIu32 " "
2275
3.44k
                   "(ssn->server.last_ack %" PRIu32 ")",
2276
3.44k
                ssn, ssn->client.isn, ssn->client.next_seq, ssn->client.last_ack,
2277
3.44k
                ssn->server.last_ack);
2278
2279
        /* done here */
2280
3.44k
        return 0;
2281
5.16k
    }
2282
2283
    /* check for bad responses */
2284
167k
    if (!StateSynSentValidateTimestamp(ssn, p)) {
2285
17.9k
        StreamTcpSetEvent(p, STREAM_PKT_INVALID_TIMESTAMP);
2286
17.9k
        return -1;
2287
17.9k
    }
2288
2289
    /* RST */
2290
149k
    if (tcph->th_flags & TH_RST) {
2291
2292
8.93k
        if (!StreamTcpValidateRst(ssn, p))
2293
6.54k
            return -1;
2294
2295
2.38k
        if (PKT_IS_TOSERVER(p)) {
2296
1.31k
            if (SEQ_EQ(TCP_GET_RAW_SEQ(tcph), ssn->client.isn) &&
2297
0
                    SEQ_EQ(TCP_GET_RAW_WINDOW(tcph), 0) &&
2298
0
                    SEQ_EQ(TCP_GET_RAW_ACK(tcph), (ssn->client.isn + 1))) {
2299
0
                SCLogDebug("ssn->server.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2300
0
                ssn->server.flags |= STREAMTCP_STREAM_FLAG_RST_RECV;
2301
0
                StreamTcpCloseSsnWithReset(p, ssn);
2302
0
                StreamTcp3wsFreeQueue(ssn);
2303
0
            }
2304
1.31k
        } else {
2305
1.07k
            ssn->client.flags |= STREAMTCP_STREAM_FLAG_RST_RECV;
2306
1.07k
            SCLogDebug("ssn->client.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2307
1.07k
            StreamTcpCloseSsnWithReset(p, ssn);
2308
1.07k
            StreamTcp3wsFreeQueue(ssn);
2309
1.07k
        }
2310
2311
        /* FIN */
2312
140k
    } else if (tcph->th_flags & TH_FIN) {
2313
        /** \todo */
2314
2315
123k
    } else if (tcph->th_flags & TH_SYN) {
2316
49.7k
        SCLogDebug("ssn %p: SYN packet on state SYN_SENT... resent", ssn);
2317
49.7k
        if (ssn->flags & STREAMTCP_FLAG_4WHS) {
2318
9.35k
            SCLogDebug("ssn %p: SYN packet on state SYN_SENT... resent of "
2319
9.35k
                    "4WHS SYN", ssn);
2320
9.35k
        }
2321
2322
49.7k
        if (PKT_IS_TOCLIENT(p)) {
2323
            /** a SYN only packet in the opposite direction could be:
2324
             *  http://www.breakingpointsystems.com/community/blog/tcp-
2325
             *  portals-the-three-way-handshake-is-a-lie
2326
             *
2327
             * \todo improve resetting the session */
2328
2329
            /* indicate that we're dealing with 4WHS here */
2330
11.7k
            ssn->flags |= STREAMTCP_FLAG_4WHS;
2331
11.7k
            SCLogDebug("ssn %p: STREAMTCP_FLAG_4WHS flag set", ssn);
2332
2333
            /* set the sequence numbers and window for server
2334
             * We leave the ssn->client.isn in place as we will
2335
             * check the SYN/ACK pkt with that.
2336
             */
2337
11.7k
            ssn->server.isn = TCP_GET_RAW_SEQ(tcph);
2338
11.7k
            STREAMTCP_SET_RA_BASE_SEQ(&ssn->server, ssn->server.isn);
2339
11.7k
            ssn->server.next_seq = ssn->server.isn + 1;
2340
2341
            /* Set the stream timestamp value, if packet has timestamp
2342
             * option enabled. */
2343
11.7k
            if (TCP_HAS_TS(p)) {
2344
8.36k
                ssn->server.last_ts = TCP_GET_TSVAL(p);
2345
8.36k
                SCLogDebug("ssn %p: %02x", ssn, ssn->server.last_ts);
2346
2347
8.36k
                if (ssn->server.last_ts == 0)
2348
18
                    ssn->server.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
2349
8.36k
                ssn->server.last_pkt_ts = (uint32_t)SCTIME_SECS(p->ts);
2350
8.36k
                ssn->server.flags |= STREAMTCP_STREAM_FLAG_TIMESTAMP;
2351
8.36k
            }
2352
2353
11.7k
            ssn->server.window = TCP_GET_RAW_WINDOW(tcph);
2354
11.7k
            if (TCP_HAS_WSCALE(p)) {
2355
11.5k
                ssn->flags |= STREAMTCP_FLAG_SERVER_WSCALE;
2356
11.5k
                ssn->server.wscale = TCP_GET_WSCALE(p);
2357
11.5k
            } else {
2358
292
                ssn->flags &= ~STREAMTCP_FLAG_SERVER_WSCALE;
2359
292
                ssn->server.wscale = 0;
2360
292
            }
2361
2362
11.7k
            if (TCP_GET_SACKOK(p)) {
2363
8.34k
                ssn->flags |= STREAMTCP_FLAG_CLIENT_SACKOK;
2364
8.34k
            } else {
2365
3.44k
                ssn->flags &= ~STREAMTCP_FLAG_CLIENT_SACKOK;
2366
3.44k
            }
2367
2368
11.7k
            SCLogDebug("ssn %p: 4WHS ssn->server.isn %" PRIu32 ", "
2369
11.7k
                    "ssn->server.next_seq %" PRIu32 ", "
2370
11.7k
                    "ssn->server.last_ack %"PRIu32"", ssn,
2371
11.7k
                    ssn->server.isn, ssn->server.next_seq,
2372
11.7k
                    ssn->server.last_ack);
2373
11.7k
            SCLogDebug("ssn %p: 4WHS ssn->client.isn %" PRIu32 ", "
2374
11.7k
                    "ssn->client.next_seq %" PRIu32 ", "
2375
11.7k
                    "ssn->client.last_ack %"PRIu32"", ssn,
2376
11.7k
                    ssn->client.isn, ssn->client.next_seq,
2377
11.7k
                    ssn->client.last_ack);
2378
37.9k
        } else if (PKT_IS_TOSERVER(p)) {
2379
            /* on a SYN resend we queue up the SYN's until a SYN/ACK moves the state
2380
             * to SYN_RECV. We update the ssn to the most recent, as it is most likely
2381
             * to be correct. */
2382
2383
37.9k
            TcpStateQueue syn_pkt, syn_ssn;
2384
37.9k
            TcpStateQueueInitFromPktSyn(p, &syn_pkt);
2385
37.9k
            TcpStateQueueInitFromSsnSyn(ssn, &syn_ssn);
2386
2387
37.9k
            if (memcmp(&syn_pkt, &syn_ssn, sizeof(TcpStateQueue)) != 0) {
2388
                /* store the old session settings */
2389
25.1k
                StreamTcp3whsStoreSyn(ssn, p);
2390
25.1k
                SCLogDebug("ssn %p: Retransmitted SYN. Updating ssn from packet %" PRIu64
2391
25.1k
                           ". Stored previous state",
2392
25.1k
                        ssn, p->pcap_cnt);
2393
25.1k
            }
2394
37.9k
            StreamTcp3whsStoreSynApplyToSsn(ssn, &syn_pkt);
2395
37.9k
        }
2396
73.8k
    } else if (tcph->th_flags & TH_ACK) {
2397
        /* Handle the asynchronous stream, when we receive a  SYN packet
2398
           and now instead of receiving a SYN/ACK we receive a ACK from the
2399
           same host, which sent the SYN, this suggests the ASYNC streams.*/
2400
73.2k
        if (!stream_config.async_oneside)
2401
73.2k
            return 0;
2402
2403
        /* we are in ASYNC (one side) mode now. */
2404
2405
        /* one side async means we won't see a SYN/ACK, so we can
2406
         * only check the SYN. */
2407
0
        if (!(SEQ_EQ(TCP_GET_RAW_SEQ(tcph), ssn->client.next_seq))) {
2408
0
            StreamTcpSetEvent(p, STREAM_3WHS_ASYNC_WRONG_SEQ);
2409
2410
0
            SCLogDebug("ssn %p: SEQ mismatch, packet SEQ %" PRIu32 " != "
2411
0
                       "%" PRIu32 " from stream",
2412
0
                    ssn, TCP_GET_RAW_SEQ(tcph), ssn->client.next_seq);
2413
0
            return -1;
2414
0
        }
2415
2416
0
        ssn->flags |= STREAMTCP_FLAG_ASYNC;
2417
0
        StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
2418
0
        SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2419
0
        StreamTcp3wsFreeQueue(ssn);
2420
2421
0
        ssn->client.window = TCP_GET_RAW_WINDOW(tcph);
2422
0
        ssn->client.last_ack = TCP_GET_RAW_SEQ(tcph);
2423
0
        ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
2424
2425
        /* Set the server side parameters */
2426
0
        ssn->server.isn = TCP_GET_RAW_ACK(tcph) - 1;
2427
0
        STREAMTCP_SET_RA_BASE_SEQ(&ssn->server, ssn->server.isn);
2428
0
        ssn->server.next_seq = ssn->server.isn + 1;
2429
0
        ssn->server.last_ack = ssn->server.next_seq;
2430
0
        ssn->server.next_win = ssn->server.last_ack;
2431
2432
0
        SCLogDebug("ssn %p: synsent => Asynchronous stream, packet SEQ"
2433
0
                   " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "), "
2434
0
                   "ssn->client.next_seq %" PRIu32 "",
2435
0
                ssn, TCP_GET_RAW_SEQ(tcph), p->payload_len, TCP_GET_RAW_SEQ(tcph) + p->payload_len,
2436
0
                ssn->client.next_seq);
2437
2438
        /* if SYN had wscale, assume it to be supported. Otherwise
2439
         * we know it not to be supported. */
2440
0
        if (ssn->flags & STREAMTCP_FLAG_SERVER_WSCALE) {
2441
0
            ssn->client.wscale = TCP_WSCALE_MAX;
2442
0
        }
2443
2444
        /* Set the timestamp values used to validate the timestamp of
2445
         * received packets.*/
2446
0
        if (TCP_HAS_TS(p) &&
2447
0
                (ssn->client.flags & STREAMTCP_STREAM_FLAG_TIMESTAMP))
2448
0
        {
2449
0
            ssn->flags |= STREAMTCP_FLAG_TIMESTAMP;
2450
0
            ssn->client.flags &= ~STREAMTCP_STREAM_FLAG_TIMESTAMP;
2451
0
            ssn->client.last_pkt_ts = (uint32_t)SCTIME_SECS(p->ts);
2452
0
        } else {
2453
0
            ssn->client.last_ts = 0;
2454
0
            ssn->client.flags &= ~STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
2455
0
        }
2456
2457
0
        if (ssn->flags & STREAMTCP_FLAG_CLIENT_SACKOK) {
2458
0
            ssn->flags |= STREAMTCP_FLAG_SACKOK;
2459
0
        }
2460
2461
0
        StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
2462
2463
625
    } else {
2464
625
        SCLogDebug("ssn %p: default case", ssn);
2465
625
    }
2466
2467
69.5k
    return 0;
2468
149k
}
2469
2470
/**
2471
 *  \brief  Function to handle the TCP_SYN_RECV state. The function handles
2472
 *          SYN, SYN/ACK, ACK, FIN, RST packets and correspondingly changes
2473
 *          the connection state.
2474
 *
2475
 *  \param  tv      Thread Variable containing  input/output queue, cpu affinity
2476
 *  \param  p       Packet which has to be handled in this TCP state.
2477
 *  \param  stt     Stream Thread module registered to handle the stream handling
2478
 *
2479
 *  \retval  0 ok
2480
 *  \retval -1 error
2481
 */
2482
2483
static int StreamTcpPacketStateSynRecv(
2484
        ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn)
2485
314k
{
2486
314k
    DEBUG_VALIDATE_BUG_ON(ssn == NULL);
2487
314k
    const TCPHdr *tcph = PacketGetTCP(p);
2488
2489
314k
    if (tcph->th_flags & TH_RST) {
2490
16.3k
        if (!StreamTcpValidateRst(ssn, p))
2491
10.5k
            return -1;
2492
2493
16.3k
        bool reset = true;
2494
        /* After receiving the RST in SYN_RECV state and if detection
2495
           evasion flags has been set, then the following operating
2496
           systems will not closed the connection. As they consider the
2497
           packet as stray packet and not belonging to the current
2498
           session, for more information check
2499
           http://www.packetstan.com/2010/06/recently-ive-been-on-campaign-to-make.html */
2500
5.81k
        if (ssn->flags & STREAMTCP_FLAG_DETECTION_EVASION_ATTEMPT) {
2501
585
            if (PKT_IS_TOSERVER(p)) {
2502
581
                if ((ssn->server.os_policy == OS_POLICY_LINUX) ||
2503
581
                        (ssn->server.os_policy == OS_POLICY_OLD_LINUX) ||
2504
581
                        (ssn->server.os_policy == OS_POLICY_SOLARIS))
2505
0
                {
2506
0
                    reset = false;
2507
0
                    SCLogDebug("Detection evasion has been attempted, so"
2508
0
                            " not resetting the connection !!");
2509
0
                }
2510
581
            } else {
2511
4
                if ((ssn->client.os_policy == OS_POLICY_LINUX) ||
2512
4
                        (ssn->client.os_policy == OS_POLICY_OLD_LINUX) ||
2513
4
                        (ssn->client.os_policy == OS_POLICY_SOLARIS))
2514
0
                {
2515
0
                    reset = false;
2516
0
                    SCLogDebug("Detection evasion has been attempted, so"
2517
0
                            " not resetting the connection !!");
2518
0
                }
2519
4
            }
2520
585
        }
2521
2522
5.81k
        if (reset) {
2523
5.81k
            StreamTcpCloseSsnWithReset(p, ssn);
2524
2525
5.81k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2526
1.42k
                StreamTcpHandleTimestamp(ssn, p);
2527
1.42k
            }
2528
5.81k
        }
2529
2530
298k
    } else if (tcph->th_flags & TH_FIN) {
2531
37.9k
        /* FIN is handled in the same way as in TCP_ESTABLISHED case */;
2532
37.9k
        if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2533
15.6k
            if (!StreamTcpValidateTimestamp(ssn, p))
2534
3.25k
                return -1;
2535
15.6k
        }
2536
2537
34.6k
        if ((StreamTcpHandleFin(tv, stt, ssn, p)) == -1)
2538
18.3k
            return -1;
2539
2540
    /* SYN/ACK */
2541
260k
    } else if ((tcph->th_flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK)) {
2542
69.5k
        SCLogDebug("ssn %p: SYN/ACK packet on state SYN_RECV. resent", ssn);
2543
2544
69.5k
        if (PKT_IS_TOSERVER(p)) {
2545
4.50k
            SCLogDebug("ssn %p: SYN/ACK-pkt to server in SYN_RECV state", ssn);
2546
2547
4.50k
            StreamTcpSetEvent(p, STREAM_3WHS_SYNACK_TOSERVER_ON_SYN_RECV);
2548
4.50k
            return -1;
2549
4.50k
        }
2550
2551
        /* Check if the SYN/ACK packets ACK matches the earlier
2552
         * received SYN/ACK packet. */
2553
65.0k
        if (!(SEQ_EQ(TCP_GET_RAW_ACK(tcph), ssn->client.last_ack))) {
2554
5.80k
            SCLogDebug("ssn %p: ACK mismatch, packet ACK %" PRIu32 " != "
2555
5.80k
                       "%" PRIu32 " from stream",
2556
5.80k
                    ssn, TCP_GET_RAW_ACK(tcph), ssn->client.isn + 1);
2557
2558
5.80k
            StreamTcpSetEvent(p, STREAM_3WHS_SYNACK_RESEND_WITH_DIFFERENT_ACK);
2559
5.80k
            return -1;
2560
5.80k
        }
2561
2562
        /* Check if the SYN/ACK packet SEQ the earlier
2563
         * received SYN/ACK packet, server resend with different ISN. */
2564
59.2k
        if (!(SEQ_EQ(TCP_GET_RAW_SEQ(tcph), ssn->server.isn))) {
2565
14.3k
            SCLogDebug("ssn %p: SEQ mismatch, packet SEQ %" PRIu32 " != "
2566
14.3k
                       "%" PRIu32 " from stream",
2567
14.3k
                    ssn, TCP_GET_RAW_SEQ(tcph), ssn->client.isn);
2568
2569
14.3k
            if (StreamTcp3whsQueueSynAck(ssn, p) == -1)
2570
322
                return -1;
2571
14.0k
            SCLogDebug("ssn %p: queued different SYN/ACK", ssn);
2572
14.0k
        }
2573
2574
190k
    } else if (tcph->th_flags & TH_SYN) {
2575
19.8k
        SCLogDebug("ssn %p: SYN packet on state SYN_RECV... resent", ssn);
2576
2577
19.8k
        if (PKT_IS_TOCLIENT(p)) {
2578
7.68k
            SCLogDebug("ssn %p: SYN-pkt to client in SYN_RECV state", ssn);
2579
2580
7.68k
            StreamTcpSetEvent(p, STREAM_3WHS_SYN_TOCLIENT_ON_SYN_RECV);
2581
7.68k
            return -1;
2582
7.68k
        }
2583
2584
12.1k
        if (!(SEQ_EQ(TCP_GET_RAW_SEQ(tcph), ssn->client.isn))) {
2585
1.08k
            SCLogDebug("ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
2586
2587
1.08k
            StreamTcpSetEvent(p, STREAM_3WHS_SYN_RESEND_DIFF_SEQ_ON_SYN_RECV);
2588
1.08k
            return -1;
2589
1.08k
        }
2590
2591
171k
    } else if (tcph->th_flags & TH_ACK) {
2592
169k
        if (ssn->queue_len) {
2593
7.41k
            SCLogDebug("ssn %p: checking ACK against queued SYN/ACKs", ssn);
2594
7.41k
            TcpStateQueue *q = StreamTcp3whsFindSynAckByAck(ssn, p);
2595
7.41k
            if (q != NULL) {
2596
878
                SCLogDebug("ssn %p: here we update state against queued SYN/ACK", ssn);
2597
878
                StreamTcp3whsSynAckUpdate(ssn, p, /* using queue to update state */q);
2598
6.53k
            } else {
2599
6.53k
                SCLogDebug("ssn %p: none found, now checking ACK against original SYN/ACK (state)", ssn);
2600
6.53k
            }
2601
7.41k
        }
2602
2603
2604
        /* If the timestamp option is enabled for both the streams, then
2605
         * validate the received packet timestamp value against the
2606
         * stream->last_ts. If the timestamp is valid then process the
2607
         * packet normally otherwise the drop the packet (RFC 1323)*/
2608
169k
        if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2609
58.6k
            if (!(StreamTcpValidateTimestamp(ssn, p))) {
2610
11.3k
                return -1;
2611
11.3k
            }
2612
58.6k
        }
2613
2614
158k
        if ((ssn->flags & STREAMTCP_FLAG_4WHS) && PKT_IS_TOCLIENT(p)) {
2615
1.20k
            SCLogDebug("ssn %p: ACK received on 4WHS session",ssn);
2616
2617
1.20k
            if (!(SEQ_EQ(TCP_GET_RAW_SEQ(tcph), ssn->server.next_seq))) {
2618
157
                SCLogDebug("ssn %p: 4WHS wrong seq nr on packet", ssn);
2619
157
                StreamTcpSetEvent(p, STREAM_4WHS_WRONG_SEQ);
2620
157
                return -1;
2621
157
            }
2622
2623
1.04k
            if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
2624
42
                SCLogDebug("ssn %p: 4WHS invalid ack nr on packet", ssn);
2625
42
                StreamTcpSetEvent(p, STREAM_4WHS_INVALID_ACK);
2626
42
                return -1;
2627
42
            }
2628
2629
1.00k
            SCLogDebug("4WHS normal pkt");
2630
1.00k
            SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
2631
1.00k
                       "%" PRIu32 ", ACK %" PRIu32 "",
2632
1.00k
                    ssn, p->payload_len, TCP_GET_RAW_SEQ(tcph), TCP_GET_RAW_ACK(tcph));
2633
2634
1.00k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2635
439
                StreamTcpHandleTimestamp(ssn, p);
2636
439
            }
2637
2638
1.00k
            StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_RAW_ACK(tcph));
2639
1.00k
            StreamTcpUpdateNextSeq(ssn, &ssn->server, (ssn->server.next_seq + p->payload_len));
2640
1.00k
            ssn->client.window = TCP_GET_RAW_WINDOW(tcph) << ssn->client.wscale;
2641
1.00k
            ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
2642
2643
1.00k
            StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
2644
1.00k
            SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2645
2646
1.00k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
2647
2648
1.00k
            SCLogDebug("ssn %p: ssn->client.next_win %" PRIu32 ", "
2649
1.00k
                    "ssn->client.last_ack %"PRIu32"", ssn,
2650
1.00k
                    ssn->client.next_win, ssn->client.last_ack);
2651
1.00k
            return 0;
2652
1.04k
        }
2653
2654
158k
        bool ack_indicates_missed_3whs_ack_packet = false;
2655
        /* Check if the ACK received is in right direction. But when we have
2656
         * picked up a mid stream session after missing the initial SYN pkt,
2657
         * in this case the ACK packet can arrive from either client (normal
2658
         * case) or from server itself (asynchronous streams). Therefore
2659
         *  the check has been avoided in this case */
2660
156k
        if (PKT_IS_TOCLIENT(p)) {
2661
            /* special case, handle 4WHS, so SYN/ACK in the opposite
2662
             * direction */
2663
42.9k
            if (ssn->flags & STREAMTCP_FLAG_MIDSTREAM_SYNACK) {
2664
38.3k
                SCLogDebug("ssn %p: ACK received on midstream SYN/ACK "
2665
38.3k
                        "pickup session",ssn);
2666
                /* fall through */
2667
38.3k
            } else if (ssn->flags & STREAMTCP_FLAG_TCP_FAST_OPEN) {
2668
1.86k
                SCLogDebug("ssn %p: ACK received on TFO session",ssn);
2669
                /* fall through */
2670
2671
2.75k
            } else {
2672
                /* if we missed traffic between the S/SA and the current
2673
                 * 'wrong direction' ACK, we could end up here. In IPS
2674
                 * reject it. But in IDS mode we continue.
2675
                 *
2676
                 * IPS rejects as it should see all packets, so pktloss
2677
                 * should lead to retransmissions. As this can also be
2678
                 * pattern for MOTS/MITM injection attacks, we need to be
2679
                 * careful.
2680
                 */
2681
2.75k
                if (StreamTcpInlineMode()) {
2682
0
                    if (p->payload_len > 0 && SEQ_EQ(TCP_GET_RAW_ACK(tcph), ssn->client.last_ack) &&
2683
0
                            SEQ_EQ(TCP_GET_RAW_SEQ(tcph), ssn->server.next_seq)) {
2684
                        /* packet loss is possible but unlikely here */
2685
0
                        SCLogDebug("ssn %p: possible data injection", ssn);
2686
0
                        StreamTcpSetEvent(p, STREAM_3WHS_ACK_DATA_INJECT);
2687
0
                        return -1;
2688
0
                    }
2689
2690
0
                    SCLogDebug("ssn %p: ACK received in the wrong direction",
2691
0
                            ssn);
2692
0
                    StreamTcpSetEvent(p, STREAM_3WHS_ACK_IN_WRONG_DIR);
2693
0
                    return -1;
2694
0
                }
2695
2.75k
                ack_indicates_missed_3whs_ack_packet = true;
2696
2.75k
            }
2697
42.9k
        }
2698
2699
156k
        SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ %" PRIu32 ""
2700
156k
                   ", ACK %" PRIu32 "",
2701
156k
                ssn, p->payload_len, TCP_GET_RAW_SEQ(tcph), TCP_GET_RAW_ACK(tcph));
2702
2703
        /* Check both seq and ack number before accepting the packet and
2704
           changing to ESTABLISHED state */
2705
156k
        if ((SEQ_EQ(TCP_GET_RAW_SEQ(tcph), ssn->client.next_seq)) &&
2706
85.9k
                SEQ_EQ(TCP_GET_RAW_ACK(tcph), ssn->server.next_seq)) {
2707
78.9k
            SCLogDebug("normal pkt");
2708
2709
            /* process the packet normal, No Async streams :) */
2710
2711
78.9k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2712
21.3k
                StreamTcpHandleTimestamp(ssn, p);
2713
21.3k
            }
2714
2715
78.9k
            StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_RAW_ACK(tcph));
2716
78.9k
            StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
2717
78.9k
            ssn->server.window = TCP_GET_RAW_WINDOW(tcph) << ssn->server.wscale;
2718
2719
78.9k
            ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
2720
2721
78.9k
            if (ssn->flags & STREAMTCP_FLAG_MIDSTREAM) {
2722
21.1k
                ssn->client.window = TCP_GET_RAW_WINDOW(tcph) << ssn->client.wscale;
2723
21.1k
                ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
2724
21.1k
                ssn->server.next_win = ssn->server.last_ack +
2725
21.1k
                    ssn->server.window;
2726
21.1k
                if (!(ssn->flags & STREAMTCP_FLAG_MIDSTREAM_SYNACK)) {
2727
                    /* window scaling for midstream pickups, we can't do much
2728
                     * other than assume that it's set to the max value: 14 */
2729
0
                    ssn->server.wscale = TCP_WSCALE_MAX;
2730
0
                    ssn->client.wscale = TCP_WSCALE_MAX;
2731
0
                    ssn->flags |= STREAMTCP_FLAG_SACKOK;
2732
0
                }
2733
21.1k
            }
2734
2735
78.9k
            StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
2736
78.9k
            SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2737
2738
            /* special case: normally the packet following the 3whs is
2739
             * considered flow established, but with data we need it to
2740
             * be established now. This can happen if the original ACK was
2741
             * lost. */
2742
78.9k
            if (p->payload_len) {
2743
9.02k
                p->flowflags |= FLOW_PKT_ESTABLISHED;
2744
9.02k
            }
2745
2746
78.9k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
2747
2748
            /* If asynchronous stream handling is allowed then set the session,
2749
               if packet's seq number is equal the expected seq no.*/
2750
78.9k
        } else if (stream_config.async_oneside &&
2751
0
                   (SEQ_EQ(TCP_GET_RAW_SEQ(tcph), ssn->server.next_seq))) {
2752
            /*set the ASYNC flag used to indicate the session as async stream
2753
              and helps in relaxing the windows checks.*/
2754
0
            ssn->flags |= STREAMTCP_FLAG_ASYNC;
2755
0
            ssn->server.next_seq += p->payload_len;
2756
0
            ssn->server.last_ack = TCP_GET_RAW_SEQ(tcph);
2757
2758
0
            ssn->client.window = TCP_GET_RAW_WINDOW(tcph) << ssn->client.wscale;
2759
0
            ssn->client.last_ack = TCP_GET_RAW_ACK(tcph);
2760
2761
0
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2762
0
                StreamTcpHandleTimestamp(ssn, p);
2763
0
            }
2764
2765
0
            if (ssn->flags & STREAMTCP_FLAG_MIDSTREAM) {
2766
0
                ssn->server.window = TCP_GET_RAW_WINDOW(tcph);
2767
0
                ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
2768
                /* window scaling for midstream pickups, we can't do much
2769
                 * other than assume that it's set to the max value: 14 */
2770
0
                ssn->server.wscale = TCP_WSCALE_MAX;
2771
0
                ssn->client.wscale = TCP_WSCALE_MAX;
2772
0
                ssn->flags |= STREAMTCP_FLAG_SACKOK;
2773
0
            }
2774
2775
0
            SCLogDebug("ssn %p: synrecv => Asynchronous stream, packet SEQ"
2776
0
                       " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "), "
2777
0
                       "ssn->server.next_seq %" PRIu32,
2778
0
                    ssn, TCP_GET_RAW_SEQ(tcph), p->payload_len,
2779
0
                    TCP_GET_RAW_SEQ(tcph) + p->payload_len, ssn->server.next_seq);
2780
2781
0
            StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
2782
0
            SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2783
2784
0
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
2785
            /* Upon receiving the packet with correct seq number and wrong
2786
               ACK number, it causes the other end to send RST. But some target
2787
               system (Linux & solaris) does not RST the connection, so it is
2788
               likely to avoid the detection */
2789
77.8k
        } else if (SEQ_EQ(TCP_GET_RAW_SEQ(tcph), ssn->client.next_seq)) {
2790
6.96k
            ssn->flags |= STREAMTCP_FLAG_DETECTION_EVASION_ATTEMPT;
2791
6.96k
            SCLogDebug("ssn %p: wrong ack nr on packet, possible evasion!!",
2792
6.96k
                    ssn);
2793
2794
6.96k
            StreamTcpSetEvent(p, STREAM_3WHS_RIGHT_SEQ_WRONG_ACK_EVASION);
2795
6.96k
            return -1;
2796
2797
            /* SYN/ACK followed by more TOCLIENT suggesting packet loss */
2798
70.8k
        } else if (PKT_IS_TOCLIENT(p) && !StreamTcpInlineMode() &&
2799
41.6k
                   SEQ_GT(TCP_GET_RAW_SEQ(tcph), ssn->client.next_seq) &&
2800
11.0k
                   SEQ_GT(TCP_GET_RAW_ACK(tcph), ssn->client.last_ack)) {
2801
8.11k
            SCLogDebug("ssn %p: ACK for missing data", ssn);
2802
2803
8.11k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2804
5.27k
                StreamTcpHandleTimestamp(ssn, p);
2805
5.27k
            }
2806
2807
8.11k
            StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_RAW_ACK(tcph));
2808
2809
8.11k
            ssn->server.next_seq = TCP_GET_RAW_SEQ(tcph) + p->payload_len;
2810
8.11k
            SCLogDebug("ssn %p: ACK for missing data: ssn->server.next_seq %u", ssn,
2811
8.11k
                    ssn->server.next_seq);
2812
8.11k
            ssn->client.window = TCP_GET_RAW_WINDOW(tcph) << ssn->client.wscale;
2813
2814
8.11k
            ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
2815
2816
8.11k
            ssn->client.window = TCP_GET_RAW_WINDOW(tcph);
2817
8.11k
            ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
2818
2819
8.11k
            StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
2820
8.11k
            SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2821
2822
8.11k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
2823
2824
            /* if we get a packet with a proper ack, but a seq that is beyond
2825
             * next_seq but in-window, we probably missed some packets */
2826
62.7k
        } else if (SEQ_GT(TCP_GET_RAW_SEQ(tcph), ssn->client.next_seq) &&
2827
29.8k
                   SEQ_LEQ(TCP_GET_RAW_SEQ(tcph), ssn->client.next_win) &&
2828
23.8k
                   SEQ_EQ(TCP_GET_RAW_ACK(tcph), ssn->server.next_seq)) {
2829
7.50k
            SCLogDebug("ssn %p: ACK for missing data", ssn);
2830
2831
7.50k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
2832
598
                StreamTcpHandleTimestamp(ssn, p);
2833
598
            }
2834
2835
7.50k
            ssn->client.next_seq = TCP_GET_RAW_SEQ(tcph) + p->payload_len;
2836
7.50k
            StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_RAW_ACK(tcph));
2837
2838
7.50k
            SCLogDebug("ssn %p: ACK for missing data: ssn->client.next_seq %u", ssn, ssn->client.next_seq);
2839
7.50k
            ssn->server.window = TCP_GET_RAW_WINDOW(tcph) << ssn->server.wscale;
2840
7.50k
            ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
2841
2842
7.50k
            if (ssn->flags & STREAMTCP_FLAG_MIDSTREAM) {
2843
7.04k
                ssn->client.window = TCP_GET_RAW_WINDOW(tcph);
2844
7.04k
                ssn->server.next_win = ssn->server.last_ack +
2845
7.04k
                    ssn->server.window;
2846
                /* window scaling for midstream pickups, we can't do much
2847
                 * other than assume that it's set to the max value: 14 */
2848
7.04k
                ssn->server.wscale = TCP_WSCALE_MAX;
2849
7.04k
                ssn->client.wscale = TCP_WSCALE_MAX;
2850
7.04k
                ssn->flags |= STREAMTCP_FLAG_SACKOK;
2851
7.04k
            }
2852
2853
7.50k
            StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
2854
7.50k
            SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2855
2856
7.50k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
2857
2858
            /* toclient packet: after having missed the 3whs's final ACK */
2859
55.2k
        } else if ((ack_indicates_missed_3whs_ack_packet ||
2860
52.8k
                           (ssn->flags & STREAMTCP_FLAG_TCP_FAST_OPEN)) &&
2861
4.96k
                   SEQ_EQ(TCP_GET_RAW_ACK(tcph), ssn->client.last_ack) &&
2862
744
                   SEQ_EQ(TCP_GET_RAW_SEQ(tcph), ssn->server.next_seq)) {
2863
623
            if (ack_indicates_missed_3whs_ack_packet) {
2864
615
                SCLogDebug("ssn %p: packet fits perfectly after a missed 3whs-ACK", ssn);
2865
615
            } else {
2866
8
                SCLogDebug("ssn %p: (TFO) expected packet fits perfectly after SYN/ACK", ssn);
2867
8
            }
2868
2869
623
            StreamTcpUpdateNextSeq(ssn, &ssn->server, (TCP_GET_RAW_SEQ(tcph) + p->payload_len));
2870
2871
623
            ssn->server.window = TCP_GET_RAW_WINDOW(tcph) << ssn->server.wscale;
2872
623
            ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
2873
2874
623
            StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
2875
623
            SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2876
2877
623
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
2878
2879
54.6k
        } else {
2880
54.6k
            SCLogDebug("ssn %p: wrong seq nr on packet", ssn);
2881
2882
54.6k
            StreamTcpSetEvent(p, STREAM_3WHS_WRONG_SEQ_WRONG_ACK);
2883
54.6k
            return -1;
2884
54.6k
        }
2885
2886
95.1k
        SCLogDebug("ssn %p: ssn->server.next_win %" PRIu32 ", "
2887
95.1k
                "ssn->server.last_ack %"PRIu32"", ssn,
2888
95.1k
                ssn->server.next_win, ssn->server.last_ack);
2889
95.1k
    } else {
2890
1.70k
        SCLogDebug("ssn %p: default case", ssn);
2891
1.70k
    }
2892
2893
189k
    return 0;
2894
314k
}
2895
2896
/**
2897
 *  \brief  Function to handle the TCP_ESTABLISHED state packets, which are
2898
 *          sent by the client to server. The function handles
2899
 *          ACK packets and call StreamTcpReassembleHandleSegment() to handle
2900
 *          the reassembly.
2901
 *
2902
 *  Timestamp has already been checked at this point.
2903
 *
2904
 *  \param  tv      Thread Variable containing  input/output queue, cpu affinity etc.
2905
 *  \param  ssn     Pointer to the current TCP session
2906
 *  \param  p       Packet which has to be handled in this TCP state.
2907
 *  \param  stt     Stream Thread module registered to handle the stream handling
2908
 */
2909
static int HandleEstablishedPacketToServer(
2910
        ThreadVars *tv, TcpSession *ssn, Packet *p, StreamTcpThread *stt)
2911
3.47M
{
2912
3.47M
    const TCPHdr *tcph = PacketGetTCP(p);
2913
3.47M
    const uint32_t seq = TCP_GET_RAW_SEQ(tcph);
2914
3.47M
    const uint32_t ack = TCP_GET_RAW_ACK(tcph);
2915
3.47M
    const uint16_t window = TCP_GET_RAW_WINDOW(tcph);
2916
2917
3.47M
    SCLogDebug("ssn %p: =+ pkt (%" PRIu32 ") is to server: SEQ %" PRIu32 ","
2918
3.47M
               "ACK %" PRIu32 ", WIN %" PRIu16 "",
2919
3.47M
            ssn, p->payload_len, seq, ack, window);
2920
2921
3.47M
    const bool has_ack = (tcph->th_flags & TH_ACK) != 0;
2922
3.47M
    if (has_ack) {
2923
3.47M
        if ((ssn->flags & STREAMTCP_FLAG_ZWP_TC) && ack == ssn->server.next_seq + 1) {
2924
0
            SCLogDebug("ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
2925
0
            StreamTcpSetEvent(p, STREAM_EST_ACK_ZWP_DATA);
2926
2927
3.47M
        } else if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
2928
32.5k
            SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
2929
32.5k
            StreamTcpSetEvent(p, STREAM_EST_INVALID_ACK);
2930
32.5k
            return -1;
2931
32.5k
        }
2932
3.47M
    }
2933
2934
    /* check for Keep Alive */
2935
3.44M
    if ((p->payload_len == 0 || p->payload_len == 1) && (seq == (ssn->client.next_seq - 1))) {
2936
794
        SCLogDebug("ssn %p: pkt is keep alive", ssn);
2937
2938
    /* normal pkt */
2939
3.44M
    } else if (!(SEQ_GEQ((seq + p->payload_len), ssn->client.last_ack))) {
2940
142k
        if (ssn->flags & STREAMTCP_FLAG_ASYNC) {
2941
0
            SCLogDebug("ssn %p: server => Asynchronous stream, packet SEQ"
2942
0
                       " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "),"
2943
0
                       " ssn->client.last_ack %" PRIu32 ", ssn->client.next_win"
2944
0
                       "%" PRIu32 "(%" PRIu32 ")",
2945
0
                    ssn, seq, p->payload_len, seq + p->payload_len, ssn->client.last_ack,
2946
0
                    ssn->client.next_win, seq + p->payload_len - ssn->client.next_win);
2947
2948
            /* update the last_ack to current seq number as the session is
2949
             * async and other stream is not updating it anymore :( */
2950
0
            StreamTcpUpdateLastAck(ssn, &ssn->client, seq);
2951
2952
142k
        } else if (SEQ_EQ(ssn->client.next_seq, seq) && stream_config.async_oneside &&
2953
0
                   (ssn->flags & STREAMTCP_FLAG_MIDSTREAM)) {
2954
0
            SCLogDebug("ssn %p: server => Asynchronous stream, packet SEQ."
2955
0
                       " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "), "
2956
0
                       "ssn->client.last_ack %" PRIu32 ", ssn->client.next_win "
2957
0
                       "%" PRIu32 "(%" PRIu32 ")",
2958
0
                    ssn, seq, p->payload_len, seq + p->payload_len, ssn->client.last_ack,
2959
0
                    ssn->client.next_win, seq + p->payload_len - ssn->client.next_win);
2960
2961
            /* it seems we missed SYN and SYN/ACK packets of this session.
2962
             * Update the last_ack to current seq number as the session
2963
             * is async and other stream is not updating it anymore :( */
2964
0
            StreamTcpUpdateLastAck(ssn, &ssn->client, seq);
2965
0
            ssn->flags |= STREAMTCP_FLAG_ASYNC;
2966
2967
142k
        } else if (SEQ_EQ(ssn->client.last_ack, (ssn->client.isn + 1)) &&
2968
11.1k
                   stream_config.async_oneside && (ssn->flags & STREAMTCP_FLAG_MIDSTREAM)) {
2969
0
            SCLogDebug("ssn %p: server => Asynchronous stream, packet SEQ"
2970
0
                       " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "), "
2971
0
                       "ssn->client.last_ack %" PRIu32 ", ssn->client.next_win "
2972
0
                       "%" PRIu32 "(%" PRIu32 ")",
2973
0
                    ssn, seq, p->payload_len, seq + p->payload_len, ssn->client.last_ack,
2974
0
                    ssn->client.next_win, seq + p->payload_len - ssn->client.next_win);
2975
2976
            /* it seems we missed SYN and SYN/ACK packets of this session.
2977
             * Update the last_ack to current seq number as the session
2978
             * is async and other stream is not updating it anymore :(*/
2979
0
            StreamTcpUpdateLastAck(ssn, &ssn->client, seq);
2980
0
            ssn->flags |= STREAMTCP_FLAG_ASYNC;
2981
2982
        /* if last ack is beyond next_seq, we have accepted ack's for missing data.
2983
         * In this case we do accept the data before last_ack if it is (partly)
2984
         * beyond next seq */
2985
142k
        } else if (SEQ_GT(ssn->client.last_ack, ssn->client.next_seq) &&
2986
33.0k
                   SEQ_GT((seq + p->payload_len), ssn->client.next_seq)) {
2987
6.47k
            SCLogDebug("ssn %p: PKT SEQ %" PRIu32 " payload_len %" PRIu16
2988
6.47k
                       " before last_ack %" PRIu32 ", after next_seq %" PRIu32 ":"
2989
6.47k
                       " acked data that we haven't seen before",
2990
6.47k
                    ssn, seq, p->payload_len, ssn->client.last_ack, ssn->client.next_seq);
2991
135k
        } else {
2992
135k
            SCLogDebug("ssn %p: server => SEQ before last_ack, packet SEQ"
2993
135k
                       " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "), "
2994
135k
                       "ssn->client.last_ack %" PRIu32 ", ssn->client.next_win "
2995
135k
                       "%" PRIu32 "(%" PRIu32 ")",
2996
135k
                    ssn, seq, p->payload_len, seq + p->payload_len, ssn->client.last_ack,
2997
135k
                    ssn->client.next_win, seq + p->payload_len - ssn->client.next_win);
2998
2999
135k
            SCLogDebug("ssn %p: rejecting because pkt before last_ack", ssn);
3000
135k
            StreamTcpSetEvent(p, STREAM_EST_PKT_BEFORE_LAST_ACK);
3001
135k
            return -1;
3002
135k
        }
3003
142k
    }
3004
3005
3.30M
    int zerowindowprobe = 0;
3006
    /* zero window probe */
3007
3.30M
    if (p->payload_len == 1 && seq == ssn->client.next_seq && ssn->client.window == 0) {
3008
160
        SCLogDebug("ssn %p: zero window probe", ssn);
3009
160
        zerowindowprobe = 1;
3010
160
        STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_TCP_ZERO_WIN_PROBE);
3011
160
        ssn->flags |= STREAMTCP_FLAG_ZWP_TS;
3012
160
        StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
3013
3014
3.30M
    } else if (SEQ_GEQ(seq + p->payload_len, ssn->client.next_seq)) {
3015
3.20M
        StreamTcpUpdateNextSeq(ssn, &ssn->client, (seq + p->payload_len));
3016
3.20M
    }
3017
3018
    /* in window check */
3019
3.30M
    if (zerowindowprobe) {
3020
160
        SCLogDebug("ssn %p: zero window probe, skipping oow check", ssn);
3021
3.30M
    } else if (SEQ_LEQ(seq + p->payload_len, ssn->client.next_win) ||
3022
3.23M
               (ssn->flags & (STREAMTCP_FLAG_MIDSTREAM | STREAMTCP_FLAG_ASYNC))) {
3023
3.23M
        SCLogDebug("ssn %p: seq %" PRIu32 " in window, ssn->client.next_win "
3024
3.23M
                   "%" PRIu32 "",
3025
3.23M
                ssn, seq, ssn->client.next_win);
3026
3027
3.23M
        ssn->server.window = window << ssn->server.wscale;
3028
3.23M
        SCLogDebug("ssn %p: ssn->server.window %"PRIu32"", ssn,
3029
3.23M
                    ssn->server.window);
3030
3031
        /* Check if the ACK value is sane and inside the window limit */
3032
3.23M
        if (tcph->th_flags & TH_ACK) {
3033
3.23M
            StreamTcpUpdateLastAck(ssn, &ssn->server, ack);
3034
3.23M
            if ((ssn->flags & STREAMTCP_FLAG_ASYNC) == 0 &&
3035
3.23M
                    SEQ_GT(ssn->server.last_ack, ssn->server.next_seq)) {
3036
99.6k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_ACK_UNSEEN_DATA);
3037
99.6k
                StatsIncr(tv, stt->counter_tcp_ack_unseen_data);
3038
99.6k
            }
3039
3.23M
        }
3040
3041
3.23M
        SCLogDebug(
3042
3.23M
                "ack %u last_ack %u next_seq %u", ack, ssn->server.last_ack, ssn->server.next_seq);
3043
3044
3.23M
        if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3045
403k
            StreamTcpHandleTimestamp(ssn, p);
3046
403k
        }
3047
3048
3.23M
        StreamTcpSackUpdatePacket(&ssn->server, p);
3049
3050
        /* update next_win */
3051
3.23M
        StreamTcpUpdateNextWin(ssn, &ssn->server, (ssn->server.last_ack + ssn->server.window));
3052
3053
        /* handle data (if any) */
3054
3.23M
        StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
3055
3056
3.23M
    } else {
3057
77.0k
        SCLogDebug("ssn %p: toserver => SEQ out of window, packet SEQ "
3058
77.0k
                   "%" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "),"
3059
77.0k
                   "ssn->client.last_ack %" PRIu32 ", ssn->client.next_win "
3060
77.0k
                   "%" PRIu32 "(%" PRIu32 ")",
3061
77.0k
                ssn, seq, p->payload_len, seq + p->payload_len, ssn->client.last_ack,
3062
77.0k
                ssn->client.next_win, (seq + p->payload_len) - ssn->client.next_win);
3063
77.0k
        SCLogDebug("ssn %p: window %u sacked %u", ssn, ssn->client.window,
3064
77.0k
                StreamTcpSackedSize(&ssn->client));
3065
77.0k
        StreamTcpSetEvent(p, STREAM_EST_PACKET_OUT_OF_WINDOW);
3066
77.0k
        return -1;
3067
77.0k
    }
3068
3.23M
    return 0;
3069
3.30M
}
3070
3071
/**
3072
 *  \brief  Function to handle the TCP_ESTABLISHED state packets, which are
3073
 *          sent by the server to client. The function handles
3074
 *          ACK packets and call StreamTcpReassembleHandleSegment() to handle
3075
 *          the reassembly
3076
 *
3077
 *  Timestamp has already been checked at this point.
3078
 *
3079
 *  \param  tv      Thread Variable containing  input/output queue, cpu affinity etc.
3080
 *  \param  ssn     Pointer to the current TCP session
3081
 *  \param  p       Packet which has to be handled in this TCP state.
3082
 *  \param  stt     Stream Thread module registered to handle the stream handling
3083
 */
3084
static int HandleEstablishedPacketToClient(
3085
        ThreadVars *tv, TcpSession *ssn, Packet *p, StreamTcpThread *stt)
3086
2.80M
{
3087
2.80M
    const TCPHdr *tcph = PacketGetTCP(p);
3088
2.80M
    const uint32_t seq = TCP_GET_RAW_SEQ(tcph);
3089
2.80M
    const uint32_t ack = TCP_GET_RAW_ACK(tcph);
3090
2.80M
    const uint16_t window = TCP_GET_RAW_WINDOW(tcph);
3091
3092
2.80M
    SCLogDebug("ssn %p: =+ pkt (%" PRIu32 ") is to client: SEQ %" PRIu32 ","
3093
2.80M
               " ACK %" PRIu32 ", WIN %" PRIu16 "",
3094
2.80M
            ssn, p->payload_len, seq, ack, window);
3095
3096
2.80M
    const bool has_ack = (tcph->th_flags & TH_ACK) != 0;
3097
2.80M
    if (has_ack) {
3098
2.80M
        if ((ssn->flags & STREAMTCP_FLAG_ZWP_TS) && ack == ssn->client.next_seq + 1) {
3099
0
            SCLogDebug("ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
3100
0
            StreamTcpSetEvent(p, STREAM_EST_ACK_ZWP_DATA);
3101
3102
2.80M
        } else if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
3103
34.0k
            SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3104
34.0k
            StreamTcpSetEvent(p, STREAM_EST_INVALID_ACK);
3105
34.0k
            return -1;
3106
34.0k
        }
3107
2.80M
    }
3108
3109
    /* To get the server window value from the servers packet, when connection
3110
       is picked up as midstream */
3111
2.77M
    if ((ssn->flags & STREAMTCP_FLAG_MIDSTREAM) &&
3112
425k
            (ssn->flags & STREAMTCP_FLAG_MIDSTREAM_ESTABLISHED))
3113
48.4k
    {
3114
48.4k
        ssn->server.window = window << ssn->server.wscale;
3115
48.4k
        ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
3116
48.4k
        ssn->flags &= ~STREAMTCP_FLAG_MIDSTREAM_ESTABLISHED;
3117
48.4k
        SCLogDebug("ssn %p: adjusted midstream ssn->server.next_win to "
3118
48.4k
                "%" PRIu32 "", ssn, ssn->server.next_win);
3119
48.4k
    }
3120
3121
    /* check for Keep Alive */
3122
2.77M
    if ((p->payload_len == 0 || p->payload_len == 1) && (seq == (ssn->server.next_seq - 1))) {
3123
3.20k
        SCLogDebug("ssn %p: pkt is keep alive", ssn);
3124
3125
    /* normal pkt */
3126
2.77M
    } else if (!(SEQ_GEQ((seq + p->payload_len), ssn->server.last_ack))) {
3127
109k
        if (ssn->flags & STREAMTCP_FLAG_ASYNC) {
3128
3129
0
            SCLogDebug("ssn %p: client => Asynchronous stream, packet SEQ"
3130
0
                       " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "),"
3131
0
                       " ssn->client.last_ack %" PRIu32 ", ssn->client.next_win"
3132
0
                       " %" PRIu32 "(%" PRIu32 ")",
3133
0
                    ssn, seq, p->payload_len, seq + p->payload_len, ssn->server.last_ack,
3134
0
                    ssn->server.next_win, seq + p->payload_len - ssn->server.next_win);
3135
3136
0
            ssn->server.last_ack = seq;
3137
3138
            /* if last ack is beyond next_seq, we have accepted ack's for missing data.
3139
             * In this case we do accept the data before last_ack if it is (partly)
3140
             * beyond next seq */
3141
109k
        } else if (SEQ_GT(ssn->server.last_ack, ssn->server.next_seq) &&
3142
29.7k
                   SEQ_GT((seq + p->payload_len), ssn->server.next_seq)) {
3143
6.83k
            SCLogDebug("ssn %p: PKT SEQ %" PRIu32 " payload_len %" PRIu16
3144
6.83k
                       " before last_ack %" PRIu32 ", after next_seq %" PRIu32 ":"
3145
6.83k
                       " acked data that we haven't seen before",
3146
6.83k
                    ssn, seq, p->payload_len, ssn->server.last_ack, ssn->server.next_seq);
3147
102k
        } else {
3148
102k
            SCLogDebug("ssn %p: PKT SEQ %" PRIu32 " payload_len %" PRIu16
3149
102k
                       " before last_ack %" PRIu32 ". next_seq %" PRIu32,
3150
102k
                    ssn, seq, p->payload_len, ssn->server.last_ack, ssn->server.next_seq);
3151
102k
            StreamTcpSetEvent(p, STREAM_EST_PKT_BEFORE_LAST_ACK);
3152
102k
            return -1;
3153
102k
        }
3154
109k
    }
3155
3156
2.67M
    int zerowindowprobe = 0;
3157
    /* zero window probe */
3158
2.67M
    if (p->payload_len == 1 && seq == ssn->server.next_seq && ssn->server.window == 0) {
3159
503
        SCLogDebug("ssn %p: zero window probe", ssn);
3160
503
        zerowindowprobe = 1;
3161
503
        STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_TCP_ZERO_WIN_PROBE);
3162
503
        ssn->flags |= STREAMTCP_FLAG_ZWP_TC;
3163
3164
        /* accept the segment */
3165
503
        StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
3166
3167
2.67M
    } else if (SEQ_GEQ(seq + p->payload_len, ssn->server.next_seq)) {
3168
2.62M
        StreamTcpUpdateNextSeq(ssn, &ssn->server, (seq + p->payload_len));
3169
2.62M
    }
3170
3171
2.67M
    if (zerowindowprobe) {
3172
503
        SCLogDebug("ssn %p: zero window probe, skipping oow check", ssn);
3173
2.67M
    } else if (SEQ_LEQ(seq + p->payload_len, ssn->server.next_win) ||
3174
2.56M
               (ssn->flags & (STREAMTCP_FLAG_MIDSTREAM | STREAMTCP_FLAG_ASYNC))) {
3175
2.56M
        SCLogDebug("ssn %p: seq %" PRIu32 " in window, ssn->server.next_win "
3176
2.56M
                   "%" PRIu32 "",
3177
2.56M
                ssn, seq, ssn->server.next_win);
3178
2.56M
        ssn->client.window = window << ssn->client.wscale;
3179
2.56M
        SCLogDebug("ssn %p: ssn->client.window %"PRIu32"", ssn,
3180
2.56M
                    ssn->client.window);
3181
3182
2.56M
        if (tcph->th_flags & TH_ACK) {
3183
2.56M
            StreamTcpUpdateLastAck(ssn, &ssn->client, ack);
3184
2.56M
            if ((ssn->flags & STREAMTCP_FLAG_ASYNC) == 0 &&
3185
2.56M
                    SEQ_GT(ssn->client.last_ack, ssn->client.next_seq)) {
3186
68.9k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_ACK_UNSEEN_DATA);
3187
68.9k
                StatsIncr(tv, stt->counter_tcp_ack_unseen_data);
3188
68.9k
            }
3189
2.56M
        }
3190
3191
2.56M
        if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3192
290k
            StreamTcpHandleTimestamp(ssn, p);
3193
290k
        }
3194
3195
2.56M
        StreamTcpSackUpdatePacket(&ssn->client, p);
3196
3197
2.56M
        StreamTcpUpdateNextWin(ssn, &ssn->client, (ssn->client.last_ack + ssn->client.window));
3198
3199
2.56M
        StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
3200
2.56M
    } else {
3201
103k
        SCLogDebug("ssn %p: client => SEQ out of window, packet SEQ"
3202
103k
                   "%" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "),"
3203
103k
                   " ssn->server.last_ack %" PRIu32 ", ssn->server.next_win "
3204
103k
                   "%" PRIu32 "(%" PRIu32 ")",
3205
103k
                ssn, seq, p->payload_len, seq + p->payload_len, ssn->server.last_ack,
3206
103k
                ssn->server.next_win, seq + p->payload_len - ssn->server.next_win);
3207
103k
        StreamTcpSetEvent(p, STREAM_EST_PACKET_OUT_OF_WINDOW);
3208
103k
        return -1;
3209
103k
    }
3210
2.56M
    return 0;
3211
2.67M
}
3212
3213
static bool StreamTcpPacketIsZeroWindowProbeAck(const TcpSession *ssn, const Packet *p)
3214
9.25M
{
3215
9.25M
    const TCPHdr *tcph = PacketGetTCP(p);
3216
9.25M
    if (ssn->state < TCP_ESTABLISHED)
3217
593k
        return false;
3218
8.65M
    if (p->payload_len != 0)
3219
6.77M
        return false;
3220
1.88M
    if ((tcph->th_flags & (TH_ACK | TH_SYN | TH_FIN | TH_RST)) != TH_ACK)
3221
521k
        return false;
3222
3223
1.36M
    const TcpStream *snd, *rcv;
3224
1.36M
    if (PKT_IS_TOCLIENT(p)) {
3225
633k
        snd = &ssn->server;
3226
633k
        rcv = &ssn->client;
3227
633k
        if (!(ssn->flags & STREAMTCP_FLAG_ZWP_TS))
3228
633k
            return false;
3229
733k
    } else {
3230
733k
        snd = &ssn->client;
3231
733k
        rcv = &ssn->server;
3232
733k
        if (!(ssn->flags & STREAMTCP_FLAG_ZWP_TC))
3233
732k
            return false;
3234
733k
    }
3235
3236
624
    const uint32_t pkt_win = TCP_GET_RAW_WINDOW(tcph) << snd->wscale;
3237
624
    if (pkt_win != 0)
3238
159
        return false;
3239
465
    if (pkt_win != rcv->window)
3240
0
        return false;
3241
3242
465
    if (TCP_GET_RAW_SEQ(tcph) != snd->next_seq)
3243
290
        return false;
3244
175
    if (TCP_GET_RAW_ACK(tcph) != rcv->last_ack)
3245
143
        return false;
3246
32
    SCLogDebug("ssn %p: packet %" PRIu64 " is a Zero Window Probe ACK", ssn, p->pcap_cnt);
3247
32
    return true;
3248
175
}
3249
3250
/** \internal
3251
 *  \brief check if an ACK packet is a dup-ACK
3252
 */
3253
static bool StreamTcpPacketIsDupAck(const TcpSession *ssn, const Packet *p)
3254
9.25M
{
3255
9.25M
    const TCPHdr *tcph = PacketGetTCP(p);
3256
9.25M
    if (ssn->state < TCP_ESTABLISHED)
3257
593k
        return false;
3258
8.65M
    if (p->payload_len != 0)
3259
6.77M
        return false;
3260
1.88M
    if ((tcph->th_flags & (TH_ACK | TH_SYN | TH_FIN | TH_RST)) != TH_ACK)
3261
521k
        return false;
3262
3263
1.36M
    const TcpStream *snd, *rcv;
3264
1.36M
    if (PKT_IS_TOCLIENT(p)) {
3265
633k
        snd = &ssn->server;
3266
633k
        rcv = &ssn->client;
3267
733k
    } else {
3268
733k
        snd = &ssn->client;
3269
733k
        rcv = &ssn->server;
3270
733k
    }
3271
3272
1.36M
    const uint32_t pkt_win = TCP_GET_RAW_WINDOW(tcph) << snd->wscale;
3273
1.36M
    if (pkt_win == 0 || rcv->window == 0)
3274
43.7k
        return false;
3275
1.32M
    if (pkt_win != rcv->window)
3276
648k
        return false;
3277
3278
674k
    if (TCP_GET_RAW_SEQ(tcph) != snd->next_seq)
3279
253k
        return false;
3280
420k
    if (TCP_GET_RAW_ACK(tcph) != rcv->last_ack)
3281
236k
        return false;
3282
3283
184k
    SCLogDebug("ssn %p: packet:%" PRIu64 " seq:%u ack:%u win:%u snd %u:%u:%u rcv %u:%u:%u", ssn,
3284
184k
            p->pcap_cnt, TCP_GET_RAW_SEQ(tcph), TCP_GET_RAW_ACK(tcph), pkt_win, snd->next_seq,
3285
184k
            snd->last_ack, rcv->window, snd->next_seq, rcv->last_ack, rcv->window);
3286
184k
    return true;
3287
420k
}
3288
3289
/** \internal
3290
 *  \brief check if a ACK packet is outdated so processing can be fast tracked
3291
 *
3292
 *  Consider a packet outdated ack if:
3293
 *  - state is >= ESTABLISHED
3294
 *  - ACK < last_ACK
3295
 *  - SACK acks nothing new
3296
 *  - packet has no data
3297
 *  - SEQ == next_SEQ
3298
 *  - flags has ACK set but don't contain SYN/FIN/RST
3299
 *
3300
 *  \todo the most likely explanation for this packet is that we already
3301
 *        accepted a "newer" ACK. We will not consider an outdated timestamp
3302
 *        option an issue for this packet, but we should probably still
3303
 *        check if the ts isn't too far off.
3304
 */
3305
static bool StreamTcpPacketIsOutdatedAck(TcpSession *ssn, Packet *p)
3306
9.18M
{
3307
9.18M
    const TCPHdr *tcph = PacketGetTCP(p);
3308
9.18M
    if (ssn->state < TCP_ESTABLISHED)
3309
593k
        return false;
3310
8.58M
    if (p->payload_len != 0)
3311
6.74M
        return false;
3312
1.84M
    if ((tcph->th_flags & (TH_ACK | TH_SYN | TH_FIN | TH_RST)) != TH_ACK)
3313
521k
        return false;
3314
3315
    /* lets see if this is a packet that is entirely eclipsed by earlier ACKs */
3316
1.31M
    if (PKT_IS_TOSERVER(p)) {
3317
704k
        if (SEQ_EQ(TCP_GET_RAW_SEQ(tcph), ssn->client.next_seq) &&
3318
363k
                SEQ_LT(TCP_GET_RAW_ACK(tcph), ssn->server.last_ack)) {
3319
34.3k
            if (!TCP_HAS_SACK(p)) {
3320
24.3k
                SCLogDebug("outdated ACK (no SACK, SEQ %u vs next_seq %u)", TCP_GET_RAW_SEQ(tcph),
3321
24.3k
                        ssn->client.next_seq);
3322
24.3k
                return true;
3323
24.3k
            }
3324
3325
9.97k
            if (StreamTcpSackPacketIsOutdated(&ssn->server, p)) {
3326
759
                SCLogDebug("outdated ACK (have SACK, SEQ %u vs next_seq %u)", TCP_GET_RAW_SEQ(tcph),
3327
759
                        ssn->client.next_seq);
3328
759
                return true;
3329
759
            }
3330
9.97k
        }
3331
704k
    } else {
3332
615k
        if (SEQ_EQ(TCP_GET_RAW_SEQ(tcph), ssn->server.next_seq) &&
3333
362k
                SEQ_LT(TCP_GET_RAW_ACK(tcph), ssn->client.last_ack)) {
3334
30.8k
            if (!TCP_HAS_SACK(p)) {
3335
30.1k
                SCLogDebug("outdated ACK (no SACK, SEQ %u vs next_seq %u)", TCP_GET_RAW_SEQ(tcph),
3336
30.1k
                        ssn->client.next_seq);
3337
30.1k
                return true;
3338
30.1k
            }
3339
3340
639
            if (StreamTcpSackPacketIsOutdated(&ssn->client, p)) {
3341
94
                SCLogDebug("outdated ACK (have SACK, SEQ %u vs next_seq %u)", TCP_GET_RAW_SEQ(tcph),
3342
94
                        ssn->client.next_seq);
3343
94
                return true;
3344
94
            }
3345
639
        }
3346
615k
    }
3347
1.26M
    return false;
3348
1.31M
}
3349
3350
/** \internal
3351
 *  \brief check if packet is before ack'd windows
3352
 *  If packet is before last ack, we will not accept it
3353
 *
3354
 *  \retval 0 not spurious retransmission
3355
 *  \retval 1 before last_ack, after base_seq
3356
 *  \retval 2 before last_ack and base_seq
3357
 */
3358
static int StreamTcpPacketIsSpuriousRetransmission(const TcpSession *ssn, Packet *p)
3359
9.16M
{
3360
9.16M
    const TcpStream *stream;
3361
9.16M
    if (PKT_IS_TOCLIENT(p)) {
3362
4.17M
        stream = &ssn->server;
3363
4.98M
    } else {
3364
4.98M
        stream = &ssn->client;
3365
4.98M
    }
3366
9.16M
    if (p->payload_len == 0)
3367
2.23M
        return 0;
3368
3369
6.92M
    const TCPHdr *tcph = PacketGetTCP(p);
3370
    /* take base_seq into account to avoid edge cases where last_ack might be
3371
     * too far ahead during heavy packet loss */
3372
6.92M
    if (!(stream->flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY)) {
3373
6.42M
        if ((SEQ_LEQ(TCP_GET_RAW_SEQ(tcph) + p->payload_len, stream->base_seq))) {
3374
212k
            SCLogDebug(
3375
212k
                    "ssn %p: spurious retransmission; packet entirely before base_seq: SEQ %u(%u) "
3376
212k
                    "last_ack %u base_seq %u",
3377
212k
                    ssn, TCP_GET_RAW_SEQ(tcph), TCP_GET_RAW_SEQ(tcph) + p->payload_len,
3378
212k
                    stream->last_ack, stream->base_seq);
3379
212k
            STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_SPURIOUS_RETRANSMISSION);
3380
212k
            return 2;
3381
212k
        }
3382
6.42M
    }
3383
3384
6.71M
    if ((SEQ_LEQ(TCP_GET_RAW_SEQ(tcph) + p->payload_len, stream->last_ack))) {
3385
673k
        SCLogDebug("ssn %p: spurious retransmission; packet entirely before last_ack: SEQ %u(%u) "
3386
673k
                   "last_ack %u",
3387
673k
                ssn, TCP_GET_RAW_SEQ(tcph), TCP_GET_RAW_SEQ(tcph) + p->payload_len,
3388
673k
                stream->last_ack);
3389
673k
        STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_SPURIOUS_RETRANSMISSION);
3390
673k
        return 1;
3391
673k
    }
3392
3393
6.04M
    SCLogDebug("ssn %p: NOT spurious retransmission; packet NOT entirely before last_ack: SEQ "
3394
6.04M
               "%u(%u) last_ack %u, base_seq %u",
3395
6.04M
            ssn, TCP_GET_RAW_SEQ(tcph), TCP_GET_RAW_SEQ(tcph) + p->payload_len, stream->last_ack,
3396
6.04M
            stream->base_seq);
3397
6.04M
    return 0;
3398
6.71M
}
3399
3400
/**
3401
 *  \brief  Function to handle the TCP_ESTABLISHED state. The function handles
3402
 *          ACK, FIN, RST packets and correspondingly changes the connection
3403
 *          state. The function handles the data inside packets and call
3404
 *          StreamTcpReassembleHandleSegment(tv, ) to handle the reassembling.
3405
 *
3406
 *  \param  tv      Thread Variable containing  input/output queue, cpu affinity etc.
3407
 *  \param  p       Packet which has to be handled in this TCP state.
3408
 *  \param  stt     Stream Thread module registered to handle the stream handling
3409
 */
3410
3411
static int StreamTcpPacketStateEstablished(
3412
        ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn)
3413
6.62M
{
3414
6.62M
    DEBUG_VALIDATE_BUG_ON(ssn == NULL);
3415
6.62M
    const TCPHdr *tcph = PacketGetTCP(p);
3416
6.62M
    const uint32_t seq = TCP_GET_RAW_SEQ(tcph);
3417
6.62M
    const uint32_t ack = TCP_GET_RAW_ACK(tcph);
3418
6.62M
    const uint16_t window = TCP_GET_RAW_WINDOW(tcph);
3419
3420
6.62M
    if (tcph->th_flags & TH_RST) {
3421
38.0k
        if (!StreamTcpValidateRst(ssn, p))
3422
21.0k
            return -1;
3423
3424
16.9k
        if (PKT_IS_TOSERVER(p)) {
3425
8.22k
            StreamTcpCloseSsnWithReset(p, ssn);
3426
3427
8.22k
            ssn->server.next_seq = ack;
3428
8.22k
            ssn->client.next_seq = seq + p->payload_len;
3429
8.22k
            SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "", ssn,
3430
8.22k
                    ssn->server.next_seq);
3431
8.22k
            ssn->client.window = window << ssn->client.wscale;
3432
3433
8.22k
            if ((tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
3434
5.18k
                StreamTcpUpdateLastAck(ssn, &ssn->server, ack);
3435
3436
8.22k
            StreamTcpUpdateLastAck(ssn, &ssn->client, seq);
3437
3438
8.22k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3439
4.37k
                StreamTcpHandleTimestamp(ssn, p);
3440
4.37k
            }
3441
3442
8.22k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
3443
8.22k
            SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3444
8.22k
                    "%" PRIu32 "", ssn, ssn->client.next_seq,
3445
8.22k
                    ssn->server.last_ack);
3446
3447
            /* don't return packets to pools here just yet, the pseudo
3448
             * packet will take care, otherwise the normal session
3449
             * cleanup. */
3450
8.76k
        } else {
3451
8.76k
            StreamTcpCloseSsnWithReset(p, ssn);
3452
3453
8.76k
            ssn->server.next_seq = seq + p->payload_len + 1;
3454
8.76k
            ssn->client.next_seq = ack;
3455
3456
8.76k
            SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "", ssn,
3457
8.76k
                    ssn->server.next_seq);
3458
8.76k
            ssn->server.window = window << ssn->server.wscale;
3459
3460
8.76k
            if ((tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
3461
3.73k
                StreamTcpUpdateLastAck(ssn, &ssn->client, ack);
3462
3463
8.76k
            StreamTcpUpdateLastAck(ssn, &ssn->server, seq);
3464
3465
8.76k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3466
4.15k
                StreamTcpHandleTimestamp(ssn, p);
3467
4.15k
            }
3468
3469
8.76k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
3470
8.76k
            SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3471
8.76k
                    "%" PRIu32 "", ssn, ssn->server.next_seq,
3472
8.76k
                    ssn->client.last_ack);
3473
3474
            /* don't return packets to pools here just yet, the pseudo
3475
             * packet will take care, otherwise the normal session
3476
             * cleanup. */
3477
8.76k
        }
3478
3479
6.58M
    } else if (tcph->th_flags & TH_FIN) {
3480
117k
        if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3481
55.6k
            if (!StreamTcpValidateTimestamp(ssn, p))
3482
3.62k
                return -1;
3483
55.6k
        }
3484
3485
113k
        SCLogDebug("ssn (%p: FIN received SEQ"
3486
113k
                " %" PRIu32 ", last ACK %" PRIu32 ", next win %"PRIu32","
3487
113k
                " win %" PRIu32 "", ssn, ssn->server.next_seq,
3488
113k
                ssn->client.last_ack, ssn->server.next_win,
3489
113k
                ssn->server.window);
3490
3491
113k
        if ((StreamTcpHandleFin(tv, stt, ssn, p)) == -1)
3492
40.7k
            return -1;
3493
3494
    /* SYN/ACK */
3495
6.47M
    } else if ((tcph->th_flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK)) {
3496
81.1k
        SCLogDebug("ssn %p: SYN/ACK packet on state ESTABLISHED... resent",
3497
81.1k
                ssn);
3498
3499
81.1k
        if (PKT_IS_TOSERVER(p)) {
3500
24.2k
            SCLogDebug("ssn %p: SYN/ACK-pkt to server in ESTABLISHED state", ssn);
3501
3502
24.2k
            StreamTcpSetEvent(p, STREAM_EST_SYNACK_TOSERVER);
3503
24.2k
            return -1;
3504
24.2k
        }
3505
3506
        /* Check if the SYN/ACK packets ACK matches the earlier
3507
         * received SYN/ACK packet. */
3508
56.8k
        if (!(SEQ_EQ(ack, ssn->client.last_ack))) {
3509
38.7k
            SCLogDebug("ssn %p: ACK mismatch, packet ACK %" PRIu32 " != "
3510
38.7k
                       "%" PRIu32 " from stream",
3511
38.7k
                    ssn, ack, ssn->client.isn + 1);
3512
3513
38.7k
            StreamTcpSetEvent(p, STREAM_EST_SYNACK_RESEND_WITH_DIFFERENT_ACK);
3514
38.7k
            return -1;
3515
38.7k
        }
3516
3517
        /* Check if the SYN/ACK packet SEQ the earlier
3518
         * received SYN packet. */
3519
18.0k
        if (!(SEQ_EQ(seq, ssn->server.isn))) {
3520
2.41k
            SCLogDebug("ssn %p: SEQ mismatch, packet SEQ %" PRIu32 " != "
3521
2.41k
                       "%" PRIu32 " from stream",
3522
2.41k
                    ssn, ack, ssn->client.isn + 1);
3523
3524
2.41k
            StreamTcpSetEvent(p, STREAM_EST_SYNACK_RESEND_WITH_DIFF_SEQ);
3525
2.41k
            return -1;
3526
2.41k
        }
3527
3528
15.6k
        if (ssn->flags & STREAMTCP_FLAG_3WHS_CONFIRMED) {
3529
            /* a resend of a SYN while we are established already -- fishy */
3530
3.10k
            StreamTcpSetEvent(p, STREAM_EST_SYNACK_RESEND);
3531
3.10k
            return -1;
3532
3.10k
        }
3533
3534
12.5k
        SCLogDebug("ssn %p: SYN/ACK packet on state ESTABLISHED... resent. "
3535
12.5k
                "Likely due server not receiving final ACK in 3whs", ssn);
3536
12.5k
        return 0;
3537
3538
6.38M
    } else if (tcph->th_flags & TH_SYN) {
3539
21.6k
        SCLogDebug("ssn %p: SYN packet on state ESTABLISHED... resent", ssn);
3540
21.6k
        if (PKT_IS_TOCLIENT(p)) {
3541
6.21k
            SCLogDebug("ssn %p: SYN-pkt to client in EST state", ssn);
3542
3543
6.21k
            StreamTcpSetEvent(p, STREAM_EST_SYN_TOCLIENT);
3544
6.21k
            return -1;
3545
6.21k
        }
3546
3547
15.4k
        if (!(SEQ_EQ(ack, ssn->client.isn))) {
3548
15.4k
            SCLogDebug("ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
3549
3550
15.4k
            StreamTcpSetEvent(p, STREAM_EST_SYN_RESEND_DIFF_SEQ);
3551
15.4k
            return -1;
3552
15.4k
        }
3553
3554
        /* a resend of a SYN while we are established already -- fishy */
3555
21
        StreamTcpSetEvent(p, STREAM_EST_SYN_RESEND);
3556
21
        return -1;
3557
3558
6.36M
    } else if (tcph->th_flags & TH_ACK) {
3559
        /* Urgent pointer size can be more than the payload size, as it tells
3560
         * the future coming data from the sender will be handled urgently
3561
         * until data of size equal to urgent offset has been processed
3562
         * (RFC 2147) */
3563
3564
        /* If the timestamp option is enabled for both the streams, then
3565
         * validate the received packet timestamp value against the
3566
         * stream->last_ts. If the timestamp is valid then process the
3567
         * packet normally otherwise the drop the packet (RFC 1323) */
3568
6.36M
        if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3569
846k
            if (!StreamTcpValidateTimestamp(ssn, p))
3570
79.7k
                return -1;
3571
846k
        }
3572
3573
6.28M
        if (PKT_IS_TOSERVER(p)) {
3574
            /* Process the received packet to server */
3575
3.47M
            HandleEstablishedPacketToServer(tv, ssn, p, stt);
3576
3577
3.47M
            SCLogDebug("ssn %p: next SEQ %" PRIu32 ", last ACK %" PRIu32 ","
3578
3.47M
                    " next win %" PRIu32 ", win %" PRIu32 "", ssn,
3579
3.47M
                    ssn->client.next_seq, ssn->server.last_ack
3580
3.47M
                    ,ssn->client.next_win, ssn->client.window);
3581
3582
3.47M
        } else { /* implied to client */
3583
2.80M
            if (!(ssn->flags & STREAMTCP_FLAG_3WHS_CONFIRMED)) {
3584
122k
                ssn->flags |= STREAMTCP_FLAG_3WHS_CONFIRMED;
3585
122k
                SCLogDebug("3whs is now confirmed by server");
3586
122k
            }
3587
3588
            /* Process the received packet to client */
3589
2.80M
            HandleEstablishedPacketToClient(tv, ssn, p, stt);
3590
3591
2.80M
            SCLogDebug("ssn %p: next SEQ %" PRIu32 ", last ACK %" PRIu32 ","
3592
2.80M
                    " next win %" PRIu32 ", win %" PRIu32 "", ssn,
3593
2.80M
                    ssn->server.next_seq, ssn->client.last_ack,
3594
2.80M
                    ssn->server.next_win, ssn->server.window);
3595
2.80M
        }
3596
6.28M
    } else {
3597
3.97k
        SCLogDebug("ssn %p: default case", ssn);
3598
3.97k
    }
3599
3600
6.37M
    return 0;
3601
6.62M
}
3602
3603
/**
3604
 *  \brief  Function to handle the FIN packets for states TCP_SYN_RECV and
3605
 *          TCP_ESTABLISHED and changes to another TCP state as required.
3606
 *
3607
 *  \param  tv      Thread Variable containing  input/output queue, cpu affinity
3608
 *  \param  p       Packet which has to be handled in this TCP state.
3609
 *  \param  stt     Stream Thread module registered to handle the stream handling
3610
 *
3611
 *  \retval 0 success
3612
 *  \retval -1 something wrong with the packet
3613
 */
3614
3615
static int StreamTcpHandleFin(ThreadVars *tv, StreamTcpThread *stt, TcpSession *ssn, Packet *p)
3616
148k
{
3617
148k
    const TCPHdr *tcph = PacketGetTCP(p);
3618
148k
    const uint32_t seq = TCP_GET_RAW_SEQ(tcph);
3619
148k
    const uint32_t ack = TCP_GET_RAW_ACK(tcph);
3620
148k
    const uint16_t window = TCP_GET_RAW_WINDOW(tcph);
3621
3622
148k
    if (PKT_IS_TOSERVER(p)) {
3623
81.0k
        SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ %" PRIu32 ","
3624
81.0k
                   " ACK %" PRIu32 "",
3625
81.0k
                ssn, p->payload_len, seq, ack);
3626
3627
81.0k
        if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
3628
8.56k
            SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3629
8.56k
            StreamTcpSetEvent(p, STREAM_FIN_INVALID_ACK);
3630
8.56k
            return -1;
3631
8.56k
        }
3632
3633
72.4k
        const uint32_t pkt_re = seq + p->payload_len;
3634
72.4k
        SCLogDebug("ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn, seq, pkt_re,
3635
72.4k
                ssn->client.last_ack, ssn->client.next_win);
3636
72.4k
        if (SEQ_GEQ(seq, ssn->client.last_ack) && SEQ_LEQ(pkt_re, ssn->client.next_win)) {
3637
            // within expectations
3638
54.9k
        } else {
3639
17.4k
            SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != "
3640
17.4k
                       "%" PRIu32 " from stream",
3641
17.4k
                    ssn, seq, ssn->client.next_seq);
3642
3643
17.4k
            StreamTcpSetEvent(p, STREAM_FIN_OUT_OF_WINDOW);
3644
17.4k
            return -1;
3645
17.4k
        }
3646
3647
54.9k
        if (tcph->th_flags & TH_SYN) {
3648
3.31k
            SCLogDebug("ssn %p: FIN+SYN", ssn);
3649
3.31k
            StreamTcpSetEvent(p, STREAM_FIN_SYN);
3650
3.31k
            return -1;
3651
3.31k
        }
3652
51.6k
        StreamTcpPacketSetState(p, ssn, TCP_CLOSE_WAIT);
3653
51.6k
        SCLogDebug("ssn %p: state changed to TCP_CLOSE_WAIT", ssn);
3654
3655
        /* if we accept the FIN, next_seq needs to reflect the FIN */
3656
51.6k
        ssn->client.next_seq = seq + p->payload_len;
3657
3658
51.6k
        SCLogDebug("ssn %p: ssn->client.next_seq %" PRIu32 "", ssn,
3659
51.6k
                    ssn->client.next_seq);
3660
51.6k
        ssn->server.window = window << ssn->server.wscale;
3661
3662
51.6k
        if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3663
29.7k
            StreamTcpHandleTimestamp(ssn, p);
3664
29.7k
        }
3665
3666
        /* Update the next_seq, in case if we have missed the client packet
3667
           and server has already received and acked it */
3668
51.6k
        if (SEQ_LT(ssn->server.next_seq, ack))
3669
12.6k
            ssn->server.next_seq = ack;
3670
3671
51.6k
        if (tcph->th_flags & TH_ACK)
3672
41.8k
            StreamTcpUpdateLastAck(ssn, &ssn->server, ack);
3673
3674
51.6k
        StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
3675
3676
51.6k
        SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK %" PRIu32 "",
3677
51.6k
                ssn, ssn->client.next_seq, ssn->server.last_ack);
3678
67.3k
    } else { /* implied to client */
3679
67.3k
        SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ %" PRIu32 ", "
3680
67.3k
                   "ACK %" PRIu32 "",
3681
67.3k
                ssn, p->payload_len, seq, ack);
3682
3683
67.3k
        if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
3684
5.80k
            SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3685
5.80k
            StreamTcpSetEvent(p, STREAM_FIN_INVALID_ACK);
3686
5.80k
            return -1;
3687
5.80k
        }
3688
3689
61.5k
        const uint32_t pkt_re = seq + p->payload_len;
3690
61.5k
        SCLogDebug("ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn, seq, pkt_re,
3691
61.5k
                ssn->server.last_ack, ssn->server.next_win);
3692
61.5k
        if (SEQ_GEQ(seq, ssn->server.last_ack) && SEQ_LEQ(pkt_re, ssn->server.next_win)) {
3693
            // within expectations
3694
37.5k
        } else {
3695
23.9k
            SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != "
3696
23.9k
                       "%" PRIu32 " from stream (last_ack %u win %u = %u)",
3697
23.9k
                    ssn, seq, ssn->server.next_seq, ssn->server.last_ack, ssn->server.window,
3698
23.9k
                    (ssn->server.last_ack + ssn->server.window));
3699
3700
23.9k
            StreamTcpSetEvent(p, STREAM_FIN_OUT_OF_WINDOW);
3701
23.9k
            return -1;
3702
23.9k
        }
3703
3704
37.5k
        StreamTcpPacketSetState(p, ssn, TCP_FIN_WAIT1);
3705
37.5k
        SCLogDebug("ssn %p: state changed to TCP_FIN_WAIT1", ssn);
3706
3707
        /* if we accept the FIN, next_seq needs to reflect the FIN */
3708
37.5k
        ssn->server.next_seq = seq + p->payload_len + 1;
3709
37.5k
        SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 " updated", ssn, ssn->server.next_seq);
3710
3711
37.5k
        ssn->client.window = window << ssn->client.wscale;
3712
3713
37.5k
        if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3714
16.2k
            StreamTcpHandleTimestamp(ssn, p);
3715
16.2k
        }
3716
3717
        /* Update the next_seq, in case if we have missed the client packet
3718
           and server has already received and acked it */
3719
37.5k
        if (SEQ_LT(ssn->client.next_seq, ack))
3720
16.3k
            ssn->client.next_seq = ack;
3721
3722
37.5k
        if (tcph->th_flags & TH_ACK)
3723
29.6k
            StreamTcpUpdateLastAck(ssn, &ssn->client, ack);
3724
3725
37.5k
        StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
3726
3727
37.5k
        SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK %" PRIu32 "",
3728
37.5k
                ssn, ssn->server.next_seq, ssn->client.last_ack);
3729
37.5k
    }
3730
3731
89.2k
    return 0;
3732
148k
}
3733
3734
/**
3735
 *  \brief  Function to handle the TCP_FIN_WAIT1 state. The function handles
3736
 *          ACK, FIN, RST packets and correspondingly changes the connection
3737
 *          state.
3738
 *
3739
 *  \param  tv      Thread Variable containing  input/output queue, cpu affinity
3740
 *  \param  p       Packet which has to be handled in this TCP state.
3741
 *  \param  stt     Stream Thread module registered to handle the stream handling
3742
 *
3743
 *  \retval 0 success
3744
 *  \retval -1 something wrong with the packet
3745
 */
3746
3747
static int StreamTcpPacketStateFinWait1(
3748
        ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn)
3749
468k
{
3750
468k
    DEBUG_VALIDATE_BUG_ON(ssn == NULL);
3751
468k
    const TCPHdr *tcph = PacketGetTCP(p);
3752
468k
    const uint32_t seq = TCP_GET_RAW_SEQ(tcph);
3753
468k
    const uint32_t ack = TCP_GET_RAW_ACK(tcph);
3754
468k
    const uint16_t window = TCP_GET_RAW_WINDOW(tcph);
3755
3756
468k
    if (tcph->th_flags & TH_RST) {
3757
22.3k
        if (!StreamTcpValidateRst(ssn, p))
3758
15.2k
            return -1;
3759
3760
7.14k
        StreamTcpCloseSsnWithReset(p, ssn);
3761
3762
7.14k
        if (PKT_IS_TOSERVER(p)) {
3763
4.71k
            if ((tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
3764
1.59k
                StreamTcpUpdateLastAck(ssn, &ssn->server, ack);
3765
3766
4.71k
            StreamTcpUpdateLastAck(ssn, &ssn->client, seq);
3767
3768
4.71k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3769
4.36k
                StreamTcpHandleTimestamp(ssn, p);
3770
4.36k
            }
3771
3772
4.71k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
3773
4.71k
        } else {
3774
2.43k
            if ((tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
3775
1.62k
                StreamTcpUpdateLastAck(ssn, &ssn->client, ack);
3776
3777
2.43k
            StreamTcpUpdateLastAck(ssn, &ssn->server, seq);
3778
3779
2.43k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3780
1.44k
                StreamTcpHandleTimestamp(ssn, p);
3781
1.44k
            }
3782
3783
2.43k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
3784
2.43k
        }
3785
3786
445k
    } else if ((tcph->th_flags & (TH_FIN | TH_ACK)) == (TH_FIN | TH_ACK)) {
3787
62.6k
        if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3788
17.8k
            if (!StreamTcpValidateTimestamp(ssn, p))
3789
1.22k
                return -1;
3790
17.8k
        }
3791
3792
61.4k
        if (PKT_IS_TOSERVER(p)) {
3793
34.6k
            SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
3794
34.6k
                       "%" PRIu32 ", ACK %" PRIu32 "",
3795
34.6k
                    ssn, p->payload_len, seq, ack);
3796
34.6k
            int retransmission = 0;
3797
3798
34.6k
            if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
3799
21.1k
                SCLogDebug("ssn %p: packet is retransmission", ssn);
3800
21.1k
                retransmission = 1;
3801
21.1k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
3802
3803
21.1k
            } else if (SEQ_LT(seq, ssn->client.next_seq - 1) ||
3804
8.38k
                       SEQ_GT(seq, (ssn->client.last_ack + ssn->client.window))) {
3805
8.38k
                SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
3806
8.38k
                           " != %" PRIu32 " from stream",
3807
8.38k
                        ssn, seq, ssn->client.next_seq);
3808
8.38k
                StreamTcpSetEvent(p, STREAM_FIN1_FIN_WRONG_SEQ);
3809
8.38k
                return -1;
3810
8.38k
            }
3811
3812
26.2k
            if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
3813
1.83k
                SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3814
1.83k
                StreamTcpSetEvent(p, STREAM_FIN1_INVALID_ACK);
3815
1.83k
                return -1;
3816
1.83k
            }
3817
3818
24.4k
            if (!retransmission) {
3819
3.44k
                StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
3820
3.44k
                SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
3821
3822
3.44k
                ssn->server.window = window << ssn->server.wscale;
3823
3.44k
            }
3824
3825
24.4k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3826
5.66k
                StreamTcpHandleTimestamp(ssn, p);
3827
5.66k
            }
3828
3829
            /* Update the next_seq, in case if we have missed the client
3830
               packet and server has already received and acked it */
3831
24.4k
            if (SEQ_LT(ssn->server.next_seq - 1, ack))
3832
20.8k
                ssn->server.next_seq = ack;
3833
3834
24.4k
            if (SEQ_EQ(ssn->client.next_seq, seq)) {
3835
2.38k
                StreamTcpUpdateNextSeq(ssn, &ssn->client, (seq + p->payload_len));
3836
2.38k
            }
3837
3838
24.4k
            StreamTcpUpdateLastAck(ssn, &ssn->server, ack);
3839
3840
24.4k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
3841
3842
24.4k
            SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3843
24.4k
                    "%" PRIu32 "", ssn, ssn->client.next_seq,
3844
24.4k
                    ssn->server.last_ack);
3845
26.7k
        } else { /* implied to client */
3846
26.7k
            SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
3847
26.7k
                       "%" PRIu32 ", ACK %" PRIu32 "",
3848
26.7k
                    ssn, p->payload_len, seq, ack);
3849
26.7k
            int retransmission = 0;
3850
3851
26.7k
            if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
3852
5.63k
                SCLogDebug("ssn %p: packet is retransmission", ssn);
3853
5.63k
                retransmission = 1;
3854
5.63k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
3855
3856
21.1k
            } else if (SEQ_EQ(ssn->server.next_seq - 1, seq) && SEQ_EQ(ssn->client.last_ack, ack)) {
3857
7.54k
                SCLogDebug("ssn %p: packet is retransmission", ssn);
3858
7.54k
                retransmission = 1;
3859
7.54k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
3860
3861
13.5k
            } else if (SEQ_LT(seq, ssn->server.next_seq - 1) ||
3862
9.70k
                       SEQ_GT(seq, (ssn->server.last_ack + ssn->server.window))) {
3863
7.78k
                SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
3864
7.78k
                           " != %" PRIu32 " from stream",
3865
7.78k
                        ssn, seq, ssn->server.next_seq);
3866
7.78k
                StreamTcpSetEvent(p, STREAM_FIN1_FIN_WRONG_SEQ);
3867
7.78k
                return -1;
3868
7.78k
            }
3869
3870
18.9k
            if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
3871
4.92k
                SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3872
4.92k
                StreamTcpSetEvent(p, STREAM_FIN1_INVALID_ACK);
3873
4.92k
                return -1;
3874
4.92k
            }
3875
3876
14.0k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3877
6.04k
                StreamTcpHandleTimestamp(ssn, p);
3878
6.04k
            }
3879
3880
14.0k
            if (!retransmission) {
3881
1.93k
                StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
3882
1.93k
                SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
3883
3884
1.93k
                ssn->client.window = window << ssn->client.wscale;
3885
3886
                /* Update the next_seq, in case if we have missed the client
3887
                   packet and server has already received and acked it */
3888
1.93k
                if (SEQ_LT(ssn->client.next_seq - 1, ack))
3889
455
                    ssn->client.next_seq = ack;
3890
3891
1.93k
                if (SEQ_EQ(ssn->server.next_seq - 1, seq)) {
3892
1.41k
                    StreamTcpUpdateNextSeq(ssn, &ssn->server, (seq + p->payload_len));
3893
1.41k
                }
3894
3895
1.93k
                StreamTcpUpdateLastAck(ssn, &ssn->client, ack);
3896
1.93k
            }
3897
3898
14.0k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
3899
3900
14.0k
            SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3901
14.0k
                    "%" PRIu32 "", ssn, ssn->server.next_seq,
3902
14.0k
                    ssn->client.last_ack);
3903
14.0k
        }
3904
3905
383k
    } else if (tcph->th_flags & TH_FIN) {
3906
65.4k
        if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3907
7.95k
            if (!StreamTcpValidateTimestamp(ssn, p))
3908
976
                return -1;
3909
7.95k
        }
3910
3911
64.5k
        if (PKT_IS_TOSERVER(p)) {
3912
38.1k
            SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
3913
38.1k
                       "%" PRIu32 ", ACK %" PRIu32 "",
3914
38.1k
                    ssn, p->payload_len, seq, ack);
3915
38.1k
            int retransmission = 0;
3916
3917
38.1k
            if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
3918
32.1k
                SCLogDebug("ssn %p: packet is retransmission", ssn);
3919
32.1k
                retransmission = 1;
3920
32.1k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
3921
3922
32.1k
            } else if (SEQ_LT(seq, ssn->client.next_seq - 1) ||
3923
3.83k
                       SEQ_GT(seq, (ssn->client.last_ack + ssn->client.window))) {
3924
3.83k
                SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
3925
3.83k
                           " != %" PRIu32 " from stream",
3926
3.83k
                        ssn, seq, ssn->client.next_seq);
3927
3.83k
                StreamTcpSetEvent(p, STREAM_FIN1_FIN_WRONG_SEQ);
3928
3.83k
                return -1;
3929
3.83k
            }
3930
3931
34.3k
            if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
3932
0
                SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3933
0
                StreamTcpSetEvent(p, STREAM_FIN1_INVALID_ACK);
3934
0
                return -1;
3935
0
            }
3936
3937
34.3k
            if (!retransmission) {
3938
2.23k
                StreamTcpPacketSetState(p, ssn, TCP_CLOSING);
3939
2.23k
                SCLogDebug("ssn %p: state changed to TCP_CLOSING", ssn);
3940
3941
2.23k
                ssn->server.window = window << ssn->server.wscale;
3942
2.23k
            }
3943
3944
34.3k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
3945
1.44k
                StreamTcpHandleTimestamp(ssn, p);
3946
1.44k
            }
3947
3948
            /* Update the next_seq, in case if we have missed the client
3949
               packet and server has already received and acked it */
3950
34.3k
            if (SEQ_LT(ssn->server.next_seq - 1, ack))
3951
30.6k
                ssn->server.next_seq = ack;
3952
3953
34.3k
            if (SEQ_EQ(ssn->client.next_seq - 1, seq)) {
3954
103
                StreamTcpUpdateNextSeq(ssn, &ssn->client, (seq + p->payload_len));
3955
103
            }
3956
3957
34.3k
            if (tcph->th_flags & TH_ACK)
3958
0
                StreamTcpUpdateLastAck(ssn, &ssn->server, ack);
3959
3960
34.3k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
3961
3962
34.3k
            SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
3963
34.3k
                    "%" PRIu32 "", ssn, ssn->client.next_seq,
3964
34.3k
                    ssn->server.last_ack);
3965
34.3k
        } else { /* implied to client */
3966
26.3k
            SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
3967
26.3k
                       "%" PRIu32 ", ACK %" PRIu32 "",
3968
26.3k
                    ssn, p->payload_len, seq, ack);
3969
3970
26.3k
            int retransmission = 0;
3971
3972
26.3k
            if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
3973
16.6k
                SCLogDebug("ssn %p: packet is retransmission", ssn);
3974
16.6k
                retransmission = 1;
3975
16.6k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
3976
3977
16.6k
            } else if (SEQ_LT(seq, ssn->server.next_seq - 1) ||
3978
7.95k
                       SEQ_GT(seq, (ssn->server.last_ack + ssn->server.window))) {
3979
7.02k
                SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
3980
7.02k
                           " != %" PRIu32 " from stream",
3981
7.02k
                        ssn, seq, ssn->server.next_seq);
3982
7.02k
                StreamTcpSetEvent(p, STREAM_FIN1_FIN_WRONG_SEQ);
3983
7.02k
                return -1;
3984
7.02k
            }
3985
3986
19.2k
            if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
3987
0
                SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
3988
0
                StreamTcpSetEvent(p, STREAM_FIN1_INVALID_ACK);
3989
0
                return -1;
3990
0
            }
3991
3992
19.2k
            if (!retransmission) {
3993
2.60k
                StreamTcpPacketSetState(p, ssn, TCP_CLOSING);
3994
2.60k
                SCLogDebug("ssn %p: state changed to TCP_CLOSING", ssn);
3995
3996
2.60k
                ssn->client.window = window << ssn->client.wscale;
3997
2.60k
            }
3998
3999
19.2k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4000
4.93k
                StreamTcpHandleTimestamp(ssn, p);
4001
4.93k
            }
4002
4003
            /* Update the next_seq, in case if we have missed the client
4004
               packet and server has already received and acked it */
4005
19.2k
            if (SEQ_LT(ssn->client.next_seq - 1, ack))
4006
9.19k
                ssn->client.next_seq = ack;
4007
4008
19.2k
            if (SEQ_EQ(ssn->server.next_seq - 1, seq)) {
4009
1.82k
                StreamTcpUpdateNextSeq(ssn, &ssn->server, (seq + p->payload_len));
4010
1.82k
            }
4011
4012
19.2k
            if (tcph->th_flags & TH_ACK)
4013
0
                StreamTcpUpdateLastAck(ssn, &ssn->client, ack);
4014
4015
19.2k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
4016
4017
19.2k
            SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
4018
19.2k
                    "%" PRIu32 "", ssn, ssn->server.next_seq,
4019
19.2k
                    ssn->client.last_ack);
4020
19.2k
        }
4021
317k
    } else if (tcph->th_flags & TH_SYN) {
4022
47.8k
        SCLogDebug("ssn (%p): SYN pkt on FinWait1", ssn);
4023
47.8k
        StreamTcpSetEvent(p, STREAM_SHUTDOWN_SYN_RESEND);
4024
47.8k
        return -1;
4025
4026
269k
    } else if (tcph->th_flags & TH_ACK) {
4027
267k
        if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4028
118k
            if (!StreamTcpValidateTimestamp(ssn, p))
4029
31.2k
                return -1;
4030
118k
        }
4031
4032
235k
        if (PKT_IS_TOSERVER(p)) {
4033
124k
            SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
4034
124k
                       "%" PRIu32 ", ACK %" PRIu32 "",
4035
124k
                    ssn, p->payload_len, seq, ack);
4036
124k
            int retransmission = 0;
4037
4038
124k
            if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
4039
51.9k
                SCLogDebug("ssn %p: packet is retransmission", ssn);
4040
51.9k
                retransmission = 1;
4041
51.9k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
4042
51.9k
            }
4043
4044
124k
            if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
4045
7.86k
                SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4046
7.86k
                StreamTcpSetEvent(p, STREAM_FIN1_INVALID_ACK);
4047
7.86k
                return -1;
4048
7.86k
            }
4049
4050
117k
            if (SEQ_LT(ack, ssn->server.next_seq)) {
4051
94.2k
                SCLogDebug(
4052
94.2k
                        "ssn %p: ACK's older segment as %u < %u", ssn, ack, ssn->server.next_seq);
4053
94.2k
            } else if (!retransmission) {
4054
19.6k
                if (SEQ_EQ(ack, ssn->server.next_seq)) {
4055
14.3k
                    if (SEQ_LEQ(seq + p->payload_len, ssn->client.next_win) ||
4056
14.2k
                            (ssn->flags & (STREAMTCP_FLAG_MIDSTREAM | STREAMTCP_FLAG_ASYNC))) {
4057
14.2k
                        SCLogDebug("ssn %p: seq %" PRIu32 " in window, ssn->client.next_win "
4058
14.2k
                                   "%" PRIu32 "",
4059
14.2k
                                ssn, seq, ssn->client.next_win);
4060
14.2k
                        SCLogDebug("seq %u client.next_seq %u", seq, ssn->client.next_seq);
4061
14.2k
                        if (seq == ssn->client.next_seq) {
4062
8.56k
                            StreamTcpPacketSetState(p, ssn, TCP_FIN_WAIT2);
4063
8.56k
                            SCLogDebug("ssn %p: state changed to TCP_FIN_WAIT2", ssn);
4064
8.56k
                        }
4065
14.2k
                    } else {
4066
102
                        SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
4067
102
                                   " != %" PRIu32 " from stream",
4068
102
                                ssn, seq, ssn->client.next_seq);
4069
4070
102
                        StreamTcpSetEvent(p, STREAM_FIN1_ACK_WRONG_SEQ);
4071
102
                        return -1;
4072
102
                    }
4073
4074
14.2k
                    ssn->server.window = window << ssn->server.wscale;
4075
14.2k
                }
4076
19.6k
            }
4077
4078
116k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4079
45.0k
                StreamTcpHandleTimestamp(ssn, p);
4080
45.0k
            }
4081
4082
            /* Update the next_seq, in case if we have missed the client
4083
               packet and server has already received and acked it */
4084
116k
            if (SEQ_LT(ssn->server.next_seq - 1, ack))
4085
22.6k
                ssn->server.next_seq = ack;
4086
4087
116k
            if (SEQ_EQ(ssn->client.next_seq, seq)) {
4088
20.1k
                StreamTcpUpdateNextSeq(ssn, &ssn->client, (seq + p->payload_len));
4089
20.1k
            }
4090
4091
116k
            StreamTcpUpdateLastAck(ssn, &ssn->server, ack);
4092
4093
116k
            StreamTcpSackUpdatePacket(&ssn->server, p);
4094
4095
            /* update next_win */
4096
116k
            StreamTcpUpdateNextWin(ssn, &ssn->server, (ssn->server.last_ack + ssn->server.window));
4097
4098
116k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
4099
4100
116k
            SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
4101
116k
                    "%" PRIu32 "", ssn, ssn->client.next_seq,
4102
116k
                    ssn->server.last_ack);
4103
4104
116k
        } else { /* implied to client */
4105
4106
111k
            SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
4107
111k
                       "%" PRIu32 ", ACK %" PRIu32 "",
4108
111k
                    ssn, p->payload_len, seq, ack);
4109
4110
111k
            int retransmission = 0;
4111
4112
111k
            if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
4113
48.1k
                SCLogDebug("ssn %p: packet is retransmission", ssn);
4114
48.1k
                retransmission = 1;
4115
48.1k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
4116
48.1k
            }
4117
4118
111k
            if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
4119
14.6k
                SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4120
14.6k
                StreamTcpSetEvent(p, STREAM_FIN1_INVALID_ACK);
4121
14.6k
                return -1;
4122
14.6k
            }
4123
4124
96.3k
            if (!retransmission) {
4125
53.3k
                if (SEQ_LEQ(seq + p->payload_len, ssn->server.next_win) ||
4126
53.2k
                        (ssn->flags & (STREAMTCP_FLAG_MIDSTREAM | STREAMTCP_FLAG_ASYNC))) {
4127
53.2k
                    SCLogDebug("ssn %p: seq %" PRIu32 " in window, ssn->server.next_win "
4128
53.2k
                               "%" PRIu32 "",
4129
53.2k
                            ssn, seq, ssn->server.next_win);
4130
4131
53.2k
                    if (seq == ssn->server.next_seq - 1) {
4132
2.82k
                        StreamTcpPacketSetState(p, ssn, TCP_FIN_WAIT2);
4133
2.82k
                        SCLogDebug("ssn %p: state changed to TCP_FIN_WAIT2", ssn);
4134
2.82k
                    }
4135
53.2k
                } else {
4136
123
                    SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
4137
123
                               " != %" PRIu32 " from stream",
4138
123
                            ssn, seq, ssn->server.next_seq);
4139
123
                    StreamTcpSetEvent(p, STREAM_FIN1_ACK_WRONG_SEQ);
4140
123
                    return -1;
4141
123
                }
4142
4143
53.2k
                ssn->client.window = window << ssn->client.wscale;
4144
53.2k
            }
4145
4146
96.2k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4147
40.4k
                StreamTcpHandleTimestamp(ssn, p);
4148
40.4k
            }
4149
4150
            /* Update the next_seq, in case if we have missed the client
4151
               packet and server has already received and acked it */
4152
96.2k
            if (SEQ_LT(ssn->client.next_seq - 1, ack))
4153
25.3k
                ssn->client.next_seq = ack;
4154
4155
96.2k
            if (SEQ_EQ(ssn->server.next_seq - 1, seq)) {
4156
2.88k
                StreamTcpUpdateNextSeq(ssn, &ssn->server, (seq + p->payload_len));
4157
2.88k
            }
4158
4159
96.2k
            StreamTcpUpdateLastAck(ssn, &ssn->client, ack);
4160
4161
96.2k
            StreamTcpSackUpdatePacket(&ssn->client, p);
4162
4163
            /* update next_win */
4164
96.2k
            StreamTcpUpdateNextWin(ssn, &ssn->client, (ssn->client.last_ack + ssn->client.window));
4165
4166
96.2k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
4167
4168
96.2k
            SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
4169
96.2k
                    "%" PRIu32 "", ssn, ssn->server.next_seq,
4170
96.2k
                    ssn->client.last_ack);
4171
96.2k
        }
4172
235k
    } else {
4173
2.63k
        SCLogDebug("ssn (%p): default case", ssn);
4174
2.63k
    }
4175
4176
315k
    return 0;
4177
468k
}
4178
4179
/**
4180
 *  \brief  Function to handle the TCP_FIN_WAIT2 state. The function handles
4181
 *          ACK, RST, FIN packets and correspondingly changes the connection
4182
 *          state.
4183
 *
4184
 *  \param  tv      Thread Variable containing  input/output queue, cpu affinity
4185
 *  \param  p       Packet which has to be handled in this TCP state.
4186
 *  \param  stt     Stream Thread module registered to handle the stream handling
4187
 */
4188
4189
static int StreamTcpPacketStateFinWait2(
4190
        ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn)
4191
252k
{
4192
252k
    DEBUG_VALIDATE_BUG_ON(ssn == NULL);
4193
252k
    const TCPHdr *tcph = PacketGetTCP(p);
4194
252k
    const uint32_t seq = TCP_GET_RAW_SEQ(tcph);
4195
252k
    const uint32_t ack = TCP_GET_RAW_ACK(tcph);
4196
252k
    const uint16_t window = TCP_GET_RAW_WINDOW(tcph);
4197
4198
252k
    if (tcph->th_flags & TH_RST) {
4199
7.52k
        if (!StreamTcpValidateRst(ssn, p))
4200
2.78k
            return -1;
4201
4202
4.73k
        StreamTcpCloseSsnWithReset(p, ssn);
4203
4204
4.73k
        if (PKT_IS_TOSERVER(p)) {
4205
4.05k
            if ((tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
4206
3.75k
                StreamTcpUpdateLastAck(ssn, &ssn->server, ack);
4207
4208
4.05k
            StreamTcpUpdateLastAck(ssn, &ssn->client, seq);
4209
4210
4.05k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4211
1.35k
                StreamTcpHandleTimestamp(ssn, p);
4212
1.35k
            }
4213
4214
4.05k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
4215
4.05k
        } else {
4216
685
            if ((tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
4217
564
                StreamTcpUpdateLastAck(ssn, &ssn->client, ack);
4218
4219
685
            StreamTcpUpdateLastAck(ssn, &ssn->server, seq);
4220
4221
685
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4222
73
                StreamTcpHandleTimestamp(ssn, p);
4223
73
            }
4224
4225
685
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
4226
685
        }
4227
4228
245k
    } else if (tcph->th_flags & TH_FIN) {
4229
30.1k
        if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4230
8.93k
            if (!StreamTcpValidateTimestamp(ssn, p))
4231
709
                return -1;
4232
8.93k
        }
4233
4234
29.3k
        if (PKT_IS_TOSERVER(p)) {
4235
7.48k
            SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
4236
7.48k
                       "%" PRIu32 ", ACK %" PRIu32 "",
4237
7.48k
                    ssn, p->payload_len, seq, ack);
4238
7.48k
            int retransmission = 0;
4239
4240
7.48k
            if (SEQ_EQ(seq, ssn->client.next_seq - 1) && SEQ_EQ(ack, ssn->server.last_ack)) {
4241
95
                SCLogDebug("ssn %p: retransmission", ssn);
4242
95
                retransmission = 1;
4243
95
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
4244
7.38k
            } else if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
4245
2.43k
                SCLogDebug("ssn %p: packet is retransmission", ssn);
4246
2.43k
                retransmission = 1;
4247
2.43k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
4248
4249
4.95k
            } else if (SEQ_LT(seq, ssn->client.next_seq) ||
4250
3.70k
                       SEQ_GT(seq, (ssn->client.last_ack + ssn->client.window))) {
4251
1.65k
                SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ "
4252
1.65k
                           "%" PRIu32 " != %" PRIu32 " from stream",
4253
1.65k
                        ssn, seq, ssn->client.next_seq);
4254
1.65k
                StreamTcpSetEvent(p, STREAM_FIN2_FIN_WRONG_SEQ);
4255
1.65k
                return -1;
4256
1.65k
            }
4257
4258
5.82k
            if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
4259
477
                SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4260
477
                StreamTcpSetEvent(p, STREAM_FIN2_INVALID_ACK);
4261
477
                return -1;
4262
477
            }
4263
4264
5.35k
            if (!retransmission) {
4265
3.18k
                StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
4266
3.18k
                SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
4267
4268
3.18k
                if (SEQ_EQ(ssn->client.next_seq, seq)) {
4269
3.04k
                    StreamTcpUpdateNextSeq(
4270
3.04k
                            ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
4271
3.04k
                }
4272
3.18k
                ssn->server.window = window << ssn->server.wscale;
4273
3.18k
            }
4274
4275
5.35k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4276
2.56k
                StreamTcpHandleTimestamp(ssn, p);
4277
2.56k
            }
4278
4279
            /* Update the next_seq, in case if we have missed the client
4280
               packet and server has already received and acked it */
4281
5.35k
            if (SEQ_LT(ssn->server.next_seq, ack))
4282
241
                ssn->server.next_seq = ack;
4283
4284
5.35k
            if (tcph->th_flags & TH_ACK)
4285
4.15k
                StreamTcpUpdateLastAck(ssn, &ssn->server, ack);
4286
4287
5.35k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
4288
4289
5.35k
            SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
4290
5.35k
                    "%" PRIu32 "", ssn, ssn->client.next_seq,
4291
5.35k
                    ssn->server.last_ack);
4292
21.9k
        } else { /* implied to client */
4293
21.9k
            SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
4294
21.9k
                       "%" PRIu32 ", ACK %" PRIu32 "",
4295
21.9k
                    ssn, p->payload_len, seq, ack);
4296
21.9k
            int retransmission = 0;
4297
4298
21.9k
            if (SEQ_EQ(seq, ssn->server.next_seq - 1) && SEQ_EQ(ack, ssn->client.last_ack)) {
4299
3.82k
                SCLogDebug("ssn %p: retransmission", ssn);
4300
3.82k
                retransmission = 1;
4301
3.82k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
4302
18.0k
            } else if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
4303
5.39k
                SCLogDebug("ssn %p: packet is retransmission", ssn);
4304
5.39k
                retransmission = 1;
4305
5.39k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
4306
4307
12.6k
            } else if (SEQ_LT(seq, ssn->server.next_seq) ||
4308
9.95k
                       SEQ_GT(seq, (ssn->server.last_ack + ssn->server.window))) {
4309
9.95k
                SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ "
4310
9.95k
                           "%" PRIu32 " != %" PRIu32 " from stream",
4311
9.95k
                        ssn, seq, ssn->server.next_seq);
4312
9.95k
                StreamTcpSetEvent(p, STREAM_FIN2_FIN_WRONG_SEQ);
4313
9.95k
                return -1;
4314
9.95k
            }
4315
4316
11.9k
            if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
4317
1.70k
                SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4318
1.70k
                StreamTcpSetEvent(p, STREAM_FIN2_INVALID_ACK);
4319
1.70k
                return -1;
4320
1.70k
            }
4321
4322
10.2k
            if (!retransmission) {
4323
1.04k
                StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
4324
1.04k
                SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
4325
4326
1.04k
                ssn->client.window = window << ssn->client.wscale;
4327
1.04k
            }
4328
4329
10.2k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4330
4.42k
                StreamTcpHandleTimestamp(ssn, p);
4331
4.42k
            }
4332
4333
            /* Update the next_seq, in case if we have missed the client
4334
               packet and server has already received and acked it */
4335
10.2k
            if (SEQ_LT(ssn->client.next_seq, ack))
4336
291
                ssn->client.next_seq = ack;
4337
4338
10.2k
            if (tcph->th_flags & TH_ACK)
4339
6.32k
                StreamTcpUpdateLastAck(ssn, &ssn->client, ack);
4340
4341
10.2k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
4342
10.2k
            SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
4343
10.2k
                    "%" PRIu32 "", ssn, ssn->server.next_seq,
4344
10.2k
                    ssn->client.last_ack);
4345
10.2k
        }
4346
4347
214k
    } else if (tcph->th_flags & TH_SYN) {
4348
11.7k
        SCLogDebug("ssn (%p): SYN pkt on FinWait2", ssn);
4349
11.7k
        StreamTcpSetEvent(p, STREAM_SHUTDOWN_SYN_RESEND);
4350
11.7k
        return -1;
4351
4352
203k
    } else if (tcph->th_flags & TH_ACK) {
4353
202k
        if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4354
51.6k
            if (!StreamTcpValidateTimestamp(ssn, p))
4355
17.6k
                return -1;
4356
51.6k
        }
4357
4358
185k
        if (PKT_IS_TOSERVER(p)) {
4359
89.4k
            SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
4360
89.4k
                       "%" PRIu32 ", ACK %" PRIu32 "",
4361
89.4k
                    ssn, p->payload_len, seq, ack);
4362
89.4k
            int retransmission = 0;
4363
4364
89.4k
            if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
4365
33.9k
                SCLogDebug("ssn %p: packet is retransmission", ssn);
4366
33.9k
                retransmission = 1;
4367
33.9k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
4368
33.9k
            }
4369
4370
89.4k
            if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
4371
3.82k
                SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4372
3.82k
                StreamTcpSetEvent(p, STREAM_FIN2_INVALID_ACK);
4373
3.82k
                return -1;
4374
3.82k
            }
4375
4376
85.6k
            if (!retransmission) {
4377
52.3k
                if (SEQ_LEQ(seq + p->payload_len, ssn->client.next_win) ||
4378
52.0k
                        (ssn->flags & (STREAMTCP_FLAG_MIDSTREAM | STREAMTCP_FLAG_ASYNC))) {
4379
52.0k
                    SCLogDebug("ssn %p: seq %" PRIu32 " in window, ssn->client.next_win "
4380
52.0k
                               "%" PRIu32 "",
4381
52.0k
                            ssn, seq, ssn->client.next_win);
4382
4383
52.0k
                } else {
4384
274
                    SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
4385
274
                               " != %" PRIu32 " from stream",
4386
274
                            ssn, seq, ssn->client.next_seq);
4387
274
                    StreamTcpSetEvent(p, STREAM_FIN2_ACK_WRONG_SEQ);
4388
274
                    return -1;
4389
274
                }
4390
4391
52.0k
                ssn->server.window = window << ssn->server.wscale;
4392
52.0k
            }
4393
4394
85.3k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4395
12.9k
                StreamTcpHandleTimestamp(ssn, p);
4396
12.9k
            }
4397
4398
85.3k
            if (SEQ_EQ(ssn->client.next_seq, seq)) {
4399
14.0k
                StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
4400
14.0k
            }
4401
4402
85.3k
            StreamTcpUpdateLastAck(ssn, &ssn->server, ack);
4403
4404
85.3k
            StreamTcpSackUpdatePacket(&ssn->server, p);
4405
4406
            /* update next_win */
4407
85.3k
            StreamTcpUpdateNextWin(ssn, &ssn->server, (ssn->server.last_ack + ssn->server.window));
4408
4409
85.3k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
4410
4411
85.3k
            SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
4412
85.3k
                    "%" PRIu32 "", ssn, ssn->client.next_seq,
4413
85.3k
                    ssn->server.last_ack);
4414
95.5k
        } else { /* implied to client */
4415
95.5k
            SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
4416
95.5k
                       "%" PRIu32 ", ACK %" PRIu32 "",
4417
95.5k
                    ssn, p->payload_len, seq, ack);
4418
95.5k
            int retransmission = 0;
4419
4420
95.5k
            if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
4421
60.4k
                SCLogDebug("ssn %p: packet is retransmission", ssn);
4422
60.4k
                retransmission = 1;
4423
60.4k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
4424
60.4k
            }
4425
4426
95.5k
            if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
4427
6.27k
                SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4428
6.27k
                StreamTcpSetEvent(p, STREAM_FIN2_INVALID_ACK);
4429
6.27k
                return -1;
4430
6.27k
            }
4431
4432
89.2k
            if (!retransmission) {
4433
30.6k
                if (SEQ_LEQ(seq + p->payload_len, ssn->server.next_win) ||
4434
30.2k
                        (ssn->flags & (STREAMTCP_FLAG_MIDSTREAM | STREAMTCP_FLAG_ASYNC))) {
4435
30.2k
                    SCLogDebug("ssn %p: seq %" PRIu32 " in window, ssn->server.next_win "
4436
30.2k
                               "%" PRIu32 "",
4437
30.2k
                            ssn, seq, ssn->server.next_win);
4438
30.2k
                } else {
4439
460
                    SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
4440
460
                               " != %" PRIu32 " from stream",
4441
460
                            ssn, seq, ssn->server.next_seq);
4442
460
                    StreamTcpSetEvent(p, STREAM_FIN2_ACK_WRONG_SEQ);
4443
460
                    return -1;
4444
460
                }
4445
4446
30.2k
                ssn->client.window = window << ssn->client.wscale;
4447
30.2k
            }
4448
4449
88.8k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4450
19.2k
                StreamTcpHandleTimestamp(ssn, p);
4451
19.2k
            }
4452
4453
88.8k
            if (SEQ_EQ(ssn->server.next_seq, seq)) {
4454
10.9k
                StreamTcpUpdateNextSeq(ssn, &ssn->server, (ssn->server.next_seq + p->payload_len));
4455
10.9k
            }
4456
4457
88.8k
            StreamTcpUpdateLastAck(ssn, &ssn->client, ack);
4458
4459
88.8k
            StreamTcpSackUpdatePacket(&ssn->client, p);
4460
4461
            /* update next_win */
4462
88.8k
            StreamTcpUpdateNextWin(ssn, &ssn->client, (ssn->client.last_ack + ssn->client.window));
4463
4464
88.8k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
4465
4466
88.8k
            SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
4467
88.8k
                    "%" PRIu32 "", ssn, ssn->server.next_seq,
4468
88.8k
                    ssn->client.last_ack);
4469
88.8k
        }
4470
185k
    } else {
4471
589
        SCLogDebug("ssn %p: default case", ssn);
4472
589
    }
4473
4474
195k
    return 0;
4475
252k
}
4476
4477
/**
4478
 *  \brief  Function to handle the TCP_CLOSING state. Upon arrival of ACK
4479
 *          the connection goes to TCP_TIME_WAIT state. The state has been
4480
 *          reached as both end application has been closed.
4481
 *
4482
 *  \param  tv      Thread Variable containing  input/output queue, cpu affinity
4483
 *  \param  p       Packet which has to be handled in this TCP state.
4484
 *  \param  stt     Stream Thread module registered to handle the stream handling
4485
 */
4486
4487
static int StreamTcpPacketStateClosing(
4488
        ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn)
4489
72.8k
{
4490
72.8k
    DEBUG_VALIDATE_BUG_ON(ssn == NULL);
4491
72.8k
    const TCPHdr *tcph = PacketGetTCP(p);
4492
72.8k
    const uint32_t seq = TCP_GET_RAW_SEQ(tcph);
4493
72.8k
    const uint32_t ack = TCP_GET_RAW_ACK(tcph);
4494
72.8k
    const uint16_t window = TCP_GET_RAW_WINDOW(tcph);
4495
4496
72.8k
    if (tcph->th_flags & TH_RST) {
4497
2.71k
        if (!StreamTcpValidateRst(ssn, p))
4498
1.28k
            return -1;
4499
4500
1.42k
        StreamTcpCloseSsnWithReset(p, ssn);
4501
4502
1.42k
        if (PKT_IS_TOSERVER(p)) {
4503
496
            if ((tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
4504
320
                StreamTcpUpdateLastAck(ssn, &ssn->server, ack);
4505
4506
496
            StreamTcpUpdateLastAck(ssn, &ssn->client, seq);
4507
4508
496
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4509
460
                StreamTcpHandleTimestamp(ssn, p);
4510
460
            }
4511
4512
496
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
4513
928
        } else {
4514
928
            if ((tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
4515
832
                StreamTcpUpdateLastAck(ssn, &ssn->client, ack);
4516
4517
928
            StreamTcpUpdateLastAck(ssn, &ssn->server, seq);
4518
4519
928
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4520
59
                StreamTcpHandleTimestamp(ssn, p);
4521
59
            }
4522
4523
928
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
4524
928
        }
4525
4526
70.1k
    } else if (tcph->th_flags & TH_SYN) {
4527
4.47k
        SCLogDebug("ssn (%p): SYN pkt on Closing", ssn);
4528
4.47k
        StreamTcpSetEvent(p, STREAM_SHUTDOWN_SYN_RESEND);
4529
4.47k
        return -1;
4530
4531
65.6k
    } else if (tcph->th_flags & TH_ACK) {
4532
52.0k
        if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4533
33.0k
            if (!StreamTcpValidateTimestamp(ssn, p))
4534
7.96k
                return -1;
4535
33.0k
        }
4536
4537
44.0k
        if (PKT_IS_TOSERVER(p)) {
4538
23.1k
            SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
4539
23.1k
                       "%" PRIu32 ", ACK %" PRIu32 "",
4540
23.1k
                    ssn, p->payload_len, seq, ack);
4541
23.1k
            int retransmission = 0;
4542
23.1k
            if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
4543
7.81k
                SCLogDebug("ssn %p: packet is retransmission", ssn);
4544
7.81k
                retransmission = 1;
4545
7.81k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
4546
7.81k
            }
4547
4548
23.1k
            if (seq != ssn->client.next_seq) {
4549
22.3k
                SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
4550
22.3k
                           " != %" PRIu32 " from stream",
4551
22.3k
                        ssn, seq, ssn->client.next_seq);
4552
22.3k
                StreamTcpSetEvent(p, STREAM_CLOSING_ACK_WRONG_SEQ);
4553
22.3k
                return -1;
4554
22.3k
            }
4555
4556
863
            if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
4557
473
                SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4558
473
                StreamTcpSetEvent(p, STREAM_CLOSING_INVALID_ACK);
4559
473
                return -1;
4560
473
            }
4561
4562
390
            if (!retransmission) {
4563
383
                StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
4564
383
                SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
4565
4566
383
                ssn->client.window = window << ssn->client.wscale;
4567
383
            }
4568
4569
390
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4570
239
                StreamTcpHandleTimestamp(ssn, p);
4571
239
            }
4572
            /* Update the next_seq, in case if we have missed the client
4573
               packet and server has already received and acked it */
4574
390
            if (SEQ_LT(ssn->server.next_seq, ack))
4575
135
                ssn->server.next_seq = ack;
4576
4577
390
            StreamTcpUpdateLastAck(ssn, &ssn->server, ack);
4578
4579
390
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
4580
390
            SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
4581
390
                    "%" PRIu32 "", ssn, ssn->client.next_seq,
4582
390
                    ssn->server.last_ack);
4583
20.8k
        } else { /* implied to client */
4584
20.8k
            SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
4585
20.8k
                       "%" PRIu32 ", ACK %" PRIu32 "",
4586
20.8k
                    ssn, p->payload_len, seq, ack);
4587
20.8k
            int retransmission = 0;
4588
20.8k
            if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
4589
9.28k
                SCLogDebug("ssn %p: packet is retransmission", ssn);
4590
9.28k
                retransmission = 1;
4591
9.28k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
4592
9.28k
            }
4593
4594
20.8k
            if (seq != ssn->server.next_seq) {
4595
19.3k
                SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
4596
19.3k
                           " != %" PRIu32 " from stream",
4597
19.3k
                        ssn, seq, ssn->server.next_seq);
4598
19.3k
                StreamTcpSetEvent(p, STREAM_CLOSING_ACK_WRONG_SEQ);
4599
19.3k
                return -1;
4600
19.3k
            }
4601
4602
1.51k
            if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
4603
1.03k
                SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4604
1.03k
                StreamTcpSetEvent(p, STREAM_CLOSING_INVALID_ACK);
4605
1.03k
                return -1;
4606
1.03k
            }
4607
4608
485
            if (!retransmission) {
4609
477
                StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
4610
477
                SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
4611
4612
477
                ssn->client.window = window << ssn->client.wscale;
4613
477
            }
4614
4615
485
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4616
156
                StreamTcpHandleTimestamp(ssn, p);
4617
156
            }
4618
4619
            /* Update the next_seq, in case if we have missed the client
4620
               packet and server has already received and acked it */
4621
485
            if (SEQ_LT(ssn->client.next_seq, ack))
4622
35
                ssn->client.next_seq = ack;
4623
4624
485
            StreamTcpUpdateLastAck(ssn, &ssn->client, ack);
4625
4626
485
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
4627
485
            SCLogDebug("StreamTcpPacketStateClosing (%p): =+ next SEQ "
4628
485
                    "%" PRIu32 ", last ACK %" PRIu32 "", ssn,
4629
485
                    ssn->server.next_seq, ssn->client.last_ack);
4630
485
        }
4631
44.0k
    } else {
4632
13.6k
        SCLogDebug("ssn %p: default case", ssn);
4633
13.6k
    }
4634
4635
15.9k
    return 0;
4636
72.8k
}
4637
4638
/**
4639
 *  \brief  Function to handle the TCP_CLOSE_WAIT state. Upon arrival of FIN
4640
 *          packet from server the connection goes to TCP_LAST_ACK state.
4641
 *          The state is possible only for server host.
4642
 *
4643
 *  \param  tv      Thread Variable containing  input/output queue, cpu affinity
4644
 *  \param  p       Packet which has to be handled in this TCP state.
4645
 *  \param  stt     Stream Thread module registered to handle the stream handling
4646
 */
4647
4648
static int StreamTcpPacketStateCloseWait(
4649
        ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn)
4650
411k
{
4651
411k
    SCEnter();
4652
411k
    const TCPHdr *tcph = PacketGetTCP(p);
4653
411k
    const uint32_t seq = TCP_GET_RAW_SEQ(tcph);
4654
411k
    const uint32_t ack = TCP_GET_RAW_ACK(tcph);
4655
411k
    const uint16_t window = TCP_GET_RAW_WINDOW(tcph);
4656
4657
411k
    DEBUG_VALIDATE_BUG_ON(ssn == NULL);
4658
4659
411k
    if (PKT_IS_TOCLIENT(p)) {
4660
166k
        SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
4661
166k
                   "%" PRIu32 ", ACK %" PRIu32 "",
4662
166k
                ssn, p->payload_len, seq, ack);
4663
244k
    } else {
4664
244k
        SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
4665
244k
                   "%" PRIu32 ", ACK %" PRIu32 "",
4666
244k
                ssn, p->payload_len, seq, ack);
4667
244k
    }
4668
4669
411k
    if (tcph->th_flags & TH_RST) {
4670
15.8k
        if (!StreamTcpValidateRst(ssn, p))
4671
6.55k
            return -1;
4672
4673
9.31k
        StreamTcpCloseSsnWithReset(p, ssn);
4674
4675
9.31k
        if (PKT_IS_TOSERVER(p)) {
4676
3.66k
            if ((tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
4677
771
                StreamTcpUpdateLastAck(ssn, &ssn->server, ack);
4678
4679
3.66k
            StreamTcpUpdateLastAck(ssn, &ssn->client, seq);
4680
4681
3.66k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4682
2.49k
                StreamTcpHandleTimestamp(ssn, p);
4683
2.49k
            }
4684
4685
3.66k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
4686
5.65k
        } else {
4687
5.65k
            if ((tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
4688
2.52k
                StreamTcpUpdateLastAck(ssn, &ssn->client, ack);
4689
4690
5.65k
            StreamTcpUpdateLastAck(ssn, &ssn->server, seq);
4691
4692
5.65k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4693
3.76k
                StreamTcpHandleTimestamp(ssn, p);
4694
3.76k
            }
4695
4696
5.65k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
4697
5.65k
        }
4698
4699
395k
    } else if (tcph->th_flags & TH_FIN) {
4700
100k
        if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4701
27.7k
            if (!StreamTcpValidateTimestamp(ssn, p))
4702
2.88k
                SCReturnInt(-1);
4703
27.7k
        }
4704
4705
97.2k
        if (PKT_IS_TOSERVER(p)) {
4706
79.3k
            SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
4707
79.3k
                       "%" PRIu32 ", ACK %" PRIu32 "",
4708
79.3k
                    ssn, p->payload_len, seq, ack);
4709
4710
79.3k
            int retransmission = 0;
4711
79.3k
            if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
4712
31.0k
                SCLogDebug("ssn %p: packet is retransmission", ssn);
4713
31.0k
                retransmission = 1;
4714
31.0k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
4715
31.0k
            }
4716
4717
79.3k
            if (!retransmission) {
4718
48.2k
                if (SEQ_LT(seq, ssn->client.next_seq) ||
4719
35.5k
                        SEQ_GT(seq, (ssn->client.last_ack + ssn->client.window))) {
4720
13.8k
                    SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
4721
13.8k
                               " != %" PRIu32 " from stream",
4722
13.8k
                            ssn, seq, ssn->client.next_seq);
4723
13.8k
                    StreamTcpSetEvent(p, STREAM_CLOSEWAIT_FIN_OUT_OF_WINDOW);
4724
13.8k
                    SCReturnInt(-1);
4725
13.8k
                }
4726
48.2k
            }
4727
4728
65.4k
            if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
4729
6.82k
                SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4730
6.82k
                StreamTcpSetEvent(p, STREAM_CLOSEWAIT_INVALID_ACK);
4731
6.82k
                SCReturnInt(-1);
4732
6.82k
            }
4733
4734
            /* don't update to LAST_ACK here as we want a toclient FIN for that */
4735
4736
58.6k
            if (!retransmission)
4737
30.3k
                ssn->server.window = window << ssn->server.wscale;
4738
4739
58.6k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4740
9.41k
                StreamTcpHandleTimestamp(ssn, p);
4741
9.41k
            }
4742
4743
            /* Update the next_seq, in case if we have missed the client
4744
               packet and server has already received and acked it */
4745
58.6k
            if (SEQ_LT(ssn->server.next_seq, ack))
4746
2.90k
                ssn->server.next_seq = ack;
4747
4748
58.6k
            if (tcph->th_flags & TH_ACK)
4749
19.1k
                StreamTcpUpdateLastAck(ssn, &ssn->server, ack);
4750
4751
58.6k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
4752
58.6k
            SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
4753
58.6k
                    "%" PRIu32 "", ssn, ssn->client.next_seq,
4754
58.6k
                    ssn->server.last_ack);
4755
58.6k
        } else {
4756
17.9k
            SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
4757
17.9k
                       "%" PRIu32 ", ACK %" PRIu32 "",
4758
17.9k
                    ssn, p->payload_len, seq, ack);
4759
4760
17.9k
            int retransmission = 0;
4761
17.9k
            if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
4762
1.59k
                SCLogDebug("ssn %p: packet is retransmission", ssn);
4763
1.59k
                retransmission = 1;
4764
1.59k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
4765
1.59k
            }
4766
4767
17.9k
            if (!retransmission) {
4768
16.3k
                if (SEQ_LT(seq, ssn->server.next_seq) ||
4769
12.3k
                        SEQ_GT(seq, (ssn->server.last_ack + ssn->server.window))) {
4770
4.32k
                    SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
4771
4.32k
                               " != %" PRIu32 " from stream",
4772
4.32k
                            ssn, seq, ssn->server.next_seq);
4773
4.32k
                    StreamTcpSetEvent(p, STREAM_CLOSEWAIT_FIN_OUT_OF_WINDOW);
4774
4.32k
                    SCReturnInt(-1);
4775
4.32k
                }
4776
16.3k
            }
4777
4778
13.6k
            if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
4779
453
                SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4780
453
                StreamTcpSetEvent(p, STREAM_CLOSEWAIT_INVALID_ACK);
4781
453
                SCReturnInt(-1);
4782
453
            }
4783
4784
13.1k
            if (!retransmission) {
4785
11.7k
                StreamTcpPacketSetState(p, ssn, TCP_LAST_ACK);
4786
11.7k
                SCLogDebug("ssn %p: state changed to TCP_LAST_ACK", ssn);
4787
4788
11.7k
                ssn->client.window = window << ssn->client.wscale;
4789
11.7k
            }
4790
4791
13.1k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4792
7.73k
                StreamTcpHandleTimestamp(ssn, p);
4793
7.73k
            }
4794
4795
            /* Update the next_seq, in case if we have missed the client
4796
               packet and server has already received and acked it */
4797
13.1k
            if (SEQ_LT(ssn->client.next_seq, ack))
4798
4.60k
                ssn->client.next_seq = ack;
4799
4800
13.1k
            if (tcph->th_flags & TH_ACK)
4801
11.5k
                StreamTcpUpdateLastAck(ssn, &ssn->client, ack);
4802
4803
13.1k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
4804
13.1k
            SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
4805
13.1k
                    "%" PRIu32 "", ssn, ssn->server.next_seq,
4806
13.1k
                    ssn->client.last_ack);
4807
13.1k
        }
4808
4809
295k
    } else if (tcph->th_flags & TH_SYN) {
4810
14.0k
        SCLogDebug("ssn (%p): SYN pkt on CloseWait", ssn);
4811
14.0k
        StreamTcpSetEvent(p, STREAM_SHUTDOWN_SYN_RESEND);
4812
14.0k
        SCReturnInt(-1);
4813
4814
281k
    } else if (tcph->th_flags & TH_ACK) {
4815
279k
        if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4816
181k
            if (!StreamTcpValidateTimestamp(ssn, p))
4817
43.2k
                SCReturnInt(-1);
4818
181k
        }
4819
4820
236k
        if (PKT_IS_TOSERVER(p)) {
4821
122k
            SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
4822
122k
                       "%" PRIu32 ", ACK %" PRIu32 "",
4823
122k
                    ssn, p->payload_len, seq, ack);
4824
4825
122k
            int retransmission = 0;
4826
122k
            if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
4827
36.2k
                SCLogDebug("ssn %p: packet is retransmission", ssn);
4828
36.2k
                retransmission = 1;
4829
36.2k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
4830
36.2k
            }
4831
4832
122k
            if (p->payload_len > 0 && (SEQ_LEQ((seq + p->payload_len), ssn->client.last_ack))) {
4833
19.2k
                SCLogDebug("ssn %p: -> retransmission", ssn);
4834
19.2k
                StreamTcpSetEvent(p, STREAM_CLOSEWAIT_PKT_BEFORE_LAST_ACK);
4835
19.2k
                SCReturnInt(-1);
4836
4837
103k
            } else if (SEQ_GT(seq, (ssn->client.last_ack + ssn->client.window))) {
4838
2.61k
                SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
4839
2.61k
                           " != %" PRIu32 " from stream",
4840
2.61k
                        ssn, seq, ssn->client.next_seq);
4841
2.61k
                StreamTcpSetEvent(p, STREAM_CLOSEWAIT_ACK_OUT_OF_WINDOW);
4842
2.61k
                SCReturnInt(-1);
4843
2.61k
            }
4844
4845
100k
            if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
4846
11.9k
                SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4847
11.9k
                StreamTcpSetEvent(p, STREAM_CLOSEWAIT_INVALID_ACK);
4848
11.9k
                SCReturnInt(-1);
4849
11.9k
            }
4850
4851
88.6k
            if (!retransmission) {
4852
75.1k
                ssn->server.window = window << ssn->server.wscale;
4853
75.1k
            }
4854
4855
88.6k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4856
62.5k
                StreamTcpHandleTimestamp(ssn, p);
4857
62.5k
            }
4858
4859
            /* Update the next_seq, in case if we have missed the client
4860
               packet and server has already received and acked it */
4861
88.6k
            if (SEQ_LT(ssn->server.next_seq, ack))
4862
8.75k
                ssn->server.next_seq = ack;
4863
4864
88.6k
            if (SEQ_EQ(seq, ssn->client.next_seq))
4865
46.7k
                StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
4866
4867
88.6k
            StreamTcpUpdateLastAck(ssn, &ssn->server, ack);
4868
4869
88.6k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
4870
88.6k
            SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
4871
88.6k
                    "%" PRIu32 "", ssn, ssn->client.next_seq,
4872
88.6k
                    ssn->server.last_ack);
4873
114k
        } else {
4874
114k
            SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
4875
114k
                       "%" PRIu32 ", ACK %" PRIu32 "",
4876
114k
                    ssn, p->payload_len, seq, ack);
4877
114k
            int retransmission = 0;
4878
114k
            if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
4879
24.9k
                SCLogDebug("ssn %p: packet is retransmission", ssn);
4880
24.9k
                retransmission = 1;
4881
24.9k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
4882
24.9k
            }
4883
4884
114k
            if (p->payload_len > 0 && (SEQ_LEQ((seq + p->payload_len), ssn->server.last_ack))) {
4885
21.0k
                SCLogDebug("ssn %p: -> retransmission", ssn);
4886
21.0k
                StreamTcpSetEvent(p, STREAM_CLOSEWAIT_PKT_BEFORE_LAST_ACK);
4887
21.0k
                SCReturnInt(-1);
4888
4889
93.1k
            } else if (SEQ_GT(seq, (ssn->server.last_ack + ssn->server.window))) {
4890
4.29k
                SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
4891
4.29k
                           " != %" PRIu32 " from stream",
4892
4.29k
                        ssn, seq, ssn->server.next_seq);
4893
4.29k
                StreamTcpSetEvent(p, STREAM_CLOSEWAIT_ACK_OUT_OF_WINDOW);
4894
4.29k
                SCReturnInt(-1);
4895
4.29k
            }
4896
4897
88.8k
            if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
4898
975
                SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
4899
975
                StreamTcpSetEvent(p, STREAM_CLOSEWAIT_INVALID_ACK);
4900
975
                SCReturnInt(-1);
4901
975
            }
4902
4903
87.8k
            if (!retransmission) {
4904
84.1k
                ssn->client.window = window << ssn->client.wscale;
4905
84.1k
            }
4906
4907
87.8k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4908
57.4k
                StreamTcpHandleTimestamp(ssn, p);
4909
57.4k
            }
4910
4911
            /* Update the next_seq, in case if we have missed the client
4912
               packet and server has already received and acked it */
4913
87.8k
            if (SEQ_LT(ssn->client.next_seq, ack))
4914
15.6k
                ssn->client.next_seq = ack;
4915
4916
87.8k
            if (SEQ_EQ(seq, ssn->server.next_seq))
4917
58.4k
                StreamTcpUpdateNextSeq(ssn, &ssn->server, (ssn->server.next_seq + p->payload_len));
4918
4919
87.8k
            StreamTcpUpdateLastAck(ssn, &ssn->client, ack);
4920
4921
87.8k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
4922
87.8k
            SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
4923
87.8k
                    "%" PRIu32 "", ssn, ssn->server.next_seq,
4924
87.8k
                    ssn->client.last_ack);
4925
87.8k
        }
4926
4927
236k
    } else {
4928
1.52k
        SCLogDebug("ssn %p: default case", ssn);
4929
1.52k
    }
4930
411k
    SCReturnInt(0);
4931
411k
}
4932
4933
/**
4934
 *  \brief  Function to handle the TCP_LAST_ACK state. Upon arrival of ACK
4935
 *          the connection goes to TCP_CLOSED state and stream memory is
4936
 *          returned back to pool. The state is possible only for server host.
4937
 *
4938
 *  \param  tv      Thread Variable containing  input/output queue, cpu affinity
4939
 *  \param  p       Packet which has to be handled in this TCP state.
4940
 *  \param  stt     Stream Thread module registered to handle the stream handling
4941
 */
4942
4943
static int StreamTcpPacketStateLastAck(
4944
        ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn)
4945
60.1k
{
4946
60.1k
    DEBUG_VALIDATE_BUG_ON(ssn == NULL);
4947
60.1k
    const TCPHdr *tcph = PacketGetTCP(p);
4948
60.1k
    const uint32_t seq = TCP_GET_RAW_SEQ(tcph);
4949
60.1k
    const uint32_t ack = TCP_GET_RAW_ACK(tcph);
4950
60.1k
    const uint16_t window = TCP_GET_RAW_WINDOW(tcph);
4951
4952
60.1k
    if (tcph->th_flags & TH_RST) {
4953
3.37k
        if (!StreamTcpValidateRst(ssn, p))
4954
728
            return -1;
4955
4956
2.64k
        StreamTcpCloseSsnWithReset(p, ssn);
4957
4958
2.64k
        if (PKT_IS_TOSERVER(p)) {
4959
1.33k
            if ((tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
4960
529
                StreamTcpUpdateLastAck(ssn, &ssn->server, ack);
4961
4962
1.33k
            StreamTcpUpdateLastAck(ssn, &ssn->client, seq);
4963
4964
1.33k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4965
1.01k
                StreamTcpHandleTimestamp(ssn, p);
4966
1.01k
            }
4967
4968
1.33k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
4969
1.33k
        } else {
4970
1.30k
            if ((tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
4971
464
                StreamTcpUpdateLastAck(ssn, &ssn->client, ack);
4972
4973
1.30k
            StreamTcpUpdateLastAck(ssn, &ssn->server, seq);
4974
4975
1.30k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4976
447
                StreamTcpHandleTimestamp(ssn, p);
4977
447
            }
4978
4979
1.30k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
4980
1.30k
        }
4981
4982
56.8k
    } else if (tcph->th_flags & TH_FIN) {
4983
        /** \todo */
4984
9.59k
        SCLogDebug("ssn (%p): FIN pkt on LastAck", ssn);
4985
4986
47.2k
    } else if (tcph->th_flags & TH_SYN) {
4987
3.44k
        SCLogDebug("ssn (%p): SYN pkt on LastAck", ssn);
4988
3.44k
        StreamTcpSetEvent(p, STREAM_SHUTDOWN_SYN_RESEND);
4989
3.44k
        return -1;
4990
4991
43.7k
    } else if (tcph->th_flags & TH_ACK) {
4992
43.0k
        if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
4993
29.3k
            if (!StreamTcpValidateTimestamp(ssn, p))
4994
5.69k
                return -1;
4995
29.3k
        }
4996
4997
37.3k
        if (PKT_IS_TOSERVER(p)) {
4998
23.7k
            SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
4999
23.7k
                       "%" PRIu32 ", ACK %" PRIu32 "",
5000
23.7k
                    ssn, p->payload_len, seq, ack);
5001
5002
23.7k
            int retransmission = 0;
5003
23.7k
            if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
5004
5.88k
                SCLogDebug("ssn %p: packet is retransmission", ssn);
5005
5.88k
                retransmission = 1;
5006
5.88k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
5007
5.88k
            }
5008
5009
23.7k
            if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
5010
705
                SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
5011
705
                StreamTcpSetEvent(p, STREAM_LASTACK_INVALID_ACK);
5012
705
                SCReturnInt(-1);
5013
705
            }
5014
5015
23.0k
            if (!retransmission) {
5016
17.2k
                if (SEQ_LT(seq, ssn->client.next_seq)) {
5017
8.30k
                    SCLogDebug("ssn %p: not updating state as packet is before next_seq", ssn);
5018
8.91k
                } else if (seq != ssn->client.next_seq && seq != ssn->client.next_seq + 1) {
5019
2.36k
                    SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
5020
2.36k
                               " != %" PRIu32 " from stream",
5021
2.36k
                            ssn, seq, ssn->client.next_seq);
5022
2.36k
                    StreamTcpSetEvent(p, STREAM_LASTACK_ACK_WRONG_SEQ);
5023
2.36k
                    return -1;
5024
6.55k
                } else {
5025
6.55k
                    StreamTcpPacketSetState(p, ssn, TCP_CLOSED);
5026
6.55k
                    SCLogDebug("ssn %p: state changed to TCP_CLOSED", ssn);
5027
6.55k
                }
5028
14.8k
                ssn->server.window = window << ssn->server.wscale;
5029
14.8k
            }
5030
5031
20.6k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
5032
11.8k
                StreamTcpHandleTimestamp(ssn, p);
5033
11.8k
            }
5034
5035
            /* Update the next_seq, in case if we have missed the client
5036
               packet and server has already received and acked it */
5037
20.6k
            if (SEQ_LT(ssn->server.next_seq, ack))
5038
8.44k
                ssn->server.next_seq = ack;
5039
5040
20.6k
            StreamTcpUpdateLastAck(ssn, &ssn->server, ack);
5041
5042
20.6k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
5043
20.6k
            SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
5044
20.6k
                    "%" PRIu32 "", ssn, ssn->client.next_seq,
5045
20.6k
                    ssn->server.last_ack);
5046
20.6k
        }
5047
37.3k
    } else {
5048
755
        SCLogDebug("ssn %p: default case", ssn);
5049
755
    }
5050
5051
47.2k
    return 0;
5052
60.1k
}
5053
5054
/**
5055
 *  \brief  Function to handle the TCP_TIME_WAIT state. Upon arrival of ACK
5056
 *          the connection goes to TCP_CLOSED state and stream memory is
5057
 *          returned back to pool.
5058
 *
5059
 *  \param  tv      Thread Variable containing  input/output queue, cpu affinity
5060
 *  \param  p       Packet which has to be handled in this TCP state.
5061
 *  \param  stt     Stream Thread module registered to handle the stream handling
5062
 */
5063
5064
static int StreamTcpPacketStateTimeWait(
5065
        ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn)
5066
114k
{
5067
114k
    DEBUG_VALIDATE_BUG_ON(ssn == NULL);
5068
114k
    const TCPHdr *tcph = PacketGetTCP(p);
5069
114k
    const uint32_t seq = TCP_GET_RAW_SEQ(tcph);
5070
114k
    const uint32_t ack = TCP_GET_RAW_ACK(tcph);
5071
114k
    const uint16_t window = TCP_GET_RAW_WINDOW(tcph);
5072
5073
114k
    if (tcph->th_flags & TH_RST) {
5074
6.31k
        if (!StreamTcpValidateRst(ssn, p))
5075
3.37k
            return -1;
5076
5077
2.94k
        StreamTcpCloseSsnWithReset(p, ssn);
5078
5079
2.94k
        if (PKT_IS_TOSERVER(p)) {
5080
995
            if ((tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
5081
332
                StreamTcpUpdateLastAck(ssn, &ssn->server, ack);
5082
5083
995
            StreamTcpUpdateLastAck(ssn, &ssn->client, seq);
5084
5085
995
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
5086
866
                StreamTcpHandleTimestamp(ssn, p);
5087
866
            }
5088
5089
995
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
5090
1.95k
        } else {
5091
1.95k
            if ((tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
5092
620
                StreamTcpUpdateLastAck(ssn, &ssn->client, ack);
5093
5094
1.95k
            StreamTcpUpdateLastAck(ssn, &ssn->server, seq);
5095
5096
1.95k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
5097
872
                StreamTcpHandleTimestamp(ssn, p);
5098
872
            }
5099
5100
1.95k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
5101
1.95k
        }
5102
5103
107k
    } else if (tcph->th_flags & TH_FIN) {
5104
        /** \todo */
5105
5106
88.2k
    } else if (tcph->th_flags & TH_SYN) {
5107
15.6k
        SCLogDebug("ssn (%p): SYN pkt on TimeWait", ssn);
5108
15.6k
        StreamTcpSetEvent(p, STREAM_SHUTDOWN_SYN_RESEND);
5109
15.6k
        return -1;
5110
5111
72.6k
    } else if (tcph->th_flags & TH_ACK) {
5112
71.2k
        if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
5113
36.1k
            if (!StreamTcpValidateTimestamp(ssn, p))
5114
11.4k
                return -1;
5115
36.1k
        }
5116
5117
59.8k
        if (PKT_IS_TOSERVER(p)) {
5118
32.8k
            SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
5119
32.8k
                       "%" PRIu32 ", ACK %" PRIu32 "",
5120
32.8k
                    ssn, p->payload_len, seq, ack);
5121
32.8k
            int retransmission = 0;
5122
32.8k
            if (StreamTcpPacketIsRetransmission(&ssn->client, p)) {
5123
10.5k
                SCLogDebug("ssn %p: packet is retransmission", ssn);
5124
10.5k
                retransmission = 1;
5125
10.5k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
5126
5127
22.3k
            } else if (seq != ssn->client.next_seq && seq != ssn->client.next_seq + 1) {
5128
20.7k
                SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
5129
20.7k
                           " != %" PRIu32 " from stream",
5130
20.7k
                        ssn, seq, ssn->client.next_seq);
5131
20.7k
                StreamTcpSetEvent(p, STREAM_TIMEWAIT_ACK_WRONG_SEQ);
5132
20.7k
                return -1;
5133
20.7k
            }
5134
5135
12.1k
            if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
5136
2.04k
                SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
5137
2.04k
                StreamTcpSetEvent(p, STREAM_TIMEWAIT_INVALID_ACK);
5138
2.04k
                SCReturnInt(-1);
5139
2.04k
            }
5140
5141
10.0k
            if (!retransmission) {
5142
875
                StreamTcpPacketSetState(p, ssn, TCP_CLOSED);
5143
875
                SCLogDebug("ssn %p: state changed to TCP_CLOSED", ssn);
5144
5145
875
                ssn->server.window = window << ssn->server.wscale;
5146
875
            }
5147
5148
10.0k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
5149
5.20k
                StreamTcpHandleTimestamp(ssn, p);
5150
5.20k
            }
5151
5152
            /* Update the next_seq, in case if we have missed the client
5153
               packet and server has already received and acked it */
5154
10.0k
            if (SEQ_LT(ssn->server.next_seq, ack))
5155
474
                ssn->server.next_seq = ack;
5156
5157
10.0k
            StreamTcpUpdateLastAck(ssn, &ssn->server, ack);
5158
5159
10.0k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
5160
10.0k
            SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
5161
10.0k
                    "%" PRIu32 "", ssn, ssn->client.next_seq,
5162
10.0k
                    ssn->server.last_ack);
5163
27.0k
        } else {
5164
27.0k
            SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
5165
27.0k
                       "%" PRIu32 ", ACK %" PRIu32 "",
5166
27.0k
                    ssn, p->payload_len, seq, ack);
5167
27.0k
            int retransmission = 0;
5168
27.0k
            if (StreamTcpPacketIsRetransmission(&ssn->server, p)) {
5169
10.4k
                SCLogDebug("ssn %p: packet is retransmission", ssn);
5170
10.4k
                retransmission = 1;
5171
10.4k
                STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_RETRANSMISSION);
5172
16.5k
            } else if (seq != ssn->server.next_seq - 1 && seq != ssn->server.next_seq) {
5173
10.8k
                if (p->payload_len > 0 && seq == ssn->server.last_ack) {
5174
359
                    SCLogDebug("ssn %p: -> retransmission", ssn);
5175
359
                    SCReturnInt(0);
5176
10.5k
                } else {
5177
10.5k
                    SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
5178
10.5k
                               " != %" PRIu32 " from stream",
5179
10.5k
                            ssn, seq, ssn->server.next_seq);
5180
10.5k
                    StreamTcpSetEvent(p, STREAM_TIMEWAIT_ACK_WRONG_SEQ);
5181
10.5k
                    return -1;
5182
10.5k
                }
5183
10.8k
            }
5184
5185
16.1k
            if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
5186
1.87k
                SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
5187
1.87k
                StreamTcpSetEvent(p, STREAM_TIMEWAIT_INVALID_ACK);
5188
1.87k
                SCReturnInt(-1);
5189
1.87k
            }
5190
5191
14.2k
            if (!retransmission) {
5192
4.24k
                StreamTcpPacketSetState(p, ssn, TCP_CLOSED);
5193
4.24k
                SCLogDebug("ssn %p: state changed to TCP_CLOSED", ssn);
5194
5195
4.24k
                ssn->client.window = window << ssn->client.wscale;
5196
4.24k
            }
5197
5198
14.2k
            if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
5199
6.54k
                StreamTcpHandleTimestamp(ssn, p);
5200
6.54k
            }
5201
5202
            /* Update the next_seq, in case if we have missed the client
5203
               packet and server has already received and acked it */
5204
14.2k
            if (SEQ_LT(ssn->client.next_seq, ack))
5205
3.99k
                ssn->client.next_seq = ack;
5206
5207
14.2k
            StreamTcpUpdateLastAck(ssn, &ssn->client, ack);
5208
5209
14.2k
            StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
5210
14.2k
            SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
5211
14.2k
                    "%" PRIu32 "", ssn, ssn->server.next_seq,
5212
14.2k
                    ssn->client.last_ack);
5213
14.2k
        }
5214
5215
59.8k
    } else {
5216
1.30k
        SCLogDebug("ssn %p: default case", ssn);
5217
1.30k
    }
5218
5219
48.2k
    return 0;
5220
114k
}
5221
5222
static int StreamTcpPacketStateClosed(
5223
        ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn)
5224
378k
{
5225
378k
    DEBUG_VALIDATE_BUG_ON(ssn == NULL);
5226
5227
378k
    const TCPHdr *tcph = PacketGetTCP(p);
5228
378k
    if (tcph->th_flags & TH_RST) {
5229
22.6k
        SCLogDebug("RST on closed state");
5230
22.6k
        return 0;
5231
22.6k
    }
5232
5233
356k
    TcpStream *stream = NULL, *ostream = NULL;
5234
356k
    if (PKT_IS_TOSERVER(p)) {
5235
180k
        stream = &ssn->client;
5236
180k
        ostream = &ssn->server;
5237
180k
    } else {
5238
175k
        stream = &ssn->server;
5239
175k
        ostream = &ssn->client;
5240
175k
    }
5241
5242
356k
    SCLogDebug("stream %s ostream %s",
5243
356k
            stream->flags & STREAMTCP_STREAM_FLAG_RST_RECV?"true":"false",
5244
356k
            ostream->flags & STREAMTCP_STREAM_FLAG_RST_RECV ? "true":"false");
5245
5246
    /* if we've seen a RST on our direction, but not on the other
5247
     * see if we perhaps need to continue processing anyway. */
5248
356k
    if ((stream->flags & STREAMTCP_STREAM_FLAG_RST_RECV) == 0) {
5249
354k
        if (ostream->flags & STREAMTCP_STREAM_FLAG_RST_RECV) {
5250
3.29k
            if (StreamTcpStateDispatch(tv, p, stt, ssn, ssn->pstate) < 0)
5251
1.96k
                return -1;
5252
            /* if state is still "closed", it wasn't updated by our dispatch. */
5253
1.33k
            if (ssn->state == TCP_CLOSED)
5254
1.04k
                ssn->state = ssn->pstate;
5255
1.33k
        }
5256
354k
    }
5257
354k
    return 0;
5258
356k
}
5259
5260
static void StreamTcpPacketCheckPostRst(TcpSession *ssn, Packet *p)
5261
8.57M
{
5262
8.57M
    if (p->flags & PKT_PSEUDO_STREAM_END) {
5263
197k
        return;
5264
197k
    }
5265
8.38M
    const TCPHdr *tcph = PacketGetTCP(p);
5266
    /* more RSTs are not unusual */
5267
8.38M
    if ((tcph->th_flags & (TH_RST)) != 0) {
5268
85.1k
        return;
5269
85.1k
    }
5270
5271
8.29M
    TcpStream *ostream = NULL;
5272
8.29M
    if (PKT_IS_TOSERVER(p)) {
5273
4.56M
        ostream = &ssn->server;
5274
4.56M
    } else {
5275
3.73M
        ostream = &ssn->client;
5276
3.73M
    }
5277
5278
8.29M
    if (ostream->flags & STREAMTCP_STREAM_FLAG_RST_RECV) {
5279
4.08k
        SCLogDebug("regular packet %"PRIu64" from same sender as "
5280
4.08k
                "the previous RST. Looks like it injected!", p->pcap_cnt);
5281
4.08k
        ostream->flags &= ~STREAMTCP_STREAM_FLAG_RST_RECV;
5282
4.08k
        ssn->flags &= ~STREAMTCP_FLAG_CLOSED_BY_RST;
5283
4.08k
        StreamTcpSetEvent(p, STREAM_SUSPECTED_RST_INJECT);
5284
4.08k
        return;
5285
4.08k
    }
5286
8.29M
}
5287
5288
/**
5289
 *  \retval 1 packet is a keep alive pkt
5290
 *  \retval 0 packet is not a keep alive pkt
5291
 */
5292
static int StreamTcpPacketIsKeepAlive(TcpSession *ssn, Packet *p)
5293
9.28M
{
5294
9.28M
    if (p->flags & PKT_PSEUDO_STREAM_END)
5295
0
        return 0;
5296
5297
    /* rfc 1122:
5298
       An implementation SHOULD send a keep-alive segment with no
5299
       data; however, it MAY be configurable to send a keep-alive
5300
       segment containing one garbage octet, for compatibility with
5301
       erroneous TCP implementations.
5302
     */
5303
9.28M
    if (p->payload_len > 1)
5304
6.27M
        return 0;
5305
5306
3.00M
    const TCPHdr *tcph = PacketGetTCP(p);
5307
3.00M
    if ((tcph->th_flags & (TH_SYN | TH_FIN | TH_RST)) != 0) {
5308
789k
        return 0;
5309
789k
    }
5310
5311
2.21M
    TcpStream *stream = NULL, *ostream = NULL;
5312
2.21M
    if (PKT_IS_TOSERVER(p)) {
5313
1.10M
        stream = &ssn->client;
5314
1.10M
        ostream = &ssn->server;
5315
1.10M
    } else {
5316
1.10M
        stream = &ssn->server;
5317
1.10M
        ostream = &ssn->client;
5318
1.10M
    }
5319
5320
2.21M
    const uint32_t seq = TCP_GET_RAW_SEQ(tcph);
5321
2.21M
    const uint32_t ack = TCP_GET_RAW_ACK(tcph);
5322
2.21M
    if (ack == ostream->last_ack && seq == (stream->next_seq - 1)) {
5323
26.8k
        SCLogDebug("packet is TCP keep-alive: %"PRIu64, p->pcap_cnt);
5324
26.8k
        stream->flags |= STREAMTCP_STREAM_FLAG_KEEPALIVE;
5325
26.8k
        STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_KEEPALIVE);
5326
26.8k
        return 1;
5327
26.8k
    }
5328
2.18M
    SCLogDebug("seq %u (%u), ack %u (%u)", seq,  (stream->next_seq - 1), ack, ostream->last_ack);
5329
2.18M
    return 0;
5330
2.21M
}
5331
5332
/**
5333
 *  \retval 1 packet is a keep alive ACK pkt
5334
 *  \retval 0 packet is not a keep alive ACK pkt
5335
 */
5336
static int StreamTcpPacketIsKeepAliveACK(TcpSession *ssn, Packet *p)
5337
9.25M
{
5338
9.25M
    TcpStream *stream = NULL, *ostream = NULL;
5339
9.25M
    uint32_t seq;
5340
9.25M
    uint32_t ack;
5341
9.25M
    uint32_t pkt_win;
5342
5343
9.25M
    if (p->flags & PKT_PSEUDO_STREAM_END)
5344
0
        return 0;
5345
    /* should get a normal ACK to a Keep Alive */
5346
9.25M
    if (p->payload_len > 0)
5347
6.95M
        return 0;
5348
5349
2.30M
    const TCPHdr *tcph = PacketGetTCP(p);
5350
2.30M
    if ((tcph->th_flags & (TH_SYN | TH_FIN | TH_RST)) != 0)
5351
783k
        return 0;
5352
5353
1.52M
    if (TCP_GET_RAW_WINDOW(tcph) == 0)
5354
2.39k
        return 0;
5355
5356
1.51M
    if (PKT_IS_TOSERVER(p)) {
5357
849k
        stream = &ssn->client;
5358
849k
        ostream = &ssn->server;
5359
849k
    } else {
5360
668k
        stream = &ssn->server;
5361
668k
        ostream = &ssn->client;
5362
668k
    }
5363
5364
1.51M
    seq = TCP_GET_RAW_SEQ(tcph);
5365
1.51M
    ack = TCP_GET_RAW_ACK(tcph);
5366
5367
1.51M
    pkt_win = TCP_GET_RAW_WINDOW(tcph) << ostream->wscale;
5368
1.51M
    if (pkt_win != ostream->window)
5369
683k
        return 0;
5370
5371
834k
    if ((ostream->flags & STREAMTCP_STREAM_FLAG_KEEPALIVE) && ack == ostream->last_ack && seq == stream->next_seq) {
5372
2.64k
        SCLogDebug("packet is TCP keep-aliveACK: %"PRIu64, p->pcap_cnt);
5373
2.64k
        ostream->flags &= ~STREAMTCP_STREAM_FLAG_KEEPALIVE;
5374
2.64k
        STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_KEEPALIVEACK);
5375
2.64k
        return 1;
5376
2.64k
    }
5377
831k
    SCLogDebug("seq %u (%u), ack %u (%u) FLAG_KEEPALIVE: %s", seq, stream->next_seq, ack, ostream->last_ack,
5378
831k
            ostream->flags & STREAMTCP_STREAM_FLAG_KEEPALIVE ? "set" : "not set");
5379
831k
    return 0;
5380
834k
}
5381
5382
static void StreamTcpClearKeepAliveFlag(TcpSession *ssn, Packet *p)
5383
9.25M
{
5384
9.25M
    TcpStream *stream = NULL;
5385
5386
9.25M
    if (p->flags & PKT_PSEUDO_STREAM_END)
5387
0
        return;
5388
5389
9.25M
    if (PKT_IS_TOSERVER(p)) {
5390
5.02M
        stream = &ssn->client;
5391
5.02M
    } else {
5392
4.23M
        stream = &ssn->server;
5393
4.23M
    }
5394
5395
9.25M
    if (stream->flags & STREAMTCP_STREAM_FLAG_KEEPALIVE) {
5396
21.2k
        stream->flags &= ~STREAMTCP_STREAM_FLAG_KEEPALIVE;
5397
21.2k
        SCLogDebug("FLAG_KEEPALIVE cleared");
5398
21.2k
    }
5399
9.25M
}
5400
5401
/**
5402
 *  \retval 1 packet is a window update pkt
5403
 *  \retval 0 packet is not a window update pkt
5404
 */
5405
static int StreamTcpPacketIsWindowUpdate(TcpSession *ssn, Packet *p)
5406
9.25M
{
5407
9.25M
    TcpStream *stream = NULL, *ostream = NULL;
5408
9.25M
    uint32_t seq;
5409
9.25M
    uint32_t ack;
5410
9.25M
    uint32_t pkt_win;
5411
5412
9.25M
    if (p->flags & PKT_PSEUDO_STREAM_END)
5413
0
        return 0;
5414
5415
9.25M
    if (ssn->state < TCP_ESTABLISHED)
5416
593k
        return 0;
5417
5418
8.65M
    if (p->payload_len > 0)
5419
6.77M
        return 0;
5420
5421
1.88M
    const TCPHdr *tcph = PacketGetTCP(p);
5422
1.88M
    if ((tcph->th_flags & (TH_SYN | TH_FIN | TH_RST)) != 0)
5423
516k
        return 0;
5424
5425
1.36M
    if (TCP_GET_RAW_WINDOW(tcph) == 0)
5426
2.17k
        return 0;
5427
5428
1.36M
    if (PKT_IS_TOSERVER(p)) {
5429
733k
        stream = &ssn->client;
5430
733k
        ostream = &ssn->server;
5431
733k
    } else {
5432
634k
        stream = &ssn->server;
5433
634k
        ostream = &ssn->client;
5434
634k
    }
5435
5436
1.36M
    seq = TCP_GET_RAW_SEQ(tcph);
5437
1.36M
    ack = TCP_GET_RAW_ACK(tcph);
5438
5439
1.36M
    pkt_win = TCP_GET_RAW_WINDOW(tcph) << ostream->wscale;
5440
1.36M
    if (pkt_win == ostream->window)
5441
793k
        return 0;
5442
5443
574k
    if (ack == ostream->last_ack && seq == stream->next_seq) {
5444
33.9k
        SCLogDebug("packet is TCP window update: %"PRIu64, p->pcap_cnt);
5445
33.9k
        STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_WINDOWUPDATE);
5446
33.9k
        return 1;
5447
33.9k
    }
5448
540k
    SCLogDebug("seq %u (%u), ack %u (%u)", seq, stream->next_seq, ack, ostream->last_ack);
5449
540k
    return 0;
5450
574k
}
5451
5452
/**
5453
 *  Try to detect whether a packet is a valid FIN 4whs final ack.
5454
 *
5455
 */
5456
static int StreamTcpPacketIsFinShutdownAck(TcpSession *ssn, Packet *p)
5457
9.25M
{
5458
9.25M
    TcpStream *stream = NULL, *ostream = NULL;
5459
9.25M
    uint32_t seq;
5460
9.25M
    uint32_t ack;
5461
5462
9.25M
    if (p->flags & PKT_PSEUDO_STREAM_END)
5463
0
        return 0;
5464
9.25M
    if (!(ssn->state == TCP_TIME_WAIT || ssn->state == TCP_CLOSE_WAIT || ssn->state == TCP_LAST_ACK))
5465
8.62M
        return 0;
5466
626k
    const TCPHdr *tcph = PacketGetTCP(p);
5467
626k
    if (tcph->th_flags != TH_ACK)
5468
444k
        return 0;
5469
181k
    if (p->payload_len != 0)
5470
2.61k
        return 0;
5471
5472
178k
    if (PKT_IS_TOSERVER(p)) {
5473
100k
        stream = &ssn->client;
5474
100k
        ostream = &ssn->server;
5475
100k
    } else {
5476
77.7k
        stream = &ssn->server;
5477
77.7k
        ostream = &ssn->client;
5478
77.7k
    }
5479
5480
178k
    seq = TCP_GET_RAW_SEQ(tcph);
5481
178k
    ack = TCP_GET_RAW_ACK(tcph);
5482
5483
178k
    SCLogDebug("%"PRIu64", seq %u ack %u stream->next_seq %u ostream->next_seq %u",
5484
178k
            p->pcap_cnt, seq, ack, stream->next_seq, ostream->next_seq);
5485
5486
178k
    if (SEQ_EQ(stream->next_seq + 1, seq) && SEQ_EQ(ack, ostream->next_seq + 1)) {
5487
1.54k
        return 1;
5488
1.54k
    }
5489
177k
    return 0;
5490
178k
}
5491
5492
/**
5493
 *  Try to detect packets doing bad window updates
5494
 *
5495
 *  See bug 1238.
5496
 *
5497
 *  Find packets that are unexpected, and shrink the window to the point
5498
 *  where the packets we do expect are rejected for being out of window.
5499
 *
5500
 *  The logic we use here is:
5501
 *  - packet seq > next_seq
5502
 *  - packet ack > next_seq (packet acks unseen data)
5503
 *  - packet shrinks window more than it's own data size
5504
 *  - packet shrinks window more than the diff between it's ack and the
5505
 *    last_ack value
5506
 *
5507
 *  Packets coming in after packet loss can look quite a bit like this.
5508
 */
5509
static int StreamTcpPacketIsBadWindowUpdate(TcpSession *ssn, Packet *p)
5510
9.21M
{
5511
9.21M
    TcpStream *stream = NULL, *ostream = NULL;
5512
9.21M
    uint32_t seq;
5513
9.21M
    uint32_t ack;
5514
9.21M
    uint32_t pkt_win;
5515
5516
9.21M
    if (p->flags & PKT_PSEUDO_STREAM_END)
5517
0
        return 0;
5518
5519
9.21M
    if (ssn->state < TCP_ESTABLISHED || ssn->state == TCP_CLOSED)
5520
999k
        return 0;
5521
5522
8.21M
    const TCPHdr *tcph = PacketGetTCP(p);
5523
8.21M
    if ((tcph->th_flags & (TH_SYN | TH_FIN | TH_RST)) != 0)
5524
741k
        return 0;
5525
5526
7.47M
    if (PKT_IS_TOSERVER(p)) {
5527
4.09M
        stream = &ssn->client;
5528
4.09M
        ostream = &ssn->server;
5529
4.09M
    } else {
5530
3.38M
        stream = &ssn->server;
5531
3.38M
        ostream = &ssn->client;
5532
3.38M
    }
5533
5534
7.47M
    seq = TCP_GET_RAW_SEQ(tcph);
5535
7.47M
    ack = TCP_GET_RAW_ACK(tcph);
5536
7.47M
    pkt_win = TCP_GET_RAW_WINDOW(tcph) << ostream->wscale;
5537
5538
7.47M
    if (pkt_win < ostream->window) {
5539
754k
        uint32_t diff = ostream->window - pkt_win;
5540
754k
        if (diff > p->payload_len &&
5541
667k
                SEQ_GT(ack, ostream->next_seq) &&
5542
89.8k
                SEQ_GT(seq, stream->next_seq))
5543
44.7k
        {
5544
44.7k
            SCLogDebug("%"PRIu64", pkt_win %u, stream win %u, diff %u, dsize %u",
5545
44.7k
                p->pcap_cnt, pkt_win, ostream->window, diff, p->payload_len);
5546
44.7k
            SCLogDebug("%"PRIu64", pkt_win %u, stream win %u",
5547
44.7k
                p->pcap_cnt, pkt_win, ostream->window);
5548
44.7k
            SCLogDebug("%"PRIu64", seq %u ack %u ostream->next_seq %u ostream->last_ack %u, ostream->next_win %u, diff %u (%u)",
5549
44.7k
                    p->pcap_cnt, seq, ack, ostream->next_seq, ostream->last_ack, ostream->next_win,
5550
44.7k
                    ostream->next_seq - ostream->last_ack, stream->next_seq - stream->last_ack);
5551
5552
            /* get the expected window shrinking from looking at ack vs last_ack.
5553
             * Observed a lot of just a little overrunning that value. So added some
5554
             * margin that is still ok. To make sure this isn't a loophole to still
5555
             * close the window, this is limited to windows above 1024. Both values
5556
             * are rather arbitrary. */
5557
44.7k
            uint32_t adiff = ack - ostream->last_ack;
5558
44.7k
            if (((pkt_win > 1024) && (diff > (adiff + 32))) ||
5559
10.7k
                ((pkt_win <= 1024) && (diff > adiff)))
5560
35.2k
            {
5561
35.2k
                SCLogDebug("pkt ACK %u is %u bytes beyond last_ack %u, shrinks window by %u "
5562
35.2k
                        "(allowing 32 bytes extra): pkt WIN %u", ack, adiff, ostream->last_ack, diff, pkt_win);
5563
35.2k
                SCLogDebug("%u - %u = %u (state %u)", diff, adiff, diff - adiff, ssn->state);
5564
35.2k
                StreamTcpSetEvent(p, STREAM_PKT_BAD_WINDOW_UPDATE);
5565
35.2k
                return 1;
5566
35.2k
            }
5567
44.7k
        }
5568
5569
754k
    }
5570
7.44M
    SCLogDebug("seq %u (%u), ack %u (%u)", seq, stream->next_seq, ack, ostream->last_ack);
5571
7.44M
    return 0;
5572
7.47M
}
5573
5574
/** \internal
5575
 *  \brief call packet handling function for 'state'
5576
 *  \param state current TCP state
5577
 */
5578
static inline int StreamTcpStateDispatch(
5579
        ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn, const uint8_t state)
5580
8.95M
{
5581
8.95M
    DEBUG_VALIDATE_BUG_ON(ssn == NULL);
5582
5583
8.95M
    SCLogDebug("ssn: %p", ssn);
5584
8.95M
    switch (state) {
5585
255k
        case TCP_SYN_SENT:
5586
255k
            SCLogDebug("packet received on TCP_SYN_SENT state");
5587
255k
            if (StreamTcpPacketStateSynSent(tv, p, stt, ssn)) {
5588
43.3k
                return -1;
5589
43.3k
            }
5590
211k
            break;
5591
314k
        case TCP_SYN_RECV:
5592
314k
            SCLogDebug("packet received on TCP_SYN_RECV state");
5593
314k
            if (StreamTcpPacketStateSynRecv(tv, p, stt, ssn)) {
5594
124k
                return -1;
5595
124k
            }
5596
190k
            break;
5597
6.62M
        case TCP_ESTABLISHED:
5598
6.62M
            SCLogDebug("packet received on TCP_ESTABLISHED state");
5599
6.62M
            if (StreamTcpPacketStateEstablished(tv, p, stt, ssn)) {
5600
235k
                return -1;
5601
235k
            }
5602
6.39M
            break;
5603
6.39M
        case TCP_FIN_WAIT1:
5604
468k
            SCLogDebug("packet received on TCP_FIN_WAIT1 state");
5605
468k
            if (StreamTcpPacketStateFinWait1(tv, p, stt, ssn)) {
5606
153k
                return -1;
5607
153k
            }
5608
315k
            break;
5609
315k
        case TCP_FIN_WAIT2:
5610
252k
            SCLogDebug("packet received on TCP_FIN_WAIT2 state");
5611
252k
            if (StreamTcpPacketStateFinWait2(tv, p, stt, ssn)) {
5612
57.4k
                return -1;
5613
57.4k
            }
5614
195k
            break;
5615
195k
        case TCP_CLOSING:
5616
72.8k
            SCLogDebug("packet received on TCP_CLOSING state");
5617
72.8k
            if (StreamTcpPacketStateClosing(tv, p, stt, ssn)) {
5618
56.9k
                return -1;
5619
56.9k
            }
5620
15.9k
            break;
5621
411k
        case TCP_CLOSE_WAIT:
5622
411k
            SCLogDebug("packet received on TCP_CLOSE_WAIT state");
5623
411k
            if (StreamTcpPacketStateCloseWait(tv, p, stt, ssn)) {
5624
152k
                return -1;
5625
152k
            }
5626
259k
            break;
5627
259k
        case TCP_LAST_ACK:
5628
60.1k
            SCLogDebug("packet received on TCP_LAST_ACK state");
5629
60.1k
            if (StreamTcpPacketStateLastAck(tv, p, stt, ssn)) {
5630
12.9k
                return -1;
5631
12.9k
            }
5632
47.2k
            break;
5633
114k
        case TCP_TIME_WAIT:
5634
114k
            SCLogDebug("packet received on TCP_TIME_WAIT state");
5635
114k
            if (StreamTcpPacketStateTimeWait(tv, p, stt, ssn)) {
5636
65.6k
                return -1;
5637
65.6k
            }
5638
48.5k
            break;
5639
378k
        case TCP_CLOSED:
5640
            /* TCP session memory is not returned to pool until timeout. */
5641
378k
            SCLogDebug("packet received on closed state");
5642
5643
378k
            if (StreamTcpPacketStateClosed(tv, p, stt, ssn)) {
5644
1.96k
                return -1;
5645
1.96k
            }
5646
5647
376k
            break;
5648
376k
        default:
5649
0
            SCLogDebug("packet received on default state");
5650
0
            break;
5651
8.95M
    }
5652
8.05M
    return 0;
5653
8.95M
}
5654
5655
static inline void CheckThreadId(ThreadVars *tv, Packet *p, StreamTcpThread *stt)
5656
9.85M
{
5657
9.85M
    const int idx = (!(PKT_IS_TOSERVER(p)));
5658
5659
    /* assign the thread id to the flow */
5660
9.85M
    if (likely(p->flow->thread_id[idx] != 0)) {
5661
0
        if (unlikely((FlowThreadId)tv->id != p->flow->thread_id[idx])) {
5662
0
            SCLogDebug("wrong thread: flow has %u, we are %d", p->flow->thread_id[idx], tv->id);
5663
0
            if (p->pkt_src == PKT_SRC_WIRE) {
5664
0
                StatsIncr(tv, stt->counter_tcp_wrong_thread);
5665
0
                if ((p->flow->flags & FLOW_WRONG_THREAD) == 0) {
5666
0
                    p->flow->flags |= FLOW_WRONG_THREAD;
5667
0
                    StreamTcpSetEvent(p, STREAM_WRONG_THREAD);
5668
0
                }
5669
0
            }
5670
0
        }
5671
0
    }
5672
9.85M
}
5673
5674
/* flow is and stays locked */
5675
int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt,
5676
                     PacketQueueNoLock *pq)
5677
9.85M
{
5678
9.85M
    SCEnter();
5679
5680
9.85M
    DEBUG_ASSERT_FLOW_LOCKED(p->flow);
5681
5682
9.85M
    SCLogDebug("p->pcap_cnt %"PRIu64, p->pcap_cnt);
5683
5684
9.85M
    TcpSession *ssn = (TcpSession *)p->flow->protoctx;
5685
9.85M
    const TCPHdr *tcph = PacketGetTCP(p);
5686
5687
    /* track TCP flags */
5688
9.85M
    if (ssn != NULL) {
5689
9.48M
        ssn->tcp_packet_flags |= tcph->th_flags;
5690
9.48M
        if (PKT_IS_TOSERVER(p))
5691
5.14M
            ssn->client.tcp_flags |= tcph->th_flags;
5692
4.33M
        else if (PKT_IS_TOCLIENT(p))
5693
4.33M
            ssn->server.tcp_flags |= tcph->th_flags;
5694
5695
        /* check if we need to unset the ASYNC flag */
5696
9.48M
        if (ssn->flags & STREAMTCP_FLAG_ASYNC &&
5697
0
            ssn->client.tcp_flags != 0 &&
5698
0
            ssn->server.tcp_flags != 0)
5699
0
        {
5700
0
            SCLogDebug("ssn %p: removing ASYNC flag as we have packets on both sides", ssn);
5701
0
            ssn->flags &= ~STREAMTCP_FLAG_ASYNC;
5702
0
        }
5703
9.48M
    }
5704
5705
    /* broken TCP http://ask.wireshark.org/questions/3183/acknowledgment-number-broken-tcp-the-acknowledge-field-is-nonzero-while-the-ack-flag-is-not-set */
5706
9.85M
    if (!(tcph->th_flags & TH_ACK) && TCP_GET_RAW_ACK(tcph) != 0) {
5707
370k
        StreamTcpSetEvent(p, STREAM_PKT_BROKEN_ACK);
5708
370k
    }
5709
5710
9.85M
    if ((tcph->th_flags & TH_URG) && StreamTcpInlineDropUrg()) {
5711
0
        PacketDrop(p, ACTION_DROP, PKT_DROP_REASON_STREAM_URG);
5712
0
        SCLogDebug("dropping urgent packet");
5713
0
        SCReturnInt(0);
5714
0
    }
5715
5716
    /* If we are on IPS mode, and got a drop action triggered from
5717
     * the IP only module, or from a reassembled msg and/or from an
5718
     * applayer detection, then drop the rest of the packets of the
5719
     * same stream and avoid inspecting it any further */
5720
9.85M
    if (StreamTcpCheckFlowDrops(p) == 1) {
5721
0
        DEBUG_VALIDATE_BUG_ON(!(PKT_IS_PSEUDOPKT(p)) && !PacketCheckAction(p, ACTION_DROP));
5722
0
        SCLogDebug("flow triggered a drop rule");
5723
0
        StreamTcpDisableAppLayer(p->flow);
5724
        /* return the segments to the pool */
5725
0
        StreamTcpSessionPktFree(p);
5726
0
        SCReturnInt(0);
5727
0
    }
5728
5729
9.85M
    if (ssn == NULL || ssn->state == TCP_NONE) {
5730
376k
        if (StreamTcpPacketStateNone(tv, p, stt, ssn) == -1) {
5731
78.9k
            goto error;
5732
78.9k
        }
5733
297k
        ssn = (TcpSession *)p->flow->protoctx;
5734
5735
297k
        if (ssn != NULL)
5736
280k
            SCLogDebug("ssn->alproto %"PRIu16"", p->flow->alproto);
5737
9.48M
    } else {
5738
        /* special case for PKT_PSEUDO_STREAM_END packets:
5739
         * bypass the state handling and various packet checks,
5740
         * we care about reassembly here. */
5741
9.48M
        if (p->flags & PKT_PSEUDO_STREAM_END) {
5742
197k
            if (PKT_IS_TOCLIENT(p)) {
5743
92.7k
                StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
5744
104k
            } else {
5745
104k
                StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
5746
104k
            }
5747
            /* straight to 'skip' as we already handled reassembly */
5748
197k
            goto skip;
5749
197k
        }
5750
5751
9.28M
        if (p->flow->flags & FLOW_WRONG_THREAD) {
5752
            /* Stream and/or session in known bad condition. Block events
5753
             * from being set. */
5754
0
            p->flags |= PKT_STREAM_NO_EVENTS;
5755
0
        }
5756
5757
9.28M
        if (StreamTcpPacketIsKeepAlive(ssn, p) == 1) {
5758
26.8k
            goto skip;
5759
26.8k
        }
5760
9.25M
        if (StreamTcpPacketIsKeepAliveACK(ssn, p) == 1) {
5761
2.64k
            StreamTcpClearKeepAliveFlag(ssn, p);
5762
2.64k
            goto skip;
5763
2.64k
        }
5764
9.25M
        StreamTcpClearKeepAliveFlag(ssn, p);
5765
5766
9.25M
        const bool is_zwp_ack = StreamTcpPacketIsZeroWindowProbeAck(ssn, p);
5767
9.25M
        if (PKT_IS_TOCLIENT(p)) {
5768
4.23M
            ssn->flags &= ~STREAMTCP_FLAG_ZWP_TS;
5769
5.02M
        } else {
5770
5.02M
            ssn->flags &= ~STREAMTCP_FLAG_ZWP_TC;
5771
5.02M
        }
5772
9.25M
        if (is_zwp_ack) {
5773
32
            STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_TCP_ZERO_WIN_PROBE_ACK);
5774
32
            goto skip;
5775
32
        }
5776
5777
9.25M
        if (StreamTcpPacketIsDupAck(ssn, p)) {
5778
184k
            STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_DUP_ACK);
5779
            // TODO see if we can skip work on these
5780
184k
        }
5781
5782
        /* if packet is not a valid window update, check if it is perhaps
5783
         * a bad window update that we should ignore (and alert on) */
5784
9.25M
        if (StreamTcpPacketIsFinShutdownAck(ssn, p) == 0) {
5785
9.25M
            if (StreamTcpPacketIsWindowUpdate(ssn, p) == 0) {
5786
9.21M
                if (StreamTcpPacketIsBadWindowUpdate(ssn,p))
5787
35.2k
                    goto skip;
5788
9.18M
                if (StreamTcpPacketIsOutdatedAck(ssn, p))
5789
55.3k
                    goto skip;
5790
9.18M
            }
5791
9.25M
        }
5792
5793
9.16M
        int ret = StreamTcpPacketIsSpuriousRetransmission(ssn, p);
5794
9.16M
        if (ret > 0) {
5795
885k
            StreamTcpSetEvent(p, STREAM_PKT_SPURIOUS_RETRANSMISSION);
5796
            /* skip packet if fully before base_seq */
5797
885k
            if (ret == 2)
5798
212k
                goto skip;
5799
885k
        }
5800
5801
        /* handle the per 'state' logic */
5802
8.95M
        if (StreamTcpStateDispatch(tv, p, stt, ssn, ssn->state) < 0)
5803
902k
            goto error;
5804
5805
8.57M
    skip:
5806
8.57M
        StreamTcpPacketCheckPostRst(ssn, p);
5807
8.57M
    }
5808
5809
8.87M
    if (ssn != NULL) {
5810
        /* recalc the csum on the packet if it was modified */
5811
8.85M
        if (p->flags & PKT_STREAM_MODIFIED) {
5812
0
            ReCalculateChecksum(p);
5813
0
        }
5814
5815
        /* if ssn was set in this run, reflect TCP state on the packet */
5816
8.85M
        if (ssn->state >= TCP_ESTABLISHED) {
5817
8.38M
            p->flags |= PKT_STREAM_EST;
5818
8.38M
        }
5819
5820
        /* check for conditions that may make us not want to log this packet */
5821
5822
        /* streams that hit depth */
5823
8.85M
        if ((ssn->client.flags & STREAMTCP_STREAM_FLAG_DEPTH_REACHED) ||
5824
8.73M
             (ssn->server.flags & STREAMTCP_STREAM_FLAG_DEPTH_REACHED))
5825
156k
        {
5826
            /* we can call bypass callback, if enabled */
5827
156k
            if (StreamTcpBypassEnabled()) {
5828
0
                PacketBypassCallback(p);
5829
0
            }
5830
156k
        }
5831
5832
8.85M
        if ((ssn->client.flags & STREAMTCP_STREAM_FLAG_DEPTH_REACHED) ||
5833
8.73M
             (ssn->server.flags & STREAMTCP_STREAM_FLAG_DEPTH_REACHED))
5834
156k
        {
5835
156k
            p->flags |= PKT_STREAM_NOPCAPLOG;
5836
156k
        }
5837
5838
        /* encrypted packets */
5839
8.85M
        if ((PKT_IS_TOSERVER(p) && (ssn->client.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY)) ||
5840
8.52M
            (PKT_IS_TOCLIENT(p) && (ssn->server.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY)))
5841
596k
        {
5842
596k
            p->flags |= PKT_STREAM_NOPCAPLOG;
5843
596k
        }
5844
5845
8.85M
        if (ssn->flags & STREAMTCP_FLAG_BYPASS) {
5846
0
            PacketBypassCallback(p);
5847
8.85M
        } else if (g_detect_disabled &&
5848
0
                (ssn->client.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY) &&
5849
0
                (ssn->server.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY) &&
5850
0
                StreamTcpBypassEnabled())
5851
0
        {
5852
            /* if stream is dead and we have no detect engine at all, bypass. */
5853
0
            SCLogDebug("bypass as stream is dead and we have no rules");
5854
0
            PacketBypassCallback(p);
5855
0
        }
5856
8.85M
    }
5857
5858
8.87M
    SCReturnInt(0);
5859
5860
981k
error:
5861
    /* recalc the csum on the packet if it was modified */
5862
981k
    if (p->flags & PKT_STREAM_MODIFIED) {
5863
0
        ReCalculateChecksum(p);
5864
0
    }
5865
5866
981k
    if (StreamTcpInlineDropInvalid()) {
5867
        /* disable payload inspection as we're dropping this packet
5868
         * anyway. Doesn't disable all detection, so we can still
5869
         * match on the stream event that was set. */
5870
0
        DecodeSetNoPayloadInspectionFlag(p);
5871
0
        PacketDrop(p, ACTION_DROP, PKT_DROP_REASON_STREAM_ERROR);
5872
0
    }
5873
981k
    SCReturnInt(-1);
5874
9.85M
}
5875
5876
/**
5877
 *  \brief  Function to validate the checksum of the received packet. If the
5878
 *          checksum is invalid, packet will be dropped, as the end system will
5879
 *          also drop the packet.
5880
 *
5881
 *  \param  p       Packet of which checksum has to be validated
5882
 *  \retval  1 if the checksum is valid, otherwise 0
5883
 */
5884
static inline int StreamTcpValidateChecksum(Packet *p)
5885
0
{
5886
0
    int ret = 1;
5887
5888
0
    if (p->flags & PKT_IGNORE_CHECKSUM)
5889
0
        return ret;
5890
5891
0
    if (!p->l4.csum_set) {
5892
0
        const TCPHdr *tcph = PacketGetTCP(p);
5893
0
        if (PacketIsIPv4(p)) {
5894
0
            const IPV4Hdr *ip4h = PacketGetIPv4(p);
5895
0
            p->l4.csum = TCPChecksum(ip4h->s_ip_addrs, (uint16_t *)tcph,
5896
0
                    (p->payload_len + TCP_GET_RAW_HLEN(tcph)), tcph->th_sum);
5897
0
            p->l4.csum_set = true;
5898
0
        } else if (PacketIsIPv6(p)) {
5899
0
            const IPV6Hdr *ip6h = PacketGetIPv6(p);
5900
0
            p->l4.csum = TCPV6Checksum(ip6h->s_ip6_addrs, (uint16_t *)tcph,
5901
0
                    (p->payload_len + TCP_GET_RAW_HLEN(tcph)), tcph->th_sum);
5902
0
            p->l4.csum_set = true;
5903
0
        }
5904
0
    }
5905
5906
0
    if (p->l4.csum != 0) {
5907
0
        ret = 0;
5908
0
        if (p->livedev) {
5909
0
            (void) SC_ATOMIC_ADD(p->livedev->invalid_checksums, 1);
5910
0
        } else if (p->pcap_cnt) {
5911
0
            PcapIncreaseInvalidChecksum();
5912
0
        }
5913
0
    }
5914
5915
0
    return ret;
5916
0
}
5917
5918
/** \internal
5919
 *  \brief check if a packet is a valid stream started
5920
 *  \retval bool true/false */
5921
static int TcpSessionPacketIsStreamStarter(const Packet *p)
5922
9.42M
{
5923
9.42M
    const TCPHdr *tcph = PacketGetTCP(p);
5924
9.42M
    if (tcph->th_flags & (TH_RST | TH_FIN)) {
5925
763k
        return 0;
5926
763k
    }
5927
5928
8.66M
    if ((tcph->th_flags & (TH_SYN | TH_ACK)) == TH_SYN) {
5929
136k
        SCLogDebug("packet %" PRIu64 " is a stream starter: %02x", p->pcap_cnt, tcph->th_flags);
5930
136k
        return 1;
5931
136k
    }
5932
5933
8.52M
    if (stream_config.midstream || stream_config.async_oneside) {
5934
8.52M
        if ((tcph->th_flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK)) {
5935
393k
            SCLogDebug("packet %" PRIu64 " is a midstream stream starter: %02x", p->pcap_cnt,
5936
393k
                    tcph->th_flags);
5937
393k
            return 1;
5938
393k
        }
5939
8.52M
    }
5940
8.13M
    return 0;
5941
8.52M
}
5942
5943
/** \internal
5944
 *  \brief Check if Flow and TCP SSN allow this flow/tuple to be reused
5945
 *  \retval bool true yes reuse, false no keep tracking old ssn */
5946
static bool TcpSessionReuseDoneEnoughSyn(const Packet *p, const Flow *f, const TcpSession *ssn)
5947
136k
{
5948
136k
    const TCPHdr *tcph = PacketGetTCP(p);
5949
136k
    if (FlowGetPacketDirection(f, p) == TOSERVER) {
5950
93.3k
        if (ssn == NULL) {
5951
            /* most likely a flow that was picked up after the 3whs, or a flow that
5952
             * does not have a session due to memcap issues. */
5953
5.06k
            SCLogDebug("steam starter packet %" PRIu64 ", ssn %p null. Reuse.", p->pcap_cnt, ssn);
5954
5.06k
            return true;
5955
5.06k
        }
5956
88.2k
        if (ssn->flags & STREAMTCP_FLAG_TFO_DATA_IGNORED) {
5957
24
            SCLogDebug("steam starter packet %" PRIu64
5958
24
                       ", ssn %p. STREAMTCP_FLAG_TFO_DATA_IGNORED set. Reuse.",
5959
24
                    p->pcap_cnt, ssn);
5960
24
            return true;
5961
24
        }
5962
88.2k
        if (SEQ_EQ(ssn->client.isn, TCP_GET_RAW_SEQ(tcph))) {
5963
76.9k
            SCLogDebug("steam starter packet %"PRIu64", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.", p->pcap_cnt, ssn);
5964
76.9k
            return false;
5965
76.9k
        }
5966
11.3k
        if (ssn->state >= TCP_LAST_ACK) {
5967
2.83k
            SCLogDebug("steam starter packet %"PRIu64", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->pcap_cnt, ssn, ssn->state);
5968
2.83k
            return true;
5969
8.48k
        } else if (ssn->state == TCP_NONE) {
5970
0
            SCLogDebug("steam starter packet %"PRIu64", ssn %p state == TCP_NONE (%u). Reuse.", p->pcap_cnt, ssn, ssn->state);
5971
0
            return true;
5972
8.48k
        } else { // < TCP_LAST_ACK
5973
8.48k
            SCLogDebug("steam starter packet %"PRIu64", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->pcap_cnt, ssn, ssn->state);
5974
8.48k
            return false;
5975
8.48k
        }
5976
5977
43.5k
    } else {
5978
43.5k
        if (ssn == NULL) {
5979
401
            SCLogDebug("steam starter packet %"PRIu64", ssn %p null. Reuse.", p->pcap_cnt, ssn);
5980
401
            return true;
5981
401
        }
5982
43.1k
        if (ssn->state >= TCP_LAST_ACK) {
5983
9.97k
            SCLogDebug("steam starter packet %"PRIu64", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->pcap_cnt, ssn, ssn->state);
5984
9.97k
            return true;
5985
33.2k
        } else if (ssn->state == TCP_NONE) {
5986
0
            SCLogDebug("steam starter packet %"PRIu64", ssn %p state == TCP_NONE (%u). Reuse.", p->pcap_cnt, ssn, ssn->state);
5987
0
            return true;
5988
33.2k
        } else { // < TCP_LAST_ACK
5989
33.2k
            SCLogDebug("steam starter packet %"PRIu64", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->pcap_cnt, ssn, ssn->state);
5990
33.2k
            return false;
5991
33.2k
        }
5992
43.1k
    }
5993
5994
0
    SCLogDebug("default: how did we get here?");
5995
0
    return false;
5996
136k
}
5997
5998
/** \internal
5999
 *  \brief check if ssn is done enough for reuse by syn/ack
6000
 *  \note should only be called if midstream is enabled
6001
 */
6002
static bool TcpSessionReuseDoneEnoughSynAck(const Packet *p, const Flow *f, const TcpSession *ssn)
6003
393k
{
6004
393k
    const TCPHdr *tcph = PacketGetTCP(p);
6005
393k
    if (FlowGetPacketDirection(f, p) == TOCLIENT) {
6006
293k
        if (ssn == NULL) {
6007
335
            SCLogDebug("steam starter packet %"PRIu64", ssn %p null. No reuse.", p->pcap_cnt, ssn);
6008
335
            return false;
6009
335
        }
6010
293k
        if (SEQ_EQ(ssn->server.isn, TCP_GET_RAW_SEQ(tcph))) {
6011
154k
            SCLogDebug("steam starter packet %"PRIu64", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.", p->pcap_cnt, ssn);
6012
154k
            return false;
6013
154k
        }
6014
138k
        if (ssn->state >= TCP_LAST_ACK) {
6015
24.4k
            SCLogDebug("steam starter packet %"PRIu64", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->pcap_cnt, ssn, ssn->state);
6016
24.4k
            return true;
6017
113k
        } else if (ssn->state == TCP_NONE) {
6018
0
            SCLogDebug("steam starter packet %"PRIu64", ssn %p state == TCP_NONE (%u). Reuse.", p->pcap_cnt, ssn, ssn->state);
6019
0
            return true;
6020
113k
        } else { // < TCP_LAST_ACK
6021
113k
            SCLogDebug("steam starter packet %"PRIu64", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->pcap_cnt, ssn, ssn->state);
6022
113k
            return false;
6023
113k
        }
6024
6025
138k
    } else {
6026
99.6k
        if (ssn == NULL) {
6027
1.06k
            SCLogDebug("steam starter packet %"PRIu64", ssn %p null. Reuse.", p->pcap_cnt, ssn);
6028
1.06k
            return true;
6029
1.06k
        }
6030
98.5k
        if (ssn->state >= TCP_LAST_ACK) {
6031
27.4k
            SCLogDebug("steam starter packet %"PRIu64", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->pcap_cnt, ssn, ssn->state);
6032
27.4k
            return true;
6033
71.1k
        } else if (ssn->state == TCP_NONE) {
6034
0
            SCLogDebug("steam starter packet %"PRIu64", ssn %p state == TCP_NONE (%u). Reuse.", p->pcap_cnt, ssn, ssn->state);
6035
0
            return true;
6036
71.1k
        } else { // < TCP_LAST_ACK
6037
71.1k
            SCLogDebug("steam starter packet %"PRIu64", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->pcap_cnt, ssn, ssn->state);
6038
71.1k
            return false;
6039
71.1k
        }
6040
98.5k
    }
6041
6042
0
    SCLogDebug("default: how did we get here?");
6043
0
    return false;
6044
393k
}
6045
6046
/** \brief Check if SSN is done enough for reuse
6047
 *
6048
 *  Reuse means a new TCP session reuses the tuple (flow in suri)
6049
 *
6050
 *  \retval bool true if ssn can be reused, false if not */
6051
static bool TcpSessionReuseDoneEnough(const Packet *p, const Flow *f, const TcpSession *ssn)
6052
530k
{
6053
530k
    const TCPHdr *tcph = PacketGetTCP(p);
6054
530k
    if ((tcph->th_flags & (TH_SYN | TH_ACK)) == TH_SYN) {
6055
136k
        return TcpSessionReuseDoneEnoughSyn(p, f, ssn);
6056
136k
    }
6057
6058
393k
    if (stream_config.midstream || stream_config.async_oneside) {
6059
393k
        if ((tcph->th_flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK)) {
6060
393k
            return TcpSessionReuseDoneEnoughSynAck(p, f, ssn);
6061
393k
        }
6062
393k
    }
6063
6064
0
    return false;
6065
393k
}
6066
6067
bool TcpSessionPacketSsnReuse(const Packet *p, const Flow *f, const void *tcp_ssn)
6068
10.5M
{
6069
10.5M
    if (p->proto == IPPROTO_TCP && PacketIsTCP(p)) {
6070
9.42M
        if (TcpSessionPacketIsStreamStarter(p) == 1) {
6071
530k
            if (TcpSessionReuseDoneEnough(p, f, tcp_ssn) == 1) {
6072
71.3k
                return true;
6073
71.3k
            }
6074
530k
        }
6075
9.42M
    }
6076
10.4M
    return false;
6077
10.5M
}
6078
6079
TmEcode StreamTcp (ThreadVars *tv, Packet *p, void *data, PacketQueueNoLock *pq)
6080
9.85M
{
6081
9.85M
    DEBUG_VALIDATE_BUG_ON(p->flow == NULL);
6082
9.85M
    if (unlikely(p->flow == NULL)) {
6083
0
        return TM_ECODE_OK;
6084
0
    }
6085
6086
9.85M
    StreamTcpThread *stt = (StreamTcpThread *)data;
6087
6088
9.85M
    SCLogDebug("p->pcap_cnt %" PRIu64 " direction %s pkt_src %s", p->pcap_cnt,
6089
9.85M
            p->flow ? (FlowGetPacketDirection(p->flow, p) == TOSERVER ? "toserver" : "toclient")
6090
9.85M
                    : "noflow",
6091
9.85M
            PktSrcToString(p->pkt_src));
6092
9.85M
    t_pcapcnt = p->pcap_cnt;
6093
6094
9.85M
    if (!(PacketIsTCP(p))) {
6095
0
        return TM_ECODE_OK;
6096
0
    }
6097
6098
9.85M
    CheckThreadId(tv, p, stt);
6099
6100
    /* only TCP packets with a flow from here */
6101
6102
9.85M
    if (!(p->flags & PKT_PSEUDO_STREAM_END)) {
6103
9.66M
        if (stream_config.flags & STREAMTCP_INIT_FLAG_CHECKSUM_VALIDATION) {
6104
0
            if (StreamTcpValidateChecksum(p) == 0) {
6105
0
                StatsIncr(tv, stt->counter_tcp_invalid_checksum);
6106
0
                return TM_ECODE_OK;
6107
0
            }
6108
0
        }
6109
9.66M
    }
6110
9.85M
    AppLayerProfilingReset(stt->ra_ctx->app_tctx);
6111
6112
9.85M
    (void)StreamTcpPacket(tv, p, stt, pq);
6113
6114
9.85M
    return TM_ECODE_OK;
6115
9.85M
}
6116
6117
TmEcode StreamTcpThreadInit(ThreadVars *tv, void *initdata, void **data)
6118
4
{
6119
4
    SCEnter();
6120
4
    StreamTcpThread *stt = SCCalloc(1, sizeof(StreamTcpThread));
6121
4
    if (unlikely(stt == NULL))
6122
0
        SCReturnInt(TM_ECODE_FAILED);
6123
4
    stt->ssn_pool_id = -1;
6124
4
    StreamTcpThreadCacheEnable();
6125
6126
4
    *data = (void *)stt;
6127
6128
4
    stt->counter_tcp_active_sessions = StatsRegisterCounter("tcp.active_sessions", tv);
6129
4
    stt->counter_tcp_sessions = StatsRegisterCounter("tcp.sessions", tv);
6130
4
    stt->counter_tcp_ssn_memcap = StatsRegisterCounter("tcp.ssn_memcap_drop", tv);
6131
4
    stt->counter_tcp_ssn_from_cache = StatsRegisterCounter("tcp.ssn_from_cache", tv);
6132
4
    stt->counter_tcp_ssn_from_pool = StatsRegisterCounter("tcp.ssn_from_pool", tv);
6133
4
    ExceptionPolicySetStatsCounters(tv, &stt->counter_tcp_ssn_memcap_eps, &stream_memcap_eps_stats,
6134
4
            stream_config.ssn_memcap_policy, "exception_policy.tcp.ssn_memcap.",
6135
4
            IsStreamTcpSessionMemcapExceptionPolicyStatsValid);
6136
6137
4
    stt->counter_tcp_pseudo = StatsRegisterCounter("tcp.pseudo", tv);
6138
4
    stt->counter_tcp_invalid_checksum = StatsRegisterCounter("tcp.invalid_checksum", tv);
6139
4
    stt->counter_tcp_midstream_pickups = StatsRegisterCounter("tcp.midstream_pickups", tv);
6140
4
    if (stream_config.midstream) {
6141
4
        ExceptionPolicySetStatsCounters(tv, &stt->counter_tcp_midstream_eps,
6142
4
                &stream_midstream_enabled_eps_stats, stream_config.midstream_policy,
6143
4
                "exception_policy.tcp.midstream.", IsMidstreamExceptionPolicyStatsValid);
6144
4
    } else {
6145
0
        ExceptionPolicySetStatsCounters(tv, &stt->counter_tcp_midstream_eps,
6146
0
                &stream_midstream_disabled_eps_stats, stream_config.midstream_policy,
6147
0
                "exception_policy.tcp.midstream.", IsMidstreamExceptionPolicyStatsValid);
6148
0
    }
6149
6150
4
    stt->counter_tcp_wrong_thread = StatsRegisterCounter("tcp.pkt_on_wrong_thread", tv);
6151
4
    stt->counter_tcp_ack_unseen_data = StatsRegisterCounter("tcp.ack_unseen_data", tv);
6152
6153
    /* init reassembly ctx */
6154
4
    stt->ra_ctx = StreamTcpReassembleInitThreadCtx(tv);
6155
4
    if (stt->ra_ctx == NULL)
6156
0
        SCReturnInt(TM_ECODE_FAILED);
6157
6158
4
    stt->ra_ctx->counter_tcp_segment_memcap = StatsRegisterCounter("tcp.segment_memcap_drop", tv);
6159
6160
4
    ExceptionPolicySetStatsCounters(tv, &stt->ra_ctx->counter_tcp_reas_eps,
6161
4
            &stream_reassembly_memcap_eps_stats, stream_config.reassembly_memcap_policy,
6162
4
            "exception_policy.tcp.reassembly.", IsReassemblyMemcapExceptionPolicyStatsValid);
6163
6164
4
    stt->ra_ctx->counter_tcp_segment_from_cache =
6165
4
            StatsRegisterCounter("tcp.segment_from_cache", tv);
6166
4
    stt->ra_ctx->counter_tcp_segment_from_pool = StatsRegisterCounter("tcp.segment_from_pool", tv);
6167
4
    stt->ra_ctx->counter_tcp_stream_depth = StatsRegisterCounter("tcp.stream_depth_reached", tv);
6168
4
    stt->ra_ctx->counter_tcp_reass_gap = StatsRegisterCounter("tcp.reassembly_gap", tv);
6169
4
    stt->ra_ctx->counter_tcp_reass_overlap = StatsRegisterCounter("tcp.overlap", tv);
6170
4
    stt->ra_ctx->counter_tcp_reass_overlap_diff_data = StatsRegisterCounter("tcp.overlap_diff_data", tv);
6171
6172
4
    stt->ra_ctx->counter_tcp_reass_data_normal_fail = StatsRegisterCounter("tcp.insert_data_normal_fail", tv);
6173
4
    stt->ra_ctx->counter_tcp_reass_data_overlap_fail = StatsRegisterCounter("tcp.insert_data_overlap_fail", tv);
6174
4
    stt->ra_ctx->counter_tcp_urgent_oob = StatsRegisterCounter("tcp.urgent_oob_data", tv);
6175
6176
4
    SCLogDebug("StreamTcp thread specific ctx online at %p, reassembly ctx %p",
6177
4
                stt, stt->ra_ctx);
6178
6179
4
    SCMutexLock(&ssn_pool_mutex);
6180
4
    if (ssn_pool == NULL) {
6181
4
        ssn_pool = PoolThreadInit(1, /* thread */
6182
4
                0, /* unlimited */
6183
4
                stream_config.prealloc_sessions,
6184
4
                sizeof(TcpSession),
6185
4
                StreamTcpSessionPoolAlloc,
6186
4
                StreamTcpSessionPoolInit, NULL,
6187
4
                StreamTcpSessionPoolCleanup, NULL);
6188
4
        stt->ssn_pool_id = 0;
6189
4
        SCLogDebug("pool size %d, thread ssn_pool_id %d", PoolThreadSize(ssn_pool), stt->ssn_pool_id);
6190
4
    } else {
6191
        /* grow ssn_pool until we have a element for our thread id */
6192
0
        stt->ssn_pool_id = PoolThreadExpand(ssn_pool);
6193
0
        SCLogDebug("pool size %d, thread ssn_pool_id %d", PoolThreadSize(ssn_pool), stt->ssn_pool_id);
6194
0
    }
6195
4
    SCMutexUnlock(&ssn_pool_mutex);
6196
4
    if (stt->ssn_pool_id < 0 || ssn_pool == NULL) {
6197
0
        SCLogError("failed to setup/expand stream session pool. Expand stream.memcap?");
6198
0
        SCReturnInt(TM_ECODE_FAILED);
6199
0
    }
6200
6201
4
    SCReturnInt(TM_ECODE_OK);
6202
4
}
6203
6204
TmEcode StreamTcpThreadDeinit(ThreadVars *tv, void *data)
6205
0
{
6206
0
    SCEnter();
6207
0
    StreamTcpThread *stt = (StreamTcpThread *)data;
6208
0
    if (stt == NULL) {
6209
0
        return TM_ECODE_OK;
6210
0
    }
6211
6212
    /* XXX */
6213
6214
    /* free reassembly ctx */
6215
0
    StreamTcpReassembleFreeThreadCtx(stt->ra_ctx);
6216
6217
    /* clear memory */
6218
0
    memset(stt, 0, sizeof(StreamTcpThread));
6219
6220
0
    SCFree(stt);
6221
0
    SCReturnInt(TM_ECODE_OK);
6222
0
}
6223
6224
/**
6225
 *  \brief   Function to check the validity of the RST packets based on the
6226
 *           target OS of the given packet.
6227
 *
6228
 *  \param   ssn    TCP session to which the given packet belongs
6229
 *  \param   p      Packet which has to be checked for its validity
6230
 *
6231
 *  \retval 0 unacceptable RST
6232
 *  \retval 1 acceptable RST
6233
 *
6234
 *  WebSense sends RST packets that are:
6235
 *  - RST flag, win 0, ack 0, seq = nextseq
6236
 *
6237
 */
6238
6239
static int StreamTcpValidateRst(TcpSession *ssn, Packet *p)
6240
121k
{
6241
121k
    uint8_t os_policy;
6242
121k
    const TCPHdr *tcph = PacketGetTCP(p);
6243
121k
    const uint32_t seq = TCP_GET_RAW_SEQ(tcph);
6244
6245
121k
    if (ssn->flags & STREAMTCP_FLAG_LOSSY_BE_LIBERAL) {
6246
11.9k
        SCReturnInt(1);
6247
11.9k
    }
6248
6249
109k
    if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
6250
41.8k
        if (!StreamTcpValidateTimestamp(ssn, p)) {
6251
786
            SCReturnInt(0);
6252
786
        }
6253
41.8k
    }
6254
6255
    /* RST with data, it's complicated:
6256
6257
         4.2.2.12  RST Segment: RFC-793 Section 3.4
6258
6259
            A TCP SHOULD allow a received RST segment to include data.
6260
6261
            DISCUSSION
6262
                 It has been suggested that a RST segment could contain
6263
                 ASCII text that encoded and explained the cause of the
6264
                 RST.  No standard has yet been established for such
6265
                 data.
6266
    */
6267
108k
    if (p->payload_len)
6268
44.3k
        StreamTcpSetEvent(p, STREAM_RST_WITH_DATA);
6269
6270
    /* Set up the os_policy to be used in validating the RST packets based on
6271
       target system */
6272
108k
    if (PKT_IS_TOSERVER(p)) {
6273
55.6k
        if (ssn->server.os_policy == 0)
6274
11.4k
            StreamTcpSetOSPolicy(&ssn->server, p);
6275
6276
55.6k
        os_policy = ssn->server.os_policy;
6277
6278
55.6k
        if (tcph->th_flags & TH_ACK && TCP_GET_RAW_ACK(tcph) &&
6279
25.1k
                StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
6280
8.56k
            SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
6281
8.56k
            StreamTcpSetEvent(p, STREAM_RST_INVALID_ACK);
6282
8.56k
            SCReturnInt(0);
6283
8.56k
        }
6284
6285
55.6k
    } else {
6286
53.2k
        if (ssn->client.os_policy == 0)
6287
9.94k
            StreamTcpSetOSPolicy(&ssn->client, p);
6288
6289
53.2k
        os_policy = ssn->client.os_policy;
6290
6291
53.2k
        if (tcph->th_flags & TH_ACK && TCP_GET_RAW_ACK(tcph) &&
6292
26.8k
                StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
6293
12.2k
            SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
6294
12.2k
            StreamTcpSetEvent(p, STREAM_RST_INVALID_ACK);
6295
12.2k
            SCReturnInt(0);
6296
12.2k
        }
6297
53.2k
    }
6298
6299
    /* RFC 2385 md5 signature header or RFC 5925 TCP AO headerpresent. Since we can't
6300
     * validate these (requires key that is set/transferred out of band), we can't know
6301
     * if the RST will be accepted or rejected by the end host. We accept it, but keep
6302
     * tracking if the sender of it ignores it, which would be a sign of injection. */
6303
88.1k
    if (p->l4.vars.tcp.md5_option_present || p->l4.vars.tcp.ao_option_present) {
6304
4.47k
        TcpStream *receiver_stream;
6305
4.47k
        if (PKT_IS_TOSERVER(p)) {
6306
2.34k
            receiver_stream = &ssn->server;
6307
2.34k
        } else {
6308
2.13k
            receiver_stream = &ssn->client;
6309
2.13k
        }
6310
4.47k
        SCLogDebug("ssn %p: setting STREAMTCP_STREAM_FLAG_RST_RECV on receiver stream", ssn);
6311
4.47k
        receiver_stream->flags |= STREAMTCP_STREAM_FLAG_RST_RECV;
6312
4.47k
    }
6313
6314
88.1k
    if (ssn->flags & STREAMTCP_FLAG_ASYNC) {
6315
0
        if (PKT_IS_TOSERVER(p)) {
6316
0
            if (SEQ_GEQ(seq, ssn->client.next_seq)) {
6317
0
                SCLogDebug("ssn %p: ASYNC accept RST", ssn);
6318
0
                return 1;
6319
0
            }
6320
0
        } else {
6321
0
            if (SEQ_GEQ(seq, ssn->server.next_seq)) {
6322
0
                SCLogDebug("ssn %p: ASYNC accept RST", ssn);
6323
0
                return 1;
6324
0
            }
6325
0
        }
6326
0
        SCLogDebug("ssn %p: ASYNC reject RST", ssn);
6327
0
        return 0;
6328
0
    }
6329
6330
88.1k
    switch (os_policy) {
6331
0
        case OS_POLICY_HPUX11:
6332
0
            if(PKT_IS_TOSERVER(p)){
6333
0
                if (SEQ_GEQ(seq, ssn->client.next_seq)) {
6334
0
                    SCLogDebug("reset is Valid! Packet SEQ: %" PRIu32 "", seq);
6335
0
                    return 1;
6336
0
                } else {
6337
0
                    SCLogDebug("reset is not Valid! Packet SEQ: %" PRIu32 " "
6338
0
                               "and server SEQ: %" PRIu32 "",
6339
0
                            seq, ssn->client.next_seq);
6340
0
                    return 0;
6341
0
                }
6342
0
            } else { /* implied to client */
6343
0
                if (SEQ_GEQ(seq, ssn->server.next_seq)) {
6344
0
                    SCLogDebug("reset is valid! Packet SEQ: %" PRIu32 "", seq);
6345
0
                    return 1;
6346
0
                } else {
6347
0
                    SCLogDebug("reset is not valid! Packet SEQ: %" PRIu32 " "
6348
0
                               "and client SEQ: %" PRIu32 "",
6349
0
                            seq, ssn->server.next_seq);
6350
0
                    return 0;
6351
0
                }
6352
0
            }
6353
0
            break;
6354
0
        case OS_POLICY_OLD_LINUX:
6355
0
        case OS_POLICY_LINUX:
6356
0
        case OS_POLICY_SOLARIS:
6357
0
            if(PKT_IS_TOSERVER(p)){
6358
0
                if (SEQ_GEQ((seq + p->payload_len),
6359
0
                            ssn->client.last_ack)) { /*window base is needed !!*/
6360
0
                    if (SEQ_LT(seq, (ssn->client.next_seq + ssn->client.window))) {
6361
0
                        SCLogDebug("reset is Valid! Packet SEQ: %" PRIu32 "", seq);
6362
0
                        return 1;
6363
0
                    }
6364
0
                } else {
6365
0
                    SCLogDebug("reset is not valid! Packet SEQ: %" PRIu32 " and"
6366
0
                               " server SEQ: %" PRIu32 "",
6367
0
                            seq, ssn->client.next_seq);
6368
0
                    return 0;
6369
0
                }
6370
0
            } else { /* implied to client */
6371
0
                if (SEQ_GEQ((seq + p->payload_len),
6372
0
                            ssn->server.last_ack)) { /*window base is needed !!*/
6373
0
                    if (SEQ_LT(seq, (ssn->server.next_seq + ssn->server.window))) {
6374
0
                        SCLogDebug("reset is Valid! Packet SEQ: %" PRIu32 "", seq);
6375
0
                        return 1;
6376
0
                    }
6377
0
                } else {
6378
0
                    SCLogDebug("reset is not valid! Packet SEQ: %" PRIu32 " and"
6379
0
                               " client SEQ: %" PRIu32 "",
6380
0
                            seq, ssn->server.next_seq);
6381
0
                    return 0;
6382
0
                }
6383
0
            }
6384
0
            break;
6385
0
        default:
6386
88.1k
        case OS_POLICY_BSD:
6387
88.1k
        case OS_POLICY_FIRST:
6388
88.1k
        case OS_POLICY_HPUX10:
6389
88.1k
        case OS_POLICY_IRIX:
6390
88.1k
        case OS_POLICY_MACOS:
6391
88.1k
        case OS_POLICY_LAST:
6392
88.1k
        case OS_POLICY_WINDOWS:
6393
88.1k
        case OS_POLICY_WINDOWS2K3:
6394
88.1k
        case OS_POLICY_VISTA:
6395
88.1k
            if(PKT_IS_TOSERVER(p)) {
6396
47.0k
                if (SEQ_EQ(seq, ssn->client.next_seq)) {
6397
22.0k
                    SCLogDebug("reset is valid! Packet SEQ: %" PRIu32 "", seq);
6398
22.0k
                    return 1;
6399
25.0k
                } else {
6400
25.0k
                    SCLogDebug("reset is not valid! Packet SEQ: %" PRIu32 " "
6401
25.0k
                               "and server SEQ: %" PRIu32 "",
6402
25.0k
                            seq, ssn->client.next_seq);
6403
25.0k
                    return 0;
6404
25.0k
                }
6405
47.0k
            } else { /* implied to client */
6406
41.0k
                if (SEQ_EQ(seq, ssn->server.next_seq)) {
6407
19.4k
                    SCLogDebug("reset is valid! Packet SEQ: %" PRIu32 " Stream %u", seq,
6408
19.4k
                            ssn->server.next_seq);
6409
19.4k
                    return 1;
6410
21.5k
                } else {
6411
21.5k
                    SCLogDebug("reset is not valid! Packet SEQ: %" PRIu32 " and"
6412
21.5k
                               " client SEQ: %" PRIu32 "",
6413
21.5k
                            seq, ssn->server.next_seq);
6414
21.5k
                    return 0;
6415
21.5k
                }
6416
41.0k
            }
6417
0
            break;
6418
88.1k
    }
6419
0
    return 0;
6420
88.1k
}
6421
6422
/**
6423
 *  \brief Function to check the validity of the received timestamp based on
6424
 *         the target OS of the given stream.
6425
 *
6426
 *  It's passive except for:
6427
 *  1. it sets the os policy on the stream if necessary
6428
 *  2. it sets an event in the packet if necessary
6429
 *
6430
 *  \param ssn TCP session to which the given packet belongs
6431
 *  \param p Packet which has to be checked for its validity
6432
 *
6433
 *  \retval 1 if the timestamp is valid
6434
 *  \retval 0 if the timestamp is invalid
6435
 */
6436
static int StreamTcpValidateTimestamp (TcpSession *ssn, Packet *p)
6437
1.53M
{
6438
1.53M
    SCEnter();
6439
6440
1.53M
    TcpStream *sender_stream;
6441
1.53M
    TcpStream *receiver_stream;
6442
1.53M
    uint8_t ret = 1;
6443
1.53M
    uint8_t check_ts = 1;
6444
1.53M
    const TCPHdr *tcph = PacketGetTCP(p);
6445
1.53M
    const uint32_t seq = TCP_GET_RAW_SEQ(tcph);
6446
6447
1.53M
    if (PKT_IS_TOSERVER(p)) {
6448
875k
        sender_stream = &ssn->client;
6449
875k
        receiver_stream = &ssn->server;
6450
875k
    } else {
6451
654k
        sender_stream = &ssn->server;
6452
654k
        receiver_stream = &ssn->client;
6453
654k
    }
6454
6455
    /* Set up the os_policy to be used in validating the timestamps based on
6456
       the target system */
6457
1.53M
    if (receiver_stream->os_policy == 0) {
6458
91.9k
        StreamTcpSetOSPolicy(receiver_stream, p);
6459
91.9k
    }
6460
6461
1.53M
    if (TCP_HAS_TS(p)) {
6462
1.40M
        uint32_t ts = TCP_GET_TSVAL(p);
6463
1.40M
        uint32_t last_pkt_ts = sender_stream->last_pkt_ts;
6464
1.40M
        uint32_t last_ts = sender_stream->last_ts;
6465
6466
1.40M
        if (sender_stream->flags & STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP) {
6467
            /* The 3whs used the timestamp with 0 value. */
6468
5.16k
            switch (receiver_stream->os_policy) {
6469
0
                case OS_POLICY_LINUX:
6470
0
                case OS_POLICY_WINDOWS2K3:
6471
                    /* Linux and windows 2003 does not allow the use of 0 as
6472
                     * timestamp in the 3whs. */
6473
0
                    check_ts = 0;
6474
0
                    break;
6475
6476
0
                case OS_POLICY_OLD_LINUX:
6477
0
                case OS_POLICY_WINDOWS:
6478
0
                case OS_POLICY_VISTA:
6479
0
                    if (SEQ_EQ(sender_stream->next_seq, seq)) {
6480
0
                        last_ts = ts;
6481
0
                        check_ts = 0; /*next packet will be checked for validity
6482
                                        and stream TS has been updated with this
6483
                                        one.*/
6484
0
                    }
6485
0
                    break;
6486
5.16k
            }
6487
5.16k
        }
6488
6489
1.40M
        if (receiver_stream->os_policy == OS_POLICY_HPUX11) {
6490
            /* HPUX11 ignores the timestamp of out of order packets */
6491
0
            if (!SEQ_EQ(sender_stream->next_seq, seq))
6492
0
                check_ts = 0;
6493
0
        }
6494
6495
1.40M
        if (ts == 0) {
6496
6.76k
            switch (receiver_stream->os_policy) {
6497
0
                case OS_POLICY_OLD_LINUX:
6498
0
                case OS_POLICY_WINDOWS:
6499
0
                case OS_POLICY_WINDOWS2K3:
6500
0
                case OS_POLICY_VISTA:
6501
0
                case OS_POLICY_SOLARIS:
6502
                    /* Old Linux and windows allowed packet with 0 timestamp. */
6503
0
                    break;
6504
6.76k
                default:
6505
                    /* other OS simply drop the packet with 0 timestamp, when
6506
                     * 3whs has valid timestamp*/
6507
6.76k
                    goto invalid;
6508
6.76k
            }
6509
6.76k
        }
6510
6511
1.39M
        if (check_ts) {
6512
1.39M
            int32_t result = 0;
6513
6514
1.39M
            SCLogDebug("ts %"PRIu32", last_ts %"PRIu32"", ts, last_ts);
6515
6516
1.39M
            if (receiver_stream->os_policy == OS_POLICY_LINUX || stream_config.liberal_timestamps) {
6517
                /* Linux accepts TS which are off by one.*/
6518
1.39M
                result = (int32_t) ((ts - last_ts) + 1);
6519
1.39M
            } else {
6520
0
                result = (int32_t) (ts - last_ts);
6521
0
            }
6522
6523
1.39M
            SCLogDebug("result %" PRIi32 ", p->ts(secs) %" PRIuMAX "", result,
6524
1.39M
                    (uintmax_t)SCTIME_SECS(p->ts));
6525
6526
1.39M
            if (last_pkt_ts == 0 &&
6527
89.0k
                    (ssn->flags & STREAMTCP_FLAG_MIDSTREAM))
6528
85.8k
            {
6529
85.8k
                last_pkt_ts = (uint32_t)SCTIME_SECS(p->ts);
6530
85.8k
            }
6531
6532
1.39M
            if (result < 0) {
6533
207k
                SCLogDebug("timestamp is not valid last_ts "
6534
207k
                           "%" PRIu32 " p->tcpvars->ts %" PRIu32 " result "
6535
207k
                           "%" PRId32 "", last_ts, ts, result);
6536
                /* candidate for rejection */
6537
207k
                ret = 0;
6538
1.18M
            } else if ((sender_stream->last_ts != 0) &&
6539
1.18M
                       (((uint32_t)SCTIME_SECS(p->ts)) > last_pkt_ts + PAWS_24DAYS)) {
6540
12.5k
                SCLogDebug("packet is not valid last_pkt_ts "
6541
12.5k
                           "%" PRIu32 " p->ts(sec) %" PRIu32 "",
6542
12.5k
                        last_pkt_ts, (uint32_t)SCTIME_SECS(p->ts));
6543
                /* candidate for rejection */
6544
12.5k
                ret = 0;
6545
12.5k
            }
6546
6547
1.39M
            if (ret == 0) {
6548
                /* if the timestamp of packet is not valid then, check if the
6549
                 * current stream timestamp is not so old. if so then we need to
6550
                 * accept the packet and update the stream->last_ts (RFC 1323)*/
6551
220k
                if ((SEQ_EQ(sender_stream->next_seq, seq)) &&
6552
26.7k
                        (((uint32_t)SCTIME_SECS(p->ts) > (last_pkt_ts + PAWS_24DAYS)))) {
6553
4.97k
                    SCLogDebug("timestamp considered valid anyway");
6554
215k
                } else {
6555
215k
                    goto invalid;
6556
215k
                }
6557
220k
            }
6558
1.39M
        }
6559
1.39M
    }
6560
6561
1.53M
    SCReturnInt(1);
6562
6563
221k
invalid:
6564
221k
    StreamTcpSetEvent(p, STREAM_PKT_INVALID_TIMESTAMP);
6565
221k
    SCReturnInt(0);
6566
1.53M
}
6567
6568
/**
6569
 *  \brief Function to check the validity of the received timestamp based on
6570
 *         the target OS of the given stream and update the session.
6571
 *
6572
 *  \param ssn TCP session to which the given packet belongs
6573
 *  \param p Packet which has to be checked for its validity
6574
 *
6575
 *  \retval 1 if the timestamp is valid
6576
 *  \retval 0 if the timestamp is invalid
6577
 */
6578
static int StreamTcpHandleTimestamp (TcpSession *ssn, Packet *p)
6579
1.09M
{
6580
1.09M
    SCEnter();
6581
6582
1.09M
    TcpStream *sender_stream;
6583
1.09M
    TcpStream *receiver_stream;
6584
1.09M
    uint8_t ret = 1;
6585
1.09M
    uint8_t check_ts = 1;
6586
1.09M
    const TCPHdr *tcph = PacketGetTCP(p);
6587
1.09M
    const uint32_t seq = TCP_GET_RAW_SEQ(tcph);
6588
6589
1.09M
    if (PKT_IS_TOSERVER(p)) {
6590
627k
        sender_stream = &ssn->client;
6591
627k
        receiver_stream = &ssn->server;
6592
627k
    } else {
6593
471k
        sender_stream = &ssn->server;
6594
471k
        receiver_stream = &ssn->client;
6595
471k
    }
6596
6597
    /* Set up the os_policy to be used in validating the timestamps based on
6598
       the target system */
6599
1.09M
    if (receiver_stream->os_policy == 0) {
6600
0
        StreamTcpSetOSPolicy(receiver_stream, p);
6601
0
    }
6602
6603
1.09M
    if (TCP_HAS_TS(p)) {
6604
1.00M
        uint32_t ts = TCP_GET_TSVAL(p);
6605
6606
1.00M
        if (sender_stream->flags & STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP) {
6607
            /* The 3whs used the timestamp with 0 value. */
6608
3.10k
            switch (receiver_stream->os_policy) {
6609
0
                case OS_POLICY_LINUX:
6610
0
                case OS_POLICY_WINDOWS2K3:
6611
                    /* Linux and windows 2003 does not allow the use of 0 as
6612
                     * timestamp in the 3whs. */
6613
0
                    ssn->flags &= ~STREAMTCP_FLAG_TIMESTAMP;
6614
0
                    check_ts = 0;
6615
0
                    break;
6616
6617
0
                case OS_POLICY_OLD_LINUX:
6618
0
                case OS_POLICY_WINDOWS:
6619
0
                case OS_POLICY_VISTA:
6620
0
                    sender_stream->flags &= ~STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
6621
0
                    if (SEQ_EQ(sender_stream->next_seq, seq)) {
6622
0
                        sender_stream->last_ts = ts;
6623
0
                        check_ts = 0; /*next packet will be checked for validity
6624
                                        and stream TS has been updated with this
6625
                                        one.*/
6626
0
                    }
6627
0
                    break;
6628
3.10k
                default:
6629
3.10k
                    break;
6630
3.10k
            }
6631
3.10k
        }
6632
6633
1.00M
        if (receiver_stream->os_policy == OS_POLICY_HPUX11) {
6634
            /*HPUX11 ignores the timestamp of out of order packets*/
6635
0
            if (!SEQ_EQ(sender_stream->next_seq, seq))
6636
0
                check_ts = 0;
6637
0
        }
6638
6639
1.00M
        if (ts == 0) {
6640
5
            switch (receiver_stream->os_policy) {
6641
0
                case OS_POLICY_OLD_LINUX:
6642
0
                case OS_POLICY_WINDOWS:
6643
0
                case OS_POLICY_WINDOWS2K3:
6644
0
                case OS_POLICY_VISTA:
6645
0
                case OS_POLICY_SOLARIS:
6646
                    /* Old Linux and windows allowed packet with 0 timestamp. */
6647
0
                    break;
6648
5
                default:
6649
                    /* other OS simply drop the packet with 0 timestamp, when
6650
                     * 3whs has valid timestamp*/
6651
5
                    goto invalid;
6652
5
            }
6653
5
        }
6654
6655
1.00M
        if (check_ts) {
6656
1.00M
            int32_t result = 0;
6657
6658
1.00M
            SCLogDebug("ts %"PRIu32", last_ts %"PRIu32"", ts, sender_stream->last_ts);
6659
6660
1.00M
            if (receiver_stream->os_policy == OS_POLICY_LINUX || stream_config.liberal_timestamps) {
6661
                /* Linux accepts TS which are off by one.*/
6662
1.00M
                result = (int32_t) ((ts - sender_stream->last_ts) + 1);
6663
1.00M
            } else {
6664
0
                result = (int32_t) (ts - sender_stream->last_ts);
6665
0
            }
6666
6667
1.00M
            SCLogDebug("result %" PRIi32 ", p->ts(sec) %" PRIuMAX "", result,
6668
1.00M
                    (uintmax_t)SCTIME_SECS(p->ts));
6669
6670
1.00M
            if (sender_stream->last_pkt_ts == 0 &&
6671
46.3k
                    (ssn->flags & STREAMTCP_FLAG_MIDSTREAM))
6672
43.8k
            {
6673
43.8k
                sender_stream->last_pkt_ts = (uint32_t)SCTIME_SECS(p->ts);
6674
43.8k
            }
6675
6676
1.00M
            if (result < 0) {
6677
207
                SCLogDebug("timestamp is not valid sender_stream->last_ts "
6678
207
                           "%" PRIu32 " p->tcpvars->ts %" PRIu32 " result "
6679
207
                           "%" PRId32 "", sender_stream->last_ts, ts, result);
6680
                /* candidate for rejection */
6681
207
                ret = 0;
6682
1.00M
            } else if ((sender_stream->last_ts != 0) &&
6683
1.00M
                       (((uint32_t)SCTIME_SECS(p->ts)) >
6684
1.00M
                               sender_stream->last_pkt_ts + PAWS_24DAYS)) {
6685
4.84k
                SCLogDebug("packet is not valid sender_stream->last_pkt_ts "
6686
4.84k
                           "%" PRIu32 " p->ts(sec) %" PRIu32 "",
6687
4.84k
                        sender_stream->last_pkt_ts, (uint32_t)SCTIME_SECS(p->ts));
6688
                /* candidate for rejection */
6689
4.84k
                ret = 0;
6690
4.84k
            }
6691
6692
1.00M
            if (ret == 1) {
6693
                /* Update the timestamp and last seen packet time for this
6694
                 * stream */
6695
1.00M
                if (SEQ_EQ(sender_stream->next_seq, seq))
6696
460k
                    sender_stream->last_ts = ts;
6697
6698
1.00M
                sender_stream->last_pkt_ts = (uint32_t)SCTIME_SECS(p->ts);
6699
6700
1.00M
            } else if (ret == 0) {
6701
                /* if the timestamp of packet is not valid then, check if the
6702
                 * current stream timestamp is not so old. if so then we need to
6703
                 * accept the packet and update the stream->last_ts (RFC 1323)*/
6704
5.05k
                if ((SEQ_EQ(sender_stream->next_seq, seq)) &&
6705
667
                        (((uint32_t)SCTIME_SECS(p->ts) >
6706
667
                                (sender_stream->last_pkt_ts + PAWS_24DAYS)))) {
6707
655
                    sender_stream->last_ts = ts;
6708
655
                    sender_stream->last_pkt_ts = (uint32_t)SCTIME_SECS(p->ts);
6709
6710
655
                    SCLogDebug("timestamp considered valid anyway");
6711
4.39k
                } else {
6712
4.39k
                    goto invalid;
6713
4.39k
                }
6714
5.05k
            }
6715
1.00M
        }
6716
1.00M
    } else {
6717
        /* Solaris stops using timestamps if a packet is received
6718
           without a timestamp and timestamps were used on that stream. */
6719
92.1k
        if (receiver_stream->os_policy == OS_POLICY_SOLARIS)
6720
0
            ssn->flags &= ~STREAMTCP_FLAG_TIMESTAMP;
6721
92.1k
    }
6722
6723
1.09M
    SCReturnInt(1);
6724
6725
4.40k
invalid:
6726
4.40k
    StreamTcpSetEvent(p, STREAM_PKT_INVALID_TIMESTAMP);
6727
4.40k
    SCReturnInt(0);
6728
1.09M
}
6729
6730
/**
6731
 *  \brief  Function to test the received ACK values against the stream window
6732
 *          and previous ack value. ACK values should be higher than previous
6733
 *          ACK value and less than the next_win value.
6734
 *
6735
 *  \param  ssn     TcpSession for state access
6736
 *  \param  stream  TcpStream of which last_ack needs to be tested
6737
 *  \param  p       Packet which is used to test the last_ack
6738
 *
6739
 *  \retval 0  ACK is valid, last_ack is updated if ACK was higher
6740
 *  \retval -1 ACK is invalid
6741
 */
6742
static inline int StreamTcpValidateAck(TcpSession *ssn, TcpStream *stream, Packet *p)
6743
7.37M
{
6744
7.37M
    SCEnter();
6745
6746
7.37M
    const TCPHdr *tcph = PacketGetTCP(p);
6747
7.37M
    const uint32_t ack = TCP_GET_RAW_ACK(tcph);
6748
6749
7.37M
    if (!(tcph->th_flags & TH_ACK))
6750
136k
        SCReturnInt(0);
6751
6752
    /* fast track */
6753
7.23M
    if (SEQ_GT(ack, stream->last_ack) && SEQ_LEQ(ack, stream->next_win))
6754
3.13M
    {
6755
3.13M
        SCLogDebug("ssn %p: ACK %u in bounds > %u <= %u", ssn, ack, stream->last_ack,
6756
3.13M
                stream->next_win);
6757
3.13M
        SCReturnInt(0);
6758
3.13M
    }
6759
    /* fast track */
6760
4.09M
    else if (SEQ_EQ(ack, stream->last_ack)) {
6761
3.30M
        SCLogDebug("ssn %p: pkt ACK %" PRIu32 " == stream last ACK %" PRIu32, ssn, ack,
6762
3.30M
                stream->last_ack);
6763
3.30M
        SCReturnInt(0);
6764
3.30M
    }
6765
6766
    /* exception handling */
6767
790k
    if (SEQ_LT(ack, stream->last_ack)) {
6768
681k
        SCLogDebug("pkt ACK %" PRIu32 " < stream last ACK %" PRIu32, ack, stream->last_ack);
6769
6770
        /* This is an attempt to get a 'left edge' value that we can check against.
6771
         * It doesn't work when the window is 0, need to think of a better way. */
6772
6773
681k
        if (stream->window != 0 && SEQ_LT(ack, (stream->last_ack - stream->window))) {
6774
62.7k
            SCLogDebug("ACK %"PRIu32" is before last_ack %"PRIu32" - window "
6775
62.7k
                    "%"PRIu32" = %"PRIu32, ack, stream->last_ack,
6776
62.7k
                    stream->window, stream->last_ack - stream->window);
6777
62.7k
            goto invalid;
6778
62.7k
        }
6779
6780
681k
        SCReturnInt(0);
6781
681k
    }
6782
6783
    /* no further checks possible for ASYNC */
6784
108k
    if ((ssn->flags & STREAMTCP_FLAG_ASYNC) != 0) {
6785
0
        SCReturnInt(0);
6786
0
    }
6787
6788
108k
    if (ssn->state > TCP_SYN_SENT && SEQ_GT(ack, stream->next_win)) {
6789
106k
        SCLogDebug("ACK %"PRIu32" is after next_win %"PRIu32, ack, stream->next_win);
6790
106k
        goto invalid;
6791
        /* a toclient RST as a response to SYN, next_win is 0, ack will be isn+1, just like
6792
         * the syn ack */
6793
106k
    } else if (ssn->state == TCP_SYN_SENT && PKT_IS_TOCLIENT(p) && tcph->th_flags & TH_RST &&
6794
733
               SEQ_EQ(ack, stream->isn + 1)) {
6795
200
        SCReturnInt(0);
6796
200
    }
6797
6798
1.47k
    SCLogDebug("default path leading to invalid: ACK %"PRIu32", last_ack %"PRIu32
6799
1.47k
        " next_win %"PRIu32, ack, stream->last_ack, stream->next_win);
6800
171k
invalid:
6801
171k
    StreamTcpSetEvent(p, STREAM_PKT_INVALID_ACK);
6802
171k
    SCReturnInt(-1);
6803
1.47k
}
6804
6805
/** \brief update reassembly progress
6806
6807
 * \param ssn TCP Session
6808
 * \param direction direction to set the flag in: 0 toserver, 1 toclient
6809
 */
6810
void StreamTcpUpdateAppLayerProgress(TcpSession *ssn, char direction,
6811
        const uint32_t progress)
6812
20.9M
{
6813
20.9M
    if (direction) {
6814
10.5M
        ssn->server.app_progress_rel += progress;
6815
10.5M
        SCLogDebug("progress now %" PRIu64, STREAM_APP_PROGRESS(&ssn->server));
6816
10.5M
    } else {
6817
10.4M
        ssn->client.app_progress_rel += progress;
6818
10.4M
        SCLogDebug("progress now %" PRIu64, STREAM_APP_PROGRESS(&ssn->client));
6819
10.4M
    }
6820
20.9M
}
6821
6822
/** \brief disable reassembly
6823
6824
 *  Disable app layer and set raw inspect to no longer accept new data.
6825
 *  Stream engine will then fully disable raw after last inspection.
6826
 *
6827
 * \param ssn TCP Session to set the flag in
6828
 * \param direction direction to set the flag in: 0 toserver, 1 toclient
6829
 */
6830
void StreamTcpSetSessionNoReassemblyFlag(TcpSession *ssn, char direction)
6831
0
{
6832
0
    ssn->flags |= STREAMTCP_FLAG_APP_LAYER_DISABLED;
6833
0
    StreamTcpSetDisableRawReassemblyFlag(ssn, direction);
6834
0
}
6835
6836
/** \brief  Set the No reassembly flag for the given direction in given TCP
6837
 *          session.
6838
 *
6839
 * \param ssn TCP Session to set the flag in
6840
 * \param direction direction to set the flag in: 0 toserver, 1 toclient
6841
 */
6842
void StreamTcpSetDisableRawReassemblyFlag(TcpSession *ssn, char direction)
6843
7.79k
{
6844
7.79k
    direction ? (ssn->server.flags |= STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED) :
6845
7.79k
                (ssn->client.flags |= STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED);
6846
7.79k
}
6847
6848
/** \brief enable bypass
6849
 *
6850
 * \param ssn TCP Session to set the flag in
6851
 * \param direction direction to set the flag in: 0 toserver, 1 toclient
6852
 */
6853
void StreamTcpSetSessionBypassFlag(TcpSession *ssn)
6854
0
{
6855
0
    ssn->flags |= STREAMTCP_FLAG_BYPASS;
6856
0
}
6857
6858
/** \brief Create a pseudo packet injected into the engine to signal the
6859
 *         opposing direction of this stream trigger detection/logging.
6860
 *
6861
 *  \param parent real packet
6862
 *  \param pq packet queue to store the new pseudo packet in
6863
 *  \param dir 0 ts 1 tc
6864
 */
6865
static void StreamTcpPseudoPacketCreateDetectLogFlush(ThreadVars *tv,
6866
        StreamTcpThread *stt, Packet *parent,
6867
        TcpSession *ssn, PacketQueueNoLock *pq, int dir)
6868
58.5k
{
6869
58.5k
    SCEnter();
6870
58.5k
    Flow *f = parent->flow;
6871
58.5k
    TCPHdr *tcph = NULL;
6872
6873
58.5k
    if (parent->flags & PKT_PSEUDO_DETECTLOG_FLUSH) {
6874
0
        SCReturn;
6875
0
    }
6876
58.5k
    if ((f->flags & (FLOW_IPV4 | FLOW_IPV6)) == 0) {
6877
0
        SCReturn;
6878
0
    }
6879
6880
58.5k
    Packet *np = PacketPoolGetPacket();
6881
58.5k
    if (np == NULL) {
6882
0
        SCReturn;
6883
0
    }
6884
58.5k
    PKT_SET_SRC(np, PKT_SRC_STREAM_TCP_DETECTLOG_FLUSH);
6885
6886
58.5k
    np->tenant_id = f->tenant_id;
6887
58.5k
    np->datalink = DLT_RAW;
6888
58.5k
    np->proto = IPPROTO_TCP;
6889
58.5k
    FlowReference(&np->flow, f);
6890
58.5k
    np->flags |= PKT_STREAM_EST;
6891
58.5k
    np->flags |= PKT_HAS_FLOW;
6892
58.5k
    np->flags |= PKT_IGNORE_CHECKSUM;
6893
58.5k
    np->flags |= PKT_PSEUDO_DETECTLOG_FLUSH;
6894
58.5k
    memcpy(&np->vlan_id[0], &f->vlan_id[0], sizeof(np->vlan_id));
6895
58.5k
    np->vlan_idx = f->vlan_idx;
6896
58.5k
    np->livedev = (struct LiveDevice_ *)f->livedev;
6897
6898
58.5k
    if (parent->flags & PKT_NOPACKET_INSPECTION) {
6899
0
        DecodeSetNoPacketInspectionFlag(np);
6900
0
    }
6901
58.5k
    if (parent->flags & PKT_NOPAYLOAD_INSPECTION) {
6902
0
        DecodeSetNoPayloadInspectionFlag(np);
6903
0
    }
6904
6905
58.5k
    if (dir == 0) {
6906
29.2k
        SCLogDebug("pseudo is to_server");
6907
29.2k
        np->flowflags |= FLOW_PKT_TOSERVER;
6908
29.2k
    } else {
6909
29.2k
        SCLogDebug("pseudo is to_client");
6910
29.2k
        np->flowflags |= FLOW_PKT_TOCLIENT;
6911
29.2k
    }
6912
58.5k
    np->flowflags |= FLOW_PKT_ESTABLISHED;
6913
58.5k
    np->payload = NULL;
6914
58.5k
    np->payload_len = 0;
6915
6916
58.5k
    if (FLOW_IS_IPV4(f)) {
6917
57.5k
        if (dir == 0) {
6918
28.7k
            FLOW_COPY_IPV4_ADDR_TO_PACKET(&f->src, &np->src);
6919
28.7k
            FLOW_COPY_IPV4_ADDR_TO_PACKET(&f->dst, &np->dst);
6920
28.7k
            np->sp = f->sp;
6921
28.7k
            np->dp = f->dp;
6922
28.7k
        } else {
6923
28.7k
            FLOW_COPY_IPV4_ADDR_TO_PACKET(&f->src, &np->dst);
6924
28.7k
            FLOW_COPY_IPV4_ADDR_TO_PACKET(&f->dst, &np->src);
6925
28.7k
            np->sp = f->dp;
6926
28.7k
            np->dp = f->sp;
6927
28.7k
        }
6928
6929
        /* Check if we have enough room in direct data. We need ipv4 hdr + tcp hdr.
6930
         * Force an allocation if it is not the case.
6931
         */
6932
57.5k
        if (GET_PKT_DIRECT_MAX_SIZE(np) <  40) {
6933
0
            if (PacketCallocExtPkt(np, 40) == -1) {
6934
0
                goto error;
6935
0
            }
6936
0
        }
6937
        /* set the ip header */
6938
57.5k
        IPV4Hdr *ip4h = PacketSetIPV4(np, GET_PKT_DATA(np));
6939
        /* version 4 and length 20 bytes for the tcp header */
6940
57.5k
        ip4h->ip_verhl = 0x45;
6941
57.5k
        ip4h->ip_tos = 0;
6942
57.5k
        ip4h->ip_len = htons(40);
6943
57.5k
        ip4h->ip_id = 0;
6944
57.5k
        ip4h->ip_off = 0;
6945
57.5k
        ip4h->ip_ttl = 64;
6946
57.5k
        ip4h->ip_proto = IPPROTO_TCP;
6947
57.5k
        if (dir == 0) {
6948
28.7k
            ip4h->s_ip_src.s_addr = f->src.addr_data32[0];
6949
28.7k
            ip4h->s_ip_dst.s_addr = f->dst.addr_data32[0];
6950
28.7k
        } else {
6951
28.7k
            ip4h->s_ip_src.s_addr = f->dst.addr_data32[0];
6952
28.7k
            ip4h->s_ip_dst.s_addr = f->src.addr_data32[0];
6953
28.7k
        }
6954
6955
        /* set the tcp header */
6956
57.5k
        tcph = PacketSetTCP(np, GET_PKT_DATA(np) + 20);
6957
6958
57.5k
        SET_PKT_LEN(np, 40); /* ipv4 hdr + tcp hdr */
6959
57.5k
    } else {
6960
        /* implied IPv6 */
6961
6962
944
        if (dir == 0) {
6963
472
            FLOW_COPY_IPV6_ADDR_TO_PACKET(&f->src, &np->src);
6964
472
            FLOW_COPY_IPV6_ADDR_TO_PACKET(&f->dst, &np->dst);
6965
472
            np->sp = f->sp;
6966
472
            np->dp = f->dp;
6967
472
        } else {
6968
472
            FLOW_COPY_IPV6_ADDR_TO_PACKET(&f->src, &np->dst);
6969
472
            FLOW_COPY_IPV6_ADDR_TO_PACKET(&f->dst, &np->src);
6970
472
            np->sp = f->dp;
6971
472
            np->dp = f->sp;
6972
472
        }
6973
6974
        /* Check if we have enough room in direct data. We need ipv6 hdr + tcp hdr.
6975
         * Force an allocation if it is not the case.
6976
         */
6977
944
        if (GET_PKT_DIRECT_MAX_SIZE(np) <  60) {
6978
0
            if (PacketCallocExtPkt(np, 60) == -1) {
6979
0
                goto error;
6980
0
            }
6981
0
        }
6982
        /* set the ip header */
6983
944
        IPV6Hdr *ip6h = PacketSetIPV6(np, GET_PKT_DATA(np));
6984
        /* version 6 */
6985
944
        ip6h->s_ip6_vfc = 0x60;
6986
944
        ip6h->s_ip6_flow = 0;
6987
944
        ip6h->s_ip6_nxt = IPPROTO_TCP;
6988
944
        ip6h->s_ip6_plen = htons(20);
6989
944
        ip6h->s_ip6_hlim = 64;
6990
944
        if (dir == 0) {
6991
472
            ip6h->s_ip6_src[0] = f->src.addr_data32[0];
6992
472
            ip6h->s_ip6_src[1] = f->src.addr_data32[1];
6993
472
            ip6h->s_ip6_src[2] = f->src.addr_data32[2];
6994
472
            ip6h->s_ip6_src[3] = f->src.addr_data32[3];
6995
472
            ip6h->s_ip6_dst[0] = f->dst.addr_data32[0];
6996
472
            ip6h->s_ip6_dst[1] = f->dst.addr_data32[1];
6997
472
            ip6h->s_ip6_dst[2] = f->dst.addr_data32[2];
6998
472
            ip6h->s_ip6_dst[3] = f->dst.addr_data32[3];
6999
472
        } else {
7000
472
            ip6h->s_ip6_src[0] = f->dst.addr_data32[0];
7001
472
            ip6h->s_ip6_src[1] = f->dst.addr_data32[1];
7002
472
            ip6h->s_ip6_src[2] = f->dst.addr_data32[2];
7003
472
            ip6h->s_ip6_src[3] = f->dst.addr_data32[3];
7004
472
            ip6h->s_ip6_dst[0] = f->src.addr_data32[0];
7005
472
            ip6h->s_ip6_dst[1] = f->src.addr_data32[1];
7006
472
            ip6h->s_ip6_dst[2] = f->src.addr_data32[2];
7007
472
            ip6h->s_ip6_dst[3] = f->src.addr_data32[3];
7008
472
        }
7009
7010
        /* set the tcp header */
7011
944
        tcph = PacketSetTCP(np, GET_PKT_DATA(np) + 40);
7012
7013
944
        SET_PKT_LEN(np, 60); /* ipv6 hdr + tcp hdr */
7014
944
    }
7015
7016
58.5k
    tcph->th_offx2 = 0x50;
7017
58.5k
    tcph->th_flags |= TH_ACK;
7018
58.5k
    tcph->th_win = 10;
7019
58.5k
    tcph->th_urp = 0;
7020
7021
    /* to server */
7022
58.5k
    if (dir == 0) {
7023
29.2k
        tcph->th_sport = htons(f->sp);
7024
29.2k
        tcph->th_dport = htons(f->dp);
7025
7026
29.2k
        tcph->th_seq = htonl(ssn->client.next_seq);
7027
29.2k
        tcph->th_ack = htonl(ssn->server.last_ack);
7028
7029
        /* to client */
7030
29.2k
    } else {
7031
29.2k
        tcph->th_sport = htons(f->dp);
7032
29.2k
        tcph->th_dport = htons(f->sp);
7033
7034
29.2k
        tcph->th_seq = htonl(ssn->server.next_seq);
7035
29.2k
        tcph->th_ack = htonl(ssn->client.last_ack);
7036
29.2k
    }
7037
7038
    /* use parent time stamp */
7039
58.5k
    np->ts = parent->ts;
7040
7041
58.5k
    SCLogDebug("np %p", np);
7042
58.5k
    PacketEnqueueNoLock(pq, np);
7043
7044
58.5k
    StatsIncr(tv, stt->counter_tcp_pseudo);
7045
58.5k
    SCReturn;
7046
0
error:
7047
0
    FlowDeReference(&np->flow);
7048
0
    SCReturn;
7049
58.5k
}
7050
7051
/** \brief create packets in both directions to flush out logging
7052
 *         and detection before switching protocols.
7053
 *         In IDS mode, create first in packet dir, 2nd in opposing
7054
 *         In IPS mode, do the reverse.
7055
 *         Flag TCP engine that data needs to be inspected regardless
7056
 *         of how far we are wrt inspect limits.
7057
 */
7058
void StreamTcpDetectLogFlush(ThreadVars *tv, StreamTcpThread *stt, Flow *f, Packet *p,
7059
        PacketQueueNoLock *pq)
7060
{
7061
    TcpSession *ssn = f->protoctx;
7062
    ssn->client.flags |= STREAMTCP_STREAM_FLAG_TRIGGER_RAW;
7063
    ssn->server.flags |= STREAMTCP_STREAM_FLAG_TRIGGER_RAW;
7064
    bool ts = PKT_IS_TOSERVER(p) ? true : false;
7065
    ts ^= StreamTcpInlineMode();
7066
    StreamTcpPseudoPacketCreateDetectLogFlush(tv, stt, p, ssn, pq, ts^1);
7067
    StreamTcpPseudoPacketCreateDetectLogFlush(tv, stt, p, ssn, pq, ts ^ 0);
7068
}
7069
7070
/**
7071
 * \brief Run callback function on each TCP segment in a single direction.
7072
 *
7073
 * \note when stream engine is running in inline mode all segments are used,
7074
 *       in IDS/non-inline mode only ack'd segments are iterated.
7075
 *
7076
 * \note Must be called under flow lock.
7077
 * \var flag determines the direction to run callback on (either to server or to client).
7078
 *
7079
 * \return -1 in case of error, the number of segment in case of success
7080
 *
7081
 */
7082
int StreamTcpSegmentForEach(const Packet *p, uint8_t flag, StreamSegmentCallback CallbackFunc, void *data)
7083
0
{
7084
0
    TcpStream *stream = NULL;
7085
0
    int cnt = 0;
7086
7087
0
    if (p->flow == NULL)
7088
0
        return 0;
7089
7090
0
    TcpSession *ssn = (TcpSession *)p->flow->protoctx;
7091
0
    if (ssn == NULL) {
7092
0
        return 0;
7093
0
    }
7094
7095
0
    if (flag & STREAM_DUMP_TOSERVER) {
7096
0
        stream = &(ssn->server);
7097
0
    } else {
7098
0
        stream = &(ssn->client);
7099
0
    }
7100
7101
    /* for IDS, return ack'd segments. For IPS all. */
7102
0
    TcpSegment *seg;
7103
0
    RB_FOREACH(seg, TCPSEG, &stream->seg_tree) {
7104
0
        if (!(stream_config.flags & STREAMTCP_INIT_FLAG_INLINE)) {
7105
0
            if (PKT_IS_PSEUDOPKT(p)) {
7106
                /* use un-ACK'd data as well */
7107
0
            } else {
7108
                /* in IDS mode, use ACK'd data */
7109
0
                if (SEQ_GEQ(seg->seq, stream->last_ack)) {
7110
0
                    break;
7111
0
                }
7112
0
            }
7113
0
        }
7114
7115
0
        const uint8_t *seg_data;
7116
0
        uint32_t seg_datalen;
7117
0
        StreamingBufferSegmentGetData(&stream->sb, &seg->sbseg, &seg_data, &seg_datalen);
7118
7119
0
        int ret = CallbackFunc(p, seg, data, seg_data, seg_datalen);
7120
0
        if (ret != 1) {
7121
0
            SCLogDebug("Callback function has failed");
7122
0
            return -1;
7123
0
        }
7124
7125
0
        cnt++;
7126
0
    }
7127
0
    return cnt;
7128
0
}
7129
7130
/**
7131
 * \brief Run callback function on each TCP segment in both directions of a session.
7132
 *
7133
 * \note when stream engine is running in inline mode all segments are used,
7134
 *       in IDS/non-inline mode only ack'd segments are iterated.
7135
 *
7136
 * \note Must be called under flow lock.
7137
 *
7138
 * \return -1 in case of error, the number of segment in case of success
7139
 *
7140
 */
7141
int StreamTcpSegmentForSession(
7142
        const Packet *p, uint8_t flag, StreamSegmentCallback CallbackFunc, void *data)
7143
0
{
7144
0
    int ret = 0;
7145
0
    int cnt = 0;
7146
7147
0
    if (p->flow == NULL)
7148
0
        return 0;
7149
7150
0
    TcpSession *ssn = (TcpSession *)p->flow->protoctx;
7151
7152
0
    if (ssn == NULL) {
7153
0
        return -1;
7154
0
    }
7155
7156
0
    TcpStream *server_stream = &(ssn->server);
7157
0
    TcpStream *client_stream = &(ssn->client);
7158
7159
0
    TcpSegment *server_node = RB_MIN(TCPSEG, &server_stream->seg_tree);
7160
0
    TcpSegment *client_node = RB_MIN(TCPSEG, &client_stream->seg_tree);
7161
0
    if (server_node == NULL && client_node == NULL) {
7162
0
        return cnt;
7163
0
    }
7164
7165
0
    while (server_node != NULL || client_node != NULL) {
7166
0
        const uint8_t *seg_data;
7167
0
        uint32_t seg_datalen;
7168
0
        if (server_node == NULL) {
7169
            /*
7170
             * This means the server side RB Tree has been completely searched,
7171
             * thus all that remains is to dump the TcpSegments on the client
7172
             * side.
7173
             */
7174
0
            StreamingBufferSegmentGetData(
7175
0
                    &client_stream->sb, &client_node->sbseg, &seg_data, &seg_datalen);
7176
0
            ret = CallbackFunc(p, client_node, data, seg_data, seg_datalen);
7177
0
            if (ret != 1) {
7178
0
                SCLogDebug("Callback function has failed");
7179
0
                return -1;
7180
0
            }
7181
0
            client_node = TCPSEG_RB_NEXT(client_node);
7182
0
        } else if (client_node == NULL) {
7183
            /*
7184
             * This means the client side RB Tree has been completely searched,
7185
             * thus all that remains is to dump the TcpSegments on the server
7186
             * side.
7187
             */
7188
0
            StreamingBufferSegmentGetData(
7189
0
                    &server_stream->sb, &server_node->sbseg, &seg_data, &seg_datalen);
7190
0
            ret = CallbackFunc(p, server_node, data, seg_data, seg_datalen);
7191
0
            if (ret != 1) {
7192
0
                SCLogDebug("Callback function has failed");
7193
0
                return -1;
7194
0
            }
7195
0
            server_node = TCPSEG_RB_NEXT(server_node);
7196
0
        } else {
7197
0
            if (SCTIME_CMP_LT(
7198
0
                        client_node->pcap_hdr_storage->ts, server_node->pcap_hdr_storage->ts)) {
7199
0
                StreamingBufferSegmentGetData(
7200
0
                        &client_stream->sb, &client_node->sbseg, &seg_data, &seg_datalen);
7201
0
                ret = CallbackFunc(p, client_node, data, seg_data, seg_datalen);
7202
0
                if (ret != 1) {
7203
0
                    SCLogDebug("Callback function has failed");
7204
0
                    return -1;
7205
0
                }
7206
0
                client_node = TCPSEG_RB_NEXT(client_node);
7207
0
            } else {
7208
0
                StreamingBufferSegmentGetData(
7209
0
                        &server_stream->sb, &server_node->sbseg, &seg_data, &seg_datalen);
7210
0
                ret = CallbackFunc(p, server_node, data, seg_data, seg_datalen);
7211
0
                if (ret != 1) {
7212
0
                    SCLogDebug("Callback function has failed");
7213
0
                    return -1;
7214
0
                }
7215
0
                server_node = TCPSEG_RB_NEXT(server_node);
7216
0
            }
7217
0
        }
7218
7219
0
        cnt++;
7220
0
    }
7221
0
    return cnt;
7222
0
}
7223
7224
int StreamTcpBypassEnabled(void)
7225
156k
{
7226
156k
    return (stream_config.flags & STREAMTCP_INIT_FLAG_BYPASS);
7227
156k
}
7228
7229
/**
7230
 *  \brief See if stream engine is operating in inline mode
7231
 *
7232
 *  \retval 0 no
7233
 *  \retval 1 yes
7234
 */
7235
bool StreamTcpInlineMode(void)
7236
29.7M
{
7237
29.7M
    return (stream_config.flags & STREAMTCP_INIT_FLAG_INLINE);
7238
29.7M
}
7239
7240
7241
void TcpSessionSetReassemblyDepth(TcpSession *ssn, uint32_t size)
7242
216k
{
7243
216k
    if (size > ssn->reassembly_depth || size == 0) {
7244
36.0k
        ssn->reassembly_depth = size;
7245
36.0k
    }
7246
216k
}
7247
7248
const char *StreamTcpStateAsString(const enum TcpState state)
7249
134k
{
7250
134k
    const char *tcp_state = NULL;
7251
134k
    switch (state) {
7252
0
        case TCP_NONE:
7253
0
            tcp_state = "none";
7254
0
            break;
7255
5.72k
        case TCP_SYN_SENT:
7256
5.72k
            tcp_state = "syn_sent";
7257
5.72k
            break;
7258
10.4k
        case TCP_SYN_RECV:
7259
10.4k
            tcp_state = "syn_recv";
7260
10.4k
            break;
7261
28.2k
        case TCP_ESTABLISHED:
7262
28.2k
            tcp_state = "established";
7263
28.2k
            break;
7264
9.10k
        case TCP_FIN_WAIT1:
7265
9.10k
            tcp_state = "fin_wait1";
7266
9.10k
            break;
7267
840
        case TCP_FIN_WAIT2:
7268
840
            tcp_state = "fin_wait2";
7269
840
            break;
7270
1.41k
        case TCP_TIME_WAIT:
7271
1.41k
            tcp_state = "time_wait";
7272
1.41k
            break;
7273
1.50k
        case TCP_LAST_ACK:
7274
1.50k
            tcp_state = "last_ack";
7275
1.50k
            break;
7276
26.1k
        case TCP_CLOSE_WAIT:
7277
26.1k
            tcp_state = "close_wait";
7278
26.1k
            break;
7279
1.94k
        case TCP_CLOSING:
7280
1.94k
            tcp_state = "closing";
7281
1.94k
            break;
7282
49.1k
        case TCP_CLOSED:
7283
49.1k
            tcp_state = "closed";
7284
49.1k
            break;
7285
134k
    }
7286
134k
    return tcp_state;
7287
134k
}
7288
7289
const char *StreamTcpSsnStateAsString(const TcpSession *ssn)
7290
0
{
7291
0
    if (ssn == NULL)
7292
0
        return NULL;
7293
0
    return StreamTcpStateAsString(ssn->state);
7294
0
}
7295
7296
#ifdef UNITTESTS
7297
#include "tests/stream-tcp.c"
7298
#endif