diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/tdi/isn/fwd/rcvind.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/tdi/isn/fwd/rcvind.c')
-rw-r--r-- | private/ntos/tdi/isn/fwd/rcvind.c | 825 |
1 files changed, 825 insertions, 0 deletions
diff --git a/private/ntos/tdi/isn/fwd/rcvind.c b/private/ntos/tdi/isn/fwd/rcvind.c new file mode 100644 index 000000000..7c4bc2d39 --- /dev/null +++ b/private/ntos/tdi/isn/fwd/rcvind.c @@ -0,0 +1,825 @@ +/*++ + +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 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) + SendPacket (pktTag->PT_InterfaceReference, pktTag); + else + ProcessNetbiosPacket (pktTag->PT_InterfaceReference, pktTag); + + } + else { + IpxFwdDbgPrint (DBG_RECV, DBG_ERROR, + ("IpxFwd: Transfer data failed for packet %08lx on interface %08lx!\n", + pktTag, pktTag->PT_InterfaceReference)); + if (*(pktTag->PT_Data + IPXH_PKTTYPE) != IPX_NETBIOS_TYPE) { + InterlockedIncrement ( + &pktTag->PT_InterfaceReference->ICB_Stats.OutDiscards); + } + else { // For netbios packets interface reference is + // actually a source interface + 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 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); + else { + ASSERT (action==FILTER_DENY_IN); + InterlockedIncrement (&srcIf->ICB_Stats.InFiltered); + } + 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 + |