-
Notifications
You must be signed in to change notification settings - Fork 1.1k
FreeRTOS+TCP: Let xDataLength always mean "total number of bytes" #1513
Conversation
/bot run checks |
When UDP packets are sent or received, the field A simple change in - lReturn = ( int32_t ) pxNetworkBuffer->xDataLength;
+ lReturn = ( int32_t ) pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t ); In - pxNetworkBuffer->xDataLength = xTotalDataLength;
+ pxNetworkBuffer->xDataLength = xTotalDataLength + sizeof( UDPPacket_t ); In - if( pxNetworkBuffer->xDataLength >= sizeof( DNSMessage_t ) )
+ size_t uxPayloadSize = pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t );
+ if( uxPayloadSize >= sizeof( DNSMessage_t ) ) In
All tested again with and without: DNS, LLMNR, NBNS, and UDP messages in both directions. Hein |
pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, xDataLength + 16 ); | ||
/* The field xDataLength was set to the total length of the UDP packet, | ||
i.e. the payload size plus sizeof( UDPPacket_t ). */ | ||
pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, pxNetworkBuffer->xDataLength + 16 ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the +16 represent sizeof(UDPPacket_t)? In any case, can you please use an appropriate symbolic value instead of the "magic number"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The +16
was there already, in two cases.
In the first case it means sizeof( LLMNRAnswer_t )
,
in the second case it means sizeof( NBNSAnswer_t )
.
Now adapted.
{ | ||
pxNetworkBuffer->xDataLength = FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usLength ) - sizeof( UDPHeader_t ); | ||
pxNetworkBuffer->xDataLength = uxPayloadSize_2 + sizeof( UDPPacket_t ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line does not appear to be consistent with the big block comment above. Can you please confirm (i.e. especially since is probably an important block of code for mitigating buffer overflow risk, and it's not obvious to read)?
@@ -704,7 +704,7 @@ EventBits_t xEventBits = ( EventBits_t ) 0; | |||
|
|||
/* The returned value is the data length, which may have been capped to | |||
the receive buffer size. */ | |||
lReturn = ( int32_t ) pxNetworkBuffer->xDataLength; | |||
lReturn = ( int32_t ) pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hasn't the header already been removed before this function was called? Or did that happen without updating the data length? If the latter, that would appear to be a flaw in the interface (i.e. risky behavior).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hasn't the header already been removed before this function was called?
Indeed, the headers were not removed, the packet still contains them when FreeRTOS_recvfrom()
is called.
Currently this function would look at a full packet ( >= 42 bytes ), where the xDataLength
field would reflect the length of the payload.
A little further the function is accessing the buffer as:
&( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] )
Note that ipUDP_PAYLOAD_OFFSET_IPv4
== sizeof( UDPPacket_t )
== 42.
The aim of this PR is to let xDataLength
reflect the length of the buffer, independent from the context.
Maybe some clarification about receiving UDP packets: NetworkInterface receives a UDP packet :
The packet is sent to a queue and waits for the IP-task. IP-task receives the network buffer and processes it in
API call
Zero-copy: the user receives an object of type void FreeRTOS_ReleaseUDPPayloadBuffer( void *pvBuffer ) We don't know in advance if ``xDataLength` is correct. Therefor we take the smaller of the 2 calculated payloads, with a minimum of 0 bytes. |
/bot run checks |
Since we got two approvals and tests are passing, I'm merging this PR as part of the oncall duty. |
Description
A network buffer (
NetworkBufferDescriptor_t
) has a fieldxDataLength
. This is the total length of the buffer. It includes the 14-byte Ethernet header and everything after that.Just recently, @aggarg wanted to add a length check in the function
vARPGenerateRequestPacket()
, something like:This function failed because there are two cases in which
xDataLength
has a different meaning.In order to avoid confusion, I'd like to correct that:
xDataLength
will always contain the total number of bytes.Checklist:
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.