浏览代码

BTap: add support for TUN devices (Linux only)

ambrop7 15 年之前
父节点
当前提交
c19974dffd
共有 3 个文件被更改,包括 49 次插入38 次删除
  1. 2 3
      client/client.c
  2. 40 27
      tuntap/BTap.c
  3. 7 8
      tuntap/BTap.h

+ 2 - 3
client/client.c

@@ -44,7 +44,6 @@
 #include <misc/debug.h>
 #include <misc/offset.h>
 #include <misc/byteorder.h>
-#include <misc/ethernet_proto.h>
 #include <misc/nsskey.h>
 #include <misc/loglevel.h>
 #include <misc/loggers_string.h>
@@ -488,13 +487,13 @@ int main (int argc, char *argv[])
     }
     
     // init device
-    if (!BTap_Init(&device.btap, &ss, options.tapdev, device_error_handler, NULL)) {
+    if (!BTap_Init(&device.btap, &ss, options.tapdev, device_error_handler, NULL, 0)) {
         BLog(BLOG_ERROR, "BTap_Init failed");
         goto fail5;
     }
     
     // remember device MTU
-    device.mtu = sizeof(struct ethernet_header) + BTap_GetDeviceMTU(&device.btap);
+    device.mtu = BTap_GetMTU(&device.btap);
     
     BLog(BLOG_INFO, "device MTU is %d", device.mtu);
     

+ 40 - 27
tuntap/BTap.c

@@ -428,8 +428,10 @@ void output_handler_recv (BTap *o, uint8_t *data)
     PacketRecvInterface_Done(&o->output, bytes);
 }
 
-int BTap_Init (BTap *o, BReactor *reactor, char *devname, BTap_handler_error handler_error, void *handler_error_user)
+int BTap_Init (BTap *o, BReactor *reactor, char *devname, BTap_handler_error handler_error, void *handler_error_user, int tun)
 {
+    ASSERT(tun == 0 || tun == 1)
+    
     // init arguments
     o->reactor = reactor;
     o->handler_error = handler_error;
@@ -437,6 +439,11 @@ int BTap_Init (BTap *o, BReactor *reactor, char *devname, BTap_handler_error han
     
     #ifdef BADVPN_USE_WINAPI
     
+    if (tun) {
+        DEBUG("TUN not supported on Windows");
+        goto fail0;
+    }
+    
     char *device_component_id;
     char *device_name;
     
@@ -583,8 +590,7 @@ int BTap_Init (BTap *o, BReactor *reactor, char *devname, BTap_handler_error han
         goto fail1;
     }
     
-    o->dev_mtu = umtu;
-    o->frame_mtu = o->dev_mtu + BTAP_ETHERNET_HEADER_LENGTH;
+    o->frame_mtu = umtu + BTAP_ETHERNET_HEADER_LENGTH;
     
     // set connected
     
@@ -637,14 +643,19 @@ fail0:
     
     if ((o->fd = open("/dev/net/tun", O_RDWR)) < 0) {
         DEBUG("error opening device");
-        return 0;
+        goto fail0;
     }
     
     // configure device
     
     struct ifreq ifr;
     memset(&ifr, 0, sizeof(ifr));
-    ifr.ifr_flags |= IFF_TAP | IFF_NO_PI;    
+    ifr.ifr_flags |= IFF_NO_PI;
+    if (tun) {
+        ifr.ifr_flags |= IFF_TUN;
+    } else {
+        ifr.ifr_flags |= IFF_TAP;
+    }
     if (devname) {
         snprintf(ifr.ifr_name, IFNAMSIZ, "%s", devname);
     }
@@ -656,30 +667,31 @@ fail0:
     
     strcpy(o->devname, ifr.ifr_name);
     
-    // open dummy socket for ioctls
-    
-    int sock = socket(AF_INET, SOCK_DGRAM, 0);
-    if (sock < 0) {
-        DEBUG("socket failed");
-        goto fail1;
-    }
-    
     // get MTU
-    
-    memset(&ifr, 0, sizeof(ifr));
-    strcpy(ifr.ifr_name, o->devname);
-    
-    if (ioctl(sock, SIOCGIFMTU, (void *)&ifr) < 0) {
-        DEBUG("error getting MTU");
+    if (tun) {
+        o->frame_mtu = 65535;
+    } else {
+        // open dummy socket for ioctls
+        int sock = socket(AF_INET, SOCK_DGRAM, 0);
+        if (sock < 0) {
+            DEBUG("socket failed");
+            goto fail1;
+        }
+        
+        memset(&ifr, 0, sizeof(ifr));
+        strcpy(ifr.ifr_name, o->devname);
+        
+        if (ioctl(sock, SIOCGIFMTU, (void *)&ifr) < 0) {
+            DEBUG("error getting MTU");
+            close(sock);
+            goto fail1;
+        }
+        
+        o->frame_mtu = ifr.ifr_mtu + BTAP_ETHERNET_HEADER_LENGTH;
+        
         close(sock);
-        goto fail1;
     }
     
-    o->dev_mtu = ifr.ifr_mtu;
-    o->frame_mtu = o->dev_mtu + BTAP_ETHERNET_HEADER_LENGTH;
-    
-    close(sock);
-    
     // set non-blocking
     if (fcntl(o->fd, F_SETFL, O_NONBLOCK) < 0) {
         DEBUG("cannot set non-blocking");
@@ -698,6 +710,7 @@ fail0:
     
 fail1:
     ASSERT_FORCE(close(o->fd) == 0)
+fail0:
     return 0;
     
     #endif
@@ -778,11 +791,11 @@ void BTap_Free (BTap *o)
     #endif
 }
 
-int BTap_GetDeviceMTU (BTap *o)
+int BTap_GetMTU (BTap *o)
 {
     DebugObject_Access(&o->d_obj);
     
-    return o->dev_mtu;
+    return o->frame_mtu;
 }
 
 PacketPassInterface * BTap_GetInput (BTap *o)

+ 7 - 8
tuntap/BTap.h

@@ -56,7 +56,6 @@ typedef struct {
     BReactor *reactor;
     BTap_handler_error handler_error;
     void *handler_error_user;
-    int dev_mtu;
     int frame_mtu;
     PacketPassInterface input;
     PacketRecvInterface output;
@@ -99,9 +98,10 @@ typedef struct {
  *                Specifying a NULL devname is equivalent to specifying ":".
  * @param handler_error error handler function
  * @param handler_error_user value passed to error handler
+ * @param tun whether to create a TUN (IP) device or a TAP (Ethernet) device. Must be 0 or 1.
  * @return 1 on success, 0 on failure
  */
-int BTap_Init (BTap *o, BReactor *bsys, char *devname, BTap_handler_error handler_error, void *handler_error_user) WARN_UNUSED;
+int BTap_Init (BTap *o, BReactor *bsys, char *devname, BTap_handler_error handler_error, void *handler_error_user, int tun) WARN_UNUSED;
 
 /**
  * Frees the TAP device.
@@ -111,17 +111,16 @@ int BTap_Init (BTap *o, BReactor *bsys, char *devname, BTap_handler_error handle
 void BTap_Free (BTap *o);
 
 /**
- * Returns the device's maximum transmission unit, excluding
- * the Ethernet header.
+ * Returns the device's maximum transmission unit (including any protocol headers).
  *
  * @param o the object
- * @return device's MTU, excluding the Ethernet header
+ * @return device's MTU
  */
-int BTap_GetDeviceMTU (BTap *o);
+int BTap_GetMTU (BTap *o);
 
 /**
  * Returns a {@link PacketPassInterface} for writing packets to the device.
- * The MTU of the interface will be {@link BTap_GetDeviceMTU} + BTAP_ETHERNET_HEADER_LENGTH.
+ * The MTU of the interface will be {@link BTap_GetMTU}.
  *
  * @param o the object
  * @return input interface
@@ -130,7 +129,7 @@ PacketPassInterface * BTap_GetInput (BTap *o);
 
 /**
  * Returns a {@link PacketRecvInterface} for reading packets from the device.
- * The MTU of the interface will be {@link BTap_GetDeviceMTU} + BTAP_ETHERNET_HEADER_LENGTH.
+ * The MTU of the interface will be {@link BTap_GetMTU}.
  * The interface will support cancel functionality.
  * 
  * @param o the object