2 * Copyright (c) 2019-2020 Apple Inc. All rights reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * https://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #ifndef __MDNS_RESOLVER_H__
18 #define __MDNS_RESOLVER_H__
20 #include "mdns_base.h"
21 #include "mdns_address.h"
22 #include "mdns_object.h"
24 #include <dispatch/dispatch.h>
31 // Workaround for the new SVCB and HTTPS resource record types, to which some DNS servers react negatively.
32 #define MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND 1
34 OS_CLOSED_ENUM(mdns_resolver_type
, int,
35 mdns_resolver_type_null
= 0,
36 /*! @const mdns_resolver_type_normal A resolver that uses normal DNS, i.e., DNS over UDP and TCP. */
37 mdns_resolver_type_normal
= 1,
38 /*! @const mdns_resolver_type_tcp A resolver that uses DNS over TCP. */
39 mdns_resolver_type_tcp
= 2,
40 /*! @const mdns_resolver_type_tls A resolver that uses DNS over TLS. */
41 mdns_resolver_type_tls
= 3,
42 /*! @const mdns_resolver_type_https A resolver that uses DNS over HTTPS. */
43 mdns_resolver_type_https
= 4
46 MDNS_ASSUME_NONNULL_BEGIN
48 static inline const char *
49 mdns_resolver_type_to_string(mdns_resolver_type_t type
)
52 case mdns_resolver_type_null
: return "null";
53 case mdns_resolver_type_normal
: return "normal";
54 case mdns_resolver_type_tcp
: return "tcp";
55 case mdns_resolver_type_tls
: return "tls";
56 case mdns_resolver_type_https
: return "https";
57 default: return "<INVALID RESOLVER TYPE>";
65 * Creates a resolver object, which represents a DNS service.
68 * The type of resolver to create.
70 * @param interface_index
71 * Index of the interface to use for network traffic to the DNS service.
74 * A new resolver object or NULL if there was a lack of resources.
77 * Generally, the servers that implement the DNS service are specified with
78 * mdns_resolver_add_server_address().
80 * However, for resolvers of type mdns_resolver_type_tls and mdns_resolver_type_https, no server addresses
81 * need to be specified at all so long as a hostname is specified with mdns_resolver_set_provider_name(),
82 * and, optionally, a port number with mdns_resolver_set_port(). In this case, the system's stub resolver
83 * will be used to resolve the hostname to IP addresses.
85 MDNS_RETURNS_RETAINED mdns_resolver_t _Nullable
86 mdns_resolver_create(mdns_resolver_type_t type
, uint32_t interface_index
, OSStatus
* _Nullable out_error
);
90 * Specifies the queue on which to invoke the resolver's asynchronous handlers.
99 * Currently, a resolver's only asynchronous handler is its event handler.
101 * This function has no effect on a querier that has been activated or invalidated.
104 mdns_resolver_set_queue(mdns_resolver_t resolver
, dispatch_queue_t queue
);
106 OS_CLOSED_ENUM(mdns_resolver_event
, int,
107 /*! @const mdns_resolver_event_null This value represents the absence of an event (will never be delivered). */
108 mdns_resolver_event_null
= 0,
109 /*! @const mdns_resolver_event_invalidated Indicates that the resolver has been invalidated. */
110 mdns_resolver_event_invalidated
= 1,
111 /*! @const mdns_resolver_event_connection Used to report the status of a resolver's connection. */
112 mdns_resolver_event_connection
= 2
115 static inline const char *
116 mdns_resolver_event_to_string(const mdns_resolver_event_t event
)
119 case mdns_resolver_event_null
: return "null";
120 case mdns_resolver_event_invalidated
: return "invalidated";
121 case mdns_resolver_event_connection
: return "connection";
122 default: return "<invalid event value>";
126 #define MDNS_RESOLVER_EVENT_CONNECTION_INFO_KEY_CANNOT_CONNECT "cannot_connect"
130 * A block for handling an asynchronous resolver event.
133 * Indicates the event's type.
136 * A dictionary whose format is specific to the event's type. The information contained in the dictionary
137 * is relevant to the event currently being handled. If the dictionary is required after the handler has
138 * finished executing, it should be retained with xpc_retain().
140 typedef void (^mdns_resolver_event_handler_t
)(mdns_resolver_event_t event
, xpc_object_t _Nullable info
);
144 * Sets a resolver's event handler.
153 * If invoked, the event handler will be submitted to the dispatch queue specified by
154 * mdns_resolver_set_queue() for any of the following events:
156 * - mdns_resolver_event_invalidated
157 * Indicates that the resolver has been completely invalidated. After this event, the event handler
158 * will never be invoked again. This event doesn't provide an info dictionary.
160 * The event handler will never be invoked prior to a call to either mdns_resolver_activate() or
161 * mdns_resolver_invalidate().
163 * This function has no effect on a resolver that has been activated or invalidated.
166 mdns_resolver_set_event_handler(mdns_resolver_t resolver
, mdns_resolver_event_handler_t handler
);
170 * Specifies the "provider name" of the DNS service represented by a resolver.
175 * @param provider_name
179 * kNoErr if the provider name was successfully set. Otherwise, a non-zero error code.
182 * The meaning of a provider name depends on the type of resolver.
184 * This function is currently only meaningful for resolvers that use DNS over TLS or HTTPS, i.e., resolvers
185 * of type mdns_resolver_type_tls or mdns_resolver_type_https. For these resolvers, the provider name is
186 * the hostname used for TLS certificate authentication.
188 * If no server addresses are specified with mdns_resolver_add_server_address() and the DNS service uses a
189 * port number other than the default for its type of service, then use mdns_resolver_set_port() to specify
192 * This function has no effect on a resolver that has been activated or invalidated.
195 mdns_resolver_set_provider_name(mdns_resolver_t resolver
, const char * _Nullable provider_name
);
199 * Specifies the port number of the DNS service represented by a resolver.
205 * The port number. A value of 0 means to use the DNS service's default port number.
208 * This function is currently only meaningful for resolvers that use DNS over TLS or HTTPS, i.e., resolvers
209 * of type mdns_resolver_type_tls or mdns_resolver_type_https, and only when a hostname has been specified
210 * with mdns_resolver_set_provider_name() and no server addresses have been specified with
211 * mdns_resolver_add_server_address().
213 * This function has no effect on a resolver that has been activated or invalidated.
216 mdns_resolver_set_port(mdns_resolver_t resolver
, uint16_t port
);
220 * For resolvers that use HTTP, specifies the path part of the DNS service's URL.
226 * The path part of the DNS service's URL.
229 * kNoErr if the URL path was successfully set. Otherwise, a non-zero error code.
232 * This function has no effect on a resolver that has been activated or invalidated.
234 * This function is currently only meaningful for resolvers that use DNS over HTTPS, i.e., resolvers of type
235 * mdns_resolver_type_https.
238 mdns_resolver_set_url_path(mdns_resolver_t resolver
, const char * _Nullable url_path
);
242 * Squash CNAME chains for responses.
247 * @param squash_cnames
248 * A boolean to indicate that CNAME chains should be squashed.
251 * This function has no effect on a resolver that has been activated or invalidated.
254 mdns_resolver_set_squash_cnames(mdns_resolver_t resolver
, bool squash_cnames
);
258 * Determines whether a resolver reports DNS server responsiveness symptoms.
264 * If true, the resolver will report DNS server responsiveness symptoms. If false, it will not.
267 * Symptom reporting is disabled by default.
269 * This function has no effect on a resolver that has been activated or invalidated.
272 mdns_resolver_enable_symptom_reporting(mdns_resolver_t resolver
, bool enable
);
276 * Specifies the IP address and port pair of one of the servers that implement the DNS service represented
283 * The server's IP address and port pair. If the port number is 0, then the DNS service's default port
284 * number will be used.
287 * kNoErr on success. Otherwise, a non-zero error code.
290 * This function has no effect on a resolver that has been activated or invalidated.
293 mdns_resolver_add_server_address(mdns_resolver_t resolver
, mdns_address_t address
);
297 * Specifies the initial datagram retransmission interval in seconds.
302 * @param interval_secs
303 * The interval in seconds.
306 * This function has no effect on a resolver that has been activated or invalidated.
309 mdns_resolver_set_initial_datagram_retransmission_interval(mdns_resolver_t resolver
, uint32_t interval_secs
);
313 * Determines whether a resolver makes an effort to reuse existing connections for queries that need to be
314 * sent over a connection.
320 * If true, disables connection reuse. If false, enables connection reuse.
323 * For efficiency, connection reuse is enabled by default. If a query needs to be sent to a server via a
324 * connection (as opposed to via a datagram) and a connection to the server already exists, then that
325 * connection will be reused instead of establishing a new connection.
327 * If connection reuse is disabled, then each query that needs to be sent over a connection will use its
330 * This function has no effect on a resolver that has been activated or invalidated.
333 mdns_resolver_disable_connection_reuse(mdns_resolver_t resolver
, bool disable
);
335 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
338 * Enables or disables a workaround where a resolver's queriers will refrain from sending queries of type
339 * SVCB and HTTPS to a server if the server has been determined to not respond to queries of those types.
345 * If greater than zero, the workaround is enabled. Otherwise, the workaround is disabled.
348 * This is a workaround for DNS servers that don't respond to SVCB and HTTPS queries and then become less
349 * responsive to queries of other types as more SVCB and HTTPS retry queries are sent.
351 * The workaround is disabled by default.
353 * This function has no effect on a resolver after it has been activated or invalidated.
356 mdns_resolver_enable_problematic_qtype_workaround(mdns_resolver_t resolver
, int threshold
);
361 * Activates a resolver.
367 * Activation makes the resolver usable to its queriers.
369 * This function has no effect on a resolver that has already been activated or one that has been invalidated.
372 mdns_resolver_activate(mdns_resolver_t resolver
);
376 * Invalidates a resolver.
382 * This function should be called when the resolver is no longer needed. When called, all outstanding
383 * queriers that were created by this resolver will asynchronously conclude with a kEndingErr error, unless
384 * a response or some other error is pending.
386 * If a queue was specified with mdns_resolver_set_queue() and an event handler was specified with
387 * mdns_resolver_set_event_handler(), then an mdns_resolver_event_invalidated event will be asynchronously
388 * delivered to the event handler to indicate when the invalidation is complete.
390 * This function has no effect on a resolver that has already been invalidated.
393 mdns_resolver_invalidate(mdns_resolver_t resolver
);
397 * Determines if resolvers of a given type use encryption.
403 * Returns true if the resolvers of the specified type use encryption. Otherwise, returns false.
406 mdns_resolver_type_uses_encryption(mdns_resolver_type_t type
);
410 * Creates a querier to issue queries to the DNS service represented by the resolver.
416 * A querier issues one or more queries to the DNS service represented by a resolver for a particular QNAME,
417 * QTYPE, and QCLASS triple until is gets a response.
419 MDNS_RETURNS_RETAINED mdns_querier_t _Nullable
420 mdns_resolver_create_querier(mdns_resolver_t resolver
, OSStatus
* _Nullable out_error
);
424 * Specifies the queue on which to invoke the querier's result handler.
433 * This function must be called before activating the querier.
435 * This function has no effect on a querier that has been activated or invalidated.
438 mdns_querier_set_queue(mdns_querier_t querier
, dispatch_queue_t queue
);
442 * Defines the query, i.e., the name, type, and class of the resource record(s) to query for.
448 * The name of the resource record(s) to query for as a sequence of domain name labels, i.e., the querier's
449 * DNS query's QNAME value.
452 * The type of the resource record(s) to query for, i.e., the querier's DNS query's QTYPE value.
455 * The class of the resource record(s) to query for, i.e., the querier's DNS query's QCLASS value.
458 * This function must be called before activating the querier.
460 * This function has no effect on a querier that has been activated or invalidated.
463 mdns_querier_set_query(mdns_querier_t querier
, const uint8_t *qname
, uint16_t qtype
, uint16_t qclass
);
467 * Determines whether a querier's queries will include an OPT record in the additional section with the
468 * "DNSSEC OK" (DO) bit set.
474 * If true, a querier's queries will include an OPT record in the additional section with the DO bit set.
476 * If false and the querier's queries do include an OPT record in the additional section, then the DO bit
480 * From section 3 of RFC3225 <https://tools.ietf.org/html/rfc3225#section-3>:
482 * Setting the DO bit to one in a query indicates to the server that the
483 * resolver is able to accept DNSSEC security RRs. The DO bit cleared
484 * (set to zero) indicates the resolver is unprepared to handle DNSSEC
485 * security RRs and those RRs MUST NOT be returned in the response
486 * (unless DNSSEC security RRs are explicitly queried for).
488 * If an OPT record is included in a query, the default behavior is to clear the DO bit.
490 * This function has no effect on a querier that has been activated or invalidated.
493 mdns_querier_set_dnssec_ok(mdns_querier_t querier
, bool dnssec_ok
);
497 * Determines whether a querier's queries will have the Checking Disabled (CD) bit set.
502 * @param checking_disabled
503 * If true, a querier's queries will have the CD bit set.
505 * If false, a querier's queries will have the CD bit cleared.
508 * From section 3.2.2 of RFC4035 <https://tools.ietf.org/html/rfc4035#section-3.2.2>:
510 * The CD bit exists in order to allow a security-aware resolver to
511 * disable signature validation in a security-aware name server's
512 * processing of a particular query.
514 * The default behavior is to clear the CD bit.
516 * This function has no effect on a querier that has been activated or invalidated.
519 mdns_querier_set_checking_disabled(mdns_querier_t querier
, bool checking_disabled
);
523 * Sets the querier's delegator by its process identifier (PID).
529 * The delegator's PID.
532 * This function marks the querier's datagram network traffic as belonging to the delegator.
534 * If this functionality is needed, this function must be called before activating the querier.
536 * This function has no effect on a querier that has been activated or invalidated.
539 mdns_querier_set_delegator_pid(mdns_querier_t querier
, pid_t pid
);
543 * Sets the querier's delegator by its universally unique identifier (UUID).
549 * The delegator's UUID.
552 * This function marks the querier's datagram network traffic as belonging to the delegator.
554 * If this functionality is needed, this function must be called before activating the querier.
556 * This function has no effect on a querier that has been activated or invalidated.
559 mdns_querier_set_delegator_uuid(mdns_querier_t querier
, uuid_t _Nonnull uuid
);
563 * Sets the querier's logging label.
569 * The printf-style format string for the label.
572 * Log messages associated with this querier will be prefixed with the specified label.
574 * If this functionality is needed, this function must be called before activating the querier.
576 * This function has no effect on a querier that has been activated or invalidated.
579 mdns_querier_set_log_label(mdns_querier_t querier
, const char *format
, ...) MDNS_PRINTF_FORMAT(2, 3);
582 * @typedef mdns_querier_result_type_t
585 * Inidicates the type of result with which a querier concluded.
587 * @const mdns_querier_result_type_null
588 * Used as a placeholder value to indicate no result. A querier will never conclude with this result type.
590 * @const mdns_querier_result_type_response
591 * Indicates that a querier concluded with a response to its query.
593 * @const mdns_querier_result_type_timeout
594 * Indicates that a querier concluded because it reached its current time limit before getting a response.
596 * @const mdns_querier_result_type_invalidation
597 * Indicates that a querier concluded because it was invalidated before getting a response.
599 * @const mdns_querier_result_type_resolver_invalidation
600 * Indicates that a querier concluded because its resolver was invalidated before getting a response.
602 * @const mdns_querier_result_type_error
603 * Indicates that a querier concluded because it ran into a fatal error before getting a response.
605 OS_CLOSED_ENUM(mdns_querier_result_type
, int,
606 mdns_querier_result_type_null
= 0,
607 mdns_querier_result_type_response
= 1,
608 mdns_querier_result_type_timeout
= 2,
609 mdns_querier_result_type_invalidation
= 3,
610 mdns_querier_result_type_resolver_invalidation
= 4,
611 mdns_querier_result_type_error
= 5
614 static inline const char *
615 mdns_querier_result_type_to_string(const mdns_querier_result_type_t type
)
618 case mdns_querier_result_type_null
: return "null";
619 case mdns_querier_result_type_response
: return "response";
620 case mdns_querier_result_type_timeout
: return "timeout";
621 case mdns_querier_result_type_invalidation
: return "invalidation";
622 case mdns_querier_result_type_resolver_invalidation
: return "resolver-invalidation";
623 case mdns_querier_result_type_error
: return "error";
625 return "<INVALID RESOLVER TYPE>";
628 (^mdns_querier_result_handler_t
)(void);
632 * Sets a querier's result handler.
638 * The result handler.
641 * The result handler will be invoked on the dispatch queue specified by
642 * mdns_querier_set_queue() and will never be invoked more than once.
644 * A querier's result type can be determined with mdns_querier_get_result_type().
646 * This function has no effect on a querier that has been activated or invalidated.
649 mdns_querier_set_result_handler(mdns_querier_t querier
, mdns_querier_result_handler_t handler
);
653 * Imposes a time limit on the time that a querier spends waiting for a response to its query.
658 * @param time_limit_ms
659 * The time limit in milliseconds.
662 * This function can be called more than once to reset the current time limit.
664 * If this function is called before activation, then the time limit doesn't apply until activation.
666 * This function has no effect on a querier that has concluded.
669 mdns_querier_set_time_limit_ms(mdns_querier_t querier
, int32_t time_limit_ms
);
673 * Sets a user-defined identifier on a querier.
682 * This function is a convenience function meant to help users in situations where a querier is associated
683 * with a numerical value. This function has no effect on a querier's operational behavior.
685 * The default identifier is 0.
687 * This function has no effect on a querier that has been activated.
690 mdns_querier_set_user_id(mdns_querier_t querier
, uint32_t user_id
);
694 * Activates a querier.
700 * This function has no effect on a querier that has already been activated or one that has been invalidated.
703 mdns_querier_activate(mdns_querier_t querier
);
707 * Invalidates a querier.
713 * This function should be called when the querier is no longer needed.
715 * This function has no effect on a querier that has already been invalidated.
718 mdns_querier_invalidate(mdns_querier_t querier
);
722 * Gets the QNAME value that a querier uses for its DNS queries.
728 * If at least one successful call was made to mdns_querier_set_query(), then this function returns a
729 * non-NULL pointer to a domain name as a sequence of labels that's equal in value to the qname argument
730 * used for the last successful call to mdns_querier_set_query(). Otherwise, NULL.
732 * If the result is a non-NULL pointer, then the pointer is guaranteed to be valid until the next
733 * successful call to mdns_querier_set_query() or until all references to the querier have been released,
734 * whichever comes first.
736 const uint8_t * _Nullable
737 mdns_querier_get_qname(mdns_querier_t querier
);
741 * Gets the QTYPE value that a querier uses for its DNS queries.
747 * If at least one successful call was made to mdns_querier_set_query(), then this function returns a value
748 * equal to the qtype argument used for the last successful call to mdns_querier_set_query(). Otherwise, 0.
751 mdns_querier_get_qtype(mdns_querier_t querier
);
755 * Gets the QCLASS value that a querier uses for its DNS queries.
761 * If at least one successful call was made to mdns_querier_set_query(), then this function returns a value
762 * equal to the qclass argument used for the last successful call to mdns_querier_set_query(). Otherwise,
766 mdns_querier_get_qclass(mdns_querier_t querier
);
770 * Gets a querier's resolver type.
776 mdns_querier_get_resolver_type(mdns_querier_t querier
);
780 * Returns the type of result with which a querier concluded.
786 * This function should only be called from the result handler or after the result handler has been
789 mdns_querier_result_type_t
790 mdns_querier_get_result_type(mdns_querier_t querier
);
794 * Gets the current number of queries that a querier has sent.
800 * It's safe to call this function before a querier has concluded.
803 mdns_querier_get_send_count(mdns_querier_t querier
);
807 * Gets the byte-length of a querier's DNS query message.
813 * This function should only be called from the result handler or after the result handler has been
817 mdns_querier_get_query_length(mdns_querier_t querier
);
821 * Returns a pointer to the first bye of a querier's DNS response message in wire format.
827 * This function should only be called from the result handler or after the result handler has been
828 * invoked. The pointer returned is only meaningful if the querier's result type is
829 * mdns_querier_result_type_response.
831 const uint8_t * _Nullable
832 mdns_querier_get_response_ptr(mdns_querier_t querier
);
836 * Gets the byte-length of a querier's DNS response message.
842 * This function should only be called from the result handler or after the result handler has been
843 * invoked. The length returned is only meaningful if the querier's result type is
844 * mdns_querier_result_type_response.
847 mdns_querier_get_response_length(mdns_querier_t querier
);
851 * Returns whether or not a querier's response is fabricated.
857 * Returns true if the response is fabricated. Otherwise, false.
860 * This function should only be called from the result handler or after the result handler has been
861 * invoked. The value returned is only meaningful if the querier's result type is
862 * mdns_querier_result_type_response.
865 mdns_querier_response_is_fabricated(mdns_querier_t querier
);
869 * Returns the fatal error encountered by a querier.
875 * This function should only be called from the result handler or after the result handler has been
876 * invoked. The error returned is only meaningful if the querier's result type is
877 * mdns_querier_result_type_error.
880 mdns_querier_get_error(mdns_querier_t querier
);
884 * Gets the DNSSEC OK bit of the querier.
890 mdns_querier_get_dnssec_ok(mdns_querier_t querier
);
892 OS_CLOSED_ENUM(mdns_query_over_tcp_reason
, int,
893 mdns_query_over_tcp_reason_null
= 0,
894 mdns_query_over_tcp_reason_truncation
= 1,
895 mdns_query_over_tcp_reason_got_suspicious_reply
= 2,
896 mdns_query_over_tcp_reason_in_suspicious_mode
= 3
901 * If a querier uses a DNS53 resolver and at some point switched over to TCP to send its query, then this
902 * function returns the reason for doing so.
908 * If the querier didn't use a DNS53 resolver or used UDP exclusively, then the return value is
909 * mdns_query_over_tcp_reason_null. Otherwise, one of the other mdns_query_over_tcp_reason_t enum values.
912 * This function should only be called from the result handler or after the result handler has been
915 mdns_query_over_tcp_reason_t
916 mdns_querier_get_over_tcp_reason(mdns_querier_t querier
);
920 * Determines whether a querier has been configured to query for a DNS resource record of a given name,
927 * A domain name as a sequence of domain labels.
930 * A DNS resource record type.
933 * A DNS resource record class.
936 * Returns true if the querier was configured to query for a DNS resource record of the given name, type,
937 * and class. Otherwise, false.
940 mdns_querier_match(mdns_querier_t querier
, const uint8_t *qname
, int qtype
, int qclass
);
944 * Determines whether or not a querier has concluded.
950 * Returns true if the querier has concluded. Otherwise, false.
953 * Before the result handler specified by mdns_querier_set_result_handler() has been invoked, this
954 * function should only be called from the dispatch queue specified by mdns_querier_set_queue().
957 mdns_querier_has_concluded(mdns_querier_t querier
);
961 * Returns a querier's user-defined ID.
967 * The value returned is the last value set with mdns_querier_set_user_id() before activation.
970 mdns_querier_get_user_id(mdns_querier_t querier
);
974 #define mdns_querier_forget(X) mdns_forget_with_invalidation(X, querier)
975 #define mdns_resolver_forget(X) mdns_forget_with_invalidation(X, resolver)
977 MDNS_ASSUME_NONNULL_END
979 #endif // __MDNS_RESOLVER_H__