Permalink
Browse files

BSD does not initialize a TUN synchronously so need to poll.

  • Loading branch information...
1 parent 0f3cd1c commit 1028977903ee09fb38ccd4e711d0daf717fcee9c Caleb James DeLisle committed Dec 10, 2012
View
@@ -161,7 +161,7 @@ void Core_initTunnel(String* desiredDeviceName,
logger,
eh);
- struct TUNInterface* tun = TUNInterface_new(tunPtr, eventBase, alloc);
+ struct TUNInterface* tun = TUNInterface_new(tunPtr, eventBase, alloc, logger);
// broken
//struct ICMP6Generator* icmp = ICMP6Generator_new(alloc);
View
@@ -18,6 +18,7 @@
#include "util/events/Event.h"
#include "util/Identity.h"
#include "util/platform/Socket.h"
+#include "util/log/Log.h"
#include "wire/Ethernet.h"
#include <unistd.h>
@@ -30,6 +31,7 @@ struct TUNInterface_pvt
{
struct TUNInterface pub;
Socket tunSocket;
+ struct Log* logger;
Identity
};
@@ -43,7 +45,7 @@ static void handleEvent(void* vcontext)
ssize_t length = read(tun->tunSocket, msg->bytes, msg->length);
if (length < 4) {
- printf("Error reading from TUN device %d\n", (int) length);
+ Log_warn(tun->logger, "Error reading from TUN device [%s]", Errno_getString());
return;
}
msg->length = length;
@@ -60,19 +62,39 @@ static uint8_t sendMessage(struct Message* message, struct Interface* iface)
ssize_t ret = write(tun->tunSocket, message->bytes, message->length);
if (ret < 0) {
- printf("Error writing to TUN device %d\n", Errno_get());
+ Log_warn(tun->logger, "Error writing to TUN device [%s]", Errno_getString());
}
// TODO: report errors
return 0;
}
+/**
+ * When a TUN device first comes up, on some platforms (BSD)
+ * using it right away creates a race condition.
+ * This busy polls it until it becomes "ready" and then returns.
+ */
+static inline void pollTun(Socket sock, struct Log* logger)
+{
+ Log_debug(logger, "Waiting for tun device to become ready");
+ int i = 0;
+ ssize_t length;
+ do {
+ Assert_always(++i < 100000);
+ uint8_t buff[24];
+ length = read(sock, buff, 24);
+ } while (length > 0 || Errno_get() == Errno_EHOSTDOWN);
+ Log_debug(logger, "Polled tun [%d] times", i);
+}
+
struct TUNInterface* TUNInterface_new(void* tunSocket,
struct EventBase* base,
- struct Allocator* allocator)
+ struct Allocator* allocator,
+ struct Log* logger)
{
Socket tunSock = (Socket) ((intptr_t) tunSocket);
Socket_makeNonBlocking(tunSock);
+ pollTun(tunSock, logger);
struct TUNInterface_pvt* tun = Allocator_clone(allocator, (&(struct TUNInterface_pvt) {
.pub = {
@@ -83,7 +105,8 @@ struct TUNInterface* TUNInterface_new(void* tunSocket,
.maxMessageLength = MAX_PACKET_SIZE
}
},
- .tunSocket = tunSock
+ .tunSocket = tunSock,
+ .logger = logger
}));
Identity_set(tun);
View
@@ -34,9 +34,11 @@ struct TUNInterface
* @param tunSocket an pointer to a file descriptor provided by TUNConfigurator_configure().
* @param base the libevent event base to use for listening for incoming packet events.
* @param allocator a means of getting memory.
+ * @param logger for logging messages about the tun device.
* @return a TUNInterface structure.
*/
struct TUNInterface* TUNInterface_new(void* tunSocket,
struct EventBase* base,
- struct Allocator* allocator);
+ struct Allocator* allocator,
+ struct Log* logger);
#endif
@@ -120,7 +120,7 @@ int main(int argc, char** argv)
char assignedInterfaceName[TUNConfigurator_IFNAMSIZ];
void* tunPtr = TUNConfigurator_initTun(NULL, assignedInterfaceName, logger, NULL);
TUNConfigurator_addIp4Address(assignedInterfaceName, testAddrA, 30, logger, NULL);
- struct TUNInterface* tun = TUNInterface_new(tunPtr, base, alloc);
+ struct TUNInterface* tun = TUNInterface_new(tunPtr, base, alloc, logger);
struct UDPInterface* udp = UDPInterface_new(base, "0.0.0.0", alloc, NULL, logger, &ic);
@@ -80,8 +80,7 @@ static uint8_t receiveMessageTUN(struct Message* msg, struct Interface* iface)
Assert_always(!Bits_memcmp(header->destinationAddr, testAddrB, 16));
if (Bits_memcmp(header->sourceAddr, testAddrA, 16)) {
- Assert_always(header->sourceAddr[0] == 0xfc);
- printf("Message has the wrong source address from existing TUN device.\n");
+ printf("Message has the wrong source address from existing TUN device.");
}
Bits_memcpyConst(header->destinationAddr, testAddrA, 16);
@@ -122,9 +121,9 @@ int main(int argc, char** argv)
char assignedInterfaceName[TUNConfigurator_IFNAMSIZ];
void* tunPtr = TUNConfigurator_initTun(NULL, assignedInterfaceName, logger, NULL);
TUNConfigurator_addIp6Address(assignedInterfaceName, testAddrA, 126, logger, NULL);
- struct TUNInterface* tun = TUNInterface_new(tunPtr, base, alloc);
+ struct TUNInterface* tun = TUNInterface_new(tunPtr, base, alloc, logger);
- struct UDPInterface* udp = UDPInterface_new(base, "[::]", alloc, NULL, logger, &ic);
+ struct UDPInterface* udp = UDPInterface_new(base, "[fd00::1]", alloc, NULL, logger, &ic);
struct sockaddr_in6 sin = { .sin6_family = AF_INET6 };
sin.sin6_port = udp->boundPort_be;

0 comments on commit 1028977

Please sign in to comment.