mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
589 lines
14 KiB
589 lines
14 KiB
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
mlidrcv.c
|
|
|
|
Abstract:
|
|
|
|
This file contains all routines for receiving packets.
|
|
|
|
Author:
|
|
|
|
Sean Selitrennikoff (SeanSe) 3-8-93
|
|
|
|
Environment:
|
|
|
|
Kernel Mode.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <ndis.h>
|
|
#include "lsl.h"
|
|
#include "frames.h"
|
|
#include "mlid.h"
|
|
#include "ndismlid.h"
|
|
|
|
|
|
|
|
UINT32
|
|
ReceiveGetFrameType(
|
|
PMLID_STRUCT Mlid,
|
|
PUINT8 MediaHeader,
|
|
PUINT8 DataBuffer
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine returns the ODI FrameID of the MediaHeader and DataBuffer supplied.
|
|
It examines them to make a determination.
|
|
|
|
NOTE: This routine assumes that MediaHeader and DataBuffer have sufficient
|
|
bytes to make a determination.
|
|
|
|
NOTE: Called with Mlid->MlidSpinLock held!!
|
|
|
|
Arguments:
|
|
|
|
Mlid - Pointer to MLID struct that this came in on.
|
|
|
|
MediaHeader - Pointer to the raw media header as defined by NDIS 3.0
|
|
|
|
MediaHeaderLength - Length of the media header.
|
|
|
|
DataBuffer - Pointer to the rest of the packet.
|
|
|
|
FrameLength - Length of the NDIS 3.0 data portion of the packet.
|
|
|
|
Return Value:
|
|
|
|
ODI FrameID.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Switch on media type
|
|
//
|
|
switch (Mlid->NdisMlidMedium) {
|
|
|
|
case NdisMedium802_5:
|
|
|
|
|
|
//
|
|
// Find frame type
|
|
//
|
|
if ((DataBuffer[0] == 0xAA) &&
|
|
(DataBuffer[1] == 0xAA) &&
|
|
(DataBuffer[2] == 0x03)) {
|
|
|
|
return(TOKEN_RING_SNAP_FRAME_ID);
|
|
|
|
}
|
|
|
|
return(TOKEN_RING_802_2_FRAME_ID);
|
|
break;
|
|
|
|
|
|
case NdisMedium802_3:
|
|
|
|
if (*((USHORT UNALIGNED *)(&(MediaHeader[13]))) > 1500) {
|
|
|
|
return(ETHERNET_II_FRAME_ID);
|
|
|
|
}
|
|
|
|
if ((DataBuffer[0] == 0xFF) && (DataBuffer[1] == 0xFF)) {
|
|
|
|
return(ETHERNET_802_3_FRAME_ID);
|
|
}
|
|
|
|
if ((DataBuffer[0] == 0xAA) &&
|
|
(DataBuffer[1] == 0xAA) &&
|
|
(DataBuffer[2] == 0x03)) {
|
|
|
|
return(ETHERNET_SNAP_FRAME_ID);
|
|
|
|
}
|
|
|
|
return(ETHERNET_802_2_FRAME_ID);
|
|
break;
|
|
|
|
|
|
case NdisMediumFddi:
|
|
|
|
//
|
|
// Check for short addresses (unsupported)
|
|
//
|
|
if ((MediaHeader[0] & 0x40) == 0) {
|
|
|
|
return((UINT32)-1);
|
|
}
|
|
|
|
//
|
|
// Find frame type
|
|
//
|
|
if ((DataBuffer[0] == 0xAA) &&
|
|
(DataBuffer[1] == 0xAA) &&
|
|
(DataBuffer[2] == 0x03)) {
|
|
|
|
return(FDDI_SNAP_FRAME_ID);
|
|
|
|
}
|
|
|
|
return(FDDI_802_2_FRAME_ID);
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
//
|
|
// Should never happen
|
|
//
|
|
ASSERT(0);
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
ReceiveGetProtocolID(
|
|
PMLID_STRUCT Mlid,
|
|
PLOOKAHEAD OdiLookAhead,
|
|
UINT32 FrameID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets the ProtocolID field in the lookahead structure. It examines
|
|
the lookahead structure media header and data pointer, so these must be filled in.
|
|
|
|
NOTE: Called with Mlid->MlidSpinLock held!!
|
|
|
|
Arguments:
|
|
|
|
Mlid - Pointer to the MLID which received the packet.
|
|
|
|
OdiLookAhead - Pointer to a partially filled in lookahead structure.
|
|
|
|
FrameID - Frame ID of the received frame.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PUINT8 DSAPArea;
|
|
|
|
RtlZeroMemory(OdiLookAhead->LkAhd_ProtocolID, 6);
|
|
|
|
switch (FrameID) {
|
|
|
|
case ETHERNET_II_FRAME_ID:
|
|
|
|
OdiLookAhead->LkAhd_ProtocolID[4] = OdiLookAhead->LkAhd_MediaHeaderPtr[12];
|
|
OdiLookAhead->LkAhd_ProtocolID[5] = OdiLookAhead->LkAhd_MediaHeaderPtr[13];
|
|
break;
|
|
|
|
case ETHERNET_802_3_FRAME_ID:
|
|
|
|
break;
|
|
|
|
case ETHERNET_SNAP_FRAME_ID:
|
|
|
|
RtlCopyMemory(&(OdiLookAhead->LkAhd_ProtocolID[1]),
|
|
&(OdiLookAhead->LkAhd_MediaHeaderPtr[17]),
|
|
5
|
|
);
|
|
break;
|
|
|
|
case ETHERNET_802_2_FRAME_ID:
|
|
|
|
if (OdiLookAhead->LkAhd_MediaHeaderPtr[16] != 0x03) {
|
|
|
|
//
|
|
// A Type II frame
|
|
//
|
|
OdiLookAhead->LkAhd_ProtocolID[0] = 0x3;
|
|
OdiLookAhead->LkAhd_ProtocolID[2] = OdiLookAhead->LkAhd_MediaHeaderPtr[14];
|
|
OdiLookAhead->LkAhd_ProtocolID[3] = OdiLookAhead->LkAhd_MediaHeaderPtr[15];
|
|
OdiLookAhead->LkAhd_ProtocolID[4] = OdiLookAhead->LkAhd_MediaHeaderPtr[16];
|
|
OdiLookAhead->LkAhd_ProtocolID[5] = OdiLookAhead->LkAhd_MediaHeaderPtr[17];
|
|
|
|
} else {
|
|
|
|
//
|
|
// A Type I frame
|
|
//
|
|
if (OdiLookAhead->LkAhd_MediaHeaderPtr[14] !=
|
|
OdiLookAhead->LkAhd_MediaHeaderPtr[15]) {
|
|
OdiLookAhead->LkAhd_ProtocolID[0] = 0x2;
|
|
OdiLookAhead->LkAhd_ProtocolID[3] = OdiLookAhead->LkAhd_MediaHeaderPtr[14];
|
|
OdiLookAhead->LkAhd_ProtocolID[4] = OdiLookAhead->LkAhd_MediaHeaderPtr[15];
|
|
OdiLookAhead->LkAhd_ProtocolID[5] = OdiLookAhead->LkAhd_MediaHeaderPtr[16];
|
|
|
|
} else {
|
|
OdiLookAhead->LkAhd_ProtocolID[5] = OdiLookAhead->LkAhd_MediaHeaderPtr[14];
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TOKEN_RING_SNAP_FRAME_ID:
|
|
|
|
if (OdiLookAhead->LkAhd_MediaHeaderPtr[8] & 0x80) {
|
|
//
|
|
// Skip Source Routining info
|
|
//
|
|
|
|
DSAPArea = OdiLookAhead->LkAhd_MediaHeaderPtr +
|
|
14 +
|
|
(OdiLookAhead->LkAhd_MediaHeaderPtr[14] & 0x0F);
|
|
} else{
|
|
|
|
DSAPArea = OdiLookAhead->LkAhd_MediaHeaderPtr + 14;
|
|
|
|
}
|
|
|
|
RtlCopyMemory(&(OdiLookAhead->LkAhd_ProtocolID[1]),
|
|
DSAPArea + 3,
|
|
5
|
|
);
|
|
break;
|
|
|
|
case TOKEN_RING_802_2_FRAME_ID:
|
|
|
|
if (OdiLookAhead->LkAhd_MediaHeaderPtr[8] & 0x80) {
|
|
//
|
|
// Skip Source Routining info
|
|
//
|
|
|
|
DSAPArea = OdiLookAhead->LkAhd_MediaHeaderPtr +
|
|
14 +
|
|
(OdiLookAhead->LkAhd_MediaHeaderPtr[14] & 0x0F);
|
|
|
|
} else {
|
|
|
|
DSAPArea = OdiLookAhead->LkAhd_MediaHeaderPtr + 14;
|
|
|
|
}
|
|
|
|
if (DSAPArea[2] != 0x03) {
|
|
|
|
//
|
|
// A Type II frame
|
|
//
|
|
OdiLookAhead->LkAhd_ProtocolID[0] = 0x3;
|
|
OdiLookAhead->LkAhd_ProtocolID[2] = DSAPArea[0];
|
|
OdiLookAhead->LkAhd_ProtocolID[3] = DSAPArea[1];
|
|
OdiLookAhead->LkAhd_ProtocolID[4] = DSAPArea[2];
|
|
OdiLookAhead->LkAhd_ProtocolID[5] = DSAPArea[3];
|
|
|
|
} else {
|
|
|
|
//
|
|
// A Type I frame
|
|
//
|
|
if (DSAPArea[0] != DSAPArea[1]) {
|
|
OdiLookAhead->LkAhd_ProtocolID[0] = 0x2;
|
|
OdiLookAhead->LkAhd_ProtocolID[3] = DSAPArea[0];
|
|
OdiLookAhead->LkAhd_ProtocolID[4] = DSAPArea[1];
|
|
OdiLookAhead->LkAhd_ProtocolID[5] = DSAPArea[2];
|
|
|
|
} else {
|
|
OdiLookAhead->LkAhd_ProtocolID[5] = DSAPArea[0];
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FDDI_SNAP_FRAME_ID:
|
|
|
|
RtlCopyMemory(&(OdiLookAhead->LkAhd_ProtocolID[1]),
|
|
&(OdiLookAhead->LkAhd_MediaHeaderPtr[18]),
|
|
5
|
|
);
|
|
break;
|
|
|
|
case FDDI_802_2_FRAME_ID:
|
|
|
|
if (OdiLookAhead->LkAhd_MediaHeaderPtr[17] != 0x03) {
|
|
|
|
//
|
|
// A Type II frame
|
|
//
|
|
OdiLookAhead->LkAhd_ProtocolID[0] = 0x3;
|
|
OdiLookAhead->LkAhd_ProtocolID[2] = OdiLookAhead->LkAhd_MediaHeaderPtr[15];
|
|
OdiLookAhead->LkAhd_ProtocolID[3] = OdiLookAhead->LkAhd_MediaHeaderPtr[16];
|
|
OdiLookAhead->LkAhd_ProtocolID[4] = OdiLookAhead->LkAhd_MediaHeaderPtr[17];
|
|
OdiLookAhead->LkAhd_ProtocolID[5] = OdiLookAhead->LkAhd_MediaHeaderPtr[18];
|
|
|
|
} else {
|
|
|
|
//
|
|
// A Type I frame
|
|
//
|
|
if (OdiLookAhead->LkAhd_MediaHeaderPtr[15] !=
|
|
OdiLookAhead->LkAhd_MediaHeaderPtr[16]) {
|
|
OdiLookAhead->LkAhd_ProtocolID[0] = 0x2;
|
|
OdiLookAhead->LkAhd_ProtocolID[3] = OdiLookAhead->LkAhd_MediaHeaderPtr[15];
|
|
OdiLookAhead->LkAhd_ProtocolID[4] = OdiLookAhead->LkAhd_MediaHeaderPtr[16];
|
|
OdiLookAhead->LkAhd_ProtocolID[5] = OdiLookAhead->LkAhd_MediaHeaderPtr[17];
|
|
|
|
} else {
|
|
OdiLookAhead->LkAhd_ProtocolID[5] = OdiLookAhead->LkAhd_MediaHeaderPtr[15];
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
ReceiveSetDestinationType(
|
|
PMLID_STRUCT Mlid,
|
|
PLOOKAHEAD OdiLookAhead
|
|
)
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets the DestType field in the lookahead structure. It examines
|
|
the lookahead structure media header and data pointer, so these must be filled in.
|
|
|
|
NOTE: Require the ImmediateAddress field to be filled with the source address.
|
|
NOTE: Called with Mlid->MlidSpinLock held!!
|
|
|
|
Arguments:
|
|
|
|
Mlid - Pointer to MLID receiving the packet.
|
|
|
|
OdiLookAhead - Pointer to a partially filled in lookahead structure.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOLEAN Result;
|
|
|
|
if (OdiLookAhead->LkAhd_PktAttr != 0) {
|
|
|
|
OdiLookAhead->LkAhd_DestType = 0x20; // Global Error
|
|
return;
|
|
|
|
}
|
|
|
|
OdiLookAhead->LkAhd_DestType = 0x0;
|
|
|
|
switch (Mlid->NdisMlidMedium) {
|
|
|
|
case NdisMedium802_3:
|
|
|
|
//*\\ Does not support setting MulticastRemote bit in DestType. Is this OK?
|
|
|
|
if (ETH_IS_BROADCAST(OdiLookAhead->LkAhd_ImmediateAddress)) {
|
|
OdiLookAhead->LkAhd_DestType = 0x3; // Broadcast
|
|
return;
|
|
}
|
|
|
|
if (ETH_IS_MULTICAST(OdiLookAhead->LkAhd_ImmediateAddress)) {
|
|
OdiLookAhead->LkAhd_DestType = 0x1; // Multicast
|
|
return;
|
|
}
|
|
|
|
COMPARE_NETWORK_ADDRESSES(OdiLookAhead->LkAhd_ImmediateAddress,
|
|
Mlid->ConfigTable.MLIDCFG_NodeAddress,
|
|
&Result);
|
|
if (Result) {
|
|
OdiLookAhead->LkAhd_DestType = 0x80; // Direct
|
|
return;
|
|
}
|
|
|
|
OdiLookAhead->LkAhd_DestType = 0x4; // Directed to another station
|
|
|
|
break;
|
|
|
|
case NdisMedium802_5:
|
|
|
|
//
|
|
// First check for SR Info
|
|
//
|
|
if (OdiLookAhead->LkAhd_ImmediateAddress[0] & 0x80) {
|
|
|
|
//
|
|
// Yes
|
|
//
|
|
if (Mlid->ConfigTable.MLIDCFG_SourceRouting == NULL) {
|
|
|
|
//
|
|
// Set bit and exit
|
|
//
|
|
OdiLookAhead->LkAhd_DestType = 0x10; // No Source Routing
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
TR_IS_BROADCAST(OdiLookAhead->LkAhd_ImmediateAddress, &Result);
|
|
if (Result == TRUE) {
|
|
OdiLookAhead->LkAhd_DestType = 0x3; // Broadcast
|
|
return;
|
|
}
|
|
|
|
TR_IS_GROUP(OdiLookAhead->LkAhd_ImmediateAddress, &Result);
|
|
if (Result == TRUE) {
|
|
OdiLookAhead->LkAhd_DestType = 0x1; // Multicast
|
|
return;
|
|
}
|
|
|
|
TR_IS_FUNCTIONAL(OdiLookAhead->LkAhd_ImmediateAddress, &Result);
|
|
if (Result == TRUE) {
|
|
OdiLookAhead->LkAhd_DestType = 0x1; // Multicast
|
|
return;
|
|
}
|
|
|
|
COMPARE_NETWORK_ADDRESSES(OdiLookAhead->LkAhd_ImmediateAddress,
|
|
Mlid->ConfigTable.MLIDCFG_NodeAddress,
|
|
&Result);
|
|
if (Result) {
|
|
OdiLookAhead->LkAhd_DestType = 0x80; // Direct
|
|
return;
|
|
}
|
|
|
|
OdiLookAhead->LkAhd_DestType = 0x4; // Directed to another station
|
|
|
|
break;
|
|
|
|
case NdisMediumFddi:
|
|
|
|
if (ETH_IS_BROADCAST(OdiLookAhead->LkAhd_ImmediateAddress)) {
|
|
OdiLookAhead->LkAhd_DestType = 0x3; // Broadcast
|
|
return;
|
|
}
|
|
|
|
if (ETH_IS_MULTICAST(OdiLookAhead->LkAhd_ImmediateAddress)) {
|
|
OdiLookAhead->LkAhd_DestType = 0x1; // Multicast
|
|
return;
|
|
}
|
|
|
|
COMPARE_NETWORK_ADDRESSES(OdiLookAhead->LkAhd_ImmediateAddress,
|
|
Mlid->ConfigTable.MLIDCFG_NodeAddress,
|
|
&Result);
|
|
if (Result) {
|
|
OdiLookAhead->LkAhd_DestType = 0x80; // Direct
|
|
return;
|
|
}
|
|
|
|
OdiLookAhead->LkAhd_DestType = 0x4; // Directed to another station
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
BuildReceiveBufferChain(
|
|
PMLID_STRUCT Mlid,
|
|
PNDIS_PACKET NdisReceivePacket,
|
|
PECB ReceiveECB
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine builds an MDL chain describing the ECB fragment list
|
|
and attaches it to the NDIS_PACKET.
|
|
|
|
NOTE: Called with Mlid->MlidSpinLock held!!
|
|
|
|
Arguments:
|
|
|
|
Mlid - Owning Mlid.
|
|
|
|
Packet - Pointer to the NDIS_PACKET to free.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT32 i;
|
|
PNDIS_BUFFER NdisBuffer;
|
|
NDIS_STATUS NdisStatus;
|
|
|
|
//
|
|
// Convert ECB fragment list into an MDL chain
|
|
//
|
|
for (i = 0; i < ReceiveECB->ECB_FragmentCount; i++) {
|
|
|
|
NdisAllocateBuffer(
|
|
&NdisStatus,
|
|
&NdisBuffer,
|
|
Mlid->ReceiveBufferPool,
|
|
ReceiveECB->ECB_Fragment[i].FragmentAddress,
|
|
ReceiveECB->ECB_Fragment[i].FragmentLength
|
|
);
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
|
|
|
//
|
|
// Unchain all NDIS_BUFFERs from packet
|
|
//
|
|
|
|
NdisUnchainBufferAtFront(
|
|
NdisReceivePacket,
|
|
&NdisBuffer
|
|
);
|
|
|
|
while (NdisBuffer != NULL) {
|
|
|
|
NdisFreeBuffer(NdisBuffer);
|
|
|
|
NdisUnchainBufferAtFront(
|
|
NdisReceivePacket,
|
|
&NdisBuffer
|
|
);
|
|
|
|
}
|
|
|
|
return(NDIS_STATUS_RESOURCES);
|
|
|
|
}
|
|
|
|
NdisChainBufferAtBack(
|
|
NdisReceivePacket,
|
|
NdisBuffer
|
|
);
|
|
|
|
}
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
|
|
}
|
|
|