2 * Copyright (c) 2012, 2013, 2015, 2016, 2018 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 <os/availability.h>
25 #include <TargetConditionals.h>
26 #include <dispatch/dispatch.h>
27 #include <dispatch/private.h>
30 #include <vproc_priv.h>
33 #include "libSystemConfiguration_client.h"
34 #include "libSystemConfiguration_internal.h"
38 #pragma mark libSC fork handlers
41 static boolean_t _available
= TRUE
;
43 // These functions are registered with libSystem to
44 // handle pthread_atfork callbacks.
47 _libSC_info_fork_prepare()
53 _libSC_info_fork_parent()
59 _libSC_info_fork_child()
61 if (_dispatch_is_fork_of_multithreaded_parent()) {
70 #pragma mark Support functions
74 log_xpc_object(const char *msg
, xpc_object_t obj
)
78 desc
= xpc_copy_description(obj
);
79 os_log(OS_LOG_DEFAULT
, "%s = %s", msg
, desc
);
86 libSC_info_available()
93 libSC_info_client_dealloc(libSC_info_client_t
*client
)
95 free(client
->service_description
);
96 free(client
->service_name
);
103 libSC_info_client_t
*
104 libSC_info_client_create(dispatch_queue_t q
,
105 const char *service_name
,
106 const char *service_description
)
109 libSC_info_client_t
*client
;
110 #if !TARGET_OS_SIMULATOR || TARGET_OS_IOSMAC
111 const uint64_t flags
= XPC_CONNECTION_MACH_SERVICE_PRIVILEGED
;
112 #else // !TARGET_OS_SIMULATOR || TARGET_OS_IOSMAC
113 const uint64_t flags
= 0;
114 #endif // !TARGET_OS_SIMULATOR || TARGET_OS_IOSMAC
120 client
= malloc(sizeof(libSC_info_client_t
));
121 client
->active
= TRUE
;
122 client
->service_description
= strdup(service_description
);
123 client
->service_name
= strdup(service_name
);
125 c
= xpc_connection_create_mach_service(service_name
, q
, flags
);
127 xpc_connection_set_event_handler(c
, ^(xpc_object_t xobj
) {
130 type
= xpc_get_type(xobj
);
131 if (type
== XPC_TYPE_DICTIONARY
) {
132 os_log(OS_LOG_DEFAULT
, "%s: unexpected message", client
->service_name
);
133 log_xpc_object(" dict = ", xobj
);
134 } else if (type
== XPC_TYPE_ERROR
) {
135 if (xobj
== XPC_ERROR_CONNECTION_INVALID
) {
136 os_log(OS_LOG_DEFAULT
, "%s: server not available", client
->service_name
);
137 client
->active
= FALSE
;
138 } else if (xobj
== XPC_ERROR_CONNECTION_INTERRUPTED
) {
139 os_log_debug(OS_LOG_DEFAULT
, "%s: server failed", client
->service_name
);
143 desc
= xpc_dictionary_get_string(xobj
, XPC_ERROR_KEY_DESCRIPTION
);
144 os_log_debug(OS_LOG_DEFAULT
,
145 "%s: connection error: %d : %s",
146 client
->service_name
,
147 xpc_connection_get_pid(c
),
151 os_log(OS_LOG_DEFAULT
,
152 "%s: unknown event type : %p",
153 client
->service_name
,
158 client
->connection
= c
;
160 xpc_connection_set_context(c
, client
);
161 xpc_connection_set_finalizer_f(c
, (xpc_finalizer_t
)libSC_info_client_dealloc
);
163 xpc_connection_resume(c
);
171 libSC_info_client_release(libSC_info_client_t
*client
)
173 xpc_release(client
->connection
);
180 libSC_send_message_with_reply_sync(libSC_info_client_t
*client
,
181 xpc_object_t message
)
186 // send request to the DNS configuration server
187 reply
= xpc_connection_send_message_with_reply_sync(client
->connection
, message
);
191 type
= xpc_get_type(reply
);
192 if (type
== XPC_TYPE_DICTIONARY
) {
197 if ((type
== XPC_TYPE_ERROR
) && (reply
== XPC_ERROR_CONNECTION_INTERRUPTED
)) {
198 os_log_debug(OS_LOG_DEFAULT
,
199 "%s server failure, retrying",
200 client
->service_description
);
206 if ((type
== XPC_TYPE_ERROR
) && (reply
== XPC_ERROR_CONNECTION_INVALID
)) {
207 os_log(OS_LOG_DEFAULT
,
208 "%s server not available",
209 client
->service_description
);
210 client
->active
= FALSE
;
212 os_log(OS_LOG_DEFAULT
,
213 "%s xpc_connection_send_message_with_reply_sync() with unexpected reply",
214 client
->service_description
);
215 log_xpc_object(" reply", reply
);