1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2024-11-26 19:39:53 +03:00

Merge pull request #1576 from domosekai/ipv6

Fix IPv6 ND for Windows 11 PPP clients
This commit is contained in:
Yihong Wu 2022-04-27 20:37:25 +08:00 committed by GitHub
commit c8dca265b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1503,6 +1503,7 @@ void IPCProcessL3EventsEx(IPC *ipc, UINT64 now)
if (p->IPv6HeaderPacketInfo.Protocol == IP_PROTO_ICMPV6) if (p->IPv6HeaderPacketInfo.Protocol == IP_PROTO_ICMPV6)
{ {
IP icmpHeaderAddr; IP icmpHeaderAddr;
UINT header_size = 0;
// We need to parse the Router Advertisement and Neighbor Advertisement messages // We need to parse the Router Advertisement and Neighbor Advertisement messages
// to build the Neighbor Discovery Table (aka ARP table for IPv6) // to build the Neighbor Discovery Table (aka ARP table for IPv6)
switch (p->ICMPv6HeaderPacketInfo.Type) switch (p->ICMPv6HeaderPacketInfo.Type)
@ -1512,6 +1513,8 @@ void IPCProcessL3EventsEx(IPC *ipc, UINT64 now)
IPCIPv6AddRouterPrefixes(ipc, &p->ICMPv6HeaderPacketInfo.OptionList, src_mac, &ip_src); IPCIPv6AddRouterPrefixes(ipc, &p->ICMPv6HeaderPacketInfo.OptionList, src_mac, &ip_src);
IPCIPv6AssociateOnNDTEx(ipc, &ip_src, src_mac, true); IPCIPv6AssociateOnNDTEx(ipc, &ip_src, src_mac, true);
IPCIPv6AssociateOnNDTEx(ipc, &ip_src, p->ICMPv6HeaderPacketInfo.OptionList.SourceLinkLayer->Address, true); IPCIPv6AssociateOnNDTEx(ipc, &ip_src, p->ICMPv6HeaderPacketInfo.OptionList.SourceLinkLayer->Address, true);
ndtProcessed = true;
header_size = sizeof(ICMPV6_ROUTER_ADVERTISEMENT_HEADER);
break; break;
case ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT: case ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT:
// We save the neighbor advertisements into NDT // We save the neighbor advertisements into NDT
@ -1519,7 +1522,76 @@ void IPCProcessL3EventsEx(IPC *ipc, UINT64 now)
IPCIPv6AssociateOnNDTEx(ipc, &icmpHeaderAddr, src_mac, true); IPCIPv6AssociateOnNDTEx(ipc, &icmpHeaderAddr, src_mac, true);
IPCIPv6AssociateOnNDTEx(ipc, &ip_src, src_mac, true); IPCIPv6AssociateOnNDTEx(ipc, &ip_src, src_mac, true);
ndtProcessed = true; ndtProcessed = true;
header_size = sizeof(ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER);
break; break;
case ICMPV6_TYPE_NEIGHBOR_SOLICIATION:
header_size = sizeof(ICMPV6_NEIGHBOR_SOLICIATION_HEADER);
break;
}
// Remove link-layer address options for Windows clients (required on Windows 11)
if (header_size > 0)
{
UCHAR *src = p->ICMPv6HeaderPacketInfo.Headers.HeaderPointer + header_size;
UINT opt_size = p->ICMPv6HeaderPacketInfo.DataSize - header_size;
UCHAR *dst = src;
UINT removed = 0;
while (opt_size > sizeof(ICMPV6_OPTION))
{
ICMPV6_OPTION *option_header;
UINT header_total_size;
option_header = (ICMPV6_OPTION *)src;
// Calculate the entire header size
header_total_size = option_header->Length * 8;
if (header_total_size == 0)
{
// The size is zero
break;
}
if (opt_size < header_total_size)
{
// Size shortage
break;
}
switch (option_header->Type)
{
case ICMPV6_OPTION_TYPE_SOURCE_LINK_LAYER:
case ICMPV6_OPTION_TYPE_TARGET_LINK_LAYER:
// Skip source or target link-layer option
removed += header_total_size;
break;
default:
// Copy options other than source link-layer
if (src != dst)
{
UCHAR *tmp = Clone(src, header_total_size);
Copy(dst, tmp, header_total_size);
Free(tmp);
}
dst += header_total_size;
}
src += header_total_size;
opt_size -= header_total_size;
}
// Recalculate length and checksum if modified
if (removed > 0)
{
size -= removed;
p->L3.IPv6Header->PayloadLength = Endian16(size - sizeof(IPV6_HEADER));
p->L4.ICMPHeader->Checksum = 0;
p->L4.ICMPHeader->Checksum =
CalcChecksumForIPv6(&p->L3.IPv6Header->SrcAddress,
&p->L3.IPv6Header->DestAddress, IP_PROTO_ICMPV6,
p->L4.ICMPHeader, size - sizeof(IPV6_HEADER), 0);
Copy(data, b->Buf + 14, size);
}
} }
} }
@ -2483,10 +2555,20 @@ void IPCIPv6SendWithDestMacAddr(IPC *ipc, void *data, UINT size, UCHAR *dest_mac
BUF *buf; BUF *buf;
BUF *optBuf; BUF *optBuf;
BUF *packet; BUF *packet;
UINT header_size = 0;
// We need to rebuild the packet to // We need to rebuild the packet to
switch (p->ICMPv6HeaderPacketInfo.Type) switch (p->ICMPv6HeaderPacketInfo.Type)
{ {
case ICMPV6_TYPE_ROUTER_SOLICIATION:
header_size = sizeof(ICMPV6_ROUTER_SOLICIATION_HEADER);
if (p->ICMPv6HeaderPacketInfo.OptionList.SourceLinkLayer == NULL)
{
p->ICMPv6HeaderPacketInfo.OptionList.SourceLinkLayer = &linkLayer;
}
Copy(p->ICMPv6HeaderPacketInfo.OptionList.SourceLinkLayer->Address, ipc->MacAddress, 6);
break;
case ICMPV6_TYPE_NEIGHBOR_SOLICIATION: case ICMPV6_TYPE_NEIGHBOR_SOLICIATION:
header_size = sizeof(ICMPV6_NEIGHBOR_SOLICIATION_HEADER);
if (p->ICMPv6HeaderPacketInfo.OptionList.SourceLinkLayer == NULL) if (p->ICMPv6HeaderPacketInfo.OptionList.SourceLinkLayer == NULL)
{ {
p->ICMPv6HeaderPacketInfo.OptionList.SourceLinkLayer = &linkLayer; p->ICMPv6HeaderPacketInfo.OptionList.SourceLinkLayer = &linkLayer;
@ -2494,6 +2576,7 @@ void IPCIPv6SendWithDestMacAddr(IPC *ipc, void *data, UINT size, UCHAR *dest_mac
Copy(p->ICMPv6HeaderPacketInfo.OptionList.SourceLinkLayer->Address, ipc->MacAddress, 6); Copy(p->ICMPv6HeaderPacketInfo.OptionList.SourceLinkLayer->Address, ipc->MacAddress, 6);
break; break;
case ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT: case ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT:
header_size = sizeof(ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER);
if (p->ICMPv6HeaderPacketInfo.OptionList.TargetLinkLayer == NULL) if (p->ICMPv6HeaderPacketInfo.OptionList.TargetLinkLayer == NULL)
{ {
p->ICMPv6HeaderPacketInfo.OptionList.TargetLinkLayer = &linkLayer; p->ICMPv6HeaderPacketInfo.OptionList.TargetLinkLayer = &linkLayer;
@ -2503,12 +2586,12 @@ void IPCIPv6SendWithDestMacAddr(IPC *ipc, void *data, UINT size, UCHAR *dest_mac
} }
switch (p->ICMPv6HeaderPacketInfo.Type) switch (p->ICMPv6HeaderPacketInfo.Type)
{ {
case ICMPV6_TYPE_ROUTER_SOLICIATION:
case ICMPV6_TYPE_NEIGHBOR_SOLICIATION: case ICMPV6_TYPE_NEIGHBOR_SOLICIATION:
case ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT: case ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT:
optBuf = BuildICMPv6Options(&p->ICMPv6HeaderPacketInfo.OptionList); optBuf = BuildICMPv6Options(&p->ICMPv6HeaderPacketInfo.OptionList);
buf = NewBuf(); buf = NewBuf();
WriteBuf(buf, p->ICMPv6HeaderPacketInfo.Headers.HeaderPointer, WriteBuf(buf, p->ICMPv6HeaderPacketInfo.Headers.HeaderPointer, header_size);
p->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_NEIGHBOR_SOLICIATION ? sizeof(ICMPV6_NEIGHBOR_SOLICIATION_HEADER) : sizeof(ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER));
WriteBufBuf(buf, optBuf); WriteBufBuf(buf, optBuf);
packet = BuildICMPv6(&p->IPv6HeaderPacketInfo.IPv6Header->SrcAddress, packet = BuildICMPv6(&p->IPv6HeaderPacketInfo.IPv6Header->SrcAddress,
&p->IPv6HeaderPacketInfo.IPv6Header->DestAddress, &p->IPv6HeaderPacketInfo.IPv6Header->DestAddress,