Add TCP_GET_WSCALE macro for easy access to wscale. Update StreamTcp to use it. Default to wscale 14 (max) in case of midstream as there seems to be no reliable way to predict wscale if we missed it.

remotes/origin/master-1.0.x
Victor Julien 16 years ago
parent f92ac1fbdb
commit 301522f316

@ -367,6 +367,134 @@ static int TCPV6CalculateInvalidChecksumtest04(void)
(uint16_t *)(raw_ipv6 + 54), 32));
}
/** \test Get the wscale of 2 */
static int TCPGetWscaleTest01(void)
{
int retval = 0;
static uint8_t raw_tcp[] = {0xda, 0xc1, 0x00, 0x50, 0xb6, 0x21, 0x7f, 0x58,
0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 0x16, 0xd0,
0x8a, 0xaf, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4,
0x04, 0x02, 0x08, 0x0a, 0x00, 0x62, 0x88, 0x28,
0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x02};
Packet p;
IPV4Hdr ip4h;
ThreadVars tv;
DecodeThreadVars dtv;
memset(&tv, 0, sizeof(ThreadVars));
memset(&p, 0, sizeof(Packet));
memset(&dtv, 0, sizeof(DecodeThreadVars));
memset(&ip4h, 0, sizeof(IPV4Hdr));
p.src.family = AF_INET;
p.dst.family = AF_INET;
p.ip4h = &ip4h;
FlowInitConfig(FLOW_QUIET);
DecodeTCP(&tv, &dtv, &p, raw_tcp, sizeof(raw_tcp), NULL);
FlowShutdown();
if (p.tcph == NULL) {
printf("tcp packet decode failed: ");
goto end;
}
uint8_t wscale = TCP_GET_WSCALE(&p);
if (wscale != 2) {
printf("wscale %"PRIu8", expected 2: ", wscale);
goto end;
}
retval = 1;
end:
return retval;
}
/** \test Get the wscale of 15, so see if return 0 properly */
static int TCPGetWscaleTest02(void)
{
int retval = 0;
static uint8_t raw_tcp[] = {0xda, 0xc1, 0x00, 0x50, 0xb6, 0x21, 0x7f, 0x58,
0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 0x16, 0xd0,
0x8a, 0xaf, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4,
0x04, 0x02, 0x08, 0x0a, 0x00, 0x62, 0x88, 0x28,
0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x0f};
Packet p;
IPV4Hdr ip4h;
ThreadVars tv;
DecodeThreadVars dtv;
memset(&tv, 0, sizeof(ThreadVars));
memset(&p, 0, sizeof(Packet));
memset(&dtv, 0, sizeof(DecodeThreadVars));
memset(&ip4h, 0, sizeof(IPV4Hdr));
p.src.family = AF_INET;
p.dst.family = AF_INET;
p.ip4h = &ip4h;
FlowInitConfig(FLOW_QUIET);
DecodeTCP(&tv, &dtv, &p, raw_tcp, sizeof(raw_tcp), NULL);
FlowShutdown();
if (p.tcph == NULL) {
printf("tcp packet decode failed: ");
goto end;
}
uint8_t wscale = TCP_GET_WSCALE(&p);
if (wscale != 0) {
printf("wscale %"PRIu8", expected 0: ", wscale);
goto end;
}
retval = 1;
end:
return retval;
}
/** \test Get the wscale, but it's missing, so see if return 0 properly */
static int TCPGetWscaleTest03(void)
{
int retval = 0;
static uint8_t raw_tcp[] = {0xda, 0xc1, 0x00, 0x50, 0xb6, 0x21, 0x7f, 0x59,
0xdd, 0xa3, 0x6f, 0xf8, 0x80, 0x10, 0x05, 0xb4,
0x7c, 0x70, 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a,
0x00, 0x62, 0x88, 0x9e, 0x00, 0x00, 0x00, 0x00};
Packet p;
IPV4Hdr ip4h;
ThreadVars tv;
DecodeThreadVars dtv;
memset(&tv, 0, sizeof(ThreadVars));
memset(&p, 0, sizeof(Packet));
memset(&dtv, 0, sizeof(DecodeThreadVars));
memset(&ip4h, 0, sizeof(IPV4Hdr));
p.src.family = AF_INET;
p.dst.family = AF_INET;
p.ip4h = &ip4h;
FlowInitConfig(FLOW_QUIET);
DecodeTCP(&tv, &dtv, &p, raw_tcp, sizeof(raw_tcp), NULL);
FlowShutdown();
if (p.tcph == NULL) {
printf("tcp packet decode failed: ");
goto end;
}
uint8_t wscale = TCP_GET_WSCALE(&p);
if (wscale != 0) {
printf("wscale %"PRIu8", expected 0: ", wscale);
goto end;
}
retval = 1;
end:
return retval;
}
void DecodeTCPRegisterTests(void)
{
@ -378,4 +506,7 @@ void DecodeTCPRegisterTests(void)
TCPV6CalculateValidChecksumtest03, 1);
UtRegisterTest("TCPV6CalculateInvalidChecksumtest04",
TCPV6CalculateInvalidChecksumtest04, 0);
UtRegisterTest("TCPGetWscaleTest01", TCPGetWscaleTest01, 1);
UtRegisterTest("TCPGetWscaleTest02", TCPGetWscaleTest02, 1);
UtRegisterTest("TCPGetWscaleTest03", TCPGetWscaleTest03, 1);
}

@ -41,6 +41,9 @@
#define TCP_OPT_TS_LEN 10
#define TCP_OPT_MSS_LEN 4
/** Max valid wscale value. */
#define TCP_WSCALE_MAX 14
#define TCP_OPTS tcpvars.tcp_opts
#define TCP_OPTS_CNT tcpvars.tcp_opt_cnt
@ -66,6 +69,9 @@
#define TCP_GET_TS2(p) ((p)->tcpc.ts2 != 0 ? \
(p)->tcpc.ts2 : (p)->tcpvars.ts ? ((p)->tcpc.ts2 = (uint32_t)ntohl((*(uint32_t *)((p)->tcpvars.ts->data+4)))) : 0)
/** macro for getting the wscale from the packet. */
#define TCP_GET_WSCALE(p) ((p)->tcpvars.ws ? (((*(uint8_t *)(p)->tcpvars.ws->data) <= TCP_WSCALE_MAX) ? (*(uint8_t *)((p)->tcpvars.ws->data)) : 0) : 0)
#define TCP_GET_OFFSET(p) TCP_GET_RAW_OFFSET(p->tcph)
#define TCP_GET_HLEN(p) TCP_GET_OFFSET(p) << 2
#define TCP_GET_SRC_PORT(p) TCP_GET_RAW_SRC_PORT(p->tcph)

@ -44,6 +44,7 @@ enum
#define STREAMTCP_FLAG_MIDSTREAM 0x01 /*Flag for mid stream session*/
#define STREAMTCP_FLAG_MIDSTREAM_ESTABLISHED 0x02 /*Flag for mid stream established session*/
#define STREAMTCP_FLAG_SERVER_WSCALE 0x08 /**< Server supports wscale (even though it can be 0) */
/* Macro's for comparing Sequence numbers
* Page 810 from TCP/IP Illustrated, Volume 2. */

@ -309,17 +309,15 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p, StreamTcpThread *
ssn->client.last_ts = *p->tcpvars.ts->data;
ssn->server.window = TCP_GET_WINDOW(p);
if (p->tcpvars.ws != NULL) {
ssn->flags |= STREAMTCP_FLAG_SERVER_WSCALE;
ssn->server.wscale = TCP_GET_WSCALE(p);
}
#ifdef DEBUG
printf("StreamTcpPacketStateNone (%p): ssn->client.isn %" PRIu32 ", ssn->client.next_seq %" PRIu32 ", ssn->client.last_ack %"PRIu32"\n",
ssn, ssn->client.isn, ssn->client.next_seq, ssn->client.last_ack);
#endif
if (p->tcpvars.ws != NULL) {
#ifdef DEBUG
printf("StreamTcpPacketStateNone (%p): p->tcpvars.ws %p, %02x\n", ssn, p->tcpvars.ws, *p->tcpvars.ws->data);
#endif
ssn->server.wscale = *p->tcpvars.ws->data;
}
break;
}
case TH_SYN|TH_ACK:
@ -352,18 +350,17 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p, StreamTcpThread *
ssn->client.next_seq = ssn->client.isn + 1;
ssn->client.last_ack = TCP_GET_ACK(p);
/** If the client has a wscale option the server had it too,
* so set the wscale for the server to max. Otherwise none
* will have the wscale opt just like it should. */
if (p->tcpvars.ws != NULL) {
ssn->client.wscale = TCP_GET_WSCALE(p);
ssn->server.wscale = TCP_WSCALE_MAX;
}
#ifdef DEBUG
printf("StreamTcpPacketStateNone (%p): ssn->client.isn %"PRIu32", ssn->client.next_seq %"PRIu32", ssn->client.last_ack %"PRIu32"\n",
ssn, ssn->client.isn, ssn->client.next_seq, ssn->client.last_ack);
#endif
if (p->tcpvars.ws != NULL) {
#ifdef DEBUG
printf("StreamTcpPacketStateNone (%p): p->tcpvars.ws %p, %02x\n", ssn, p->tcpvars.ws, *p->tcpvars.ws->data);
#endif
ssn->client.wscale = *p->tcpvars.ws->data;
}
#ifdef DEBUG
printf("StreamTcpPacketStateNone (%p): ssn->server.isn %"PRIu32", ssn->server.next_seq %"PRIu32", ssn->server.last_ack %"PRIu32"\n",
ssn, ssn->server.isn, ssn->server.next_seq, ssn->server.last_ack);
#endif
@ -411,9 +408,10 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p, StreamTcpThread *
ssn, ssn->client.last_ack, ssn->server.last_ack);
#endif
/** \todo window scaling for midstream pickups */
ssn->client.wscale = 0;
ssn->server.wscale = 0;
/** 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;
StreamTcpReassembleHandleSegment(ssn, &ssn->client, p);
break;
@ -502,11 +500,10 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p, StreamTcpThrea
ssn->client.last_ack = TCP_GET_ACK(p);
ssn->server.last_ack = ssn->server.isn + 1;
if (ssn->server.wscale != 0 && p->tcpvars.ws != NULL) {
#ifdef DEBUG
printf("StreamTcpPacketStateSynSent (%p): p->tcpvars.ws %p, %02x\n", ssn, p->tcpvars.ws, *p->tcpvars.ws->data);
#endif
ssn->client.wscale = *p->tcpvars.ws->data;
/** check for the presense of the ws ptr to determine if we
* support wscale at all */
if (ssn->flags & STREAMTCP_FLAG_SERVER_WSCALE && p->tcpvars.ws != NULL) {
ssn->client.wscale = TCP_GET_WSCALE(p);
} else {
ssn->client.wscale = 0;
}
@ -583,9 +580,10 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p, StreamTcpThrea
if (ssn->flags & STREAMTCP_FLAG_MIDSTREAM) {
ssn->client.window = TCP_GET_WINDOW(p);
ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
/** \todo window scaling need to be addressed for midstream pickups */
ssn->server.wscale = 0;
ssn->client.wscale = 0;
/** window scaling for midstream pickups, we can't do much other
* than assume that it's set to the max value: 14 */
ssn->server.wscale = TCP_WSCALE_MAX;
ssn->client.wscale = TCP_WSCALE_MAX;
}
#ifdef DEBUG
printf("StreamTcpPacketStateSynRecv (%p): pkt (%" PRIu32 ") is to server: SEQ %" PRIu32 ", ACK %" PRIu32 "\n",

Loading…
Cancel
Save