xref: /FreeRTOS-Plus-TCP-v4.0.0/source/include/FreeRTOS_DNS_Globals.h (revision df5aed9e58a72e2489b6c1936788885672c62981)
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 #ifndef FREERTOS_DNS_GLOBALS_H
29 #define FREERTOS_DNS_GLOBALS_H
30 
31 #include "FreeRTOS.h"
32 
33 #include "FreeRTOSIPConfig.h"
34 #include "FreeRTOSIPConfigDefaults.h"
35 #include "IPTraceMacroDefaults.h"
36 
37 #include "FreeRTOS_Sockets.h"
38 
39 #define dnsPARSE_ERROR              0UL
40 
41 #if ( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )
42     #define dnsDNS_PORT             0x3500U     /**< Little endian: Port used for DNS. */
43     #define dnsONE_QUESTION         0x0100U     /**< Little endian representation of a DNS question.*/
44     #define dnsOUTGOING_FLAGS       0x0001U     /**< Little endian representation of standard query. */
45     #define dnsRX_FLAGS_MASK        0x0f80U     /**< Little endian:  The bits of interest in the flags field of incoming DNS messages. */
46     #define dnsEXPECTED_RX_FLAGS    0x0080U     /**< Little Endian: Should be a response, without any errors. */
47 #else
48     #define dnsDNS_PORT             0x0035U     /**< Big endian: Port used for DNS. */
49     #define dnsONE_QUESTION         0x0001U     /**< Big endian representation of a DNS question.*/
50     #define dnsOUTGOING_FLAGS       0x0100U     /**< Big endian representation of standard query. */
51     #define dnsRX_FLAGS_MASK        0x800fU     /**< Big endian: The bits of interest in the flags field of incoming DNS messages. */
52     #define dnsEXPECTED_RX_FLAGS    0x8000U     /**< Big endian: Should be a response, without any errors. */
53 
54 #endif /* ipconfigBYTE_ORDER */
55 #if ( ipconfigUSE_DNS != 0 )
56 
57 /** @brief If the top two bits in the first character of a name field are set then the
58  * name field is an offset to the string, rather than the string itself. */
59     #define dnsNAME_IS_OFFSET    ( ( uint8_t ) 0xc0 )
60 
61 /** @brief The maximum number of times a DNS request should be sent out if a response
62  * is not received, before giving up. */
63     #ifndef ipconfigDNS_REQUEST_ATTEMPTS
64         #define ipconfigDNS_REQUEST_ATTEMPTS    5
65     #endif
66 
67 
68 /* NBNS flags. */
69     #if ( ipconfigUSE_NBNS == 1 )
70         #define dnsNBNS_FLAGS_RESPONSE        0x8000U /**< NBNS response flag. */
71         #define dnsNBNS_FLAGS_OPCODE_MASK     0x7800U /**< NBNS opcode bitmask. */
72         #define dnsNBNS_FLAGS_OPCODE_QUERY    0x0000U /**< NBNS opcode query. */
73     #endif /* ( ipconfigUSE_NBNS == 1 ) */
74 
75 /* Host types. */
76     #define dnsTYPE_A_HOST            0x01U /**< DNS type A host. */
77     #define dnsTYPE_AAAA_HOST         0x001CU
78     #define dnsTYPE_ANY_HOST          0x00FFU
79 
80     #define dnsCLASS_IN               0x01U /**< DNS class IN (Internet). */
81 
82 /* Maximum hostname length as defined in RFC 1035 section 3.1. */
83     #define dnsMAX_HOSTNAME_LENGTH    0xFFU
84 
85     #ifndef _lint
86         /* LLMNR constants. */
87         #define dnsLLMNR_TTL_VALUE           300U     /**< LLMNR time to live value of 5 minutes. */
88         #define dnsLLMNR_FLAGS_IS_REPONSE    0x8000U  /**< LLMNR flag value for response. */
89     #endif /* _lint */
90 
91 /* NBNS constants. */
92     #if ( ipconfigUSE_NBNS != 0 )
93         #define dnsNBNS_TTL_VALUE               3600UL  /**< NBNS TTL: 1 hour valid. */
94         #define dnsNBNS_TYPE_NET_BIOS           0x0020U /**< NBNS Type: NetBIOS. */
95         #define dnsNBNS_CLASS_IN                0x01U   /**< NBNS Class: IN (Internet). */
96         #define dnsNBNS_NAME_FLAGS              0x6000U /**< NBNS name flags. */
97         #define dnsNBNS_ENCODED_NAME_LENGTH     32      /**< NBNS encoded name length. */
98 
99 /** @brief If the queried NBNS name matches with the device's name,
100  * the query will be responded to with these flags: */
101         #define dnsNBNS_QUERY_RESPONSE_FLAGS    ( 0x8500U )
102     #endif /* ( ipconfigUSE_NBNS != 0 ) */
103 
104 
105     #ifndef _lint
106         #if ( ipconfigUSE_DNS_CACHE == 0 )
107             #if ( ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY != 1 )
108                 #error When DNS caching is disabled, please make ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY equal to 1.
109             #endif
110         #endif
111     #endif
112 
113 /** @brief Define the ASCII value of '.' (Period/Full-stop). */
114     #define ASCII_BASELINE_DOT    46U
115 
116 /* The Link-local Multicast Name Resolution (LLMNR)
117  * is included.
118  * Note that a special MAC address is required in addition to the NIC's actual
119  * MAC address: 01:00:5E:00:00:FC
120  *
121  * The target IP address will be 224.0.0.252
122  */
123     #if ( ipconfigBYTE_ORDER == pdFREERTOS_BIG_ENDIAN )
124         #define ipLLMNR_IP_ADDR    0xE00000FCUL
125     #else
126         #define ipLLMNR_IP_ADDR    0xFC0000E0UL
127     #endif /* ipconfigBYTE_ORDER == pdFREERTOS_BIG_ENDIAN */
128 
129     #define ipMDNS_TIME_TO_LIVE    255U
130 
131     #define ipLLMNR_PORT           5355U  /* Standard LLMNR port. */
132     #define ipDNS_PORT             53U    /* Standard DNS port. */
133     #define ipNBNS_PORT            137U   /* NetBIOS Name Service. */
134     #define ipNBDGM_PORT           138U   /* Datagram Service, not included. */
135 
136 /** @brief freertos_addrinfo is the equivalent of 'struct addrinfo'. */
137     struct freertos_addrinfo
138     {
139         BaseType_t ai_flags;                /**< The field is included for completeness, but it is not used. */
140         BaseType_t ai_family;               /**< The type of IP-address, either FREERTOS_AF_INET4 or FREERTOS_AF_INET6. */
141         BaseType_t ai_socktype;             /**< n.a. */
142         BaseType_t ai_protocol;             /**< n.a. */
143         socklen_t ai_addrlen;               /**< The length of the address, either ipSIZE_OF_IPv4_ADDRESS or ipSIZE_OF_IPv6_ADDRESS. */
144         struct freertos_sockaddr * ai_addr; /**< The socket address. */
145         char * ai_canonname;                /**< The name of the host. */
146         struct freertos_addrinfo * ai_next; /**< A pointer to the next find result, or NULL. */
147         struct
148         {
149             /* In order to avoid allocations, reserve space here for *ai_addr and *ai_canonname. */
150             struct freertos_sockaddr sockaddr;
151 
152             #if ( ipconfigUSE_DNS_CACHE != 0 )
153                 char ucName[ ipconfigDNS_CACHE_NAME_LENGTH ];
154             #endif
155         }
156         xPrivateStorage; /**< In order to avoid extra calls to malloc, the necessary space is reserved 'statically'. */
157     };
158 /* DNS answer record header. */
159     #include "pack_struct_start.h"
160     struct xDNSAnswerRecord
161     {
162         uint16_t usType;       /**< Type of DNS answer record. */
163         uint16_t usClass;      /**< Class of DNS answer record. */
164         uint32_t ulTTL;        /**< Number of seconds the result can be cached. */
165         uint16_t usDataLength; /**< Length of the data field. */
166     }
167     #include "pack_struct_end.h"
168     typedef struct xDNSAnswerRecord DNSAnswerRecord_t;
169 
170 /* Below #include just tells the compiler to pack the structure.
171  * It is included in to make the code more readable */
172     #include "pack_struct_start.h"
173     struct xDNSMessage
174     {
175         uint16_t usIdentifier;    /**< Query identifier. Used to match up replies to outstanding queries. */
176         uint16_t usFlags;         /**< Flags. */
177         uint16_t usQuestions;     /**< Number of questions asked in this query. */
178         uint16_t usAnswers;       /**< Number of answers being provided in this query. */
179         uint16_t usAuthorityRRs;  /**< Authoritative name server resource records. */
180         uint16_t usAdditionalRRs; /**< Additional resource records.*/
181     }
182     #include "pack_struct_end.h"
183     typedef struct xDNSMessage DNSMessage_t;
184 
185 /** @brief A struct with a set of variables that are shared among the helper functions
186  *         for the function 'DNS_ParseDNSReply()'. For internal use only.
187  */
188     typedef struct xParseSet
189     {
190         DNSMessage_t * pxDNSMessageHeader; /**< A pointer to the UDP payload buffer where the DNS message is stored. */
191         uint16_t usQuestions;              /**< The number of DNS questions that were asked. */
192         uint8_t * pucUDPPayloadBuffer;     /**< A pointer to the original UDP load buffer. */
193         uint8_t * pucByte;                 /**< A pointer that is used while parsing. */
194         size_t uxBufferLength;             /**< The total number of bytes received in the UDP payload. */
195         size_t uxSourceBytesRemaining;     /**< As pucByte is incremented, 'uxSourceBytesRemaining' will be decremented. */
196         uint16_t usType;                   /**< The type of address, recognised are dnsTYPE_A_HOST ( Ipv4 ) and
197                                             *   dnsTYPE_AAAA_HOST ( IPv6 ). */
198         uint32_t ulIPAddress;              /**< The IPv4 address found. In an IPv6 look-up, store a non-zero value when
199                                             *   an IPv6 address was found. */
200         size_t uxAddressLength;            /**< The size of the address, either ipSIZE_OF_IPv4_ADDRESS or
201                                             *   ipSIZE_OF_IPv6_ADDRESS */
202         uint16_t usNumARecordsStored;      /**< The number of A-records stored during a look-up. */
203         uint16_t usPortNumber;             /**< The port number that belong to the protocol ( DNS, MDNS etc ). */
204         #if ( ipconfigUSE_LLMNR == 1 ) || ( ipconfigUSE_MDNS == 1 )
205             uint16_t usClass;              /**< Only the value 'dnsCLASS_IN' is recognised, which stands for "Internet". */
206             char * pcRequestedName;        /**< A pointer to the full name of the host being looked up. */
207         #endif
208         #if ( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 ) || ( ipconfigUSE_MDNS == 1 )
209             BaseType_t xDoStore;                          /**< Becomes true when a DNS reply was requested by this device,
210                                                            *   i.e. it has a matching request ID. */
211             char pcName[ ipconfigDNS_CACHE_NAME_LENGTH ]; /**< A copy of the name that is mentioned in the questions. */
212         #endif
213         struct freertos_addrinfo * pxLastAddress;         /**< This variable is used while creating a linked-list of IP-addresses. */
214         struct freertos_addrinfo ** ppxLastAddress;       /**< This variable is also used while creating a linked-list of IP-addresses. */
215     } ParseSet_t;
216     #if ( ipconfigUSE_LLMNR == 1 ) || ( ipconfigUSE_MDNS == 1 )
217 
218         #include "pack_struct_start.h"
219         struct xLLMNRAnswer
220         {
221             uint8_t ucNameCode;    /**< Name type. */
222             uint8_t ucNameOffset;  /**< The name is not repeated in the answer, only the offset is given with "0xc0 <offs>" */
223             uint16_t usType;       /**< Type of the Resource record. */
224             uint16_t usClass;      /**< Class of the Resource record. */
225             uint32_t ulTTL;        /**< Seconds till this entry can be cached. */
226             uint16_t usDataLength; /**< Length of the address in this record. */
227             uint32_t ulIPAddress;  /**< The IP-address. */
228         }
229         #include "pack_struct_end.h"
230         typedef struct xLLMNRAnswer LLMNRAnswer_t;
231     #endif /* if ( ipconfigUSE_LLMNR == 1 ) || ( ipconfigUSE_MDNS == 1 ) */
232 
233     #if ( ipconfigUSE_NBNS == 1 )
234 
235         #include "pack_struct_start.h"
236         struct xNBNSRequest
237         {
238             uint16_t usRequestId;                          /**< NBNS request ID. */
239             uint16_t usFlags;                              /**< Flags of the DNS message. */
240             uint16_t ulRequestCount;                       /**< The number of requests/questions in this query. */
241             uint16_t usAnswerRSS;                          /**< The number of answers in this query. */
242             uint16_t usAuthRSS;                            /**< Number of authoritative resource records. */
243             uint16_t usAdditionalRSS;                      /**< Number of additional resource records. */
244             uint8_t ucNameSpace;                           /**< Length of name. */
245             uint8_t ucName[ dnsNBNS_ENCODED_NAME_LENGTH ]; /**< The domain name. */
246             uint8_t ucNameZero;                            /**< Terminator of the name. */
247             uint16_t usType;                               /**< Type of NBNS record. */
248             uint16_t usClass;                              /**< Class of NBNS request. */
249         }
250         #include "pack_struct_end.h"
251         typedef struct xNBNSRequest NBNSRequest_t;
252 
253         #include "pack_struct_start.h"
254         struct xNBNSAnswer
255         {
256             uint16_t usType;       /**< Type of NBNS answer. */
257             uint16_t usClass;      /**< Class of NBNS answer. */
258             uint32_t ulTTL;        /**< Time in seconds for which the answer can be cached. */
259             uint16_t usDataLength; /**< Data length. */
260             uint16_t usNbFlags;    /**< NetBIOS flags 0x6000 : IP-address, big-endian. */
261             uint32_t ulIPAddress;  /**< The IPv4 address. */
262         }
263         #include "pack_struct_end.h"
264         typedef struct xNBNSAnswer NBNSAnswer_t;
265     #endif /* if ( ipconfigUSE_NBNS == 1 ) */
266 
267     #if ( ipconfigDNS_USE_CALLBACKS != 0 )
268 
269 /*
270  * Users may define this type of function as a callback.
271  * It will be called when a DNS reply is received or when a timeout has been reached.
272  */
273         typedef void (* FOnDNSEvent ) ( const char * /* pcName */,
274                                         void * /* pvSearchID */,
275                                         struct freertos_addrinfo * /* pxAddressInfo */ );
276         /** @brief The structure to hold information for a DNS callback. */
277         typedef struct xDNS_Callback
278         {
279             TickType_t uxRemainingTime;    /**< Timeout in ms */
280             FOnDNSEvent pCallbackFunction; /**< Function to be called when the address has been found or when a timeout has been reached */
281             TimeOut_t uxTimeoutState;      /**< Timeout state. */
282             void * pvSearchID;             /**< Search ID of the callback function. */
283             struct xLIST_ITEM xListItem;   /**< List struct. */
284             BaseType_t xIsIPv6;            /**< Remember whether this was a IPv6 lookup. */
285             char pcName[ 1 ];              /**< 1 character name. */
286         } DNSCallback_t;
287     #endif /* if ( ipconfigDNS_USE_CALLBACKS != 0 ) */
288 
289 /**
290  * @brief structure to hold the buffer, its size and the data length
291  */
292     typedef struct xDNSBuffer
293     {
294         uint8_t * pucPayloadBuffer; /**< Buffer pointer */
295         size_t uxPayloadLength;     /**< Payload size */
296     } DNSBuffer_t;
297 
298     #if ( ipconfigUSE_MDNS == 1 ) || ( ipconfigUSE_LLMNR == 1 ) || ( ipconfigUSE_NBNS == 1 )
299 
300 /*
301  * The following function should be provided by the user and return true if it
302  * matches the domain name.
303  */
304         #if ( ipconfigIPv4_BACKWARD_COMPATIBLE == 1 )
305             /* Even though the function is defined in main.c, the rule is violated. */
306             /* misra_c_2012_rule_8_6_violation */
307             extern BaseType_t xApplicationDNSQueryHook( const char * pcName );
308         #else
309             /* Even though the function is defined in main.c, the rule is violated. */
310             /* misra_c_2012_rule_8_6_violation */
311             extern BaseType_t xApplicationDNSQueryHook_Multi( struct xNetworkEndPoint * pxEndPoint,
312                                                               const char * pcName );
313         #endif
314 
315     #endif /* ( ipconfigUSE_LLMNR == 1 ) || ( ipconfigUSE_NBNS == 1 ) */
316 #endif /* ipconfigUSE_DNS */
317 
318 /* Keeping this outside of ipconfigUSE_DNS flag as these are used inside IPv4 UDP code */
319 #define ipMDNS_PORT              5353U       /* Standard mDNS port. */
320 
321 #if ( ipconfigBYTE_ORDER == pdFREERTOS_BIG_ENDIAN )
322     #define ipMDNS_IP_ADDRESS    0xe00000fbU /* 224.0.0.251 */
323 #else
324     #define ipMDNS_IP_ADDRESS    0xfb0000e0U /* 224.0.0.251 */
325 #endif
326 
327 #endif /* ifndef FREERTOS_DNS_GLOBALS_H */
328