diff --git a/server/drone_main.cpp b/server/drone_main.cpp index 3f16bcc..e59cb48 100644 --- a/server/drone_main.cpp +++ b/server/drone_main.cpp @@ -21,10 +21,19 @@ along with this program. If not, see #include "../common/protocolmanager.h" +#ifdef Q_OS_UNIX +#include "signal.h" +#endif + extern ProtocolManager *OstProtocolManager; int myport; +void cleanup(int /*signum*/) +{ + qApp->exit(-1); +} + int main(int argc, char *argv[]) { QApplication app(argc, argv); @@ -39,11 +48,24 @@ int main(int argc, char *argv[]) if (!drone.init()) exit(-1); +#ifdef Q_OS_UNIX + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = cleanup; + if (sigaction(SIGTERM, &sa, NULL)) + qDebug("Failed to install SIGTERM handler. Cleanup may not happen!!!"); + if (sigaction(SIGINT, &sa, NULL)) + qDebug("Failed to install SIGINT handler. Cleanup may not happen!!!"); +#endif + drone.setWindowFlags(drone.windowFlags() | Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint); drone.showMinimized(); app.exec(); + + delete OstProtocolManager; + return 0; } diff --git a/server/linuxport.cpp b/server/linuxport.cpp index 82d9277..7e15101 100644 --- a/server/linuxport.cpp +++ b/server/linuxport.cpp @@ -23,9 +23,13 @@ along with this program. If not, see #include -#include -#include +#include #include +#include +#include +#include +#include +#include QList LinuxPort::allPorts_; LinuxPort::StatsMonitor *LinuxPort::monitor_; @@ -33,13 +37,16 @@ LinuxPort::StatsMonitor *LinuxPort::monitor_; LinuxPort::LinuxPort(int id, const char *device) : PcapPort(id, device) { + clearPromisc_ = false; + // We don't need per port Rx/Tx monitors for Linux delete monitorRx_; delete monitorTx_; + monitorRx_ = monitorTx_ = NULL; // We have one monitor for both Rx/Tx of all ports if (!monitor_) - monitor_ = new StatsMonitor(); + monitor_ = new StatsMonitor(); data_.set_is_exclusive_control(hasExclusiveControl()); minPacketSetSize_ = 16; @@ -50,6 +57,32 @@ LinuxPort::LinuxPort(int id, const char *device) LinuxPort::~LinuxPort() { + qDebug("In %s", __FUNCTION__); + + if (clearPromisc_) + { + int sd = socket(AF_INET, SOCK_DGRAM, 0); + struct ifreq ifr; + + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, name(), sizeof(ifr.ifr_name)); + + if (ioctl(sd, SIOCGIFFLAGS, &ifr) != -1) + { + if (ifr.ifr_flags & IFF_PROMISC) + { + ifr.ifr_flags &= ~IFF_PROMISC; + if (ioctl(sd, SIOCSIFFLAGS, &ifr) == -1) + qDebug("Failed clearing promisc flag. SIOCSIFFLAGS failed: %s", + strerror(errno)); + } + } + else + qDebug("Failed clearing promisc flag. SIOCGIFFLAGS failed: %s", + strerror(errno)); + + close(sd); + } } void LinuxPort::init() @@ -57,7 +90,7 @@ void LinuxPort::init() // TODO: Update Notes with Promisc/Non-Promisc if (!monitor_->isRunning()) - monitor_->start(); + monitor_->start(); } OstProto::LinkState LinuxPort::linkState() @@ -86,16 +119,17 @@ LinuxPort::StatsMonitor::StatsMonitor() void LinuxPort::StatsMonitor::run() { PortStats **portStats; - int fd; + int fd, sd; QByteArray buf; int len; char *p, *end; int count, index; const char* fmtopt[] = { - "%llu%llu%u%u%u%u%u%u%llu%llu%u%u%u%u%u%u\n", - "%llu%llu%u%u%u%u%n%n%llu%llu%u%u%u%u%u%n\n", + "%llu%llu%u%u%u%u%u%u%llu%llu%u%u%u%u%u%u\n", + "%llu%llu%u%u%u%u%n%n%llu%llu%u%u%u%u%u%n\n", }; const char *fmt; + struct ifreq ifr; // // We first setup stuff before we start polling for stats @@ -103,16 +137,16 @@ void LinuxPort::StatsMonitor::run() fd = open("/proc/net/dev", O_RDONLY); if (fd < 0) { - qWarning("Unable to open /proc/net/dev - no stats will be available"); - return; + qWarning("Unable to open /proc/net/dev - no stats will be available"); + return; } buf.fill('\0', 8192); len = read(fd, (void*) buf.data(), buf.size()); if (len < 0) { - qWarning("initial buffer size is too small. no stats will be available"); - return; + qWarning("initial buffer size is too small. no stats will be available"); + return; } p = buf.data(); @@ -120,29 +154,33 @@ void LinuxPort::StatsMonitor::run() // Select scanf format if (strstr(buf, "compressed")) - fmt = fmtopt[0]; + fmt = fmtopt[0]; else - fmt = fmtopt[1]; + fmt = fmtopt[1]; // Count number of lines - number of ports is 2 less than number of lines count = 0; while (p < end) { - if (*p == '\n') - count++; - p++; + if (*p == '\n') + count++; + p++; } count -= 2; if (count <= 0) { - qWarning("no ports in /proc/dev/net - no stats will be available"); - return; + qWarning("no ports in /proc/dev/net - no stats will be available"); + return; } portStats = (PortStats**) calloc(count, sizeof(PortStats)); Q_ASSERT(portStats != NULL); + sd = socket(AF_INET, SOCK_DGRAM, 0); + Q_ASSERT(sd >= 0); + memset(&ifr, 0, sizeof(ifr)); + // // Populate the port stats array // @@ -150,48 +188,73 @@ void LinuxPort::StatsMonitor::run() // Skip first two lines while (*p != '\n') - p++; + p++; p++; while (*p != '\n') - p++; + p++; p++; index = 0; while (p < end) { - char* q; + char* q; - // Skip whitespace - while ((p < end) && (*p == ' ')) - p++; - - q = p; + // Skip whitespace + while ((p < end) && (*p == ' ')) + p++; - // Get interface name - while ((q < end) && (*q != ':') && (*q != '\n')) - q++; + q = p; - if ((q < end) && (*q == ':')) - { - foreach(LinuxPort* port, allPorts_) + // Get interface name + while ((q < end) && (*q != ':') && (*q != '\n')) + q++; + + if ((q < end) && (*q == ':')) { - if (strncmp(port->name(), p, int(q-p)) == 0) - { - portStats[index] = &(port->stats_); - break; - } - } - } - index++; + foreach(LinuxPort* port, allPorts_) + { + if (strncmp(port->name(), p, int(q-p)) == 0) + { + portStats[index] = &(port->stats_); - // Skip till newline - p = q; - while (*p != '\n') + // Set promisc mode, if not already set + strncpy(ifr.ifr_name, port->name(), sizeof(ifr.ifr_name)); + if (ioctl(sd, SIOCGIFFLAGS, &ifr) != -1) + { + if ((ifr.ifr_flags & IFF_PROMISC) == 0) + { + ifr.ifr_flags |= IFF_PROMISC; + if (ioctl(sd, SIOCSIFFLAGS, &ifr) != -1) + port->clearPromisc_ = true; + else + { + qDebug("%s: failed to set promisc; " + "SIOCSIFFLAGS failed (%s)", + port->name(), strerror(errno)); + } + } + } + else + { + qDebug("%s: failed to set promisc; SIOCGIFFLAGS failed (%s)", + port->name(), strerror(errno)); + } + break; + } + } + } + index++; + + // Skip till newline + p = q; + while (*p != '\n') + p++; p++; - p++; } Q_ASSERT(index == count); + close(sd); + qDebug("stats for %d ports setup", count); // @@ -199,77 +262,77 @@ void LinuxPort::StatsMonitor::run() // while (1) { - lseek(fd, 0, SEEK_SET); - len = read(fd, (void*) buf.data(), buf.size()); - if (len < 0) - { - if (buf.size() > 1*1024*1024) + lseek(fd, 0, SEEK_SET); + len = read(fd, (void*) buf.data(), buf.size()); + if (len < 0) { - qWarning("buffer size hit limit. no more stats"); - return; - } - qDebug("doubling buffer size. curr = %d", buf.size()); - buf.resize(buf.size() * 2); - continue; - } - - p = buf.data(); - end = p + len; - - // Skip first two lines - while (*p != '\n') - p++; - p++; - while (*p != '\n') - p++; - p++; - - index = 0; - while (p < end) - { - uint dummy; - quint64 rxBytes, rxPkts; - quint64 txBytes, txPkts; - - // Skip interface name - we assume the number and order of ports - // won't change since we parsed the output before we started polling - while ((p < end) && (*p != ':') && (*p != '\n')) - p++; - if (p >= end) - break; - if (*p == '\n') - { - index++; - continue; - } - p++; - - sscanf(p, fmt, - &rxBytes, &rxPkts, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, - &txBytes, &txPkts, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy); - - if (index < count) - { - AbstractPort::PortStats *stats = portStats[index]; - if (stats) - { - stats->rxPps = (rxPkts - stats->rxPkts)/kRefreshFreq_; - stats->rxBps = (rxBytes - stats->rxBytes)/kRefreshFreq_; - stats->rxPkts = rxPkts; - stats->rxBytes = rxBytes; - stats->txPps = (txPkts - stats->txPkts)/kRefreshFreq_; - stats->txBps = (txBytes - stats->txBytes)/kRefreshFreq_; - stats->txPkts = txPkts; - stats->txBytes = txBytes; - } + if (buf.size() > 1*1024*1024) + { + qWarning("buffer size hit limit. no more stats"); + return; + } + qDebug("doubling buffer size. curr = %d", buf.size()); + buf.resize(buf.size() * 2); + continue; } + p = buf.data(); + end = p + len; + + // Skip first two lines while (*p != '\n') + p++; p++; + while (*p != '\n') + p++; p++; - index++; - } - QThread::sleep(kRefreshFreq_); + + index = 0; + while (p < end) + { + uint dummy; + quint64 rxBytes, rxPkts; + quint64 txBytes, txPkts; + + // Skip interface name - we assume the number and order of ports + // won't change since we parsed the output before we started polling + while ((p < end) && (*p != ':') && (*p != '\n')) + p++; + if (p >= end) + break; + if (*p == '\n') + { + index++; + continue; + } + p++; + + sscanf(p, fmt, + &rxBytes, &rxPkts, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, + &txBytes, &txPkts, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy); + + if (index < count) + { + AbstractPort::PortStats *stats = portStats[index]; + if (stats) + { + stats->rxPps = (rxPkts - stats->rxPkts)/kRefreshFreq_; + stats->rxBps = (rxBytes - stats->rxBytes)/kRefreshFreq_; + stats->rxPkts = rxPkts; + stats->rxBytes = rxBytes; + stats->txPps = (txPkts - stats->txPkts)/kRefreshFreq_; + stats->txBps = (txBytes - stats->txBytes)/kRefreshFreq_; + stats->txPkts = txPkts; + stats->txBytes = txBytes; + } + } + + while (*p != '\n') + p++; + p++; + index++; + } + QThread::sleep(kRefreshFreq_); } } diff --git a/server/linuxport.h b/server/linuxport.h index 8fbedf5..4fe3305 100644 --- a/server/linuxport.h +++ b/server/linuxport.h @@ -48,6 +48,7 @@ protected: static const int kRefreshFreq_ = 1; // in seconds }; + bool clearPromisc_; static QList allPorts_; static StatsMonitor *monitor_; // rx/tx stats for ALL ports };