summaryrefslogtreecommitdiff
path: root/node/EthernetTap.cpp
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2014-02-11 14:21:59 -0800
committerAdam Ierymenko <adam.ierymenko@gmail.com>2014-02-11 14:21:59 -0800
commit3f912eb4ada67610eee21d3749ba7d5cfb083359 (patch)
treefe8fac739717067998bcdc732f64f1b721f077a5 /node/EthernetTap.cpp
parentf1b45f7df0381dbf6c46208daa86cde336ab644c (diff)
downloadinfinitytier-3f912eb4ada67610eee21d3749ba7d5cfb083359.tar.gz
infinitytier-3f912eb4ada67610eee21d3749ba7d5cfb083359.zip
Fix for GitHub issue #37: remember *nix device names.
Diffstat (limited to 'node/EthernetTap.cpp')
-rw-r--r--node/EthernetTap.cpp47
1 files changed, 35 insertions, 12 deletions
diff --git a/node/EthernetTap.cpp b/node/EthernetTap.cpp
index 86e96f33..d2302e3f 100644
--- a/node/EthernetTap.cpp
+++ b/node/EthernetTap.cpp
@@ -234,6 +234,7 @@ EthernetTap::EthernetTap(
_fd(0)
{
char procpath[128];
+ struct stat sbuf;
Mutex::Lock _l(__tapCreateLock); // create only one tap at a time, globally
if (mtu > 4096)
@@ -246,13 +247,19 @@ EthernetTap::EthernetTap(
struct ifreq ifr;
memset(&ifr,0,sizeof(ifr));
- { // pick an unused device name
+ // Try to recall our last device name, or pick an unused one if that fails.
+ bool recalledDevice = false;
+ if ((tag)&&(tag[0])) {
+ Utils::scopy(ifr.ifr_name,sizeof(ifr.ifr_name),tag);
+ Utils::snprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.fr_name);
+ recalledDevice = (stat(procpath,&sbuf) != 0);
+ }
+ if (!recalledDevice) {
int devno = 0;
- struct stat sbuf;
do {
Utils::snprintf(ifr.ifr_name,sizeof(ifr.ifr_name),"zt%d",devno++);
Utils::snprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name);
- } while (stat(procpath,&sbuf) == 0);
+ } while (stat(procpath,&sbuf) == 0); // try zt#++ until we find one that does not exist
}
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
@@ -359,17 +366,33 @@ EthernetTap::EthernetTap(
if (stat("/dev/zt0",&stattmp))
throw std::runtime_error("/dev/zt# tap devices do not exist and unable to load kernel extension");
- // Open the first available device (ones in use will fail with resource busy)
- for(int i=0;i<256;++i) {
- Utils::snprintf(devpath,sizeof(devpath),"/dev/zt%d",i);
- if (stat(devpath,&stattmp))
- throw std::runtime_error("no more TAP devices available");
- _fd = ::open(devpath,O_RDWR);
- if (_fd > 0) {
- Utils::snprintf(_dev,sizeof(_dev),"zt%d",i);
- break;
+ // Try to reopen the last device we had, if we had one and it's still unused.
+ bool recalledDevice = false;
+ if ((tag)&&(tag[0])) {
+ Utils::snprintf(devpath,sizeof(devpath),"/dev/%s",tag);
+ if (stat(devpath,&stattmp) == 0) {
+ _fd = ::open(devpath,O_RDWR);
+ if (_fd > 0) {
+ Utils::scopy(_dev,sizeof(_dev),tag);
+ recalledDevice = true;
+ }
}
}
+
+ // Open the first unused tap device if we didn't recall a previous one.
+ if (!recalledDevice) {
+ for(int i=0;i<256;++i) {
+ Utils::snprintf(devpath,sizeof(devpath),"/dev/zt%d",i);
+ if (stat(devpath,&stattmp))
+ throw std::runtime_error("no more TAP devices available");
+ _fd = ::open(devpath,O_RDWR);
+ if (_fd > 0) {
+ Utils::snprintf(_dev,sizeof(_dev),"zt%d",i);
+ break;
+ }
+ }
+ }
+
if (_fd <= 0)
throw std::runtime_error("unable to open TAP device or no more devices available");