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);
|
||||
bcastDevice.setMac(kBcastMac);
|
||||
|
||||
int count = ifInfo->ip4.size(); // FIXME: IPv6
|
||||
int count = ifInfo->ip4.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->ip4.at(i).address & 0xffff0000) == 0xa9fe0000)
|
||||
&& (count > 1))
|
||||
continue;
|
||||
Device *device = HostDevice::create(port_->name(), this);
|
||||
device->setMac(ifInfo->mac);
|
||||
device->setIp4(ifInfo->ip4.at(i).address,
|
||||
@ -82,7 +87,41 @@ void DeviceManager::createHostDevices(void)
|
||||
|
||||
bcastList_.insert(bcastDevice.key(), device);
|
||||
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) {
|
||||
OstEmul::ArpEntry *arp = neighbors->add_arp();
|
||||
arp->set_ip4(qToBigEndian(quint32(
|
||||
nbrs->Table[i].Address.Ipv4.sin_addr.s_addr)));
|
||||
arp->set_ip4(qFromBigEndian<quint32>(
|
||||
nbrs->Table[i].Address.Ipv4.sin_addr.s_addr));
|
||||
arp->set_mac(qFromBigEndian<quint64>(
|
||||
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);
|
||||
@ -121,12 +129,22 @@ quint64 WindowsHostDevice::arpLookup(quint32 ip)
|
||||
return 0;
|
||||
}
|
||||
|
||||
quint64 WindowsHostDevice::ndpLookup(UInt128 /*ip*/)
|
||||
quint64 WindowsHostDevice::ndpLookup(UInt128 ip)
|
||||
{
|
||||
if (!luid_.Value)
|
||||
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)
|
||||
@ -145,9 +163,20 @@ void WindowsHostDevice::sendArpRequest(quint32 tgtIp)
|
||||
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
|
||||
|
@ -26,6 +26,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
|
||||
#include <ws2ipdef.h>
|
||||
|
||||
PIP_ADAPTER_ADDRESSES WinPcapPort::adapterList_ = NULL;
|
||||
const uint OID_GEN_MEDIA_CONNECT_STATUS = 0x00010114;
|
||||
|
||||
@ -261,6 +263,9 @@ void WinPcapPort::populateInterfaceInfo()
|
||||
#define SOCKET_ADDRESS_IP4(x) \
|
||||
(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
|
||||
quint32 ip4Gateway = 0;
|
||||
PIP_ADAPTER_GATEWAY_ADDRESS gateway = adapter->FirstGatewayAddress;
|
||||
@ -271,7 +276,15 @@ void WinPcapPort::populateInterfaceInfo()
|
||||
}
|
||||
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;
|
||||
while (ucast) {
|
||||
@ -282,11 +295,18 @@ void WinPcapPort::populateInterfaceInfo()
|
||||
ip.gateway = ip4Gateway;
|
||||
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;
|
||||
}
|
||||
#undef SOCKET_ADDRESS_FAMILY
|
||||
#undef SOCKET_ADDRESS_IP4
|
||||
#undef SOCKET_ADDRESS_IP6
|
||||
}
|
||||
|
||||
void WinPcapPort::populateAdapterList()
|
||||
|
Loading…
Reference in New Issue
Block a user