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
);