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(&params_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(&params);
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