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_NET_SOCKETS_POLL_MAX)
145 BUILD_ASSERT(CONFIG_NET_SOCKETS_POLL_MAX >= DNS_DISPATCHER_MAX_POLL,
146 "CONFIG_NET_SOCKETS_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 /** There can be two contexts to dispatch. This points to the other
206 * context if sharing the socket between resolver / responder.
207 */
208 struct dns_socket_dispatcher *pair;
209 /** Mutex lock protecting access to this dispatcher context */
210 struct k_mutex lock;
211 /** Buffer allocation timeout */
212 k_timeout_t buf_timeout;
213 };
214
215 struct mdns_responder_context {
216 struct sockaddr server_addr;
217 struct dns_socket_dispatcher dispatcher;
218 struct zsock_pollfd fds[1];
219 int sock;
220 };
221
222 /**
223 * @brief Register a DNS dispatcher socket. Each code wanting to use
224 * the dispatcher needs to create the dispatcher context and call
225 * this function.
226 *
227 * @param ctx DNS socket dispatcher context.
228 *
229 * @return 0 if ok, <1 if error
230 */
231 int dns_dispatcher_register(struct dns_socket_dispatcher *ctx);
232
233 /**
234 * @brief Unregister a DNS dispatcher socket. Called when the
235 * resolver/responder no longer needs to receive traffic for the
236 * socket.
237 *
238 * @param ctx DNS socket dispatcher context.
239 *
240 * @return 0 if ok, <1 if error
241 */
242 int dns_dispatcher_unregister(struct dns_socket_dispatcher *ctx);
243
244 /** @endcond */
245
246 /**
247 * Address info struct is passed to callback that gets all the results.
248 */
249 struct dns_addrinfo {
250 /** IP address information */
251 struct sockaddr ai_addr;
252 /** Length of the ai_addr field */
253 socklen_t ai_addrlen;
254 /** Address family of the address information */
255 uint8_t ai_family;
256 /** Canonical name of the address */
257 char ai_canonname[DNS_MAX_NAME_SIZE + 1];
258 };
259
260 /**
261 * Status values for the callback.
262 */
263 enum dns_resolve_status {
264 /** Invalid value for `ai_flags' field */
265 DNS_EAI_BADFLAGS = -1,
266 /** NAME or SERVICE is unknown */
267 DNS_EAI_NONAME = -2,
268 /** Temporary failure in name resolution */
269 DNS_EAI_AGAIN = -3,
270 /** Non-recoverable failure in name res */
271 DNS_EAI_FAIL = -4,
272 /** No address associated with NAME */
273 DNS_EAI_NODATA = -5,
274 /** `ai_family' not supported */
275 DNS_EAI_FAMILY = -6,
276 /** `ai_socktype' not supported */
277 DNS_EAI_SOCKTYPE = -7,
278 /** SRV not supported for `ai_socktype' */
279 DNS_EAI_SERVICE = -8,
280 /** Address family for NAME not supported */
281 DNS_EAI_ADDRFAMILY = -9,
282 /** Memory allocation failure */
283 DNS_EAI_MEMORY = -10,
284 /** System error returned in `errno' */
285 DNS_EAI_SYSTEM = -11,
286 /** Argument buffer overflow */
287 DNS_EAI_OVERFLOW = -12,
288 /** Processing request in progress */
289 DNS_EAI_INPROGRESS = -100,
290 /** Request canceled */
291 DNS_EAI_CANCELED = -101,
292 /** Request not canceled */
293 DNS_EAI_NOTCANCELED = -102,
294 /** All requests done */
295 DNS_EAI_ALLDONE = -103,
296 /** IDN encoding failed */
297 DNS_EAI_IDN_ENCODE = -105,
298 };
299
300 /**
301 * @typedef dns_resolve_cb_t
302 * @brief DNS resolve callback
303 *
304 * @details The DNS resolve callback is called after a successful
305 * DNS resolving. The resolver can call this callback multiple times, one
306 * for each resolved address.
307 *
308 * @param status The status of the query:
309 * DNS_EAI_INPROGRESS returned for each resolved address
310 * DNS_EAI_ALLDONE mark end of the resolving, info is set to NULL in
311 * this case
312 * DNS_EAI_CANCELED if the query was canceled manually or timeout happened
313 * DNS_EAI_FAIL if the name cannot be resolved by the server
314 * DNS_EAI_NODATA if there is no such name
315 * other values means that an error happened.
316 * @param info Query results are stored here.
317 * @param user_data The user data given in dns_resolve_name() call.
318 */
319 typedef void (*dns_resolve_cb_t)(enum dns_resolve_status status,
320 struct dns_addrinfo *info,
321 void *user_data);
322
323 /** @cond INTERNAL_HIDDEN */
324
325 enum dns_resolve_context_state {
326 DNS_RESOLVE_CONTEXT_ACTIVE,
327 DNS_RESOLVE_CONTEXT_DEACTIVATING,
328 DNS_RESOLVE_CONTEXT_INACTIVE,
329 };
330
331 /** @endcond */
332
333 /**
334 * DNS resolve context structure.
335 */
336 struct dns_resolve_context {
337 /** List of configured DNS servers */
338 struct dns_server {
339 /** DNS server information */
340 struct sockaddr dns_server;
341
342 /** Connection to the DNS server */
343 int sock;
344
345 /** Is this server mDNS one */
346 uint8_t is_mdns : 1;
347
348 /** Is this server LLMNR one */
349 uint8_t is_llmnr : 1;
350
351 /** @cond INTERNAL_HIDDEN */
352 /** Dispatch DNS data between resolver and responder */
353 struct dns_socket_dispatcher dispatcher;
354 /** @endcond */
355 } servers[DNS_RESOLVER_MAX_POLL];
356
357 /** @cond INTERNAL_HIDDEN */
358 /** Socket polling for each server connection */
359 struct zsock_pollfd fds[DNS_RESOLVER_MAX_POLL];
360 /** @endcond */
361
362 /** Prevent concurrent access */
363 struct k_mutex lock;
364
365 /** This timeout is also used when a buffer is required from the
366 * buffer pools.
367 */
368 k_timeout_t buf_timeout;
369
370 /** Result callbacks. We have multiple callbacks here so that it is
371 * possible to do multiple queries at the same time.
372 *
373 * Contents of this structure can be inspected and changed only when
374 * the lock is held.
375 */
376 struct dns_pending_query {
377 /** Timeout timer */
378 struct k_work_delayable timer;
379
380 /** Back pointer to ctx, needed in timeout handler */
381 struct dns_resolve_context *ctx;
382
383 /** Result callback.
384 *
385 * A null value indicates the slot is not in use.
386 */
387 dns_resolve_cb_t cb;
388
389 /** User data */
390 void *user_data;
391
392 /** TX timeout */
393 k_timeout_t timeout;
394
395 /** String containing the thing to resolve like www.example.com
396 *
397 * This is set to a non-null value when the query is started,
398 * and is not used thereafter.
399 *
400 * If the query completed at a point where the work item was
401 * still pending the pointer is cleared to indicate that the
402 * query is complete, but release of the query slot will be
403 * deferred until a request for a slot determines that the
404 * work item has been released.
405 */
406 const char *query;
407
408 /** Query type */
409 enum dns_query_type query_type;
410
411 /** DNS id of this query */
412 uint16_t id;
413
414 /** Hash of the DNS name + query type we are querying.
415 * This hash is calculated so we can match the response that
416 * we are receiving. This is needed mainly for mDNS which is
417 * setting the DNS id to 0, which means that the id alone
418 * cannot be used to find correct pending query.
419 */
420 uint16_t query_hash;
421 } queries[DNS_NUM_CONCUR_QUERIES];
422
423 /** Is this context in use */
424 enum dns_resolve_context_state state;
425 };
426
427 /**
428 * @brief Init DNS resolving context.
429 *
430 * @details This function sets the DNS server address and initializes the
431 * DNS context that is used by the actual resolver. DNS server addresses
432 * can be specified either in textual form, or as struct sockaddr (or both).
433 * Note that the recommended way to resolve DNS names is to use
434 * the dns_get_addr_info() API. In that case user does not need to
435 * call dns_resolve_init() as the DNS servers are already setup by the system.
436 *
437 * @param ctx DNS context. If the context variable is allocated from
438 * the stack, then the variable needs to be valid for the whole duration of
439 * the resolving. Caller does not need to fill the variable beforehand or
440 * edit the context afterwards.
441 * @param dns_servers_str DNS server addresses using textual strings. The
442 * array is NULL terminated. The port number can be given in the string.
443 * Syntax for the server addresses with or without port numbers:
444 * IPv4 : 10.0.9.1
445 * IPv4 + port : 10.0.9.1:5353
446 * IPv6 : 2001:db8::22:42
447 * IPv6 + port : [2001:db8::22:42]:5353
448 * @param dns_servers_sa DNS server addresses as struct sockaddr. The array
449 * is NULL terminated. Port numbers are optional in struct sockaddr, the
450 * default will be used if set to 0.
451 *
452 * @return 0 if ok, <0 if error.
453 */
454 int dns_resolve_init(struct dns_resolve_context *ctx,
455 const char *dns_servers_str[],
456 const struct sockaddr *dns_servers_sa[]);
457
458 /**
459 * @brief Init DNS resolving context with default Kconfig options.
460 *
461 * @param ctx DNS context.
462 *
463 * @return 0 if ok, <0 if error.
464 */
465 int dns_resolve_init_default(struct dns_resolve_context *ctx);
466
467 /**
468 * @brief Close DNS resolving context.
469 *
470 * @details This releases DNS resolving context and marks the context unusable.
471 * Caller must call the dns_resolve_init() again to make context usable.
472 *
473 * @param ctx DNS context
474 *
475 * @return 0 if ok, <0 if error.
476 */
477 int dns_resolve_close(struct dns_resolve_context *ctx);
478
479 /**
480 * @brief Reconfigure DNS resolving context.
481 *
482 * @details Reconfigures DNS context with new server list.
483 *
484 * @param ctx DNS context
485 * @param servers_str DNS server addresses using textual strings. The
486 * array is NULL terminated. The port number can be given in the string.
487 * Syntax for the server addresses with or without port numbers:
488 * IPv4 : 10.0.9.1
489 * IPv4 + port : 10.0.9.1:5353
490 * IPv6 : 2001:db8::22:42
491 * IPv6 + port : [2001:db8::22:42]:5353
492 * @param servers_sa DNS server addresses as struct sockaddr. The array
493 * is NULL terminated. Port numbers are optional in struct sockaddr, the
494 * default will be used if set to 0.
495 *
496 * @return 0 if ok, <0 if error.
497 */
498 int dns_resolve_reconfigure(struct dns_resolve_context *ctx,
499 const char *servers_str[],
500 const struct sockaddr *servers_sa[]);
501
502 /**
503 * @brief Cancel a pending DNS query.
504 *
505 * @details This releases DNS resources used by a pending query.
506 *
507 * @param ctx DNS context
508 * @param dns_id DNS id of the pending query
509 *
510 * @return 0 if ok, <0 if error.
511 */
512 int dns_resolve_cancel(struct dns_resolve_context *ctx,
513 uint16_t dns_id);
514
515 /**
516 * @brief Cancel a pending DNS query using id, name and type.
517 *
518 * @details This releases DNS resources used by a pending query.
519 *
520 * @param ctx DNS context
521 * @param dns_id DNS id of the pending query
522 * @param query_name Name of the resource we are trying to query (hostname)
523 * @param query_type Type of the query (A or AAAA)
524 *
525 * @return 0 if ok, <0 if error.
526 */
527 int dns_resolve_cancel_with_name(struct dns_resolve_context *ctx,
528 uint16_t dns_id,
529 const char *query_name,
530 enum dns_query_type query_type);
531
532 /**
533 * @brief Resolve DNS name.
534 *
535 * @details This function can be used to resolve e.g., IPv4 or IPv6 address.
536 * Note that this is asynchronous call, the function will return immediately
537 * and system will call the callback after resolving has finished or timeout
538 * has occurred.
539 * We might send the query to multiple servers (if there are more than one
540 * server configured), but we only use the result of the first received
541 * response.
542 *
543 * @param ctx DNS context
544 * @param query What the caller wants to resolve.
545 * @param type What kind of data the caller wants to get.
546 * @param dns_id DNS id is returned to the caller. This is needed if one
547 * wishes to cancel the query. This can be set to NULL if there is no need
548 * to cancel the query.
549 * @param cb Callback to call after the resolving has finished or timeout
550 * has happened.
551 * @param user_data The user data.
552 * @param timeout The timeout value for the query. Possible values:
553 * SYS_FOREVER_MS: the query is tried forever, user needs to cancel it
554 * manually if it takes too long time to finish
555 * >0: start the query and let the system timeout it after specified ms
556 *
557 * @return 0 if resolving was started ok, < 0 otherwise
558 */
559 int dns_resolve_name(struct dns_resolve_context *ctx,
560 const char *query,
561 enum dns_query_type type,
562 uint16_t *dns_id,
563 dns_resolve_cb_t cb,
564 void *user_data,
565 int32_t timeout);
566
567 /**
568 * @brief Get default DNS context.
569 *
570 * @details The system level DNS context uses DNS servers that are
571 * defined in project config file. If no DNS servers are defined by the
572 * user, then resolving DNS names using default DNS context will do nothing.
573 * The configuration options are described in subsys/net/lib/dns/Kconfig file.
574 *
575 * @return Default DNS context.
576 */
577 struct dns_resolve_context *dns_resolve_get_default(void);
578
579 /**
580 * @brief Get IP address info from DNS.
581 *
582 * @details This function can be used to resolve e.g., IPv4 or IPv6 address.
583 * Note that this is asynchronous call, the function will return immediately
584 * and system will call the callback after resolving has finished or timeout
585 * has occurred.
586 * We might send the query to multiple servers (if there are more than one
587 * server configured), but we only use the result of the first received
588 * response.
589 * This variant uses system wide DNS servers.
590 *
591 * @param query What the caller wants to resolve.
592 * @param type What kind of data the caller wants to get.
593 * @param dns_id DNS id is returned to the caller. This is needed if one
594 * wishes to cancel the query. This can be set to NULL if there is no need
595 * to cancel the query.
596 * @param cb Callback to call after the resolving has finished or timeout
597 * has happened.
598 * @param user_data The user data.
599 * @param timeout The timeout value for the connection. Possible values:
600 * SYS_FOREVER_MS: the query is tried forever, user needs to cancel it
601 * manually if it takes too long time to finish
602 * >0: start the query and let the system timeout it after specified ms
603 *
604 * @return 0 if resolving was started ok, < 0 otherwise
605 */
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)606 static inline int dns_get_addr_info(const char *query,
607 enum dns_query_type type,
608 uint16_t *dns_id,
609 dns_resolve_cb_t cb,
610 void *user_data,
611 int32_t timeout)
612 {
613 return dns_resolve_name(dns_resolve_get_default(),
614 query,
615 type,
616 dns_id,
617 cb,
618 user_data,
619 timeout);
620 }
621
622 /**
623 * @brief Cancel a pending DNS query.
624 *
625 * @details This releases DNS resources used by a pending query.
626 *
627 * @param dns_id DNS id of the pending query
628 *
629 * @return 0 if ok, <0 if error.
630 */
dns_cancel_addr_info(uint16_t dns_id)631 static inline int dns_cancel_addr_info(uint16_t dns_id)
632 {
633 return dns_resolve_cancel(dns_resolve_get_default(), dns_id);
634 }
635
636 /**
637 * @}
638 */
639
640 /** @cond INTERNAL_HIDDEN */
641
642 /**
643 * @brief Initialize DNS subsystem.
644 */
645 #if defined(CONFIG_DNS_RESOLVER_AUTO_INIT)
646 void dns_init_resolver(void);
647
648 #else
649 #define dns_init_resolver(...)
650 #endif /* CONFIG_DNS_RESOLVER_AUTO_INIT */
651
652 /** @endcond */
653
654 #ifdef __cplusplus
655 }
656 #endif
657
658 #endif /* ZEPHYR_INCLUDE_NET_DNS_RESOLVE_H_ */
659