/* * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * Modification History * * August 5, 2004 Allan Nathanson * - initial revision */ #include "scutil.h" #include "net.h" #include /* -------------------- */ static CFArrayRef _copy_interfaces() { CFMutableArrayRef interfaces; CFArrayRef real_interfaces; real_interfaces = SCNetworkInterfaceCopyAll(); if (real_interfaces == NULL) { SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError())); return NULL; } interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); // include real interfaces CFArrayAppendArray(interfaces, real_interfaces, CFRangeMake(0, CFArrayGetCount(real_interfaces))); CFRelease(real_interfaces); // include pseudo interfaces CFArrayAppendValue(interfaces, kSCNetworkInterfaceIPv4); // include interfaces that we have created if (new_interfaces != NULL) { CFArrayAppendArray(interfaces, new_interfaces, CFRangeMake(0, CFArrayGetCount(new_interfaces))); } return (CFArrayRef)interfaces; } __private_extern__ SCNetworkInterfaceRef _find_interface(char *match) { Boolean allowIndex = TRUE; CFIndex i; CFIndex n; CFStringRef select_name = NULL; SCNetworkInterfaceRef selected = NULL; if (strcasecmp(match, "$child") == 0) { if (net_interface == NULL) { SCPrint(TRUE, stdout, CFSTR("interface not selected\n")); goto done; } selected = SCNetworkInterfaceGetInterface(net_interface); if(selected == NULL) { SCPrint(TRUE, stdout, CFSTR("no child interface\n")); } goto done; } else if (strcasecmp(match, "$service") == 0) { if (net_service == NULL) { SCPrint(TRUE, stdout, CFSTR("service not selected\n")); goto done; } selected = SCNetworkServiceGetInterface(net_service); if(selected == NULL) { SCPrint(TRUE, stdout, CFSTR("no interface for service\n")); } goto done; } if (interfaces == NULL) { interfaces = _copy_interfaces(); if (interfaces == NULL) { return NULL; } allowIndex = FALSE; } // try to select the interface by its display name select_name = CFStringCreateWithCString(NULL, match, kCFStringEncodingUTF8); n = CFArrayGetCount(interfaces); for (i = 0; i < n; i++) { SCNetworkInterfaceRef interface; CFStringRef interfaceName; interface = CFArrayGetValueAtIndex(interfaces, i); interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface); if ((interfaceName != NULL) && CFEqual(select_name, interfaceName)) { if (selected == NULL) { selected = interface; } else { // if multiple interfaces match selected = NULL; SCPrint(TRUE, stdout, CFSTR("multiple interfaces match\n")); goto done; } } } if (selected != NULL) { goto done; } // try to select the interface by its BSD name for (i = 0; i < n; i++) { 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); } } if ((bsd_name != NULL) && CFEqual(select_name, bsd_name)) { if (selected == NULL) { selected = interface; } else { // if multiple interfaces match selected = NULL; SCPrint(TRUE, stdout, CFSTR("multiple interfaces match\n")); goto done; } } } if (selected != NULL) { goto done; } // try to select the interface by its interface type for (i = 0; i < n; i++) { SCNetworkInterfaceRef interface; CFStringRef interfaceType; interface = CFArrayGetValueAtIndex(interfaces, i); interfaceType = SCNetworkInterfaceGetInterfaceType(interface); if (CFEqual(select_name, interfaceType)) { if (selected == NULL) { selected = interface; } else { // if multiple interfaces match selected = NULL; SCPrint(TRUE, stdout, CFSTR("multiple interfaces match\n")); goto done; } } } if (selected != NULL) { goto done; } if (allowIndex) { char *end; char *str = match; long val; // try to select the interface by its index errno = 0; val = strtol(str, &end, 10); if ((*str != '\0') && ((*end == '\0') || (*end == '.')) && (errno == 0)) { if ((val > 0) && (val <= n)) { selected = CFArrayGetValueAtIndex(interfaces, val - 1); if (*end == '.') { str = end + 1; val = strtol(str, &end, 10); if ((*str != '\0') && (*end == '\0') && (errno == 0)) { while (val-- > 0) { selected = SCNetworkInterfaceGetInterface(selected); if (selected == NULL) { break; } } } } } } } if (selected != NULL) { goto done; } SCPrint(TRUE, stdout, CFSTR("no match\n")); done : if (select_name != NULL) CFRelease(select_name); return selected; } /* -------------------- */ __private_extern__ void create_interface(int argc, char **argv) { SCNetworkInterfaceRef interface; CFStringRef interfaceName; CFStringRef interfaceType; SCNetworkInterfaceRef new_interface; if (argc < 1) { SCPrint(TRUE, stdout, CFSTR("what interface type?\n")); return; } interfaceType = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); 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; } interface = net_interface; } else { interface = _find_interface(argv[1]); } if (interface == NULL) { return; } new_interface = SCNetworkInterfaceCreateWithInterface(interface, interfaceType); if (new_interface == NULL) { SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError())); goto done; } } if (new_interfaces == NULL) { new_interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); } CFArrayAppendValue(new_interfaces, new_interface); if (net_interface != NULL) CFRelease(net_interface); net_interface = new_interface; interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(net_interface); if (interfaceName == NULL) { interfaceName = SCNetworkInterfaceGetBSDName(net_interface); } if (interfaceName == NULL) { interfaceName = SCNetworkInterfaceGetInterfaceType(net_interface); } SCPrint(TRUE, stdout, CFSTR("interface \"%@\" created and selected\n"), interfaceName); done : CFRelease(interfaceType); return; } /* -------------------- */ __private_extern__ void select_interface(int argc, char **argv) { SCNetworkInterfaceRef interface; interface = _find_interface(argv[0]); if (interface != NULL) { CFStringRef interfaceName; if (net_interface != NULL) CFRelease(net_interface); net_interface = CFRetain(interface); interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface); if (interfaceName == NULL) { interfaceName = SCNetworkInterfaceGetBSDName(interface); } if (interfaceName == NULL) { interfaceName = SCNetworkInterfaceGetInterfaceType(interface); } SCPrint(TRUE, stdout, CFSTR("interface \"%@\" selected\n"), interfaceName); } return; } /* -------------------- */ __private_extern__ void _show_interface(SCNetworkInterfaceRef interface, CFStringRef prefix, Boolean showChild) { CFDictionaryRef configuration; CFStringRef if_bsd_name; CFStringRef if_localized_name; CFStringRef if_mac_address; CFStringRef if_type; CFArrayRef supported; if_localized_name = SCNetworkInterfaceGetLocalizedDisplayName(interface); if (if_localized_name != NULL) { SCPrint(TRUE, stdout, CFSTR("%@ name = %@\n"), prefix, if_localized_name); } if_bsd_name = SCNetworkInterfaceGetBSDName(interface); if (if_bsd_name != NULL) { SCPrint(TRUE, stdout, CFSTR("%@ interface name = %@\n"), prefix, if_bsd_name); } if_type = SCNetworkInterfaceGetInterfaceType(interface); SCPrint(TRUE, stdout, CFSTR("%@ type = %@\n"), prefix, if_type); if_mac_address = SCNetworkInterfaceGetHardwareAddressString(interface); if (if_mac_address != NULL) { SCPrint(TRUE, stdout, CFSTR("%@ address = %@\n"), prefix, if_mac_address); } configuration = SCNetworkInterfaceGetConfiguration(interface); if ((configuration != NULL) && CFDictionaryContainsKey(configuration, kSCResvInactive)) { configuration = NULL; } if (if_bsd_name != NULL) { CFArrayRef available; CFDictionaryRef active; int mtu_cur; int mtu_min; int mtu_max; if (NetworkInterfaceCopyMTU(if_bsd_name, &mtu_cur, &mtu_min, &mtu_max)) { char isCurrent = '*'; if (configuration != NULL) { int mtu_req; CFNumberRef num; num = CFDictionaryGetValue(configuration, kSCPropNetEthernetMTU); if (isA_CFNumber(num)) { CFNumberGetValue(num, kCFNumberIntType, &mtu_req); if (mtu_cur != mtu_req) { mtu_cur = mtu_req; isCurrent = ' '; } } } SCPrint(TRUE, stdout, CFSTR("%@ mtu %c = %ld (%ld < n < %ld)\n"), prefix, isCurrent, mtu_cur, mtu_min, mtu_max); } if (NetworkInterfaceCopyMediaOptions(if_bsd_name, NULL, &active, &available, TRUE)) { char isCurrent = ' '; CFArrayRef options = NULL; CFArrayRef options_req = NULL; CFStringRef subtype = NULL; CFStringRef subtype_req = NULL; if (configuration != NULL) { subtype_req = CFDictionaryGetValue(configuration, kSCPropNetEthernetMediaSubType); options_req = CFDictionaryGetValue(configuration, kSCPropNetEthernetMediaOptions); } if (subtype_req == NULL) { subtype_req = CFSTR("autoselect"); } if (active != NULL) { subtype = CFDictionaryGetValue(active, kSCPropNetEthernetMediaSubType); options = CFDictionaryGetValue(active, kSCPropNetEthernetMediaOptions); } if (subtype != NULL) { if (((subtype_req != NULL) && CFEqual(subtype, subtype_req)) && ((options == options_req) || ((options != NULL) && (options_req != NULL) && CFEqual(options, options_req))) ) { isCurrent = '*'; } else if ((subtype_req == NULL) || ((subtype_req != NULL) && CFEqual(subtype_req, CFSTR("autoselect")))) { // if requested subtype not specified or "autoselect" isCurrent = '*'; } } if (subtype_req != NULL) { SCPrint(TRUE, stdout, CFSTR("%@ media %c = %@"), prefix, isCurrent, subtype_req); if ((options_req != NULL) && (CFArrayGetCount(options_req) > 0)) { CFStringRef options_str; options_str = CFStringCreateByCombiningStrings(NULL, options_req, CFSTR(",")); SCPrint(TRUE, stdout, CFSTR(" <%@>"), options_str); CFRelease(options_str); } SCPrint(TRUE, stdout, CFSTR("\n")); } SCPrint(TRUE, stdout, CFSTR("\n")); if (available != NULL) { CFIndex i; CFIndex n_subtypes; CFArrayRef subtypes; subtypes = NetworkInterfaceCopyMediaSubTypes(available); n_subtypes = (subtypes != NULL) ? CFArrayGetCount(subtypes) : 0; for (i = 0; i < n_subtypes; i++) { CFIndex j; CFIndex n_subtype_options; CFStringRef subtype; CFArrayRef subtype_options; subtype = CFArrayGetValueAtIndex(subtypes, i); subtype_options = NetworkInterfaceCopyMediaSubTypeOptions(available, subtype); n_subtype_options = (subtype_options != NULL) ? CFArrayGetCount(subtype_options) : 0; for (j = 0; j < n_subtype_options; j++) { char isCurrent = ' '; CFArrayRef options; options = CFArrayGetValueAtIndex(subtype_options, j); if (((subtype_req != NULL) && CFEqual(subtype, subtype_req)) && ((options == options_req) || ((options != NULL) && (options_req != NULL) && CFEqual(options, options_req))) ) { isCurrent = '*'; } SCPrint(TRUE, stdout, CFSTR("%@ %s %c = %@"), prefix, ((i == 0) && (j == 0)) ? "supported media" : " ", isCurrent, subtype); if ((options != NULL) && (CFArrayGetCount(options) > 0)) { CFStringRef options_str; options_str = CFStringCreateByCombiningStrings(NULL, options, CFSTR(",")); SCPrint(TRUE, stdout, CFSTR(" <%@>"), options_str); CFRelease(options_str); } SCPrint(TRUE, stdout, CFSTR("\n")); } CFRelease(subtype_options); } } } else { SCPrint(TRUE, stdout, CFSTR("\n")); } } supported = SCNetworkInterfaceGetSupportedInterfaceTypes(interface); SCPrint(TRUE, stdout, CFSTR("%@ supported interfaces = "), prefix); if (supported != NULL) { CFIndex i; CFIndex n = CFArrayGetCount(supported); for (i = 0; i < n; i++) { SCPrint(TRUE, stdout, CFSTR("%s%@"), (i == 0) ? "" : ", ", CFArrayGetValueAtIndex(supported, i)); } } SCPrint(TRUE, stdout, CFSTR("\n")); supported = SCNetworkInterfaceGetSupportedProtocolTypes(interface); SCPrint(TRUE, stdout, CFSTR("%@ supported protocols = "), prefix); if (supported != NULL) { CFIndex i; CFIndex n = CFArrayGetCount(supported); for (i = 0; i < n; i++) { SCPrint(TRUE, stdout, CFSTR("%s%@"), (i == 0) ? "" : ", ", CFArrayGetValueAtIndex(supported, i)); } } SCPrint(TRUE, stdout, CFSTR("\n")); if (configuration != NULL) { CFMutableDictionaryRef effective; effective = CFDictionaryCreateMutableCopy(NULL, 0, configuration); // remove known (and already reported) interface configuration keys if (CFDictionaryContainsKey(effective, kSCResvInactive)) { CFDictionaryRemoveAllValues(effective); } CFDictionaryRemoveValue(effective, kSCPropNetEthernetMTU); CFDictionaryRemoveValue(effective, kSCPropNetEthernetMediaSubType); CFDictionaryRemoveValue(effective, kSCPropNetEthernetMediaOptions); if (CFDictionaryGetCount(effective) > 0) { SCPrint(TRUE, stdout, CFSTR("\n%@ per-interface configuration\n"), prefix); _show_entity(configuration, prefix); } CFRelease(effective); } if (_sc_debug) { SCPrint(TRUE, stdout, CFSTR("\n%@\n"), interface); } interface = SCNetworkInterfaceGetInterface(interface); if (interface != NULL) { CFStringRef newPrefix; newPrefix = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ "), prefix); SCPrint(TRUE, stdout, CFSTR("\n%@child interface\n"), newPrefix); _show_interface(interface, newPrefix, showChild); CFRelease(newPrefix); } return; } /* -------------------- */ __private_extern__ void show_interfaces(int argc, char **argv) { CFIndex i; CFIndex n; if (interfaces != NULL) CFRelease(interfaces); interfaces = _copy_interfaces(); if (interfaces == NULL) { return; } n = CFArrayGetCount(interfaces); for (i = 0; i < n; i++) { CFIndex childIndex = 0; SCNetworkInterfaceRef interface; interface = CFArrayGetValueAtIndex(interfaces, i); do { CFStringRef interfaceName; char isSelected; interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface); if (interfaceName == NULL) { interfaceName = SCNetworkInterfaceGetBSDName(interface); } if (interfaceName == NULL) { interfaceName = SCNetworkInterfaceGetInterfaceType(interface); } isSelected = ' '; if ((net_interface != NULL) && CFEqual(interface, net_interface)) { isSelected = '>'; } if (childIndex == 0) { SCPrint(TRUE, stdout, CFSTR("%c%2d: %@\n"), isSelected, i + 1, interfaceName); } else { SCPrint(TRUE, stdout, CFSTR("%c%2d.%d: %@\n"), isSelected, i + 1, childIndex, interfaceName); } interface = SCNetworkInterfaceGetInterface(interface); childIndex++; } while (interface != NULL); } return; } /* -------------------- */ static Boolean set_interface_bond(int argc, char **argv, CFMutableDictionaryRef newConfiguration) { // xxxxx ("+device", "-device") SCPrint(TRUE, stdout, CFSTR("bond interface management not yet supported\n")); return FALSE; } /* -------------------- */ static Boolean set_interface_airport(int argc, char **argv, CFMutableDictionaryRef newConfiguration) { SCPrint(TRUE, stdout, CFSTR("airport interface management not yet supported\n")); return FALSE; } /* -------------------- */ static options ethernetOptions[] = { { "mtu" , NULL, isNumber , &kSCPropNetEthernetMTU , NULL, NULL }, { "media" , NULL, isString , &kSCPropNetEthernetMediaSubType, NULL, NULL }, { "mediaopt" , NULL, isStringArray, &kSCPropNetEthernetMediaOptions, NULL, 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) { CFNumberRef mtu; CFArrayRef options; CFStringRef subtype; // validate configuration mtu = CFDictionaryGetValue(newConfiguration, kSCPropNetEthernetMTU); if (isA_CFNumber(mtu)) { int mtu_max; int mtu_min; int mtu_val; if (!NetworkInterfaceCopyMTU(interfaceName, NULL, &mtu_min, &mtu_max)) { SCPrint(TRUE, stdout, CFSTR("cannot set MTU\n")); return FALSE; } if (!CFNumberGetValue(mtu, kCFNumberIntType, &mtu_val) || (mtu_val < mtu_min) || (mtu_val > mtu_max)) { SCPrint(TRUE, stdout, CFSTR("mtu out of range\n")); return FALSE; } } subtype = CFDictionaryGetValue(newConfiguration, kSCPropNetEthernetMediaSubType); options = CFDictionaryGetValue(newConfiguration, kSCPropNetEthernetMediaOptions); if (subtype != NULL) { CFArrayRef available = NULL; CFArrayRef config_options = options; CFArrayRef subtypes = NULL; CFArrayRef subtype_options = NULL; ok = FALSE; if (options == NULL) { 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)) { SCPrint(TRUE, stdout, CFSTR("media type / options not available\n")); goto checked; } if (available == NULL) { goto checked; } subtypes = NetworkInterfaceCopyMediaSubTypes(available); if ((subtypes == NULL) || !CFArrayContainsValue(subtypes, CFRangeMake(0, CFArrayGetCount(subtypes)), subtype)) { SCPrint(TRUE, stdout, CFSTR("media type not valid\n")); goto checked; } subtype_options = NetworkInterfaceCopyMediaSubTypeOptions(available, subtype); if ((subtype_options == NULL) || !CFArrayContainsValue(subtype_options, CFRangeMake(0, CFArrayGetCount(subtype_options)), config_options)) { SCPrint(TRUE, stdout, CFSTR("media options not valid for \"%@\"\n"), subtype); goto checked; } if (options == NULL) { CFDictionarySetValue(newConfiguration, kSCPropNetEthernetMediaOptions, config_options); } ok = TRUE; checked : if (available != NULL) CFRelease(available); if (subtypes != NULL) CFRelease(subtypes); if (subtype_options != NULL) CFRelease(subtype_options); if (options == NULL) CFRelease(config_options); } else { if (options != NULL) { SCPrint(TRUE, stdout, CFSTR("media type and options must both be specified\n")); return FALSE; } } } return ok; } /* -------------------- */ 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}]" } }; #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; } /* -------------------- */ static int __doPPPAuthPW(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) { if (argc < 1) { SCPrint(TRUE, stdout, CFSTR("PPP password not specified\n")); return -1; } if (strlen(argv[0]) > 0) { CFStringRef encryptionType; encryptionType = CFDictionaryGetValue(newConfiguration, kSCPropNetPPPAuthPasswordEncryption); if (encryptionType == NULL) { 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 *)CFDataGetMutableBytePtr(pw)); CFRelease(str); CFDictionarySetValue(newConfiguration, key, pw); CFRelease(pw); } else { SCPrint(TRUE, stdout, CFSTR("PPP password type \"%@\" not supported\n"), encryptionType); return -1; } } else { CFDictionaryRemoveValue(newConfiguration, key); } return 1; } static int __doPPPAuthPWType(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) { if (argc < 1) { SCPrint(TRUE, stdout, CFSTR("PPP password type mode not specified\n")); return -1; } if (strlen(argv[0]) > 0) { if (strcasecmp(argv[0], "keychain") == 0) { CFDictionarySetValue(newConfiguration, key, kSCValNetPPPAuthPasswordEncryptionKeychain); } else { SCPrint(TRUE, stdout, CFSTR("invalid password type\n")); return -1; } } else { CFDictionaryRemoveValue(newConfiguration, key); } // encryption type changed, reset password CFDictionaryRemoveValue(newConfiguration, kSCPropNetPPPAuthPassword); return 1; } static selections authPromptSelections[] = { { CFSTR("before"), &kSCValNetPPPAuthPromptBefore, 0 }, { CFSTR("after") , &kSCValNetPPPAuthPromptAfter , 0 }, { NULL , NULL , 0 } }; static selections authProtocolSelections[] = { { CFSTR("CHAP") , &kSCValNetPPPAuthProtocolCHAP , 0 }, { CFSTR("EAP") , &kSCValNetPPPAuthProtocolEAP , 0 }, { CFSTR("MSCHAP1"), &kSCValNetPPPAuthProtocolMSCHAP1, 0 }, { CFSTR("MSCHAP2"), &kSCValNetPPPAuthProtocolMSCHAP2, 0 }, { CFSTR("PAP") , &kSCValNetPPPAuthProtocolPAP , 0 }, { NULL , NULL , 0 } }; 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 }, // --- 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 }, // --- 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 }, // --- CCP: --- { "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 }, // --- 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 }, // --- Help --- { "?" , NULL , isHelp , NULL , NULL , "\nPPP configuration commands\n\n" " set interface [Account account]\n" " set interface [Password password]\n" " set interface [Number telephone-number]\n" " set interface [AlternateNumber telephone-number]\n" " set interface [IdleReminder {enable|disable}]\n" " 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}]" } }; #define N_PPP_OPTIONS (sizeof(pppOptions) / sizeof(pppOptions[0])) static Boolean set_interface_ppp(int argc, char **argv, CFMutableDictionaryRef newConfiguration) { Boolean ok; ok = _process_options(pppOptions, N_PPP_OPTIONS, argc, argv, newConfiguration); return ok; } /* -------------------- */ static Boolean set_interface_vlan(int argc, char **argv, CFMutableDictionaryRef newConfiguration) { // xxxxx ("device", "tag") SCPrint(TRUE, stdout, CFSTR("vlan interface management not yet supported\n")); return FALSE; } /* -------------------- */ __private_extern__ void set_interface(int argc, char **argv) { CFDictionaryRef configuration; CFStringRef interfaceType; CFMutableDictionaryRef newConfiguration = NULL; Boolean ok = FALSE; if (net_interface == NULL) { SCPrint(TRUE, stdout, CFSTR("interface not selected\n")); return; } if (argc < 1) { SCPrint(TRUE, stdout, CFSTR("set what?\n")); return; } configuration = SCNetworkInterfaceGetConfiguration(net_interface); if (configuration == NULL) { 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)) { ok = set_interface_ethernet(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, kSCNetworkInterfaceTypeVLAN)) { ok = set_interface_vlan(argc, argv, newConfiguration); } else { SCPrint(TRUE, stdout, CFSTR("this interfaces configuration cannot be changed\n")); } if (!ok) { goto done; } if (((configuration == NULL) && (CFDictionaryGetCount(newConfiguration) > 0)) || ((configuration != NULL) && !CFEqual(configuration, newConfiguration))) { if (!SCNetworkInterfaceSetConfiguration(net_interface, 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; } net_changed = TRUE; } done : if (newConfiguration != NULL) CFRelease(newConfiguration); return; } /* -------------------- */ __private_extern__ void show_interface(int argc, char **argv) { SCNetworkInterfaceRef interface; if (argc == 1) { interface = _find_interface(argv[0]); } else { if (net_interface != NULL) { interface = net_interface; } else { SCPrint(TRUE, stdout, CFSTR("interface not selected\n")); return; } } if (interface != NULL) { _show_interface(interface, CFSTR(""), TRUE); } return; } /* -------------------- */ __private_extern__ CFStringRef _interface_description(SCNetworkInterfaceRef interface) { CFMutableStringRef description; CFStringRef if_bsd_name; CFStringRef if_type; description = CFStringCreateMutable(NULL, 0); if_type = SCNetworkInterfaceGetInterfaceType(interface); CFStringAppend(description, if_type); if_bsd_name = SCNetworkInterfaceGetBSDName(interface); if (if_bsd_name != NULL) { CFStringAppendFormat(description, NULL, CFSTR(" (%@)"), if_bsd_name); } interface = SCNetworkInterfaceGetInterface(interface); while ((interface != NULL) && !CFEqual(interface, kSCNetworkInterfaceIPv4)) { CFStringRef childDescription; childDescription = _interface_description(interface); CFStringAppendFormat(description, NULL, CFSTR(" / %@"), childDescription); CFRelease(childDescription); interface = SCNetworkInterfaceGetInterface(interface); } return description; }