1
0
mirror of https://github.com/FreeRTOS/FreeRTOS-Plus-TCP synced 2025-10-23 18:38:33 +08:00
Files
FreeRTOS-Plus-TCP/source/FreeRTOS_TCP_Transmission_IPV6.c
Tony Josi 0e9628796c Fixing doxygen comments (#728)
* updating doxygen config

* fixing doxygen comments

* adding IPv6 files and fixing comments

* fix doxygen cfg and file names in comments

* wip doxygen v6 docs

* adding doxygen comments

* include RA src file to doxgendocs generation

* fix spell check issues

* Uncrustify: triggered by comment.

* fix minor build issue

* fix spell check issues

* Uncrustify: triggered by comment

* fix trailing white space

* Dev integration hein.v8 (#738)

* Updating tcp utilities

* Some more change in dev_integration_hein.v8

* In FreeRTOS_DNS_Parser.c : use 'ipUDP_PAYLOAD_OFFSET_IPv4' in stead of 'ipIP_PAYLOAD_OFFSET'

* And a few more corrections

* Changes to WinPCap network interface, removed debugging code

* After applying uncrustify

* Oops, I forgot the push changes in include files.

* Now removing it, hopefully

---------

Co-authored-by: Nikhil Kamath <110539926+amazonKamath@users.noreply.github.com>
Co-authored-by: Monika Singh <108652024+moninom1@users.noreply.github.com>

* Fix CBMC proofs for DNS (#718)

* Use CBMC XML output to enable VSCode debugger (#673)

Prior to this commit, CBMC would emit logging information in plain text
format, which does not contain information required for the CBMC VSCode
debugger. This commit makes CBMC use XML instead of plain text.

Co-authored-by: Mark Tuttle <tuttle@acm.org>

* wip

* wip DNSgetHostByName

* wip DNSgetHostByName

* fixed cbmc proof for DNS_ReadNameField

* wip DNSgetHostByName_a_harness

* Fix CBMC prooff for DNSgetHostByName

* wip fix DNSgetHostByName_a CBMC proof

* fixed cbmc target func not called issue in DNSclear

* fixed cbmc target func not called issue in DNSlookup

* fix DNSgetHostByName_a CBMC proof

* update comments

* more asserts

* fixing formatting

* updating as per review comments

* fix dns after review comments

* adding more asserts

* adds more asserts

* minor fix

* fixing comments

* fixing comments

* fixing minor issue

* fixing DNS_ReadReply() signature

* making code more consistant

* adding more  asserts

* making code more consistent

---------

Co-authored-by: Kareem Khazem <karkhaz@amazon.com>
Co-authored-by: Mark Tuttle <tuttle@acm.org>

* Uncrustify: triggered by comment

* fixing formatting

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Hein Tibosch <hein_tibosch@yahoo.es>
Co-authored-by: Nikhil Kamath <110539926+amazonKamath@users.noreply.github.com>
Co-authored-by: Monika Singh <108652024+moninom1@users.noreply.github.com>
Co-authored-by: Kareem Khazem <karkhaz@amazon.com>
Co-authored-by: Mark Tuttle <tuttle@acm.org>
2023-02-24 13:58:53 +05:30

545 lines
25 KiB
C

/*
* FreeRTOS+TCP <DEVELOPMENT BRANCH>
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/**
* @file FreeRTOS_TCP_Transmission_IPV6.c
* @brief Module which prepares the packet to be sent through
* a socket for FreeRTOS+TCP.
* It depends on FreeRTOS_TCP_WIN.c, which handles the TCP windowing
* schemes.
*
* Endianness: in this module all ports and IP addresses are stored in
* host byte-order, except fields in the IP-packets
*/
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "NetworkInterface.h"
#include "NetworkBufferManagement.h"
#include "FreeRTOS_ARP.h"
#include "FreeRTOSIPConfigDefaults.h"
#include "FreeRTOS_ND.h"
#include "FreeRTOS_TCP_IP.h"
#include "FreeRTOS_TCP_Reception.h"
#include "FreeRTOS_TCP_Transmission.h"
#include "FreeRTOS_TCP_State_Handling.h"
#include "FreeRTOS_TCP_Utils.h"
/* *INDENT-OFF* */
#if( ipconfigUSE_IPv6 != 0 )
/* *INDENT-ON* */
/* Just make sure the contents doesn't get compiled if TCP is not enabled. */
#if ipconfigUSE_TCP == 1
/*------------------------------------------------------------------------*/
/**
* @brief Return (or send) a packet to the peer. The data is stored in pxBuffer,
* which may either point to a real network buffer or to a TCP socket field
* called 'xTCP.xPacket'. A temporary xNetworkBuffer will be used to pass
* the data to the NIC.
*
* @param[in] pxSocket: The socket owning the connection.
* @param[in] pxDescriptor: The network buffer descriptor carrying the packet.
* @param[in] ulLen: Length of the packet being sent.
* @param[in] xReleaseAfterSend: pdTRUE if the ownership of the descriptor is
* transferred to the network interface.
*/
void prvTCPReturnPacket_IPV6( FreeRTOS_Socket_t * pxSocket,
NetworkBufferDescriptor_t * pxDescriptor,
uint32_t ulLen,
BaseType_t xReleaseAfterSend )
{
TCPPacket_IPv6_t * pxTCPPacket = NULL;
ProtocolHeaders_t * pxProtocolHeaders = NULL;
IPHeader_IPv6_t * pxIPHeader = NULL;
BaseType_t xDoRelease = xReleaseAfterSend;
EthernetHeader_t * pxEthernetHeader = NULL;
NetworkBufferDescriptor_t * pxNetworkBuffer = pxDescriptor;
NetworkBufferDescriptor_t xTempBuffer;
/* memcpy() helper variables for MISRA Rule 21.15 compliance*/
MACAddress_t xMACAddress;
const void * pvCopySource = NULL;
void * pvCopyDest = NULL;
const size_t uxIPHeaderSize = ipSIZE_OF_IPv6_HEADER;
IPv6_Address_t xDestinationIPAddress;
do
{
/* Use do/while to be able to break out of the flow */
if( ( pxNetworkBuffer == NULL ) && ( pxSocket == NULL ) )
{
/* Either 'pxNetworkBuffer' or 'pxSocket' should be defined. */
break;
}
/* For sending, a pseudo network buffer will be used, as explained above. */
if( pxNetworkBuffer == NULL )
{
pxNetworkBuffer = &xTempBuffer;
memset( &xTempBuffer, 0, sizeof( xTempBuffer ) );
#if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
{
pxNetworkBuffer->pxNextBuffer = NULL;
}
#endif
pxNetworkBuffer->pucEthernetBuffer = pxSocket->u.xTCP.xPacket.u.ucLastPacket;
pxNetworkBuffer->xDataLength = sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket );
xDoRelease = pdFALSE;
}
#if ( ipconfigZERO_COPY_TX_DRIVER != 0 )
{
if( xDoRelease == pdFALSE )
{
/* A zero-copy network driver wants to pass the packet buffer
* to DMA, so a new buffer must be created. */
pxNetworkBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, ( size_t ) pxNetworkBuffer->xDataLength );
if( pxNetworkBuffer != NULL )
{
xDoRelease = pdTRUE;
}
else
{
FreeRTOS_debug_printf( ( "prvTCPReturnPacket: duplicate failed\n" ) );
}
}
}
#endif /* ipconfigZERO_COPY_TX_DRIVER */
/* MISRA Ref 11.3.1 [Misaligned access] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
/* coverity[misra_c_2012_rule_11_3_violation] */
pxIPHeader = ( ( IPHeader_IPv6_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER ] ) );
#ifndef __COVERITY__
if( pxNetworkBuffer != NULL ) /* LCOV_EXCL_BR_LINE the 2nd branch will never be reached */
#endif
{
/* Map the Ethernet buffer onto a TCPPacket_t struct for easy access to the fields. */
/* MISRA Ref 11.3.1 [Misaligned access] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
/* coverity[misra_c_2012_rule_11_3_violation] */
pxTCPPacket = ( TCPPacket_IPv6_t * ) pxNetworkBuffer->pucEthernetBuffer;
pxEthernetHeader = ( EthernetHeader_t * ) &( pxTCPPacket->xEthernetHeader );
/* MISRA Ref 11.3.1 [Misaligned access] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
/* coverity[misra_c_2012_rule_11_3_violation] */
pxProtocolHeaders = ( ProtocolHeaders_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + uxIPHeaderSize ] );
if( pxNetworkBuffer->pxEndPoint == NULL )
{
prvTCPReturn_SetEndPoint( pxSocket, pxNetworkBuffer, uxIPHeaderSize );
if( pxNetworkBuffer->pxEndPoint == NULL )
{
if( xDoRelease != pdFALSE )
{
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
}
pxNetworkBuffer = NULL;
break;
}
}
/* Fill the packet, swapping from- and to-addresses. */
if( pxSocket != NULL )
{
prvTCPReturn_CheckTCPWindow( pxSocket, pxNetworkBuffer, uxIPHeaderSize );
prvTCPReturn_SetSequenceNumber( pxSocket, pxNetworkBuffer, uxIPHeaderSize, ulLen );
( void ) memcpy( pxIPHeader->xDestinationAddress.ucBytes, pxSocket->u.xTCP.xRemoteIP.xIP_IPv6.ucBytes, ipSIZE_OF_IPv6_ADDRESS );
( void ) memcpy( pxIPHeader->xSourceAddress.ucBytes, pxNetworkBuffer->pxEndPoint->ipv6_settings.xIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS );
}
else
{
IPv6_Address_t xTempAddress;
/* Sending data without a socket, probably replying with a RST flag
* Just swap the two sequence numbers. */
vFlip_32( pxProtocolHeaders->xTCPHeader.ulSequenceNumber, pxProtocolHeaders->xTCPHeader.ulAckNr );
( void ) memcpy( xTempAddress.ucBytes, pxIPHeader->xDestinationAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS );
( void ) memcpy( pxIPHeader->xDestinationAddress.ucBytes, pxIPHeader->xSourceAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS );
( void ) memcpy( pxIPHeader->xSourceAddress.ucBytes, xTempAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS );
}
/* In IPv6, the "payload length" does not include the size of the IP-header */
pxIPHeader->usPayloadLength = FreeRTOS_htons( ulLen - sizeof( IPHeader_IPv6_t ) );
#if ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )
{
/* calculate the TCP checksum for an outgoing packet. */
uint32_t ulTotalLength = ulLen + ipSIZE_OF_ETH_HEADER;
( void ) usGenerateProtocolChecksum( ( uint8_t * ) pxNetworkBuffer->pucEthernetBuffer, ulTotalLength, pdTRUE );
}
#endif /* ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 */
vFlip_16( pxProtocolHeaders->xTCPHeader.usSourcePort, pxProtocolHeaders->xTCPHeader.usDestinationPort );
/* Important: tell NIC driver how many bytes must be sent. */
pxNetworkBuffer->xDataLength = ( size_t ) ulLen;
pxNetworkBuffer->xDataLength += ipSIZE_OF_ETH_HEADER;
#if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
{
pxNetworkBuffer->pxNextBuffer = NULL;
}
#endif
memcpy( xDestinationIPAddress.ucBytes, pxIPHeader->xDestinationAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS );
eARPLookupResult_t eResult;
eResult = eNDGetCacheEntry( &xDestinationIPAddress, &xMACAddress, &( pxNetworkBuffer->pxEndPoint ) );
if( eResult == eARPCacheHit )
{
pvCopySource = &xMACAddress;
}
else
{
pvCopySource = &pxEthernetHeader->xSourceAddress;
}
/* Fill in the destination MAC addresses. */
pvCopyDest = &pxEthernetHeader->xDestinationAddress;
( void ) memcpy( pvCopyDest, pvCopySource, sizeof( pxEthernetHeader->xDestinationAddress ) );
/*
* Use helper variables for memcpy() to remain
* compliant with MISRA Rule 21.15. These should be
* optimized away.
*/
/* The source MAC addresses is fixed to 'ipLOCAL_MAC_ADDRESS'. */
pvCopySource = pxNetworkBuffer->pxEndPoint->xMACAddress.ucBytes;
pvCopyDest = &pxEthernetHeader->xSourceAddress;
( void ) memcpy( pvCopyDest, pvCopySource, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
#if ( ipconfigETHERNET_MINIMUM_PACKET_BYTES > 0 )
{
if( pxNetworkBuffer->xDataLength < ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES )
{
BaseType_t xIndex;
for( xIndex = ( BaseType_t ) pxNetworkBuffer->xDataLength; xIndex < ( BaseType_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; xIndex++ )
{
pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0U;
}
pxNetworkBuffer->xDataLength = ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES;
}
}
#endif /* if( ipconfigETHERNET_MINIMUM_PACKET_BYTES > 0 ) */
/* Send! */
iptraceNETWORK_INTERFACE_OUTPUT( pxNetworkBuffer->xDataLength, pxNetworkBuffer->pucEthernetBuffer );
/* _HT_ added some asserts that are useful while testing. */
configASSERT( pxNetworkBuffer != NULL );
configASSERT( pxNetworkBuffer->pxEndPoint != NULL );
configASSERT( pxNetworkBuffer->pxEndPoint->pxNetworkInterface != NULL );
configASSERT( pxNetworkBuffer->pxEndPoint->pxNetworkInterface->pfOutput != NULL );
NetworkInterface_t * pxInterface = pxNetworkBuffer->pxEndPoint->pxNetworkInterface;
( void ) pxInterface->pfOutput( pxInterface, pxNetworkBuffer, xDoRelease );
if( xDoRelease == pdFALSE )
{
/* Swap-back some fields, as pxBuffer probably points to a socket field
* containing the packet header. */
vFlip_16( pxTCPPacket->xTCPHeader.usSourcePort, pxTCPPacket->xTCPHeader.usDestinationPort );
if( pxIPHeader != NULL )
{
( void ) memcpy( pxIPHeader->xSourceAddress.ucBytes, pxIPHeader->xDestinationAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS );
}
}
else
{
/* Nothing to do: the buffer has been passed to DMA and will be released after use */
}
} /* if( pxNetworkBuffer != NULL ) */
} while( ipFALSE_BOOL );
}
/*-----------------------------------------------------------*/
/**
* @brief Let ARP look-up the MAC-address of the peer and initialise the first SYN
* packet.
*
* @param[in] pxSocket: The socket owning the TCP connection. The first packet shall
* be created in this socket.
*
* @return pdTRUE: if the packet was successfully created and the first SYN can be sent.
* Else pdFALSE.
*
* @note Connecting sockets have a special state: eCONNECT_SYN. In this phase,
* the Ethernet address of the target will be found using ARP. In case the
* target IP address is not within the netmask, the hardware address of the
* gateway will be used.
*/
BaseType_t prvTCPPrepareConnect_IPV6( FreeRTOS_Socket_t * pxSocket )
{
TCPPacket_IPv6_t * pxTCPPacket = NULL;
IPHeader_IPv6_t * pxIPHeader = NULL;
eARPLookupResult_t eReturned;
IP_Address_t xRemoteIP;
MACAddress_t xEthAddress;
BaseType_t xReturn = pdTRUE;
uint32_t ulInitialSequenceNumber = 0;
ProtocolHeaders_t * pxProtocolHeaders = NULL;
NetworkEndPoint_t * pxEndPoint = NULL;
#if ( ipconfigHAS_PRINTF != 0 )
{
/* Only necessary for nicer logging. */
( void ) memset( xEthAddress.ucBytes, 0, sizeof( xEthAddress.ucBytes ) );
}
#endif /* ipconfigHAS_PRINTF != 0 */
( void ) memset( xRemoteIP.xIP_IPv6.ucBytes, 0, ipSIZE_OF_IPv6_ADDRESS );
( void ) memcpy( xRemoteIP.xIP_IPv6.ucBytes, pxSocket->u.xTCP.xRemoteIP.xIP_IPv6.ucBytes, ipSIZE_OF_IPv6_ADDRESS );
eReturned = eNDGetCacheEntry( &( xRemoteIP.xIP_IPv6 ), &( xEthAddress ), &( pxEndPoint ) );
FreeRTOS_printf( ( "eNDGetCacheEntry: %d with end-point %p\n", eReturned, pxEndPoint ) );
if( pxEndPoint != NULL )
{
pxSocket->pxEndPoint = pxEndPoint;
}
/* MISRA Ref 11.3.1 [Misaligned access] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
/* coverity[misra_c_2012_rule_11_3_violation] */
pxProtocolHeaders = ( ( ProtocolHeaders_t * )
&( pxSocket->u.xTCP.xPacket.u.ucLastPacket[ ipSIZE_OF_ETH_HEADER + uxIPHeaderSizeSocket( pxSocket ) ] ) );
switch( eReturned )
{
case eARPCacheHit: /* An ARP table lookup found a valid entry. */
break; /* We can now prepare the SYN packet. */
case eARPCacheMiss: /* An ARP table lookup did not find a valid entry. */
case eCantSendPacket: /* There is no IP address, or an ARP is still in progress. */
default:
/* Count the number of times it could not find the ARP address. */
pxSocket->u.xTCP.ucRepCount++;
FreeRTOS_printf( ( "Looking up %pip with%s end-point\n", xRemoteIP.xIP_IPv6.ucBytes, ( pxEndPoint != NULL ) ? "" : "out" ) );
if( pxEndPoint != NULL )
{
size_t uxNeededSize;
NetworkBufferDescriptor_t * pxNetworkBuffer;
uxNeededSize = ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv6_HEADER + sizeof( ICMPHeader_IPv6_t );
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( uxNeededSize, 0U );
if( pxNetworkBuffer != NULL )
{
pxNetworkBuffer->pxEndPoint = pxEndPoint;
vNDSendNeighbourSolicitation( pxNetworkBuffer, &( xRemoteIP.xIP_IPv6 ) );
}
}
xReturn = pdFALSE;
break;
}
if( xReturn != pdFALSE )
{
/* Get a difficult-to-predict initial sequence number for this 4-tuple. */
ulInitialSequenceNumber = ulApplicationGetNextSequenceNumber( *ipLOCAL_IP_ADDRESS_POINTER,
pxSocket->usLocalPort,
pxSocket->u.xTCP.xRemoteIP.ulIP_IPv4,
pxSocket->u.xTCP.usRemotePort );
/* Check for a random number generation error. */
if( ulInitialSequenceNumber == 0U )
{
xReturn = pdFALSE;
}
}
if( xReturn != pdFALSE )
{
/* The MAC-address of the peer (or gateway) has been found,
* now prepare the initial TCP packet and some fields in the socket. Map
* the buffer onto the TCPPacket_IPv6_t struct to easily access it's field. */
/* MISRA Ref 11.3.1 [Misaligned access] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
/* coverity[misra_c_2012_rule_11_3_violation] */
pxTCPPacket = ( ( TCPPacket_IPv6_t * ) pxSocket->u.xTCP.xPacket.u.ucLastPacket );
pxIPHeader = &( pxTCPPacket->xIPHeader );
/* reset the retry counter to zero. */
pxSocket->u.xTCP.ucRepCount = 0U;
/* And remember that the connect/SYN data are prepared. */
pxSocket->u.xTCP.bits.bConnPrepared = pdTRUE_UNSIGNED;
/* Now that the Ethernet address is known, the initial packet can be
* prepared. */
( void ) memset( pxSocket->u.xTCP.xPacket.u.ucLastPacket, 0, sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );
/* Write the Ethernet address in Source, because it will be swapped by
* prvTCPReturnPacket(). */
( void ) memcpy( ( void * ) ( &( pxTCPPacket->xEthernetHeader.xSourceAddress ) ), ( const void * ) ( &xEthAddress ), sizeof( xEthAddress ) );
if( pxSocket->bits.bIsIPv6 != pdFALSE_UNSIGNED )
{
/* 'ipIPv4_FRAME_TYPE' is already in network-byte-order. */
pxTCPPacket->xEthernetHeader.usFrameType = ipIPv6_FRAME_TYPE;
pxIPHeader->ucVersionTrafficClass = ( uint8_t ) 0x60U;
pxIPHeader->ucTrafficClassFlow = ( uint8_t ) 0x00;
pxIPHeader->usFlowLabel = ( uint16_t ) 0x0000U;
pxIPHeader->usPayloadLength = FreeRTOS_htons( sizeof( TCPHeader_t ) );
pxIPHeader->ucNextHeader = ( uint8_t ) ipPROTOCOL_TCP;
pxIPHeader->ucHopLimit = 128;
/* The Source and Destination addresses will be swapped later. */
( void ) memcpy( pxIPHeader->xSourceAddress.ucBytes, pxSocket->u.xTCP.xRemoteIP.xIP_IPv6.ucBytes, sizeof( pxIPHeader->xSourceAddress.ucBytes ) );
( void ) memcpy( pxIPHeader->xDestinationAddress.ucBytes, pxSocket->xLocalAddress.xIP_IPv6.ucBytes, sizeof( pxIPHeader->xDestinationAddress.ucBytes ) );
pxEndPoint = pxSocket->pxEndPoint;
}
}
if( pxEndPoint != NULL )
{
pxSocket->pxEndPoint = pxEndPoint;
pxProtocolHeaders->xTCPHeader.usSourcePort = FreeRTOS_htons( pxSocket->u.xTCP.usRemotePort );
pxProtocolHeaders->xTCPHeader.usDestinationPort = FreeRTOS_htons( pxSocket->usLocalPort );
/* We are actively connecting, so the peer's Initial Sequence Number (ISN)
* isn't known yet. */
pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber = 0U;
/* Start with ISN (Initial Sequence Number). */
pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber = ulInitialSequenceNumber;
/* The TCP header size is 20 bytes, divided by 4 equals 5, which is put in
* the high nibble of the TCP offset field. */
pxProtocolHeaders->xTCPHeader.ucTCPOffset = 0x50U;
/* Only set the SYN flag. */
pxProtocolHeaders->xTCPHeader.ucTCPFlags = tcpTCP_FLAG_SYN;
/* Set the value of usMSS for this socket. */
prvSocketSetMSS( pxSocket );
/* The initial sequence numbers at our side are known. Later
* vTCPWindowInit() will be called to fill in the peer's sequence numbers, but
* first wait for a SYN+ACK reply. */
prvTCPCreateWindow( pxSocket );
}
else
{
FreeRTOS_printf( ( "prvTCPPrepareConnect: No pxEndPoint yet?\n" ) );
xReturn = pdFAIL;
}
return xReturn;
}
/*-----------------------------------------------------------*/
/**
* @brief Common code for sending a TCP protocol control packet (i.e. no options, no
* payload, just flags).
*
* @param[in] pxNetworkBuffer: The network buffer received from the peer.
* @param[in] ucTCPFlags: The flags to determine what kind of packet this is.
*
* @return pdFAIL always indicating that the packet was not consumed.
*/
BaseType_t prvTCPSendSpecialPktHelper_IPV6( NetworkBufferDescriptor_t * pxNetworkBuffer,
uint8_t ucTCPFlags )
{
#if ( ipconfigIGNORE_UNKNOWN_PACKETS == 1 )
/* Configured to ignore unknown packets just suppress a compiler warning. */
( void ) pxNetworkBuffer;
( void ) ucTCPFlags;
#else
{
/* Map the ethernet buffer onto the TCPPacket_t struct for easy access to the fields. */
/* MISRA Ref 11.3.1 [Misaligned access] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
/* coverity[misra_c_2012_rule_11_3_violation] */
TCPPacket_IPv6_t * pxTCPPacket = ( ( TCPPacket_IPv6_t * ) pxNetworkBuffer->pucEthernetBuffer );
const uint32_t ulSendLength =
ipSIZE_OF_IPv6_HEADER + ipSIZE_OF_TCP_HEADER; /* Plus 0 options. */
uint8_t ucFlagsReceived = pxTCPPacket->xTCPHeader.ucTCPFlags;
pxTCPPacket->xTCPHeader.ucTCPFlags = ucTCPFlags;
pxTCPPacket->xTCPHeader.ucTCPOffset = ( ipSIZE_OF_TCP_HEADER ) << 2;
if( ( ucFlagsReceived & tcpTCP_FLAG_SYN ) != 0U )
{
/* A synchronise packet is received. It counts as 1 pseudo byte of data,
* so increase the variable with 1. Before sending a reply, the values of
* 'ulSequenceNumber' and 'ulAckNr' will be swapped. */
uint32_t ulSequenceNumber = FreeRTOS_ntohl( pxTCPPacket->xTCPHeader.ulSequenceNumber );
ulSequenceNumber++;
pxTCPPacket->xTCPHeader.ulSequenceNumber = FreeRTOS_htonl( ulSequenceNumber );
}
prvTCPReturnPacket( NULL, pxNetworkBuffer, ulSendLength, pdFALSE );
}
#endif /* !ipconfigIGNORE_UNKNOWN_PACKETS */
/* The packet was not consumed. */
return pdFAIL;
}
/*-----------------------------------------------------------*/
#endif /* ipconfigUSE_TCP == 1 */
/* *INDENT-OFF* */
#endif /* ( ipconfigUSE_IPv6 != 0 ) */
/* *INDENT-ON* */