Skip to content
This repository
Browse code

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

  • Loading branch information...
commit 1028977903ee09fb38ccd4e711d0daf717fcee9c 1 parent 0f3cd1c
authored
2  admin/angel/Core.c
@@ -161,7 +161,7 @@ void Core_initTunnel(String* desiredDeviceName,
161 161
                                            logger,
162 162
                                            eh);
163 163
 
164  
-    struct TUNInterface* tun = TUNInterface_new(tunPtr, eventBase, alloc);
  164
+    struct TUNInterface* tun = TUNInterface_new(tunPtr, eventBase, alloc, logger);
165 165
 
166 166
     // broken
167 167
     //struct ICMP6Generator* icmp = ICMP6Generator_new(alloc);
31  interface/TUNInterface.c
@@ -18,6 +18,7 @@
18 18
 #include "util/events/Event.h"
19 19
 #include "util/Identity.h"
20 20
 #include "util/platform/Socket.h"
  21
+#include "util/log/Log.h"
21 22
 #include "wire/Ethernet.h"
22 23
 
23 24
 #include <unistd.h>
@@ -30,6 +31,7 @@ struct TUNInterface_pvt
30 31
 {
31 32
     struct TUNInterface pub;
32 33
     Socket tunSocket;
  34
+    struct Log* logger;
33 35
     Identity
34 36
 };
35 37
 
@@ -43,7 +45,7 @@ static void handleEvent(void* vcontext)
43 45
     ssize_t length = read(tun->tunSocket, msg->bytes, msg->length);
44 46
 
45 47
     if (length < 4) {
46  
-        printf("Error reading from TUN device %d\n", (int) length);
  48
+        Log_warn(tun->logger, "Error reading from TUN device [%s]", Errno_getString());
47 49
         return;
48 50
     }
49 51
     msg->length = length;
@@ -60,19 +62,39 @@ static uint8_t sendMessage(struct Message* message, struct Interface* iface)
60 62
 
61 63
     ssize_t ret = write(tun->tunSocket, message->bytes, message->length);
62 64
     if (ret < 0) {
63  
-        printf("Error writing to TUN device %d\n", Errno_get());
  65
+        Log_warn(tun->logger, "Error writing to TUN device [%s]", Errno_getString());
64 66
     }
65 67
     // TODO: report errors
66 68
     return 0;
67 69
 }
68 70
 
  71
+/**
  72
+ * When a TUN device first comes up, on some platforms (BSD)
  73
+ * using it right away creates a race condition.
  74
+ * This busy polls it until it becomes "ready" and then returns.
  75
+ */
  76
+static inline void pollTun(Socket sock, struct Log* logger)
  77
+{
  78
+    Log_debug(logger, "Waiting for tun device to become ready");
  79
+    int i = 0;
  80
+    ssize_t length;
  81
+    do {
  82
+        Assert_always(++i < 100000);
  83
+        uint8_t buff[24];
  84
+        length = read(sock, buff, 24);
  85
+    } while (length > 0 || Errno_get() == Errno_EHOSTDOWN);
  86
+    Log_debug(logger, "Polled tun [%d] times", i);
  87
+}
  88
+
69 89
 struct TUNInterface* TUNInterface_new(void* tunSocket,
70 90
                                       struct EventBase* base,
71  
-                                      struct Allocator* allocator)
  91
+                                      struct Allocator* allocator,
  92
+                                      struct Log* logger)
72 93
 {
73 94
     Socket tunSock = (Socket) ((intptr_t) tunSocket);
74 95
 
75 96
     Socket_makeNonBlocking(tunSock);
  97
+    pollTun(tunSock, logger);
76 98
 
77 99
     struct TUNInterface_pvt* tun = Allocator_clone(allocator, (&(struct TUNInterface_pvt) {
78 100
         .pub = {
@@ -83,7 +105,8 @@ struct TUNInterface* TUNInterface_new(void* tunSocket,
83 105
                 .maxMessageLength = MAX_PACKET_SIZE
84 106
             }
85 107
         },
86  
-        .tunSocket = tunSock
  108
+        .tunSocket = tunSock,
  109
+        .logger = logger
87 110
     }));
88 111
     Identity_set(tun);
89 112
 
4  interface/TUNInterface.h
@@ -34,9 +34,11 @@ struct TUNInterface
34 34
  * @param tunSocket an pointer to a file descriptor provided by TUNConfigurator_configure().
35 35
  * @param base the libevent event base to use for listening for incoming packet events.
36 36
  * @param allocator a means of getting memory.
  37
+ * @param logger for logging messages about the tun device.
37 38
  * @return a TUNInterface structure.
38 39
  */
39 40
 struct TUNInterface* TUNInterface_new(void* tunSocket,
40 41
                                       struct EventBase* base,
41  
-                                      struct Allocator* allocator);
  42
+                                      struct Allocator* allocator,
  43
+                                      struct Log* logger);
42 44
 #endif
2  interface/test/TUNInterface_ipv4_root_test.c
@@ -120,7 +120,7 @@ int main(int argc, char** argv)
120 120
     char assignedInterfaceName[TUNConfigurator_IFNAMSIZ];
121 121
     void* tunPtr = TUNConfigurator_initTun(NULL, assignedInterfaceName, logger, NULL);
122 122
     TUNConfigurator_addIp4Address(assignedInterfaceName, testAddrA, 30, logger, NULL);
123  
-    struct TUNInterface* tun = TUNInterface_new(tunPtr, base, alloc);
  123
+    struct TUNInterface* tun = TUNInterface_new(tunPtr, base, alloc, logger);
124 124
 
125 125
     struct UDPInterface* udp = UDPInterface_new(base, "0.0.0.0", alloc, NULL, logger, &ic);
126 126
 
7  interface/test/TUNInterface_ipv6_root_test.c
@@ -80,8 +80,7 @@ static uint8_t receiveMessageTUN(struct Message* msg, struct Interface* iface)
80 80
     Assert_always(!Bits_memcmp(header->destinationAddr, testAddrB, 16));
81 81
 
82 82
     if (Bits_memcmp(header->sourceAddr, testAddrA, 16)) {
83  
-        Assert_always(header->sourceAddr[0] == 0xfc);
84  
-        printf("Message has the wrong source address from existing TUN device.\n");
  83
+        printf("Message has the wrong source address from existing TUN device.");
85 84
     }
86 85
 
87 86
     Bits_memcpyConst(header->destinationAddr, testAddrA, 16);
@@ -122,9 +121,9 @@ int main(int argc, char** argv)
122 121
     char assignedInterfaceName[TUNConfigurator_IFNAMSIZ];
123 122
     void* tunPtr = TUNConfigurator_initTun(NULL, assignedInterfaceName, logger, NULL);
124 123
     TUNConfigurator_addIp6Address(assignedInterfaceName, testAddrA, 126, logger, NULL);
125  
-    struct TUNInterface* tun = TUNInterface_new(tunPtr, base, alloc);
  124
+    struct TUNInterface* tun = TUNInterface_new(tunPtr, base, alloc, logger);
126 125
 
127  
-    struct UDPInterface* udp = UDPInterface_new(base, "[::]", alloc, NULL, logger, &ic);
  126
+    struct UDPInterface* udp = UDPInterface_new(base, "[fd00::1]", alloc, NULL, logger, &ic);
128 127
 
129 128
     struct sockaddr_in6 sin = { .sin6_family = AF_INET6 };
130 129
     sin.sin6_port = udp->boundPort_be;

0 notes on commit 1028977

Please sign in to comment.
Something went wrong with that request. Please try again.