Fix for crash when NIC doesn't support setting promisc mode

This commit is contained in:
Srivats P. 2011-02-20 13:10:33 +05:30
parent 481005a994
commit 73afecc07a
5 changed files with 58 additions and 19 deletions

View File

@ -26,6 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
AbstractPort::AbstractPort(int id, const char *device) AbstractPort::AbstractPort(int id, const char *device)
{ {
isUsable_ = true;
data_.mutable_port_id()->set_id(id); data_.mutable_port_id()->set_id(id);
data_.set_name(device); data_.set_name(device);

View File

@ -47,6 +47,8 @@ public:
AbstractPort(int id, const char *device); AbstractPort(int id, const char *device);
virtual ~AbstractPort(); virtual ~AbstractPort();
bool isUsable() { return isUsable_; }
virtual void init(); virtual void init();
int id() { return data_.port_id().id(); } int id() { return data_.port_id().id(); }
@ -86,6 +88,7 @@ public:
void resetStats() { epochStats_ = stats_; } void resetStats() { epochStats_ = stats_; }
protected: protected:
bool isUsable_;
OstProto::Port data_; OstProto::Port data_;
OstProto::LinkState linkState_; OstProto::LinkState linkState_;

View File

@ -35,6 +35,9 @@ PcapPort::PcapPort(int id, const char *device)
transmitter_ = new PortTransmitter(device); transmitter_ = new PortTransmitter(device);
capturer_ = new PortCapturer(device); capturer_ = new PortCapturer(device);
if (!monitorRx_->handle() || !monitorTx_->handle())
isUsable_ = false;
if (!deviceList_) if (!deviceList_)
{ {
char errbuf[PCAP_ERRBUF_SIZE]; char errbuf[PCAP_ERRBUF_SIZE];
@ -106,16 +109,27 @@ PcapPort::PortMonitor::PortMonitor(const char *device, Direction direction,
AbstractPort::PortStats *stats) AbstractPort::PortStats *stats)
{ {
int ret; int ret;
char errbuf[PCAP_ERRBUF_SIZE]; int flag = PCAP_OPENFLAG_PROMISCUOUS;
char errbuf[PCAP_ERRBUF_SIZE] = "";
direction_ = direction; direction_ = direction;
isDirectional_ = true; isDirectional_ = true;
stats_ = stats; stats_ = stats;
handle_ = pcap_open_live(device, 64 /* FIXME */, PCAP_OPENFLAG_PROMISCUOUS, _retry:
handle_ = pcap_open_live(device, 64 /* FIXME */, flag,
1000 /* ms */, errbuf); 1000 /* ms */, errbuf);
if (handle_ == NULL) if (handle_ == NULL)
{
if (flag && QString(errbuf).contains("promiscuous"))
{
qDebug("%s:can't set promiscuous mode, trying non-promisc", device);
flag = 0;
goto _retry;
}
else
goto _open_error; goto _open_error;
}
#ifdef Q_OS_WIN32 #ifdef Q_OS_WIN32
// pcap_setdirection() API is not supported in Windows. // pcap_setdirection() API is not supported in Windows.
// NOTE: WinPcap 4.1.1 and above exports a dummy API that returns -1 // NOTE: WinPcap 4.1.1 and above exports a dummy API that returns -1
@ -149,7 +163,7 @@ _set_direction_error:
return; return;
_open_error: _open_error:
qDebug("Error opening port %s: %s\n", device, pcap_geterr(handle_)); qDebug("%s: Error opening port %s: %s\n", __FUNCTION__, device, errbuf);
} }
void PcapPort::PortMonitor::run() void PcapPort::PortMonitor::run()
@ -201,7 +215,7 @@ void PcapPort::PortMonitor::run()
PcapPort::PortTransmitter::PortTransmitter(const char *device) PcapPort::PortTransmitter::PortTransmitter(const char *device)
{ {
char errbuf[PCAP_ERRBUF_SIZE]; char errbuf[PCAP_ERRBUF_SIZE] = "";
#ifdef Q_OS_WIN32 #ifdef Q_OS_WIN32
LARGE_INTEGER freq; LARGE_INTEGER freq;
@ -216,8 +230,7 @@ PcapPort::PortTransmitter::PortTransmitter(const char *device)
stop_ = false; stop_ = false;
stats_ = new AbstractPort::PortStats; stats_ = new AbstractPort::PortStats;
usingInternalStats_ = true; usingInternalStats_ = true;
handle_ = pcap_open_live(device, 64 /* FIXME */, PCAP_OPENFLAG_PROMISCUOUS, handle_ = pcap_open_live(device, 64 /* FIXME */, 0, 1000 /* ms */, errbuf);
1000 /* ms */, errbuf);
if (handle_ == NULL) if (handle_ == NULL)
goto _open_error; goto _open_error;
@ -227,7 +240,7 @@ PcapPort::PortTransmitter::PortTransmitter(const char *device)
return; return;
_open_error: _open_error:
qDebug("Error opening port %s: %s\n", device, pcap_geterr(handle_)); qDebug("%s: Error opening port %s: %s\n", __FUNCTION__, device, errbuf);
usingInternalHandle_ = false; usingInternalHandle_ = false;
} }
@ -434,7 +447,8 @@ PcapPort::PortCapturer::~PortCapturer()
void PcapPort::PortCapturer::run() void PcapPort::PortCapturer::run()
{ {
char errbuf[PCAP_ERRBUF_SIZE]; int flag = PCAP_OPENFLAG_PROMISCUOUS;
char errbuf[PCAP_ERRBUF_SIZE] = "";
qDebug("In %s", __PRETTY_FUNCTION__); qDebug("In %s", __PRETTY_FUNCTION__);
@ -443,15 +457,26 @@ void PcapPort::PortCapturer::run()
qWarning("temp cap file is not open"); qWarning("temp cap file is not open");
return; return;
} }
_retry:
handle_ = pcap_open_live(device_.toAscii().constData(), 65535, handle_ = pcap_open_live(device_.toAscii().constData(), 65535,
PCAP_OPENFLAG_PROMISCUOUS, 1000 /* ms */, errbuf); flag, 1000 /* ms */, errbuf);
if (handle_ == NULL) if (handle_ == NULL)
{ {
qDebug("Error opening port %s: %s\n", if (flag && QString(errbuf).contains("promiscuous"))
device_.toAscii().constData(), pcap_geterr(handle_)); {
qDebug("%s:can't set promiscuous mode, trying non-promisc",
device_.toAscii().constData());
flag = 0;
goto _retry;
}
else
{
qDebug("%s: Error opening port %s: %s\n", __FUNCTION__,
device_.toAscii().constData(), errbuf);
return; return;
} }
}
dumpHandle_ = pcap_dump_open(handle_, dumpHandle_ = pcap_dump_open(handle_,
capFile_.fileName().toAscii().constData()); capFile_.fileName().toAscii().constData());

View File

@ -43,18 +43,27 @@ PortManager::PortManager()
{ {
AbstractPort *port; AbstractPort *port;
qDebug("%d. %s", i, device->name);
if (device->description)
qDebug(" (%s)\n", device->description);
#ifdef Q_OS_WIN32 #ifdef Q_OS_WIN32
port = new WinPcapPort(i, device->name); port = new WinPcapPort(i, device->name);
#else #else
port = new PcapPort(i, device->name); port = new PcapPort(i, device->name);
#endif #endif
if (!port->isUsable())
{
qDebug("%s: unable to open %s. Skipping!", __FUNCTION__,
device->name);
delete port;
i--;
continue;
}
port->init(); port->init();
portList_.append(port); portList_.append(port);
qDebug("%d. %s", i, device->name);
if (device->description)
qDebug(" (%s)\n", device->description);
} }
pcap_freealldevs(deviceList); pcap_freealldevs(deviceList);

View File

@ -124,6 +124,7 @@ WinPcapPort::PortMonitor::PortMonitor(const char *device, Direction direction,
AbstractPort::PortStats *stats) AbstractPort::PortStats *stats)
: PcapPort::PortMonitor(device, direction, stats) : PcapPort::PortMonitor(device, direction, stats)
{ {
if (handle())
pcap_setmode(handle(), MODE_STAT); pcap_setmode(handle(), MODE_STAT);
} }