/* ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- */ static void nc_start(int argc, char **argv) { CFMutableDictionaryRef userOptions = NULL; CFStringRef iftype = NULL; CFStringRef ifsubtype = NULL; SCNetworkServiceRef service = NULL; nc_create_connection(argc, argv, TRUE); service = SCNetworkConnectionGetService(connection); nc_get_service_type_and_subtype(service, &iftype, &ifsubtype); userOptions = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); Boolean isL2TP = (CFEqual(iftype, kSCEntNetPPP) && (ifsubtype != NULL) && CFEqual(ifsubtype, kSCValNetInterfaceSubTypeL2TP)); if (CFEqual(iftype, kSCEntNetPPP)) { CFMutableDictionaryRef pppEntity = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (username != NULL) { CFDictionarySetValue(pppEntity, kSCPropNetPPPAuthName, username); } if (password != NULL) { CFDictionarySetValue(pppEntity, kSCPropNetPPPAuthPassword, password); } CFDictionarySetValue(userOptions, kSCEntNetPPP, pppEntity); my_CFRelease(&pppEntity); } if (CFEqual(iftype, kSCEntNetIPSec) || isL2TP) { CFMutableDictionaryRef ipsecEntity = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (!isL2TP) { if (username != NULL) { CFDictionarySetValue(ipsecEntity, kSCPropNetIPSecXAuthName, username); } if (password != NULL) { CFDictionarySetValue(ipsecEntity, kSCPropNetIPSecXAuthPassword, password); } } if (sharedsecret != NULL) { CFDictionarySetValue(ipsecEntity, kSCPropNetIPSecSharedSecret, sharedsecret); } CFDictionarySetValue(userOptions, kSCEntNetIPSec, ipsecEntity); my_CFRelease(&ipsecEntity); } if (CFEqual(iftype, kSCEntNetVPN)) { CFMutableDictionaryRef vpnEntity = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (username != NULL) { CFDictionarySetValue(vpnEntity, kSCPropNetVPNAuthName, username); } if (password != NULL) { CFDictionarySetValue(vpnEntity, kSCPropNetVPNAuthPassword, password); } CFDictionarySetValue(userOptions, kSCEntNetVPN, vpnEntity); my_CFRelease(&vpnEntity); } // If it doesn't match any VPN type, fail silently if (!SCNetworkConnectionStart(connection, userOptions, TRUE)) { SCPrint(TRUE, stderr, CFSTR("Could not start connection: %s\n"), SCErrorString(SCError())); exit(1); }; CFRelease(userOptions); nc_release_connection(); exit(0); }
int main (int argc, const char * argv[]) // This program finds the first PPP connection service in the // current network configuration and then connects and // disconnects that service. { int err; Boolean ok; CFStringRef serviceToDial; CFDictionaryRef optionsForDial; SCNetworkConnectionRef connection; CallbackParams params; serviceToDial = NULL; optionsForDial = NULL; connection = NULL; // If we're run without an argument, just print the usage. err = 0; if (argc != 1) { const char *programName; programName = strrchr(argv[0], '/'); if (programName == NULL) { programName = argv[0]; } else { programName += 1; } fprintf(stderr, "Usage: %s\n", programName); err = ECANCELED; } // Find the serviceID of the PPP service to dial and the user's // preferred dialling options. This routine picks up the last // service dialled using Internet Connect (and the associated // options) or, if Internet Connect has not been used, returns // the first PPP service listed in the Network preferences pane. if (err == 0) { ok = SCNetworkConnectionCopyUserPreferences( NULL, &serviceToDial, &optionsForDial ); if ( ! ok ) { err = SCError(); } } // Create a SCNetworkConnectionRef for it. if (err == 0) { SCNetworkConnectionContext context; // Set up the parameters to our callback function. params.magic = kCallbackParamsMagic; params.forcePrintStatus = true; params.lastMinorStatus = kSCNetworkConnectionDisconnected; params.lastMinorStatus = kSCNetworkConnectionPPPDisconnected; // Set up the context to reference those parameters. context.version = 0; context.info = (void *) ¶ms; context.retain = NULL; context.release = NULL; context.copyDescription = NULL; connection = SCNetworkConnectionCreateWithServiceID( NULL, serviceToDial, MyNetworkConnectionCallBack, &context ); if (connection == NULL) { err = SCError(); } } // Schedule our callback with the runloop. if (err == 0) { ok = SCNetworkConnectionScheduleWithRunLoop( connection, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode ); if ( ! ok ) { err = SCError(); } } // Check the status. If we're already connected tell the user. // If we're not connected, initiate the connection. if (err == 0) { err = ECANCELED; // Most cases involve us bailing out, // so set the error here. switch ( SCNetworkConnectionGetStatus(connection) ) { case kSCNetworkConnectionDisconnected: err = 0; break; case kSCNetworkConnectionConnecting: fprintf(stderr, "Service is already connecting.\n"); break; case kSCNetworkConnectionDisconnecting: fprintf(stderr, "Service is disconnecting.\n"); break; case kSCNetworkConnectionConnected: fprintf(stderr, "Service is already connected.\n"); break; case kSCNetworkConnectionInvalid: fprintf(stderr, "Service is invalid. Weird.\n"); break; default: fprintf(stderr, "Unexpected status.\n"); break; } } // Initiate the connection. if (err == 0) { fprintf(stderr, "Connecting...\n"); ok = SCNetworkConnectionStart( connection, optionsForDial, false ); if ( ! ok ) { err = SCError(); } } // Run the runloop and wait for our connection attempt to be resolved. // Once that happens, print the result. if (err == 0) { CFRunLoopRun(); switch (params.lastMinorStatus) { case kSCNetworkConnectionPPPConnected: fprintf(stderr, "Connection succeeded\n"); break; case kSCNetworkConnectionPPPDisconnected: fprintf(stderr, "Connection failed\n"); err = ECANCELED; break; default: fprintf( stderr, "Bad params.lastMinorStatus (%ld)\n", (long) params.lastMinorStatus ); err = EINVAL; break; } } // Wait for a few seconds. if (err == 0) { fprintf(stderr, "Waiting for a few seconds...\n"); (void) sleep(5); // Initiate a disconnect. params.forcePrintStatus = true; fprintf(stderr, "Disconnecting...\n"); ok = SCNetworkConnectionStop( connection, true ); if ( ! ok ) { err = SCError(); } } // Run the runloop and wait for our disconnection attempt to be // resolved. Once that happens, print the result. if (err == 0) { CFRunLoopRun(); switch (params.lastMinorStatus) { case kSCNetworkConnectionPPPDisconnected: fprintf(stderr, "Disconnection succeeded\n"); break; case kSCNetworkConnectionPPPConnected: fprintf(stderr, "Disconnection failed\n"); err = ECANCELED; break; default: fprintf( stderr, "Bad params.lastMinorStatus (%ld)\n", (long) params.lastMinorStatus ); err = EINVAL; break; } } // Clean up. if (serviceToDial != NULL) { CFRelease(serviceToDial); } if (optionsForDial != NULL) { CFRelease(optionsForDial); } if (connection != NULL) { (void) SCNetworkConnectionUnscheduleFromRunLoop( connection, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode ); CFRelease(connection); } if (err == 0) { return EXIT_SUCCESS; } else { if (err != ECANCELED) { fprintf(stderr, "Failed with error %d\n.", err); } return EXIT_FAILURE; } }