📄 sr.c
字号:
break;
case VRR_OPTION_TYPE_SETUP:
//
// VrrSetup options must be large enough to hold Setup preamble.
//
if (Walk->optDataLen < VRRSETUP_LEN(0)) {
KdPrint(("VRR!CheckPacket: Setup length < sizeof(VrrSetup preamble)\n"));
return NDIS_STATUS_INVALID_PACKET;
}
//
// VrrSetup vset length must be a multiple of VirtualAddress.
//
if (Walk->optDataLen > VRRSETUP_LEN(0)) {
uint VABuff = Walk->optDataLen - (sizeof(VrrSetup) - sizeof(VRROption));
if (0 != VABuff % sizeof(VirtualAddress)) {
KdPrint(("VRR!CheckPacket: VrrSetup trailer not multiple of VirtualAddress\n"));
return NDIS_STATUS_INVALID_PACKET;
}
}
break;
case VRR_OPTION_TYPE_TEARDOWN:
//
// VrrTearDown options must be large enough to hold TearDown preamble.
//
if (Walk->optDataLen < VRRTEARDOWN_LEN(0,0)) {
KdPrint(("VRR!CheckPacket: VrrTearDown length < sizeof(TearDown preamble)\n"));
return NDIS_STATUS_INVALID_PACKET;
}
//
// VrrTearDown options must be large enough to hold the specified Global PathId list.
//
if (Walk->optDataLen < VRRTEARDOWN_LEN(((VrrTearDown *)Walk)->NumGlobalPathId, 0)) {
KdPrint(("VRR!CheckPacket: VrrTearDown length < sizeof(GlobalPIF[NumPId])\n"));
return NDIS_STATUS_INVALID_PACKET;
}
//
// TearDown vset length must be a multiple of VirtualAddress.
//
if (Walk->optDataLen > (((VrrTearDown *)Walk)->NumGlobalPathId, 0)) {
uint VABuff = Walk->optDataLen
- (sizeof(VrrTearDown)
- sizeof(VRROption)
- VRRTEARDOWN_LEN(((VrrTearDown *)Walk)->NumGlobalPathId, 0));
if (0 != VABuff % sizeof(VirtualAddress)) {
KdPrint(("VRR!CheckPacket: VrrSetup trailer not multiple of VirtualAddress\n"));
return NDIS_STATUS_INVALID_PACKET;
}
}
break;
case VRR_OPTION_TYPE_SETUPREQ:
//
// SetupReq options must be large enough to hold SetupReq preamble.
//
if (Walk->optDataLen < VRRSETUPREQ_LEN(0)) {
KdPrint(("VRR!CheckPacket: SetupReq length < sizeof(SetupReq preamble)\n"));
return NDIS_STATUS_INVALID_PACKET;
}
//
// VrrSetupReq vset length must be a multiple of VirtualAddress.
//
if (Walk->optDataLen > VRRSETUPREQ_LEN(0)) {
uint VABuff = Walk->optDataLen - (sizeof(VrrSetupReq) - sizeof(VRROption));
if (0 != VABuff % sizeof(VirtualAddress)) {
KdPrint(("VRR!CheckPacket: VrrSetupReq trailer not multiple of VirtualAddress\n"));
return NDIS_STATUS_INVALID_PACKET;
}
}
break;
default:
KdPrint(("VRR!CheckPacket: bad option type\n"));
return NDIS_STATUS_INVALID_PACKET;
}
//
// Move on to the next option (if any).
//
Left -= sizeof(VRROption) + Walk->optDataLen;
(uchar *)Walk += sizeof(VRROption) + Walk->optDataLen;
}
return NDIS_STATUS_SUCCESS;
}
//* InsertOptions
//
// Helper function for SRPacketToPkt.
//
static void
InsertOptions(VRROption **Walk, void *Field, uchar Type)
{
InternalOption *IntOpt;
SIZE_T Amount;
UNREFERENCED_PARAMETER(Type); // Only used in checked builds.
for (IntOpt = Field; IntOpt != NULL; IntOpt = IntOpt->Next) {
VRRASSERT(IntOpt->Opt.optionType == Type);
Amount = sizeof(VRROption) + IntOpt->Opt.optDataLen;
RtlCopyMemory(*Walk, &IntOpt->Opt, Amount);
*Walk = (VRROption *)(((char *)*Walk) + Amount);
}
}
//* SRPacketToPkt
//
// Converts the SRPacket to an NDIS packet that can be transmitted.
// The NDIS packet should be deallocated with NdisFreePacketClone.
//
// If the packet will be transmitted via a single physical adapter,
// then PC(Packet)->PA is initialized.
//
NDIS_STATUS
SRPacketToPkt(
MiniportAdapter *VA,
const SRPacket *SRP,
NDIS_PACKET **pPacket)
{
uint HeaderLength = SROptionLength(SRP);
NDIS_PACKET *Packet;
#if DBG
uint PacketLength;
#endif
void *CloneHeader;
EtherHeader *CloneEther;
VRRHeader *CloneVRR;
VRROption *Walk;
NDIS_STATUS Status;
const uchar *Dest;
VRRIf OutIf;
VRRIf InIf;
VRRIf LocIF;
VRRIf RemIF;
ProtocolAdapter *PA;
uint FoundNextHop;
FindNextHopResult Result;
if (IsFixedDestSRP(SRP)) {
//
// Certain VRR messages have fixed NextHop.
// They must not be rerouted by FNH.
// At this point the NextHop should already be known.
//
VRRASSERT(! IsNullTxToken((TxToken *)&SRP->Token) );
}
else {
//
// Use routing state to initialize for tx.
// First, confirm we are forwarding the packet.
// Find the next hop to Dest from the Route Table and
// update the SRPacket TxToken.
//
Result = FindNextHop(VA,
(uchar *)SRP->Dest,
VRR_IFID_UNSPECIFIED,
VRR_IFID_UNSPECIFIED,
(TxToken *)&SRP->Token,
NULL,
NULL_SR_FLAGS);
if (Result == Error) {
VrrKdPrint("SRPacketToPkt: FNH(d)=Error - cannot forward SRPacket", NULL, (char *)SRP->Dest);
return NDIS_STATUS_NO_ROUTE_TO_DESTINATION;
}
else if (Result == SuccessRcvNearest) {
//
// Do not form NDIS packet for SRP if exists closer node to dest than self.
//
if (ExistsCloserNTEorPLEthanSelf(VA, SRP->Dest, FALSE, FALSE)) {
VrrKdPrint("SRPacketToPkt: drop: FNH(d)=Nearest but closer [NTE|PLE] exists", NULL, (char *)SRP->Dest);
InterlockedIncrement((PLONG)&VA->CountNTECloserThanSelf);
return NDIS_STATUS_NO_ROUTE_TO_DESTINATION;
}
}
}
//
// Obtain an NDIS packet (clone).
//
if (SRP->Packet == NULL) {
VRRASSERT(SRP->PayloadOffset == 0);
Status = MiniportMakeEmptyPacket(VA,
sizeof(EtherHeader) + sizeof(VRRHeader) + HeaderLength,
&Packet, &CloneHeader);
}
else {
void *OrigHeader;
Status = MiniportClonePacket(VA, SRP->Packet,
SRP->PayloadOffset,
(sizeof(EtherHeader) +
sizeof(VRRHeader) +
HeaderLength),
0, // No lookahead needed.
&OrigHeader, &Packet, &CloneHeader);
}
if (Status != NDIS_STATUS_SUCCESS)
return Status;
PC(Packet)->PA = SRP->Token.PA;
#if DBG
//
// Check that we are not exceeding the physical link MTU.
// The basic VRR header fits in PROTOCOL_MIN_FRAME_SIZE (1500) -
// MINIPORT_MAX_FRAME_SIZE (1280) bytes, and
// the piggy-backing code will avoid adding too many options.
//
NdisQueryPacketLength(Packet, &PacketLength);
VRRASSERT(PacketLength <= sizeof(EtherHeader) + PROTOCOL_MIN_FRAME_SIZE);
#endif
CloneEther = (EtherHeader *) CloneHeader;
CloneVRR = (VRRHeader *) (CloneEther + 1);
Walk = (VRROption *) (CloneVRR + 1);
CloneEther->Type = ETYPE_MSFT;
CloneVRR->Code = VRR_CODE;
// CloneVRR->MAC computed below.
RtlCopyMemory(CloneVRR->IV, SRP->IV, VRR_IV_LENGTH);
CloneVRR->HeaderLength = (ushort) HeaderLength;
//
// Fill in VRR header.
//
RtlCopyMemory(CloneVRR->Source, VA->Address, sizeof(VirtualAddress));
RtlCopyMemory(CloneVRR->Dest, SRP->Token.Dest, sizeof(VirtualAddress));
RtlCopyMemory(CloneVRR->Origin, SRP->Origin, sizeof(VirtualAddress));
CloneVRR->FrameSeqNo = RtlUlongByteSwap(SRP->FrameSeqNo);
CloneVRR->HopCount = SRP->HopCount + 1;
if (SRP->VrrHello == NULL) {
//
// Common case. Transmit packet to physical address of
// node with nearest virtual address to the desination
// virtual address.
//
RtlCopyMemory(CloneEther->Dest, SRP->Token.NextPAddress, sizeof(PhysicalAddress));
RtlCopyMemory((SRPacket *)SRP->EtherDest, SRP->Token.NextPAddress, sizeof(PhysicalAddress));
}
else {
//
// In a few special cases we use link local broadcast.
//
RtlFillMemory(CloneEther->Dest, IEEE_802_ADDR_LENGTH, (uchar)0xff);
RtlFillMemory(CloneVRR->Dest, sizeof(VirtualAddress), (uchar)0xff);
}
//
// Reassembly order doesn't matter.
//
InsertOptions(&Walk, SRP->ackreq, VRR_OPTION_TYPE_ACKREQ);
InsertOptions(&Walk, SRP->ack, VRR_OPTION_TYPE_ACK);
InsertOptions(&Walk, SRP->Probe, VRR_OPTION_TYPE_PROBE);
InsertOptions(&Walk, SRP->ProbeReply, VRR_OPTION_TYPE_PROBEREPLY);
InsertOptions(&Walk, SRP->VrrHello, VRR_OPTION_TYPE_HELLO);
InsertOptions(&Walk, SRP->VrrSetup, VRR_OPTION_TYPE_SETUP);
InsertOptions(&Walk, SRP->VrrTearDown, VRR_OPTION_TYPE_TEARDOWN);
InsertOptions(&Walk, SRP->VrrSetupReq, VRR_OPTION_TYPE_SETUPREQ);
//
// Compute the MAC.
//
SRPacketMAC(VA, CloneVRR->MAC, Packet);
*pPacket = Packet;
return NDIS_STATUS_SUCCESS;
}
//* SRPacketToProbe
//
// Similar to SRPacketToPkt adapted to support probe packets which
// are often sent to nodes whose NCE state is rejected by the
// mainline forwarding code in FindNextHop(). Since the target of
// a probe is often not an active member of the ring, or even in a
// position to join the ring, we will only send it messages of type
// PROBE or PROBEREPLY.
//
// gregos: better to get SRPacketToProbe effect with extra arg to SRPacketToPkt?
//
// Converts the SRPacket to an NDIS packet that can be transmitted.
// The NDIS packet should be deallocated with NdisFreePacketClone.
//
// If the packet will be transmitted via a single physical adapter,
// then PC(Packet)->PA is initialized.
//
// The caller must hold NC->Lock.
//
NDIS_STATUS
SRPacketToProbe(
MiniportAdapter *VA,
SRPacket *SRP,
NDIS_PACKET **pPacket)
{
uint HeaderLength = SROptionLength(SRP);
NDIS_PACKET *Packet;
#if DBG
uint PacketLength;
#endif
void *CloneHeader;
EtherHeader *CloneEther;
VRRHeader *CloneVRR;
VRROption *Walk;
NDIS_STATUS Status;
const uchar *Dest;
VRRIf OutIf;
VRRIf InIf;
VRRIf LocIF;
VRRIf RemIF;
ProtocolAdapter *PA;
uint FoundNextHop;
NeighborCache *NC = &VA->NC;
NeighborCacheEntry *NCE;
//
// Probes are constructed using NCE state rather than route state.
// Why is because we often want to probe nodes whose NCE is not LINKED.
//
VRRASSERT(SRP->Probe != NULL || SRP->ProbeReply != NULL);
VRRASSERT(SRP->Probe == NULL || SRP->ProbeReply == NULL);
if (SRP->Probe != NULL) {
LocIF = SRP->Probe->Opt.OutIf;
RemIF = SRP->Probe->Opt.InIf;
}else {
LocIF = SRP->ProbeReply->Opt.OutIf;
RemIF = SRP->ProbeReply->Opt.InIf;
}
NCE = FindNCE(NC,
SRP->Dest,
LocIF,
RemIF,
VRR_NCE_STATE_VALID);
if (NCE == NULL) {
VrrKdPrint("SRPacketToProbe: FindNCE(d)==NULL, okay if rare",NULL,SRP->Dest);
return NDIS_STATUS_NO_ROUTE_TO_DESTINATION;
}
VRRASSERT(VirtualAddressEqual(SRP->Dest,NCE->VAddress));
//
// Init the SRP->TxToken from state in NCE.
//
RtlZeroMemory(&SRP->Token, sizeof(TxToken));
SRP->Token.PA=FindPhysicalAdapterFromIndex(VA, NCE->LocIF);
RtlCopyMemory(SRP->Token.Source, VA->Address, sizeof(VirtualAddress));
RtlCopyMemory(SRP->Token.Dest, NCE->VAddress, sizeof(VirtualAddress));
RtlCopyMemory(SRP->Token.NextVAddress, NCE->VAddress, sizeof(VirtualAddress));
RtlCopyMemory(SRP->Token.NextPAddress, NCE->PAddress, sizeof(PhysicalAddress));
SRP->Token.LocIF = NCE->LocIF;
SRP->Token.RemIF = NCE->RemIF;
//
// Obtain an NDIS packet (clone).
//
if (SRP->Packet == NULL) {
VRRASSERT(SRP->PayloadOffset == 0);
Status = MiniportMakeEmptyPacket(VA,
sizeof(EtherHeader) + sizeof(VRRHeader) + HeaderLength,
&Packet, &CloneHeader);
}
else {
void *OrigHeader;
Status = MiniportClonePacket(VA, SRP->Packet,
SRP->PayloadOffset,
(sizeof(EtherHeader) +
sizeof(VRRHeader) +
HeaderLength),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -