net/tcp/tcp_input.c: Correct bad check of urgent data length

Urgent data preceded "normal" data in the TCP payload.  If the urgent data is larger than the size of the TCP payload, this indicates that the entire payload is urgent data and that urgent data continues in the next packet.

This case was handled correctly for the case where urgent data was present but was not being handled correctly in the case where the urgent data was NOT present.
This commit is contained in:
Gregory Nutt 2020-11-29 23:16:12 -08:00 committed by Brennan Ashton
parent e4e4cce696
commit b34096a4fa

View file

@ -794,13 +794,13 @@ found:
return;
}
/* Check the URG flag. If this is set, the segment carries urgent
#ifdef CONFIG_NET_TCPURGDATA
/* Check the URG flag. If this is set, the segment carries urgent
* data that we must pass to the application.
*/
if ((tcp->flags & TCP_URG) != 0)
{
#ifdef CONFIG_NET_TCPURGDATA
dev->d_urglen = (tcp->urgp[0] << 8) | tcp->urgp[1];
if (dev->d_urglen > dev->d_len)
{
@ -809,6 +809,16 @@ found:
dev->d_urglen = dev->d_len;
}
/* The d_len field contains the length of the incoming data.
* d_urgdata points to the "urgent" data at the beginning of
* the payload; d_appdata field points to the any "normal" data
* that may follow the urgent data.
*
* NOTE: If the urgent data continues in the next packet, then
* d_len will be zero and d_appdata will point past the end of
* the payload (which is OK).
*/
net_incr32(conn->rcvseq, dev->d_urglen);
dev->d_len -= dev->d_urglen;
dev->d_urgdata = dev->d_appdata;
@ -816,14 +826,41 @@ found:
}
else
{
/* No urgent data */
dev->d_urglen = 0;
#else /* CONFIG_NET_TCPURGDATA */
dev->d_appdata = ((FAR uint8_t *)dev->d_appdata) +
((tcp->urgp[0] << 8) | tcp->urgp[1]);
dev->d_len -= (tcp->urgp[0] << 8) | tcp->urgp[1];
#endif /* CONFIG_NET_TCPURGDATA */
}
#else /* CONFIG_NET_TCPURGDATA */
/* Check the URG flag. If this is set, We must gracefully ignore
* and discard the urgent data.
*/
if ((tcp->flags & TCP_URG) != 0)
{
uint16_t urglen = (tcp->urgp[0] << 8) | tcp->urgp[1];
if (urglen > dev->d_len)
{
/* There is more urgent data in the next segment to come. */
urglen = dev->d_len;
}
/* The d_len field contains the length of the incoming data;
* The d_appdata field points to the any "normal" data that
* may follow the urgent data.
*
* NOTE: If the urgent data continues in the next packet, then
* d_len will be zero and d_appdata will point past the end of
* the payload (which is OK).
*/
net_incr32(conn->rcvseq, urglen);
dev->d_len -= urglen;
dev->d_appdata += urglen;
}
#endif /* CONFIG_NET_TCPURGDATA */
#ifdef CONFIG_NET_TCP_KEEPALIVE
/* If the established socket receives an ACK or any kind of data
* from the remote peer (whether we accept it or not), then reset