+ { "rank" , NULL, isOther , NULL , __doRank, NULL },
+
+ { "?" , NULL, isHelp , NULL , NULL,
+ "\nEthernet configuration commands\n\n"
+ " set interface [mtu n] [media type] [mediaopts opts]\n"
+ }
+};
+#define N_ETHERNET_OPTIONS (sizeof(ethernetOptions) / sizeof(ethernetOptions[0]))
+
+
+static Boolean
+set_interface_ethernet(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ CFStringRef interfaceName;
+ Boolean ok;
+
+ interfaceName = SCNetworkInterfaceGetBSDName(net_interface);
+ if (interfaceName == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("no BSD interface\n"));
+ return FALSE;
+ }
+
+ ok = _process_options(ethernetOptions, N_ETHERNET_OPTIONS, argc, argv, newConfiguration);
+ if (ok) {
+ // validate configuration
+ if (!validateMediaOptions(net_interface, newConfiguration)) {
+ return FALSE;
+ }
+ }
+
+ return ok;
+}
+
+
+#pragma mark -
+#pragma mark IPSec options
+
+
+static int
+__doIPSecSharedSecret(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ CFStringRef encryptionType;
+
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("IPSec shared secret not specified\n"));
+ return -1;
+ }
+
+ encryptionType = CFDictionaryGetValue(newConfiguration, kSCPropNetIPSecSharedSecretEncryption);
+ if (strlen(argv[0]) > 0) {
+ if (encryptionType == NULL) {
+#ifdef INLINE_PASSWORDS_USE_CFSTRING
+ CFStringRef pw;
+
+ pw = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+#else // INLINE_PASSWORDS_USE_CFSTRING
+ CFIndex n;
+ CFMutableDataRef pw;
+ CFStringRef str;
+
+ str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ n = CFStringGetLength(str);
+ pw = CFDataCreateMutable(NULL, n * sizeof(UniChar));
+ CFDataSetLength(pw, n * sizeof(UniChar));
+ /* ALIGN: CF aligns to at least >8 bytes */
+ CFStringGetCharacters(str,
+ CFRangeMake(0, n),
+ (UniChar *)(void *)CFDataGetMutableBytePtr(pw));
+ CFRelease(str);
+#endif // INLINE_PASSWORDS_USE_CFSTRING
+
+ CFDictionarySetValue(newConfiguration, key, pw);
+ CFRelease(pw);
+ } else if (CFEqual(encryptionType, kSCValNetIPSecSharedSecretEncryptionKeychain)) {
+ Boolean ok;
+ CFDataRef pw;
+ CFStringRef str;
+
+ str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ pw = CFStringCreateExternalRepresentation(NULL, str, kCFStringEncodingUTF8, 0);
+ ok = SCNetworkInterfaceSetPassword(net_interface,
+ kSCNetworkInterfacePasswordTypeIPSecSharedSecret,
+ pw,
+ NULL);
+ CFRelease(pw);
+ CFRelease(str);
+ if (ok) {
+ updateInterfaceConfiguration(newConfiguration);
+ } else {
+ return -1;
+ }
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("IPSec shared secret type \"%@\" not supported\n"), encryptionType);
+ return -1;
+ }
+ } else {
+ if (encryptionType == NULL) {
+ CFDictionaryRemoveValue(newConfiguration, key);
+ } else if (CFEqual(encryptionType, kSCValNetIPSecSharedSecretEncryptionKeychain)) {
+ Boolean ok;
+ ok = SCNetworkInterfaceRemovePassword(net_interface, kSCNetworkInterfacePasswordTypeIPSecSharedSecret);
+ if (ok) {
+ updateInterfaceConfiguration(newConfiguration);
+ } else {
+ return -1;
+ }
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("IPSec shared secret type \"%@\" not supported\n"), encryptionType);
+ return -1;
+ }
+ }
+
+ return 1;
+}
+
+
+static int
+__doIPSecSharedSecretType(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("IPSec shared secret type mode not specified\n"));
+ return -1;
+ }
+
+ if (strlen(argv[0]) > 0) {
+ if (strcasecmp(argv[0], "keychain") == 0) {
+ CFDictionarySetValue(newConfiguration, key, kSCValNetIPSecSharedSecretEncryptionKeychain);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("invalid shared secret type\n"));
+ return -1;
+ }
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, key);
+ }
+
+ // encryption type changed, reset shared secret
+ CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPSecSharedSecret);
+
+ return 1;
+}
+
+
+static int
+__doIPSecXAuthPassword(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ CFStringRef encryptionType;
+
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("IPSec XAuth password not specified\n"));
+ return -1;
+ }
+
+ encryptionType = CFDictionaryGetValue(newConfiguration, kSCPropNetIPSecXAuthPasswordEncryption);
+ if (strlen(argv[0]) > 0) {
+ if (encryptionType == NULL) {
+#ifdef INLINE_PASSWORDS_USE_CFSTRING
+ CFStringRef pw;
+
+ pw = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+#else // INLINE_PASSWORDS_USE_CFSTRING
+ CFIndex n;
+ CFMutableDataRef pw;
+ CFStringRef str;
+
+ str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ n = CFStringGetLength(str);
+ pw = CFDataCreateMutable(NULL, n * sizeof(UniChar));
+ CFDataSetLength(pw, n * sizeof(UniChar));
+ /* ALIGN: CF aligns to at least >8 byte boundries */
+ CFStringGetCharacters(str,
+ CFRangeMake(0, n),
+ (UniChar *)(void *)CFDataGetMutableBytePtr(pw));
+ CFRelease(str);
+#endif // INLINE_PASSWORDS_USE_CFSTRING
+
+ CFDictionarySetValue(newConfiguration, key, pw);
+ CFRelease(pw);
+ } else if (CFEqual(encryptionType, kSCValNetIPSecXAuthPasswordEncryptionKeychain)) {
+ Boolean ok;
+ CFDataRef pw;
+ CFStringRef str;
+
+ str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ pw = CFStringCreateExternalRepresentation(NULL, str, kCFStringEncodingUTF8, 0);
+ ok = SCNetworkInterfaceSetPassword(net_interface,
+ kSCNetworkInterfacePasswordTypeIPSecXAuth,
+ pw,
+ NULL);
+ CFRelease(pw);
+ CFRelease(str);
+ if (ok) {
+ updateInterfaceConfiguration(newConfiguration);
+ } else {
+ return -1;
+ }
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("IPSec XAuthPassword type \"%@\" not supported\n"), encryptionType);
+ return -1;
+ }
+ } else {
+ if (encryptionType == NULL) {
+ CFDictionaryRemoveValue(newConfiguration, key);
+ } else if (CFEqual(encryptionType, kSCValNetIPSecXAuthPasswordEncryptionKeychain)) {
+ Boolean ok;
+
+ ok = SCNetworkInterfaceRemovePassword(net_interface, kSCNetworkInterfacePasswordTypeIPSecXAuth);
+ if (ok) {
+ updateInterfaceConfiguration(newConfiguration);
+ } else {
+ return -1;
+ }
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("IPSec XAuthPassword type \"%@\" not supported\n"), encryptionType);
+ return -1;
+ }
+ }
+
+ return 1;
+}
+
+
+static int
+__doIPSecXAuthPasswordType(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("IPSec XAuth password type mode not specified\n"));
+ return -1;
+ }
+
+ if (strlen(argv[0]) > 0) {
+ if (strcasecmp(argv[0], "keychain") == 0) {
+ CFDictionarySetValue(newConfiguration, key, kSCValNetIPSecXAuthPasswordEncryptionKeychain);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("invalid XAuth password type\n"));
+ return -1;
+ }
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, key);
+ }
+
+ // encryption type changed, reset XAuthPassword
+ CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPSecXAuthPassword);
+
+ return 1;
+}
+
+
+static CF_RETURNS_RETAINED CFStringRef
+__cleanupDomainName(CFStringRef domain)
+{
+ CFMutableStringRef newDomain;
+
+ newDomain = CFStringCreateMutableCopy(NULL, 0, domain);
+ CFStringTrimWhitespace(newDomain);
+ CFStringTrim(newDomain, CFSTR("."));
+ if (CFStringGetLength(newDomain) == 0) {
+ CFRelease(newDomain);
+ newDomain = NULL;
+ }
+
+ return newDomain;
+}
+
+
+static int
+__doOnDemandDomains(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ CFMutableArrayRef domains;
+
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("OnDemand domain name(s) not specified\n"));
+ return -1;
+ }
+
+ domains = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ if (strlen(argv[0]) > 0) {
+ CFArrayRef array;
+ CFStringRef str;
+
+ str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(","));
+ CFRelease(str);
+
+ if (array != NULL) {
+ CFIndex i;
+ CFIndex n = CFArrayGetCount(array);
+
+ for (i = 0; i < n; i++) {
+ CFStringRef domain;
+
+ domain = __cleanupDomainName(CFArrayGetValueAtIndex(array, i));
+ if (domain != NULL) {
+ CFArrayAppendValue(domains, domain);
+ CFRelease(domain);
+ } else {
+ CFRelease(array);
+ CFRelease(domains);
+ SCPrint(TRUE, stdout, CFSTR("invalid OnDemand domain name\n"));
+ return -1;
+ }
+ }
+ CFRelease(array);
+ }
+ }
+
+ if (CFArrayGetCount(domains) > 0) {
+ CFDictionarySetValue(newConfiguration, key, domains);
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, key);
+ }
+
+ CFRelease(domains);
+ return 1;
+}
+
+
+static options ipsecOnDemandOptions[] = {
+ { "OnDemandMatchDomainsAlways" , "domain", isOther , &kSCPropNetIPSecOnDemandMatchDomainsAlways , __doOnDemandDomains, NULL },
+ { "always" , "domain", isOther , &kSCPropNetIPSecOnDemandMatchDomainsAlways , __doOnDemandDomains, NULL },
+ { "OnDemandMatchDomainsOnRetry", "domain", isOther , &kSCPropNetIPSecOnDemandMatchDomainsOnRetry, __doOnDemandDomains, NULL },
+ { "retry" , "domain", isOther , &kSCPropNetIPSecOnDemandMatchDomainsOnRetry, __doOnDemandDomains, NULL },
+ { "OnDemandMatchDomainsNever" , "domain", isOther , &kSCPropNetIPSecOnDemandMatchDomainsNever , __doOnDemandDomains, NULL },
+ { "never" , "domain", isOther , &kSCPropNetIPSecOnDemandMatchDomainsNever , __doOnDemandDomains, NULL },
+
+ { "?" , NULL , isHelp , NULL , NULL ,
+ "\nOnDemandMatch configuration commands\n\n"
+ " set interface OnDemandMatch always domain-name[,domain-name]\n"
+ " set interface OnDemandMatch retry domain-name[,domain-name]\n"
+ " set interface OnDemandMatch never domain-name[,domain-name]\n"
+ }
+};
+#define N_IPSEC_ONDEMAND_OPTIONS (sizeof(ipsecOnDemandOptions) / sizeof(ipsecOnDemandOptions[0]))
+
+
+static int
+__doIPSecOnDemandMatch(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ Boolean ok;
+
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("set what?\n"));
+ return -1;
+ }
+
+ ok = _process_options(ipsecOnDemandOptions, N_IPSEC_ONDEMAND_OPTIONS, argc, argv, newConfiguration);
+ if (!ok) {
+ goto done;
+ }
+
+ done :
+
+ return argc;
+}
+
+
+static selections ipsecAuthenticationMethodSelections[] = {
+ { CFSTR("SharedSecret"), &kSCValNetIPSecAuthenticationMethodSharedSecret, 0 },
+ { CFSTR("Certificate") , &kSCValNetIPSecAuthenticationMethodCertificate , 0 },
+ { CFSTR("Hybrid") , &kSCValNetIPSecAuthenticationMethodHybrid , 0 },
+ { NULL , NULL , 0 }
+};
+
+
+static selections ipsecLocalIdentifierTypeSelections[] = {
+ { CFSTR("KeyID") , &kSCValNetIPSecLocalIdentifierTypeKeyID , 0 },
+ { NULL , NULL , 0 }
+};
+
+
+static options ipsecOptions[] = {
+ { "AuthenticationMethod" , NULL, isChooseOne , &kSCPropNetIPSecAuthenticationMethod , NULL , (void *)ipsecAuthenticationMethodSelections },
+ { "LocalIdentifier" , NULL, isString , &kSCPropNetIPSecLocalIdentifier , NULL , NULL },
+ { "group" , NULL, isString , &kSCPropNetIPSecLocalIdentifier , NULL , NULL },
+ { "LocalIdentifierType" , NULL, isChooseOne , &kSCPropNetIPSecLocalIdentifierType , NULL , (void *)ipsecLocalIdentifierTypeSelections },
+ { "RemoteAddress" , NULL, isString , &kSCPropNetIPSecRemoteAddress , NULL , NULL },
+ { "SharedSecret" , NULL, isOther , &kSCPropNetIPSecSharedSecret , __doIPSecSharedSecret , NULL },
+ { "SharedSecretEncryption" , NULL, isOther , &kSCPropNetIPSecSharedSecretEncryption , __doIPSecSharedSecretType , NULL },
+
+ // --- XAuth: ---
+ { "XAuthEnabled" , NULL, isBoolean , &kSCPropNetIPSecXAuthEnabled , NULL , NULL },
+ { "XAuthName" , NULL, isString , &kSCPropNetIPSecXAuthName , NULL , NULL },
+ { "XAuthPassword" , NULL, isOther , &kSCPropNetIPSecXAuthPassword , __doIPSecXAuthPassword , NULL },
+ { "XAuthPasswordEncryption", NULL, isOther , &kSCPropNetIPSecXAuthPasswordEncryption, __doIPSecXAuthPasswordType, NULL },
+
+ // --- OnDemand: ---
+ { "OnDemandEnabled" , NULL, isBoolean , &kSCPropNetIPSecOnDemandEnabled , NULL , NULL },
+ { "OnDemandMatch" , NULL, isOther , NULL , __doIPSecOnDemandMatch , NULL },
+
+ { "?" , NULL , isHelp , NULL , NULL,
+ "\nIPSec configuration commands\n\n"
+ " set interface [AuthenticationMethod {SharedSecret|Certificate|Hybrid}]\n"
+ " set interface [LocalIdentifier group]\n"
+ " set interface [LocalIdentifierType {KeyID}]\n"
+ " set interface [RemoteAddress name-or-address]\n"
+ " set interface [SharedSecret secret]\n"
+ " set interface [SharedSecretEncryption {Keychain}]\n"
+ " set interface [XAuthEnabled {enable|disable}]\n"
+ " set interface [XAuthPassword password]\n"
+ " set interface [XAuthPasswordEncryption {Keychain}]\n"
+ " set interface [OnDemandEnabled {enable|disable}]\n"
+ " set interface [OnDemandMatch <match-options>]\n"
+ }
+};
+#define N_IPSEC_OPTIONS (sizeof(ipsecOptions) / sizeof(ipsecOptions[0]))
+
+
+static Boolean
+set_interface_ipsec(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ Boolean ok;
+
+ ok = _process_options(ipsecOptions, N_IPSEC_OPTIONS, argc, argv, newConfiguration);
+ return ok;
+}
+
+
+#pragma mark -
+#pragma mark FireWire options
+
+
+static options firewireOptions[] = {
+ { "mtu" , NULL, isNumber , &kSCPropNetEthernetMTU , NULL, NULL },
+ { "media" , NULL, isString , &kSCPropNetEthernetMediaSubType, NULL, NULL },
+ { "mediaopt" , NULL, isStringArray, &kSCPropNetEthernetMediaOptions, NULL, NULL },
+
+ { "?" , NULL , isHelp , NULL , NULL,
+ "\nFireWire configuration commands\n\n"
+ " set interface [mtu n] [media type] [mediaopts opts]\n"
+ }
+};
+#define N_FIREWIRE_OPTIONS (sizeof(firewireOptions) / sizeof(firewireOptions[0]))
+
+
+static Boolean
+set_interface_firewire(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ CFStringRef interfaceName;
+ Boolean ok;
+
+ interfaceName = SCNetworkInterfaceGetBSDName(net_interface);
+ if (interfaceName == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("no BSD interface\n"));
+ return FALSE;
+ }
+
+ ok = _process_options(firewireOptions, N_FIREWIRE_OPTIONS, argc, argv, newConfiguration);
+ if (ok) {
+ // validate configuration
+ if (!validateMediaOptions(net_interface, newConfiguration)) {
+ return FALSE;
+ }
+ }
+
+ return ok;
+}
+
+
+#pragma mark -
+#pragma mark Modem options
+
+
+static selections modemDialSelections[] = {
+ { CFSTR("ignore"), &kSCValNetModemDialModeIgnoreDialTone , 0 },
+ { CFSTR("manual"), &kSCValNetModemDialModeManual , 0 },
+ { CFSTR("wait") , &kSCValNetModemDialModeWaitForDialTone, 0 },
+ { NULL , NULL , 0 }
+};
+
+static options modemOptions[] = {
+ { "ConnectionScript" , "script", isString , &kSCPropNetModemConnectionScript , NULL, NULL },
+ { "DialMode" , "mode" , isChooseOne, &kSCPropNetModemDialMode , NULL, (void *)modemDialSelections },
+ { "CallWaiting" , NULL , isBoolean , &kSCPropNetModemHoldEnabled , NULL, NULL },
+ { "CallWaitingAlert" , NULL , isBoolean , &kSCPropNetModemHoldCallWaitingAudibleAlert, NULL, NULL },
+ { "CallWaitingDisconnectOnAnswer", NULL , isBoolean , &kSCPropNetModemHoldDisconnectOnAnswer , NULL, NULL },
+ { "DataCompression" , NULL , isBoolean , &kSCPropNetModemDataCompression , NULL, NULL },
+ { "ErrorCorrection" , NULL , isBoolean , &kSCPropNetModemErrorCorrection , NULL, NULL },
+ { "HoldReminder" , NULL , isBoolean , &kSCPropNetModemHoldReminder , NULL, NULL },
+ { "HoldReminderTime" , "time" , isNumber , &kSCPropNetModemHoldReminderTime , NULL, NULL },
+ { "PulseDial" , NULL , isBoolean , &kSCPropNetModemPulseDial , NULL, NULL },
+ { "Speaker" , NULL , isBoolean , &kSCPropNetModemSpeaker , NULL, NULL },
+
+ { "?" , NULL , isHelp , NULL , NULL,
+ "\nModem configuration commands\n\n"
+ " set interface [ConnectionScript connection-script]\n"
+ " set interface [CallWaiting {enable|disable}]\n"
+ " set interface [CallWaitingAlert {enable|disable}]\n"
+ " set interface [CallWaitingDisconnectOnAnswer {enable|disable}]\n"
+ " set interface [DialMode {ignore|wait}]\n"
+ " set interface [DataCompression {enable|disable}]\n"
+ " set interface [ErrorCorrection {enable|disable}]\n"
+ " set interface [HoldReminder {enable|disable}]\n"
+ " set interface [HoldReminderTime n]\n"
+ " set interface [PulseDial {enable|disable}]\n"
+ " set interface [Speaker {enable|disable}]\n"
+ }
+};
+#define N_MODEM_OPTIONS (sizeof(modemOptions) / sizeof(modemOptions[0]))
+
+
+static Boolean
+set_interface_modem(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ Boolean ok;
+
+ ok = _process_options(modemOptions, N_MODEM_OPTIONS, argc, argv, newConfiguration);
+ return ok;
+}
+
+
+#pragma mark -
+#pragma mark PPP options
+
+
+static int