+SCNetworkReachabilityRef
+SCNetworkReachabilityCreateWithOptions(CFAllocatorRef allocator,
+ CFDictionaryRef options)
+{
+ CFDataRef data;
+ struct addrinfo *hints = NULL;
+ CFStringRef nodename;
+ CFStringRef servname;
+ SCNetworkReachabilityPrivateRef targetPrivate;
+
+ if (!isA_CFDictionary(options)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return NULL;
+ }
+
+ nodename = CFDictionaryGetValue(options, kSCNetworkReachabilityOptionNodeName);
+ if ((nodename != NULL) &&
+ (!isA_CFString(nodename) || (CFStringGetLength(nodename) == 0))) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return NULL;
+ }
+ servname = CFDictionaryGetValue(options, kSCNetworkReachabilityOptionServName);
+ if ((servname != NULL) &&
+ (!isA_CFString(servname) || (CFStringGetLength(servname) == 0))) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return NULL;
+ }
+ data = CFDictionaryGetValue(options, kSCNetworkReachabilityOptionHints);
+ if (data != NULL) {
+ if (!isA_CFData(data) || (CFDataGetLength(data) != sizeof(targetPrivate->hints))) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return NULL;
+ }
+
+ hints = (struct addrinfo *)CFDataGetBytePtr(data);
+ if ((hints->ai_addrlen != 0) ||
+ (hints->ai_addr != NULL) ||
+ (hints->ai_canonname != NULL) ||
+ (hints->ai_next != NULL)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return NULL;
+ }
+ }
+ if ((nodename == NULL) && (servname == NULL)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return NULL;
+ }
+
+ targetPrivate = __SCNetworkReachabilityCreatePrivate(allocator);
+ if (targetPrivate == NULL) {
+ return NULL;
+ }
+ targetPrivate->type = reachabilityTypeName;
+ targetPrivate->flags |= kSCNetworkFlagsFirstResolvePending;
+ if (nodename != NULL) {
+ targetPrivate->name = _SC_cfstring_to_cstring(nodename, NULL, 0, kCFStringEncodingUTF8);
+ }
+ if (servname != NULL) {
+ targetPrivate->serv = _SC_cfstring_to_cstring(servname, NULL, 0, kCFStringEncodingUTF8);
+ }
+ if (hints != NULL) {
+ bcopy(hints, &targetPrivate->hints, sizeof(targetPrivate->hints));
+ }
+
+ return (SCNetworkReachabilityRef)targetPrivate;
+}
+
+