Add support for npcap as winpcap replacement
For now both winpcap and npcap are supported with the latter being experimentally supported till we get some feedback from users and confirm that things are all working fine with npcap. OID for link state has been changed to one that supports both. To check which is being used, run 'drone -v'. Fixes #236
This commit is contained in:
parent
018a8490cf
commit
db66d7c5ea
@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#include "params.h"
|
||||
#include "pcapextra.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
@ -46,6 +47,11 @@ int Params::parseCommandLine(int argc, char* argv[])
|
||||
break;
|
||||
case 'v':
|
||||
printf("Ostinato Drone %s rev %s\n", version, revision);
|
||||
printf("PCAP Lib: %s\n", pcap_lib_version());
|
||||
#ifdef Q_OS_WIN32
|
||||
printf("Service npf status %s\n", pcapServiceStatus(L"npf"));
|
||||
printf("Service npcap status %s\n", pcapServiceStatus(L"npcap"));
|
||||
#endif
|
||||
exit(0);
|
||||
case 'h':
|
||||
default:
|
||||
|
@ -24,7 +24,66 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
/* NOTE: All code borrowed from WinPcap */
|
||||
|
||||
#ifndef Q_OS_WIN32
|
||||
#ifdef Q_OS_WIN32
|
||||
|
||||
const char* pcapServiceStatus(const wchar_t* name)
|
||||
{
|
||||
SC_HANDLE scm, svc;
|
||||
SERVICE_STATUS_PROCESS svcStatus;
|
||||
DWORD size;
|
||||
BOOL result;
|
||||
const char *status = "unknown";
|
||||
|
||||
scm = OpenSCManager(nullptr, nullptr, SC_MANAGER_ENUMERATE_SERVICE);
|
||||
if(!scm)
|
||||
goto _exit;
|
||||
|
||||
svc = OpenService(scm, name, SERVICE_QUERY_STATUS);
|
||||
if(!svc)
|
||||
goto _close_exit;
|
||||
|
||||
result = QueryServiceStatusEx(svc, SC_STATUS_PROCESS_INFO,
|
||||
reinterpret_cast<LPBYTE>(&svcStatus), sizeof(svcStatus),
|
||||
&size);
|
||||
|
||||
if(result == 0)
|
||||
goto _close_exit;
|
||||
|
||||
switch(svcStatus.dwCurrentState) {
|
||||
case SERVICE_CONTINUE_PENDING:
|
||||
status = "continue pending";
|
||||
break;
|
||||
case SERVICE_PAUSE_PENDING:
|
||||
status = "pause pending";
|
||||
break;
|
||||
case SERVICE_PAUSED:
|
||||
status = "paused";
|
||||
break;
|
||||
case SERVICE_RUNNING:
|
||||
status = "running";
|
||||
break;
|
||||
case SERVICE_START_PENDING:
|
||||
status = "start pending";
|
||||
break;
|
||||
case SERVICE_STOP_PENDING:
|
||||
status = "stop pending";
|
||||
break;
|
||||
case SERVICE_STOPPED:
|
||||
status = "stopped";
|
||||
break;
|
||||
}
|
||||
|
||||
_close_exit:
|
||||
if (svc)
|
||||
CloseServiceHandle(svc);
|
||||
if (scm)
|
||||
CloseServiceHandle(scm);
|
||||
_exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
#else // non-Windows
|
||||
|
||||
pcap_send_queue* pcap_sendqueue_alloc (u_int memsize)
|
||||
{
|
||||
pcap_send_queue *tqueue;
|
||||
|
@ -23,7 +23,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
#include <pcap.h>
|
||||
#include <QtGlobal>
|
||||
|
||||
#ifndef Q_OS_WIN32
|
||||
#ifdef Q_OS_WIN32
|
||||
|
||||
const char* pcapServiceStatus(const wchar_t *name);
|
||||
|
||||
#else // non-windows
|
||||
|
||||
#define PCAP_OPENFLAG_PROMISCUOUS 1
|
||||
|
||||
|
@ -342,7 +342,8 @@ void PcapPort::PortMonitor::run()
|
||||
void PcapPort::PortMonitor::stop()
|
||||
{
|
||||
stop_ = true;
|
||||
pcap_breakloop(handle());
|
||||
if (handle())
|
||||
pcap_breakloop(handle());
|
||||
}
|
||||
|
||||
/*
|
||||
@ -404,6 +405,11 @@ _retry:
|
||||
}
|
||||
|
||||
dumpHandle_ = pcap_dump_open(handle_, qPrintable(capFile_.fileName()));
|
||||
if (!dumpHandle_) {
|
||||
qDebug("failed to start capture: %s", pcap_geterr(handle_));
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
PcapSession::preRun();
|
||||
state_ = kRunning;
|
||||
while (1)
|
||||
|
@ -51,6 +51,11 @@ PortManager::PortManager()
|
||||
AbstractPort::Accuracy txRateAccuracy;
|
||||
|
||||
qDebug("PCAP Lib: %s", pcap_lib_version());
|
||||
#ifdef Q_OS_WIN32
|
||||
qDebug("Service npf status %s\n", pcapServiceStatus(L"npf"));
|
||||
qDebug("Service npcap status %s\n", pcapServiceStatus(L"npcap"));
|
||||
#endif
|
||||
|
||||
qDebug("Retrieving the device list from the local machine\n");
|
||||
|
||||
#if defined(Q_OS_WIN32)
|
||||
|
@ -26,10 +26,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
|
||||
#include <ntddndis.h>
|
||||
#include <ws2ipdef.h>
|
||||
|
||||
PIP_ADAPTER_ADDRESSES WinPcapPort::adapterList_ = NULL;
|
||||
const uint OID_GEN_MEDIA_CONNECT_STATUS = 0x00010114;
|
||||
|
||||
WinPcapPort::WinPcapPort(int id, const char *device, const char *description)
|
||||
: PcapPort(id, device)
|
||||
@ -53,7 +53,7 @@ WinPcapPort::WinPcapPort(int id, const char *device, const char *description)
|
||||
if (!adapter_)
|
||||
qFatal("Unable to open adapter %s", device);
|
||||
linkStateOid_ = (PPACKET_OID_DATA) malloc(sizeof(PACKET_OID_DATA) +
|
||||
sizeof(uint));
|
||||
sizeof(NDIS_LINK_STATE));
|
||||
if (!linkStateOid_)
|
||||
qFatal("failed to alloc oidData");
|
||||
|
||||
@ -67,24 +67,36 @@ WinPcapPort::~WinPcapPort()
|
||||
|
||||
OstProto::LinkState WinPcapPort::linkState()
|
||||
{
|
||||
memset(linkStateOid_, 0, sizeof(PACKET_OID_DATA) + sizeof(uint));
|
||||
memset(linkStateOid_, 0, sizeof(PACKET_OID_DATA) + sizeof(NDIS_LINK_STATE));
|
||||
|
||||
linkStateOid_->Oid = OID_GEN_MEDIA_CONNECT_STATUS;
|
||||
linkStateOid_->Length = sizeof(uint);
|
||||
linkStateOid_->Oid = OID_GEN_LINK_STATE;
|
||||
linkStateOid_->Length = sizeof(NDIS_LINK_STATE);
|
||||
|
||||
// TODO: migrate to the npcap-only pcap_oid_get_request() when Ostinato
|
||||
// stops supporting WinPcap
|
||||
if (PacketRequest(adapter_, 0, linkStateOid_))
|
||||
{
|
||||
uint state;
|
||||
|
||||
if (linkStateOid_->Length == sizeof(state))
|
||||
if (linkStateOid_->Length == sizeof(NDIS_LINK_STATE))
|
||||
{
|
||||
memcpy((void*)&state, (void*)linkStateOid_->Data,
|
||||
linkStateOid_->Length);
|
||||
memcpy((void*)&state,
|
||||
(void*)(linkStateOid_->Data+sizeof(NDIS_OBJECT_HEADER)),
|
||||
sizeof(state));
|
||||
//qDebug("%s: state = %d", data_.description().c_str(), state);
|
||||
if (state == 0)
|
||||
linkState_ = OstProto::LinkStateUp;
|
||||
linkState_ = OstProto::LinkStateUnknown;
|
||||
else if (state == 1)
|
||||
linkState_ = OstProto::LinkStateUp;
|
||||
else if (state == 2)
|
||||
linkState_ = OstProto::LinkStateDown;
|
||||
}
|
||||
else {
|
||||
//qDebug("%s: link state fail", data_.description().c_str());
|
||||
}
|
||||
}
|
||||
else {
|
||||
//qDebug("%s: link state request fail", data_.description().c_str());
|
||||
}
|
||||
|
||||
return linkState_;
|
||||
|
Loading…
Reference in New Issue
Block a user