static uint32_t prvGetHostByName( const char *pcHostName, TickType_t xIdentifier, TickType_t xReadTimeOut_ms ) { struct freertos_sockaddr xAddress; Socket_t xDNSSocket; uint32_t ulIPAddress = 0UL; uint8_t *pucUDPPayloadBuffer; static uint32_t ulAddressLength; BaseType_t xAttempt; int32_t lBytes; size_t xPayloadLength, xExpectedPayloadLength; TickType_t xWriteTimeOut_ms = 100U; #if( ipconfigUSE_LLMNR == 1 ) BaseType_t bHasDot = pdFALSE; #endif /* ipconfigUSE_LLMNR == 1 */ /* If LLMNR is being used then determine if the host name includes a '.' - if not then LLMNR can be used as the lookup method. */ #if( ipconfigUSE_LLMNR == 1 ) { const char *pucPtr; for( pucPtr = pcHostName; *pucPtr; pucPtr++ ) { if( *pucPtr == '.' ) { bHasDot = pdTRUE; break; } } } #endif /* ipconfigUSE_LLMNR == 1 */ /* Two is added at the end for the count of characters in the first subdomain part and the string end byte. */ xExpectedPayloadLength = sizeof( DNSMessage_t ) + strlen( pcHostName ) + sizeof( uint16_t ) + sizeof( uint16_t ) + 2u; xDNSSocket = prvCreateDNSSocket(); if( xDNSSocket != NULL ) { FreeRTOS_setsockopt( xDNSSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &xWriteTimeOut_ms, sizeof( TickType_t ) ); FreeRTOS_setsockopt( xDNSSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &xReadTimeOut_ms, sizeof( TickType_t ) ); for( xAttempt = 0; xAttempt < ipconfigDNS_REQUEST_ATTEMPTS; xAttempt++ ) { /* Get a buffer. This uses a maximum delay, but the delay will be capped to ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS so the return value still needs to be tested. */ pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xExpectedPayloadLength, portMAX_DELAY ); if( pucUDPPayloadBuffer != NULL ) { /* Create the message in the obtained buffer. */ xPayloadLength = prvCreateDNSMessage( pucUDPPayloadBuffer, pcHostName, xIdentifier ); iptraceSENDING_DNS_REQUEST(); /* Obtain the DNS server address. */ FreeRTOS_GetAddressConfiguration( NULL, NULL, NULL, &ulIPAddress ); /* Send the DNS message. */ #if( ipconfigUSE_LLMNR == 1 ) if( bHasDot == pdFALSE ) { /* Use LLMNR addressing. */ ( ( DNSMessage_t * ) pucUDPPayloadBuffer) -> usFlags = 0; xAddress.sin_addr = ipLLMNR_IP_ADDR; /* Is in network byte order. */ xAddress.sin_port = FreeRTOS_ntohs( ipLLMNR_PORT ); } else #endif { /* Use DNS server. */ xAddress.sin_addr = ulIPAddress; xAddress.sin_port = dnsDNS_PORT; } ulIPAddress = 0UL; if( FreeRTOS_sendto( xDNSSocket, pucUDPPayloadBuffer, xPayloadLength, FREERTOS_ZERO_COPY, &xAddress, sizeof( xAddress ) ) != 0 ) { /* Wait for the reply. */ lBytes = FreeRTOS_recvfrom( xDNSSocket, &pucUDPPayloadBuffer, 0, FREERTOS_ZERO_COPY, &xAddress, &ulAddressLength ); if( lBytes > 0 ) { /* The reply was received. Process it. */ ulIPAddress = prvParseDNSReply( pucUDPPayloadBuffer, xIdentifier ); /* Finished with the buffer. The zero copy interface is being used, so the buffer must be freed by the task. */ FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer ); if( ulIPAddress != 0UL ) { /* All done. */ break; } } } else { /* The message was not sent so the stack will not be releasing the zero copy - it must be released here. */ FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer ); } } } /* Finished with the socket. */ FreeRTOS_closesocket( xDNSSocket ); } return ulIPAddress; }
uint32_t FreeRTOS_gethostbyname( const uint8_t *pcHostName ) { static uint16_t usIdentifier = 0; struct freertos_sockaddr xAddress; static xSocket_t xDNSSocket = NULL; uint32_t ulIPAddress = 0UL; uint8_t *pucUDPPayloadBuffer; static uint32_t ulAddressLength; portBASE_TYPE xAttempt; int32_t lBytes; size_t xPayloadLength; const size_t xExpectedPayloadLength = sizeof( xDNSMessage_t ) + strlen( ( const char * const ) pcHostName ) + sizeof( uint16_t ) + sizeof( uint16_t ) + 2; /* Two for the count of characters in the first subdomain part, and the string end byte */ if( xDNSSocket == NULL ) { xDNSSocket = prvCreateDNSSocket(); } if( xDNSSocket != NULL ) { /* Generate a unique identifier for this query. */ usIdentifier++; for( xAttempt = 0; xAttempt < dnsMAX_REQUEST_ATTEMPTS; xAttempt++ ) { /* Get a buffer. This uses a maximum delay, but the delay will be capped to ipconfigMAX_SEND_BLOCK_TIME_TICKS so the return value still needs to be tested. */ pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xExpectedPayloadLength, portMAX_DELAY ); if( pucUDPPayloadBuffer != NULL ) { /* Create the message in the obtained buffer. */ xPayloadLength = prvCreateDNSMessage( pucUDPPayloadBuffer, pcHostName, usIdentifier ); iptraceSENDING_DNS_REQUEST(); /* Obtain the DNS server address. */ FreeRTOS_GetAddressConfiguration( NULL, NULL, NULL, &ulIPAddress ); /* Send the DNS message. */ xAddress.sin_addr = ulIPAddress; xAddress.sin_port = dnsDNS_PORT; ulIPAddress = 0; if( FreeRTOS_sendto( xDNSSocket, pucUDPPayloadBuffer, xPayloadLength, FREERTOS_ZERO_COPY, &xAddress, sizeof( xAddress ) ) != 0 ) { /* Wait for the reply. */ lBytes = FreeRTOS_recvfrom( xDNSSocket, &pucUDPPayloadBuffer, 0, FREERTOS_ZERO_COPY, &xAddress, &ulAddressLength ); if( lBytes > 0 ) { /* The reply was received. Process it. */ ulIPAddress = prvParseDNSReply( pucUDPPayloadBuffer, usIdentifier ); /* Finished with the buffer. The zero copy interface is being used, so the buffer must be freed by the task. */ FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer ); if( ulIPAddress != 0 ) { /* All done. */ break; } } } else { /* The message was not sent so the stack will not be releasing the zero copy - it must be released here. */ FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer ); } } } } return ulIPAddress; }