Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Refactoring the tun code again

  • Loading branch information...
commit f1a751b3ccb1a37d3fa9e899f2722db1026bb4ae 1 parent c340147
Caleb James DeLisle authored
15 cjdroute.c
View
@@ -317,13 +317,16 @@ static void registerRouter(Dict* config, struct Address* addr, struct Context* c
if (String_equals(Dict_getString(iface, String_CONST("type")), String_CONST("TUNInterface"))) {
String* ifName = Dict_getString(iface, String_CONST("tunDevice"));
- void* tunDesc = TUNConfigurator_configure(((ifName) ? ifName->bytes : NULL),
- addr->ip6.bytes,
- 8,
- context->logger,
- AbortHandler_INSTANCE);
+ char assignedTunName[TUNConfigurator_IFNAMSIZ];
+ void* tunPtr = TUNConfigurator_initTun(((ifName) ? ifName->bytes : NULL),
+ assignedTunName,
+ context->logger,
+ AbortHandler_INSTANCE);
+
+ TUNConfigurator_setIpAddress(
+ assignedTunName, addr->ip6.bytes, 8, context->logger, AbortHandler_INSTANCE);
- struct TUNInterface* tun = TUNInterface_new(tunDesc, context->base, context->allocator);
+ struct TUNInterface* tun = TUNInterface_new(tunPtr, context->base, context->allocator);
context->tunInterface = TUNInterface_asGeneric(tun);
}
52 interface/TUNConfigurator.h
View
@@ -19,25 +19,49 @@
#include "util/Log.h"
/**
- * Configure a TUNInterface.
+ * This is the maximum size that will be accepted as an interface name.
+ * If this runs on a system where IFNAMSIZ is less then 16, names larger
+ * than that will also be rejected.
+ */
+#define TUNConfigurator_IFNAMSIZ 16
+
+/**
+ * Open the TUN device.
*
- * @param interface to configure.
- * @param address the ipv6 address in binary form.
- * @param prefixLen the number of bits in the network mask.
- * @param logger
+ * @param interfaceName the interface name you *want* to use or NULL to let the kernel decide.
+ * @param assignedInterfaceName an empty buffer which will be filled in with the interface
+ * name that is assigned.
+ * @param log
* @param eh if this function fails, it will raise one of the following.
* TUNConfigurator_configure_BAD_TUNNEL interfaceName was an invalid tun device name.
- * TUNConfigurator_configure_MALFORMED_ADDRESS myIp was an invalid ipv6 address.
* TUNConfigurator_configure_INTERNAL Something went wrong internally.
+ * TUNConfigurator_initTun_PERMISSION The user running this process doesn't have
+ * permission to open a tun device.
* @return an opaque pointer which represents the file descriptor for the newly configured tunnel.
*/
-#define TUNConfigurator_configure_BAD_TUNNEL -1
-#define TUNConfigurator_configure_MALFORMED_ADDRESS -2
-#define TUNConfigurator_configure_INTERNAL -3
-void* TUNConfigurator_configure(const char* interfaceName,
- const uint8_t myIp[40],
- int prefixLen,
- struct Log* logger,
- struct Except* eh);
+#define TUNConfigurator_initTun_INTERNAL -3
+#define TUNConfigurator_initTun_BAD_TUNNEL -2
+#define TUNConfigurator_initTun_PERMISSION -1
+void* TUNConfigurator_initTun(const char* interfaceName,
+ char assignedInterfaceName[TUNConfigurator_IFNAMSIZ],
+ struct Log* logger,
+ struct Except* eh);
+
+/**
+ * Set an IPv6 address on an interface, bring the interface up, and configure a route.
+ *
+ * @param interfaceName the name of the interface to alter.
+ * @param address the ip address to set.
+ * @param prefixLen the number of bits netmask to include in the route.
+ * @param logger
+ * @param eh if this function fails, it will raise one of the following.
+ * TUNConfigurator_setIpAddress_INTERNAL Catch all exception code for failures.
+ */
+#define TUNConfigurator_setIpAddress_INTERNAL -1
+void TUNConfigurator_setIpAddress(const char* interfaceName,
+ const uint8_t address[16],
+ int prefixLen,
+ struct Log* logger,
+ struct Except* eh);
#endif
129 interface/TUNConfigurator_Illumos.c
View
@@ -67,11 +67,65 @@ static void maskForPrefix(uint8_t mask[16], int prefix)
}
}
-void* TUNConfigurator_configure(const char* interfaceName,
- const uint8_t address[16],
- int prefixLen,
- struct Log* logger,
- struct Except* eh)
+void TUNConfigurator_setIpAddress(const char* interfaceName,
+ const uint8_t address[16],
+ int prefixLen,
+ struct Log* logger,
+ struct Except* eh)
+{
+ struct lifreq ifr = {
+ .lifr_ppa = 0,
+ .lifr_flags = 0
+ };
+ String* error = NULL;
+ struct sockaddr_in6* sin6 = (struct sockaddr_in6 *) &ifr.lifr_addr;
+ maskForPrefix((uint8_t*) sin6->sin6_addr.s6_addr, prefixLen);
+ ifr.lifr_addr.ss_family = AF_INET6;
+ strncpy(ifr.lifr_name, interfaceName, LIFNAMSIZ);
+
+ int udpSock = socket(AF_INET6, SOCK_DGRAM, 0);
+ if (udpSock < 0) {
+ error = "socket(AF_INET6, SOCK_DGRAM, 0)";
+
+ } else if (ioctl(udpSock, SIOCSLIFNETMASK, (caddr_t)&ifr) < 0) {
+ // set the netmask.
+ error = "ioctl(SIOCSLIFNETMASK) (setting netmask)";
+ }
+ Bits_memcpyConst(&sin6->sin6_addr, address, 16);
+ if (!error && ioctl(udpSock, SIOCSLIFADDR, (caddr_t)&ifr) < 0) {
+ // set the ip address.
+ error = "ioctl(SIOCSLIFADDR) (setting ipv6 address)";
+ }
+ if (!error && ioctl(udpSock, SIOCSLIFDSTADDR, (caddr_t)&ifr) < 0) {
+ // set the destination address for the point-to-point connection
+ // use the same as the source address since we're not really using it.
+ error = "ioctl(SIOCGLIFDSTADDR) (setting point-to-point destination address)";
+ }
+ memset(sin6, 0, sizeof(struct sockaddr_in6));
+ if (!error && ioctl(udpSock, SIOCGLIFFLAGS, (caddr_t)&ifr) < 0) {
+ // get the flags for the device.
+ error = "ioctl(SIOCGLIFFLAGS) (getting device flags)";
+ }
+ ifr.lifr_flags |= IFF_UP;
+ if (!error && ioctl(udpSock, SIOCSLIFFLAGS, (caddr_t)&ifr) < 0) {
+ // bring the interface up
+ error = "ioctl(SIOCSLIFFLAGS) (bringing the interface up)";
+ }
+
+ if (error) {
+ int err = errno;
+ close(udpSock);
+ Except_raise(eh, TUNConfigurator_setIpAddress_INTERNAL, "%s [%s]", error, strerror(err));
+ }
+ close(udpSock);
+
+ // TODO: set the route.
+}
+
+void* TUNConfigurator_initTun(const char* interfaceName,
+ char assignedInterfaceName[TUNConfigurator_IFNAMSIZ]
+ struct Log* logger,
+ struct Except* eh)
{
// Extract the number eg: 0 from tun0
int ppa = 0;
@@ -113,19 +167,20 @@ void* TUNConfigurator_configure(const char* interfaceName,
} else if (tunFd2 < 0) {
error = "open(\"/dev/tun\") (opening for plumbing interface)";
}
- Except_raise(eh, TUNConfigurator_configure_INTERNAL, error, strerror(err));
+ Except_raise(eh, TUNConfigurator_initTun_INTERNAL, error, strerror(err));
}
-
- // Since devices are numbered rather than named, it's not possible to have tun0 and cjdns0
- // so we'll skip the pretty names and call everything tunX
- char assignedName[LIFNAMSIZ];
- snprintf(assignedName, LIFNAMSIZ, "tun%d", ppa);
struct lifreq ifr = {
.lifr_ppa = ppa,
.lifr_flags = IFF_IPV6
};
- Bits_memcpyConst(ifr.lifr_name, assignedName, LIFNAMSIZ);
+
+ // Since devices are numbered rather than named, it's not possible to have tun0 and cjdns0
+ // so we'll skip the pretty names and call everything tunX
+ int maxNameSize =
+ (LIFNAMSIZ < TUNConfigurator_IFNAMSIZ) ? LIFNAMSIZ : TUNConfigurator_IFNAMSIZ;
+ snprintf(assignedName, maxNameSize, "tun%d", ppa);
+ snprintf(ifr.lifr_name, maxNameSize, "tun%d", ppa);
char* error = NULL;
@@ -145,56 +200,16 @@ void* TUNConfigurator_configure(const char* interfaceName,
error = "ioctl(I_LINK)";
}
- int udpSock = -1;
- if (!error && address) {
- ifr.lifr_flags = 0;
- ifr.lifr_ppa = 0;
- struct sockaddr_in6* sin6 = (struct sockaddr_in6 *) &ifr.lifr_addr;
- maskForPrefix((uint8_t*) sin6->sin6_addr.s6_addr, prefixLen);
- ifr.lifr_addr.ss_family = AF_INET6;
-
- udpSock = socket(AF_INET6, SOCK_DGRAM, 0);
- if (udpSock < 0) {
- // the schnozberries really do taste liek schnozberries
- error = "socket(AF_INET6, SOCK_DGRAM, 0)";
-
- } else if (ioctl(udpSock, SIOCSLIFNETMASK, (caddr_t)&ifr) < 0) {
- // set the netmask.
- error = "ioctl(SIOCSLIFNETMASK) (setting netmask)";
- }
- Bits_memcpyConst(&sin6->sin6_addr, address, 16);
- if (!error && ioctl(udpSock, SIOCSLIFADDR, (caddr_t)&ifr) < 0) {
- // set the ip address.
- error = "ioctl(SIOCSLIFADDR) (setting ipv6 address)";
- }
- if (!error && ioctl(udpSock, SIOCSLIFDSTADDR, (caddr_t)&ifr) < 0) {
- // set the destination address for the point-to-point connection
- // use the same as the source address since we're not really using it.
- error = "ioctl(SIOCGLIFDSTADDR) (setting point-to-point destination address)";
- }
- memset(sin6, 0, sizeof(struct sockaddr_in6));
- if (!error && ioctl(udpSock, SIOCGLIFFLAGS, (caddr_t)&ifr) < 0) {
- // get the flags for the device.
- error = "ioctl(SIOCGLIFFLAGS) (getting device flags)";
- }
- ifr.lifr_flags |= IFF_UP;
- if (!error && ioctl(udpSock, SIOCSLIFFLAGS, (caddr_t)&ifr) < 0) {
- // bring the interface up
- error = "ioctl(SIOCSLIFFLAGS) (bringing the interface up)";
- }
- }
-
- int err = errno;
-
- close(ipFd);
- close(udpSock);
-
if (error) {
+ int err = errno;
+ close(ipFd);
close(tunFd2);
close(tunFd);
- Except_raise(eh, TUNConfigurator_configure_INTERNAL, "%s [%s]", error, strerror(err));
+ Except_raise(eh, TUNConfigurator_initTun_INTERNAL, "%s [%s]", error, strerror(err));
}
+ close(ipFd);
+
intptr_t ret = (intptr_t) tunFd;
return (void*) ret;
}
72 interface/TUNConfigurator_Linux.c
View
@@ -44,7 +44,6 @@
};
#endif
-
/**
* Open the tun device.
*
@@ -54,47 +53,58 @@
* @param eh
* @return a file descriptor for the tunnel.
*/
-static int openTunnel(const char* interfaceName,
- char assignedInterfaceName[IFNAMSIZ],
- struct Log* logger,
- struct Except* eh)
+void* TUNConfigurator_initTun(const char* interfaceName,
+ char assignedInterfaceName[TUNConfigurator_IFNAMSIZ],
+ struct Log* logger,
+ struct Except* eh)
{
+ uint32_t maxNameSize =
+ (IFNAMSIZ < TUNConfigurator_IFNAMSIZ) ? IFNAMSIZ : TUNConfigurator_IFNAMSIZ;
Log_info(logger, "Initializing tun device [%s]", ((interfaceName) ? interfaceName : "auto"));
struct ifreq ifRequest = { .ifr_flags = IFF_TUN };
if (interfaceName) {
- strncpy(ifRequest.ifr_name, interfaceName, IFNAMSIZ);
+ if (strlen(interfaceName) > maxNameSize) {
+ Except_raise(eh, TUNConfigurator_initTun_BAD_TUNNEL,
+ "tunnel name too big, limit is [%d] characters", maxNameSize);
+ }
+ strncpy(ifRequest.ifr_name, interfaceName, maxNameSize);
}
int tunFileDescriptor = open("/dev/net/tun", O_RDWR);
if (tunFileDescriptor < 0) {
- Except_raise(eh, TUNConfigurator_configure_INTERNAL,
- "open(\"/dev/net/tun\") [%s]", strerror(errno));
+ int code = (errno == EPERM)
+ ? TUNConfigurator_initTun_PERMISSION
+ : TUNConfigurator_initTun_INTERNAL;
+ Except_raise(eh, code, "open(\"/dev/net/tun\") [%s]", strerror(errno));
}
if (ioctl(tunFileDescriptor, TUNSETIFF, &ifRequest) < 0) {
int err = errno;
+ int code = (err == EPERM)
+ ? TUNConfigurator_initTun_PERMISSION
+ : TUNConfigurator_initTun_INTERNAL;
close(tunFileDescriptor);
- Except_raise(eh, TUNConfigurator_configure_INTERNAL,
- "ioctl(TUNSETIFF) [%s]", strerror(err));
+ Except_raise(eh, code, "ioctl(TUNSETIFF) [%s]", strerror(err));
}
- strncpy(assignedInterfaceName, ifRequest.ifr_name, IFNAMSIZ);
+ strncpy(assignedInterfaceName, ifRequest.ifr_name, maxNameSize);
- return tunFileDescriptor;
+ uintptr_t tunPtr = (uintptr_t) tunFileDescriptor;
+ return (void*) tunPtr;
}
-static void setupIpv6(const char* interfaceName,
- const uint8_t myIp[40],
- int prefixLen,
- struct Log* logger,
- struct Except* eh)
+void TUNConfigurator_setIpAddress(const char* interfaceName,
+ const uint8_t address[16],
+ int prefixLen,
+ struct Log* logger,
+ struct Except* eh)
{
int s;
struct ifreq ifRequest;
struct in6_ifreq ifr6;
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
- Except_raise(eh, TUNConfigurator_configure_INTERNAL,
+ Except_raise(eh, TUNConfigurator_setIpAddress_INTERNAL,
"socket() failed: [%s]", strerror(errno));
}
@@ -103,44 +113,28 @@ static void setupIpv6(const char* interfaceName,
if (ioctl(s, SIOCGIFINDEX, &ifRequest) < 0) {
int err = errno;
close(s);
- Except_raise(eh, TUNConfigurator_configure_INTERNAL,
+ Except_raise(eh, TUNConfigurator_setIpAddress_INTERNAL,
"ioctl(SIOCGIFINDEX) failed: [%s]", strerror(err));
}
ifr6.ifr6_ifindex = ifRequest.ifr_ifindex;
ifr6.ifr6_prefixlen = prefixLen;
+ uint8_t myIp[40];
+ AddrTools_printIp(myIp, address);
inet_pton(AF_INET6, (char*) myIp, &ifr6.ifr6_addr);
ifRequest.ifr_flags |= IFF_UP | IFF_RUNNING;
if (ioctl(s, SIOCSIFFLAGS, &ifRequest) < 0) {
int err = errno;
close(s);
- Except_raise(eh, TUNConfigurator_configure_INTERNAL,
+ Except_raise(eh, TUNConfigurator_setIpAddress_INTERNAL,
"ioctl(SIOCSIFFLAGS) failed: [%s]", strerror(err));
}
if (ioctl(s, SIOCSIFADDR, &ifr6) < 0) {
int err = errno;
close(s);
- Except_raise(eh, TUNConfigurator_configure_INTERNAL,
+ Except_raise(eh, TUNConfigurator_setIpAddress_INTERNAL,
"ioctl(SIOCSIFADDR) failed: [%s]", strerror(err));
}
}
-
-void* TUNConfigurator_configure(const char* interfaceName,
- const uint8_t address[16],
- int prefixLen,
- struct Log* logger,
- struct Except* eh)
-{
- /* stringify our IP address */
- uint8_t myIp[40];
- AddrTools_printIp(myIp, address);
-
- char assignedInterfaceName[IFNAMSIZ];
- intptr_t tunFd = (intptr_t) openTunnel(interfaceName, assignedInterfaceName, logger, eh);
- if (address) {
- setupIpv6(assignedInterfaceName, myIp, prefixLen, logger, eh);
- }
- return (void*) tunFd;
-}
61 interface/TUNConfigurator_OSX.c
View
@@ -42,7 +42,6 @@
/* Tun Configurator for Apple computers. */
-
/**
* Open the tun device.
*
@@ -52,11 +51,12 @@
* @param eh
* @return a file descriptor for the tunnel.
*/
-static int openTunnel(const char* interfaceName,
- char assignedInterfaceName[IFNAMSIZ],
- struct Log* logger,
- struct Except* eh)
+void* TUNConfigurator_initTun(const char* interfaceName,
+ char assignedInterfaceName[IFNAMSIZ],
+ struct Log* logger,
+ struct Except* eh)
{
+ int maxNameSize = (IFNAMSIZ < TUNConfigurator_IFNAMSIZ) ? IFNAMSIZ : TUNConfigurator_IFNAMSIZ;
int tunUnit = 0; /* allocate dynamically by default */
if (interfaceName) {
@@ -64,7 +64,7 @@ static int openTunnel(const char* interfaceName,
if (sscanf(interfaceName, "utun%i", &parsedUnit) != 1 || parsedUnit < 0) {
Except_raise(eh,
- TUNConfigurator_configure_BAD_TUNNEL,
+ TUNConfigurator_initTun_BAD_TUNNEL,
"Invalid utun device %s",
interfaceName);
}
@@ -90,7 +90,7 @@ static int openTunnel(const char* interfaceName,
int err = errno;
close(tunFileDescriptor);
Except_raise(eh,
- TUNConfigurator_configure_INTERNAL,
+ TUNConfigurator_initTun_INTERNAL,
"getting utun device id [%s]",
strerror(err));
}
@@ -108,22 +108,20 @@ static int openTunnel(const char* interfaceName,
int err = errno;
close(tunFileDescriptor);
Except_raise(eh,
- TUNConfigurator_configure_INTERNAL,
+ TUNConfigurator_initTun_INTERNAL,
"connecting to utun device [%s]",
strerror(err));
}
/* retrieve the assigned utun interface name */
- uint32_t assignedInterfaceNameLength = IFNAMSIZ;
-
if (getsockopt(tunFileDescriptor, SYSPROTO_CONTROL, UTUN_OPT_IFNAME,
- assignedInterfaceName, &assignedInterfaceNameLength) >= 0) {
+ assignedInterfaceName, &maxNameSize) >= 0) {
Log_info(logger, "Initialized utun interface [%s]\n", assignedInterfaceName);
} else {
int err = errno;
close(tunFileDescriptor);
Except_raise(eh,
- TUNConfigurator_configure_INTERNAL,
+ TUNConfigurator_initTun_INTERNAL,
"getting utun interface name [%s]",
strerror(err));
}
@@ -131,12 +129,16 @@ static int openTunnel(const char* interfaceName,
return tunFileDescriptor;
}
-static void setupIpv6(const char* interfaceName,
- const char myIp[40],
- int prefixLen,
- struct Log* logger,
- struct Except* eh)
+void TUNConfigurator_setIpAddress(const char* interfaceName,
+ const uint8_t address[16],
+ int prefixLen,
+ struct Log* logger,
+ struct Except* eh)
{
+ /* stringify our IP address */
+ char myIp[40];
+ AddrTools_printIp((uint8_t*)myIp, address);
+
/* set up the interface ip assignment request */
struct in6_aliasreq in6_addreq;
memset(&in6_addreq, 0, sizeof(in6_addreq));
@@ -150,8 +152,9 @@ static void setupIpv6(const char* interfaceName,
hints.ai_family = AF_INET6;
int err = getaddrinfo((const char *)myIp, NULL, &hints, &result);
if (err) {
+ // Should never happen since the address is specified as binary.
Except_raise(eh,
- TUNConfigurator_configure_MALFORMED_ADDRESS,
+ TUNConfigurator_setIpAddress_INTERNAL,
"bad IPv6 address [%s]",
gai_strerror(err));
}
@@ -180,7 +183,7 @@ static void setupIpv6(const char* interfaceName,
int s = socket(AF_INET6, SOCK_DGRAM, 0);
if (s < 0) {
Except_raise(eh,
- TUNConfigurator_configure_INTERNAL,
+ TUNConfigurator_setIpAddress_INTERNAL,
"socket() failed [%s]",
strerror(errno));
}
@@ -189,7 +192,7 @@ static void setupIpv6(const char* interfaceName,
int err = errno;
close(s);
Except_raise(eh,
- TUNConfigurator_configure_INTERNAL,
+ TUNConfigurator_setIpAddress_INTERNAL,
"ioctl(SIOCAIFADDR) failed [%s]",
strerror(err));
}
@@ -198,21 +201,3 @@ static void setupIpv6(const char* interfaceName,
close(s);
}
-
-void* TUNConfigurator_configure(const char* interfaceName,
- const uint8_t address[16],
- int prefixLen,
- struct Log* logger,
- struct Except* eh)
-{
- /* stringify our IP address */
- char myIp[40];
- AddrTools_printIp((uint8_t*)myIp, address);
-
- char assignedInterfaceName[IFNAMSIZ];
- intptr_t tunFd = (intptr_t) openTunnel(interfaceName, assignedInterfaceName, logger, eh);
- if (address) {
- setupIpv6(assignedInterfaceName, myIp, prefixLen, logger, eh);
- }
- return (void*) tunFd;
-}
4 scripts/checkfiles.pl
View
@@ -87,6 +87,10 @@ sub error {
if ($name =~ /^W32(.*)$/) {
$n = $1;
}
+ # implementations.. TUNConfigurator_Linux contains TUNConfigurator_doStuff...
+ if ($name =~ /^([^_]*)_.*$/) {
+ $n = $1;
+ }
if ($line =~ /^\w+\s.*\(/) {
if (!($line =~ /^int main\(/
|| $line =~ / ${n}/
Please sign in to comment.
Something went wrong with that request. Please try again.