}\
}
+#define StreamTcpAsyncLastAckUpdate(ssn, stream) { \
+ if ((ssn)->flags & STREAMTCP_FLAG_ASYNC) { \
+ if (SEQ_GT((stream)->next_seq, (stream)->last_ack)) { \
+ uint32_t ack_diff = (stream)->next_seq - (stream)->last_ack; \
+ (stream)->last_ack += ack_diff; \
+ SCLogDebug("ssn %p: ASYNC last_ack set to %"PRIu32", moved %u forward", \
+ (ssn), (stream)->next_seq, ack_diff); \
+ } \
+ } \
+}
+
+#define StreamTcpUpdateNextSeq(ssn, stream, seq) { \
+ (stream)->next_seq = seq; \
+ SCLogDebug("ssn %p: next_seq %" PRIu32, (ssn), (stream)->next_seq); \
+ StreamTcpAsyncLastAckUpdate((ssn), (stream)); \
+}
+
/**
* \brief macro to update next_win only if the new value is higher
*
ssn->flags |= STREAMTCP_FLAG_MIDSTREAM;
/* Flag used to change the direct in the later stage in the session */
ssn->flags |= STREAMTCP_FLAG_MIDSTREAM_SYNACK;
+ if (stream_config.async_oneside) {
+ SCLogDebug("ssn %p: =~ ASYNC", ssn);
+ ssn->flags |= STREAMTCP_FLAG_ASYNC;
+ }
/* sequence number & window */
ssn->server.isn = TCP_GET_SEQ(p);
if (TCP_HAS_WSCALE(p)) {
ssn->client.wscale = TCP_GET_WSCALE(p);
ssn->server.wscale = TCP_WSCALE_MAX;
+ SCLogDebug("ssn %p: wscale enabled. client %u server %u",
+ ssn, ssn->client.wscale, ssn->server.wscale);
}
SCLogDebug("ssn %p: ssn->client.isn %"PRIu32", ssn->client.next_seq"
StreamTcpPacketSetState(p, ssn, TCP_SYN_SENT);
SCLogDebug("ssn %p: =~ ssn state is now TCP_SYN_SENT", ssn);
+ if (stream_config.async_oneside) {
+ SCLogDebug("ssn %p: =~ ASYNC", ssn);
+ ssn->flags |= STREAMTCP_FLAG_ASYNC;
+ }
+
/* set the sequence numbers and window */
ssn->client.isn = TCP_GET_SEQ(p);
STREAMTCP_SET_RA_BASE_SEQ(&ssn->client, ssn->client.isn);
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 */
}
StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
- ssn->server.next_seq += p->payload_len;
+ StreamTcpUpdateNextSeq(ssn, &ssn->server, (ssn->server.next_seq + p->payload_len));
ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
}
StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p));
-
- ssn->client.next_seq += p->payload_len;
+ StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
" acked data that we haven't seen before",
ssn, TCP_GET_SEQ(p), p->payload_len, ssn->client.last_ack, ssn->client.next_seq);
if (SEQ_EQ(TCP_GET_SEQ(p),ssn->client.next_seq)) {
- ssn->client.next_seq += p->payload_len;
+ StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
}
} else {
SCLogDebug("ssn %p: server => SEQ before last_ack, packet SEQ"
/* expected packet */
} else if (SEQ_EQ(ssn->client.next_seq, TCP_GET_SEQ(p))) {
- ssn->client.next_seq += p->payload_len;
- SCLogDebug("ssn %p: ssn->client.next_seq %" PRIu32 "",
- ssn, ssn->client.next_seq);
+ StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
+
/* not completely as expected, but valid */
} else if (SEQ_LT(TCP_GET_SEQ(p),ssn->client.next_seq) &&
SEQ_GT((TCP_GET_SEQ(p)+p->payload_len), ssn->client.next_seq))
{
- ssn->client.next_seq = TCP_GET_SEQ(p) + p->payload_len;
+ StreamTcpUpdateNextSeq(ssn, &ssn->client, (TCP_GET_SEQ(p) + p->payload_len));
SCLogDebug("ssn %p: ssn->client.next_seq %"PRIu32
" (started before next_seq, ended after)",
ssn, ssn->client.next_seq);
+
/* if next_seq has fallen behind last_ack, we got some catching up to do */
} else if (SEQ_LT(ssn->client.next_seq, ssn->client.last_ack)) {
- ssn->client.next_seq = TCP_GET_SEQ(p) + p->payload_len;
+ StreamTcpUpdateNextSeq(ssn, &ssn->client, (TCP_GET_SEQ(p) + p->payload_len));
SCLogDebug("ssn %p: ssn->client.next_seq %"PRIu32
" (next_seq had fallen behind last_ack)",
ssn, ssn->client.next_seq);
+
} else {
SCLogDebug("ssn %p: no update to ssn->client.next_seq %"PRIu32
" SEQ %u SEQ+ %u last_ack %u",
if (zerowindowprobe) {
SCLogDebug("ssn %p: zero window probe, skipping oow check", ssn);
} else if (SEQ_LEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->client.next_win) ||
- (ssn->flags & STREAMTCP_FLAG_MIDSTREAM) ||
- (ssn->flags & STREAMTCP_FLAG_ASYNC))
+ (ssn->flags & (STREAMTCP_FLAG_MIDSTREAM|STREAMTCP_FLAG_ASYNC)))
{
SCLogDebug("ssn %p: seq %"PRIu32" in window, ssn->client.next_win "
"%" PRIu32 "", ssn, TCP_GET_SEQ(p), ssn->client.next_win);
" acked data that we haven't seen before",
ssn, TCP_GET_SEQ(p), p->payload_len, ssn->server.last_ack, ssn->server.next_seq);
if (SEQ_EQ(TCP_GET_SEQ(p),ssn->server.next_seq)) {
- ssn->server.next_seq += p->payload_len;
+ StreamTcpUpdateNextSeq(ssn, &ssn->server, (ssn->server.next_seq + p->payload_len));
}
} else {
SCLogDebug("ssn %p: PKT SEQ %"PRIu32" payload_len %"PRIu16
/* expected packet */
} else if (SEQ_EQ(ssn->server.next_seq, TCP_GET_SEQ(p))) {
- ssn->server.next_seq += p->payload_len;
- SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "",
- ssn, ssn->server.next_seq);
+ StreamTcpUpdateNextSeq(ssn, &ssn->server, (ssn->server.next_seq + p->payload_len));
+
/* not completely as expected, but valid */
} else if (SEQ_LT(TCP_GET_SEQ(p),ssn->server.next_seq) &&
SEQ_GT((TCP_GET_SEQ(p)+p->payload_len), ssn->server.next_seq))
{
- ssn->server.next_seq = TCP_GET_SEQ(p) + p->payload_len;
+ StreamTcpUpdateNextSeq(ssn, &ssn->server, (TCP_GET_SEQ(p) + p->payload_len));
SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32
" (started before next_seq, ended after)",
ssn, ssn->server.next_seq);
+
/* if next_seq has fallen behind last_ack, we got some catching up to do */
} else if (SEQ_LT(ssn->server.next_seq, ssn->server.last_ack)) {
- ssn->server.next_seq = TCP_GET_SEQ(p) + p->payload_len;
+ StreamTcpUpdateNextSeq(ssn, &ssn->server, (TCP_GET_SEQ(p) + p->payload_len));
SCLogDebug("ssn %p: ssn->server.next_seq %"PRIu32
" (next_seq had fallen behind last_ack)",
ssn, ssn->server.next_seq);
+
} else {
SCLogDebug("ssn %p: no update to ssn->server.next_seq %"PRIu32
" SEQ %u SEQ+ %u last_ack %u",
if (zerowindowprobe) {
SCLogDebug("ssn %p: zero window probe, skipping oow check", ssn);
} else if (SEQ_LEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->server.next_win) ||
- (ssn->flags & STREAMTCP_FLAG_MIDSTREAM) ||
- (ssn->flags & STREAMTCP_FLAG_ASYNC)) {
+ (ssn->flags & (STREAMTCP_FLAG_MIDSTREAM|STREAMTCP_FLAG_ASYNC)))
+ {
SCLogDebug("ssn %p: seq %"PRIu32" in window, ssn->server.next_win "
"%" PRIu32 "", ssn, TCP_GET_SEQ(p), ssn->server.next_win);
ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
}
if (SEQ_LT(TCP_GET_SEQ(p), ssn->server.next_seq) ||
- SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + ssn->server.window)))
+ SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + ssn->server.window)))
{
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != "
- "%" PRIu32 " from stream", ssn, TCP_GET_SEQ(p),
- ssn->server.next_seq);
+ "%" PRIu32 " from stream (last_ack %u win %u = %u)", ssn, TCP_GET_SEQ(p),
+ ssn->server.next_seq, ssn->server.last_ack, ssn->server.window, (ssn->server.last_ack + ssn->server.window));
StreamTcpSetEvent(p, STREAM_FIN_OUT_OF_WINDOW);
return -1;
ssn->server.next_seq = TCP_GET_ACK(p);
if (SEQ_EQ(ssn->client.next_seq, TCP_GET_SEQ(p))) {
- ssn->client.next_seq += p->payload_len;
- SCLogDebug("ssn %p: ssn->client.next_seq %" PRIu32 "",
- ssn, ssn->client.next_seq);
+ StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
ssn->client.next_seq = TCP_GET_ACK(p);
if (SEQ_EQ(ssn->server.next_seq, TCP_GET_SEQ(p))) {
- ssn->server.next_seq += p->payload_len;
- SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "",
- ssn, ssn->server.next_seq);
+ StreamTcpUpdateNextSeq(ssn, &ssn->server, (ssn->server.next_seq + p->payload_len));
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
ssn->server.next_seq = TCP_GET_ACK(p);
if (SEQ_EQ(ssn->client.next_seq, TCP_GET_SEQ(p))) {
- ssn->client.next_seq += p->payload_len;
- SCLogDebug("ssn %p: ssn->client.next_seq %" PRIu32 "",
- ssn, ssn->client.next_seq);
+ StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
ssn->client.next_seq = TCP_GET_ACK(p);
if (SEQ_EQ(ssn->server.next_seq, TCP_GET_SEQ(p))) {
- ssn->server.next_seq += p->payload_len;
- SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "",
- ssn, ssn->server.next_seq);
+ StreamTcpUpdateNextSeq(ssn, &ssn->server, (ssn->server.next_seq + p->payload_len));
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
if (!retransmission) {
if (SEQ_LEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->client.next_win) ||
- (ssn->flags & STREAMTCP_FLAG_MIDSTREAM) ||
- ssn->flags & STREAMTCP_FLAG_ASYNC)
+ (ssn->flags & (STREAMTCP_FLAG_MIDSTREAM|STREAMTCP_FLAG_ASYNC)))
{
SCLogDebug("ssn %p: seq %"PRIu32" in window, ssn->client.next_win "
"%" PRIu32 "", ssn, TCP_GET_SEQ(p), ssn->client.next_win);
ssn->server.next_seq = TCP_GET_ACK(p);
if (SEQ_EQ(ssn->client.next_seq, TCP_GET_SEQ(p))) {
- ssn->client.next_seq += p->payload_len;
- SCLogDebug("ssn %p: ssn->client.next_seq %" PRIu32 "",
- ssn, ssn->client.next_seq);
+ StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
}
StreamTcpSackUpdatePacket(&ssn->server, p);
if (!retransmission) {
if (SEQ_LEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->server.next_win) ||
- (ssn->flags & STREAMTCP_FLAG_MIDSTREAM) ||
- (ssn->flags & STREAMTCP_FLAG_ASYNC))
+ (ssn->flags & (STREAMTCP_FLAG_MIDSTREAM|STREAMTCP_FLAG_ASYNC)))
{
SCLogDebug("ssn %p: seq %"PRIu32" in window, ssn->server.next_win "
"%" PRIu32 "", ssn, TCP_GET_SEQ(p), ssn->server.next_win);
ssn->client.next_seq = TCP_GET_ACK(p);
if (SEQ_EQ(ssn->server.next_seq, TCP_GET_SEQ(p))) {
- ssn->server.next_seq += p->payload_len;
- SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "",
- ssn, ssn->server.next_seq);
+ StreamTcpUpdateNextSeq(ssn, &ssn->server, (ssn->server.next_seq + p->payload_len));
}
StreamTcpSackUpdatePacket(&ssn->client, p);
if (!retransmission) {
if (SEQ_LEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->client.next_win) ||
- (ssn->flags & STREAMTCP_FLAG_MIDSTREAM) ||
- (ssn->flags & STREAMTCP_FLAG_ASYNC))
+ (ssn->flags & (STREAMTCP_FLAG_MIDSTREAM|STREAMTCP_FLAG_ASYNC)))
{
SCLogDebug("ssn %p: seq %"PRIu32" in window, ssn->client.next_win "
"%" PRIu32 "", ssn, TCP_GET_SEQ(p), ssn->client.next_win);
}
if (SEQ_EQ(ssn->client.next_seq, TCP_GET_SEQ(p))) {
- ssn->client.next_seq += p->payload_len;
- SCLogDebug("ssn %p: ssn->client.next_seq %" PRIu32 "",
- ssn, ssn->client.next_seq);
+ StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
}
StreamTcpSackUpdatePacket(&ssn->server, p);
if (!retransmission) {
if (SEQ_LEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->server.next_win) ||
- (ssn->flags & STREAMTCP_FLAG_MIDSTREAM) ||
- (ssn->flags & STREAMTCP_FLAG_ASYNC))
+ (ssn->flags & (STREAMTCP_FLAG_MIDSTREAM|STREAMTCP_FLAG_ASYNC)))
{
SCLogDebug("ssn %p: seq %"PRIu32" in window, ssn->server.next_win "
"%" PRIu32 "", ssn, TCP_GET_SEQ(p), ssn->server.next_win);
}
if (SEQ_EQ(ssn->server.next_seq, TCP_GET_SEQ(p))) {
- ssn->server.next_seq += p->payload_len;
- SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "",
- ssn, ssn->server.next_seq);
+ StreamTcpUpdateNextSeq(ssn, &ssn->server, (ssn->server.next_seq + p->payload_len));
}
StreamTcpSackUpdatePacket(&ssn->client, p);
ssn->server.next_seq = TCP_GET_ACK(p);
if (SEQ_EQ(TCP_GET_SEQ(p),ssn->client.next_seq))
- ssn->client.next_seq += p->payload_len;
+ StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->client, p, pq);
ssn->client.next_seq = TCP_GET_ACK(p);
if (SEQ_EQ(TCP_GET_SEQ(p),ssn->server.next_seq))
- ssn->server.next_seq += p->payload_len;
+ StreamTcpUpdateNextSeq(ssn, &ssn->server, (ssn->server.next_seq + p->payload_len));
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->server, p, pq);
ssn->client.tcp_flags |= p->tcph->th_flags;
else if (PKT_IS_TOCLIENT(p))
ssn->server.tcp_flags |= p->tcph->th_flags;
+
+ /* check if we need to unset the ASYNC flag */
+ if (ssn->flags & STREAMTCP_FLAG_ASYNC &&
+ ssn->client.tcp_flags != 0 &&
+ ssn->server.tcp_flags != 0)
+ {
+ SCLogDebug("ssn %p: removing ASYNC flag as we have packets on both sides", ssn);
+ ssn->flags &= ~STREAMTCP_FLAG_ASYNC;
+ }
}
/* update counters */
return 0;
}
} else { /* implied to client */
- if(SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq)) {
- SCLogDebug("reset is valid! Packet SEQ: %" PRIu32 "",
- TCP_GET_SEQ(p));
+ if (SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq)) {
+ SCLogDebug("reset is valid! Packet SEQ: %" PRIu32 " Stream %u",
+ TCP_GET_SEQ(p), ssn->server.next_seq);
return 1;
} else {
SCLogDebug("reset is not valid! Packet SEQ: %" PRIu32 " and"
- " client SEQ: %" PRIu32 "", TCP_GET_SEQ(p),
- ssn->server.next_seq);
+ " client SEQ: %" PRIu32 "",
+ TCP_GET_SEQ(p), ssn->server.next_seq);
return 0;
}
}