Skip to content

Commit

Permalink
Better socket opening code
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisballinger committed Apr 14, 2014
1 parent 9d82e75 commit b7aa0b6
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 73 deletions.
119 changes: 90 additions & 29 deletions CBTunService/PrivilegedAgent.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,64 +24,125 @@

#include <stdlib.h> // exit, etc.

int
tun(void)

// the below C functions have been adapted from OpenVPN's tun.c

/* Helper functions that tries to open utun device
return -2 on early initialization failures (utun not supported
at all (old OS X) and -1 on initlization failure of utun
device (utun works but utunX is already used */
static
int utun_open_helper (struct ctl_info ctlInfo, int utunnum)
{
struct sockaddr_ctl sc;
struct ctl_info ctlInfo;
int fd;


memset(&ctlInfo, 0, sizeof(ctlInfo));
if (strlcpy(ctlInfo.ctl_name, UTUN_CONTROL_NAME, sizeof(ctlInfo.ctl_name)) >=
sizeof(ctlInfo.ctl_name)) {
fprintf(stderr,"UTUN_CONTROL_NAME too long");
return -1;
}
fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);

if (fd == -1) {
perror ("socket(SYSPROTO_CONTROL)");
return -1;
if (fd < 0)
{
NSLog(@"Opening utun (%s): %s", "socket(SYSPROTO_CONTROL)",
strerror (errno));
return -2;
}
if (ioctl(fd, CTLIOCGINFO, &ctlInfo) == -1) {
perror ("ioctl(CTLIOCGINFO)");
close(fd);
return -1;

if (ioctl(fd, CTLIOCGINFO, &ctlInfo) == -1)
{
close (fd);
NSLog(@"Opening utun (%s): %s", "ioctl(CTLIOCGINFO)",
strerror (errno));
return -2;
}


sc.sc_id = ctlInfo.ctl_id;
sc.sc_len = sizeof(sc);
sc.sc_family = AF_SYSTEM;
sc.ss_sysaddr = AF_SYS_CONTROL;
sc.sc_unit = 2; /* Only have one, in this example... */

sc.sc_unit = utunnum+1;

// If the connect is successful, a tun%d device will be created, where "%d"
// is our unit number -1

if (connect(fd, (struct sockaddr *)&sc, sizeof(sc)) == -1) {
perror ("connect(AF_SYS_CONTROL)");
/* If the connect is successful, a utun%d device will be created, where "%d"
* is (sc.sc_unit - 1) */

if (connect (fd, (struct sockaddr *)&sc, sizeof(sc)) < 0)
{
NSLog(@"Opening utun (%s): %s", "connect(AF_SYS_CONTROL)",
strerror (errno));
close(fd);
return -1;
}

fcntl (fd, F_SETFL, O_NONBLOCK);
fcntl (fd, F_SETFD, FD_CLOEXEC); /* don't pass fd to scripts */

return fd;
}

@implementation PrivilegedAgent

- (void)openTun:(void (^)(NSFileHandle *tun, NSError *error))reply {
[self closeTun];
int utunfd = tun();
- (NSFileHandle*) openUtun {
struct ctl_info ctlInfo;
int fd = -1;
int utunnum =-1;

NSError * error = nil;
memset(&(ctlInfo), 0, sizeof(ctlInfo));

if (utunfd != -1) {
self.tunHandle = [[NSFileHandle alloc] initWithFileDescriptor:utunfd closeOnDealloc:YES];
if (strlcpy(ctlInfo.ctl_name, UTUN_CONTROL_NAME, sizeof(ctlInfo.ctl_name)) >=
sizeof(ctlInfo.ctl_name))
{
NSLog(@"Opening utun: UTUN_CONTROL_NAME too long");
}

/* try to open first available utun device if no specific utun is requested */
if (utunnum == -1)
{
for (utunnum=0; utunnum<255; utunnum++)
{
fd = utun_open_helper (ctlInfo, utunnum);
/* Break if the fd is valid,
* or if early initalization failed (-2) */
if (fd !=-1)
break;
}
}
else
{
fd = utun_open_helper (ctlInfo, utunnum);
}

/* opening an utun device failed */
if (fd < 0) {
return nil;
}

NSFileHandle *fileHandle = [[NSFileHandle alloc] initWithFileDescriptor:fd closeOnDealloc:YES];
return fileHandle;
}

- (NSString*) getHandleInterfaceName:(NSFileHandle*)fileHandle {
int fd = fileHandle.fileDescriptor;
char utunname[20];
socklen_t utunname_len = sizeof(utunname);

NSString *interfaceName = nil;
/* Retrieve the assigned interface name. */
if (getsockopt (fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, utunname, &utunname_len)) {
NSLog(@"Error retrieving utun interface name");
} else {
interfaceName = [[NSString alloc] initWithBytes:utunname length:utunname_len encoding:NSUTF8StringEncoding];
}
return interfaceName;
}

- (void)openTun:(void (^)(NSFileHandle *tun, NSError *error))reply {
[self closeTun];
self.tunHandle = [self openUtun];
NSError *error = nil;
if (!self.tunHandle) {
error = [NSError errorWithDomain:@"com.chrisballinger.CBTunService" code:100 userInfo:@{NSLocalizedDescriptionKey: @"Error opening TUN fd"}];
}

if (reply) {
reply(self.tunHandle, error);
}
Expand Down
45 changes: 1 addition & 44 deletions Tether.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
D931A61418304D1200593FF9 /* CBDeviceConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = D931A61318304D1200593FF9 /* CBDeviceConnection.m */; };
D950871618F6836900EF884A /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CDD1E9FE263401C93089B68 /* libPods.a */; };
D9792EE518FB563F002F2E28 /* ServiceManagement.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9792EE418FB563F002F2E28 /* ServiceManagement.framework */; };
D9792EF318FB58E2002F2E28 /* CBTunService.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = D9792EF218FB58E2002F2E28 /* CBTunService.1 */; };
D9792EF718FB593A002F2E28 /* PrivilegedAgent.m in Sources */ = {isa = PBXBuildFile; fileRef = D9792EDE18FB4DCF002F2E28 /* PrivilegedAgent.m */; };
D9792EF818FB593A002F2E28 /* PrivilegedServiceDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D9792EE018FB4DCF002F2E28 /* PrivilegedServiceDelegate.m */; };
D9792EF918FB593A002F2E28 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D9792ED618FB4CCE002F2E28 /* main.m */; };
Expand Down Expand Up @@ -69,7 +68,6 @@
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
D9792EF318FB58E2002F2E28 /* CBTunService.1 in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 1;
};
Expand Down Expand Up @@ -110,8 +108,6 @@
D9792EE018FB4DCF002F2E28 /* PrivilegedServiceDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PrivilegedServiceDelegate.m; sourceTree = "<group>"; };
D9792EE418FB563F002F2E28 /* ServiceManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ServiceManagement.framework; path = System/Library/Frameworks/ServiceManagement.framework; sourceTree = SDKROOT; };
D9792EEE18FB58E2002F2E28 /* com.chrisballinger.CBTunService */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = com.chrisballinger.CBTunService; sourceTree = BUILT_PRODUCTS_DIR; };
D9792EF018FB58E2002F2E28 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = "<group>"; };
D9792EF218FB58E2002F2E28 /* CBTunService.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = CBTunService.1; sourceTree = "<group>"; };
D9B76799184A8734000566D6 /* Tether.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Tether.app; sourceTree = BUILT_PRODUCTS_DIR; };
D9B7679A184A8734000566D6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
D9B7679C184A8734000566D6 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
Expand All @@ -123,9 +119,6 @@
D9B767A9184A8734000566D6 /* CBAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CBAppDelegate.h; sourceTree = "<group>"; };
D9B767AA184A8734000566D6 /* CBAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CBAppDelegate.m; sourceTree = "<group>"; };
D9B767AC184A8734000566D6 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
D9B767BA184A8735000566D6 /* TetherTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "TetherTests-Info.plist"; sourceTree = "<group>"; };
D9B767BC184A8735000566D6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
D9B767BE184A8735000566D6 /* TetherTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TetherTests.m; sourceTree = "<group>"; };
D9B767C8184A88BA000566D6 /* main-mac.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "main-mac.m"; sourceTree = "<group>"; };
D9B767CA184A8991000566D6 /* CBRootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CBRootViewController.h; sourceTree = "<group>"; };
D9B767CB184A8991000566D6 /* CBRootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CBRootViewController.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -182,9 +175,7 @@
D9B767C7184A877A000566D6 /* USBMuxClient */,
D90E325E182F07DC00A6F642 /* TetherMac */,
D9B767A0184A8734000566D6 /* Tether-iOS */,
D9B767B8184A8735000566D6 /* TetherTests */,
D9792ECF18FB4CCE002F2E28 /* CBTunService */,
D9792EEF18FB58E2002F2E28 /* CBTunService */,
D90E3257182F07DC00A6F642 /* Frameworks */,
D90E3256182F07DC00A6F642 /* Products */,
3344A729C1604CC882D91F05 /* Pods.xcconfig */,
Expand Down Expand Up @@ -286,15 +277,6 @@
name = "Supporting Files";
sourceTree = "<group>";
};
D9792EEF18FB58E2002F2E28 /* CBTunService */ = {
isa = PBXGroup;
children = (
D9792EF018FB58E2002F2E28 /* main.c */,
D9792EF218FB58E2002F2E28 /* CBTunService.1 */,
);
path = CBTunService;
sourceTree = "<group>";
};
D9B767A0184A8734000566D6 /* Tether-iOS */ = {
isa = PBXGroup;
children = (
Expand All @@ -320,24 +302,6 @@
name = "Supporting Files";
sourceTree = "<group>";
};
D9B767B8184A8735000566D6 /* TetherTests */ = {
isa = PBXGroup;
children = (
D9B767BE184A8735000566D6 /* TetherTests.m */,
D9B767B9184A8735000566D6 /* Supporting Files */,
);
path = TetherTests;
sourceTree = "<group>";
};
D9B767B9184A8735000566D6 /* Supporting Files */ = {
isa = PBXGroup;
children = (
D9B767BA184A8735000566D6 /* TetherTests-Info.plist */,
D9B767BB184A8735000566D6 /* InfoPlist.strings */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
D9B767C7184A877A000566D6 /* USBMuxClient */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -585,14 +549,6 @@
name = InfoPlist.strings;
sourceTree = "<group>";
};
D9B767BB184A8735000566D6 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
D9B767BC184A8735000566D6 /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */

/* Begin XCBuildConfiguration section */
Expand Down Expand Up @@ -835,6 +791,7 @@
D9792EF618FB58E2002F2E28 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
D9B767C0184A8735000566D6 /* Build configuration list for PBXNativeTarget "Tether" */ = {
isa = XCConfigurationList;
Expand Down
1 change: 1 addition & 0 deletions Tether/CBDeviceWindowController.m
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ - (void)windowDidLoad
}];
}

// HexFiend has a great example how to do this properly
- (BOOL)blessHelperWithLabel:(NSString *)label
error:(NSError **)error {

Expand Down

0 comments on commit b7aa0b6

Please sign in to comment.