1 /* 2 * FreeRTOS+TCP V2.3.1 3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a copy of 6 * this software and associated documentation files (the "Software"), to deal in 7 * the Software without restriction, including without limitation the rights to 8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 * the Software, and to permit persons to whom the Software is furnished to do so, 10 * subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in all 13 * copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * http://aws.amazon.com/freertos 23 * http://www.FreeRTOS.org 24 */ 25 26 #ifndef FREERTOS_ROUTING_H 27 #define FREERTOS_ROUTING_H 28 29 #include "FreeRTOS.h" 30 #include "FreeRTOS_IP.h" 31 32 #if ( ipconfigUSE_DHCP != 0 ) 33 #include "FreeRTOS_DHCP.h" 34 #endif 35 36 #if ( ipconfigUSE_IPv6 != 0 ) 37 #include "FreeRTOS_DHCPv6.h" 38 #endif 39 40 #ifdef __cplusplus 41 extern "C" { 42 #endif 43 44 /* Every NetworkInterface needs a set of access functions: */ 45 46 /* Initialise the interface. */ 47 typedef BaseType_t ( * NetworkInterfaceInitialiseFunction_t ) ( struct xNetworkInterface * pxDescriptor ); 48 49 /* Send out an Ethernet packet. */ 50 typedef BaseType_t ( * NetworkInterfaceOutputFunction_t ) ( struct xNetworkInterface * pxDescriptor, 51 NetworkBufferDescriptor_t * const pxNetworkBuffer, 52 BaseType_t xReleaseAfterSend ); 53 54 /* Return true as long as the LinkStatus on the PHY is present. */ 55 typedef BaseType_t ( * GetPhyLinkStatusFunction_t ) ( struct xNetworkInterface * pxDescriptor ); 56 57 /** @brief These NetworkInterface access functions are collected in a struct: */ 58 typedef struct xNetworkInterface 59 { 60 const char * pcName; /**< Just for logging, debugging. */ 61 void * pvArgument; /**< Will be passed to the access functions. */ 62 NetworkInterfaceInitialiseFunction_t pfInitialise; /**< This function will be called upon initialisation and repeated until it returns pdPASS. */ 63 NetworkInterfaceOutputFunction_t pfOutput; /**< This function is supposed to send out a packet. */ 64 GetPhyLinkStatusFunction_t pfGetPhyLinkStatus; /**< This function will return pdTRUE as long as the PHY Link Status is high. */ 65 struct 66 { 67 uint32_t 68 bInterfaceUp : 1, /**< Non-zero as soon as the interface is up. */ 69 bCallDownEvent : 1; /**< The down-event must be called. */ 70 } bits; /**< A collection of boolean flags. */ 71 72 struct xNetworkEndPoint * pxEndPoint; /**< A list of end-points bound to this interface. */ 73 struct xNetworkInterface * pxNext; /**< The next interface in a linked list. */ 74 } NetworkInterface_t; 75 76 /* 77 * // As an example: 78 * NetworkInterface_t xZynqDescriptor = { 79 * .pcName = "Zynq-GEM", 80 * .pvArgument = ( void * )1, 81 * .pfInitialise = xZynqGEMInitialise, 82 * .pfOutput = xZynqGEMOutput, 83 * .pfGetPhyLinkStatus = xZynqGEMGetPhyLinkStatus, 84 * }; 85 */ 86 87 /** @brief The network settings for IPv4. */ 88 typedef struct xIPV4Parameters 89 { 90 uint32_t ulIPAddress; /**< The actual IPv4 address. Will be 0 as long as end-point is still down. */ 91 uint32_t ulNetMask; /**< The netmask. */ 92 uint32_t ulGatewayAddress; /**< The IP-address of the gateway. */ 93 uint32_t ulDNSServerAddresses[ ipconfigENDPOINT_DNS_ADDRESS_COUNT ]; /**< IP-addresses of DNS servers. */ 94 uint32_t ulBroadcastAddress; /**< The local broadcast address, e.g. '192.168.1.255'. */ 95 uint8_t ucDNSIndex; /**< The index of the next DNS address to be used. */ 96 } IPV4Parameters_t; 97 98 #if ( ipconfigUSE_IPv6 != 0 ) 99 typedef struct xIPV6Parameters 100 { 101 IPv6_Address_t xIPAddress; /* The actual IPv4 address. Will be 0 as long as end-point is still down. */ 102 size_t uxPrefixLength; /* Number of valid bytes in the network prefix. */ 103 IPv6_Address_t xPrefix; /* The network prefix, e.g. fe80::/10 */ 104 IPv6_Address_t xGatewayAddress; /* Gateway to the web. */ 105 IPv6_Address_t xDNSServerAddresses[ ipconfigENDPOINT_DNS_ADDRESS_COUNT ]; 106 uint8_t ucDNSIndex; /**< The index of the next DNS address to be used. */ 107 } IPV6Parameters_t; 108 #endif 109 110 #if ( ipconfigUSE_RA != 0 ) 111 /* Router Advertisement (RA). End-points can obtain their IP-address by asking for a RA. */ 112 typedef enum xRAState 113 { 114 eRAStateApply, /* Send a Router Solicitation. */ 115 eRAStateWait, /* Wait for a Router Advertisement. */ 116 eRAStateIPTest, /* Take a random IP address, test if another device is using it already. */ 117 eRAStateIPWait, /* Wait for a reply, if any */ 118 eRAStatePreLease, /* The device is ready to go to the 'eRAStateLease' state. */ 119 eRAStateLease, /* The device is up, repeat the RA-process when timer expires. */ 120 eRAStateFailed, 121 } eRAState_t; 122 123 struct xRA_DATA 124 { 125 struct 126 { 127 uint32_t 128 bRouterReplied : 1, 129 bIPAddressInUse : 1; 130 } 131 bits; 132 TickType_t ulPreferredLifeTime; 133 UBaseType_t uxRetryCount; 134 /* Maintains the RA state machine state. */ 135 eRAState_t eRAState; 136 }; 137 138 typedef struct xRA_DATA RAData_t; 139 #endif /* ( ipconfigUSE_RA != 0 ) */ 140 141 /** @brief The description of an end-point. */ 142 typedef struct xNetworkEndPoint 143 { 144 union 145 { 146 struct 147 { 148 IPV4Parameters_t ipv4_settings; /**< Actual IPv4 settings used by the end-point. */ 149 IPV4Parameters_t ipv4_defaults; /**< Use values form "ipv4_defaults" in case DHCP has failed. */ 150 }; 151 #if ( ipconfigUSE_IPv6 != 0 ) 152 struct 153 { 154 IPV6Parameters_t ipv6_settings; /**< Actual IPv6 settings used by the end-point. */ 155 IPV6Parameters_t ipv6_defaults; /**< Use values form "ipv6_defaults" in case DHCP has failed. */ 156 }; 157 #endif 158 }; 159 MACAddress_t xMACAddress; /**< The MAC-address assigned to this end-point. */ 160 struct 161 { 162 uint32_t 163 bIsDefault : 1, /**< This bit will be removed. */ 164 #if ( ipconfigUSE_DHCP != 0 ) || ( ipconfigUSE_DHCPv6 != 0 ) 165 bWantDHCP : 1, /**< This end-point wants to use DHCPv4 to obtain an IP-address. */ 166 #endif /* ipconfigUSE_DHCP */ 167 #if ( ipconfigUSE_RA != 0 ) 168 bWantRA : 1, /**< This end-point wants to use RA/SLAAC to obtain an IP-address. */ 169 #endif /* ipconfigUSE_RA */ 170 bIPv6 : 1, /**< This end-point has an IP-address of type IPv6. */ 171 #if ( ipconfigUSE_NETWORK_EVENT_HOOK != 0 ) 172 bCallDownHook : 1, /**< The network down hook-must be called for this end-point. */ 173 #endif /* ipconfigUSE_NETWORK_EVENT_HOOK */ 174 bEndPointUp : 1; /**< The end-point is up. */ 175 } bits; /**< A collection of boolean properties. */ 176 uint8_t usDNSType; /**< A LLMNR/mDNS lookup is being done for an IPv6 address. 177 * This field is only valid while xApplicationDNSQueryHook() is called. */ 178 #if ( ipconfigUSE_DHCP != 0 ) || ( ipconfigUSE_RA != 0 ) 179 IPTimer_t xDHCP_RATimer; /**< The timer used to call the DHCP/DHCPv6/RA state machine. */ 180 #endif /* ( ipconfigUSE_DHCP != 0 ) || ( ipconfigUSE_RA != 0 ) */ 181 #if ( ipconfigUSE_DHCP != 0 ) || ( ipconfigUSE_DHCPv6 != 0 ) 182 DHCPData_t xDHCPData; /**< A description of the DHCP client state machine. */ 183 #endif /* ( ipconfigUSE_DHCP != 0 ) || ( ipconfigUSE_DHCPv6 != 0 ) */ 184 #if ( ipconfigUSE_IPv6 != 0 ) 185 DHCPMessage_IPv6_t * pxDHCPMessage; /**< A description of the DHCPv6 client state machine. */ 186 #endif 187 #if ( ipconfigUSE_RA != 0 ) 188 RAData_t xRAData; /**< A description of the Router Advertisement ( RA ) client state machine. */ 189 #endif /* ( ipconfigUSE_RA != 0 ) */ 190 NetworkInterface_t * pxNetworkInterface; /**< The network interface that owns this end-point. */ 191 struct xNetworkEndPoint * pxNext; /**< The next end-point in the chain. */ 192 } NetworkEndPoint_t; 193 194 #define END_POINT_USES_DHCP( pxEndPoint ) ( ( pxEndPoint )->bits.bWantDHCP != pdFALSE_UNSIGNED ) 195 #define END_POINT_USES_RA( pxEndPoint ) ( ( ( pxEndPoint )->bits.bIPv6 != pdFALSE_UNSIGNED ) && ( ( pxEndPoint )->bits.bWantRA != pdFALSE_UNSIGNED ) ) 196 197 #define ENDPOINT_IS_IPv4( pxEndPoint ) ( ( ( pxEndPoint ) != NULL ) && ( ( pxEndPoint )->bits.bIPv6 == 0U ) ) 198 #define ENDPOINT_IS_IPv6( pxEndPoint ) ( ( ( pxEndPoint ) != NULL ) && ( ( pxEndPoint )->bits.bIPv6 != 0U ) ) 199 200 201 /* 202 * Add a new physical Network Interface. The object pointed to by 'pxInterface' 203 * must continue to exist. 204 * Only the Network Interface function xx_FillInterfaceDescriptor() shall call this function. 205 */ 206 NetworkInterface_t * FreeRTOS_AddNetworkInterface( NetworkInterface_t * pxInterface ); 207 208 /* 209 * Get the first Network Interface. 210 */ 211 NetworkInterface_t * FreeRTOS_FirstNetworkInterface( void ); 212 213 /* 214 * Get the next Network Interface. 215 */ 216 NetworkInterface_t * FreeRTOS_NextNetworkInterface( const NetworkInterface_t * pxInterface ); 217 218 /* 219 * Get the first end-point belonging to a given interface. When pxInterface is 220 * NULL, the very first end-point will be returned. 221 */ 222 NetworkEndPoint_t * FreeRTOS_FirstEndPoint( const NetworkInterface_t * pxInterface ); 223 224 /* 225 * Get the next end-point. When pxInterface is null, all end-points can be 226 * iterated. 227 */ 228 NetworkEndPoint_t * FreeRTOS_NextEndPoint( const NetworkInterface_t * pxInterface, 229 NetworkEndPoint_t * pxEndPoint ); 230 231 /* 232 * Find the end-point with given IP-address. 233 */ 234 NetworkEndPoint_t * FreeRTOS_FindEndPointOnIP_IPv4( uint32_t ulIPAddress, 235 uint32_t ulWhere ); 236 237 #if ( ipconfigUSE_IPv6 != 0 ) 238 /* Find the end-point with given IP-address. */ 239 NetworkEndPoint_t * FreeRTOS_FindEndPointOnIP_IPv6( const IPv6_Address_t * pxIPAddress ); 240 #endif /* ipconfigUSE_IPv6 */ 241 242 /* 243 * Find the end-point with given MAC-address. 244 * The search can be limited by supplying a particular interface. 245 */ 246 NetworkEndPoint_t * FreeRTOS_FindEndPointOnMAC( const MACAddress_t * pxMACAddress, 247 const NetworkInterface_t * pxInterface ); 248 249 /* 250 * Find the best fitting end-point to reach a given IP-address. 251 * Find an end-point whose IP-address is in the same network as the IP-address provided. 252 * 'ulWhere' is temporary and or debugging only. 253 */ 254 NetworkEndPoint_t * FreeRTOS_FindEndPointOnNetMask( uint32_t ulIPAddress, 255 uint32_t ulWhere ); 256 257 /* 258 * Find the best fitting end-point to reach a given IP-address on a given interface 259 * 'ulWhere' is temporary and or debugging only. 260 */ 261 NetworkEndPoint_t * FreeRTOS_InterfaceEndPointOnNetMask( const NetworkInterface_t * pxInterface, 262 uint32_t ulIPAddress, 263 uint32_t ulWhere ); 264 265 #if ( ipconfigUSE_IPv6 != 0 ) 266 NetworkEndPoint_t * FreeRTOS_FindEndPointOnNetMask_IPv6( const IPv6_Address_t * pxIPv6Address ); 267 #endif /* ipconfigUSE_IPv6 */ 268 269 #if ( ipconfigUSE_IPv6 != 0 ) 270 271 /* Get the first end-point belonging to a given interface. 272 * When pxInterface is NULL, the very first end-point will be returned. */ 273 NetworkEndPoint_t * FreeRTOS_FirstEndPoint_IPv6( const NetworkInterface_t * pxInterface ); 274 #endif /* ipconfigUSE_IPv6 */ 275 276 /* A ethernet packet has come in on a certain network interface. 277 * Find the best matching end-point. */ 278 NetworkEndPoint_t * FreeRTOS_MatchingEndpoint( const NetworkInterface_t * pxNetworkInterface, 279 const uint8_t * pucEthernetBuffer ); 280 281 /* Find an end-point that has a defined gateway. 282 * xIPType should equal ipTYPE_IPv4 or ipTYPE_IPv6. */ 283 NetworkEndPoint_t * FreeRTOS_FindGateWay( BaseType_t xIPType ); 284 285 /* Fill-in the end-point structure. */ 286 void FreeRTOS_FillEndPoint( NetworkInterface_t * pxNetworkInterface, 287 NetworkEndPoint_t * pxEndPoint, 288 const uint8_t ucIPAddress[ ipIP_ADDRESS_LENGTH_BYTES ], 289 const uint8_t ucNetMask[ ipIP_ADDRESS_LENGTH_BYTES ], 290 const uint8_t ucGatewayAddress[ ipIP_ADDRESS_LENGTH_BYTES ], 291 const uint8_t ucDNSServerAddress[ ipIP_ADDRESS_LENGTH_BYTES ], 292 const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] ); 293 294 #if ( ipconfigUSE_IPv6 != 0 ) 295 /* Fill-in the end-point structure. */ 296 void FreeRTOS_FillEndPoint_IPv6( NetworkInterface_t * pxNetworkInterface, 297 NetworkEndPoint_t * pxEndPoint, 298 const IPv6_Address_t * pxIPAddress, 299 const IPv6_Address_t * pxNetPrefix, 300 size_t uxPrefixLength, 301 const IPv6_Address_t * pxGatewayAddress, 302 const IPv6_Address_t * pxDNSServerAddress, /* Not used yet. */ 303 const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] ); 304 #endif 305 306 #if ( ipconfigHAS_ROUTING_STATISTICS == 1 ) 307 /** @brief Some simple network statistics. */ 308 typedef struct xRoutingStats 309 { 310 UBaseType_t ulOnIp; /**< The number of times 'FreeRTOS_FindEndPointOnIP_IPv4()' has been called. */ 311 UBaseType_t ulOnMAC; /**< The number of times 'FreeRTOS_FindEndPointOnMAC()' has been called. */ 312 UBaseType_t ulOnNetMask; /**< The number of times 'FreeRTOS_InterfaceEndPointOnNetMask()' has been called. */ 313 UBaseType_t ulMatching; /**< The number of times 'FreeRTOS_MatchingEndpoint()' has been called. */ 314 UBaseType_t ulLocations[ 14 ]; /**< The number of times 'FreeRTOS_InterfaceEndPointOnNetMask()' has been called from a particular location. */ 315 UBaseType_t ulLocationsIP[ 8 ]; /**< The number of times 'FreeRTOS_FindEndPointOnIP_IPv4()' has been called from a particular location. */ 316 } RoutingStats_t; 317 318 extern RoutingStats_t xRoutingStatistics; 319 #endif /* ( ipconfigHAS_ROUTING_STATISTICS == 1 ) */ 320 321 NetworkEndPoint_t * pxGetSocketEndpoint( ConstSocket_t xSocket ); 322 void vSetSocketEndpoint( Socket_t xSocket, 323 NetworkEndPoint_t * pxEndPoint ); 324 325 const char * pcEndpointName( const NetworkEndPoint_t * pxEndPoint, 326 char * pcBuffer, 327 size_t uxSize ); 328 329 typedef enum 330 { 331 eIPv6_Global, /* 001 */ 332 eIPv6_LinkLocal, /* 1111 1110 10 */ 333 eIPv6_SiteLocal, /* 1111 1110 11 */ 334 eIPv6_Multicast, /* 1111 1111 */ 335 eIPv6_Unknown, /* Not implemented. */ 336 } 337 IPv6_Type_t; 338 339 /** 340 * @brief Check the type of an IPv16 address. 341 * 342 * @return A value from enum IPv6_Type_t. 343 */ 344 IPv6_Type_t xIPv6_GetIPType( const IPv6_Address_t * pxAddress ); 345 346 #ifdef __cplusplus 347 } /* extern "C" */ 348 #endif 349 350 #endif /* FREERTOS_ROUTING_H */ 351