1 /** @file
2  * @brief DNS resolving library
3  *
4  * An API for applications to resolve a DNS name.
5  */
6 
7 /*
8  * Copyright (c) 2017 Intel Corporation
9  *
10  * SPDX-License-Identifier: Apache-2.0
11  */
12 
13 #ifndef ZEPHYR_INCLUDE_NET_DNS_RESOLVE_H_
14 #define ZEPHYR_INCLUDE_NET_DNS_RESOLVE_H_
15 
16 #include <zephyr/kernel.h>
17 #include <zephyr/net/net_ip.h>
18 #include <zephyr/net/socket_poll.h>
19 #include <zephyr/net/net_core.h>
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 /**
26  * @brief DNS resolving library
27  * @defgroup dns_resolve DNS Resolve Library
28  * @since 1.8
29  * @version 0.8.0
30  * @ingroup networking
31  * @{
32  */
33 
34 /**
35  * DNS query type enum
36  */
37 enum dns_query_type {
38 	/** IPv4 query */
39 	DNS_QUERY_TYPE_A = 1,
40 	/** IPv6 query */
41 	DNS_QUERY_TYPE_AAAA = 28
42 };
43 
44 /** Max size of the resolved name. */
45 #ifndef DNS_MAX_NAME_SIZE
46 #define DNS_MAX_NAME_SIZE 20
47 #endif
48 
49 /** @cond INTERNAL_HIDDEN */
50 
51 #define DNS_BUF_TIMEOUT K_MSEC(500) /* ms */
52 
53 /* This value is recommended by RFC 1035 */
54 #define DNS_RESOLVER_MAX_BUF_SIZE	512
55 
56 /* Make sure that we can compile things even if CONFIG_DNS_RESOLVER
57  * is not enabled.
58  */
59 #if defined(CONFIG_DNS_RESOLVER_MAX_SERVERS)
60 #define DNS_RESOLVER_MAX_SERVERS CONFIG_DNS_RESOLVER_MAX_SERVERS
61 #else
62 #define DNS_RESOLVER_MAX_SERVERS 0
63 #endif
64 
65 #if defined(CONFIG_DNS_NUM_CONCUR_QUERIES)
66 #define DNS_NUM_CONCUR_QUERIES CONFIG_DNS_NUM_CONCUR_QUERIES
67 #else
68 #define DNS_NUM_CONCUR_QUERIES 1
69 #endif
70 
71 #if defined(CONFIG_NET_IF_MAX_IPV6_COUNT)
72 #define MAX_IPV6_IFACE_COUNT CONFIG_NET_IF_MAX_IPV6_COUNT
73 #else
74 #define MAX_IPV6_IFACE_COUNT 1
75 #endif
76 
77 #if defined(CONFIG_NET_IF_MAX_IPV4_COUNT)
78 #define MAX_IPV4_IFACE_COUNT CONFIG_NET_IF_MAX_IPV4_COUNT
79 #else
80 #define MAX_IPV4_IFACE_COUNT 1
81 #endif
82 
83 /* If mDNS is enabled, then add some extra well known multicast servers to the
84  * server list.
85  */
86 #if defined(CONFIG_MDNS_RESOLVER)
87 #if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_IPV4)
88 #define MDNS_SERVER_COUNT 2
89 #else
90 #define MDNS_SERVER_COUNT 1
91 #endif /* CONFIG_NET_IPV6 && CONFIG_NET_IPV4 */
92 #else
93 #define MDNS_SERVER_COUNT 0
94 #endif /* CONFIG_MDNS_RESOLVER */
95 
96 /* If LLMNR is enabled, then add some extra well known multicast servers to the
97  * server list.
98  */
99 #if defined(CONFIG_LLMNR_RESOLVER)
100 #if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_IPV4)
101 #define LLMNR_SERVER_COUNT 2
102 #else
103 #define LLMNR_SERVER_COUNT 1
104 #endif /* CONFIG_NET_IPV6 && CONFIG_NET_IPV4 */
105 #else
106 #define LLMNR_SERVER_COUNT 0
107 #endif /* CONFIG_MDNS_RESOLVER */
108 
109 #define DNS_MAX_MCAST_SERVERS (MDNS_SERVER_COUNT + LLMNR_SERVER_COUNT)
110 
111 #if defined(CONFIG_MDNS_RESPONDER)
112 #if defined(CONFIG_NET_IPV6)
113 #define MDNS_MAX_IPV6_IFACE_COUNT CONFIG_NET_IF_MAX_IPV6_COUNT
114 #else
115 #define MDNS_MAX_IPV6_IFACE_COUNT 0
116 #endif /* CONFIG_NET_IPV6 */
117 
118 #if defined(CONFIG_NET_IPV4)
119 #define MDNS_MAX_IPV4_IFACE_COUNT CONFIG_NET_IF_MAX_IPV4_COUNT
120 #else
121 #define MDNS_MAX_IPV4_IFACE_COUNT 0
122 #endif /* CONFIG_NET_IPV4 */
123 
124 #define MDNS_MAX_POLL (MDNS_MAX_IPV4_IFACE_COUNT + MDNS_MAX_IPV6_IFACE_COUNT)
125 #else
126 #define MDNS_MAX_POLL 0
127 #endif /* CONFIG_MDNS_RESPONDER */
128 
129 #if defined(CONFIG_LLMNR_RESPONDER)
130 #if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_IPV4)
131 #define LLMNR_MAX_POLL 2
132 #else
133 #define LLMNR_MAX_POLL 1
134 #endif
135 #else
136 #define LLMNR_MAX_POLL 0
137 #endif /* CONFIG_LLMNR_RESPONDER */
138 
139 #define DNS_RESOLVER_MAX_POLL (DNS_RESOLVER_MAX_SERVERS + DNS_MAX_MCAST_SERVERS)
140 
141 /** How many sockets the dispatcher is able to poll. */
142 #define DNS_DISPATCHER_MAX_POLL (DNS_RESOLVER_MAX_POLL + MDNS_MAX_POLL + LLMNR_MAX_POLL)
143 
144 #if defined(CONFIG_ZVFS_POLL_MAX)
145 BUILD_ASSERT(CONFIG_ZVFS_POLL_MAX >= DNS_DISPATCHER_MAX_POLL,
146 	     "CONFIG_ZVFS_POLL_MAX must be larger than " STRINGIFY(DNS_DISPATCHER_MAX_POLL));
147 #endif
148 
149 /** @brief What is the type of the socket given to DNS socket dispatcher,
150  * resolver or responder.
151  */
152 enum dns_socket_type {
153 	DNS_SOCKET_RESOLVER = 1,  /**< Socket is used for resolving (client type) */
154 	DNS_SOCKET_RESPONDER = 2  /**< Socket is used for responding (server type) */
155 };
156 
157 struct dns_resolve_context;
158 struct mdns_responder_context;
159 
160 /**
161  * @typedef dns_socket_dispatcher_cb
162  * @brief Callback used when the DNS socket dispatcher has found a handler for
163  * this type of socket.
164  *
165  * @param ctx DNS resolve or mDNS responder context.
166  * @param sock Socket which is seeing traffic.
167  * @param addr Socket address of the peer that sent the DNS packet.
168  * @param addrlen Length of the socket address.
169  * @param buf Pointer to data buffer containing the DNS message.
170  * @param data_len Length of the data in buffer chain.
171  *
172  * @return 0 if ok, <0 if error
173  */
174 typedef int (*dns_socket_dispatcher_cb)(void *ctx, int sock,
175 					struct sockaddr *addr, size_t addrlen,
176 					struct net_buf *buf, size_t data_len);
177 
178 /** @brief DNS socket dispatcher context. */
179 struct dns_socket_dispatcher {
180 	/** slist node for the different dispatcher contexts */
181 	sys_snode_t node;
182 	/** Socket service for this dispatcher instance */
183 	const struct net_socket_service_desc *svc;
184 	/** DNS resolver context that contains information needed by the
185 	 * resolver/responder handler, or mDNS responder context.
186 	 */
187 	union {
188 		void *ctx;
189 		struct dns_resolve_context *resolve_ctx;
190 		struct mdns_responder_context *mdns_ctx;
191 	};
192 
193 	/** Type of the socket (resolver / responder) */
194 	enum dns_socket_type type;
195 	/** Local endpoint address (used when binding the socket) */
196 	struct sockaddr local_addr;
197 	/** DNS socket dispatcher callback is called for incoming traffic */
198 	dns_socket_dispatcher_cb cb;
199 	/** Socket descriptors to poll */
200 	struct zsock_pollfd *fds;
201 	/** Length of the poll array */
202 	int fds_len;
203 	/** Local socket to dispatch */
204 	int sock;
205 	/** Interface we are bound to */
206 	int ifindex;
207 	/** There can be two contexts to dispatch. This points to the other
208 	 * context if sharing the socket between resolver / responder.
209 	 */
210 	struct dns_socket_dispatcher *pair;
211 	/** Mutex lock protecting access to this dispatcher context */
212 	struct k_mutex lock;
213 	/** Buffer allocation timeout */
214 	k_timeout_t buf_timeout;
215 };
216 
217 struct mdns_responder_context {
218 	struct sockaddr server_addr;
219 	struct dns_socket_dispatcher dispatcher;
220 	struct zsock_pollfd fds[1];
221 	int sock;
222 };
223 
224 /**
225  * @brief Register a DNS dispatcher socket. Each code wanting to use
226  * the dispatcher needs to create the dispatcher context and call
227  * this function.
228  *
229  * @param ctx DNS socket dispatcher context.
230  *
231  * @return 0 if ok, <1 if error
232  */
233 int dns_dispatcher_register(struct dns_socket_dispatcher *ctx);
234 
235 /**
236  * @brief Unregister a DNS dispatcher socket. Called when the
237  * resolver/responder no longer needs to receive traffic for the
238  * socket.
239  *
240  * @param ctx DNS socket dispatcher context.
241  *
242  * @return 0 if ok, <1 if error
243  */
244 int dns_dispatcher_unregister(struct dns_socket_dispatcher *ctx);
245 
246 /** @endcond */
247 
248 /**
249  * Address info struct is passed to callback that gets all the results.
250  */
251 struct dns_addrinfo {
252 	/** IP address information */
253 	struct sockaddr ai_addr;
254 	/** Length of the ai_addr field */
255 	socklen_t       ai_addrlen;
256 	/** Address family of the address information */
257 	uint8_t         ai_family;
258 	/** Canonical name of the address */
259 	char            ai_canonname[DNS_MAX_NAME_SIZE + 1];
260 };
261 
262 /**
263  * Status values for the callback.
264  */
265 enum dns_resolve_status {
266 	/** Invalid value for `ai_flags' field */
267 	DNS_EAI_BADFLAGS    = -1,
268 	/** NAME or SERVICE is unknown */
269 	DNS_EAI_NONAME      = -2,
270 	/** Temporary failure in name resolution */
271 	DNS_EAI_AGAIN       = -3,
272 	/** Non-recoverable failure in name res */
273 	DNS_EAI_FAIL        = -4,
274 	/** No address associated with NAME */
275 	DNS_EAI_NODATA      = -5,
276 	/** `ai_family' not supported */
277 	DNS_EAI_FAMILY      = -6,
278 	/** `ai_socktype' not supported */
279 	DNS_EAI_SOCKTYPE    = -7,
280 	/** SRV not supported for `ai_socktype' */
281 	DNS_EAI_SERVICE     = -8,
282 	/** Address family for NAME not supported */
283 	DNS_EAI_ADDRFAMILY  = -9,
284 	/** Memory allocation failure */
285 	DNS_EAI_MEMORY      = -10,
286 	/** System error returned in `errno' */
287 	DNS_EAI_SYSTEM      = -11,
288 	/** Argument buffer overflow */
289 	DNS_EAI_OVERFLOW    = -12,
290 	/** Processing request in progress */
291 	DNS_EAI_INPROGRESS  = -100,
292 	/** Request canceled */
293 	DNS_EAI_CANCELED    = -101,
294 	/** Request not canceled */
295 	DNS_EAI_NOTCANCELED = -102,
296 	/** All requests done */
297 	DNS_EAI_ALLDONE     = -103,
298 	/** IDN encoding failed */
299 	DNS_EAI_IDN_ENCODE  = -105,
300 };
301 
302 /**
303  * @typedef dns_resolve_cb_t
304  * @brief DNS resolve callback
305  *
306  * @details The DNS resolve callback is called after a successful
307  * DNS resolving. The resolver can call this callback multiple times, one
308  * for each resolved address.
309  *
310  * @param status The status of the query:
311  *  DNS_EAI_INPROGRESS returned for each resolved address
312  *  DNS_EAI_ALLDONE    mark end of the resolving, info is set to NULL in
313  *                     this case
314  *  DNS_EAI_CANCELED   if the query was canceled manually or timeout happened
315  *  DNS_EAI_FAIL       if the name cannot be resolved by the server
316  *  DNS_EAI_NODATA     if there is no such name
317  *  other values means that an error happened.
318  * @param info Query results are stored here.
319  * @param user_data The user data given in dns_resolve_name() call.
320  */
321 typedef void (*dns_resolve_cb_t)(enum dns_resolve_status status,
322 				 struct dns_addrinfo *info,
323 				 void *user_data);
324 
325 /** @cond INTERNAL_HIDDEN */
326 
327 enum dns_resolve_context_state {
328 	DNS_RESOLVE_CONTEXT_ACTIVE,
329 	DNS_RESOLVE_CONTEXT_DEACTIVATING,
330 	DNS_RESOLVE_CONTEXT_INACTIVE,
331 };
332 
333 /** @endcond */
334 
335 /**
336  * DNS resolve context structure.
337  */
338 struct dns_resolve_context {
339 	/** List of configured DNS servers */
340 	struct dns_server {
341 		/** DNS server information */
342 		struct sockaddr dns_server;
343 
344 		/** Connection to the DNS server */
345 		int sock;
346 
347 		/** Network interface index if the DNS resolving should be done
348 		 * via this interface. Value 0 indicates any interface can be used.
349 		 */
350 		int if_index;
351 
352 		/** Is this server mDNS one */
353 		uint8_t is_mdns : 1;
354 
355 		/** Is this server LLMNR one */
356 		uint8_t is_llmnr : 1;
357 
358 /** @cond INTERNAL_HIDDEN */
359 		/** Dispatch DNS data between resolver and responder */
360 		struct dns_socket_dispatcher dispatcher;
361 /** @endcond */
362 	} servers[DNS_RESOLVER_MAX_POLL];
363 
364 /** @cond INTERNAL_HIDDEN */
365 	/** Socket polling for each server connection */
366 	struct zsock_pollfd fds[DNS_RESOLVER_MAX_POLL];
367 /** @endcond */
368 
369 	/** Prevent concurrent access */
370 	struct k_mutex lock;
371 
372 	/** This timeout is also used when a buffer is required from the
373 	 * buffer pools.
374 	 */
375 	k_timeout_t buf_timeout;
376 
377 	/** Result callbacks. We have multiple callbacks here so that it is
378 	 * possible to do multiple queries at the same time.
379 	 *
380 	 * Contents of this structure can be inspected and changed only when
381 	 * the lock is held.
382 	 */
383 	struct dns_pending_query {
384 		/** Timeout timer */
385 		struct k_work_delayable timer;
386 
387 		/** Back pointer to ctx, needed in timeout handler */
388 		struct dns_resolve_context *ctx;
389 
390 		/** Result callback.
391 		 *
392 		 * A null value indicates the slot is not in use.
393 		 */
394 		dns_resolve_cb_t cb;
395 
396 		/** User data */
397 		void *user_data;
398 
399 		/** TX timeout */
400 		k_timeout_t timeout;
401 
402 		/** String containing the thing to resolve like www.example.com
403 		 *
404 		 * This is set to a non-null value when the query is started,
405 		 * and is not used thereafter.
406 		 *
407 		 * If the query completed at a point where the work item was
408 		 * still pending the pointer is cleared to indicate that the
409 		 * query is complete, but release of the query slot will be
410 		 * deferred until a request for a slot determines that the
411 		 * work item has been released.
412 		 */
413 		const char *query;
414 
415 		/** Query type */
416 		enum dns_query_type query_type;
417 
418 		/** DNS id of this query */
419 		uint16_t id;
420 
421 		/** Hash of the DNS name + query type we are querying.
422 		 * This hash is calculated so we can match the response that
423 		 * we are receiving. This is needed mainly for mDNS which is
424 		 * setting the DNS id to 0, which means that the id alone
425 		 * cannot be used to find correct pending query.
426 		 */
427 		uint16_t query_hash;
428 	} queries[DNS_NUM_CONCUR_QUERIES];
429 
430 	/** Is this context in use */
431 	enum dns_resolve_context_state state;
432 };
433 
434 /**
435  * @brief Init DNS resolving context.
436  *
437  * @details This function sets the DNS server address and initializes the
438  * DNS context that is used by the actual resolver. DNS server addresses
439  * can be specified either in textual form, or as struct sockaddr (or both).
440  * Note that the recommended way to resolve DNS names is to use
441  * the dns_get_addr_info() API. In that case user does not need to
442  * call dns_resolve_init() as the DNS servers are already setup by the system.
443  *
444  * @param ctx DNS context. If the context variable is allocated from
445  * the stack, then the variable needs to be valid for the whole duration of
446  * the resolving. Caller does not need to fill the variable beforehand or
447  * edit the context afterwards.
448  * @param dns_servers_str DNS server addresses using textual strings. The
449  * array is NULL terminated. The port number can be given in the string.
450  * Syntax for the server addresses with or without port numbers:
451  *    IPv4        : 10.0.9.1
452  *    IPv4 + port : 10.0.9.1:5353
453  *    IPv6        : 2001:db8::22:42
454  *    IPv6 + port : [2001:db8::22:42]:5353
455  * @param dns_servers_sa DNS server addresses as struct sockaddr. The array
456  * is NULL terminated. Port numbers are optional in struct sockaddr, the
457  * default will be used if set to 0.
458  *
459  * @return 0 if ok, <0 if error.
460  */
461 int dns_resolve_init(struct dns_resolve_context *ctx,
462 		     const char *dns_servers_str[],
463 		     const struct sockaddr *dns_servers_sa[]);
464 
465 /**
466  * @brief Init DNS resolving context with default Kconfig options.
467  *
468  * @param ctx DNS context.
469  *
470  * @return 0 if ok, <0 if error.
471  */
472 int dns_resolve_init_default(struct dns_resolve_context *ctx);
473 
474 /**
475  * @brief Close DNS resolving context.
476  *
477  * @details This releases DNS resolving context and marks the context unusable.
478  * Caller must call the dns_resolve_init() again to make context usable.
479  *
480  * @param ctx DNS context
481  *
482  * @return 0 if ok, <0 if error.
483  */
484 int dns_resolve_close(struct dns_resolve_context *ctx);
485 
486 /**
487  * @brief Reconfigure DNS resolving context.
488  *
489  * @details Reconfigures DNS context with new server list.
490  *
491  * @param ctx DNS context
492  * @param servers_str DNS server addresses using textual strings. The
493  * array is NULL terminated. The port number can be given in the string.
494  * Syntax for the server addresses with or without port numbers:
495  *    IPv4        : 10.0.9.1
496  *    IPv4 + port : 10.0.9.1:5353
497  *    IPv6        : 2001:db8::22:42
498  *    IPv6 + port : [2001:db8::22:42]:5353
499  * @param servers_sa DNS server addresses as struct sockaddr. The array
500  * is NULL terminated. Port numbers are optional in struct sockaddr, the
501  * default will be used if set to 0.
502  *
503  * @return 0 if ok, <0 if error.
504  */
505 int dns_resolve_reconfigure(struct dns_resolve_context *ctx,
506 			    const char *servers_str[],
507 			    const struct sockaddr *servers_sa[]);
508 
509 /**
510  * @brief Cancel a pending DNS query.
511  *
512  * @details This releases DNS resources used by a pending query.
513  *
514  * @param ctx DNS context
515  * @param dns_id DNS id of the pending query
516  *
517  * @return 0 if ok, <0 if error.
518  */
519 int dns_resolve_cancel(struct dns_resolve_context *ctx,
520 		       uint16_t dns_id);
521 
522 /**
523  * @brief Cancel a pending DNS query using id, name and type.
524  *
525  * @details This releases DNS resources used by a pending query.
526  *
527  * @param ctx DNS context
528  * @param dns_id DNS id of the pending query
529  * @param query_name Name of the resource we are trying to query (hostname)
530  * @param query_type Type of the query (A or AAAA)
531  *
532  * @return 0 if ok, <0 if error.
533  */
534 int dns_resolve_cancel_with_name(struct dns_resolve_context *ctx,
535 				 uint16_t dns_id,
536 				 const char *query_name,
537 				 enum dns_query_type query_type);
538 
539 /**
540  * @brief Resolve DNS name.
541  *
542  * @details This function can be used to resolve e.g., IPv4 or IPv6 address.
543  * Note that this is asynchronous call, the function will return immediately
544  * and system will call the callback after resolving has finished or timeout
545  * has occurred.
546  * We might send the query to multiple servers (if there are more than one
547  * server configured), but we only use the result of the first received
548  * response.
549  *
550  * @param ctx DNS context
551  * @param query What the caller wants to resolve.
552  * @param type What kind of data the caller wants to get.
553  * @param dns_id DNS id is returned to the caller. This is needed if one
554  * wishes to cancel the query. This can be set to NULL if there is no need
555  * to cancel the query.
556  * @param cb Callback to call after the resolving has finished or timeout
557  * has happened.
558  * @param user_data The user data.
559  * @param timeout The timeout value for the query. Possible values:
560  * SYS_FOREVER_MS: the query is tried forever, user needs to cancel it
561  *            manually if it takes too long time to finish
562  * >0: start the query and let the system timeout it after specified ms
563  *
564  * @return 0 if resolving was started ok, < 0 otherwise
565  */
566 int dns_resolve_name(struct dns_resolve_context *ctx,
567 		     const char *query,
568 		     enum dns_query_type type,
569 		     uint16_t *dns_id,
570 		     dns_resolve_cb_t cb,
571 		     void *user_data,
572 		     int32_t timeout);
573 
574 /**
575  * @brief Get default DNS context.
576  *
577  * @details The system level DNS context uses DNS servers that are
578  * defined in project config file. If no DNS servers are defined by the
579  * user, then resolving DNS names using default DNS context will do nothing.
580  * The configuration options are described in subsys/net/lib/dns/Kconfig file.
581  *
582  * @return Default DNS context.
583  */
584 struct dns_resolve_context *dns_resolve_get_default(void);
585 
586 /**
587  * @brief Get IP address info from DNS.
588  *
589  * @details This function can be used to resolve e.g., IPv4 or IPv6 address.
590  * Note that this is asynchronous call, the function will return immediately
591  * and system will call the callback after resolving has finished or timeout
592  * has occurred.
593  * We might send the query to multiple servers (if there are more than one
594  * server configured), but we only use the result of the first received
595  * response.
596  * This variant uses system wide DNS servers.
597  *
598  * @param query What the caller wants to resolve.
599  * @param type What kind of data the caller wants to get.
600  * @param dns_id DNS id is returned to the caller. This is needed if one
601  * wishes to cancel the query. This can be set to NULL if there is no need
602  * to cancel the query.
603  * @param cb Callback to call after the resolving has finished or timeout
604  * has happened.
605  * @param user_data The user data.
606  * @param timeout The timeout value for the connection. Possible values:
607  * SYS_FOREVER_MS: the query is tried forever, user needs to cancel it
608  *            manually if it takes too long time to finish
609  * >0: start the query and let the system timeout it after specified ms
610  *
611  * @return 0 if resolving was started ok, < 0 otherwise
612  */
dns_get_addr_info(const char * query,enum dns_query_type type,uint16_t * dns_id,dns_resolve_cb_t cb,void * user_data,int32_t timeout)613 static inline int dns_get_addr_info(const char *query,
614 				    enum dns_query_type type,
615 				    uint16_t *dns_id,
616 				    dns_resolve_cb_t cb,
617 				    void *user_data,
618 				    int32_t timeout)
619 {
620 	return dns_resolve_name(dns_resolve_get_default(),
621 				query,
622 				type,
623 				dns_id,
624 				cb,
625 				user_data,
626 				timeout);
627 }
628 
629 /**
630  * @brief Cancel a pending DNS query.
631  *
632  * @details This releases DNS resources used by a pending query.
633  *
634  * @param dns_id DNS id of the pending query
635  *
636  * @return 0 if ok, <0 if error.
637  */
dns_cancel_addr_info(uint16_t dns_id)638 static inline int dns_cancel_addr_info(uint16_t dns_id)
639 {
640 	return dns_resolve_cancel(dns_resolve_get_default(), dns_id);
641 }
642 
643 /**
644  * @}
645  */
646 
647 /** @cond INTERNAL_HIDDEN */
648 
649 /**
650  * @brief Initialize DNS subsystem.
651  */
652 #if defined(CONFIG_DNS_RESOLVER_AUTO_INIT)
653 void dns_init_resolver(void);
654 
655 #else
656 #define dns_init_resolver(...)
657 #endif /* CONFIG_DNS_RESOLVER_AUTO_INIT */
658 
659 /** @endcond */
660 
661 #ifdef __cplusplus
662 }
663 #endif
664 
665 #endif /* ZEPHYR_INCLUDE_NET_DNS_RESOLVE_H_ */
666