2 * Copyright (c) 2019 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 "mDNSMacOSX.h"
23 #include <CoreUtils/CommonServices.h>
24 #include <CoreUtils/DebugServices.h>
27 #include <sys/proc_info.h>
28 #include <xpc/private.h>
31 //======================================================================================================================
32 #pragma mark - Kind Declarations
35 #define DX_STRUCT(NAME) struct dx_ ## NAME ## _s
36 #define DX_TYPE(NAME) dx_ ## NAME ## _t
37 #define DX_KIND_DECLARE(NAME) typedef DX_STRUCT(NAME) * DX_TYPE(NAME)
39 #define DX_KIND_DECLARE_FULL(NAME) \
40 DX_KIND_DECLARE(NAME); \
43 _dx_ ## NAME ## _invalidate(DX_TYPE(NAME) object); \
46 _dx_ ## NAME ## _finalize(DX_TYPE(NAME) object); \
48 static DX_TYPE(NAME) \
49 _dx_ ## NAME ## _alloc(void)
51 // Note: The last check checks if the base's type is equal to that of the superkind. If it's not, then the pointer
52 // comparison used as the argument to sizeof will cause a "comparison of distinct pointer types" warning, so long as
53 // the warning hasn't been disabled.
55 #define DX_BASE_CHECK(NAME, SUPER) \
56 check_compile_time(offsetof(DX_STRUCT(NAME), base) == 0); \
57 check_compile_time(sizeof_field(DX_STRUCT(NAME), base) == sizeof(DX_STRUCT(SUPER))); \
58 extern int _dx_base_type_check[sizeof(&(((DX_TYPE(NAME))0)->base) == ((DX_TYPE(SUPER))0))]
60 #define DX_KIND_DEFINE(NAME, SUPER) \
61 static const struct dx_kind_s _dx_ ## NAME ## _kind = { \
62 &_dx_ ## SUPER ##_kind, \
63 _dx_ ## NAME ## _invalidate, \
64 _dx_ ## NAME ## _finalize, \
67 static DX_TYPE(NAME) \
68 _dx_ ## NAME ## _alloc(void) \
70 const DX_TYPE(NAME) obj = (DX_TYPE(NAME))calloc(1, sizeof(*obj)); \
71 require_quiet(obj, exit); \
73 const dx_base_t base = (dx_base_t)obj; \
74 base->ref_count = 1; \
75 base->kind = &_dx_ ## NAME ## _kind; \
80 DX_BASE_CHECK(NAME, SUPER)
82 DX_KIND_DECLARE(base
);
83 DX_KIND_DECLARE(request
);
84 DX_KIND_DECLARE_FULL(session
);
85 DX_KIND_DECLARE_FULL(getaddrinfo_request
);
91 dx_getaddrinfo_request_t getaddrinfo_request
;
92 } dx_any_t
__attribute__((__transparent_union__
));
94 typedef void (*dx_invalidate_f
)(dx_any_t object
);
95 typedef void (*dx_finalize_f
)(dx_any_t object
);
97 typedef const struct dx_kind_s
* dx_kind_t
;
99 dx_kind_t superkind
; // This kind's superkind. All kinds have a superkind, except the base kind.
100 dx_invalidate_f invalidate
; // Stops an object's outstanding operations, if any.
101 dx_finalize_f finalize
; // Releases object's resources right before the object is freed.
105 //======================================================================================================================
106 #pragma mark - Base Kind Definition
110 dx_kind_t kind
; // The object's kind.
111 int32_t ref_count
; // Reference count.
114 static const struct dx_kind_s _dx_base_kind
= {
115 NULL
, // No superkind.
116 NULL
, // No invalidate method.
117 NULL
, // No finalize method.
121 //======================================================================================================================
122 #pragma mark - Request Kind Definition
125 struct dx_request_s
{
126 struct dx_base_s base
; // Object base.
127 dx_request_t next
; // Next request in list.
128 xpc_object_t result_array
; // Array of pending results.
129 uint64_t command_id
; // ID to distinquish multiple commands during a session.
130 uint32_t request_id
; // Request ID, used for logging purposes.
131 DNSServiceErrorType error
; // Pending error.
132 bool sent_error
; // True if the pending error has been sent to client.
136 _dx_request_finalize(dx_any_t request
);
138 static const struct dx_kind_s _dx_request_kind
= {
140 NULL
, // No invalidate method.
141 _dx_request_finalize
,
143 DX_BASE_CHECK(request
, base
);
146 //======================================================================================================================
147 #pragma mark - Session Kind Definition
150 struct dx_session_s
{
151 struct dx_base_s base
; // Object base;
152 dx_session_t next
; // Next session in list.
153 dx_request_t request_list
; // List of outstanding requests.
154 xpc_connection_t connection
; // Underlying XPC connection.
155 bool has_delegate_entitlement
; // True if the client is entitled to be a delegate.
158 DX_KIND_DEFINE(session
, base
);
161 //======================================================================================================================
162 #pragma mark - GetAddrInfo Request Kind Definition
165 struct dx_getaddrinfo_request_s
{
166 struct dx_request_s base
; // Request object base.
167 GetAddrInfoClientRequest gai
; // Underlying GetAddrInfoClientRequest.
168 xpc_object_t hostname
; // Hostname to be resolved for getaddrinfo requests.
169 uuid_t client_uuid
; // Client's UUID for authenticating results.
170 bool need_auth
; // True if results need to be authenticated.
171 bool active
; // True if the GetAddrInfoClientRequest is currently active.
174 DX_KIND_DEFINE(getaddrinfo_request
, request
);
177 //======================================================================================================================
178 #pragma mark - Local Prototypes
181 static dispatch_queue_t
182 _dx_server_queue(void);
185 _dx_server_register_session(dx_session_t session
);
188 _dx_server_deregister_session(dx_session_t session
);
191 _dx_retain(dx_any_t object
);
194 _dx_release(dx_any_t object
);
195 #define _dx_release_null_safe(X) do { if (X) { _dx_release(X); } } while (0)
198 _dx_invalidate(dx_any_t object
);
201 _dx_session_create(xpc_connection_t connection
);
204 _dx_session_activate(dx_session_t me
);
206 static DNSServiceErrorType
207 _dx_session_handle_getaddrinfo_command(dx_session_t session
, xpc_object_t msg
);
209 static DNSServiceErrorType
210 _dx_session_handle_stop_command(dx_session_t session
, xpc_object_t msg
);
213 _dx_session_send_results(dx_session_t session
);
215 static dx_getaddrinfo_request_t
216 _dx_getaddrinfo_request_create(uint64_t command_id
, uint32_t request_id
);
218 static DNSServiceErrorType
219 _dx_getaddrinfo_request_set_hostname(dx_getaddrinfo_request_t request
, xpc_object_t hostname
);
222 _dx_getaddrinfo_request_set_need_authenticaed_results(dx_getaddrinfo_request_t request
, bool need
,
223 const uuid_t client_uuid
);
225 static DNSServiceErrorType
226 _dx_getaddrinfo_request_activate(dx_getaddrinfo_request_t request
, uint32_t interface_index
, DNSServiceFlags flags
,
227 DNSServiceProtocol protocols
, pid_t pid
, const uuid_t uuid
, uid_t uid
);
230 _dx_getaddrinfo_request_result_handler(mDNS
*m
, DNSQuestion
*question
, const ResourceRecord
*answer
,
231 QC_result qc_result
, DNSServiceErrorType error
, void *context
);
234 //======================================================================================================================
235 #pragma mark - Server Functions
239 _dx_server_handle_new_connection(xpc_connection_t connection
);
242 dnssd_server_init(void)
244 static xpc_connection_t listener
= NULL
;
246 listener
= xpc_connection_create_mach_service(DNSSD_MACH_SERVICE_NAME
, _dx_server_queue(),
247 XPC_CONNECTION_MACH_SERVICE_LISTENER
);
248 xpc_connection_set_event_handler(listener
,
249 ^(xpc_object_t event
)
251 if (xpc_get_type(event
) == XPC_TYPE_CONNECTION
) {
252 _dx_server_handle_new_connection((xpc_connection_t
)event
);
255 xpc_connection_activate(listener
);
259 _dx_server_handle_new_connection(xpc_connection_t connection
)
261 const dx_session_t session
= _dx_session_create(connection
);
263 _dx_session_activate(session
);
264 _dx_server_register_session(session
);
265 _dx_release(session
);
267 xpc_connection_cancel(connection
);
272 //======================================================================================================================
274 static dx_session_t g_session_list
= NULL
;
277 dnssd_server_idle(void)
279 for (dx_session_t session
= g_session_list
; session
; session
= session
->next
) {
280 _dx_session_send_results(session
);
284 //======================================================================================================================
286 static dispatch_queue_t
287 _dx_server_queue(void)
289 static dispatch_once_t once
= 0;
290 static dispatch_queue_t queue
= NULL
;
294 const dispatch_queue_attr_t attr
= dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL
,
295 QOS_CLASS_UTILITY
, 0);
296 queue
= dispatch_queue_create("com.apple.dnssd.server", attr
);
301 //======================================================================================================================
304 _dx_server_register_session(dx_session_t session
)
306 session
->next
= g_session_list
;
307 g_session_list
= session
;
311 //======================================================================================================================
314 _dx_server_deregister_session(dx_session_t session
)
317 for (ptr
= &g_session_list
; *ptr
; ptr
= &(*ptr
)->next
) {
318 if (*ptr
== session
) {
323 *ptr
= session
->next
;
324 session
->next
= NULL
;
325 _dx_release(session
);
330 //======================================================================================================================
331 #pragma mark - Base Methods
335 _dx_retain(dx_any_t object
)
337 ++object
.base
->ref_count
;
340 //======================================================================================================================
343 _dx_release(dx_any_t object
)
345 if (--object
.base
->ref_count
== 0) {
346 for (dx_kind_t kind
= object
.base
->kind
; kind
; kind
= kind
->superkind
) {
347 if (kind
->finalize
) {
348 kind
->finalize(object
);
355 //======================================================================================================================
358 _dx_invalidate(dx_any_t object
)
360 for (dx_kind_t kind
= object
.base
->kind
; kind
; kind
= kind
->superkind
) {
361 if (kind
->invalidate
) {
362 kind
->invalidate(object
);
369 //======================================================================================================================
370 #pragma mark - Session Methods
374 _dx_session_create(xpc_connection_t connection
)
376 const dx_session_t obj
= _dx_session_alloc();
377 require_quiet(obj
, exit
);
379 obj
->connection
= connection
;
380 xpc_retain(obj
->connection
);
386 //======================================================================================================================
389 _dx_session_handle_message(dx_session_t session
, xpc_object_t msg
);
391 #define DNSSD_DELEGATE_ENTITLEMENT "com.apple.private.network.socket-delegate"
394 _dx_session_activate(dx_session_t me
)
396 const xpc_object_t value
= xpc_connection_copy_entitlement_value(me
->connection
, DNSSD_DELEGATE_ENTITLEMENT
);
398 if (value
== XPC_BOOL_TRUE
) {
399 me
->has_delegate_entitlement
= true;
404 xpc_connection_set_target_queue(me
->connection
, _dx_server_queue());
405 xpc_connection_set_event_handler(me
->connection
,
406 ^(xpc_object_t event
) {
407 const xpc_type_t type
= xpc_get_type(event
);
408 if (type
== XPC_TYPE_DICTIONARY
) {
410 _dx_session_handle_message(me
, event
);
411 KQueueUnlock("_dx_session_handle_message");
412 } else if (event
== XPC_ERROR_CONNECTION_INVALID
) {
414 _dx_server_deregister_session(me
);
415 KQueueUnlock("_dx_server_deregister_session");
416 _dx_session_invalidate(me
);
419 xpc_connection_cancel(me
->connection
);
422 xpc_connection_activate(me
->connection
);
426 _dx_session_handle_message(dx_session_t me
, xpc_object_t msg
)
428 DNSServiceErrorType error
;
429 const char * const command
= dnssd_xpc_message_get_command(msg
);
430 require_action_quiet(command
, exit
, error
= kDNSServiceErr_BadParam
);
432 if (strcmp(command
, DNSSD_COMMAND_GETADDRINFO
) == 0) {
433 error
= _dx_session_handle_getaddrinfo_command(me
, msg
);
434 } else if (strcmp(command
, DNSSD_COMMAND_STOP
) == 0) {
435 error
= _dx_session_handle_stop_command(me
, msg
);
437 error
= kDNSServiceErr_BadParam
;
442 const xpc_object_t reply
= xpc_dictionary_create_reply(msg
);
444 dnssd_xpc_message_set_error(reply
, error
);
445 xpc_connection_send_message(me
->connection
, reply
);
448 xpc_connection_cancel(me
->connection
);
453 //======================================================================================================================
456 _dx_session_invalidate(dx_session_t me
)
458 xpc_connection_forget(&me
->connection
);
460 while ((req
= me
->request_list
) != NULL
)
462 me
->request_list
= req
->next
;
468 //======================================================================================================================
471 _dx_session_finalize(dx_session_t me
)
476 //======================================================================================================================
479 _dx_get_getaddrinfo_params(xpc_object_t msg
, uint64_t *out_command_id
, xpc_object_t
*out_hostname
,
480 uint32_t *out_interface_index
, DNSServiceFlags
*out_flags
, DNSServiceProtocol
*out_protocols
,
481 pid_t
*out_delegate_pid
, const uint8_t **out_delegate_uuid
, bool *out_need_auth_tags
);
483 extern mDNS mDNSStorage
;
484 #define g_mdns mDNSStorage
486 static DNSServiceErrorType
487 _dx_session_handle_getaddrinfo_command(dx_session_t me
, xpc_object_t msg
)
489 dx_getaddrinfo_request_t req
= NULL
;
490 DNSServiceErrorType error
;
492 xpc_object_t hostname
;
493 uint32_t interface_index
;
494 DNSServiceFlags flags
;
495 DNSServiceProtocol protocols
;
497 const uint8_t * uuid
;
500 const bool valid
= _dx_get_getaddrinfo_params(msg
, &command_id
, &hostname
, &interface_index
, &flags
, &protocols
,
501 &pid
, &uuid
, &need_auth
);
502 require_action_quiet(valid
, exit
, error
= kDNSServiceErr_BadParam
);
504 if (uuid
|| (pid
!= 0)) {
505 require_action_quiet(me
->has_delegate_entitlement
, exit
, error
= kDNSServiceErr_NoAuth
);
507 pid
= xpc_connection_get_pid(me
->connection
);
510 req
= _dx_getaddrinfo_request_create(command_id
, g_mdns
.next_request_id
++);
511 require_action_quiet(req
, exit
, error
= kDNSServiceErr_NoMemory
);
513 error
= _dx_getaddrinfo_request_set_hostname(req
, hostname
);
514 require_noerr_quiet(error
, exit
);
517 struct proc_uniqidentifierinfo info
;
518 const int n
= proc_pidinfo(pid
, PROC_PIDUNIQIDENTIFIERINFO
, 1, &info
, sizeof(info
));
519 if (n
== (int)sizeof(info
)) {
520 _dx_getaddrinfo_request_set_need_authenticaed_results(req
, true, info
.p_uuid
);
524 const uid_t euid
= xpc_connection_get_euid(me
->connection
);
525 error
= _dx_getaddrinfo_request_activate(req
, interface_index
, flags
, protocols
, pid
, uuid
, euid
);
526 require_noerr_quiet(error
, exit
);
528 req
->base
.next
= me
->request_list
;
529 me
->request_list
= (dx_request_t
)req
;
533 _dx_release_null_safe(req
);
534 static_analyzer_malloc_freed(req
);
539 _dx_get_getaddrinfo_params(xpc_object_t msg
, uint64_t *out_command_id
, xpc_object_t
*out_hostname
,
540 uint32_t *out_interface_index
, DNSServiceFlags
*out_flags
, DNSServiceProtocol
*out_protocols
,
541 pid_t
*out_delegate_pid
, const uint8_t **out_delegate_uuid
, bool *out_need_auth_tags
)
543 bool params_are_valid
= false;
545 const uint64_t command_id
= dnssd_xpc_message_get_id(msg
, &valid
);
546 require_quiet(valid
, exit
);
548 const xpc_object_t params
= dnssd_xpc_message_get_parameters(msg
);
549 require_quiet(params
, exit
);
551 xpc_object_t hostname
= dnssd_xpc_parameters_get_hostname_object(params
);
552 require_quiet(hostname
, exit
);
554 const uint32_t interface_index
= dnssd_xpc_parameters_get_interface_index(params
, &valid
);
555 require_quiet(valid
, exit
);
557 const DNSServiceFlags flags
= dnssd_xpc_parameters_get_flags(params
, &valid
);
558 require_quiet(valid
, exit
);
560 const uint32_t protocols
= dnssd_xpc_parameters_get_protocols(params
, &valid
);
561 require_quiet(valid
, exit
);
564 const uint8_t * const uuid
= dnssd_xpc_parameters_get_delegate_uuid(params
);
568 pid
= dnssd_xpc_parameters_get_delegate_pid(params
, NULL
);
571 *out_command_id
= command_id
;
572 *out_hostname
= hostname
;
573 *out_interface_index
= interface_index
;
575 *out_protocols
= protocols
;
576 *out_delegate_pid
= pid
;
577 *out_delegate_uuid
= uuid
;
578 *out_need_auth_tags
= dnssd_xpc_parameters_get_need_authentication_tags(params
);
579 params_are_valid
= true;
582 return params_are_valid
;
585 //======================================================================================================================
587 static DNSServiceErrorType
588 _dx_session_handle_stop_command(dx_session_t me
, xpc_object_t msg
)
591 DNSServiceErrorType error
;
592 const uint64_t command_id
= dnssd_xpc_message_get_id(msg
, &valid
);
593 require_action_quiet(valid
, exit
, error
= kDNSServiceErr_BadParam
);
597 for (ptr
= &me
->request_list
; (req
= *ptr
) != NULL
; ptr
= &req
->next
) {
598 if (req
->command_id
== command_id
) {
602 require_action_quiet(req
, exit
, error
= kDNSServiceErr_BadReference
);
609 error
= kDNSServiceErr_NoError
;
615 //======================================================================================================================
618 _dx_session_send_results(dx_session_t me
)
620 bool success
= false;
621 for (dx_request_t req
= me
->request_list
; req
; req
= req
->next
) {
622 if (req
->result_array
&& (xpc_array_get_count(req
->result_array
) > 0)) {
623 const xpc_object_t msg
= xpc_dictionary_create(NULL
, NULL
, 0);
624 require_quiet(msg
, exit
);
626 dnssd_xpc_message_set_id(msg
, req
->command_id
);
627 dnssd_xpc_message_set_error(msg
, kDNSServiceErr_NoError
);
628 dnssd_xpc_message_set_results(msg
, req
->result_array
);
629 xpc_connection_send_message(me
->connection
, msg
);
632 xpc_release(req
->result_array
);
633 req
->result_array
= xpc_array_create(NULL
, 0);
634 require_quiet(req
->result_array
, exit
);
636 if (req
->error
&& !req
->sent_error
) {
637 const xpc_object_t msg
= xpc_dictionary_create(NULL
, NULL
, 0);
638 require_quiet(msg
, exit
);
640 dnssd_xpc_message_set_id(msg
, req
->command_id
);
641 dnssd_xpc_message_set_error(msg
, req
->error
);
642 xpc_connection_send_message(me
->connection
, msg
);
644 req
->sent_error
= true;
650 if (unlikely(!success
)) {
651 xpc_connection_cancel(me
->connection
);
656 //======================================================================================================================
657 #pragma mark - Request Methods
661 _dx_request_finalize(dx_request_t me
)
663 xpc_forget(&me
->result_array
);
667 //======================================================================================================================
668 #pragma mark - GetAddrInfo Request Methods
671 static dx_getaddrinfo_request_t
672 _dx_getaddrinfo_request_create(uint64_t command_id
, uint32_t request_id
)
674 dx_getaddrinfo_request_t req
= NULL
;
675 dx_getaddrinfo_request_t obj
= _dx_getaddrinfo_request_alloc();
676 require_quiet(obj
, exit
);
678 obj
->base
.command_id
= command_id
;
679 obj
->base
.request_id
= request_id
;
680 obj
->base
.result_array
= xpc_array_create(NULL
, 0);
681 require_quiet(obj
->base
.result_array
, exit
);
687 _dx_release_null_safe(obj
);
691 //======================================================================================================================
693 static DNSServiceErrorType
694 _dx_getaddrinfo_request_set_hostname(dx_getaddrinfo_request_t me
, xpc_object_t hostname
)
696 DNSServiceErrorType err
;
697 require_action_quiet(xpc_string_get_length(hostname
) <= MAX_ESCAPED_DOMAIN_NAME
, exit
,
698 err
= kDNSServiceErr_BadParam
);
700 xpc_release_null_safe(me
->hostname
);
701 me
->hostname
= xpc_copy(hostname
);
702 require_action_quiet(me
->hostname
, exit
, err
= kDNSServiceErr_NoMemory
);
704 err
= kDNSServiceErr_NoError
;
710 //======================================================================================================================
713 _dx_getaddrinfo_request_set_need_authenticaed_results(dx_getaddrinfo_request_t me
, bool need
, const uuid_t client_uuid
)
716 uuid_copy(me
->client_uuid
, client_uuid
);
717 me
->need_auth
= true;
719 uuid_clear(me
->client_uuid
);
720 me
->need_auth
= false;
724 //======================================================================================================================
726 static DNSServiceErrorType
727 _dx_getaddrinfo_request_activate(dx_getaddrinfo_request_t me
, uint32_t interface_index
, DNSServiceFlags flags
,
728 DNSServiceProtocol protocols
, pid_t pid
, const uuid_t uuid
, uid_t uid
)
730 DNSServiceErrorType err
;
731 const char * const hostname_str
= xpc_string_get_string_ptr(me
->hostname
);
732 require_action_quiet(hostname_str
, exit
, err
= kDNSServiceErr_Unknown
);
734 err
= GetAddrInfoClientRequestStart(&me
->gai
, me
->base
.request_id
, hostname_str
, interface_index
, flags
,
735 protocols
, pid
, uuid
, uid
, _dx_getaddrinfo_request_result_handler
, me
);
736 require_noerr_quiet(err
, exit
);
745 //======================================================================================================================
748 _dx_getaddrinfo_request_invalidate(dx_getaddrinfo_request_t me
)
751 GetAddrInfoClientRequestStop(&me
->gai
);
757 //======================================================================================================================
760 _dx_getaddrinfo_request_finalize(dx_getaddrinfo_request_t me
)
762 xpc_forget(&me
->hostname
);
765 //======================================================================================================================
767 #if defined(NECP_CLIENT_ACTION_SIGN)
768 #define DNSSD_AUTHENTICATION_TAG_SIZE 32 // XXX: Defined as a workaround until NECP header defines this length.
771 _dx_authenticate_answer(uuid_t client_id
, xpc_object_t hostname
, int record_type
, const void *record_data
,
772 uint8_t out_auth_tag
[STATIC_PARAM DNSSD_AUTHENTICATION_TAG_SIZE
]);
776 _dx_getaddrinfo_request_result_handler(mDNS
*m
, DNSQuestion
*question
, const ResourceRecord
*answer
,
777 QC_result qc_result
, DNSServiceErrorType error
, void *context
)
781 const dx_getaddrinfo_request_t me
= (dx_getaddrinfo_request_t
)context
;
782 if (error
&& (error
!= kDNSServiceErr_NoSuchRecord
)) {
783 if (!me
->base
.error
) {
784 me
->base
.error
= error
;
788 require_quiet((answer
->rrtype
== kDNSServiceType_A
) || (answer
->rrtype
== kDNSServiceType_AAAA
), exit
);
790 const void * rdata_ptr
;
793 if (answer
->rrtype
== kDNSServiceType_A
) {
794 rdata_ptr
= answer
->rdata
->u
.ipv4
.b
;
797 rdata_ptr
= answer
->rdata
->u
.ipv6
.b
;
805 DNSServiceFlags flags
= 0;
806 if (qc_result
!= QC_rmv
) {
807 flags
|= kDNSServiceFlagsAdd
;
809 if (answer
->mortality
== Mortality_Ghost
) {
810 flags
|= kDNSServiceFlagsExpiredAnswer
;
812 if (!question
->InitialCacheMiss
) {
813 flags
|= kDNSServiceFlagAnsweredFromCache
;
816 const uint32_t interface_index
= mDNSPlatformInterfaceIndexfromInterfaceID(m
, answer
->InterfaceID
, mDNStrue
);
817 const xpc_object_t result
= xpc_dictionary_create(NULL
, NULL
, 0);
818 if (likely(result
)) {
819 char name_str
[MAX_ESCAPED_DOMAIN_NAME
];
820 ConvertDomainNameToCString(answer
->name
, name_str
);
822 dnssd_xpc_result_set_error(result
, error
);
823 dnssd_xpc_result_set_flags(result
, flags
);
824 dnssd_xpc_result_set_interface_index(result
, interface_index
);
825 dnssd_xpc_result_set_record_name(result
, name_str
);
826 dnssd_xpc_result_set_record_type(result
, answer
->rrtype
);
827 dnssd_xpc_result_set_record_class(result
, answer
->rrclass
);
828 dnssd_xpc_result_set_record_data(result
, rdata_ptr
, rdata_len
);
830 #if defined(NECP_CLIENT_ACTION_SIGN)
831 if (me
->need_auth
&& !error
&& (flags
& kDNSServiceFlagsAdd
)) {
832 uint8_t auth_tag
[DNSSD_AUTHENTICATION_TAG_SIZE
];
833 const bool success
= _dx_authenticate_answer(me
->client_uuid
, me
->hostname
, answer
->rrtype
, rdata_ptr
,
836 dnssd_xpc_result_set_authentication_tag(result
, auth_tag
, sizeof(auth_tag
));
840 xpc_array_append_value(me
->base
.result_array
, result
);
843 me
->base
.error
= kDNSServiceErr_NoMemory
;
850 #if defined(NECP_CLIENT_ACTION_SIGN)
852 struct necp_client_resolver_answer hdr
;
853 uint8_t hostname
[MAX_ESCAPED_DOMAIN_NAME
];
856 check_compile_time(offsetof(dx_necp_answer_t
, hdr
) == 0);
857 check_compile_time(endof_field(struct necp_client_resolver_answer
, hostname_length
) == offsetof(dx_necp_answer_t
, hostname
));
860 _dx_authenticate_answer(uuid_t client_id
, xpc_object_t hostname
, int record_type
, const void *record_data
,
861 uint8_t out_auth_tag
[STATIC_PARAM DNSSD_AUTHENTICATION_TAG_SIZE
])
863 static int necp_fd
= -1;
865 bool success
= false;
867 necp_fd
= necp_open(0);
869 require_quiet(necp_fd
>= 0, exit
);
871 dx_necp_answer_t answer
;
872 memset(&answer
, 0, sizeof(answer
));
874 struct necp_client_resolver_answer
* const hdr
= &answer
.hdr
;
875 uuid_copy(hdr
->client_id
, client_id
);
877 hdr
->sign_type
= NECP_CLIENT_SIGN_TYPE_RESOLVER_ANSWER
;
879 switch (record_type
) {
880 case kDNSServiceType_A
:
881 hdr
->address_answer
.sa
.sa_family
= AF_INET
;
882 hdr
->address_answer
.sa
.sa_len
= sizeof(struct sockaddr_in
);
883 memcpy(&hdr
->address_answer
.sin
.sin_addr
.s_addr
, record_data
, 4);
886 case kDNSServiceType_AAAA
:
887 hdr
->address_answer
.sa
.sa_family
= AF_INET6
;
888 hdr
->address_answer
.sa
.sa_len
= sizeof(struct sockaddr_in6
);
889 memcpy(hdr
->address_answer
.sin6
.sin6_addr
.s6_addr
, record_data
, 16);
895 const size_t hostname_len
= xpc_string_get_length(hostname
);
896 require_quiet(hostname_len
<= sizeof(answer
.hostname
), exit
);
898 hdr
->hostname_length
= (uint32_t)hostname_len
;
899 memcpy(answer
.hostname
, xpc_string_get_string_ptr(hostname
), hdr
->hostname_length
);
901 const int necp_err
= necp_client_action(necp_fd
, NECP_CLIENT_ACTION_SIGN
, (void *)&answer
,
902 sizeof(answer
.hdr
) + hdr
->hostname_length
, out_auth_tag
, DNSSD_AUTHENTICATION_TAG_SIZE
);
903 require_noerr_quiet(necp_err
, exit
);
910 #endif // defined(NECP_CLIENT_ACTION_SIGN)