tuntap hacks for FreeBSD vbox hosts (bandaid till vbox-net driver...)

Juergen Lock nox at jelal.kn-bremen.de
Wed Aug 19 18:58:46 UTC 2009


Hi!

 After inquiring on the #vbox-dev channel whether the tuntap code could
be resurrected for hosts that don't have vbox net/bridge drivers yet
(like FreeBSD :) I now got it working - except the config gui and
ifup/down scripts, the code for at least the latter seems to have been
ripped out for good indeed...  So for now you have to use VBoxManage
something like this,
	VBoxManage modifyvm <VM name> --nic1 bridged --bridgeadapter1 tap0
and manually configure your tap interface and (optionally) add it to a
bridge before the VM starts.  If you already have setup your host system to
use tuntap networking with qemu you probably can just chown/chmod /dev/tap0
(or whichever one you use) to 660 root:vboxusers and then run your
/usr/local/etc/qemu-ifup script with the same tap interface as arg,
otherwise do something like...
	kldload if_tap if_bridge
	sysctl net.link.tap.user_open=1
	chown root:vboxusers /dev/tap0
	chmod 660 /dev/tap0
	ifconfig bridge0 create
	ifconfig bridge0 addm <host physical interface>
	ifconfig tap0 <ip> netmask <netmask>
	ifconfig bridge0 addm tap0
and then start the guest.  (You'll have to rerun the `ifconfig tap0 ...'
each time before you start the guest again.)

 Tested on the stable/8 FreeBSD branch with the vbox version currently
in ports.  (which btw today seems to have hit the same FreeBSD vboxdrv
bug with svm and npt here while scp'ing a big file out of a guest that
I previously thought only plagued intel vt-x users, see this post for
details...
	http://lists.freebsd.org/pipermail/freebsd-emulation/2009-August/006692.html
)

 Anyway, here comes the patch, enjoy! :)

Index: Config.kmk
@@ -490,7 +490,7 @@
  endif
 endif
 # Use VBoxNetFlt for host interface networking.
-if1of ($(KBUILD_TARGET), darwin linux solaris win freebsd)
+if1of ($(KBUILD_TARGET), darwin linux solaris win)
  VBOX_WITH_NETFLT = 1
  VBOX_SOLARIS_NSL_RESOLVED = 1
  if1of ($(KBUILD_TARGET), darwin solaris linux)
Index: src/VBox/Devices/Makefile.kmk
@@ -802,7 +802,8 @@
 	Storage/DrvHostFloppy% \
 	, $(Drivers_SOURCES)) \
 	Audio/ossaudio.c
-Drivers_SOURCES.freebsd =
+Drivers_SOURCES.freebsd = \
+	Network/DrvTAP.cpp
 endif # freebsd
 
 
Index: src/VBox/Main/include/ConsoleImpl.h
@@ -573,7 +573,7 @@
     PPDMLED     mapNetworkLeds[SchemaDefs::NetworkAdapterCount];
     PPDMLED     mapSharedFolderLed;
     PPDMLED     mapUSBLed[2];
-#if !defined(VBOX_WITH_NETFLT) && defined(RT_OS_LINUX)
+#if !defined(VBOX_WITH_NETFLT) && (defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD))
     Utf8Str     maTAPDeviceName[8];
     RTFILE      maTapFD[8];
 #endif
Index: src/VBox/Devices/Builtins.h
@@ -100,7 +100,7 @@
 extern const PDMDRVREG g_DrvRawImage;
 extern const PDMDRVREG g_DrvISCSI;
 extern const PDMDRVREG g_DrvISCSITransportTcp;
-#ifdef RT_OS_LINUX
+#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
 extern const PDMDRVREG g_DrvHostInterface;
 #endif
 extern const PDMDRVREG g_DrvIntNet;
Index: src/VBox/Devices/Builtins.cpp
@@ -227,7 +227,7 @@
     if (RT_FAILURE(rc))
         return rc;
 #endif
-#if defined(RT_OS_LINUX)
+#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
     rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvHostInterface);
     if (RT_FAILURE(rc))
         return rc;
Index: src/VBox/Frontends/VBoxBFE/NetworkAdapterImpl.h
@@ -61,7 +61,7 @@
         BOOL mCableConnected;
         BOOL mTraceEnabled;
         Bstr mHostInterface;
-#ifdef RT_OS_LINUX
+#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
         Bstr mTAPSetupApplication;
         Bstr mTAPTerminateApplication;
         RTFILE mTAPFD;
@@ -89,7 +89,7 @@
     //    STDMETHOD(COMGETTER(AttachmentType))(NetworkAttachmentType_T *attachmentType);
     STDMETHOD(COMGETTER(HostInterface))(BSTR *hostInterface);
     STDMETHOD(COMSETTER(HostInterface))(INPTR BSTR hostInterface);
-#ifdef RT_OS_LINUX
+#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
     STDMETHOD(COMGETTER(TAPFileDescriptor))(LONG *tapFileDescriptor);
     STDMETHOD(COMSETTER(TAPFileDescriptor))(LONG tapFileDescriptor);
     STDMETHOD(COMGETTER(TAPSetupApplication))(BSTR *tapSetupApplication);
Index: src/VBox/Main/ConsoleImpl.cpp
@@ -34,6 +34,16 @@
 #   include <stdio.h>
 #   include <stdlib.h>
 #   include <string.h>
+#elif defined(RT_OS_FREEBSD)
+#   include <errno.h>
+#   include <sys/ioctl.h>
+#   include <sys/poll.h>
+#   include <sys/fcntl.h>
+#   include <sys/types.h>
+#   include <sys/wait.h>
+#   include <stdio.h>
+#   include <stdlib.h>
+#   include <string.h>
 #endif
 
 #include "ConsoleImpl.h"
@@ -6023,7 +6033,7 @@
  */
 HRESULT Console::attachToBridgedInterface(INetworkAdapter *networkAdapter)
 {
-#if !defined(RT_OS_LINUX) || defined(VBOX_WITH_NETFLT)
+#if (!defined(RT_OS_LINUX) && !defined(RT_OS_FREEBSD)) || defined(VBOX_WITH_NETFLT)
     /*
      * Nothing to do here.
      *
@@ -6033,7 +6043,7 @@
     NOREF(networkAdapter);
     return S_OK;
 
-#else /* RT_OS_LINUX && !VBOX_WITH_NETFLT */
+#else /* (RT_OS_LINUX || RT_OS_FREEBSD) && !VBOX_WITH_NETFLT */
 
     LogFlowThisFunc(("\n"));
     /* sanity check */
@@ -6055,6 +6065,7 @@
     /*
      * Allocate a host interface device
      */
+#ifdef RT_OS_LINUX
     int rcVBox = RTFileOpen(&maTapFD[slot], "/dev/net/tun",
                             RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_INHERIT);
     if (VBOX_SUCCESS(rcVBox))
@@ -6133,6 +6144,48 @@
                 break;
         }
     }
+#elif RT_OS_FREEBSD
+    /*
+     * Set/obtain the tap interface.
+     */
+    /* The name of the TAP interface we are using */
+    Bstr tapDeviceName;
+    rc = networkAdapter->COMGETTER(HostInterface)(tapDeviceName.asOutParam());
+    if (FAILED(rc))
+        tapDeviceName.setNull();  /* Is this necessary? */
+    if (tapDeviceName.isEmpty())
+    {
+        LogRel(("No TAP device name was supplied.\n"));
+        rc = setError(E_FAIL, tr ("No TAP device name was supplied for the host networking interface"));
+    }
+    char szTapdev[1024] = "/dev/";
+    /* If we are using a static TAP device then try to open it. */
+    Utf8Str str(tapDeviceName);
+    if (str.length() + strlen(szTapdev) <= sizeof(szTapdev))
+        strcat(szTapdev, str.raw());
+    else
+        memcpy(szTapdev + strlen(szTapdev), str.raw(), sizeof(szTapdev) - strlen(szTapdev) - 1); /** @todo bitch about names which are too long... */
+    int rcVBox = RTFileOpen(&maTapFD[slot], szTapdev,
+                            RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_INHERIT | RTFILE_O_NON_BLOCK);
+
+    if (VBOX_SUCCESS(rcVBox))
+    {
+        maTAPDeviceName[slot] = tapDeviceName;
+        rcVBox = VINF_SUCCESS;
+    } else {
+        switch (rcVBox)
+        {
+            case VERR_ACCESS_DENIED:
+                /* will be handled by our caller */
+                rc = rcVBox;
+                break;
+            default:
+                rc = setError(E_FAIL, tr ("Failed to open the host network interface %ls"),
+                      tapDeviceName.raw());
+                break;
+        }
+    }
+#endif /* RT_OS_FREEBSD */
     /* in case of failure, cleanup. */
     if (VBOX_FAILURE(rcVBox) && SUCCEEDED(rc))
     {
@@ -6141,7 +6194,7 @@
     }
     LogFlowThisFunc(("rc=%d\n", rc));
     return rc;
-#endif /* RT_OS_LINUX */
+#endif /* RT_OS_LINUX || RT_OS_FREEBSD */
 }
 
 /**
@@ -6154,7 +6207,7 @@
  */
 HRESULT Console::detachFromBridgedInterface(INetworkAdapter *networkAdapter)
 {
-#if !defined(RT_OS_LINUX) || defined(VBOX_WITH_NETFLT)
+#if (!defined(RT_OS_LINUX) && !defined(RT_OS_FREEBSD)) || defined(VBOX_WITH_NETFLT)
     /*
      * Nothing to do here.
      */
@@ -6211,7 +6264,7 @@
     }
     LogFlowThisFunc(("returning %d\n", rc));
     return rc;
-#endif /* RT_OS_LINUX */
+#endif /* RT_OS_LINUX || RT_OS_FREEBSD */
 }
 
 
Index: src/VBox/Main/ConsoleImpl2.cpp
@@ -2182,7 +2182,13 @@
 
         case NetworkAttachmentType_Bridged:
         {
-#if !defined(VBOX_WITH_NETFLT) && defined(RT_OS_LINUX)
+#if !defined(VBOX_WITH_NETFLT) && (defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD))
+            hrc = pThis->attachToBridgedInterface(aNetworkAdapter);
+            if (FAILED(hrc))
+            {
+                LogRel(("NetworkAttachmentType_Bridged: attachToBridgedInterface failed, hrc (0x%x)", hrc));
+                H();
+            }
             Assert ((int)pThis->maTapFD[uInstance] >= 0);
             if ((int)pThis->maTapFD[uInstance] >= 0)
             {

PS: error handling can probably be improved...


More information about the freebsd-emulation mailing list