2 * Copyright (c) 2001 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
24 * Modification History
26 * March 28, 2001 Allan Nathanson <ajn@apple.com>
30 #include <SystemConfiguration/SystemConfiguration.h>
31 #include <SystemConfiguration/SCPrivate.h>
32 #include "SCDynamicStoreInternal.h"
34 #include "v1Compatibility.h"
36 extern void __Initialize();
40 /* configuration data associated with key */
41 CFPropertyListRef data
;
43 /* instance value of last fetched data */
46 } SCDHandlePrivate
, *SCDHandlePrivateRef
;
52 SCDHandlePrivateRef privateHandle
= CFAllocatorAllocate(NULL
, sizeof(SCDHandlePrivate
), 0);
55 privateHandle
->data
= NULL
;
58 privateHandle
->instance
= 0;
60 return (SCDHandleRef
)privateHandle
;
65 SCDHandleRelease(SCDHandleRef handle
)
67 SCDHandlePrivateRef privateHandle
= (SCDHandlePrivateRef
)handle
;
69 if (privateHandle
->data
)
70 CFRelease(privateHandle
->data
);
72 CFAllocatorDeallocate(NULL
, privateHandle
);
78 SCDHandleGetInstance(SCDHandleRef handle
)
80 SCDHandlePrivateRef privateHandle
= (SCDHandlePrivateRef
)handle
;
82 return privateHandle
->instance
;
87 _SCDHandleSetInstance(SCDHandleRef handle
, int instance
)
89 SCDHandlePrivateRef privateHandle
= (SCDHandlePrivateRef
)handle
;
91 privateHandle
->instance
= instance
;
97 SCDHandleGetData(SCDHandleRef handle
)
99 SCDHandlePrivateRef privateHandle
= (SCDHandlePrivateRef
)handle
;
101 if (privateHandle
->data
== NULL
) {
102 return CFSTR("SCDHandleRef not initialized.");
105 return privateHandle
->data
;
110 SCDHandleSetData(SCDHandleRef handle
, CFPropertyListRef data
)
112 SCDHandlePrivateRef privateHandle
= (SCDHandlePrivateRef
)handle
;
114 /* remove reference to data previously associated with handle */
115 if (privateHandle
->data
)
116 CFRelease(privateHandle
->data
);
118 /* associate new data with handle, keep a reference as needed */
119 privateHandle
->data
= data
;
120 if (privateHandle
->data
)
121 CFRetain(privateHandle
->data
);
127 convert_SCDStatus_To_SCStatus(SCDStatus status
)
130 case SCD_OK
: return kSCStatusOK
;
131 case SCD_NOSESSION
: return kSCStatusNoStoreSession
;
132 case SCD_NOSERVER
: return kSCStatusNoStoreServer
;
133 case SCD_LOCKED
: return kSCStatusLocked
;
134 case SCD_NEEDLOCK
: return kSCStatusNeedLock
;
135 case SCD_EACCESS
: return kSCStatusAccessError
;
136 case SCD_NOKEY
: return kSCStatusNoKey
;
137 case SCD_EXISTS
: return kSCStatusKeyExists
;
138 case SCD_STALE
: return kSCStatusStale
;
139 case SCD_INVALIDARGUMENT
: return kSCStatusInvalidArgument
;
140 case SCD_NOTIFIERACTIVE
: return kSCStatusNotifierActive
;
141 case SCD_FAILED
: return kSCStatusFailed
;
142 default : return kSCStatusFailed
;
147 SCDOpen(SCDSessionRef
*session
, CFStringRef name
)
149 SCDynamicStoreRef newStore
;
151 __Initialize(); /* initialize framework */
153 newStore
= SCDynamicStoreCreate(NULL
, name
, NULL
, NULL
);
158 *session
= (SCDSessionRef
)newStore
;
163 SCDClose(SCDSessionRef
*session
)
171 SCDLock(SCDSessionRef session
)
173 return SCDynamicStoreLock((SCDynamicStoreRef
)session
) ? SCD_OK
: SCD_FAILED
;
177 SCDUnlock(SCDSessionRef session
)
179 return SCDynamicStoreUnlock((SCDynamicStoreRef
)session
) ? SCD_OK
: SCD_FAILED
;
183 SCDList(SCDSessionRef session
, CFStringRef key
, int regexOptions
, CFArrayRef
*subKeys
)
185 CFMutableStringRef pattern
;
187 pattern
= CFStringCreateMutableCopy(NULL
, 0, key
);
188 if ((regexOptions
& kSCDRegexKey
) != kSCDRegexKey
) {
189 CFStringAppend(pattern
, CFSTR(".*"));
191 *subKeys
= SCDynamicStoreCopyKeyList((SCDynamicStoreRef
)session
, pattern
);
194 return (*subKeys
) ? SCD_OK
: SCD_FAILED
;
198 SCDAdd(SCDSessionRef session
, CFStringRef key
, SCDHandleRef handle
)
200 CFTypeRef value
= SCDHandleGetData(handle
);
201 return SCDynamicStoreAddValue((SCDynamicStoreRef
)session
, key
, value
) ? SCD_OK
: SCD_EXISTS
;
205 SCDAddSession(SCDSessionRef session
, CFStringRef key
, SCDHandleRef handle
)
207 CFTypeRef value
= SCDHandleGetData(handle
);
208 return SCDynamicStoreAddTemporaryValue((SCDynamicStoreRef
)session
, key
, value
) ? SCD_OK
: SCD_EXISTS
;
212 SCDGet(SCDSessionRef session
, CFStringRef key
, SCDHandleRef
*handle
)
216 value
= SCDynamicStoreCopyValue((SCDynamicStoreRef
)session
, key
);
218 *handle
= SCDHandleInit();
219 SCDHandleSetData(*handle
, value
);
227 SCDSet(SCDSessionRef session
, CFStringRef key
, SCDHandleRef handle
)
229 CFTypeRef value
= SCDHandleGetData(handle
);
230 return SCDynamicStoreSetValue((SCDynamicStoreRef
)session
, key
, value
) ? SCD_OK
: SCD_EXISTS
;
234 SCDRemove(SCDSessionRef session
, CFStringRef key
)
236 return SCDynamicStoreRemoveValue((SCDynamicStoreRef
)session
, key
) ? SCD_OK
: SCD_NOKEY
;
240 SCDTouch(SCDSessionRef session
, CFStringRef key
)
242 return SCDynamicStoreTouchValue((SCDynamicStoreRef
)session
, key
) ? SCD_OK
: SCD_FAILED
;
246 SCDNotifierList(SCDSessionRef session
, int regexOptions
, CFArrayRef
*notifierKeys
)
248 *notifierKeys
= SCDynamicStoreCopyWatchedKeyList((SCDynamicStoreRef
)session
,
249 ((regexOptions
& kSCDRegexKey
) == kSCDRegexKey
));
250 return (*notifierKeys
) ? SCD_OK
: SCD_FAILED
;
254 SCDNotifierAdd(SCDSessionRef session
, CFStringRef key
, int regexOptions
)
256 return SCDynamicStoreAddWatchedKey((SCDynamicStoreRef
)session
,
258 ((regexOptions
& kSCDRegexKey
) == kSCDRegexKey
)) ? SCD_OK
: SCD_EXISTS
;
262 SCDNotifierRemove(SCDSessionRef session
, CFStringRef key
, int regexOptions
)
264 return SCDynamicStoreRemoveWatchedKey((SCDynamicStoreRef
)session
,
266 ((regexOptions
& kSCDRegexKey
) == kSCDRegexKey
)) ? SCD_OK
: SCD_NOKEY
;
270 SCDNotifierGetChanges(SCDSessionRef session
, CFArrayRef
*changedKeys
)
272 *changedKeys
= SCDynamicStoreCopyNotifiedKeys((SCDynamicStoreRef
)session
);
273 return (*changedKeys
) ? SCD_OK
: SCD_FAILED
;
277 SCDNotifierWait(SCDSessionRef session
)
279 return SCDynamicStoreNotifyWait((SCDynamicStoreRef
)session
) ? SCD_OK
: SCD_FAILED
;
283 SCDNotifierInformViaCallback(SCDSessionRef session
, SCDCallbackRoutine_t func
, void *arg
)
285 return SCDynamicStoreNotifyCallback((SCDynamicStoreRef
)session
,
286 CFRunLoopGetCurrent(),
287 (SCDynamicStoreCallBack_v1
)func
,
288 arg
) ? SCD_OK
: SCD_NOTIFIERACTIVE
;
292 SCDNotifierInformViaMachPort(SCDSessionRef session
, mach_msg_id_t msgid
, mach_port_t
*port
)
294 return SCDynamicStoreNotifyMachPort((SCDynamicStoreRef
)session
, msgid
, port
) ? SCD_OK
: SCD_NOTIFIERACTIVE
;
298 SCDNotifierInformViaFD(SCDSessionRef session
, int32_t identifier
, int *fd
)
300 return SCDynamicStoreNotifyFileDescriptor((SCDynamicStoreRef
)session
, identifier
, fd
) ? SCD_OK
: SCD_NOTIFIERACTIVE
;
304 SCDNotifierInformViaSignal(SCDSessionRef session
, pid_t pid
, int sig
)
306 return SCDynamicStoreNotifySignal((SCDynamicStoreRef
)session
, pid
, sig
) ? SCD_OK
: SCD_NOTIFIERACTIVE
;
310 SCDNotifierCancel(SCDSessionRef session
)
312 return SCDynamicStoreNotifyCancel((SCDynamicStoreRef
)session
) ? SCD_OK
: SCD_NOTIFIERACTIVE
;
316 SCDSnapshot(SCDSessionRef session
)
318 return SCDynamicStoreSnapshot((SCDynamicStoreRef
)session
) ? SCD_OK
: SCD_NOTIFIERACTIVE
;
322 SCDOptionGet(SCDSessionRef session
, int option
)
327 static Boolean warned
= FALSE
;
329 SCLog(TRUE
, LOG_NOTICE
, CFSTR("per-session options are no longer supported, using global options."));
335 case kSCDOptionDebug
:
336 value
= _sc_debug
? 1 : 0;
339 case kSCDOptionVerbose
:
340 value
= _sc_verbose
? 1 : 0;
343 case kSCDOptionUseSyslog
:
344 value
= _sc_log
? 1 : 0;
347 case kSCDOptionUseCFRunLoop
:
348 value
= 1; /* always TRUE */
356 SCDOptionSet(SCDSessionRef session
, int option
, int value
)
359 static Boolean warned
= FALSE
;
361 SCLog(TRUE
, LOG_NOTICE
, CFSTR("per-session options are no longer supported, using global options."));
367 case kSCDOptionDebug
:
368 _sc_debug
= (value
!= 0);
369 _sc_log
= (value
== 0);
372 case kSCDOptionVerbose
:
373 _sc_verbose
= (value
!= 0);
376 case kSCDOptionUseSyslog
:
378 _sc_log
= (value
!= 0);
382 case kSCDOptionUseCFRunLoop
:
384 static Boolean warned
= FALSE
;
385 if ((value
== FALSE
) && !warned
) {
386 SCLog(TRUE
, LOG_NOTICE
, CFSTR("The kSCDOptionUseCFRunLoop option can no longer be set FALSE. The"));
387 SCLog(TRUE
, LOG_NOTICE
, CFSTR("SCDNotifierInformViaCallback requires the use of a CFRunLoop."));
398 SCDSessionLog(SCDSessionRef session
, int level
, CFStringRef formatString
, ...)
401 FILE *f
= (LOG_PRI(level
) > LOG_NOTICE
) ? stderr
: stdout
;
402 CFStringRef resultString
;
404 if ((LOG_PRI(level
) == LOG_DEBUG
) && !SCDOptionGet(session
, kSCDOptionVerbose
)) {
405 /* it's a debug message and we haven't requested verbose logging */
409 va_start(argList
, formatString
);
410 resultString
= CFStringCreateWithFormatAndArguments(NULL
, NULL
, formatString
, argList
);
413 if (SCDOptionGet(session
, kSCDOptionUseSyslog
)) {
414 __SCLog(level
, resultString
);
416 CFStringRef newString
;
419 newString
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@\n"), resultString
);
420 __SCPrint(f
, newString
);
421 CFRelease(newString
);
423 CFRelease(resultString
);
427 SCDLog(int level
, CFStringRef formatString
, ...)
430 FILE *f
= (LOG_PRI(level
) > LOG_NOTICE
) ? stderr
: stdout
;
431 CFStringRef resultString
;
433 if ((LOG_PRI(level
) == LOG_DEBUG
) && !SCDOptionGet(NULL
, kSCDOptionVerbose
)) {
434 /* it's a debug message and we haven't requested verbose logging */
438 va_start(argList
, formatString
);
439 resultString
= CFStringCreateWithFormatAndArguments(NULL
, NULL
, formatString
, argList
);
442 if (SCDOptionGet(NULL
, kSCDOptionUseSyslog
)) {
443 __SCLog(level
, resultString
);
445 CFStringRef newString
;
448 newString
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@\n"), resultString
);
449 __SCPrint(f
, newString
);
450 CFRelease(newString
);
452 CFRelease(resultString
);
456 SCDError(SCDStatus status
)
458 return SCErrorString(convert_SCDStatus_To_SCStatus(status
));
462 SCDKeyCreate(CFStringRef fmt
, ...)
466 return (CFStringCreateWithFormatAndArguments(NULL
,
473 SCDKeyCreateNetworkGlobalEntity(CFStringRef domain
, CFStringRef entity
)
475 return SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, domain
, entity
);
479 SCDKeyCreateNetworkInterface(CFStringRef domain
)
481 return SCDynamicStoreKeyCreateNetworkInterface(NULL
, domain
);
485 SCDKeyCreateNetworkInterfaceEntity(CFStringRef domain
, CFStringRef ifname
, CFStringRef entity
)
487 return SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
, domain
, ifname
, entity
);
491 SCDKeyCreateNetworkServiceEntity(CFStringRef domain
, CFStringRef serviceID
, CFStringRef entity
)
493 return SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
, domain
, serviceID
, entity
);
497 convert_SCPStatus_To_SCStatus(SCPStatus status
)
500 case SCP_OK
: return kSCStatusOK
;
501 case SCP_NOSESSION
: return kSCStatusNoPrefsSession
;
502 case SCP_BUSY
: return kSCStatusPrefsBusy
;
503 case SCP_NEEDLOCK
: return kSCStatusNeedLock
;
504 case SCP_EACCESS
: return kSCStatusAccessError
;
505 case SCP_ENOENT
: return kSCStatusNoConfigFile
;
506 case SCP_BADCF
: return kSCStatusFailed
;
507 case SCP_NOKEY
: return kSCStatusNoKey
;
508 case SCP_NOLINK
: return kSCStatusNoLink
;
509 case SCP_EXISTS
: return kSCStatusKeyExists
;
510 case SCP_STALE
: return kSCStatusStale
;
511 case SCP_INVALIDARGUMENT
: return kSCStatusInvalidArgument
;
512 case SCP_FAILED
: return kSCStatusFailed
;
513 default : return kSCStatusFailed
;
518 SCPOpen(SCPSessionRef
*session
, CFStringRef name
, CFStringRef prefsID
, int options
)
523 __Initialize(); /* initialize framework */
525 *session
= (SCPSessionRef
)SCPreferencesCreate(NULL
, name
, prefsID
);
526 if (*session
== NULL
) {
530 keys
= SCPreferencesCopyKeyList(*session
);
531 nKeys
= CFArrayGetCount(keys
);
535 ((options
& kSCPOpenCreatePrefs
) != kSCPOpenCreatePrefs
)) {
536 /* if no keys and not requesting the file be created */
544 SCPUserOpen(SCPSessionRef
*session
, CFStringRef name
, CFStringRef prefsID
, CFStringRef user
, int options
)
549 __Initialize(); /* initialize framework */
551 *session
= (SCPSessionRef
)SCUserPreferencesCreate(NULL
, name
, prefsID
, user
);
552 if (*session
== NULL
) {
556 keys
= SCPreferencesCopyKeyList(*session
);
557 nKeys
= CFArrayGetCount(keys
);
561 ((options
& kSCPOpenCreatePrefs
) != kSCPOpenCreatePrefs
)) {
562 /* if no keys and not requesting the file be created */
570 SCPClose(SCPSessionRef
*session
)
578 SCPLock(SCPSessionRef session
, boolean_t wait
)
580 /* XXXXX: old API error codes included kSCStatusPrefsBusy, kSCStatusAccessError, and kSCStatusStale */
581 return SCPreferencesLock((SCPreferencesRef
)session
, wait
) ? SCP_OK
: SCP_FAILED
;
585 SCPCommit(SCPSessionRef session
)
587 /* XXXXX: old API error codes included kSCStatusAccessError, kSCStatusStale */
588 return SCPreferencesCommitChanges((SCPreferencesRef
)session
) ? SCP_OK
: SCP_FAILED
;
592 SCPApply(SCPSessionRef session
)
594 return SCPreferencesApplyChanges((SCPreferencesRef
)session
) ? SCP_OK
: SCP_EACCESS
;
598 SCPUnlock(SCPSessionRef session
)
600 return SCPreferencesUnlock((SCPreferencesRef
)session
) ? SCP_OK
: SCP_FAILED
;
604 SCPGetSignature(SCPSessionRef session
, CFDataRef
*signature
)
606 *signature
= SCPreferencesGetSignature((SCPreferencesRef
)session
);
607 return (*signature
) ? SCP_OK
: SCP_FAILED
;
611 SCPList(SCPSessionRef session
, CFArrayRef
*keys
)
613 *keys
= SCPreferencesCopyKeyList((SCPreferencesRef
)session
);
614 return (*keys
) ? SCP_OK
: SCP_FAILED
;
618 SCPGet(SCPSessionRef session
, CFStringRef key
, CFPropertyListRef
*data
)
620 *data
= SCPreferencesGetValue((SCPreferencesRef
)session
, key
);
621 return (*data
) ? SCP_OK
: SCP_NOKEY
;
625 SCPAdd(SCPSessionRef session
, CFStringRef key
, CFPropertyListRef data
)
627 return SCPreferencesAddValue((SCPreferencesRef
)session
, key
, data
) ? SCP_OK
: SCP_EXISTS
;
631 SCPSet(SCPSessionRef session
, CFStringRef key
, CFPropertyListRef data
)
633 return SCPreferencesSetValue((SCPreferencesRef
)session
, key
, data
) ? SCP_OK
: SCP_FAILED
;
637 SCPRemove(SCPSessionRef session
, CFStringRef key
)
639 return SCPreferencesRemoveValue((SCPreferencesRef
)session
, key
) ? SCP_OK
: SCP_NOKEY
;
643 SCPNotificationKeyCreate(CFStringRef prefsID
, int keyType
)
645 return SCDynamicStoreKeyCreatePreferences(NULL
, prefsID
, keyType
);
649 SCPUserNotificationKeyCreate(CFStringRef prefsID
, CFStringRef user
, int keyType
)
651 return SCDynamicStoreKeyCreateUserPreferences(NULL
, prefsID
, user
, keyType
);
655 SCPPathCreateUniqueChild(SCPSessionRef session
, CFStringRef prefix
, CFStringRef
*newPath
)
657 *newPath
= SCPreferencesPathCreateUniqueChild((SCPreferencesRef
)session
, prefix
);
658 return (*newPath
) ? SCP_OK
: SCP_NOKEY
;
662 SCPPathGetValue(SCPSessionRef session
, CFStringRef path
, CFDictionaryRef
*value
)
664 *value
= SCPreferencesPathGetValue((SCPreferencesRef
)session
, path
);
665 return (*value
) ? SCP_OK
: SCP_NOKEY
;
669 SCPPathGetLink(SCPSessionRef session
, CFStringRef path
, CFStringRef
*link
)
671 *link
= SCPreferencesPathGetLink((SCPreferencesRef
)session
, path
);
672 return (*link
) ? SCP_OK
: SCP_NOKEY
;
676 SCPPathSetValue(SCPSessionRef session
, CFStringRef path
, CFDictionaryRef value
)
678 return SCPreferencesPathSetValue((SCPreferencesRef
)session
, path
, value
) ? SCP_OK
: SCP_FAILED
;
682 SCPPathSetLink(SCPSessionRef session
, CFStringRef path
, CFStringRef link
)
684 return SCPreferencesPathSetLink((SCPreferencesRef
)session
, path
, link
) ? SCP_OK
: SCP_FAILED
;
688 SCPPathRemove(SCPSessionRef session
, CFStringRef path
)
690 return SCPreferencesPathRemoveValue((SCPreferencesRef
)session
, path
) ? SCP_OK
: SCP_NOKEY
;
694 SCPError(SCPStatus status
)
696 return SCErrorString(convert_SCPStatus_To_SCStatus(status
));
700 SCDKeyCreateConsoleUser()
702 return SCDynamicStoreKeyCreateConsoleUser(NULL
);
706 SCDConsoleUserGet(char *user
, int userlen
, uid_t
*uid
, gid_t
*gid
)
708 CFStringRef consoleUser
;
710 consoleUser
= SCDynamicStoreCopyConsoleUser(NULL
, uid
, gid
);
715 if (user
&& (userlen
> 0)) {
719 bzero(user
, userlen
);
720 range
= CFRangeMake(0, CFStringGetLength(consoleUser
));
721 (void) CFStringGetBytes(consoleUser
,
723 kCFStringEncodingMacRoman
,
730 CFRelease(consoleUser
);
735 SCDConsoleUserSet(const char *user
, uid_t uid
, gid_t gid
)
737 return SCDynamicStoreSetConsoleUser(NULL
, user
, uid
, gid
) ? SCD_OK
: SCD_FAILED
;
741 SCDKeyCreateHostName()
743 return SCDynamicStoreKeyCreateComputerName(NULL
);
747 SCDHostNameGet(CFStringRef
*name
, CFStringEncoding
*nameEncoding
)
749 *name
= SCDynamicStoreCopyComputerName(NULL
, nameEncoding
);
750 return (*name
) ? SCD_OK
: SCD_FAILED
;
754 convertReachability(int newFlags
, int *oldFlags
)
756 SCNStatus scn_status
= SCN_REACHABLE_NO
;
758 if (newFlags
& kSCNetworkFlagsTransientConnection
) {
760 *oldFlags
|= kSCNFlagsTransientConnection
;
764 if (newFlags
& kSCNetworkFlagsReachable
) {
765 scn_status
= SCN_REACHABLE_YES
;
767 if (newFlags
& kSCNetworkFlagsConnectionRequired
) {
768 scn_status
= SCN_REACHABLE_CONNECTION_REQUIRED
;
771 if (newFlags
& kSCNetworkFlagsConnectionAutomatic
) {
773 *oldFlags
|= kSCNFlagsConnectionAutomatic
;
777 if (newFlags
& kSCNetworkFlagsInterventionRequired
) {
779 *oldFlags
|= kSCNFlagsInterventionRequired
;
788 SCNIsReachableByAddress(const struct sockaddr
*address
, const int addrlen
, int *flags
, const char **errorMessage
)
790 SCNetworkConnectionFlags newFlags
;
792 if (!SCNetworkCheckReachabilityByAddress(address
, addrlen
, &newFlags
)) {
794 *errorMessage
= SCErrorString(kSCStatusReachabilityUnknown
);
796 return SCN_REACHABLE_UNKNOWN
;
799 return convertReachability(newFlags
, flags
);
804 SCNIsReachableByName(const char *nodename
, int *flags
, const char **errorMessage
)
806 SCNetworkConnectionFlags newFlags
;
808 if (!SCNetworkCheckReachabilityByName(nodename
, &newFlags
)) {
810 *errorMessage
= SCErrorString(kSCStatusReachabilityUnknown
);
812 return SCN_REACHABLE_UNKNOWN
;
815 return convertReachability(newFlags
, flags
);