2 * Copyright (c) 2006-2018, 2020 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@
25 * Modification History
27 * June 26, 2006 Allan Nathanson <ajn@apple.com>
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
38 #include <sys/sysctl.h>
41 #include <net/if_dl.h>
42 #include <netinet/in.h>
43 #include <arpa/inet.h>
44 #include <netdb_async.h>
46 #include <smb_server_prefs.h>
48 #include <CoreFoundation/CoreFoundation.h>
49 #include <CoreFoundation/CFStringDefaultEncoding.h> // for __CFStringGetInstallationEncodingAndRegion()
50 #include <SystemConfiguration/SystemConfiguration.h>
51 #include <SystemConfiguration/SCValidation.h>
52 #include <SystemConfiguration/SCPrivate.h>
55 #define my_log(__level, __format, ...) SCPrint(TRUE, stdout, CFSTR(__format "\n"), ## __VA_ARGS__)
57 #include "ip_plugin.h"
60 #define NETBIOS_NAME_LEN 16
62 #define SMB_STARTUP_DELAY 60.0
63 #define SMB_DEBOUNCE_DELAY 5.0
64 #define SMB_CONFIGURATION_QUEUE "com.apple.config.smb-configuration"
66 static SCDynamicStoreRef store
= NULL
;
67 static CFRunLoopRef rl
= NULL
;
68 static CFRunLoopSourceRef rls
= NULL
;
69 static dispatch_queue_t queue
= NULL
;
71 static int notify_token
= -1;
73 static struct timeval ptrQueryStart
;
74 static SCNetworkReachabilityRef ptrTarget
= NULL
;
76 static CFRunLoopTimerRef timer
= NULL
;
82 static CFAbsoluteTime bt
= 0;
85 int mib
[2] = { CTL_KERN
, KERN_BOOTTIME
};
87 size_t tv_len
= sizeof(tv
);
89 if (sysctl(mib
, sizeof(mib
) / sizeof(mib
[0]), &tv
, &tv_len
, NULL
, 0) == -1) {
90 my_log(LOG_ERR
, "sysctl() CTL_KERN/KERN_BOOTTIME failed: %s", strerror(errno
));
91 return kCFAbsoluteTimeIntervalSince1970
;
94 // Note: we need to convert from Unix time to CF time.
95 bt
= (CFTimeInterval
)tv
.tv_sec
- kCFAbsoluteTimeIntervalSince1970
;
96 bt
+= (1.0E-6 * (CFTimeInterval
)tv
.tv_usec
);
104 copy_default_name(void)
108 CFMutableStringRef str
;
111 model
= _SC_hw_model(TRUE
);
116 // start off with the [trunated] HW model
117 str
= CFStringCreateMutable(NULL
, 0);
118 CFStringAppend(str
, model
);
120 // truncate as needed
121 n
= CFStringGetLength(str
);
122 if (n
> (NETBIOS_NAME_LEN
- 1)) {
124 CFRangeMake(NETBIOS_NAME_LEN
- 1, n
- (NETBIOS_NAME_LEN
- 1)),
126 n
= NETBIOS_NAME_LEN
- 1;
130 // if there is room for at least one byte (two hex characters)
131 // of the MAC address than append that to the NetBIOS name.
133 // NETBIOS_NAME_LEN max length
134 // -1 the last byte is reserved
137 if (n
< (NETBIOS_NAME_LEN
- 1 - 3)) {
138 SCNetworkInterfaceRef interface
;
140 interface
= _SCNetworkInterfaceCreateWithBSDName(NULL
, CFSTR("en0"),
141 kIncludeNoVirtualInterfaces
);
142 if (interface
!= NULL
) {
143 CFMutableStringRef en0_MAC
;
145 en0_MAC
= (CFMutableStringRef
)SCNetworkInterfaceGetHardwareAddressString(interface
);
146 if (en0_MAC
!= NULL
) {
149 // remove ":" characters from MAC address string
150 en0_MAC
= CFStringCreateMutableCopy(NULL
, 0, en0_MAC
);
151 CFStringFindAndReplace(en0_MAC
,
154 CFRangeMake(0, CFStringGetLength(en0_MAC
)),
158 // compute how may bytes (characters) to append
159 // ... and limit that number to 6
161 // NETBIOS_NAME_LEN max length
162 // -1 the last byte is reserved
166 n
= ((NETBIOS_NAME_LEN
- 1 - n
- 1) / 2) * 2;
171 // remove what we don't want
172 en0_MAC_len
= CFStringGetLength(en0_MAC
);
173 if (en0_MAC_len
> n
) {
174 CFStringDelete(en0_MAC
, CFRangeMake(0, en0_MAC_len
- n
));
178 CFStringAppendFormat(str
, NULL
, CFSTR("-%@"), en0_MAC
);
182 CFRelease(interface
);
186 CFStringUppercase(str
, NULL
);
191 static CFDictionaryRef
192 smb_copy_global_configuration(SCDynamicStoreRef store
)
194 CFDictionaryRef dict
;
197 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
,
198 kSCDynamicStoreDomainState
,
200 dict
= SCDynamicStoreCopyValue(store
, key
);
204 if (isA_CFDictionary(dict
)) {
211 dict
= CFDictionaryCreate(NULL
, // allocator
215 &kCFTypeDictionaryKeyCallBacks
,
216 &kCFTypeDictionaryValueCallBacks
);
222 update_pref(SCPreferencesRef prefs
, CFStringRef key
, CFTypeRef newVal
, Boolean
*changed
)
226 curVal
= SCPreferencesGetValue(prefs
, key
);
227 if (!_SC_CFEqual(curVal
, newVal
)) {
228 if (newVal
!= NULL
) {
229 SCPreferencesSetValue(prefs
, key
, newVal
);
231 SCPreferencesRemoveValue(prefs
, key
);
242 smb_set_configuration(SCDynamicStoreRef store
, CFDictionaryRef dict
)
245 Boolean changed
= FALSE
;
246 UInt32 dosCodepage
= 0;
247 CFStringEncoding dosEncoding
= 0;
248 CFStringEncoding macEncoding
= kCFStringEncodingMacRoman
;
249 uint32_t macRegion
= 0;
251 SCPreferencesRef prefs
;
254 prefs
= SCPreferencesCreate(NULL
, CFSTR("smb-configuration"), CFSTR(kSMBPreferencesAppID
));
257 "smb_set_configuration: SCPreferencesCreate() failed: %s",
258 SCErrorString(SCError()));
262 ok
= SCPreferencesLock(prefs
, TRUE
);
265 "smb_set_configuration: SCPreferencesLock() failed: %s",
266 SCErrorString(SCError()));
270 // Server description
271 str
= SCDynamicStoreCopyComputerName(store
, &macEncoding
);
272 update_pref(prefs
, CFSTR(kSMBPrefServerDescription
), str
, &changed
);
276 if (macEncoding
== kCFStringEncodingMacRoman
) {
278 CFDictionaryRef dict
;
281 key
= SCDynamicStoreKeyCreateComputerName(NULL
);
282 dict
= SCDynamicStoreCopyValue(store
, key
);
285 if (isA_CFDictionary(dict
)) {
289 num
= CFDictionaryGetValue(dict
, kSCPropSystemComputerNameRegion
);
290 if (isA_CFNumber(num
) &&
291 CFNumberGetValue(num
, kCFNumberSInt32Type
, &val
)) {
292 macRegion
= (uint32_t)val
;
302 // Important: must have root acccess (eUID==0) to access the config file!
303 __CFStringGetInstallationEncodingAndRegion((uint32_t *)&macEncoding
, &macRegion
);
305 _SC_dos_encoding_and_codepage(macEncoding
, macRegion
, &dosEncoding
, &dosCodepage
);
306 str
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%d"), (unsigned int)dosCodepage
);
308 update_pref(prefs
, CFSTR(kSMBPrefDOSCodePage
), str
, &changed
);
312 str
= CFDictionaryGetValue(dict
, kSCPropNetSMBNetBIOSName
);
313 str
= isA_CFString(str
);
314 update_pref(prefs
, CFSTR(kSMBPrefNetBIOSName
), str
, &changed
);
317 str
= CFDictionaryGetValue(dict
, kSCPropNetSMBNetBIOSNodeType
);
318 str
= isA_CFString(str
);
320 if (CFEqual(str
, kSCValNetSMBNetBIOSNodeTypeBroadcast
)) {
322 str
= CFSTR(kSMBPrefNetBIOSNodeBroadcast
);
323 } else if (CFEqual(str
, kSCValNetSMBNetBIOSNodeTypePeer
)) {
325 str
= CFSTR(kSMBPrefNetBIOSNodePeer
);
326 } else if (CFEqual(str
, kSCValNetSMBNetBIOSNodeTypeMixed
)) {
328 str
= CFSTR(kSMBPrefNetBIOSNodeMixed
);
329 } else if (CFEqual(str
, kSCValNetSMBNetBIOSNodeTypeHybrid
)) {
331 str
= CFSTR(kSMBPrefNetBIOSNodeHybrid
);
336 update_pref(prefs
, CFSTR(kSMBPrefNetBIOSNodeType
), str
, &changed
);
338 #ifdef ADD_NETBIOS_SCOPE
340 str
= CFDictionaryGetValue(dict
, kSCPropNetSMBNetBIOSScope
);
341 str
= isA_CFString(str
);
342 update_pref(prefs
, CFSTR(kSMBPrefNetBIOSScope
), str
, &changed
);
343 #endif // ADD_NETBIOS_SCOPE
346 array
= CFDictionaryGetValue(dict
, kSCPropNetSMBWINSAddresses
);
347 array
= isA_CFArray(array
);
348 update_pref(prefs
, CFSTR(kSMBPrefWINSServerAddressList
), array
, &changed
);
350 // Workgroup (or domain)
351 str
= CFDictionaryGetValue(dict
, kSCPropNetSMBWorkgroup
);
352 str
= isA_CFString(str
);
353 update_pref(prefs
, CFSTR(kSMBPrefWorkgroup
), str
, &changed
);
356 ok
= SCPreferencesCommitChanges(prefs
);
358 if ((SCError() != EROFS
)) {
360 "smb_set_configuration: SCPreferencesCommitChanges() failed: %s",
361 SCErrorString(SCError()));
366 ok
= SCPreferencesApplyChanges(prefs
);
369 "smb_set_configuration: SCPreferencesApplyChanges() failed: %s",
370 SCErrorString(SCError()));
377 (void) SCPreferencesUnlock(prefs
);
384 copy_primary_service(SCDynamicStoreRef store
)
386 CFDictionaryRef dict
;
388 CFStringRef serviceID
= NULL
;
390 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
,
391 kSCDynamicStoreDomainState
,
393 dict
= SCDynamicStoreCopyValue(store
, key
);
397 if (isA_CFDictionary(dict
)) {
398 serviceID
= CFDictionaryGetValue(dict
, kSCDynamicStorePropNetPrimaryService
);
399 if (isA_CFString(serviceID
)) {
413 copy_primary_ip(SCDynamicStoreRef store
, CFStringRef serviceID
)
415 CFStringRef address
= NULL
;
416 CFDictionaryRef dict
;
419 key
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
,
420 kSCDynamicStoreDomainState
,
423 dict
= SCDynamicStoreCopyValue(store
, key
);
427 if (isA_CFDictionary(dict
)) {
428 CFArrayRef addresses
;
430 addresses
= CFDictionaryGetValue(dict
, kSCPropNetIPv4Addresses
);
431 if (isA_CFArray(addresses
) && (CFArrayGetCount(addresses
) > 0)) {
432 address
= CFArrayGetValueAtIndex(addresses
, 0);
433 if (isA_CFString(address
)) {
450 if (ptrTarget
== NULL
) {
454 my_log(LOG_INFO
, "NetBIOS name: ptr query stop");
456 SCNetworkReachabilitySetCallback(ptrTarget
, NULL
, NULL
);
457 SCNetworkReachabilityUnscheduleFromRunLoop(ptrTarget
, rl
, kCFRunLoopDefaultMode
);
458 CFRelease(ptrTarget
);
466 ptr_query_callback(SCNetworkReachabilityRef target
, SCNetworkReachabilityFlags flags
, void *info
)
469 CFDictionaryRef dict
;
471 CFMutableDictionaryRef newDict
;
472 struct timeval ptrQueryComplete
;
473 struct timeval ptrQueryElapsed
;
475 (void) gettimeofday(&ptrQueryComplete
, NULL
);
476 timersub(&ptrQueryComplete
, &ptrQueryStart
, &ptrQueryElapsed
);
477 my_log(LOG_INFO
, "NetBIOS name: ptr query complete%s (query time = %ld.%3.3d)",
478 (flags
& kSCNetworkReachabilityFlagsReachable
) ? "" : ", host not found",
479 ptrQueryElapsed
.tv_sec
,
480 ptrQueryElapsed
.tv_usec
/ 1000);
482 // get network configuration
483 dict
= smb_copy_global_configuration(store
);
485 // use NetBIOS name from network configuration (if available)
486 name
= CFDictionaryGetValue(dict
, kSCPropNetSMBNetBIOSName
);
487 if ((name
!= NULL
) && _SC_CFStringIsValidNetBIOSName(name
)) {
488 my_log(LOG_INFO
, "NetBIOS name (network configuration) = %@", name
);
492 // use reverse DNS name, if available
495 if (flags
& kSCNetworkReachabilityFlagsReachable
) {
500 * if [reverse] DNS query was successful
502 hosts
= SCNetworkReachabilityCopyResolvedAddress(target
, &error_num
);
504 if (CFArrayGetCount(hosts
) > 0) {
506 CFMutableStringRef ptrName
;
509 name
= CFArrayGetValueAtIndex(hosts
, 0);
510 ptrName
= CFStringCreateMutableCopy(NULL
, 0, name
);
511 ptrLen
= CFStringGetLength(ptrName
);
512 if (CFStringFindWithOptions(ptrName
,
514 CFRangeMake(0, ptrLen
),
517 CFStringDelete(ptrName
,
518 CFRangeMake(range
.location
, ptrLen
- range
.location
));
526 if (_SC_CFStringIsValidNetBIOSName(name
)) {
527 my_log(LOG_INFO
, "NetBIOS name (reverse DNS query) = %@", name
);
533 // try local (multicast DNS) name, if available
534 name
= SCDynamicStoreCopyLocalHostName(store
);
536 if (_SC_CFStringIsValidNetBIOSName(name
)) {
537 my_log(LOG_INFO
, "NetBIOS name (multicast DNS) = %@", name
);
543 // use "default" name
544 name
= copy_default_name();
546 my_log(LOG_INFO
, "NetBIOS name (default) = %@", name
);
554 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
555 CFDictionarySetValue(newDict
, kSCPropNetSMBNetBIOSName
, name
);
562 // update SMB configuration
563 smb_set_configuration(store
, dict
);
577 ptr_query_start(CFStringRef address
)
581 struct sockaddr_in sin
;
582 struct sockaddr_in6 sin6
;
586 CFMutableDictionaryRef options
;
588 if (_SC_cfstring_to_cstring(address
, buf
, sizeof(buf
), kCFStringEncodingASCII
) == NULL
) {
589 my_log(LOG_ERR
, "could not convert [primary] address string");
593 if (_SC_string_to_sockaddr(buf
, AF_UNSPEC
, (void *)&addr
, sizeof(addr
)) == NULL
) {
594 my_log(LOG_ERR
, "could not convert [primary] address");
598 options
= CFDictionaryCreateMutable(NULL
,
600 &kCFTypeDictionaryKeyCallBacks
,
601 &kCFTypeDictionaryValueCallBacks
);
602 data
= CFDataCreate(NULL
, (const UInt8
*)&addr
.sa
, addr
.sa
.sa_len
);
603 CFDictionarySetValue(options
, kSCNetworkReachabilityOptionPTRAddress
, data
);
605 ptrTarget
= SCNetworkReachabilityCreateWithOptions(NULL
, options
);
607 if (ptrTarget
== NULL
) {
608 my_log(LOG_ERR
, "could not resolve [primary] address");
612 my_log(LOG_INFO
, "NetBIOS name: ptr query start");
614 (void) gettimeofday(&ptrQueryStart
, NULL
);
615 (void) SCNetworkReachabilitySetCallback(ptrTarget
, ptr_query_callback
, NULL
);
616 (void) SCNetworkReachabilityScheduleWithRunLoop(ptrTarget
, rl
, kCFRunLoopDefaultMode
);
623 smb_update_configuration(CFRunLoopTimerRef _timer
, void *info
)
625 #pragma unused(_timer)
626 CFStringRef address
= NULL
;
627 CFDictionaryRef dict
;
629 CFStringRef serviceID
= NULL
;
630 SCDynamicStoreRef store
= (SCDynamicStoreRef
)info
;
632 // get network configuration
633 dict
= smb_copy_global_configuration(store
);
635 // use NetBIOS name from network configuration (if available)
636 name
= CFDictionaryGetValue(dict
, kSCPropNetSMBNetBIOSName
);
637 if ((name
!= NULL
) && _SC_CFStringIsValidNetBIOSName(name
)) {
638 my_log(LOG_INFO
, "NetBIOS name (network configuration) = %@", name
);
642 // get primary service ID
643 serviceID
= copy_primary_service(store
);
644 if (serviceID
== NULL
) {
645 // if no primary service
649 // get DNS name associated with primary IP, if available
650 address
= copy_primary_ip(store
, serviceID
);
651 if (address
!= NULL
) {
654 // start reverse DNS query using primary IP address
655 ok
= ptr_query_start(address
);
664 // get local (multicast DNS) name, if available
666 name
= SCDynamicStoreCopyLocalHostName(store
);
668 if (_SC_CFStringIsValidNetBIOSName(name
)) {
669 CFMutableDictionaryRef newDict
;
671 my_log(LOG_INFO
, "NetBIOS name (multicast DNS) = %@", name
);
672 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
673 CFDictionarySetValue(newDict
, kSCPropNetSMBNetBIOSName
, name
);
682 // get "default" name
683 name
= copy_default_name();
685 CFMutableDictionaryRef newDict
;
687 my_log(LOG_INFO
, "NetBIOS name (default) = %@", name
);
688 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
689 CFDictionarySetValue(newDict
, kSCPropNetSMBNetBIOSName
, name
);
697 // update SMB configuration
698 smb_set_configuration(store
, dict
);
702 if (address
!= NULL
) CFRelease(address
);
703 if (dict
!= NULL
) CFRelease(dict
);
704 if (serviceID
!= NULL
) CFRelease(serviceID
);
707 CFRunLoopTimerInvalidate(timer
);
717 configuration_changed(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *info
)
719 #pragma unused(changedKeys)
721 CFRunLoopTimerContext context
= { 0, (void *)store
, CFRetain
, CFRelease
, NULL
};
722 CFAbsoluteTime time_boot
;
723 CFAbsoluteTime time_now
;
725 // if active, cancel any in-progress attempt to resolve the primary IP address
727 if (ptrTarget
!= NULL
) {
731 // if active, cancel any queued configuration change
733 CFRunLoopTimerInvalidate(timer
);
738 // queue configuration change
739 time_boot
= boottime() + SMB_STARTUP_DELAY
;
740 time_now
= CFAbsoluteTimeGetCurrent() + SMB_DEBOUNCE_DELAY
;
742 timer
= CFRunLoopTimerCreate(NULL
,
743 time_now
> time_boot
? time_now
: time_boot
,
747 smb_update_configuration
,
749 CFRunLoopAddTimer(rl
, timer
, kCFRunLoopDefaultMode
);
757 load_smb_configuration(Boolean verbose
)
759 #pragma unused(verbose)
761 CFMutableArrayRef keys
= NULL
;
762 dispatch_block_t notify_block
;
764 CFMutableArrayRef patterns
= NULL
;
767 /* initialize a few globals */
768 queue
= dispatch_queue_create(SMB_CONFIGURATION_QUEUE
, NULL
);
771 "dispatch_queue_create() failed");
775 store
= SCDynamicStoreCreate(NULL
, CFSTR("smb-configuration"), configuration_changed
, NULL
);
778 "SCDynamicStoreCreate() failed: %s",
779 SCErrorString(SCError()));
783 /* establish notification keys and patterns */
785 keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
786 patterns
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
788 /* ...watch for SMB configuration changes */
789 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
,
790 kSCDynamicStoreDomainState
,
792 CFArrayAppendValue(keys
, key
);
795 /* ...watch for ComputerName changes */
796 key
= SCDynamicStoreKeyCreateComputerName(NULL
);
797 CFArrayAppendValue(keys
, key
);
800 /* ...watch for local (multicast DNS) hostname changes */
801 key
= SCDynamicStoreKeyCreateHostNames(NULL
);
802 CFArrayAppendValue(keys
, key
);
805 /* register the keys/patterns */
806 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, patterns
);
811 "SCDynamicStoreSetNotificationKeys() failed: %s",
812 SCErrorString(SCError()));
816 rl
= CFRunLoopGetCurrent();
817 rls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, 0);
820 "SCDynamicStoreCreateRunLoopSource() failed: %s",
821 SCErrorString(SCError()));
824 CFRunLoopAddSource(rl
, rls
, kCFRunLoopDefaultMode
);
826 /* ...watch for primary service/interface and DNS configuration changes */
831 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
,
832 kSCDynamicStoreDomainState
,
834 changes
= CFArrayCreate(NULL
, (const void **)&key
, 1, &kCFTypeArrayCallBacks
);
835 (*configuration_changed
)(store
, changes
, NULL
);
841 status
= notify_register_dispatch(_SC_NOTIFY_NETWORK_CHANGE
,
845 #pragma unused(token)
846 CFRunLoopPerformBlock(rl
,
847 kCFRunLoopDefaultMode
,
851 if (status
!= NOTIFY_STATUS_OK
) {
852 my_log(LOG_ERR
, "notify_register_dispatch() failed: %u", status
);
861 CFRunLoopRemoveSource(rl
, rls
, kCFRunLoopDefaultMode
);
870 dispatch_release(queue
);
880 main(int argc
, char **argv
)
886 CFStringRef serviceID
;
887 SCDynamicStoreRef store
;
889 _sc_log
= kSCLogDestinationFile
;
890 if ((argc
> 1) && (strcmp(argv
[1], "-d") == 0)) {
896 store
= SCDynamicStoreCreate(NULL
, CFSTR("smb-configuration"), NULL
, NULL
);
898 SCPrint(TRUE
, stdout
,
899 CFSTR("SCDynamicStoreCreate() failed: %s\n"),
900 SCErrorString(SCError()));
904 // get "default" name
905 name
= copy_default_name();
907 SCPrint(TRUE
, stdout
, CFSTR("default name = %@\n"), name
);
911 // get primary service
912 serviceID
= copy_primary_service(store
);
913 if (serviceID
!= NULL
) {
914 SCPrint(TRUE
, stdout
, CFSTR("primary service ID = %@\n"), serviceID
);
916 SCPrint(TRUE
, stdout
, CFSTR("No primary service\n"));
920 if ((argc
== (2+1)) && (argv
[1][0] == 's')) {
921 if (serviceID
!= NULL
) CFRelease(serviceID
);
922 serviceID
= CFStringCreateWithCString(NULL
, argv
[2], kCFStringEncodingUTF8
);
923 SCPrint(TRUE
, stdout
, CFSTR("alternate service ID = %@\n"), serviceID
);
926 // get primary IP address
927 address
= copy_primary_ip(store
, serviceID
);
928 CFRelease(serviceID
);
929 if (address
!= NULL
) {
930 SCPrint(TRUE
, stdout
, CFSTR("primary address = %@\n"), address
);
932 if ((argc
== (2+1)) && (argv
[1][0] == 'a')) {
933 if (address
!= NULL
) CFRelease(address
);
934 address
= CFStringCreateWithCString(NULL
, argv
[2], kCFStringEncodingUTF8
);
935 SCPrint(TRUE
, stdout
, CFSTR("alternate primary address = %@\n"), address
);
938 // start reverse DNS query using primary IP address
939 (void) ptr_query_start(address
);
945 smb_update_configuration(NULL
, (void *)store
);
953 _sc_log
= kSCLogDestinationFile
;
954 _sc_verbose
= (argc
> 1) ? TRUE
: FALSE
;
956 load_smb_configuration((argc
> 1) ? TRUE
: FALSE
);