tcp: pick up a midstream session even with FIN flag

Ticket: #5437
pull/8536/head
Philippe Antoine 3 years ago committed by Victor Julien
parent 609df1776e
commit 3365ef72c3

@ -935,11 +935,102 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p,
return -1;
} else if (p->tcph->th_flags & TH_FIN) {
StreamTcpSetEvent(p, STREAM_FIN_BUT_NO_SESSION);
SCLogDebug("FIN packet received, no session setup");
return -1;
/* Drop reason will only be used if midstream policy is set to fail closed */
ExceptionPolicyApply(p, stream_config.midstream_policy, PKT_DROP_REASON_STREAM_MIDSTREAM);
/* SYN/ACK */
if (!stream_config.midstream || p->payload_len == 0) {
StreamTcpSetEvent(p, STREAM_FIN_BUT_NO_SESSION);
SCLogDebug("FIN packet received, no session setup");
return -1;
}
if (!(stream_config.midstream_policy == EXCEPTION_POLICY_NOT_SET ||
stream_config.midstream_policy == EXCEPTION_POLICY_PASS_FLOW ||
stream_config.midstream_policy == EXCEPTION_POLICY_PASS_PACKET)) {
StreamTcpSetEvent(p, STREAM_FIN_BUT_NO_SESSION);
SCLogDebug("FIN packet received, no session setup");
return -1;
}
SCLogDebug("midstream picked up");
if (ssn == NULL) {
ssn = StreamTcpNewSession(tv, stt, p, stt->ssn_pool_id);
if (ssn == NULL) {
StatsIncr(tv, stt->counter_tcp_ssn_memcap);
return -1;
}
StatsIncr(tv, stt->counter_tcp_sessions);
StatsIncr(tv, stt->counter_tcp_active_sessions);
StatsIncr(tv, stt->counter_tcp_midstream_pickups);
}
/* set the state */
StreamTcpPacketSetState(p, ssn, TCP_FIN_WAIT1);
SCLogDebug("ssn %p: =~ midstream picked ssn state is now "
"TCP_FIN_WAIT1",
ssn);
ssn->flags = STREAMTCP_FLAG_MIDSTREAM;
ssn->flags |= STREAMTCP_FLAG_MIDSTREAM_ESTABLISHED;
if (stream_config.async_oneside) {
SCLogDebug("ssn %p: =~ ASYNC", ssn);
ssn->flags |= STREAMTCP_FLAG_ASYNC;
}
/** window scaling for midstream pickups, we can't do much other
* than assume that it's set to the max value: 14 */
ssn->client.wscale = TCP_WSCALE_MAX;
ssn->server.wscale = TCP_WSCALE_MAX;
/* set the sequence numbers and window */
ssn->client.isn = TCP_GET_SEQ(p) - 1;
STREAMTCP_SET_RA_BASE_SEQ(&ssn->client, ssn->client.isn);
ssn->client.next_seq = TCP_GET_SEQ(p) + p->payload_len;
ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
ssn->client.last_ack = TCP_GET_SEQ(p);
ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
SCLogDebug("ssn %p: ssn->client.isn %u, ssn->client.next_seq %u", ssn, ssn->client.isn,
ssn->client.next_seq);
ssn->server.isn = TCP_GET_ACK(p) - 1;
STREAMTCP_SET_RA_BASE_SEQ(&ssn->server, ssn->server.isn);
ssn->server.next_seq = ssn->server.isn + 1;
ssn->server.last_ack = TCP_GET_ACK(p);
ssn->server.next_win = ssn->server.last_ack;
SCLogDebug("ssn %p: ssn->client.next_win %" PRIu32 ", "
"ssn->server.next_win %" PRIu32 "",
ssn, ssn->client.next_win, ssn->server.next_win);
SCLogDebug("ssn %p: ssn->client.last_ack %" PRIu32 ", "
"ssn->server.last_ack %" PRIu32 "",
ssn, ssn->client.last_ack, ssn->server.last_ack);
/* Set the timestamp value for both streams, if packet has timestamp
* option enabled.*/
if (TCP_HAS_TS(p)) {
ssn->client.last_ts = TCP_GET_TSVAL(p);
ssn->server.last_ts = TCP_GET_TSECR(p);
SCLogDebug("ssn %p: ssn->server.last_ts %" PRIu32 " "
"ssn->client.last_ts %" PRIu32 "",
ssn, ssn->server.last_ts, ssn->client.last_ts);
ssn->flags |= STREAMTCP_FLAG_TIMESTAMP;
ssn->client.last_pkt_ts = SCTIME_SECS(p->ts);
if (ssn->server.last_ts == 0)
ssn->server.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
if (ssn->client.last_ts == 0)
ssn->client.flags |= STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP;
} else {
ssn->server.last_ts = 0;
ssn->client.last_ts = 0;
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p, pq);
ssn->flags |= STREAMTCP_FLAG_SACKOK;
SCLogDebug("ssn %p: assuming SACK permitted for both sides", ssn);
/* SYN/ACK */
} else if ((p->tcph->th_flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK)) {
/* Drop reason will only be used if midstream policy is set to fail closed */
ExceptionPolicyApply(p, stream_config.midstream_policy, PKT_DROP_REASON_STREAM_MIDSTREAM);

Loading…
Cancel
Save