windows-nt/Source/XPSP1/NT/net/nwlink/fwd/rcvind.c

856 lines
29 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
ntos\tdi\isn\fwd\rcvind.c
Abstract:
Receive indication processing
Author:
Vadim Eydelman
Revision History:
--*/
#include "precomp.h"
#if DBG
VOID
DbgFilterReceivedPacket(PUCHAR hdrp);
#endif
// Doesn't allow accepting packets (for routing) from dial-in clients
BOOLEAN ThisMachineOnly = FALSE;
/*++
*******************************************************************
F w R e c e i v e
Routine Description:
Called by the IPX stack to indicate that the IPX packet was
received by the NIC dirver. Only external destined packets are
indicated by this routine (with the exception of Netbios boradcasts
that indicated both for internal and external handlers)
Arguments:
MacBindingHandle - handle of NIC driver
MaxReceiveContext - NIC driver context
RemoteAddress - sender's address
MacOptions -
LookaheadBuffer - packet lookahead buffer that contains complete
IPX header
LookaheadBufferSize - its size (at least 30 bytes)
LookaheadBufferOffset - offset of lookahead buffer in the physical
packet
Return Value:
TRUE if we take the MDL chain to return later with NdisReturnPacket
*******************************************************************
--*/
BOOLEAN
IpxFwdReceive (
NDIS_HANDLE MacBindingHandle,
NDIS_HANDLE MacReceiveContext,
ULONG_PTR Context,
PIPX_LOCAL_TARGET RemoteAddress,
ULONG MacOptions,
PUCHAR LookaheadBuffer,
UINT LookaheadBufferSize,
UINT LookaheadBufferOffset,
UINT PacketSize,
PMDL pMdl)
{
PINTERFACE_CB srcIf, dstIf;
PPACKET_TAG pktTag;
PNDIS_PACKET pktDscr;
NDIS_STATUS status;
UINT BytesTransferred;
LARGE_INTEGER PerfCounter;
// check that our configuration process has terminated OK
if (!EnterForwarder ()) {
return FALSE;
}
if (!MeasuringPerformance) {
PerfCounter.QuadPart = 0;
}
else {
#if DBG
static LONGLONG LastCall = 0;
KIRQL oldIRQL;
#endif
PerfCounter = KeQueryPerformanceCounter (NULL);
#if DBG
KeAcquireSpinLock (&PerfCounterLock, &oldIRQL);
ASSERT (PerfCounter.QuadPart-LastCall<ActivityTreshhold);
LastCall = PerfCounter.QuadPart;
KeReleaseSpinLock (&PerfCounterLock, oldIRQL);
#endif
}
IpxFwdDbgPrint (DBG_RECV, DBG_INFORMATION,
("IpxFwd: FwdReceive on %0lx,"
" dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
Context, GETULONG (LookaheadBuffer+IPXH_DESTNET),
LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
LookaheadBuffer[IPXH_PKTTYPE]));
#if DBG
DbgFilterReceivedPacket (LookaheadBuffer);
#endif
srcIf = InterfaceContextToReference ((PVOID)Context, RemoteAddress->NicId);
// Check if interface is valid
if (srcIf!=NULL) {
USHORT pktlen;
ULONG dstNet;
KIRQL oldIRQL;
dstNet = GETULONG (LookaheadBuffer + IPXH_DESTNET);
pktlen = GETUSHORT(LookaheadBuffer + IPXH_LENGTH);
// check if we got the whole IPX header in the lookahead buffer
if ((LookaheadBufferSize >= IPXH_HDRSIZE)
&& (*(LookaheadBuffer + IPXH_XPORTCTL) < 16)
&& (pktlen<=PacketSize)) {
// Lock interface CB to ensure coherency of information in it
KeAcquireSpinLock(&srcIf->ICB_Lock, &oldIRQL);
// Check if shoud accept packets on this interface
if (IS_IF_ENABLED(srcIf)
&& (srcIf->ICB_Stats.OperationalState!=FWD_OPER_STATE_DOWN)
&& (!ThisMachineOnly
|| (srcIf->ICB_InterfaceType
!=FWD_IF_REMOTE_WORKSTATION))) {
// Check for looped back packets
if (IPX_NODE_CMP (RemoteAddress->MacAddress,
srcIf->ICB_LocalNode)!=0) {
// Separate processing of netbios broadcast packets (20)
if (*(LookaheadBuffer + IPXH_PKTTYPE) != IPX_NETBIOS_TYPE) {
PFWD_ROUTE dstRoute;
INT srcListId, dstListId;
// Temp IPX bug fix, they shou;d ensure that
// we only get packets that can be routed
if ((dstNet==srcIf->ICB_Network)
|| (dstNet==InternalInterface->ICB_Network)) {
InterlockedIncrement (&srcIf->ICB_Stats.InDiscards);
KeReleaseSpinLock(&srcIf->ICB_Lock, oldIRQL);
ReleaseInterfaceReference (srcIf);
LeaveForwarder ();
return FALSE;
}
// ASSERT (dstNet!=srcIf->ICB_Network);
// ASSERT ((InternalInterface==NULL)
// || (InternalInterface->ICB_Network==0)
// || (dstNet!=InternalInterface->ICB_Network));
// Check if needed route is in cash
if ((srcIf->ICB_CashedRoute!=NULL)
&& (dstNet==srcIf->ICB_CashedRoute->FR_Network)
// If route was changed or deleted, this will fail
&& (srcIf->ICB_CashedRoute->FR_InterfaceReference
==srcIf->ICB_CashedInterface)) {
dstIf = srcIf->ICB_CashedInterface;
dstRoute = srcIf->ICB_CashedRoute;
AcquireInterfaceReference (dstIf);
AcquireRouteReference (dstRoute);
IpxFwdDbgPrint (DBG_RECV, DBG_INFORMATION,
("IpxFwd: Destination in cash.\n"));
}
else { // Find and cash the route
dstIf = FindDestination (dstNet,
LookaheadBuffer+IPXH_DESTNODE,
&dstRoute
);
if (dstIf!=NULL) { // If route is found
IpxFwdDbgPrint (DBG_RECV, DBG_INFORMATION,
("IpxFwd: Found destination %0lx.\n", dstIf));
// Don't cash global wan clients and
// routes to the same net
if ((dstNet!=GlobalNetwork)
&& (dstIf!=srcIf)) {
if (srcIf->ICB_CashedInterface!=NULL)
ReleaseInterfaceReference (srcIf->ICB_CashedInterface);
if (srcIf->ICB_CashedRoute!=NULL)
ReleaseRouteReference (srcIf->ICB_CashedRoute);
srcIf->ICB_CashedInterface = dstIf;
srcIf->ICB_CashedRoute = dstRoute;
AcquireInterfaceReference (dstIf);
AcquireRouteReference (dstRoute);
}
}
else { // No route
InterlockedIncrement (&srcIf->ICB_Stats.InNoRoutes);
KeReleaseSpinLock(&srcIf->ICB_Lock, oldIRQL);
IpxFwdDbgPrint (DBG_RECV, DBG_WARNING,
("IpxFwd: No route for packet on interface %ld (icb:%0lx),"
" dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
srcIf->ICB_Index, srcIf, dstNet,
LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
LookaheadBuffer[IPXH_PKTTYPE]));
ReleaseInterfaceReference (srcIf);
LeaveForwarder ();
return FALSE;
}
}
srcListId = srcIf->ICB_PacketListId;
KeReleaseSpinLock(&srcIf->ICB_Lock, oldIRQL);
// Check if destination if can take the packet
if (IS_IF_ENABLED (dstIf)
// If interface is UP check packet againts actual size limit
&& (((dstIf->ICB_Stats.OperationalState==FWD_OPER_STATE_UP)
&& (PacketSize<=dstIf->ICB_Stats.MaxPacketSize))
// if sleeping (WAN), check we can allocate it from WAN list
|| ((dstIf->ICB_Stats.OperationalState==FWD_OPER_STATE_SLEEPING)
&& (PacketSize<=WAN_PACKET_SIZE))
// otherwise, interface is down and we can't take the packet
) ){
FILTER_ACTION action;
action = FltFilter (LookaheadBuffer, LookaheadBufferSize,
srcIf->ICB_FilterInContext,
dstIf->ICB_FilterOutContext);
if (action==FILTER_PERMIT) {
InterlockedIncrement (&srcIf->ICB_Stats.InDelivers);
dstListId = dstIf->ICB_PacketListId;
// try to get a packet from the rcv pkt pool
AllocatePacket (srcListId, dstListId, pktTag);
if (pktTag!=NULL) {
// Set destination mac in local target if
// possible
KeAcquireSpinLock (&dstIf->ICB_Lock, &oldIRQL);
if (dstIf->ICB_InterfaceType==FWD_IF_PERMANENT) {
// Permanent interface: send to the next
// hop router if net is not directly connected
// or to the dest node otherwise
if (dstNet!=dstIf->ICB_Network) {
IPX_NODE_CPY (pktTag->PT_Target.MacAddress,
dstRoute->FR_NextHopAddress);
}
else {
IPX_NODE_CPY (pktTag->PT_Target.MacAddress,
LookaheadBuffer+IPXH_DESTNODE);
}
}
else { // Demand dial interface: assumed to be
// point to point connection -> send to
// the other party if connection has already
// been made, otherwise wait till connected
if (dstIf->ICB_Stats.OperationalState
== FWD_OPER_STATE_UP) {
IPX_NODE_CPY (pktTag->PT_Target.MacAddress,
dstIf->ICB_RemoteNode);
} // Copy source mac address and nic id in case
// we need to spoof this packet
else if ((*(LookaheadBuffer+IPXH_PKTTYPE)==0)
&& (pktlen==IPXH_HDRSIZE+2)
&& ((LookaheadBufferSize<IPXH_HDRSIZE+2)
||(*(LookaheadBuffer+IPXH_HDRSIZE+1)=='?'))) {
IPX_NODE_CPY (pktTag->PT_Target.MacAddress,
RemoteAddress->MacAddress);
pktTag->PT_SourceIf = srcIf;
AcquireInterfaceReference (srcIf);
pktTag->PT_Flags |= PT_SOURCE_IF;
}
}
KeReleaseSpinLock (&dstIf->ICB_Lock, oldIRQL);
ReleaseRouteReference (dstRoute);
goto GetPacket;
}
else { // Allocation failure
InterlockedIncrement (&dstIf->ICB_Stats.OutDiscards);
}
}
else {// Filtered out
if (action==FILTER_DENY_OUT)
InterlockedIncrement (&dstIf->ICB_Stats.OutFiltered);
else {
ASSERT (action==FILTER_DENY_IN);
InterlockedIncrement (&srcIf->ICB_Stats.InFiltered);
}
IpxFwdDbgPrint (DBG_RECV, DBG_WARNING,
("IpxFwd: Filtered out"
" packet on interface %ld (icb:%0lx),"
" dst-%ld (icb %08lx) %08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
srcIf->ICB_Index, srcIf, dstIf->ICB_Index, dstIf, dstNet,
LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
LookaheadBuffer[IPXH_PKTTYPE]));
}
}
else { // Destination interface is down
InterlockedIncrement (&srcIf->ICB_Stats.InDelivers);
InterlockedIncrement (&dstIf->ICB_Stats.OutDiscards);
IpxFwdDbgPrint (DBG_RECV, DBG_WARNING,
("IpxFwd: Dest interface %ld (icb %08lx) down"
" for packet on interface %ld (icb:%0lx),"
" dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
dstIf->ICB_Index, dstIf, srcIf->ICB_Index, srcIf, dstNet,
LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
LookaheadBuffer[IPXH_PKTTYPE]));
}
ReleaseInterfaceReference (dstIf);
ReleaseRouteReference (dstRoute);
}
else { // if netbios
// check that this is a netbios bcast packet and
// didnt exceed the limit of routers to traverse
// and we can accept it on this interface
if (srcIf->ICB_NetbiosAccept
&& (*(LookaheadBuffer + IPXH_XPORTCTL) < 8)) {
INT srcListId;
srcListId = srcIf->ICB_PacketListId;
KeReleaseSpinLock(&srcIf->ICB_Lock, oldIRQL);
// Check if packet is valid
if (IPX_NODE_CMP (LookaheadBuffer + IPXH_DESTNODE,
BROADCAST_NODE)==0) {
// Check if we haven't exceeded the quota
if (InterlockedDecrement (&NetbiosPacketsQuota)>=0) {
// try to get a packet from the rcv pkt pool
AllocatePacket (srcListId, srcListId, pktTag);
if (pktTag!=NULL) {
dstIf = srcIf;
AcquireInterfaceReference (dstIf);
goto GetPacket;
}
}
else {// Netbios quota exceded
IpxFwdDbgPrint (DBG_NETBIOS, DBG_WARNING,
("IpxFwd: Netbios quota exceded"
" for packet on interface %ld (icb:%0lx),"
" dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
srcIf->ICB_Index, srcIf, dstNet,
LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
LookaheadBuffer[IPXH_PKTTYPE]));
InterlockedIncrement (&srcIf->ICB_Stats.InDiscards);
}
InterlockedIncrement (&NetbiosPacketsQuota);
}
else { // Bad netbios packet
IpxFwdDbgPrint (DBG_NETBIOS, DBG_WARNING,
("IpxFwd: Bad nb packet on interface %ld (icb:%0lx),"
" dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
srcIf->ICB_Index, srcIf, dstNet,
LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
LookaheadBuffer[IPXH_PKTTYPE]));
InterlockedIncrement (&srcIf->ICB_Stats.InHdrErrors);
}
}
else { // Netbios accept disabled or to many routers crossed
KeReleaseSpinLock(&srcIf->ICB_Lock, oldIRQL);
InterlockedIncrement (&srcIf->ICB_Stats.InDiscards);
IpxFwdDbgPrint (DBG_NETBIOS, DBG_WARNING,
("IpxFwd: NB packet dropped on disabled interface %ld (icb:%0lx),"
" dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
srcIf->ICB_Index, srcIf, dstNet,
LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
LookaheadBuffer[IPXH_PKTTYPE]));
}
} // End netbios specific processing (else if netbios)
}
else { // Looped back packets discarded without counting
// (We shouldn't get them in IPX stack does the right job)
KeReleaseSpinLock(&srcIf->ICB_Lock, oldIRQL);
}
}
else { // Interface is down or disabled
KeReleaseSpinLock(&srcIf->ICB_Lock, oldIRQL);
InterlockedIncrement (&srcIf->ICB_Stats.InDiscards);
IpxFwdDbgPrint (DBG_RECV, DBG_WARNING,
("IpxFwd: Packet dropped on disabled interface %ld (icb:%0lx),"
" dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
srcIf->ICB_Index, srcIf, dstNet,
LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
LookaheadBuffer[IPXH_PKTTYPE]));
}
}
else { // Obvious header errors (shouldn't IPX do this for us ?
InterlockedIncrement (&srcIf->ICB_Stats.InHdrErrors);
IpxFwdDbgPrint (DBG_RECV, DBG_ERROR,
("IpxFwd: Header errors in packet on interface %ld (icb:%0lx),"
" dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
srcIf->ICB_Index, srcIf, dstNet,
LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
LookaheadBuffer[IPXH_PKTTYPE]));
}
ReleaseInterfaceReference (srcIf);
} // We could not locate the interface from IPX supplied context: there
// is just a little time window when interface is deleted
// but IPX had already pushed the context on the stack
else {
IpxFwdDbgPrint (DBG_RECV, DBG_ERROR,
("IpxFwd: Receive, type-%02x"
" - src interface context is invalid.\n",
LookaheadBuffer[IPXH_PKTTYPE]));
}
LeaveForwarder ();
return FALSE ;
GetPacket:
InterlockedIncrement (&srcIf->ICB_Stats.InDelivers);
ReleaseInterfaceReference (srcIf);
pktDscr = CONTAINING_RECORD (pktTag, NDIS_PACKET, ProtocolReserved);
pktTag->PT_InterfaceReference = dstIf;
pktTag->PT_PerfCounter = PerfCounter.QuadPart;
// try to get the packet data
IPXTransferData(&status,
MacBindingHandle,
MacReceiveContext,
LookaheadBufferOffset, // start of IPX header
PacketSize, // packet size starting at IPX header
pktDscr,
&BytesTransferred);
if (status != NDIS_STATUS_PENDING) {
// complete the frame processing (LeaveForwarder will be called there)
IpxFwdTransferDataComplete(pktDscr, status, BytesTransferred);
}
return FALSE;
}
/*++
*******************************************************************
F w T r a n s f e r D a t a C o m p l e t e
Routine Description:
Called by the IPX stack when NIC driver completes data transger.
Arguments:
pktDscr - handle of NIC driver
status - result of the transfer
bytesTransferred - number of bytest trasferred
Return Value:
None
*******************************************************************
--*/
VOID
IpxFwdTransferDataComplete (
PNDIS_PACKET pktDscr,
NDIS_STATUS status,
UINT bytesTransferred)
{
PPACKET_TAG pktTag;
pktTag = (PPACKET_TAG)(&pktDscr->ProtocolReserved);
// If transfer failed, release the packet and interface
//
if (status==NDIS_STATUS_SUCCESS)
{
if (*(pktTag->PT_Data + IPXH_PKTTYPE) != IPX_NETBIOS_TYPE)
{
// pmay: 260480
//
// Increment the transport control field so that
// the number of routers that this packet has
// traversed is increased. IpxFwdReceive will drop
// all packets that have traversed more that 15 routers.
//
// Netbios packets will have their transport control
// fields incremented by ProcessNetbiosPacket
//
*(pktTag->PT_Data + IPXH_XPORTCTL) += 1;
SendPacket (pktTag->PT_InterfaceReference, pktTag);
}
else
{
ProcessNetbiosPacket (pktTag->PT_InterfaceReference, pktTag);
}
}
else
{
IpxFwdDbgPrint (DBG_RECV, DBG_ERROR,
("IpxFwd: Trans data failed: packet %08lx on if %08lx!\n",
pktTag, pktTag->PT_InterfaceReference));
// Record the fact that we're discarding
//
if (*(pktTag->PT_Data + IPXH_PKTTYPE) != IPX_NETBIOS_TYPE)
{
InterlockedIncrement (
&pktTag->PT_InterfaceReference->ICB_Stats.OutDiscards);
}
// For netbios packets interface reference is
// actually a source interface
else
{
InterlockedIncrement (&NetbiosPacketsQuota);
InterlockedIncrement (
&pktTag->PT_InterfaceReference->ICB_Stats.InDiscards);
}
ReleaseInterfaceReference (pktTag->PT_InterfaceReference);
FreePacket (pktTag);
}
LeaveForwarder ();
return;
}
/*++
*******************************************************************
F w R e c e i v e C o m p l e t e
Routine Description:
This routine receives control from the IPX driver after one or
more receive operations have completed and no receive is in progress.
It is called under less severe time constraints than IpxFwdReceive.
It is used to process netbios queue
Arguments:
None
Return Value:
None
*******************************************************************
--*/
VOID
IpxFwdReceiveComplete (
USHORT NicId
) {
// check that our configuration process has terminated OK
if(!EnterForwarder ()) {
return;
}
IpxFwdDbgPrint (DBG_RECV, DBG_INFORMATION, ("IpxFwd: FwdReceiveComplete.\n"));
ScheduleNetbiosWorker ();
LeaveForwarder ();
}
/*++
*******************************************************************
I p x F w d I n t e r n a l R e c e i v e
Routine Description:
Called by the IPX stack to indicate that the IPX packet destined
to local client was received by the NIC dirver.
Arguments:
Context - forwarder context associated with
the NIC (interface block pointer)
RemoteAddress - sender's address
LookaheadBuffer - packet lookahead buffer that contains complete
IPX header
LookaheadBufferSize - its size (at least 30 bytes)
Return Value:
STATUS_SUCCESS - the packet will be delivered to local destination
STATUS_UNSUCCESSFUL - the packet will be dropped
*******************************************************************
--*/
NTSTATUS
IpxFwdInternalReceive (
IN ULONG_PTR Context,
IN PIPX_LOCAL_TARGET RemoteAddress,
IN PUCHAR LookAheadBuffer,
IN UINT LookAheadBufferSize
) {
NTSTATUS status = STATUS_SUCCESS;
PINTERFACE_CB srcIf;
if (!EnterForwarder ()) {
return STATUS_UNSUCCESSFUL;
}
if (Context!=VIRTUAL_NET_FORWARDER_CONTEXT) {
// Check if interface context supplied by IPX driver is valid
srcIf = InterfaceContextToReference ((PVOID)Context, RemoteAddress->NicId);
}
else {
srcIf = InternalInterface;
AcquireInterfaceReference (srcIf);
}
if (srcIf!=NULL) {
// Check if we can accept on this interface
if (IS_IF_ENABLED (srcIf)
&& (srcIf->ICB_Stats.OperationalState!=FWD_OPER_STATE_DOWN)
&& ((*(LookAheadBuffer + IPXH_PKTTYPE) != IPX_NETBIOS_TYPE)
|| srcIf->ICB_NetbiosAccept)) {
// Check if we can accept on internal interface
if (IS_IF_ENABLED(InternalInterface)) {
FILTER_ACTION action;
action = FltFilter (LookAheadBuffer, LookAheadBufferSize,
srcIf->ICB_FilterInContext,
InternalInterface->ICB_FilterOutContext);
// Check the filter
if (action==FILTER_PERMIT) {
// Update source interface statistics
InterlockedIncrement (&srcIf->ICB_Stats.InDelivers);
// Handle NB packets separatedly
if (*(LookAheadBuffer + IPXH_PKTTYPE) != IPX_NETBIOS_TYPE) {
InterlockedIncrement (
&InternalInterface->ICB_Stats.OutDelivers);
IpxFwdDbgPrint (DBG_INT_RECV, DBG_INFORMATION,
("IpxFwd: FwdInternalReceive,"
" from %d(%lx)-%.2x%.2x%.2x%.2x:%.2x%.2x%.2x%.2x%.2x%.2x,"
" type-%02x.\n",
srcIf->ICB_Index, srcIf,
LookAheadBuffer[IPXH_SRCNET],LookAheadBuffer[IPXH_SRCNET+1],
LookAheadBuffer[IPXH_SRCNET+2],LookAheadBuffer[IPXH_SRCNET+3],
LookAheadBuffer[IPXH_SRCNODE],LookAheadBuffer[IPXH_SRCNODE+1],
LookAheadBuffer[IPXH_SRCNODE+2],LookAheadBuffer[IPXH_SRCNODE+3],
LookAheadBuffer[IPXH_SRCNODE+4],LookAheadBuffer[IPXH_SRCNODE+5],
LookAheadBuffer[IPXH_PKTTYPE]));
}
else {
// Check if destination netbios name is staticly assigned to
// an external interface or netbios delivery options do not
// allow us to deliver this packet
PINTERFACE_CB dstIf;
USHORT dstSock = GETUSHORT (LookAheadBuffer+IPXH_DESTSOCK);
InterlockedIncrement (&srcIf->ICB_Stats.NetbiosReceived);
// First try to find a static name if we have enough data
// in the lookahead buffer
if ((dstSock==IPX_NETBIOS_SOCKET)
&& (LookAheadBufferSize>(NB_NAME+16)))
dstIf = FindNBDestination (LookAheadBuffer+(NB_NAME-IPXH_HDRSIZE));
else if ((dstSock==IPX_SMB_NAME_SOCKET)
&& (LookAheadBufferSize>(SMB_NAME+16)))
dstIf = FindNBDestination (LookAheadBuffer+(SMB_NAME-IPXH_HDRSIZE));
else
dstIf = NULL;
// Now see, if we can deliver the packet
if ((((dstIf==NULL) || (dstIf==InternalInterface))
&& (InternalInterface->ICB_NetbiosDeliver==FWD_NB_DELIVER_ALL))
|| ((dstIf==InternalInterface)
&& (InternalInterface->ICB_NetbiosDeliver==FWD_NB_DELIVER_STATIC))) {
InterlockedIncrement (
&InternalInterface->ICB_Stats.NetbiosSent);
InterlockedIncrement (
&InternalInterface->ICB_Stats.OutDelivers);
IpxFwdDbgPrint (DBG_INT_RECV, DBG_INFORMATION,
("IpxFwd: FwdInternalReceive, NB"
" from %d(%lx)-%.2x%.2x%.2x%.2x:%.2x%.2x%.2x%.2x%.2x%.2x\n",
srcIf->ICB_Index, srcIf,
LookAheadBuffer[IPXH_SRCNET],LookAheadBuffer[IPXH_SRCNET+1],
LookAheadBuffer[IPXH_SRCNET+2],LookAheadBuffer[IPXH_SRCNET+3],
LookAheadBuffer[IPXH_SRCNODE],LookAheadBuffer[IPXH_SRCNODE+1],
LookAheadBuffer[IPXH_SRCNODE+2],LookAheadBuffer[IPXH_SRCNODE+3],
LookAheadBuffer[IPXH_SRCNODE+4],LookAheadBuffer[IPXH_SRCNODE+5]));
}
else {
InterlockedIncrement (
&InternalInterface->ICB_Stats.OutDiscards);
IpxFwdDbgPrint (DBG_INT_RECV, DBG_WARNING,
("IpxFwd: FwdInternalReceive, NB dropped because delivery disabled"
" from %d(%lx)-%.2x%.2x%.2x%.2x:%.2x%.2x%.2x%.2x%.2x%.2x\n",
srcIf->ICB_Index, srcIf,
LookAheadBuffer[IPXH_SRCNET],LookAheadBuffer[IPXH_SRCNET+1],
LookAheadBuffer[IPXH_SRCNET+2],LookAheadBuffer[IPXH_SRCNET+3],
LookAheadBuffer[IPXH_SRCNODE],LookAheadBuffer[IPXH_SRCNODE+1],
LookAheadBuffer[IPXH_SRCNODE+2],LookAheadBuffer[IPXH_SRCNODE+3],
LookAheadBuffer[IPXH_SRCNODE+4],LookAheadBuffer[IPXH_SRCNODE+5]));
status = STATUS_UNSUCCESSFUL;
}
if (dstIf!=NULL)
ReleaseInterfaceReference (dstIf);
}
}
else {// Filtered Out
if (action==FILTER_DENY_OUT) {
InterlockedIncrement (
&InternalInterface->ICB_Stats.OutFiltered);
status=STATUS_UNSUCCESSFUL;
}
else {
ASSERT (action==FILTER_DENY_IN);
InterlockedIncrement (&srcIf->ICB_Stats.InFiltered);
status=STATUS_UNSUCCESSFUL;
}
IpxFwdDbgPrint (DBG_INT_RECV, DBG_WARNING,
("IpxFwd: FwdInternalReceive, filtered out"
" from %d(%lx)-%.2x%.2x%.2x%.2x:%.2x%.2x%.2x%.2x%.2x%.2x,"
" type-%02x.\n",
srcIf->ICB_Index, srcIf,
LookAheadBuffer[IPXH_SRCNET],LookAheadBuffer[IPXH_SRCNET+1],
LookAheadBuffer[IPXH_SRCNET+2],LookAheadBuffer[IPXH_SRCNET+3],
LookAheadBuffer[IPXH_SRCNODE],LookAheadBuffer[IPXH_SRCNODE+1],
LookAheadBuffer[IPXH_SRCNODE+2],LookAheadBuffer[IPXH_SRCNODE+3],
LookAheadBuffer[IPXH_SRCNODE+4],LookAheadBuffer[IPXH_SRCNODE+5],
LookAheadBuffer[IPXH_PKTTYPE]));
}
}
else {// Internal interface is disabled
InterlockedIncrement (
&InternalInterface->ICB_Stats.OutDiscards);
status = STATUS_UNSUCCESSFUL;
IpxFwdDbgPrint (DBG_INT_RECV, DBG_WARNING,
("IpxFwd: FwdInternalReceive, internal if disabled"
" from %d(%lx)-%.2x%.2x%.2x%.2x:%.2x%.2x%.2x%.2x%.2x%.2x,"
" type-%02x.\n",
srcIf->ICB_Index, srcIf,
LookAheadBuffer[IPXH_SRCNET],LookAheadBuffer[IPXH_SRCNET+1],
LookAheadBuffer[IPXH_SRCNET+2],LookAheadBuffer[IPXH_SRCNET+3],
LookAheadBuffer[IPXH_SRCNODE],LookAheadBuffer[IPXH_SRCNODE+1],
LookAheadBuffer[IPXH_SRCNODE+2],LookAheadBuffer[IPXH_SRCNODE+3],
LookAheadBuffer[IPXH_SRCNODE+4],LookAheadBuffer[IPXH_SRCNODE+5],
LookAheadBuffer[IPXH_PKTTYPE]));
}
}
else { // Disabled source interface
InterlockedIncrement (&srcIf->ICB_Stats.InDiscards);
IpxFwdDbgPrint (DBG_INT_RECV, DBG_ERROR,
("IpxFwd: FwdInternalReceive, source if disabled"
" from %d(%lx)-%.2x%.2x%.2x%.2x:%.2x%.2x%.2x%.2x%.2x%.2x,"
" type-%02x.\n",
srcIf->ICB_Index, srcIf,
LookAheadBuffer[IPXH_SRCNET],LookAheadBuffer[IPXH_SRCNET+1],
LookAheadBuffer[IPXH_SRCNET+2],LookAheadBuffer[IPXH_SRCNET+3],
LookAheadBuffer[IPXH_SRCNODE],LookAheadBuffer[IPXH_SRCNODE+1],
LookAheadBuffer[IPXH_SRCNODE+2],LookAheadBuffer[IPXH_SRCNODE+3],
LookAheadBuffer[IPXH_SRCNODE+4],LookAheadBuffer[IPXH_SRCNODE+5],
LookAheadBuffer[IPXH_PKTTYPE]));
status = STATUS_UNSUCCESSFUL;
}
ReleaseInterfaceReference (srcIf);
}
else { // Invalid source interface context
IpxFwdDbgPrint (DBG_INT_RECV, DBG_ERROR,
("IpxFwd: FwdInternalReceive, source if context is invalid"
" from (%lx:%d)-%.2x%.2x%.2x%.2x:%.2x%.2x%.2x%.2x%.2x%.2x,"
" type-%02x.\n",
Context, RemoteAddress->NicId,
LookAheadBuffer[IPXH_SRCNET],LookAheadBuffer[IPXH_SRCNET+1],
LookAheadBuffer[IPXH_SRCNET+2],LookAheadBuffer[IPXH_SRCNET+3],
LookAheadBuffer[IPXH_SRCNODE],LookAheadBuffer[IPXH_SRCNODE+1],
LookAheadBuffer[IPXH_SRCNODE+2],LookAheadBuffer[IPXH_SRCNODE+3],
LookAheadBuffer[IPXH_SRCNODE+4],LookAheadBuffer[IPXH_SRCNODE+5],
LookAheadBuffer[IPXH_PKTTYPE]));
status = STATUS_UNSUCCESSFUL;
}
LeaveForwarder ();
return status;
}
/*++
*******************************************************************
D e l e t e R e c v Q u e u e
Routine Description:
Initializes the netbios bradcast queue
Arguments:
None
Return Value:
None
*******************************************************************
--*/
VOID
DeleteRecvQueue (
void
) {
// while (!IsListEmpty (&RecvQueue)) {
// PPACKET_TAG pktTag = CONTAINING_RECORD (RecvQueue.Flink,
// PACKET_TAG,
// PT_QueueLink);
// RemoveEntryList (&pktTag->PT_QueueLink);
// if (pktTag->PT_InterfaceReference!=NULL) {
// ReleaseInterfaceReference (pktTag->PT_InterfaceReference);
// }
// FreePacket (pktTag);
// }
}
#if DBG
ULONG DbgFilterTrap = 0; // 1 - on dst and src (net + node),
// 2 - on dst (net + node),
// 3 - on src (net + node),
// 4 - on dst (net + node + socket)
UCHAR DbgFilterDstNet[4];
UCHAR DbgFilterDstNode[6];
UCHAR DbgFilterDstSocket[2];
UCHAR DbgFilterSrcNet[4];
UCHAR DbgFilterSrcNode[6];
UCHAR DbgFilterSrcSocket[2];
PUCHAR DbgFilterFrame;
VOID
DbgFilterReceivedPacket(PUCHAR hdrp)
{
switch(DbgFilterTrap) {
case 1:
if(!memcmp(hdrp + IPXH_DESTNET, DbgFilterDstNet, 4) &&
!memcmp(hdrp + IPXH_DESTNODE, DbgFilterDstNode, 6) &&
!memcmp(hdrp + IPXH_SRCNET, DbgFilterSrcNet, 4) &&
!memcmp(hdrp + IPXH_SRCNODE, DbgFilterSrcNode, 6)) {
DbgBreakPoint();
}
break;
case 2:
if(!memcmp(hdrp + IPXH_DESTNET, DbgFilterDstNet, 4) &&
!memcmp(hdrp + IPXH_DESTNODE, DbgFilterDstNode, 6)) {
DbgBreakPoint();
}
break;
case 3:
if(!memcmp(hdrp + IPXH_SRCNET, DbgFilterSrcNet, 4) &&
!memcmp(hdrp + IPXH_SRCNODE, DbgFilterSrcNode, 6)) {
DbgBreakPoint();
}
break;
case 4:
if(!memcmp(hdrp + IPXH_DESTNET, DbgFilterDstNet, 4) &&
!memcmp(hdrp + IPXH_DESTNODE, DbgFilterDstNode, 6) &&
!memcmp(hdrp + IPXH_DESTSOCK, DbgFilterDstSocket, 2)) {
DbgBreakPoint();
}
break;
default:
break;
}
DbgFilterFrame = hdrp;
}
#endif