Browse Source

use /dev/tap{0..3}; it is fully working now

Daniel Skowroński 8 years ago
parent
commit
218ace51a7
1 changed files with 31 additions and 10 deletions
  1. 31 10
      osdep/NetBSDEthernetTap.cpp

+ 31 - 10
osdep/NetBSDEthernetTap.cpp

@@ -61,6 +61,8 @@
 #include "OSUtils.hpp"
 #include "OSUtils.hpp"
 #include "NetBSDEthernetTap.hpp"
 #include "NetBSDEthernetTap.hpp"
 
 
+#include <iostream>
+using namespace std;
 #define ZT_BASE32_CHARS "0123456789abcdefghijklmnopqrstuv"
 #define ZT_BASE32_CHARS "0123456789abcdefghijklmnopqrstuv"
 
 
 // ff:ff:ff:ff:ff:ff with no ADI
 // ff:ff:ff:ff:ff:ff with no ADI
@@ -111,13 +113,12 @@ NetBSDEthernetTap::NetBSDEthernetTap(
 	if (mtu > 2800)
 	if (mtu > 2800)
 		throw std::runtime_error("max tap MTU is 2800");
 		throw std::runtime_error("max tap MTU is 2800");
 
 
-	// On BSD we create taps and they can have high numbers, so use ones starting
-	// at 9993 to not conflict with other stuff. Then we rename it to zt<base32 of nwid>
+	// On NetBSD there are /dev/tap{0..3} pre-created and for a moment I will stick with only them
 	std::vector<std::string> devFiles(OSUtils::listDirectory("/dev"));
 	std::vector<std::string> devFiles(OSUtils::listDirectory("/dev"));
-	for(int i=9993;i<(9993+128);++i) {
+	for(int i=0;i<4;++i) {
 		Utils::snprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i);
 		Utils::snprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i);
 		Utils::snprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname);
 		Utils::snprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname);
-		if (std::find(devFiles.begin(),devFiles.end(),std::string(tmpdevname)) == devFiles.end()) {
+		//if (std::find(devFiles.begin(),devFiles.end(),std::string(tmpdevname)) == devFiles.end()) {
 			long cpid = (long)vfork();
 			long cpid = (long)vfork();
 			if (cpid == 0) {
 			if (cpid == 0) {
 				::execl("/sbin/ifconfig","/sbin/ifconfig",tmpdevname,"create",(const char *)0);
 				::execl("/sbin/ifconfig","/sbin/ifconfig",tmpdevname,"create",(const char *)0);
@@ -127,8 +128,10 @@ NetBSDEthernetTap::NetBSDEthernetTap(
 				::waitpid(cpid,&exitcode,0);
 				::waitpid(cpid,&exitcode,0);
 			} else throw std::runtime_error("fork() failed");
 			} else throw std::runtime_error("fork() failed");
 
 
+			_dev = tmpdevname;
+			_fd = ::open(  devpath,O_RDWR);
 			if (!stat(devpath,&stattmp)) {
 			if (!stat(devpath,&stattmp)) {
-				cpid = (long)vfork();
+				/*cpid = (long)vfork();
 				if (cpid == 0) {
 				if (cpid == 0) {
 					::execl("/sbin/ifconfig","/sbin/ifconfig",tmpdevname,"name",_dev.c_str(),(const char *)0);
 					::execl("/sbin/ifconfig","/sbin/ifconfig",tmpdevname,"name",_dev.c_str(),(const char *)0);
 					::_exit(-1);
 					::_exit(-1);
@@ -137,16 +140,16 @@ NetBSDEthernetTap::NetBSDEthernetTap(
 					::waitpid(cpid,&exitcode,0);
 					::waitpid(cpid,&exitcode,0);
 					if (exitcode)
 					if (exitcode)
 						throw std::runtime_error("ifconfig rename operation failed");
 						throw std::runtime_error("ifconfig rename operation failed");
-				} else throw std::runtime_error("fork() failed");
+				} else throw std::runtime_error("fork() failed");*/
+
 
 
-				_fd = ::open(devpath,O_RDWR);
 				if (_fd > 0)
 				if (_fd > 0)
 					break;
 					break;
-				else throw std::runtime_error("unable to open created tap device");
+				//else throw std::runtime_error("unable to open created tap device ");
 			} else {
 			} else {
 				throw std::runtime_error("cannot find /dev node for newly created tap device");
 				throw std::runtime_error("cannot find /dev node for newly created tap device");
 			}
 			}
-		}
+		//}
 	}
 	}
 
 
 	if (_fd <= 0)
 	if (_fd <= 0)
@@ -163,7 +166,7 @@ NetBSDEthernetTap::NetBSDEthernetTap(
 	Utils::snprintf(metstr,sizeof(metstr),"%u",_metric);
 	Utils::snprintf(metstr,sizeof(metstr),"%u",_metric);
 	long cpid = (long)vfork();
 	long cpid = (long)vfork();
 	if (cpid == 0) {
 	if (cpid == 0) {
-		::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"lladdr",ethaddr,"mtu",mtustr,"metric",metstr,"up",(const char *)0);
+		::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"link",ethaddr,"mtu",mtustr,"metric",metstr,"up",(const char *)0);
 		::_exit(-1);
 		::_exit(-1);
 	} else if (cpid > 0) {
 	} else if (cpid > 0) {
 		int exitcode = -1;
 		int exitcode = -1;
@@ -174,12 +177,30 @@ NetBSDEthernetTap::NetBSDEthernetTap(
 		}
 		}
 	}
 	}
 
 
+	// ifconfig link seems to be different from address
+	// https://wiki.netbsd.org/tutorials/faking_a_mac_address/
+	cpid = (long)vfork();
+	if (cpid == 0) {
+		string cmdline = "net.link.tap."+string(_dev);
+		cmdline += "="+string(ethaddr);
+		::execl("/sbin/sysctl","/sbin/sysctl","-w",cmdline.c_str(),(const char *)0);
+		::_exit(-1);
+	} else if (cpid > 0) {
+		int exitcode = -1;
+		::waitpid(cpid,&exitcode,0);
+		if (exitcode) {
+			::close(_fd);
+			throw std::runtime_error("sysctl failure setting link-layer address and activating tap interface");
+		}
+	}
+
 	// Set close-on-exec so that devices cannot persist if we fork/exec for update
 	// Set close-on-exec so that devices cannot persist if we fork/exec for update
 	fcntl(_fd,F_SETFD,fcntl(_fd,F_GETFD) | FD_CLOEXEC);
 	fcntl(_fd,F_SETFD,fcntl(_fd,F_GETFD) | FD_CLOEXEC);
 
 
 	::pipe(_shutdownSignalPipe);
 	::pipe(_shutdownSignalPipe);
 
 
 	_thread = Thread::start(this);
 	_thread = Thread::start(this);
+
 }
 }
 
 
 NetBSDEthernetTap::~NetBSDEthernetTap()
 NetBSDEthernetTap::~NetBSDEthernetTap()