+#pragma mark -
+#pragma mark SMB
+
+
+static CFStringRef
+__cleanupName(CFStringRef name)
+{
+ CFMutableStringRef newName;
+
+ newName = CFStringCreateMutableCopy(NULL, 0, name);
+ CFStringTrimWhitespace(newName);
+ if (CFStringGetLength(newName) == 0) {
+ CFRelease(newName);
+ newName = NULL;
+ }
+
+ return newName;
+}
+
+
+static int
+__doSMBName(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("NetBIOS name not specified\n"));
+ return -1;
+ }
+
+ if (strlen(argv[0]) > 0) {
+ CFStringRef name;
+ CFStringRef str;
+
+ str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ name = __cleanupName(str);
+ CFRelease(str);
+
+ if (name != NULL) {
+ CFDictionarySetValue(newConfiguration, key, name);
+ CFRelease(name);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("invalid NetBIOS name\n"));
+ return -1;
+ }
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, key);
+ }
+
+ return 1;
+}
+
+
+static int
+__doSMBWorkgroup(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("Workgroup not specified\n"));
+ return -1;
+ }
+
+ if (strlen(argv[0]) > 0) {
+ CFStringRef name;
+ CFStringRef str;
+
+ str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ name = __cleanupName(str);
+ CFRelease(str);
+
+ if (name != NULL) {
+ CFDictionarySetValue(newConfiguration, key, name);
+ CFRelease(name);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("invalid Workgroup\n"));
+ return -1;
+ }
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, key);
+ }
+
+ return 1;
+}
+
+
+static int
+__doSMBWINSAddresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ CFMutableArrayRef servers;
+
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("WINS address(es) not specified\n"));
+ return -1;
+ }
+
+ servers = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ if (strlen(argv[0]) > 0) {
+ CFArrayRef array;
+ CFIndex i;
+ CFIndex n;
+ CFStringRef str;
+
+ str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(","));
+ CFRelease(str);
+
+ n = (array != NULL) ? CFArrayGetCount(array) : 0;
+ for (i = 0; i < n; i++) {
+ char str[32];
+
+ if (_SC_cfstring_to_cstring(CFArrayGetValueAtIndex(array, i),
+ str,
+ sizeof(str),
+ kCFStringEncodingUTF8) != NULL) {
+ CFStringRef server;
+
+ server = __copyIPv4Address(str);
+ //if (server == NULL) {
+ // server = __copyIPv6Address(str);
+ //}
+ if (server != NULL) {
+ CFArrayAppendValue(servers, server);
+ CFRelease(server);
+ continue;
+ }
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("invalid WINS address\n"));
+ CFRelease(array);
+ CFRelease(servers);
+ return -1;
+ }
+ if (array != NULL) CFRelease(array);
+ }
+
+ if (CFArrayGetCount(servers) > 0) {
+ CFDictionarySetValue(newConfiguration, key, servers);
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, key);
+ }
+
+ CFRelease(servers);
+ return 1;
+}
+
+
+static selections smbNodeTypes[] = {
+ { CFSTR("Broadcast"), &kSCValNetSMBNetBIOSNodeTypeBroadcast, 0 },
+ { CFSTR("Peer") , &kSCValNetSMBNetBIOSNodeTypePeer , 0 },
+ { CFSTR("Mixed") , &kSCValNetSMBNetBIOSNodeTypeMixed , 0 },
+ { CFSTR("Hybrid") , &kSCValNetSMBNetBIOSNodeTypeHybrid , 0 },
+ { NULL , NULL , 0 }
+};
+
+
+static options smbOptions[] = {
+ { "NetBIOSName" , "name" , isOther , &kSCPropNetSMBNetBIOSName , __doSMBName , NULL },
+ { "name" , "name" , isOther , &kSCPropNetSMBNetBIOSName , __doSMBName , NULL },
+ { "NetBIOSNodeType", "type" , isChooseOne, &kSCPropNetSMBNetBIOSNodeType, NULL , (void *)smbNodeTypes },
+ { "type", "type" , isChooseOne, &kSCPropNetSMBNetBIOSNodeType, NULL , (void *)smbNodeTypes },
+ { "Workgroup" , "workgroup", isOther , &kSCPropNetSMBWorkgroup , __doSMBWorkgroup , NULL },
+ { "WINSAddresses" , "wins" , isOther , &kSCPropNetSMBWINSAddresses , __doSMBWINSAddresses, NULL },
+ { "wins" , "wins" , isOther , &kSCPropNetSMBWINSAddresses , __doSMBWINSAddresses, NULL },
+
+ { "?" , NULL , isHelp , NULL , NULL,
+ "\nSMB configuration commands\n\n"
+ " set protocol name NetBIOS-name\n"
+ " set protocol type (Broadcast|Peer|Mixed|Hybrid)\n"
+ " set protocol workgroup SMB-workgroup\n"
+ " set protocol wins x1.x1.x1.x1[,x2.x2.x2.x2]"
+ }
+};
+#define N_SMB_OPTIONS (sizeof(smbOptions) / sizeof(smbOptions[0]))
+
+
+static Boolean
+set_protocol_smb(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ Boolean ok;
+
+ ok = _process_options(smbOptions, N_SMB_OPTIONS, argc, argv, newConfiguration);
+ return ok;
+}
+
+
+#pragma mark -
+#pragma mark *Protocol*