From 3f912eb4ada67610eee21d3749ba7d5cfb083359 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 11 Feb 2014 14:21:59 -0800 Subject: Fix for GitHub issue #37: remember *nix device names. --- node/EthernetTap.cpp | 47 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 12 deletions(-) (limited to 'node/EthernetTap.cpp') 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"); -- cgit v1.2.3