net/tcp: parse tcp options in common function
Signed-off-by: chao an <anchao@xiaomi.com>
This commit is contained in:
parent
d175f50f01
commit
c581cc5f9b
@ -564,6 +564,100 @@ clear:
|
||||
}
|
||||
#endif /* CONFIG_NET_TCP_OUT_OF_ORDER */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_parse_option
|
||||
*
|
||||
* Description:
|
||||
* Parse incoming TCP options
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The device driver structure containing the received TCP packet.
|
||||
* conn - The TCP connection of interest
|
||||
* iplen - Length of the IP header (IPv4_HDRLEN or IPv6_HDRLEN).
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* The network is locked.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void tcp_parse_option(FAR struct net_driver_s *dev,
|
||||
FAR struct tcp_conn_s *conn,
|
||||
unsigned int iplen)
|
||||
{
|
||||
FAR struct tcp_hdr_s *tcp;
|
||||
unsigned int tcpiplen;
|
||||
uint16_t tmp16;
|
||||
uint8_t opt;
|
||||
int i;
|
||||
|
||||
tcp = IPBUF(iplen);
|
||||
|
||||
if ((tcp->tcpoffset & 0xf0) <= 0x50)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tcpiplen = iplen + TCP_HDRLEN;
|
||||
|
||||
for (i = 0; i < ((tcp->tcpoffset >> 4) - 5) << 2 ; )
|
||||
{
|
||||
opt = IPDATA(tcpiplen + i);
|
||||
if (opt == TCP_OPT_END)
|
||||
{
|
||||
/* End of options. */
|
||||
|
||||
break;
|
||||
}
|
||||
else if (opt == TCP_OPT_NOOP)
|
||||
{
|
||||
/* NOP option. */
|
||||
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
else if (opt == TCP_OPT_MSS &&
|
||||
IPDATA(tcpiplen + 1 + i) == TCP_OPT_MSS_LEN)
|
||||
{
|
||||
uint16_t tcp_mss = TCP_MSS(dev, iplen);
|
||||
|
||||
/* An MSS option with the right option length. */
|
||||
|
||||
tmp16 = ((uint16_t)IPDATA(tcpiplen + 2 + i) << 8) |
|
||||
(uint16_t)IPDATA(tcpiplen + 3 + i);
|
||||
conn->mss = tmp16 > tcp_mss ? tcp_mss : tmp16;
|
||||
}
|
||||
#ifdef CONFIG_NET_TCP_WINDOW_SCALE
|
||||
else if (opt == TCP_OPT_WS &&
|
||||
IPDATA(tcpiplen + 1 + i) == TCP_OPT_WS_LEN)
|
||||
{
|
||||
conn->snd_scale = IPDATA(tcpiplen + 2 + i);
|
||||
conn->rcv_scale = CONFIG_NET_TCP_WINDOW_SCALE_FACTOR;
|
||||
conn->flags |= TCP_WSCALE;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
/* All other options have a length field, so that we
|
||||
* easily can skip past them.
|
||||
*/
|
||||
|
||||
if (IPDATA(tcpiplen + 1 + i) == 0)
|
||||
{
|
||||
/* If the length field is zero, the options are
|
||||
* malformed and we don't process them further.
|
||||
*/
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
i += IPDATA(tcpiplen + 1 + i);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_input
|
||||
*
|
||||
@ -593,9 +687,7 @@ static void tcp_input(FAR struct net_driver_s *dev, uint8_t domain,
|
||||
uint16_t tmp16;
|
||||
uint16_t flags;
|
||||
uint16_t result;
|
||||
uint8_t opt;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
#ifdef CONFIG_NET_STATISTICS
|
||||
/* Bump up the count of TCP packets received */
|
||||
@ -748,63 +840,7 @@ static void tcp_input(FAR struct net_driver_s *dev, uint8_t domain,
|
||||
|
||||
/* Parse the TCP MSS option, if present. */
|
||||
|
||||
if ((tcp->tcpoffset & 0xf0) > 0x50)
|
||||
{
|
||||
for (i = 0; i < ((tcp->tcpoffset >> 4) - 5) << 2 ; )
|
||||
{
|
||||
opt = IPDATA(tcpiplen + i);
|
||||
if (opt == TCP_OPT_END)
|
||||
{
|
||||
/* End of options. */
|
||||
|
||||
break;
|
||||
}
|
||||
else if (opt == TCP_OPT_NOOP)
|
||||
{
|
||||
/* NOP option. */
|
||||
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
else if (opt == TCP_OPT_MSS &&
|
||||
IPDATA(tcpiplen + 1 + i) == TCP_OPT_MSS_LEN)
|
||||
{
|
||||
uint16_t tcp_mss = TCP_MSS(dev, iplen);
|
||||
|
||||
/* An MSS option with the right option length. */
|
||||
|
||||
tmp16 = ((uint16_t)IPDATA(tcpiplen + 2 + i) << 8) |
|
||||
(uint16_t)IPDATA(tcpiplen + 3 + i);
|
||||
conn->mss = tmp16 > tcp_mss ? tcp_mss : tmp16;
|
||||
}
|
||||
#ifdef CONFIG_NET_TCP_WINDOW_SCALE
|
||||
else if (opt == TCP_OPT_WS &&
|
||||
IPDATA(tcpiplen + 1 + i) == TCP_OPT_WS_LEN)
|
||||
{
|
||||
conn->snd_scale = IPDATA(tcpiplen + 2 + i);
|
||||
conn->rcv_scale = CONFIG_NET_TCP_WINDOW_SCALE_FACTOR;
|
||||
conn->flags |= TCP_WSCALE;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
/* All other options have a length field, so that we
|
||||
* easily can skip past them.
|
||||
*/
|
||||
|
||||
if (IPDATA(tcpiplen + 1 + i) == 0)
|
||||
{
|
||||
/* If the length field is zero, the options are
|
||||
* malformed and we don't process them further.
|
||||
*/
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
i += IPDATA(tcpiplen + 1 + i);
|
||||
}
|
||||
}
|
||||
tcp_parse_option(dev, conn, iplen);
|
||||
|
||||
/* Our response will be a SYNACK. */
|
||||
|
||||
@ -1245,63 +1281,7 @@ found:
|
||||
{
|
||||
/* Parse the TCP MSS option, if present. */
|
||||
|
||||
if ((tcp->tcpoffset & 0xf0) > 0x50)
|
||||
{
|
||||
for (i = 0; i < ((tcp->tcpoffset >> 4) - 5) << 2 ; )
|
||||
{
|
||||
opt = IPDATA(tcpiplen + i);
|
||||
if (opt == TCP_OPT_END)
|
||||
{
|
||||
/* End of options. */
|
||||
|
||||
break;
|
||||
}
|
||||
else if (opt == TCP_OPT_NOOP)
|
||||
{
|
||||
/* NOP option. */
|
||||
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
else if (opt == TCP_OPT_MSS &&
|
||||
IPDATA(tcpiplen + 1 + i) == TCP_OPT_MSS_LEN)
|
||||
{
|
||||
uint16_t tcp_mss = TCP_MSS(dev, iplen);
|
||||
|
||||
/* An MSS option with the right option length. */
|
||||
|
||||
tmp16 = (IPDATA(tcpiplen + 2 + i) << 8) |
|
||||
IPDATA(tcpiplen + 3 + i);
|
||||
conn->mss = tmp16 > tcp_mss ? tcp_mss : tmp16;
|
||||
}
|
||||
#ifdef CONFIG_NET_TCP_WINDOW_SCALE
|
||||
else if (opt == TCP_OPT_WS &&
|
||||
IPDATA(tcpiplen + 1 + i) == TCP_OPT_WS_LEN)
|
||||
{
|
||||
conn->snd_scale = IPDATA(tcpiplen + 2 + i);
|
||||
conn->rcv_scale = CONFIG_NET_TCP_WINDOW_SCALE_FACTOR;
|
||||
conn->flags |= TCP_WSCALE;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
/* All other options have a length field, so that we
|
||||
* easily can skip past them.
|
||||
*/
|
||||
|
||||
if (IPDATA(tcpiplen + 1 + i) == 0)
|
||||
{
|
||||
/* If the length field is zero, the options are
|
||||
* malformed and we don't process them further.
|
||||
*/
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
i += IPDATA(tcpiplen + 1 + i);
|
||||
}
|
||||
}
|
||||
tcp_parse_option(dev, conn, iplen);
|
||||
|
||||
conn->tcpstateflags = TCP_ESTABLISHED;
|
||||
memcpy(conn->rcvseq, tcp->seqno, 4);
|
||||
|
Loading…
x
Reference in New Issue
Block a user