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
};