📄 ipv6.c
字号:
return TRUE;
}
return FALSE;
}
//* IPv6FakeDHTtxNA
//
// Constructs an IPv6 Neighbor Advert for the magic
// DHT transmit address and loops it back to the local
// IPv6 stack. This because the neighbor cache of the
// local IPv6 stack requires ND state for the DHT transmit
// address before it will transmit packets towards that
// address.
//
boolint
IPv6FakeDHTtxNA(
MiniportAdapter *VA,
IPv6Addr SolicitSource)
{
NDIS_PACKET *AdvertPacket = NULL;
NDIS_STATUS Status;
uchar *Data;
EtherHeader UNALIGNED *AdvertEther;
VRRHeader UNALIGNED *AdvertVRR;
ushort UNALIGNED *EthType;
IPv6Header UNALIGNED *AdvertIPv6;
IPv6NA UNALIGNED *AdvertICMPv6;
u_long Flags = (ND_NA_FLAG_OVERRIDE | ND_NA_FLAG_SOLICITED);
ushort PayloadLength = sizeof(IPv6NA);
ushort Checksum;
const AdvertSize = sizeof(EtherHeader)
+ sizeof(IPv6Header)
+ PayloadLength;
//
// Obtain NDIS packet, NDIS buffer and memory for IPv6 Neighbor Advert.
//
Status = MiniportMakeEmptyPacket(VA, AdvertSize, &AdvertPacket, &Data);
if (Status != NDIS_STATUS_SUCCESS)
goto ReleaseAndReturn;
//
// Initialize eth header.
//
AdvertEther = (EtherHeader UNALIGNED *)Data;
RtlCopyMemory(AdvertEther->Dest, VA->Address, sizeof(VirtualAddress));
RtlCopyMemory(AdvertEther->Source, DHTMagicL2, sizeof(VirtualAddress));
AdvertEther->Type = RtlUshortByteSwap(ETYPE_IPv6);
//
// Initialize IPv6 header.
//
AdvertIPv6 = (IPv6Header UNALIGNED *)(AdvertEther + 1);
AdvertIPv6->VersClassFlow = IP_VERSION6;
AdvertIPv6->PayloadLength = RtlUshortByteSwap(PayloadLength);
AdvertIPv6->NextHeader = IP_PROTOCOL_ICMPv6;
AdvertIPv6->HopLimit = 255;
RtlCopyMemory(&AdvertIPv6->Source, &DHTrxAddr, sizeof(in6_addr));
RtlCopyMemory(&AdvertIPv6->Dest, &SolicitSource, sizeof(in6_addr));
//
// Initialize ICMPv6 header of type Neighbor Advert.
//
AdvertICMPv6 = (IPv6NA UNALIGNED *)(AdvertIPv6 + 1);
AdvertICMPv6->ICMPHeader.Type = ICMPv6_NEIGHBOR_ADVERT;
AdvertICMPv6->ICMPHeader.Code = 0;
AdvertICMPv6->ICMPHeader.Checksum = 0;
AdvertICMPv6->Flags = RtlUlongByteSwap(Flags);
RtlCopyMemory(&AdvertICMPv6->TargetAddress, &DHTtxAddr, sizeof(in6_addr));
AdvertICMPv6->TLLAType = 2;
AdvertICMPv6->TLLALength = 1;
RtlCopyMemory(&AdvertICMPv6->TLLAddress, DHTMagicL2, sizeof(PhysicalAddress));
//
// Initialize ICMPv6 checksum.
//
Checksum = ChecksumPacket(AdvertPacket,
(u_long)AdvertICMPv6 - (u_long)Data,
NULL,
sizeof *AdvertICMPv6, // amount to checksum. aka PayloadLength
&AdvertIPv6->Source,
&AdvertIPv6->Dest,
IP_PROTOCOL_ICMPv6);
AdvertICMPv6->ICMPHeader.Checksum = Checksum; // Note: no byte-swap.
//
// Send the NA to our local IPv6 protocol driver.
// The receive completion handling will free our NDIS packet.
//
PC(AdvertPacket)->srp = NULL;
PC(AdvertPacket)->ReceiveComplete = MiniportReceiveComplete;
NDIS_SET_PACKET_STATUS(AdvertPacket, NDIS_STATUS_SUCCESS);
NDIS_SET_PACKET_HEADER_SIZE(AdvertPacket, sizeof(EtherHeader));
NdisMIndicateReceivePacket(VA->MiniportHandle, &AdvertPacket, 1);
return TRUE;
ReleaseAndReturn:
if (AdvertPacket != NULL)
NdisFreePacketClone(AdvertPacket);
return FALSE;
}
//* SetVSetChanged
//
// Sets a flag so that an unsolicited DHT message
// of type DHT_QUERY_VSET will be generated and
// sent to the local IPv6 stack. This is used to
// signal changes of driver state to DHT apps.
//
void
SetVSetChanged (
MiniportAdapter *VA)
{
InterlockedExchange(&VA->NT.DHTQueryVSet, TRUE);
}
//* TestVSetChanged
//
// Indicates whether an unsolicited DHT message of type
// DHT_QUERY_VSET is pending, clearing the indicator.
//
// Returns non-zero iff DHT_QUERY_VSET is pending.
//
boolint
TestVSetChanged (
MiniportAdapter *VA)
{
return InterlockedCompareExchange(&VA->NT.DHTQueryVSet, FALSE, TRUE);
}
//* DHTDriverRequest
//
// DHT applications may send requests to their local
// VRR driver by constructing a UDP packet addressed to
// a well-known destination. The driver intercepts these
// packets and replies using a looped back UDP packet or,
// as a special case, by delivering the request up to a
// higher-level driver as a packet.
//
// The caller must guarantee that *RequestDHT is contiguous
// in memory for RequestLength bytes.
//
void
DHTDriverRequest (
MiniportAdapter *VA,
uchar MsgType,
DHTHeader UNALIGNED *RequestDHT,
ushort RequestLength,
ushort Port)
{
NDIS_PACKET *Packet = NULL;
NDIS_STATUS Status;
uchar *Data;
EtherHeader UNALIGNED *Ether;
IPv6Header UNALIGNED *IPv6;
ICMPv6Header UNALIGNED *ICMPv6;
UDPHeader UNALIGNED *UDP;
DHTHeader UNALIGNED *DHT;
uint PacketLength;
ushort IPv6Length;
//
// Validate message type and length. Calculate
// reply length.
//
IPv6Length = sizeof(UDPHeader)
+ sizeof(DHTHeader);
if (MsgType == DHT_QUERY_VSET) {
IPv6Length += sizeof(DHTQueryVSet);
PacketLength = sizeof(EtherHeader)
+ sizeof(IPv6Header)
+ IPv6Length;
}
else if (MsgType == DHT_QUERY_NEXT_HOP &&
RequestLength >= sizeof(DHTHeader) &&
RequestDHT != NULL) {
IPv6Length += sizeof(DHTReplyNextHop);
PacketLength = sizeof(EtherHeader)
+ sizeof(IPv6Header)
+ IPv6Length;
}
else if (MsgType == DHT_ERROR_NEXT_HOP &&
RequestLength >= sizeof(DHTHeader) &&
RequestDHT != NULL) {
IPv6Length += RequestLength;
PacketLength = sizeof(EtherHeader)
+ sizeof(IPv6Header)
+ IPv6Length;
}
else if (MsgType == DHT_TRAP_PACKET) {
if (RequestLength > DHTTrapPacketMaxSize()) {
KdPrint(("VrrKdPrint: (%u) DHTDriverRequest(TRAP): pkt (%i) too large for DHT payload (%i)\n",
TIMESTAMP, RequestLength, DHTTrapPacketMaxSize()));
goto ReleaseAndReturn;
}
IPv6Length += RequestLength;
PacketLength = sizeof(EtherHeader)
+ sizeof(IPv6Header)
+ IPv6Length;
}
else if (MsgType == DHT_LOOPBACK) {
PacketLength = RequestLength - sizeof(DHTHeader);
}
else if (MsgType == DHT_COMMAND &&
RequestLength >= (sizeof(DHTHeader) + sizeof(DHTCommand)) &&
RequestDHT != NULL) {
IPv6Length += sizeof(DHTCommand);
PacketLength = sizeof(EtherHeader)
+ sizeof(IPv6Header)
+ IPv6Length;
}
else {
KdPrint(("VrrKdPrint: (%u) DHTDriverReply: invalid Msg Type(%u) Len(%u)\n",
TIMESTAMP, MsgType, RequestLength));
goto ReleaseAndReturn;
}
//
// Obtain NDIS packet, NDIS buffer and memory.
//
Status = MiniportMakeEmptyPacket(VA, PacketLength, &Packet, &Data);
if (Status != NDIS_STATUS_SUCCESS)
goto ReleaseAndReturn;
RtlZeroMemory(Data,PacketLength);
//
// Loopback: caller must supply all headers. We treat
// as an opaque payload - whatever our caller supplied
// after the DHTHeader gets looped back.
//
if (MsgType == DHT_LOOPBACK) {
uchar *SrcBuff = (uchar UNALIGNED *)RequestDHT;
SrcBuff += sizeof(DHTHeader);
RtlCopyMemory(Data, SrcBuff, PacketLength);
VrrKdPrint("DHTDriverRequest(TRAP) looping back packet",NULL,NULL);
goto ReceivePacket;
}
//
// Initialize eth header.
//
Ether = (EtherHeader UNALIGNED *)Data;
RtlCopyMemory(Ether->Dest, VA->Address, sizeof(VirtualAddress));
RtlCopyMemory(Ether->Source, VA->Address, sizeof(VirtualAddress));
Ether->Type = RtlUshortByteSwap(ETYPE_IPv6);
//
// Initialize IPv6 header.
//
IPv6 = (IPv6Header UNALIGNED *)(Ether + 1);
IPv6->VersClassFlow = IP_VERSION6;
IPv6->PayloadLength = RtlUshortByteSwap(IPv6Length);
IPv6->NextHeader = IP_PROTOCOL_UDP;
IPv6->HopLimit = 255;
RtlCopyMemory(&IPv6->Source, &DHTtxAddr, sizeof(in6_addr));
RtlCopyMemory(&IPv6->Dest, &DHTrxAddr, sizeof(in6_addr));
//
// Initialize UDP header.
//
UDP = (UDPHeader UNALIGNED *)(IPv6 + 1);
Port = (Port == 0) ? DHT_DEFAULT_UDP_PORT : Port;
UDP->Source = RtlUshortByteSwap(Port);
UDP->Dest = RtlUshortByteSwap(Port);
UDP->Checksum = 0;
//
// Initialize DHTHeader.
//
DHT = (DHTHeader UNALIGNED *)(UDP + 1);
RtlCopyMemory(&DHT->Dest,VA->Address,sizeof(VirtualAddress));
//
// Initialize reply.
//
switch (MsgType) {
case DHT_QUERY_VSET: {
//
// Reply enumerates our VSet.
//
DHTQueryVSet UNALIGNED *Reply;
KIRQL OldIrql;
NodeTableEntry *NTE;
VirtualAddress *self;
uint i;
#if DHT_QUERY_VSET_NEW
AddressList *ALE = NULL;
#else
uchar CountLeft = 0;
uchar CountRight = 0;
#endif
VirtualAddress *VSet;
DHT->Type.Type = DHT_QUERY_VSET;
Reply = (DHTQueryVSet UNALIGNED *)(DHT + 1);
Reply->MaxVSetSize = VRR_MAX_VSET_SIZE;
//
// Initialize state bits.
//
if (IsDriverActive(VA))
Reply->State.DriverActive = 1;
if (InterlockedCompareExchange(&VA->VrrAPIJoined,0,0))
Reply->State.VrrAPIJoined = 1;
if (IsJoiningOnHold(VA))
Reply->State.JoiningOnHold = 1;
UDP->Length = RtlUshortByteSwap(sizeof(DHTHeader)
+ sizeof(DHTQueryVSet));
KeAcquireSpinLock(&VA->NT.Lock, &OldIrql);
//
// Initialize entry for self.
//
self = (VirtualAddress *)Reply->VSet[VRR_WING_SIZE];
RtlCopyMemory(self,VA->NT.Self->Address,sizeof(VirtualAddress));
#if DHT_QUERY_VSET_NEW
//
// Initialize entries for LHS neighbours.
//
VRRASSERT(AddressListCount(VA->NT.VSetLeft) <= VRR_WING_SIZE);
VSet = self;
Reply->CountLeft = (uchar)AddressListCount(VA->NT.VSetLeft);
for (ALE = VA->NT.VSetLeft; ALE != NULL; ALE = ALE->Next)
RtlCopyMemory(*(--VSet), ALE->Address, sizeof(VirtualAddress));
//
// Initialize entries for RHS neighbours.
//
VRRASSERT(AddressListCount(VA->NT.VSetRight) <= VRR_WING_SIZE);
VSet = self;
Reply->CountRight = (uchar)AddressListCount(VA->NT.VSetRight);
for (ALE = VA->NT.VSetRight; ALE != NULL; ALE = ALE->Next)
RtlCopyMemory(*(++VSet), ALE->Address, sizeof(VirtualAddress));
#else
//
// Initialize entries for LHS neighbours.
//
NTE = VA->NT.Self;
VRRASSERT(VA->NT.CountLeft <= 0xff);
VSet = self;
for (i = 0; i < VA->NT.CountLeft; i++) {
NTE = NTE->Prev;
CountLeft++;
RtlCopyMemory(*(--VSet), NTE->Address, sizeof(VirtualAddress));
}
Reply->CountLeft = CountLeft;
//
// Initialize entries for RHS neighbours.
//
NTE = VA->NT.Self;
VRRASSERT(VA->NT.CountRight <= 0xff);
VSet = self;
for (i = 0; i < VA->NT.CountRight; i++) {
NTE = NTE->Next;
CountRight++;
RtlCopyMemory(*(++VSet), NTE->Address, sizeof(VirtualAddress));
}
Reply->CountRight = CountRight;
#endif
KeReleaseSpinLock(&VA->NT.Lock, OldIrql);
break;
}
case DHT_QUERY_NEXT_HOP: {
//
// Reply indicates next hop towards given destination.
//
DHTReplyNextHop UNALIGNED *Reply;
TxToken Token;
FindNextHopResult Result;
DHT->Type.Type = DHT_QUERY_NEXT_HOP;
Reply = (DHTReplyNextHop UNALIGNED *)(DHT + 1);
UDP->Length = RtlUshortByteSwap(sizeof(DHTHeader)
+ sizeof(DHTReplyNextHop));
RtlCopyMemory(Reply->Dest, RequestDHT->Dest, sizeof(VirtualAddress));
//
// Find next hop.
//
Result = FindNextHop(VA,
RequestDHT->Dest,
VRR_IFID_UNSPECIFIED,
VRR_IFID_UNSPECIFIED,
&Token,
NULL,
NULL_SR_FLAGS);
if (Result == SuccessFwd) {
//
// Next hop is to a neighboring node.
//
Reply->Success = TRUE;
RtlCopyMemory(Reply->NextHop, Token.NextVAddress, sizeof(VirtualAddress));
}
else if (Result == SuccessRcvSelf || Result == SuccessRcvNearest) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -