• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
create vpn/pptp connection programmatically
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

create vpn/pptp connection programmatically


  • Subject: create vpn/pptp connection programmatically
  • From: Juping Jin <email@hidden>
  • Date: Mon, 04 Jul 2011 15:34:55 -0400
  • Importance: Normal

I am trying to create vpn/pptp connection using SystemConfiguration framework. After reading Apple's SC programming guide and  some codes I could find on Internet, I came up with the follow code.

The code doesn't work (of course). SCNetworkConnectionStart(...) return error code 1001 which is a non-specific error (completely useless). 

Then I looked at Network panel in System Preference, the connection is there but shown as "Not Configured". all entries are empty. It seems like that the options I set in the program didn't make it into data store.

Can someone tell me where I did wrong?

Apple's SC programming guide (http://developer.apple.com/library/mac/#documentation/Networking/Conceptual/SystemConfigFrameworks/SC_UnderstandSchema/SC_UnderstandSchema.html)
t
mentioned a sample code MORESCF. But I could not find it in Sample code library. Does anyone have a copy of it and send it to me?

Thanks.

 +(int) createPptpConnection: (CFStringRef) username

withPassword: (CFStringRef) password

remoteServer: (CFStringRef) address

{

// PPP options

CFStringRef keysPPP[4]  = { NULL, NULL, NULL, NULL };

CFStringRef valsPPP[4]  = { NULL, NULL, NULL, NULL };

CFIndex numkeys         = 0;

CFStringRef kVendorName = CFSTR("myvpn.com");

CFStringRef kAppName = CFSTR("myvpn");

    OSStatus        authErr = noErr;

CFDictionaryRef serviceOptions;

SCNetworkConnectionRef connection;

keysPPP[numkeys]    = kSCPropNetPPPAuthName;

valsPPP[numkeys++]  = username;

keysPPP[numkeys]    = kSCPropNetPPPAuthPassword;

valsPPP[numkeys++]  = password;

keysPPP[numkeys]    = kSCPropNetPPPCommRemoteAddress;

valsPPP[numkeys++]  = address;

keysPPP[numkeys]    = kSCPropUserDefinedName;

valsPPP[numkeys++]  = kAppName;

    int err = 0;


CFDictionaryRef pppOptionsForDial   = CFDictionaryCreate (NULL,

  (const void **)&keysPPP,

  (const void **)&valsPPP,

  numkeys,  

  &kCFTypeDictionaryKeyCallBacks,

  &kCFTypeDictionaryValueCallBacks);

    // Release strings after including them in dictionary

    CFRelease(username);

    CFRelease(password);

    CFRelease(address);

// Interface options

CFStringRef keysInt[]   = { kSCPropNetInterfaceType, kSCPropNetInterfaceSubType };

CFStringRef valsInt[]   = { kSCValNetInterfaceTypePPP, kSCValNetInterfaceSubTypePPTP };

CFDictionaryRef interfaceOptionsForDial = CFDictionaryCreate (NULL,

  (const void **)&keysInt,

  (const void **)&valsInt,

  2,  

  &kCFTypeDictionaryKeyCallBacks,

  &kCFTypeDictionaryValueCallBacks);

// IPv4 options

CFStringRef keysIPv4[]  = { kSCPropNetIPv4ConfigMethod, kSCPropNetOverridePrimary };

CFStringRef valsIPv4[]  = { kSCValNetIPv4ConfigMethodPPP, CFSTR("1") };

CFDictionaryRef ipv4OptionsForDial  = CFDictionaryCreate (NULL, 

  (const void **)&keysIPv4,

  (const void **)&valsIPv4,

  2,  

  &kCFTypeDictionaryKeyCallBacks,

  &kCFTypeDictionaryValueCallBacks);

// IPv6 options

CFStringRef keysIPv6[]  = { kSCPropNetIPv6ConfigMethod };

CFStringRef valsIPv6[]  = { kSCValNetIPv6ConfigMethodAutomatic };

CFDictionaryRef ipv6OptionsForDial  = CFDictionaryCreate (NULL,

  (const void **)&keysIPv6,

  (const void **)&valsIPv6,

  1,  

  &kCFTypeDictionaryKeyCallBacks,

  &kCFTypeDictionaryValueCallBacks);

CFStringRef keys[] = { kSCEntNetInterface, kSCEntNetIPv4, kSCEntNetIPv6, kSCEntNetPPP };

CFDictionaryRef vals[] = { interfaceOptionsForDial, ipv4OptionsForDial, ipv6OptionsForDial, pppOptionsForDial };    

CFDictionaryRef optionsForDial = CFDictionaryCreate (NULL,

(const void **) &keys,

(const void **) &vals,

4,

&kCFTypeDictionaryKeyCallBacks, 

&kCFTypeDictionaryValueCallBacks);

CFRelease( interfaceOptionsForDial);

CFRelease( ipv4OptionsForDial );

CFRelease( ipv6OptionsForDial );

CFRelease( pppOptionsForDial);

interfaceOptionsForDial = NULL;

ipv4OptionsForDial = NULL;

ipv6OptionsForDial = NULL;

pppOptionsForDial = NULL;


// Authority

AuthorizationFlags rootFlags = 

kAuthorizationFlagDefaults              |

kAuthorizationFlagExtendRights          |

kAuthorizationFlagInteractionAllowed    |

kAuthorizationFlagPreAuthorize;

AuthorizationRef auth;

authErr = AuthorizationCreate(NULL,

kAuthorizationEmptyEnvironment,

rootFlags,

&auth);

// Create preferences for interface.

SCPreferencesRef prefs;

    if (authErr == noErr) {

        prefs = SCPreferencesCreateWithAuthorization(NULL, kVendorName, NULL, auth);

    } else {

        prefs = SCPreferencesCreate(NULL, kVendorName, NULL);

    }

    if (prefs == NULL) {

        NSLog(@"Could not create preferences\n");

        err = SCError();

    }

    CFIndex i, arraySize;

CFStringRef serviceToDial;

Boolean serviceFound = FALSE;

SCNetworkInterfaceRef pptpItfc;

SCNetworkInterfaceRef iface;

CallbackParams          params;

SCNetworkServiceRef service;

CFArrayRef              servicesArray;

Boolean ok;

    if (err == 0) {

        servicesArray = SCNetworkServiceCopyAll(prefs);

        if (servicesArray == NULL) {

            NSLog(@"No network services");

            return -1;

        }

arraySize = CFArrayGetCount(servicesArray);

        for (i = 0; i < arraySize; ++i) {

            service = (SCNetworkServiceRef) CFArrayGetValueAtIndex(servicesArray, i);

            CFStringRef serviceName = SCNetworkServiceGetName(service);

            if (CFStringCompare(serviceName, kAppName, 0) == kCFCompareEqualTo) {

                serviceFound = TRUE;

                serviceToDial = SCNetworkServiceGetServiceID(service);

                break;

            }

        }

    }

    if (!SCPreferencesLock(prefs, TRUE)){

NSLog(@"Failed to call SCPreferencesLock");

        err = SCError();

}

    if( (err == 0) && !serviceFound) {

pptpItfc = SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4, 

kSCNetworkInterfaceTypePPTP);

iface = SCNetworkInterfaceCreateWithInterface(pptpItfc, kSCNetworkInterfaceTypePPP);

if (prefs && iface) {

service = SCNetworkServiceCreate(prefs, iface);

SCNetworkServiceSetName(service, kAppName);

iface = SCNetworkServiceGetInterface(service);

if (! SCNetworkInterfaceSetConfiguration(iface, optionsForDial)){

NSLog(@"Failed to set interface configuration");

err = SCError();

}

SCNetworkServiceEstablishDefaultConfiguration(service);

SCNetworkSetRef set = SCNetworkSetCopyCurrent(prefs);

if (set && SCNetworkSetAddService(set, service)) {

if (SCPreferencesCommitChanges(prefs)) {

if (SCPreferencesApplyChanges(prefs)){

SCPreferencesSynchronize(prefs);

serviceToDial = SCNetworkServiceGetServiceID(service);

}

}

}

}

} else {


if (SCNetworkServiceGetEnabled(service)) {

iface = SCNetworkServiceGetInterface(service);

if (! (iface && SCNetworkInterfaceSetConfiguration(iface, optionsForDial)) ){

NSLog(@"Failed to set interface configuration");

err = SCError();

}

}

        NSLog(@"Service was found!");

        SCNetworkConnectionCopyUserPreferences(NULL, &serviceToDial, &serviceOptions);

    }

SCPreferencesUnlock(prefs);

if (servicesArray != NULL) {

CFRelease(servicesArray);

}

    // 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 *) &params;

        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) {

        // Most cases involve us bailing out, set the error here

        err = ECANCELED;

        switch (SCNetworkConnectionGetStatus(connection)) {

            case kSCNetworkConnectionDisconnected:

                err = 0;

                break;

            case kSCNetworkConnectionConnecting:

                NSLog(@"Service is already connecting.\n");

                break;

            case kSCNetworkConnectionDisconnecting:

                NSLog(@"Service is disconnecting.\n");

                break;

            case kSCNetworkConnectionConnected:

                NSLog(@"Service is already connected.\n");

                break;

            case kSCNetworkConnectionInvalid:

                NSLog(@"Service is invalid. Weird.\n");

                break;

            default:

                NSLog(@"Unexpected status.\n");

                break;

        }

    }

    // Initiate the connection.

    if (err == 0) {

        NSLog(@"Connecting...\n");

        ok = SCNetworkConnectionStart(connection, optionsForDial, false);

        if (!ok) {

            err = SCError();

NSLog(@"SCNetworkConnectionStart failed: %d", err);

        }

    }

    // Run the runloop and wait for our connection attempt to be resolved.

    // Once that happens, print the result.

    CFDictionaryRef failedstatus;

    if (err == 0) {

        CFRunLoopRun();

        switch (params.lastMinorStatus) {

            case kSCNetworkConnectionPPPConnected:

                NSLog(@"Connection succeeded\n");

                break;

            case kSCNetworkConnectionPPPDisconnected:

                NSLog(@"Connection failed\n");

                failedstatus = SCNetworkConnectionCopyExtendedStatus(connection);

                CFShow(failedstatus);

                err = ECANCELED;

                break;

            default:

                NSLog(@"Bad params.lastMinorStatus (%ld)\n",

                        (long) params.lastMinorStatus);

                err = EINVAL;

        }

    }

    // Run this loop indefinitely until a SIGINT signal is received

    if (err == 0) {

        CFRunLoopRun();

    }

    // Clean up.

    if (serviceToDial != NULL) {

        CFRelease(serviceToDial);

        NSLog(@"Cleaning up serviceToDial\n");

    }

    if (serviceOptions != NULL) {

        NSLog(@"Cleaning up serviceOptions\n");

    }

    if (optionsForDial != NULL) {

        CFRelease(optionsForDial);

        NSLog(@"Cleaning up optionsForDial\n");

    }

    if (pppOptionsForDial != NULL) {

        CFRelease(pppOptionsForDial);

        NSLog(@"Cleaning up pppOptionsForDial\n");

    }

    if (connection != NULL) {

        (void) SCNetworkConnectionUnscheduleFromRunLoop(connection,

                                                        CFRunLoopGetCurrent(),

                                                        kCFRunLoopDefaultMode);

        CFRelease(connection);

        NSLog(@"Cleaning up connection\n");

    }

    if (err == 0) {

        return EXIT_SUCCESS;

    } else {

        if (err != ECANCELED) {

            NSLog(@"Failed with error %d\n.", err);

        }

        return EXIT_FAILURE;

    }

}


 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Macnetworkprog mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden

  • Follow-Ups:
    • Re: create vpn/pptp connection programmatically
      • From: "Quinn \"The Eskimo!\"" <email@hidden>
  • Prev by Date: Re: NSURLDownload and http proxy username/password
  • Next by Date: Re: Releasing CFHost
  • Previous by thread: Re: NSURLDownload and http proxy username/password
  • Next by thread: Re: create vpn/pptp connection programmatically
  • Index(es):
    • Date
    • Thread