2 * Copyright (c) 2003-2013 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 #ifndef _SCNETWORKREACHABILITYINTERNAL_H
25 #define _SCNETWORKREACHABILITYINTERNAL_H
27 #include <Availability.h>
28 #include <TargetConditionals.h>
29 #include <sys/cdefs.h>
30 #include <CoreFoundation/CoreFoundation.h>
31 #include <CoreFoundation/CFRuntime.h>
32 #include <SystemConfiguration/SystemConfiguration.h>
33 #include <SystemConfiguration/SCPrivate.h>
34 #include <dispatch/dispatch.h>
38 #include <sys/socket.h>
41 #if ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 50000))
42 #define HAVE_REACHABILITY_SERVER
44 #endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 50000))
46 #if ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000))
47 #define HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL
48 #endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000))
50 #if ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000))
51 #define HAVE_IPSEC_STATUS
52 #define HAVE_VPN_STATUS
53 #endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000))
57 #if ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080/*FIXME*/) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
58 #define USE_DNSSERVICEGETADDRINFO
59 #endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080/*FIXME*/) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
63 #pragma mark SCNetworkReachability
66 #define kSCNetworkReachabilityFlagsFirstResolvePending (1<<31)
70 #define kSCNetworkReachabilityFlagsMask 0x00ffffff // top 8-bits reserved for implementation
81 reachabilityTypeAddress
,
82 reachabilityTypeAddressPair
,
84 } ReachabilityAddressType
;
89 SCNetworkReachabilityFlags flags
;
90 unsigned int if_index
;
91 char if_name
[IFNAMSIZ
];
98 /* base CFType information */
102 pthread_mutex_t lock
;
105 ReachabilityAddressType type
;
107 /* target host name */
110 CFArrayRef resolvedAddresses
; /* CFArray[CFData] */
112 SCNetworkReachabilityFlags resolverFlags
;
114 /* [scoped routing] interface constraints */
115 unsigned int if_index
;
116 char if_name
[IFNAMSIZ
];
118 /* local & remote addresses */
119 struct sockaddr
*localAddress
;
120 struct sockaddr
*remoteAddress
;
122 /* current reachability flags */
124 ReachabilityInfo info
;
125 ReachabilityInfo last_notify
;
127 /* run loop source, callout, context, rl scheduling info */
129 CFRunLoopSourceRef rls
;
130 SCNetworkReachabilityCallBack rlsFunction
;
131 SCNetworkReachabilityContext rlsContext
;
132 CFMutableArrayRef rlList
;
134 dispatch_group_t dispatchGroup
;
135 dispatch_queue_t dispatchQueue
; // SCNetworkReachabilitySetDispatchQueue
137 /* [async] DNS query info */
139 mach_port_t dnsMP
; // != MACH_PORT_NULL (if active)
140 CFMachPortRef dnsPort
; // for CFRunLoop queries
141 CFRunLoopSourceRef dnsRLS
; // for CFRunLoop queries
142 dispatch_source_t dnsSource
; // for dispatch queries
143 struct timeval dnsQueryStart
;
144 struct timeval dnsQueryEnd
;
146 /* [async] processing info */
147 struct timeval last_dns
;
148 struct timeval last_network
;
149 #if !TARGET_OS_IPHONE
150 struct timeval last_power
;
151 #endif // !TARGET_OS_IPHONE
152 struct timeval last_push
;
155 Boolean onDemandBypass
;
156 CFStringRef onDemandName
;
157 CFStringRef onDemandRemoteAddress
;
158 SCNetworkReachabilityRef onDemandServer
;
159 CFStringRef onDemandServiceID
;
165 Boolean dnsActive
:1; // if DNSServiceGetAddrInfo active
167 Boolean dnsHaveError
:1; // error during query
168 Boolean dnsHaveV4
:1; // have IPv4 (A) reply
169 Boolean dnsHaveV6
:1; // have IPv6 (AAAA) reply
170 Boolean dnsHaveTimeout
:1; // no replies (A and/or AAAA)
173 CFArrayRef dnsAddresses
; // CFArray[CFData]
174 Boolean dnsBlocked
; // if DNS query blocked
176 DNSServiceRef dnsMain
;
177 DNSServiceRef dnsTarget
;
179 #ifdef HAVE_REACHABILITY_SERVER
180 /* SCNetworkReachability server "client" info */
181 Boolean serverActive
;
182 Boolean serverBypass
;
183 Boolean serverScheduled
;
184 ReachabilityInfo serverInfo
;
186 /* SCNetworkReachability server "server" info */
187 CFDataRef serverDigest
;
188 dispatch_group_t serverGroup
;
189 Boolean serverInfoValid
;
190 unsigned int serverSyncQueryActive
; // 0 == no [sync] query active, else # waiting on group
191 dispatch_queue_t serverQueue
;
192 unsigned int serverReferences
; // how many [client] targets
193 CFMutableDictionaryRef serverWatchers
; // [client_id/target_id] watchers
195 Boolean useVPNAppLayer
; // if App-Layer VPN, only use client mode
196 #endif // HAVE_REACHABILITY_SERVER
197 Boolean resolverBypass
; // set this flag to bypass resolving the name
204 } SCNetworkReachabilityPrivate
, *SCNetworkReachabilityPrivateRef
;
207 #ifdef HAVE_REACHABILITY_SERVER
209 // ------------------------------------------------------------
212 #pragma mark [XPC] Reachability Server
215 #define REACH_SERVER_VERSION 20110323
217 #if !TARGET_IPHONE_SIMULATOR
218 #define REACH_SERVICE_NAME "com.apple.SystemConfiguration.SCNetworkReachability"
219 #else // !TARGET_IPHONE_SIMULATOR
220 #define REACH_SERVICE_NAME "com.apple.SystemConfiguration.SCNetworkReachability_sim"
221 #endif // !TARGET_IPHONE_SIMULATOR
223 // ------------------------------------------------------------
227 #pragma mark [XPC] Reachability Server (client->server request)
230 #define REACH_CLIENT_PROC_NAME "proc_name" // string
231 #define REACH_CLIENT_TARGET_ID "target_id" // uint64
233 #define REACH_REQUEST "request_op" // int64
236 REACH_REQUEST_CREATE
= 0x0001,
237 REACH_REQUEST_REMOVE
,
238 REACH_REQUEST_SCHEDULE
,
239 REACH_REQUEST_STATUS
,
240 REACH_REQUEST_UNSCHEDULE
,
241 REACH_REQUEST_SNAPSHOT
= 0x0101,
244 #define REACH_TARGET_NAME "name" // string
245 #define REACH_TARGET_IF_INDEX "if_index" // int64
246 #define REACH_TARGET_IF_NAME "if_name" // string
247 #define REACH_TARGET_LOCAL_ADDR "local_address" // data (struct sockaddr)
248 #define REACH_TARGET_REMOTE_ADDR "remote_address" // data (struct sockaddr)
249 #define REACH_TARGET_ONDEMAND_BYPASS "ondemand_bypass" // bool
250 #define REACH_TARGET_RESOLVER_BYPASS "resolver_bypass" // bool
253 #define REACH_REQUEST_REPLY "reply" // int64
254 #define REACH_REQUEST_REPLY_DETAIL "reply_detail" // string
257 REACH_REQUEST_REPLY_OK
= 0x0000,
258 REACH_REQUEST_REPLY_FAILED
,
259 REACH_REQUEST_REPLY_UNKNOWN
,
263 // ------------------------------------------------------------
267 #pragma mark [XPC] Reachability Server (server->client request)
270 #define MESSAGE_NOTIFY "notify_op" // int64
273 MESSAGE_REACHABILITY_STATUS
= 0x1001,
276 #define REACH_STATUS_CYCLE "cycle" // uint64
277 #define REACH_STATUS_FLAGS "flags" // uint64
278 #define REACH_STATUS_IF_INDEX "if_index" // uint64
279 #define REACH_STATUS_IF_NAME "if_name" // data (char if_name[IFNAMSIZ])
280 #define REACH_STATUS_RESOLVED_ADDRESSES "resolved_addresses" // array[data]
281 #define REACH_STATUS_RESOLVED_ERROR "resolved_error" // int64
282 #define REACH_STATUS_SLEEPING "sleeping" // bool
285 // ------------------------------------------------------------
287 #endif // HAVE_REACHABILITY_SERVER
293 _SCNetworkReachabilityCopyTargetDescription (SCNetworkReachabilityRef target
);
296 _SCNetworkReachabilityCopyTargetFlags (SCNetworkReachabilityRef target
);
299 __SCNetworkReachabilityPerform (SCNetworkReachabilityRef target
);
302 __SCNetworkReachabilityPerformConcurrent (SCNetworkReachabilityRef target
);
304 #ifdef HAVE_REACHABILITY_SERVER
307 __SCNetworkReachability_concurrent_queue (void);
310 #pragma mark [XPC] Reachability Server (client APIs)
313 _SCNetworkReachabilityServer_snapshot (void);
316 __SCNetworkReachabilityServer_targetAdd (SCNetworkReachabilityRef target
);
319 __SCNetworkReachabilityServer_targetRemove (SCNetworkReachabilityRef target
);
322 __SCNetworkReachabilityServer_targetSchedule (SCNetworkReachabilityRef target
);
325 __SCNetworkReachabilityServer_targetStatus (SCNetworkReachabilityRef target
);
328 __SCNetworkReachabilityServer_targetUnschedule (SCNetworkReachabilityRef target
);
332 __SC_checkResolverReachabilityInternal (SCDynamicStoreRef
*storeP
,
333 SCNetworkReachabilityFlags
*flags
,
335 const char *nodename
,
336 uint32_t *resolver_if_index
,
337 int *dns_config_index
);
339 #endif // HAVE_REACHABILITY_SERVER
341 static __inline__
void
342 __SCNetworkReachabilityPrintFlags(SCNetworkReachabilityFlags flags
)
345 if (flags
& kSCNetworkReachabilityFlagsReachable
) {
346 SCPrint(TRUE
, stdout
, CFSTR("Reachable"));
347 flags
&= ~kSCNetworkReachabilityFlagsReachable
;
348 SCPrint(flags
!= 0, stdout
, CFSTR(","));
350 if (flags
& kSCNetworkReachabilityFlagsTransientConnection
) {
351 SCPrint(TRUE
, stdout
, CFSTR("Transient Connection"));
352 flags
&= ~kSCNetworkReachabilityFlagsTransientConnection
;
353 SCPrint(flags
!= 0, stdout
, CFSTR(","));
355 if (flags
& kSCNetworkReachabilityFlagsConnectionRequired
) {
356 SCPrint(TRUE
, stdout
, CFSTR("Connection Required"));
357 flags
&= ~kSCNetworkReachabilityFlagsConnectionRequired
;
358 SCPrint(flags
!= 0, stdout
, CFSTR(","));
360 if (flags
& kSCNetworkReachabilityFlagsConnectionOnTraffic
) {
361 SCPrint(TRUE
, stdout
, CFSTR("Automatic Connection On Traffic"));
362 flags
&= ~kSCNetworkReachabilityFlagsConnectionOnTraffic
;
363 SCPrint(flags
!= 0, stdout
, CFSTR(","));
365 if (flags
& kSCNetworkReachabilityFlagsConnectionOnDemand
) {
366 SCPrint(TRUE
, stdout
, CFSTR("Automatic Connection On Demand"));
367 flags
&= ~kSCNetworkReachabilityFlagsConnectionOnDemand
;
368 SCPrint(flags
!= 0, stdout
, CFSTR(","));
370 if (flags
& kSCNetworkReachabilityFlagsInterventionRequired
) {
371 SCPrint(TRUE
, stdout
, CFSTR("Intervention Required"));
372 flags
&= ~kSCNetworkReachabilityFlagsInterventionRequired
;
373 SCPrint(flags
!= 0, stdout
, CFSTR(","));
375 if (flags
& kSCNetworkReachabilityFlagsIsLocalAddress
) {
376 SCPrint(TRUE
, stdout
, CFSTR("Local Address"));
377 flags
&= ~kSCNetworkReachabilityFlagsIsLocalAddress
;
378 SCPrint(flags
!= 0, stdout
, CFSTR(","));
380 if (flags
& kSCNetworkReachabilityFlagsIsDirect
) {
381 SCPrint(TRUE
, stdout
, CFSTR("Directly Reachable Address"));
382 flags
&= ~kSCNetworkReachabilityFlagsIsDirect
;
383 SCPrint(flags
!= 0, stdout
, CFSTR(","));
386 if (flags
& kSCNetworkReachabilityFlagsIsWWAN
) {
387 SCPrint(TRUE
, stdout
, CFSTR("WWAN"));
388 flags
&= ~kSCNetworkReachabilityFlagsIsWWAN
;
389 SCPrint(flags
!= 0, stdout
, CFSTR(","));
391 #endif // TARGET_OS_IPHONE
393 SCPrint(TRUE
, stdout
, CFSTR("0x%08x"), flags
);
396 SCPrint(TRUE
, stdout
, CFSTR("Not Reachable"));
405 #endif // _SCNETWORKREACHABILITYINTERNAL_H