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/abstractprotocol.h"
|
||||||
#include "../common/streambase.h"
|
#include "../common/streambase.h"
|
||||||
#include "devicemanager.h"
|
#include "devicemanager.h"
|
||||||
|
#include "interfaceinfo.h"
|
||||||
#include "packetbuffer.h"
|
#include "packetbuffer.h"
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
@ -47,6 +48,7 @@ AbstractPort::AbstractPort(int id, const char *device)
|
|||||||
minPacketSetSize_ = 1;
|
minPacketSetSize_ = 1;
|
||||||
|
|
||||||
deviceManager_ = new DeviceManager(this);
|
deviceManager_ = new DeviceManager(this);
|
||||||
|
interfaceInfo_ = NULL;
|
||||||
|
|
||||||
maxStatsValue_ = ULLONG_MAX; // assume 64-bit stats
|
maxStatsValue_ = ULLONG_MAX; // assume 64-bit stats
|
||||||
memset((void*) &stats_, 0, sizeof(stats_));
|
memset((void*) &stats_, 0, sizeof(stats_));
|
||||||
@ -56,10 +58,13 @@ AbstractPort::AbstractPort(int id, const char *device)
|
|||||||
AbstractPort::~AbstractPort()
|
AbstractPort::~AbstractPort()
|
||||||
{
|
{
|
||||||
delete deviceManager_;
|
delete deviceManager_;
|
||||||
|
delete interfaceInfo_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractPort::init()
|
void AbstractPort::init()
|
||||||
{
|
{
|
||||||
|
if (deviceManager_)
|
||||||
|
deviceManager_->createHostDevices();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Can we modify Port with these params? Should modify cause port dirty? */
|
/*! 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;
|
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"
|
#include "../common/protocol.pb.h"
|
||||||
|
|
||||||
class DeviceManager;
|
class DeviceManager;
|
||||||
|
struct InterfaceInfo;
|
||||||
class StreamBase;
|
class StreamBase;
|
||||||
class PacketBuffer;
|
class PacketBuffer;
|
||||||
class QIODevice;
|
class QIODevice;
|
||||||
@ -77,6 +78,8 @@ public:
|
|||||||
bool canModify(const OstProto::Port &port, bool *dirty);
|
bool canModify(const OstProto::Port &port, bool *dirty);
|
||||||
bool modify(const OstProto::Port &port);
|
bool modify(const OstProto::Port &port);
|
||||||
|
|
||||||
|
const InterfaceInfo* interfaceInfo() const;
|
||||||
|
|
||||||
virtual OstProto::LinkState linkState() { return linkState_; }
|
virtual OstProto::LinkState linkState() { return linkState_; }
|
||||||
virtual bool hasExclusiveControl() = 0;
|
virtual bool hasExclusiveControl() = 0;
|
||||||
virtual bool setExclusiveControl(bool exclusive) = 0;
|
virtual bool setExclusiveControl(bool exclusive) = 0;
|
||||||
@ -151,6 +154,7 @@ protected:
|
|||||||
StreamStats streamStats_;
|
StreamStats streamStats_;
|
||||||
//! \todo Need lock for stats access/update
|
//! \todo Need lock for stats access/update
|
||||||
|
|
||||||
|
struct InterfaceInfo *interfaceInfo_;
|
||||||
DeviceManager *deviceManager_;
|
DeviceManager *deviceManager_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -169,7 +173,6 @@ private:
|
|||||||
QList<StreamBase*> streamList_;
|
QList<StreamBase*> streamList_;
|
||||||
|
|
||||||
struct PortStats epochStats_;
|
struct PortStats epochStats_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,9 +20,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include "devicemanager.h"
|
#include "devicemanager.h"
|
||||||
|
|
||||||
#include "abstractport.h"
|
#include "abstractport.h"
|
||||||
#include "device.h"
|
|
||||||
#include "emuldevice.h"
|
#include "emuldevice.h"
|
||||||
#include "../common/emulation.h"
|
#include "../common/emulation.h"
|
||||||
|
#include "hostdevice.h"
|
||||||
|
#include "interfaceinfo.h"
|
||||||
|
#include "nulldevice.h"
|
||||||
#include "packetbuffer.h"
|
#include "packetbuffer.h"
|
||||||
|
|
||||||
#include "../common/emulproto.pb.h"
|
#include "../common/emulproto.pb.h"
|
||||||
@ -50,6 +52,40 @@ DeviceManager::DeviceManager(AbstractPort *parent)
|
|||||||
port_ = 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()
|
DeviceManager::~DeviceManager()
|
||||||
{
|
{
|
||||||
foreach(Device *dev, deviceList_)
|
foreach(Device *dev, deviceList_)
|
||||||
@ -57,6 +93,9 @@ DeviceManager::~DeviceManager()
|
|||||||
|
|
||||||
foreach(OstProto::DeviceGroup *devGrp, deviceGroupList_)
|
foreach(OstProto::DeviceGroup *devGrp, deviceGroupList_)
|
||||||
delete devGrp;
|
delete devGrp;
|
||||||
|
|
||||||
|
foreach(Device *dev, hostDeviceList_)
|
||||||
|
delete dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DeviceManager::deviceGroupCount()
|
int DeviceManager::deviceGroupCount()
|
||||||
@ -153,7 +192,7 @@ bool DeviceManager::modifyDeviceGroup(const OstProto::DeviceGroup *deviceGroup)
|
|||||||
|
|
||||||
int DeviceManager::deviceCount()
|
int DeviceManager::deviceCount()
|
||||||
{
|
{
|
||||||
return deviceList_.size();
|
return deviceList_.size() + 1; // FIXME: why +1 for hostdev?
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceManager::getDeviceList(
|
void DeviceManager::getDeviceList(
|
||||||
|
@ -39,6 +39,8 @@ public:
|
|||||||
DeviceManager(AbstractPort *parent = 0);
|
DeviceManager(AbstractPort *parent = 0);
|
||||||
~DeviceManager();
|
~DeviceManager();
|
||||||
|
|
||||||
|
void createHostDevices();
|
||||||
|
|
||||||
int deviceGroupCount();
|
int deviceGroupCount();
|
||||||
const OstProto::DeviceGroup* deviceGroupAtIndex(int index);
|
const OstProto::DeviceGroup* deviceGroupAtIndex(int index);
|
||||||
const OstProto::DeviceGroup* deviceGroup(uint deviceGroupId);
|
const OstProto::DeviceGroup* deviceGroup(uint deviceGroupId);
|
||||||
@ -71,11 +73,14 @@ private:
|
|||||||
Operation oper);
|
Operation oper);
|
||||||
|
|
||||||
AbstractPort *port_;
|
AbstractPort *port_;
|
||||||
|
|
||||||
QHash<uint, OstProto::DeviceGroup*> deviceGroupList_;
|
QHash<uint, OstProto::DeviceGroup*> deviceGroupList_;
|
||||||
QHash<DeviceKey, Device*> deviceList_; // fast access to devices
|
QHash<DeviceKey, Device*> deviceList_; // fast access to devices
|
||||||
QMap<DeviceKey, Device*> sortedDeviceList_; // sorted access to devices
|
QMap<DeviceKey, Device*> sortedDeviceList_; // sorted access to devices
|
||||||
QMultiHash<DeviceKey, Device*> bcastList_;
|
QMultiHash<DeviceKey, Device*> bcastList_;
|
||||||
QHash<quint16, uint> tpidList_; // Key: TPID, Value: RefCount
|
QHash<quint16, uint> tpidList_; // Key: TPID, Value: RefCount
|
||||||
|
|
||||||
|
QList<Device*> hostDeviceList_; // TODO: use to add/remove from devicelist on useHostDevice flag toggle
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,10 +6,12 @@ linux*:system(grep -q IFLA_STATS64 /usr/include/linux/if_link.h): \
|
|||||||
DEFINES += HAVE_IFLA_STATS64
|
DEFINES += HAVE_IFLA_STATS64
|
||||||
INCLUDEPATH += "../rpc"
|
INCLUDEPATH += "../rpc"
|
||||||
win32 {
|
win32 {
|
||||||
|
# Support Windows Vista and above only
|
||||||
|
DEFINES += WIN32_LEAN_AND_MEAN NTDDI_VERSION=0x06000000 _WIN32_WINNT=0x0600
|
||||||
DEFINES += HAVE_REMOTE WPCAP
|
DEFINES += HAVE_REMOTE WPCAP
|
||||||
CONFIG += console
|
CONFIG += console
|
||||||
QMAKE_LFLAGS += -static
|
QMAKE_LFLAGS += -static
|
||||||
LIBS += -lwpcap -lpacket
|
LIBS += -lwpcap -lpacket -liphlpapi
|
||||||
CONFIG(debug, debug|release) {
|
CONFIG(debug, debug|release) {
|
||||||
LIBS += -L"../common/debug" -lostproto
|
LIBS += -L"../common/debug" -lostproto
|
||||||
LIBS += -L"../rpc/debug" -lpbrpc
|
LIBS += -L"../rpc/debug" -lpbrpc
|
||||||
@ -49,6 +51,7 @@ SOURCES += \
|
|||||||
pcaptxthread.cpp \
|
pcaptxthread.cpp \
|
||||||
bsdport.cpp \
|
bsdport.cpp \
|
||||||
linuxport.cpp \
|
linuxport.cpp \
|
||||||
|
winhostdevice.cpp \
|
||||||
winpcapport.cpp
|
winpcapport.cpp
|
||||||
SOURCES += myservice.cpp
|
SOURCES += myservice.cpp
|
||||||
SOURCES += pcapextra.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()
|
void PcapPort::init()
|
||||||
{
|
{
|
||||||
|
AbstractPort::init();
|
||||||
|
|
||||||
if (!monitorTx_->isDirectional())
|
if (!monitorTx_->isDirectional())
|
||||||
transmitter_->useExternalStats(&stats_);
|
transmitter_->useExternalStats(&stats_);
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@ PortManager *PortManager::instance_ = NULL;
|
|||||||
#if defined(Q_OS_WIN32)
|
#if defined(Q_OS_WIN32)
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
#include <ipHlpApi.h>
|
#include <ipHlpApi.h>
|
||||||
#define NETIO_STATUS NTSTATUS
|
|
||||||
// Define the function prototypes since they are not defined in ipHlpApi.h
|
// Define the function prototypes since they are not defined in ipHlpApi.h
|
||||||
NETIO_STATUS WINAPI ConvertInterfaceGuidToLuid(
|
NETIO_STATUS WINAPI ConvertInterfaceGuidToLuid(
|
||||||
const GUID *InterfaceGuid, PNET_LUID InterfaceLuid);
|
const GUID *InterfaceGuid, PNET_LUID InterfaceLuid);
|
||||||
@ -52,6 +51,10 @@ PortManager::PortManager()
|
|||||||
qDebug("PCAP Lib: %s", pcap_lib_version());
|
qDebug("PCAP Lib: %s", pcap_lib_version());
|
||||||
qDebug("Retrieving the device list from the local machine\n");
|
qDebug("Retrieving the device list from the local machine\n");
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN32)
|
||||||
|
WinPcapPort::populateAdapterList();
|
||||||
|
#endif
|
||||||
|
|
||||||
txRateAccuracy = rateAccuracy();
|
txRateAccuracy = rateAccuracy();
|
||||||
|
|
||||||
pcap_if_t *deviceList = GetPortList();
|
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 "winpcapport.h"
|
||||||
|
|
||||||
|
#include "interfaceinfo.h"
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
|
||||||
#ifdef Q_OS_WIN32
|
#ifdef Q_OS_WIN32
|
||||||
|
|
||||||
|
PIP_ADAPTER_ADDRESSES WinPcapPort::adapterList_ = NULL;
|
||||||
const uint OID_GEN_MEDIA_CONNECT_STATUS = 0x00010114;
|
const uint OID_GEN_MEDIA_CONNECT_STATUS = 0x00010114;
|
||||||
|
|
||||||
WinPcapPort::WinPcapPort(int id, const char *device, const char *description)
|
WinPcapPort::WinPcapPort(int id, const char *device, const char *description)
|
||||||
: PcapPort(id, device)
|
: PcapPort(id, device)
|
||||||
{
|
{
|
||||||
|
populateInterfaceInfo();
|
||||||
|
|
||||||
monitorRx_->stop();
|
monitorRx_->stop();
|
||||||
monitorTx_->stop();
|
monitorTx_->stop();
|
||||||
monitorRx_->wait();
|
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
|
#endif
|
||||||
|
@ -28,6 +28,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include <packet32.h>
|
#include <packet32.h>
|
||||||
|
|
||||||
|
#include <iphlpapi.h>
|
||||||
|
|
||||||
class WinPcapPort : public PcapPort
|
class WinPcapPort : public PcapPort
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -38,6 +40,8 @@ public:
|
|||||||
virtual bool hasExclusiveControl();
|
virtual bool hasExclusiveControl();
|
||||||
virtual bool setExclusiveControl(bool exclusive);
|
virtual bool setExclusiveControl(bool exclusive);
|
||||||
|
|
||||||
|
static void populateAdapterList();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
class PortMonitor: public PcapPort::PortMonitor
|
class PortMonitor: public PcapPort::PortMonitor
|
||||||
{
|
{
|
||||||
@ -47,8 +51,12 @@ protected:
|
|||||||
void run();
|
void run();
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
|
void populateInterfaceInfo();
|
||||||
|
|
||||||
LPADAPTER adapter_;
|
LPADAPTER adapter_;
|
||||||
PPACKET_OID_DATA linkStateOid_ ;
|
PPACKET_OID_DATA linkStateOid_ ;
|
||||||
|
|
||||||
|
static PIP_ADAPTER_ADDRESSES adapterList_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user