Ported tun_device initialization to OS X utun

This commit is contained in:
Martin Willi
2012-08-28 11:16:31 +02:00
parent 8528f841de
commit 584c063e36
+86 -20
View File
@@ -3,6 +3,7 @@
* Copyright (C) 2012 Giuliano Grassi * Copyright (C) 2012 Giuliano Grassi
* Copyright (C) 2012 Ralf Sager * Copyright (C) 2012 Ralf Sager
* Hochschule fuer Technik Rapperswil * Hochschule fuer Technik Rapperswil
* Copyright (C) 2012 Martin Willi
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
@@ -24,8 +25,16 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#ifdef __APPLE__
#include <net/if.h>
#include <net/if_utun.h>
#include <netinet/in_var.h>
#include <sys/kern_control.h>
#else /* !__APPLE__ */
#include <linux/if.h> #include <linux/if.h>
#include <linux/if_tun.h> #include <linux/if_tun.h>
#endif /* !__APPLE__ */
#include "tun_device.h" #include "tun_device.h"
@@ -127,6 +136,14 @@ METHOD(tun_device_t, set_address, bool,
this->if_name, strerror(errno)); this->if_name, strerror(errno));
return FALSE; return FALSE;
} }
#ifdef __APPLE__
if (ioctl(this->sock, SIOCSIFDSTADDR, &ifr) < 0)
{
DBG1(DBG_LIB, "failed to set dest address on %s: %s",
this->if_name, strerror(errno));
return FALSE;
}
#endif /* __APPLE__ */
set_netmask(&ifr, family, netmask); set_netmask(&ifr, family, netmask);
@@ -278,18 +295,70 @@ METHOD(tun_device_t, destroy, void,
} }
/** /**
* Allocate a TUN device * Initialize the tun device
*/ */
static int tun_alloc(char dev[IFNAMSIZ]) static bool init_tun(private_tun_device_t *this, const char *name_tmpl)
{ {
struct ifreq ifr; #ifdef __APPLE__
int fd;
fd = open("/dev/net/tun", O_RDWR); struct ctl_info info;
if (fd < 0) struct sockaddr_ctl addr;
socklen_t size = IFNAMSIZ;
memset(&info, 0, sizeof(info));
memset(&addr, 0, sizeof(addr));
this->tunfd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
if (this->tunfd < 0)
{
DBG1(DBG_LIB, "failed to open tundevice PF_SYSTEM socket: %s",
strerror(errno));
return FALSE;
}
/* get a control identifier for the utun kernel extension */
strncpy(info.ctl_name, UTUN_CONTROL_NAME, strlen(UTUN_CONTROL_NAME));
if (ioctl(this->tunfd, CTLIOCGINFO, &info) < 0)
{
DBG1(DBG_LIB, "failed to ioctl tundevice: %s", strerror(errno));
close(this->tunfd);
return FALSE;
}
addr.sc_id = info.ctl_id;
addr.sc_len = sizeof(addr);
addr.sc_family = AF_SYSTEM;
addr.ss_sysaddr = AF_SYS_CONTROL;
/* allocate identifier dynamically */
addr.sc_unit = 0;
if (connect(this->tunfd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
{
DBG1(DBG_LIB, "failed to connect tundevice: %s", strerror(errno));
close(this->tunfd);
return FALSE;
}
if (getsockopt(this->tunfd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME,
this->if_name, &size) < 0)
{
DBG1(DBG_LIB, "getting tundevice name failed: %s", strerror(errno));
close(this->tunfd);
return FALSE;
}
return TRUE;
#else /* !__APPLE__ */
struct ifreq ifr;
strncpy(this->if_name, name_tmpl ?: "tun%d", IFNAMSIZ);
this->if_name[IFNAMSIZ-1] = '\0';
this->tunfd = open("/dev/net/tun", O_RDWR);
if (this->tunfd < 0)
{ {
DBG1(DBG_LIB, "failed to open /dev/net/tun: %s", strerror(errno)); DBG1(DBG_LIB, "failed to open /dev/net/tun: %s", strerror(errno));
return fd; return FALSE;
} }
memset(&ifr, 0, sizeof(ifr)); memset(&ifr, 0, sizeof(ifr));
@@ -297,16 +366,17 @@ static int tun_alloc(char dev[IFNAMSIZ])
/* TUN device, no packet info */ /* TUN device, no packet info */
ifr.ifr_flags = IFF_TUN | IFF_NO_PI; ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
strncpy(ifr.ifr_name, dev, IFNAMSIZ); strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
if (ioctl(this->tunfd, TUNSETIFF, (void*)&ifr) < 0)
if (ioctl(fd, TUNSETIFF, (void*)&ifr) < 0)
{ {
DBG1(DBG_LIB, "failed to configure TUN device: %s", strerror(errno)); DBG1(DBG_LIB, "failed to configure TUN device: %s", strerror(errno));
close(fd); close(this->tunfd);
return -1; return FALSE;
} }
strncpy(dev, ifr.ifr_name, IFNAMSIZ); strncpy(this->if_name, ifr.ifr_name, IFNAMSIZ);
return fd; return TRUE;
#endif /* !__APPLE__ */
} }
/* /*
@@ -331,13 +401,9 @@ tun_device_t *tun_device_create(const char *name_tmpl)
.sock = -1, .sock = -1,
); );
strncpy(this->if_name, name_tmpl ?: "tun%d", IFNAMSIZ); if (!init_tun(this, name_tmpl))
this->if_name[IFNAMSIZ-1] = '\0';
this->tunfd = tun_alloc(this->if_name);
if (this->tunfd < 0)
{ {
destroy(this); free(this);
return NULL; return NULL;
} }
DBG1(DBG_LIB, "created TUN device: %s", this->if_name); DBG1(DBG_LIB, "created TUN device: %s", this->if_name);