Source code of Windows XP (NT5)
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.

855 lines
29 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. ntos\tdi\isn\fwd\rcvind.c
  5. Abstract:
  6. Receive indication processing
  7. Author:
  8. Vadim Eydelman
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #if DBG
  13. VOID
  14. DbgFilterReceivedPacket(PUCHAR hdrp);
  15. #endif
  16. // Doesn't allow accepting packets (for routing) from dial-in clients
  17. BOOLEAN ThisMachineOnly = FALSE;
  18. /*++
  19. *******************************************************************
  20. F w R e c e i v e
  21. Routine Description:
  22. Called by the IPX stack to indicate that the IPX packet was
  23. received by the NIC dirver. Only external destined packets are
  24. indicated by this routine (with the exception of Netbios boradcasts
  25. that indicated both for internal and external handlers)
  26. Arguments:
  27. MacBindingHandle - handle of NIC driver
  28. MaxReceiveContext - NIC driver context
  29. RemoteAddress - sender's address
  30. MacOptions -
  31. LookaheadBuffer - packet lookahead buffer that contains complete
  32. IPX header
  33. LookaheadBufferSize - its size (at least 30 bytes)
  34. LookaheadBufferOffset - offset of lookahead buffer in the physical
  35. packet
  36. Return Value:
  37. TRUE if we take the MDL chain to return later with NdisReturnPacket
  38. *******************************************************************
  39. --*/
  40. BOOLEAN
  41. IpxFwdReceive (
  42. NDIS_HANDLE MacBindingHandle,
  43. NDIS_HANDLE MacReceiveContext,
  44. ULONG_PTR Context,
  45. PIPX_LOCAL_TARGET RemoteAddress,
  46. ULONG MacOptions,
  47. PUCHAR LookaheadBuffer,
  48. UINT LookaheadBufferSize,
  49. UINT LookaheadBufferOffset,
  50. UINT PacketSize,
  51. PMDL pMdl)
  52. {
  53. PINTERFACE_CB srcIf, dstIf;
  54. PPACKET_TAG pktTag;
  55. PNDIS_PACKET pktDscr;
  56. NDIS_STATUS status;
  57. UINT BytesTransferred;
  58. LARGE_INTEGER PerfCounter;
  59. // check that our configuration process has terminated OK
  60. if (!EnterForwarder ()) {
  61. return FALSE;
  62. }
  63. if (!MeasuringPerformance) {
  64. PerfCounter.QuadPart = 0;
  65. }
  66. else {
  67. #if DBG
  68. static LONGLONG LastCall = 0;
  69. KIRQL oldIRQL;
  70. #endif
  71. PerfCounter = KeQueryPerformanceCounter (NULL);
  72. #if DBG
  73. KeAcquireSpinLock (&PerfCounterLock, &oldIRQL);
  74. ASSERT (PerfCounter.QuadPart-LastCall<ActivityTreshhold);
  75. LastCall = PerfCounter.QuadPart;
  76. KeReleaseSpinLock (&PerfCounterLock, oldIRQL);
  77. #endif
  78. }
  79. IpxFwdDbgPrint (DBG_RECV, DBG_INFORMATION,
  80. ("IpxFwd: FwdReceive on %0lx,"
  81. " dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
  82. Context, GETULONG (LookaheadBuffer+IPXH_DESTNET),
  83. LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
  84. LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
  85. LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
  86. LookaheadBuffer[IPXH_PKTTYPE]));
  87. #if DBG
  88. DbgFilterReceivedPacket (LookaheadBuffer);
  89. #endif
  90. srcIf = InterfaceContextToReference ((PVOID)Context, RemoteAddress->NicId);
  91. // Check if interface is valid
  92. if (srcIf!=NULL) {
  93. USHORT pktlen;
  94. ULONG dstNet;
  95. KIRQL oldIRQL;
  96. dstNet = GETULONG (LookaheadBuffer + IPXH_DESTNET);
  97. pktlen = GETUSHORT(LookaheadBuffer + IPXH_LENGTH);
  98. // check if we got the whole IPX header in the lookahead buffer
  99. if ((LookaheadBufferSize >= IPXH_HDRSIZE)
  100. && (*(LookaheadBuffer + IPXH_XPORTCTL) < 16)
  101. && (pktlen<=PacketSize)) {
  102. // Lock interface CB to ensure coherency of information in it
  103. KeAcquireSpinLock(&srcIf->ICB_Lock, &oldIRQL);
  104. // Check if shoud accept packets on this interface
  105. if (IS_IF_ENABLED(srcIf)
  106. && (srcIf->ICB_Stats.OperationalState!=FWD_OPER_STATE_DOWN)
  107. && (!ThisMachineOnly
  108. || (srcIf->ICB_InterfaceType
  109. !=FWD_IF_REMOTE_WORKSTATION))) {
  110. // Check for looped back packets
  111. if (IPX_NODE_CMP (RemoteAddress->MacAddress,
  112. srcIf->ICB_LocalNode)!=0) {
  113. // Separate processing of netbios broadcast packets (20)
  114. if (*(LookaheadBuffer + IPXH_PKTTYPE) != IPX_NETBIOS_TYPE) {
  115. PFWD_ROUTE dstRoute;
  116. INT srcListId, dstListId;
  117. // Temp IPX bug fix, they shou;d ensure that
  118. // we only get packets that can be routed
  119. if ((dstNet==srcIf->ICB_Network)
  120. || (dstNet==InternalInterface->ICB_Network)) {
  121. InterlockedIncrement (&srcIf->ICB_Stats.InDiscards);
  122. KeReleaseSpinLock(&srcIf->ICB_Lock, oldIRQL);
  123. ReleaseInterfaceReference (srcIf);
  124. LeaveForwarder ();
  125. return FALSE;
  126. }
  127. // ASSERT (dstNet!=srcIf->ICB_Network);
  128. // ASSERT ((InternalInterface==NULL)
  129. // || (InternalInterface->ICB_Network==0)
  130. // || (dstNet!=InternalInterface->ICB_Network));
  131. // Check if needed route is in cash
  132. if ((srcIf->ICB_CashedRoute!=NULL)
  133. && (dstNet==srcIf->ICB_CashedRoute->FR_Network)
  134. // If route was changed or deleted, this will fail
  135. && (srcIf->ICB_CashedRoute->FR_InterfaceReference
  136. ==srcIf->ICB_CashedInterface)) {
  137. dstIf = srcIf->ICB_CashedInterface;
  138. dstRoute = srcIf->ICB_CashedRoute;
  139. AcquireInterfaceReference (dstIf);
  140. AcquireRouteReference (dstRoute);
  141. IpxFwdDbgPrint (DBG_RECV, DBG_INFORMATION,
  142. ("IpxFwd: Destination in cash.\n"));
  143. }
  144. else { // Find and cash the route
  145. dstIf = FindDestination (dstNet,
  146. LookaheadBuffer+IPXH_DESTNODE,
  147. &dstRoute
  148. );
  149. if (dstIf!=NULL) { // If route is found
  150. IpxFwdDbgPrint (DBG_RECV, DBG_INFORMATION,
  151. ("IpxFwd: Found destination %0lx.\n", dstIf));
  152. // Don't cash global wan clients and
  153. // routes to the same net
  154. if ((dstNet!=GlobalNetwork)
  155. && (dstIf!=srcIf)) {
  156. if (srcIf->ICB_CashedInterface!=NULL)
  157. ReleaseInterfaceReference (srcIf->ICB_CashedInterface);
  158. if (srcIf->ICB_CashedRoute!=NULL)
  159. ReleaseRouteReference (srcIf->ICB_CashedRoute);
  160. srcIf->ICB_CashedInterface = dstIf;
  161. srcIf->ICB_CashedRoute = dstRoute;
  162. AcquireInterfaceReference (dstIf);
  163. AcquireRouteReference (dstRoute);
  164. }
  165. }
  166. else { // No route
  167. InterlockedIncrement (&srcIf->ICB_Stats.InNoRoutes);
  168. KeReleaseSpinLock(&srcIf->ICB_Lock, oldIRQL);
  169. IpxFwdDbgPrint (DBG_RECV, DBG_WARNING,
  170. ("IpxFwd: No route for packet on interface %ld (icb:%0lx),"
  171. " dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
  172. srcIf->ICB_Index, srcIf, dstNet,
  173. LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
  174. LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
  175. LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
  176. LookaheadBuffer[IPXH_PKTTYPE]));
  177. ReleaseInterfaceReference (srcIf);
  178. LeaveForwarder ();
  179. return FALSE;
  180. }
  181. }
  182. srcListId = srcIf->ICB_PacketListId;
  183. KeReleaseSpinLock(&srcIf->ICB_Lock, oldIRQL);
  184. // Check if destination if can take the packet
  185. if (IS_IF_ENABLED (dstIf)
  186. // If interface is UP check packet againts actual size limit
  187. && (((dstIf->ICB_Stats.OperationalState==FWD_OPER_STATE_UP)
  188. && (PacketSize<=dstIf->ICB_Stats.MaxPacketSize))
  189. // if sleeping (WAN), check we can allocate it from WAN list
  190. || ((dstIf->ICB_Stats.OperationalState==FWD_OPER_STATE_SLEEPING)
  191. && (PacketSize<=WAN_PACKET_SIZE))
  192. // otherwise, interface is down and we can't take the packet
  193. ) ){
  194. FILTER_ACTION action;
  195. action = FltFilter (LookaheadBuffer, LookaheadBufferSize,
  196. srcIf->ICB_FilterInContext,
  197. dstIf->ICB_FilterOutContext);
  198. if (action==FILTER_PERMIT) {
  199. InterlockedIncrement (&srcIf->ICB_Stats.InDelivers);
  200. dstListId = dstIf->ICB_PacketListId;
  201. // try to get a packet from the rcv pkt pool
  202. AllocatePacket (srcListId, dstListId, pktTag);
  203. if (pktTag!=NULL) {
  204. // Set destination mac in local target if
  205. // possible
  206. KeAcquireSpinLock (&dstIf->ICB_Lock, &oldIRQL);
  207. if (dstIf->ICB_InterfaceType==FWD_IF_PERMANENT) {
  208. // Permanent interface: send to the next
  209. // hop router if net is not directly connected
  210. // or to the dest node otherwise
  211. if (dstNet!=dstIf->ICB_Network) {
  212. IPX_NODE_CPY (pktTag->PT_Target.MacAddress,
  213. dstRoute->FR_NextHopAddress);
  214. }
  215. else {
  216. IPX_NODE_CPY (pktTag->PT_Target.MacAddress,
  217. LookaheadBuffer+IPXH_DESTNODE);
  218. }
  219. }
  220. else { // Demand dial interface: assumed to be
  221. // point to point connection -> send to
  222. // the other party if connection has already
  223. // been made, otherwise wait till connected
  224. if (dstIf->ICB_Stats.OperationalState
  225. == FWD_OPER_STATE_UP) {
  226. IPX_NODE_CPY (pktTag->PT_Target.MacAddress,
  227. dstIf->ICB_RemoteNode);
  228. } // Copy source mac address and nic id in case
  229. // we need to spoof this packet
  230. else if ((*(LookaheadBuffer+IPXH_PKTTYPE)==0)
  231. && (pktlen==IPXH_HDRSIZE+2)
  232. && ((LookaheadBufferSize<IPXH_HDRSIZE+2)
  233. ||(*(LookaheadBuffer+IPXH_HDRSIZE+1)=='?'))) {
  234. IPX_NODE_CPY (pktTag->PT_Target.MacAddress,
  235. RemoteAddress->MacAddress);
  236. pktTag->PT_SourceIf = srcIf;
  237. AcquireInterfaceReference (srcIf);
  238. pktTag->PT_Flags |= PT_SOURCE_IF;
  239. }
  240. }
  241. KeReleaseSpinLock (&dstIf->ICB_Lock, oldIRQL);
  242. ReleaseRouteReference (dstRoute);
  243. goto GetPacket;
  244. }
  245. else { // Allocation failure
  246. InterlockedIncrement (&dstIf->ICB_Stats.OutDiscards);
  247. }
  248. }
  249. else {// Filtered out
  250. if (action==FILTER_DENY_OUT)
  251. InterlockedIncrement (&dstIf->ICB_Stats.OutFiltered);
  252. else {
  253. ASSERT (action==FILTER_DENY_IN);
  254. InterlockedIncrement (&srcIf->ICB_Stats.InFiltered);
  255. }
  256. IpxFwdDbgPrint (DBG_RECV, DBG_WARNING,
  257. ("IpxFwd: Filtered out"
  258. " packet on interface %ld (icb:%0lx),"
  259. " dst-%ld (icb %08lx) %08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
  260. srcIf->ICB_Index, srcIf, dstIf->ICB_Index, dstIf, dstNet,
  261. LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
  262. LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
  263. LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
  264. LookaheadBuffer[IPXH_PKTTYPE]));
  265. }
  266. }
  267. else { // Destination interface is down
  268. InterlockedIncrement (&srcIf->ICB_Stats.InDelivers);
  269. InterlockedIncrement (&dstIf->ICB_Stats.OutDiscards);
  270. IpxFwdDbgPrint (DBG_RECV, DBG_WARNING,
  271. ("IpxFwd: Dest interface %ld (icb %08lx) down"
  272. " for packet on interface %ld (icb:%0lx),"
  273. " dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
  274. dstIf->ICB_Index, dstIf, srcIf->ICB_Index, srcIf, dstNet,
  275. LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
  276. LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
  277. LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
  278. LookaheadBuffer[IPXH_PKTTYPE]));
  279. }
  280. ReleaseInterfaceReference (dstIf);
  281. ReleaseRouteReference (dstRoute);
  282. }
  283. else { // if netbios
  284. // check that this is a netbios bcast packet and
  285. // didnt exceed the limit of routers to traverse
  286. // and we can accept it on this interface
  287. if (srcIf->ICB_NetbiosAccept
  288. && (*(LookaheadBuffer + IPXH_XPORTCTL) < 8)) {
  289. INT srcListId;
  290. srcListId = srcIf->ICB_PacketListId;
  291. KeReleaseSpinLock(&srcIf->ICB_Lock, oldIRQL);
  292. // Check if packet is valid
  293. if (IPX_NODE_CMP (LookaheadBuffer + IPXH_DESTNODE,
  294. BROADCAST_NODE)==0) {
  295. // Check if we haven't exceeded the quota
  296. if (InterlockedDecrement (&NetbiosPacketsQuota)>=0) {
  297. // try to get a packet from the rcv pkt pool
  298. AllocatePacket (srcListId, srcListId, pktTag);
  299. if (pktTag!=NULL) {
  300. dstIf = srcIf;
  301. AcquireInterfaceReference (dstIf);
  302. goto GetPacket;
  303. }
  304. }
  305. else {// Netbios quota exceded
  306. IpxFwdDbgPrint (DBG_NETBIOS, DBG_WARNING,
  307. ("IpxFwd: Netbios quota exceded"
  308. " for packet on interface %ld (icb:%0lx),"
  309. " dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
  310. srcIf->ICB_Index, srcIf, dstNet,
  311. LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
  312. LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
  313. LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
  314. LookaheadBuffer[IPXH_PKTTYPE]));
  315. InterlockedIncrement (&srcIf->ICB_Stats.InDiscards);
  316. }
  317. InterlockedIncrement (&NetbiosPacketsQuota);
  318. }
  319. else { // Bad netbios packet
  320. IpxFwdDbgPrint (DBG_NETBIOS, DBG_WARNING,
  321. ("IpxFwd: Bad nb packet on interface %ld (icb:%0lx),"
  322. " dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
  323. srcIf->ICB_Index, srcIf, dstNet,
  324. LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
  325. LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
  326. LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
  327. LookaheadBuffer[IPXH_PKTTYPE]));
  328. InterlockedIncrement (&srcIf->ICB_Stats.InHdrErrors);
  329. }
  330. }
  331. else { // Netbios accept disabled or to many routers crossed
  332. KeReleaseSpinLock(&srcIf->ICB_Lock, oldIRQL);
  333. InterlockedIncrement (&srcIf->ICB_Stats.InDiscards);
  334. IpxFwdDbgPrint (DBG_NETBIOS, DBG_WARNING,
  335. ("IpxFwd: NB packet dropped on disabled interface %ld (icb:%0lx),"
  336. " dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
  337. srcIf->ICB_Index, srcIf, dstNet,
  338. LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
  339. LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
  340. LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
  341. LookaheadBuffer[IPXH_PKTTYPE]));
  342. }
  343. } // End netbios specific processing (else if netbios)
  344. }
  345. else { // Looped back packets discarded without counting
  346. // (We shouldn't get them in IPX stack does the right job)
  347. KeReleaseSpinLock(&srcIf->ICB_Lock, oldIRQL);
  348. }
  349. }
  350. else { // Interface is down or disabled
  351. KeReleaseSpinLock(&srcIf->ICB_Lock, oldIRQL);
  352. InterlockedIncrement (&srcIf->ICB_Stats.InDiscards);
  353. IpxFwdDbgPrint (DBG_RECV, DBG_WARNING,
  354. ("IpxFwd: Packet dropped on disabled interface %ld (icb:%0lx),"
  355. " dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
  356. srcIf->ICB_Index, srcIf, dstNet,
  357. LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
  358. LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
  359. LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
  360. LookaheadBuffer[IPXH_PKTTYPE]));
  361. }
  362. }
  363. else { // Obvious header errors (shouldn't IPX do this for us ?
  364. InterlockedIncrement (&srcIf->ICB_Stats.InHdrErrors);
  365. IpxFwdDbgPrint (DBG_RECV, DBG_ERROR,
  366. ("IpxFwd: Header errors in packet on interface %ld (icb:%0lx),"
  367. " dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
  368. srcIf->ICB_Index, srcIf, dstNet,
  369. LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
  370. LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
  371. LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
  372. LookaheadBuffer[IPXH_PKTTYPE]));
  373. }
  374. ReleaseInterfaceReference (srcIf);
  375. } // We could not locate the interface from IPX supplied context: there
  376. // is just a little time window when interface is deleted
  377. // but IPX had already pushed the context on the stack
  378. else {
  379. IpxFwdDbgPrint (DBG_RECV, DBG_ERROR,
  380. ("IpxFwd: Receive, type-%02x"
  381. " - src interface context is invalid.\n",
  382. LookaheadBuffer[IPXH_PKTTYPE]));
  383. }
  384. LeaveForwarder ();
  385. return FALSE ;
  386. GetPacket:
  387. InterlockedIncrement (&srcIf->ICB_Stats.InDelivers);
  388. ReleaseInterfaceReference (srcIf);
  389. pktDscr = CONTAINING_RECORD (pktTag, NDIS_PACKET, ProtocolReserved);
  390. pktTag->PT_InterfaceReference = dstIf;
  391. pktTag->PT_PerfCounter = PerfCounter.QuadPart;
  392. // try to get the packet data
  393. IPXTransferData(&status,
  394. MacBindingHandle,
  395. MacReceiveContext,
  396. LookaheadBufferOffset, // start of IPX header
  397. PacketSize, // packet size starting at IPX header
  398. pktDscr,
  399. &BytesTransferred);
  400. if (status != NDIS_STATUS_PENDING) {
  401. // complete the frame processing (LeaveForwarder will be called there)
  402. IpxFwdTransferDataComplete(pktDscr, status, BytesTransferred);
  403. }
  404. return FALSE;
  405. }
  406. /*++
  407. *******************************************************************
  408. F w T r a n s f e r D a t a C o m p l e t e
  409. Routine Description:
  410. Called by the IPX stack when NIC driver completes data transger.
  411. Arguments:
  412. pktDscr - handle of NIC driver
  413. status - result of the transfer
  414. bytesTransferred - number of bytest trasferred
  415. Return Value:
  416. None
  417. *******************************************************************
  418. --*/
  419. VOID
  420. IpxFwdTransferDataComplete (
  421. PNDIS_PACKET pktDscr,
  422. NDIS_STATUS status,
  423. UINT bytesTransferred)
  424. {
  425. PPACKET_TAG pktTag;
  426. pktTag = (PPACKET_TAG)(&pktDscr->ProtocolReserved);
  427. // If transfer failed, release the packet and interface
  428. //
  429. if (status==NDIS_STATUS_SUCCESS)
  430. {
  431. if (*(pktTag->PT_Data + IPXH_PKTTYPE) != IPX_NETBIOS_TYPE)
  432. {
  433. // pmay: 260480
  434. //
  435. // Increment the transport control field so that
  436. // the number of routers that this packet has
  437. // traversed is increased. IpxFwdReceive will drop
  438. // all packets that have traversed more that 15 routers.
  439. //
  440. // Netbios packets will have their transport control
  441. // fields incremented by ProcessNetbiosPacket
  442. //
  443. *(pktTag->PT_Data + IPXH_XPORTCTL) += 1;
  444. SendPacket (pktTag->PT_InterfaceReference, pktTag);
  445. }
  446. else
  447. {
  448. ProcessNetbiosPacket (pktTag->PT_InterfaceReference, pktTag);
  449. }
  450. }
  451. else
  452. {
  453. IpxFwdDbgPrint (DBG_RECV, DBG_ERROR,
  454. ("IpxFwd: Trans data failed: packet %08lx on if %08lx!\n",
  455. pktTag, pktTag->PT_InterfaceReference));
  456. // Record the fact that we're discarding
  457. //
  458. if (*(pktTag->PT_Data + IPXH_PKTTYPE) != IPX_NETBIOS_TYPE)
  459. {
  460. InterlockedIncrement (
  461. &pktTag->PT_InterfaceReference->ICB_Stats.OutDiscards);
  462. }
  463. // For netbios packets interface reference is
  464. // actually a source interface
  465. else
  466. {
  467. InterlockedIncrement (&NetbiosPacketsQuota);
  468. InterlockedIncrement (
  469. &pktTag->PT_InterfaceReference->ICB_Stats.InDiscards);
  470. }
  471. ReleaseInterfaceReference (pktTag->PT_InterfaceReference);
  472. FreePacket (pktTag);
  473. }
  474. LeaveForwarder ();
  475. return;
  476. }
  477. /*++
  478. *******************************************************************
  479. F w R e c e i v e C o m p l e t e
  480. Routine Description:
  481. This routine receives control from the IPX driver after one or
  482. more receive operations have completed and no receive is in progress.
  483. It is called under less severe time constraints than IpxFwdReceive.
  484. It is used to process netbios queue
  485. Arguments:
  486. None
  487. Return Value:
  488. None
  489. *******************************************************************
  490. --*/
  491. VOID
  492. IpxFwdReceiveComplete (
  493. USHORT NicId
  494. ) {
  495. // check that our configuration process has terminated OK
  496. if(!EnterForwarder ()) {
  497. return;
  498. }
  499. IpxFwdDbgPrint (DBG_RECV, DBG_INFORMATION, ("IpxFwd: FwdReceiveComplete.\n"));
  500. ScheduleNetbiosWorker ();
  501. LeaveForwarder ();
  502. }
  503. /*++
  504. *******************************************************************
  505. I p x F w d I n t e r n a l R e c e i v e
  506. Routine Description:
  507. Called by the IPX stack to indicate that the IPX packet destined
  508. to local client was received by the NIC dirver.
  509. Arguments:
  510. Context - forwarder context associated with
  511. the NIC (interface block pointer)
  512. RemoteAddress - sender's address
  513. LookaheadBuffer - packet lookahead buffer that contains complete
  514. IPX header
  515. LookaheadBufferSize - its size (at least 30 bytes)
  516. Return Value:
  517. STATUS_SUCCESS - the packet will be delivered to local destination
  518. STATUS_UNSUCCESSFUL - the packet will be dropped
  519. *******************************************************************
  520. --*/
  521. NTSTATUS
  522. IpxFwdInternalReceive (
  523. IN ULONG_PTR Context,
  524. IN PIPX_LOCAL_TARGET RemoteAddress,
  525. IN PUCHAR LookAheadBuffer,
  526. IN UINT LookAheadBufferSize
  527. ) {
  528. NTSTATUS status = STATUS_SUCCESS;
  529. PINTERFACE_CB srcIf;
  530. if (!EnterForwarder ()) {
  531. return STATUS_UNSUCCESSFUL;
  532. }
  533. if (Context!=VIRTUAL_NET_FORWARDER_CONTEXT) {
  534. // Check if interface context supplied by IPX driver is valid
  535. srcIf = InterfaceContextToReference ((PVOID)Context, RemoteAddress->NicId);
  536. }
  537. else {
  538. srcIf = InternalInterface;
  539. AcquireInterfaceReference (srcIf);
  540. }
  541. if (srcIf!=NULL) {
  542. // Check if we can accept on this interface
  543. if (IS_IF_ENABLED (srcIf)
  544. && (srcIf->ICB_Stats.OperationalState!=FWD_OPER_STATE_DOWN)
  545. && ((*(LookAheadBuffer + IPXH_PKTTYPE) != IPX_NETBIOS_TYPE)
  546. || srcIf->ICB_NetbiosAccept)) {
  547. // Check if we can accept on internal interface
  548. if (IS_IF_ENABLED(InternalInterface)) {
  549. FILTER_ACTION action;
  550. action = FltFilter (LookAheadBuffer, LookAheadBufferSize,
  551. srcIf->ICB_FilterInContext,
  552. InternalInterface->ICB_FilterOutContext);
  553. // Check the filter
  554. if (action==FILTER_PERMIT) {
  555. // Update source interface statistics
  556. InterlockedIncrement (&srcIf->ICB_Stats.InDelivers);
  557. // Handle NB packets separatedly
  558. if (*(LookAheadBuffer + IPXH_PKTTYPE) != IPX_NETBIOS_TYPE) {
  559. InterlockedIncrement (
  560. &InternalInterface->ICB_Stats.OutDelivers);
  561. IpxFwdDbgPrint (DBG_INT_RECV, DBG_INFORMATION,
  562. ("IpxFwd: FwdInternalReceive,"
  563. " from %d(%lx)-%.2x%.2x%.2x%.2x:%.2x%.2x%.2x%.2x%.2x%.2x,"
  564. " type-%02x.\n",
  565. srcIf->ICB_Index, srcIf,
  566. LookAheadBuffer[IPXH_SRCNET],LookAheadBuffer[IPXH_SRCNET+1],
  567. LookAheadBuffer[IPXH_SRCNET+2],LookAheadBuffer[IPXH_SRCNET+3],
  568. LookAheadBuffer[IPXH_SRCNODE],LookAheadBuffer[IPXH_SRCNODE+1],
  569. LookAheadBuffer[IPXH_SRCNODE+2],LookAheadBuffer[IPXH_SRCNODE+3],
  570. LookAheadBuffer[IPXH_SRCNODE+4],LookAheadBuffer[IPXH_SRCNODE+5],
  571. LookAheadBuffer[IPXH_PKTTYPE]));
  572. }
  573. else {
  574. // Check if destination netbios name is staticly assigned to
  575. // an external interface or netbios delivery options do not
  576. // allow us to deliver this packet
  577. PINTERFACE_CB dstIf;
  578. USHORT dstSock = GETUSHORT (LookAheadBuffer+IPXH_DESTSOCK);
  579. InterlockedIncrement (&srcIf->ICB_Stats.NetbiosReceived);
  580. // First try to find a static name if we have enough data
  581. // in the lookahead buffer
  582. if ((dstSock==IPX_NETBIOS_SOCKET)
  583. && (LookAheadBufferSize>(NB_NAME+16)))
  584. dstIf = FindNBDestination (LookAheadBuffer+(NB_NAME-IPXH_HDRSIZE));
  585. else if ((dstSock==IPX_SMB_NAME_SOCKET)
  586. && (LookAheadBufferSize>(SMB_NAME+16)))
  587. dstIf = FindNBDestination (LookAheadBuffer+(SMB_NAME-IPXH_HDRSIZE));
  588. else
  589. dstIf = NULL;
  590. // Now see, if we can deliver the packet
  591. if ((((dstIf==NULL) || (dstIf==InternalInterface))
  592. && (InternalInterface->ICB_NetbiosDeliver==FWD_NB_DELIVER_ALL))
  593. || ((dstIf==InternalInterface)
  594. && (InternalInterface->ICB_NetbiosDeliver==FWD_NB_DELIVER_STATIC))) {
  595. InterlockedIncrement (
  596. &InternalInterface->ICB_Stats.NetbiosSent);
  597. InterlockedIncrement (
  598. &InternalInterface->ICB_Stats.OutDelivers);
  599. IpxFwdDbgPrint (DBG_INT_RECV, DBG_INFORMATION,
  600. ("IpxFwd: FwdInternalReceive, NB"
  601. " from %d(%lx)-%.2x%.2x%.2x%.2x:%.2x%.2x%.2x%.2x%.2x%.2x\n",
  602. srcIf->ICB_Index, srcIf,
  603. LookAheadBuffer[IPXH_SRCNET],LookAheadBuffer[IPXH_SRCNET+1],
  604. LookAheadBuffer[IPXH_SRCNET+2],LookAheadBuffer[IPXH_SRCNET+3],
  605. LookAheadBuffer[IPXH_SRCNODE],LookAheadBuffer[IPXH_SRCNODE+1],
  606. LookAheadBuffer[IPXH_SRCNODE+2],LookAheadBuffer[IPXH_SRCNODE+3],
  607. LookAheadBuffer[IPXH_SRCNODE+4],LookAheadBuffer[IPXH_SRCNODE+5]));
  608. }
  609. else {
  610. InterlockedIncrement (
  611. &InternalInterface->ICB_Stats.OutDiscards);
  612. IpxFwdDbgPrint (DBG_INT_RECV, DBG_WARNING,
  613. ("IpxFwd: FwdInternalReceive, NB dropped because delivery disabled"
  614. " from %d(%lx)-%.2x%.2x%.2x%.2x:%.2x%.2x%.2x%.2x%.2x%.2x\n",
  615. srcIf->ICB_Index, srcIf,
  616. LookAheadBuffer[IPXH_SRCNET],LookAheadBuffer[IPXH_SRCNET+1],
  617. LookAheadBuffer[IPXH_SRCNET+2],LookAheadBuffer[IPXH_SRCNET+3],
  618. LookAheadBuffer[IPXH_SRCNODE],LookAheadBuffer[IPXH_SRCNODE+1],
  619. LookAheadBuffer[IPXH_SRCNODE+2],LookAheadBuffer[IPXH_SRCNODE+3],
  620. LookAheadBuffer[IPXH_SRCNODE+4],LookAheadBuffer[IPXH_SRCNODE+5]));
  621. status = STATUS_UNSUCCESSFUL;
  622. }
  623. if (dstIf!=NULL)
  624. ReleaseInterfaceReference (dstIf);
  625. }
  626. }
  627. else {// Filtered Out
  628. if (action==FILTER_DENY_OUT) {
  629. InterlockedIncrement (
  630. &InternalInterface->ICB_Stats.OutFiltered);
  631. status=STATUS_UNSUCCESSFUL;
  632. }
  633. else {
  634. ASSERT (action==FILTER_DENY_IN);
  635. InterlockedIncrement (&srcIf->ICB_Stats.InFiltered);
  636. status=STATUS_UNSUCCESSFUL;
  637. }
  638. IpxFwdDbgPrint (DBG_INT_RECV, DBG_WARNING,
  639. ("IpxFwd: FwdInternalReceive, filtered out"
  640. " from %d(%lx)-%.2x%.2x%.2x%.2x:%.2x%.2x%.2x%.2x%.2x%.2x,"
  641. " type-%02x.\n",
  642. srcIf->ICB_Index, srcIf,
  643. LookAheadBuffer[IPXH_SRCNET],LookAheadBuffer[IPXH_SRCNET+1],
  644. LookAheadBuffer[IPXH_SRCNET+2],LookAheadBuffer[IPXH_SRCNET+3],
  645. LookAheadBuffer[IPXH_SRCNODE],LookAheadBuffer[IPXH_SRCNODE+1],
  646. LookAheadBuffer[IPXH_SRCNODE+2],LookAheadBuffer[IPXH_SRCNODE+3],
  647. LookAheadBuffer[IPXH_SRCNODE+4],LookAheadBuffer[IPXH_SRCNODE+5],
  648. LookAheadBuffer[IPXH_PKTTYPE]));
  649. }
  650. }
  651. else {// Internal interface is disabled
  652. InterlockedIncrement (
  653. &InternalInterface->ICB_Stats.OutDiscards);
  654. status = STATUS_UNSUCCESSFUL;
  655. IpxFwdDbgPrint (DBG_INT_RECV, DBG_WARNING,
  656. ("IpxFwd: FwdInternalReceive, internal if disabled"
  657. " from %d(%lx)-%.2x%.2x%.2x%.2x:%.2x%.2x%.2x%.2x%.2x%.2x,"
  658. " type-%02x.\n",
  659. srcIf->ICB_Index, srcIf,
  660. LookAheadBuffer[IPXH_SRCNET],LookAheadBuffer[IPXH_SRCNET+1],
  661. LookAheadBuffer[IPXH_SRCNET+2],LookAheadBuffer[IPXH_SRCNET+3],
  662. LookAheadBuffer[IPXH_SRCNODE],LookAheadBuffer[IPXH_SRCNODE+1],
  663. LookAheadBuffer[IPXH_SRCNODE+2],LookAheadBuffer[IPXH_SRCNODE+3],
  664. LookAheadBuffer[IPXH_SRCNODE+4],LookAheadBuffer[IPXH_SRCNODE+5],
  665. LookAheadBuffer[IPXH_PKTTYPE]));
  666. }
  667. }
  668. else { // Disabled source interface
  669. InterlockedIncrement (&srcIf->ICB_Stats.InDiscards);
  670. IpxFwdDbgPrint (DBG_INT_RECV, DBG_ERROR,
  671. ("IpxFwd: FwdInternalReceive, source if disabled"
  672. " from %d(%lx)-%.2x%.2x%.2x%.2x:%.2x%.2x%.2x%.2x%.2x%.2x,"
  673. " type-%02x.\n",
  674. srcIf->ICB_Index, srcIf,
  675. LookAheadBuffer[IPXH_SRCNET],LookAheadBuffer[IPXH_SRCNET+1],
  676. LookAheadBuffer[IPXH_SRCNET+2],LookAheadBuffer[IPXH_SRCNET+3],
  677. LookAheadBuffer[IPXH_SRCNODE],LookAheadBuffer[IPXH_SRCNODE+1],
  678. LookAheadBuffer[IPXH_SRCNODE+2],LookAheadBuffer[IPXH_SRCNODE+3],
  679. LookAheadBuffer[IPXH_SRCNODE+4],LookAheadBuffer[IPXH_SRCNODE+5],
  680. LookAheadBuffer[IPXH_PKTTYPE]));
  681. status = STATUS_UNSUCCESSFUL;
  682. }
  683. ReleaseInterfaceReference (srcIf);
  684. }
  685. else { // Invalid source interface context
  686. IpxFwdDbgPrint (DBG_INT_RECV, DBG_ERROR,
  687. ("IpxFwd: FwdInternalReceive, source if context is invalid"
  688. " from (%lx:%d)-%.2x%.2x%.2x%.2x:%.2x%.2x%.2x%.2x%.2x%.2x,"
  689. " type-%02x.\n",
  690. Context, RemoteAddress->NicId,
  691. LookAheadBuffer[IPXH_SRCNET],LookAheadBuffer[IPXH_SRCNET+1],
  692. LookAheadBuffer[IPXH_SRCNET+2],LookAheadBuffer[IPXH_SRCNET+3],
  693. LookAheadBuffer[IPXH_SRCNODE],LookAheadBuffer[IPXH_SRCNODE+1],
  694. LookAheadBuffer[IPXH_SRCNODE+2],LookAheadBuffer[IPXH_SRCNODE+3],
  695. LookAheadBuffer[IPXH_SRCNODE+4],LookAheadBuffer[IPXH_SRCNODE+5],
  696. LookAheadBuffer[IPXH_PKTTYPE]));
  697. status = STATUS_UNSUCCESSFUL;
  698. }
  699. LeaveForwarder ();
  700. return status;
  701. }
  702. /*++
  703. *******************************************************************
  704. D e l e t e R e c v Q u e u e
  705. Routine Description:
  706. Initializes the netbios bradcast queue
  707. Arguments:
  708. None
  709. Return Value:
  710. None
  711. *******************************************************************
  712. --*/
  713. VOID
  714. DeleteRecvQueue (
  715. void
  716. ) {
  717. // while (!IsListEmpty (&RecvQueue)) {
  718. // PPACKET_TAG pktTag = CONTAINING_RECORD (RecvQueue.Flink,
  719. // PACKET_TAG,
  720. // PT_QueueLink);
  721. // RemoveEntryList (&pktTag->PT_QueueLink);
  722. // if (pktTag->PT_InterfaceReference!=NULL) {
  723. // ReleaseInterfaceReference (pktTag->PT_InterfaceReference);
  724. // }
  725. // FreePacket (pktTag);
  726. // }
  727. }
  728. #if DBG
  729. ULONG DbgFilterTrap = 0; // 1 - on dst and src (net + node),
  730. // 2 - on dst (net + node),
  731. // 3 - on src (net + node),
  732. // 4 - on dst (net + node + socket)
  733. UCHAR DbgFilterDstNet[4];
  734. UCHAR DbgFilterDstNode[6];
  735. UCHAR DbgFilterDstSocket[2];
  736. UCHAR DbgFilterSrcNet[4];
  737. UCHAR DbgFilterSrcNode[6];
  738. UCHAR DbgFilterSrcSocket[2];
  739. PUCHAR DbgFilterFrame;
  740. VOID
  741. DbgFilterReceivedPacket(PUCHAR hdrp)
  742. {
  743. switch(DbgFilterTrap) {
  744. case 1:
  745. if(!memcmp(hdrp + IPXH_DESTNET, DbgFilterDstNet, 4) &&
  746. !memcmp(hdrp + IPXH_DESTNODE, DbgFilterDstNode, 6) &&
  747. !memcmp(hdrp + IPXH_SRCNET, DbgFilterSrcNet, 4) &&
  748. !memcmp(hdrp + IPXH_SRCNODE, DbgFilterSrcNode, 6)) {
  749. DbgBreakPoint();
  750. }
  751. break;
  752. case 2:
  753. if(!memcmp(hdrp + IPXH_DESTNET, DbgFilterDstNet, 4) &&
  754. !memcmp(hdrp + IPXH_DESTNODE, DbgFilterDstNode, 6)) {
  755. DbgBreakPoint();
  756. }
  757. break;
  758. case 3:
  759. if(!memcmp(hdrp + IPXH_SRCNET, DbgFilterSrcNet, 4) &&
  760. !memcmp(hdrp + IPXH_SRCNODE, DbgFilterSrcNode, 6)) {
  761. DbgBreakPoint();
  762. }
  763. break;
  764. case 4:
  765. if(!memcmp(hdrp + IPXH_DESTNET, DbgFilterDstNet, 4) &&
  766. !memcmp(hdrp + IPXH_DESTNODE, DbgFilterDstNode, 6) &&
  767. !memcmp(hdrp + IPXH_DESTSOCK, DbgFilterDstSocket, 2)) {
  768. DbgBreakPoint();
  769. }
  770. break;
  771. default:
  772. break;
  773. }
  774. DbgFilterFrame = hdrp;
  775. }
  776. #endif
  777.