1 /*
2 * Copyright (c) 2019-2020 Apple Inc. All rights reserved.
3 *
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
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17 #include "mdns_internal.h"
18 #include "mdns_resolver.h"
19
20 #include "mdns_helpers.h"
21 #include "mdns_message.h"
22 #include "mdns_objects.h"
23 #include "mdns_symptoms.h"
24
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>
31
32 //======================================================================================================================
33 // MARK: - Resolver Kind Definition
34
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]
59 #endif
60 };
61
62 // Notes:
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.
68
69 MDNS_OBJECT_SUBKIND_DEFINE_ABSTRACT(resolver);
70
71 typedef union {
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__));
78
79 typedef OSStatus
80 (*mdns_resolver_set_provider_name_f)(mdns_any_resolver_t resolver, const char *provider_name);
81
82 typedef void
83 (*mdns_resolver_set_port_f)(mdns_any_resolver_t resolver, uint16_t port);
84
85 typedef OSStatus
86 (*mdns_resolver_set_url_path_f)(mdns_any_resolver_t resolver, const char *url_path);
87
88 typedef nw_parameters_t
89 (*mdns_resolver_get_datagram_params_f)(mdns_any_resolver_t resolver, OSStatus *out_error);
90
91 typedef nw_parameters_t
92 (*mdns_resolver_get_stream_params_f)(mdns_any_resolver_t resolver, OSStatus *out_error);
93
94 typedef nw_endpoint_t
95 (*mdns_resolver_create_hostname_endpoint_f)(mdns_any_resolver_t resolver);
96
97 typedef const struct mdns_resolver_kind_s * mdns_resolver_kind_t;
98 struct mdns_resolver_kind_s {
99 struct mdns_kind_s base;
100 const char * name;
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;
111 bool stream_only;
112 bool needs_edns0_padding;
113 bool needs_zero_ids;
114 bool suspicious_reply_defense;
115 bool no_stream_session_sharing;
116 };
117
118 #define MDNS_RESOLVER_SUBKIND_DECLARE(NAME) MDNS_DECL_SUBKIND(NAME ## _resolver, resolver)
119 #define MDNS_RESOLVER_SUBKIND_DEFINE(NAME, ...) \
120 static void \
121 _mdns_ ## NAME ## _resolver_finalize(mdns_ ## NAME ## _resolver_t resolver); \
122 \
123 static const struct mdns_resolver_kind_s _mdns_ ## NAME ## _resolver_kind = { \
124 .base = { \
125 .superkind = &_mdns_resolver_kind, \
126 .name = "mdns_" # NAME "_resolver", \
127 .finalize = _mdns_ ## NAME ## _resolver_finalize \
128 }, \
129 .name = # NAME "_resolver", \
130 .type = mdns_resolver_type_ ## NAME, \
131 __VA_ARGS__ \
132 }; \
133 \
134 static mdns_resolver_t \
135 _mdns_ ## NAME ## _resolver_alloc(void) \
136 { \
137 mdns_resolver_t obj = mdns_resolver_object_alloc(sizeof(struct mdns_ ## NAME ## _resolver_s)); \
138 require_quiet(obj, exit); \
139 \
140 const mdns_object_t object = (mdns_object_t)obj; \
141 object->kind = &_mdns_ ## NAME ## _resolver_kind.base; \
142 \
143 exit: \
144 return obj; \
145 } \
146 MDNS_BASE_CHECK(NAME ## _resolver, resolver)
147
148 #define MDNS_RESOLVER_SERVER_COUNT_MAX 32
149
150 //======================================================================================================================
151 // MARK: - Normal Resolver Kind Definition
152
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
156 #endif
157
158 MDNS_RESOLVER_SUBKIND_DECLARE(normal);
159
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.
164 };
165
166 static nw_parameters_t
167 _mdns_normal_resolver_get_datagram_params(mdns_normal_resolver_t resolver, OSStatus *out_error);
168
169 static nw_parameters_t
170 _mdns_normal_resolver_get_stream_params(mdns_normal_resolver_t resolver, OSStatus *out_error);
171
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
179 );
180
181 //======================================================================================================================
182 // MARK: - TCP-Only Resolver Kind Definition
183
184 MDNS_RESOLVER_SUBKIND_DECLARE(tcp);
185
186 struct mdns_tcp_resolver_s {
187 struct mdns_resolver_s base; // Resolver object base.
188 nw_parameters_t params; // TCP parameters.
189 };
190
191 static nw_parameters_t
192 _mdns_tcp_resolver_get_stream_params(mdns_tcp_resolver_t resolver, OSStatus *out_error);
193
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>.
198 .stream_only = true,
199 );
200
201 //======================================================================================================================
202 // MARK: - TLS Resolver Kind Definition
203
204 MDNS_RESOLVER_SUBKIND_DECLARE(tls);
205
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.
211 };
212
213 static OSStatus
214 _mdns_tls_resolver_set_provider_name(mdns_tls_resolver_t resolver, const char *provider_name);
215
216 static void
217 _mdns_tls_resolver_set_port(mdns_tls_resolver_t resolver, uint16_t port);
218
219 static nw_parameters_t
220 _mdns_tls_resolver_get_stream_params(mdns_tls_resolver_t resolver, OSStatus *out_error);
221
222 static nw_endpoint_t
223 _mdns_tls_resolver_create_hostname_endpoint(mdns_tls_resolver_t resolver);
224
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>.
232 .stream_only = true,
233 .needs_edns0_padding = true
234 );
235
236 //======================================================================================================================
237 // MARK: - HTTPS Resolver Kind Definition
238
239 MDNS_RESOLVER_SUBKIND_DECLARE(https);
240
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.
247 };
248
249 static OSStatus
250 _mdns_https_resolver_set_provider_name(mdns_https_resolver_t resolver, const char *provider_name);
251
252 static void
253 _mdns_https_resolver_set_port(mdns_https_resolver_t resolver, uint16_t port);
254
255 static OSStatus
256 _mdns_https_resolver_set_url_path(mdns_https_resolver_t resolver, const char *url_path);
257
258 static nw_parameters_t
259 _mdns_https_resolver_get_stream_params(mdns_https_resolver_t resolver, OSStatus *out_error);
260
261 static nw_endpoint_t
262 _mdns_https_resolver_create_hostname_endpoint(mdns_https_resolver_t resolver);
263
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>.
272 .stream_only = true,
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.
276 );
277
278 //======================================================================================================================
279 // MARK: - Server Kind Definition
280
281 #define MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND 1
282
283 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
284 typedef struct pqw_qname_item_s pqw_qname_item_t;
285
286 struct pqw_qname_item_s {
287 pqw_qname_item_t * next; // Next item in list.
288 uint8_t * qname; // QNAME.
289 };
290
291 typedef struct {
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.
295 } pqw_info_t;
296
297 // Notes:
298 // 1. When the threshold has been reached, problematic QTYPEs will no longer be sent to the server that owns this
299 // data structure.
300
301 #endif
302
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.
321 #endif
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.
326 #endif
327 };
328
329 // Notes:
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.
335
336 MDNS_OBJECT_SUBKIND_DEFINE(server);
337
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
346
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
349
350 //======================================================================================================================
351 // MARK: - Delegation
352
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.
357 );
358
359 typedef struct {
360 mdns_delegation_type_t type; // Type of delegation.
361 union {
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.
365 } mdns_delegation_t;
366
367 //======================================================================================================================
368 // MARK: - Session Kind Definition
369
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
375 );
376
377 typedef void
378 (*mdns_session_handle_event_f)(mdns_session_t session, mdns_session_event_t event, OSStatus error, void *context);
379
380 typedef void
381 (*mdns_session_receive_f)(mdns_session_t session, dispatch_data_t response, void *context);
382
383 typedef void
384 (*mdns_session_finalize_context_f)(void *context);
385
386 typedef struct {
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;
391
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
397 );
398
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).
413 };
414
415 MDNS_OBJECT_SUBKIND_DEFINE_ABSTRACT(session);
416
417 typedef union {
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__));
423
424 typedef OSStatus
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);
427
428 typedef OSStatus
429 (*mdns_session_activate_f)(mdns_any_session_t session);
430
431 typedef void
432 (*mdns_session_invalidate_f)(mdns_any_session_t session);
433
434 typedef bool
435 (*mdns_session_is_ready_f)(mdns_any_session_t session);
436
437 typedef void
438 (*mdns_session_send_f)(mdns_any_session_t session, dispatch_data_t message, uint16_t qtype);
439
440 typedef bool
441 (*mdns_session_is_bytestream_f)(mdns_any_session_t session);
442
443 typedef const struct mdns_session_kind_s * mdns_session_kind_t;
444 struct mdns_session_kind_s {
445 struct mdns_kind_s base;
446 const char * name;
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;
453 bool is_bytestream;
454 bool is_always_ready;
455 };
456
457 #define MDNS_SESSION_SUBKIND_DECLARE(NAME) MDNS_DECL_SUBKIND(NAME ## _session, session)
458 #define MDNS_SESSION_SUBKIND_DEFINE(NAME, ...) \
459 static void \
460 _mdns_ ## NAME ## _session_finalize(mdns_ ## NAME ## _session_t session); \
461 \
462 static OSStatus \
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); \
465 \
466 static OSStatus \
467 _mdns_ ## NAME ## _session_activate(mdns_ ## NAME ## _session_t session); \
468 \
469 static void \
470 _mdns_ ## NAME ## _session_invalidate(mdns_ ## NAME ## _session_t session); \
471 \
472 static void \
473 _mdns_ ## NAME ## _session_send(mdns_ ## NAME ## _session_t session, dispatch_data_t message, uint16_t qtype); \
474 \
475 static const struct mdns_session_kind_s _mdns_ ## NAME ## _session_kind = { \
476 .base = { \
477 .superkind = &_mdns_session_kind, \
478 .name = "mdns_" # NAME "_session", \
479 .finalize = _mdns_ ## NAME ## _session_finalize, \
480 }, \
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, \
486 __VA_ARGS__ \
487 }; \
488 \
489 static mdns_session_t \
490 _mdns_ ## NAME ## _session_alloc(void) \
491 { \
492 mdns_session_t obj = mdns_session_object_alloc(sizeof(struct mdns_ ## NAME ## _session_s)); \
493 require_quiet(obj, exit); \
494 \
495 const mdns_object_t object = (mdns_object_t)obj; \
496 object->kind = &_mdns_ ## NAME ## _session_kind.base; \
497 \
498 exit: \
499 return obj; \
500 } \
501 MDNS_BASE_CHECK(NAME ## _session, session)
502
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
508 );
509
510 //======================================================================================================================
511 // MARK: - Connection Session Kind Definition
512
513 MDNS_SESSION_SUBKIND_DECLARE(connection);
514
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.
519 };
520
521 static bool
522 _mdns_connection_session_is_bytestream(mdns_connection_session_t session);
523
524 MDNS_SESSION_SUBKIND_DEFINE(connection,
525 .is_bytestream_check = _mdns_connection_session_is_bytestream
526 );
527
528 //======================================================================================================================
529 // MARK: - UDP Socket Session Kind Definition
530
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
536 #endif
537
538 MDNS_SESSION_SUBKIND_DECLARE(udp_socket);
539
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;
548 #else
549 sockaddr_ip server_addr; // sockaddr containing address of server.
550 socklen_t server_addr_len; // Length of server sockaddr.
551 #endif
552 };
553
554 #if MDNS_USE_CONNECTED_UDP_SOCKETS
555 static bool
556 _mdns_udp_socket_session_is_ready(mdns_udp_socket_session_t session);
557 #endif
558
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
563 );
564 #else
565 MDNS_SESSION_SUBKIND_DEFINE(udp_socket,
566 .is_bytestream = false,
567 .is_always_ready = true
568 );
569 #endif
570
571 //======================================================================================================================
572 // MARK: - URL Session Kind Definition
573
574 MDNS_SESSION_SUBKIND_DECLARE(url);
575
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.
580 };
581
582 MDNS_SESSION_SUBKIND_DEFINE(url,
583 .is_bytestream = true,
584 .is_always_ready = true
585 );
586
587 //======================================================================================================================
588 // MARK: - Querier Kind Definition
589
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.
609 #endif
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.
629 };
630
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);
636 #endif
637
638 MDNS_OBJECT_SUBKIND_DEFINE(querier);
639
640 //======================================================================================================================
641 // MARK: - Local Prototypes
642
643 static dispatch_queue_t
644 _mdns_resolver_queue(void);
645
646 static bool
647 _mdns_message_is_query_response_ignoring_id(const uint8_t *msg_ptr, size_t msg_len, mdns_query_message_t query,
648 uint16_t *out_id);
649
650 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND
651 static bool
652 _mdns_message_is_query_response_ignoring_qtype(mdns_message_t msg, mdns_query_message_t query, uint16_t *out_qtype);
653 #endif
654
655 static bool
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);
658
659 static uint64_t
660 _mdns_ticks_per_second(void);
661
662 static bool
663 _mdns_path_to_server_is_usable(nw_path_t path, bool encrypted_resolver);
664
665 static uint32_t
666 _mdns_rank_to_bitmask(const unsigned int rank);
667
668 static const char *
669 mdns_session_event_to_string(mdns_session_event_t event);
670
671 static int64_t
672 _mdns_ticks_diff(uint64_t t1, uint64_t t2);
673
674 static uint64_t
675 _mdns_ticks_to_whole_seconds(uint64_t ticks);
676
677 static uint64_t
678 _mdns_ticks_to_fractional_milliseconds(uint64_t ticks);
679
680 static dispatch_source_t
681 _mdns_resolver_create_oneshot_timer(uint32_t time_ms, unsigned int leeway_percent_numerator);
682
683 static void
684 _mdns_querier_activate_if_ready(mdns_querier_t querier);
685
686 static void
687 _mdns_querier_initiate_send(mdns_querier_t querier);
688
689 static void
690 _mdns_querier_start(mdns_querier_t querier);
691
692 static void
693 _mdns_querier_send_query(mdns_querier_t querier, mdns_session_t session);
694
695 static const char *
696 _mdns_querier_get_log_label(mdns_querier_t querier);
697
698 static OSStatus
699 _mdns_querier_reset_time_limit(mdns_querier_t querier);
700
701 static void
702 _mdns_querier_handle_no_response(mdns_querier_t querier);
703
704 static void
705 _mdns_querier_set_current_server(mdns_querier_t querier, mdns_server_t server);
706
707 static mdns_server_t
708 _mdns_querier_get_eligible_server(mdns_querier_t querier);
709
710 static mdns_server_t
711 _mdns_querier_get_unpenalized_eligible_server(mdns_querier_t querier);
712
713 static void
714 _mdns_querier_handle_stream_error(mdns_querier_t querier, mdns_server_t server);
715
716 static void
717 _mdns_querier_handle_bad_rcode(mdns_querier_t querier, mdns_message_t response, int rcode, mdns_server_t server);
718
719 static const uint8_t *
720 _mdns_querier_get_response_ptr_safe(mdns_querier_t querier);
721
722 static size_t
723 _mdns_querier_get_response_length_safe(mdns_querier_t querier);
724
725 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
726 static void
727 _mdns_querier_set_test_query_got_response(mdns_querier_t querier, mdns_server_t server, bool got_response);
728
729 static bool
730 _mdns_querier_test_query_got_response(mdns_querier_t querier, mdns_server_t server);
731 #endif
732
733 static bool
734 _mdns_server_has_stream_problems(mdns_server_t server);
735
736 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
737 static bool
738 _mdns_server_supports_qtype(mdns_server_t server, int qtype);
739
740 static void
741 _mdns_server_handle_lack_of_response(mdns_server_t server, mdns_querier_t querier);
742
743 static uint16_t
744 _mdns_server_get_test_query_qtype(mdns_server_t server);
745 #endif
746
747 static bool
748 _mdns_session_is_ready(mdns_session_t session);
749
750 static void
751 _mdns_session_send(mdns_session_t session, dispatch_data_t message, uint16_t qtype);
752
753 static bool
754 _mdns_session_is_bytestream(mdns_session_t session);
755
756 static void
757 _mdns_session_invalidate(mdns_session_t session);
758 #define mdns_session_forget(X) ForgetCustomEx(X, _mdns_session_invalidate, mdns_release)
759
760 static void
761 _mdns_session_set_callbacks(mdns_session_t session, const mdns_session_callbacks_t *callbacks, void *context);
762
763 static void
764 _mdns_session_set_lateness_time(mdns_session_t session, uint32_t time_ms);
765
766 static OSStatus
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);
769
770 static void
771 _mdns_session_activate(mdns_session_t session);
772
773 static nw_endpoint_t
774 _mdns_common_session_get_server_endpoint(mdns_any_session_t session);
775
776 static void
777 _mdns_common_session_invoke_ready_event_handler(mdns_any_session_t session);
778
779 static void
780 _mdns_common_session_invoke_receive(mdns_any_session_t session, dispatch_data_t msg);
781
782 static void
783 _mdns_common_session_terminate(mdns_any_session_t session, OSStatus error);
784
785 static void
786 _mdns_common_session_terminate_async(mdns_any_session_t session, OSStatus error);
787
788 static mdns_resolver_kind_t
789 _mdns_resolver_get_kind(mdns_resolver_t resolver);
790
791 static const char *
792 _mdns_resolver_get_bytestream_protocol_string(mdns_resolver_t resolver);
793
794 static const char *
795 _mdns_resolver_get_datagram_protocol_string(mdns_resolver_t resolver);
796
797 static uint16_t
798 _mdns_resolver_get_default_port(mdns_any_resolver_t resolver);
799
800 static bool
801 _mdns_resolver_is_stream_only(mdns_resolver_t resolver);
802
803 static bool
804 _mdns_resolver_needs_edns0_padding(mdns_resolver_t resolver);
805
806 static bool
807 _mdns_resolver_needs_zero_ids(mdns_resolver_t resolver);
808
809 static bool
810 _mdns_resolver_needs_suspicious_reply_defense(mdns_resolver_t resolver);
811
812 static bool
813 _mdns_resolver_no_stream_session_sharing(mdns_resolver_t resolver);
814
815 static OSStatus
816 _mdns_resolver_add_server_by_endpoint(mdns_resolver_t resolver, nw_endpoint_t endpoint);
817
818 static void
819 _mdns_resolver_activate_internal(mdns_resolver_t resolver);
820
821 static nw_parameters_t
822 _mdns_resolver_get_stream_params(mdns_resolver_t resolver, OSStatus *out_error);
823
824 static nw_endpoint_t
825 _mdns_resolver_create_hostname_endpoint(mdns_resolver_t resolver);
826
827 static nw_parameters_t
828 _mdns_resolver_get_datagram_params(mdns_resolver_t resolver, OSStatus *out_error);
829
830 static void
831 _mdns_resolver_deregister_querier(mdns_resolver_t resolver, mdns_querier_t querier);
832
833 static void
834 _mdns_resolver_register_querier(mdns_resolver_t resolver, mdns_querier_t querier, bool force_stream_mode);
835
836 static void
837 _mdns_resolver_session_handle_event(mdns_session_t session, mdns_session_event_t event, OSStatus error, void *context);
838
839 static void
840 _mdns_resolver_session_receive(mdns_session_t session, dispatch_data_t response, void *context);
841
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);
845
846 static const char *
847 _mdns_resolver_get_protocol_log_string(mdns_resolver_t resolver, bool for_bytestream);
848
849 static const char *
850 _mdns_resolver_get_interface_log_string(mdns_resolver_t resolver);
851
852 static mdns_resolver_type_t
853 _mdns_resolver_get_type(mdns_resolver_t resolver);
854
855 static void
856 _mdns_resolver_log_receive(mdns_resolver_t resolver, mdns_session_t session, mdns_message_t message, bool acceptable,
857 const char *log_prefix);
858
859 static void
860 _mdns_resolver_handle_stream_error(mdns_resolver_t resolver, mdns_server_t server, const char *label);
861
862 static void
863 _mdns_resolver_handle_stream_lateness(mdns_resolver_t resolver, mdns_server_t server, uint64_t session_start_ticks,
864 const char *label);
865
866 static void
867 _mdns_resolver_handle_stream_response(mdns_resolver_t resolver, mdns_server_t server);
868
869 static void
870 _mdns_resolver_check_for_problematic_servers(mdns_resolver_t resolver);
871
872 static bool
873 _mdns_resolver_has_usable_server_without_connection_problems(mdns_resolver_t resolver);
874
875 static void
876 _mdns_resolver_generate_event(mdns_any_resolver_t resolver, mdns_resolver_event_t event, xpc_object_t info);
877
878 static void
879 _mdns_resolver_generate_connection_event(mdns_resolver_t resolver);
880
881 static void
882 _mdns_resolver_log_server_problems(mdns_resolver_t resolver, mdns_server_t server, const char *label);
883
884 static bool
885 _mdns_resolver_uses_encryption(mdns_resolver_t resolver);
886
887 static void
888 _mdns_resolver_start_serverless_queries(mdns_resolver_t resolver);
889
890 static void
891 _mdns_resolver_start_serverless_queries_async(mdns_resolver_t resolver);
892
893 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
894 static bool
895 _mdns_resolver_use_problematic_qtype_workaround(mdns_resolver_t resolver);
896 #endif
897
898 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND
899 static bool
900 _mdns_resolver_use_mixed_up_responses_workaround(mdns_resolver_t resolver);
901 #endif
902
903 static bool
904 _mdns_querier_is_response_acceptable(mdns_querier_t querier, mdns_message_t response, bool *out_truncated,
905 bool *out_suspicious, int *out_rcode);
906
907 static void
908 _mdns_querier_conclude(mdns_querier_t querier, mdns_querier_result_type_t result_type);
909
910 static void
911 _mdns_querier_conclude_async(mdns_querier_t querier, mdns_querier_result_type_t result_type);
912
913 static void
914 _mdns_querier_conclude_with_error(mdns_querier_t querier, OSStatus error);
915
916 static void
917 _mdns_querier_conclude_with_error_async(mdns_querier_t querier, OSStatus error);
918
919 static void
920 _mdns_querier_conclude_with_response(mdns_querier_t querier, mdns_message_t response);
921
922 static void
923 _mdns_querier_conclude_with_response_async(mdns_querier_t querier, mdns_message_t response, bool fabricated);
924
925 static void
926 _mdns_querier_conclude_ex(mdns_querier_t querier, mdns_querier_result_type_t result_type, OSStatus status,
927 mdns_message_t response);
928
929 static OSStatus
930 _mdns_add_dns_over_bytestream_framer(nw_parameters_t params);
931
932 static nw_parameters_t
933 _mdns_create_udp_parameters(OSStatus *out_error);
934
935 static nw_parameters_t
936 _mdns_create_tcp_parameters(OSStatus *out_error);
937
938 static bool
939 _mdns_rcode_is_good(const int rcode);
940
941 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND || MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
942 static bool
943 _mdns_qtype_is_problematic(int qtype);
944
945 static mdns_message_t
946 _mdns_create_empty_response_for_query(mdns_query_message_t query, int rcode, OSStatus *out_error);
947 #endif
948
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);
952
953 static bool
954 _mdns_message_is_adequate_test_query_response(mdns_message_t msg, mdns_query_message_t query);
955
956 static pqw_info_t *
957 _pqw_info_create(unsigned int threshold);
958
959 static void
960 _pqw_info_free(pqw_info_t *info);
961 #define _pqw_info_forget(X) ForgetCustom(X, _pqw_info_free)
962
963 static bool
964 _pqw_info_threshold_reached(const pqw_info_t *info);
965
966 static bool
967 _pqw_info_can_accept_qname(const pqw_info_t *info, const uint8_t *qname);
968
969 static pqw_qname_item_t *
970 _pqw_qname_item_create(const uint8_t *qname, OSStatus *out_error);
971
972 static void
973 _pqw_qname_item_free(pqw_qname_item_t *item);
974 #define _pqw_qname_item_forget(X) ForgetCustom(X, _pqw_qname_item_free)
975
976 static void
977 _pqw_qname_list_free(pqw_qname_item_t *list);
978 #define _pqw_qname_list_forget(X) ForgetCustom(X, _pqw_qname_list_free)
979 #endif
980
981 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND
982 typedef bool
983 (*qtype_test_f)(int qtype);
984
985 static bool
986 _mdns_qtype_is_address_type(int qtype);
987 #endif
988
989 //======================================================================================================================
990 // MARK: - Internals
991
992 MDNS_LOG_CATEGORY_DEFINE(resolver, "resolver");
993
994 #define MDNS_RESOLVER_CONNECTION_TIMEOUT_MS 1500
995
996 //======================================================================================================================
997 // MARK: - Resolver Public Methods
998
999 mdns_resolver_t
mdns_resolver_create(mdns_resolver_type_t type,uint32_t interface_index,OSStatus * out_error)1000 mdns_resolver_create(mdns_resolver_type_t type, uint32_t interface_index, OSStatus *out_error)
1001 {
1002 mdns_resolver_t resolver = NULL;
1003 mdns_resolver_t obj;
1004 OSStatus err;
1005 switch (type) {
1006 case mdns_resolver_type_normal:
1007 obj = _mdns_normal_resolver_alloc();
1008 require_action_quiet(obj, exit, err = kNoMemoryErr);
1009 break;
1010
1011 case mdns_resolver_type_tcp:
1012 obj = _mdns_tcp_resolver_alloc();
1013 require_action_quiet(obj, exit, err = kNoMemoryErr);
1014 break;
1015
1016 case mdns_resolver_type_tls:
1017 obj = _mdns_tls_resolver_alloc();
1018 require_action_quiet(obj, exit, err = kNoMemoryErr);
1019 break;
1020
1021 case mdns_resolver_type_https:
1022 obj = _mdns_https_resolver_alloc();
1023 require_action_quiet(obj, exit, err = kNoMemoryErr);
1024 break;
1025
1026 case mdns_resolver_type_null:
1027 default:
1028 obj = NULL;
1029 err = kTypeErr;
1030 goto exit;
1031 }
1032 obj->server_array = CFArrayCreateMutable(NULL, 0, &mdns_cfarray_callbacks);
1033 require_action_quiet(obj->server_array, exit, err = kNoResourcesErr);
1034
1035 if (interface_index != 0) {
1036 obj->interface = nw_interface_create_with_index(interface_index);
1037 require_action_quiet(obj->interface, exit, err = kUnknownErr);
1038 }
1039 resolver = obj;
1040 obj = NULL;
1041 err = kNoErr;
1042
1043 exit:
1044 if (out_error) {
1045 *out_error = err;
1046 }
1047 mdns_release_null_safe(obj);
1048 return resolver;
1049 }
1050
1051 //======================================================================================================================
1052
1053 void
mdns_resolver_set_queue(const mdns_resolver_t me,const dispatch_queue_t queue)1054 mdns_resolver_set_queue(const mdns_resolver_t me, const dispatch_queue_t queue)
1055 {
1056 if (!me->user_activated) {
1057 dispatch_retain(queue);
1058 dispatch_release_null_safe(me->user_queue);
1059 me->user_queue = queue;
1060 }
1061 }
1062
1063 //======================================================================================================================
1064
1065 void
mdns_resolver_set_event_handler(const mdns_resolver_t me,const mdns_resolver_event_handler_t handler)1066 mdns_resolver_set_event_handler(const mdns_resolver_t me, const mdns_resolver_event_handler_t handler)
1067 {
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);
1072 }
1073 me->event_handler = new_handler;
1074 }
1075 }
1076
1077 //======================================================================================================================
1078
1079 OSStatus
mdns_resolver_set_provider_name(mdns_resolver_t me,const char * provider_name)1080 mdns_resolver_set_provider_name(mdns_resolver_t me, const char *provider_name)
1081 {
1082 OSStatus err;
1083 require_action_quiet(!me->user_activated, exit, err = kAlreadyInitializedErr);
1084
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);
1088 } else {
1089 err = kNoErr;
1090 }
1091
1092 exit:
1093 return err;
1094 }
1095
1096 //======================================================================================================================
1097
1098 void
mdns_resolver_set_port(const mdns_resolver_t me,const uint16_t port)1099 mdns_resolver_set_port(const mdns_resolver_t me, const uint16_t port)
1100 {
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);
1105 }
1106 }
1107 }
1108
1109 //======================================================================================================================
1110
1111 OSStatus
mdns_resolver_set_url_path(mdns_resolver_t me,const char * url_path)1112 mdns_resolver_set_url_path(mdns_resolver_t me, const char *url_path)
1113 {
1114 OSStatus err;
1115 require_action_quiet(!me->user_activated, exit, err = kAlreadyInitializedErr);
1116
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);
1120 } else {
1121 err = kNoErr;
1122 }
1123
1124 exit:
1125 return err;
1126 }
1127
1128 //======================================================================================================================
1129
1130 void
mdns_resolver_set_squash_cnames(const mdns_resolver_t me,const bool enable)1131 mdns_resolver_set_squash_cnames(const mdns_resolver_t me, const bool enable)
1132 {
1133 if (!me->user_activated) {
1134 me->squash_cnames = enable ? true : false;
1135 }
1136 }
1137
1138 //======================================================================================================================
1139
1140 void
mdns_resolver_enable_symptom_reporting(const mdns_resolver_t me,const bool enable)1141 mdns_resolver_enable_symptom_reporting(const mdns_resolver_t me, const bool enable)
1142 {
1143 if (!me->user_activated) {
1144 me->report_symptoms = enable ? true : false;
1145 }
1146 }
1147
1148 //======================================================================================================================
1149
1150 OSStatus
mdns_resolver_add_server_address(mdns_resolver_t me,mdns_address_t address)1151 mdns_resolver_add_server_address(mdns_resolver_t me, mdns_address_t address)
1152 {
1153 OSStatus err;
1154 require_action_quiet(!me->user_activated, exit, err = kAlreadyInitializedErr);
1155
1156 sockaddr_ip sip;
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));
1164 }
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));
1169 }
1170 } else {
1171 err = kTypeErr;
1172 goto exit;
1173 }
1174 nw_endpoint_t endpoint = nw_endpoint_create_address(&sip.sa);
1175 require_action_quiet(endpoint, exit, err = kUnknownErr);
1176
1177 if (me->interface) {
1178 nw_endpoint_set_interface(endpoint, me->interface);
1179 }
1180 err = _mdns_resolver_add_server_by_endpoint(me, endpoint);
1181 nw_forget(&endpoint);
1182
1183 exit:
1184 return err;
1185 }
1186
1187 //======================================================================================================================
1188
1189 void
mdns_resolver_set_initial_datagram_retransmission_interval(const mdns_resolver_t me,const uint32_t interval_secs)1190 mdns_resolver_set_initial_datagram_retransmission_interval(const mdns_resolver_t me, const uint32_t interval_secs)
1191 {
1192 if (!me->user_activated) {
1193 if (interval_secs < (UINT32_MAX / kMillisecondsPerSecond)) {
1194 me->initial_dgram_rtx_ms = interval_secs * kMillisecondsPerSecond;
1195 } else {
1196 me->initial_dgram_rtx_ms = UINT32_MAX;
1197 }
1198 }
1199 }
1200
1201 //======================================================================================================================
1202
1203 void
mdns_resolver_disable_connection_reuse(const mdns_resolver_t me,const bool disable)1204 mdns_resolver_disable_connection_reuse(const mdns_resolver_t me, const bool disable)
1205 {
1206 if (!me->user_activated) {
1207 me->force_no_stream_sharing = disable ? true : false;
1208 }
1209 }
1210
1211 //======================================================================================================================
1212
1213 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
1214 #define MDNS_RESOLVER_PQW_THRESHOLD_MAX 100
1215 void
mdns_resolver_enable_problematic_qtype_workaround(const mdns_resolver_t me,const int threshold)1216 mdns_resolver_enable_problematic_qtype_workaround(const mdns_resolver_t me, const int threshold)
1217 {
1218 require_return(!me->user_activated);
1219 if (threshold > 0) {
1220 me->pqw_threshold = Min((unsigned int)threshold, MDNS_RESOLVER_PQW_THRESHOLD_MAX);
1221 } else {
1222 me->pqw_threshold = 0;
1223 }
1224 }
1225 #endif
1226
1227 //======================================================================================================================
1228
1229 void
mdns_resolver_activate(mdns_resolver_t me)1230 mdns_resolver_activate(mdns_resolver_t me)
1231 {
1232 if (!me->user_activated) {
1233 me->user_activated = true;
1234 mdns_retain(me);
1235 dispatch_async(_mdns_resolver_queue(),
1236 ^{
1237 _mdns_resolver_activate_internal(me);
1238 mdns_release(me);
1239 });
1240 }
1241 }
1242
1243 //======================================================================================================================
1244
1245 static void
1246 _mdns_resolver_invalidate_internal(mdns_resolver_t resolver);
1247
1248 void
mdns_resolver_invalidate(mdns_resolver_t me)1249 mdns_resolver_invalidate(mdns_resolver_t me)
1250 {
1251 mdns_retain(me);
1252 dispatch_async(_mdns_resolver_queue(),
1253 ^{
1254 _mdns_resolver_invalidate_internal(me);
1255 mdns_release(me);
1256 });
1257 }
1258
1259 static void
_mdns_resolver_invalidate_internal(mdns_resolver_t me)1260 _mdns_resolver_invalidate_internal(mdns_resolver_t me)
1261 {
1262 require_return(!me->invalidated);
1263
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);
1273 }
1274 mdns_session_forget(&server->shared_stream_session);
1275 }
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);
1281 }
1282 if (me->event_handler) {
1283 mdns_retain(me);
1284 dispatch_async(me->user_queue,
1285 ^{
1286 me->event_handler(mdns_resolver_event_invalidated, NULL);
1287 mdns_release(me);
1288 });
1289 }
1290 }
1291
1292 //======================================================================================================================
1293
1294 bool
mdns_resolver_type_uses_encryption(const mdns_resolver_type_t type)1295 mdns_resolver_type_uses_encryption(const mdns_resolver_type_t type)
1296 {
1297 // Note: A default case isn't used so that the compiler can catch missing resolver types.
1298 switch (type) {
1299 case mdns_resolver_type_null:
1300 case mdns_resolver_type_normal:
1301 case mdns_resolver_type_tcp:
1302 return false;
1303
1304 case mdns_resolver_type_tls:
1305 case mdns_resolver_type_https:
1306 return true;
1307 }
1308 return false;
1309 }
1310
1311 //======================================================================================================================
1312
1313 mdns_querier_t
mdns_resolver_create_querier(mdns_resolver_t me,OSStatus * out_error)1314 mdns_resolver_create_querier(mdns_resolver_t me, OSStatus *out_error)
1315 {
1316 OSStatus err;
1317 mdns_querier_t querier = NULL;
1318 mdns_querier_t obj = _mdns_querier_alloc();
1319 require_action_quiet(obj, exit, err = kNoMemoryErr);
1320
1321 atomic_init(&obj->send_count, 0);
1322 obj->resolver = me;
1323 mdns_retain(obj->resolver);
1324
1325 obj->query = mdns_query_message_create(mdns_message_init_option_disable_header_printing);
1326 require_action_quiet(obj->query, exit, err = kNoResourcesErr);
1327
1328 querier = obj;
1329 obj = NULL;
1330 err = kNoErr;
1331
1332 exit:
1333 if (out_error) {
1334 *out_error = err;
1335 }
1336 mdns_release_null_safe(obj);
1337 return querier;
1338 }
1339
1340 //======================================================================================================================
1341 // MARK: - Resolver Private Methods
1342
1343 static void
_mdns_resolver_finalize(mdns_resolver_t me)1344 _mdns_resolver_finalize(mdns_resolver_t me)
1345 {
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);
1351 }
1352
1353 //======================================================================================================================
1354
1355 static char *
_mdns_resolver_copy_description(mdns_resolver_t me,const bool debug,const bool privacy)1356 _mdns_resolver_copy_description(mdns_resolver_t me, const bool debug, const bool privacy)
1357 {
1358 char * description = NULL;
1359 char buffer[256];
1360 char * dst = buffer;
1361 const char * const lim = &buffer[countof(buffer)];
1362 int n;
1363
1364 *dst = '\0';
1365 if (debug) {
1366 n = mdns_snprintf_add(&dst, lim, "<%s: %p>: ", me->base.kind->name, me);
1367 require_quiet(n >= 0, exit);
1368 }
1369 n = mdns_snprintf_add(&dst, lim, "%s ", _mdns_resolver_get_kind(me)->name);
1370 require_quiet(n >= 0, exit);
1371
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);
1377 }
1378 n = mdns_snprintf_add(&dst, lim, "with servers [");
1379 require_quiet(n >= 0, exit);
1380
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);
1385
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);
1390 separator = ", ";
1391 }
1392 n = mdns_snprintf_add(&dst, lim, "]");
1393 require_quiet(n >= 0, exit);
1394
1395 description = strdup(buffer);
1396
1397 exit:
1398 return description;
1399 }
1400
1401 //======================================================================================================================
1402
1403 static mdns_resolver_kind_t
_mdns_resolver_get_kind(const mdns_resolver_t me)1404 _mdns_resolver_get_kind(const mdns_resolver_t me)
1405 {
1406 return (mdns_resolver_kind_t)me->base.kind;
1407 }
1408
1409 //======================================================================================================================
1410
1411 static const char *
_mdns_resolver_get_datagram_protocol_string(const mdns_resolver_t me)1412 _mdns_resolver_get_datagram_protocol_string(const mdns_resolver_t me)
1413 {
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 : "???");
1417 }
1418
1419 //======================================================================================================================
1420
1421 static const char *
_mdns_resolver_get_bytestream_protocol_string(const mdns_resolver_t me)1422 _mdns_resolver_get_bytestream_protocol_string(const mdns_resolver_t me)
1423 {
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 : "???");
1427 }
1428
1429 //======================================================================================================================
1430
1431 static uint16_t
_mdns_resolver_get_default_port(const mdns_any_resolver_t any)1432 _mdns_resolver_get_default_port(const mdns_any_resolver_t any)
1433 {
1434 const mdns_resolver_kind_t kind = _mdns_resolver_get_kind(any.resolver);
1435 return kind->default_port;
1436 }
1437
1438 //======================================================================================================================
1439
1440 static bool
_mdns_resolver_is_stream_only(const mdns_resolver_t me)1441 _mdns_resolver_is_stream_only(const mdns_resolver_t me)
1442 {
1443 const mdns_resolver_kind_t kind = _mdns_resolver_get_kind(me);
1444 return kind->stream_only;
1445 }
1446
1447 //======================================================================================================================
1448
1449 static bool
_mdns_resolver_needs_edns0_padding(const mdns_resolver_t me)1450 _mdns_resolver_needs_edns0_padding(const mdns_resolver_t me)
1451 {
1452 const mdns_resolver_kind_t kind = _mdns_resolver_get_kind(me);
1453 return kind->needs_edns0_padding;
1454 }
1455
1456 //======================================================================================================================
1457
1458 static bool
_mdns_resolver_needs_zero_ids(const mdns_resolver_t me)1459 _mdns_resolver_needs_zero_ids(const mdns_resolver_t me)
1460 {
1461 const mdns_resolver_kind_t kind = _mdns_resolver_get_kind(me);
1462 return kind->needs_zero_ids;
1463 }
1464
1465 //======================================================================================================================
1466
1467 static bool
_mdns_resolver_needs_suspicious_reply_defense(const mdns_resolver_t me)1468 _mdns_resolver_needs_suspicious_reply_defense(const mdns_resolver_t me)
1469 {
1470 const mdns_resolver_kind_t kind = _mdns_resolver_get_kind(me);
1471 return kind->suspicious_reply_defense;
1472 }
1473
1474 //======================================================================================================================
1475
1476 static bool
_mdns_resolver_no_stream_session_sharing(const mdns_resolver_t me)1477 _mdns_resolver_no_stream_session_sharing(const mdns_resolver_t me)
1478 {
1479 if (me->force_no_stream_sharing) {
1480 return true;
1481 }
1482 const mdns_resolver_kind_t kind = _mdns_resolver_get_kind(me);
1483 return kind->no_stream_session_sharing;
1484 }
1485
1486 //======================================================================================================================
1487
1488 static OSStatus
_mdns_resolver_add_server_by_endpoint(mdns_resolver_t me,nw_endpoint_t endpoint)1489 _mdns_resolver_add_server_by_endpoint(mdns_resolver_t me, nw_endpoint_t endpoint)
1490 {
1491 OSStatus err;
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);
1495
1496 server = _mdns_server_alloc();
1497 require_action_quiet(server, exit, err = kNoMemoryErr);
1498
1499 server->endpoint = endpoint;
1500 nw_retain(server->endpoint);
1501
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;
1505 }
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;
1510
1511 CFArrayAppendValue(me->server_array, server);
1512 err = kNoErr;
1513
1514 exit:
1515 mdns_release_null_safe(server);
1516 return err;
1517 }
1518
1519 //======================================================================================================================
1520
1521 #define MDNS_QUERIER_INITIAL_RTX_INTERVAL_DEFAULT_MS 1000
1522
1523 static void
1524 _mdns_resolver_activate_servers(mdns_resolver_t resolver);
1525
1526 static void
1527 _mdns_resolver_set_up_server_path_evaluator(mdns_resolver_t resolver, mdns_server_t server);
1528
1529 static void
_mdns_resolver_activate_internal(const mdns_resolver_t me)1530 _mdns_resolver_activate_internal(const mdns_resolver_t me)
1531 {
1532 require_return(!me->invalidated && !me->activated);
1533
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);
1538 }
1539 if (me->initial_dgram_rtx_ms <= 0) {
1540 me->initial_dgram_rtx_ms = MDNS_QUERIER_INITIAL_RTX_INTERVAL_DEFAULT_MS;
1541 }
1542 const CFIndex n = CFArrayGetCount(me->server_array);
1543 if (n <= 0) {
1544 const nw_endpoint_t endpoint = _mdns_resolver_create_hostname_endpoint(me);
1545 if (endpoint) {
1546 _mdns_resolver_add_server_by_endpoint(me, endpoint);
1547 nw_release(endpoint);
1548 }
1549 }
1550 _mdns_resolver_activate_servers(me);
1551 if (_mdns_resolver_is_stream_only(me)) {
1552 _mdns_resolver_check_for_problematic_servers(me);
1553 }
1554 }
1555
1556 static void
_mdns_resolver_activate_servers(const mdns_resolver_t me)1557 _mdns_resolver_activate_servers(const mdns_resolver_t me)
1558 {
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);
1563
1564 // Append server to list.
1565 server->next = NULL;
1566 *ptr = server;
1567 ptr = &server->next;
1568
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);
1575 } else {
1576 server->usable = true;
1577 }
1578 os_log(_mdns_resolver_log(), "Server %@ is %{public}susable", server, server->usable ? "" : "un");
1579 }
1580 }
1581
1582 static void
_mdns_resolver_set_up_server_path_evaluator(const mdns_resolver_t me,const mdns_server_t server)1583 _mdns_resolver_set_up_server_path_evaluator(const mdns_resolver_t me, const mdns_server_t server)
1584 {
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.
1589 return;
1590 }
1591 // Start the server's path evaluator.
1592 nw_path_evaluator_set_queue(server->path_evaluator, _mdns_resolver_queue());
1593 mdns_retain(me);
1594 mdns_retain(server);
1595 nw_path_evaluator_set_update_handler(server->path_evaluator, _mdns_resolver_queue(),
1596 ^(nw_path_t updated_path)
1597 {
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);
1603 }
1604 } else {
1605 if (server->usable) {
1606 server->usable = false;
1607 os_log(_mdns_resolver_log(), "Server %@ is now unusable", server);
1608 }
1609 }
1610 });
1611 nw_path_evaluator_set_cancel_handler(server->path_evaluator,
1612 ^{
1613 mdns_release(me);
1614 mdns_release(server);
1615 });
1616 nw_path_evaluator_start(server->path_evaluator);
1617
1618 nw_path_t path = nw_path_evaluator_copy_path(server->path_evaluator);
1619 if (path) {
1620 if (_mdns_path_to_server_is_usable(path, _mdns_resolver_uses_encryption(me))) {
1621 server->usable = true;
1622 }
1623 nw_forget(&path);
1624 }
1625 }
1626
1627 //======================================================================================================================
1628
1629 static nw_parameters_t
_mdns_resolver_get_datagram_params(mdns_resolver_t me,OSStatus * out_error)1630 _mdns_resolver_get_datagram_params(mdns_resolver_t me, OSStatus *out_error)
1631 {
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);
1635 } else {
1636 if (out_error) {
1637 *out_error = kUnsupportedErr;
1638 }
1639 return NULL;
1640 }
1641 }
1642
1643 //======================================================================================================================
1644
1645 static nw_parameters_t
_mdns_resolver_get_stream_params(mdns_resolver_t me,OSStatus * out_error)1646 _mdns_resolver_get_stream_params(mdns_resolver_t me, OSStatus *out_error)
1647 {
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);
1651 } else {
1652 if (out_error) {
1653 *out_error = kUnsupportedErr;
1654 }
1655 return NULL;
1656 }
1657 }
1658
1659 //======================================================================================================================
1660
1661 static nw_endpoint_t
_mdns_resolver_create_hostname_endpoint(mdns_resolver_t me)1662 _mdns_resolver_create_hostname_endpoint(mdns_resolver_t me)
1663 {
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);
1667 } else {
1668 return NULL;
1669 }
1670 }
1671
1672 //======================================================================================================================
1673
1674 static void
_mdns_resolver_insert_server(mdns_resolver_t me,mdns_server_t server)1675 _mdns_resolver_insert_server(mdns_resolver_t me, mdns_server_t server)
1676 {
1677 mdns_server_t *ptr;
1678 for (ptr = &me->server_list; *ptr; ptr = &(*ptr)->next) {
1679 if ((*ptr)->penalized || ((*ptr)->rank) > server->rank) {
1680 break;
1681 }
1682 }
1683 server->next = *ptr;
1684 *ptr = server;
1685 }
1686
1687 //======================================================================================================================
1688
1689 static void
_mdns_resolver_note_responsiveness(const mdns_resolver_t me,mdns_server_t server,const bool via_stream,const uint64_t session_start_ticks,const int qtype)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)
1692 {
1693 if (_mdns_ticks_diff(session_start_ticks, server->latest_session_start_ticks) > 0) {
1694 server->latest_session_start_ticks = session_start_ticks;
1695 }
1696 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
1697 if (!server->responds_to_problematics && _mdns_qtype_is_problematic(qtype)) {
1698 server->responds_to_problematics = true;
1699 }
1700 #else
1701 (void)qtype;
1702 #endif
1703 if (server->penalized) {
1704 mdns_server_t *ptr;
1705 for (ptr = &me->server_list; *ptr; ptr = &(*ptr)->next) {
1706 if (*ptr == server) {
1707 break;
1708 }
1709 }
1710 if (*ptr) {
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);
1716 }
1717 }
1718 if (via_stream) {
1719 _mdns_resolver_handle_stream_response(me, server);
1720 }
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;
1726 }
1727 }
1728 }
1729
1730 //======================================================================================================================
1731
1732 static void
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);
1735
1736 static void
_mdns_resolver_penalize_server(const mdns_resolver_t me,const mdns_server_t server)1737 _mdns_resolver_penalize_server(const mdns_resolver_t me, const mdns_server_t server)
1738 {
1739 _mdns_resolver_penalize_server_ex(me, server, false, NULL, 0);
1740 }
1741
1742 static void
_mdns_resolver_penalize_unresponsive_server(const mdns_resolver_t me,const mdns_server_t server,const mdns_querier_t querier,const uint64_t last_send_ticks)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)
1745 {
1746 _mdns_resolver_penalize_server_ex(me, server, true, querier, last_send_ticks);
1747 }
1748
1749 #define MDNS_SERVER_PENALTY_TIME_SECS 60
1750
1751 static void
_mdns_resolver_penalize_server_ex(const mdns_resolver_t me,const mdns_server_t server,const bool unresponsive,const mdns_querier_t querier,const uint64_t last_send_ticks)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)
1754 {
1755 if (unresponsive) {
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);
1759 }
1760 #endif
1761 if (_mdns_ticks_diff(last_send_ticks, server->latest_session_start_ticks) < 0) {
1762 return;
1763 }
1764 }
1765 mdns_server_t *ptr;
1766 for (ptr = &me->server_list; *ptr; ptr = &(*ptr)->next) {
1767 if (*ptr == server) {
1768 break;
1769 }
1770 }
1771 if (*ptr) {
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;
1776 while (*ptr) {
1777 ptr = &(*ptr)->next;
1778 }
1779 *ptr = server;
1780 }
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;
1789 }
1790 }
1791 }
1792
1793 //======================================================================================================================
1794
1795 static bool
1796 _mdns_server_is_excluded(mdns_server_t server, uint32_t exclude_bitmap);
1797
1798 static mdns_server_t
_mdns_resolver_get_server(const mdns_resolver_t me,const uint32_t exclude_bitmap)1799 _mdns_resolver_get_server(const mdns_resolver_t me, const uint32_t exclude_bitmap)
1800 {
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) {
1806 int64_t diff;
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);
1812
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));
1816 } else {
1817 ptr = &server->next;
1818 }
1819 }
1820 for (server = me->server_list; server; server = server->next) {
1821 if (!_mdns_server_is_excluded(server, exclude_bitmap)) {
1822 break;
1823 }
1824 }
1825 }
1826 return server;
1827 }
1828
1829 static bool
_mdns_server_is_excluded(const mdns_server_t me,const uint32_t exclude_bitmap)1830 _mdns_server_is_excluded(const mdns_server_t me, const uint32_t exclude_bitmap)
1831 {
1832 if (!me->usable || (exclude_bitmap & _mdns_rank_to_bitmask(me->rank))) {
1833 return true;
1834 } else {
1835 return false;
1836 }
1837 }
1838
1839 //======================================================================================================================
1840
1841 static void
_mdns_resolver_session_handle_event(const mdns_session_t session,const mdns_session_event_t event,const OSStatus error,void * const context)1842 _mdns_resolver_session_handle_event(const mdns_session_t session, const mdns_session_event_t event,
1843 const OSStatus error, void * const context)
1844 {
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);
1849
1850 const mdns_resolver_t me = (mdns_resolver_t)context;
1851 switch (event) {
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);
1857 }
1858 }
1859 break;
1860 }
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) {
1865 break;
1866 }
1867 }
1868 require_quiet(server, exit);
1869
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);
1874 }
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);
1878 }
1879 }
1880 break;
1881 }
1882 case mdns_session_event_lateness_warning:
1883 _mdns_resolver_handle_stream_lateness(me, session->server, session->start_ticks, NULL);
1884 break;
1885
1886 default:
1887 break;
1888 }
1889
1890 exit:
1891 return;
1892 }
1893
1894 //======================================================================================================================
1895
1896 static void
_mdns_resolver_session_receive(mdns_session_t session,dispatch_data_t msg_data,void * context)1897 _mdns_resolver_session_receive(mdns_session_t session, dispatch_data_t msg_data, void *context)
1898 {
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);
1902
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;
1909 int rcode = 0;
1910 const bool acceptable = _mdns_querier_is_response_acceptable(querier, msg, NULL, NULL, &rcode);
1911 if (acceptable) {
1912 if (!logged_msg) {
1913 _mdns_resolver_log_receive(me, session, msg, true, _mdns_querier_get_log_label(querier));
1914 logged_msg = true;
1915 }
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);
1920 } else {
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);
1923 }
1924 }
1925 }
1926 if (!logged_msg) {
1927 _mdns_resolver_log_receive(me, session, msg, false, NULL);
1928 }
1929 mdns_release(msg);
1930 }
1931
1932 //======================================================================================================================
1933
1934 static bool
1935 _mdns_resolver_is_in_suspicious_mode(mdns_resolver_t resolver);
1936
1937 static void
_mdns_resolver_register_querier(mdns_resolver_t me,mdns_querier_t querier,bool force_stream_mode)1938 _mdns_resolver_register_querier(mdns_resolver_t me, mdns_querier_t querier, bool force_stream_mode)
1939 {
1940 require_return_action(!me->invalidated,
1941 _mdns_querier_conclude_async(querier, mdns_querier_result_type_resolver_invalidation));
1942
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;
1948 } else {
1949 querier->use_stream = false;
1950 }
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;
1955 } else {
1956 querier->use_shared_stream = true;
1957 }
1958 mdns_querier_t *ptr = &me->querier_list;
1959 while (*ptr) {
1960 ptr = &(*ptr)->next;
1961 }
1962 *ptr = querier;
1963 mdns_retain(*ptr);
1964 _mdns_querier_start(querier);
1965 }
1966
1967 static bool
_mdns_resolver_is_in_suspicious_mode(const mdns_resolver_t me)1968 _mdns_resolver_is_in_suspicious_mode(const mdns_resolver_t me)
1969 {
1970 if (_mdns_resolver_needs_suspicious_reply_defense(me) && me->suspicious_mode) {
1971 int64_t diff;
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));
1978 return true;
1979 } else {
1980 me->suspicious_mode = false;
1981 }
1982 }
1983 return false;
1984 }
1985
1986 //======================================================================================================================
1987
1988 static void
1989 _mdns_forget_session_list(mdns_session_t *list_ptr);
1990
1991 static void
_mdns_resolver_deregister_querier(mdns_resolver_t me,mdns_querier_t querier)1992 _mdns_resolver_deregister_querier(mdns_resolver_t me, mdns_querier_t querier)
1993 {
1994 dispatch_source_forget(&querier->rtx_timer);
1995
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;
2001 }
2002 if (*ptr) {
2003 *ptr = querier->next;
2004 querier->next = NULL;
2005 mdns_release(querier);
2006 }
2007 }
2008
2009 static void
_mdns_forget_session_list(mdns_session_t * const list_ptr)2010 _mdns_forget_session_list(mdns_session_t * const list_ptr)
2011 {
2012 mdns_session_t list = *list_ptr;
2013 if (list) {
2014 *list_ptr = NULL;
2015 mdns_session_t session;
2016 while ((session = list) != NULL) {
2017 list = session->next;
2018 session->next = NULL;
2019 mdns_session_forget(&session);
2020 }
2021 }
2022 }
2023
2024 //======================================================================================================================
2025
2026 static mdns_session_t
_mdns_resolver_create_session(const mdns_resolver_t me,const mdns_server_t server,const bool need_bytestream,const mdns_delegation_t * const delegation,const uint8_t * const qname,OSStatus * const out_error)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)
2029 {
2030 mdns_session_t session = NULL;
2031
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;
2038 #else
2039 session_type = mdns_session_type_udp_socket;
2040 #endif
2041 } else {
2042 session_type = mdns_session_type_connection;
2043 }
2044 break;
2045
2046 case mdns_resolver_type_tcp:
2047 case mdns_resolver_type_tls:
2048 session_type = mdns_session_type_connection;
2049 break;
2050
2051 case mdns_resolver_type_https:
2052 session_type = mdns_session_type_url;
2053 break;
2054
2055 case mdns_resolver_type_null:
2056 default:
2057 session_type = mdns_session_type_null;
2058 break;
2059 }
2060 OSStatus err;
2061 mdns_session_t obj;
2062 switch (session_type) {
2063 case mdns_session_type_connection:
2064 obj = _mdns_connection_session_alloc();
2065 require_action_quiet(obj, exit, err = kNoMemoryErr);
2066 break;
2067
2068 case mdns_session_type_udp_socket:
2069 obj = _mdns_udp_socket_session_alloc();
2070 require_action_quiet(obj, exit, err = kNoMemoryErr);
2071 break;
2072
2073 case mdns_session_type_url:
2074 obj = _mdns_url_session_alloc();
2075 require_action_quiet(obj, exit, err = kNoMemoryErr);
2076 break;
2077
2078 case mdns_session_type_null:
2079 default:
2080 obj = NULL;
2081 err = kTypeErr;
2082 goto exit;
2083 }
2084 obj->server = server;
2085 mdns_retain(obj->server);
2086
2087 err = _mdns_session_initialize(obj, me, need_bytestream, delegation, qname);
2088 require_noerr_quiet(err, exit);
2089
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;
2093 session = obj;
2094 obj = NULL;
2095
2096 exit:
2097 if (out_error) {
2098 *out_error = err;
2099 }
2100 mdns_release_null_safe(obj);
2101 return session;
2102 }
2103
2104 //======================================================================================================================
2105
2106 #define MDNS_RESOLVER_SUSPICIOUS_MODE_DURATION_SECS 10
2107
2108 static void
_mdns_resolver_got_suspicious_reply(const mdns_resolver_t me)2109 _mdns_resolver_got_suspicious_reply(const mdns_resolver_t me)
2110 {
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;
2114
2115 os_log_info(_mdns_resolver_log(), "Got suspicious response, entering suspicious mode for %d seconds",
2116 MDNS_RESOLVER_SUSPICIOUS_MODE_DURATION_SECS);
2117 }
2118
2119 //======================================================================================================================
2120
2121 static const char *
_mdns_resolver_get_protocol_log_string(mdns_resolver_t me,bool for_bytestream)2122 _mdns_resolver_get_protocol_log_string(mdns_resolver_t me, bool for_bytestream)
2123 {
2124 if (for_bytestream) {
2125 return _mdns_resolver_get_bytestream_protocol_string(me);
2126 } else {
2127 return _mdns_resolver_get_datagram_protocol_string(me);
2128 }
2129 }
2130
2131 //======================================================================================================================
2132
2133 static const char *
_mdns_resolver_get_interface_log_string(mdns_resolver_t me)2134 _mdns_resolver_get_interface_log_string(mdns_resolver_t me)
2135 {
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));
2140 }
2141 return (me->interface_log_str ? me->interface_log_str : "???");
2142 } else {
2143 return "any interface";
2144 }
2145 }
2146
2147 //======================================================================================================================
2148
2149 static mdns_resolver_type_t
_mdns_resolver_get_type(const mdns_resolver_t me)2150 _mdns_resolver_get_type(const mdns_resolver_t me)
2151 {
2152 return _mdns_resolver_get_kind(me)->type;
2153 }
2154
2155 //======================================================================================================================
2156
2157 static void
_mdns_resolver_log_receive(const mdns_resolver_t me,const mdns_session_t session,const mdns_message_t msg,const bool acceptable,const char * log_prefix)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)
2160 {
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",
2167 msg_len,
2168 session->server,
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),
2172 msg);
2173 }
2174
2175 //======================================================================================================================
2176
2177 static void
_mdns_resolver_handle_stream_error(const mdns_resolver_t me,const mdns_server_t server,const char * const label)2178 _mdns_resolver_handle_stream_error(const mdns_resolver_t me, const mdns_server_t server, const char * const label)
2179 {
2180 require_return(_mdns_resolver_is_stream_only(me));
2181
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);
2192 }
2193 }
2194 _mdns_resolver_check_for_problematic_servers(me);
2195 }
2196
2197 //======================================================================================================================
2198
2199 static void
_mdns_resolver_handle_stream_lateness(const mdns_resolver_t me,const mdns_server_t server,const uint64_t session_start_ticks,const char * const label)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)
2202 {
2203 require_return(_mdns_resolver_is_stream_only(me));
2204
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);
2210 }
2211 _mdns_resolver_check_for_problematic_servers(me);
2212 }
2213 }
2214
2215 //======================================================================================================================
2216
2217 static void
_mdns_resolver_handle_stream_response(const mdns_resolver_t me,const mdns_server_t server)2218 _mdns_resolver_handle_stream_response(const mdns_resolver_t me, const mdns_server_t server)
2219 {
2220 require_return(_mdns_resolver_is_stream_only(me));
2221
2222 const bool had_problems = _mdns_server_has_stream_problems(server);
2223 server->stream_error_count = 0;
2224 server->stream_lateness = false;
2225 if (had_problems) {
2226 os_log(_mdns_resolver_log(), "Cleared stream problems with %{public}s server %@",
2227 _mdns_resolver_get_bytestream_protocol_string(me), server);
2228 }
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);
2238 }
2239 }
2240
2241 //======================================================================================================================
2242
2243 static void
2244 _mdns_resolver_start_probe_querier(mdns_resolver_t resolver);
2245
2246 #define MDNS_RESOLVER_PROBE_RETRY_INTERVAL_SECS 30
2247
2248 static void
_mdns_resolver_check_for_problematic_servers(const mdns_resolver_t me)2249 _mdns_resolver_check_for_problematic_servers(const mdns_resolver_t me)
2250 {
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"));
2255
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,
2261 ^{
2262 _mdns_resolver_start_probe_querier(me);
2263 });
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);
2269 }
2270 }
2271
2272 exit:
2273 return;
2274 }
2275
2276 static void
_mdns_resolver_start_probe_querier(const mdns_resolver_t me)2277 _mdns_resolver_start_probe_querier(const mdns_resolver_t me)
2278 {
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"));
2282
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);
2288
2289 exit:
2290 return;
2291 }
2292
2293 //======================================================================================================================
2294
2295 static bool
_mdns_resolver_has_usable_server_without_connection_problems(const mdns_resolver_t me)2296 _mdns_resolver_has_usable_server_without_connection_problems(const mdns_resolver_t me)
2297 {
2298 for (mdns_server_t server = me->server_list; server; server = server->next) {
2299 if (server->usable && !_mdns_server_has_stream_problems(server)) {
2300 return true;
2301 }
2302 }
2303 return false;
2304 }
2305
2306 //======================================================================================================================
2307
2308 static void
_mdns_resolver_generate_event(const mdns_any_resolver_t any,const mdns_resolver_event_t event,const xpc_object_t info)2309 _mdns_resolver_generate_event(const mdns_any_resolver_t any, const mdns_resolver_event_t event, const xpc_object_t info)
2310 {
2311 const mdns_resolver_t me = any.resolver;
2312 require_quiet(!me->invalidated, exit);
2313
2314 if (me->event_handler) {
2315 mdns_retain(me);
2316 xpc_retain(info);
2317 dispatch_async(me->user_queue,
2318 ^{
2319 me->event_handler(event, info);
2320 mdns_release(me);
2321 xpc_release(info);
2322 });
2323 }
2324
2325 exit:
2326 return;
2327 }
2328
2329 //======================================================================================================================
2330
2331 static void
_mdns_resolver_generate_connection_event(const mdns_resolver_t me)2332 _mdns_resolver_generate_connection_event(const mdns_resolver_t me)
2333 {
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);
2337 xpc_release(info);
2338 }
2339
2340 //======================================================================================================================
2341
2342 static void
_mdns_resolver_log_server_problems(const mdns_resolver_t me,const mdns_server_t server,const char * const label)2343 _mdns_resolver_log_server_problems(const mdns_resolver_t me, const mdns_server_t server, const char * const label)
2344 {
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);
2349 }
2350
2351 //======================================================================================================================
2352
2353 static bool
_mdns_resolver_uses_encryption(const mdns_resolver_t me)2354 _mdns_resolver_uses_encryption(const mdns_resolver_t me)
2355 {
2356 return mdns_resolver_type_uses_encryption(_mdns_resolver_get_type(me));
2357 }
2358
2359 //======================================================================================================================
2360
2361 static void
_mdns_resolver_start_serverless_queries(const mdns_resolver_t me)2362 _mdns_resolver_start_serverless_queries(const mdns_resolver_t me)
2363 {
2364 require_return(!me->invalidated);
2365
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;
2370 break;
2371 }
2372 }
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);
2377 }
2378 }
2379 }
2380 }
2381
2382 //======================================================================================================================
2383
2384 static void
_mdns_resolver_start_serverless_queries_async(const mdns_resolver_t me)2385 _mdns_resolver_start_serverless_queries_async(const mdns_resolver_t me)
2386 {
2387 mdns_retain(me);
2388 dispatch_async(_mdns_resolver_queue(),
2389 ^{
2390 _mdns_resolver_start_serverless_queries(me);
2391 mdns_release(me);
2392 });
2393 }
2394
2395 //======================================================================================================================
2396
2397 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
2398 static bool
_mdns_resolver_use_problematic_qtype_workaround(const mdns_resolver_t me)2399 _mdns_resolver_use_problematic_qtype_workaround(const mdns_resolver_t me)
2400 {
2401 return (me->pqw_threshold > 0);
2402 }
2403 #endif
2404
2405 //======================================================================================================================
2406
2407 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND
2408 static bool
_mdns_resolver_use_mixed_up_responses_workaround(const mdns_resolver_t me)2409 _mdns_resolver_use_mixed_up_responses_workaround(const mdns_resolver_t me)
2410 {
2411 return (_mdns_resolver_get_type(me) == mdns_resolver_type_normal);
2412 }
2413 #endif
2414
2415 //======================================================================================================================
2416 // MARK: - Normal Resolver Private Methods
2417
2418 static void
_mdns_normal_resolver_finalize(mdns_normal_resolver_t me)2419 _mdns_normal_resolver_finalize(mdns_normal_resolver_t me)
2420 {
2421 nw_forget(&me->udp_params);
2422 nw_forget(&me->tcp_params);
2423 }
2424
2425 //======================================================================================================================
2426
2427 static nw_parameters_t
_mdns_normal_resolver_get_datagram_params(mdns_normal_resolver_t me,OSStatus * out_error)2428 _mdns_normal_resolver_get_datagram_params(mdns_normal_resolver_t me, OSStatus *out_error)
2429 {
2430 OSStatus err;
2431 nw_parameters_t params = NULL;
2432
2433 if (!me->udp_params) {
2434 me->udp_params = _mdns_create_udp_parameters(&err);
2435 require_noerr_quiet(err, exit);
2436 }
2437 params = me->udp_params;
2438 err = kNoErr;
2439
2440 exit:
2441 if (out_error) {
2442 *out_error = err;
2443 }
2444 return params;
2445 }
2446
2447 //======================================================================================================================
2448
2449 static nw_parameters_t
_mdns_normal_resolver_get_stream_params(mdns_normal_resolver_t me,OSStatus * out_error)2450 _mdns_normal_resolver_get_stream_params(mdns_normal_resolver_t me, OSStatus *out_error)
2451 {
2452 OSStatus err;
2453 nw_parameters_t params = NULL;
2454
2455 if (!me->tcp_params) {
2456 me->tcp_params = _mdns_create_tcp_parameters(&err);
2457 require_noerr_quiet(err, exit);
2458 }
2459 params = me->tcp_params;
2460 err = kNoErr;
2461
2462 exit:
2463 if (out_error) {
2464 *out_error = err;
2465 }
2466 return params;
2467 }
2468
2469 //======================================================================================================================
2470 // MARK: - TCP-Only Resolver Private Methods
2471
2472 static void
_mdns_tcp_resolver_finalize(mdns_tcp_resolver_t me)2473 _mdns_tcp_resolver_finalize(mdns_tcp_resolver_t me)
2474 {
2475 nw_forget(&me->params);
2476 }
2477
2478 //======================================================================================================================
2479
2480 static nw_parameters_t
_mdns_tcp_resolver_get_stream_params(mdns_tcp_resolver_t me,OSStatus * out_error)2481 _mdns_tcp_resolver_get_stream_params(mdns_tcp_resolver_t me, OSStatus *out_error)
2482 {
2483 OSStatus err;
2484 nw_parameters_t params = NULL;
2485 if (!me->params) {
2486 me->params = _mdns_create_tcp_parameters(&err);
2487 require_noerr_quiet(err, exit);
2488 }
2489 params = me->params;
2490 err = kNoErr;
2491
2492 exit:
2493 if (out_error) {
2494 *out_error = err;
2495 }
2496 return params;
2497 }
2498
2499 //======================================================================================================================
2500 // MARK: - TLS Resolver Private Methods
2501
2502 static void
_mdns_tls_resolver_finalize(mdns_tls_resolver_t me)2503 _mdns_tls_resolver_finalize(mdns_tls_resolver_t me)
2504 {
2505 ForgetMem(&me->hostname);
2506 nw_forget(&me->params);
2507 }
2508
2509 //======================================================================================================================
2510
2511 static OSStatus
_mdns_tls_resolver_set_provider_name(mdns_tls_resolver_t me,const char * provider_name)2512 _mdns_tls_resolver_set_provider_name(mdns_tls_resolver_t me, const char *provider_name)
2513 {
2514 return mdns_replace_string(&me->hostname, provider_name);
2515 }
2516
2517 //======================================================================================================================
2518
2519 static void
_mdns_tls_resolver_set_port(const mdns_tls_resolver_t me,const uint16_t port)2520 _mdns_tls_resolver_set_port(const mdns_tls_resolver_t me, const uint16_t port)
2521 {
2522 me->port = port;
2523 }
2524
2525 //======================================================================================================================
2526
2527 static nw_parameters_t
2528 _mdns_tls_resolver_create_stream_params(mdns_tls_resolver_t me, OSStatus *out_error);
2529
2530 static nw_parameters_t
_mdns_tls_resolver_get_stream_params(mdns_tls_resolver_t me,OSStatus * out_error)2531 _mdns_tls_resolver_get_stream_params(mdns_tls_resolver_t me, OSStatus *out_error)
2532 {
2533 OSStatus err;
2534 nw_parameters_t params = NULL;
2535 if (!me->params) {
2536 me->params = _mdns_tls_resolver_create_stream_params(me, &err);
2537 require_noerr_quiet(err, exit);
2538 }
2539 params = me->params;
2540 err = kNoErr;
2541
2542 exit:
2543 if (out_error) {
2544 *out_error = err;
2545 }
2546 return params;
2547 }
2548
2549 static nw_parameters_t
_mdns_tls_resolver_create_stream_params(mdns_tls_resolver_t me,OSStatus * out_error)2550 _mdns_tls_resolver_create_stream_params(mdns_tls_resolver_t me, OSStatus *out_error)
2551 {
2552 OSStatus err;
2553 nw_parameters_t params = NULL;
2554 nw_parameters_t obj;
2555 if (me->hostname) {
2556 __block bool server_name_was_set = false;
2557 nw_parameters_configure_protocol_block_t configure_tls = ^(nw_protocol_options_t tls_options)
2558 {
2559 const sec_protocol_options_t sec_options = nw_tls_copy_sec_protocol_options(tls_options);
2560 if (sec_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;
2565 }
2566 };
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);
2570 } else {
2571 obj = nw_parameters_create_secure_tcp(NW_PARAMETERS_DEFAULT_CONFIGURATION, NW_PARAMETERS_DEFAULT_CONFIGURATION);
2572 require_action_quiet(obj, exit, err = kNoResourcesErr);
2573 }
2574 nw_parameters_set_indefinite(obj, false);
2575
2576 err = _mdns_add_dns_over_bytestream_framer(obj);
2577 require_noerr_quiet(err, exit);
2578
2579 params = obj;
2580 obj = NULL;
2581
2582 exit:
2583 if (out_error) {
2584 *out_error = err;
2585 }
2586 nw_release_null_safe(obj);
2587 return params;
2588 }
2589
2590 //======================================================================================================================
2591
2592 static nw_endpoint_t
_mdns_tls_resolver_create_hostname_endpoint(mdns_tls_resolver_t me)2593 _mdns_tls_resolver_create_hostname_endpoint(mdns_tls_resolver_t me)
2594 {
2595 if (me->hostname) {
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);
2598 } else {
2599 return NULL;
2600 }
2601 }
2602
2603 //======================================================================================================================
2604 // MARK: - HTTPS Resolver Private Methods
2605
2606 static void
_mdns_https_resolver_finalize(mdns_https_resolver_t me)2607 _mdns_https_resolver_finalize(mdns_https_resolver_t me)
2608 {
2609 ForgetMem(&me->provider_name);
2610 ForgetMem(&me->url_path);
2611 nw_forget(&me->params);
2612 }
2613
2614 //======================================================================================================================
2615
2616 static OSStatus
_mdns_https_resolver_set_provider_name(mdns_https_resolver_t me,const char * provider_name)2617 _mdns_https_resolver_set_provider_name(mdns_https_resolver_t me, const char *provider_name)
2618 {
2619 return mdns_replace_string(&me->provider_name, provider_name);
2620 }
2621
2622 //======================================================================================================================
2623
2624 static void
_mdns_https_resolver_set_port(const mdns_https_resolver_t me,const uint16_t port)2625 _mdns_https_resolver_set_port(const mdns_https_resolver_t me, const uint16_t port)
2626 {
2627 me->port = port;
2628 }
2629
2630 //======================================================================================================================
2631
2632 static OSStatus
_mdns_https_resolver_set_url_path(mdns_https_resolver_t me,const char * url_path)2633 _mdns_https_resolver_set_url_path(mdns_https_resolver_t me, const char *url_path)
2634 {
2635 return mdns_replace_string(&me->url_path, url_path);
2636 }
2637
2638 //======================================================================================================================
2639
2640 static nw_parameters_t
_mdns_https_resolver_create_stream_params(mdns_https_resolver_t me,OSStatus * out_error)2641 _mdns_https_resolver_create_stream_params(mdns_https_resolver_t me, OSStatus *out_error)
2642 {
2643 OSStatus err = 0;
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)
2649 {
2650 const sec_protocol_options_t sec_options = nw_tls_copy_sec_protocol_options(tls_options);
2651 if (sec_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;
2657 }
2658 };
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);
2662 } else {
2663 obj = nw_parameters_create_secure_tcp(NW_PARAMETERS_DEFAULT_CONFIGURATION, NW_PARAMETERS_DEFAULT_CONFIGURATION);
2664 require_action_quiet(obj, exit, err = kNoResourcesErr);
2665 }
2666
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);
2671
2672 nw_parameters_set_indefinite(obj, false);
2673
2674 params = obj;
2675 obj = NULL;
2676
2677 exit:
2678 if (out_error) {
2679 *out_error = err;
2680 }
2681 nw_release_null_safe(obj);
2682 return params;
2683 }
2684
2685 static nw_parameters_t
_mdns_https_resolver_get_stream_params(mdns_https_resolver_t me,OSStatus * out_error)2686 _mdns_https_resolver_get_stream_params(mdns_https_resolver_t me, OSStatus *out_error)
2687 {
2688 OSStatus err;
2689 nw_parameters_t params = NULL;
2690 if (!me->params) {
2691 me->params = _mdns_https_resolver_create_stream_params(me, &err);
2692 require_noerr_quiet(err, exit);
2693 }
2694 params = me->params;
2695 err = kNoErr;
2696
2697 exit:
2698 if (out_error) {
2699 *out_error = err;
2700 }
2701 return params;
2702 }
2703
2704 //======================================================================================================================
2705
2706 static nw_endpoint_t
_mdns_https_resolver_create_hostname_endpoint(mdns_https_resolver_t me)2707 _mdns_https_resolver_create_hostname_endpoint(mdns_https_resolver_t me)
2708 {
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);
2712 } else {
2713 return NULL;
2714 }
2715 }
2716
2717 //======================================================================================================================
2718 // MARK: - Server Private Methods
2719
2720 static void
_mdns_server_finalize(mdns_server_t me)2721 _mdns_server_finalize(mdns_server_t me)
2722 {
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);
2727 #endif
2728 }
2729
2730 //======================================================================================================================
2731
2732 static char *
_mdns_server_copy_description(mdns_server_t me,const bool debug,const bool privacy)2733 _mdns_server_copy_description(mdns_server_t me, const bool debug, const bool privacy)
2734 {
2735 char * description = NULL;
2736 char buffer[128];
2737 char * dst = buffer;
2738 const char * const lim = &buffer[countof(buffer)];
2739 int n;
2740
2741 *dst = '\0';
2742 if (debug) {
2743 n = mdns_snprintf_add(&dst, lim, "<%s: %p>: ", me->base.kind->name, me);
2744 require_quiet(n >= 0, exit);
2745 }
2746 if (privacy) {
2747 char strbuf[64];
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);
2754 if (n >= 0) {
2755 str = strbuf;
2756 }
2757 }
2758 if (str) {
2759 n = mdns_snprintf_add(&dst, lim, "%s", str);
2760 require_quiet(n >= 0, exit);
2761 } else {
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);
2765 }
2766 } else {
2767 const char *str = NULL;
2768 const char *hostname = nw_endpoint_get_hostname(me->endpoint);
2769 if (hostname) {
2770 n = DNSMessagePrintObfuscatedString(strbuf, sizeof(strbuf), hostname);
2771 if (n >= 0) {
2772 str = strbuf;
2773 }
2774 }
2775 if (str) {
2776 n = mdns_snprintf_add(&dst, lim, "%s", str);
2777 require_quiet(n >= 0, exit);
2778 } else {
2779 n = mdns_snprintf_add(&dst, lim, "<H#%u>", me->rank);
2780 require_quiet(n >= 0, exit);
2781 }
2782 }
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);
2786 }
2787 } else {
2788 const char *hostname = nw_endpoint_get_hostname(me->endpoint);
2789 if (!hostname) {
2790 hostname = "<unknown>";
2791 }
2792 n = mdns_snprintf_add(&dst, lim, "%s", hostname);
2793 require_quiet(n >= 0, exit);
2794
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) {
2800 sep = ".";
2801 }
2802 }
2803 n = mdns_snprintf_add(&dst, lim, "%s%d", sep, nw_endpoint_get_port(me->endpoint));
2804 require_quiet(n >= 0, exit);
2805 }
2806 }
2807 description = strdup(buffer);
2808
2809 exit:
2810 return description;
2811 }
2812
2813 //======================================================================================================================
2814
2815 static bool
_mdns_server_has_stream_problems(const mdns_server_t me)2816 _mdns_server_has_stream_problems(const mdns_server_t me)
2817 {
2818 return (me->stream_lateness || (me->stream_error_count >= MDNS_SERVER_STREAM_ERROR_COUNT_THRESHOLD));
2819 }
2820
2821 //======================================================================================================================
2822
2823 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND || MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
2824 static bool
_mdns_server_supports_qtype(const mdns_server_t me,const int qtype)2825 _mdns_server_supports_qtype(const mdns_server_t me, const int qtype)
2826 {
2827 if (_mdns_qtype_is_problematic(qtype)) {
2828 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND
2829 if (me->mixes_up_responses) {
2830 return false;
2831 }
2832 #endif
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)) {
2837 return false;
2838 }
2839 }
2840 #endif
2841 }
2842 return true;
2843 }
2844 #endif
2845
2846 //======================================================================================================================
2847
2848 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
2849 static void
_mdns_server_handle_lack_of_response(const mdns_server_t me,const mdns_querier_t querier)2850 _mdns_server_handle_lack_of_response(const mdns_server_t me, const mdns_querier_t querier)
2851 {
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)) {
2855 return;
2856 }
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)));
2861 }
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));
2871
2872 item->next = info->qname_list;
2873 info->qname_list = item;
2874 ++info->qname_count;
2875 } else {
2876 _pqw_qname_list_forget(&info->qname_list);
2877 info->qname_count = info->threshold;
2878 }
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);
2882 }
2883 }
2884
2885 //======================================================================================================================
2886
2887 static uint16_t
_mdns_server_get_test_query_qtype(const mdns_server_t me)2888 _mdns_server_get_test_query_qtype(const mdns_server_t me)
2889 {
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;
2896 }
2897 }
2898 me->test_query_qtype = qtype;
2899 }
2900 return me->test_query_qtype;
2901 }
2902 #endif // MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
2903
2904 //======================================================================================================================
2905 // MARK: - Session Private Methods
2906
2907 static void
_mdns_session_finalize(mdns_session_t me)2908 _mdns_session_finalize(mdns_session_t me)
2909 {
2910 mdns_forget(&me->server);
2911 me->context = NULL;
2912 }
2913
2914 //======================================================================================================================
2915
2916 static char *
_mdns_session_copy_description(mdns_session_t me,const bool debug,__unused const bool privacy)2917 _mdns_session_copy_description(mdns_session_t me, const bool debug, __unused const bool privacy)
2918 {
2919 char * description = NULL;
2920 char buffer[128];
2921 char * dst = buffer;
2922 const char * const lim = &buffer[countof(buffer)];
2923 int n;
2924
2925 *dst = '\0';
2926 if (debug) {
2927 n = mdns_snprintf_add(&dst, lim, "<%s: %p>: ", me->base.kind->name, me);
2928 require_quiet(n >= 0, exit);
2929 }
2930 description = strdup(buffer);
2931
2932 exit:
2933 return description;
2934 }
2935
2936 //======================================================================================================================
2937
2938 static void
2939 _mdns_session_invalidate_internal(mdns_session_t session);
2940
2941 static void
_mdns_session_invalidate(mdns_session_t me)2942 _mdns_session_invalidate(mdns_session_t me)
2943 {
2944 // Set the state to done to prevent any further callback invocations.
2945 me->state = mdns_session_state_done;
2946 mdns_retain(me);
2947 dispatch_async(_mdns_resolver_queue(),
2948 ^{
2949 _mdns_session_invalidate_internal(me);
2950 if (me->callbacks->finalize_context) {
2951 me->callbacks->finalize_context(me->context);
2952 }
2953 me->context = NULL;
2954 mdns_release(me);
2955 });
2956 }
2957
2958 static void
_mdns_session_invalidate_internal(const mdns_session_t me)2959 _mdns_session_invalidate_internal(const mdns_session_t me)
2960 {
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);
2965 }
2966 }
2967
2968 //======================================================================================================================
2969
2970 static bool
_mdns_session_is_ready(const mdns_session_t me)2971 _mdns_session_is_ready(const mdns_session_t me)
2972 {
2973 return ((me->state == mdns_session_state_activated) && me->is_ready);
2974 }
2975
2976 //======================================================================================================================
2977
2978 static OSStatus
_mdns_session_initialize(const mdns_session_t me,const mdns_resolver_t resolver,const bool need_bytestream,const mdns_delegation_t * const delegation,const uint8_t * const qname)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)
2981 {
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);
2985 } else {
2986 return kNoErr;
2987 }
2988 }
2989
2990 //======================================================================================================================
2991
2992 static void
_mdns_session_activate(const mdns_session_t me)2993 _mdns_session_activate(const mdns_session_t me)
2994 {
2995 require_return(me->state == mdns_session_state_nascent);
2996
2997 OSStatus err;
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);
3001
3002 dispatch_source_set_event_handler(me->lateness_timer,
3003 ^{
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);
3008 }
3009 }
3010 });
3011 dispatch_activate(me->lateness_timer);
3012 }
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);
3020 }
3021 me->state = mdns_session_state_activated;
3022 err = kNoErr;
3023
3024 exit:
3025 if (err) {
3026 me->state = mdns_session_state_failed;
3027 _mdns_common_session_terminate_async(me, err);
3028 }
3029 }
3030
3031 //======================================================================================================================
3032
3033 static void
_mdns_session_send(const mdns_session_t me,const dispatch_data_t msg,const uint16_t qtype)3034 _mdns_session_send(const mdns_session_t me, const dispatch_data_t msg, const uint16_t qtype)
3035 {
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;
3039 if (kind->send) {
3040 kind->send(me, msg, qtype);
3041 }
3042 }
3043 }
3044
3045 //======================================================================================================================
3046
3047 static bool
_mdns_session_is_bytestream(const mdns_session_t me)3048 _mdns_session_is_bytestream(const mdns_session_t me)
3049 {
3050 return me->is_stream;
3051 }
3052
3053 //======================================================================================================================
3054
3055 static void
_mdns_session_set_callbacks(mdns_session_t me,const mdns_session_callbacks_t * const callbacks,void * const context)3056 _mdns_session_set_callbacks(mdns_session_t me, const mdns_session_callbacks_t * const callbacks, void * const context)
3057 {
3058 if (me->state == mdns_session_state_nascent) {
3059 me->context = context;
3060 me->callbacks = callbacks;
3061 }
3062 }
3063
3064 //======================================================================================================================
3065
3066 static void
_mdns_session_set_lateness_time(const mdns_session_t me,uint32_t time_ms)3067 _mdns_session_set_lateness_time(const mdns_session_t me, uint32_t time_ms)
3068 {
3069 require_return(me->state == mdns_session_state_nascent);
3070 me->lateness_time_ms = time_ms;
3071 }
3072
3073 //======================================================================================================================
3074
3075 static void
_mdns_session_finalize_context_with_release(void * const context)3076 _mdns_session_finalize_context_with_release(void * const context)
3077 {
3078 mdns_release((mdns_object_t)context);
3079 }
3080
3081 //======================================================================================================================
3082 // MARK: - Session Common Subkind Methods
3083
3084 static nw_endpoint_t
_mdns_common_session_get_server_endpoint(const mdns_any_session_t any)3085 _mdns_common_session_get_server_endpoint(const mdns_any_session_t any)
3086 {
3087 const mdns_session_t me = any.session;
3088 return me->server->endpoint;
3089 }
3090
3091 //======================================================================================================================
3092
3093 static void
_mdns_common_session_invoke_ready_event_handler(const mdns_any_session_t any)3094 _mdns_common_session_invoke_ready_event_handler(const mdns_any_session_t any)
3095 {
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);
3101 }
3102 }
3103 }
3104
3105 //======================================================================================================================
3106
3107 static void
_mdns_common_session_invoke_receive(const mdns_any_session_t any,const dispatch_data_t msg)3108 _mdns_common_session_invoke_receive(const mdns_any_session_t any, const dispatch_data_t msg)
3109 {
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);
3116 }
3117 }
3118 }
3119
3120 //======================================================================================================================
3121
3122 static void
_mdns_common_session_terminate(const mdns_any_session_t any,const OSStatus error)3123 _mdns_common_session_terminate(const mdns_any_session_t any, const OSStatus error)
3124 {
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);
3131 }
3132 }
3133 }
3134
3135 //======================================================================================================================
3136
3137 static void
_mdns_common_session_terminate_async(const mdns_any_session_t any,const OSStatus error)3138 _mdns_common_session_terminate_async(const mdns_any_session_t any, const OSStatus error)
3139 {
3140 const mdns_session_t me = any.session;
3141 mdns_retain(me);
3142 dispatch_async(_mdns_resolver_queue(),
3143 ^{
3144 _mdns_common_session_terminate(me, error);
3145 mdns_release(me);
3146 });
3147 }
3148
3149 //======================================================================================================================
3150 // MARK: - Connection Session Private Methods
3151
3152 static void
_mdns_connection_session_finalize(__unused const mdns_connection_session_t me)3153 _mdns_connection_session_finalize(__unused const mdns_connection_session_t me)
3154 {
3155 // Nothing to free.
3156 }
3157
3158 //======================================================================================================================
3159
3160 static nw_endpoint_t
3161 _mdns_create_domain_attributed_endpoint(nw_endpoint_t original_endpoint, const uint8_t *hostname, OSStatus *out_error);
3162
3163 static OSStatus
_mdns_connection_session_initialize(const mdns_connection_session_t me,const mdns_resolver_t resolver,const bool need_bytestream,const mdns_delegation_t * const delegation,const uint8_t * const qname)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)
3166 {
3167 OSStatus err;
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);
3174
3175 me->is_bytestream = true;
3176 } else {
3177 params = _mdns_resolver_get_datagram_params(resolver, &err);
3178 require_noerr_quiet(err, exit);
3179
3180 me->is_bytestream = false;
3181 }
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);
3186
3187 if (delegation->type == mdns_delegation_type_pid) {
3188 nw_parameters_set_pid(params_alt, delegation->ident.pid);
3189 } else {
3190 nw_parameters_set_e_proc_uuid(params_alt, delegation->ident.uuid);
3191 }
3192 params = params_alt;
3193 }
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, *)) {
3196 if (qname) {
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;
3201 } else {
3202 os_log_error(_mdns_resolver_log(),
3203 "Failed to create domain-attributed endpoint for %@: %{mdns:err}ld",
3204 server_endpoint, (long)create_err);
3205 }
3206 }
3207 }
3208 me->connection = nw_connection_create(server_endpoint, params);
3209 require_action_quiet(me->connection, exit, err = kNoResourcesErr);
3210
3211 exit:
3212 nw_forget(¶ms_alt);
3213 nw_forget(&server_endpoint_alt);
3214 return err;
3215 }
3216
3217 static nw_endpoint_t
_mdns_create_domain_attributed_endpoint(const nw_endpoint_t original_endpoint,const uint8_t * const domain,OSStatus * out_error)3218 _mdns_create_domain_attributed_endpoint(const nw_endpoint_t original_endpoint, const uint8_t * const domain,
3219 OSStatus *out_error)
3220 {
3221 OSStatus err;
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);
3225
3226 nw_endpoint_t endpoint = nw_endpoint_create_address(sa);
3227 require_action_quiet(endpoint, exit, err = kNoResourcesErr);
3228
3229 char domain_str[kDNSServiceMaxDomainName];
3230 err = DomainNameToString(domain, NULL, domain_str, NULL);
3231 require_noerr_quiet(err, exit);
3232
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);
3236
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);
3239 }
3240 nw_forget(&parent);
3241 result = endpoint;
3242 endpoint = NULL;
3243
3244 exit:
3245 nw_forget(&endpoint);
3246 if (out_error) {
3247 *out_error = err;
3248 }
3249 return result;
3250 }
3251
3252 //======================================================================================================================
3253
3254 static void
3255 _mdns_connection_session_schedule_receive(mdns_connection_session_t session);
3256
3257 static OSStatus
_mdns_connection_session_activate(const mdns_connection_session_t me)3258 _mdns_connection_session_activate(const mdns_connection_session_t me)
3259 {
3260 mdns_retain(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)
3264 {
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);
3272 }
3273 }
3274 if (state == nw_connection_state_cancelled) {
3275 mdns_release(me);
3276 }
3277 });
3278 nw_connection_start(me->connection);
3279 _mdns_connection_session_schedule_receive(me);
3280 return kNoErr;
3281 }
3282
3283 static void
_mdns_connection_session_schedule_receive(const mdns_connection_session_t me)3284 _mdns_connection_session_schedule_receive(const mdns_connection_session_t me)
3285 {
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)
3288 {
3289 if (likely(me->connection)) {
3290 if (msg) {
3291 _mdns_common_session_invoke_receive(me, msg);
3292 }
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);
3296 } else {
3297 _mdns_connection_session_schedule_receive(me);
3298 }
3299 }
3300 });
3301 }
3302
3303 //======================================================================================================================
3304
3305 static void
_mdns_connection_session_invalidate(const mdns_connection_session_t me)3306 _mdns_connection_session_invalidate(const mdns_connection_session_t me)
3307 {
3308 if (me->connection) {
3309 nw_connection_cancel(me->connection);
3310 nw_forget(&me->connection);
3311 }
3312 }
3313
3314 //======================================================================================================================
3315
3316 static void
_mdns_connection_session_send(const mdns_connection_session_t me,const dispatch_data_t msg,const uint16_t qtype)3317 _mdns_connection_session_send(const mdns_connection_session_t me, const dispatch_data_t msg, const uint16_t qtype)
3318 {
3319 os_log_debug(_mdns_resolver_log(), "Sending message on connection %@", me->connection);
3320
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);
3326 }
3327 if (activity) {
3328 nw_connection_start_activity(me->connection, activity);
3329 }
3330 nw_connection_send(me->connection, msg, NW_CONNECTION_DEFAULT_MESSAGE_CONTEXT, true,
3331 ^(const nw_error_t error)
3332 {
3333 if (activity) {
3334 if (me->connection) {
3335 nw_connection_end_activity(me->connection, activity);
3336 }
3337 nw_release(activity);
3338 }
3339 if (likely(me->connection) && error) {
3340 _mdns_common_session_terminate(me, kConnectionErr);
3341 }
3342 });
3343 }
3344
3345 //======================================================================================================================
3346
3347 static bool
_mdns_connection_session_is_bytestream(const mdns_connection_session_t me)3348 _mdns_connection_session_is_bytestream(const mdns_connection_session_t me)
3349 {
3350 return me->is_bytestream;
3351 }
3352
3353 //======================================================================================================================
3354 // MARK: - UDP Socket Session Private Methods
3355
3356 static void
_mdns_udp_socket_session_finalize(const mdns_udp_socket_session_t me)3357 _mdns_udp_socket_session_finalize(const mdns_udp_socket_session_t me)
3358 {
3359 _mdns_socket_forget(&me->sock);
3360 }
3361
3362 //======================================================================================================================
3363
3364 static OSStatus
3365 _mdns_bind_ipv6_socket_to_random_port(const int sock);
3366
3367 static OSStatus
_mdns_udp_socket_session_initialize(const mdns_udp_socket_session_t me,const mdns_resolver_t resolver,__unused const bool need_bytestream,const mdns_delegation_t * const delegation,const uint8_t * const qname)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)
3370 {
3371 OSStatus err;
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);
3375
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;
3387 }
3388 }
3389 #endif
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);
3394
3395 #define _do_setsockopt(SOCK, LEVEL, NAME, VALUE_PTR, VALUE_LEN) \
3396 do { \
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); \
3402 } \
3403 } while (0)
3404
3405 const int on = 1;
3406 // Ensure that socket binds to a random port.
3407 if (ipv4) {
3408 _do_setsockopt(sock, SOL_SOCKET, SO_RANDOMPORT, &on, sizeof(on));
3409 } else {
3410 // Workaround for SO_RANDOMPORT not working for UDP/IPv6.
3411 _mdns_bind_ipv6_socket_to_random_port(sock);
3412 }
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);
3419 if (ipv4) {
3420 _do_setsockopt(sock, IPPROTO_IP, IP_BOUND_IF, &if_index, sizeof(if_index));
3421 } else {
3422 _do_setsockopt(sock, IPPROTO_IPV6, IPV6_BOUND_IF, &if_index, sizeof(if_index));
3423 }
3424 }
3425 // If delegation info is provided, attribute outbound data to the delegator.
3426 if (delegation) {
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));
3430 break;
3431
3432 case mdns_delegation_type_uuid:
3433 _do_setsockopt(sock, SOL_SOCKET, SO_DELEGATED_UUID, delegation->ident.uuid,
3434 sizeof(delegation->ident.uuid));
3435 break;
3436
3437 default:
3438 case mdns_delegation_type_none:
3439 break;
3440 }
3441 }
3442 #undef _do_setsockopt
3443 if (qname) {
3444 char qname_str[kDNSServiceMaxDomainName];
3445 err = DomainNameToString(qname, NULL, qname_str, NULL);
3446 require_noerr_quiet(err, exit);
3447
3448 const bool ok = ne_session_set_socket_attributes(sock, qname_str, NULL);
3449 if (!ok) {
3450 os_log_error(_mdns_resolver_log(), "ne_session_set_socket_attributes() failed for '%s'", qname_str);
3451 }
3452 }
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);
3457 if (!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);
3464 err = kNoErr;
3465 } else {
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);
3468 goto exit;
3469 }
3470 #else
3471 memcpy(&me->server_addr, dst, dst_len);
3472 me->server_addr_len = dst_len;
3473 #endif
3474 me->sock = sock;
3475 sock = kInvalidSocketRef;
3476
3477 exit:
3478 _mdns_socket_forget(&sock);
3479 return err;
3480 }
3481
3482 static OSStatus
_mdns_bind_ipv6_socket_to_random_port(const int sock)3483 _mdns_bind_ipv6_socket_to_random_port(const int sock)
3484 {
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;
3490 uint16_t port;
3491 OSStatus err;
3492 int tries = 0;
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.
3495 do {
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);
3500 ++tries;
3501 } while ((err == EADDRINUSE) && (tries < 10000));
3502 if (err) {
3503 os_log_error(_mdns_resolver_log(),
3504 "Binding IPv6 socket to random port failed -- error: %{mdns:err}ld, tries: %d", (long)err, tries);
3505 } else {
3506 os_log_debug(_mdns_resolver_log(),
3507 "Binding IPv6 socket to random port succeeded -- port: %u, tries: %d", port, tries);
3508 }
3509 return err;
3510 }
3511
3512 //======================================================================================================================
3513
3514 static void
3515 _mdns_udp_socket_session_read_handler(void *ctx);
3516
3517 #if MDNS_USE_CONNECTED_UDP_SOCKETS
3518 static void
3519 _mdns_udp_socket_session_write_handler(void *ctx);
3520 #endif
3521
3522 static void
3523 _mdns_udp_socket_session_cancel_handler(void *ctx);
3524
3525 static OSStatus
_mdns_udp_socket_session_activate(const mdns_udp_socket_session_t me)3526 _mdns_udp_socket_session_activate(const mdns_udp_socket_session_t me)
3527 {
3528 OSStatus err;
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);
3531
3532 mdns_retain(me);
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;
3540 } else {
3541 me->read_source_suspended = true;
3542
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);
3546
3547 mdns_retain(me);
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);
3552 }
3553 #else
3554 dispatch_activate(me->read_source);
3555 #endif
3556 err = kNoErr;
3557
3558 exit:
3559 return err;
3560 }
3561
3562 static void
_mdns_udp_socket_session_read_handler(void * const ctx)3563 _mdns_udp_socket_session_read_handler(void * const ctx)
3564 {
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);
3569 #else
3570 sockaddr_ip sender;
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);
3573 #endif
3574 const OSStatus err = map_socket_value_errno(me->sock, n >= 0, n);
3575 require_noerr_quiet(err, exit);
3576
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);
3583 } else {
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);
3588
3589 if (IN6_IS_ADDR_LINKLOCAL(&sa1->sin6_addr) && (sa1->sin6_scope_id != 0) &&
3590 (sa1->sin6_scope_id != sa2->sin6_scope_id)) {
3591 goto exit;
3592 }
3593 }
3594 #endif
3595 dispatch_data_t msg = dispatch_data_create(msg_buf, (size_t)n, _mdns_resolver_queue(),
3596 DISPATCH_DATA_DESTRUCTOR_DEFAULT);
3597 if (msg) {
3598 _mdns_common_session_invoke_receive(me, msg);
3599 dispatch_forget(&msg);
3600 }
3601
3602 exit:
3603 if (err && (err != EWOULDBLOCK)) {
3604 _mdns_common_session_terminate(me, err);
3605 }
3606 }
3607
3608 #if MDNS_USE_CONNECTED_UDP_SOCKETS
3609 static void
_mdns_udp_socket_session_write_handler(void * const ctx)3610 _mdns_udp_socket_session_write_handler(void * const ctx)
3611 {
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);
3618 }
3619 #endif
3620
3621 static void
_mdns_udp_socket_session_cancel_handler(void * const ctx)3622 _mdns_udp_socket_session_cancel_handler(void * const ctx)
3623 {
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);
3628 }
3629 #else
3630 _mdns_socket_forget(&me->sock);
3631 #endif
3632 mdns_release(me);
3633 }
3634
3635 //======================================================================================================================
3636
3637 static void
_mdns_udp_socket_session_invalidate(const mdns_udp_socket_session_t me)3638 _mdns_udp_socket_session_invalidate(const mdns_udp_socket_session_t me)
3639 {
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);
3643 #else
3644 dispatch_source_forget(&me->read_source);
3645 #endif
3646 }
3647
3648 //======================================================================================================================
3649
3650 #if MDNS_USE_CONNECTED_UDP_SOCKETS
3651 static bool
_mdns_udp_socket_session_is_ready(const mdns_udp_socket_session_t me)3652 _mdns_udp_socket_session_is_ready(const mdns_udp_socket_session_t me)
3653 {
3654 return me->connected;
3655 }
3656 #endif
3657
3658 //======================================================================================================================
3659
3660 static void
_mdns_udp_socket_session_send(const mdns_udp_socket_session_t me,const dispatch_data_t msg,__unused const uint16_t qtype)3661 _mdns_udp_socket_session_send(const mdns_udp_socket_session_t me, const dispatch_data_t msg,
3662 __unused const uint16_t qtype)
3663 {
3664 const void * msg_ptr;
3665 size_t msg_len;
3666 dispatch_data_t msg_map = dispatch_data_create_map(msg, &msg_ptr, &msg_len);
3667 require_quiet(msg_map, exit);
3668
3669 #if MDNS_USE_CONNECTED_UDP_SOCKETS
3670 const ssize_t n = send(me->sock, msg_ptr, msg_len, 0);
3671 #else
3672 const ssize_t n = sendto(me->sock, msg_ptr, msg_len, 0, &me->server_addr.sa, me->server_addr_len);
3673 #endif
3674 const OSStatus err = map_socket_value_errno(me->sock, n >= 0, n);
3675 if (err) {
3676 os_log_error(_mdns_resolver_log(), "sending to %@ failed: %{darwin.errno}d", me->base.server, (int)err);
3677 }
3678 require_noerr_quiet(err, exit);
3679
3680 exit:
3681 dispatch_release_null_safe(msg_map);
3682 }
3683
3684 //======================================================================================================================
3685 // MARK: - URL Session Private Methods
3686
3687 static void
_mdns_url_session_finalize(__unused const mdns_url_session_t me)3688 _mdns_url_session_finalize(__unused const mdns_url_session_t me)
3689 {
3690 nw_forget(&me->url_endpoint);
3691 }
3692
3693 //======================================================================================================================
3694
3695 static OSStatus
_mdns_url_session_initialize(const mdns_url_session_t me,const mdns_resolver_t resolver,__unused const bool need_bytestream,__unused const mdns_delegation_t * const delegation,__unused const uint8_t * const qname)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)
3699 {
3700 OSStatus err;
3701 const nw_parameters_t params = _mdns_resolver_get_stream_params(resolver, &err);
3702 require_noerr_quiet(err, exit);
3703
3704 me->url_endpoint = nw_parameters_copy_url_endpoint(params);
3705 require_action_quiet(me->url_endpoint, exit, err = kNoResourcesErr);
3706
3707 exit:
3708 return err;
3709 }
3710
3711 //======================================================================================================================
3712
3713 static OSStatus
_mdns_url_session_activate(__unused const mdns_url_session_t me)3714 _mdns_url_session_activate(__unused const mdns_url_session_t me)
3715 {
3716 // Nothing to do for now.
3717 return kNoErr;
3718 }
3719
3720 //======================================================================================================================
3721
3722 static void
_mdns_url_session_invalidate(const mdns_url_session_t me)3723 _mdns_url_session_invalidate(const mdns_url_session_t me)
3724 {
3725 if (me->http_task) {
3726 http_task_cancel(me->http_task);
3727 me->http_task = NULL;
3728 }
3729 }
3730
3731 //======================================================================================================================
3732
3733 static void
_mdns_url_session_send(const mdns_url_session_t me,const dispatch_data_t msg,const uint16_t qtype)3734 _mdns_url_session_send(const mdns_url_session_t me, const dispatch_data_t msg, const uint16_t qtype)
3735 {
3736 os_log_debug(_mdns_resolver_log(), "Sending message on URL %@", me->url_endpoint);
3737
3738 mdns_retain(me);
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)) {
3744 invoked = true;
3745 if (likely(me->http_task)) {
3746 if (data) {
3747 _mdns_common_session_invoke_receive(me, data);
3748 }
3749 if (task_error) {
3750 os_log_error(_mdns_resolver_log(), "Got error %@", task_error);
3751 _mdns_common_session_terminate(me, (OSStatus)CFErrorGetCode(task_error));
3752 }
3753 }
3754 mdns_release(me);
3755 }
3756 });
3757 if (me->http_task) {
3758 http_task_start(me->http_task);
3759 } else {
3760 os_log_error(_mdns_resolver_log(), "Failed to create HTTP task");
3761 _mdns_common_session_terminate_async(me, kUnknownErr);
3762 }
3763 }
3764
3765 //======================================================================================================================
3766 // MARK: - Querier Public Methods
3767
3768 void
mdns_querier_set_queue(mdns_querier_t me,dispatch_queue_t queue)3769 mdns_querier_set_queue(mdns_querier_t me, dispatch_queue_t queue)
3770 {
3771 if (!me->user_activated || !me->user_queue)
3772 {
3773 if (queue) {
3774 dispatch_retain(queue);
3775 }
3776 dispatch_release_null_safe(me->user_queue);
3777 me->user_queue = queue;
3778 _mdns_querier_activate_if_ready(me);
3779 }
3780 }
3781
3782 //======================================================================================================================
3783
3784 OSStatus
mdns_querier_set_query(mdns_querier_t me,const uint8_t * qname,uint16_t qtype,uint16_t qclass)3785 mdns_querier_set_query(mdns_querier_t me, const uint8_t *qname, uint16_t qtype, uint16_t qclass)
3786 {
3787 OSStatus err;
3788 require_action_quiet(!me->user_activated || !mdns_query_message_get_qname(me->query), exit,
3789 err = kAlreadyInitializedErr);
3790
3791 err = mdns_query_message_set_qname(me->query, qname);
3792 require_noerr_quiet(err, exit);
3793
3794 mdns_query_message_set_qtype(me->query, qtype);
3795 mdns_query_message_set_qclass(me->query, qclass);
3796
3797 _mdns_querier_activate_if_ready(me);
3798 err = kNoErr;
3799
3800 exit:
3801 return err;
3802 }
3803
3804 //======================================================================================================================
3805
3806 void
mdns_querier_set_dnssec_ok(const mdns_querier_t me,const bool set)3807 mdns_querier_set_dnssec_ok(const mdns_querier_t me, const bool set)
3808 {
3809 require_return(!me->user_activated);
3810 mdns_query_message_set_do_bit(me->query, set);
3811 }
3812
3813 //======================================================================================================================
3814
3815 void
mdns_querier_set_checking_disabled(const mdns_querier_t me,const bool checking_disabled)3816 mdns_querier_set_checking_disabled(const mdns_querier_t me, const bool checking_disabled)
3817 {
3818 require_return(!me->user_activated);
3819 mdns_query_message_set_cd_bit(me->query, checking_disabled);
3820 }
3821
3822 //======================================================================================================================
3823
3824 void
mdns_querier_set_delegator_pid(mdns_querier_t me,pid_t pid)3825 mdns_querier_set_delegator_pid(mdns_querier_t me, pid_t pid)
3826 {
3827 if (!me->user_activated) {
3828 me->delegation.type = mdns_delegation_type_pid;
3829 me->delegation.ident.pid = pid;
3830 }
3831 }
3832
3833 //======================================================================================================================
3834
3835 void
mdns_querier_set_delegator_uuid(mdns_querier_t me,uuid_t uuid)3836 mdns_querier_set_delegator_uuid(mdns_querier_t me, uuid_t uuid)
3837 {
3838 if (!me->user_activated) {
3839 me->delegation.type = mdns_delegation_type_uuid;
3840 uuid_copy(me->delegation.ident.uuid, uuid);
3841 }
3842 }
3843
3844 //======================================================================================================================
3845
3846 void
mdns_querier_set_user_id(const mdns_querier_t me,const uint32_t user_id)3847 mdns_querier_set_user_id(const mdns_querier_t me, const uint32_t user_id)
3848 {
3849 require_return(!me->user_activated);
3850 me->user_id = user_id;
3851 }
3852
3853 //======================================================================================================================
3854
3855 OSStatus
mdns_querier_set_log_label(const mdns_querier_t me,const char * const format,...)3856 mdns_querier_set_log_label(const mdns_querier_t me, const char * const format, ...)
3857 {
3858 require_return_value(!me->user_activated, kAlreadyInitializedErr);
3859
3860 va_list args;
3861 va_start(args, format);
3862 char *inner_str = NULL;
3863 vasprintf(&inner_str, format, args);
3864 va_end(args);
3865 OSStatus err;
3866 require_action_quiet(inner_str, exit, err = kNoMemoryErr);
3867
3868 char *log_label = NULL;
3869 asprintf(&log_label, "[%s] ", inner_str);
3870 require_action_quiet(log_label, exit, err = kNoMemoryErr);
3871
3872 FreeNullSafe(me->log_label);
3873 me->log_label = log_label;
3874 log_label = NULL;
3875 err = kNoErr;
3876
3877 exit:
3878 ForgetMem(&inner_str);
3879 return err;
3880 }
3881
3882 //======================================================================================================================
3883
3884 void
mdns_querier_set_result_handler(mdns_querier_t me,mdns_querier_result_handler_t handler)3885 mdns_querier_set_result_handler(mdns_querier_t me, mdns_querier_result_handler_t handler)
3886 {
3887 if (!me->user_activated) {
3888 const mdns_querier_result_handler_t new_handler = handler ? Block_copy(handler) : NULL;
3889 if (me->handler) {
3890 Block_release(me->handler);
3891 }
3892 me->handler = new_handler;
3893 }
3894 }
3895
3896 //======================================================================================================================
3897
3898 static void
3899 _mdns_querier_set_time_limit_ms(mdns_querier_t querier, int32_t time_limit_ms);
3900
3901 void
mdns_querier_set_time_limit_ms(const mdns_querier_t me,const int32_t time_limit_ms)3902 mdns_querier_set_time_limit_ms(const mdns_querier_t me, const int32_t time_limit_ms)
3903 {
3904 mdns_retain(me);
3905 dispatch_async(_mdns_resolver_queue(),
3906 ^{
3907 _mdns_querier_set_time_limit_ms(me, time_limit_ms);
3908 mdns_release(me);
3909 });
3910 }
3911
3912 static void
_mdns_querier_set_time_limit_ms(const mdns_querier_t me,const int32_t time_limit_ms)3913 _mdns_querier_set_time_limit_ms(const mdns_querier_t me, const int32_t time_limit_ms)
3914 {
3915 if (likely(!me->concluded)) {
3916 me->time_limit_ms = time_limit_ms;
3917 const OSStatus err = _mdns_querier_reset_time_limit(me);
3918 if (err) {
3919 _mdns_querier_conclude(me, err);
3920 }
3921 }
3922 }
3923
3924 //======================================================================================================================
3925
3926 void
mdns_querier_activate(mdns_querier_t me)3927 mdns_querier_activate(mdns_querier_t me)
3928 {
3929 if (!me->user_activated) {
3930 me->user_activated = true;
3931 _mdns_querier_activate_if_ready(me);
3932 }
3933 }
3934
3935 //======================================================================================================================
3936
3937 void
mdns_querier_invalidate(mdns_querier_t me)3938 mdns_querier_invalidate(mdns_querier_t me)
3939 {
3940 mdns_retain(me);
3941 dispatch_async(_mdns_resolver_queue(),
3942 ^{
3943 _mdns_querier_conclude(me, mdns_querier_result_type_invalidation);
3944 mdns_release(me);
3945 });
3946 }
3947
3948 //======================================================================================================================
3949
3950 const uint8_t *
mdns_querier_get_qname(const mdns_querier_t me)3951 mdns_querier_get_qname(const mdns_querier_t me)
3952 {
3953 return mdns_query_message_get_qname(me->query);
3954 }
3955
3956 //======================================================================================================================
3957
3958 uint16_t
mdns_querier_get_qtype(const mdns_querier_t me)3959 mdns_querier_get_qtype(const mdns_querier_t me)
3960 {
3961 return mdns_query_message_get_qtype(me->query);
3962 }
3963
3964 //======================================================================================================================
3965
3966 uint16_t
mdns_querier_get_qclass(const mdns_querier_t me)3967 mdns_querier_get_qclass(const mdns_querier_t me)
3968 {
3969 return mdns_query_message_get_qclass(me->query);
3970 }
3971
3972 //======================================================================================================================
3973
3974 mdns_resolver_type_t
mdns_querier_get_resolver_type(const mdns_querier_t me)3975 mdns_querier_get_resolver_type(const mdns_querier_t me)
3976 {
3977 return _mdns_resolver_get_type(me->resolver);
3978 }
3979
3980 //======================================================================================================================
3981
3982 mdns_querier_result_type_t
mdns_querier_get_result_type(const mdns_querier_t me)3983 mdns_querier_get_result_type(const mdns_querier_t me)
3984 {
3985 return me->result_type;
3986 }
3987
3988 //======================================================================================================================
3989
3990 uint32_t
mdns_querier_get_send_count(const mdns_querier_t me)3991 mdns_querier_get_send_count(const mdns_querier_t me)
3992 {
3993 return atomic_load(&me->send_count);
3994 }
3995
3996 //======================================================================================================================
3997
3998 uint32_t
mdns_querier_get_query_length(const mdns_querier_t me)3999 mdns_querier_get_query_length(const mdns_querier_t me)
4000 {
4001 return (uint32_t)mdns_message_get_length(me->query);
4002 }
4003
4004 //======================================================================================================================
4005
4006 const uint8_t *
mdns_querier_get_response_ptr(const mdns_querier_t me)4007 mdns_querier_get_response_ptr(const mdns_querier_t me)
4008 {
4009 return _mdns_querier_get_response_ptr_safe(me);
4010 }
4011
4012 //======================================================================================================================
4013
4014 uint32_t
mdns_querier_get_response_length(const mdns_querier_t me)4015 mdns_querier_get_response_length(const mdns_querier_t me)
4016 {
4017 return (uint32_t)_mdns_querier_get_response_length_safe(me);
4018 }
4019
4020 //======================================================================================================================
4021
4022 bool
mdns_querier_response_is_fabricated(const mdns_querier_t me)4023 mdns_querier_response_is_fabricated(const mdns_querier_t me)
4024 {
4025 return me->response_is_fabricated;
4026 }
4027
4028 //======================================================================================================================
4029
4030 OSStatus
mdns_querier_get_error(const mdns_querier_t me)4031 mdns_querier_get_error(const mdns_querier_t me)
4032 {
4033 return me->error;
4034 }
4035
4036 //======================================================================================================================
4037
4038 bool
mdns_querier_get_dnssec_ok(const mdns_querier_t me)4039 mdns_querier_get_dnssec_ok(const mdns_querier_t me)
4040 {
4041 return mdns_query_message_do_bit_is_set(me->query);
4042 }
4043
4044 //======================================================================================================================
4045
4046 mdns_query_over_tcp_reason_t
mdns_querier_get_over_tcp_reason(const mdns_querier_t me)4047 mdns_querier_get_over_tcp_reason(const mdns_querier_t me)
4048 {
4049 return me->over_tcp_reason;
4050 }
4051
4052 //======================================================================================================================
4053
4054 bool
mdns_querier_match(const mdns_querier_t me,const uint8_t * const qname,const int qtype,const int qclass)4055 mdns_querier_match(const mdns_querier_t me, const uint8_t * const qname, const int qtype, const int qclass)
4056 {
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)) {
4060 return true;
4061 }
4062 }
4063 return false;
4064 }
4065
4066 //======================================================================================================================
4067
4068 bool
mdns_querier_has_concluded(const mdns_querier_t me)4069 mdns_querier_has_concluded(const mdns_querier_t me)
4070 {
4071 return (me->result_type != mdns_querier_result_type_null);
4072 }
4073
4074 //======================================================================================================================
4075
4076 uint32_t
mdns_querier_get_user_id(const mdns_querier_t me)4077 mdns_querier_get_user_id(const mdns_querier_t me)
4078 {
4079 return me->user_id;
4080 }
4081
4082 //======================================================================================================================
4083 // MARK: - Querier Private Methods
4084
4085 static void
_mdns_querier_finalize(mdns_querier_t me)4086 _mdns_querier_finalize(mdns_querier_t me)
4087 {
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);
4097 #endif
4098 }
4099
4100 //======================================================================================================================
4101
4102 static char *
_mdns_querier_copy_description(mdns_querier_t me,const bool debug,const bool privacy)4103 _mdns_querier_copy_description(mdns_querier_t me, const bool debug, const bool privacy)
4104 {
4105 char * description = NULL;
4106 char buffer[128];
4107 char * dst = buffer;
4108 const char * const lim = &buffer[countof(buffer)];
4109 int n;
4110 char qname_str[kDNSServiceMaxDomainName];
4111
4112 *dst = '\0';
4113 if (debug) {
4114 n = mdns_snprintf_add(&dst, lim, "<%s: %p>: ", me->base.kind->name, me);
4115 require_quiet(n >= 0, exit);
4116 }
4117 const char *qname;
4118 char strbuf[64];
4119 const uint8_t * const query_qname = mdns_query_message_get_qname(me->query);
4120 if (query_qname) {
4121 if (DomainNameToString(query_qname, NULL, qname_str, NULL) == kNoErr) {
4122 if (privacy) {
4123 n = DNSMessagePrintObfuscatedString(strbuf, sizeof(strbuf), qname_str);
4124 qname = (n >= 0) ? strbuf : "<REDACTED QNAME>";
4125 } else {
4126 qname = qname_str;
4127 }
4128 } else {
4129 qname = "<INVALID QNAME>";
4130 }
4131 } else {
4132 qname = "<NO QNAME>";
4133 }
4134 n = mdns_snprintf_add(&dst, lim, "%s", qname);
4135 require_quiet(n >= 0, exit);
4136
4137 const char * const type_str = DNSRecordTypeValueToString(mdns_query_message_get_qtype(me->query));
4138 if (type_str) {
4139 n = mdns_snprintf_add(&dst, lim, " %s", type_str);
4140 require_quiet(n >= 0, exit);
4141 } else {
4142 n = mdns_snprintf_add(&dst, lim, " TYPE%u", mdns_query_message_get_qtype(me->query));
4143 require_quiet(n >= 0, exit);
4144 }
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);
4148 } else {
4149 n = mdns_snprintf_add(&dst, lim, " CLASS%u", mdns_query_message_get_qclass(me->query));
4150 require_quiet(n >= 0, exit);
4151 }
4152 description = strdup(buffer);
4153
4154 exit:
4155 return description;
4156 }
4157
4158 //======================================================================================================================
4159
4160 static void
4161 _mdns_querier_activate(mdns_querier_t querier);
4162
4163 static void
_mdns_querier_activate_if_ready(mdns_querier_t me)4164 _mdns_querier_activate_if_ready(mdns_querier_t me)
4165 {
4166 if (me->user_activated && me->user_queue && mdns_query_message_get_qname(me->query)) {
4167 mdns_retain(me);
4168 dispatch_async(_mdns_resolver_queue(),
4169 ^{
4170 _mdns_querier_activate(me);
4171 mdns_release(me);
4172 });
4173 }
4174 }
4175
4176 static void
_mdns_querier_activate(mdns_querier_t me)4177 _mdns_querier_activate(mdns_querier_t me)
4178 {
4179 require_return(!me->activated && !me->concluded);
4180
4181 mdns_retain(me);
4182 me->activated = true;
4183
4184 uint16_t msg_id;
4185 if (_mdns_resolver_needs_zero_ids(me->resolver)) {
4186 msg_id = 0;
4187 } else {
4188 msg_id = (uint16_t)RandomRange(1, UINT16_MAX);
4189 }
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);
4194
4195 if (me->time_limit_ms != 0) {
4196 err = _mdns_querier_reset_time_limit(me);
4197 require_noerr_quiet(err, exit);
4198 }
4199 _mdns_resolver_register_querier(me->resolver, me, false);
4200
4201 exit:
4202 if (err) {
4203 _mdns_querier_conclude(me, err);
4204 }
4205 }
4206
4207 //======================================================================================================================
4208
4209 static void
_mdns_querier_session_handle_event(const mdns_session_t session,const mdns_session_event_t event,const OSStatus error,void * const context)4210 _mdns_querier_session_handle_event(const mdns_session_t session, const mdns_session_event_t event,
4211 const OSStatus error, void * const context)
4212 {
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);
4218
4219 switch (event) {
4220 case mdns_session_event_ready:
4221 _mdns_querier_send_query(me, session);
4222 break;
4223
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;
4229 }
4230 require_quiet(*ptr, exit);
4231
4232 *ptr = session->next;
4233 session->next = NULL;
4234 mdns_session_t tmp = session;
4235 mdns_session_forget(&tmp);
4236
4237 if (is_stream) {
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);
4242 }
4243 _mdns_querier_handle_stream_error(me, server);
4244 }
4245 break;
4246 }
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));
4251 }
4252 break;
4253
4254 default:
4255 break;
4256 }
4257
4258 exit:
4259 return;
4260 }
4261
4262 //======================================================================================================================
4263
4264 static bool
_mdns_querier_is_response_acceptable(const mdns_querier_t me,const mdns_message_t msg,bool * const out_truncated,bool * const out_suspicious,int * const out_rcode)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)
4267 {
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);
4273
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);
4278
4279 id_match = (msg_id == mdns_query_message_get_message_id(me->query)) ? true : false;
4280 if (id_match) {
4281 acceptable = true;
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))) {
4288 truncated = false;
4289 }
4290 *out_truncated = truncated;
4291 }
4292 if (out_rcode) {
4293 *out_rcode = DNSFlagsGetRCode(flags);
4294 }
4295 }
4296
4297 exit:
4298 if (out_suspicious) {
4299 *out_suspicious = (!id_match && question_match) ? true : false;
4300 }
4301 return acceptable;
4302 }
4303
4304 //======================================================================================================================
4305
4306 static void
_mdns_querier_conclude(const mdns_querier_t me,const mdns_querier_result_type_t result_type)4307 _mdns_querier_conclude(const mdns_querier_t me, const mdns_querier_result_type_t result_type)
4308 {
4309 _mdns_querier_conclude_ex(me, result_type, 0, NULL);
4310 }
4311
4312 //======================================================================================================================
4313
4314 static void
_mdns_querier_conclude_async(const mdns_querier_t me,const mdns_querier_result_type_t result_type)4315 _mdns_querier_conclude_async(const mdns_querier_t me, const mdns_querier_result_type_t result_type)
4316 {
4317 mdns_retain(me);
4318 dispatch_async(_mdns_resolver_queue(),
4319 ^{
4320 _mdns_querier_conclude(me, result_type);
4321 mdns_release(me);
4322 });
4323 }
4324
4325 //======================================================================================================================
4326
4327 static void
_mdns_querier_conclude_with_error(const mdns_querier_t me,const OSStatus error)4328 _mdns_querier_conclude_with_error(const mdns_querier_t me, const OSStatus error)
4329 {
4330 _mdns_querier_conclude_ex(me, mdns_querier_result_type_error, error, NULL);
4331 }
4332
4333 //======================================================================================================================
4334
4335 static void
_mdns_querier_conclude_with_error_async(const mdns_querier_t me,const OSStatus error)4336 _mdns_querier_conclude_with_error_async(const mdns_querier_t me, const OSStatus error)
4337 {
4338 mdns_retain(me);
4339 dispatch_async(_mdns_resolver_queue(),
4340 ^{
4341 _mdns_querier_conclude_with_error(me, error);
4342 mdns_release(me);
4343 });
4344 }
4345
4346 //======================================================================================================================
4347
4348 static void
_mdns_querier_conclude_with_response(const mdns_querier_t me,const mdns_message_t response)4349 _mdns_querier_conclude_with_response(const mdns_querier_t me, const mdns_message_t response)
4350 {
4351 _mdns_querier_conclude_ex(me, mdns_querier_result_type_response, 0, response);
4352 }
4353
4354 //======================================================================================================================
4355
4356 #define MDNS_QUERIER_RESPONSE_STATUS_FABRICATED 1
4357
4358 static void
_mdns_querier_conclude_with_response_async(const mdns_querier_t me,const mdns_message_t response,const bool fabricated)4359 _mdns_querier_conclude_with_response_async(const mdns_querier_t me, const mdns_message_t response,
4360 const bool fabricated)
4361 {
4362 mdns_retain(me);
4363 mdns_retain(response);
4364 dispatch_async(_mdns_resolver_queue(),
4365 ^{
4366 const OSStatus status = fabricated ? MDNS_QUERIER_RESPONSE_STATUS_FABRICATED : 0;
4367 _mdns_querier_conclude_ex(me, mdns_querier_result_type_response, status, response);
4368 mdns_release(me);
4369 mdns_release(response);
4370 });
4371 }
4372
4373 //======================================================================================================================
4374
4375 static bool
4376 _mdns_querier_postprocess_response(mdns_querier_t querier);
4377
4378 static void
_mdns_querier_conclude_ex(const mdns_querier_t me,const mdns_querier_result_type_t result_type,const OSStatus status,const mdns_message_t response)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)
4381 {
4382 dispatch_source_forget(&me->rtx_timer);
4383 dispatch_source_forget(&me->timeout_timer);
4384 mdns_forget(&me->bad_rcode_response);
4385
4386 _mdns_resolver_deregister_querier(me->resolver, me);
4387 require_return(!me->concluded);
4388
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));
4398 } else {
4399 os_log_info(_mdns_resolver_log(),
4400 "%{public}sQuerier concluded -- reason: response", _mdns_querier_get_log_label(me));
4401 }
4402 break;
4403 }
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));
4407 break;
4408
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));
4412 break;
4413
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));
4417 break;
4418
4419 case mdns_querier_result_type_error:
4420 me->error = status;
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);
4424 break;
4425
4426 case mdns_querier_result_type_null:
4427 break;
4428 }
4429 if (me->user_queue) {
4430 const mdns_querier_result_handler_t handler = me->handler;
4431 me->handler = NULL;
4432 mdns_retain(me);
4433 dispatch_async(me->user_queue,
4434 ^{
4435 me->result_type = result_type;
4436 if (handler) {
4437 handler();
4438 Block_release(handler);
4439 }
4440 mdns_release(me);
4441 });
4442 }
4443 if (me->activated) {
4444 mdns_release(me);
4445 }
4446 }
4447
4448 static bool
_mdns_querier_postprocess_response(const mdns_querier_t me)4449 _mdns_querier_postprocess_response(const mdns_querier_t me)
4450 {
4451 if (!me->resolver->squash_cnames) {
4452 return false;
4453 }
4454 const uint8_t *resp_ptr = _mdns_querier_get_response_ptr_safe(me);
4455 require_return_value(resp_ptr, false);
4456
4457 mdns_message_t new_msg = NULL;
4458 OSStatus err;
4459 size_t new_len;
4460 uint8_t *new_ptr = DNSMessageCollapse(resp_ptr, _mdns_querier_get_response_length_safe(me), &new_len, &err);
4461 if (new_ptr) {
4462 dispatch_data_t data = dispatch_data_create(new_ptr, new_len, NULL, DISPATCH_DATA_DESTRUCTOR_FREE);
4463 if (data) {
4464 new_ptr = NULL;
4465 new_msg = mdns_message_create_with_dispatch_data(data, mdns_message_init_option_disable_header_printing);
4466 dispatch_forget(&data);
4467 if (!new_msg) {
4468 err = kNoResourcesErr;
4469 }
4470 } else {
4471 ForgetMem(&new_ptr);
4472 err = kNoResourcesErr;
4473 }
4474 }
4475 bool fabricated;
4476 if (new_msg) {
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);
4484 fabricated = true;
4485 } else {
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);
4489 fabricated = false;
4490 }
4491 return fabricated;
4492 }
4493
4494 //======================================================================================================================
4495
4496 static void
4497 _mdns_querier_reregister_in_stream_mode(mdns_querier_t querier);
4498
4499 static void
_mdns_querier_session_receive(const mdns_session_t session,const dispatch_data_t msg_data,void * const context)4500 _mdns_querier_session_receive(const mdns_session_t session, const dispatch_data_t msg_data, void * const context)
4501 {
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));
4506
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;
4513 int rcode = 0;
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;
4517 if (acceptable) {
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);
4524 } else {
4525 _mdns_querier_conclude_with_response(me, msg);
4526 }
4527 } else {
4528 // Note: _mdns_querier_handle_bad_rcode() may or may not conclude the querier.
4529 _mdns_querier_handle_bad_rcode(me, msg, rcode, server);
4530 }
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
4536 } else {
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;
4545 }
4546 }
4547 #endif
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;
4557 }
4558 if (qtype_test) {
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;
4563 }
4564 }
4565 }
4566 }
4567 }
4568 #else
4569 (void)handled_response;
4570 #endif
4571 #endif
4572 }
4573 mdns_release(msg);
4574 }
4575
4576 static void
_mdns_querier_reregister_in_stream_mode(mdns_querier_t me)4577 _mdns_querier_reregister_in_stream_mode(mdns_querier_t me)
4578 {
4579 _mdns_resolver_deregister_querier(me->resolver, me);
4580 _mdns_resolver_register_querier(me->resolver, me, true);
4581 }
4582
4583 //======================================================================================================================
4584
4585 static mdns_session_t
4586 _mdns_querier_get_shared_session(mdns_querier_t querier);
4587
4588 static mdns_session_t
4589 _mdns_querier_get_unshared_session(mdns_querier_t querier);
4590
4591 static void
_mdns_querier_initiate_send(const mdns_querier_t me)4592 _mdns_querier_initiate_send(const mdns_querier_t me)
4593 {
4594 dispatch_source_forget(&me->rtx_timer);
4595 do {
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);
4600 return;
4601 }
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));
4606 return;
4607 }
4608 }
4609 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND || MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
4610 bool check_qtype_support = false;
4611 if (0) {
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;
4615 #endif
4616 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
4617 } else if (_mdns_resolver_use_problematic_qtype_workaround(me->resolver)) {
4618 check_qtype_support = true;
4619 #endif
4620 }
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)) {
4625 if (0) {
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);
4631 #endif
4632 } else {
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);
4636 }
4637 if (!me->bad_rcode_response) {
4638 OSStatus err;
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;
4643 }
4644 me->bad_rcode_bitmap |= _mdns_rank_to_bitmask(server->rank);
4645 _mdns_querier_set_current_server(me, NULL);
4646 }
4647 }
4648 #endif // MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND || MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
4649 } while (!me->current_server);
4650
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));
4653
4654 dispatch_source_set_event_handler(me->rtx_timer,
4655 ^{
4656 dispatch_source_forget(&me->rtx_timer);
4657 _mdns_querier_handle_no_response(me);
4658 });
4659 dispatch_activate(me->rtx_timer);
4660
4661 mdns_session_t session;
4662 if (me->use_shared_stream) {
4663 session = _mdns_querier_get_shared_session(me);
4664 } else {
4665 session = _mdns_querier_get_unshared_session(me);
4666 }
4667 if (session) {
4668 _mdns_querier_send_query(me, session);
4669 }
4670 }
4671
4672 #define MDNS_RESOLVER_STREAM_LATENESS_TIME_MS (10 * kMillisecondsPerSecond)
4673
4674 static mdns_session_t
_mdns_querier_get_shared_session(const mdns_querier_t me)4675 _mdns_querier_get_shared_session(const mdns_querier_t me)
4676 {
4677 require_return_value(me->current_server, NULL);
4678
4679 const mdns_server_t server = me->current_server;
4680 mdns_session_t session = server->shared_stream_session;
4681 if (!session) {
4682 os_log_debug(_mdns_resolver_log(),
4683 "%{public}sCreating shared session to %@", _mdns_querier_get_log_label(me), server);
4684 OSStatus err;
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
4691 };
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;
4697 } else {
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);
4702 }
4703 }
4704 return session;
4705 }
4706
4707 static mdns_session_t
_mdns_querier_get_unshared_session(const mdns_querier_t me)4708 _mdns_querier_get_unshared_session(const mdns_querier_t me)
4709 {
4710 require_return_value(me->current_server, NULL);
4711
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) {
4717 break;
4718 }
4719 ptr = &session->next;
4720 }
4721 if (!session) {
4722 os_log_debug(_mdns_resolver_log(),
4723 "%{public}sCreating session to %@", _mdns_querier_get_log_label(me), server);
4724 OSStatus err;
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
4732 };
4733 mdns_retain(me);
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);
4737 }
4738 _mdns_session_activate(session);
4739 *ptr = session;
4740 } else {
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);
4745 }
4746 }
4747 return session;
4748 }
4749
4750 //======================================================================================================================
4751
4752 static void
_mdns_querier_start(const mdns_querier_t me)4753 _mdns_querier_start(const mdns_querier_t me)
4754 {
4755 _mdns_querier_set_current_server(me, NULL);
4756 if (me->use_stream) {
4757 me->rtx_interval_ms = MDNS_RESOLVER_CONNECTION_TIMEOUT_MS;
4758 } else {
4759 me->rtx_interval_ms = me->resolver->initial_dgram_rtx_ms;
4760 }
4761 _mdns_querier_initiate_send(me);
4762 }
4763
4764 //======================================================================================================================
4765
4766 static void
4767 _mdns_querier_send_query_immediate(mdns_querier_t querier, mdns_session_t session);
4768
4769 static void
4770 _mdns_querier_log_query_send(mdns_querier_t querier, mdns_session_t session);
4771
4772 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
4773 static void
4774 _mdns_querier_log_test_query_send(mdns_querier_t querier, mdns_session_t session);
4775
4776 static bool
4777 _mdns_querier_needs_test_query(mdns_querier_t querier, mdns_server_t server);
4778 #endif
4779
4780 static void
_mdns_querier_send_query(const mdns_querier_t me,const mdns_session_t session)4781 _mdns_querier_send_query(const mdns_querier_t me, const mdns_session_t session)
4782 {
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;
4790 }
4791 } else {
4792 _mdns_querier_send_query_immediate(me, session);
4793 me->did_send_bitmap |= bitmask;
4794 }
4795 } else {
4796 me->will_send_bitmap |= bitmask;
4797 }
4798 }
4799
4800 static void
_mdns_querier_send_query_immediate(const mdns_querier_t me,const mdns_session_t session)4801 _mdns_querier_send_query_immediate(const mdns_querier_t me, const mdns_session_t session)
4802 {
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));
4813 }
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);
4819 } else {
4820 os_log_error(_mdns_resolver_log(),
4821 "%{public}sFailed to create test query", _mdns_querier_get_log_label(me));
4822 }
4823 }
4824 }
4825 #endif
4826 }
4827
4828 static void
_mdns_querier_log_query_send(const mdns_querier_t me,const mdns_session_t session)4829 _mdns_querier_log_query_send(const mdns_querier_t me, const mdns_session_t session)
4830 {
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),
4835 query_len,
4836 me->send_count,
4837 session->server,
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),
4841 me->query);
4842 }
4843
4844 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
4845 static void
_mdns_querier_log_test_query_send(const mdns_querier_t me,const mdns_session_t session)4846 _mdns_querier_log_test_query_send(const mdns_querier_t me, const mdns_session_t session)
4847 {
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),
4853 query_len,
4854 me->test_send_count,
4855 session->server,
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),
4859 me->test_query);
4860 }
4861
4862 static bool
_mdns_querier_needs_test_query(const mdns_querier_t me,const mdns_server_t server)4863 _mdns_querier_needs_test_query(const mdns_querier_t me, const mdns_server_t server)
4864 {
4865 if (server->responds_to_problematics) {
4866 return false;
4867 }
4868 const int qtype = mdns_query_message_get_qtype(me->query);
4869 if (!_mdns_qtype_is_problematic(qtype)) {
4870 return false;
4871 }
4872 if (_mdns_querier_test_query_got_response(me, server)) {
4873 return false;
4874 }
4875 if (server->pqw_info && !_pqw_info_can_accept_qname(server->pqw_info, mdns_query_message_get_qname(me->query))) {
4876 return false;
4877 }
4878 return true;
4879 }
4880 #endif
4881
4882 //======================================================================================================================
4883
4884 static const char *
_mdns_querier_get_log_label(const mdns_querier_t me)4885 _mdns_querier_get_log_label(const mdns_querier_t me)
4886 {
4887 return (me->log_label ? me->log_label : "");
4888 }
4889
4890 //======================================================================================================================
4891
4892 static OSStatus
_mdns_querier_reset_time_limit(const mdns_querier_t me)4893 _mdns_querier_reset_time_limit(const mdns_querier_t me)
4894 {
4895 OSStatus err;
4896 require_action_quiet(!me->concluded && me->activated, exit, err = kNoErr);
4897
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);
4902
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);
4906
4907 dispatch_source_set_event_handler(me->timeout_timer,
4908 ^{
4909 _mdns_querier_conclude(me, mdns_querier_result_type_timeout);
4910 });
4911 dispatch_activate(me->timeout_timer);
4912 }
4913 err = kNoErr;
4914
4915 exit:
4916 return err;
4917 }
4918
4919 //======================================================================================================================
4920
4921 #define MDNS_QUERIER_UNANSWERED_QUERY_COUNT_MAX 2
4922 #define MDNS_QUERIER_RTX_INTERVAL_MAX_MS (120 * kMillisecondsPerSecond)
4923
4924 static void
_mdns_querier_handle_no_response(const mdns_querier_t me)4925 _mdns_querier_handle_no_response(const mdns_querier_t me)
4926 {
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);
4931 } else {
4932 ++me->unanswered_query_count;
4933 if (me->rtx_interval_ms <= (MDNS_QUERIER_RTX_INTERVAL_MAX_MS / 2)) {
4934 me->rtx_interval_ms *= 2;
4935 } else {
4936 me->rtx_interval_ms = MDNS_QUERIER_RTX_INTERVAL_MAX_MS;
4937 }
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;
4942 }
4943 if (session) {
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);
4948 #endif
4949 }
4950 _mdns_querier_set_current_server(me, NULL);
4951 }
4952 }
4953 }
4954 _mdns_querier_initiate_send(me);
4955 }
4956
4957 //======================================================================================================================
4958
4959 static void
_mdns_querier_set_current_server(const mdns_querier_t me,const mdns_server_t server)4960 _mdns_querier_set_current_server(const mdns_querier_t me, const mdns_server_t server)
4961 {
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;
4968 }
4969 }
4970 }
4971
4972 //======================================================================================================================
4973
4974 static mdns_server_t
_mdns_querier_get_eligible_server(const mdns_querier_t me)4975 _mdns_querier_get_eligible_server(const mdns_querier_t me)
4976 {
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;
4981 }
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));
4986 server = NULL;
4987 }
4988 return server;
4989 }
4990
4991 //======================================================================================================================
4992
4993 static mdns_server_t
_mdns_querier_get_unpenalized_eligible_server(const mdns_querier_t me)4994 _mdns_querier_get_unpenalized_eligible_server(const mdns_querier_t me)
4995 {
4996 const mdns_server_t server = _mdns_querier_get_eligible_server(me);
4997 return ((server && !server->penalized) ? server : NULL);
4998 }
4999
5000 //======================================================================================================================
5001
5002 static void
_mdns_querier_handle_stream_error(const mdns_querier_t me,const mdns_server_t server)5003 _mdns_querier_handle_stream_error(const mdns_querier_t me, const mdns_server_t server)
5004 {
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);
5012 }
5013 } else if (!me->current_server && !me->rtx_timer) {
5014 _mdns_querier_initiate_send(me);
5015 }
5016 }
5017
5018 //======================================================================================================================
5019
5020 static void
_mdns_querier_handle_bad_rcode(const mdns_querier_t me,const mdns_message_t response,const int rcode,const mdns_server_t server)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)
5023 {
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);
5028 me->bad_rcode = 0;
5029 }
5030 #endif
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;
5038 }
5039 if (rcode == kDNSRCode_Refused) {
5040 _mdns_resolver_penalize_server(me->resolver, server);
5041 }
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);
5048 }
5049 } else {
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);
5054 }
5055 }
5056
5057 //======================================================================================================================
5058
5059 static const uint8_t *
_mdns_querier_get_response_ptr_safe(const mdns_querier_t me)5060 _mdns_querier_get_response_ptr_safe(const mdns_querier_t me)
5061 {
5062 return (me->response ? mdns_message_get_byte_ptr(me->response) : NULL);
5063 }
5064
5065 //======================================================================================================================
5066
5067 static size_t
_mdns_querier_get_response_length_safe(const mdns_querier_t me)5068 _mdns_querier_get_response_length_safe(const mdns_querier_t me)
5069 {
5070 return (me->response ? mdns_message_get_length(me->response) : 0);
5071 }
5072
5073 //======================================================================================================================
5074
5075 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
5076 static void
_mdns_querier_set_test_query_got_response(const mdns_querier_t me,const mdns_server_t server,const bool got_response)5077 _mdns_querier_set_test_query_got_response(const mdns_querier_t me, const mdns_server_t server, const bool got_response)
5078 {
5079 const uint32_t bitmask = _mdns_rank_to_bitmask(server->rank);
5080 if (got_response) {
5081 me->test_query_resp_bitmap |= bitmask;
5082 } else {
5083 me->test_query_resp_bitmap &= ~bitmask;
5084 }
5085 }
5086
5087 //======================================================================================================================
5088
5089 static bool
_mdns_querier_test_query_got_response(const mdns_querier_t me,const mdns_server_t server)5090 _mdns_querier_test_query_got_response(const mdns_querier_t me, const mdns_server_t server)
5091 {
5092 return ((me->test_query_resp_bitmap & _mdns_rank_to_bitmask(server->rank)) ? true : false);
5093 }
5094 #endif
5095
5096 //======================================================================================================================
5097 // MARK: - Helper Functions
5098
5099 static dispatch_queue_t
_mdns_resolver_queue(void)5100 _mdns_resolver_queue(void)
5101 {
5102 static dispatch_once_t s_once = 0;
5103 static dispatch_queue_t s_queue = NULL;
5104
5105 dispatch_once(&s_once,
5106 ^{
5107 s_queue = dispatch_queue_create("com.apple.mdns.resolver-queue", DISPATCH_QUEUE_SERIAL);
5108 http_set_resolver_queue(s_queue);
5109 });
5110 return s_queue;
5111 }
5112
5113 //======================================================================================================================
5114
5115 static bool
_mdns_message_is_query_response_ignoring_id(const uint8_t * const msg_ptr,const size_t msg_len,const mdns_query_message_t query,uint16_t * out_id)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)
5118 {
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);
5121 }
5122
5123 //======================================================================================================================
5124
5125 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND
5126 static bool
_mdns_message_is_query_response_ignoring_qtype(const mdns_message_t msg,const mdns_query_message_t query,uint16_t * const out_qtype)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)
5129 {
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);
5133 }
5134 #endif
5135
5136 //======================================================================================================================
5137
5138 static bool
_mdns_message_is_query_response_ex(const uint8_t * const msg_ptr,const size_t msg_len,const mdns_query_message_t query,uint16_t * const out_id,uint16_t * const out_qtype,const bool ignore_qnames)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)
5141 {
5142 require_return_value(msg_len >= kDNSHeaderLength, false);
5143
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);
5147
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);
5152
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);
5161 if (out_id) {
5162 *out_id = msg_id;
5163 }
5164 if (out_qtype) {
5165 *out_qtype = qtype;
5166 }
5167 return true;
5168 }
5169
5170 //======================================================================================================================
5171
5172 static nw_parameters_t
_mdns_create_udp_parameters(OSStatus * out_error)5173 _mdns_create_udp_parameters(OSStatus *out_error)
5174 {
5175 OSStatus err;
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);
5179
5180 err = kNoErr;
5181
5182 exit:
5183 if (out_error) {
5184 *out_error = err;
5185 }
5186 return params;
5187 }
5188
5189 //======================================================================================================================
5190
5191 static nw_parameters_t
_mdns_create_tcp_parameters(OSStatus * out_error)5192 _mdns_create_tcp_parameters(OSStatus *out_error)
5193 {
5194 OSStatus err;
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);
5198
5199 nw_parameters_set_indefinite(params, false);
5200
5201 err = _mdns_add_dns_over_bytestream_framer(params);
5202 require_noerr_quiet(err, exit);
5203
5204 exit:
5205 if (err) {
5206 nw_forget(¶ms);
5207 }
5208 if (out_error) {
5209 *out_error = err;
5210 }
5211 return params;
5212 }
5213
5214 //======================================================================================================================
5215
5216 static nw_protocol_definition_t
5217 _mdns_copy_dns_over_bytestream_framer(void);
5218
5219 static OSStatus
_mdns_add_dns_over_bytestream_framer(nw_parameters_t params)5220 _mdns_add_dns_over_bytestream_framer(nw_parameters_t params)
5221 {
5222 OSStatus err;
5223 nw_protocol_definition_t framer_def = NULL;
5224 nw_protocol_options_t framer_opts = NULL;
5225
5226 nw_protocol_stack_t stack = nw_parameters_copy_default_protocol_stack(params);
5227 require_action_quiet(stack, exit, err = kNoResourcesErr);
5228
5229 framer_def = _mdns_copy_dns_over_bytestream_framer();
5230 require_action_quiet(framer_def, exit, err = kNoResourcesErr);
5231
5232 framer_opts = nw_framer_create_options(framer_def);
5233 require_action_quiet(framer_opts, exit, err = kNoResourcesErr);
5234
5235 nw_protocol_stack_prepend_application_protocol(stack, framer_opts);
5236 err = kNoErr;
5237
5238 exit:
5239 nw_release_null_safe(stack);
5240 nw_release_null_safe(framer_def);
5241 nw_release_null_safe(framer_opts);
5242 return err;
5243 }
5244
5245 static nw_protocol_definition_t
5246 _mdns_create_dns_over_bytestream_framer(void);
5247
5248 static nw_protocol_definition_t
_mdns_copy_dns_over_bytestream_framer(void)5249 _mdns_copy_dns_over_bytestream_framer(void)
5250 {
5251 static dispatch_once_t s_once = 0;
5252 static nw_protocol_definition_t s_framer_def = NULL;
5253
5254 dispatch_once(&s_once,
5255 ^{
5256 s_framer_def = _mdns_create_dns_over_bytestream_framer();
5257 });
5258 if (likely(s_framer_def)) {
5259 nw_retain(s_framer_def);
5260 }
5261 return s_framer_def;
5262 }
5263
5264 static nw_protocol_definition_t
_mdns_create_dns_over_bytestream_framer(void)5265 _mdns_create_dns_over_bytestream_framer(void)
5266 {
5267 static const nw_framer_input_handler_t input_handler =
5268 ^ size_t (nw_framer_t framer)
5269 {
5270 for (;;) {
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)
5274 {
5275 return ((buf_len >= sizeof(length_buf)) ? sizeof(length_buf) : 0);
5276 });
5277 if (!ok) {
5278 return sizeof(length_buf);
5279 }
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);
5283 nw_release(msg);
5284 if (!ok) {
5285 return sizeof(length_buf);
5286 }
5287 }
5288 };
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)
5291 {
5292 if (msg_len > UINT16_MAX) {
5293 nw_framer_mark_failed_with_error(framer, EMSGSIZE);
5294 return;
5295 }
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);
5300 };
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)
5304 {
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;
5308 });
5309 return framer_def;
5310 }
5311
5312 //======================================================================================================================
5313
5314 static uint64_t
_mdns_ticks_per_second(void)5315 _mdns_ticks_per_second(void)
5316 {
5317 return mdns_mach_ticks_per_second();
5318 }
5319
5320 //======================================================================================================================
5321
5322 static bool
_mdns_path_to_server_is_usable(const nw_path_t path,bool encrypted_resolver)5323 _mdns_path_to_server_is_usable(const nw_path_t path, bool encrypted_resolver)
5324 {
5325 const nw_path_status_t status = nw_path_get_status(path);
5326 if ((status == nw_path_status_satisfied) || (status == nw_path_status_satisfiable)) {
5327 return true;
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.
5333 return true;
5334 } else {
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;
5344 }
5345 }
5346 nw_forget(&endpoint);
5347 }
5348
5349 return nat64_eligible;
5350 }
5351 }
5352
5353 //======================================================================================================================
5354
5355 static uint32_t
_mdns_rank_to_bitmask(const unsigned int rank)5356 _mdns_rank_to_bitmask(const unsigned int rank)
5357 {
5358 if ((rank >= 1) && (rank <= 32)) {
5359 return (UINT32_C(1) << (rank - 1));
5360 } else {
5361 return 0;
5362 }
5363 }
5364
5365 //======================================================================================================================
5366
5367 static const char *
mdns_session_event_to_string(const mdns_session_event_t event)5368 mdns_session_event_to_string(const mdns_session_event_t event)
5369 {
5370 switch (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>";
5376 }
5377 }
5378
5379 //======================================================================================================================
5380
5381 static int64_t
_mdns_ticks_diff(const uint64_t t1,const uint64_t t2)5382 _mdns_ticks_diff(const uint64_t t1, const uint64_t t2)
5383 {
5384 return ((int64_t)(t1 - t2));
5385 }
5386
5387 //======================================================================================================================
5388
5389 static uint64_t
_mdns_ticks_to_whole_seconds(const uint64_t ticks)5390 _mdns_ticks_to_whole_seconds(const uint64_t ticks)
5391 {
5392 return (ticks / _mdns_ticks_per_second());
5393 }
5394
5395 //======================================================================================================================
5396
5397 static uint64_t
_mdns_ticks_to_fractional_milliseconds(const uint64_t ticks)5398 _mdns_ticks_to_fractional_milliseconds(const uint64_t ticks)
5399 {
5400 const uint64_t remainder = ticks % _mdns_ticks_per_second();
5401 return ((remainder * kMillisecondsPerSecond) / _mdns_ticks_per_second());
5402 }
5403
5404 //======================================================================================================================
5405
5406 static dispatch_source_t
_mdns_resolver_create_oneshot_timer(const uint32_t time_ms,const unsigned int leeway_percent_numerator)5407 _mdns_resolver_create_oneshot_timer(const uint32_t time_ms, const unsigned int leeway_percent_numerator)
5408 {
5409 const dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _mdns_resolver_queue());
5410 require_quiet(timer, exit);
5411
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);
5415
5416 exit:
5417 return timer;
5418 }
5419
5420 //======================================================================================================================
5421
5422 static bool
_mdns_rcode_is_good(const int rcode)5423 _mdns_rcode_is_good(const int rcode)
5424 {
5425 return ((rcode == kDNSRCode_NoError) || (rcode == kDNSRCode_NXDomain) || (rcode == kDNSRCode_NotAuth));
5426 }
5427
5428 //======================================================================================================================
5429
5430 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND || MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
5431 static bool
_mdns_qtype_is_problematic(const int qtype)5432 _mdns_qtype_is_problematic(const int qtype)
5433 {
5434 return ((qtype == kDNSRecordType_HTTPS) || (qtype == kDNSRecordType_SVCB));
5435 }
5436
5437 //======================================================================================================================
5438
5439 static mdns_message_t
_mdns_create_empty_response_for_query(const mdns_query_message_t query,const int rcode,OSStatus * const out_error)5440 _mdns_create_empty_response_for_query(const mdns_query_message_t query, const int rcode, OSStatus * const out_error)
5441 {
5442 mdns_message_t response_msg = NULL;
5443 OSStatus err;
5444 const size_t len = mdns_message_get_length(query);
5445 require_action_quiet(len > kDNSHeaderLength, exit, err = kInternalErr);
5446
5447 uint8_t *response_ptr = malloc(len);
5448 require_action_quiet(response_ptr, exit, err = kNoMemoryErr);
5449
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);
5458
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;
5462
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);
5467 err = kNoErr;
5468
5469 exit:
5470 if (out_error) {
5471 *out_error = err;
5472 }
5473 return response_msg;
5474 }
5475 #endif // MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND || MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
5476
5477 //======================================================================================================================
5478
5479 #if MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
5480 static mdns_query_message_t
_mdns_create_simple_test_query(const mdns_query_message_t query,const uint16_t qtype)5481 _mdns_create_simple_test_query(const mdns_query_message_t query, const uint16_t qtype)
5482 {
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);
5486
5487 OSStatus err = mdns_query_message_set_qname(test_query, mdns_query_message_get_qname(query));
5488 require_noerr_quiet(err, exit);
5489
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)) {
5495 msg_id = ~msg_id;
5496 if (msg_id == 0) {
5497 msg_id = 1;
5498 }
5499 }
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);
5503
5504 result = test_query;
5505 test_query = NULL;
5506
5507 exit:
5508 mdns_forget(&test_query);
5509 return result;
5510 }
5511
5512 //======================================================================================================================
5513
5514 static bool
_mdns_message_is_adequate_test_query_response(const mdns_message_t msg,const mdns_query_message_t query)5515 _mdns_message_is_adequate_test_query_response(const mdns_message_t msg, const mdns_query_message_t query)
5516 {
5517 return _mdns_message_is_query_response_ex(mdns_message_get_byte_ptr(msg), mdns_message_get_length(msg), query,
5518 NULL, NULL, true);
5519 }
5520
5521 //======================================================================================================================
5522
5523 static pqw_info_t *
_pqw_info_create(const unsigned int threshold)5524 _pqw_info_create(const unsigned int threshold)
5525 {
5526 pqw_info_t *info = (pqw_info_t *)calloc(1, sizeof(*info));
5527 require_return_value(info, NULL);
5528 info->threshold = threshold;
5529 return info;
5530 }
5531
5532 //======================================================================================================================
5533
5534 static void
_pqw_info_free(pqw_info_t * const info)5535 _pqw_info_free(pqw_info_t * const info)
5536 {
5537 _pqw_qname_list_forget(&info->qname_list);
5538 free(info);
5539 }
5540
5541 //======================================================================================================================
5542
5543 static bool
_pqw_info_threshold_reached(const pqw_info_t * const info)5544 _pqw_info_threshold_reached(const pqw_info_t * const info)
5545 {
5546 return ((info->qname_count < info->threshold) ? false : true);
5547 }
5548
5549 //======================================================================================================================
5550
5551 static bool
_pqw_info_can_accept_qname(const pqw_info_t * const info,const uint8_t * const qname)5552 _pqw_info_can_accept_qname(const pqw_info_t * const info, const uint8_t * const qname)
5553 {
5554 if (_pqw_info_threshold_reached(info)) {
5555 return false;
5556 }
5557 for (const pqw_qname_item_t *item = info->qname_list; item; item = item->next) {
5558 if (DomainNameEqual(item->qname, qname)) {
5559 return false;
5560 }
5561 }
5562 return true;
5563 }
5564
5565 //======================================================================================================================
5566
5567 static pqw_qname_item_t *
_pqw_qname_item_create(const uint8_t * const qname,OSStatus * const out_error)5568 _pqw_qname_item_create(const uint8_t * const qname, OSStatus * const out_error)
5569 {
5570 pqw_qname_item_t *result = NULL;
5571 OSStatus err;
5572 pqw_qname_item_t *item = (pqw_qname_item_t *)calloc(1, sizeof(*item));
5573 require_action_quiet(item, exit, err = kNoMemoryErr);
5574
5575 err = DomainNameDup(qname, &item->qname, NULL);
5576 require_noerr_quiet(err, exit);
5577
5578 result = item;
5579 item = NULL;
5580
5581 exit:
5582 if (out_error) {
5583 *out_error = err;
5584 }
5585 _pqw_qname_item_forget(&item);
5586 return result;
5587 }
5588
5589 //======================================================================================================================
5590
5591 static void
_pqw_qname_item_free(pqw_qname_item_t * const item)5592 _pqw_qname_item_free(pqw_qname_item_t * const item)
5593 {
5594 ForgetMem(&item->qname);
5595 free(item);
5596 }
5597
5598 //======================================================================================================================
5599
5600 static void
_pqw_qname_list_free(pqw_qname_item_t * list)5601 _pqw_qname_list_free(pqw_qname_item_t *list)
5602 {
5603 pqw_qname_item_t *item;
5604 while ((item = list) != NULL) {
5605 list = item->next;
5606 _pqw_qname_item_free(item);
5607 }
5608 }
5609 #endif // MDNS_RESOLVER_PROBLEMATIC_QTYPE_WORKAROUND
5610
5611 //======================================================================================================================
5612
5613 #if MDNS_RESOLVER_MIXED_UP_RESPONSES_WORKAROUND
5614 static bool
_mdns_qtype_is_address_type(const int qtype)5615 _mdns_qtype_is_address_type(const int qtype)
5616 {
5617 return ((qtype == kDNSRecordType_A) || (qtype == kDNSRecordType_AAAA));
5618 }
5619 #endif
5620