2 * Copyright (c) 2012, 2013, 2015, 2016, 2018, 2019 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <TargetConditionals.h>
25 #include <dispatch/dispatch.h>
26 #include <dispatch/private.h>
29 #include <vproc_priv.h>
32 #include "libSystemConfiguration_client.h"
33 #include "libSystemConfiguration_internal.h"
37 #pragma mark libSC fork handlers
40 static boolean_t _available
= TRUE
;
42 // These functions are registered with libSystem to
43 // handle pthread_atfork callbacks.
46 _libSC_info_fork_prepare()
52 _libSC_info_fork_parent()
58 _libSC_info_fork_child()
60 if (_dispatch_is_fork_of_multithreaded_parent()) {
69 #pragma mark Support functions
73 log_xpc_object(const char *msg
, xpc_object_t obj
)
77 desc
= xpc_copy_description(obj
);
78 os_log(OS_LOG_DEFAULT
, "%s = %s", msg
, desc
);
85 libSC_info_available()
92 libSC_info_client_dealloc(libSC_info_client_t
*client
)
94 free(client
->service_description
);
95 free(client
->service_name
);
102 libSC_info_client_t
*
103 libSC_info_client_create(dispatch_queue_t q
,
104 const char *service_name
,
105 const char *service_description
)
108 libSC_info_client_t
*client
;
109 #if !TARGET_OS_SIMULATOR || TARGET_OS_MACCATALYST
110 const uint64_t flags
= XPC_CONNECTION_MACH_SERVICE_PRIVILEGED
;
111 #else // !TARGET_OS_SIMULATOR || TARGET_OS_MACCATALYST
112 const uint64_t flags
= 0;
113 #endif // !TARGET_OS_SIMULATOR || TARGET_OS_MACCATALYST
119 client
= malloc(sizeof(libSC_info_client_t
));
120 client
->active
= TRUE
;
121 client
->service_description
= strdup(service_description
);
122 client
->service_name
= strdup(service_name
);
124 c
= xpc_connection_create_mach_service(service_name
, q
, flags
);
126 xpc_connection_set_event_handler(c
, ^(xpc_object_t xobj
) {
129 type
= xpc_get_type(xobj
);
130 if (type
== XPC_TYPE_DICTIONARY
) {
131 os_log(OS_LOG_DEFAULT
, "%s: unexpected message", client
->service_name
);
132 log_xpc_object(" dict = ", xobj
);
133 } else if (type
== XPC_TYPE_ERROR
) {
134 if (xobj
== XPC_ERROR_CONNECTION_INVALID
) {
135 os_log(OS_LOG_DEFAULT
, "%s: server not available", client
->service_name
);
136 client
->active
= FALSE
;
137 } else if (xobj
== XPC_ERROR_CONNECTION_INTERRUPTED
) {
138 os_log_debug(OS_LOG_DEFAULT
, "%s: server failed", client
->service_name
);
142 desc
= xpc_dictionary_get_string(xobj
, XPC_ERROR_KEY_DESCRIPTION
);
143 os_log_debug(OS_LOG_DEFAULT
,
144 "%s: connection error: %d : %s",
145 client
->service_name
,
146 xpc_connection_get_pid(c
),
150 os_log(OS_LOG_DEFAULT
,
151 "%s: unknown event type : %p",
152 client
->service_name
,
157 client
->connection
= c
;
159 xpc_connection_set_context(c
, client
);
160 xpc_connection_set_finalizer_f(c
, (xpc_finalizer_t
)libSC_info_client_dealloc
);
162 xpc_connection_resume(c
);
170 libSC_info_client_release(libSC_info_client_t
*client
)
172 xpc_release(client
->connection
);
179 libSC_send_message_with_reply_sync(libSC_info_client_t
*client
,
180 xpc_object_t message
)
185 // send request to the DNS configuration server
186 reply
= xpc_connection_send_message_with_reply_sync(client
->connection
, message
);
190 type
= xpc_get_type(reply
);
191 if (type
== XPC_TYPE_DICTIONARY
) {
196 if ((type
== XPC_TYPE_ERROR
) && (reply
== XPC_ERROR_CONNECTION_INTERRUPTED
)) {
197 os_log_debug(OS_LOG_DEFAULT
,
198 "%s server failure, retrying",
199 client
->service_description
);
205 if ((type
== XPC_TYPE_ERROR
) && (reply
== XPC_ERROR_CONNECTION_INVALID
)) {
206 os_log(OS_LOG_DEFAULT
,
207 "%s server not available",
208 client
->service_description
);
209 client
->active
= FALSE
;
211 os_log(OS_LOG_DEFAULT
,
212 "%s xpc_connection_send_message_with_reply_sync() with unexpected reply",
213 client
->service_description
);
214 log_xpc_object(" reply", reply
);