705 lines
19 KiB
C
705 lines
19 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
llcaddr.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module provides a network independent interface to build
|
|||
|
lan headers for the sent and received frames.
|
|||
|
This is a re-entarnt library module having no access to the data
|
|||
|
structures of data link module.
|
|||
|
|
|||
|
Contents:
|
|||
|
LlcBuildAddress
|
|||
|
LlcBuildAddressFromLanHeader
|
|||
|
LlcGetMaxInfoField
|
|||
|
LlcCopyReceivedLanHeader
|
|||
|
CopyLanHeader
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Antti Saarenheimo (o-anttis) 30-MAY-1991
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include <llc.h>
|
|||
|
|
|||
|
#define FDDI_FC 0x57 // Frame Control: async, 48-bit address, LLC, pri 7
|
|||
|
|
|||
|
static USHORT ausLongestFrameTranslation[8] = {
|
|||
|
516,
|
|||
|
1470,
|
|||
|
2052,
|
|||
|
4472,
|
|||
|
8144,
|
|||
|
11407,
|
|||
|
17800,
|
|||
|
17800
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
UINT
|
|||
|
LlcBuildAddress(
|
|||
|
IN NDIS_MEDIUM NdisMedium,
|
|||
|
IN PUCHAR DestinationAddress,
|
|||
|
IN PVOID pSrcRouting,
|
|||
|
IN OUT PUCHAR pLanHeader
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
The primitive implements a network independent handling of
|
|||
|
the address information in the LAN header. It builds LAN a
|
|||
|
802.3, DIX or 802.5 header from an address and an optional source
|
|||
|
routing info. The source SAP number and the current node address are
|
|||
|
provided by the link driver.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
NdisMedium - medium that MAC talks over
|
|||
|
DestinationAddress - LAN destination address (or a broadcast/multicast/
|
|||
|
functional address).
|
|||
|
pSrcRouting - optional source routing information. Must be set
|
|||
|
NULL when not used.
|
|||
|
pLanHeader - buffer provided by the upper protocol for the
|
|||
|
address information of the frame header.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
length of the LAN header
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UCHAR SourceRoutingIndicator = 0x01;
|
|||
|
UINT minimumLanHeader = 14;
|
|||
|
|
|||
|
if (NdisMedium == NdisMediumFddi) {
|
|||
|
pLanHeader[0] = FDDI_FC;
|
|||
|
++pLanHeader;
|
|||
|
minimumLanHeader = 13;
|
|||
|
} else if (NdisMedium == NdisMedium802_5) {
|
|||
|
pLanHeader[0] = 0; // DEFAULT_TR_ACCESS;
|
|||
|
pLanHeader[1] = 0x40; // NON_MAC_FRAME;
|
|||
|
pLanHeader += 2;
|
|||
|
SourceRoutingIndicator = 0x80;
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// We build always the DIX ethernet header, even if it is not used
|
|||
|
// when the link works in 802.3. IN the automatic mode
|
|||
|
// we need just to copy the lan header length from all received U-
|
|||
|
// command frames and we are using the same mode as the other side.
|
|||
|
// However, there is a problem: the remote node may response
|
|||
|
// the SAMBE request with Rxx or even with I-frame, but we
|
|||
|
// don't want to put any extra checking on our main code path
|
|||
|
// (U- command frames would definitely be outside of it).
|
|||
|
// The other side will send RR- if it cannot get any acknowledge
|
|||
|
// from us, and after a while it closes the link.
|
|||
|
//-----
|
|||
|
// We considered the using of connect timeout to change the
|
|||
|
// ethernet mode, but that might have procedured too long waithing
|
|||
|
// times (something 1s and 30s)
|
|||
|
//-----
|
|||
|
// Usually the client tries to connect to the host and the client
|
|||
|
// sends first the data. We may also assume, that IBM host machines
|
|||
|
// use the standard LLC implementations (SABME is always acknowledged
|
|||
|
// by UA)
|
|||
|
//
|
|||
|
|
|||
|
pLanHeader[12] = 0x80;
|
|||
|
pLanHeader[13] = 0xD5;
|
|||
|
}
|
|||
|
LlcMemCpy(pLanHeader, DestinationAddress, 6);
|
|||
|
|
|||
|
//
|
|||
|
// We must support the source routing information also for
|
|||
|
// ethernet, because the underlaying network could be token-ring.
|
|||
|
// The source routing bit must be a local variable, because it
|
|||
|
// is different in token-ring and ethernet
|
|||
|
//
|
|||
|
|
|||
|
if (!pSrcRouting) {
|
|||
|
pLanHeader[6] &= ~SourceRoutingIndicator;
|
|||
|
return minimumLanHeader;
|
|||
|
} else {
|
|||
|
pLanHeader[6] |= SourceRoutingIndicator;
|
|||
|
pLanHeader[0] &= ~SourceRoutingIndicator;
|
|||
|
|
|||
|
//
|
|||
|
// 5 Lowest bits are the source routing information length.
|
|||
|
//
|
|||
|
|
|||
|
if ( (*((PUCHAR)pSrcRouting) & 0x1f) > MAX_TR_SRC_ROUTING_INFO) {
|
|||
|
return DLC_STATUS_INVALID_ROUTING_INFO;
|
|||
|
}
|
|||
|
LlcMemCpy(&pLanHeader[12],
|
|||
|
pSrcRouting,
|
|||
|
*((PUCHAR)pSrcRouting) & 0x1f // Length
|
|||
|
);
|
|||
|
return minimumLanHeader + *((PUCHAR)pSrcRouting) & 0x1f;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
UINT
|
|||
|
LlcBuildAddressFromLanHeader(
|
|||
|
IN NDIS_MEDIUM NdisMedium,
|
|||
|
IN PUCHAR pRcvLanHeader,
|
|||
|
IN OUT PUCHAR pLanHeader
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
The routine builds a transmit lan header form the received frame and
|
|||
|
returns the frames header length, nul if invalid address
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
NdisMedium - Ndis menium of the address information
|
|||
|
pRcvFrameHeader - pointer to any frame received from the network.
|
|||
|
The buffer must include the whole LAN header of the frame
|
|||
|
including the LLC header.
|
|||
|
pLanHeader - buffer to receive the information (minimum size is 32 bytes)
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UINT LlcOffset;
|
|||
|
|
|||
|
if (NdisMedium == NdisMedium802_3) {
|
|||
|
|
|||
|
#ifndef SUPPORT_ETHERNET_CLIENT
|
|||
|
|
|||
|
LlcOffset = LlcBuildAddress(NdisMedium,
|
|||
|
&pRcvLanHeader[6],
|
|||
|
NULL,
|
|||
|
pLanHeader
|
|||
|
);
|
|||
|
|
|||
|
#else
|
|||
|
|
|||
|
LlcOffset = LlcBuildAddress(NdisMedium,
|
|||
|
&pRcvLanHeader[6],
|
|||
|
(pRcvLanHeader[6] & 0x01)
|
|||
|
? &pRcvLanHeader[12]
|
|||
|
: NULL,
|
|||
|
pLanHeader
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// We must swap the direction bit and reset the possible
|
|||
|
// broadcast type in the source routing header.
|
|||
|
//
|
|||
|
|
|||
|
if (pLanHeader[6] & 0x01) {
|
|||
|
pLanHeader[12] &= 0x1f;
|
|||
|
pLanHeader[13] ^= 0x80;
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
} else if (NdisMedium == NdisMediumFddi) {
|
|||
|
LlcOffset = LlcBuildAddress(NdisMedium,
|
|||
|
&pRcvLanHeader[7],
|
|||
|
NULL, // no source routing in FDDI
|
|||
|
pLanHeader
|
|||
|
);
|
|||
|
} else {
|
|||
|
LlcOffset = LlcBuildAddress(NdisMedium,
|
|||
|
&pRcvLanHeader[8],
|
|||
|
(pRcvLanHeader[8] & 0x80)
|
|||
|
? &pRcvLanHeader[14]
|
|||
|
: NULL,
|
|||
|
pLanHeader
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// We must swap the direction bit and reset the possible broadcast type
|
|||
|
//
|
|||
|
|
|||
|
if (pLanHeader[8] & 0x80) {
|
|||
|
pLanHeader[14] &= 0x1f;
|
|||
|
pLanHeader[15] ^= 0x80;
|
|||
|
}
|
|||
|
}
|
|||
|
return LlcOffset;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
USHORT
|
|||
|
LlcGetMaxInfoField(
|
|||
|
IN NDIS_MEDIUM NdisMedium,
|
|||
|
IN PVOID hBinding,
|
|||
|
IN PUCHAR pLanHeader
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Procedure returns the maximum informatiuon field for
|
|||
|
the given LAN header. It checks both the source routing
|
|||
|
information and the maximum packet length defined for
|
|||
|
the adapter and decrements the LAN and LLC headers
|
|||
|
from the length
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
NdisMedium - Ndis medium of the address information
|
|||
|
pBinding - current binding context on data link driver
|
|||
|
pLanHeader - any lan header
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Maximum information field length
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PUCHAR pSourceRouting;
|
|||
|
UCHAR LanHeaderLength = 14;
|
|||
|
USHORT MaxFrameSize;
|
|||
|
USHORT usMaxBridgeSize;
|
|||
|
|
|||
|
MaxFrameSize = (USHORT)((PBINDING_CONTEXT)hBinding)->pAdapterContext->MaxFrameSize;
|
|||
|
|
|||
|
//
|
|||
|
// We may run DLC within the DIX in ethernet network, so add 3 bytes for
|
|||
|
// SNA DIX LAN header and padding
|
|||
|
//
|
|||
|
|
|||
|
if (((PBINDING_CONTEXT)hBinding)->pAdapterContext->NdisMedium == NdisMedium802_3) {
|
|||
|
LanHeaderLength += 3;
|
|||
|
}
|
|||
|
|
|||
|
pSourceRouting = NULL;
|
|||
|
if (NdisMedium == NdisMedium802_5) {
|
|||
|
if (pLanHeader[8] & 0x80) {
|
|||
|
pSourceRouting = pLanHeader + 14;
|
|||
|
}
|
|||
|
} else if (NdisMedium == NdisMediumFddi) {
|
|||
|
if (pLanHeader[6] & 0x80) {
|
|||
|
pSourceRouting = pLanHeader + 13;
|
|||
|
}
|
|||
|
} else {
|
|||
|
if (pLanHeader[6] & 0x01) {
|
|||
|
pSourceRouting = pLanHeader + 12;
|
|||
|
}
|
|||
|
}
|
|||
|
if (pSourceRouting != NULL) {
|
|||
|
|
|||
|
//
|
|||
|
// Add the source routing info length to the LAN header length
|
|||
|
//
|
|||
|
|
|||
|
LanHeaderLength += (UCHAR)(*pSourceRouting & (UCHAR)0x1f);
|
|||
|
usMaxBridgeSize = ausLongestFrameTranslation[(pSourceRouting[1] & SRC_ROUTING_LF_MASK) >> 4];
|
|||
|
|
|||
|
//
|
|||
|
// RLF 10/01/92. Ignore the 'bridge size'. This is misleading. For
|
|||
|
// instance, the IBM mainframe is currently sending RI of 02 80 in
|
|||
|
// all frames, indicating that the max I-frame it can accept/transmit
|
|||
|
// is 516 bytes (x000xxxx in byte #2). It later sends us a 712 byte
|
|||
|
// frame, 683 bytes of which are info field. We reject it (FRMR)
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// must work this out properly
|
|||
|
//
|
|||
|
|
|||
|
//if (MaxFrameSize > usMaxBridgeSize) {
|
|||
|
// MaxFrameSize = usMaxBridgeSize;
|
|||
|
//}
|
|||
|
}
|
|||
|
return (USHORT)(MaxFrameSize - LanHeaderLength - sizeof(LLC_HEADER));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
UINT
|
|||
|
LlcCopyReceivedLanHeader(
|
|||
|
IN PBINDING_CONTEXT pBinding,
|
|||
|
IN PUCHAR DestinationAddress,
|
|||
|
IN PUCHAR SourceAddress
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Function copies and translates the received lan header to
|
|||
|
the address format used by the client. By default the
|
|||
|
source is the current received frame.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pBinding - pointer to Binding Context
|
|||
|
DestinationAddress - pointer to output destination net address
|
|||
|
SourceAddress - pointer to input source net address
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Length of copied LAN header
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
if (SourceAddress == NULL) {
|
|||
|
SourceAddress = pBinding->pAdapterContext->pHeadBuf;
|
|||
|
}
|
|||
|
if (pBinding->pAdapterContext->FrameType == LLC_DIRECT_ETHERNET_TYPE) {
|
|||
|
|
|||
|
//
|
|||
|
// when receiving a DIX frame, the LAN header is always the 12 bytes
|
|||
|
// before the ethernet type field
|
|||
|
//
|
|||
|
|
|||
|
LlcMemCpy(DestinationAddress, SourceAddress, 12);
|
|||
|
return 12;
|
|||
|
} else {
|
|||
|
|
|||
|
UCHAR LanHeaderLength = 14;
|
|||
|
|
|||
|
switch (pBinding->AddressTranslation) {
|
|||
|
case LLC_SEND_802_5_TO_802_5:
|
|||
|
|
|||
|
//
|
|||
|
// Copy also the source routing info, if it has been defined
|
|||
|
//
|
|||
|
|
|||
|
LlcMemCpy(DestinationAddress,
|
|||
|
SourceAddress,
|
|||
|
(SourceAddress[8] & 0x80)
|
|||
|
? LanHeaderLength + (SourceAddress[14] & 0x1f)
|
|||
|
: LanHeaderLength
|
|||
|
);
|
|||
|
break;
|
|||
|
|
|||
|
case LLC_SEND_802_5_TO_802_3:
|
|||
|
case LLC_SEND_802_5_TO_DIX:
|
|||
|
DestinationAddress[0] = 0; // default AC
|
|||
|
DestinationAddress[1] = 0x40; // default frame type: non-MAC
|
|||
|
|
|||
|
//
|
|||
|
// RLF 03/31/93
|
|||
|
//
|
|||
|
// we are receiving an Ethernet frame. We always reverse the bits
|
|||
|
// in the destination address (ie our node address). We reverse the
|
|||
|
// source (sender's node address) based on the SwapAddressBits flag.
|
|||
|
// If this is TRUE (default) then we also swap the source address
|
|||
|
// bits so that ethernet addresses are presented to the app in
|
|||
|
// standard non-canonical format. If SwapAddressBits is FALSE then
|
|||
|
// we leave them in canonical format (a real ethernet address) or
|
|||
|
// presumably the address is a Token Ring address from the other
|
|||
|
// side of an ethernet-token ring bridge
|
|||
|
//
|
|||
|
|
|||
|
SwappingMemCpy(&DestinationAddress[2],
|
|||
|
SourceAddress,
|
|||
|
6
|
|||
|
);
|
|||
|
SwapMemCpy(pBinding->pAdapterContext->ConfigInfo.SwapAddressBits,
|
|||
|
&DestinationAddress[8],
|
|||
|
SourceAddress+6,
|
|||
|
6
|
|||
|
);
|
|||
|
break;
|
|||
|
|
|||
|
case LLC_SEND_802_5_TO_FDDI:
|
|||
|
DestinationAddress[0] = 0;
|
|||
|
DestinationAddress[1] = 0x40;
|
|||
|
SwappingMemCpy(&DestinationAddress[2],
|
|||
|
SourceAddress+1,
|
|||
|
6
|
|||
|
);
|
|||
|
SwapMemCpy(pBinding->pAdapterContext->ConfigInfo.SwapAddressBits,
|
|||
|
&DestinationAddress[8],
|
|||
|
SourceAddress+7,
|
|||
|
6
|
|||
|
);
|
|||
|
break;
|
|||
|
|
|||
|
#ifdef SUPPORT_ETHERNET_CLIENT
|
|||
|
case LLC_SEND_802_3_TO_802_3:
|
|||
|
case LLC_SEND_802_3_TO_DIX:
|
|||
|
LlcMemCpy(DestinationAddress, SourceAddress, LanHeaderLength);
|
|||
|
break;
|
|||
|
|
|||
|
case LLC_SEND_802_3_TO_802_5:
|
|||
|
|
|||
|
//
|
|||
|
// check the source routing bit
|
|||
|
//
|
|||
|
|
|||
|
SwappingMemCpy(DestinationAddress, &SourceAddress[2], 12);
|
|||
|
|
|||
|
if (SourceAddress[8] & 0x80) {
|
|||
|
LanHeaderLength += SourceAddress[14] & 0x1f;
|
|||
|
LlcMemCpy(&DestinationAddress[12],
|
|||
|
&SourceAddress[14],
|
|||
|
SourceAddress[14] & 0x1f
|
|||
|
);
|
|||
|
}
|
|||
|
break;
|
|||
|
#endif
|
|||
|
|
|||
|
case LLC_SEND_FDDI_TO_FDDI:
|
|||
|
DestinationAddress[0] = FDDI_FC;
|
|||
|
LlcMemCpy(DestinationAddress+1, SourceAddress, 12);
|
|||
|
return 13;
|
|||
|
|
|||
|
#if LLC_DBG
|
|||
|
default:
|
|||
|
LlcInvalidObjectType();
|
|||
|
break;
|
|||
|
#endif
|
|||
|
|
|||
|
}
|
|||
|
return LanHeaderLength;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
UCHAR
|
|||
|
CopyLanHeader(
|
|||
|
IN UINT AddressTranslationMode,
|
|||
|
IN PUCHAR pSrcLanHeader,
|
|||
|
IN PUCHAR pNodeAddress,
|
|||
|
OUT PUCHAR pDestLanHeader,
|
|||
|
IN BOOLEAN SwapAddressBits
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
The primitive translates the given LAN header and its type to
|
|||
|
a real network header and patches the local node address to
|
|||
|
the source address field. It also returns the length
|
|||
|
of the LAN header (== offset of LLC header).
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
AddressTranslationMode - the network format mapping case
|
|||
|
pSrcLanHeader - the initial LAN header
|
|||
|
pNodeAddress - the current node address
|
|||
|
pDestLanHeader - storage for the new LAN header
|
|||
|
SwapAddressBits - TRUE if we will swap address bits for Ethernet/FDDI
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Length of the built network header
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UCHAR LlcOffset = 14;
|
|||
|
UCHAR NodeAddressOffset = 6;
|
|||
|
UCHAR SourceRoutingFlag = 0;
|
|||
|
|
|||
|
//
|
|||
|
// LLC driver API supports both 802.3 (ethernet) and 802.5 (token-ring)
|
|||
|
// address presentation formats. The 802.3 header may include the source
|
|||
|
// routing information, when it is used on token-ring.
|
|||
|
//
|
|||
|
// Internally LLC supports 802.3, DIX and 802.5 networks.
|
|||
|
// The transport level driver needs to support only one format. It is
|
|||
|
// translated to the actual network header by LLC.
|
|||
|
// Thus we have these six address mappings.
|
|||
|
//
|
|||
|
|
|||
|
switch (AddressTranslationMode) {
|
|||
|
case LLC_SEND_802_5_TO_802_5:
|
|||
|
|
|||
|
//
|
|||
|
// TOKEN-RING 802.5 -> TOKEN-RING 802.5
|
|||
|
//
|
|||
|
|
|||
|
NodeAddressOffset = 8;
|
|||
|
LlcMemCpy(pDestLanHeader, pSrcLanHeader, 8);
|
|||
|
|
|||
|
//
|
|||
|
// set the AC & FC bytes: FC = 0x40 == LLC-level frame
|
|||
|
//
|
|||
|
// THIS MAY NOT BE THE CORRECT PLACE TO DO THIS, UNLESS MAC
|
|||
|
// LEVEL FRAMES CHANGE FC BACK TO 0x00 AFTER THIS ROUTINE AND
|
|||
|
// BEFORE THE FRAME IS PUT ON THE WIRE
|
|||
|
//
|
|||
|
|
|||
|
pDestLanHeader[0] = 0; // AC = no pritority
|
|||
|
pDestLanHeader[1] = 0x40; // FS = Non-MAC
|
|||
|
SourceRoutingFlag = pSrcLanHeader[8] & (UCHAR)0x80;
|
|||
|
if (SourceRoutingFlag) {
|
|||
|
|
|||
|
//
|
|||
|
// Copy the source routing info
|
|||
|
//
|
|||
|
|
|||
|
LlcOffset += pSrcLanHeader[14] & 0x1f;
|
|||
|
LlcMemCpy(&pDestLanHeader[14],
|
|||
|
&pSrcLanHeader[14],
|
|||
|
pSrcLanHeader[14] & 0x1f
|
|||
|
);
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case LLC_SEND_802_5_TO_DIX:
|
|||
|
|
|||
|
//
|
|||
|
// TOKEN-RING -> DIX-ETHERNET
|
|||
|
//
|
|||
|
// The ethernet type is a small endiand!!
|
|||
|
//
|
|||
|
|
|||
|
pDestLanHeader[12] = 0x80;
|
|||
|
pDestLanHeader[13] = 0xD5;
|
|||
|
LlcOffset = 17;
|
|||
|
|
|||
|
//
|
|||
|
// **** FALL THROUGH ****
|
|||
|
//
|
|||
|
|
|||
|
case LLC_SEND_802_5_TO_802_3:
|
|||
|
|
|||
|
//
|
|||
|
// TOKEN-RING 802.5 -> ETHERNET 802.3
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// RLF 03/31/93
|
|||
|
//
|
|||
|
// Once again, we swap the bits in the destination address ONLY if the
|
|||
|
// SwapAddressBits flag is TRUE.
|
|||
|
// This *could* be a frame intended to go to an ethernet-token ring
|
|||
|
// bridge. The bridge may or may not swap the destination address bits
|
|||
|
// depending on whether there's a 'y' in the month
|
|||
|
//
|
|||
|
|
|||
|
SwapMemCpy(SwapAddressBits,
|
|||
|
pDestLanHeader,
|
|||
|
&pSrcLanHeader[2],
|
|||
|
6
|
|||
|
);
|
|||
|
break;
|
|||
|
|
|||
|
case LLC_SEND_802_5_TO_FDDI:
|
|||
|
pDestLanHeader[0] = FDDI_FC;
|
|||
|
SwapMemCpy(SwapAddressBits, pDestLanHeader+1, &pSrcLanHeader[2], 6);
|
|||
|
NodeAddressOffset = 7;
|
|||
|
LlcOffset = 13;
|
|||
|
break;
|
|||
|
|
|||
|
case LLC_SEND_DIX_TO_DIX:
|
|||
|
LlcOffset = 12;
|
|||
|
|
|||
|
case LLC_SEND_802_3_TO_802_3:
|
|||
|
|
|||
|
//
|
|||
|
// ETHERNET 802.3 -> ETHERNET 802.3
|
|||
|
//
|
|||
|
|
|||
|
LlcMemCpy(pDestLanHeader, pSrcLanHeader, 6);
|
|||
|
break;
|
|||
|
|
|||
|
case LLC_SEND_802_3_TO_DIX:
|
|||
|
|
|||
|
//
|
|||
|
// The ethernet type is a small endiand!!
|
|||
|
//
|
|||
|
|
|||
|
pDestLanHeader[12] = 0x80;
|
|||
|
pDestLanHeader[13] = 0xD5;
|
|||
|
LlcOffset = 17;
|
|||
|
|
|||
|
//
|
|||
|
// ETHERNET 802.3 -> DIX-ETHERNET
|
|||
|
//
|
|||
|
|
|||
|
LlcMemCpy(pDestLanHeader, pSrcLanHeader, 6);
|
|||
|
break;
|
|||
|
|
|||
|
#ifdef SUPPORT_ETHERNET_CLIENT
|
|||
|
|
|||
|
case LLC_SEND_802_3_TO_802_5:
|
|||
|
|
|||
|
//
|
|||
|
// ETHERNET 802.3 -> TOKEN-RING 802.5
|
|||
|
//
|
|||
|
|
|||
|
NodeAddressOffset = 8;
|
|||
|
pDestLanHeader[0] = 0; // AC = no pritority
|
|||
|
pDestLanHeader[1] = 0x40; // FS = Non-MAC
|
|||
|
SwappingMemCpy(pDestLanHeader + 2, pSrcLanHeader, 6);
|
|||
|
|
|||
|
//
|
|||
|
// Note: Ethernet source routing info indication flag is swapped!
|
|||
|
//
|
|||
|
|
|||
|
if (pSrcLanHeader[6] & 0x01) {
|
|||
|
SourceRoutingFlag = 0x80;
|
|||
|
|
|||
|
//
|
|||
|
// Copy the source routing info, the source routing info
|
|||
|
// must always be in token-ring bit order (reverse)
|
|||
|
//
|
|||
|
|
|||
|
pDestLanHeader[8] |= 0x80;
|
|||
|
LlcOffset += pSrcLanHeader[12] & 0x1f;
|
|||
|
LlcMemCpy(&pDestLanHeader[14],
|
|||
|
&pSrcLanHeader[12],
|
|||
|
pSrcLanHeader[12] & 0x1f
|
|||
|
);
|
|||
|
}
|
|||
|
break;
|
|||
|
#endif
|
|||
|
|
|||
|
case LLC_SEND_UNMODIFIED:
|
|||
|
return 0;
|
|||
|
break;
|
|||
|
|
|||
|
case LLC_SEND_FDDI_TO_FDDI:
|
|||
|
LlcMemCpy(pDestLanHeader, pSrcLanHeader, 7);
|
|||
|
NodeAddressOffset = 7;
|
|||
|
LlcOffset = 13;
|
|||
|
break;
|
|||
|
|
|||
|
case LLC_SEND_FDDI_TO_802_5:
|
|||
|
break;
|
|||
|
|
|||
|
case LLC_SEND_FDDI_TO_802_3:
|
|||
|
break;
|
|||
|
|
|||
|
#if LLC_DBG
|
|||
|
default:
|
|||
|
LlcInvalidObjectType();
|
|||
|
break;
|
|||
|
#endif
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// copy the source address from the node address (ie. our adapter's address)
|
|||
|
// in the correct format for the medium (canonical or non-canonical address
|
|||
|
// format)
|
|||
|
//
|
|||
|
|
|||
|
LlcMemCpy(&pDestLanHeader[NodeAddressOffset], pNodeAddress, 6);
|
|||
|
pDestLanHeader[NodeAddressOffset] |= SourceRoutingFlag;
|
|||
|
|
|||
|
return LlcOffset;
|
|||
|
}
|