HostDev: Added infra and windows IPv4 implementation
This commit is contained in:
parent
0d5e836d3f
commit
bc972e4476
@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
#include "../common/abstractprotocol.h"
|
||||
#include "../common/streambase.h"
|
||||
#include "devicemanager.h"
|
||||
#include "interfaceinfo.h"
|
||||
#include "packetbuffer.h"
|
||||
|
||||
#include <QString>
|
||||
@ -47,6 +48,7 @@ AbstractPort::AbstractPort(int id, const char *device)
|
||||
minPacketSetSize_ = 1;
|
||||
|
||||
deviceManager_ = new DeviceManager(this);
|
||||
interfaceInfo_ = NULL;
|
||||
|
||||
maxStatsValue_ = ULLONG_MAX; // assume 64-bit stats
|
||||
memset((void*) &stats_, 0, sizeof(stats_));
|
||||
@ -56,10 +58,13 @@ AbstractPort::AbstractPort(int id, const char *device)
|
||||
AbstractPort::~AbstractPort()
|
||||
{
|
||||
delete deviceManager_;
|
||||
delete interfaceInfo_;
|
||||
}
|
||||
|
||||
void AbstractPort::init()
|
||||
{
|
||||
if (deviceManager_)
|
||||
deviceManager_->createHostDevices();
|
||||
}
|
||||
|
||||
/*! Can we modify Port with these params? Should modify cause port dirty? */
|
||||
@ -786,3 +791,8 @@ quint64 AbstractPort::neighborMacAddress(int streamId, int frameIndex)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const InterfaceInfo* AbstractPort::interfaceInfo() const
|
||||
{
|
||||
return interfaceInfo_;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
#include "../common/protocol.pb.h"
|
||||
|
||||
class DeviceManager;
|
||||
struct InterfaceInfo;
|
||||
class StreamBase;
|
||||
class PacketBuffer;
|
||||
class QIODevice;
|
||||
@ -77,6 +78,8 @@ public:
|
||||
bool canModify(const OstProto::Port &port, bool *dirty);
|
||||
bool modify(const OstProto::Port &port);
|
||||
|
||||
const InterfaceInfo* interfaceInfo() const;
|
||||
|
||||
virtual OstProto::LinkState linkState() { return linkState_; }
|
||||
virtual bool hasExclusiveControl() = 0;
|
||||
virtual bool setExclusiveControl(bool exclusive) = 0;
|
||||
@ -151,6 +154,7 @@ protected:
|
||||
StreamStats streamStats_;
|
||||
//! \todo Need lock for stats access/update
|
||||
|
||||
struct InterfaceInfo *interfaceInfo_;
|
||||
DeviceManager *deviceManager_;
|
||||
|
||||
private:
|
||||
@ -169,7 +173,6 @@ private:
|
||||
QList<StreamBase*> streamList_;
|
||||
|
||||
struct PortStats epochStats_;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -20,9 +20,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
#include "devicemanager.h"
|
||||
|
||||
#include "abstractport.h"
|
||||
#include "device.h"
|
||||
#include "emuldevice.h"
|
||||
#include "../common/emulation.h"
|
||||
#include "hostdevice.h"
|
||||
#include "interfaceinfo.h"
|
||||
#include "nulldevice.h"
|
||||
#include "packetbuffer.h"
|
||||
|
||||
#include "../common/emulproto.pb.h"
|
||||
@ -50,6 +52,40 @@ DeviceManager::DeviceManager(AbstractPort *parent)
|
||||
port_ = parent;
|
||||
}
|
||||
|
||||
void DeviceManager::createHostDevices(void)
|
||||
{
|
||||
const InterfaceInfo *ifInfo = port_->interfaceInfo();
|
||||
|
||||
if (!ifInfo)
|
||||
return;
|
||||
|
||||
NullDevice bcastDevice(this);
|
||||
bcastDevice.setMac(kBcastMac);
|
||||
|
||||
int count = ifInfo->ip4.size(); // FIXME: IPv6
|
||||
for (int i = 0; i < count; i++) {
|
||||
Device *device = HostDevice::create(port_->name(), this);
|
||||
device->setMac(ifInfo->mac);
|
||||
device->setIp4(ifInfo->ip4.at(i).address,
|
||||
ifInfo->ip4.at(i).prefixLength,
|
||||
ifInfo->ip4.at(i).gateway);
|
||||
|
||||
if (deviceList_.contains(device->key())) {
|
||||
qWarning("%s: error adding host device %s (EEXIST)",
|
||||
__FUNCTION__, qPrintable(device->config()));
|
||||
delete device;
|
||||
continue;
|
||||
}
|
||||
hostDeviceList_.append(device);
|
||||
deviceList_.insert(device->key(), device);
|
||||
sortedDeviceList_.insert(device->key(), device);
|
||||
|
||||
bcastList_.insert(bcastDevice.key(), device);
|
||||
qDebug("host(add): %s", qPrintable(device->config()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DeviceManager::~DeviceManager()
|
||||
{
|
||||
foreach(Device *dev, deviceList_)
|
||||
@ -57,6 +93,9 @@ DeviceManager::~DeviceManager()
|
||||
|
||||
foreach(OstProto::DeviceGroup *devGrp, deviceGroupList_)
|
||||
delete devGrp;
|
||||
|
||||
foreach(Device *dev, hostDeviceList_)
|
||||
delete dev;
|
||||
}
|
||||
|
||||
int DeviceManager::deviceGroupCount()
|
||||
@ -153,7 +192,7 @@ bool DeviceManager::modifyDeviceGroup(const OstProto::DeviceGroup *deviceGroup)
|
||||
|
||||
int DeviceManager::deviceCount()
|
||||
{
|
||||
return deviceList_.size();
|
||||
return deviceList_.size() + 1; // FIXME: why +1 for hostdev?
|
||||
}
|
||||
|
||||
void DeviceManager::getDeviceList(
|
||||
|
@ -39,6 +39,8 @@ public:
|
||||
DeviceManager(AbstractPort *parent = 0);
|
||||
~DeviceManager();
|
||||
|
||||
void createHostDevices();
|
||||
|
||||
int deviceGroupCount();
|
||||
const OstProto::DeviceGroup* deviceGroupAtIndex(int index);
|
||||
const OstProto::DeviceGroup* deviceGroup(uint deviceGroupId);
|
||||
@ -71,11 +73,14 @@ private:
|
||||
Operation oper);
|
||||
|
||||
AbstractPort *port_;
|
||||
|
||||
QHash<uint, OstProto::DeviceGroup*> deviceGroupList_;
|
||||
QHash<DeviceKey, Device*> deviceList_; // fast access to devices
|
||||
QMap<DeviceKey, Device*> sortedDeviceList_; // sorted access to devices
|
||||
QMultiHash<DeviceKey, Device*> bcastList_;
|
||||
QHash<quint16, uint> tpidList_; // Key: TPID, Value: RefCount
|
||||
|
||||
QList<Device*> hostDeviceList_; // TODO: use to add/remove from devicelist on useHostDevice flag toggle
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -6,10 +6,12 @@ linux*:system(grep -q IFLA_STATS64 /usr/include/linux/if_link.h): \
|
||||
DEFINES += HAVE_IFLA_STATS64
|
||||
INCLUDEPATH += "../rpc"
|
||||
win32 {
|
||||
# Support Windows Vista and above only
|
||||
DEFINES += WIN32_LEAN_AND_MEAN NTDDI_VERSION=0x06000000 _WIN32_WINNT=0x0600
|
||||
DEFINES += HAVE_REMOTE WPCAP
|
||||
CONFIG += console
|
||||
QMAKE_LFLAGS += -static
|
||||
LIBS += -lwpcap -lpacket
|
||||
LIBS += -lwpcap -lpacket -liphlpapi
|
||||
CONFIG(debug, debug|release) {
|
||||
LIBS += -L"../common/debug" -lostproto
|
||||
LIBS += -L"../rpc/debug" -lpbrpc
|
||||
@ -49,6 +51,7 @@ SOURCES += \
|
||||
pcaptxthread.cpp \
|
||||
bsdport.cpp \
|
||||
linuxport.cpp \
|
||||
winhostdevice.cpp \
|
||||
winpcapport.cpp
|
||||
SOURCES += myservice.cpp
|
||||
SOURCES += pcapextra.cpp
|
||||
|
45
server/hostdevice.h
Normal file
45
server/hostdevice.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright (C) 2018 Srivats P.
|
||||
|
||||
This file is part of "Ostinato"
|
||||
|
||||
This is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _HOST_DEVICE_H
|
||||
#define _HOST_DEVICE_H
|
||||
|
||||
#include "winhostdevice.h"
|
||||
|
||||
class DeviceManager;
|
||||
|
||||
/*!
|
||||
* HostDevice abstracts the various OS-specific host device classes
|
||||
*/
|
||||
class HostDevice
|
||||
{
|
||||
public:
|
||||
static Device* create(QString portName, DeviceManager *deviceManager)
|
||||
{
|
||||
#ifdef Q_OS_WIN32
|
||||
return new WindowsHostDevice(portName, deviceManager);
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
44
server/interfaceinfo.h
Normal file
44
server/interfaceinfo.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright (C) 2018 Srivats P.
|
||||
|
||||
This file is part of "Ostinato"
|
||||
|
||||
This is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _INTERFACE_INFO_H
|
||||
#define _INTERFACE_INFO_H
|
||||
|
||||
#include "../common/uint128.h"
|
||||
#include <QtGlobal>
|
||||
|
||||
template <typename IpType>
|
||||
struct IpConfig
|
||||
{
|
||||
IpType address;
|
||||
int prefixLength;
|
||||
IpType gateway;
|
||||
};
|
||||
|
||||
using Ip4Config = IpConfig<quint32>;
|
||||
using Ip6Config = IpConfig<UInt128>;
|
||||
|
||||
struct InterfaceInfo
|
||||
{
|
||||
quint64 mac;
|
||||
QList<Ip4Config> ip4;
|
||||
QList<Ip6Config> ip6;
|
||||
};
|
||||
|
||||
#endif
|
47
server/nulldevice.h
Normal file
47
server/nulldevice.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright (C) 2018 Srivats P.
|
||||
|
||||
This file is part of "Ostinato"
|
||||
|
||||
This is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _NULL_DEVICE_H
|
||||
#define _NULL_DEVICE_H
|
||||
|
||||
#include "device.h"
|
||||
|
||||
/*!
|
||||
* NullDevice does nothing.
|
||||
* Since the base Device class is abstract, NullDevice is a convenience
|
||||
* subclass that can be instantiated for DeviceKey related operations
|
||||
*/
|
||||
class NullDevice: public Device
|
||||
{
|
||||
public:
|
||||
using Device::Device;
|
||||
|
||||
virtual void receivePacket(PacketBuffer* /*pktBuf*/) {}
|
||||
virtual void clearNeighbors(Device::NeighborSet /*set*/) {}
|
||||
virtual void getNeighbors(OstEmul::DeviceNeighborList* /*neighbors*/) {}
|
||||
|
||||
protected:
|
||||
virtual quint64 arpLookup(quint32 /*ip*/) { return 0; }
|
||||
virtual quint64 ndpLookup(UInt128 /*ip*/) { return 0; }
|
||||
virtual void sendArpRequest(quint32 /*tgtIp*/) {}
|
||||
virtual void sendNeighborSolicit(UInt128 /*tgtIp*/) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -63,6 +63,8 @@ PcapPort::PcapPort(int id, const char *device)
|
||||
|
||||
void PcapPort::init()
|
||||
{
|
||||
AbstractPort::init();
|
||||
|
||||
if (!monitorTx_->isDirectional())
|
||||
transmitter_->useExternalStats(&stats_);
|
||||
|
||||
|
@ -32,7 +32,6 @@ PortManager *PortManager::instance_ = NULL;
|
||||
#if defined(Q_OS_WIN32)
|
||||
#include <QUuid>
|
||||
#include <ipHlpApi.h>
|
||||
#define NETIO_STATUS NTSTATUS
|
||||
// Define the function prototypes since they are not defined in ipHlpApi.h
|
||||
NETIO_STATUS WINAPI ConvertInterfaceGuidToLuid(
|
||||
const GUID *InterfaceGuid, PNET_LUID InterfaceLuid);
|
||||
@ -52,6 +51,10 @@ PortManager::PortManager()
|
||||
qDebug("PCAP Lib: %s", pcap_lib_version());
|
||||
qDebug("Retrieving the device list from the local machine\n");
|
||||
|
||||
#if defined(Q_OS_WIN32)
|
||||
WinPcapPort::populateAdapterList();
|
||||
#endif
|
||||
|
||||
txRateAccuracy = rateAccuracy();
|
||||
|
||||
pcap_if_t *deviceList = GetPortList();
|
||||
|
132
server/winhostdevice.cpp
Normal file
132
server/winhostdevice.cpp
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
Copyright (C) 2018 Srivats P.
|
||||
|
||||
This file is part of "Ostinato"
|
||||
|
||||
This is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#include "winhostdevice.h"
|
||||
|
||||
#include <QUuid>
|
||||
|
||||
WindowsHostDevice::WindowsHostDevice(QString portName,
|
||||
DeviceManager *deviceManager)
|
||||
: Device(deviceManager)
|
||||
{
|
||||
GUID guid = static_cast<GUID>(QUuid(portName.right(38)));
|
||||
ulong status = ConvertInterfaceGuidToLuid(&guid, &luid_);
|
||||
if (status != NO_ERROR) {
|
||||
qWarning("ConvertInterfaceGuidToLuid failed for %s with error %lx",
|
||||
qPrintable(portName), status);
|
||||
luid_.Value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void WindowsHostDevice::receivePacket(PacketBuffer* /*pktBuf*/)
|
||||
{
|
||||
// Do Nothing
|
||||
}
|
||||
|
||||
void WindowsHostDevice::clearNeighbors(Device::NeighborSet set)
|
||||
{
|
||||
// No need to do anything - see AbstractPort::resolveDeviceNeighbors()
|
||||
// on when this is used
|
||||
if (set == kUnresolvedNeighbors)
|
||||
return;
|
||||
|
||||
NET_IFINDEX ifIndex;
|
||||
ulong status = ConvertInterfaceLuidToIndex(&luid_, &ifIndex);
|
||||
if (status != NO_ERROR) {
|
||||
qWarning("luid2ifIdx convert failed with error %lx", status);
|
||||
return;
|
||||
}
|
||||
|
||||
status = FlushIpNetTable2(AF_UNSPEC, ifIndex);
|
||||
if(status != NO_ERROR)
|
||||
qWarning("Flush ARP/ND table failed with error %lx", status);
|
||||
}
|
||||
|
||||
void WindowsHostDevice::getNeighbors(OstEmul::DeviceNeighborList *neighbors)
|
||||
{
|
||||
PMIB_IPNET_TABLE2 nbrs = NULL;
|
||||
// TODO: optimization: use AF_UNSPEC only if hasIp4 and hasIp6
|
||||
ulong status = GetIpNetTable2(AF_UNSPEC, &nbrs) != NO_ERROR;
|
||||
if (status != NO_ERROR) {
|
||||
qWarning("Get ARP/ND table failed with error %lx", status);
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint i = 0; i < nbrs->NumEntries; i++) {
|
||||
if (nbrs->Table[i].InterfaceLuid.Value != luid_.Value)
|
||||
continue;
|
||||
|
||||
if (nbrs->Table[i].Address.si_family == AF_INET) {
|
||||
OstEmul::ArpEntry *arp = neighbors->add_arp();
|
||||
arp->set_ip4(qToBigEndian(quint32(
|
||||
nbrs->Table[i].Address.Ipv4.sin_addr.s_addr)));
|
||||
arp->set_mac(qFromBigEndian<quint64>(
|
||||
nbrs->Table[i].PhysicalAddress) >> 16);
|
||||
}
|
||||
// TODO: IPv6
|
||||
}
|
||||
|
||||
FreeMibTable(nbrs);
|
||||
}
|
||||
|
||||
quint64 WindowsHostDevice::arpLookup(quint32 ip)
|
||||
{
|
||||
if (!luid_.Value)
|
||||
return 0;
|
||||
|
||||
MIB_IPNET_ROW2 arpEntry;
|
||||
arpEntry.InterfaceLuid = luid_;
|
||||
arpEntry.Address.si_family = AF_INET;
|
||||
arpEntry.Address.Ipv4.sin_addr.s_addr = qToBigEndian(ip);
|
||||
|
||||
if ((GetIpNetEntry2(&arpEntry) == NO_ERROR)
|
||||
&& (arpEntry.PhysicalAddressLength == 6)) {
|
||||
return qFromBigEndian<quint64>(arpEntry.PhysicalAddress) >> 16;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
quint64 WindowsHostDevice::ndpLookup(UInt128 /*ip*/)
|
||||
{
|
||||
if (!luid_.Value)
|
||||
return 0;
|
||||
|
||||
return 0; // TODO
|
||||
}
|
||||
|
||||
void WindowsHostDevice::sendArpRequest(quint32 tgtIp)
|
||||
{
|
||||
SOCKADDR_INET src;
|
||||
src.Ipv4.sin_addr.s_addr = qToBigEndian(ip4_);
|
||||
|
||||
MIB_IPNET_ROW2 arpEntry;
|
||||
arpEntry.InterfaceLuid = luid_;
|
||||
arpEntry.Address.si_family = AF_INET;
|
||||
arpEntry.Address.Ipv4.sin_addr.s_addr = qToBigEndian(tgtIp);
|
||||
|
||||
ulong status = ResolveIpNetEntry2(&arpEntry, &src);
|
||||
if (ResolveIpNetEntry2(&arpEntry, &src) != NO_ERROR)
|
||||
qWarning("Resolve arp failed with error %lx", status);
|
||||
}
|
||||
|
||||
void WindowsHostDevice::sendNeighborSolicit(UInt128 /*tgtIp*/)
|
||||
{
|
||||
// TODO
|
||||
}
|
48
server/winhostdevice.h
Normal file
48
server/winhostdevice.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
Copyright (C) 2018 Srivats P.
|
||||
|
||||
This file is part of "Ostinato"
|
||||
|
||||
This is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _WINDOWS_HOST_DEVICE_H
|
||||
#define _WINDOWS_HOST_DEVICE_H
|
||||
|
||||
#include "device.h"
|
||||
|
||||
#include <Ws2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
|
||||
class WindowsHostDevice: public Device
|
||||
{
|
||||
public:
|
||||
WindowsHostDevice(QString portName, DeviceManager *deviceManager);
|
||||
virtual ~WindowsHostDevice() {};
|
||||
|
||||
virtual void receivePacket(PacketBuffer *pktBuf);
|
||||
virtual void clearNeighbors(Device::NeighborSet set);
|
||||
virtual void getNeighbors(OstEmul::DeviceNeighborList *neighbors);
|
||||
|
||||
protected:
|
||||
virtual quint64 arpLookup(quint32 ip);
|
||||
virtual quint64 ndpLookup(UInt128 ip);
|
||||
virtual void sendArpRequest(quint32 tgtIp);
|
||||
virtual void sendNeighborSolicit(UInt128 tgtIp);
|
||||
|
||||
private:
|
||||
NET_LUID luid_;
|
||||
};
|
||||
|
||||
#endif
|
@ -19,16 +19,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
#include "winpcapport.h"
|
||||
|
||||
#include "interfaceinfo.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QProcess>
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
|
||||
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)
|
||||
{
|
||||
populateInterfaceInfo();
|
||||
|
||||
monitorRx_->stop();
|
||||
monitorTx_->stop();
|
||||
monitorRx_->wait();
|
||||
@ -225,4 +230,86 @@ void WinPcapPort::PortMonitor::run()
|
||||
}
|
||||
}
|
||||
|
||||
void WinPcapPort::populateInterfaceInfo()
|
||||
{
|
||||
if (!adapterList_) {
|
||||
qWarning("Adapter List not available");
|
||||
return;
|
||||
}
|
||||
|
||||
PIP_ADAPTER_ADDRESSES adapter = adapterList_;
|
||||
while (!QString(name()).endsWith(QString(adapter->AdapterName)))
|
||||
adapter = adapter->Next;
|
||||
|
||||
if (!adapter) {
|
||||
qWarning("Adapter info not found for %s", name());
|
||||
return;
|
||||
}
|
||||
|
||||
interfaceInfo_ = new InterfaceInfo;
|
||||
if (adapter->PhysicalAddressLength == 6) {
|
||||
interfaceInfo_->mac = qFromBigEndian<quint64>(
|
||||
adapter->PhysicalAddress) >> 16;
|
||||
}
|
||||
else
|
||||
interfaceInfo_->mac = 0;
|
||||
qDebug("mac = %llx", interfaceInfo_->mac);
|
||||
|
||||
#define SOCKET_ADDRESS_FAMILY(x) \
|
||||
(x.lpSockaddr->sa_family)
|
||||
|
||||
#define SOCKET_ADDRESS_IP4(x) \
|
||||
(qFromBigEndian<quint32>(((sockaddr_in*)(x.lpSockaddr))->sin_addr.S_un.S_addr));
|
||||
|
||||
// We may have multiple gateways - use the first for each family
|
||||
quint32 ip4Gateway = 0;
|
||||
PIP_ADAPTER_GATEWAY_ADDRESS gateway = adapter->FirstGatewayAddress;
|
||||
while (gateway) {
|
||||
if (SOCKET_ADDRESS_FAMILY(gateway->Address) == AF_INET) {
|
||||
ip4Gateway = SOCKET_ADDRESS_IP4(gateway->Address);
|
||||
break;
|
||||
}
|
||||
gateway = gateway->Next;
|
||||
}
|
||||
// TODO: IPv6 Gateway
|
||||
|
||||
PIP_ADAPTER_UNICAST_ADDRESS ucast = adapter->FirstUnicastAddress;
|
||||
while (ucast) {
|
||||
if (SOCKET_ADDRESS_FAMILY(ucast->Address) == AF_INET) {
|
||||
Ip4Config ip;
|
||||
ip.address = SOCKET_ADDRESS_IP4(ucast->Address);
|
||||
ip.prefixLength = ucast->OnLinkPrefixLength;
|
||||
ip.gateway = ip4Gateway;
|
||||
interfaceInfo_->ip4.append(ip);
|
||||
}
|
||||
// TODO: IPv6
|
||||
ucast = ucast->Next;
|
||||
}
|
||||
#undef SOCKET_ADDRESS_FAMILY
|
||||
#undef SOCKET_ADDRESS_IP4
|
||||
}
|
||||
|
||||
void WinPcapPort::populateAdapterList()
|
||||
{
|
||||
DWORD ret;
|
||||
ULONG bufLen = 15*1024; // MS recommended starting size
|
||||
|
||||
while (1) {
|
||||
adapterList_ = (IP_ADAPTER_ADDRESSES *) malloc(bufLen);
|
||||
ret = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_GATEWAYS, 0,
|
||||
adapterList_, &bufLen);
|
||||
if (ret == ERROR_BUFFER_OVERFLOW) {
|
||||
free(adapterList_);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret != NO_ERROR) {
|
||||
free(adapterList_);
|
||||
adapterList_ = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -28,6 +28,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
#include <packet32.h>
|
||||
|
||||
#include <iphlpapi.h>
|
||||
|
||||
class WinPcapPort : public PcapPort
|
||||
{
|
||||
public:
|
||||
@ -38,6 +40,8 @@ public:
|
||||
virtual bool hasExclusiveControl();
|
||||
virtual bool setExclusiveControl(bool exclusive);
|
||||
|
||||
static void populateAdapterList();
|
||||
|
||||
protected:
|
||||
class PortMonitor: public PcapPort::PortMonitor
|
||||
{
|
||||
@ -47,8 +51,12 @@ protected:
|
||||
void run();
|
||||
};
|
||||
private:
|
||||
void populateInterfaceInfo();
|
||||
|
||||
LPADAPTER adapter_;
|
||||
PPACKET_OID_DATA linkStateOid_ ;
|
||||
|
||||
static PIP_ADAPTER_ADDRESSES adapterList_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user