Implement set/clear promisc for Windows ports
With windows if stats, we need to put the ports explicitly in promisc mode; with internal-stats this happens implicitly when we create monitorRx/Tx
This commit is contained in:
parent
6d312764e8
commit
e5375247a9
@ -100,6 +100,10 @@ WinPcapPort::~WinPcapPort()
|
|||||||
delete monitor_;
|
delete monitor_;
|
||||||
monitor_ = nullptr;
|
monitor_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// npcap will already clear promisc at exit, but we still do explicitly
|
||||||
|
if (clearPromiscAtExit_)
|
||||||
|
clearPromisc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WinPcapPort::init()
|
void WinPcapPort::init()
|
||||||
@ -110,10 +114,8 @@ void WinPcapPort::init()
|
|||||||
monitor_->waitForSetupFinished();
|
monitor_->waitForSetupFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 // TODO
|
|
||||||
if (!isPromisc_)
|
if (!isPromisc_)
|
||||||
addNote("Non Promiscuous Mode");
|
addNote("Non Promiscuous Mode");
|
||||||
#endif
|
|
||||||
|
|
||||||
if (monitor_)
|
if (monitor_)
|
||||||
AbstractPort::init();
|
AbstractPort::init();
|
||||||
@ -203,6 +205,106 @@ bool WinPcapPort::setExclusiveControl(bool exclusive)
|
|||||||
return (exclusive == hasExclusiveControl());
|
return (exclusive == hasExclusiveControl());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WinPcapPort::setPromisc()
|
||||||
|
{
|
||||||
|
if (!promiscHandle_) {
|
||||||
|
char errbuf[PCAP_ERRBUF_SIZE] = "";
|
||||||
|
|
||||||
|
promiscHandle_ = pcap_create(name(), errbuf);
|
||||||
|
if (!promiscHandle_) {
|
||||||
|
qDebug("%s: Error opening port to set promisc mode: %s",
|
||||||
|
name(), errbuf);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int status = pcap_activate(promiscHandle_);
|
||||||
|
if (status) {
|
||||||
|
qDebug("%s: Error activating port to set promisc mode: %s",
|
||||||
|
name(), pcap_statustostr(status));
|
||||||
|
pcap_close(promiscHandle_);
|
||||||
|
promiscHandle_ = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint data = NDIS_PACKET_TYPE_PROMISCUOUS;
|
||||||
|
uint size = sizeof(data);
|
||||||
|
int status = pcap_oid_set_request(promiscHandle_,
|
||||||
|
OID_GEN_CURRENT_PACKET_FILTER, &data, &size);
|
||||||
|
if (status) {
|
||||||
|
qDebug("%s: Unable to set promisc mode: %s",
|
||||||
|
name(), pcap_statustostr(status));
|
||||||
|
pcap_close(promiscHandle_);
|
||||||
|
promiscHandle_ = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
isPromisc_ = clearPromiscAtExit_ = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WinPcapPort::clearPromisc()
|
||||||
|
{
|
||||||
|
if (!promiscHandle_) {
|
||||||
|
qDebug("%s: No promisc handle to clear promisc mode", name());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint data = NDIS_PACKET_TYPE_ALL_LOCAL
|
||||||
|
| NDIS_PACKET_TYPE_DIRECTED
|
||||||
|
| NDIS_PACKET_TYPE_BROADCAST
|
||||||
|
| NDIS_PACKET_TYPE_MULTICAST;
|
||||||
|
uint size = sizeof(data);
|
||||||
|
int status = pcap_oid_set_request(promiscHandle_,
|
||||||
|
OID_GEN_CURRENT_PACKET_FILTER, &data, &size);
|
||||||
|
if (status) {
|
||||||
|
qDebug("%s: Unable to clear promisc mode: %s",
|
||||||
|
name(), pcap_statustostr(status));
|
||||||
|
pcap_close(promiscHandle_);
|
||||||
|
promiscHandle_ = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
isPromisc_ = clearPromiscAtExit_ = false;
|
||||||
|
pcap_close(promiscHandle_);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// The above set/clearPromisc implementation using standard npcap APIs.
|
||||||
|
// The below implementation uses packet.dll APIs directly and may be
|
||||||
|
// slightly more performant? To be verified!
|
||||||
|
bool WinPcapPort::setPromiscAlt(bool promisc)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
uint data = promisc ? NDIS_PACKET_TYPE_PROMISCUOUS :
|
||||||
|
(NDIS_PACKET_TYPE_ALL_LOCAL
|
||||||
|
| NDIS_PACKET_TYPE_DIRECTED
|
||||||
|
| NDIS_PACKET_TYPE_BROADCAST
|
||||||
|
| NDIS_PACKET_TYPE_MULTICAST);
|
||||||
|
|
||||||
|
PPACKET_OID_DATA oid = (PPACKET_OID_DATA) malloc(sizeof(PACKET_OID_DATA) +
|
||||||
|
sizeof(data));
|
||||||
|
if (oid) {
|
||||||
|
memset(oid, 0, sizeof(PACKET_OID_DATA) + sizeof(data));
|
||||||
|
|
||||||
|
oid->Oid = OID_GEN_CURRENT_PACKET_FILTER;
|
||||||
|
oid->Length = sizeof(data);
|
||||||
|
memcpy(oid->Data, &data, sizeof(data));
|
||||||
|
if (PacketRequest(adapter_, true, oid)) {
|
||||||
|
isPromisc_ = clearPromiscAtExit_ = promisc;
|
||||||
|
ret = true;
|
||||||
|
} else
|
||||||
|
qDebug("%s: Unable to %s promisc mode", name(),
|
||||||
|
promisc ? "set" : "clear");
|
||||||
|
} else
|
||||||
|
qDebug("%s: failed to alloc promisc oid", name());
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
WinPcapPort::PortMonitor::PortMonitor(const char *device, Direction direction,
|
WinPcapPort::PortMonitor::PortMonitor(const char *device, Direction direction,
|
||||||
AbstractPort::PortStats *stats)
|
AbstractPort::PortStats *stats)
|
||||||
: PcapPort::PortMonitor(device, direction, stats)
|
: PcapPort::PortMonitor(device, direction, stats)
|
||||||
@ -330,6 +432,7 @@ void WinPcapPort::StatsMonitor::run()
|
|||||||
if (port->luid_.Value) {
|
if (port->luid_.Value) {
|
||||||
portList.append(
|
portList.append(
|
||||||
{port->luid_, &(port->stats_), &(port->linkState_), false});
|
{port->luid_, &(port->stats_), &(port->linkState_), false});
|
||||||
|
port->setPromisc();
|
||||||
} else {
|
} else {
|
||||||
qWarning("No LUID for port %s - stats will not be available",
|
qWarning("No LUID for port %s - stats will not be available",
|
||||||
port->name());
|
port->name());
|
||||||
|
@ -26,6 +26,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include "pcapport.h"
|
#include "pcapport.h"
|
||||||
|
|
||||||
|
// BPF_MAJOR_VERSION definition is needed to prevent redefinition of
|
||||||
|
// bpf_program, bpf_insn etc. - this was not needed in WinPcap as it
|
||||||
|
// defines it, but npcap doesn't
|
||||||
|
#define BPF_MAJOR_VERSION 1
|
||||||
#include <packet32.h>
|
#include <packet32.h>
|
||||||
|
|
||||||
#include <ws2ipdef.h>
|
#include <ws2ipdef.h>
|
||||||
@ -70,6 +74,10 @@ protected:
|
|||||||
bool setupDone_;
|
bool setupDone_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool isPromisc_{false};
|
||||||
|
bool clearPromiscAtExit_{false};
|
||||||
|
pcap_t *promiscHandle_{nullptr};
|
||||||
|
|
||||||
static QList<WinPcapPort*> allPorts_;
|
static QList<WinPcapPort*> allPorts_;
|
||||||
static StatsMonitor *monitor_; // rx/tx stats for ALL ports
|
static StatsMonitor *monitor_; // rx/tx stats for ALL ports
|
||||||
static bool internalPortStats_;
|
static bool internalPortStats_;
|
||||||
@ -77,6 +85,9 @@ protected:
|
|||||||
private:
|
private:
|
||||||
void populateInterfaceInfo();
|
void populateInterfaceInfo();
|
||||||
|
|
||||||
|
bool setPromisc();
|
||||||
|
bool clearPromisc();
|
||||||
|
|
||||||
LPADAPTER adapter_;
|
LPADAPTER adapter_;
|
||||||
NET_LUID luid_;
|
NET_LUID luid_;
|
||||||
PPACKET_OID_DATA linkStateOid_ ;
|
PPACKET_OID_DATA linkStateOid_ ;
|
||||||
|
Loading…
Reference in New Issue
Block a user