HostDev: Add IPv6 support for Windows hosts
This commit is contained in:
parent
e2a11bfa4e
commit
f58c4e309c
@ -62,8 +62,13 @@ void DeviceManager::createHostDevices(void)
|
|||||||
NullDevice bcastDevice(this);
|
NullDevice bcastDevice(this);
|
||||||
bcastDevice.setMac(kBcastMac);
|
bcastDevice.setMac(kBcastMac);
|
||||||
|
|
||||||
int count = ifInfo->ip4.size(); // FIXME: IPv6
|
int count = ifInfo->ip4.size();
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
|
// FIXME: Since we can't support multiple IPs with same mac,
|
||||||
|
// skip link-local IP - unless it is the only one
|
||||||
|
if (((ifInfo->ip4.at(i).address & 0xffff0000) == 0xa9fe0000)
|
||||||
|
&& (count > 1))
|
||||||
|
continue;
|
||||||
Device *device = HostDevice::create(port_->name(), this);
|
Device *device = HostDevice::create(port_->name(), this);
|
||||||
device->setMac(ifInfo->mac);
|
device->setMac(ifInfo->mac);
|
||||||
device->setIp4(ifInfo->ip4.at(i).address,
|
device->setIp4(ifInfo->ip4.at(i).address,
|
||||||
@ -82,7 +87,41 @@ void DeviceManager::createHostDevices(void)
|
|||||||
|
|
||||||
bcastList_.insert(bcastDevice.key(), device);
|
bcastList_.insert(bcastDevice.key(), device);
|
||||||
qDebug("host(add): %s", qPrintable(device->config()));
|
qDebug("host(add): %s", qPrintable(device->config()));
|
||||||
break;
|
|
||||||
|
break; // FIXME: support multiple IPs with same mac
|
||||||
|
}
|
||||||
|
|
||||||
|
count = ifInfo->ip6.size();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
// FIXME: Since we can't support multiple IPs with same mac,
|
||||||
|
// skip link-local IP - unless it is the only one
|
||||||
|
if (((ifInfo->ip6.at(i).address.hi64() >> 48) == 0xfe80)
|
||||||
|
&& (count > 1))
|
||||||
|
continue;
|
||||||
|
NullDevice dk(this);
|
||||||
|
dk.setMac(ifInfo->mac);
|
||||||
|
Device *device = deviceList_.value(dk.key());
|
||||||
|
if (!device) {
|
||||||
|
device = HostDevice::create(port_->name(), this);
|
||||||
|
device->setMac(ifInfo->mac);
|
||||||
|
device->setIp6(ifInfo->ip6.at(i).address,
|
||||||
|
ifInfo->ip6.at(i).prefixLength,
|
||||||
|
ifInfo->ip6.at(i).gateway);
|
||||||
|
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()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
device->setIp6(ifInfo->ip6.at(i).address,
|
||||||
|
ifInfo->ip6.at(i).prefixLength,
|
||||||
|
ifInfo->ip6.at(i).gateway);
|
||||||
|
qDebug("host(update): %s", qPrintable(device->config()));
|
||||||
|
}
|
||||||
|
|
||||||
|
break; // FIXME: support multiple IPs with same mac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,12 +92,20 @@ void WindowsHostDevice::getNeighbors(OstEmul::DeviceNeighborList *neighbors)
|
|||||||
|
|
||||||
if (nbrs->Table[i].Address.si_family == AF_INET) {
|
if (nbrs->Table[i].Address.si_family == AF_INET) {
|
||||||
OstEmul::ArpEntry *arp = neighbors->add_arp();
|
OstEmul::ArpEntry *arp = neighbors->add_arp();
|
||||||
arp->set_ip4(qToBigEndian(quint32(
|
arp->set_ip4(qFromBigEndian<quint32>(
|
||||||
nbrs->Table[i].Address.Ipv4.sin_addr.s_addr)));
|
nbrs->Table[i].Address.Ipv4.sin_addr.s_addr));
|
||||||
arp->set_mac(qFromBigEndian<quint64>(
|
arp->set_mac(qFromBigEndian<quint64>(
|
||||||
nbrs->Table[i].PhysicalAddress) >> 16);
|
nbrs->Table[i].PhysicalAddress) >> 16);
|
||||||
}
|
}
|
||||||
// TODO: IPv6
|
else if (nbrs->Table[i].Address.si_family == AF_INET6) {
|
||||||
|
OstEmul::NdpEntry *ndp = neighbors->add_ndp();
|
||||||
|
ndp->mutable_ip6()->set_hi(qFromBigEndian<quint64>(
|
||||||
|
nbrs->Table[i].Address.Ipv6.sin6_addr.u.Byte));
|
||||||
|
ndp->mutable_ip6()->set_lo(qFromBigEndian<quint64>(
|
||||||
|
nbrs->Table[i].Address.Ipv6.sin6_addr.u.Byte+8));
|
||||||
|
ndp->set_mac(qFromBigEndian<quint64>(
|
||||||
|
nbrs->Table[i].PhysicalAddress) >> 16);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeMibTable(nbrs);
|
FreeMibTable(nbrs);
|
||||||
@ -121,12 +129,22 @@ quint64 WindowsHostDevice::arpLookup(quint32 ip)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
quint64 WindowsHostDevice::ndpLookup(UInt128 /*ip*/)
|
quint64 WindowsHostDevice::ndpLookup(UInt128 ip)
|
||||||
{
|
{
|
||||||
if (!luid_.Value)
|
if (!luid_.Value)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return 0; // TODO
|
MIB_IPNET_ROW2 ndpEntry;
|
||||||
|
ndpEntry.InterfaceLuid = luid_;
|
||||||
|
ndpEntry.Address.si_family = AF_INET6;
|
||||||
|
memcpy(&ndpEntry.Address.Ipv6.sin6_addr.u, ip.toArray(), 16);
|
||||||
|
|
||||||
|
if ((GetIpNetEntry2(&ndpEntry) == NO_ERROR)
|
||||||
|
&& (ndpEntry.PhysicalAddressLength == 6)) {
|
||||||
|
return qFromBigEndian<quint64>(ndpEntry.PhysicalAddress) >> 16;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowsHostDevice::sendArpRequest(quint32 tgtIp)
|
void WindowsHostDevice::sendArpRequest(quint32 tgtIp)
|
||||||
@ -145,9 +163,20 @@ void WindowsHostDevice::sendArpRequest(quint32 tgtIp)
|
|||||||
luid_.Value, errMsg(status));
|
luid_.Value, errMsg(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowsHostDevice::sendNeighborSolicit(UInt128 /*tgtIp*/)
|
void WindowsHostDevice::sendNeighborSolicit(UInt128 tgtIp)
|
||||||
{
|
{
|
||||||
// TODO
|
SOCKADDR_INET src;
|
||||||
|
memcpy(&src.Ipv6.sin6_addr.u, ip6_.toArray(), 16);
|
||||||
|
|
||||||
|
MIB_IPNET_ROW2 ndpEntry;
|
||||||
|
ndpEntry.InterfaceLuid = luid_;
|
||||||
|
ndpEntry.Address.si_family = AF_INET6;
|
||||||
|
memcpy(&ndpEntry.Address.Ipv6.sin6_addr.u, tgtIp.toArray(), 16);
|
||||||
|
|
||||||
|
ulong status = ResolveIpNetEntry2(&ndpEntry, &src);
|
||||||
|
if (ResolveIpNetEntry2(&ndpEntry, &src) != NO_ERROR)
|
||||||
|
qWarning("Resolve ndp failed for LUID %llx: %s",
|
||||||
|
luid_.Value, errMsg(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,6 +26,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#ifdef Q_OS_WIN32
|
#ifdef Q_OS_WIN32
|
||||||
|
|
||||||
|
#include <ws2ipdef.h>
|
||||||
|
|
||||||
PIP_ADAPTER_ADDRESSES WinPcapPort::adapterList_ = NULL;
|
PIP_ADAPTER_ADDRESSES WinPcapPort::adapterList_ = NULL;
|
||||||
const uint OID_GEN_MEDIA_CONNECT_STATUS = 0x00010114;
|
const uint OID_GEN_MEDIA_CONNECT_STATUS = 0x00010114;
|
||||||
|
|
||||||
@ -261,6 +263,9 @@ void WinPcapPort::populateInterfaceInfo()
|
|||||||
#define SOCKET_ADDRESS_IP4(x) \
|
#define SOCKET_ADDRESS_IP4(x) \
|
||||||
(qFromBigEndian<quint32>(((sockaddr_in*)(x.lpSockaddr))->sin_addr.S_un.S_addr));
|
(qFromBigEndian<quint32>(((sockaddr_in*)(x.lpSockaddr))->sin_addr.S_un.S_addr));
|
||||||
|
|
||||||
|
#define SOCKET_ADDRESS_IP6(x) \
|
||||||
|
(UInt128(((PSOCKADDR_IN6)(x.lpSockaddr))->sin6_addr.u.Byte));
|
||||||
|
|
||||||
// We may have multiple gateways - use the first for each family
|
// We may have multiple gateways - use the first for each family
|
||||||
quint32 ip4Gateway = 0;
|
quint32 ip4Gateway = 0;
|
||||||
PIP_ADAPTER_GATEWAY_ADDRESS gateway = adapter->FirstGatewayAddress;
|
PIP_ADAPTER_GATEWAY_ADDRESS gateway = adapter->FirstGatewayAddress;
|
||||||
@ -271,7 +276,15 @@ void WinPcapPort::populateInterfaceInfo()
|
|||||||
}
|
}
|
||||||
gateway = gateway->Next;
|
gateway = gateway->Next;
|
||||||
}
|
}
|
||||||
// TODO: IPv6 Gateway
|
UInt128 ip6Gateway(0, 0);
|
||||||
|
gateway = adapter->FirstGatewayAddress;
|
||||||
|
while (gateway) {
|
||||||
|
if (SOCKET_ADDRESS_FAMILY(gateway->Address) == AF_INET6) {
|
||||||
|
ip6Gateway = SOCKET_ADDRESS_IP6(gateway->Address);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gateway = gateway->Next;
|
||||||
|
}
|
||||||
|
|
||||||
PIP_ADAPTER_UNICAST_ADDRESS ucast = adapter->FirstUnicastAddress;
|
PIP_ADAPTER_UNICAST_ADDRESS ucast = adapter->FirstUnicastAddress;
|
||||||
while (ucast) {
|
while (ucast) {
|
||||||
@ -282,11 +295,18 @@ void WinPcapPort::populateInterfaceInfo()
|
|||||||
ip.gateway = ip4Gateway;
|
ip.gateway = ip4Gateway;
|
||||||
interfaceInfo_->ip4.append(ip);
|
interfaceInfo_->ip4.append(ip);
|
||||||
}
|
}
|
||||||
// TODO: IPv6
|
else if (SOCKET_ADDRESS_FAMILY(ucast->Address) == AF_INET6) {
|
||||||
|
Ip6Config ip;
|
||||||
|
ip.address = SOCKET_ADDRESS_IP6(ucast->Address);
|
||||||
|
ip.prefixLength = ucast->OnLinkPrefixLength;
|
||||||
|
ip.gateway = ip6Gateway;
|
||||||
|
interfaceInfo_->ip6.append(ip);
|
||||||
|
}
|
||||||
ucast = ucast->Next;
|
ucast = ucast->Next;
|
||||||
}
|
}
|
||||||
#undef SOCKET_ADDRESS_FAMILY
|
#undef SOCKET_ADDRESS_FAMILY
|
||||||
#undef SOCKET_ADDRESS_IP4
|
#undef SOCKET_ADDRESS_IP4
|
||||||
|
#undef SOCKET_ADDRESS_IP6
|
||||||
}
|
}
|
||||||
|
|
||||||
void WinPcapPort::populateAdapterList()
|
void WinPcapPort::populateAdapterList()
|
||||||
|
Loading…
Reference in New Issue
Block a user