]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOSX/dnssd_server.c
mDNSResponder-1310.60.4.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / dnssd_server.c
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 * http://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 "dnssd_server.h"
18
19 #include "ClientRequests.h"
20 #include "dnssd_xpc.h"
21 #include "dnssd_svcb.h"
22 #include "dnssd_private.h"
23 #include "mdns_helpers.h"
24 #include "mDNSMacOSX.h"
25
26 #include <bsm/libbsm.h>
27 #include <CoreUtils/CommonServices.h>
28 #include <CoreUtils/DebugServices.h>
29 #include <libproc.h>
30 #include <mach/mach_time.h>
31 #include <net/necp.h>
32 #include <os/lock.h>
33 #include <stdatomic.h>
34 #include <sys/proc_info.h>
35 #include <xpc/private.h>
36
37 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
38 #include "QuerierSupport.h"
39 #endif
40
41 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
42 #include "mdns_trust.h"
43 #include <os/feature_private.h>
44 #endif
45
46 //======================================================================================================================
47 // MARK: - Kind Declarations
48
49 #define DX_STRUCT(NAME) struct dx_ ## NAME ## _s
50 #define DX_KIND_DECLARE_ABSTRACT(NAME) typedef DX_STRUCT(NAME) * dx_ ## NAME ## _t
51 #define DX_KIND_DECLARE(NAME) \
52 DX_KIND_DECLARE_ABSTRACT(NAME); \
53 \
54 static dx_ ## NAME ## _t \
55 _dx_ ## NAME ## _alloc_and_init(void)
56
57 // Note: The last check checks if the base's type is equal to that of the superkind. If it's not, then the pointer
58 // comparison used as the argument to sizeof will cause a "comparison of distinct pointer types" warning, so long as
59 // the warning hasn't been disabled.
60
61 #define DX_BASE_CHECK(NAME, SUPER) \
62 check_compile_time(offsetof(DX_STRUCT(NAME), base) == 0); \
63 check_compile_time(sizeof_field(DX_STRUCT(NAME), base) == sizeof(DX_STRUCT(SUPER))); \
64 extern int _dx_base_type_check[sizeof(&(((dx_ ## NAME ## _t)0)->base) == ((dx_ ## SUPER ## _t)0))]
65
66 #define DX_SUBKIND_DEFINE_ABSTRACT(NAME, SUPER, ...) \
67 static const struct dx_kind_s _dx_ ## NAME ## _kind = { \
68 .superkind = &_dx_ ## SUPER ##_kind, \
69 __VA_ARGS__ \
70 }; \
71 DX_BASE_CHECK(NAME, SUPER)
72
73 #define DX_SUBKIND_DEFINE(NAME, SUPER, ...) \
74 DX_SUBKIND_DEFINE_ABSTRACT(NAME, SUPER, __VA_ARGS__); \
75 \
76 static dx_ ## NAME ## _t \
77 _dx_ ## NAME ## _alloc_and_init(void) \
78 { \
79 const dx_ ## NAME ## _t obj = (dx_ ## NAME ## _t)calloc(1, sizeof(*obj)); \
80 require_quiet(obj, exit); \
81 \
82 const dx_object_t object = (dx_object_t)obj; \
83 object->ref_count = 1; \
84 object->kind = &_dx_ ## NAME ## _kind; \
85 _dx_init(object); \
86 \
87 exit: \
88 return obj; \
89 }
90
91 #define DX_OBJECT_SUBKIND_DEFINE_ABSTRACT(NAME, ...) DX_SUBKIND_DEFINE_ABSTRACT(NAME, object, __VA_ARGS__)
92 #define DX_OBJECT_SUBKIND_DEFINE(NAME, ...) DX_SUBKIND_DEFINE(NAME, object, __VA_ARGS__)
93 #define DX_REQUEST_SUBKIND_DEFINE(NAME, ...) DX_SUBKIND_DEFINE(NAME, request, __VA_ARGS__)
94
95 DX_KIND_DECLARE_ABSTRACT(object);
96 DX_KIND_DECLARE(session);
97 DX_KIND_DECLARE_ABSTRACT(request);
98 DX_KIND_DECLARE(gai_request);
99
100 #define DX_TRANSPARENT_UNION_MEMBER(NAME) DX_STRUCT(NAME) * NAME
101
102 typedef union {
103 DX_TRANSPARENT_UNION_MEMBER(object);
104 DX_TRANSPARENT_UNION_MEMBER(session);
105 DX_TRANSPARENT_UNION_MEMBER(request);
106 DX_TRANSPARENT_UNION_MEMBER(gai_request);
107 } dx_any_t __attribute__((__transparent_union__));
108
109 typedef void
110 (*dx_init_f)(dx_any_t object);
111
112 typedef void
113 (*dx_invalidate_f)(dx_any_t object);
114
115 typedef void
116 (*dx_finalize_f)(dx_any_t object);
117
118 typedef const struct dx_kind_s * dx_kind_t;
119 struct dx_kind_s {
120 dx_kind_t superkind; // This kind's superkind. All kinds have a superkind, except the base kind.
121 dx_init_f init; // Initializes an object.
122 dx_invalidate_f invalidate; // Stops an object's outstanding operations, if any.
123 dx_finalize_f finalize; // Releases object's resources right before the object is freed.
124 };
125
126 //======================================================================================================================
127 // MARK: - Object Kind Definition
128
129 struct dx_object_s {
130 dx_kind_t kind; // The object's kind.
131 _Atomic(int32_t) ref_count; // Reference count.
132 };
133
134 static void
135 _dx_init(dx_object_t object);
136
137 static void
138 _dx_retain(dx_any_t object);
139
140 static void
141 _dx_release(dx_any_t object);
142 #define _dx_release_null_safe(X) \
143 do { \
144 if (X) { \
145 _dx_release(X); \
146 } \
147 } while (0)
148 #define _dx_forget(X) ForgetCustom(X, _dx_release)
149
150 static void
151 _dx_invalidate(dx_any_t object);
152
153 static const struct dx_kind_s _dx_object_kind = {
154 .superkind = NULL,
155 .init = NULL,
156 .invalidate = NULL,
157 .finalize = NULL
158 };
159
160 //======================================================================================================================
161 // MARK: - Session Kind Definition
162
163 struct dx_session_s {
164 struct dx_object_s base; // Object base;
165 dx_session_t next; // Next session in list.
166 dx_request_t request_list; // List of outstanding requests.
167 xpc_connection_t connection; // Underlying XPC connection.
168 uint64_t pending_send_start_ticks; // Start time in mach ticks of the current pending send condition.
169 audit_token_t audit_token; // Client's audit_token.
170 uid_t client_euid; // Client's EUID.
171 pid_t client_pid; // Client's PID.
172 uint32_t pending_send_count; // Count of sent messages that still haven't been processed.
173 uint32_t pending_send_count_max; // Maximum pending_send_count value.
174 char client_name[MAXCOMLEN]; // Client's process name.
175 bool has_delegate_entitlement; // True if the client is entitled to be a delegate.
176 bool terminated; // True if the session was prematurely ended due to a fatal error.
177 };
178
179 static void
180 _dx_session_invalidate(dx_session_t session);
181
182 DX_OBJECT_SUBKIND_DEFINE(session,
183 .invalidate = _dx_session_invalidate
184 );
185
186 typedef union {
187 DX_TRANSPARENT_UNION_MEMBER(request);
188 DX_TRANSPARENT_UNION_MEMBER(gai_request);
189 } dx_any_request_t __attribute__((__transparent_union__));
190
191 //======================================================================================================================
192 // MARK: - Request Kind Definition
193
194 struct dx_request_s {
195 struct dx_object_s base; // Object base.
196 dx_request_t next; // Next request in list.
197 dx_session_t session; // Back pointer to parent session.
198 xpc_object_t results; // Array of pending results.
199 uint64_t command_id; // ID to distinquish multiple commands during a session.
200 uint32_t request_id; // Request ID, used for logging purposes.
201 DNSServiceErrorType error; // Pending error.
202 os_unfair_lock lock; // Lock for pending error and results array.
203 bool sent_error; // True if the pending error has been sent to client.
204 };
205
206 static void
207 _dx_request_init(dx_request_t request);
208
209 static void
210 _dx_request_finalize(dx_request_t request);
211
212 DX_OBJECT_SUBKIND_DEFINE_ABSTRACT(request,
213 .init = _dx_request_init,
214 .finalize = _dx_request_finalize
215 );
216
217 //======================================================================================================================
218 // MARK: - GetAddrInfo Request Kind Definition
219
220 struct dx_gai_request_s {
221 struct dx_request_s base; // Request object base.
222 GetAddrInfoClientRequest gai; // Underlying GAI request.
223 QueryRecordClientRequest query; // Underlying SVCB/HTTPS query request.
224 xpc_object_t params; // Parameter dictionary from client's message.
225 xpc_object_t hostname_obj; // Hostname string from parameter dictionary.
226 const char * hostname; // Hostname C string to be resolved for getaddrinfo request.
227 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
228 mdns_trust_t trust; // Trust instance if status is mdns_trust_status_pending
229 #endif
230 mdns_dns_service_id_t custom_service_id; // ID for this request's custom DNS service.
231 xpc_object_t cnames_a; // Hostname's canonical names for A records as an XPC array.
232 ssize_t cnames_a_expire_idx; // Index of the first expired canonical name in cnames_a.
233 xpc_object_t cnames_aaaa; // Hostname's canonical names for AAAA records as an XPC array.
234 ssize_t cnames_aaaa_expire_idx; // Index of the first expired canonical name in cnames_aaaa.
235 uuid_t effective_uuid; // Effective client UUID for creating result auth tags.
236 bool cnames_a_changed; // True if cnames_a has changed.
237 bool cnames_aaaa_changed; // True if cnames_aaaa has changed.
238 bool gai_active; // True if the GAI request is currently active.
239 bool query_active; // True if the SVCB/HTTPS query request is currently active.
240 bool need_auth; // True if GAI results need to be authenticated.
241 };
242
243 static void
244 _dx_gai_request_invalidate(dx_gai_request_t request);
245
246 static void
247 _dx_gai_request_finalize(dx_gai_request_t request);
248
249 DX_REQUEST_SUBKIND_DEFINE(gai_request,
250 .invalidate = _dx_gai_request_invalidate,
251 .finalize = _dx_gai_request_finalize
252 );
253
254 //======================================================================================================================
255 // MARK: - Local Prototypes
256
257 static dispatch_queue_t
258 _dx_server_queue(void);
259
260 static void
261 _dx_server_handle_new_connection(xpc_connection_t connection);
262
263 static void
264 _dx_server_register_session(dx_session_t session);
265
266 static void
267 _dx_server_deregister_session(dx_session_t session);
268
269 static void
270 _dx_server_check_sessions(void);
271
272 static dx_session_t
273 _dx_session_create(xpc_connection_t connection);
274
275 static void
276 _dx_session_activate(dx_session_t session);
277
278 static void
279 _dx_session_handle_message(dx_session_t session, xpc_object_t msg);
280
281 static DNSServiceErrorType
282 _dx_session_handle_getaddrinfo_command(dx_session_t session, xpc_object_t msg);
283
284 static DNSServiceErrorType
285 _dx_session_handle_stop_command(dx_session_t session, xpc_object_t msg);
286
287 static void
288 _dx_session_append_request(dx_session_t session, dx_any_request_t any);
289
290 static void
291 _dx_session_check(dx_session_t session, uint64_t now_ticks);
292
293 static void
294 _dx_session_send_message(dx_session_t session, xpc_object_t msg);
295
296 static void
297 _dx_session_terminate(dx_session_t session);
298
299 static void
300 _dx_session_log_error(dx_session_t session, DNSServiceErrorType error);
301
302 static void
303 _dx_session_log_pending_send_count_increase(dx_session_t session);
304
305 static void
306 _dx_session_log_pending_send_count_decrease(dx_session_t session);
307
308 static void
309 _dx_session_log_termination(dx_session_t session);
310
311 static xpc_object_t
312 _dx_request_take_results(dx_request_t request);
313
314 typedef void (^dx_block_t)(void);
315
316 static void
317 _dx_request_locked(dx_any_request_t request, dx_block_t block);
318
319 static void
320 _dx_request_append_result(dx_any_request_t request, xpc_object_t result);
321
322 static DNSServiceErrorType
323 _dx_request_get_error(dx_any_request_t request);
324
325 static bool
326 _dx_request_set_error(dx_any_request_t request, DNSServiceErrorType error);
327
328 static bool
329 _dx_request_send_pending_error(dx_any_request_t request);
330
331 static dx_gai_request_t
332 _dx_gai_request_create(uint64_t command_id, dx_session_t session);
333
334 static DNSServiceErrorType
335 _dx_gai_request_activate(dx_gai_request_t request);
336
337 static DNSServiceErrorType
338 _dx_gai_request_activate_internal(dx_gai_request_t request);
339
340 static DNSServiceErrorType
341 _dx_gai_request_start_client_requests(dx_gai_request_t request, GetAddrInfoClientRequestParams *gai_params,
342 QueryRecordClientRequestParams *query_params, const uint8_t *resolver_uuid, xpc_object_t fallback_config);
343
344 static void
345 _dx_gai_request_stop_client_requests(dx_gai_request_t request);
346
347 static xpc_object_t *
348 _dx_gai_request_get_cnames_ptr(dx_gai_request_t request, int qtype, bool **out_changed_ptr,
349 ssize_t **out_expire_idx_ptr);
350
351 static void
352 _dx_gai_request_append_cname(dx_gai_request_t request, int qtype, const domainname *cname, bool expired, bool unwind);
353 #define _dx_gai_request_unwind_cnames_if_necessary(R, T) _dx_gai_request_append_cname(R, T, NULL, false, true)
354
355 static xpc_object_t
356 _dx_gai_request_copy_cname_update(dx_gai_request_t request, int qtype);
357
358 static void
359 _dx_gai_request_gai_result_handler(mDNS *m, DNSQuestion *q, const ResourceRecord *answer, QC_result qc_result,
360 DNSServiceErrorType error, void *context);
361
362 static void
363 _dx_gai_request_query_result_handler(mDNS *m, DNSQuestion *q, const ResourceRecord *answer, QC_result qc_result,
364 DNSServiceErrorType error, void *context);
365
366 static void
367 _dx_gai_request_enqueue_result(dx_gai_request_t request, uint32_t if_index, const domainname *name, uint16_t type,
368 uint16_t class, const uint8_t *rdata_ptr, size_t rdata_len, bool is_expired, bool is_add, bool answered_from_cache,
369 DNSServiceErrorType error, dnssd_getaddrinfo_result_protocol_t protocol, const char *provider_name);
370
371 static void
372 _dx_gai_request_get_delegator_ids(dx_gai_request_t request, pid_t *out_delegator_pid,
373 const uint8_t **out_delegator_uuid, const audit_token_t **out_delegator_audit_token, audit_token_t *storage);
374
375 static DNSServiceErrorType
376 _dx_gai_request_get_svcb_name_and_type(dx_gai_request_t request, const char **out_svcb_name,
377 uint16_t *out_svcb_type, char **out_svcb_memory);
378
379 static DNSServiceErrorType
380 _dx_gai_request_set_need_authenticated_results(dx_gai_request_t request, pid_t effective_pid,
381 const uuid_t effective_uuid);
382
383 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
384 static const uint8_t *
385 _dx_gai_request_get_resolver_uuid(dx_gai_request_t request);
386 #endif
387
388 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
389 static bool
390 _dx_gai_request_is_for_in_app_browser(dx_gai_request_t request);
391 #endif
392
393 static void
394 _dx_gai_request_log_start(dx_gai_request_t request, DNSServiceFlags flags, uint32_t if_index,
395 DNSServiceProtocol protocols, pid_t delegator_pid, const uuid_t delegator_uuid);
396
397 static void
398 _dx_gai_request_log_stop(dx_gai_request_t request);
399
400 static void
401 _dx_gai_request_log_a_result(dx_gai_request_t request, uint32_t query_id, uint32_t if_index, const domainname *name,
402 const uint8_t *rdata, MortalityState mortality, bool is_add_event);
403
404 static void
405 _dx_gai_request_log_aaaa_result(dx_gai_request_t request, uint32_t query_id, uint32_t if_index, const domainname *name,
406 const uint8_t *rdata, MortalityState mortality, bool is_add);
407
408 static void
409 _dx_gai_request_log_svcb_result(dx_gai_request_t request, uint32_t query_id, uint32_t if_index, const domainname *name,
410 const char *type_str, const uint8_t *rdata_ptr, size_t rdata_len, const ResourceRecord *answer, bool is_add_event);
411
412 static void
413 _dx_gai_request_log_no_such_record_result(dx_gai_request_t request, uint32_t query_id, uint32_t if_index,
414 const domainname *name, const char *type_str, MortalityState mortality, bool is_add);
415
416 static void
417 _dx_gai_request_log_error(dx_gai_request_t request, DNSServiceErrorType error);
418
419 #define DNSSD_AUTHENTICATION_TAG_SIZE 32 // XXX: Defined as a workaround until NECP header defines this length.
420
421 static bool
422 _dx_authenticate_address_rdata(uuid_t effective_uuid, const char *hostname, int type, const uint8_t *rdata,
423 uint8_t out_auth_tag[STATIC_PARAM DNSSD_AUTHENTICATION_TAG_SIZE]);
424
425 static char *
426 _dx_pid_to_name(pid_t pid, char out_name[STATIC_PARAM MAXCOMLEN]);
427
428 static void
429 _dx_kqueue_locked(const char *description, dx_block_t block);
430
431 //======================================================================================================================
432 // MARK: - Globals
433
434 static dx_session_t g_session_list = NULL;
435
436 //======================================================================================================================
437 // MARK: - Server Functions
438
439 mDNSexport void
440 dnssd_server_init(void)
441 {
442 static dispatch_once_t s_once = 0;
443 static xpc_connection_t s_listener = NULL;
444
445 dispatch_once(&s_once,
446 ^{
447 s_listener = xpc_connection_create_mach_service(DNSSD_MACH_SERVICE_NAME, _dx_server_queue(),
448 XPC_CONNECTION_MACH_SERVICE_LISTENER);
449 xpc_connection_set_event_handler(s_listener,
450 ^(xpc_object_t event)
451 {
452 if (xpc_get_type(event) == XPC_TYPE_CONNECTION) {
453 _dx_server_handle_new_connection((xpc_connection_t)event);
454 }
455 });
456 xpc_connection_activate(s_listener);
457 });
458 }
459
460 //======================================================================================================================
461
462 mDNSexport void
463 dnssd_server_idle(void)
464 {
465 static dispatch_once_t s_once = 0;
466 static dispatch_source_t s_source = NULL;
467 dispatch_once(&s_once,
468 ^{
469 s_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_OR, 0, 0, _dx_server_queue());
470 dispatch_source_set_event_handler(s_source,
471 ^{
472 _dx_server_check_sessions();
473 });
474 dispatch_activate(s_source);
475 });
476 dispatch_source_merge_data(s_source, 1);
477 }
478
479 //======================================================================================================================
480
481 uint32_t
482 dnssd_server_get_new_request_id(void)
483 {
484 static _Atomic(uint32_t) s_next_id = 1;
485 return atomic_fetch_add(&s_next_id, 1);
486 }
487
488 //======================================================================================================================
489
490 static dispatch_queue_t
491 _dx_server_queue(void)
492 {
493 static dispatch_once_t once = 0;
494 static dispatch_queue_t queue = NULL;
495
496 dispatch_once(&once,
497 ^{
498 const dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL,
499 QOS_CLASS_USER_INITIATED, 0);
500 queue = dispatch_queue_create("com.apple.dnssd.server", attr);
501 });
502 return queue;
503 }
504
505 //======================================================================================================================
506
507 static void
508 _dx_server_handle_new_connection(const xpc_connection_t connection)
509 {
510 dx_session_t session = _dx_session_create(connection);
511 if (session) {
512 _dx_session_activate(session);
513 _dx_server_register_session(session);
514 _dx_forget(&session);
515 } else {
516 xpc_connection_cancel(connection);
517 }
518 }
519
520 //======================================================================================================================
521
522 static void
523 _dx_server_register_session(dx_session_t session)
524 {
525 dx_session_t *ptr = &g_session_list;
526 while (*ptr) {
527 ptr = &(*ptr)->next;
528 }
529 session->next = NULL;
530 *ptr = session;
531 _dx_retain(*ptr);
532 }
533
534 //======================================================================================================================
535
536 static void
537 _dx_server_deregister_session(dx_session_t session)
538 {
539 dx_session_t *ptr = &g_session_list;
540 while (*ptr && (*ptr != session)) {
541 ptr = &(*ptr)->next;
542 }
543 if (*ptr) {
544 *ptr = session->next;
545 session->next = NULL;
546 _dx_forget(&session);
547 }
548 }
549
550 //======================================================================================================================
551
552 static void
553 _dx_server_check_sessions(void)
554 {
555 if (g_session_list) {
556 const uint64_t now_ticks = mach_continuous_time();
557 for (dx_session_t session = g_session_list; session; session = session->next) {
558 _dx_session_check(session, now_ticks);
559 }
560 }
561 }
562
563 //======================================================================================================================
564 // MARK: - Object Methods
565
566 static void
567 _dx_recursive_init(dx_object_t object, dx_kind_t kind);
568
569 static void
570 _dx_init(const dx_object_t me)
571 {
572 _dx_recursive_init(me, me->kind);
573 }
574
575 static void
576 _dx_recursive_init(const dx_object_t me, const dx_kind_t kind)
577 {
578 if (kind->superkind) {
579 _dx_recursive_init(me, kind->superkind);
580 }
581 if (kind->init) {
582 kind->init(me);
583 }
584 }
585
586 //======================================================================================================================
587
588 static void
589 _dx_retain(const dx_any_t any)
590 {
591 const dx_object_t me = any.object;
592 atomic_fetch_add(&me->ref_count, 1);
593 }
594
595 //======================================================================================================================
596
597 static void
598 _dx_finalize(dx_object_t object);
599
600 static void
601 _dx_release(const dx_any_t any)
602 {
603 const dx_object_t me = any.object;
604 if (atomic_fetch_sub(&me->ref_count, 1) == 1) {
605 _dx_finalize(me);
606 free(me);
607 }
608 }
609
610 static void
611 _dx_finalize(const dx_object_t me)
612 {
613 for (dx_kind_t kind = me->kind; kind; kind = kind->superkind) {
614 if (kind->finalize) {
615 kind->finalize(me);
616 }
617 }
618 }
619
620 //======================================================================================================================
621
622 static void
623 _dx_invalidate(const dx_any_t any)
624 {
625 const dx_object_t me = any.object;
626 for (dx_kind_t kind = me->kind; kind; kind = kind->superkind) {
627 if (kind->invalidate) {
628 kind->invalidate(me);
629 return;
630 }
631 }
632 }
633
634 //======================================================================================================================
635 // MARK: - Session Methods
636
637 #define DNSSD_DELEGATE_ENTITLEMENT "com.apple.private.network.socket-delegate"
638
639 static dx_session_t
640 _dx_session_create(const xpc_connection_t connection)
641 {
642 const dx_session_t obj = _dx_session_alloc_and_init();
643 require_quiet(obj, exit);
644
645 obj->connection = connection;
646 xpc_retain(obj->connection);
647 xpc_connection_get_audit_token(obj->connection, &obj->audit_token);
648 obj->client_pid = xpc_connection_get_pid(obj->connection);
649 obj->client_euid = xpc_connection_get_euid(obj->connection);
650 _dx_pid_to_name(obj->client_pid, obj->client_name);
651
652 xpc_object_t value = xpc_connection_copy_entitlement_value(obj->connection, DNSSD_DELEGATE_ENTITLEMENT);
653 if (value) {
654 if (value == XPC_BOOL_TRUE) {
655 obj->has_delegate_entitlement = true;
656 }
657 xpc_forget(&value);
658 }
659
660 exit:
661 return obj;
662 }
663
664 //======================================================================================================================
665
666 static void
667 _dx_session_activate(const dx_session_t me)
668 {
669 _dx_retain(me);
670 xpc_connection_set_target_queue(me->connection, _dx_server_queue());
671 xpc_connection_set_event_handler(me->connection,
672 ^(const xpc_object_t event) {
673 const xpc_type_t type = xpc_get_type(event);
674 if (type == XPC_TYPE_DICTIONARY) {
675 if (me->connection) {
676 _dx_session_handle_message(me, event);
677 }
678 } else if (event == XPC_ERROR_CONNECTION_INVALID) {
679 _dx_server_deregister_session(me);
680 _dx_session_invalidate(me);
681 _dx_release(me);
682 } else {
683 xpc_connection_forget(&me->connection);
684 }
685 });
686 xpc_connection_activate(me->connection);
687 }
688
689 //======================================================================================================================
690
691 static void
692 _dx_session_invalidate(const dx_session_t me)
693 {
694 xpc_connection_forget(&me->connection);
695 dx_request_t req;
696 while ((req = me->request_list) != NULL)
697 {
698 me->request_list = req->next;
699 _dx_invalidate(req);
700 _dx_release(req);
701 }
702 }
703
704 //======================================================================================================================
705
706 static void
707 _dx_session_handle_message(const dx_session_t me, const xpc_object_t msg)
708 {
709 DNSServiceErrorType err;
710 const char * const command = dnssd_xpc_message_get_command(msg);
711 require_action_quiet(command, exit, err = kDNSServiceErr_BadParam);
712
713 if (strcmp(command, DNSSD_COMMAND_GETADDRINFO) == 0) {
714 err = _dx_session_handle_getaddrinfo_command(me, msg);
715 } else if (strcmp(command, DNSSD_COMMAND_STOP) == 0) {
716 err = _dx_session_handle_stop_command(me, msg);
717 } else {
718 err = kDNSServiceErr_BadParam;
719 }
720
721 exit:;
722 xpc_object_t reply = xpc_dictionary_create_reply(msg);
723 if (likely(reply)) {
724 dnssd_xpc_message_set_error(reply, err);
725 _dx_session_send_message(me, reply);
726 xpc_forget(&reply);
727 } else {
728 _dx_session_terminate(me);
729 }
730 }
731
732 //======================================================================================================================
733
734 static DNSServiceErrorType
735 _dx_session_handle_getaddrinfo_command(const dx_session_t me, const xpc_object_t msg)
736 {
737 dx_gai_request_t req = NULL;
738 bool valid;
739 DNSServiceErrorType err;
740 const uint64_t command_id = dnssd_xpc_message_get_id(msg, &valid);
741 require_action_quiet(valid, exit, err = kDNSServiceErr_BadParam);
742
743 const xpc_object_t params = dnssd_xpc_message_get_parameters(msg);
744 require_action_quiet(params, exit, err = kDNSServiceErr_BadParam);
745
746 req = _dx_gai_request_create(command_id, me);
747 require_action_quiet(req, exit, err = kDNSServiceErr_NoMemory);
748
749 req->params = params;
750 xpc_retain(req->params);
751
752 err = _dx_gai_request_activate(req);
753 require_noerr_quiet(err, exit);
754
755 _dx_session_append_request(me, req);
756
757 exit:
758 if (err) {
759 if (req) {
760 _dx_gai_request_log_error(req, err);
761 } else {
762 _dx_session_log_error(me, err);
763 }
764 }
765 _dx_release_null_safe(req);
766 return err;
767 }
768
769 //======================================================================================================================
770
771 static DNSServiceErrorType
772 _dx_session_handle_stop_command(const dx_session_t me, const xpc_object_t msg)
773 {
774 bool valid;
775 DNSServiceErrorType err;
776 const uint64_t command_id = dnssd_xpc_message_get_id(msg, &valid);
777 require_action_quiet(valid, exit, err = kDNSServiceErr_BadParam);
778
779 dx_request_t *ptr;
780 dx_request_t req;
781 for (ptr = &me->request_list; (req = *ptr) != NULL; ptr = &req->next) {
782 if (req->command_id == command_id) {
783 break;
784 }
785 }
786 require_action_quiet(req, exit, err = kDNSServiceErr_BadReference);
787
788 *ptr = req->next;
789 req->next = NULL;
790 _dx_invalidate(req);
791 _dx_forget(&req);
792 err = kDNSServiceErr_NoError;
793
794 exit:
795 return err;
796 }
797
798 //======================================================================================================================
799
800 static void
801 _dx_session_append_request(const dx_session_t me, const dx_any_request_t any)
802 {
803 dx_request_t *ptr = &me->request_list;
804 while (*ptr) {
805 ptr = &(*ptr)->next;
806 }
807 const dx_request_t req = any.request;
808 req->next = NULL;
809 *ptr = req;
810 _dx_retain(*ptr);
811 }
812
813 //======================================================================================================================
814
815 #define DX_SESSION_BACK_PRESSURE_TIMEOUT_SECS 5
816
817 static void
818 _dx_session_check(const dx_session_t me, const uint64_t now_ticks)
819 {
820 bool terminate;
821 xpc_object_t results = NULL;
822 require_action_quiet(me->connection, exit, terminate = false);
823
824 if (me->pending_send_count > 0) {
825 const uint64_t elapsed_secs = (now_ticks - me->pending_send_start_ticks) / mdns_mach_ticks_per_second();
826 require_action_quiet(elapsed_secs < DX_SESSION_BACK_PRESSURE_TIMEOUT_SECS, exit, terminate = true);
827 }
828 for (dx_request_t req = me->request_list; req; req = req->next) {
829 results = _dx_request_take_results(req);
830 if (results) {
831 xpc_object_t msg = xpc_dictionary_create(NULL, NULL, 0);
832 require_action_quiet(msg, exit, terminate = true);
833
834 dnssd_xpc_message_set_id(msg, req->command_id);
835 dnssd_xpc_message_set_error(msg, kDNSServiceErr_NoError);
836 dnssd_xpc_message_set_results(msg, results);
837 xpc_forget(&results);
838 _dx_session_send_message(me, msg);
839 xpc_forget(&msg);
840 }
841 const bool ok = _dx_request_send_pending_error(req);
842 require_action_quiet(ok, exit, terminate = true);
843 }
844 terminate = false;
845
846 exit:
847 if (unlikely(terminate)) {
848 _dx_session_terminate(me);
849 }
850 xpc_forget(&results);
851 }
852
853 //======================================================================================================================
854
855 static void
856 _dx_session_send_message(const dx_session_t me, const xpc_object_t msg)
857 {
858 require_quiet(me->connection, exit);
859
860 xpc_connection_send_message(me->connection, msg);
861 if (me->pending_send_count++ == 0) {
862 me->pending_send_start_ticks = mach_continuous_time();
863 } else {
864 _dx_session_log_pending_send_count_increase(me);
865 }
866 me->pending_send_count_max = me->pending_send_count;
867 _dx_retain(me);
868 xpc_connection_send_barrier(me->connection,
869 ^{
870 --me->pending_send_count;
871 if (me->pending_send_count_max > 1) {
872 _dx_session_log_pending_send_count_decrease(me);
873 }
874 if (me->pending_send_count == 0) {
875 me->pending_send_count_max = 0;
876 }
877 _dx_release(me);
878 });
879
880 exit:
881 return;
882 }
883
884 //======================================================================================================================
885
886 static void
887 _dx_session_terminate(const dx_session_t me)
888 {
889 if (!me->terminated) {
890 _dx_session_log_termination(me);
891 xpc_connection_forget(&me->connection);
892 me->terminated = true;
893 }
894 }
895
896 //======================================================================================================================
897
898 static void
899 _dx_session_log_error(const dx_session_t me, const DNSServiceErrorType error)
900 {
901 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
902 "XPC session error -- error: %{mdns:err}ld, client pid: %lld (" PUB_S ")",
903 (long)error, (long long)me->client_pid, me->client_name);
904 }
905
906 //======================================================================================================================
907
908 static void
909 _dx_session_log_pending_send_count_increase(const dx_session_t me)
910 {
911 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
912 "XPC session to client with pid %lld (%s) pending send count increased to %d",
913 (long long)me->client_pid, me->client_name, me->pending_send_count);
914 }
915
916 //======================================================================================================================
917
918 static void
919 _dx_session_log_pending_send_count_decrease(const dx_session_t me)
920 {
921 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
922 "XPC session to client with pid %lld (%s) pending send count decreased to %d",
923 (long long)me->client_pid, me->client_name, me->pending_send_count);
924 }
925
926 //======================================================================================================================
927
928 static void
929 _dx_session_log_termination(const dx_session_t me)
930 {
931 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
932 "XPC session termination -- pending send count: %u, pending send count max: %u, client pid: %lld (" PUB_S ")",
933 me->pending_send_count, me->pending_send_count_max, (long long)me->client_pid, me->client_name);
934 }
935
936 //======================================================================================================================
937 // MARK: - Request Methods
938
939 static void
940 _dx_request_init(const dx_request_t me)
941 {
942 me->request_id = dnssd_server_get_new_request_id();
943 me->lock = OS_UNFAIR_LOCK_INIT;
944 }
945
946 //======================================================================================================================
947
948 static void
949 _dx_request_finalize(const dx_request_t me)
950 {
951 _dx_forget(&me->session);
952 xpc_forget(&me->results);
953 }
954
955 //======================================================================================================================
956
957 static xpc_object_t
958 _dx_request_take_results(const dx_request_t me)
959 {
960 __block xpc_object_t results = NULL;
961 _dx_request_locked(me,
962 ^{
963 if (me->results && (xpc_array_get_count(me->results) > 0)) {
964 results = me->results;
965 me->results = NULL;
966 }
967 });
968 return results;
969 }
970
971 //======================================================================================================================
972
973 static void
974 _dx_request_locked(const dx_any_request_t any, const dx_block_t block)
975 {
976 const dx_request_t me = any.request;
977 os_unfair_lock_lock(&me->lock);
978 block();
979 os_unfair_lock_unlock(&me->lock);
980 }
981
982 //======================================================================================================================
983
984 static void
985 _dx_request_append_result(const dx_any_request_t any, const xpc_object_t result)
986 {
987 const dx_request_t me = any.request;
988 _dx_request_locked(me,
989 ^{
990 if (!me->results) {
991 me->results = xpc_array_create(NULL, 0);
992 }
993 if (likely(me->results)) {
994 xpc_array_append_value(me->results, result);
995 } else {
996 if (!me->error) {
997 me->error = kDNSServiceErr_NoMemory;
998 }
999 }
1000 });
1001 }
1002
1003 //======================================================================================================================
1004
1005 static DNSServiceErrorType
1006 _dx_request_get_error(const dx_any_request_t any)
1007 {
1008 const dx_request_t me = any.request;
1009 __block DNSServiceErrorType error;
1010 _dx_request_locked(me,
1011 ^{
1012 error = me->error;
1013 });
1014 return error;
1015 }
1016
1017 //======================================================================================================================
1018
1019 static bool
1020 _dx_request_set_error(const dx_any_request_t any, const DNSServiceErrorType error)
1021 {
1022 __block bool did_set = false;
1023 if (error) {
1024 const dx_request_t me = any.request;
1025 _dx_request_locked(me,
1026 ^{
1027 if (!me->error) {
1028 me->error = error;
1029 did_set = true;
1030 }
1031 });
1032 }
1033 return did_set;
1034 }
1035
1036 //======================================================================================================================
1037
1038 static bool
1039 _dx_request_send_pending_error(const dx_any_request_t any)
1040 {
1041 bool ok = false;
1042 const dx_request_t me = any.request;
1043 const DNSServiceErrorType error = _dx_request_get_error(me);
1044 if (error && !me->sent_error) {
1045 xpc_object_t msg = xpc_dictionary_create(NULL, NULL, 0);
1046 require_quiet(msg, exit);
1047
1048 dnssd_xpc_message_set_id(msg, me->command_id);
1049 dnssd_xpc_message_set_error(msg, error);
1050 _dx_session_send_message(me->session, msg);
1051 xpc_forget(&msg);
1052 me->sent_error = true;
1053 }
1054 ok = true;
1055
1056 exit:
1057 return ok;
1058 }
1059
1060 //======================================================================================================================
1061 // MARK: - GetAddrInfo Request Methods
1062
1063 static dx_gai_request_t
1064 _dx_gai_request_create(const uint64_t command_id, const dx_session_t session)
1065 {
1066 dx_gai_request_t obj = _dx_gai_request_alloc_and_init();
1067 require_quiet(obj, exit);
1068
1069 obj->base.command_id = command_id;
1070 obj->base.session = session;
1071 _dx_retain(obj->base.session);
1072
1073 obj->cnames_a_expire_idx = -1;
1074 obj->cnames_aaaa_expire_idx = -1;
1075
1076 exit:
1077 return obj;
1078 }
1079
1080 //======================================================================================================================
1081
1082 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
1083 static DNSServiceErrorType
1084 _dx_gai_request_trust_check(dx_gai_request_t request, bool *out_activate_deferred);
1085 #endif
1086
1087 static DNSServiceErrorType
1088 _dx_gai_request_activate(const dx_gai_request_t me)
1089 {
1090 DNSServiceErrorType err;
1091 me->hostname_obj = dnssd_xpc_parameters_get_hostname_object(me->params);
1092 require_action_quiet(me->hostname_obj, exit, err = kDNSServiceErr_BadParam);
1093
1094 xpc_retain(me->hostname_obj);
1095 me->hostname = xpc_string_get_string_ptr(me->hostname_obj);
1096 require_action_quiet(me->hostname, exit, err = kDNSServiceErr_Unknown);
1097
1098 bool defer_activation = false;
1099 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
1100 if (os_feature_enabled(mDNSResponder, bonjour_privacy)) {
1101 err = _dx_gai_request_trust_check(me, &defer_activation);
1102 require_noerr_quiet(err, exit);
1103 }
1104 #endif
1105 if (!defer_activation) {
1106 err = _dx_gai_request_activate_internal(me);
1107 require_noerr_quiet(err, exit);
1108 }
1109 err = kDNSServiceErr_NoError;
1110
1111 exit:
1112 return err;
1113 }
1114
1115 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
1116 static DNSServiceErrorType
1117 _dx_gai_request_trust_check(const dx_gai_request_t me, bool * const out_defer_activation)
1118 {
1119 DNSServiceErrorType err;
1120 bool defer_activation = false;
1121 const dx_session_t session = me->base.session;
1122 mdns_trust_flags_t flags = mdns_trust_flags_none;
1123 const mdns_trust_status_t status = mdns_trust_check_getaddrinfo(session->audit_token, me->hostname, &flags);
1124 switch (status) {
1125 case mdns_trust_status_granted:
1126 err = kDNSServiceErr_NoError;
1127 break;
1128
1129 case mdns_trust_status_denied:
1130 case mdns_trust_status_pending:
1131 me->trust = mdns_trust_create(session->audit_token, NULL, flags);
1132 require_action_quiet(me->trust, exit, err = kDNSServiceErr_NoMemory);
1133
1134 _dx_retain(me);
1135 mdns_trust_set_queue(me->trust, _dx_server_queue());
1136 mdns_trust_set_event_handler(me->trust,
1137 ^(const mdns_trust_event_t event, const mdns_trust_status_t update)
1138 {
1139 if (me->trust && (event == mdns_trust_event_result)) {
1140 DNSServiceErrorType handler_err;
1141 if (update == mdns_trust_status_granted) {
1142 handler_err = _dx_gai_request_activate_internal(me);
1143 } else {
1144 handler_err = kDNSServiceErr_PolicyDenied;
1145 }
1146 if (handler_err && _dx_request_set_error(me, handler_err)) {
1147 _dx_gai_request_log_error(me, handler_err);
1148 _dx_request_send_pending_error(me);
1149 }
1150 }
1151 mdns_forget(&me->trust);
1152 _dx_release(me);
1153 });
1154 mdns_trust_activate(me->trust);
1155 defer_activation = true;
1156 err = kDNSServiceErr_NoError;
1157 break;
1158
1159 case mdns_trust_status_no_entitlement:
1160 err = kDNSServiceErr_NoAuth;
1161 break;
1162
1163 default:
1164 err = kDNSServiceErr_Unknown;
1165 break;
1166 }
1167
1168 exit:
1169 if (out_defer_activation) {
1170 *out_defer_activation = defer_activation;
1171 }
1172 return err;
1173 }
1174 #endif
1175
1176 //======================================================================================================================
1177
1178 static void
1179 _dx_gai_request_invalidate(const dx_gai_request_t me)
1180 {
1181 _dx_gai_request_log_stop(me);
1182 _dx_gai_request_stop_client_requests(me);
1183 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
1184 mdns_trust_forget(&me->trust);
1185 #endif
1186 }
1187
1188 //======================================================================================================================
1189
1190 static void
1191 _dx_gai_request_finalize(const dx_gai_request_t me)
1192 {
1193 me->hostname = NULL;
1194 xpc_forget(&me->params);
1195 xpc_forget(&me->hostname_obj);
1196 xpc_forget(&me->cnames_a);
1197 xpc_forget(&me->cnames_aaaa);
1198 }
1199
1200 //======================================================================================================================
1201
1202 static DNSServiceErrorType
1203 _dx_gai_request_start_client_requests(const dx_gai_request_t me, GetAddrInfoClientRequestParams * const gai_params,
1204 QueryRecordClientRequestParams * const query_params, const uint8_t * const resolver_uuid,
1205 const xpc_object_t fallback_config)
1206 {
1207 __block DNSServiceErrorType err = kDNSServiceErr_NoError;
1208 _dx_kqueue_locked("dx_gai_request: starting client requests",
1209 ^{
1210 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
1211 if (resolver_uuid && !uuid_is_null(resolver_uuid)) {
1212 Querier_RegisterPathResolver(resolver_uuid);
1213 }
1214 if ((me->custom_service_id == 0) && fallback_config) {
1215 me->custom_service_id = Querier_RegisterCustomDNSService(fallback_config);
1216 }
1217 if (gai_params) {
1218 gai_params->resolverUUID = resolver_uuid;
1219 gai_params->customID = me->custom_service_id;
1220 }
1221 if (query_params) {
1222 query_params->resolverUUID = resolver_uuid;
1223 query_params->customID = me->custom_service_id;
1224 }
1225 #else
1226 (void)resolver_uuid;
1227 (void)fallback_config;
1228 #endif
1229 // If present, run the query for SVCB/HTTPSSVC first, in case the ALPN and address hints come back first.
1230 if (query_params && !me->query_active) {
1231 err = QueryRecordClientRequestStart(&me->query, query_params, _dx_gai_request_query_result_handler, me);
1232 require_noerr_return(err);
1233 me->query_active = true;
1234 }
1235 // Run the A/AAAA lookup.
1236 if (gai_params && !me->gai_active) {
1237 err = GetAddrInfoClientRequestStart(&me->gai, gai_params, _dx_gai_request_gai_result_handler, me);
1238 require_noerr_return(err);
1239 me->gai_active = true;
1240 }
1241 });
1242 if (err) {
1243 _dx_gai_request_stop_client_requests(me);
1244 }
1245 return err;
1246 }
1247
1248 //======================================================================================================================
1249
1250 static void
1251 _dx_gai_request_stop_client_requests(const dx_gai_request_t me)
1252 {
1253 _dx_kqueue_locked("dx_gai_request: stopping client requests",
1254 ^{
1255 if (me->gai_active) {
1256 GetAddrInfoClientRequestStop(&me->gai);
1257 me->gai_active = false;
1258 }
1259 if (me->query_active) {
1260 QueryRecordClientRequestStop(&me->query);
1261 me->query_active = false;
1262 }
1263 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
1264 if (me->custom_service_id != 0) {
1265 Querier_DeregisterCustomDNSService(me->custom_service_id);
1266 me->custom_service_id = 0;
1267 }
1268 #endif
1269 });
1270 }
1271
1272 //======================================================================================================================
1273
1274 static xpc_object_t *
1275 _dx_gai_request_get_cnames_ptr(const dx_gai_request_t me, const int qtype, bool ** const out_changed_ptr,
1276 ssize_t **out_expire_idx_ptr)
1277 {
1278 ssize_t *expire_idx_ptr;
1279 xpc_object_t *cnames_ptr;
1280 bool *changed_ptr;
1281 switch (qtype) {
1282 case kDNSServiceType_A:
1283 cnames_ptr = &me->cnames_a;
1284 changed_ptr = &me->cnames_a_changed;
1285 expire_idx_ptr = &me->cnames_a_expire_idx;
1286 break;
1287
1288 case kDNSServiceType_AAAA:
1289 cnames_ptr = &me->cnames_aaaa;
1290 changed_ptr = &me->cnames_aaaa_changed;
1291 expire_idx_ptr = &me->cnames_aaaa_expire_idx;
1292 break;
1293
1294 default:
1295 cnames_ptr = NULL;
1296 expire_idx_ptr = NULL;
1297 changed_ptr = NULL;
1298 break;
1299 }
1300 if (out_expire_idx_ptr) {
1301 *out_expire_idx_ptr = expire_idx_ptr;
1302 }
1303 if (out_changed_ptr) {
1304 *out_changed_ptr = changed_ptr;
1305 }
1306 return cnames_ptr;
1307 }
1308
1309 //======================================================================================================================
1310
1311 static void
1312 _dx_gai_request_append_cname(const dx_gai_request_t me, const int qtype, const domainname * const cname,
1313 const bool expired, const bool unwind)
1314 {
1315 bool *changed_ptr;
1316 ssize_t *expire_idx_ptr;
1317 xpc_object_t * const cnames_ptr = _dx_gai_request_get_cnames_ptr(me, qtype, &changed_ptr, &expire_idx_ptr);
1318 require_quiet(cnames_ptr, exit);
1319
1320 const char *cname_str = NULL;
1321 char cname_buf[MAX_ESCAPED_DOMAIN_NAME];
1322 if (cname) {
1323 if (!ConvertDomainNameToCString(cname, cname_buf)) {
1324 cname_buf[0] = '\0';
1325 }
1326 cname_str = cname_buf;
1327 }
1328 _dx_request_locked(me,
1329 ^{
1330 if (unwind) {
1331 const ssize_t expire_idx = *expire_idx_ptr;
1332 if (*cnames_ptr && (expire_idx >= 0)) {
1333 xpc_object_t new_cnames = xpc_array_create(NULL, 0);
1334 if (new_cnames && (expire_idx > 0)) {
1335 xpc_array_apply(*cnames_ptr,
1336 ^ bool (const size_t index, const xpc_object_t _Nonnull value)
1337 {
1338 bool proceed = false;
1339 if (index < (size_t)expire_idx) {
1340 xpc_array_append_value(new_cnames, value);
1341 proceed = true;
1342 }
1343 return proceed;
1344 });
1345 }
1346 xpc_forget(cnames_ptr);
1347 *cnames_ptr = new_cnames;
1348 *changed_ptr = true;
1349 }
1350 *expire_idx_ptr = -1;
1351 }
1352 if (cname_str) {
1353 xpc_object_t cnames = *cnames_ptr;
1354 if (expired && (*expire_idx_ptr < 0)) {
1355 *expire_idx_ptr = cnames ? (ssize_t)xpc_array_get_count(cnames) : 0;
1356 }
1357 if (!cnames) {
1358 cnames = xpc_array_create(NULL, 0);
1359 *cnames_ptr = cnames;
1360 }
1361 if (cnames) {
1362 xpc_array_set_string(cnames, XPC_ARRAY_APPEND, cname_str);
1363 *changed_ptr = true;
1364 }
1365 }
1366 });
1367
1368 exit:
1369 return;
1370 }
1371
1372 //======================================================================================================================
1373
1374 static xpc_object_t
1375 _dx_gai_request_copy_cname_update(const dx_gai_request_t me, const int qtype)
1376 {
1377 __block xpc_object_t result = NULL;
1378 bool *changed_ptr;
1379 xpc_object_t * const cnames_ptr = _dx_gai_request_get_cnames_ptr(me, qtype, &changed_ptr, NULL);
1380 require_quiet(cnames_ptr, exit);
1381
1382 _dx_request_locked(me,
1383 ^{
1384 if (*changed_ptr) {
1385 const xpc_object_t cnames = *cnames_ptr;
1386 if (cnames) {
1387 result = xpc_copy(cnames);
1388 }
1389 *changed_ptr = false;
1390 }
1391 });
1392
1393 exit:
1394 return result;
1395 }
1396
1397 //======================================================================================================================
1398
1399 static void
1400 _dx_gai_request_gai_result_handler(mDNS * const m, DNSQuestion * const q, const ResourceRecord * const answer,
1401 const QC_result qc_result, const DNSServiceErrorType error, void * const context)
1402 {
1403 const dx_gai_request_t me = (dx_gai_request_t)context;
1404 if (!error || (error == kDNSServiceErr_NoSuchRecord)) {
1405 const bool expired = (answer->mortality == Mortality_Ghost) ? true : false;
1406 if (answer->rrtype == kDNSServiceType_CNAME) {
1407 require_quiet(!error, exit);
1408
1409 _dx_gai_request_append_cname(me, q->qtype, &answer->rdata->u.name, expired, q->CNAMEReferrals == 0);
1410 }
1411 require_quiet((answer->rrtype == kDNSServiceType_A) || (answer->rrtype == kDNSServiceType_AAAA), exit);
1412
1413 if (q->CNAMEReferrals == 0) {
1414 _dx_gai_request_unwind_cnames_if_necessary(me, q->qtype);
1415 }
1416 const uint8_t * rdata_ptr;
1417 size_t rdata_len;
1418 const uint32_t query_id = mDNSVal16(q->TargetQID);
1419 const uint32_t if_index = mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNStrue);
1420 const bool add_result = (qc_result != QC_rmv) ? true : false;
1421 if (!error) {
1422 if (answer->rrtype == kDNSServiceType_A) {
1423 rdata_ptr = answer->rdata->u.ipv4.b;
1424 rdata_len = 4;
1425 _dx_gai_request_log_a_result(me, query_id, if_index, answer->name, rdata_ptr, answer->mortality,
1426 add_result);
1427 } else {
1428 rdata_ptr = answer->rdata->u.ipv6.b;
1429 rdata_len = 16;
1430 _dx_gai_request_log_aaaa_result(me, query_id, if_index, answer->name, rdata_ptr, answer->mortality,
1431 add_result);
1432 }
1433 } else {
1434 rdata_ptr = NULL;
1435 rdata_len = 0;
1436 const char * const type_str = (answer->rrtype == kDNSServiceType_A) ? "A" : "AAAA";
1437 _dx_gai_request_log_no_such_record_result(me, query_id, if_index, answer->name, type_str, answer->mortality,
1438 add_result);
1439 }
1440 const bool answered_from_cache = !q->InitialCacheMiss ? true : false;
1441 const char *provider_name = NULL;
1442 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
1443 if (answer->dnsservice) {
1444 provider_name = mdns_dns_service_get_provider_name(answer->dnsservice);
1445 }
1446 const dnssd_getaddrinfo_result_protocol_t protocol = answer->protocol;
1447 #else
1448 const dnssd_getaddrinfo_result_protocol_t protocol = dnssd_getaddrinfo_result_protocol_udp;
1449 #endif
1450 _dx_gai_request_enqueue_result(me, if_index, answer->name, answer->rrtype, answer->rrclass, rdata_ptr,
1451 rdata_len, expired, add_result, answered_from_cache, error, protocol, provider_name);
1452 } else {
1453 _dx_request_set_error(me, error);
1454 }
1455
1456 exit:
1457 return;
1458 }
1459
1460 //======================================================================================================================
1461
1462 static void
1463 _dx_gai_request_query_result_handler(mDNS * const m, DNSQuestion * const q, const ResourceRecord * const answer,
1464 const QC_result qc_result, const DNSServiceErrorType error, void * const context)
1465 {
1466 const dx_gai_request_t me = (dx_gai_request_t)context;
1467 if (!error || (error == kDNSServiceErr_NoSuchRecord)) {
1468 require_quiet((answer->rrtype == kDNSServiceType_SVCB) || (answer->rrtype == kDNSServiceType_HTTPS), exit);
1469
1470 const uint8_t * rdata_ptr;
1471 size_t rdata_len;
1472 const uint32_t query_id = mDNSVal16(q->TargetQID);
1473 const uint32_t if_index = mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNStrue);
1474 const bool add_result = (qc_result != QC_rmv) ? true : false;
1475 const char * const type_str = (answer->rrtype == kDNSServiceType_SVCB) ? "SVCB" : "HTTPS";
1476 if (!error) {
1477 rdata_ptr = answer->rdata->u.data;
1478 rdata_len = answer->rdlength;
1479
1480 _dx_gai_request_log_svcb_result(me, query_id, if_index, answer->name, type_str, rdata_ptr, rdata_len,
1481 answer, add_result);
1482 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
1483 char * const svcb_doh_uri = dnssd_svcb_copy_doh_uri(rdata_ptr, rdata_len);
1484 // Check for a valid DoH URI.
1485 if (svcb_doh_uri) {
1486 // Pass the domain to map if the record is DNSSEC signed.
1487 char *svcb_domain = NULL;
1488 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
1489 char svcb_domain_buffer[MAX_ESCAPED_DOMAIN_NAME] = "";
1490 if (answer->dnssec_result == dnssec_secure) {
1491 if (ConvertDomainNameToCString(answer->name, svcb_domain_buffer)) {
1492 svcb_domain = svcb_domain_buffer;
1493 }
1494 }
1495 #endif
1496 Querier_RegisterDoHURI(svcb_doh_uri, svcb_domain);
1497 free(svcb_doh_uri);
1498 }
1499 #endif
1500 } else {
1501 rdata_ptr = NULL;
1502 rdata_len = 0;
1503 _dx_gai_request_log_no_such_record_result(me, query_id, if_index, answer->name, type_str, answer->mortality,
1504 add_result);
1505 }
1506 const bool answered_from_cache = !q->InitialCacheMiss ? true : false;
1507 const char *provider_name = NULL;
1508 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
1509 if (answer->dnsservice) {
1510 provider_name = mdns_dns_service_get_provider_name(answer->dnsservice);
1511 }
1512 const dnssd_getaddrinfo_result_protocol_t protocol = answer->protocol;
1513 #else
1514 const dnssd_getaddrinfo_result_protocol_t protocol = dnssd_getaddrinfo_result_protocol_udp;
1515 #endif
1516 _dx_gai_request_enqueue_result(me, if_index, answer->name, answer->rrtype, answer->rrclass, rdata_ptr,
1517 rdata_len, answer->mortality == Mortality_Ghost, add_result, answered_from_cache, error, protocol,
1518 provider_name);
1519 } else {
1520 _dx_request_set_error(me, error);
1521 }
1522
1523 exit:
1524 return;
1525 }
1526
1527 //======================================================================================================================
1528
1529 static void
1530 _dx_gai_request_enqueue_result(const dx_gai_request_t me, const uint32_t if_index, const domainname * const name,
1531 const uint16_t type, const uint16_t class, const uint8_t * const rdata_ptr, const size_t rdata_len,
1532 const bool is_expired, const bool is_add, const bool answered_from_cache, const DNSServiceErrorType result_error,
1533 const dnssd_getaddrinfo_result_protocol_t protocol, const char * const provider_name)
1534 {
1535 DNSServiceErrorType err;
1536 xpc_object_t result = xpc_dictionary_create(NULL, NULL, 0);
1537 require_action_quiet(result, exit, err = kDNSServiceErr_NoMemory);
1538
1539 char name_str[MAX_ESCAPED_DOMAIN_NAME];
1540 if (!ConvertDomainNameToCString(name, name_str)) {
1541 name_str[0] = '\0';
1542 }
1543 DNSServiceFlags flags = 0;
1544 if (is_add) {
1545 flags |= kDNSServiceFlagsAdd;
1546 if (answered_from_cache) {
1547 flags |= kDNSServiceFlagAnsweredFromCache;
1548 }
1549 }
1550 if (is_expired) {
1551 flags |= kDNSServiceFlagsExpiredAnswer;
1552 }
1553 dnssd_xpc_result_set_error(result, result_error);
1554 dnssd_xpc_result_set_flags(result, flags);
1555 dnssd_xpc_result_set_interface_index(result, if_index);
1556 dnssd_xpc_result_set_record_name(result, name_str);
1557 dnssd_xpc_result_set_record_type(result, type);
1558 dnssd_xpc_result_set_record_protocol(result, protocol);
1559 dnssd_xpc_result_set_record_class(result, class);
1560 dnssd_xpc_result_set_record_data(result, rdata_ptr, rdata_len);
1561 if (provider_name) {
1562 dnssd_xpc_result_set_provider_name(result, provider_name);
1563 }
1564 if (me->need_auth && is_add && !result_error) {
1565 uint8_t auth_tag[DNSSD_AUTHENTICATION_TAG_SIZE];
1566 const bool ok = _dx_authenticate_address_rdata(me->effective_uuid, me->hostname, type, rdata_ptr, auth_tag);
1567 if (ok) {
1568 dnssd_xpc_result_set_authentication_tag(result, auth_tag, sizeof(auth_tag));
1569 }
1570 }
1571 xpc_object_t cname_update = _dx_gai_request_copy_cname_update(me, type);
1572 if (cname_update) {
1573 dnssd_xpc_result_set_cname_update(result, cname_update);
1574 xpc_forget(&cname_update);
1575 }
1576 _dx_request_append_result(me, result);
1577 xpc_forget(&result);
1578 err = kDNSServiceErr_NoError;
1579
1580 exit:
1581 if (err) {
1582 _dx_request_set_error(me, err);
1583 }
1584 }
1585
1586 //======================================================================================================================
1587
1588 static void
1589 _dx_gai_request_get_delegator_ids(const dx_gai_request_t me, pid_t * const out_delegator_pid,
1590 const uint8_t ** const out_delegator_uuid, const audit_token_t ** const out_delegator_audit_token,
1591 audit_token_t * const storage)
1592 {
1593 pid_t pid;
1594 const uint8_t *uuid;
1595 const audit_token_t * const token = dnssd_xpc_parameters_get_delegate_audit_token(me->params, storage);
1596 if (token) {
1597 pid = audit_token_to_pid(*token);
1598 uuid = NULL;
1599 } else {
1600 uuid = dnssd_xpc_parameters_get_delegate_uuid(me->params);
1601 if (uuid) {
1602 pid = 0;
1603 } else {
1604 pid = dnssd_xpc_parameters_get_delegate_pid(me->params, NULL);
1605 }
1606 }
1607 if (out_delegator_pid) {
1608 *out_delegator_pid = pid;
1609 }
1610 if (out_delegator_uuid) {
1611 *out_delegator_uuid = uuid;
1612 }
1613 if (out_delegator_audit_token) {
1614 *out_delegator_audit_token = token;
1615 }
1616 }
1617
1618 //======================================================================================================================
1619
1620 static DNSServiceErrorType
1621 _dx_gai_request_get_svcb_name_and_type(const dx_gai_request_t me, const char ** const out_svcb_name,
1622 uint16_t * const out_svcb_type, char ** const out_svcb_memory)
1623 {
1624 DNSServiceErrorType err;
1625 const char * svcb_name = NULL;
1626 uint16_t svcb_type = 0;
1627 char * svcb_memory = NULL;
1628 const char * const service_scheme = dnssd_xpc_parameters_get_service_scheme(me->params);
1629 if (service_scheme) {
1630 if (strcasecmp(service_scheme, "_443._https") == 0) {
1631 svcb_name = me->hostname;
1632 svcb_type = kDNSType_HTTPS;
1633 } else {
1634 asprintf(&svcb_memory, "%s.%s", service_scheme, me->hostname);
1635 require_action_quiet(svcb_memory, exit, err = kDNSServiceErr_NoMemory);
1636
1637 svcb_name = svcb_memory;
1638 svcb_type = kDNSType_SVCB;
1639 }
1640 }
1641 if (out_svcb_name) {
1642 *out_svcb_name = svcb_name;
1643 }
1644 if (out_svcb_type) {
1645 *out_svcb_type = svcb_type;
1646 }
1647 *out_svcb_memory = svcb_memory;
1648 err = kDNSServiceErr_NoError;
1649
1650 exit:
1651 return err;
1652 }
1653
1654 //======================================================================================================================
1655
1656 static DNSServiceErrorType
1657 _dx_gai_request_set_need_authenticated_results(const dx_gai_request_t me, const pid_t effective_pid,
1658 const uuid_t effective_uuid)
1659 {
1660 DNSServiceErrorType err;
1661 if (effective_uuid) {
1662 uuid_copy(me->effective_uuid, effective_uuid);
1663 } else {
1664 struct proc_uniqidentifierinfo info;
1665 const int n = proc_pidinfo(effective_pid, PROC_PIDUNIQIDENTIFIERINFO, 1, &info, sizeof(info));
1666 require_action_quiet(n == (int)sizeof(info), exit, err = kDNSServiceErr_Unknown);
1667 uuid_copy(me->effective_uuid, info.p_uuid);
1668 }
1669 me->need_auth = true;
1670 err = kDNSServiceErr_NoError;
1671
1672 exit:
1673 return err;
1674 }
1675
1676 //======================================================================================================================
1677
1678 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
1679 static const uint8_t *
1680 _dx_gai_request_get_resolver_uuid(const dx_gai_request_t me)
1681 {
1682 const xpc_object_t resolver_uuids = dnssd_xpc_parameters_get_resolver_uuid_array(me->params);
1683 if (resolver_uuids && (xpc_array_get_count(resolver_uuids) > 0)) {
1684 return xpc_array_get_uuid(resolver_uuids, 0);
1685 } else {
1686 return NULL;
1687 }
1688 }
1689 #endif
1690
1691 //======================================================================================================================
1692
1693 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
1694 static bool
1695 _dx_gai_request_is_for_in_app_browser(const dx_gai_request_t me)
1696 {
1697 const char * const account_id = dnssd_xpc_parameters_get_account_id(me->params);
1698 if (account_id && (strcmp(account_id, "com.apple.WebKit.InAppBrowser") == 0)) {
1699 return true;
1700 } else {
1701 return false;
1702 }
1703 }
1704 #endif
1705
1706 //======================================================================================================================
1707
1708 static void
1709 _dx_gai_request_log_start(const dx_gai_request_t me, const DNSServiceFlags flags, const uint32_t if_index,
1710 const DNSServiceProtocol protocols, const pid_t delegator_pid, const uuid_t delegator_uuid)
1711 {
1712 char delegator_str[64];
1713 if (delegator_uuid) {
1714 uuid_string_t delegator_uuid_str;
1715 uuid_unparse_lower(delegator_uuid, delegator_uuid_str);
1716 snprintf(delegator_str, sizeof(delegator_str), ", delegator uuid: %s", delegator_uuid_str);
1717 } else if (delegator_pid != 0) {
1718 char delegator_name[MAXCOMLEN];
1719 snprintf(delegator_str, sizeof(delegator_str),
1720 ", delegator pid: %lld (%s)", (long long)delegator_pid, _dx_pid_to_name(delegator_pid, delegator_name));
1721 } else {
1722 delegator_str[0] = '\0';
1723 }
1724 char options_str[64];
1725 snprintf(options_str, sizeof(options_str), "%s", me->need_auth ? "A" : "");
1726 const dx_session_t session = me->base.session;
1727 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
1728 "[R%u] getaddrinfo start -- flags: 0x%X, ifindex: %d, protocols: %u, hostname: " PRI_S ", "
1729 "options: {" PUB_S "}, client pid: %lld (" PUB_S ")" PUB_S,
1730 me->base.request_id, flags, (int32_t)if_index, protocols, me->hostname, options_str,
1731 (long long)session->client_pid, session->client_name, delegator_str);
1732 }
1733
1734 //======================================================================================================================
1735
1736 static void
1737 _dx_gai_request_log_stop(const dx_gai_request_t me)
1738 {
1739 const dx_session_t session = me->base.session;
1740 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
1741 "[R%u] getaddrinfo stop" PUB_S " -- hostname: " PRI_S ", client pid: %lld (" PUB_S ")",
1742 me->base.request_id, session->terminated ? " (forced)" : "", me->hostname, (long long)session->client_pid,
1743 session->client_name);
1744 }
1745
1746 //======================================================================================================================
1747
1748 static void
1749 _dx_gai_request_log_a_result(const dx_gai_request_t me, const uint32_t query_id, const uint32_t if_index,
1750 const domainname * const name, const uint8_t * const rdata, const MortalityState mortality, const bool is_add)
1751 {
1752 const char * const event_str = is_add ? "add" : "rmv";
1753 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
1754 "[R%u->Q%u] getaddrinfo result -- event: " PUB_S ", ifindex: %d, name: " PRI_DM_NAME ", type: A, "
1755 "rdata: " PRI_IPv4_ADDR " (" PUB_S ")",
1756 me->base.request_id, query_id, event_str, if_index, DM_NAME_PARAM(name), rdata,
1757 MortalityDisplayString(mortality));
1758 }
1759
1760 //======================================================================================================================
1761
1762 static void
1763 _dx_gai_request_log_aaaa_result(const dx_gai_request_t me, const uint32_t query_id, const uint32_t if_index,
1764 const domainname * const name, const uint8_t * const rdata, const MortalityState mortality, const bool is_add)
1765 {
1766 const char * const event_str = is_add ? "add" : "rmv";
1767 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
1768 "[R%u->Q%u] getaddrinfo result -- event: " PUB_S ", ifindex: %d, name: " PRI_DM_NAME ", type: AAAA, "
1769 "rdata: " PRI_IPv6_ADDR " (" PUB_S ")",
1770 me->base.request_id, query_id, event_str, if_index, DM_NAME_PARAM(name), rdata,
1771 MortalityDisplayString(mortality));
1772 }
1773
1774 //======================================================================================================================
1775
1776 static void
1777 _dx_gai_request_log_svcb_result(const dx_gai_request_t me, const uint32_t query_id, const uint32_t if_index,
1778 const domainname * const name, const char * const type_str, const uint8_t * const rdata_ptr, const size_t rdata_len,
1779 const ResourceRecord * const answer, const bool is_add_event)
1780 {
1781 const char * const event_str = is_add_event ? "add" : "rmv";
1782 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
1783 const char * const dnssec_str = (answer->dnssec_result == dnssec_secure) ? "secure" : "insecure";
1784 #else
1785 const char * const dnssec_str = "insecure";
1786 #endif
1787 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
1788 "[R%u->Q%u] getaddrinfo result -- event: " PUB_S ", ifindex: %d, name: " PRI_DM_NAME ", type: " PUB_S ", "
1789 "rdata: " PRI_SVCB ", DNSSEC: " PUB_S " (" PUB_S ")",
1790 me->base.request_id, query_id, event_str, if_index, DM_NAME_PARAM(name), type_str,
1791 SVCB_PARAM(rdata_ptr, (int)rdata_len), dnssec_str, MortalityDisplayString(answer->mortality));
1792 }
1793
1794 //======================================================================================================================
1795
1796 static void
1797 _dx_gai_request_log_no_such_record_result(const dx_gai_request_t me, const uint32_t query_id, const uint32_t if_index,
1798 const domainname * const name, const char * const type_str, const MortalityState mortality, const bool is_add)
1799 {
1800 const char * const event_str = is_add ? "add" : "rmv";
1801 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
1802 "[R%u->Q%u] getaddrinfo result -- event: " PUB_S ", ifindex: %d, name: " PRI_DM_NAME ", type: " PUB_S ", "
1803 "rdata: <none> (" PUB_S ")",
1804 me->base.request_id, query_id, event_str, if_index, DM_NAME_PARAM(name), type_str,
1805 MortalityDisplayString(mortality));
1806 }
1807
1808 //======================================================================================================================
1809
1810 static void
1811 _dx_gai_request_log_error(const dx_gai_request_t me, const DNSServiceErrorType error)
1812 {
1813 const dx_session_t session = me->base.session;
1814 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
1815 "[R%u] getaddrinfo error -- error: %{mdns:err}ld, client pid: %lld (" PUB_S ")",
1816 me->base.request_id, (long)error, (long long)session->client_pid, session->client_name);
1817 }
1818
1819 //======================================================================================================================
1820
1821 static DNSServiceErrorType
1822 _dx_gai_request_activate_internal(const dx_gai_request_t me)
1823 {
1824 char *svcb_memory = NULL;
1825
1826 // Get standard parameters.
1827 bool valid;
1828 DNSServiceErrorType err;
1829 const DNSServiceFlags flags = dnssd_xpc_parameters_get_flags(me->params, &valid);
1830 require_action_quiet(valid, exit, err = kDNSServiceErr_BadParam);
1831
1832 const uint32_t if_index = dnssd_xpc_parameters_get_interface_index(me->params, &valid);
1833 require_action_quiet(valid, exit, err = kDNSServiceErr_BadParam);
1834
1835 const uint32_t protocols = dnssd_xpc_parameters_get_protocols(me->params, &valid);
1836 require_action_quiet(valid, exit, err = kDNSServiceErr_BadParam);
1837
1838 const dx_session_t session = me->base.session;
1839
1840 // Get delegator IDs.
1841 pid_t delegator_pid;
1842 const uint8_t *delegator_uuid;
1843 const audit_token_t *delegator_audit_token;
1844 audit_token_t storage;
1845 _dx_gai_request_get_delegator_ids(me, &delegator_pid, &delegator_uuid, &delegator_audit_token, &storage);
1846 if (delegator_audit_token || delegator_uuid || (delegator_pid != 0)) {
1847 require_action_quiet(session->has_delegate_entitlement, exit, err = kDNSServiceErr_NoAuth);
1848 }
1849 _dx_gai_request_log_start(me, flags, if_index, protocols, delegator_pid, delegator_uuid);
1850
1851 // Determine effective IDs.
1852 // Note: The mDNS core requires that the effective PID be set to zero if the effective UUID is set.
1853 const uint8_t * effective_uuid;
1854 pid_t effective_pid;
1855 if (delegator_uuid) {
1856 effective_uuid = delegator_uuid;
1857 effective_pid = 0;
1858 } else {
1859 effective_uuid = NULL;
1860 effective_pid = (delegator_pid != 0) ? delegator_pid : session->client_pid;
1861 }
1862 const bool need_auth_tags = dnssd_xpc_parameters_get_need_authentication_tags(me->params);
1863 if (need_auth_tags) {
1864 err = _dx_gai_request_set_need_authenticated_results(me, effective_pid, effective_uuid);
1865 require_noerr_quiet(err, exit);
1866 }
1867
1868 // Set up GetAddrInfo parameters.
1869 GetAddrInfoClientRequestParams gai_params;
1870 GetAddrInfoClientRequestParamsInit(&gai_params);
1871 gai_params.hostnameStr = me->hostname;
1872 gai_params.requestID = me->base.request_id;
1873 gai_params.interfaceIndex = if_index;
1874 gai_params.flags = flags;
1875 gai_params.protocols = protocols;
1876 gai_params.effectivePID = effective_pid;
1877 gai_params.effectiveUUID = effective_uuid;
1878 gai_params.peerUID = session->client_euid;
1879 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
1880 const uint8_t * const resolver_uuid = _dx_gai_request_get_resolver_uuid(me);
1881 const xpc_object_t fallback_config = dnssd_xpc_parameters_get_fallback_config(me->params);
1882 const bool need_encryption = dnssd_xpc_parameters_get_need_encrypted_query(me->params);
1883 gai_params.needEncryption = need_encryption ? mDNStrue : mDNSfalse;
1884 #endif
1885 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
1886 const bool for_in_app_browser = _dx_gai_request_is_for_in_app_browser(me);
1887 gai_params.peerAuditToken = &session->audit_token;
1888 gai_params.delegatorAuditToken = delegator_audit_token;
1889 gai_params.isInAppBrowserRequest = for_in_app_browser ? mDNStrue : mDNSfalse;
1890 #endif
1891 // Set up QueryRecord parameters.
1892 QueryRecordClientRequestParams query_params;
1893 QueryRecordClientRequestParams *query_params_ptr = NULL;
1894 const char *svcb_name = NULL;
1895 uint16_t svcb_type = 0;
1896 err = _dx_gai_request_get_svcb_name_and_type(me, &svcb_name, &svcb_type, &svcb_memory);
1897 require_noerr_quiet(err, exit);
1898 if (svcb_name) {
1899 QueryRecordClientRequestParamsInit(&query_params);
1900 query_params.requestID = me->base.request_id;
1901 query_params.qnameStr = svcb_name;
1902 query_params.interfaceIndex = if_index;
1903 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
1904 query_params.flags = flags | kDNSServiceFlagsEnableDNSSEC;
1905 #else
1906 query_params.flags = flags;
1907 #endif
1908 query_params.qtype = svcb_type;
1909 query_params.qclass = kDNSServiceClass_IN;
1910 query_params.effectivePID = effective_pid;
1911 query_params.effectiveUUID = effective_uuid;
1912 query_params.peerUID = session->client_euid;
1913 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
1914 query_params.needEncryption = need_encryption ? mDNStrue : mDNSfalse;
1915 #endif
1916 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
1917 query_params.peerAuditToken = &session->audit_token;
1918 query_params.delegatorAuditToken = delegator_audit_token;
1919 query_params.isInAppBrowserRequest = for_in_app_browser ? mDNStrue : mDNSfalse;
1920 #endif
1921 query_params_ptr = &query_params;
1922 }
1923 // Activate request.
1924 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
1925 err = _dx_gai_request_start_client_requests(me, &gai_params, query_params_ptr, resolver_uuid, fallback_config);
1926 #else
1927 err = _dx_gai_request_start_client_requests(me, &gai_params, query_params_ptr, NULL, NULL);
1928 #endif
1929 require_noerr_quiet(err, exit);
1930
1931 exit:
1932 ForgetMem(&svcb_memory);
1933 return err;
1934 }
1935
1936 //======================================================================================================================
1937 // MARK: - Helper Functions
1938
1939 typedef struct {
1940 struct necp_client_resolver_answer hdr;
1941 uint8_t hostname[MAX_ESCAPED_DOMAIN_NAME];
1942 } dx_necp_answer_t;
1943
1944 check_compile_time(sizeof_field(dx_necp_answer_t, hdr) == offsetof(dx_necp_answer_t, hostname));
1945
1946 static bool
1947 _dx_authenticate_address_rdata(uuid_t effective_uuid, const char * const hostname, const int type,
1948 const uint8_t * const rdata, uint8_t out_auth_tag[STATIC_PARAM DNSSD_AUTHENTICATION_TAG_SIZE])
1949 {
1950 bool ok = false;
1951 require_quiet((type == kDNSServiceType_A) || (type == kDNSServiceType_AAAA), exit);
1952
1953 dx_necp_answer_t answer;
1954 struct necp_client_resolver_answer * const hdr = &answer.hdr;
1955 memset(hdr, 0, sizeof(*hdr));
1956 uuid_copy(hdr->client_id, effective_uuid);
1957
1958 hdr->sign_type = NECP_CLIENT_SIGN_TYPE_RESOLVER_ANSWER;
1959 if (type == kDNSServiceType_A) {
1960 hdr->address_answer.sa.sa_family = AF_INET;
1961 hdr->address_answer.sa.sa_len = sizeof(struct sockaddr_in);
1962 memcpy(&hdr->address_answer.sin.sin_addr.s_addr, rdata, 4);
1963 } else {
1964 hdr->address_answer.sa.sa_family = AF_INET6;
1965 hdr->address_answer.sa.sa_len = sizeof(struct sockaddr_in6);
1966 memcpy(hdr->address_answer.sin6.sin6_addr.s6_addr, rdata, 16);
1967 }
1968 const size_t hostname_len = strlen(hostname);
1969 require_quiet(hostname_len <= sizeof(answer.hostname), exit);
1970
1971 hdr->hostname_length = (uint32_t)hostname_len;
1972 memcpy(answer.hostname, hostname, hdr->hostname_length);
1973
1974 static int necp_fd = -1;
1975 if (necp_fd < 0) {
1976 necp_fd = necp_open(0);
1977 }
1978 require_quiet(necp_fd >= 0, exit);
1979
1980 const int err = necp_client_action(necp_fd, NECP_CLIENT_ACTION_SIGN, (uint8_t *)&answer.hdr,
1981 sizeof(answer.hdr) + hdr->hostname_length, out_auth_tag, DNSSD_AUTHENTICATION_TAG_SIZE);
1982 require_noerr_quiet(err, exit);
1983
1984 ok = true;
1985
1986 exit:
1987 return ok;
1988 }
1989
1990 //======================================================================================================================
1991
1992 static char *
1993 _dx_pid_to_name(const pid_t pid, char out_name[STATIC_PARAM MAXCOMLEN])
1994 {
1995 out_name[0] = '\0';
1996 if (pid != 0) {
1997 struct proc_bsdshortinfo info;
1998 const int n = proc_pidinfo(pid, PROC_PIDT_SHORTBSDINFO, 1, &info, PROC_PIDT_SHORTBSDINFO_SIZE);
1999 if (n == (int)sizeof(info)) {
2000 check_compile_time_code(sizeof(info.pbsi_comm) == MAXCOMLEN);
2001 strlcpy(out_name, info.pbsi_comm, MAXCOMLEN);
2002 }
2003 }
2004 return out_name;
2005 }
2006
2007 //======================================================================================================================
2008
2009 static void
2010 _dx_kqueue_locked(const char * const description, const dx_block_t block)
2011 {
2012 KQueueLock();
2013 block();
2014 KQueueUnlock(description);
2015 }