X-Git-Url: https://git.saurik.com/apple/configd.git/blobdiff_plain/d6c893b2b88c79d2370e2c1a989b792a23b3e0da..17d3ee29fb04fcc79d3be0b9d5c7bcb377cfc610:/scutil.tproj/net_interface.c diff --git a/scutil.tproj/net_interface.c b/scutil.tproj/net_interface.c index f6133eb..ba12204 100644 --- a/scutil.tproj/net_interface.c +++ b/scutil.tproj/net_interface.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2005 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2004-2011 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -29,13 +29,21 @@ */ +#include #include "scutil.h" #include "net.h" +#include "prefs.h" #include -/* -------------------- */ +#if TARGET_OS_EMBEDDED +#define INLINE_PASSWORDS_USE_CFSTRING +#endif // TARGET_OS_EMBEDDED + + +#pragma mark - +#pragma mark Interface management static CFArrayRef @@ -44,7 +52,7 @@ _copy_interfaces() CFMutableArrayRef interfaces; CFArrayRef real_interfaces; - real_interfaces = SCNetworkInterfaceCopyAll(); + real_interfaces = _SCNetworkInterfaceCopyAllWithPreferences(prefs); if (real_interfaces == NULL) { SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError())); return NULL; @@ -59,6 +67,7 @@ _copy_interfaces() CFRelease(real_interfaces); // include pseudo interfaces + CFArrayAppendValue(interfaces, kSCNetworkInterfaceLoopback); CFArrayAppendValue(interfaces, kSCNetworkInterfaceIPv4); // include interfaces that we have created @@ -74,15 +83,23 @@ _copy_interfaces() __private_extern__ SCNetworkInterfaceRef -_find_interface(char *match) +_find_interface(int argc, char **argv, int *nArgs) { Boolean allowIndex = TRUE; CFIndex i; + CFArrayRef myInterfaces = interfaces; CFIndex n; CFStringRef select_name = NULL; SCNetworkInterfaceRef selected = NULL; - if (strcasecmp(match, "$child") == 0) { + if (argc < 1) { + SCPrint(TRUE, stdout, CFSTR("no interface specified\n")); + return NULL; + } + + if (nArgs != NULL) *nArgs = 1; + + if (strcasecmp(argv[0], "$child") == 0) { if (net_interface == NULL) { SCPrint(TRUE, stdout, CFSTR("interface not selected\n")); goto done; @@ -94,7 +111,7 @@ _find_interface(char *match) } goto done; - } else if (strcasecmp(match, "$service") == 0) { + } else if (strcasecmp(argv[0], "$service") == 0) { if (net_service == NULL) { SCPrint(TRUE, stdout, CFSTR("service not selected\n")); goto done; @@ -108,24 +125,109 @@ _find_interface(char *match) goto done; } - if (interfaces == NULL) { +#if !TARGET_OS_IPHONE + else if (strcasecmp(argv[0], "$bond") == 0) { + CFStringRef interfaceType; + + if (net_interface == NULL) { + SCPrint(TRUE, stdout, CFSTR("interface not selected\n")); + goto done; + } + + interfaceType = SCNetworkInterfaceGetInterfaceType(net_interface); + if (!CFEqual(interfaceType, kSCNetworkInterfaceTypeBond)) { + SCPrint(TRUE, stdout, CFSTR("interface not Bond\n")); + goto done; + } + + if (argc < 2) { + SCPrint(TRUE, stdout, CFSTR("no member interface specified\n")); + return NULL; + } + argv++; + argc--; + if (nArgs != NULL) *nArgs += 1; + + myInterfaces = SCBondInterfaceGetMemberInterfaces(net_interface); + if (myInterfaces == NULL) { + SCPrint(TRUE, stdout, CFSTR("no member interfaces\n")); + goto done; + } + allowIndex = FALSE; + } +#endif // !TARGET_OS_IPHONE + + else if (strcasecmp(argv[0], "$bridge") == 0) { + CFStringRef interfaceType; + + if (net_interface == NULL) { + SCPrint(TRUE, stdout, CFSTR("interface not selected\n")); + goto done; + } + + interfaceType = SCNetworkInterfaceGetInterfaceType(net_interface); + if (!CFEqual(interfaceType, kSCNetworkInterfaceTypeBridge)) { + SCPrint(TRUE, stdout, CFSTR("interface not Bridge\n")); + goto done; + } + + if (argc < 2) { + SCPrint(TRUE, stdout, CFSTR("no member interface specified\n")); + return NULL; + } + argv++; + argc--; + if (nArgs != NULL) *nArgs += 1; + + myInterfaces = SCBridgeInterfaceGetMemberInterfaces(net_interface); + if (myInterfaces == NULL) { + SCPrint(TRUE, stdout, CFSTR("no member interfaces\n")); + goto done; + } + allowIndex = FALSE; + } + + else if (strcasecmp(argv[0], "$vlan") == 0) { + CFStringRef interfaceType; + + if (net_interface == NULL) { + SCPrint(TRUE, stdout, CFSTR("interface not selected\n")); + goto done; + } + + interfaceType = SCNetworkInterfaceGetInterfaceType(net_interface); + if (!CFEqual(interfaceType, kSCNetworkInterfaceTypeVLAN)) { + SCPrint(TRUE, stdout, CFSTR("interface not VLAN\n")); + goto done; + } + + selected = SCVLANInterfaceGetPhysicalInterface(net_interface); + if(selected == NULL) { + SCPrint(TRUE, stdout, CFSTR("no physical interface\n")); + } + + goto done; + } + + if ((myInterfaces == NULL) && (interfaces == NULL)) { interfaces = _copy_interfaces(); if (interfaces == NULL) { return NULL; } + myInterfaces = interfaces; allowIndex = FALSE; } // try to select the interface by its display name - select_name = CFStringCreateWithCString(NULL, match, kCFStringEncodingUTF8); + select_name = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); - n = CFArrayGetCount(interfaces); + n = (myInterfaces != NULL) ? CFArrayGetCount(myInterfaces) : 0; for (i = 0; i < n; i++) { SCNetworkInterfaceRef interface; CFStringRef interfaceName; - interface = CFArrayGetValueAtIndex(interfaces, i); + interface = CFArrayGetValueAtIndex(myInterfaces, i); interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface); if ((interfaceName != NULL) && CFEqual(select_name, interfaceName)) { if (selected == NULL) { @@ -149,13 +251,13 @@ _find_interface(char *match) SCNetworkInterfaceRef interface; CFStringRef bsd_name = NULL; - interface = CFArrayGetValueAtIndex(interfaces, i); - while ((interface != NULL) && (bsd_name == NULL)) { - bsd_name = SCNetworkInterfaceGetBSDName(interface); - if (bsd_name == NULL) { - interface = SCNetworkInterfaceGetInterface(interface); - } - } + interface = CFArrayGetValueAtIndex(myInterfaces, i); + while ((interface != NULL) && (bsd_name == NULL)) { + bsd_name = SCNetworkInterfaceGetBSDName(interface); + if (bsd_name == NULL) { + interface = SCNetworkInterfaceGetInterface(interface); + } + } if ((bsd_name != NULL) && CFEqual(select_name, bsd_name)) { if (selected == NULL) { @@ -179,7 +281,7 @@ _find_interface(char *match) SCNetworkInterfaceRef interface; CFStringRef interfaceType; - interface = CFArrayGetValueAtIndex(interfaces, i); + interface = CFArrayGetValueAtIndex(myInterfaces, i); interfaceType = SCNetworkInterfaceGetInterfaceType(interface); if (CFEqual(select_name, interfaceType)) { if (selected == NULL) { @@ -199,7 +301,7 @@ _find_interface(char *match) if (allowIndex) { char *end; - char *str = match; + char *str = argv[0]; long val; // try to select the interface by its index @@ -210,7 +312,7 @@ _find_interface(char *match) ((*end == '\0') || (*end == '.')) && (errno == 0)) { if ((val > 0) && (val <= n)) { - selected = CFArrayGetValueAtIndex(interfaces, val - 1); + selected = CFArrayGetValueAtIndex(myInterfaces, val - 1); if (*end == '.') { str = end + 1; @@ -259,36 +361,41 @@ create_interface(int argc, char **argv) } interfaceType = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); + argv++; + argc--; + if (CFEqual(interfaceType, kSCNetworkInterfaceTypeBond)) { + SCPrint(TRUE, stdout, CFSTR("bond creation not yet supported\n")); + goto done; + } + if (CFEqual(interfaceType, kSCNetworkInterfaceTypeBridge)) { + SCPrint(TRUE, stdout, CFSTR("bridge creation not yet supported\n")); + goto done; + } if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVLAN)) { -// xxxxx -SCPrint(TRUE, stdout, CFSTR("vlan creation not yet supported\n")); -goto done; - } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeBond)) { -// xxxxx -SCPrint(TRUE, stdout, CFSTR("bond creation not yet supported\n")); -goto done; - } else { - if (argc < 2) { - if (net_interface == NULL) { - SCPrint(TRUE, stdout, CFSTR("no network interface selected\n")); - goto done; - } + SCPrint(TRUE, stdout, CFSTR("vlan creation not yet supported\n")); + goto done; + } - interface = net_interface; - } else { - interface = _find_interface(argv[1]); + if (argc < 1) { + if (net_interface == NULL) { + SCPrint(TRUE, stdout, CFSTR("no network interface selected\n")); + goto done; } - if (interface == NULL) { - return; - } + interface = net_interface; + } else { + interface = _find_interface(argc, argv, NULL); + } - new_interface = SCNetworkInterfaceCreateWithInterface(interface, interfaceType); - if (new_interface == NULL) { - SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError())); - goto done; - } + if (interface == NULL) { + goto done; + } + + new_interface = SCNetworkInterfaceCreateWithInterface(interface, interfaceType); + if (new_interface == NULL) { + SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError())); + goto done; } if (new_interfaces == NULL) { @@ -324,8 +431,7 @@ select_interface(int argc, char **argv) { SCNetworkInterfaceRef interface; - interface = _find_interface(argv[0]); - + interface = _find_interface(argc, argv, NULL); if (interface != NULL) { CFStringRef interfaceName; @@ -388,11 +494,57 @@ _show_interface(SCNetworkInterfaceRef interface, CFStringRef prefix, Boolean sho if (if_bsd_name != NULL) { CFArrayRef available; CFDictionaryRef active; + CFDictionaryRef cap_current; int mtu_cur; int mtu_min; int mtu_max; - if (NetworkInterfaceCopyMTU(if_bsd_name, &mtu_cur, &mtu_min, &mtu_max)) { + cap_current = SCNetworkInterfaceCopyCapability(interface, NULL); + if (cap_current != NULL) { + CFIndex i; + CFArrayRef cap_names; + CFMutableArrayRef cap_sorted; + const void **keys; + CFIndex n; + + n = CFDictionaryGetCount(cap_current); + keys = CFAllocatorAllocate(NULL, n * sizeof(CFStringRef), 0); + CFDictionaryGetKeysAndValues(cap_current, keys, NULL); + cap_names = CFArrayCreate(NULL, keys, n, &kCFTypeArrayCallBacks); + CFAllocatorDeallocate(NULL, keys); + + cap_sorted = CFArrayCreateMutableCopy(NULL, 0, cap_names); + CFRelease(cap_names); + + CFArraySortValues(cap_sorted, CFRangeMake(0, n), (CFComparatorFunction)CFStringCompare, NULL); + + SCPrint(TRUE, stdout, CFSTR("%@ capabilities = "), prefix); + for (i = 0; i < n; i++) { + CFStringRef cap_name; + int cap_val; + CFNumberRef val = NULL; + + cap_name = CFArrayGetValueAtIndex(cap_sorted, i); + if (configuration != NULL) { + val = CFDictionaryGetValue(configuration, cap_name); + } + if (!isA_CFNumber(val)) { + val = CFDictionaryGetValue(cap_current, cap_name); + } + + SCPrint(TRUE, stdout, CFSTR("%s%@%c"), + (i == 0) ? "" : ",", + cap_name, + (CFNumberGetValue(val, kCFNumberIntType, &cap_val) && + (cap_val != 0)) ? '+' : '-'); + } + SCPrint(TRUE, stdout, CFSTR("\n")); + + CFRelease(cap_sorted); + CFRelease(cap_current); + } + + if (SCNetworkInterfaceCopyMTU(interface, &mtu_cur, &mtu_min, &mtu_max)) { char isCurrent = '*'; if (configuration != NULL) { @@ -409,7 +561,7 @@ _show_interface(SCNetworkInterfaceRef interface, CFStringRef prefix, Boolean sho } } - SCPrint(TRUE, stdout, CFSTR("%@ mtu %c = %ld (%ld < n < %ld)\n"), + SCPrint(TRUE, stdout, CFSTR("%@ mtu %c = %d (%d < n < %d)\n"), prefix, isCurrent, mtu_cur, @@ -417,7 +569,7 @@ _show_interface(SCNetworkInterfaceRef interface, CFStringRef prefix, Boolean sho mtu_max); } - if (NetworkInterfaceCopyMediaOptions(if_bsd_name, NULL, &active, &available, TRUE)) { + if (SCNetworkInterfaceCopyMediaOptions(interface, NULL, &active, &available, TRUE)) { char isCurrent = ' '; CFArrayRef options = NULL; CFArrayRef options_req = NULL; @@ -480,7 +632,7 @@ _show_interface(SCNetworkInterfaceRef interface, CFStringRef prefix, Boolean sho CFIndex n_subtypes; CFArrayRef subtypes; - subtypes = NetworkInterfaceCopyMediaSubTypes(available); + subtypes = SCNetworkInterfaceCopyMediaSubTypes(available); n_subtypes = (subtypes != NULL) ? CFArrayGetCount(subtypes) : 0; for (i = 0; i < n_subtypes; i++) { CFIndex j; @@ -489,7 +641,7 @@ _show_interface(SCNetworkInterfaceRef interface, CFStringRef prefix, Boolean sho CFArrayRef subtype_options; subtype = CFArrayGetValueAtIndex(subtypes, i); - subtype_options = NetworkInterfaceCopyMediaSubTypeOptions(available, subtype); + subtype_options = SCNetworkInterfaceCopyMediaSubTypeOptions(available, subtype); n_subtype_options = (subtype_options != NULL) ? CFArrayGetCount(subtype_options) : 0; for (j = 0; j < n_subtype_options; j++) { char isCurrent = ' '; @@ -524,8 +676,9 @@ _show_interface(SCNetworkInterfaceRef interface, CFStringRef prefix, Boolean sho SCPrint(TRUE, stdout, CFSTR("\n")); } - CFRelease(subtype_options); + if (subtype_options != NULL) CFRelease(subtype_options); } + if (subtypes != NULL) CFRelease(subtypes); } } else { SCPrint(TRUE, stdout, CFSTR("\n")); @@ -575,12 +728,33 @@ _show_interface(SCNetworkInterfaceRef interface, CFStringRef prefix, Boolean sho if (CFDictionaryGetCount(effective) > 0) { SCPrint(TRUE, stdout, CFSTR("\n%@ per-interface configuration\n"), prefix); - _show_entity(configuration, prefix); + _show_entity(effective, prefix); } CFRelease(effective); } + if (CFEqual(if_type, kSCNetworkInterfaceTypePPP)) { + SCNetworkInterfaceRef childInterface; + + childInterface = SCNetworkInterfaceGetInterface(interface); + if (childInterface != NULL) { + CFStringRef childInterfaceType; + + childInterfaceType = SCNetworkInterfaceGetInterfaceType(childInterface); + if (CFEqual(childInterfaceType, kSCNetworkInterfaceTypeL2TP)) { + CFDictionaryRef ipsec_configuration; + + ipsec_configuration = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec); + if (isA_CFDictionary(ipsec_configuration) && + (CFDictionaryGetCount(ipsec_configuration) > 0)) { + SCPrint(TRUE, stdout, CFSTR("\n%@ per-interface IPSec configuration\n"), prefix); + _show_entity(ipsec_configuration, prefix); + } + } + } + } + if (_sc_debug) { SCPrint(TRUE, stdout, CFSTR("\n%@\n"), interface); } @@ -603,7 +777,7 @@ _show_interface(SCNetworkInterfaceRef interface, CFStringRef prefix, Boolean sho static Boolean -validateMediaOptions(CFStringRef interfaceName, CFMutableDictionaryRef newConfiguration) +validateMediaOptions(SCNetworkInterfaceRef interface, CFMutableDictionaryRef newConfiguration) { Boolean ok = TRUE; CFNumberRef mtu; @@ -616,7 +790,7 @@ validateMediaOptions(CFStringRef interfaceName, CFMutableDictionaryRef newConfig int mtu_min; int mtu_val; - if (!NetworkInterfaceCopyMTU(interfaceName, NULL, &mtu_min, &mtu_max)) { + if (!SCNetworkInterfaceCopyMTU(interface, NULL, &mtu_min, &mtu_max)) { SCPrint(TRUE, stdout, CFSTR("cannot set MTU\n")); return FALSE; } @@ -644,12 +818,7 @@ validateMediaOptions(CFStringRef interfaceName, CFMutableDictionaryRef newConfig config_options = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); } - if (interfaceName == NULL) { - SCPrint(TRUE, stdout, CFSTR("media type / options not available\n")); - goto checked; - } - - if (!NetworkInterfaceCopyMediaOptions(interfaceName, NULL, NULL, &available, FALSE)) { + if (!SCNetworkInterfaceCopyMediaOptions(interface, NULL, NULL, &available, FALSE)) { SCPrint(TRUE, stdout, CFSTR("media type / options not available\n")); goto checked; } @@ -658,7 +827,7 @@ validateMediaOptions(CFStringRef interfaceName, CFMutableDictionaryRef newConfig goto checked; } - subtypes = NetworkInterfaceCopyMediaSubTypes(available); + subtypes = SCNetworkInterfaceCopyMediaSubTypes(available); if ((subtypes == NULL) || !CFArrayContainsValue(subtypes, CFRangeMake(0, CFArrayGetCount(subtypes)), @@ -667,7 +836,7 @@ validateMediaOptions(CFStringRef interfaceName, CFMutableDictionaryRef newConfig goto checked; } - subtype_options = NetworkInterfaceCopyMediaSubTypeOptions(available, subtype); + subtype_options = SCNetworkInterfaceCopyMediaSubTypeOptions(available, subtype); if ((subtype_options == NULL) || !CFArrayContainsValue(subtype_options, CFRangeMake(0, CFArrayGetCount(subtype_options)), @@ -763,33 +932,108 @@ show_interfaces(int argc, char **argv) /* -------------------- */ -static Boolean -set_interface_bond(int argc, char **argv, CFMutableDictionaryRef newConfiguration) +static int +__doRank(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) { -// xxxxx ("+device", "-device") -SCPrint(TRUE, stdout, CFSTR("bond interface management not yet supported\n")); - return FALSE; + SCNetworkInterfaceRef interface; + CFStringRef interfaceName; + Boolean ok = FALSE; + SCNetworkServicePrimaryRank rank = kSCNetworkServicePrimaryRankDefault; + SCDynamicStoreRef store; + + if (argc < 1) { + SCPrint(TRUE, stdout, + CFSTR("%s not specified\n"), + description != NULL ? description : "rank"); + return -1; + } + + if (strlen(argv[0]) == 0) { + rank = kSCNetworkServicePrimaryRankDefault; + } else if ((strcasecmp(argv[0], "First") == 0)) { + rank = kSCNetworkServicePrimaryRankFirst; + } else if ((strcasecmp(argv[0], "Last") == 0)) { + rank = kSCNetworkServicePrimaryRankLast; + } else if ((strcasecmp(argv[0], "Never") == 0)) { + rank = kSCNetworkServicePrimaryRankNever; + } else { + SCPrint(TRUE, stdout, CFSTR("invalid rank\n")); + return -1; + } + + interfaceName = SCNetworkInterfaceGetBSDName(net_interface); + if (interfaceName == NULL) { + SCPrint(TRUE, stdout, CFSTR("no BSD interface\n")); + return FALSE; + } + + store = SCDynamicStoreCreate(NULL, CFSTR("scutil --net"), NULL, NULL); + interface = _SCNetworkInterfaceCopyActive(store, interfaceName); + CFRelease(store); + if (interface == NULL) { + SCPrint(TRUE, stdout, CFSTR("No active interface\n")); + return -1; + } + + ok = SCNetworkInterfaceSetPrimaryRank(interface, rank); + CFRelease(interface); + if (!ok) { + SCPrint(TRUE, stdout, CFSTR("could not update per-interface rank\n")); + return -1; + } + + return 1; } /* -------------------- */ -static options airportOptions[] = { +static void +_replaceOne(const void *key, const void *value, void *context) +{ + CFMutableDictionaryRef newConfiguration = (CFMutableDictionaryRef)context; + + CFDictionarySetValue(newConfiguration, key, value); + return; +} + + +static void +updateInterfaceConfiguration(CFMutableDictionaryRef newConfiguration) +{ + CFDictionaryRef configuration; + + CFDictionaryRemoveAllValues(newConfiguration); + + configuration = SCNetworkInterfaceGetConfiguration(net_interface); + if (configuration != NULL) { + CFDictionaryApplyFunction(configuration, _replaceOne, (void *)newConfiguration); + } + + return; +} + + +#pragma mark - +#pragma mark Bond options + + +static options bondOptions[] = { { "mtu" , NULL, isNumber , &kSCPropNetEthernetMTU , NULL, NULL }, - { "media" , NULL, isString , &kSCPropNetEthernetMediaSubType, NULL, NULL }, - { "mediaopt" , NULL, isStringArray, &kSCPropNetEthernetMediaOptions, NULL, NULL }, + // xxx { "+device" , ... }, + // xxx { "-device" , ... }, { "?" , NULL , isHelp , NULL , NULL, - "\nAirPort configuration commands\n\n" - " set interface [mtu n] [media type] [mediaopts opts]\n" + "\nBond configuration commands\n\n" + " set interface [mtu n] [media type] [mediaopts opts]\n" } }; -#define N_AIRPORT_OPTIONS (sizeof(airportOptions) / sizeof(airportOptions[0])) +#define N_BOND_OPTIONS (sizeof(bondOptions) / sizeof(bondOptions[0])) static Boolean -set_interface_airport(int argc, char **argv, CFMutableDictionaryRef newConfiguration) +set_interface_bond(int argc, char **argv, CFMutableDictionaryRef newConfiguration) { CFStringRef interfaceName; Boolean ok; @@ -800,10 +1044,10 @@ set_interface_airport(int argc, char **argv, CFMutableDictionaryRef newConfigura return FALSE; } - ok = _process_options(airportOptions, N_AIRPORT_OPTIONS, argc, argv, newConfiguration); + ok = _process_options(bondOptions, N_BOND_OPTIONS, argc, argv, newConfiguration); if (ok) { // validate configuration - if (!validateMediaOptions(interfaceName, newConfiguration)) { + if (!validateMediaOptions(net_interface, newConfiguration)) { return FALSE; } } @@ -812,24 +1056,25 @@ set_interface_airport(int argc, char **argv, CFMutableDictionaryRef newConfigura } -/* -------------------- */ +#pragma mark - +#pragma mark Bridge options -static options ethernetOptions[] = { +static options bridgeOptions[] = { { "mtu" , NULL, isNumber , &kSCPropNetEthernetMTU , NULL, NULL }, - { "media" , NULL, isString , &kSCPropNetEthernetMediaSubType, NULL, NULL }, - { "mediaopt" , NULL, isStringArray, &kSCPropNetEthernetMediaOptions, NULL, NULL }, +// xxx { "+device" , ... }, +// xxx { "-device" , ... }, { "?" , NULL , isHelp , NULL , NULL, - "\nEthernet configuration commands\n\n" + "\nBridge configuration commands\n\n" " set interface [mtu n] [media type] [mediaopts opts]\n" } }; -#define N_ETHERNET_OPTIONS (sizeof(ethernetOptions) / sizeof(ethernetOptions[0])) +#define N_BRIDGE_OPTIONS (sizeof(bridgeOptions) / sizeof(bridgeOptions[0])) static Boolean -set_interface_ethernet(int argc, char **argv, CFMutableDictionaryRef newConfiguration) +set_interface_bridge(int argc, char **argv, CFMutableDictionaryRef newConfiguration) { CFStringRef interfaceName; Boolean ok; @@ -840,10 +1085,10 @@ set_interface_ethernet(int argc, char **argv, CFMutableDictionaryRef newConfigur return FALSE; } - ok = _process_options(ethernetOptions, N_ETHERNET_OPTIONS, argc, argv, newConfiguration); + ok = _process_options(bridgeOptions, N_BRIDGE_OPTIONS, argc, argv, newConfiguration); if (ok) { // validate configuration - if (!validateMediaOptions(interfaceName, newConfiguration)) { + if (!validateMediaOptions(net_interface, newConfiguration)) { return FALSE; } } @@ -852,24 +1097,27 @@ set_interface_ethernet(int argc, char **argv, CFMutableDictionaryRef newConfigur } -/* -------------------- */ +#pragma mark - +#pragma mark AirPort options -static options firewireOptions[] = { +static options airportOptions[] = { { "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" + { "rank" , NULL, isOther , NULL , __doRank, NULL }, + + { "?" , NULL, isHelp , NULL , NULL, + "\nAirPort configuration commands\n\n" " set interface [mtu n] [media type] [mediaopts opts]\n" } }; -#define N_FIREWIRE_OPTIONS (sizeof(firewireOptions) / sizeof(firewireOptions[0])) +#define N_AIRPORT_OPTIONS (sizeof(airportOptions) / sizeof(airportOptions[0])) static Boolean -set_interface_firewire(int argc, char **argv, CFMutableDictionaryRef newConfiguration) +set_interface_airport(int argc, char **argv, CFMutableDictionaryRef newConfiguration) { CFStringRef interfaceName; Boolean ok; @@ -880,10 +1128,10 @@ set_interface_firewire(int argc, char **argv, CFMutableDictionaryRef newConfigur return FALSE; } - ok = _process_options(firewireOptions, N_FIREWIRE_OPTIONS, argc, argv, newConfiguration); + ok = _process_options(airportOptions, N_AIRPORT_OPTIONS, argc, argv, newConfiguration); if (ok) { // validate configuration - if (!validateMediaOptions(interfaceName, newConfiguration)) { + if (!validateMediaOptions(net_interface, newConfiguration)) { return FALSE; } } @@ -892,73 +1140,596 @@ set_interface_firewire(int argc, char **argv, CFMutableDictionaryRef newConfigur } -/* -------------------- */ - +#pragma mark - +#pragma mark Ethernet 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 }, +static int +__doCapability(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) +{ + Boolean ok = FALSE; - { "?" , 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}]" + if (argc < 1) { + SCPrint(TRUE, stdout, + CFSTR("%s not specified\n"), + description != NULL ? description : "enable/disable"); + return -1; } -}; -#define N_MODEM_OPTIONS (sizeof(modemOptions) / sizeof(modemOptions[0])) + if (strlen(argv[0]) == 0) { + ok = SCNetworkInterfaceSetCapability(net_interface, key, NULL); + } else if ((strcasecmp(argv[0], "disable") == 0) || + (strcasecmp(argv[0], "no" ) == 0) || + (strcasecmp(argv[0], "off" ) == 0) || + (strcasecmp(argv[0], "0" ) == 0)) { + ok = SCNetworkInterfaceSetCapability(net_interface, key, CFNumberRef_0); + } else if ((strcasecmp(argv[0], "enable") == 0) || + (strcasecmp(argv[0], "yes" ) == 0) || + (strcasecmp(argv[0], "on" ) == 0) || + (strcasecmp(argv[0], "1" ) == 0)) { + ok = SCNetworkInterfaceSetCapability(net_interface, key, CFNumberRef_1); + } else { + SCPrint(TRUE, stdout, CFSTR("invalid value\n")); + return -1; + } -static Boolean -set_interface_modem(int argc, char **argv, CFMutableDictionaryRef newConfiguration) -{ - Boolean ok; + if (ok) { + updateInterfaceConfiguration(newConfiguration); + } else { + SCPrint(TRUE, stdout, + CFSTR("%@ not updated: %s\n"), + key, + SCErrorString(SCError())); + return -1; + } - ok = _process_options(modemOptions, N_MODEM_OPTIONS, argc, argv, newConfiguration); - return ok; + return 1; } -/* -------------------- */ +static options ethernetOptions[] = { + { "mtu" , NULL, isNumber , &kSCPropNetEthernetMTU , NULL, NULL }, + { "media" , NULL, isString , &kSCPropNetEthernetMediaSubType, NULL, NULL }, + { "mediaopt" , NULL, isStringArray, &kSCPropNetEthernetMediaOptions, NULL, NULL }, + { "av" , NULL, isOther , &kSCPropNetEthernetCapabilityAV , __doCapability, NULL }, + { "lro" , NULL, isOther , &kSCPropNetEthernetCapabilityLRO , __doCapability, NULL }, + { "rxcsum" , NULL, isOther , &kSCPropNetEthernetCapabilityRXCSUM, __doCapability, NULL }, + { "tso" , NULL, isOther , &kSCPropNetEthernetCapabilityTSO , __doCapability, NULL }, + { "txcsum" , NULL, isOther , &kSCPropNetEthernetCapabilityTXCSUM, __doCapability, NULL }, -static int + { "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 ]\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 __doPPPAuthPW(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) { + CFStringRef encryptionType; + if (argc < 1) { SCPrint(TRUE, stdout, CFSTR("PPP password not specified\n")); return -1; } + encryptionType = CFDictionaryGetValue(newConfiguration, kSCPropNetPPPAuthPasswordEncryption); if (strlen(argv[0]) > 0) { - CFStringRef encryptionType; - - encryptionType = CFDictionaryGetValue(newConfiguration, kSCPropNetPPPAuthPasswordEncryption); 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; @@ -967,19 +1738,53 @@ __doPPPAuthPW(CFStringRef key, const char *description, void *info, int argc, ch 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 *)CFDataGetMutableBytePtr(pw)); + (UniChar *)(void *)CFDataGetMutableBytePtr(pw)); CFRelease(str); +#endif // INLINE_PASSWORDS_USE_CFSTRING CFDictionarySetValue(newConfiguration, key, pw); CFRelease(pw); + } else if (CFEqual(encryptionType, kSCValNetPPPAuthPasswordEncryptionKeychain)) { + Boolean ok; + CFDataRef pw; + CFStringRef str; + + str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); + pw = CFStringCreateExternalRepresentation(NULL, str, kCFStringEncodingUTF8, 0); + ok = SCNetworkInterfaceSetPassword(net_interface, + kSCNetworkInterfacePasswordTypePPP, + pw, + NULL); + CFRelease(pw); + CFRelease(str); + if (ok) { + updateInterfaceConfiguration(newConfiguration); + } else { + return -1; + } } else { SCPrint(TRUE, stdout, CFSTR("PPP password type \"%@\" not supported\n"), encryptionType); return -1; } } else { - CFDictionaryRemoveValue(newConfiguration, key); + if (encryptionType == NULL) { + CFDictionaryRemoveValue(newConfiguration, key); + } else if (CFEqual(encryptionType, kSCValNetPPPAuthPasswordEncryptionKeychain)) { + Boolean ok; + + ok = SCNetworkInterfaceRemovePassword(net_interface, kSCNetworkInterfacePasswordTypePPP); + if (ok) { + updateInterfaceConfiguration(newConfiguration); + } else { + return -1; + } + } else { + SCPrint(TRUE, stdout, CFSTR("PPP password type \"%@\" not supported\n"), encryptionType); + return -1; + } } return 1; @@ -1012,6 +1817,123 @@ __doPPPAuthPWType(CFStringRef key, const char *description, void *info, int argc } +static options l2tp_ipsecOptions[] = { + { "SharedSecret" , NULL, isOther , &kSCPropNetIPSecSharedSecret , __doIPSecSharedSecret , NULL }, + { "SharedSecretEncryption", NULL, isOther , &kSCPropNetIPSecSharedSecretEncryption, __doIPSecSharedSecretType, NULL }, + + { "?" , NULL , isHelp , NULL , NULL, + "\nIPSec configuration commands\n\n" + " set interface ipsec [SharedSecret secret]\n" + " set interface ipsec [SharedSecretEncryption {Keychain}]\n" + } +}; +#define N_L2TP_IPSEC_OPTIONS (sizeof(l2tp_ipsecOptions) / sizeof(l2tp_ipsecOptions[0])) + + +static int +__doPPPIPSec(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newPPPConfiguration) +{ + SCNetworkInterfaceRef childInterface; + CFStringRef childInterfaceType; + CFDictionaryRef configuration; + CFMutableDictionaryRef newConfiguration; + Boolean ok; + + if (argc < 1) { + SCPrint(TRUE, stdout, CFSTR("set what?\n")); + return -1; + } + + childInterface = SCNetworkInterfaceGetInterface(net_interface); + if (childInterface == NULL) { + SCPrint(TRUE, stdout, CFSTR("this interfaces configuration cannot be changed\n")); + return -1; + } + + childInterfaceType = SCNetworkInterfaceGetInterfaceType(childInterface); + if (!CFEqual(childInterfaceType, kSCNetworkInterfaceTypeL2TP)) { + SCPrint(TRUE, stdout, CFSTR("this interfaces configuration cannot be changed\n")); + return -1; + } + + configuration = SCNetworkInterfaceGetExtendedConfiguration(net_interface, kSCEntNetIPSec); + if (configuration == NULL) { + newConfiguration = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + } else { + newConfiguration = CFDictionaryCreateMutableCopy(NULL, 0, configuration); + CFDictionaryRemoveValue(newConfiguration, kSCResvInactive); + } + + ok = _process_options(l2tp_ipsecOptions, N_L2TP_IPSEC_OPTIONS, argc, argv, newConfiguration); + if (!ok) { + goto done; + } + + if (((configuration == NULL) && (CFDictionaryGetCount(newConfiguration) > 0)) || + ((configuration != NULL) && !CFEqual(configuration, newConfiguration))) { + if (!SCNetworkInterfaceSetExtendedConfiguration(net_interface, kSCEntNetIPSec, newConfiguration)) { + if (SCError() == kSCStatusNoKey) { + SCPrint(TRUE, stdout, CFSTR("could not update per-service interface configuration\n")); + } else { + SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError())); + } + goto done; + } + + _prefs_changed = TRUE; + } + + done : + + if (newConfiguration != NULL) CFRelease(newConfiguration); + return argc; +} + + +#ifdef NOTYET +static options pppOnDemandOptions[] = { + { "OnDemandMatchDomainsAlways" , "domain", isOther , &kSCPropNetPPPOnDemandMatchDomainsAlways , __doOnDemandDomains, NULL }, + { "always" , "domain", isOther , &kSCPropNetPPPOnDemandMatchDomainsAlways , __doOnDemandDomains, NULL }, + { "OnDemandMatchDomainsOnRetry", "domain", isOther , &kSCPropNetPPPOnDemandMatchDomainsOnRetry, __doOnDemandDomains, NULL }, + { "retry" , "domain", isOther , &kSCPropNetPPPOnDemandMatchDomainsOnRetry, __doOnDemandDomains, NULL }, + { "OnDemandMatchDomainsNever" , "domain", isOther , &kSCPropNetPPPOnDemandMatchDomainsNever , __doOnDemandDomains, NULL }, + { "never" , "domain", isOther , &kSCPropNetPPPOnDemandMatchDomainsNever , __doOnDemandDomains, NULL }, + + { "?" , NULL , isHelp , NULL , NULL , + "\nOnDemandMatch configuration commands\n\n" + " set interface OnDemand always domain-name[,domain-name]\n" + " set interface OnDemand retry domain-name[,domain-name]\n" + " set interface OnDemand never domain-name[,domain-name]\n" + } +}; +#define N_PPP_ONDEMAND_OPTIONS (sizeof(pppOnDemandOptions) / sizeof(pppOnDemandOptions[0])) + + +static int +__doPPPOnDemandMatch(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(pppOnDemandOptions, N_PPP_ONDEMAND_OPTIONS, argc, argv, newConfiguration); + if (!ok) { + goto done; + } + + done : + + return argc; +} +#endif // NOTYET + + static selections authPromptSelections[] = { { CFSTR("before"), &kSCValNetPPPAuthPromptBefore, 0 }, { CFSTR("after") , &kSCValNetPPPAuthPromptAfter , 0 }, @@ -1030,67 +1952,76 @@ static selections authProtocolSelections[] = { static options pppOptions[] = { - { "ACSP" , NULL , isBoolean , &kSCPropNetPPPACSPEnabled , NULL , NULL }, - { "ConnectTime" , "?time" , isNumber , &kSCPropNetPPPConnectTime , NULL , NULL }, - { "DialOnDemand" , NULL , isBoolean , &kSCPropNetPPPDialOnDemand , NULL , NULL }, - { "DisconnectOnFastUserSwitch", NULL , isBoolean , &kSCPropNetPPPDisconnectOnFastUserSwitch, NULL , NULL }, - { "DisconnectOnIdle" , NULL , isBoolean , &kSCPropNetPPPDisconnectOnIdle , NULL , NULL }, - { "DisconnectOnIdleTimer" , "timeout" , isNumber , &kSCPropNetPPPDisconnectOnIdleTimer , NULL , NULL }, - { "DisconnectOnLogout" , NULL , isBoolean , &kSCPropNetPPPDisconnectOnLogout , NULL , NULL }, - { "DisconnectOnSleep" , NULL , isBoolean , &kSCPropNetPPPDisconnectOnSleep , NULL , NULL }, - { "DisconnectTime" , "?time" , isNumber , &kSCPropNetPPPDisconnectTime , NULL , NULL }, - { "IdleReminder" , NULL , isBoolean , &kSCPropNetPPPIdleReminder , NULL , NULL }, - { "IdleReminderTimer" , "time" , isNumber , &kSCPropNetPPPIdleReminderTimer , NULL , NULL }, - { "Logfile" , "path" , isString , &kSCPropNetPPPLogfile , NULL , NULL }, - { "Plugins" , "plugin" , isStringArray , &kSCPropNetPPPPlugins , NULL , NULL }, - { "RetryConnectTime" , "time" , isNumber , &kSCPropNetPPPRetryConnectTime , NULL , NULL }, - { "SessionTimer" , "time" , isNumber , &kSCPropNetPPPSessionTimer , NULL , NULL }, - { "UseSessionTimer" , NULL , isBoolean , &kSCPropNetPPPUseSessionTimer , NULL , NULL }, - { "VerboseLogging" , NULL , isBoolean , &kSCPropNetPPPVerboseLogging , NULL , NULL }, + { "ACSP" , NULL , isBoolean , &kSCPropNetPPPACSPEnabled , NULL , NULL }, + { "ConnectTime" , "?time" , isNumber , &kSCPropNetPPPConnectTime , NULL , NULL }, + { "DialOnDemand" , NULL , isBoolean , &kSCPropNetPPPDialOnDemand , NULL , NULL }, + { "DisconnectOnFastUserSwitch", NULL , isBoolean , &kSCPropNetPPPDisconnectOnFastUserSwitch, NULL , NULL }, + { "DisconnectOnIdle" , NULL , isBoolean , &kSCPropNetPPPDisconnectOnIdle , NULL , NULL }, + { "DisconnectOnIdleTimer" , "timeout" , isNumber , &kSCPropNetPPPDisconnectOnIdleTimer , NULL , NULL }, + { "DisconnectOnLogout" , NULL , isBoolean , &kSCPropNetPPPDisconnectOnLogout , NULL , NULL }, + { "DisconnectOnSleep" , NULL , isBoolean , &kSCPropNetPPPDisconnectOnSleep , NULL , NULL }, + { "DisconnectTime" , "?time" , isNumber , &kSCPropNetPPPDisconnectTime , NULL , NULL }, + { "IdleReminder" , NULL , isBoolean , &kSCPropNetPPPIdleReminder , NULL , NULL }, + { "IdleReminderTimer" , "time" , isNumber , &kSCPropNetPPPIdleReminderTimer , NULL , NULL }, + { "Logfile" , "path" , isString , &kSCPropNetPPPLogfile , NULL , NULL }, + { "Plugins" , "plugin" , isStringArray , &kSCPropNetPPPPlugins , NULL , NULL }, + { "RetryConnectTime" , "time" , isNumber , &kSCPropNetPPPRetryConnectTime , NULL , NULL }, + { "SessionTimer" , "time" , isNumber , &kSCPropNetPPPSessionTimer , NULL , NULL }, + { "UseSessionTimer" , NULL , isBoolean , &kSCPropNetPPPUseSessionTimer , NULL , NULL }, + { "VerboseLogging" , NULL , isBoolean , &kSCPropNetPPPVerboseLogging , NULL , NULL }, // --- Auth: --- - { "AuthEAPPlugins" , "plugin" , isStringArray , &kSCPropNetPPPAuthEAPPlugins , NULL , NULL }, - { "AuthName" , "account" , isString , &kSCPropNetPPPAuthName , NULL , NULL }, - { "Account" , "account" , isString , &kSCPropNetPPPAuthName , NULL , NULL }, - { "AuthPassword" , "password" , isOther , &kSCPropNetPPPAuthPassword , __doPPPAuthPW , NULL }, - { "Password" , "password" , isOther , &kSCPropNetPPPAuthPassword , __doPPPAuthPW , NULL }, - { "AuthPasswordEncryption" , "type" , isOther , &kSCPropNetPPPAuthPasswordEncryption , __doPPPAuthPWType, NULL }, - { "AuthPrompt" , "before/after", isChooseOne , &kSCPropNetPPPAuthPrompt , NULL , (void *)authPromptSelections }, - { "AuthProtocol" , "protocol" , isChooseMultiple , &kSCPropNetPPPAuthProtocol , NULL , (void *)authProtocolSelections }, + { "AuthEAPPlugins" , "plugin" , isStringArray , &kSCPropNetPPPAuthEAPPlugins , NULL , NULL }, + { "AuthName" , "account" , isString , &kSCPropNetPPPAuthName , NULL , NULL }, + { "Account" , "account" , isString , &kSCPropNetPPPAuthName , NULL , NULL }, + { "AuthPassword" , "password" , isOther , &kSCPropNetPPPAuthPassword , __doPPPAuthPW , NULL }, + { "Password" , "password" , isOther , &kSCPropNetPPPAuthPassword , __doPPPAuthPW , NULL }, + { "AuthPasswordEncryption" , "type" , isOther , &kSCPropNetPPPAuthPasswordEncryption , __doPPPAuthPWType , NULL }, + { "AuthPrompt" , "before/after", isChooseOne , &kSCPropNetPPPAuthPrompt , NULL , (void *)authPromptSelections }, + { "AuthProtocol" , "protocol" , isChooseMultiple , &kSCPropNetPPPAuthProtocol , NULL , (void *)authProtocolSelections }, // --- Comm: --- - { "CommRemoteAddress" , "phone#" , isString , &kSCPropNetPPPCommRemoteAddress , NULL , NULL }, - { "CommAlternateRemoteAddress", "phone#" , isString , &kSCPropNetPPPCommAlternateRemoteAddress, NULL , NULL }, - { "CommConnectDelay" , "time" , isNumber , &kSCPropNetPPPCommConnectDelay , NULL , NULL }, - { "CommDisplayTerminalWindow" , NULL , isBoolean , &kSCPropNetPPPCommDisplayTerminalWindow , NULL , NULL }, - { "CommRedialCount" , "retry count" , isNumber , &kSCPropNetPPPCommRedialCount , NULL , NULL }, - { "CommRedialEnabled" , NULL , isBoolean , &kSCPropNetPPPCommRedialEnabled , NULL , NULL }, - { "CommRedialInterval" , "retry delay" , isNumber , &kSCPropNetPPPCommRedialInterval , NULL , NULL }, - { "CommTerminalScript" , "script" , isString , &kSCPropNetPPPCommTerminalScript , NULL , NULL }, - { "CommUseTerminalScript" , NULL , isBoolean , &kSCPropNetPPPCommUseTerminalScript , NULL , NULL }, + { "CommRemoteAddress" , "phone#" , isString , &kSCPropNetPPPCommRemoteAddress , NULL , NULL }, + { "CommAlternateRemoteAddress", "phone#" , isString , &kSCPropNetPPPCommAlternateRemoteAddress, NULL , NULL }, + { "CommConnectDelay" , "time" , isNumber , &kSCPropNetPPPCommConnectDelay , NULL , NULL }, + { "CommDisplayTerminalWindow" , NULL , isBoolean , &kSCPropNetPPPCommDisplayTerminalWindow , NULL , NULL }, + { "CommRedialCount" , "retry count" , isNumber , &kSCPropNetPPPCommRedialCount , NULL , NULL }, + { "CommRedialEnabled" , NULL , isBoolean , &kSCPropNetPPPCommRedialEnabled , NULL , NULL }, + { "CommRedialInterval" , "retry delay" , isNumber , &kSCPropNetPPPCommRedialInterval , NULL , NULL }, + { "CommTerminalScript" , "script" , isString , &kSCPropNetPPPCommTerminalScript , NULL , NULL }, + { "CommUseTerminalScript" , NULL , isBoolean , &kSCPropNetPPPCommUseTerminalScript , NULL , NULL }, // --- CCP: --- - { "CCPEnabled" , NULL , isBoolean , &kSCPropNetPPPCCPEnabled , NULL , NULL }, - { "CCPMPPE40Enabled" , NULL , isBoolean , &kSCPropNetPPPCCPMPPE40Enabled , NULL , NULL }, - { "CCPMPPE128Enabled" , NULL , isBoolean , &kSCPropNetPPPCCPMPPE128Enabled , NULL , NULL }, + { "CCPEnabled" , NULL , isBoolean , &kSCPropNetPPPCCPEnabled , NULL , NULL }, + { "CCPMPPE40Enabled" , NULL , isBoolean , &kSCPropNetPPPCCPMPPE40Enabled , NULL , NULL }, + { "CCPMPPE128Enabled" , NULL , isBoolean , &kSCPropNetPPPCCPMPPE128Enabled , NULL , NULL }, // --- IPCP: --- - { "IPCPCompressionVJ" , NULL , isBoolean , &kSCPropNetPPPIPCPCompressionVJ , NULL , NULL }, - { "IPCPUsePeerDNS" , NULL , isBoolean , &kSCPropNetPPPIPCPUsePeerDNS , NULL , NULL }, + { "IPCPCompressionVJ" , NULL , isBoolean , &kSCPropNetPPPIPCPCompressionVJ , NULL , NULL }, + { "IPCPUsePeerDNS" , NULL , isBoolean , &kSCPropNetPPPIPCPUsePeerDNS , NULL , NULL }, // --- LCP: --- - { "LCPEchoEnabled" , NULL , isBoolean , &kSCPropNetPPPLCPEchoEnabled , NULL , NULL }, - { "LCPEchoFailure" , NULL , isNumber , &kSCPropNetPPPLCPEchoFailure , NULL , NULL }, - { "LCPEchoInterval" , NULL , isNumber , &kSCPropNetPPPLCPEchoInterval , NULL , NULL }, - { "LCPCompressionACField" , NULL , isBoolean , &kSCPropNetPPPLCPCompressionACField , NULL , NULL }, - { "LCPCompressionPField" , NULL , isBoolean , &kSCPropNetPPPLCPCompressionPField , NULL , NULL }, - { "LCPMRU" , NULL , isNumber , &kSCPropNetPPPLCPMRU , NULL , NULL }, - { "LCPMTU" , NULL , isNumber , &kSCPropNetPPPLCPMTU , NULL , NULL }, - { "LCPReceiveACCM" , NULL , isNumber , &kSCPropNetPPPLCPReceiveACCM , NULL , NULL }, - { "LCPTransmitACCM" , NULL , isNumber , &kSCPropNetPPPLCPTransmitACCM , NULL , NULL }, + { "LCPEchoEnabled" , NULL , isBoolean , &kSCPropNetPPPLCPEchoEnabled , NULL , NULL }, + { "LCPEchoFailure" , NULL , isNumber , &kSCPropNetPPPLCPEchoFailure , NULL , NULL }, + { "LCPEchoInterval" , NULL , isNumber , &kSCPropNetPPPLCPEchoInterval , NULL , NULL }, + { "LCPCompressionACField" , NULL , isBoolean , &kSCPropNetPPPLCPCompressionACField , NULL , NULL }, + { "LCPCompressionPField" , NULL , isBoolean , &kSCPropNetPPPLCPCompressionPField , NULL , NULL }, + { "LCPMRU" , NULL , isNumber , &kSCPropNetPPPLCPMRU , NULL , NULL }, + { "LCPMTU" , NULL , isNumber , &kSCPropNetPPPLCPMTU , NULL , NULL }, + { "LCPReceiveACCM" , NULL , isNumber , &kSCPropNetPPPLCPReceiveACCM , NULL , NULL }, + { "LCPTransmitACCM" , NULL , isNumber , &kSCPropNetPPPLCPTransmitACCM , NULL , NULL }, + + // --- IPSec: --- + { "IPSec" , NULL , isOther , NULL , __doPPPIPSec , NULL }, + +#ifdef NOTYET + // --- OnDemand: --- + { "OnDemandEnabled" , NULL , isBoolean , &kSCPropNetPPPOnDemandEnabled , NULL , NULL }, + { "OnDemandMatch" , NULL , isOther , NULL , __doPPPOnDemandMatch, NULL }, +#endif // NOTYET // --- Help --- - { "?" , NULL , isHelp , NULL , NULL , + { "?" , NULL , isHelp , NULL , NULL , "\nPPP configuration commands\n\n" " set interface [Account account]\n" " set interface [Password password]\n" @@ -1100,7 +2031,12 @@ static options pppOptions[] = { " set interface [IdleReminderTimer time-in-seconds]\n" " set interface [DisconnectOnIdle {enable|disable}]\n" " set interface [DisconnectOnIdleTimer time-in-seconds]\n" - " set interface [DisconnectOnLogout {enable|disable}]" + " set interface [DisconnectOnLogout {enable|disable}]\n" + " set interface [IPSec ]\n" +#ifdef NOTYET + " set interface [OnDemandEnabled {enable|disable}]\n" + " set interface [OnDemandMatch ]\n" +#endif // NOTYET } }; #define N_PPP_OPTIONS (sizeof(pppOptions) / sizeof(pppOptions[0])) @@ -1116,7 +2052,8 @@ set_interface_ppp(int argc, char **argv, CFMutableDictionaryRef newConfiguration } -/* -------------------- */ +#pragma mark - +#pragma mark VLAN options static Boolean @@ -1128,7 +2065,165 @@ SCPrint(TRUE, stdout, CFSTR("vlan interface management not yet supported\n")); } -/* -------------------- */ +#pragma mark - +#pragma mark VPN options + + +static int +__doVPNAuthPW(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) +{ + CFStringRef encryptionType; + + if (argc < 1) { + SCPrint(TRUE, stdout, CFSTR("VPN password not specified\n")); + return -1; + } + + encryptionType = CFDictionaryGetValue(newConfiguration, kSCPropNetVPNAuthPasswordEncryption); + 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)); + 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, kSCValNetVPNAuthPasswordEncryptionKeychain)) { + Boolean ok; + CFDataRef pw; + CFStringRef str; + + str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); + pw = CFStringCreateExternalRepresentation(NULL, str, kCFStringEncodingUTF8, 0); + ok = SCNetworkInterfaceSetPassword(net_interface, + kSCNetworkInterfacePasswordTypeVPN, + pw, + NULL); + CFRelease(pw); + CFRelease(str); + if (ok) { + updateInterfaceConfiguration(newConfiguration); + } else { + return -1; + } + } else { + SCPrint(TRUE, stdout, CFSTR("VPN password type \"%@\" not supported\n"), encryptionType); + return -1; + } + } else { + if (encryptionType == NULL) { + CFDictionaryRemoveValue(newConfiguration, key); + } else if (CFEqual(encryptionType, kSCValNetVPNAuthPasswordEncryptionKeychain)) { + Boolean ok; + + ok = SCNetworkInterfaceRemovePassword(net_interface, kSCNetworkInterfacePasswordTypeVPN); + if (ok) { + updateInterfaceConfiguration(newConfiguration); + } else { + return -1; + } + } else { + SCPrint(TRUE, stdout, CFSTR("PPP password type \"%@\" not supported\n"), encryptionType); + return -1; + } + } + + return 1; +} + + +static int +__doVPNAuthPWType(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) +{ + if (argc < 1) { + SCPrint(TRUE, stdout, CFSTR("VPN password type mode not specified\n")); + return -1; + } + + if (strlen(argv[0]) > 0) { + if (strcasecmp(argv[0], "keychain") == 0) { + CFDictionarySetValue(newConfiguration, key, kSCValNetVPNAuthPasswordEncryptionKeychain); + } else if (strcasecmp(argv[0], "prompt") == 0) { + CFDictionarySetValue(newConfiguration, key, kSCValNetVPNAuthPasswordEncryptionPrompt); + } else { + SCPrint(TRUE, stdout, CFSTR("invalid password type\n")); + return -1; + } + } else { + CFDictionaryRemoveValue(newConfiguration, key); + } + + // encryption type changed, reset password + CFDictionaryRemoveValue(newConfiguration, kSCPropNetVPNAuthPassword); + + return 1; +} + + +static selections vpnAuthenticationMethodSelections[] = { + { CFSTR("Password") , &kSCValNetVPNAuthenticationMethodPassword , 0 }, + { CFSTR("Certificate") , &kSCValNetVPNAuthenticationMethodCertificate , 0 }, + { NULL , NULL , 0 } +}; + + +static options vpnOptions[] = { + { "AuthName" , "account" , isString , &kSCPropNetVPNAuthName , NULL , NULL }, + { "Account" , "account" , isString , &kSCPropNetVPNAuthName , NULL , NULL }, + { "AuthPassword" , "password" , isOther , &kSCPropNetVPNAuthPassword , __doVPNAuthPW , NULL }, + { "Password" , "password" , isOther , &kSCPropNetVPNAuthPassword , __doVPNAuthPW , NULL }, + { "AuthPasswordEncryption" , "type" , isOther , &kSCPropNetVPNAuthPasswordEncryption , __doVPNAuthPWType , NULL }, + { "AuthenticationMethod" , NULL , isChooseOne , &kSCPropNetVPNAuthenticationMethod , NULL , (void *)vpnAuthenticationMethodSelections }, + { "ConnectTime" , "?time" , isNumber , &kSCPropNetVPNConnectTime , NULL , NULL }, + { "DisconnectOnFastUserSwitch", NULL , isBoolean , &kSCPropNetVPNDisconnectOnFastUserSwitch, NULL , NULL }, + { "DisconnectOnIdle" , NULL , isBoolean , &kSCPropNetVPNDisconnectOnIdle , NULL , NULL }, + { "DisconnectOnIdleTimer" , "timeout" , isNumber , &kSCPropNetVPNDisconnectOnIdleTimer , NULL , NULL }, + { "DisconnectOnLogout" , NULL , isBoolean , &kSCPropNetVPNDisconnectOnLogout , NULL , NULL }, + { "DisconnectOnSleep" , NULL , isBoolean , &kSCPropNetVPNDisconnectOnSleep , NULL , NULL }, + { "Logfile" , "path" , isString , &kSCPropNetVPNLogfile , NULL , NULL }, + { "MTU" , NULL , isNumber , &kSCPropNetVPNMTU , NULL , NULL }, + { "RemoteAddress" , "server" , isString , &kSCPropNetVPNRemoteAddress , NULL , NULL }, + { "Server" , "server" , isString , &kSCPropNetVPNRemoteAddress , NULL , NULL }, + { "VerboseLogging" , NULL , isBoolean , &kSCPropNetVPNVerboseLogging , NULL , NULL }, + + // --- Help --- + { "?" , NULL , isHelp , NULL , NULL , + "\nVPN configuration commands\n\n" + " set interface [Server server]\n" + " set interface [Account account]\n" + " set interface [Password password]\n" + } +}; +#define N_VPN_OPTIONS (sizeof(vpnOptions) / sizeof(vpnOptions[0])) + + +static Boolean +set_interface_vpn(int argc, char **argv, CFMutableDictionaryRef newConfiguration) +{ + Boolean ok; + + ok = _process_options(vpnOptions, N_VPN_OPTIONS, argc, argv, newConfiguration); + return ok; +} + + +#pragma mark - +#pragma mark [more] Interface management __private_extern__ @@ -1151,32 +2246,39 @@ set_interface(int argc, char **argv) } configuration = SCNetworkInterfaceGetConfiguration(net_interface); - if (configuration == NULL) { + if (configuration != NULL) { + configuration = CFDictionaryCreateCopy(NULL, configuration); + newConfiguration = CFDictionaryCreateMutableCopy(NULL, 0, configuration); + CFDictionaryRemoveValue(newConfiguration, kSCResvInactive); + } else { newConfiguration = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - } else { - newConfiguration = CFDictionaryCreateMutableCopy(NULL, 0, configuration); - CFDictionaryRemoveValue(newConfiguration, kSCResvInactive); } interfaceType = SCNetworkInterfaceGetInterfaceType(net_interface); - if (CFEqual(interfaceType, kSCNetworkInterfaceTypeBond)) { - ok = set_interface_bond(argc, argv, newConfiguration); - } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeEthernet)) { + if (CFEqual(interfaceType, kSCNetworkInterfaceTypeEthernet)) { ok = set_interface_ethernet(argc, argv, newConfiguration); } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeFireWire)) { ok = set_interface_firewire(argc, argv, newConfiguration); + } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeIPSec)) { + ok = set_interface_ipsec(argc, argv, newConfiguration); } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeModem)) { ok = set_interface_modem(argc, argv, newConfiguration); } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeIEEE80211)) { ok = set_interface_airport(argc, argv, newConfiguration); } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) { ok = set_interface_ppp(argc, argv, newConfiguration); + } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeBond)) { + ok = set_interface_bond(argc, argv, newConfiguration); + } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeBridge)) { + ok = set_interface_bridge(argc, argv, newConfiguration); } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVLAN)) { ok = set_interface_vlan(argc, argv, newConfiguration); + } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVPN)) { + ok = set_interface_vpn(argc, argv, newConfiguration); } else { SCPrint(TRUE, stdout, CFSTR("this interfaces configuration cannot be changed\n")); } @@ -1196,11 +2298,12 @@ set_interface(int argc, char **argv) goto done; } - net_changed = TRUE; + _prefs_changed = TRUE; } done : + if (configuration != NULL) CFRelease(configuration); if (newConfiguration != NULL) CFRelease(newConfiguration); return; } @@ -1215,8 +2318,8 @@ show_interface(int argc, char **argv) { SCNetworkInterfaceRef interface; - if (argc == 1) { - interface = _find_interface(argv[0]); + if (argc >= 1) { + interface = _find_interface(argc, argv, NULL); } else { if (net_interface != NULL) { interface = net_interface; @@ -1238,7 +2341,7 @@ show_interface(int argc, char **argv) __private_extern__ -CFStringRef +CF_RETURNS_RETAINED CFStringRef _interface_description(SCNetworkInterfaceRef interface) { CFMutableStringRef description;