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 * http://aws.amazon.com/freertos 25 * http://www.FreeRTOS.org 26 */ 27 28 /** 29 * @file FreeRTOS_DNS_Networking.c 30 * @brief Implements the Domain Name System Networking 31 * for the FreeRTOS+TCP network stack. 32 */ 33 34 #include "FreeRTOS.h" 35 36 #include "FreeRTOS_DNS_Networking.h" 37 38 #if ( ipconfigUSE_DNS != 0 ) 39 40 /** 41 * @brief Bind the socket to a port number. 42 * @param[in] xSocket the socket that must be bound. 43 * @param[in] usPort the port number to bind to. 44 * @return The created socket - or NULL if the socket could not be created or could not be bound. 45 */ DNS_BindSocket(Socket_t xSocket,uint16_t usPort)46 BaseType_t DNS_BindSocket( Socket_t xSocket, 47 uint16_t usPort ) 48 { 49 struct freertos_sockaddr xAddress; 50 BaseType_t xReturn; 51 52 ( void ) memset( &( xAddress ), 0, sizeof( xAddress ) ); 53 xAddress.sin_family = FREERTOS_AF_INET; 54 xAddress.sin_port = usPort; 55 56 xReturn = FreeRTOS_bind( xSocket, &xAddress, ( socklen_t ) sizeof( xAddress ) ); 57 58 return xReturn; 59 } 60 61 /** 62 * @brief Create a socket and bind it to the standard DNS port number. 63 * 64 * @return The created socket - or NULL if the socket could not be created or could not be bound. 65 */ DNS_CreateSocket(TickType_t uxReadTimeOut_ticks)66 Socket_t DNS_CreateSocket( TickType_t uxReadTimeOut_ticks ) 67 { 68 Socket_t xSocket; 69 TickType_t uxWriteTimeOut_ticks = ipconfigDNS_SEND_BLOCK_TIME_TICKS; 70 71 /* This must be the first time this function has been called. Create 72 * the socket. */ 73 xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); 74 75 if( xSocketValid( xSocket ) == pdFALSE ) 76 { 77 /* There was an error, return NULL. */ 78 xSocket = NULL; 79 } 80 else 81 { 82 /* Ideally we should check for the return value. But since we are passing 83 * correct parameters, and xSocket is != NULL, the return value is 84 * going to be '0' i.e. success. Thus, return value is discarded */ 85 ( void ) FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, &( uxWriteTimeOut_ticks ), sizeof( TickType_t ) ); 86 ( void ) FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &( uxReadTimeOut_ticks ), sizeof( TickType_t ) ); 87 } 88 89 return xSocket; 90 } 91 92 /** 93 * @brief perform a DNS network request 94 * @param xDNSSocket Created socket 95 * @param xAddress address structure (ip, port etc) 96 * @param pxDNSBuf buffer to send 97 * @return xReturn: true if the message could be sent 98 * false otherwise 99 * 100 */ DNS_SendRequest(Socket_t xDNSSocket,const struct freertos_sockaddr * xAddress,const struct xDNSBuffer * pxDNSBuf)101 BaseType_t DNS_SendRequest( Socket_t xDNSSocket, 102 const struct freertos_sockaddr * xAddress, 103 const struct xDNSBuffer * pxDNSBuf ) 104 { 105 BaseType_t xReturn = pdFALSE; 106 BaseType_t xSent; 107 108 iptraceSENDING_DNS_REQUEST(); 109 110 /* Send the DNS message. */ 111 xSent = FreeRTOS_sendto( xDNSSocket, 112 pxDNSBuf->pucPayloadBuffer, 113 pxDNSBuf->uxPayloadLength, 114 FREERTOS_ZERO_COPY, 115 xAddress, 116 ( socklen_t ) sizeof( *xAddress ) ); 117 118 if( xSent == ( BaseType_t ) pxDNSBuf->uxPayloadLength ) 119 { 120 xReturn = pdPASS; 121 } 122 else 123 { 124 /* The message was not sent so the stack will not be 125 * releasing the zero copy - it must be released here. */ 126 xReturn = pdFAIL; 127 } 128 129 return xReturn; 130 } 131 /*-----------------------------------------------------------*/ 132 133 /** 134 * @brief perform a DNS network read 135 * @param xDNSSocket socket 136 * @param xAddress address to read from 137 * @param pxReceiveBuffer buffer to fill with received data 138 */ DNS_ReadReply(ConstSocket_t xDNSSocket,struct freertos_sockaddr * xAddress,struct xDNSBuffer * pxReceiveBuffer)139 BaseType_t DNS_ReadReply( ConstSocket_t xDNSSocket, 140 struct freertos_sockaddr * xAddress, 141 struct xDNSBuffer * pxReceiveBuffer ) 142 { 143 BaseType_t xReturn; 144 uint32_t ulAddressLength = ( uint32_t ) sizeof( struct freertos_sockaddr ); 145 146 /* Wait for the reply. */ 147 xReturn = FreeRTOS_recvfrom( xDNSSocket, 148 &pxReceiveBuffer->pucPayloadBuffer, 149 0, 150 FREERTOS_ZERO_COPY, 151 xAddress, 152 &ulAddressLength ); 153 154 if( xReturn <= 0 ) 155 { 156 /* 'pdFREERTOS_ERRNO_EWOULDBLOCK' is returned in case of a timeout. */ 157 FreeRTOS_printf( ( "DNS_ReadReply returns %d\n", ( int ) xReturn ) ); 158 } 159 160 return xReturn; 161 } 162 /*-----------------------------------------------------------*/ 163 164 /** 165 * @brief perform a DNS network close 166 * @param xDNSSocket the DNS socket to close 167 */ DNS_CloseSocket(Socket_t xDNSSocket)168 void DNS_CloseSocket( Socket_t xDNSSocket ) 169 { 170 ( void ) FreeRTOS_closesocket( xDNSSocket ); 171 } 172 #endif /* if ( ipconfigUSE_DNS != 0 ) */ 173 /*-----------------------------------------------------------*/ 174