2 * Copyright (c) 2019-2020 Apple Inc. All rights reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "dnssd_server.h"
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"
26 #include <bsm/libbsm.h>
27 #include <CoreUtils/CommonServices.h>
28 #include <CoreUtils/DebugServices.h>
30 #include <mach/mach_time.h>
33 #include <stdatomic.h>
34 #include <sys/proc_info.h>
35 #include <xpc/private.h>
37 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
38 #include "QuerierSupport.h"
41 #if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
42 #include "mdns_trust.h"
43 #include <os/feature_private.h>
46 //======================================================================================================================
47 // MARK: - Kind Declarations
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); \
54 static dx_ ## NAME ## _t \
55 _dx_ ## NAME ## _alloc_and_init(void)
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.
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))]
66 #define DX_SUBKIND_DEFINE_ABSTRACT(NAME, SUPER, ...) \
67 static const struct dx_kind_s _dx_ ## NAME ## _kind = { \
68 .superkind = &_dx_ ## SUPER ##_kind, \
71 DX_BASE_CHECK(NAME, SUPER)
73 #define DX_SUBKIND_DEFINE(NAME, SUPER, ...) \
74 DX_SUBKIND_DEFINE_ABSTRACT(NAME, SUPER, __VA_ARGS__); \
76 static dx_ ## NAME ## _t \
77 _dx_ ## NAME ## _alloc_and_init(void) \
79 const dx_ ## NAME ## _t obj = (dx_ ## NAME ## _t)calloc(1, sizeof(*obj)); \
80 require_quiet(obj, exit); \
82 const dx_object_t object = (dx_object_t)obj; \
83 object->ref_count = 1; \
84 object->kind = &_dx_ ## NAME ## _kind; \
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__)
95 DX_KIND_DECLARE_ABSTRACT(object
);
96 DX_KIND_DECLARE(session
);
97 DX_KIND_DECLARE_ABSTRACT(request
);
98 DX_KIND_DECLARE(gai_request
);
100 #define DX_TRANSPARENT_UNION_MEMBER(NAME) DX_STRUCT(NAME) * NAME
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__
));
110 (*dx_init_f
)(dx_any_t object
);
113 (*dx_invalidate_f
)(dx_any_t object
);
116 (*dx_finalize_f
)(dx_any_t object
);
118 typedef const struct dx_kind_s
* dx_kind_t
;
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.
126 //======================================================================================================================
127 // MARK: - Object Kind Definition
130 dx_kind_t kind
; // The object's kind.
131 _Atomic(int32_t) ref_count
; // Reference count.
135 _dx_init(dx_object_t object
);
138 _dx_retain(dx_any_t object
);
141 _dx_release(dx_any_t object
);
142 #define _dx_release_null_safe(X) \
148 #define _dx_forget(X) ForgetCustom(X, _dx_release)
151 _dx_invalidate(dx_any_t object
);
153 static const struct dx_kind_s _dx_object_kind
= {
160 //======================================================================================================================
161 // MARK: - Session Kind Definition
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.
180 _dx_session_invalidate(dx_session_t session
);
182 DX_OBJECT_SUBKIND_DEFINE(session
,
183 .invalidate
= _dx_session_invalidate
187 DX_TRANSPARENT_UNION_MEMBER(request
);
188 DX_TRANSPARENT_UNION_MEMBER(gai_request
);
189 } dx_any_request_t
__attribute__((__transparent_union__
));
191 //======================================================================================================================
192 // MARK: - Request Kind Definition
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.
207 _dx_request_init(dx_request_t request
);
210 _dx_request_finalize(dx_request_t request
);
212 DX_OBJECT_SUBKIND_DEFINE_ABSTRACT(request
,
213 .init
= _dx_request_init
,
214 .finalize
= _dx_request_finalize
217 //======================================================================================================================
218 // MARK: - GetAddrInfo Request Kind Definition
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
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.
244 _dx_gai_request_invalidate(dx_gai_request_t request
);
247 _dx_gai_request_finalize(dx_gai_request_t request
);
249 DX_REQUEST_SUBKIND_DEFINE(gai_request
,
250 .invalidate
= _dx_gai_request_invalidate
,
251 .finalize
= _dx_gai_request_finalize
254 //======================================================================================================================
255 // MARK: - Local Prototypes
257 static dispatch_queue_t
258 _dx_server_queue(void);
261 _dx_server_handle_new_connection(xpc_connection_t connection
);
264 _dx_server_register_session(dx_session_t session
);
267 _dx_server_deregister_session(dx_session_t session
);
270 _dx_server_check_sessions(void);
273 _dx_session_create(xpc_connection_t connection
);
276 _dx_session_activate(dx_session_t session
);
279 _dx_session_handle_message(dx_session_t session
, xpc_object_t msg
);
281 static DNSServiceErrorType
282 _dx_session_handle_getaddrinfo_command(dx_session_t session
, xpc_object_t msg
);
284 static DNSServiceErrorType
285 _dx_session_handle_stop_command(dx_session_t session
, xpc_object_t msg
);
288 _dx_session_append_request(dx_session_t session
, dx_any_request_t any
);
291 _dx_session_check(dx_session_t session
, uint64_t now_ticks
);
294 _dx_session_send_message(dx_session_t session
, xpc_object_t msg
);
297 _dx_session_terminate(dx_session_t session
);
300 _dx_session_log_error(dx_session_t session
, DNSServiceErrorType error
);
303 _dx_session_log_pending_send_count_increase(dx_session_t session
);
306 _dx_session_log_pending_send_count_decrease(dx_session_t session
);
309 _dx_session_log_termination(dx_session_t session
);
312 _dx_request_take_results(dx_request_t request
);
314 typedef void (^dx_block_t
)(void);
317 _dx_request_locked(dx_any_request_t request
, dx_block_t block
);
320 _dx_request_append_result(dx_any_request_t request
, xpc_object_t result
);
322 static DNSServiceErrorType
323 _dx_request_get_error(dx_any_request_t request
);
326 _dx_request_set_error(dx_any_request_t request
, DNSServiceErrorType error
);
329 _dx_request_send_pending_error(dx_any_request_t request
);
331 static dx_gai_request_t
332 _dx_gai_request_create(uint64_t command_id
, dx_session_t session
);
334 static DNSServiceErrorType
335 _dx_gai_request_activate(dx_gai_request_t request
);
337 static DNSServiceErrorType
338 _dx_gai_request_activate_internal(dx_gai_request_t request
);
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
);
345 _dx_gai_request_stop_client_requests(dx_gai_request_t request
);
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
);
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)
356 _dx_gai_request_copy_cname_update(dx_gai_request_t request
, int qtype
);
359 _dx_gai_request_gai_result_handler(mDNS
*m
, DNSQuestion
*q
, const ResourceRecord
*answer
, QC_result qc_result
,
360 DNSServiceErrorType error
, void *context
);
363 _dx_gai_request_query_result_handler(mDNS
*m
, DNSQuestion
*q
, const ResourceRecord
*answer
, QC_result qc_result
,
364 DNSServiceErrorType error
, void *context
);
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
);
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
);
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
);
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
);
383 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
384 static const uint8_t *
385 _dx_gai_request_get_resolver_uuid(dx_gai_request_t request
);
388 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
390 _dx_gai_request_is_for_in_app_browser(dx_gai_request_t request
);
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
);
398 _dx_gai_request_log_stop(dx_gai_request_t request
);
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
);
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
);
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
);
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
);
417 _dx_gai_request_log_error(dx_gai_request_t request
, DNSServiceErrorType error
);
419 #define DNSSD_AUTHENTICATION_TAG_SIZE 32 // XXX: Defined as a workaround until NECP header defines this length.
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
]);
426 _dx_pid_to_name(pid_t pid
, char out_name
[STATIC_PARAM MAXCOMLEN
]);
429 _dx_kqueue_locked(const char *description
, dx_block_t block
);
431 //======================================================================================================================
434 static dx_session_t g_session_list
= NULL
;
436 //======================================================================================================================
437 // MARK: - Server Functions
440 dnssd_server_init(void)
442 static dispatch_once_t s_once
= 0;
443 static xpc_connection_t s_listener
= NULL
;
445 dispatch_once(&s_once
,
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
)
452 if (xpc_get_type(event
) == XPC_TYPE_CONNECTION
) {
453 _dx_server_handle_new_connection((xpc_connection_t
)event
);
456 xpc_connection_activate(s_listener
);
460 //======================================================================================================================
463 dnssd_server_idle(void)
465 static dispatch_once_t s_once
= 0;
466 static dispatch_source_t s_source
= NULL
;
467 dispatch_once(&s_once
,
469 s_source
= dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_OR
, 0, 0, _dx_server_queue());
470 dispatch_source_set_event_handler(s_source
,
472 _dx_server_check_sessions();
474 dispatch_activate(s_source
);
476 dispatch_source_merge_data(s_source
, 1);
479 //======================================================================================================================
482 dnssd_server_get_new_request_id(void)
484 static _Atomic(uint32_t) s_next_id
= 1;
485 return atomic_fetch_add(&s_next_id
, 1);
488 //======================================================================================================================
490 static dispatch_queue_t
491 _dx_server_queue(void)
493 static dispatch_once_t once
= 0;
494 static dispatch_queue_t queue
= NULL
;
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
);
505 //======================================================================================================================
508 _dx_server_handle_new_connection(const xpc_connection_t connection
)
510 dx_session_t session
= _dx_session_create(connection
);
512 _dx_session_activate(session
);
513 _dx_server_register_session(session
);
514 _dx_forget(&session
);
516 xpc_connection_cancel(connection
);
520 //======================================================================================================================
523 _dx_server_register_session(dx_session_t session
)
525 dx_session_t
*ptr
= &g_session_list
;
529 session
->next
= NULL
;
534 //======================================================================================================================
537 _dx_server_deregister_session(dx_session_t session
)
539 dx_session_t
*ptr
= &g_session_list
;
540 while (*ptr
&& (*ptr
!= session
)) {
544 *ptr
= session
->next
;
545 session
->next
= NULL
;
546 _dx_forget(&session
);
550 //======================================================================================================================
553 _dx_server_check_sessions(void)
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
);
563 //======================================================================================================================
564 // MARK: - Object Methods
567 _dx_recursive_init(dx_object_t object
, dx_kind_t kind
);
570 _dx_init(const dx_object_t me
)
572 _dx_recursive_init(me
, me
->kind
);
576 _dx_recursive_init(const dx_object_t me
, const dx_kind_t kind
)
578 if (kind
->superkind
) {
579 _dx_recursive_init(me
, kind
->superkind
);
586 //======================================================================================================================
589 _dx_retain(const dx_any_t any
)
591 const dx_object_t me
= any
.object
;
592 atomic_fetch_add(&me
->ref_count
, 1);
595 //======================================================================================================================
598 _dx_finalize(dx_object_t object
);
601 _dx_release(const dx_any_t any
)
603 const dx_object_t me
= any
.object
;
604 if (atomic_fetch_sub(&me
->ref_count
, 1) == 1) {
611 _dx_finalize(const dx_object_t me
)
613 for (dx_kind_t kind
= me
->kind
; kind
; kind
= kind
->superkind
) {
614 if (kind
->finalize
) {
620 //======================================================================================================================
623 _dx_invalidate(const dx_any_t any
)
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
);
634 //======================================================================================================================
635 // MARK: - Session Methods
637 #define DNSSD_DELEGATE_ENTITLEMENT "com.apple.private.network.socket-delegate"
640 _dx_session_create(const xpc_connection_t connection
)
642 const dx_session_t obj
= _dx_session_alloc_and_init();
643 require_quiet(obj
, exit
);
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
);
652 xpc_object_t value
= xpc_connection_copy_entitlement_value(obj
->connection
, DNSSD_DELEGATE_ENTITLEMENT
);
654 if (value
== XPC_BOOL_TRUE
) {
655 obj
->has_delegate_entitlement
= true;
664 //======================================================================================================================
667 _dx_session_activate(const dx_session_t 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
);
678 } else if (event
== XPC_ERROR_CONNECTION_INVALID
) {
679 _dx_server_deregister_session(me
);
680 _dx_session_invalidate(me
);
683 xpc_connection_forget(&me
->connection
);
686 xpc_connection_activate(me
->connection
);
689 //======================================================================================================================
692 _dx_session_invalidate(const dx_session_t me
)
694 xpc_connection_forget(&me
->connection
);
696 while ((req
= me
->request_list
) != NULL
)
698 me
->request_list
= req
->next
;
704 //======================================================================================================================
707 _dx_session_handle_message(const dx_session_t me
, const xpc_object_t msg
)
709 DNSServiceErrorType err
;
710 const char * const command
= dnssd_xpc_message_get_command(msg
);
711 require_action_quiet(command
, exit
, err
= kDNSServiceErr_BadParam
);
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
);
718 err
= kDNSServiceErr_BadParam
;
722 xpc_object_t reply
= xpc_dictionary_create_reply(msg
);
724 dnssd_xpc_message_set_error(reply
, err
);
725 _dx_session_send_message(me
, reply
);
728 _dx_session_terminate(me
);
732 //======================================================================================================================
734 static DNSServiceErrorType
735 _dx_session_handle_getaddrinfo_command(const dx_session_t me
, const xpc_object_t msg
)
737 dx_gai_request_t req
= NULL
;
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
);
743 const xpc_object_t params
= dnssd_xpc_message_get_parameters(msg
);
744 require_action_quiet(params
, exit
, err
= kDNSServiceErr_BadParam
);
746 req
= _dx_gai_request_create(command_id
, me
);
747 require_action_quiet(req
, exit
, err
= kDNSServiceErr_NoMemory
);
749 req
->params
= params
;
750 xpc_retain(req
->params
);
752 err
= _dx_gai_request_activate(req
);
753 require_noerr_quiet(err
, exit
);
755 _dx_session_append_request(me
, req
);
760 _dx_gai_request_log_error(req
, err
);
762 _dx_session_log_error(me
, err
);
765 _dx_release_null_safe(req
);
769 //======================================================================================================================
771 static DNSServiceErrorType
772 _dx_session_handle_stop_command(const dx_session_t me
, const xpc_object_t msg
)
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
);
781 for (ptr
= &me
->request_list
; (req
= *ptr
) != NULL
; ptr
= &req
->next
) {
782 if (req
->command_id
== command_id
) {
786 require_action_quiet(req
, exit
, err
= kDNSServiceErr_BadReference
);
792 err
= kDNSServiceErr_NoError
;
798 //======================================================================================================================
801 _dx_session_append_request(const dx_session_t me
, const dx_any_request_t any
)
803 dx_request_t
*ptr
= &me
->request_list
;
807 const dx_request_t req
= any
.request
;
813 //======================================================================================================================
815 #define DX_SESSION_BACK_PRESSURE_TIMEOUT_SECS 5
818 _dx_session_check(const dx_session_t me
, const uint64_t now_ticks
)
821 xpc_object_t results
= NULL
;
822 require_action_quiet(me
->connection
, exit
, terminate
= false);
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);
828 for (dx_request_t req
= me
->request_list
; req
; req
= req
->next
) {
829 results
= _dx_request_take_results(req
);
831 xpc_object_t msg
= xpc_dictionary_create(NULL
, NULL
, 0);
832 require_action_quiet(msg
, exit
, terminate
= true);
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
);
841 const bool ok
= _dx_request_send_pending_error(req
);
842 require_action_quiet(ok
, exit
, terminate
= true);
847 if (unlikely(terminate
)) {
848 _dx_session_terminate(me
);
850 xpc_forget(&results
);
853 //======================================================================================================================
856 _dx_session_send_message(const dx_session_t me
, const xpc_object_t msg
)
858 require_quiet(me
->connection
, exit
);
860 xpc_connection_send_message(me
->connection
, msg
);
861 if (me
->pending_send_count
++ == 0) {
862 me
->pending_send_start_ticks
= mach_continuous_time();
864 _dx_session_log_pending_send_count_increase(me
);
866 me
->pending_send_count_max
= me
->pending_send_count
;
868 xpc_connection_send_barrier(me
->connection
,
870 --me
->pending_send_count
;
871 if (me
->pending_send_count_max
> 1) {
872 _dx_session_log_pending_send_count_decrease(me
);
874 if (me
->pending_send_count
== 0) {
875 me
->pending_send_count_max
= 0;
884 //======================================================================================================================
887 _dx_session_terminate(const dx_session_t me
)
889 if (!me
->terminated
) {
890 _dx_session_log_termination(me
);
891 xpc_connection_forget(&me
->connection
);
892 me
->terminated
= true;
896 //======================================================================================================================
899 _dx_session_log_error(const dx_session_t me
, const DNSServiceErrorType error
)
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
);
906 //======================================================================================================================
909 _dx_session_log_pending_send_count_increase(const dx_session_t me
)
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
);
916 //======================================================================================================================
919 _dx_session_log_pending_send_count_decrease(const dx_session_t me
)
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
);
926 //======================================================================================================================
929 _dx_session_log_termination(const dx_session_t me
)
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
);
936 //======================================================================================================================
937 // MARK: - Request Methods
940 _dx_request_init(const dx_request_t me
)
942 me
->request_id
= dnssd_server_get_new_request_id();
943 me
->lock
= OS_UNFAIR_LOCK_INIT
;
946 //======================================================================================================================
949 _dx_request_finalize(const dx_request_t me
)
951 _dx_forget(&me
->session
);
952 xpc_forget(&me
->results
);
955 //======================================================================================================================
958 _dx_request_take_results(const dx_request_t me
)
960 __block xpc_object_t results
= NULL
;
961 _dx_request_locked(me
,
963 if (me
->results
&& (xpc_array_get_count(me
->results
) > 0)) {
964 results
= me
->results
;
971 //======================================================================================================================
974 _dx_request_locked(const dx_any_request_t any
, const dx_block_t block
)
976 const dx_request_t me
= any
.request
;
977 os_unfair_lock_lock(&me
->lock
);
979 os_unfair_lock_unlock(&me
->lock
);
982 //======================================================================================================================
985 _dx_request_append_result(const dx_any_request_t any
, const xpc_object_t result
)
987 const dx_request_t me
= any
.request
;
988 _dx_request_locked(me
,
991 me
->results
= xpc_array_create(NULL
, 0);
993 if (likely(me
->results
)) {
994 xpc_array_append_value(me
->results
, result
);
997 me
->error
= kDNSServiceErr_NoMemory
;
1003 //======================================================================================================================
1005 static DNSServiceErrorType
1006 _dx_request_get_error(const dx_any_request_t any
)
1008 const dx_request_t me
= any
.request
;
1009 __block DNSServiceErrorType error
;
1010 _dx_request_locked(me
,
1017 //======================================================================================================================
1020 _dx_request_set_error(const dx_any_request_t any
, const DNSServiceErrorType error
)
1022 __block
bool did_set
= false;
1024 const dx_request_t me
= any
.request
;
1025 _dx_request_locked(me
,
1036 //======================================================================================================================
1039 _dx_request_send_pending_error(const dx_any_request_t any
)
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
);
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
);
1052 me
->sent_error
= true;
1060 //======================================================================================================================
1061 // MARK: - GetAddrInfo Request Methods
1063 static dx_gai_request_t
1064 _dx_gai_request_create(const uint64_t command_id
, const dx_session_t session
)
1066 dx_gai_request_t obj
= _dx_gai_request_alloc_and_init();
1067 require_quiet(obj
, exit
);
1069 obj
->base
.command_id
= command_id
;
1070 obj
->base
.session
= session
;
1071 _dx_retain(obj
->base
.session
);
1073 obj
->cnames_a_expire_idx
= -1;
1074 obj
->cnames_aaaa_expire_idx
= -1;
1080 //======================================================================================================================
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
);
1087 static DNSServiceErrorType
1088 _dx_gai_request_activate(const dx_gai_request_t me
)
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
);
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
);
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
);
1105 if (!defer_activation
) {
1106 err
= _dx_gai_request_activate_internal(me
);
1107 require_noerr_quiet(err
, exit
);
1109 err
= kDNSServiceErr_NoError
;
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
)
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
);
1125 case mdns_trust_status_granted
:
1126 err
= kDNSServiceErr_NoError
;
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
);
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
)
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
);
1144 handler_err
= kDNSServiceErr_PolicyDenied
;
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
);
1151 mdns_forget(&me
->trust
);
1154 mdns_trust_activate(me
->trust
);
1155 defer_activation
= true;
1156 err
= kDNSServiceErr_NoError
;
1159 case mdns_trust_status_no_entitlement
:
1160 err
= kDNSServiceErr_NoAuth
;
1164 err
= kDNSServiceErr_Unknown
;
1169 if (out_defer_activation
) {
1170 *out_defer_activation
= defer_activation
;
1176 //======================================================================================================================
1179 _dx_gai_request_invalidate(const dx_gai_request_t me
)
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
);
1188 //======================================================================================================================
1191 _dx_gai_request_finalize(const dx_gai_request_t me
)
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
);
1200 //======================================================================================================================
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
)
1207 __block DNSServiceErrorType err
= kDNSServiceErr_NoError
;
1208 _dx_kqueue_locked("dx_gai_request: starting client requests",
1210 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
1211 if (resolver_uuid
&& !uuid_is_null(resolver_uuid
)) {
1212 Querier_RegisterPathResolver(resolver_uuid
);
1214 if ((me
->custom_service_id
== 0) && fallback_config
) {
1215 me
->custom_service_id
= Querier_RegisterCustomDNSService(fallback_config
);
1218 gai_params
->resolverUUID
= resolver_uuid
;
1219 gai_params
->customID
= me
->custom_service_id
;
1222 query_params
->resolverUUID
= resolver_uuid
;
1223 query_params
->customID
= me
->custom_service_id
;
1226 (void)resolver_uuid
;
1227 (void)fallback_config
;
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;
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;
1243 _dx_gai_request_stop_client_requests(me
);
1248 //======================================================================================================================
1251 _dx_gai_request_stop_client_requests(const dx_gai_request_t me
)
1253 _dx_kqueue_locked("dx_gai_request: stopping client requests",
1255 if (me
->gai_active
) {
1256 GetAddrInfoClientRequestStop(&me
->gai
);
1257 me
->gai_active
= false;
1259 if (me
->query_active
) {
1260 QueryRecordClientRequestStop(&me
->query
);
1261 me
->query_active
= false;
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;
1272 //======================================================================================================================
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
)
1278 ssize_t
*expire_idx_ptr
;
1279 xpc_object_t
*cnames_ptr
;
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
;
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
;
1296 expire_idx_ptr
= NULL
;
1300 if (out_expire_idx_ptr
) {
1301 *out_expire_idx_ptr
= expire_idx_ptr
;
1303 if (out_changed_ptr
) {
1304 *out_changed_ptr
= changed_ptr
;
1309 //======================================================================================================================
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
)
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
);
1320 const char *cname_str
= NULL
;
1321 char cname_buf
[MAX_ESCAPED_DOMAIN_NAME
];
1323 if (!ConvertDomainNameToCString(cname
, cname_buf
)) {
1324 cname_buf
[0] = '\0';
1326 cname_str
= cname_buf
;
1328 _dx_request_locked(me
,
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
)
1338 bool proceed
= false;
1339 if (index
< (size_t)expire_idx
) {
1340 xpc_array_append_value(new_cnames
, value
);
1346 xpc_forget(cnames_ptr
);
1347 *cnames_ptr
= new_cnames
;
1348 *changed_ptr
= true;
1350 *expire_idx_ptr
= -1;
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;
1358 cnames
= xpc_array_create(NULL
, 0);
1359 *cnames_ptr
= cnames
;
1362 xpc_array_set_string(cnames
, XPC_ARRAY_APPEND
, cname_str
);
1363 *changed_ptr
= true;
1372 //======================================================================================================================
1375 _dx_gai_request_copy_cname_update(const dx_gai_request_t me
, const int qtype
)
1377 __block xpc_object_t result
= NULL
;
1379 xpc_object_t
* const cnames_ptr
= _dx_gai_request_get_cnames_ptr(me
, qtype
, &changed_ptr
, NULL
);
1380 require_quiet(cnames_ptr
, exit
);
1382 _dx_request_locked(me
,
1385 const xpc_object_t cnames
= *cnames_ptr
;
1387 result
= xpc_copy(cnames
);
1389 *changed_ptr
= false;
1397 //======================================================================================================================
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
)
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
);
1409 _dx_gai_request_append_cname(me
, q
->qtype
, &answer
->rdata
->u
.name
, expired
, q
->CNAMEReferrals
== 0);
1411 require_quiet((answer
->rrtype
== kDNSServiceType_A
) || (answer
->rrtype
== kDNSServiceType_AAAA
), exit
);
1413 if (q
->CNAMEReferrals
== 0) {
1414 _dx_gai_request_unwind_cnames_if_necessary(me
, q
->qtype
);
1416 const uint8_t * rdata_ptr
;
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;
1422 if (answer
->rrtype
== kDNSServiceType_A
) {
1423 rdata_ptr
= answer
->rdata
->u
.ipv4
.b
;
1425 _dx_gai_request_log_a_result(me
, query_id
, if_index
, answer
->name
, rdata_ptr
, answer
->mortality
,
1428 rdata_ptr
= answer
->rdata
->u
.ipv6
.b
;
1430 _dx_gai_request_log_aaaa_result(me
, query_id
, if_index
, answer
->name
, rdata_ptr
, answer
->mortality
,
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
,
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
);
1446 const dnssd_getaddrinfo_result_protocol_t protocol
= answer
->protocol
;
1448 const dnssd_getaddrinfo_result_protocol_t protocol
= dnssd_getaddrinfo_result_protocol_udp
;
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
);
1453 _dx_request_set_error(me
, error
);
1460 //======================================================================================================================
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
)
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
);
1470 const uint8_t * rdata_ptr
;
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";
1477 rdata_ptr
= answer
->rdata
->u
.data
;
1478 rdata_len
= answer
->rdlength
;
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.
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
;
1496 Querier_RegisterDoHURI(svcb_doh_uri
, svcb_domain
);
1503 _dx_gai_request_log_no_such_record_result(me
, query_id
, if_index
, answer
->name
, type_str
, answer
->mortality
,
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
);
1512 const dnssd_getaddrinfo_result_protocol_t protocol
= answer
->protocol
;
1514 const dnssd_getaddrinfo_result_protocol_t protocol
= dnssd_getaddrinfo_result_protocol_udp
;
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
,
1520 _dx_request_set_error(me
, error
);
1527 //======================================================================================================================
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
)
1535 DNSServiceErrorType err
;
1536 xpc_object_t result
= xpc_dictionary_create(NULL
, NULL
, 0);
1537 require_action_quiet(result
, exit
, err
= kDNSServiceErr_NoMemory
);
1539 char name_str
[MAX_ESCAPED_DOMAIN_NAME
];
1540 if (!ConvertDomainNameToCString(name
, name_str
)) {
1543 DNSServiceFlags flags
= 0;
1545 flags
|= kDNSServiceFlagsAdd
;
1546 if (answered_from_cache
) {
1547 flags
|= kDNSServiceFlagAnsweredFromCache
;
1551 flags
|= kDNSServiceFlagsExpiredAnswer
;
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
);
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
);
1568 dnssd_xpc_result_set_authentication_tag(result
, auth_tag
, sizeof(auth_tag
));
1571 xpc_object_t cname_update
= _dx_gai_request_copy_cname_update(me
, type
);
1573 dnssd_xpc_result_set_cname_update(result
, cname_update
);
1574 xpc_forget(&cname_update
);
1576 _dx_request_append_result(me
, result
);
1577 xpc_forget(&result
);
1578 err
= kDNSServiceErr_NoError
;
1582 _dx_request_set_error(me
, err
);
1586 //======================================================================================================================
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
)
1594 const uint8_t *uuid
;
1595 const audit_token_t
* const token
= dnssd_xpc_parameters_get_delegate_audit_token(me
->params
, storage
);
1597 pid
= audit_token_to_pid(*token
);
1600 uuid
= dnssd_xpc_parameters_get_delegate_uuid(me
->params
);
1604 pid
= dnssd_xpc_parameters_get_delegate_pid(me
->params
, NULL
);
1607 if (out_delegator_pid
) {
1608 *out_delegator_pid
= pid
;
1610 if (out_delegator_uuid
) {
1611 *out_delegator_uuid
= uuid
;
1613 if (out_delegator_audit_token
) {
1614 *out_delegator_audit_token
= token
;
1618 //======================================================================================================================
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
)
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
;
1634 asprintf(&svcb_memory
, "%s.%s", service_scheme
, me
->hostname
);
1635 require_action_quiet(svcb_memory
, exit
, err
= kDNSServiceErr_NoMemory
);
1637 svcb_name
= svcb_memory
;
1638 svcb_type
= kDNSType_SVCB
;
1641 if (out_svcb_name
) {
1642 *out_svcb_name
= svcb_name
;
1644 if (out_svcb_type
) {
1645 *out_svcb_type
= svcb_type
;
1647 *out_svcb_memory
= svcb_memory
;
1648 err
= kDNSServiceErr_NoError
;
1654 //======================================================================================================================
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
)
1660 DNSServiceErrorType err
;
1661 if (effective_uuid
) {
1662 uuid_copy(me
->effective_uuid
, effective_uuid
);
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
);
1669 me
->need_auth
= true;
1670 err
= kDNSServiceErr_NoError
;
1676 //======================================================================================================================
1678 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
1679 static const uint8_t *
1680 _dx_gai_request_get_resolver_uuid(const dx_gai_request_t me
)
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);
1691 //======================================================================================================================
1693 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
1695 _dx_gai_request_is_for_in_app_browser(const dx_gai_request_t me
)
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)) {
1706 //======================================================================================================================
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
)
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
));
1722 delegator_str
[0] = '\0';
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
);
1734 //======================================================================================================================
1737 _dx_gai_request_log_stop(const dx_gai_request_t me
)
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
);
1746 //======================================================================================================================
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
)
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
));
1760 //======================================================================================================================
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
)
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
));
1774 //======================================================================================================================
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
)
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";
1785 const char * const dnssec_str
= "insecure";
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
));
1794 //======================================================================================================================
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
)
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
));
1808 //======================================================================================================================
1811 _dx_gai_request_log_error(const dx_gai_request_t me
, const DNSServiceErrorType error
)
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
);
1819 //======================================================================================================================
1821 static DNSServiceErrorType
1822 _dx_gai_request_activate_internal(const dx_gai_request_t me
)
1824 char *svcb_memory
= NULL
;
1826 // Get standard parameters.
1828 DNSServiceErrorType err
;
1829 const DNSServiceFlags flags
= dnssd_xpc_parameters_get_flags(me
->params
, &valid
);
1830 require_action_quiet(valid
, exit
, err
= kDNSServiceErr_BadParam
);
1832 const uint32_t if_index
= dnssd_xpc_parameters_get_interface_index(me
->params
, &valid
);
1833 require_action_quiet(valid
, exit
, err
= kDNSServiceErr_BadParam
);
1835 const uint32_t protocols
= dnssd_xpc_parameters_get_protocols(me
->params
, &valid
);
1836 require_action_quiet(valid
, exit
, err
= kDNSServiceErr_BadParam
);
1838 const dx_session_t session
= me
->base
.session
;
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
);
1849 _dx_gai_request_log_start(me
, flags
, if_index
, protocols
, delegator_pid
, delegator_uuid
);
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
;
1859 effective_uuid
= NULL
;
1860 effective_pid
= (delegator_pid
!= 0) ? delegator_pid
: session
->client_pid
;
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
);
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
;
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
;
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
);
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
;
1906 query_params
.flags
= flags
;
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
;
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
;
1921 query_params_ptr
= &query_params
;
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
);
1927 err
= _dx_gai_request_start_client_requests(me
, &gai_params
, query_params_ptr
, NULL
, NULL
);
1929 require_noerr_quiet(err
, exit
);
1932 ForgetMem(&svcb_memory
);
1936 //======================================================================================================================
1937 // MARK: - Helper Functions
1940 struct necp_client_resolver_answer hdr
;
1941 uint8_t hostname
[MAX_ESCAPED_DOMAIN_NAME
];
1944 check_compile_time(sizeof_field(dx_necp_answer_t
, hdr
) == offsetof(dx_necp_answer_t
, hostname
));
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
])
1951 require_quiet((type
== kDNSServiceType_A
) || (type
== kDNSServiceType_AAAA
), exit
);
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
);
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);
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);
1968 const size_t hostname_len
= strlen(hostname
);
1969 require_quiet(hostname_len
<= sizeof(answer
.hostname
), exit
);
1971 hdr
->hostname_length
= (uint32_t)hostname_len
;
1972 memcpy(answer
.hostname
, hostname
, hdr
->hostname_length
);
1974 static int necp_fd
= -1;
1976 necp_fd
= necp_open(0);
1978 require_quiet(necp_fd
>= 0, exit
);
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
);
1990 //======================================================================================================================
1993 _dx_pid_to_name(const pid_t pid
, char out_name
[STATIC_PARAM MAXCOMLEN
])
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
);
2007 //======================================================================================================================
2010 _dx_kqueue_locked(const char * const description
, const dx_block_t block
)
2014 KQueueUnlock(description
);