我想创建将与L2TP协议建立新连接的代码。
下面是我的代码。
我没有发现任何错误,但代码运行成功并创建新网络,但它没有显示我传递的数据,例如用户名。
- (IBAction)connectVPN_Cliced:(NSButton *)sender{
VPNServiceConfig *config = [[VPNServiceConfig alloc]init];
config.username = @"username";
config.password = @"password";
config.endpointPrefix = @"Server IP end prefix";
config.endpointSuffix = @"Server IP end endpointSuffix";
config.sharedSecret = @"sharedkey";
config.name = @"L2TP By Mac Application";
config.endpoint = @"Server IP";
config.type = 1;
[self setupVPN:config];
}
- (AuthorizationRef) getAuth {
AuthorizationRef auth = NULL;
OSStatus status;
status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, [self flags], &auth);
if (status == errAuthorizationSuccess) {
NSLog(@"Successfully obtained Authorization reference");
} else {
NSLog(@"Could not obtain Authorization reference");
exit(101);
}
return auth;
}
- (AuthorizationFlags) flags {
return kAuthorizationFlagDefaults |
kAuthorizationFlagExtendRights |
kAuthorizationFlagInteractionAllowed |
kAuthorizationFlagPreAuthorize;
}
- (void)setupVPN:(VPNServiceConfig *)vpnConfig {
// Obtaining permission to modify network settings
AuthorizationRef auth = [self getAuth];
SCPreferencesRef prefs = SCPreferencesCreateWithAuthorization(kCFAllocatorDefault, CFSTR("macVPN"), NULL, auth);
SCPreferencesUnlock(prefs);
//-------- This is i tried by me to add data but it's not working ------ Start //
SCPreferencesSetValue(prefs, CFSTR("Type"), CFSTR("PPP"));
SCPreferencesSetValue(prefs, CFSTR("SubType"), CFSTR("L2TP"));
SCPreferencesSetValue(prefs, CFSTR("AuthName"), CFSTR("username"));
SCPreferencesSetValue(prefs, CFSTR("AuthPassword"), CFSTR("password"));
SCPreferencesSetValue(prefs, CFSTR("CommRemoteAddress"), CFSTR("server ip"));
NSData *pppData = [@"0000" dataUsingEncoding:NSUTF8StringEncoding];
CFDataRef ref = CFDataCreate(kCFAllocatorDefault, pppData.bytes, pppData.length);
// CFPropertyListFormat
CFPropertyListRef propertyRef = CFPropertyListCreateWithData(kCFAllocatorDefault, ref, kCFPropertyListMutableContainers, nil,nil);
Boolean isValidData = CFPropertyListIsValid(propertyRef, kCFPropertyListXMLFormat_v1_0);
SCPreferencesSetValue(prefs, CFSTR("AuthPassword"), propertyRef);
//-------- This is i tried by me to add data but it's not working ------ End //
// Making sure other process cannot make configuration modifications
// by obtaining a system-wide lock over the system preferences.
if (SCPreferencesLock(prefs, TRUE)) {
NSLog(@"Gained superhuman rights.");
} else {
NSLog(@"Sorry, without superuser privileges I won't be able to add any VPN interfaces.");
return;
}
// If everything will work out fin
[self createService:vpnConfig usingPreferencesRef:prefs];
// We're done, other processes may modify the system configuration again
return;
}
- (void) createService:(VPNServiceConfig *)config usingPreferencesRef:(SCPreferencesRef)prefs {
NSLog(@"Creating new %@ Service using %@", config.humanType, config);
// These variables will hold references to our new interfaces
SCNetworkInterfaceRef bottomInterface = SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,kSCNetworkInterfaceTypeL2TP);
SCNetworkInterfaceRef topInterface = SCNetworkInterfaceCreateWithInterface(bottomInterface, kSCNetworkInterfaceTypePPP);
// Creating a new, fresh VPN service in memory using the interface we already created
SCNetworkServiceRef service = SCNetworkServiceCreate(prefs, topInterface);
// That service is to have a name
SCNetworkServiceSetName(service, (__bridge CFStringRef)config.name);
// And we also woould like to know the internal ID of this service
NSString *serviceID = (__bridge NSString *)(SCNetworkServiceGetServiceID(service));
// It will be used to find the correct passwords in the system keychain
//config.serviceID = serviceID;
[config setServiceID:serviceID];
// Interestingly enough, the interface variables in itself are now worthless
// We used them to create the service and that's it, we cannot modify them any more.
CFRelease(topInterface);
CFRelease(bottomInterface);
topInterface = NULL;
bottomInterface = NULL;
topInterface = SCNetworkServiceGetInterface(service);
// Let's apply all configuration to the PPTP interface
// Specifically, the servername, account username and password
if (SCNetworkInterfaceSetConfiguration(topInterface, config.L2TPIPSecConfig)) {
NSLog(@"Successfully configured PPP interface of service %@", config.name);
} else {
NSLog(@"Error: Could not configure PPP interface for service %@", config.name);
return;
}
if (SCNetworkInterfaceSetExtendedConfiguration(topInterface, kSCEntNetIPSec, config.L2TPIPSecConfig)) {
NSLog(@"Successfully configured IPSec on PPP interface for service %@", config.name);
} else {
NSLog(@"Error: Could not configure PPTP on PPP interface for service %@. %s (Code %i)", config.name, SCErrorString(SCError()), SCError());
//return;
}
NSLog(@"Adding default protocols (DNS, etc.) to service %@...", config.name);
if (!SCNetworkServiceEstablishDefaultConfiguration(service)) {
NSLog(@"Error: Could not establish a default service configuration for %@. %s (Code %i)", config.name, SCErrorString(SCError()), SCError());
return;
}
NSLog(@"Fetching set of all available network services...");
SCNetworkSetRef networkSet = SCNetworkSetCopyCurrent(prefs);
if (!networkSet) {
NSLog(@"Error: Could not fetch current network set when creating %@. %s (Code %i)", config.name, SCErrorString(SCError()), SCError());
return;
}
if (!SCNetworkSetAddService (networkSet, service)) {
if (SCError() == 1005) {
NSLog(@"Skipping VPN Service %@ because it already exists.", config.humanType);
return;
} else {
NSLog(@"Error: Could not add new VPN service %@ to current network set. %s (Code %i)", config.name, SCErrorString(SCError()), SCError());
return;
}
}
NSLog(@"Fetching IPv4 protocol of service %@....", config.name);
SCNetworkProtocolRef protocol = SCNetworkServiceCopyProtocol(service, kSCNetworkProtocolTypeIPv4);
if (!protocol) {
NSLog(@"Error: Could not fetch IPv4 protocol of %@. %s (Code %i)", config.name, SCErrorString(SCError()), SCError());
return;
}
NSLog(@"Configuring IPv4 protocol of service %@...", config.name);
if (!SCNetworkProtocolSetConfiguration(protocol, config.L2TPIPSecConfig)) {
NSLog(@"Error: Could not configure IPv4 protocol of %@. %s (Code %i)", config.name, SCErrorString(SCError()), SCError());
return;
}
NSLog(@"Commiting all changes including service %@...", config.name);
if (!SCPreferencesCommitChanges(prefs)) {
NSLog(@"Error: Could not commit preferences with service %@. %s (Code %i)", config.name, SCErrorString(SCError()), SCError());
return;
}
NSLog(@"Preparing to add Keychain items for service %@...", config.name);
// The password and the shared secret are not stored directly in the System Preferences .plist file
// Instead we put them into the KeyChain. I know we're creating new items each time you run this application
// But this actually is the same behaviour you get using the official System Preferences Network Pane
[VPNKeychain createPasswordKeyChainItem:config.name forService:serviceID withAccount:config.username andPassword:config.password];
[VPNKeychain createSharedSecretKeyChainItem:config.name forService:serviceID withPassword:config.sharedSecret];
if (!SCPreferencesApplyChanges(prefs)) {
NSLog(@"Error: Could not apply changes with service %@. %s (Code %i)", config.name, SCErrorString(SCError()), SCError());
return;
}
NSLog(@"Successfully created %@ VPN %@ with ID %@", config.humanType, config.name, serviceID);
return;
}
我试过这个: how to set up a vpn connection programmatically in MAC?
更新: 代码我曾经自动连接到vpn服务器
SCNetworkConnectionRef connetionRef = SCNetworkConnectionCreateWithServiceID(kCFAllocatorDefault, (__bridge CFStringRef)(newServiceId), myCallBack, &callBackContext);
SCNetworkConnectionStart(connetionRef, config.L2TPPPPConfig, FALSE);