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 #include "mdns_internal.h"
18 #include "mdns_resolver.h"
20 #include "mdns_helpers.h"
21 #include "mdns_message.h"
22 #include "mdns_objects.h"
23 #include "mdns_symptoms.h"
25 #include "DNSMessage.h"
26 #include "HTTPUtilities.h"
27 #include <CFNetwork/CFNetworkErrors.h>
28 #include <CoreUtils/CoreUtils.h>
29 #include <ne_session.h>
30 #include <stdatomic.h>
32 //======================================================================================================================
33 // MARK: - Resolver Kind Definition
35 struct mdns_resolver_s
{
36 struct mdns_object_s base
; // Object base.
37 mdns_server_t server_list
; // Dynamic list of servers that implement DNS service.
38 mdns_querier_t querier_list
; // List of active queriers.
39 nw_interface_t interface
; // If non-NULL, interface to use for network traffic.
40 CFMutableArrayRef server_array
; // Array of servers that implement DNS service.
41 char * interface_log_str
; // Logging string for network interface.
42 dispatch_queue_t user_queue
; // User's event queue.
43 mdns_resolver_event_handler_t event_handler
; // User's event handler.
44 uint64_t suspicious_mode_expiry
; // When suspicious mode expires in ticks.
45 dispatch_source_t probe_timer
; // Periodic timer for restarting probe querier.
46 mdns_querier_t probe_querier
; // Querier to detect when DNS service is usable again.
47 uint32_t probe_querier_id
; // ID number of current probe querier.
48 uint32_t initial_dgram_rtx_ms
; // Initial datagram retransmission interval in ms.
49 bool report_symptoms
; // True if this resolver should report symptoms.
50 bool squash_cnames
; // True if this resolver should squash CNAMEs.
51 bool suspicious_mode
; // True if currently in suspicious mode.
52 bool activated
; // True if resolver has been activated.
53 bool invalidated
; // True if resolver has bee invalidated.
54 bool user_activated
; // True if user called activate method.
55 bool force_no_stream_sharing
; // True to force queriers to not share stream sessions.
56 bool cannot_connect
; // True if all usable servers have connection problems.
57 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
58 unsigned int pqw_threshold
; // Threshold value for problematic QTYPE workaround. [1]
63 // 1. If a server don't send prompt responses to queries for problematic QTYPEs (SVCB and HTTPS), then queries for
64 // such QTYPEs will no longer be sent to that server as a workaround. Instead, a NotImp response message will be
65 // fabricated. If the threshold value is zero, the workaround never goes into effect. If the threshold value is
66 // greater than zero, then the value specifies the number of unique QNAME queries that must go without a prompt
67 // response before the workaround goes into effect.
69 MDNS_OBJECT_SUBKIND_DEFINE_ABSTRACT(resolver
);
72 MDNS_UNION_MEMBER(resolver
);
73 MDNS_UNION_MEMBER(normal_resolver
);
74 MDNS_UNION_MEMBER(tcp_resolver
);
75 MDNS_UNION_MEMBER(tls_resolver
);
76 MDNS_UNION_MEMBER(https_resolver
);
77 } mdns_any_resolver_t
__attribute__((__transparent_union__
));
80 (*mdns_resolver_set_provider_name_f
)(mdns_any_resolver_t resolver
, const char *provider_name
);
83 (*mdns_resolver_set_port_f
)(mdns_any_resolver_t resolver
, uint16_t port
);
86 (*mdns_resolver_set_url_path_f
)(mdns_any_resolver_t resolver
, const char *url_path
);
88 typedef nw_parameters_t
89 (*mdns_resolver_get_datagram_params_f
)(mdns_any_resolver_t resolver
, OSStatus
*out_error
);
91 typedef nw_parameters_t
92 (*mdns_resolver_get_stream_params_f
)(mdns_any_resolver_t resolver
, OSStatus
*out_error
);
95 (*mdns_resolver_create_hostname_endpoint_f
)(mdns_any_resolver_t resolver
);
97 typedef const struct mdns_resolver_kind_s
* mdns_resolver_kind_t
;
98 struct mdns_resolver_kind_s
{
99 struct mdns_kind_s base
;
101 mdns_resolver_set_provider_name_f set_provider_name
;
102 mdns_resolver_set_port_f set_port
;
103 mdns_resolver_set_url_path_f set_url_path
;
104 mdns_resolver_get_datagram_params_f get_datagram_params
;
105 mdns_resolver_get_stream_params_f get_stream_params
;
106 mdns_resolver_create_hostname_endpoint_f create_hostname_endpoint
;
107 const char * datagram_protocol_str
;
108 const char * bytestream_protocol_str
;
109 mdns_resolver_type_t type
;
110 uint16_t default_port
;
112 bool needs_edns0_padding
;
114 bool suspicious_reply_defense
;
115 bool no_stream_session_sharing
;
118 #define MDNS_RESOLVER_SUBKIND_DECLARE(NAME) MDNS_DECL_SUBKIND(NAME ## _resolver, resolver)
119 #define MDNS_RESOLVER_SUBKIND_DEFINE(NAME, ...) \
121 _mdns_ ## NAME ## _resolver_finalize(mdns_ ## NAME ## _resolver_t resolver); \
123 static const struct mdns_resolver_kind_s _mdns_ ## NAME ## _resolver_kind = { \
125 .superkind = &_mdns_resolver_kind, \
126 .name = "mdns_" # NAME "_resolver", \
127 .finalize = _mdns_ ## NAME ## _resolver_finalize \
129 .name = # NAME "_resolver", \
130 .type = mdns_resolver_type_ ## NAME, \
134 static mdns_resolver_t \
135 _mdns_ ## NAME ## _resolver_alloc(void) \
137 mdns_resolver_t obj = mdns_resolver_object_alloc(sizeof(struct mdns_ ## NAME ## _resolver_s)); \
138 require_quiet(obj, exit); \
140 const mdns_object_t object = (mdns_object_t)obj; \
141 object->kind = &_mdns_ ## NAME ## _resolver_kind.base; \
146 MDNS_BASE_CHECK(NAME ## _resolver, resolver)
148 #define MDNS_RESOLVER_SERVER_COUNT_MAX 32
150 //======================================================================================================================
151 // MARK: - Normal Resolver Kind Definition
153 // As recommended by libnetwork team, use sockets for UDP.
154 #if !defined(MDNS_USE_NW_CONNECTION_FOR_UDP_INSTEAD_OF_SOCKETS)
155 #define MDNS_USE_NW_CONNECTION_FOR_UDP_INSTEAD_OF_SOCKETS 0
158 MDNS_RESOLVER_SUBKIND_DECLARE(normal
);
160 struct mdns_normal_resolver_s
{
161 struct mdns_resolver_s base
; // Resolver object base.
162 nw_parameters_t udp_params
; // UDP parameters.
163 nw_parameters_t tcp_params
; // TCP parameters.
166 static nw_parameters_t
167 _mdns_normal_resolver_get_datagram_params(mdns_normal_resolver_t resolver
, OSStatus
*out_error
);
169 static nw_parameters_t
170 _mdns_normal_resolver_get_stream_params(mdns_normal_resolver_t resolver
, OSStatus
*out_error
);
172 MDNS_RESOLVER_SUBKIND_DEFINE(normal
,
173 .get_datagram_params
= _mdns_normal_resolver_get_datagram_params
,
174 .get_stream_params
= _mdns_normal_resolver_get_stream_params
,
175 .datagram_protocol_str
= "UDP",
176 .bytestream_protocol_str
= "TCP",
177 .default_port
= 53, // See <https://tools.ietf.org/html/rfc1035#section-4.2>.
178 .suspicious_reply_defense
= true
181 //======================================================================================================================
182 // MARK: - TCP-Only Resolver Kind Definition
184 MDNS_RESOLVER_SUBKIND_DECLARE(tcp
);
186 struct mdns_tcp_resolver_s
{
187 struct mdns_resolver_s base
; // Resolver object base.
188 nw_parameters_t params
; // TCP parameters.
191 static nw_parameters_t
192 _mdns_tcp_resolver_get_stream_params(mdns_tcp_resolver_t resolver
, OSStatus
*out_error
);
194 MDNS_RESOLVER_SUBKIND_DEFINE(tcp
,
195 .get_stream_params
= _mdns_tcp_resolver_get_stream_params
,
196 .bytestream_protocol_str
= "TCP",
197 .default_port
= 53, // See <https://tools.ietf.org/html/rfc1035#section-4.2.2>.
201 //======================================================================================================================
202 // MARK: - TLS Resolver Kind Definition
204 MDNS_RESOLVER_SUBKIND_DECLARE(tls
);
206 struct mdns_tls_resolver_s
{
207 struct mdns_resolver_s base
; // Resolver object base.
208 char * hostname
; // Hostname to use for TLS.
209 nw_parameters_t params
; // TLS parameters.
210 uint16_t port
; // Port to use if no server addresses are specified.
214 _mdns_tls_resolver_set_provider_name(mdns_tls_resolver_t resolver
, const char *provider_name
);
217 _mdns_tls_resolver_set_port(mdns_tls_resolver_t resolver
, uint16_t port
);
219 static nw_parameters_t
220 _mdns_tls_resolver_get_stream_params(mdns_tls_resolver_t resolver
, OSStatus
*out_error
);
223 _mdns_tls_resolver_create_hostname_endpoint(mdns_tls_resolver_t resolver
);
225 MDNS_RESOLVER_SUBKIND_DEFINE(tls
,
226 .set_provider_name
= _mdns_tls_resolver_set_provider_name
,
227 .set_port
= _mdns_tls_resolver_set_port
,
228 .get_stream_params
= _mdns_tls_resolver_get_stream_params
,
229 .create_hostname_endpoint
= _mdns_tls_resolver_create_hostname_endpoint
,
230 .bytestream_protocol_str
= "TLS",
231 .default_port
= 853, // See <https://tools.ietf.org/html/rfc7858#section-3.1>.
233 .needs_edns0_padding
= true
236 //======================================================================================================================
237 // MARK: - HTTPS Resolver Kind Definition
239 MDNS_RESOLVER_SUBKIND_DECLARE(https
);
241 struct mdns_https_resolver_s
{
242 struct mdns_resolver_s base
; // Resolver object base.
243 char * provider_name
; // Hostname to use for HTTPS.
244 char * url_path
; // Path to use for HTTPS queries.
245 nw_parameters_t params
; // HTTPS parameters.
246 uint16_t port
; // Port to use if no server addresses are specified.
250 _mdns_https_resolver_set_provider_name(mdns_https_resolver_t resolver
, const char *provider_name
);
253 _mdns_https_resolver_set_port(mdns_https_resolver_t resolver
, uint16_t port
);
256 _mdns_https_resolver_set_url_path(mdns_https_resolver_t resolver
, const char *url_path
);
258 static nw_parameters_t
259 _mdns_https_resolver_get_stream_params(mdns_https_resolver_t resolver
, OSStatus
*out_error
);
262 _mdns_https_resolver_create_hostname_endpoint(mdns_https_resolver_t resolver
);
264 MDNS_RESOLVER_SUBKIND_DEFINE(https
,
265 .set_provider_name
= _mdns_https_resolver_set_provider_name
,
266 .set_port
= _mdns_https_resolver_set_port
,
267 .set_url_path
= _mdns_https_resolver_set_url_path
,
268 .get_stream_params
= _mdns_https_resolver_get_stream_params
,
269 .create_hostname_endpoint
= _mdns_https_resolver_create_hostname_endpoint
,
270 .bytestream_protocol_str
= "HTTPS",
271 .default_port
= 443, // See <https://tools.ietf.org/html/rfc8484#section-8.1>.
273 .needs_edns0_padding
= true,
274 .needs_zero_ids
= true, // See <https://tools.ietf.org/html/rfc8484#section-4.1>.
275 .no_stream_session_sharing
= true // For DoH, each mdns_session uses an NSURLSessionDataTask.
278 //======================================================================================================================
279 // MARK: - Server Kind Definition
281 #define MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND 1
283 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
284 typedef struct pqw_qname_item_s pqw_qname_item_t
;
286 struct pqw_qname_item_s
{
287 pqw_qname_item_t
* next
; // Next item in list.
288 uint8_t * qname
; // QNAME.
292 pqw_qname_item_t
* qname_list
; // List of unique QNAMEs whose problematic query didn't get a prompt response.
293 unsigned int qname_count
; // Current number QNAMEs on list. [1]
294 unsigned int threshold
; // The maximum number of unique QNAMEs to allow on list.
298 // 1. When the threshold has been reached, problematic QTYPEs will no longer be sent to the server that owns this
303 struct mdns_server_s
{
304 struct mdns_object_s base
; // Object base.
305 mdns_server_t next
; // Next server in list.
306 mdns_session_t shared_stream_session
; // Shared byte-stream connection to server.
307 nw_endpoint_t endpoint
; // Endpoint that represents server's IP address and port.
308 nw_path_evaluator_t path_evaluator
; // Path evaluator for monitoring server's reachability.
309 uint64_t penalty_expiry
; // If currently penalized, time when penalization will end.
310 uint64_t latest_session_start_ticks
; // Latest start time, in ticks, of sessions that got a response.
311 uint64_t last_stream_error_ticks
; // When stream_error_count was last incremented. [1]
312 uint32_t stream_error_count
; // Numer of errors experienced by bytestream sessions. [2,3]
313 unsigned int rank
; // Ordinal rank number of this server.
314 bool usable
; // True if the server is currently potentially usable.
315 bool penalized
; // True if the server is currently penalized.
316 bool stream_lateness
; // True if a bytestream sessions are experiencing lateness.
317 bool reported_unresponsiveness
; // True if an unresponsiveness symptom has been reported.
318 bool uses_default_port
; // True if the endpoint's port is a default port.
319 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND
320 bool mixes_up_responses
; // True if server mixes up A/AAAA and HTTPS/SVCB responses.
322 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
323 bool responds_to_problematics
; // True if server responds to queries with problematic QTYPEs.
324 uint16_t test_query_qtype
; // The QTYPE that should be used for a test query.
325 pqw_info_t
* pqw_info
; // Information about problematic QTYPEs.
330 // 1. last_stream_error_ticks is used to track bursts of errors, which can occur if multiple outstanding queriers
331 // experience the same underlying error at once.
332 // 2. stream_error_count is incremented whenever a bystream session experiences an error, so long as
333 // stream_error_count was last incremented at least one second ago.
334 // 3. stream_error_count is reset to zero whenever an acceptable response is received.
336 MDNS_OBJECT_SUBKIND_DEFINE(server
);
338 // MDNS_SERVER_STREAM_ERROR_COUNT_THRESHOLD is the number of consecutive errors, as tracked by stream_error_count,
339 // that have to be experienced by bytestream sessions to a server, before the server is considered to be
340 // problematic (in the absence of bytestream lateness). In the absence of bytestream lateness, when the threshold
341 // is reached, a cannot-connect event is generated, so value should be greater than one to not overreact to the
342 // case where there's a one-off error and the the subsequent retry is error-free. Three consecutive errors seems
343 // small enough to be reactive to longer-term problems, such as a firewall that blocks connections using TCP
344 // resets, or a bad server certificate, but not too sensitive to transient errors.
345 #define MDNS_SERVER_STREAM_ERROR_COUNT_THRESHOLD 3
347 // MDNS_SERVER_STREAM_ERROR_BURST_WINDOW_SECS is the width of a bytestream session error burst window in seconds.
348 #define MDNS_SERVER_STREAM_ERROR_BURST_WINDOW_SECS 1
350 //======================================================================================================================
351 // MARK: - Delegation
353 OS_CLOSED_ENUM(mdns_delegation_type
, int,
354 mdns_delegation_type_none
= 0, // No delegation.
355 mdns_delegation_type_pid
= 1, // Delegation by PID.
356 mdns_delegation_type_uuid
= 2 // Delegation by UUID.
360 mdns_delegation_type_t type
; // Type of delegation.
362 pid_t pid
; // Delegator's PID if type is mdns_delegation_type_pid.
363 uuid_t uuid
; // Delegator's UUID if type is mdns_delegation_type_uuid.
364 } ident
; // Delegator's identifier.
367 //======================================================================================================================
368 // MARK: - Session Kind Definition
370 OS_CLOSED_ENUM(mdns_session_event
, int,
371 mdns_session_event_null
= 0,
372 mdns_session_event_ready
= 1,
373 mdns_session_event_lateness_warning
= 2,
374 mdns_session_event_terminated
= 3
378 (*mdns_session_handle_event_f
)(mdns_session_t session
, mdns_session_event_t event
, OSStatus error
, void *context
);
381 (*mdns_session_receive_f
)(mdns_session_t session
, dispatch_data_t response
, void *context
);
384 (*mdns_session_finalize_context_f
)(void *context
);
387 mdns_session_handle_event_f handle_event
;
388 mdns_session_receive_f receive
;
389 mdns_session_finalize_context_f finalize_context
;
390 } mdns_session_callbacks_t
;
392 OS_CLOSED_ENUM(mdns_session_state
, int,
393 mdns_session_state_nascent
= 0,
394 mdns_session_state_activated
= 1,
395 mdns_session_state_failed
= 2,
396 mdns_session_state_done
= 3
399 struct mdns_session_s
{
400 struct mdns_object_s base
; // Object base.
401 mdns_session_t next
; // Next session in list.
402 mdns_server_t server
; // Server associated with this session.
403 dispatch_source_t lateness_timer
; // Lateness timer.
404 void * context
; // User object's context for callbacks.
405 const mdns_session_callbacks_t
* callbacks
; // User object's callbacks.
406 uint64_t start_ticks
; // Time, in ticks, when the session was activated.
407 uint64_t last_send_ticks
; // Time, in ticks, of the last send.
408 mdns_session_state_t state
; // Current state.
409 uint32_t lateness_time_ms
; // Time in ms after activation before lateness timer fires.
410 uint32_t receive_count
; // Number of messages received.
411 bool is_stream
; // True if session is bytestream instead of datagram.
412 bool is_ready
; // True if session is ready for sending (while activated).
415 MDNS_OBJECT_SUBKIND_DEFINE_ABSTRACT(session
);
418 MDNS_UNION_MEMBER(session
);
419 MDNS_UNION_MEMBER(connection_session
);
420 MDNS_UNION_MEMBER(udp_socket_session
);
421 MDNS_UNION_MEMBER(url_session
);
422 } mdns_any_session_t
__attribute__((__transparent_union__
));
425 (*mdns_session_initialize_f
)(mdns_any_session_t session
, mdns_resolver_t resolver
, bool need_bytestream
,
426 const mdns_delegation_t
*delegation
, const uint8_t *qname
);
429 (*mdns_session_activate_f
)(mdns_any_session_t session
);
432 (*mdns_session_invalidate_f
)(mdns_any_session_t session
);
435 (*mdns_session_is_ready_f
)(mdns_any_session_t session
);
438 (*mdns_session_send_f
)(mdns_any_session_t session
, dispatch_data_t message
, uint16_t qtype
);
441 (*mdns_session_is_bytestream_f
)(mdns_any_session_t session
);
443 typedef const struct mdns_session_kind_s
* mdns_session_kind_t
;
444 struct mdns_session_kind_s
{
445 struct mdns_kind_s base
;
447 mdns_session_initialize_f initialize
;
448 mdns_session_activate_f activate
;
449 mdns_session_invalidate_f invalidate
;
450 mdns_session_send_f send
;
451 mdns_session_is_bytestream_f is_bytestream_check
;
452 mdns_session_is_ready_f is_ready_check
;
454 bool is_always_ready
;
457 #define MDNS_SESSION_SUBKIND_DECLARE(NAME) MDNS_DECL_SUBKIND(NAME ## _session, session)
458 #define MDNS_SESSION_SUBKIND_DEFINE(NAME, ...) \
460 _mdns_ ## NAME ## _session_finalize(mdns_ ## NAME ## _session_t session); \
463 _mdns_ ## NAME ## _session_initialize(mdns_ ## NAME ## _session_t session, mdns_resolver_t resolver, \
464 bool need_bytestream, const mdns_delegation_t *delegation, const uint8_t *qname); \
467 _mdns_ ## NAME ## _session_activate(mdns_ ## NAME ## _session_t session); \
470 _mdns_ ## NAME ## _session_invalidate(mdns_ ## NAME ## _session_t session); \
473 _mdns_ ## NAME ## _session_send(mdns_ ## NAME ## _session_t session, dispatch_data_t message, uint16_t qtype); \
475 static const struct mdns_session_kind_s _mdns_ ## NAME ## _session_kind = { \
477 .superkind = &_mdns_session_kind, \
478 .name = "mdns_" # NAME "_session", \
479 .finalize = _mdns_ ## NAME ## _session_finalize, \
481 .name = # NAME "_session", \
482 .initialize = _mdns_ ## NAME ## _session_initialize, \
483 .activate = _mdns_ ## NAME ## _session_activate, \
484 .invalidate = _mdns_ ## NAME ## _session_invalidate, \
485 .send = _mdns_ ## NAME ## _session_send, \
489 static mdns_session_t \
490 _mdns_ ## NAME ## _session_alloc(void) \
492 mdns_session_t obj = mdns_session_object_alloc(sizeof(struct mdns_ ## NAME ## _session_s)); \
493 require_quiet(obj, exit); \
495 const mdns_object_t object = (mdns_object_t)obj; \
496 object->kind = &_mdns_ ## NAME ## _session_kind.base; \
501 MDNS_BASE_CHECK(NAME ## _session, session)
503 OS_CLOSED_ENUM(mdns_session_type
, int,
504 mdns_session_type_null
= 0,
505 mdns_session_type_connection
= 1,
506 mdns_session_type_udp_socket
= 2,
507 mdns_session_type_url
= 3
510 //======================================================================================================================
511 // MARK: - Connection Session Kind Definition
513 MDNS_SESSION_SUBKIND_DECLARE(connection
);
515 struct mdns_connection_session_s
{
516 struct mdns_session_s base
; // Session object base.
517 nw_connection_t connection
; // Underlying connection.
518 bool is_bytestream
; // True if the session is bytestream as opposed to datagram.
522 _mdns_connection_session_is_bytestream(mdns_connection_session_t session
);
524 MDNS_SESSION_SUBKIND_DEFINE(connection
,
525 .is_bytestream_check
= _mdns_connection_session_is_bytestream
528 //======================================================================================================================
529 // MARK: - UDP Socket Session Kind Definition
531 // There are currently some performance problems with using connected UDP sockets and flow diverted traffic.
532 // When connecting a UDP socket to a flow diverted destination, the connect() call will return EINPROGRESS.
533 // The problem is that there's ambiguity as to when the socket is actually connected and ready for sending.
534 #if !defined(MDNS_USE_CONNECTED_UDP_SOCKETS)
535 #define MDNS_USE_CONNECTED_UDP_SOCKETS 0
538 MDNS_SESSION_SUBKIND_DECLARE(udp_socket
);
540 struct mdns_udp_socket_session_s
{
541 struct mdns_session_s base
; // Session object base.
542 dispatch_source_t read_source
; // GCD read source for UDP socket.
543 int sock
; // Underlying UDP socket.
544 #if MDNS_USE_CONNECTED_UDP_SOCKETS
545 dispatch_source_t write_source
; // GCD write source for UDP socket. For delayed connections.
546 bool connected
; // True if the UDP socket is connected.
547 bool read_source_suspended
; // True if the GCD read source is suspended;
549 sockaddr_ip server_addr
; // sockaddr containing address of server.
550 socklen_t server_addr_len
; // Length of server sockaddr.
554 #if MDNS_USE_CONNECTED_UDP_SOCKETS
556 _mdns_udp_socket_session_is_ready(mdns_udp_socket_session_t session
);
559 #if MDNS_USE_CONNECTED_UDP_SOCKETS
560 MDNS_SESSION_SUBKIND_DEFINE(udp_socket
,
561 .is_bytestream
= false,
562 .is_ready_check
= _mdns_udp_socket_session_is_ready
565 MDNS_SESSION_SUBKIND_DEFINE(udp_socket
,
566 .is_bytestream
= false,
567 .is_always_ready
= true
571 //======================================================================================================================
572 // MARK: - URL Session Kind Definition
574 MDNS_SESSION_SUBKIND_DECLARE(url
);
576 struct mdns_url_session_s
{
577 struct mdns_session_s base
; // Session object base.
578 nw_endpoint_t url_endpoint
; // Endpoint for URL session.
579 void * http_task
; // HTTP task object.
582 MDNS_SESSION_SUBKIND_DEFINE(url
,
583 .is_bytestream
= true,
584 .is_always_ready
= true
587 //======================================================================================================================
588 // MARK: - Querier Kind Definition
590 struct mdns_querier_s
{
591 struct mdns_object_s base
; // Object base.
592 mdns_querier_t next
; // Next querier in list.
593 mdns_resolver_t resolver
; // Resolver associated with querier.
594 mdns_server_t current_server
; // Current server being used to send datagram queries.
595 dispatch_queue_t user_queue
; // User's queue for invoking response handler.
596 mdns_querier_result_handler_t handler
; // User's result handler.
597 mdns_query_message_t query
; // Query message.
598 dispatch_source_t rtx_timer
; // Timer for scheduling datagram query retransmissions.
599 mdns_session_t dgram_session_list
; // List of datagram sessions.
600 mdns_session_t stream_session_list
; // List of bytestream sessions.
601 dispatch_source_t timeout_timer
; // Time limit timer.
602 char * log_label
; // User-specified UTF-8 prefix label to use for logging.
603 mdns_message_t response
; // Final DNS response.
604 mdns_message_t bad_rcode_response
; // DNS response received with a bad RCODE.
605 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
606 mdns_query_message_t test_query
; // Test query to send while sending problematic QTYPE query.
607 uint32_t test_send_count
; // Total number of test queries sent.
608 uint32_t test_query_resp_bitmap
; // Bitmap for keeping track of test query responses.
610 unsigned int unanswered_query_count
; // Number of timed out dgram queries sent to current_server.
611 uint32_t rtx_interval_ms
; // Current retransmit interval for datagram queries.
612 _Atomic(uint32_t) send_count
; // Total number of queries sent.
613 mdns_query_over_tcp_reason_t over_tcp_reason
; // Reason for using TCP instead of UDP. (For DNS53 only.)
614 uint32_t will_send_bitmap
; // Bitmap for keeping track of servers that we will send to.
615 uint32_t did_send_bitmap
; // Bitmap for keeping track of servers that we did sent to.
616 int32_t time_limit_ms
; // Time limit in milliseconds.
617 uint32_t bad_rcode_bitmap
; // Bitmap for keeping track of servers that sent bad RCODEs.
618 int bad_rcode
; // RCODE of bad_rcode_response.
619 uint32_t user_id
; // User-defined identifier.
620 mdns_querier_result_type_t result_type
; // Type of result the querier concluded with.
621 OSStatus error
; // The fatal error that caused the querier to conclude.
622 mdns_delegation_t delegation
; // Querier's delegation information.
623 bool use_stream
; // True if using bytestream (instead of datagram) session.
624 bool use_shared_stream
; // True if the querier is uses a shared bytestream.
625 bool activated
; // True if the querier has been activated.
626 bool concluded
; // True if the querier has concluded.
627 bool user_activated
; // True if user called activate method.
628 bool response_is_fabricated
; // True if the response is fabricated.
631 check_compile_time((sizeof_field(struct mdns_querier_s
, will_send_bitmap
) * 8) <= MDNS_RESOLVER_SERVER_COUNT_MAX
);
632 check_compile_time((sizeof_field(struct mdns_querier_s
, did_send_bitmap
) * 8) <= MDNS_RESOLVER_SERVER_COUNT_MAX
);
633 check_compile_time((sizeof_field(struct mdns_querier_s
, bad_rcode_bitmap
) * 8) <= MDNS_RESOLVER_SERVER_COUNT_MAX
);
634 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
635 check_compile_time((sizeof_field(struct mdns_querier_s
, test_query_resp_bitmap
) * 8) <= MDNS_RESOLVER_SERVER_COUNT_MAX
);
638 MDNS_OBJECT_SUBKIND_DEFINE(querier
);
640 //======================================================================================================================
641 // MARK: - Local Prototypes
643 static dispatch_queue_t
644 _mdns_resolver_queue(void);
647 _mdns_message_is_query_response_ignoring_id(const uint8_t *msg_ptr
, size_t msg_len
, mdns_query_message_t query
,
650 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND
652 _mdns_message_is_query_response_ignoring_qtype(mdns_message_t msg
, mdns_query_message_t query
, uint16_t *out_qtype
);
656 _mdns_message_is_query_response_ex(const uint8_t *msg_ptr
, size_t msg_len
, mdns_query_message_t query
,
657 uint16_t *out_id
, uint16_t *out_qtype
, bool ignore_qnames
);
660 _mdns_ticks_per_second(void);
663 _mdns_path_to_server_is_usable(nw_path_t path
, bool encrypted_resolver
);
666 _mdns_rank_to_bitmask(const unsigned int rank
);
669 mdns_session_event_to_string(mdns_session_event_t event
);
672 _mdns_ticks_diff(uint64_t t1
, uint64_t t2
);
675 _mdns_ticks_to_whole_seconds(uint64_t ticks
);
678 _mdns_ticks_to_fractional_milliseconds(uint64_t ticks
);
680 static dispatch_source_t
681 _mdns_resolver_create_oneshot_timer(uint32_t time_ms
, unsigned int leeway_percent_numerator
);
684 _mdns_querier_activate_if_ready(mdns_querier_t querier
);
687 _mdns_querier_initiate_send(mdns_querier_t querier
);
690 _mdns_querier_start(mdns_querier_t querier
);
693 _mdns_querier_send_query(mdns_querier_t querier
, mdns_session_t session
);
696 _mdns_querier_get_log_label(mdns_querier_t querier
);
699 _mdns_querier_reset_time_limit(mdns_querier_t querier
);
702 _mdns_querier_handle_no_response(mdns_querier_t querier
);
705 _mdns_querier_set_current_server(mdns_querier_t querier
, mdns_server_t server
);
708 _mdns_querier_get_eligible_server(mdns_querier_t querier
);
711 _mdns_querier_get_unpenalized_eligible_server(mdns_querier_t querier
);
714 _mdns_querier_handle_stream_error(mdns_querier_t querier
, mdns_server_t server
);
717 _mdns_querier_handle_bad_rcode(mdns_querier_t querier
, mdns_message_t response
, int rcode
, mdns_server_t server
);
719 static const uint8_t *
720 _mdns_querier_get_response_ptr_safe(mdns_querier_t querier
);
723 _mdns_querier_get_response_length_safe(mdns_querier_t querier
);
725 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
727 _mdns_querier_set_test_query_got_response(mdns_querier_t querier
, mdns_server_t server
, bool got_response
);
730 _mdns_querier_test_query_got_response(mdns_querier_t querier
, mdns_server_t server
);
734 _mdns_server_has_stream_problems(mdns_server_t server
);
736 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
738 _mdns_server_supports_qtype(mdns_server_t server
, int qtype
);
741 _mdns_server_handle_lack_of_response(mdns_server_t server
, mdns_querier_t querier
);
744 _mdns_server_get_test_query_qtype(mdns_server_t server
);
748 _mdns_session_is_ready(mdns_session_t session
);
751 _mdns_session_send(mdns_session_t session
, dispatch_data_t message
, uint16_t qtype
);
754 _mdns_session_is_bytestream(mdns_session_t session
);
757 _mdns_session_invalidate(mdns_session_t session
);
758 #define mdns_session_forget(X) ForgetCustomEx(X, _mdns_session_invalidate, mdns_release)
761 _mdns_session_set_callbacks(mdns_session_t session
, const mdns_session_callbacks_t
*callbacks
, void *context
);
764 _mdns_session_set_lateness_time(mdns_session_t session
, uint32_t time_ms
);
767 _mdns_session_initialize(mdns_session_t session
, mdns_resolver_t resolver
, bool need_bytestream
,
768 const mdns_delegation_t
*delegation
, const uint8_t *qname
);
771 _mdns_session_activate(mdns_session_t session
);
774 _mdns_common_session_get_server_endpoint(mdns_any_session_t session
);
777 _mdns_common_session_invoke_ready_event_handler(mdns_any_session_t session
);
780 _mdns_common_session_invoke_receive(mdns_any_session_t session
, dispatch_data_t msg
);
783 _mdns_common_session_terminate(mdns_any_session_t session
, OSStatus error
);
786 _mdns_common_session_terminate_async(mdns_any_session_t session
, OSStatus error
);
788 static mdns_resolver_kind_t
789 _mdns_resolver_get_kind(mdns_resolver_t resolver
);
792 _mdns_resolver_get_bytestream_protocol_string(mdns_resolver_t resolver
);
795 _mdns_resolver_get_datagram_protocol_string(mdns_resolver_t resolver
);
798 _mdns_resolver_get_default_port(mdns_any_resolver_t resolver
);
801 _mdns_resolver_is_stream_only(mdns_resolver_t resolver
);
804 _mdns_resolver_needs_edns0_padding(mdns_resolver_t resolver
);
807 _mdns_resolver_needs_zero_ids(mdns_resolver_t resolver
);
810 _mdns_resolver_needs_suspicious_reply_defense(mdns_resolver_t resolver
);
813 _mdns_resolver_no_stream_session_sharing(mdns_resolver_t resolver
);
816 _mdns_resolver_add_server_by_endpoint(mdns_resolver_t resolver
, nw_endpoint_t endpoint
);
819 _mdns_resolver_activate_internal(mdns_resolver_t resolver
);
821 static nw_parameters_t
822 _mdns_resolver_get_stream_params(mdns_resolver_t resolver
, OSStatus
*out_error
);
825 _mdns_resolver_create_hostname_endpoint(mdns_resolver_t resolver
);
827 static nw_parameters_t
828 _mdns_resolver_get_datagram_params(mdns_resolver_t resolver
, OSStatus
*out_error
);
831 _mdns_resolver_deregister_querier(mdns_resolver_t resolver
, mdns_querier_t querier
);
834 _mdns_resolver_register_querier(mdns_resolver_t resolver
, mdns_querier_t querier
, bool force_stream_mode
);
837 _mdns_resolver_session_handle_event(mdns_session_t session
, mdns_session_event_t event
, OSStatus error
, void *context
);
840 _mdns_resolver_session_receive(mdns_session_t session
, dispatch_data_t response
, void *context
);
842 static mdns_session_t
843 _mdns_resolver_create_session(mdns_resolver_t resolver
, mdns_server_t server
, bool need_bytestream
,
844 const mdns_delegation_t
*delegation
, const uint8_t *domain
, OSStatus
*out_error
);
847 _mdns_resolver_get_protocol_log_string(mdns_resolver_t resolver
, bool for_bytestream
);
850 _mdns_resolver_get_interface_log_string(mdns_resolver_t resolver
);
852 static mdns_resolver_type_t
853 _mdns_resolver_get_type(mdns_resolver_t resolver
);
856 _mdns_resolver_log_receive(mdns_resolver_t resolver
, mdns_session_t session
, mdns_message_t message
, bool acceptable
,
857 const char *log_prefix
);
860 _mdns_resolver_handle_stream_error(mdns_resolver_t resolver
, mdns_server_t server
, const char *label
);
863 _mdns_resolver_handle_stream_lateness(mdns_resolver_t resolver
, mdns_server_t server
, uint64_t session_start_ticks
,
867 _mdns_resolver_handle_stream_response(mdns_resolver_t resolver
, mdns_server_t server
);
870 _mdns_resolver_check_for_problematic_servers(mdns_resolver_t resolver
);
873 _mdns_resolver_has_usable_server_without_connection_problems(mdns_resolver_t resolver
);
876 _mdns_resolver_generate_event(mdns_any_resolver_t resolver
, mdns_resolver_event_t event
, xpc_object_t info
);
879 _mdns_resolver_generate_connection_event(mdns_resolver_t resolver
);
882 _mdns_resolver_log_server_problems(mdns_resolver_t resolver
, mdns_server_t server
, const char *label
);
885 _mdns_resolver_uses_encryption(mdns_resolver_t resolver
);
888 _mdns_resolver_start_serverless_queries(mdns_resolver_t resolver
);
891 _mdns_resolver_start_serverless_queries_async(mdns_resolver_t resolver
);
893 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
895 _mdns_resolver_use_problematic_qtype_workaround(mdns_resolver_t resolver
);
898 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND
900 _mdns_resolver_use_mixed_up_responses_workaround(mdns_resolver_t resolver
);
904 _mdns_querier_is_response_acceptable(mdns_querier_t querier
, mdns_message_t response
, bool *out_truncated
,
905 bool *out_suspicious
, int *out_rcode
);
908 _mdns_querier_conclude(mdns_querier_t querier
, mdns_querier_result_type_t result_type
);
911 _mdns_querier_conclude_async(mdns_querier_t querier
, mdns_querier_result_type_t result_type
);
914 _mdns_querier_conclude_with_error(mdns_querier_t querier
, OSStatus error
);
917 _mdns_querier_conclude_with_error_async(mdns_querier_t querier
, OSStatus error
);
920 _mdns_querier_conclude_with_response(mdns_querier_t querier
, mdns_message_t response
);
923 _mdns_querier_conclude_with_response_async(mdns_querier_t querier
, mdns_message_t response
, bool fabricated
);
926 _mdns_querier_conclude_ex(mdns_querier_t querier
, mdns_querier_result_type_t result_type
, OSStatus status
,
927 mdns_message_t response
);
930 _mdns_add_dns_over_bytestream_framer(nw_parameters_t params
);
932 static nw_parameters_t
933 _mdns_create_udp_parameters(OSStatus
*out_error
);
935 static nw_parameters_t
936 _mdns_create_tcp_parameters(OSStatus
*out_error
);
939 _mdns_rcode_is_good(const int rcode
);
941 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND || MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
943 _mdns_qtype_is_problematic(int qtype
);
945 static mdns_message_t
946 _mdns_create_empty_response_for_query(mdns_query_message_t query
, int rcode
, OSStatus
*out_error
);
949 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
950 static mdns_query_message_t
951 _mdns_create_simple_test_query(mdns_query_message_t query
, uint16_t qtype
);
954 _mdns_message_is_adequate_test_query_response(mdns_message_t msg
, mdns_query_message_t query
);
957 _pqw_info_create(unsigned int threshold
);
960 _pqw_info_free(pqw_info_t
*info
);
961 #define _pqw_info_forget(X) ForgetCustom(X, _pqw_info_free)
964 _pqw_info_threshold_reached(const pqw_info_t
*info
);
967 _pqw_info_can_accept_qname(const pqw_info_t
*info
, const uint8_t *qname
);
969 static pqw_qname_item_t
*
970 _pqw_qname_item_create(const uint8_t *qname
, OSStatus
*out_error
);
973 _pqw_qname_item_free(pqw_qname_item_t
*item
);
974 #define _pqw_qname_item_forget(X) ForgetCustom(X, _pqw_qname_item_free)
977 _pqw_qname_list_free(pqw_qname_item_t
*list
);
978 #define _pqw_qname_list_forget(X) ForgetCustom(X, _pqw_qname_list_free)
981 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND
983 (*qtype_test_f
)(int qtype
);
986 _mdns_qtype_is_address_type(int qtype
);
989 //======================================================================================================================
992 MDNS_LOG_CATEGORY_DEFINE(resolver
, "resolver");
994 #define MDNS_RESOLVER_CONNECTION_TIMEOUT_MS 1500
996 //======================================================================================================================
997 // MARK: - Resolver Public Methods
1000 mdns_resolver_create(mdns_resolver_type_t type
, uint32_t interface_index
, OSStatus
*out_error
)
1002 mdns_resolver_t resolver
= NULL
;
1003 mdns_resolver_t obj
;
1006 case mdns_resolver_type_normal
:
1007 obj
= _mdns_normal_resolver_alloc();
1008 require_action_quiet(obj
, exit
, err
= kNoMemoryErr
);
1011 case mdns_resolver_type_tcp
:
1012 obj
= _mdns_tcp_resolver_alloc();
1013 require_action_quiet(obj
, exit
, err
= kNoMemoryErr
);
1016 case mdns_resolver_type_tls
:
1017 obj
= _mdns_tls_resolver_alloc();
1018 require_action_quiet(obj
, exit
, err
= kNoMemoryErr
);
1021 case mdns_resolver_type_https
:
1022 obj
= _mdns_https_resolver_alloc();
1023 require_action_quiet(obj
, exit
, err
= kNoMemoryErr
);
1026 case mdns_resolver_type_null
:
1032 obj
->server_array
= CFArrayCreateMutable(NULL
, 0, &mdns_cfarray_callbacks
);
1033 require_action_quiet(obj
->server_array
, exit
, err
= kNoResourcesErr
);
1035 if (interface_index
!= 0) {
1036 obj
->interface
= nw_interface_create_with_index(interface_index
);
1037 require_action_quiet(obj
->interface
, exit
, err
= kUnknownErr
);
1047 mdns_release_null_safe(obj
);
1051 //======================================================================================================================
1054 mdns_resolver_set_queue(const mdns_resolver_t me
, const dispatch_queue_t queue
)
1056 if (!me
->user_activated
) {
1057 dispatch_retain(queue
);
1058 dispatch_release_null_safe(me
->user_queue
);
1059 me
->user_queue
= queue
;
1063 //======================================================================================================================
1066 mdns_resolver_set_event_handler(const mdns_resolver_t me
, const mdns_resolver_event_handler_t handler
)
1068 if (!me
->user_activated
) {
1069 const mdns_resolver_event_handler_t new_handler
= handler
? Block_copy(handler
) : NULL
;
1070 if (me
->event_handler
) {
1071 Block_release(me
->event_handler
);
1073 me
->event_handler
= new_handler
;
1077 //======================================================================================================================
1080 mdns_resolver_set_provider_name(mdns_resolver_t me
, const char *provider_name
)
1083 require_action_quiet(!me
->user_activated
, exit
, err
= kAlreadyInitializedErr
);
1085 const mdns_resolver_kind_t kind
= _mdns_resolver_get_kind(me
);
1086 if (kind
->set_provider_name
) {
1087 err
= kind
->set_provider_name(me
, provider_name
);
1096 //======================================================================================================================
1099 mdns_resolver_set_port(const mdns_resolver_t me
, const uint16_t port
)
1101 if (likely(!me
->user_activated
)) {
1102 const mdns_resolver_kind_t kind
= _mdns_resolver_get_kind(me
);
1103 if (kind
->set_port
) {
1104 kind
->set_port(me
, port
);
1109 //======================================================================================================================
1112 mdns_resolver_set_url_path(mdns_resolver_t me
, const char *url_path
)
1115 require_action_quiet(!me
->user_activated
, exit
, err
= kAlreadyInitializedErr
);
1117 const mdns_resolver_kind_t kind
= _mdns_resolver_get_kind(me
);
1118 if (kind
->set_url_path
) {
1119 err
= kind
->set_url_path(me
, url_path
);
1128 //======================================================================================================================
1131 mdns_resolver_set_squash_cnames(const mdns_resolver_t me
, const bool enable
)
1133 if (!me
->user_activated
) {
1134 me
->squash_cnames
= enable
? true : false;
1138 //======================================================================================================================
1141 mdns_resolver_enable_symptom_reporting(const mdns_resolver_t me
, const bool enable
)
1143 if (!me
->user_activated
) {
1144 me
->report_symptoms
= enable
? true : false;
1148 //======================================================================================================================
1151 mdns_resolver_add_server_address(mdns_resolver_t me
, mdns_address_t address
)
1154 require_action_quiet(!me
->user_activated
, exit
, err
= kAlreadyInitializedErr
);
1157 memset(&sip
, 0, sizeof(sip
));
1158 const sockaddr_ip
* const addr_sip
= (const sockaddr_ip
*)mdns_address_get_sockaddr(address
);
1159 const int addr_family
= addr_sip
->sa
.sa_family
;
1160 if (addr_family
== AF_INET
) {
1161 sip
.v4
= addr_sip
->v4
;
1162 if (sip
.v4
.sin_port
== 0) {
1163 sip
.v4
.sin_port
= htons(_mdns_resolver_get_default_port(me
));
1165 } else if (addr_family
== AF_INET6
) {
1166 sip
.v6
= addr_sip
->v6
;
1167 if (sip
.v6
.sin6_port
== 0) {
1168 sip
.v6
.sin6_port
= htons(_mdns_resolver_get_default_port(me
));
1174 nw_endpoint_t endpoint
= nw_endpoint_create_address(&sip
.sa
);
1175 require_action_quiet(endpoint
, exit
, err
= kUnknownErr
);
1177 if (me
->interface
) {
1178 nw_endpoint_set_interface(endpoint
, me
->interface
);
1180 err
= _mdns_resolver_add_server_by_endpoint(me
, endpoint
);
1181 nw_forget(&endpoint
);
1187 //======================================================================================================================
1190 mdns_resolver_set_initial_datagram_retransmission_interval(const mdns_resolver_t me
, const uint32_t interval_secs
)
1192 if (!me
->user_activated
) {
1193 if (interval_secs
< (UINT32_MAX
/ kMillisecondsPerSecond
)) {
1194 me
->initial_dgram_rtx_ms
= interval_secs
* kMillisecondsPerSecond
;
1196 me
->initial_dgram_rtx_ms
= UINT32_MAX
;
1201 //======================================================================================================================
1204 mdns_resolver_disable_connection_reuse(const mdns_resolver_t me
, const bool disable
)
1206 if (!me
->user_activated
) {
1207 me
->force_no_stream_sharing
= disable
? true : false;
1211 //======================================================================================================================
1213 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
1214 #define MDNS_RESOLVER_PQW_THRESHOLD_MAX 100
1216 mdns_resolver_enable_problematic_qtype_workaround(const mdns_resolver_t me
, const int threshold
)
1218 require_return(!me
->user_activated
);
1219 if (threshold
> 0) {
1220 me
->pqw_threshold
= Min((unsigned int)threshold
, MDNS_RESOLVER_PQW_THRESHOLD_MAX
);
1222 me
->pqw_threshold
= 0;
1227 //======================================================================================================================
1230 mdns_resolver_activate(mdns_resolver_t me
)
1232 if (!me
->user_activated
) {
1233 me
->user_activated
= true;
1235 dispatch_async(_mdns_resolver_queue(),
1237 _mdns_resolver_activate_internal(me
);
1243 //======================================================================================================================
1246 _mdns_resolver_invalidate_internal(mdns_resolver_t resolver
);
1249 mdns_resolver_invalidate(mdns_resolver_t me
)
1252 dispatch_async(_mdns_resolver_queue(),
1254 _mdns_resolver_invalidate_internal(me
);
1260 _mdns_resolver_invalidate_internal(mdns_resolver_t me
)
1262 require_return(!me
->invalidated
);
1264 me
->invalidated
= true;
1265 dispatch_source_forget(&me
->probe_timer
);
1266 mdns_querier_forget(&me
->probe_querier
);
1267 mdns_server_t server
;
1268 while ((server
= me
->server_list
) != NULL
) {
1269 me
->server_list
= server
->next
;
1270 if (server
->path_evaluator
) {
1271 nw_path_evaluator_cancel(server
->path_evaluator
);
1272 nw_forget(&server
->path_evaluator
);
1274 mdns_session_forget(&server
->shared_stream_session
);
1276 mdns_querier_t querier
;
1277 while ((querier
= me
->querier_list
) != NULL
) {
1278 me
->querier_list
= querier
->next
;
1279 _mdns_querier_conclude(querier
, mdns_querier_result_type_resolver_invalidation
);
1280 mdns_release(querier
);
1282 if (me
->event_handler
) {
1284 dispatch_async(me
->user_queue
,
1286 me
->event_handler(mdns_resolver_event_invalidated
, NULL
);
1292 //======================================================================================================================
1295 mdns_resolver_type_uses_encryption(const mdns_resolver_type_t type
)
1297 // Note: A default case isn't used so that the compiler can catch missing resolver types.
1299 case mdns_resolver_type_null
:
1300 case mdns_resolver_type_normal
:
1301 case mdns_resolver_type_tcp
:
1304 case mdns_resolver_type_tls
:
1305 case mdns_resolver_type_https
:
1311 //======================================================================================================================
1314 mdns_resolver_create_querier(mdns_resolver_t me
, OSStatus
*out_error
)
1317 mdns_querier_t querier
= NULL
;
1318 mdns_querier_t obj
= _mdns_querier_alloc();
1319 require_action_quiet(obj
, exit
, err
= kNoMemoryErr
);
1321 atomic_init(&obj
->send_count
, 0);
1323 mdns_retain(obj
->resolver
);
1325 obj
->query
= mdns_query_message_create(mdns_message_init_option_disable_header_printing
);
1326 require_action_quiet(obj
->query
, exit
, err
= kNoResourcesErr
);
1336 mdns_release_null_safe(obj
);
1340 //======================================================================================================================
1341 // MARK: - Resolver Private Methods
1344 _mdns_resolver_finalize(mdns_resolver_t me
)
1346 nw_forget(&me
->interface
);
1347 ForgetMem(&me
->interface_log_str
);
1348 ForgetCF(&me
->server_array
);
1349 dispatch_forget(&me
->user_queue
);
1350 BlockForget(&me
->event_handler
);
1353 //======================================================================================================================
1356 _mdns_resolver_copy_description(mdns_resolver_t me
, const bool debug
, const bool privacy
)
1358 char * description
= NULL
;
1360 char * dst
= buffer
;
1361 const char * const lim
= &buffer
[countof(buffer
)];
1366 n
= mdns_snprintf_add(&dst
, lim
, "<%s: %p>: ", me
->base
.kind
->name
, me
);
1367 require_quiet(n
>= 0, exit
);
1369 n
= mdns_snprintf_add(&dst
, lim
, "%s ", _mdns_resolver_get_kind(me
)->name
);
1370 require_quiet(n
>= 0, exit
);
1372 if (me
->interface
) {
1373 const char *interface_name
= nw_interface_get_name(me
->interface
);
1374 n
= mdns_snprintf_add(&dst
, lim
, "using interface %s (%u) ",
1375 interface_name
? interface_name
: "???", nw_interface_get_index(me
->interface
));
1376 require_quiet(n
>= 0, exit
);
1378 n
= mdns_snprintf_add(&dst
, lim
, "with servers [");
1379 require_quiet(n
>= 0, exit
);
1381 const char *separator
= "";
1382 const CFIndex count
= CFArrayGetCount(me
->server_array
);
1383 for (CFIndex i
= 0; i
< count
; ++i
) {
1384 const mdns_server_t server
= (mdns_server_t
)CFArrayGetValueAtIndex(me
->server_array
, i
);
1386 char * const server_desc
= mdns_object_copy_description(&server
->base
, false, privacy
);
1387 n
= mdns_snprintf_add(&dst
, lim
, "%s%s", separator
, server_desc
? server_desc
: "<NO SERVER DESC.>");
1388 FreeNullSafe(server_desc
);
1389 require_quiet(n
>= 0, exit
);
1392 n
= mdns_snprintf_add(&dst
, lim
, "]");
1393 require_quiet(n
>= 0, exit
);
1395 description
= strdup(buffer
);
1401 //======================================================================================================================
1403 static mdns_resolver_kind_t
1404 _mdns_resolver_get_kind(const mdns_resolver_t me
)
1406 return (mdns_resolver_kind_t
)me
->base
.kind
;
1409 //======================================================================================================================
1412 _mdns_resolver_get_datagram_protocol_string(const mdns_resolver_t me
)
1414 const mdns_resolver_kind_t kind
= _mdns_resolver_get_kind(me
);
1415 const char * const string
= kind
->datagram_protocol_str
;
1416 return (string
? string
: "???");
1419 //======================================================================================================================
1422 _mdns_resolver_get_bytestream_protocol_string(const mdns_resolver_t me
)
1424 const mdns_resolver_kind_t kind
= _mdns_resolver_get_kind(me
);
1425 const char * const string
= kind
->bytestream_protocol_str
;
1426 return (string
? string
: "???");
1429 //======================================================================================================================
1432 _mdns_resolver_get_default_port(const mdns_any_resolver_t any
)
1434 const mdns_resolver_kind_t kind
= _mdns_resolver_get_kind(any
.resolver
);
1435 return kind
->default_port
;
1438 //======================================================================================================================
1441 _mdns_resolver_is_stream_only(const mdns_resolver_t me
)
1443 const mdns_resolver_kind_t kind
= _mdns_resolver_get_kind(me
);
1444 return kind
->stream_only
;
1447 //======================================================================================================================
1450 _mdns_resolver_needs_edns0_padding(const mdns_resolver_t me
)
1452 const mdns_resolver_kind_t kind
= _mdns_resolver_get_kind(me
);
1453 return kind
->needs_edns0_padding
;
1456 //======================================================================================================================
1459 _mdns_resolver_needs_zero_ids(const mdns_resolver_t me
)
1461 const mdns_resolver_kind_t kind
= _mdns_resolver_get_kind(me
);
1462 return kind
->needs_zero_ids
;
1465 //======================================================================================================================
1468 _mdns_resolver_needs_suspicious_reply_defense(const mdns_resolver_t me
)
1470 const mdns_resolver_kind_t kind
= _mdns_resolver_get_kind(me
);
1471 return kind
->suspicious_reply_defense
;
1474 //======================================================================================================================
1477 _mdns_resolver_no_stream_session_sharing(const mdns_resolver_t me
)
1479 if (me
->force_no_stream_sharing
) {
1482 const mdns_resolver_kind_t kind
= _mdns_resolver_get_kind(me
);
1483 return kind
->no_stream_session_sharing
;
1486 //======================================================================================================================
1489 _mdns_resolver_add_server_by_endpoint(mdns_resolver_t me
, nw_endpoint_t endpoint
)
1492 mdns_server_t server
= NULL
;
1493 const CFIndex server_count
= CFArrayGetCount(me
->server_array
);
1494 require_action_quiet(server_count
< MDNS_RESOLVER_SERVER_COUNT_MAX
, exit
, err
= kCountErr
);
1496 server
= _mdns_server_alloc();
1497 require_action_quiet(server
, exit
, err
= kNoMemoryErr
);
1499 server
->endpoint
= endpoint
;
1500 nw_retain(server
->endpoint
);
1502 const int default_port
= _mdns_resolver_get_default_port(me
);
1503 if ((default_port
!= 0) && (nw_endpoint_get_port(server
->endpoint
) == default_port
)) {
1504 server
->uses_default_port
= true;
1506 server
->rank
= ((unsigned int)server_count
) + 1;
1507 const uint64_t one_hour_ago_ticks
= mach_continuous_time() - (kSecondsPerHour
* _mdns_ticks_per_second());
1508 server
->latest_session_start_ticks
= one_hour_ago_ticks
;
1509 server
->last_stream_error_ticks
= one_hour_ago_ticks
;
1511 CFArrayAppendValue(me
->server_array
, server
);
1515 mdns_release_null_safe(server
);
1519 //======================================================================================================================
1521 #define MDNS_QUERIER_INITIAL_RTX_INTERVAL_DEFAULT_MS 1000
1524 _mdns_resolver_activate_servers(mdns_resolver_t resolver
);
1527 _mdns_resolver_set_up_server_path_evaluator(mdns_resolver_t resolver
, mdns_server_t server
);
1530 _mdns_resolver_activate_internal(const mdns_resolver_t me
)
1532 require_return(!me
->invalidated
&& !me
->activated
);
1534 me
->activated
= true;
1535 if (unlikely(me
->event_handler
&& !me
->user_queue
)) {
1536 os_log_error(_mdns_resolver_log(), "API misuse: an event handler without a queue is useless!");
1537 BlockForget(&me
->event_handler
);
1539 if (me
->initial_dgram_rtx_ms
<= 0) {
1540 me
->initial_dgram_rtx_ms
= MDNS_QUERIER_INITIAL_RTX_INTERVAL_DEFAULT_MS
;
1542 const CFIndex n
= CFArrayGetCount(me
->server_array
);
1544 const nw_endpoint_t endpoint
= _mdns_resolver_create_hostname_endpoint(me
);
1546 _mdns_resolver_add_server_by_endpoint(me
, endpoint
);
1547 nw_release(endpoint
);
1550 _mdns_resolver_activate_servers(me
);
1551 if (_mdns_resolver_is_stream_only(me
)) {
1552 _mdns_resolver_check_for_problematic_servers(me
);
1557 _mdns_resolver_activate_servers(const mdns_resolver_t me
)
1559 mdns_server_t
*ptr
= &me
->server_list
;
1560 const CFIndex n
= CFArrayGetCount(me
->server_array
);
1561 for (CFIndex i
= 0; i
< n
; ++i
) {
1562 const mdns_server_t server
= (mdns_server_t
)CFArrayGetValueAtIndex(me
->server_array
, i
);
1564 // Append server to list.
1565 server
->next
= NULL
;
1567 ptr
= &server
->next
;
1569 // Set up a path evaluator if the server's endpoint is an IP address. The server's usability will be
1570 // generally based on whether the path to the IP address is satisfied. Otherwise, the endpoint is a
1571 // hostname that will be handled by libnetwork, i.e., it will request resolution, then deal with the
1572 // paths of the resulting IP addresses, so mark the server as usable.
1573 if (nw_endpoint_get_type(server
->endpoint
) == nw_endpoint_type_address
) {
1574 _mdns_resolver_set_up_server_path_evaluator(me
, server
);
1576 server
->usable
= true;
1578 os_log(_mdns_resolver_log(), "Server %@ is %{public}susable", server
, server
->usable
? "" : "un");
1583 _mdns_resolver_set_up_server_path_evaluator(const mdns_resolver_t me
, const mdns_server_t server
)
1585 server
->path_evaluator
= nw_path_create_evaluator_for_endpoint(server
->endpoint
, NULL
);
1586 if (unlikely(!server
->path_evaluator
)) {
1587 os_log_error(_mdns_resolver_log(), "Failed to create path evaluator for %@", server
);
1588 server
->usable
= true; // Assume that the server is usable.
1591 // Start the server's path evaluator.
1592 nw_path_evaluator_set_queue(server
->path_evaluator
, _mdns_resolver_queue());
1594 mdns_retain(server
);
1595 nw_path_evaluator_set_update_handler(server
->path_evaluator
, _mdns_resolver_queue(),
1596 ^(nw_path_t updated_path
)
1598 if (_mdns_path_to_server_is_usable(updated_path
, _mdns_resolver_uses_encryption(me
))) {
1599 if (!server
->usable
) {
1600 server
->usable
= true;
1601 os_log(_mdns_resolver_log(), "Server %@ is now usable", server
);
1602 _mdns_resolver_start_serverless_queries(me
);
1605 if (server
->usable
) {
1606 server
->usable
= false;
1607 os_log(_mdns_resolver_log(), "Server %@ is now unusable", server
);
1611 nw_path_evaluator_set_cancel_handler(server
->path_evaluator
,
1614 mdns_release(server
);
1616 nw_path_evaluator_start(server
->path_evaluator
);
1618 nw_path_t path
= nw_path_evaluator_copy_path(server
->path_evaluator
);
1620 if (_mdns_path_to_server_is_usable(path
, _mdns_resolver_uses_encryption(me
))) {
1621 server
->usable
= true;
1627 //======================================================================================================================
1629 static nw_parameters_t
1630 _mdns_resolver_get_datagram_params(mdns_resolver_t me
, OSStatus
*out_error
)
1632 const mdns_resolver_kind_t kind
= _mdns_resolver_get_kind(me
);
1633 if (kind
->get_datagram_params
) {
1634 return kind
->get_datagram_params(me
, out_error
);
1637 *out_error
= kUnsupportedErr
;
1643 //======================================================================================================================
1645 static nw_parameters_t
1646 _mdns_resolver_get_stream_params(mdns_resolver_t me
, OSStatus
*out_error
)
1648 const mdns_resolver_kind_t kind
= _mdns_resolver_get_kind(me
);
1649 if (kind
->get_stream_params
) {
1650 return kind
->get_stream_params(me
, out_error
);
1653 *out_error
= kUnsupportedErr
;
1659 //======================================================================================================================
1661 static nw_endpoint_t
1662 _mdns_resolver_create_hostname_endpoint(mdns_resolver_t me
)
1664 const mdns_resolver_kind_t kind
= _mdns_resolver_get_kind(me
);
1665 if (kind
->create_hostname_endpoint
) {
1666 return kind
->create_hostname_endpoint(me
);
1672 //======================================================================================================================
1675 _mdns_resolver_insert_server(mdns_resolver_t me
, mdns_server_t server
)
1678 for (ptr
= &me
->server_list
; *ptr
; ptr
= &(*ptr
)->next
) {
1679 if ((*ptr
)->penalized
|| ((*ptr
)->rank
) > server
->rank
) {
1683 server
->next
= *ptr
;
1687 //======================================================================================================================
1690 _mdns_resolver_note_responsiveness(const mdns_resolver_t me
, mdns_server_t server
, const bool via_stream
,
1691 const uint64_t session_start_ticks
, const int qtype
)
1693 if (_mdns_ticks_diff(session_start_ticks
, server
->latest_session_start_ticks
) > 0) {
1694 server
->latest_session_start_ticks
= session_start_ticks
;
1696 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
1697 if (!server
->responds_to_problematics
&& _mdns_qtype_is_problematic(qtype
)) {
1698 server
->responds_to_problematics
= true;
1703 if (server
->penalized
) {
1705 for (ptr
= &me
->server_list
; *ptr
; ptr
= &(*ptr
)->next
) {
1706 if (*ptr
== server
) {
1711 *ptr
= server
->next
;
1712 server
->next
= NULL
;
1713 server
->penalized
= false;
1714 os_log_info(_mdns_resolver_log(), "Unpenalizing responsive server %@", server
);
1715 _mdns_resolver_insert_server(me
, server
);
1719 _mdns_resolver_handle_stream_response(me
, server
);
1721 if (me
->report_symptoms
&& server
->reported_unresponsiveness
) {
1722 const nw_endpoint_t endpoint
= server
->endpoint
;
1723 if (nw_endpoint_get_type(endpoint
) == nw_endpoint_type_address
) {
1724 mdns_symptoms_report_responsive_server(nw_endpoint_get_address(endpoint
));
1725 server
->reported_unresponsiveness
= false;
1730 //======================================================================================================================
1733 _mdns_resolver_penalize_server_ex(mdns_resolver_t resolver
, mdns_server_t server
, bool unresponsive
,
1734 mdns_querier_t querier
, uint64_t last_send_ticks
);
1737 _mdns_resolver_penalize_server(const mdns_resolver_t me
, const mdns_server_t server
)
1739 _mdns_resolver_penalize_server_ex(me
, server
, false, NULL
, 0);
1743 _mdns_resolver_penalize_unresponsive_server(const mdns_resolver_t me
, const mdns_server_t server
,
1744 const mdns_querier_t querier
, const uint64_t last_send_ticks
)
1746 _mdns_resolver_penalize_server_ex(me
, server
, true, querier
, last_send_ticks
);
1749 #define MDNS_SERVER_PENALTY_TIME_SECS 60
1752 _mdns_resolver_penalize_server_ex(const mdns_resolver_t me
, const mdns_server_t server
, const bool unresponsive
,
1753 const mdns_querier_t querier
, const uint64_t last_send_ticks
)
1756 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
1757 if (_mdns_resolver_use_problematic_qtype_workaround(me
) && querier
) {
1758 _mdns_server_handle_lack_of_response(server
, querier
);
1761 if (_mdns_ticks_diff(last_send_ticks
, server
->latest_session_start_ticks
) < 0) {
1766 for (ptr
= &me
->server_list
; *ptr
; ptr
= &(*ptr
)->next
) {
1767 if (*ptr
== server
) {
1772 *ptr
= server
->next
;
1773 server
->next
= NULL
;
1774 server
->penalty_expiry
= mach_continuous_time() + (MDNS_SERVER_PENALTY_TIME_SECS
* _mdns_ticks_per_second());
1775 server
->penalized
= true;
1777 ptr
= &(*ptr
)->next
;
1781 os_log_info(_mdns_resolver_log(),
1782 "%{public}sPenalizing server %@ for " StringifyExpansion( MDNS_SERVER_PENALTY_TIME_SECS
) " seconds",
1783 querier
? _mdns_querier_get_log_label(querier
) : "", server
);
1784 if (unresponsive
&& me
->report_symptoms
) {
1785 const nw_endpoint_t endpoint
= server
->endpoint
;
1786 if (nw_endpoint_get_type(endpoint
) == nw_endpoint_type_address
) {
1787 mdns_symptoms_report_unresponsive_server(nw_endpoint_get_address(endpoint
));
1788 server
->reported_unresponsiveness
= true;
1793 //======================================================================================================================
1796 _mdns_server_is_excluded(mdns_server_t server
, uint32_t exclude_bitmap
);
1798 static mdns_server_t
1799 _mdns_resolver_get_server(const mdns_resolver_t me
, const uint32_t exclude_bitmap
)
1801 mdns_server_t server
= me
->server_list
;
1802 if (server
&& !((server
->rank
== 1) && !server
->penalized
&& !_mdns_server_is_excluded(server
, exclude_bitmap
))) {
1803 const uint64_t now
= mach_continuous_time();
1804 mdns_server_t
*ptr
= &me
->server_list
;
1805 while ((server
= *ptr
) != NULL
) {
1807 if (server
->penalized
&& ((diff
= _mdns_ticks_diff(now
, server
->penalty_expiry
)) >= 0)) {
1808 *ptr
= server
->next
;
1809 server
->next
= NULL
;
1810 server
->penalized
= false;
1811 _mdns_resolver_insert_server(me
, server
);
1813 os_log_info(_mdns_resolver_log(), "Unpenalizing server %@ (penalty expired %lld.%03lld seconds ago)",
1814 server
, (long long)_mdns_ticks_to_whole_seconds((uint64_t)diff
),
1815 (long long)_mdns_ticks_to_fractional_milliseconds((uint64_t)diff
));
1817 ptr
= &server
->next
;
1820 for (server
= me
->server_list
; server
; server
= server
->next
) {
1821 if (!_mdns_server_is_excluded(server
, exclude_bitmap
)) {
1830 _mdns_server_is_excluded(const mdns_server_t me
, const uint32_t exclude_bitmap
)
1832 if (!me
->usable
|| (exclude_bitmap
& _mdns_rank_to_bitmask(me
->rank
))) {
1839 //======================================================================================================================
1842 _mdns_resolver_session_handle_event(const mdns_session_t session
, const mdns_session_event_t event
,
1843 const OSStatus error
, void * const context
)
1845 os_log_with_type(_mdns_resolver_log(),
1846 ((event
== mdns_session_event_terminated
) && error
) ? OS_LOG_TYPE_ERROR
: OS_LOG_TYPE_INFO
,
1847 "Resolver session event -- type: %{public}s, error: %{mdns:err}ld",
1848 mdns_session_event_to_string(event
), (long)error
);
1850 const mdns_resolver_t me
= (mdns_resolver_t
)context
;
1852 case mdns_session_event_ready
: {
1853 const uint32_t bitmask
= _mdns_rank_to_bitmask(session
->server
->rank
);
1854 for (mdns_querier_t querier
= me
->querier_list
; querier
; querier
= querier
->next
) {
1855 if (querier
->use_stream
&& (querier
->will_send_bitmap
& bitmask
)) {
1856 _mdns_querier_send_query(querier
, session
);
1861 case mdns_session_event_terminated
: {
1862 mdns_server_t server
;
1863 for (server
= me
->server_list
; server
; server
= server
->next
) {
1864 if (server
->shared_stream_session
== session
) {
1868 require_quiet(server
, exit
);
1870 mdns_session_forget(&server
->shared_stream_session
);
1871 if (error
|| (session
->receive_count
== 0)) {
1872 _mdns_resolver_handle_stream_error(me
, server
, NULL
);
1873 _mdns_resolver_penalize_server(me
, server
);
1875 for (mdns_querier_t querier
= me
->querier_list
; querier
; querier
= querier
->next
) {
1876 if (querier
->use_stream
) {
1877 _mdns_querier_handle_stream_error(querier
, server
);
1882 case mdns_session_event_lateness_warning
:
1883 _mdns_resolver_handle_stream_lateness(me
, session
->server
, session
->start_ticks
, NULL
);
1894 //======================================================================================================================
1897 _mdns_resolver_session_receive(mdns_session_t session
, dispatch_data_t msg_data
, void *context
)
1899 const mdns_message_t msg
= mdns_message_create_with_dispatch_data(msg_data
,
1900 mdns_message_init_option_disable_header_printing
);
1901 require_return(msg
);
1903 const mdns_resolver_t me
= (mdns_resolver_t
)context
;
1904 bool logged_msg
= false;
1905 // The current querier might conclude while traversing the querier list, so to be safe, its next pointer is
1906 // saved at the beginning of the for-loop body.
1907 for (mdns_querier_t next
, querier
= me
->querier_list
; querier
; querier
= next
) {
1908 next
= querier
->next
;
1910 const bool acceptable
= _mdns_querier_is_response_acceptable(querier
, msg
, NULL
, NULL
, &rcode
);
1913 _mdns_resolver_log_receive(me
, session
, msg
, true, _mdns_querier_get_log_label(querier
));
1916 _mdns_resolver_note_responsiveness(me
, session
->server
, _mdns_session_is_bytestream(session
),
1917 session
->start_ticks
, mdns_querier_get_qtype(querier
));
1918 if (_mdns_rcode_is_good(rcode
)) {
1919 _mdns_querier_conclude_with_response(querier
, msg
);
1921 // Note: _mdns_querier_handle_bad_rcode() may or may not conclude the querier.
1922 _mdns_querier_handle_bad_rcode(querier
, msg
, rcode
, session
->server
);
1927 _mdns_resolver_log_receive(me
, session
, msg
, false, NULL
);
1932 //======================================================================================================================
1935 _mdns_resolver_is_in_suspicious_mode(mdns_resolver_t resolver
);
1938 _mdns_resolver_register_querier(mdns_resolver_t me
, mdns_querier_t querier
, bool force_stream_mode
)
1940 require_return_action(!me
->invalidated
,
1941 _mdns_querier_conclude_async(querier
, mdns_querier_result_type_resolver_invalidation
));
1943 if (_mdns_resolver_is_stream_only(me
) || force_stream_mode
) {
1944 querier
->use_stream
= true;
1945 } else if (_mdns_resolver_is_in_suspicious_mode(me
)) {
1946 querier
->use_stream
= true;
1947 querier
->over_tcp_reason
= mdns_query_over_tcp_reason_in_suspicious_mode
;
1949 querier
->use_stream
= false;
1951 querier
->will_send_bitmap
= 0;
1952 querier
->did_send_bitmap
= 0;
1953 if (!querier
->use_stream
|| _mdns_resolver_no_stream_session_sharing(me
)) {
1954 querier
->use_shared_stream
= false;
1956 querier
->use_shared_stream
= true;
1958 mdns_querier_t
*ptr
= &me
->querier_list
;
1960 ptr
= &(*ptr
)->next
;
1964 _mdns_querier_start(querier
);
1968 _mdns_resolver_is_in_suspicious_mode(const mdns_resolver_t me
)
1970 if (_mdns_resolver_needs_suspicious_reply_defense(me
) && me
->suspicious_mode
) {
1972 const uint64_t now
= mach_continuous_time();
1973 if ((diff
= _mdns_ticks_diff(me
->suspicious_mode_expiry
, now
)) >= 0) {
1974 os_log_info(_mdns_resolver_log(),
1975 "Suspicious mode (%lld.%03lld seconds left): forcing query over bytestream",
1976 (long long)_mdns_ticks_to_whole_seconds((uint64_t)diff
),
1977 (long long)_mdns_ticks_to_fractional_milliseconds((uint64_t)diff
));
1980 me
->suspicious_mode
= false;
1986 //======================================================================================================================
1989 _mdns_forget_session_list(mdns_session_t
*list_ptr
);
1992 _mdns_resolver_deregister_querier(mdns_resolver_t me
, mdns_querier_t querier
)
1994 dispatch_source_forget(&querier
->rtx_timer
);
1996 _mdns_forget_session_list(&querier
->dgram_session_list
);
1997 _mdns_forget_session_list(&querier
->stream_session_list
);
1998 mdns_querier_t
*ptr
= &me
->querier_list
;
1999 while (*ptr
&& (*ptr
!= querier
)) {
2000 ptr
= &(*ptr
)->next
;
2003 *ptr
= querier
->next
;
2004 querier
->next
= NULL
;
2005 mdns_release(querier
);
2010 _mdns_forget_session_list(mdns_session_t
* const list_ptr
)
2012 mdns_session_t list
= *list_ptr
;
2015 mdns_session_t session
;
2016 while ((session
= list
) != NULL
) {
2017 list
= session
->next
;
2018 session
->next
= NULL
;
2019 mdns_session_forget(&session
);
2024 //======================================================================================================================
2026 static mdns_session_t
2027 _mdns_resolver_create_session(const mdns_resolver_t me
, const mdns_server_t server
, const bool need_bytestream
,
2028 const mdns_delegation_t
* const delegation
, const uint8_t * const qname
, OSStatus
* const out_error
)
2030 mdns_session_t session
= NULL
;
2032 mdns_session_type_t session_type
;
2033 switch (_mdns_resolver_get_type(me
)) {
2034 case mdns_resolver_type_normal
:
2035 if (!need_bytestream
) {
2036 #if MDNS_USE_NW_CONNECTION_FOR_UDP_INSTEAD_OF_SOCKETS
2037 session_type
= mdns_session_type_connection
;
2039 session_type
= mdns_session_type_udp_socket
;
2042 session_type
= mdns_session_type_connection
;
2046 case mdns_resolver_type_tcp
:
2047 case mdns_resolver_type_tls
:
2048 session_type
= mdns_session_type_connection
;
2051 case mdns_resolver_type_https
:
2052 session_type
= mdns_session_type_url
;
2055 case mdns_resolver_type_null
:
2057 session_type
= mdns_session_type_null
;
2062 switch (session_type
) {
2063 case mdns_session_type_connection
:
2064 obj
= _mdns_connection_session_alloc();
2065 require_action_quiet(obj
, exit
, err
= kNoMemoryErr
);
2068 case mdns_session_type_udp_socket
:
2069 obj
= _mdns_udp_socket_session_alloc();
2070 require_action_quiet(obj
, exit
, err
= kNoMemoryErr
);
2073 case mdns_session_type_url
:
2074 obj
= _mdns_url_session_alloc();
2075 require_action_quiet(obj
, exit
, err
= kNoMemoryErr
);
2078 case mdns_session_type_null
:
2084 obj
->server
= server
;
2085 mdns_retain(obj
->server
);
2087 err
= _mdns_session_initialize(obj
, me
, need_bytestream
, delegation
, qname
);
2088 require_noerr_quiet(err
, exit
);
2090 const mdns_session_kind_t kind
= (mdns_session_kind_t
)obj
->base
.kind
;
2091 obj
->is_stream
= kind
->is_bytestream_check
? kind
->is_bytestream_check(obj
) : kind
->is_bytestream
;
2092 obj
->is_ready
= kind
->is_ready_check
? kind
->is_ready_check(obj
) : kind
->is_always_ready
;
2100 mdns_release_null_safe(obj
);
2104 //======================================================================================================================
2106 #define MDNS_RESOLVER_SUSPICIOUS_MODE_DURATION_SECS 10
2109 _mdns_resolver_got_suspicious_reply(const mdns_resolver_t me
)
2111 const uint64_t duration
= MDNS_RESOLVER_SUSPICIOUS_MODE_DURATION_SECS
* _mdns_ticks_per_second();
2112 me
->suspicious_mode_expiry
= mach_continuous_time() + duration
;
2113 me
->suspicious_mode
= true;
2115 os_log_info(_mdns_resolver_log(), "Got suspicious response, entering suspicious mode for %d seconds",
2116 MDNS_RESOLVER_SUSPICIOUS_MODE_DURATION_SECS
);
2119 //======================================================================================================================
2122 _mdns_resolver_get_protocol_log_string(mdns_resolver_t me
, bool for_bytestream
)
2124 if (for_bytestream
) {
2125 return _mdns_resolver_get_bytestream_protocol_string(me
);
2127 return _mdns_resolver_get_datagram_protocol_string(me
);
2131 //======================================================================================================================
2134 _mdns_resolver_get_interface_log_string(mdns_resolver_t me
)
2136 if (me
->interface
) {
2137 if (!me
->interface_log_str
) {
2138 const char * const if_name
= nw_interface_get_name(me
->interface
);
2139 asprintf(&me
->interface_log_str
, "%s/%u", if_name
? if_name
: "", nw_interface_get_index(me
->interface
));
2141 return (me
->interface_log_str
? me
->interface_log_str
: "???");
2143 return "any interface";
2147 //======================================================================================================================
2149 static mdns_resolver_type_t
2150 _mdns_resolver_get_type(const mdns_resolver_t me
)
2152 return _mdns_resolver_get_kind(me
)->type
;
2155 //======================================================================================================================
2158 _mdns_resolver_log_receive(const mdns_resolver_t me
, const mdns_session_t session
, const mdns_message_t msg
,
2159 const bool acceptable
, const char *log_prefix
)
2161 const size_t msg_len
= mdns_message_get_length(msg
);
2162 os_log(_mdns_resolver_log(),
2163 "%{public}sReceived %{public}sacceptable %zu-byte response from %@ over %{public}s via %{public}s -- "
2164 "%{public,mdns:dnshdr}.*P, %@",
2165 log_prefix
? log_prefix
: "",
2166 acceptable
? "" : "un",
2169 _mdns_resolver_get_protocol_log_string(me
, _mdns_session_is_bytestream(session
)),
2170 _mdns_resolver_get_interface_log_string(me
),
2171 (int)Min(msg_len
, kDNSHeaderLength
), mdns_message_get_byte_ptr(msg
),
2175 //======================================================================================================================
2178 _mdns_resolver_handle_stream_error(const mdns_resolver_t me
, const mdns_server_t server
, const char * const label
)
2180 require_return(_mdns_resolver_is_stream_only(me
));
2182 const uint64_t now_ticks
= mach_continuous_time();
2183 const uint64_t elapsed_ticks
= now_ticks
- server
->last_stream_error_ticks
;
2184 // In case there's a burst of errors, ignore errors outside of the burst window.
2185 // For example, a bunch of pending queriers may experience the same underlying error at once.
2186 if (elapsed_ticks
>= (MDNS_SERVER_STREAM_ERROR_BURST_WINDOW_SECS
* _mdns_ticks_per_second())) {
2187 const bool had_problems
= _mdns_server_has_stream_problems(server
);
2188 server
->last_stream_error_ticks
= now_ticks
;
2189 increment_saturate(server
->stream_error_count
, UINT32_MAX
);
2190 if (!had_problems
&& _mdns_server_has_stream_problems(server
)) {
2191 _mdns_resolver_log_server_problems(me
, server
, label
);
2194 _mdns_resolver_check_for_problematic_servers(me
);
2197 //======================================================================================================================
2200 _mdns_resolver_handle_stream_lateness(const mdns_resolver_t me
, const mdns_server_t server
,
2201 const uint64_t session_start_ticks
, const char * const label
)
2203 require_return(_mdns_resolver_is_stream_only(me
));
2205 if (_mdns_ticks_diff(session_start_ticks
, server
->latest_session_start_ticks
) > 0) {
2206 const bool had_problems
= _mdns_server_has_stream_problems(server
);
2207 server
->stream_lateness
= true;
2208 if (!had_problems
&& _mdns_server_has_stream_problems(server
)) {
2209 _mdns_resolver_log_server_problems(me
, server
, label
);
2211 _mdns_resolver_check_for_problematic_servers(me
);
2215 //======================================================================================================================
2218 _mdns_resolver_handle_stream_response(const mdns_resolver_t me
, const mdns_server_t server
)
2220 require_return(_mdns_resolver_is_stream_only(me
));
2222 const bool had_problems
= _mdns_server_has_stream_problems(server
);
2223 server
->stream_error_count
= 0;
2224 server
->stream_lateness
= false;
2226 os_log(_mdns_resolver_log(), "Cleared stream problems with %{public}s server %@",
2227 _mdns_resolver_get_bytestream_protocol_string(me
), server
);
2229 if (me
->cannot_connect
&& _mdns_resolver_has_usable_server_without_connection_problems(me
)) {
2230 me
->cannot_connect
= false;
2231 dispatch_source_forget(&me
->probe_timer
);
2232 mdns_querier_forget(&me
->probe_querier
);
2233 _mdns_resolver_generate_connection_event(me
);
2234 // Some queriers may have become serverless if they backed off while the probe querier was active, so check
2235 // for serverless queriers, but do it asynchronously in case we're in the middle of processing a response
2236 // for a serverless querier.
2237 _mdns_resolver_start_serverless_queries_async(me
);
2241 //======================================================================================================================
2244 _mdns_resolver_start_probe_querier(mdns_resolver_t resolver
);
2246 #define MDNS_RESOLVER_PROBE_RETRY_INTERVAL_SECS 30
2249 _mdns_resolver_check_for_problematic_servers(const mdns_resolver_t me
)
2251 if (!me
->probe_timer
&& !_mdns_resolver_has_usable_server_without_connection_problems(me
)) {
2252 me
->probe_timer
= dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER
, 0, 0, _mdns_resolver_queue());
2253 require_action_quiet(me
->probe_timer
, exit
,
2254 os_log_error(_mdns_resolver_log(), "Failed to create probe timer"));
2256 dispatch_source_set_timer(me
->probe_timer
,
2257 _dispatch_monotonictime_after_sec(MDNS_RESOLVER_PROBE_RETRY_INTERVAL_SECS
),
2258 MDNS_RESOLVER_PROBE_RETRY_INTERVAL_SECS
* UINT64_C_safe(kNanosecondsPerSecond
),
2259 MDNS_RESOLVER_PROBE_RETRY_INTERVAL_SECS
* UINT64_C_safe(kNanosecondsPerSecond
/ 20));
2260 dispatch_source_set_event_handler(me
->probe_timer
,
2262 _mdns_resolver_start_probe_querier(me
);
2264 dispatch_activate(me
->probe_timer
);
2265 _mdns_resolver_start_probe_querier(me
);
2266 if (!me
->cannot_connect
) {
2267 me
->cannot_connect
= true;
2268 _mdns_resolver_generate_connection_event(me
);
2277 _mdns_resolver_start_probe_querier(const mdns_resolver_t me
)
2279 mdns_querier_forget(&me
->probe_querier
);
2280 me
->probe_querier
= mdns_resolver_create_querier(me
, NULL
);
2281 require_action_quiet(me
->probe_querier
, exit
, os_log_error(_mdns_resolver_log(), "Failed to create probe querier"));
2283 mdns_querier_set_log_label(me
->probe_querier
, "PQ%u", ++me
->probe_querier_id
);
2284 mdns_querier_set_queue(me
->probe_querier
, _mdns_resolver_queue());
2285 const uint8_t * const probe_qname
= (const uint8_t *)"\x5" "apple" "\x3" "com";
2286 mdns_querier_set_query(me
->probe_querier
, probe_qname
, kDNSRecordType_NS
, kDNSClassType_IN
);
2287 mdns_querier_activate(me
->probe_querier
);
2293 //======================================================================================================================
2296 _mdns_resolver_has_usable_server_without_connection_problems(const mdns_resolver_t me
)
2298 for (mdns_server_t server
= me
->server_list
; server
; server
= server
->next
) {
2299 if (server
->usable
&& !_mdns_server_has_stream_problems(server
)) {
2306 //======================================================================================================================
2309 _mdns_resolver_generate_event(const mdns_any_resolver_t any
, const mdns_resolver_event_t event
, const xpc_object_t info
)
2311 const mdns_resolver_t me
= any
.resolver
;
2312 require_quiet(!me
->invalidated
, exit
);
2314 if (me
->event_handler
) {
2317 dispatch_async(me
->user_queue
,
2319 me
->event_handler(event
, info
);
2329 //======================================================================================================================
2332 _mdns_resolver_generate_connection_event(const mdns_resolver_t me
)
2334 const xpc_object_t _Nonnull info
= xpc_dictionary_create(NULL
, NULL
, 0);
2335 xpc_dictionary_set_bool(info
, MDNS_RESOLVER_EVENT_CONNECTION_INFO_KEY_CANNOT_CONNECT
, me
->cannot_connect
);
2336 _mdns_resolver_generate_event(me
, mdns_resolver_event_connection
, info
);
2340 //======================================================================================================================
2343 _mdns_resolver_log_server_problems(const mdns_resolver_t me
, const mdns_server_t server
, const char * const label
)
2345 os_log_error(_mdns_resolver_log(),
2346 "%{public}sHaving stream problems with %{public}s server %@ -- lateness: %{bool}d, error count: %u",
2347 label
? label
: "", _mdns_resolver_get_bytestream_protocol_string(me
), server
, server
->stream_lateness
,
2348 server
->stream_error_count
);
2351 //======================================================================================================================
2354 _mdns_resolver_uses_encryption(const mdns_resolver_t me
)
2356 return mdns_resolver_type_uses_encryption(_mdns_resolver_get_type(me
));
2359 //======================================================================================================================
2362 _mdns_resolver_start_serverless_queries(const mdns_resolver_t me
)
2364 require_return(!me
->invalidated
);
2366 bool have_usable_server
= false;
2367 for (mdns_server_t server
= me
->server_list
; server
; server
= server
->next
) {
2368 if (server
->usable
) {
2369 have_usable_server
= true;
2373 if (have_usable_server
) {
2374 for (mdns_querier_t querier
= me
->querier_list
; querier
; querier
= querier
->next
) {
2375 if (!querier
->current_server
) {
2376 _mdns_querier_start(querier
);
2382 //======================================================================================================================
2385 _mdns_resolver_start_serverless_queries_async(const mdns_resolver_t me
)
2388 dispatch_async(_mdns_resolver_queue(),
2390 _mdns_resolver_start_serverless_queries(me
);
2395 //======================================================================================================================
2397 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
2399 _mdns_resolver_use_problematic_qtype_workaround(const mdns_resolver_t me
)
2401 return (me
->pqw_threshold
> 0);
2405 //======================================================================================================================
2407 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND
2409 _mdns_resolver_use_mixed_up_responses_workaround(const mdns_resolver_t me
)
2411 return (_mdns_resolver_get_type(me
) == mdns_resolver_type_normal
);
2415 //======================================================================================================================
2416 // MARK: - Normal Resolver Private Methods
2419 _mdns_normal_resolver_finalize(mdns_normal_resolver_t me
)
2421 nw_forget(&me
->udp_params
);
2422 nw_forget(&me
->tcp_params
);
2425 //======================================================================================================================
2427 static nw_parameters_t
2428 _mdns_normal_resolver_get_datagram_params(mdns_normal_resolver_t me
, OSStatus
*out_error
)
2431 nw_parameters_t params
= NULL
;
2433 if (!me
->udp_params
) {
2434 me
->udp_params
= _mdns_create_udp_parameters(&err
);
2435 require_noerr_quiet(err
, exit
);
2437 params
= me
->udp_params
;
2447 //======================================================================================================================
2449 static nw_parameters_t
2450 _mdns_normal_resolver_get_stream_params(mdns_normal_resolver_t me
, OSStatus
*out_error
)
2453 nw_parameters_t params
= NULL
;
2455 if (!me
->tcp_params
) {
2456 me
->tcp_params
= _mdns_create_tcp_parameters(&err
);
2457 require_noerr_quiet(err
, exit
);
2459 params
= me
->tcp_params
;
2469 //======================================================================================================================
2470 // MARK: - TCP-Only Resolver Private Methods
2473 _mdns_tcp_resolver_finalize(mdns_tcp_resolver_t me
)
2475 nw_forget(&me
->params
);
2478 //======================================================================================================================
2480 static nw_parameters_t
2481 _mdns_tcp_resolver_get_stream_params(mdns_tcp_resolver_t me
, OSStatus
*out_error
)
2484 nw_parameters_t params
= NULL
;
2486 me
->params
= _mdns_create_tcp_parameters(&err
);
2487 require_noerr_quiet(err
, exit
);
2489 params
= me
->params
;
2499 //======================================================================================================================
2500 // MARK: - TLS Resolver Private Methods
2503 _mdns_tls_resolver_finalize(mdns_tls_resolver_t me
)
2505 ForgetMem(&me
->hostname
);
2506 nw_forget(&me
->params
);
2509 //======================================================================================================================
2512 _mdns_tls_resolver_set_provider_name(mdns_tls_resolver_t me
, const char *provider_name
)
2514 return mdns_replace_string(&me
->hostname
, provider_name
);
2517 //======================================================================================================================
2520 _mdns_tls_resolver_set_port(const mdns_tls_resolver_t me
, const uint16_t port
)
2525 //======================================================================================================================
2527 static nw_parameters_t
2528 _mdns_tls_resolver_create_stream_params(mdns_tls_resolver_t me
, OSStatus
*out_error
);
2530 static nw_parameters_t
2531 _mdns_tls_resolver_get_stream_params(mdns_tls_resolver_t me
, OSStatus
*out_error
)
2534 nw_parameters_t params
= NULL
;
2536 me
->params
= _mdns_tls_resolver_create_stream_params(me
, &err
);
2537 require_noerr_quiet(err
, exit
);
2539 params
= me
->params
;
2549 static nw_parameters_t
2550 _mdns_tls_resolver_create_stream_params(mdns_tls_resolver_t me
, OSStatus
*out_error
)
2553 nw_parameters_t params
= NULL
;
2554 nw_parameters_t obj
;
2556 __block
bool server_name_was_set
= false;
2557 nw_parameters_configure_protocol_block_t configure_tls
= ^(nw_protocol_options_t tls_options
)
2559 const sec_protocol_options_t sec_options
= nw_tls_copy_sec_protocol_options(tls_options
);
2561 sec_protocol_options_set_tls_server_name(sec_options
, me
->hostname
);
2562 sec_protocol_options_set_peer_authentication_required(sec_options
, true);
2563 sec_release(sec_options
);
2564 server_name_was_set
= true;
2567 obj
= nw_parameters_create_secure_tcp(configure_tls
, NW_PARAMETERS_DEFAULT_CONFIGURATION
);
2568 require_action_quiet(obj
, exit
, err
= kNoResourcesErr
);
2569 require_action_quiet(server_name_was_set
, exit
, err
= kUnknownErr
);
2571 obj
= nw_parameters_create_secure_tcp(NW_PARAMETERS_DEFAULT_CONFIGURATION
, NW_PARAMETERS_DEFAULT_CONFIGURATION
);
2572 require_action_quiet(obj
, exit
, err
= kNoResourcesErr
);
2574 nw_parameters_set_indefinite(obj
, false);
2576 err
= _mdns_add_dns_over_bytestream_framer(obj
);
2577 require_noerr_quiet(err
, exit
);
2586 nw_release_null_safe(obj
);
2590 //======================================================================================================================
2592 static nw_endpoint_t
2593 _mdns_tls_resolver_create_hostname_endpoint(mdns_tls_resolver_t me
)
2596 const uint16_t port
= (me
->port
== 0) ? _mdns_resolver_get_default_port(me
) : me
->port
;
2597 return nw_endpoint_create_host_with_numeric_port(me
->hostname
, port
);
2603 //======================================================================================================================
2604 // MARK: - HTTPS Resolver Private Methods
2607 _mdns_https_resolver_finalize(mdns_https_resolver_t me
)
2609 ForgetMem(&me
->provider_name
);
2610 ForgetMem(&me
->url_path
);
2611 nw_forget(&me
->params
);
2614 //======================================================================================================================
2617 _mdns_https_resolver_set_provider_name(mdns_https_resolver_t me
, const char *provider_name
)
2619 return mdns_replace_string(&me
->provider_name
, provider_name
);
2622 //======================================================================================================================
2625 _mdns_https_resolver_set_port(const mdns_https_resolver_t me
, const uint16_t port
)
2630 //======================================================================================================================
2633 _mdns_https_resolver_set_url_path(mdns_https_resolver_t me
, const char *url_path
)
2635 return mdns_replace_string(&me
->url_path
, url_path
);
2638 //======================================================================================================================
2640 static nw_parameters_t
2641 _mdns_https_resolver_create_stream_params(mdns_https_resolver_t me
, OSStatus
*out_error
)
2644 nw_parameters_t params
= NULL
;
2645 nw_parameters_t obj
;
2646 if (me
->provider_name
) {
2647 __block
bool server_name_was_set
= false;
2648 nw_parameters_configure_protocol_block_t configure_tls
= ^(nw_protocol_options_t tls_options
)
2650 const sec_protocol_options_t sec_options
= nw_tls_copy_sec_protocol_options(tls_options
);
2652 sec_protocol_options_set_tls_server_name(sec_options
, me
->provider_name
);
2653 sec_protocol_options_set_peer_authentication_required(sec_options
, true);
2654 sec_protocol_options_add_tls_application_protocol(sec_options
, "h2");
2655 sec_release(sec_options
);
2656 server_name_was_set
= true;
2659 obj
= nw_parameters_create_secure_tcp(configure_tls
, NW_PARAMETERS_DEFAULT_CONFIGURATION
);
2660 require_action_quiet(obj
, exit
, err
= kNoResourcesErr
);
2661 require_action_quiet(server_name_was_set
, exit
, err
= kUnknownErr
);
2663 obj
= nw_parameters_create_secure_tcp(NW_PARAMETERS_DEFAULT_CONFIGURATION
, NW_PARAMETERS_DEFAULT_CONFIGURATION
);
2664 require_action_quiet(obj
, exit
, err
= kNoResourcesErr
);
2667 char *url_string
= NULL
;
2668 asprintf(&url_string
, "https://%s%s", me
->provider_name
, me
->url_path
? me
->url_path
: "");
2669 nw_parameters_set_url(obj
, url_string
);
2670 FreeNullSafe(url_string
);
2672 nw_parameters_set_indefinite(obj
, false);
2681 nw_release_null_safe(obj
);
2685 static nw_parameters_t
2686 _mdns_https_resolver_get_stream_params(mdns_https_resolver_t me
, OSStatus
*out_error
)
2689 nw_parameters_t params
= NULL
;
2691 me
->params
= _mdns_https_resolver_create_stream_params(me
, &err
);
2692 require_noerr_quiet(err
, exit
);
2694 params
= me
->params
;
2704 //======================================================================================================================
2706 static nw_endpoint_t
2707 _mdns_https_resolver_create_hostname_endpoint(mdns_https_resolver_t me
)
2709 if (me
->provider_name
) {
2710 const uint16_t port
= (me
->port
== 0) ? _mdns_resolver_get_default_port(me
) : me
->port
;
2711 return nw_endpoint_create_host_with_numeric_port(me
->provider_name
, port
);
2717 //======================================================================================================================
2718 // MARK: - Server Private Methods
2721 _mdns_server_finalize(mdns_server_t me
)
2723 nw_forget(&me
->endpoint
);
2724 nw_forget(&me
->path_evaluator
);
2725 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
2726 _pqw_info_forget(&me
->pqw_info
);
2730 //======================================================================================================================
2733 _mdns_server_copy_description(mdns_server_t me
, const bool debug
, const bool privacy
)
2735 char * description
= NULL
;
2737 char * dst
= buffer
;
2738 const char * const lim
= &buffer
[countof(buffer
)];
2743 n
= mdns_snprintf_add(&dst
, lim
, "<%s: %p>: ", me
->base
.kind
->name
, me
);
2744 require_quiet(n
>= 0, exit
);
2748 if (nw_endpoint_get_type(me
->endpoint
) == nw_endpoint_type_address
) {
2749 const char *str
= NULL
;
2750 const struct sockaddr
* const sa
= nw_endpoint_get_address(me
->endpoint
);
2751 const int family
= sa
->sa_family
;
2752 if ((family
== AF_INET
) || (family
== AF_INET6
)) {
2753 n
= mdns_print_obfuscated_ip_address(strbuf
, sizeof(strbuf
), sa
);
2759 n
= mdns_snprintf_add(&dst
, lim
, "%s", str
);
2760 require_quiet(n
>= 0, exit
);
2762 const char * const version
= (family
== AF_INET
) ? "4" : ((family
== AF_INET6
) ? "6" : "?");
2763 n
= mdns_snprintf_add(&dst
, lim
, "<IPv%s#%u>", version
, me
->rank
);
2764 require_quiet(n
>= 0, exit
);
2767 const char *str
= NULL
;
2768 const char *hostname
= nw_endpoint_get_hostname(me
->endpoint
);
2770 n
= DNSMessagePrintObfuscatedString(strbuf
, sizeof(strbuf
), hostname
);
2776 n
= mdns_snprintf_add(&dst
, lim
, "%s", str
);
2777 require_quiet(n
>= 0, exit
);
2779 n
= mdns_snprintf_add(&dst
, lim
, "<H#%u>", me
->rank
);
2780 require_quiet(n
>= 0, exit
);
2783 if (!me
->uses_default_port
) {
2784 n
= mdns_snprintf_add(&dst
, lim
, ":%d", nw_endpoint_get_port(me
->endpoint
));
2785 require_quiet(n
>= 0, exit
);
2788 const char *hostname
= nw_endpoint_get_hostname(me
->endpoint
);
2790 hostname
= "<unknown>";
2792 n
= mdns_snprintf_add(&dst
, lim
, "%s", hostname
);
2793 require_quiet(n
>= 0, exit
);
2795 if (!me
->uses_default_port
) {
2796 const char *sep
= ":";
2797 if (nw_endpoint_get_type(me
->endpoint
) == nw_endpoint_type_address
) {
2798 const struct sockaddr
* const sa
= nw_endpoint_get_address(me
->endpoint
);
2799 if (sa
->sa_family
== AF_INET6
) {
2803 n
= mdns_snprintf_add(&dst
, lim
, "%s%d", sep
, nw_endpoint_get_port(me
->endpoint
));
2804 require_quiet(n
>= 0, exit
);
2807 description
= strdup(buffer
);
2813 //======================================================================================================================
2816 _mdns_server_has_stream_problems(const mdns_server_t me
)
2818 return (me
->stream_lateness
|| (me
->stream_error_count
>= MDNS_SERVER_STREAM_ERROR_COUNT_THRESHOLD
));
2821 //======================================================================================================================
2823 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND || MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
2825 _mdns_server_supports_qtype(const mdns_server_t me
, const int qtype
)
2827 if (_mdns_qtype_is_problematic(qtype
)) {
2828 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND
2829 if (me
->mixes_up_responses
) {
2833 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
2834 if (!me
->responds_to_problematics
) {
2835 const pqw_info_t
* const info
= me
->pqw_info
;
2836 if (info
&& _pqw_info_threshold_reached(info
)) {
2846 //======================================================================================================================
2848 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
2850 _mdns_server_handle_lack_of_response(const mdns_server_t me
, const mdns_querier_t querier
)
2852 require_return(!me
->responds_to_problematics
);
2853 const int qtype
= mdns_querier_get_qtype(querier
);
2854 if (!_mdns_qtype_is_problematic(qtype
) || !_mdns_querier_test_query_got_response(querier
, me
)) {
2857 if (!me
->pqw_info
) {
2858 me
->pqw_info
= _pqw_info_create(querier
->resolver
->pqw_threshold
);
2859 require_return_action(me
->pqw_info
, os_log_error(_mdns_resolver_log(),
2860 "%{public}sFailed to allocate memory for PQW info", _mdns_querier_get_log_label(querier
)));
2862 pqw_info_t
* const info
= me
->pqw_info
;
2863 const uint8_t * const qname
= mdns_querier_get_qname(querier
);
2864 if (_pqw_info_can_accept_qname(info
, qname
)) {
2865 if (info
->qname_count
< (info
->threshold
- 1)) {
2866 OSStatus create_err
;
2867 pqw_qname_item_t
*item
= _pqw_qname_item_create(qname
, &create_err
);
2868 require_return_action(item
, os_log_error(_mdns_resolver_log(),
2869 "%{public}sFailed to create PQW qname item: %{mdns:err}ld",
2870 _mdns_querier_get_log_label(querier
), (long)create_err
));
2872 item
->next
= info
->qname_list
;
2873 info
->qname_list
= item
;
2874 ++info
->qname_count
;
2876 _pqw_qname_list_forget(&info
->qname_list
);
2877 info
->qname_count
= info
->threshold
;
2879 os_log(_mdns_resolver_log(),
2880 "%{public}sNo response (%u/%u) from server %@ for qtype %{mdns:rrtype}d",
2881 _mdns_querier_get_log_label(querier
), info
->qname_count
, info
->threshold
, me
, qtype
);
2885 //======================================================================================================================
2888 _mdns_server_get_test_query_qtype(const mdns_server_t me
)
2890 if (me
->test_query_qtype
== 0) {
2891 uint16_t qtype
= kDNSRecordType_A
;
2892 if (nw_endpoint_get_type(me
->endpoint
) == nw_endpoint_type_address
) {
2893 const struct sockaddr
* const sa
= nw_endpoint_get_address(me
->endpoint
);
2894 if (sa
->sa_family
== AF_INET6
) {
2895 qtype
= kDNSRecordType_AAAA
;
2898 me
->test_query_qtype
= qtype
;
2900 return me
->test_query_qtype
;
2902 #endif // MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
2904 //======================================================================================================================
2905 // MARK: - Session Private Methods
2908 _mdns_session_finalize(mdns_session_t me
)
2910 mdns_forget(&me
->server
);
2914 //======================================================================================================================
2917 _mdns_session_copy_description(mdns_session_t me
, const bool debug
, __unused
const bool privacy
)
2919 char * description
= NULL
;
2921 char * dst
= buffer
;
2922 const char * const lim
= &buffer
[countof(buffer
)];
2927 n
= mdns_snprintf_add(&dst
, lim
, "<%s: %p>: ", me
->base
.kind
->name
, me
);
2928 require_quiet(n
>= 0, exit
);
2930 description
= strdup(buffer
);
2936 //======================================================================================================================
2939 _mdns_session_invalidate_internal(mdns_session_t session
);
2942 _mdns_session_invalidate(mdns_session_t me
)
2944 // Set the state to done to prevent any further callback invocations.
2945 me
->state
= mdns_session_state_done
;
2947 dispatch_async(_mdns_resolver_queue(),
2949 _mdns_session_invalidate_internal(me
);
2950 if (me
->callbacks
->finalize_context
) {
2951 me
->callbacks
->finalize_context(me
->context
);
2959 _mdns_session_invalidate_internal(const mdns_session_t me
)
2961 dispatch_source_forget(&me
->lateness_timer
);
2962 const mdns_session_kind_t kind
= (mdns_session_kind_t
)me
->base
.kind
;
2963 if (kind
->invalidate
) {
2964 kind
->invalidate(me
);
2968 //======================================================================================================================
2971 _mdns_session_is_ready(const mdns_session_t me
)
2973 return ((me
->state
== mdns_session_state_activated
) && me
->is_ready
);
2976 //======================================================================================================================
2979 _mdns_session_initialize(const mdns_session_t me
, const mdns_resolver_t resolver
, const bool need_bytestream
,
2980 const mdns_delegation_t
* const delegation
, const uint8_t * const qname
)
2982 const mdns_session_kind_t kind
= (mdns_session_kind_t
)me
->base
.kind
;
2983 if (kind
->initialize
) {
2984 return kind
->initialize(me
, resolver
, need_bytestream
, delegation
, qname
);
2990 //======================================================================================================================
2993 _mdns_session_activate(const mdns_session_t me
)
2995 require_return(me
->state
== mdns_session_state_nascent
);
2998 if (me
->lateness_time_ms
> 0) {
2999 me
->lateness_timer
= _mdns_resolver_create_oneshot_timer(me
->lateness_time_ms
, 5);
3000 require_action_quiet(me
->lateness_timer
, exit
, err
= kNoResourcesErr
);
3002 dispatch_source_set_event_handler(me
->lateness_timer
,
3004 dispatch_source_forget(&me
->lateness_timer
);
3005 if (me
->state
== mdns_session_state_activated
) {
3006 if (me
->callbacks
->handle_event
) {
3007 me
->callbacks
->handle_event(me
, mdns_session_event_lateness_warning
, kNoErr
, me
->context
);
3011 dispatch_activate(me
->lateness_timer
);
3013 const uint64_t now_ticks
= mach_continuous_time();
3014 me
->start_ticks
= now_ticks
;
3015 me
->last_send_ticks
= now_ticks
- (kSecondsPerHour
* _mdns_ticks_per_second());
3016 const mdns_session_kind_t kind
= (mdns_session_kind_t
)me
->base
.kind
;
3017 if (kind
->activate
) {
3018 err
= kind
->activate(me
);
3019 require_noerr_quiet(err
, exit
);
3021 me
->state
= mdns_session_state_activated
;
3026 me
->state
= mdns_session_state_failed
;
3027 _mdns_common_session_terminate_async(me
, err
);
3031 //======================================================================================================================
3034 _mdns_session_send(const mdns_session_t me
, const dispatch_data_t msg
, const uint16_t qtype
)
3036 if (me
->state
== mdns_session_state_activated
) {
3037 me
->last_send_ticks
= mach_continuous_time();
3038 const mdns_session_kind_t kind
= (mdns_session_kind_t
)me
->base
.kind
;
3040 kind
->send(me
, msg
, qtype
);
3045 //======================================================================================================================
3048 _mdns_session_is_bytestream(const mdns_session_t me
)
3050 return me
->is_stream
;
3053 //======================================================================================================================
3056 _mdns_session_set_callbacks(mdns_session_t me
, const mdns_session_callbacks_t
* const callbacks
, void * const context
)
3058 if (me
->state
== mdns_session_state_nascent
) {
3059 me
->context
= context
;
3060 me
->callbacks
= callbacks
;
3064 //======================================================================================================================
3067 _mdns_session_set_lateness_time(const mdns_session_t me
, uint32_t time_ms
)
3069 require_return(me
->state
== mdns_session_state_nascent
);
3070 me
->lateness_time_ms
= time_ms
;
3073 //======================================================================================================================
3076 _mdns_session_finalize_context_with_release(void * const context
)
3078 mdns_release((mdns_object_t
)context
);
3081 //======================================================================================================================
3082 // MARK: - Session Common Subkind Methods
3084 static nw_endpoint_t
3085 _mdns_common_session_get_server_endpoint(const mdns_any_session_t any
)
3087 const mdns_session_t me
= any
.session
;
3088 return me
->server
->endpoint
;
3091 //======================================================================================================================
3094 _mdns_common_session_invoke_ready_event_handler(const mdns_any_session_t any
)
3096 const mdns_session_t me
= any
.session
;
3097 if ((me
->state
== mdns_session_state_activated
) && !me
->is_ready
) {
3098 me
->is_ready
= true;
3099 if (me
->callbacks
->handle_event
) {
3100 me
->callbacks
->handle_event(me
, mdns_session_event_ready
, kNoErr
, me
->context
);
3105 //======================================================================================================================
3108 _mdns_common_session_invoke_receive(const mdns_any_session_t any
, const dispatch_data_t msg
)
3110 const mdns_session_t me
= any
.session
;
3111 if (me
->state
== mdns_session_state_activated
) {
3112 dispatch_source_forget(&me
->lateness_timer
);
3113 increment_saturate(me
->receive_count
, UINT32_MAX
);
3114 if (me
->callbacks
->receive
) {
3115 me
->callbacks
->receive(me
, msg
, me
->context
);
3120 //======================================================================================================================
3123 _mdns_common_session_terminate(const mdns_any_session_t any
, const OSStatus error
)
3125 const mdns_session_t me
= any
.session
;
3126 if (me
->state
!= mdns_session_state_done
) {
3127 _mdns_session_invalidate_internal(me
);
3128 me
->state
= mdns_session_state_done
;
3129 if (me
->callbacks
->handle_event
) {
3130 me
->callbacks
->handle_event(me
, mdns_session_event_terminated
, error
, me
->context
);
3135 //======================================================================================================================
3138 _mdns_common_session_terminate_async(const mdns_any_session_t any
, const OSStatus error
)
3140 const mdns_session_t me
= any
.session
;
3142 dispatch_async(_mdns_resolver_queue(),
3144 _mdns_common_session_terminate(me
, error
);
3149 //======================================================================================================================
3150 // MARK: - Connection Session Private Methods
3153 _mdns_connection_session_finalize(__unused
const mdns_connection_session_t me
)
3158 //======================================================================================================================
3160 static nw_endpoint_t
3161 _mdns_create_domain_attributed_endpoint(nw_endpoint_t original_endpoint
, const uint8_t *hostname
, OSStatus
*out_error
);
3164 _mdns_connection_session_initialize(const mdns_connection_session_t me
, const mdns_resolver_t resolver
,
3165 const bool need_bytestream
, const mdns_delegation_t
* const delegation
, const uint8_t * const qname
)
3168 nw_parameters_t params_alt
= NULL
;
3169 nw_endpoint_t server_endpoint_alt
= NULL
;
3170 nw_parameters_t params
;
3171 if (_mdns_resolver_is_stream_only(resolver
) || need_bytestream
) {
3172 params
= _mdns_resolver_get_stream_params(resolver
, &err
);
3173 require_noerr_quiet(err
, exit
);
3175 me
->is_bytestream
= true;
3177 params
= _mdns_resolver_get_datagram_params(resolver
, &err
);
3178 require_noerr_quiet(err
, exit
);
3180 me
->is_bytestream
= false;
3182 if (delegation
&& ((delegation
->type
== mdns_delegation_type_pid
) ||
3183 (delegation
->type
== mdns_delegation_type_uuid
))) {
3184 params_alt
= nw_parameters_copy(params
);
3185 require_action_quiet(params_alt
, exit
, err
= kNoResourcesErr
);
3187 if (delegation
->type
== mdns_delegation_type_pid
) {
3188 nw_parameters_set_pid(params_alt
, delegation
->ident
.pid
);
3190 nw_parameters_set_e_proc_uuid(params_alt
, delegation
->ident
.uuid
);
3192 params
= params_alt
;
3194 nw_endpoint_t server_endpoint
= _mdns_common_session_get_server_endpoint(me
);
3195 if (__builtin_available(macOS
10.16, iOS
14.0, watchOS
7.0, tvOS
14.0, *)) {
3197 OSStatus create_err
;
3198 server_endpoint_alt
= _mdns_create_domain_attributed_endpoint(server_endpoint
, qname
, &create_err
);
3199 if (likely(server_endpoint_alt
)) {
3200 server_endpoint
= server_endpoint_alt
;
3202 os_log_error(_mdns_resolver_log(),
3203 "Failed to create domain-attributed endpoint for %@: %{mdns:err}ld",
3204 server_endpoint
, (long)create_err
);
3208 me
->connection
= nw_connection_create(server_endpoint
, params
);
3209 require_action_quiet(me
->connection
, exit
, err
= kNoResourcesErr
);
3212 nw_forget(¶ms_alt
);
3213 nw_forget(&server_endpoint_alt
);
3217 static nw_endpoint_t
3218 _mdns_create_domain_attributed_endpoint(const nw_endpoint_t original_endpoint
, const uint8_t * const domain
,
3219 OSStatus
*out_error
)
3222 nw_endpoint_t result
= NULL
;
3223 const struct sockaddr
* const sa
= nw_endpoint_get_address(original_endpoint
);
3224 require_action_quiet(sa
, exit
, err
= kTypeErr
);
3226 nw_endpoint_t endpoint
= nw_endpoint_create_address(sa
);
3227 require_action_quiet(endpoint
, exit
, err
= kNoResourcesErr
);
3229 char domain_str
[kDNSServiceMaxDomainName
];
3230 err
= DomainNameToString(domain
, NULL
, domain_str
, NULL
);
3231 require_noerr_quiet(err
, exit
);
3233 const uint16_t port
= nw_endpoint_get_port(endpoint
);
3234 nw_endpoint_t parent
= nw_endpoint_create_host_with_numeric_port(domain_str
, port
);
3235 require_action_quiet(parent
, exit
, err
= kNoResourcesErr
);
3237 if (__builtin_available(macOS
10.16, iOS
14.0, watchOS
7.0, tvOS
14.0, *)) {
3238 nw_endpoint_set_parent_endpoint(endpoint
, parent
, false);
3245 nw_forget(&endpoint
);
3252 //======================================================================================================================
3255 _mdns_connection_session_schedule_receive(mdns_connection_session_t session
);
3258 _mdns_connection_session_activate(const mdns_connection_session_t me
)
3261 nw_connection_set_queue(me
->connection
, _mdns_resolver_queue());
3262 nw_connection_set_state_changed_handler(me
->connection
,
3263 ^(nw_connection_state_t state
, __unused nw_error_t error
)
3265 if (likely(me
->connection
)) {
3266 os_log_debug(_mdns_resolver_log(), "Connection state changed to %s for connection %@",
3267 nw_connection_state_to_string(state
), me
->connection
);
3268 if (state
== nw_connection_state_ready
) {
3269 _mdns_common_session_invoke_ready_event_handler(me
);
3270 } else if (state
== nw_connection_state_failed
) {
3271 _mdns_common_session_terminate(me
, kConnectionErr
);
3274 if (state
== nw_connection_state_cancelled
) {
3278 nw_connection_start(me
->connection
);
3279 _mdns_connection_session_schedule_receive(me
);
3284 _mdns_connection_session_schedule_receive(const mdns_connection_session_t me
)
3286 nw_connection_receive_message(me
->connection
,
3287 ^(dispatch_data_t msg
, nw_content_context_t context
, __unused
bool is_complete
, nw_error_t error
)
3289 if (likely(me
->connection
)) {
3291 _mdns_common_session_invoke_receive(me
, msg
);
3293 const bool final
= (context
&& nw_content_context_get_is_final(context
)) ? true : false;
3294 if (final
|| error
) {
3295 _mdns_common_session_terminate(me
, error
? kConnectionErr
: kNoErr
);
3297 _mdns_connection_session_schedule_receive(me
);
3303 //======================================================================================================================
3306 _mdns_connection_session_invalidate(const mdns_connection_session_t me
)
3308 if (me
->connection
) {
3309 nw_connection_cancel(me
->connection
);
3310 nw_forget(&me
->connection
);
3314 //======================================================================================================================
3317 _mdns_connection_session_send(const mdns_connection_session_t me
, const dispatch_data_t msg
, const uint16_t qtype
)
3319 os_log_debug(_mdns_resolver_log(), "Sending message on connection %@", me
->connection
);
3321 __block nw_activity_t activity
= NULL
;
3322 if (qtype
== kDNSRecordType_A
) {
3323 activity
= nw_activity_create(kDNSActivityDomain
, kDNSActivityLabelUnicastAQuery
);
3324 } else if (qtype
== kDNSRecordType_AAAA
) {
3325 activity
= nw_activity_create(kDNSActivityDomain
, kDNSActivityLabelUnicastAAAAQuery
);
3328 nw_connection_start_activity(me
->connection
, activity
);
3330 nw_connection_send(me
->connection
, msg
, NW_CONNECTION_DEFAULT_MESSAGE_CONTEXT
, true,
3331 ^(const nw_error_t error
)
3334 if (me
->connection
) {
3335 nw_connection_end_activity(me
->connection
, activity
);
3337 nw_release(activity
);
3339 if (likely(me
->connection
) && error
) {
3340 _mdns_common_session_terminate(me
, kConnectionErr
);
3345 //======================================================================================================================
3348 _mdns_connection_session_is_bytestream(const mdns_connection_session_t me
)
3350 return me
->is_bytestream
;
3353 //======================================================================================================================
3354 // MARK: - UDP Socket Session Private Methods
3357 _mdns_udp_socket_session_finalize(const mdns_udp_socket_session_t me
)
3359 _mdns_socket_forget(&me
->sock
);
3362 //======================================================================================================================
3365 _mdns_bind_ipv6_socket_to_random_port(const int sock
);
3368 _mdns_udp_socket_session_initialize(const mdns_udp_socket_session_t me
, const mdns_resolver_t resolver
,
3369 __unused
const bool need_bytestream
, const mdns_delegation_t
* const delegation
, const uint8_t * const qname
)
3372 int sock
= kInvalidSocketRef
;
3373 const struct sockaddr
*dst
= nw_endpoint_get_address(_mdns_common_session_get_server_endpoint(me
));
3374 require_action_quiet((dst
->sa_family
== AF_INET
) || (dst
->sa_family
== AF_INET6
), exit
, err
= kTypeErr
);
3376 #if !MDNS_USE_CONNECTED_UDP_SOCKETS
3377 struct sockaddr_in dst_ipv4
;
3378 if (dst
->sa_family
== AF_INET6
) {
3379 const struct sockaddr_in6
* const sin6
= (const struct sockaddr_in6
*)dst
;
3380 if (IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
) || IN6_IS_ADDR_V4COMPAT(&sin6
->sin6_addr
)) {
3381 memset(&dst_ipv4
, 0, sizeof(dst_ipv4
));
3382 dst_ipv4
.sin_family
= AF_INET
;
3383 SIN_LEN_SET(&dst_ipv4
);
3384 dst_ipv4
.sin_port
= sin6
->sin6_port
;
3385 memcpy(&dst_ipv4
.sin_addr
.s_addr
, &sin6
->sin6_addr
.s6_addr
[12], 4);
3386 dst
= (const struct sockaddr
*)&dst_ipv4
;
3390 const bool ipv4
= (dst
->sa_family
== AF_INET
);
3391 sock
= socket(ipv4
? AF_INET
: AF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
);
3392 err
= map_socket_creation_errno(sock
);
3393 require_noerr_quiet(err
, exit
);
3395 #define _do_setsockopt(SOCK, LEVEL, NAME, VALUE_PTR, VALUE_LEN) \
3397 int opt_err = setsockopt(SOCK, LEVEL, NAME, VALUE_PTR, (socklen_t)(VALUE_LEN)); \
3398 opt_err = map_socket_noerr_errno(SOCK, opt_err); \
3399 if (unlikely(opt_err)) { \
3400 os_log_error(_mdns_resolver_log(), \
3401 "setsockopt() for " # LEVEL "/" # NAME " failed %{darwin.errno}d", opt_err); \
3406 // Ensure that socket binds to a random port.
3408 _do_setsockopt(sock
, SOL_SOCKET
, SO_RANDOMPORT
, &on
, sizeof(on
));
3410 // Workaround for SO_RANDOMPORT not working for UDP/IPv6.
3411 _mdns_bind_ipv6_socket_to_random_port(sock
);
3413 _do_setsockopt(sock
, SOL_SOCKET
, SO_NOSIGPIPE
, &on
, sizeof(on
)); // Return EPIPE instead of raising SIGPIPE.
3414 _do_setsockopt(sock
, SOL_SOCKET
, SO_NOWAKEFROMSLEEP
, &on
, sizeof(on
)); // Don't wake from sleep on receive.
3415 mdns_make_socket_nonblocking(sock
);
3416 // Restrict socket's network traffic to a particular interface.
3417 if (resolver
->interface
) {
3418 const uint32_t if_index
= nw_interface_get_index(resolver
->interface
);
3420 _do_setsockopt(sock
, IPPROTO_IP
, IP_BOUND_IF
, &if_index
, sizeof(if_index
));
3422 _do_setsockopt(sock
, IPPROTO_IPV6
, IPV6_BOUND_IF
, &if_index
, sizeof(if_index
));
3425 // If delegation info is provided, attribute outbound data to the delegator.
3427 switch (delegation
->type
) {
3428 case mdns_delegation_type_pid
:
3429 _do_setsockopt(sock
, SOL_SOCKET
, SO_DELEGATED
, &delegation
->ident
.pid
, sizeof(delegation
->ident
.pid
));
3432 case mdns_delegation_type_uuid
:
3433 _do_setsockopt(sock
, SOL_SOCKET
, SO_DELEGATED_UUID
, delegation
->ident
.uuid
,
3434 sizeof(delegation
->ident
.uuid
));
3438 case mdns_delegation_type_none
:
3442 #undef _do_setsockopt
3444 char qname_str
[kDNSServiceMaxDomainName
];
3445 err
= DomainNameToString(qname
, NULL
, qname_str
, NULL
);
3446 require_noerr_quiet(err
, exit
);
3448 const bool ok
= ne_session_set_socket_attributes(sock
, qname_str
, NULL
);
3450 os_log_error(_mdns_resolver_log(), "ne_session_set_socket_attributes() failed for '%s'", qname_str
);
3453 const socklen_t dst_len
= (socklen_t
)(ipv4
? sizeof(struct sockaddr_in
) : sizeof(struct sockaddr_in6
));
3454 #if MDNS_USE_CONNECTED_UDP_SOCKETS
3455 err
= connect(sock
, dst
, dst_len
);
3456 err
= map_socket_noerr_errno(sock
, err
);
3458 me
->connected
= true;
3459 os_log_debug(_mdns_resolver_log(),
3460 "UDP socket connected to %{network:sockaddr}.*P", (int)dst_len
, dst
);
3461 } else if (err
== EINPROGRESS
) {
3462 os_log_info(_mdns_resolver_log(),
3463 "UDP socket connection to %{network:sockaddr}.*P is in progress", (int)dst_len
, dst
);
3466 os_log_error(_mdns_resolver_log(),
3467 "UDP socket connection to %{network:sockaddr}.*P failed: %{darwin.errno}d", (int)dst_len
, dst
, (int)err
);
3471 memcpy(&me
->server_addr
, dst
, dst_len
);
3472 me
->server_addr_len
= dst_len
;
3475 sock
= kInvalidSocketRef
;
3478 _mdns_socket_forget(&sock
);
3483 _mdns_bind_ipv6_socket_to_random_port(const int sock
)
3485 struct sockaddr_in6 sin6
;
3486 memset(&sin6
, 0, sizeof(sin6
));
3487 SIN6_LEN_SET(&sin6
);
3488 sin6
.sin6_family
= AF_INET6
;
3489 sin6
.sin6_addr
= in6addr_any
;
3493 // Bind to a random port in the ephemeral port range (see <https://tools.ietf.org/html/rfc6335#section-6>).
3494 // Note: This is the same algorithm used by mDNSResponder's MacOSX platform code for port randomization.
3496 port
= RandomRange(0xC000U
, 0xFFFFU
);
3497 sin6
.sin6_port
= htons(port
);
3498 err
= bind(sock
, (const struct sockaddr
*)&sin6
, sizeof(sin6
));
3499 err
= map_socket_noerr_errno(sock
, err
);
3501 } while ((err
== EADDRINUSE
) && (tries
< 10000));
3503 os_log_error(_mdns_resolver_log(),
3504 "Binding IPv6 socket to random port failed -- error: %{mdns:err}ld, tries: %d", (long)err
, tries
);
3506 os_log_debug(_mdns_resolver_log(),
3507 "Binding IPv6 socket to random port succeeded -- port: %u, tries: %d", port
, tries
);
3512 //======================================================================================================================
3515 _mdns_udp_socket_session_read_handler(void *ctx
);
3517 #if MDNS_USE_CONNECTED_UDP_SOCKETS
3519 _mdns_udp_socket_session_write_handler(void *ctx
);
3523 _mdns_udp_socket_session_cancel_handler(void *ctx
);
3526 _mdns_udp_socket_session_activate(const mdns_udp_socket_session_t me
)
3529 me
->read_source
= dispatch_source_create(DISPATCH_SOURCE_TYPE_READ
, (uintptr_t)me
->sock
, 0, _mdns_resolver_queue());
3530 require_action_quiet(me
->read_source
, exit
, err
= kNoResourcesErr
);
3533 dispatch_set_context(me
->read_source
, me
);
3534 dispatch_source_set_event_handler_f(me
->read_source
, _mdns_udp_socket_session_read_handler
);
3535 dispatch_source_set_cancel_handler_f(me
->read_source
, _mdns_udp_socket_session_cancel_handler
);
3536 #if MDNS_USE_CONNECTED_UDP_SOCKETS
3537 if (me
->connected
) {
3538 dispatch_activate(me
->read_source
);
3539 me
->read_source_suspended
= false;
3541 me
->read_source_suspended
= true;
3543 me
->write_source
= dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE
, (uintptr_t)me
->sock
, 0,
3544 _mdns_resolver_queue());
3545 require_action_quiet(me
->write_source
, exit
, err
= kNoResourcesErr
);
3548 dispatch_set_context(me
->write_source
, me
);
3549 dispatch_source_set_event_handler_f(me
->write_source
, _mdns_udp_socket_session_write_handler
);
3550 dispatch_source_set_cancel_handler_f(me
->write_source
, _mdns_udp_socket_session_cancel_handler
);
3551 dispatch_activate(me
->write_source
);
3554 dispatch_activate(me
->read_source
);
3563 _mdns_udp_socket_session_read_handler(void * const ctx
)
3565 const mdns_udp_socket_session_t me
= (mdns_udp_socket_session_t
)ctx
;
3566 uint8_t msg_buf
[512];
3567 #if MDNS_USE_CONNECTED_UDP_SOCKETS
3568 const ssize_t n
= recv(me
->sock
, msg_buf
, sizeof(msg_buf
), 0);
3571 socklen_t sender_len
= (socklen_t
)sizeof(sender
);
3572 const ssize_t n
= recvfrom(me
->sock
, msg_buf
, sizeof(msg_buf
), 0, &sender
.sa
, &sender_len
);
3574 const OSStatus err
= map_socket_value_errno(me
->sock
, n
>= 0, n
);
3575 require_noerr_quiet(err
, exit
);
3577 #if !MDNS_USE_CONNECTED_UDP_SOCKETS
3578 if (me
->server_addr
.sa
.sa_family
== AF_INET
) {
3579 const struct sockaddr_in
* const sa1
= &me
->server_addr
.v4
;
3580 const struct sockaddr_in
* const sa2
= &sender
.v4
;
3581 require_quiet(IN_ARE_ADDR_EQUAL(&sa1
->sin_addr
, &sa2
->sin_addr
), exit
);
3582 require_quiet(sa1
->sin_port
== sa2
->sin_port
, exit
);
3584 const struct sockaddr_in6
* const sa1
= &me
->server_addr
.v6
;
3585 const struct sockaddr_in6
* const sa2
= &sender
.v6
;
3586 require_quiet(IN6_ARE_ADDR_EQUAL(&sa1
->sin6_addr
, &sa2
->sin6_addr
), exit
);
3587 require_quiet(sa1
->sin6_port
== sa2
->sin6_port
, exit
);
3589 if (IN6_IS_ADDR_LINKLOCAL(&sa1
->sin6_addr
) && (sa1
->sin6_scope_id
!= 0) &&
3590 (sa1
->sin6_scope_id
!= sa2
->sin6_scope_id
)) {
3595 dispatch_data_t msg
= dispatch_data_create(msg_buf
, (size_t)n
, _mdns_resolver_queue(),
3596 DISPATCH_DATA_DESTRUCTOR_DEFAULT
);
3598 _mdns_common_session_invoke_receive(me
, msg
);
3599 dispatch_forget(&msg
);
3603 if (err
&& (err
!= EWOULDBLOCK
)) {
3604 _mdns_common_session_terminate(me
, err
);
3608 #if MDNS_USE_CONNECTED_UDP_SOCKETS
3610 _mdns_udp_socket_session_write_handler(void * const ctx
)
3612 const mdns_udp_socket_session_t me
= (mdns_udp_socket_session_t
)ctx
;
3613 dispatch_source_forget(&me
->write_source
);
3614 me
->connected
= true;
3615 os_log_info(_mdns_resolver_log(), "UDP socket connection to %@ is complete", me
->base
.server
);
3616 dispatch_resume_if_suspended(me
->read_source
, &me
->read_source_suspended
);
3617 _mdns_common_session_invoke_ready_event_handler(me
);
3622 _mdns_udp_socket_session_cancel_handler(void * const ctx
)
3624 const mdns_udp_socket_session_t me
= (mdns_udp_socket_session_t
)ctx
;
3625 #if MDNS_USE_CONNECTED_UDP_SOCKETS
3626 if (!me
->read_source
&& !me
->write_source
) {
3627 _mdns_socket_forget(&me
->sock
);
3630 _mdns_socket_forget(&me
->sock
);
3635 //======================================================================================================================
3638 _mdns_udp_socket_session_invalidate(const mdns_udp_socket_session_t me
)
3640 #if MDNS_USE_CONNECTED_UDP_SOCKETS
3641 dispatch_source_forget(&me
->write_source
);
3642 dispatch_source_forget_ex(&me
->read_source
, &me
->read_source_suspended
);
3644 dispatch_source_forget(&me
->read_source
);
3648 //======================================================================================================================
3650 #if MDNS_USE_CONNECTED_UDP_SOCKETS
3652 _mdns_udp_socket_session_is_ready(const mdns_udp_socket_session_t me
)
3654 return me
->connected
;
3658 //======================================================================================================================
3661 _mdns_udp_socket_session_send(const mdns_udp_socket_session_t me
, const dispatch_data_t msg
,
3662 __unused
const uint16_t qtype
)
3664 const void * msg_ptr
;
3666 dispatch_data_t msg_map
= dispatch_data_create_map(msg
, &msg_ptr
, &msg_len
);
3667 require_quiet(msg_map
, exit
);
3669 #if MDNS_USE_CONNECTED_UDP_SOCKETS
3670 const ssize_t n
= send(me
->sock
, msg_ptr
, msg_len
, 0);
3672 const ssize_t n
= sendto(me
->sock
, msg_ptr
, msg_len
, 0, &me
->server_addr
.sa
, me
->server_addr_len
);
3674 const OSStatus err
= map_socket_value_errno(me
->sock
, n
>= 0, n
);
3676 os_log_error(_mdns_resolver_log(), "sending to %@ failed: %{darwin.errno}d", me
->base
.server
, (int)err
);
3678 require_noerr_quiet(err
, exit
);
3681 dispatch_release_null_safe(msg_map
);
3684 //======================================================================================================================
3685 // MARK: - URL Session Private Methods
3688 _mdns_url_session_finalize(__unused
const mdns_url_session_t me
)
3690 nw_forget(&me
->url_endpoint
);
3693 //======================================================================================================================
3696 _mdns_url_session_initialize(const mdns_url_session_t me
, const mdns_resolver_t resolver
,
3697 __unused
const bool need_bytestream
, __unused
const mdns_delegation_t
* const delegation
,
3698 __unused
const uint8_t * const qname
)
3701 const nw_parameters_t params
= _mdns_resolver_get_stream_params(resolver
, &err
);
3702 require_noerr_quiet(err
, exit
);
3704 me
->url_endpoint
= nw_parameters_copy_url_endpoint(params
);
3705 require_action_quiet(me
->url_endpoint
, exit
, err
= kNoResourcesErr
);
3711 //======================================================================================================================
3714 _mdns_url_session_activate(__unused
const mdns_url_session_t me
)
3716 // Nothing to do for now.
3720 //======================================================================================================================
3723 _mdns_url_session_invalidate(const mdns_url_session_t me
)
3725 if (me
->http_task
) {
3726 http_task_cancel(me
->http_task
);
3727 me
->http_task
= NULL
;
3731 //======================================================================================================================
3734 _mdns_url_session_send(const mdns_url_session_t me
, const dispatch_data_t msg
, const uint16_t qtype
)
3736 os_log_debug(_mdns_resolver_log(), "Sending message on URL %@", me
->url_endpoint
);
3739 __block
bool invoked
= false;
3740 me
->http_task
= http_task_create_dns_query(_mdns_common_session_get_server_endpoint(me
),
3741 nw_endpoint_get_url(me
->url_endpoint
), msg
, qtype
, false,
3742 ^(const dispatch_data_t data
, const CFErrorRef task_error
) {
3743 if (likely(!invoked
)) {
3745 if (likely(me
->http_task
)) {
3747 _mdns_common_session_invoke_receive(me
, data
);
3750 os_log_error(_mdns_resolver_log(), "Got error %@", task_error
);
3751 _mdns_common_session_terminate(me
, (OSStatus
)CFErrorGetCode(task_error
));
3757 if (me
->http_task
) {
3758 http_task_start(me
->http_task
);
3760 os_log_error(_mdns_resolver_log(), "Failed to create HTTP task");
3761 _mdns_common_session_terminate_async(me
, kUnknownErr
);
3765 //======================================================================================================================
3766 // MARK: - Querier Public Methods
3769 mdns_querier_set_queue(mdns_querier_t me
, dispatch_queue_t queue
)
3771 if (!me
->user_activated
|| !me
->user_queue
)
3774 dispatch_retain(queue
);
3776 dispatch_release_null_safe(me
->user_queue
);
3777 me
->user_queue
= queue
;
3778 _mdns_querier_activate_if_ready(me
);
3782 //======================================================================================================================
3785 mdns_querier_set_query(mdns_querier_t me
, const uint8_t *qname
, uint16_t qtype
, uint16_t qclass
)
3788 require_action_quiet(!me
->user_activated
|| !mdns_query_message_get_qname(me
->query
), exit
,
3789 err
= kAlreadyInitializedErr
);
3791 err
= mdns_query_message_set_qname(me
->query
, qname
);
3792 require_noerr_quiet(err
, exit
);
3794 mdns_query_message_set_qtype(me
->query
, qtype
);
3795 mdns_query_message_set_qclass(me
->query
, qclass
);
3797 _mdns_querier_activate_if_ready(me
);
3804 //======================================================================================================================
3807 mdns_querier_set_dnssec_ok(const mdns_querier_t me
, const bool set
)
3809 require_return(!me
->user_activated
);
3810 mdns_query_message_set_do_bit(me
->query
, set
);
3813 //======================================================================================================================
3816 mdns_querier_set_checking_disabled(const mdns_querier_t me
, const bool checking_disabled
)
3818 require_return(!me
->user_activated
);
3819 mdns_query_message_set_cd_bit(me
->query
, checking_disabled
);
3822 //======================================================================================================================
3825 mdns_querier_set_delegator_pid(mdns_querier_t me
, pid_t pid
)
3827 if (!me
->user_activated
) {
3828 me
->delegation
.type
= mdns_delegation_type_pid
;
3829 me
->delegation
.ident
.pid
= pid
;
3833 //======================================================================================================================
3836 mdns_querier_set_delegator_uuid(mdns_querier_t me
, uuid_t uuid
)
3838 if (!me
->user_activated
) {
3839 me
->delegation
.type
= mdns_delegation_type_uuid
;
3840 uuid_copy(me
->delegation
.ident
.uuid
, uuid
);
3844 //======================================================================================================================
3847 mdns_querier_set_user_id(const mdns_querier_t me
, const uint32_t user_id
)
3849 require_return(!me
->user_activated
);
3850 me
->user_id
= user_id
;
3853 //======================================================================================================================
3856 mdns_querier_set_log_label(const mdns_querier_t me
, const char * const format
, ...)
3858 require_return_value(!me
->user_activated
, kAlreadyInitializedErr
);
3861 va_start(args
, format
);
3862 char *inner_str
= NULL
;
3863 vasprintf(&inner_str
, format
, args
);
3866 require_action_quiet(inner_str
, exit
, err
= kNoMemoryErr
);
3868 char *log_label
= NULL
;
3869 asprintf(&log_label
, "[%s] ", inner_str
);
3870 require_action_quiet(log_label
, exit
, err
= kNoMemoryErr
);
3872 FreeNullSafe(me
->log_label
);
3873 me
->log_label
= log_label
;
3878 ForgetMem(&inner_str
);
3882 //======================================================================================================================
3885 mdns_querier_set_result_handler(mdns_querier_t me
, mdns_querier_result_handler_t handler
)
3887 if (!me
->user_activated
) {
3888 const mdns_querier_result_handler_t new_handler
= handler
? Block_copy(handler
) : NULL
;
3890 Block_release(me
->handler
);
3892 me
->handler
= new_handler
;
3896 //======================================================================================================================
3899 _mdns_querier_set_time_limit_ms(mdns_querier_t querier
, int32_t time_limit_ms
);
3902 mdns_querier_set_time_limit_ms(const mdns_querier_t me
, const int32_t time_limit_ms
)
3905 dispatch_async(_mdns_resolver_queue(),
3907 _mdns_querier_set_time_limit_ms(me
, time_limit_ms
);
3913 _mdns_querier_set_time_limit_ms(const mdns_querier_t me
, const int32_t time_limit_ms
)
3915 if (likely(!me
->concluded
)) {
3916 me
->time_limit_ms
= time_limit_ms
;
3917 const OSStatus err
= _mdns_querier_reset_time_limit(me
);
3919 _mdns_querier_conclude(me
, err
);
3924 //======================================================================================================================
3927 mdns_querier_activate(mdns_querier_t me
)
3929 if (!me
->user_activated
) {
3930 me
->user_activated
= true;
3931 _mdns_querier_activate_if_ready(me
);
3935 //======================================================================================================================
3938 mdns_querier_invalidate(mdns_querier_t me
)
3941 dispatch_async(_mdns_resolver_queue(),
3943 _mdns_querier_conclude(me
, mdns_querier_result_type_invalidation
);
3948 //======================================================================================================================
3951 mdns_querier_get_qname(const mdns_querier_t me
)
3953 return mdns_query_message_get_qname(me
->query
);
3956 //======================================================================================================================
3959 mdns_querier_get_qtype(const mdns_querier_t me
)
3961 return mdns_query_message_get_qtype(me
->query
);
3964 //======================================================================================================================
3967 mdns_querier_get_qclass(const mdns_querier_t me
)
3969 return mdns_query_message_get_qclass(me
->query
);
3972 //======================================================================================================================
3974 mdns_resolver_type_t
3975 mdns_querier_get_resolver_type(const mdns_querier_t me
)
3977 return _mdns_resolver_get_type(me
->resolver
);
3980 //======================================================================================================================
3982 mdns_querier_result_type_t
3983 mdns_querier_get_result_type(const mdns_querier_t me
)
3985 return me
->result_type
;
3988 //======================================================================================================================
3991 mdns_querier_get_send_count(const mdns_querier_t me
)
3993 return atomic_load(&me
->send_count
);
3996 //======================================================================================================================
3999 mdns_querier_get_query_length(const mdns_querier_t me
)
4001 return (uint32_t)mdns_message_get_length(me
->query
);
4004 //======================================================================================================================
4007 mdns_querier_get_response_ptr(const mdns_querier_t me
)
4009 return _mdns_querier_get_response_ptr_safe(me
);
4012 //======================================================================================================================
4015 mdns_querier_get_response_length(const mdns_querier_t me
)
4017 return (uint32_t)_mdns_querier_get_response_length_safe(me
);
4020 //======================================================================================================================
4023 mdns_querier_response_is_fabricated(const mdns_querier_t me
)
4025 return me
->response_is_fabricated
;
4028 //======================================================================================================================
4031 mdns_querier_get_error(const mdns_querier_t me
)
4036 //======================================================================================================================
4039 mdns_querier_get_dnssec_ok(const mdns_querier_t me
)
4041 return mdns_query_message_do_bit_is_set(me
->query
);
4044 //======================================================================================================================
4046 mdns_query_over_tcp_reason_t
4047 mdns_querier_get_over_tcp_reason(const mdns_querier_t me
)
4049 return me
->over_tcp_reason
;
4052 //======================================================================================================================
4055 mdns_querier_match(const mdns_querier_t me
, const uint8_t * const qname
, const int qtype
, const int qclass
)
4057 if ((mdns_query_message_get_qtype(me
->query
) == qtype
) && (mdns_query_message_get_qclass(me
->query
) == qclass
)) {
4058 const uint8_t * const query_qname
= mdns_query_message_get_qname(me
->query
);
4059 if (query_qname
&& DomainNameEqual(query_qname
, qname
)) {
4066 //======================================================================================================================
4069 mdns_querier_has_concluded(const mdns_querier_t me
)
4071 return (me
->result_type
!= mdns_querier_result_type_null
);
4074 //======================================================================================================================
4077 mdns_querier_get_user_id(const mdns_querier_t me
)
4082 //======================================================================================================================
4083 // MARK: - Querier Private Methods
4086 _mdns_querier_finalize(mdns_querier_t me
)
4088 me
->current_server
= NULL
;
4089 mdns_forget(&me
->resolver
);
4090 dispatch_forget(&me
->user_queue
);
4091 BlockForget(&me
->handler
);
4092 mdns_forget(&me
->query
);
4093 mdns_forget(&me
->response
);
4094 ForgetMem(&me
->log_label
);
4095 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
4096 mdns_forget(&me
->test_query
);
4100 //======================================================================================================================
4103 _mdns_querier_copy_description(mdns_querier_t me
, const bool debug
, const bool privacy
)
4105 char * description
= NULL
;
4107 char * dst
= buffer
;
4108 const char * const lim
= &buffer
[countof(buffer
)];
4110 char qname_str
[kDNSServiceMaxDomainName
];
4114 n
= mdns_snprintf_add(&dst
, lim
, "<%s: %p>: ", me
->base
.kind
->name
, me
);
4115 require_quiet(n
>= 0, exit
);
4119 const uint8_t * const query_qname
= mdns_query_message_get_qname(me
->query
);
4121 if (DomainNameToString(query_qname
, NULL
, qname_str
, NULL
) == kNoErr
) {
4123 n
= DNSMessagePrintObfuscatedString(strbuf
, sizeof(strbuf
), qname_str
);
4124 qname
= (n
>= 0) ? strbuf
: "<REDACTED QNAME>";
4129 qname
= "<INVALID QNAME>";
4132 qname
= "<NO QNAME>";
4134 n
= mdns_snprintf_add(&dst
, lim
, "%s", qname
);
4135 require_quiet(n
>= 0, exit
);
4137 const char * const type_str
= DNSRecordTypeValueToString(mdns_query_message_get_qtype(me
->query
));
4139 n
= mdns_snprintf_add(&dst
, lim
, " %s", type_str
);
4140 require_quiet(n
>= 0, exit
);
4142 n
= mdns_snprintf_add(&dst
, lim
, " TYPE%u", mdns_query_message_get_qtype(me
->query
));
4143 require_quiet(n
>= 0, exit
);
4145 if (mdns_query_message_get_qclass(me
->query
) == kDNSClassType_IN
) {
4146 n
= mdns_snprintf_add(&dst
, lim
, " IN");
4147 require_quiet(n
>= 0, exit
);
4149 n
= mdns_snprintf_add(&dst
, lim
, " CLASS%u", mdns_query_message_get_qclass(me
->query
));
4150 require_quiet(n
>= 0, exit
);
4152 description
= strdup(buffer
);
4158 //======================================================================================================================
4161 _mdns_querier_activate(mdns_querier_t querier
);
4164 _mdns_querier_activate_if_ready(mdns_querier_t me
)
4166 if (me
->user_activated
&& me
->user_queue
&& mdns_query_message_get_qname(me
->query
)) {
4168 dispatch_async(_mdns_resolver_queue(),
4170 _mdns_querier_activate(me
);
4177 _mdns_querier_activate(mdns_querier_t me
)
4179 require_return(!me
->activated
&& !me
->concluded
);
4182 me
->activated
= true;
4185 if (_mdns_resolver_needs_zero_ids(me
->resolver
)) {
4188 msg_id
= (uint16_t)RandomRange(1, UINT16_MAX
);
4190 mdns_query_message_set_message_id(me
->query
, msg_id
);
4191 mdns_query_message_use_edns0_padding(me
->query
, _mdns_resolver_needs_edns0_padding(me
->resolver
) ? true : false);
4192 OSStatus err
= mdns_query_message_construct(me
->query
);
4193 require_noerr_quiet(err
, exit
);
4195 if (me
->time_limit_ms
!= 0) {
4196 err
= _mdns_querier_reset_time_limit(me
);
4197 require_noerr_quiet(err
, exit
);
4199 _mdns_resolver_register_querier(me
->resolver
, me
, false);
4203 _mdns_querier_conclude(me
, err
);
4207 //======================================================================================================================
4210 _mdns_querier_session_handle_event(const mdns_session_t session
, const mdns_session_event_t event
,
4211 const OSStatus error
, void * const context
)
4213 mdns_querier_t
const me
= (mdns_querier_t
)context
;
4214 os_log_with_type(_mdns_resolver_log(),
4215 ((event
== mdns_session_event_terminated
) && error
) ? OS_LOG_TYPE_ERROR
: OS_LOG_TYPE_INFO
,
4216 "%{public}sQuerier session event -- type: %{public}s, error: %{mdns:err}ld",
4217 _mdns_querier_get_log_label(me
), mdns_session_event_to_string(event
), (long)error
);
4220 case mdns_session_event_ready
:
4221 _mdns_querier_send_query(me
, session
);
4224 case mdns_session_event_terminated
: {
4225 const bool is_stream
= _mdns_session_is_bytestream(session
);
4226 mdns_session_t
*ptr
= is_stream
? &me
->stream_session_list
: &me
->dgram_session_list
;
4227 while (*ptr
&& (*ptr
!= session
)) {
4228 ptr
= &(*ptr
)->next
;
4230 require_quiet(*ptr
, exit
);
4232 *ptr
= session
->next
;
4233 session
->next
= NULL
;
4234 mdns_session_t tmp
= session
;
4235 mdns_session_forget(&tmp
);
4238 const mdns_server_t server
= session
->server
;
4239 if (error
|| (session
->receive_count
== 0)) {
4240 _mdns_resolver_handle_stream_error(me
->resolver
, server
, _mdns_querier_get_log_label(me
));
4241 _mdns_resolver_penalize_server(me
->resolver
, server
);
4243 _mdns_querier_handle_stream_error(me
, server
);
4247 case mdns_session_event_lateness_warning
:
4248 if (_mdns_session_is_bytestream(session
)) {
4249 _mdns_resolver_handle_stream_lateness(me
->resolver
, session
->server
, session
->start_ticks
,
4250 _mdns_querier_get_log_label(me
));
4262 //======================================================================================================================
4265 _mdns_querier_is_response_acceptable(const mdns_querier_t me
, const mdns_message_t msg
, bool * const out_truncated
,
4266 bool * const out_suspicious
, int * const out_rcode
)
4268 bool id_match
= false;
4269 bool question_match
= false;
4270 bool acceptable
= false;
4271 const size_t msg_len
= mdns_message_get_length(msg
);
4272 require_quiet(msg_len
>= kDNSHeaderLength
, exit
);
4274 uint16_t msg_id
= 0;
4275 const uint8_t * const msg_ptr
= mdns_message_get_byte_ptr(msg
);
4276 question_match
= _mdns_message_is_query_response_ignoring_id(msg_ptr
, msg_len
, me
->query
, &msg_id
);
4277 require_quiet(question_match
, exit
);
4279 id_match
= (msg_id
== mdns_query_message_get_message_id(me
->query
)) ? true : false;
4282 const DNSHeader
* const hdr
= (const DNSHeader
*)msg_ptr
;
4283 const unsigned int flags
= DNSHeaderGetFlags(hdr
);
4284 if (out_truncated
) {
4285 bool truncated
= (flags
& kDNSHeaderFlag_Truncation
) ? true : false;
4286 if (truncated
&& !mdns_query_message_do_bit_is_set(me
->query
) && (DNSHeaderGetAnswerCount(hdr
) > 0) &&
4287 ((DNSHeaderGetAuthorityCount(hdr
) > 0) || (DNSHeaderGetAdditionalCount(hdr
) > 0))) {
4290 *out_truncated
= truncated
;
4293 *out_rcode
= DNSFlagsGetRCode(flags
);
4298 if (out_suspicious
) {
4299 *out_suspicious
= (!id_match
&& question_match
) ? true : false;
4304 //======================================================================================================================
4307 _mdns_querier_conclude(const mdns_querier_t me
, const mdns_querier_result_type_t result_type
)
4309 _mdns_querier_conclude_ex(me
, result_type
, 0, NULL
);
4312 //======================================================================================================================
4315 _mdns_querier_conclude_async(const mdns_querier_t me
, const mdns_querier_result_type_t result_type
)
4318 dispatch_async(_mdns_resolver_queue(),
4320 _mdns_querier_conclude(me
, result_type
);
4325 //======================================================================================================================
4328 _mdns_querier_conclude_with_error(const mdns_querier_t me
, const OSStatus error
)
4330 _mdns_querier_conclude_ex(me
, mdns_querier_result_type_error
, error
, NULL
);
4333 //======================================================================================================================
4336 _mdns_querier_conclude_with_error_async(const mdns_querier_t me
, const OSStatus error
)
4339 dispatch_async(_mdns_resolver_queue(),
4341 _mdns_querier_conclude_with_error(me
, error
);
4346 //======================================================================================================================
4349 _mdns_querier_conclude_with_response(const mdns_querier_t me
, const mdns_message_t response
)
4351 _mdns_querier_conclude_ex(me
, mdns_querier_result_type_response
, 0, response
);
4354 //======================================================================================================================
4356 #define MDNS_QUERIER_RESPONSE_STATUS_FABRICATED 1
4359 _mdns_querier_conclude_with_response_async(const mdns_querier_t me
, const mdns_message_t response
,
4360 const bool fabricated
)
4363 mdns_retain(response
);
4364 dispatch_async(_mdns_resolver_queue(),
4366 const OSStatus status
= fabricated
? MDNS_QUERIER_RESPONSE_STATUS_FABRICATED
: 0;
4367 _mdns_querier_conclude_ex(me
, mdns_querier_result_type_response
, status
, response
);
4369 mdns_release(response
);
4373 //======================================================================================================================
4376 _mdns_querier_postprocess_response(mdns_querier_t querier
);
4379 _mdns_querier_conclude_ex(const mdns_querier_t me
, const mdns_querier_result_type_t result_type
, const OSStatus status
,
4380 const mdns_message_t response
)
4382 dispatch_source_forget(&me
->rtx_timer
);
4383 dispatch_source_forget(&me
->timeout_timer
);
4384 mdns_forget(&me
->bad_rcode_response
);
4386 _mdns_resolver_deregister_querier(me
->resolver
, me
);
4387 require_return(!me
->concluded
);
4389 me
->concluded
= true;
4390 switch (result_type
) {
4391 case mdns_querier_result_type_response
: {
4392 mdns_replace(&me
->response
, response
);
4393 const bool fabricated
= _mdns_querier_postprocess_response(me
);
4394 me
->response_is_fabricated
= fabricated
|| (status
== MDNS_QUERIER_RESPONSE_STATUS_FABRICATED
);
4395 if (me
->response_is_fabricated
) {
4396 os_log_info(_mdns_resolver_log(),
4397 "%{public}sQuerier concluded -- reason: response (fabricated)", _mdns_querier_get_log_label(me
));
4399 os_log_info(_mdns_resolver_log(),
4400 "%{public}sQuerier concluded -- reason: response", _mdns_querier_get_log_label(me
));
4404 case mdns_querier_result_type_timeout
:
4405 os_log_info(_mdns_resolver_log(),
4406 "%{public}sQuerier concluded -- reason: timeout", _mdns_querier_get_log_label(me
));
4409 case mdns_querier_result_type_invalidation
:
4410 os_log_info(_mdns_resolver_log(),
4411 "%{public}sQuerier concluded -- reason: invalidation", _mdns_querier_get_log_label(me
));
4414 case mdns_querier_result_type_resolver_invalidation
:
4415 os_log_info(_mdns_resolver_log(),
4416 "%{public}sQuerier concluded -- reason: resolver invalidation", _mdns_querier_get_log_label(me
));
4419 case mdns_querier_result_type_error
:
4421 os_log_error(_mdns_resolver_log(),
4422 "%{public}sQuerier concluded -- error: %{mdns:err}ld",
4423 _mdns_querier_get_log_label(me
), (long)me
->error
);
4426 case mdns_querier_result_type_null
:
4429 if (me
->user_queue
) {
4430 const mdns_querier_result_handler_t handler
= me
->handler
;
4433 dispatch_async(me
->user_queue
,
4435 me
->result_type
= result_type
;
4438 Block_release(handler
);
4443 if (me
->activated
) {
4449 _mdns_querier_postprocess_response(const mdns_querier_t me
)
4451 if (!me
->resolver
->squash_cnames
) {
4454 const uint8_t *resp_ptr
= _mdns_querier_get_response_ptr_safe(me
);
4455 require_return_value(resp_ptr
, false);
4457 mdns_message_t new_msg
= NULL
;
4460 uint8_t *new_ptr
= DNSMessageCollapse(resp_ptr
, _mdns_querier_get_response_length_safe(me
), &new_len
, &err
);
4462 dispatch_data_t data
= dispatch_data_create(new_ptr
, new_len
, NULL
, DISPATCH_DATA_DESTRUCTOR_FREE
);
4465 new_msg
= mdns_message_create_with_dispatch_data(data
, mdns_message_init_option_disable_header_printing
);
4466 dispatch_forget(&data
);
4468 err
= kNoResourcesErr
;
4471 ForgetMem(&new_ptr
);
4472 err
= kNoResourcesErr
;
4477 mdns_replace(&me
->response
, new_msg
);
4478 mdns_forget(&new_msg
);
4479 resp_ptr
= _mdns_querier_get_response_ptr_safe(me
);
4480 size_t resp_len
= _mdns_querier_get_response_length_safe(me
);
4481 os_log(_mdns_resolver_log(),
4482 "%{public}sUsing squashed response -- %{public,mdns:dnshdr}.*P, %@",
4483 _mdns_querier_get_log_label(me
), (int)Min(resp_len
, kDNSHeaderLength
), resp_ptr
, me
->response
);
4486 os_log_error(_mdns_resolver_log(),
4487 "%{public}sFailed to squash response -- error:%{mdns:err}ld",
4488 _mdns_querier_get_log_label(me
), (long)err
);
4494 //======================================================================================================================
4497 _mdns_querier_reregister_in_stream_mode(mdns_querier_t querier
);
4500 _mdns_querier_session_receive(const mdns_session_t session
, const dispatch_data_t msg_data
, void * const context
)
4502 const mdns_querier_t me
= (mdns_querier_t
)context
;
4503 const mdns_message_t msg
= mdns_message_create_with_dispatch_data(msg_data
,
4504 mdns_message_init_option_disable_header_printing
);
4505 require_return_action(msg
, _mdns_querier_conclude_with_error(me
, kNoResourcesErr
));
4507 bool truncated
= false;
4508 bool suspicious
= false;
4509 const bool is_dgram
= !_mdns_session_is_bytestream(session
);
4510 bool * const truncated_ptr
= is_dgram
? &truncated
: NULL
;
4511 const bool need_suspicious_reply_defense
= _mdns_resolver_needs_suspicious_reply_defense(me
->resolver
);
4512 bool * const suspicious_ptr
= (need_suspicious_reply_defense
&& is_dgram
) ? &suspicious
: NULL
;
4514 const bool acceptable
= _mdns_querier_is_response_acceptable(me
, msg
, truncated_ptr
, suspicious_ptr
, &rcode
);
4515 _mdns_resolver_log_receive(me
->resolver
, session
, msg
, acceptable
, _mdns_querier_get_log_label(me
));
4516 const mdns_server_t server
= session
->server
;
4518 _mdns_resolver_note_responsiveness(me
->resolver
, server
, !is_dgram
, session
->start_ticks
,
4519 mdns_querier_get_qtype(me
));
4520 if (_mdns_rcode_is_good(rcode
)) {
4521 if (is_dgram
&& truncated
) {
4522 me
->over_tcp_reason
= mdns_query_over_tcp_reason_truncation
;
4523 _mdns_querier_reregister_in_stream_mode(me
);
4525 _mdns_querier_conclude_with_response(me
, msg
);
4528 // Note: _mdns_querier_handle_bad_rcode() may or may not conclude the querier.
4529 _mdns_querier_handle_bad_rcode(me
, msg
, rcode
, server
);
4531 } else if (is_dgram
&& need_suspicious_reply_defense
&& suspicious
) {
4532 me
->over_tcp_reason
= mdns_query_over_tcp_reason_got_suspicious_reply
;
4533 _mdns_resolver_got_suspicious_reply(me
->resolver
);
4534 _mdns_querier_reregister_in_stream_mode(me
);
4535 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND || MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
4537 bool handled_response
= false;
4538 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
4539 if (_mdns_resolver_use_problematic_qtype_workaround(me
->resolver
)) {
4540 if (me
->test_query
&& _mdns_message_is_adequate_test_query_response(msg
, me
->test_query
)) {
4541 _mdns_querier_set_test_query_got_response(me
, server
, true);
4542 _mdns_resolver_note_responsiveness(me
->resolver
, server
, !is_dgram
, session
->start_ticks
,
4543 mdns_query_message_get_qtype(me
->test_query
));
4544 handled_response
= true;
4548 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND
4549 if (!handled_response
&& _mdns_resolver_use_mixed_up_responses_workaround(me
->resolver
)) {
4550 if (!server
->mixes_up_responses
) {
4551 qtype_test_f qtype_test
= NULL
;
4552 const int qtype
= mdns_querier_get_qtype(me
);
4553 if (_mdns_qtype_is_address_type(qtype
)) {
4554 qtype_test
= _mdns_qtype_is_problematic
;
4555 } else if (_mdns_qtype_is_problematic(qtype
)) {
4556 qtype_test
= _mdns_qtype_is_address_type
;
4559 uint16_t msg_qtype
= 0;
4560 if (_mdns_message_is_query_response_ignoring_qtype(msg
, me
->query
, &msg_qtype
)) {
4561 if (qtype_test(msg_qtype
)) {
4562 server
->mixes_up_responses
= true;
4569 (void)handled_response
;
4577 _mdns_querier_reregister_in_stream_mode(mdns_querier_t me
)
4579 _mdns_resolver_deregister_querier(me
->resolver
, me
);
4580 _mdns_resolver_register_querier(me
->resolver
, me
, true);
4583 //======================================================================================================================
4585 static mdns_session_t
4586 _mdns_querier_get_shared_session(mdns_querier_t querier
);
4588 static mdns_session_t
4589 _mdns_querier_get_unshared_session(mdns_querier_t querier
);
4592 _mdns_querier_initiate_send(const mdns_querier_t me
)
4594 dispatch_source_forget(&me
->rtx_timer
);
4596 if (!me
->current_server
) {
4597 if (me
->bad_rcode_response
&& !_mdns_resolver_get_server(me
->resolver
, me
->bad_rcode_bitmap
)) {
4598 const bool fabricated
= (me
->bad_rcode
< 0) ? true : false;
4599 _mdns_querier_conclude_with_response_async(me
, me
->bad_rcode_response
, fabricated
);
4602 _mdns_querier_set_current_server(me
, _mdns_querier_get_eligible_server(me
));
4603 if (!me
->current_server
) {
4604 os_log_debug(_mdns_resolver_log(),
4605 "%{public}sNo more eligible servers", _mdns_querier_get_log_label(me
));
4609 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND || MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
4610 bool check_qtype_support
= false;
4612 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND
4613 } else if (_mdns_resolver_use_mixed_up_responses_workaround(me
->resolver
)) {
4614 check_qtype_support
= true;
4616 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
4617 } else if (_mdns_resolver_use_problematic_qtype_workaround(me
->resolver
)) {
4618 check_qtype_support
= true;
4621 if (check_qtype_support
) {
4622 const mdns_server_t server
= me
->current_server
;
4623 const int qtype
= mdns_querier_get_qtype(me
);
4624 if (!_mdns_server_supports_qtype(server
, qtype
)) {
4626 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND
4627 } else if (server
->mixes_up_responses
) {
4628 os_log_info(_mdns_resolver_log(),
4629 "%{public}sNot sending query to server %@, which mixes up responses of type %{mdns:rrtype}d",
4630 _mdns_querier_get_log_label(me
), server
, qtype
);
4633 os_log_info(_mdns_resolver_log(),
4634 "%{public}sNot sending query to server %@, which ignores queries of type %{mdns:rrtype}d",
4635 _mdns_querier_get_log_label(me
), server
, qtype
);
4637 if (!me
->bad_rcode_response
) {
4639 const int rcode
= kDNSRCode_NotImp
;
4640 me
->bad_rcode_response
= _mdns_create_empty_response_for_query(me
->query
, rcode
, &err
);
4641 require_return_action(me
->bad_rcode_response
, _mdns_querier_conclude_with_error_async(me
, err
));
4642 me
->bad_rcode
= -rcode
;
4644 me
->bad_rcode_bitmap
|= _mdns_rank_to_bitmask(server
->rank
);
4645 _mdns_querier_set_current_server(me
, NULL
);
4648 #endif // MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND || MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
4649 } while (!me
->current_server
);
4651 me
->rtx_timer
= _mdns_resolver_create_oneshot_timer(me
->rtx_interval_ms
, 5);
4652 require_return_action(me
->rtx_timer
, _mdns_querier_conclude_with_error_async(me
, kNoResourcesErr
));
4654 dispatch_source_set_event_handler(me
->rtx_timer
,
4656 dispatch_source_forget(&me
->rtx_timer
);
4657 _mdns_querier_handle_no_response(me
);
4659 dispatch_activate(me
->rtx_timer
);
4661 mdns_session_t session
;
4662 if (me
->use_shared_stream
) {
4663 session
= _mdns_querier_get_shared_session(me
);
4665 session
= _mdns_querier_get_unshared_session(me
);
4668 _mdns_querier_send_query(me
, session
);
4672 #define MDNS_RESOLVER_STREAM_LATENESS_TIME_MS (10 * kMillisecondsPerSecond)
4674 static mdns_session_t
4675 _mdns_querier_get_shared_session(const mdns_querier_t me
)
4677 require_return_value(me
->current_server
, NULL
);
4679 const mdns_server_t server
= me
->current_server
;
4680 mdns_session_t session
= server
->shared_stream_session
;
4682 os_log_debug(_mdns_resolver_log(),
4683 "%{public}sCreating shared session to %@", _mdns_querier_get_log_label(me
), server
);
4685 session
= _mdns_resolver_create_session(me
->resolver
, server
, true, NULL
, NULL
, &err
);
4686 if (likely(session
)) {
4687 static const mdns_session_callbacks_t s_resolver_callbacks
= {
4688 .handle_event
= _mdns_resolver_session_handle_event
,
4689 .receive
= _mdns_resolver_session_receive
,
4690 .finalize_context
= _mdns_session_finalize_context_with_release
4692 mdns_retain(me
->resolver
);
4693 _mdns_session_set_callbacks(session
, &s_resolver_callbacks
, me
->resolver
);
4694 _mdns_session_set_lateness_time(session
, MDNS_RESOLVER_STREAM_LATENESS_TIME_MS
);
4695 _mdns_session_activate(session
);
4696 server
->shared_stream_session
= session
;
4698 os_log_error(_mdns_resolver_log(),
4699 "Failed to create session to %@ for resolver: %{mdns:err}ld", server
, (long)err
);
4700 _mdns_resolver_penalize_server(me
->resolver
, server
);
4701 _mdns_querier_set_current_server(me
, NULL
);
4707 static mdns_session_t
4708 _mdns_querier_get_unshared_session(const mdns_querier_t me
)
4710 require_return_value(me
->current_server
, NULL
);
4712 const mdns_server_t server
= me
->current_server
;
4713 mdns_session_t session
;
4714 mdns_session_t
*ptr
= me
->use_stream
? &me
->stream_session_list
: &me
->dgram_session_list
;
4715 while ((session
= *ptr
) != NULL
) {
4716 if (session
->server
== server
) {
4719 ptr
= &session
->next
;
4722 os_log_debug(_mdns_resolver_log(),
4723 "%{public}sCreating session to %@", _mdns_querier_get_log_label(me
), server
);
4725 session
= _mdns_resolver_create_session(me
->resolver
, server
, me
->use_stream
, &me
->delegation
,
4726 mdns_query_message_get_qname(me
->query
), &err
);
4727 if (likely(session
)) {
4728 static const mdns_session_callbacks_t s_querier_callbacks
= {
4729 .handle_event
= _mdns_querier_session_handle_event
,
4730 .receive
= _mdns_querier_session_receive
,
4731 .finalize_context
= _mdns_session_finalize_context_with_release
4734 _mdns_session_set_callbacks(session
, &s_querier_callbacks
, me
);
4735 if (me
->use_stream
) {
4736 _mdns_session_set_lateness_time(session
, MDNS_RESOLVER_STREAM_LATENESS_TIME_MS
);
4738 _mdns_session_activate(session
);
4741 os_log_error(_mdns_resolver_log(),
4742 "Failed to create session to %@ for querier: %{mdns:err}ld", server
, (long)err
);
4743 _mdns_resolver_penalize_server(me
->resolver
, server
);
4744 _mdns_querier_set_current_server(me
, NULL
);
4750 //======================================================================================================================
4753 _mdns_querier_start(const mdns_querier_t me
)
4755 _mdns_querier_set_current_server(me
, NULL
);
4756 if (me
->use_stream
) {
4757 me
->rtx_interval_ms
= MDNS_RESOLVER_CONNECTION_TIMEOUT_MS
;
4759 me
->rtx_interval_ms
= me
->resolver
->initial_dgram_rtx_ms
;
4761 _mdns_querier_initiate_send(me
);
4764 //======================================================================================================================
4767 _mdns_querier_send_query_immediate(mdns_querier_t querier
, mdns_session_t session
);
4770 _mdns_querier_log_query_send(mdns_querier_t querier
, mdns_session_t session
);
4772 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
4774 _mdns_querier_log_test_query_send(mdns_querier_t querier
, mdns_session_t session
);
4777 _mdns_querier_needs_test_query(mdns_querier_t querier
, mdns_server_t server
);
4781 _mdns_querier_send_query(const mdns_querier_t me
, const mdns_session_t session
)
4783 const uint32_t bitmask
= _mdns_rank_to_bitmask(session
->server
->rank
);
4784 if (_mdns_session_is_ready(session
)) {
4785 me
->will_send_bitmap
&= ~bitmask
;
4786 if (_mdns_session_is_bytestream(session
)) {
4787 if ((me
->did_send_bitmap
& bitmask
) == 0) {
4788 _mdns_querier_send_query_immediate(me
, session
);
4789 me
->did_send_bitmap
|= bitmask
;
4792 _mdns_querier_send_query_immediate(me
, session
);
4793 me
->did_send_bitmap
|= bitmask
;
4796 me
->will_send_bitmap
|= bitmask
;
4801 _mdns_querier_send_query_immediate(const mdns_querier_t me
, const mdns_session_t session
)
4803 const uint16_t qtype
= mdns_query_message_get_qtype(me
->query
);
4804 _mdns_session_send(session
, mdns_message_get_dispatch_data(me
->query
), qtype
);
4805 atomic_fetch_add(&me
->send_count
, 1);
4806 _mdns_querier_log_query_send(me
, session
);
4807 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
4808 if (_mdns_resolver_use_problematic_qtype_workaround(me
->resolver
)) {
4809 const mdns_server_t server
= session
->server
;
4810 if (_mdns_querier_needs_test_query(me
, server
)) {
4811 if (!me
->test_query
) {
4812 me
->test_query
= _mdns_create_simple_test_query(me
->query
, _mdns_server_get_test_query_qtype(server
));
4814 if (me
->test_query
) {
4815 _mdns_session_send(session
, mdns_message_get_dispatch_data(me
->test_query
),
4816 mdns_query_message_get_qtype(me
->test_query
));
4817 ++me
->test_send_count
;
4818 _mdns_querier_log_test_query_send(me
, session
);
4820 os_log_error(_mdns_resolver_log(),
4821 "%{public}sFailed to create test query", _mdns_querier_get_log_label(me
));
4829 _mdns_querier_log_query_send(const mdns_querier_t me
, const mdns_session_t session
)
4831 const size_t query_len
= mdns_message_get_length(me
->query
);
4832 os_log(_mdns_resolver_log(),
4833 "%{public}sSent %zu-byte query #%u to %@ over %{public}s via %{public}s -- %{public,mdns:dnshdr}.*P, %@",
4834 _mdns_querier_get_log_label(me
),
4838 _mdns_resolver_get_protocol_log_string(me
->resolver
, _mdns_session_is_bytestream(session
)),
4839 _mdns_resolver_get_interface_log_string(me
->resolver
),
4840 (int)Min(query_len
, kDNSHeaderLength
), mdns_message_get_byte_ptr(me
->query
),
4844 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
4846 _mdns_querier_log_test_query_send(const mdns_querier_t me
, const mdns_session_t session
)
4848 require_return(me
->test_query
);
4849 const size_t query_len
= mdns_message_get_length(me
->test_query
);
4850 os_log(_mdns_resolver_log(),
4851 "%{public}sSent %zu-byte test query #%u to %@ over %{public}s via %{public}s -- %{public,mdns:dnshdr}.*P, %@",
4852 _mdns_querier_get_log_label(me
),
4854 me
->test_send_count
,
4856 _mdns_resolver_get_protocol_log_string(me
->resolver
, _mdns_session_is_bytestream(session
)),
4857 _mdns_resolver_get_interface_log_string(me
->resolver
),
4858 (int)Min(query_len
, kDNSHeaderLength
), mdns_message_get_byte_ptr(me
->test_query
),
4863 _mdns_querier_needs_test_query(const mdns_querier_t me
, const mdns_server_t server
)
4865 if (server
->responds_to_problematics
) {
4868 const int qtype
= mdns_query_message_get_qtype(me
->query
);
4869 if (!_mdns_qtype_is_problematic(qtype
)) {
4872 if (_mdns_querier_test_query_got_response(me
, server
)) {
4875 if (server
->pqw_info
&& !_pqw_info_can_accept_qname(server
->pqw_info
, mdns_query_message_get_qname(me
->query
))) {
4882 //======================================================================================================================
4885 _mdns_querier_get_log_label(const mdns_querier_t me
)
4887 return (me
->log_label
? me
->log_label
: "");
4890 //======================================================================================================================
4893 _mdns_querier_reset_time_limit(const mdns_querier_t me
)
4896 require_action_quiet(!me
->concluded
&& me
->activated
, exit
, err
= kNoErr
);
4898 os_log_info(_mdns_resolver_log(),
4899 "%{public}sResetting time limit to %ld ms", _mdns_querier_get_log_label(me
), (long)me
->time_limit_ms
);
4900 dispatch_source_forget(&me
->timeout_timer
);
4901 require_action_quiet(me
->time_limit_ms
>= 0, exit
, err
= kTimeoutErr
);
4903 if (me
->time_limit_ms
> 0) {
4904 me
->timeout_timer
= _mdns_resolver_create_oneshot_timer((uint32_t)me
->time_limit_ms
, 5);
4905 require_action_quiet(me
->timeout_timer
, exit
, err
= kNoResourcesErr
);
4907 dispatch_source_set_event_handler(me
->timeout_timer
,
4909 _mdns_querier_conclude(me
, mdns_querier_result_type_timeout
);
4911 dispatch_activate(me
->timeout_timer
);
4919 //======================================================================================================================
4921 #define MDNS_QUERIER_UNANSWERED_QUERY_COUNT_MAX 2
4922 #define MDNS_QUERIER_RTX_INTERVAL_MAX_MS (120 * kMillisecondsPerSecond)
4925 _mdns_querier_handle_no_response(const mdns_querier_t me
)
4927 if (me
->current_server
) {
4928 if (me
->use_stream
) {
4929 _mdns_resolver_penalize_server(me
->resolver
, me
->current_server
);
4930 _mdns_querier_set_current_server(me
, NULL
);
4932 ++me
->unanswered_query_count
;
4933 if (me
->rtx_interval_ms
<= (MDNS_QUERIER_RTX_INTERVAL_MAX_MS
/ 2)) {
4934 me
->rtx_interval_ms
*= 2;
4936 me
->rtx_interval_ms
= MDNS_QUERIER_RTX_INTERVAL_MAX_MS
;
4938 if (me
->unanswered_query_count
>= MDNS_QUERIER_UNANSWERED_QUERY_COUNT_MAX
) {
4939 mdns_session_t session
= me
->dgram_session_list
;
4940 while (session
&& (session
->server
!= me
->current_server
)) {
4941 session
= session
->next
;
4944 const mdns_server_t server
= me
->current_server
;
4945 _mdns_resolver_penalize_unresponsive_server(me
->resolver
, server
, me
, session
->last_send_ticks
);
4946 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
4947 _mdns_querier_set_test_query_got_response(me
, server
, false);
4950 _mdns_querier_set_current_server(me
, NULL
);
4954 _mdns_querier_initiate_send(me
);
4957 //======================================================================================================================
4960 _mdns_querier_set_current_server(const mdns_querier_t me
, const mdns_server_t server
)
4962 me
->current_server
= server
;
4963 me
->unanswered_query_count
= 0;
4964 if (!me
->use_stream
&& me
->current_server
) {
4965 const uint32_t bitmask
= _mdns_rank_to_bitmask(me
->current_server
->rank
);
4966 if ((me
->did_send_bitmap
& bitmask
) == 0) {
4967 me
->rtx_interval_ms
= me
->resolver
->initial_dgram_rtx_ms
;
4972 //======================================================================================================================
4974 static mdns_server_t
4975 _mdns_querier_get_eligible_server(const mdns_querier_t me
)
4977 uint32_t exclude_bitmap
= me
->bad_rcode_bitmap
;
4978 if (me
->use_stream
) {
4979 exclude_bitmap
|= me
->will_send_bitmap
;
4980 exclude_bitmap
|= me
->did_send_bitmap
;
4982 mdns_server_t server
= _mdns_resolver_get_server(me
->resolver
, exclude_bitmap
);
4983 if (server
&& me
->resolver
->probe_querier
&& (me
!= me
->resolver
->probe_querier
)) {
4984 os_log(_mdns_resolver_log(),
4985 "%{public}sBacking off while probe querier is active", _mdns_querier_get_log_label(me
));
4991 //======================================================================================================================
4993 static mdns_server_t
4994 _mdns_querier_get_unpenalized_eligible_server(const mdns_querier_t me
)
4996 const mdns_server_t server
= _mdns_querier_get_eligible_server(me
);
4997 return ((server
&& !server
->penalized
) ? server
: NULL
);
5000 //======================================================================================================================
5003 _mdns_querier_handle_stream_error(const mdns_querier_t me
, const mdns_server_t server
)
5005 const uint32_t bitmask
= _mdns_rank_to_bitmask(server
->rank
);
5006 me
->will_send_bitmap
&= ~bitmask
;
5007 me
->did_send_bitmap
&= ~bitmask
;
5008 if (me
->current_server
== server
) {
5009 _mdns_querier_set_current_server(me
, _mdns_querier_get_unpenalized_eligible_server(me
));
5010 if (me
->current_server
) {
5011 _mdns_querier_initiate_send(me
);
5013 } else if (!me
->current_server
&& !me
->rtx_timer
) {
5014 _mdns_querier_initiate_send(me
);
5018 //======================================================================================================================
5021 _mdns_querier_handle_bad_rcode(const mdns_querier_t me
, const mdns_message_t response
, const int rcode
,
5022 const mdns_server_t server
)
5024 me
->bad_rcode_bitmap
|= _mdns_rank_to_bitmask(server
->rank
);
5025 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND || MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
5026 if (me
->bad_rcode
< 0) {
5027 mdns_forget(&me
->bad_rcode_response
);
5031 // Save the response if it's the first bad RCODE response that's been received.
5032 // Only replace the saved bad RCODE response if its RCODE is Refused and the newer response's RCODE is not
5033 // Refused. This way, if there's a server that consistently returns Refused, its responses won't mask a bad
5034 // RCODE response with a potentially more informative RCODE.
5035 if (!me
->bad_rcode_response
|| ((me
->bad_rcode
== kDNSRCode_Refused
) && (rcode
!= kDNSRCode_Refused
))) {
5036 mdns_replace(&me
->bad_rcode_response
, response
);
5037 me
->bad_rcode
= rcode
;
5039 if (rcode
== kDNSRCode_Refused
) {
5040 _mdns_resolver_penalize_server(me
->resolver
, server
);
5042 // If there are any servers that haven't returned a bad RCODE, then move on to the next server.
5043 // Otherwise, conclude with the saved bad RCODE response.
5044 if (_mdns_resolver_get_server(me
->resolver
, me
->bad_rcode_bitmap
)) {
5045 if (me
->current_server
== server
) {
5046 _mdns_querier_set_current_server(me
, NULL
);
5047 _mdns_querier_initiate_send(me
);
5050 const mdns_message_t bad_rcode_response
= me
->bad_rcode_response
;
5051 me
->bad_rcode_response
= NULL
;
5052 _mdns_querier_conclude_with_response(me
, bad_rcode_response
);
5053 mdns_release(bad_rcode_response
);
5057 //======================================================================================================================
5059 static const uint8_t *
5060 _mdns_querier_get_response_ptr_safe(const mdns_querier_t me
)
5062 return (me
->response
? mdns_message_get_byte_ptr(me
->response
) : NULL
);
5065 //======================================================================================================================
5068 _mdns_querier_get_response_length_safe(const mdns_querier_t me
)
5070 return (me
->response
? mdns_message_get_length(me
->response
) : 0);
5073 //======================================================================================================================
5075 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
5077 _mdns_querier_set_test_query_got_response(const mdns_querier_t me
, const mdns_server_t server
, const bool got_response
)
5079 const uint32_t bitmask
= _mdns_rank_to_bitmask(server
->rank
);
5081 me
->test_query_resp_bitmap
|= bitmask
;
5083 me
->test_query_resp_bitmap
&= ~bitmask
;
5087 //======================================================================================================================
5090 _mdns_querier_test_query_got_response(const mdns_querier_t me
, const mdns_server_t server
)
5092 return ((me
->test_query_resp_bitmap
& _mdns_rank_to_bitmask(server
->rank
)) ? true : false);
5096 //======================================================================================================================
5097 // MARK: - Helper Functions
5099 static dispatch_queue_t
5100 _mdns_resolver_queue(void)
5102 static dispatch_once_t s_once
= 0;
5103 static dispatch_queue_t s_queue
= NULL
;
5105 dispatch_once(&s_once
,
5107 s_queue
= dispatch_queue_create("com.apple.mdns.resolver-queue", DISPATCH_QUEUE_SERIAL
);
5108 http_set_resolver_queue(s_queue
);
5113 //======================================================================================================================
5116 _mdns_message_is_query_response_ignoring_id(const uint8_t * const msg_ptr
, const size_t msg_len
,
5117 const mdns_query_message_t query
, uint16_t *out_id
)
5119 uint16_t tmp_id
= 0;
5120 return _mdns_message_is_query_response_ex(msg_ptr
, msg_len
, query
, out_id
? out_id
: &tmp_id
, NULL
, false);
5123 //======================================================================================================================
5125 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND
5127 _mdns_message_is_query_response_ignoring_qtype(const mdns_message_t msg
, const mdns_query_message_t query
,
5128 uint16_t * const out_qtype
)
5130 uint16_t tmp_qtype
= 0;
5131 return _mdns_message_is_query_response_ex(mdns_message_get_byte_ptr(msg
), mdns_message_get_length(msg
), query
,
5132 NULL
, out_qtype
? out_qtype
: &tmp_qtype
, false);
5136 //======================================================================================================================
5139 _mdns_message_is_query_response_ex(const uint8_t * const msg_ptr
, const size_t msg_len
,
5140 const mdns_query_message_t query
, uint16_t * const out_id
, uint16_t * const out_qtype
, const bool ignore_qnames
)
5142 require_return_value(msg_len
>= kDNSHeaderLength
, false);
5144 const DNSHeader
* const hdr
= (const DNSHeader
*)msg_ptr
;
5145 const uint16_t msg_id
= DNSHeaderGetID(hdr
);
5146 require_return_value(out_id
|| (msg_id
== mdns_query_message_get_message_id(query
)), false);
5148 const unsigned int flags
= DNSHeaderGetFlags(hdr
);
5149 require_return_value(flags
& kDNSHeaderFlag_Response
, false);
5150 require_return_value(DNSFlagsGetOpCode(flags
) == kDNSOpCode_Query
, false);
5151 require_return_value(DNSHeaderGetQuestionCount(hdr
) == 1, false);
5153 uint16_t qtype
, qclass
;
5154 uint8_t qname
[kDomainNameLengthMax
];
5155 const uint8_t * const qptr
= (const uint8_t *)&hdr
[1];
5156 const OSStatus err
= DNSMessageExtractQuestion(msg_ptr
, msg_len
, qptr
, qname
, &qtype
, &qclass
, NULL
);
5157 require_return_value(!err
, false);
5158 require_return_value(ignore_qnames
|| DomainNameEqual(qname
, mdns_query_message_get_qname(query
)), false);
5159 require_return_value(out_qtype
|| (qtype
== mdns_query_message_get_qtype(query
)), false);
5160 require_return_value(qclass
== mdns_query_message_get_qclass(query
), false);
5170 //======================================================================================================================
5172 static nw_parameters_t
5173 _mdns_create_udp_parameters(OSStatus
*out_error
)
5176 nw_parameters_t params
= nw_parameters_create_secure_udp(NW_PARAMETERS_DISABLE_PROTOCOL
,
5177 NW_PARAMETERS_DEFAULT_CONFIGURATION
);
5178 require_action_quiet(params
, exit
, err
= kNoResourcesErr
);
5189 //======================================================================================================================
5191 static nw_parameters_t
5192 _mdns_create_tcp_parameters(OSStatus
*out_error
)
5195 nw_parameters_t params
= nw_parameters_create_secure_tcp(NW_PARAMETERS_DISABLE_PROTOCOL
,
5196 NW_PARAMETERS_DEFAULT_CONFIGURATION
);
5197 require_action_quiet(params
, exit
, err
= kNoResourcesErr
);
5199 nw_parameters_set_indefinite(params
, false);
5201 err
= _mdns_add_dns_over_bytestream_framer(params
);
5202 require_noerr_quiet(err
, exit
);
5214 //======================================================================================================================
5216 static nw_protocol_definition_t
5217 _mdns_copy_dns_over_bytestream_framer(void);
5220 _mdns_add_dns_over_bytestream_framer(nw_parameters_t params
)
5223 nw_protocol_definition_t framer_def
= NULL
;
5224 nw_protocol_options_t framer_opts
= NULL
;
5226 nw_protocol_stack_t stack
= nw_parameters_copy_default_protocol_stack(params
);
5227 require_action_quiet(stack
, exit
, err
= kNoResourcesErr
);
5229 framer_def
= _mdns_copy_dns_over_bytestream_framer();
5230 require_action_quiet(framer_def
, exit
, err
= kNoResourcesErr
);
5232 framer_opts
= nw_framer_create_options(framer_def
);
5233 require_action_quiet(framer_opts
, exit
, err
= kNoResourcesErr
);
5235 nw_protocol_stack_prepend_application_protocol(stack
, framer_opts
);
5239 nw_release_null_safe(stack
);
5240 nw_release_null_safe(framer_def
);
5241 nw_release_null_safe(framer_opts
);
5245 static nw_protocol_definition_t
5246 _mdns_create_dns_over_bytestream_framer(void);
5248 static nw_protocol_definition_t
5249 _mdns_copy_dns_over_bytestream_framer(void)
5251 static dispatch_once_t s_once
= 0;
5252 static nw_protocol_definition_t s_framer_def
= NULL
;
5254 dispatch_once(&s_once
,
5256 s_framer_def
= _mdns_create_dns_over_bytestream_framer();
5258 if (likely(s_framer_def
)) {
5259 nw_retain(s_framer_def
);
5261 return s_framer_def
;
5264 static nw_protocol_definition_t
5265 _mdns_create_dns_over_bytestream_framer(void)
5267 static const nw_framer_input_handler_t input_handler
=
5268 ^ size_t (nw_framer_t framer
)
5271 uint8_t length_buf
[2];
5272 bool ok
= nw_framer_parse_input(framer
, sizeof(length_buf
), sizeof(length_buf
), length_buf
,
5273 ^ size_t (__unused
uint8_t *buf_ptr
, size_t buf_len
, __unused
bool is_complete
)
5275 return ((buf_len
>= sizeof(length_buf
)) ? sizeof(length_buf
) : 0);
5278 return sizeof(length_buf
);
5280 const size_t msg_len
= ReadBig16(length_buf
);
5281 nw_framer_message_t msg
= nw_framer_message_create(framer
);
5282 ok
= nw_framer_deliver_input_no_copy(framer
, msg_len
, msg
, true);
5285 return sizeof(length_buf
);
5289 static const nw_framer_output_handler_t output_handler
=
5290 ^(nw_framer_t framer
, __unused nw_framer_message_t msg
, size_t msg_len
, __unused
bool is_complete
)
5292 if (msg_len
> UINT16_MAX
) {
5293 nw_framer_mark_failed_with_error(framer
, EMSGSIZE
);
5296 uint8_t length_buf
[2];
5297 WriteBig16(length_buf
, msg_len
);
5298 nw_framer_write_output(framer
, length_buf
, sizeof(length_buf
));
5299 nw_framer_write_output_no_copy(framer
, msg_len
);
5301 nw_protocol_definition_t framer_def
= nw_framer_create_definition("DNS over byte-stream",
5302 NW_FRAMER_CREATE_FLAGS_DEFAULT
,
5303 ^ nw_framer_start_result_t (nw_framer_t framer
)
5305 nw_framer_set_input_handler(framer
, input_handler
);
5306 nw_framer_set_output_handler(framer
, output_handler
);
5307 return nw_framer_start_result_ready
;
5312 //======================================================================================================================
5315 _mdns_ticks_per_second(void)
5317 return mdns_mach_ticks_per_second();
5320 //======================================================================================================================
5323 _mdns_path_to_server_is_usable(const nw_path_t path
, bool encrypted_resolver
)
5325 const nw_path_status_t status
= nw_path_get_status(path
);
5326 if ((status
== nw_path_status_satisfied
) || (status
== nw_path_status_satisfiable
)) {
5328 } else if (nw_path_is_per_app_vpn(path
)) {
5329 // For Per-App VPN, assume that the path to the server is usable since such paths will only have a
5330 // satisfied status if the right per-app parameters are provided to the path evaluator. For VPNs, it's
5331 // very likely that the DNS server addresses provided by the VPN configuration are reachable, if not, then
5332 // the server penalization logic will kick in to favor reachable server addresses over unreachable ones.
5335 // For encrypted resolvers, it is possible to use unencrypted resolvers to synthesize IPv4 addresses
5336 // on NAT64 networks.
5337 bool nat64_eligible
= false;
5338 if (encrypted_resolver
&& nw_path_has_dns(path
)) {
5339 nw_endpoint_t endpoint
= nw_path_copy_endpoint(path
);
5340 if (endpoint
!= NULL
&& nw_endpoint_get_type(endpoint
) == nw_endpoint_type_address
) {
5341 const struct sockaddr
*address
= nw_endpoint_get_address(endpoint
);
5342 if (address
!= NULL
&& address
->sa_family
== AF_INET
) {
5343 nat64_eligible
= true;
5346 nw_forget(&endpoint
);
5349 return nat64_eligible
;
5353 //======================================================================================================================
5356 _mdns_rank_to_bitmask(const unsigned int rank
)
5358 if ((rank
>= 1) && (rank
<= 32)) {
5359 return (UINT32_C(1) << (rank
- 1));
5365 //======================================================================================================================
5368 mdns_session_event_to_string(const mdns_session_event_t event
)
5371 case mdns_session_event_null
: return "null";
5372 case mdns_session_event_ready
: return "ready";
5373 case mdns_session_event_lateness_warning
: return "lateness-warning";
5374 case mdns_session_event_terminated
: return "terminated";
5375 default: return "<UNKNOWN SESSION EVENT>";
5379 //======================================================================================================================
5382 _mdns_ticks_diff(const uint64_t t1
, const uint64_t t2
)
5384 return ((int64_t)(t1
- t2
));
5387 //======================================================================================================================
5390 _mdns_ticks_to_whole_seconds(const uint64_t ticks
)
5392 return (ticks
/ _mdns_ticks_per_second());
5395 //======================================================================================================================
5398 _mdns_ticks_to_fractional_milliseconds(const uint64_t ticks
)
5400 const uint64_t remainder
= ticks
% _mdns_ticks_per_second();
5401 return ((remainder
* kMillisecondsPerSecond
) / _mdns_ticks_per_second());
5404 //======================================================================================================================
5406 static dispatch_source_t
5407 _mdns_resolver_create_oneshot_timer(const uint32_t time_ms
, const unsigned int leeway_percent_numerator
)
5409 const dispatch_source_t timer
= dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER
, 0, 0, _mdns_resolver_queue());
5410 require_quiet(timer
, exit
);
5412 const unsigned int numerator
= Min(leeway_percent_numerator
, 100);
5413 const uint64_t leeway_ns
= time_ms
* (numerator
* (UINT64_C_safe(kNanosecondsPerMillisecond
) / 100));
5414 dispatch_source_set_timer(timer
, _dispatch_monotonictime_after_msec(time_ms
), DISPATCH_TIME_FOREVER
, leeway_ns
);
5420 //======================================================================================================================
5423 _mdns_rcode_is_good(const int rcode
)
5425 return ((rcode
== kDNSRCode_NoError
) || (rcode
== kDNSRCode_NXDomain
) || (rcode
== kDNSRCode_NotAuth
));
5428 //======================================================================================================================
5430 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND || MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
5432 _mdns_qtype_is_problematic(const int qtype
)
5434 return ((qtype
== kDNSRecordType_HTTPS
) || (qtype
== kDNSRecordType_SVCB
));
5437 //======================================================================================================================
5439 static mdns_message_t
5440 _mdns_create_empty_response_for_query(const mdns_query_message_t query
, const int rcode
, OSStatus
* const out_error
)
5442 mdns_message_t response_msg
= NULL
;
5444 const size_t len
= mdns_message_get_length(query
);
5445 require_action_quiet(len
> kDNSHeaderLength
, exit
, err
= kInternalErr
);
5447 uint8_t *response_ptr
= malloc(len
);
5448 require_action_quiet(response_ptr
, exit
, err
= kNoMemoryErr
);
5450 memcpy(response_ptr
, mdns_message_get_byte_ptr(query
), len
);
5451 unsigned int flags
= 0;
5452 flags
|= kDNSHeaderFlag_Response
;
5453 DNSFlagsSetOpCode(flags
, kDNSOpCode_Query
);
5454 flags
|= kDNSHeaderFlag_RecursionDesired
;
5455 flags
|= kDNSHeaderFlag_RecursionAvailable
;
5456 DNSFlagsSetRCode(flags
, rcode
);
5457 DNSHeaderSetFlags((DNSHeader
*)response_ptr
, flags
);
5459 dispatch_data_t response_data
= dispatch_data_create(response_ptr
, len
, NULL
, DISPATCH_DATA_DESTRUCTOR_FREE
);
5460 require_action_quiet(response_data
, exit
, ForgetMem(&response_ptr
); err
= kNoResourcesErr
);
5461 response_ptr
= NULL
;
5463 response_msg
= mdns_message_create_with_dispatch_data(response_data
,
5464 mdns_message_init_option_disable_header_printing
);
5465 dispatch_forget(&response_data
);
5466 require_action_quiet(response_msg
, exit
, err
= kNoResourcesErr
);
5473 return response_msg
;
5475 #endif // MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND || MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
5477 //======================================================================================================================
5479 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
5480 static mdns_query_message_t
5481 _mdns_create_simple_test_query(const mdns_query_message_t query
, const uint16_t qtype
)
5483 mdns_query_message_t result
= NULL
;
5484 mdns_query_message_t test_query
= mdns_query_message_create(mdns_message_init_option_disable_header_printing
);
5485 require_quiet(test_query
, exit
);
5487 OSStatus err
= mdns_query_message_set_qname(test_query
, mdns_query_message_get_qname(query
));
5488 require_noerr_quiet(err
, exit
);
5490 mdns_query_message_set_qtype(test_query
, qtype
);
5491 mdns_query_message_set_qclass(test_query
, mdns_query_message_get_qclass(query
));
5492 uint16_t msg_id
= (uint16_t)RandomRange(1, UINT16_MAX
);
5493 // Make sure that the test query's ID is different from the original query's ID.
5494 if (msg_id
== mdns_query_message_get_message_id(query
)) {
5500 mdns_query_message_set_message_id(test_query
, msg_id
);
5501 err
= mdns_query_message_construct(test_query
);
5502 require_noerr_quiet(err
, exit
);
5504 result
= test_query
;
5508 mdns_forget(&test_query
);
5512 //======================================================================================================================
5515 _mdns_message_is_adequate_test_query_response(const mdns_message_t msg
, const mdns_query_message_t query
)
5517 return _mdns_message_is_query_response_ex(mdns_message_get_byte_ptr(msg
), mdns_message_get_length(msg
), query
,
5521 //======================================================================================================================
5524 _pqw_info_create(const unsigned int threshold
)
5526 pqw_info_t
*info
= (pqw_info_t
*)calloc(1, sizeof(*info
));
5527 require_return_value(info
, NULL
);
5528 info
->threshold
= threshold
;
5532 //======================================================================================================================
5535 _pqw_info_free(pqw_info_t
* const info
)
5537 _pqw_qname_list_forget(&info
->qname_list
);
5541 //======================================================================================================================
5544 _pqw_info_threshold_reached(const pqw_info_t
* const info
)
5546 return ((info
->qname_count
< info
->threshold
) ? false : true);
5549 //======================================================================================================================
5552 _pqw_info_can_accept_qname(const pqw_info_t
* const info
, const uint8_t * const qname
)
5554 if (_pqw_info_threshold_reached(info
)) {
5557 for (const pqw_qname_item_t
*item
= info
->qname_list
; item
; item
= item
->next
) {
5558 if (DomainNameEqual(item
->qname
, qname
)) {
5565 //======================================================================================================================
5567 static pqw_qname_item_t
*
5568 _pqw_qname_item_create(const uint8_t * const qname
, OSStatus
* const out_error
)
5570 pqw_qname_item_t
*result
= NULL
;
5572 pqw_qname_item_t
*item
= (pqw_qname_item_t
*)calloc(1, sizeof(*item
));
5573 require_action_quiet(item
, exit
, err
= kNoMemoryErr
);
5575 err
= DomainNameDup(qname
, &item
->qname
, NULL
);
5576 require_noerr_quiet(err
, exit
);
5585 _pqw_qname_item_forget(&item
);
5589 //======================================================================================================================
5592 _pqw_qname_item_free(pqw_qname_item_t
* const item
)
5594 ForgetMem(&item
->qname
);
5598 //======================================================================================================================
5601 _pqw_qname_list_free(pqw_qname_item_t
*list
)
5603 pqw_qname_item_t
*item
;
5604 while ((item
= list
) != NULL
) {
5606 _pqw_qname_item_free(item
);
5609 #endif // MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
5611 //======================================================================================================================
5613 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND
5615 _mdns_qtype_is_address_type(const int qtype
)
5617 return ((qtype
== kDNSRecordType_A
) || (qtype
== kDNSRecordType_AAAA
));