1/* 2 * Copyright (c) 2003-2014 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 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 11 * file. 12 * 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. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#ifndef _SCNETWORKREACHABILITYINTERNAL_H 25#define _SCNETWORKREACHABILITYINTERNAL_H 26 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> 35 36#include <dns_sd.h> 37#include <netdb.h> 38#include <sys/socket.h> 39#include <net/if.h> 40#include <xpc/xpc.h> 41 42 43 44 45#pragma mark - 46#pragma mark SCNetworkReachability 47 48 49#define kSCNetworkReachabilityFlagsFirstResolvePending (1<<31) 50 51 52 53#define kSCNetworkReachabilityFlagsMask 0x00ffffff // top 8-bits reserved for implementation 54 55 56typedef enum { 57 NO = 0, 58 YES, 59 UNKNOWN 60} lazyBoolean; 61 62 63typedef enum { 64 // by-address SCNetworkReachability targets 65 reachabilityTypeAddress, 66 reachabilityTypeAddressPair, 67 // by-name SCNetworkReachability targets 68 reachabilityTypeName, 69 reachabilityTypePTR 70} ReachabilityAddressType; 71 72#define isReachabilityTypeAddress(type) (type < reachabilityTypeName) 73#define isReachabilityTypeName(type) (type >= reachabilityTypeName) 74 75 76typedef struct { 77 uint64_t cycle; 78 SCNetworkReachabilityFlags flags; 79 unsigned int if_index; 80 char if_name[IFNAMSIZ]; 81 Boolean sleeping; 82} ReachabilityInfo; 83 84 85typedef struct { 86 87 /* base CFType information */ 88 CFRuntimeBase cfBase; 89 90 /* lock */ 91 pthread_mutex_t lock; 92 93 /* logging */ 94 Boolean quiet; 95 96 /* address type */ 97 ReachabilityAddressType type; 98 99 /* target host name */ 100 const char *name; 101 Boolean needResolve; 102 CFArrayRef resolvedAddresses; /* CFArray[CFData] or CFArray[CFString] */ 103 int resolvedError; 104 SCNetworkReachabilityFlags resolverFlags; 105 106 /* [scoped routing] interface constraints */ 107 unsigned int if_index; 108 char if_name[IFNAMSIZ]; 109 110 /* local & remote addresses */ 111 struct sockaddr *localAddress; 112 struct sockaddr *remoteAddress; 113 114 /* current reachability flags */ 115 uint64_t cycle; 116 ReachabilityInfo info; 117 ReachabilityInfo last_notify; 118 119 /* run loop source, callout, context, rl scheduling info */ 120 Boolean scheduled; 121 CFRunLoopSourceRef rls; 122 SCNetworkReachabilityCallBack rlsFunction; 123 SCNetworkReachabilityContext rlsContext; 124 CFMutableArrayRef rlList; 125 unsigned int pending; // 0 == no notifications queued, else # to be delivered 126 127 dispatch_group_t dispatchGroup; 128 dispatch_queue_t dispatchQueue; // SCNetworkReachabilitySetDispatchQueue 129 130 /* [async] DNS query info */ 131 Boolean haveDNS; 132 struct timeval dnsQueryStart; 133 struct timeval dnsQueryEnd; 134 135 /* [async] processing info */ 136 struct timeval last_dns; 137 struct timeval last_network; 138#if !TARGET_OS_IPHONE 139 struct timeval last_power; 140#endif // !TARGET_OS_IPHONE 141 struct timeval last_push; 142 143 /* on demand info */ 144 Boolean onDemandBypass; 145 CFStringRef onDemandName; 146 CFStringRef onDemandRemoteAddress; 147 SCNetworkReachabilityRef onDemandServer; 148 CFStringRef onDemandServiceID; 149 150 151 union { 152 uint32_t dnsFlags; 153 struct { 154 Boolean dnsActive :1; // if DNSServiceGetAddrInfo active 155 156 Boolean dnsHaveError :1; // error during query 157 Boolean dnsHaveV4 :1; // have IPv4 (A) reply 158 Boolean dnsHaveV6 :1; // have IPv6 (AAAA) reply 159 Boolean dnsHavePTR :1; // have PTR reply 160 Boolean dnsHaveTimeout:1; // no replies (A, AAAA, or PTR) 161 }; 162 }; 163 CFArrayRef dnsAddresses; // CFArray[CFData] 164 Boolean dnsBlocked; // if DNS query blocked 165 int dnsError; 166 int dnsFailures; // # of unexpected DNSServiceXXX errors 167 int dnsGeneration; 168 DNSServiceRef dnsTarget; 169 Boolean dnsNoAddressesSinceLastTimeout; 170 171 /* SCNetworkReachability server "client" info */ 172 Boolean serverActive; 173 Boolean serverBypass; 174 Boolean serverScheduled; 175 ReachabilityInfo serverInfo; 176 177 /* SCNetworkReachability server "server" info */ 178 CFDataRef serverDigest; 179 dispatch_group_t serverGroup; 180 Boolean serverInfoValid; 181 unsigned int serverSyncQueryActive; // 0 == no [sync] query active, else # waiting on group 182 dispatch_queue_t serverQueue; 183 unsigned int serverReferences; // how many [client] targets 184 CFMutableDictionaryRef serverWatchers; // [client_id/target_id] watchers 185 186 Boolean useNEVPN; 187 uid_t uid; 188 void *nePolicyResult; 189 Boolean serverBypassForVPN; // if serverBypassForVPN, only use client mode 190 191 Boolean resolverBypass; // set this flag to bypass resolving the name 192 193 194 195 /* logging */ 196 char log_prefix[32]; 197 198} SCNetworkReachabilityPrivate, *SCNetworkReachabilityPrivateRef; 199 200 201 202// ------------------------------------------------------------ 203 204#pragma mark - 205#pragma mark [XPC] Reachability Server 206 207 208#define REACH_SERVER_VERSION 20110323 209 210#if !TARGET_IPHONE_SIMULATOR 211#define REACH_SERVICE_NAME "com.apple.SystemConfiguration.SCNetworkReachability" 212#else // !TARGET_IPHONE_SIMULATOR 213#define REACH_SERVICE_NAME "com.apple.SystemConfiguration.SCNetworkReachability_sim" 214#endif // !TARGET_IPHONE_SIMULATOR 215 216// ------------------------------------------------------------ 217 218 219#pragma mark - 220#pragma mark [XPC] Reachability Server (client->server request) 221 222 223#define REACH_CLIENT_PROC_NAME "proc_name" // string 224#define REACH_CLIENT_TARGET_ID "target_id" // uint64 225 226#define REACH_REQUEST "request_op" // int64 227 228enum { 229 REACH_REQUEST_CREATE = 0x0001, 230 REACH_REQUEST_REMOVE, 231 REACH_REQUEST_SCHEDULE, 232 REACH_REQUEST_STATUS, 233 REACH_REQUEST_UNSCHEDULE, 234 REACH_REQUEST_SNAPSHOT = 0x0101, 235}; 236 237#define REACH_TARGET_NAME "name" // string 238 239#define REACH_TARGET_LOCAL_ADDR "local_address" // data (struct sockaddr) 240#define REACH_TARGET_REMOTE_ADDR "remote_address" // data (struct sockaddr) 241 242#define REACH_TARGET_PTR_ADDR "ptr_address" // data (struct sockaddr) 243 244#define REACH_TARGET_IF_INDEX "if_index" // int64 245#define REACH_TARGET_IF_NAME "if_name" // string 246#define REACH_TARGET_ONDEMAND_BYPASS "ondemand_bypass" // bool 247#define REACH_TARGET_RESOLVER_BYPASS "resolver_bypass" // bool 248 249 250#define REACH_REQUEST_REPLY "reply" // int64 251#define REACH_REQUEST_REPLY_DETAIL "reply_detail" // string 252 253enum { 254 REACH_REQUEST_REPLY_OK = 0x0000, 255 REACH_REQUEST_REPLY_FAILED, 256 REACH_REQUEST_REPLY_UNKNOWN, 257}; 258 259 260// ------------------------------------------------------------ 261 262 263#pragma mark - 264#pragma mark [XPC] Reachability Server (server->client request) 265 266 267#define MESSAGE_NOTIFY "notify_op" // int64 268 269enum { 270 MESSAGE_REACHABILITY_STATUS = 0x1001, 271}; 272 273#define REACH_STATUS_CYCLE "cycle" // uint64 274#define REACH_STATUS_DNS_FLAGS "dns_flags" // uint64 275#define REACH_STATUS_FLAGS "flags" // uint64 276#define REACH_STATUS_IF_INDEX "if_index" // uint64 277#define REACH_STATUS_IF_NAME "if_name" // data (char if_name[IFNAMSIZ]) 278#define REACH_STATUS_RESOLVED_ADDRESSES "resolved_addresses" // array[data] 279#define REACH_STATUS_RESOLVED_ERROR "resolved_error" // int64 280#define REACH_STATUS_SLEEPING "sleeping" // bool 281 282 283// ------------------------------------------------------------ 284 285 286__BEGIN_DECLS 287 288CFStringRef 289_SCNetworkReachabilityCopyTargetDescription (SCNetworkReachabilityRef target); 290 291CFStringRef 292_SCNetworkReachabilityCopyTargetFlags (SCNetworkReachabilityRef target); 293 294void 295__SCNetworkReachabilityUpdate (SCNetworkReachabilityRef target); 296 297void 298__SCNetworkReachabilityUpdateConcurrent (SCNetworkReachabilityRef target); 299 300dispatch_queue_t 301__SCNetworkReachability_concurrent_queue (void); 302 303#pragma mark - 304#pragma mark [XPC] Reachability Server (client APIs) 305 306Boolean 307_SCNetworkReachabilityServer_snapshot (void); 308 309Boolean 310__SCNetworkReachabilityServer_targetAdd (SCNetworkReachabilityRef target); 311 312void 313__SCNetworkReachabilityServer_targetRemove (SCNetworkReachabilityRef target); 314 315Boolean 316__SCNetworkReachabilityServer_targetSchedule (SCNetworkReachabilityRef target); 317 318Boolean 319__SCNetworkReachabilityServer_targetStatus (SCNetworkReachabilityRef target); 320 321Boolean 322__SCNetworkReachabilityServer_targetUnschedule (SCNetworkReachabilityRef target); 323 324 325Boolean 326__SC_checkResolverReachabilityInternal (SCDynamicStoreRef *storeP, 327 SCNetworkReachabilityFlags *flags, 328 Boolean *haveDNS, 329 const char *nodename, 330 uint32_t *resolver_if_index, 331 int *dns_config_index); 332 333static __inline__ void 334__SCNetworkReachabilityPrintFlags(SCNetworkReachabilityFlags flags) 335{ 336 if (flags != 0) { 337 if (flags & kSCNetworkReachabilityFlagsReachable) { 338 SCPrint(TRUE, stdout, CFSTR("Reachable")); 339 flags &= ~kSCNetworkReachabilityFlagsReachable; 340 SCPrint(flags != 0, stdout, CFSTR(",")); 341 } 342 if (flags & kSCNetworkReachabilityFlagsTransientConnection) { 343 SCPrint(TRUE, stdout, CFSTR("Transient Connection")); 344 flags &= ~kSCNetworkReachabilityFlagsTransientConnection; 345 SCPrint(flags != 0, stdout, CFSTR(",")); 346 } 347 if (flags & kSCNetworkReachabilityFlagsConnectionRequired) { 348 SCPrint(TRUE, stdout, CFSTR("Connection Required")); 349 flags &= ~kSCNetworkReachabilityFlagsConnectionRequired; 350 SCPrint(flags != 0, stdout, CFSTR(",")); 351 } 352 if (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) { 353 SCPrint(TRUE, stdout, CFSTR("Automatic Connection On Traffic")); 354 flags &= ~kSCNetworkReachabilityFlagsConnectionOnTraffic; 355 SCPrint(flags != 0, stdout, CFSTR(",")); 356 } 357 if (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) { 358 SCPrint(TRUE, stdout, CFSTR("Automatic Connection On Demand")); 359 flags &= ~kSCNetworkReachabilityFlagsConnectionOnDemand; 360 SCPrint(flags != 0, stdout, CFSTR(",")); 361 } 362 if (flags & kSCNetworkReachabilityFlagsInterventionRequired) { 363 SCPrint(TRUE, stdout, CFSTR("Intervention Required")); 364 flags &= ~kSCNetworkReachabilityFlagsInterventionRequired; 365 SCPrint(flags != 0, stdout, CFSTR(",")); 366 } 367 if (flags & kSCNetworkReachabilityFlagsIsLocalAddress) { 368 SCPrint(TRUE, stdout, CFSTR("Local Address")); 369 flags &= ~kSCNetworkReachabilityFlagsIsLocalAddress; 370 SCPrint(flags != 0, stdout, CFSTR(",")); 371 } 372 if (flags & kSCNetworkReachabilityFlagsIsDirect) { 373 SCPrint(TRUE, stdout, CFSTR("Directly Reachable Address")); 374 flags &= ~kSCNetworkReachabilityFlagsIsDirect; 375 SCPrint(flags != 0, stdout, CFSTR(",")); 376 } 377#if TARGET_OS_IPHONE 378 if (flags & kSCNetworkReachabilityFlagsIsWWAN) { 379 SCPrint(TRUE, stdout, CFSTR("WWAN")); 380 flags &= ~kSCNetworkReachabilityFlagsIsWWAN; 381 SCPrint(flags != 0, stdout, CFSTR(",")); 382 } 383#endif // TARGET_OS_IPHONE 384 if (flags != 0) { 385 SCPrint(TRUE, stdout, CFSTR("0x%08x"), flags); 386 } 387 } else { 388 SCPrint(TRUE, stdout, CFSTR("Not Reachable")); 389 } 390 391 return; 392} 393 394 395__END_DECLS 396 397#endif // _SCNETWORKREACHABILITYINTERNAL_H 398