xref: /FreeRTOS-Plus-TCP-v4.0.0/source/include/FreeRTOS_IP_Private.h (revision f5ecc5f201ba569467d090b79b19c5e0baead322)
1 /*
2  * FreeRTOS+TCP <DEVELOPMENT BRANCH>
3  * Copyright (C) 2022 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of
8  * this software and associated documentation files (the "Software"), to deal in
9  * the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11  * the Software, and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * https://www.FreeRTOS.org
25  * https://github.com/FreeRTOS
26  */
27 
28 #ifndef FREERTOS_IP_PRIVATE_H
29 #define FREERTOS_IP_PRIVATE_H
30 
31 /* Application level configuration options. */
32 #include "FreeRTOSIPConfig.h"
33 #include "FreeRTOSIPConfigDefaults.h"
34 #include "FreeRTOS_Sockets.h"
35 #include "IPTraceMacroDefaults.h"
36 #include "FreeRTOS_Stream_Buffer.h"
37 #include "FreeRTOS_Routing.h"
38 
39 #if ( ipconfigUSE_TCP == 1 )
40     #include "FreeRTOS_TCP_WIN.h"
41     #include "FreeRTOS_TCP_IP.h"
42 #endif
43 
44 #include "semphr.h"
45 
46 #include "event_groups.h"
47 
48 /* *INDENT-OFF* */
49 #ifdef __cplusplus
50     extern "C" {
51 #endif
52 /* *INDENT-ON* */
53 
54 #ifdef TEST
55     int ipFOREVER( void );
56 #else
57     #define ipFOREVER()    1
58 #endif
59 
60 /* Forward declaration. */
61 struct xNetworkEndPoint;
62 
63 typedef enum eFrameProcessingResult
64 {
65     eReleaseBuffer = 0,   /* Processing the frame did not find anything to do - just release the buffer. */
66     eProcessBuffer,       /* An Ethernet frame has a valid address - continue process its contents. */
67     eReturnEthernetFrame, /* The Ethernet frame contains an ARP or ICMP packet that can be returned to its source. */
68     eFrameConsumed,       /* Processing the Ethernet packet contents resulted in the payload being sent to the stack. */
69     eWaitingARPResolution /* Frame is awaiting ARP resolution. */
70 } eFrameProcessingResult_t;
71 
72 typedef enum
73 {
74     eNoEvent = -1,
75     eNetworkDownEvent,     /* 0: The network interface has been lost and/or needs [re]connecting. */
76     eNetworkRxEvent,       /* 1: The network interface has queued a received Ethernet frame. */
77     eNetworkTxEvent,       /* 2: Let the IP-task send a network packet. */
78     eARPTimerEvent,        /* 3: The ARP timer expired. */
79     eStackTxEvent,         /* 4: The software stack has queued a packet to transmit. */
80     eDHCPEvent,            /* 5: Process the DHCP state machine. */
81     eTCPTimerEvent,        /* 6: See if any TCP socket needs attention. */
82     eTCPAcceptEvent,       /* 7: Client API FreeRTOS_accept() waiting for client connections. */
83     eTCPNetStat,           /* 8: IP-task is asked to produce a netstat listing. */
84     eSocketBindEvent,      /* 9: Send a message to the IP-task to bind a socket to a port. */
85     eSocketCloseEvent,     /*10: Send a message to the IP-task to close a socket. */
86     eSocketSelectEvent,    /*11: Send a message to the IP-task for select(). */
87     eSocketSignalEvent,    /*12: A socket must be signalled. */
88     eSocketSetDeleteEvent, /*13: A socket set must be deleted. */
89 } eIPEvent_t;
90 
91 /**
92  * Structure to hold the information about the Network parameters.
93  */
94 typedef struct xNetworkAddressingParameters
95 {
96     uint32_t ulDefaultIPAddress; /**< The default IP address */
97     uint32_t ulNetMask;          /**< The netmask */
98     uint32_t ulGatewayAddress;   /**< The gateway address */
99     uint32_t ulDNSServerAddress; /**< The DNS server address */
100     uint32_t ulBroadcastAddress; /**< The Broadcast address */
101 } NetworkAddressingParameters_t;
102 
103 extern BaseType_t xTCPWindowLoggingLevel;
104 extern QueueHandle_t xNetworkEventQueue;
105 typedef struct xSOCKET FreeRTOS_Socket_t;
106 
107 /*-----------------------------------------------------------*/
108 /* Protocol headers.                                         */
109 /*-----------------------------------------------------------*/
110 
111 #include "pack_struct_start.h"
112 struct xETH_HEADER
113 {
114     MACAddress_t xDestinationAddress; /**< Destination address  0 + 6 = 6  */
115     MACAddress_t xSourceAddress;      /**< Source address       6 + 6 = 12 */
116     uint16_t usFrameType;             /**< The EtherType field 12 + 2 = 14 */
117 }
118 #include "pack_struct_end.h"
119 typedef struct xETH_HEADER EthernetHeader_t;
120 
121 #include "pack_struct_start.h"
122 struct xARP_HEADER
123 {
124     uint16_t usHardwareType;              /**< Network Link Protocol type                     0 +  2 =  2 */
125     uint16_t usProtocolType;              /**< The internetwork protocol                      2 +  2 =  4 */
126     uint8_t ucHardwareAddressLength;      /**< Length in octets of a hardware address         4 +  1 =  5 */
127     uint8_t ucProtocolAddressLength;      /**< Length in octets of the internetwork protocol  5 +  1 =  6 */
128     uint16_t usOperation;                 /**< Operation that the sender is performing        6 +  2 =  8 */
129     MACAddress_t xSenderHardwareAddress;  /**< Media address of the sender                    8 +  6 = 14 */
130     uint8_t ucSenderProtocolAddress[ 4 ]; /**< Internetwork address of sender                14 +  4 = 18  */
131     MACAddress_t xTargetHardwareAddress;  /**< Media address of the intended receiver        18 +  6 = 24  */
132     uint32_t ulTargetProtocolAddress;     /**< Internetwork address of the intended receiver 24 +  4 = 28  */
133 }
134 #include "pack_struct_end.h"
135 typedef struct xARP_HEADER ARPHeader_t;
136 
137 #include "pack_struct_start.h"
138 struct xICMP_HEADER
139 {
140     uint8_t ucTypeOfMessage;   /**< The ICMP type                     0 + 1 = 1 */
141     uint8_t ucTypeOfService;   /**< The ICMP subtype                  1 + 1 = 2 */
142     uint16_t usChecksum;       /**< The checksum of whole ICMP packet 2 + 2 = 4 */
143     uint16_t usIdentifier;     /**< Used in some types of ICMP        4 + 2 = 6 */
144     uint16_t usSequenceNumber; /**< Used in some types of ICMP        6 + 2 = 8 */
145 }
146 #include "pack_struct_end.h"
147 typedef struct xICMP_HEADER ICMPHeader_t;
148 
149 #include "pack_struct_start.h"
150 struct xICMPHeader_IPv6
151 {
152     uint8_t ucTypeOfMessage;     /**< The message type.     0 +  1 = 1 */
153     uint8_t ucTypeOfService;     /**< Type of service.      1 +  1 = 2 */
154     uint16_t usChecksum;         /**< Checksum.             2 +  2 = 4 */
155     uint32_t ulReserved;         /**< Reserved.             4 +  4 = 8 */
156     IPv6_Address_t xIPv6Address; /**< The IPv6 address.     8 + 16 = 24 */
157     uint8_t ucOptionType;        /**< The option type.     24 +  1 = 25 */
158     uint8_t ucOptionLength;      /**< The option length.   25 +  1 = 26 */
159     uint8_t ucOptionBytes[ 6 ];  /**< Option bytes.        26 +  6 = 32 */
160 }
161 #include "pack_struct_end.h"
162 typedef struct xICMPHeader_IPv6 ICMPHeader_IPv6_t;
163 
164 #include "pack_struct_start.h"
165 struct xUDP_HEADER
166 {
167     uint16_t usSourcePort;      /**< The source port                      0 + 2 = 2 */
168     uint16_t usDestinationPort; /**< The destination port                 2 + 2 = 4 */
169     uint16_t usLength;          /**< The size of the whole UDP packet     4 + 2 = 6 */
170     uint16_t usChecksum;        /**< The checksum of the whole UDP Packet 6 + 2 = 8 */
171 }
172 #include "pack_struct_end.h"
173 typedef struct xUDP_HEADER UDPHeader_t;
174 
175 #include "pack_struct_start.h"
176 struct xTCP_HEADER
177 {
178     uint16_t usSourcePort;                       /**< The Source port                      +  2 =  2 */
179     uint16_t usDestinationPort;                  /**< The destination port                 +  2 =  4 */
180     uint32_t ulSequenceNumber;                   /**< The Sequence number                  +  4 =  8 */
181     uint32_t ulAckNr;                            /**< The acknowledgement number           +  4 = 12 */
182     uint8_t ucTCPOffset;                         /**< The value of TCP offset              +  1 = 13 */
183     uint8_t ucTCPFlags;                          /**< The TCP-flags field                  +  1 = 14 */
184     uint16_t usWindow;                           /**< The size of the receive window       +  2 = 15 */
185     uint16_t usChecksum;                         /**< The checksum of the header           +  2 = 18 */
186     uint16_t usUrgent;                           /**< Pointer to the last urgent data byte +  2 = 20 */
187     #if ipconfigUSE_TCP == 1
188         uint8_t ucOptdata[ ipSIZE_TCP_OPTIONS ]; /**< The options + 12 = 32 */
189     #endif
190 }
191 #include "pack_struct_end.h"
192 typedef struct xTCP_HEADER TCPHeader_t;
193 
194 #include "pack_struct_start.h"
195 struct xARP_PACKET
196 {
197     EthernetHeader_t xEthernetHeader; /**< The ethernet header of an ARP Packet  0 + 14 = 14 */
198     ARPHeader_t xARPHeader;           /**< The ARP header of an ARP Packet       14 + 28 = 42 */
199 }
200 #include "pack_struct_end.h"
201 typedef struct xARP_PACKET ARPPacket_t;
202 
203 
204 #include "FreeRTOS_IPv4_Private.h"
205 #include "FreeRTOS_IPv6_Private.h"
206 
207 /**
208  * Union for the protocol packet to save space. Any packet cannot have more than one
209  * of the below protocol packets.
210  */
211 typedef union XPROT_PACKET
212 {
213     ARPPacket_t xARPPacket;   /**< Union member: ARP packet struct */
214     TCPPacket_t xTCPPacket;   /**< Union member: TCP packet struct */
215     UDPPacket_t xUDPPacket;   /**< Union member: UDP packet struct */
216     ICMPPacket_t xICMPPacket; /**< Union member: ICMP packet struct */
217 } ProtocolPacket_t;
218 
219 /**
220  * Union for protocol headers to save space (RAM). Any packet cannot have more than one of
221  * the below protocols.
222  */
223 typedef union xPROT_HEADERS
224 {
225     ICMPHeader_t xICMPHeader;          /**< Union member: ICMP header */
226     UDPHeader_t xUDPHeader;            /**< Union member: UDP header */
227     TCPHeader_t xTCPHeader;            /**< Union member: TCP header */
228     ICMPHeader_IPv6_t xICMPHeaderIPv6; /**< Union member: ICMPv6 header */
229 } ProtocolHeaders_t;
230 
231 /**
232  * Structure for the information of the commands issued to the IP task.
233  */
234 typedef struct IP_TASK_COMMANDS
235 {
236     eIPEvent_t eEventType; /**< The event-type enum */
237     void * pvData;         /**< The data in the event */
238 } IPStackEvent_t;
239 
240 /** @brief This struct describes a packet, it is used by the function
241  * usGenerateProtocolChecksum(). */
242 struct xPacketSummary
243 {
244     BaseType_t xIsIPv6;                          /**< pdTRUE for IPv6 packets. */
245     #if ipconfigUSE_IPv6
246         const IPHeader_IPv6_t * pxIPPacket_IPv6; /**< A pointer to the IPv6 header. */
247     #endif
248     #if ( ipconfigHAS_DEBUG_PRINTF != 0 )
249         const char * pcType;               /**< Just for logging purposes: the name of the protocol. */
250     #endif
251     size_t uxIPHeaderLength;               /**< Either 40 or 20, depending on the IP-type */
252     size_t uxProtocolHeaderLength;         /**< Either 8, 20, or more or 20, depending on the protocol-type */
253     uint16_t usChecksum;                   /**< Checksum accumulator. */
254     uint8_t ucProtocol;                    /**< ipPROTOCOL_TCP, ipPROTOCOL_UDP, ipPROTOCOL_ICMP */
255     const IPPacket_t * pxIPPacket;         /**< A pointer to the IPv4 header. */
256     ProtocolHeaders_t * pxProtocolHeaders; /**< Points to first byte after IP-header */
257     uint16_t usPayloadLength;              /**< Property of IP-header (for IPv4: length of IP-header included) */
258     uint16_t usProtocolBytes;              /**< The total length of the protocol data. */
259 };
260 
261 #define ipBROADCAST_IP_ADDRESS               0xffffffffU
262 
263 /* Offset into the Ethernet frame that is used to temporarily store information
264  * on the fragmentation status of the packet being sent.  The value is important,
265  * as it is past the location into which the destination address will get placed. */
266 #define ipFRAGMENTATION_PARAMETERS_OFFSET    ( 6 )
267 #define ipSOCKET_OPTIONS_OFFSET              ( 6 )
268 
269 
270 #if ( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )
271 
272 /* Ethernet frame types. */
273     #define ipARP_FRAME_TYPE                   ( 0x0608U )
274     #define ipIPv4_FRAME_TYPE                  ( 0x0008U )
275 
276 /* ARP related definitions. */
277     #define ipARP_PROTOCOL_TYPE                ( 0x0008U )
278     #define ipARP_HARDWARE_TYPE_ETHERNET       ( 0x0100U )
279     #define ipARP_REQUEST                      ( 0x0100U )
280     #define ipARP_REPLY                        ( 0x0200U )
281 
282 /* The bits in the two byte IP header field that make up the fragment offset value. */
283     #define ipFRAGMENT_OFFSET_BIT_MASK         ( ( uint16_t ) 0xff1fU )
284 
285 /* The bits in the two byte IP header field that make up the flags value. */
286     #define ipFRAGMENT_FLAGS_BIT_MASK          ( ( uint16_t ) 0x00e0U )
287 
288 /* Don't Fragment Flag */
289     #define ipFRAGMENT_FLAGS_DONT_FRAGMENT     ( ( uint16_t ) 0x0040U )
290 
291 /* More Fragments Flag */
292     #define ipFRAGMENT_FLAGS_MORE_FRAGMENTS    ( ( uint16_t ) 0x0020U )
293 
294 #else /* if ( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN ) */
295 
296 /* Ethernet frame types. */
297     #define ipARP_FRAME_TYPE                   ( 0x0806U )
298     #define ipIPv4_FRAME_TYPE                  ( 0x0800U )
299 
300 /* ARP related definitions. */
301     #define ipARP_PROTOCOL_TYPE                ( 0x0800U )
302     #define ipARP_HARDWARE_TYPE_ETHERNET       ( 0x0001U )
303     #define ipARP_REQUEST                      ( 0x0001 )
304     #define ipARP_REPLY                        ( 0x0002 )
305 
306 /* The bits in the two byte IP header field that make up the fragment offset value. */
307     #define ipFRAGMENT_OFFSET_BIT_MASK         ( ( uint16_t ) 0x1fffU )
308 
309 /* The bits in the two byte IP header field that make up the flags value. */
310     #define ipFRAGMENT_FLAGS_BIT_MASK          ( ( uint16_t ) 0xe000U )
311 
312 /* Don't Fragment Flag */
313     #define ipFRAGMENT_FLAGS_DONT_FRAGMENT     ( ( uint16_t ) 0x4000U )
314 
315 /* More Fragments Flag */
316     #define ipFRAGMENT_FLAGS_MORE_FRAGMENTS    ( ( uint16_t ) 0x2000U )
317 
318 #endif /* ipconfigBYTE_ORDER */
319 
320 /* For convenience, a MAC address of all zeros and another of all 0xffs are
321  * defined const for quick reference. */
322 extern const MACAddress_t xBroadcastMACAddress; /* all 0xff's */
323 extern uint16_t usPacketIdentifier;
324 
325 /** @brief The list that contains mappings between sockets and port numbers.
326  *         Accesses to this list must be protected by critical sections of
327  *         some kind.
328  */
329 extern List_t xBoundUDPSocketsList;
330 
331 /**
332  * Define a default UDP packet header (declared in FreeRTOS_UDP_IP.c)
333  */
334 typedef union xUDPPacketHeader
335 {
336     uint8_t ucBytes[ 24 ]; /**< Member: 8-bit array */
337     uint32_t ulWords[ 6 ]; /**< Member: 32-bit array */
338 } UDPPacketHeader_t;
339 extern UDPPacketHeader_t xDefaultPartUDPPacketHeader;
340 
341 
342 /* Structure that stores the netmask, gateway address and DNS server addresses. */
343 extern NetworkAddressingParameters_t xNetworkAddressing;
344 
345 /* Structure that stores the defaults for netmask, gateway address and DNS.
346  * These values will be copied to 'xNetworkAddressing' in case DHCP is not used,
347  * and also in case DHCP does not lead to a confirmed request. */
348 /*lint -e9003*/
349 extern NetworkAddressingParameters_t xDefaultAddressing; /*lint !e9003 could define variable 'xDefaultAddressing' at block scope [MISRA 2012 Rule 8.9, advisory]. */
350 
351 /* True when BufferAllocation_1.c was included, false for BufferAllocation_2.c */
352 extern const BaseType_t xBufferAllocFixedSize;
353 
354 /* As FreeRTOS_Routing is included later, use forward declarations
355  * of the two structs. */
356 struct xNetworkEndPoint;
357 struct xNetworkInterface;
358 
359 /* A list of all network end-points: */
360 extern struct xNetworkEndPoint * pxNetworkEndPoints;
361 
362 /* A list of all network interfaces: */
363 extern struct xNetworkInterface * pxNetworkInterfaces;
364 
365 /* Defined in FreeRTOS_Sockets.c */
366 #if ( ipconfigUSE_TCP == 1 )
367     extern List_t xBoundTCPSocketsList;
368 #endif
369 
370 /* The local IP address is accessed from within xDefaultPartUDPPacketHeader,
371  * rather than duplicated in its own variable. */
372 #define ipLOCAL_IP_ADDRESS_POINTER     ( ( uint32_t * ) &( xDefaultPartUDPPacketHeader.ulWords[ 20U / sizeof( uint32_t ) ] ) )
373 
374 /* The local MAC address is accessed from within xDefaultPartUDPPacketHeader,
375  * rather than duplicated in its own variable. */
376 #define ipLOCAL_MAC_ADDRESS            ( xDefaultPartUDPPacketHeader.ucBytes )
377 
378 /* ICMP packets are sent using the same function as UDP packets.  The port
379  * number is used to distinguish between the two, as 0 is an invalid UDP port. */
380 #define ipPACKET_CONTAINS_ICMP_DATA    ( 0 )
381 
382 /* For now, the lower 8 bits in 'xEventBits' will be reserved for the above
383  * socket events. */
384 #define SOCKET_EVENT_BIT_COUNT         8
385 
386 #define vSetField16( pxBase, xType, xField, usValue )                                                        \
387     do {                                                                                                     \
388         ( ( uint8_t * ) ( pxBase ) )[ offsetof( xType, xField ) + 0 ] = ( uint8_t ) ( ( usValue ) >> 8 );    \
389         ( ( uint8_t * ) ( pxBase ) )[ offsetof( xType, xField ) + 1 ] = ( uint8_t ) ( ( usValue ) & 0xffU ); \
390     } while( ipFALSE_BOOL )
391 
392 #define vSetField32( pxBase, xType, xField, ulValue )                                                                  \
393     {                                                                                                                  \
394         ( ( uint8_t * ) ( pxBase ) )[ offsetof( xType, xField ) + 0 ] = ( uint8_t ) ( ( ulValue ) >> 24 );             \
395         ( ( uint8_t * ) ( pxBase ) )[ offsetof( xType, xField ) + 1 ] = ( uint8_t ) ( ( ( ulValue ) >> 16 ) & 0xffU ); \
396         ( ( uint8_t * ) ( pxBase ) )[ offsetof( xType, xField ) + 2 ] = ( uint8_t ) ( ( ( ulValue ) >> 8 ) & 0xffU );  \
397         ( ( uint8_t * ) ( pxBase ) )[ offsetof( xType, xField ) + 3 ] = ( uint8_t ) ( ( ulValue ) & 0xffU );           \
398     }
399 
400 #define vFlip_16( left, right )  \
401     do {                         \
402         uint16_t tmp = ( left ); \
403         ( left ) = ( right );    \
404         ( right ) = tmp;         \
405     } while( ipFALSE_BOOL )
406 
407 #define vFlip_32( left, right )  \
408     do {                         \
409         uint32_t tmp = ( left ); \
410         ( left ) = ( right );    \
411         ( right ) = tmp;         \
412     } while( ipFALSE_BOOL )
413 
414 /** @brief Macro calculates the number of elements in an array as a size_t. */
415 #ifndef ARRAY_SIZE_X
416     #ifndef _WINDOWS_
417         #define ARRAY_SIZE_X( x )    ( ( BaseType_t ) sizeof( x ) / ( BaseType_t ) sizeof( x[ 0 ] ) )
418     #else
419         #define ARRAY_SIZE_X( x )    ( sizeof( x ) / sizeof( x[ 0 ] ) )
420     #endif
421 #endif
422 
423 /* WARNING: Do NOT use this macro when the array was received as a parameter. */
424 #ifndef ARRAY_SIZE
425     #define ARRAY_SIZE( x )    ( ( BaseType_t ) ( sizeof( x ) / sizeof( ( x )[ 0 ] ) ) )
426 #endif
427 
428 
429 #ifndef ARRAY_USIZE
430     #define ARRAY_USIZE( x )    ( ( UBaseType_t ) ( sizeof( x ) / sizeof( ( x )[ 0 ] ) ) )
431 #endif
432 
433 /*
434  * Create a message that contains a command to initialise the network interface.
435  * This is used during initialisation, and at any time the network interface
436  * goes down thereafter.  The network interface hardware driver is responsible
437  * for sending the message that contains the network interface down command/
438  * event.
439  *
440  * Only use the FreeRTOS_NetworkDownFromISR() version if the function is to be
441  * called from an interrupt service routine.  If FreeRTOS_NetworkDownFromISR()
442  * returns a non-zero value then a context switch should be performed before
443  * the interrupt is exited.
444  */
445 void FreeRTOS_NetworkDown( struct xNetworkInterface * pxNetworkInterface );
446 BaseType_t FreeRTOS_NetworkDownFromISR( struct xNetworkInterface * pxNetworkInterface );
447 
448 /*
449  * Processes incoming ARP packets.
450  */
451 eFrameProcessingResult_t eARPProcessPacket( const NetworkBufferDescriptor_t * pxNetworkBuffer );
452 
453 /*
454  * Inspect an Ethernet frame to see if it contains data that the stack needs to
455  * process.  eProcessBuffer is returned if the frame should be processed by the
456  * stack.  eReleaseBuffer is returned if the frame should be discarded.
457  */
458 eFrameProcessingResult_t eConsiderFrameForProcessing( const uint8_t * const pucEthernetBuffer );
459 
460 /*
461  * Return the checksum generated over xDataLengthBytes from pucNextData.
462  */
463 uint16_t usGenerateChecksum( uint16_t usSum,
464                              const uint8_t * pucNextData,
465                              size_t uxByteCount );
466 
467 /* Socket related private functions. */
468 
469 /*
470  * The caller must ensure that pxNetworkBuffer->xDataLength is the UDP packet
471  * payload size (excluding packet headers) and that the packet in pucEthernetBuffer
472  * is at least the size of UDPPacket_t.
473  */
474 BaseType_t xProcessReceivedUDPPacket( NetworkBufferDescriptor_t * pxNetworkBuffer,
475                                       uint16_t usPort,
476                                       BaseType_t * pxIsWaitingForARPResolution );
477 
478 BaseType_t xProcessReceivedUDPPacket_IPv4( NetworkBufferDescriptor_t * pxNetworkBuffer,
479                                            uint16_t usPort,
480                                            BaseType_t * pxIsWaitingForARPResolution );
481 
482 BaseType_t xProcessReceivedUDPPacket_IPv6( NetworkBufferDescriptor_t * pxNetworkBuffer,
483                                            uint16_t usPort,
484                                            BaseType_t * pxIsWaitingForARPResolution );
485 
486 /*
487  * Initialize the socket list data structures for TCP and UDP.
488  */
489 void vNetworkSocketsInit( void );
490 
491 /*
492  * Returns pdTRUE if the IP task has been created and is initialised.  Otherwise
493  * returns pdFALSE.
494  */
495 BaseType_t xIPIsNetworkTaskReady( void );
496 
497 #if ( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK == 1 )
498     struct xSOCKET;
499     typedef void (* SocketWakeupCallback_t)( struct xSOCKET * pxSocket );
500 #endif
501 
502 #if ( ipconfigUSE_TCP == 1 )
503 
504 /*
505  * Actually a user thing, but because xBoundTCPSocketsList, let it do by the
506  * IP-task
507  */
508     #if ( ipconfigHAS_PRINTF != 0 )
509         void vTCPNetStat( void );
510     #endif
511 
512 /*
513  * At least one socket needs to check for timeouts
514  */
515     TickType_t xTCPTimerCheck( BaseType_t xWillSleep );
516 
517 /**
518  * About the TCP flags 'bPassQueued' and 'bPassAccept':
519  *
520  * When a new TCP connection request is received on a listening socket, the bPassQueued and
521  * bPassAccept members of the newly created socket are updated as follows:
522  *
523  * 1. bPassQueued is set to indicate that the 3-way TCP handshake is in progress.
524  * 2. When the 3-way TCP handshake is complete, bPassQueued is cleared. At the same time,
525  *    bPassAccept is set to indicate that the socket is ready to be picked up by the task
526  *    that called FreeRTOS_accept().
527  * 3. When the socket is picked up by the task that called FreeRTOS_accept, the bPassAccept
528  *    is cleared.
529  */
530 
531 /**
532  * Every TCP socket has a buffer space just big enough to store
533  * the last TCP header received.
534  * As a reference of this field may be passed to DMA, force the
535  * alignment to 8 bytes.
536  */
537     typedef union
538     {
539         struct
540         {
541             uint32_t ullAlignmentWord; /**< Increase the alignment of this union by adding a 32-bit variable. */
542         } a;                           /**< A struct to increase alignment. */
543         struct
544         {
545             /* The next field only serves to give 'ucLastPacket' a correct
546              * alignment of 4 + 2.  See comments in FreeRTOS_IP.h */
547             uint8_t ucFillPacket[ ipconfigPACKET_FILLER_SIZE ];
548             uint8_t ucLastPacket[ TCP_PACKET_SIZE ];
549         } u; /**< The structure to give an alignment of 4 + 2 */
550     } LastTCPPacket_t;
551 
552 /**
553  * Note that the values of all short and long integers in these structs
554  * are being stored in the native-endian way
555  * Translation should take place when accessing any structure which defines
556  * network packets, such as IPHeader_t and TCPHeader_t
557  */
558     typedef struct TCPSOCKET
559     {
560         IP_Address_t xRemoteIP; /**< IP address of remote machine */
561         uint16_t usRemotePort;  /**< Port on remote machine */
562         struct
563         {
564             /* Most compilers do like bit-flags */
565             uint32_t
566                 bMssChange : 1,        /**< This socket has seen a change in MSS */
567                 bPassAccept : 1,       /**< See comment here above. */
568                 bPassQueued : 1,       /**< See comment here above. */
569                 bReuseSocket : 1,      /**< When a listening socket gets a connection, do not create a new instance but keep on using it */
570                 bCloseAfterSend : 1,   /**< As soon as the last byte has been transmitted, finalise the connection
571                                         * Useful in e.g. FTP connections, where the last data bytes are sent along with the FIN flag */
572                 bUserShutdown : 1,     /**< User requesting a graceful shutdown */
573                 bCloseRequested : 1,   /**< Request to finalise the connection */
574                 bLowWater : 1,         /**< high-water level has been reached. Cleared as soon as 'rx-count < lo-water' */
575                 bWinChange : 1,        /**< The value of bLowWater has changed, must send a window update */
576                 bSendKeepAlive : 1,    /**< When this flag is true, a TCP keep-alive message must be send */
577                 bWaitKeepAlive : 1,    /**< When this flag is true, a TCP keep-alive reply is expected */
578                 bConnPrepared : 1,     /**< Connecting socket: Message has been prepared */
579             #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
580                 bConnPassed : 1,       /**< Connecting socket: Socket has been passed in a successful select()  */
581             #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
582             bFinAccepted : 1,          /**< This socket has received (or sent) a FIN and accepted it */
583                 bFinSent : 1,          /**< We've sent out a FIN */
584                 bFinRecv : 1,          /**< We've received a FIN from our peer */
585                 bFinAcked : 1,         /**< Our FIN packet has been acked */
586                 bFinLast : 1,          /**< The last ACK (after FIN and FIN+ACK) has been sent or will be sent by the peer */
587                 bRxStopped : 1,        /**< Application asked to temporarily stop reception */
588                 bMallocError : 1,      /**< There was an error allocating a stream */
589                 bWinScaling : 1;       /**< A TCP-Window Scaling option was offered and accepted in the SYN phase. */
590         } bits;                        /**< The bits structure */
591         uint32_t ulHighestRxAllowed;   /**< The highest sequence number that we can receive at any moment */
592         uint16_t usTimeout;            /**< Time (in ticks) after which this socket needs attention */
593         uint16_t usMSS;                /**< Current Maximum Segment Size */
594         uint16_t usChildCount;         /**< In case of a listening socket: number of connections on this port number */
595         uint16_t usBacklog;            /**< In case of a listening socket: maximum number of concurrent connections on this port number */
596         uint8_t ucRepCount;            /**< Send repeat count, for retransmissions
597                                         * This counter is separate from the xmitCount in the
598                                         * TCP win segments */
599         eIPTCPState_t eTCPState;       /**< TCP state: see eTCP_STATE */
600         struct xSOCKET * pxPeerSocket; /**< for server socket: child, for child socket: parent */
601         #if ( ipconfigTCP_KEEP_ALIVE == 1 )
602             uint8_t ucKeepRepCount;
603             TickType_t xLastAliveTime; /**< The last value of keepalive time.*/
604         #endif /* ipconfigTCP_KEEP_ALIVE */
605         #if ( ipconfigTCP_HANG_PROTECTION == 1 )
606             TickType_t xLastActTime;                  /**< The last time when hang-protection was done.*/
607         #endif /* ipconfigTCP_HANG_PROTECTION */
608         size_t uxLittleSpace;                         /**< The value deemed as low amount of space. */
609         size_t uxEnoughSpace;                         /**< The value deemed as enough space. */
610         size_t uxRxStreamSize;                        /**< The Receive stream size */
611         size_t uxTxStreamSize;                        /**< The transmit stream size */
612         StreamBuffer_t * rxStream;                    /**< The pointer to the receive stream buffer. */
613         StreamBuffer_t * txStream;                    /**< The pointer to the transmit stream buffer. */
614         #if ( ipconfigUSE_TCP_WIN == 1 )
615             NetworkBufferDescriptor_t * pxAckMessage; /**< The pointer to the ACK message */
616         #endif /* ipconfigUSE_TCP_WIN */
617         LastTCPPacket_t xPacket;                      /**< Buffer space to store the last TCP header received. */
618         uint8_t tcpflags;                             /**< TCP flags */
619         #if ( ipconfigUSE_TCP_WIN != 0 )
620             uint8_t ucMyWinScaleFactor;               /**< Scaling factor of this device. */
621             uint8_t ucPeerWinScaleFactor;             /**< Scaling factor of the peer. */
622         #endif
623         #if ( ipconfigUSE_CALLBACKS == 1 )
624             FOnTCPReceive_t pxHandleReceive;  /**<
625                                                * In case of a TCP socket:
626                                                * typedef void (* FOnTCPReceive_t) (Socket_t xSocket, void *pData, size_t xLength );
627                                                */
628             FOnTCPSent_t pxHandleSent;        /**< Function pointer to handle a successful send event.  */
629             FOnConnected_t pxHandleConnected; /**< Actually type: typedef void (* FOnConnected_t) (Socket_t xSocket, BaseType_t ulConnected ); */
630         #endif /* ipconfigUSE_CALLBACKS */
631         uint32_t ulWindowSize;                /**< Current Window size advertised by peer */
632         size_t uxRxWinSize;                   /**< Fixed value: size of the TCP reception window */
633         size_t uxTxWinSize;                   /**< Fixed value: size of the TCP transmit window */
634 
635         TCPWindow_t xTCPWindow;               /**< The TCP window struct*/
636     } IPTCPSocket_t;
637 
638 #endif /* ipconfigUSE_TCP */
639 
640 /**
641  * Structure to hold the information about a UDP socket.
642  */
643 typedef struct UDPSOCKET
644 {
645     List_t xWaitingPacketsList;   /**< Incoming packets */
646     #if ( ipconfigUDP_MAX_RX_PACKETS > 0 )
647         UBaseType_t uxMaxPackets; /**< Protection: limits the number of packets buffered per socket */
648     #endif /* ipconfigUDP_MAX_RX_PACKETS */
649     #if ( ipconfigUSE_CALLBACKS == 1 )
650         FOnUDPReceive_t pxHandleReceive; /**<
651                                           * In case of a UDP socket:
652                                           * typedef void (* FOnUDPReceive_t) (Socket_t xSocket, void *pData, size_t xLength, struct freertos_sockaddr *pxAddr );
653                                           */
654         FOnUDPSent_t pxHandleSent;       /**< Function pointer to handle the events after a successful send. */
655     #endif /* ipconfigUSE_CALLBACKS */
656 } IPUDPSocket_t;
657 
658 /* Formally typedef'd as eSocketEvent_t. */
659 enum eSOCKET_EVENT
660 {
661     eSOCKET_RECEIVE = 0x0001,
662     eSOCKET_SEND = 0x0002,
663     eSOCKET_ACCEPT = 0x0004,
664     eSOCKET_CONNECT = 0x0008,
665     eSOCKET_BOUND = 0x0010,
666     eSOCKET_CLOSED = 0x0020,
667     eSOCKET_INTR = 0x0040,
668     eSOCKET_ALL = 0x007F,
669 };
670 
671 
672 /**
673  * Structure to hold information for a socket.
674  */
675 struct xSOCKET
676 {
677     EventBits_t xEventBits;         /**< The eventbits to keep track of events. */
678     EventGroupHandle_t xEventGroup; /**< The event group for this socket. */
679 
680     /* Most compilers do like bit-flags */
681     struct
682     {
683         uint32_t bIsIPv6 : 1; /**< Non-zero in case the connection is using IPv6. */
684         uint32_t bSomeFlag : 1;
685     }
686     bits;
687 
688     ListItem_t xBoundSocketListItem;       /**< Used to reference the socket from a bound sockets list. */
689     TickType_t xReceiveBlockTime;          /**< if recv[to] is called while no data is available, wait this amount of time. Unit in clock-ticks */
690     TickType_t xSendBlockTime;             /**< if send[to] is called while there is not enough space to send, wait this amount of time. Unit in clock-ticks */
691 
692     IP_Address_t xLocalAddress;            /**< Local IP address */
693     uint16_t usLocalPort;                  /**< Local port on this machine */
694     uint8_t ucSocketOptions;               /**< Socket options */
695     uint8_t ucProtocol;                    /**< choice of FREERTOS_IPPROTO_UDP/TCP */
696     #if ( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )
697         SemaphoreHandle_t pxUserSemaphore; /**< The user semaphore */
698     #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
699     #if ( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK == 1 )
700         SocketWakeupCallback_t pxUserWakeCallback; /**< Pointer to the callback function. */
701     #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK */
702 
703     #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
704         struct xSOCKET_SET * pxSocketSet; /**< Pointer to the socket set structure */
705         EventBits_t xSelectBits;          /**< User may indicate which bits are interesting for this socket. */
706 
707         EventBits_t xSocketBits;          /**< These bits indicate the events which have actually occurred.
708                                            * They are maintained by the IP-task */
709     #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
710     struct xNetworkEndPoint * pxEndPoint; /**< The end-point to which the socket is bound. */
711 
712     /* This field is only only by the user, and can be accessed with
713      * vSocketSetSocketID() / vSocketGetSocketID().
714      * All fields of a socket will be cleared by memset() in FreeRTOS_socket().
715      */
716     void * pvSocketID;
717 
718     /* TCP/UDP specific fields: */
719     /* Before accessing any member of this structure, it should be confirmed */
720     /* that the protocol corresponds with the type of structure */
721 
722     union
723     {
724         IPUDPSocket_t xUDP;     /**< Union member: UDP socket*/
725         #if ( ipconfigUSE_TCP == 1 )
726             IPTCPSocket_t xTCP; /**< Union member: TCP socket */
727         #endif /* ipconfigUSE_TCP */
728     }
729     u; /**< Union of TCP/UDP socket */
730 };
731 
732 #if ( ipconfigUSE_TCP == 1 )
733 
734 /*
735  * Close the socket another time.
736  */
737     void vSocketCloseNextTime( FreeRTOS_Socket_t * pxSocket );
738 
739 /*
740  * Postpone a call to listen() by the IP-task.
741  */
742     void vSocketListenNextTime( FreeRTOS_Socket_t * pxSocket );
743 
744 /*
745  * Lookup a TCP socket, using a multiple matching: both port numbers and
746  * return IP address.
747  */
748     FreeRTOS_Socket_t * pxTCPSocketLookup( uint32_t ulLocalIP,
749                                            UBaseType_t uxLocalPort,
750                                            IPv46_Address_t xRemoteIP,
751                                            UBaseType_t uxRemotePort );
752 
753 #endif /* ipconfigUSE_TCP */
754 
755 
756 /*
757  * Look up a local socket by finding a match with the local port.
758  */
759 FreeRTOS_Socket_t * pxUDPSocketLookup( UBaseType_t uxLocalPort );
760 
761 /*
762  * Calculate the upper-layer checksum
763  * Works both for UDP, ICMP and TCP packages
764  * bOut = true: checksum will be set in outgoing packets
765  * bOut = false: checksum will be calculated for incoming packets
766  *     returning 0xffff means: checksum was correct
767  */
768 uint16_t usGenerateProtocolChecksum( uint8_t * pucEthernetBuffer,
769                                      size_t uxBufferLength,
770                                      BaseType_t xOutgoingPacket );
771 
772 /*
773  * An Ethernet frame has been updated (maybe it was an ARP request or a PING
774  * request?) and is to be sent back to its source.
775  */
776 void vReturnEthernetFrame( NetworkBufferDescriptor_t * pxNetworkBuffer,
777                            BaseType_t xReleaseAfterSend );
778 
779 /*
780  * The internal version of bind()
781  * If 'ulInternal' is true, it is called by the driver
782  * The TCP driver needs to bind a socket at the moment a listening socket
783  * creates a new connected socket
784  */
785 BaseType_t vSocketBind( FreeRTOS_Socket_t * pxSocket,
786                         struct freertos_sockaddr * pxBindAddress,
787                         size_t uxAddressLength,
788                         BaseType_t xInternal );
789 
790 /*
791  * Internal function to add streaming data to a TCP socket. If ulIn == true,
792  * data will be added to the rxStream, otherwise to the tXStream.  Normally data
793  * will be written with ulOffset == 0, meaning: at the end of the FIFO.  When
794  * packet come in out-of-order, an offset will be used to put it in front and
795  * the head will not change yet.
796  */
797 int32_t lTCPAddRxdata( FreeRTOS_Socket_t * pxSocket,
798                        size_t uxOffset,
799                        const uint8_t * pcData,
800                        uint32_t ulByteCount );
801 
802 /*
803  * Currently called for any important event.
804  */
805 void vSocketWakeUpUser( FreeRTOS_Socket_t * pxSocket );
806 
807 /*
808  * Some helping function, their meaning should be clear.
809  * Going by MISRA rules, these utility functions should not be defined
810  * if they are not being used anywhere. But their use depends on the
811  * application and hence these functions are defined unconditionally.
812  */
813 extern uint32_t ulChar2u32( const uint8_t * pucPtr );
814 
815 extern uint16_t usChar2u16( const uint8_t * pucPtr );
816 
817 /* Check a single socket for retransmissions and timeouts */
818 BaseType_t xTCPSocketCheck( FreeRTOS_Socket_t * pxSocket );
819 
820 BaseType_t xTCPCheckNewClient( FreeRTOS_Socket_t * pxSocket );
821 
822 /* Defined in FreeRTOS_Sockets.c
823  * Close a socket
824  */
825 void * vSocketClose( FreeRTOS_Socket_t * pxSocket );
826 
827 /*
828  * Send the event eEvent to the IP task event queue, using a block time of
829  * zero.  Return pdPASS if the message was sent successfully, otherwise return
830  * pdFALSE.
831  */
832 BaseType_t xSendEventToIPTask( eIPEvent_t eEvent );
833 
834 /*
835  * The same as above, but a struct as a parameter, containing:
836  *      eIPEvent_t eEventType;
837  *      void *pvData;
838  */
839 BaseType_t xSendEventStructToIPTask( const IPStackEvent_t * pxEvent,
840                                      TickType_t uxTimeout );
841 
842 /*
843  * Returns a pointer to the original NetworkBuffer from a pointer to a UDP
844  * payload buffer.
845  */
846 NetworkBufferDescriptor_t * pxUDPPayloadBuffer_to_NetworkBuffer( const void * pvBuffer );
847 
848 /* Get the size of the IP-header.
849  * 'usFrameType' must be filled in if IPv6is to be recognised. */
850 size_t uxIPHeaderSizePacket( const NetworkBufferDescriptor_t * pxNetworkBuffer );
851 /*-----------------------------------------------------------*/
852 
853 /* Get the size of the IP-header.
854  * The socket is checked for its type: IPv4 or IPv6. */
855 size_t uxIPHeaderSizeSocket( const FreeRTOS_Socket_t * pxSocket );
856 /*-----------------------------------------------------------*/
857 
858 /*
859  * Internal: Sets a new state for a TCP socket and performs the necessary
860  * actions like calling a OnConnected handler to notify the socket owner.
861  */
862 #if ( ipconfigUSE_TCP == 1 )
863     void vTCPStateChange( FreeRTOS_Socket_t * pxSocket,
864                           enum eTCP_STATE eTCPState );
865 #endif /* ipconfigUSE_TCP */
866 
867 /* Returns pdTRUE is this function is called from the IP-task */
868 BaseType_t xIsCallingFromIPTask( void );
869 
870 #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
871 
872 /** @brief Structure for event groups of the Socket Select functions */
873     typedef struct xSOCKET_SET
874     {
875         /** @brief Event group for the socket select function.
876          */
877         EventGroupHandle_t xSelectGroup;
878     } SocketSelect_t;
879 
880     extern void vSocketSelect( const SocketSelect_t * pxSocketSet );
881 
882 /** @brief Define the data that must be passed for a 'eSocketSelectEvent'. */
883     typedef struct xSocketSelectMessage
884     {
885         TaskHandle_t xTaskhandle;     /**< Task handle for use in the socket select functionality. */
886         SocketSelect_t * pxSocketSet; /**< The event group for the socket select functionality. */
887     } SocketSelectMessage_t;
888 
889 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
890 
891 /* Send the network-up event and start the ARP timer. */
892 void vIPNetworkUpCalls( struct xNetworkEndPoint * pxEndPoint );
893 
894 /* *INDENT-OFF* */
895 #ifdef __cplusplus
896     } /* extern "C" */
897 #endif
898 /* *INDENT-ON* */
899 
900 #endif /* FREERTOS_IP_PRIVATE_H */
901