Leaked source code of windows server 2003
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.

3099 lines
89 KiB

  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. Module Name:
  4. Receive.c
  5. Abstract:
  6. This file contains the procedures for handling a receive indication from
  7. a Wan Miniport link, bound to the lower interface of NdisWan, and passing
  8. the data on to a protocol, bound to the upper interface of NdisWan. The
  9. upper interface of NdisWan conforms to the NDIS 3.1 Miniport specification.
  10. The lower interface of NdisWan conforms to the NDIS 3.1 Extentions for
  11. Wan Miniport drivers.
  12. Author:
  13. Tony Bell (TonyBe) June 06, 1995
  14. Environment:
  15. Kernel Mode
  16. Revision History:
  17. TonyBe 06/06/95 Created
  18. --*/
  19. #include "wan.h"
  20. #define __FILE_SIG__ RECEIVE_FILESIG
  21. VOID
  22. DoMultilinkProcessing(
  23. PLINKCB LinkCB,
  24. PRECV_DESC RecvDesc
  25. );
  26. VOID
  27. UpdateMinRecvSeqNumber(
  28. PBUNDLECB BundleCB,
  29. UINT Class
  30. );
  31. VOID
  32. TryToAssembleFrame(
  33. PBUNDLECB BundleCB,
  34. UINT Class
  35. );
  36. NDIS_STATUS
  37. ProcessPPPFrame(
  38. PBUNDLECB BundleCB,
  39. PRECV_DESC RecvDesc
  40. );
  41. NDIS_STATUS
  42. IndicateRecvPacket(
  43. PBUNDLECB BundleCB,
  44. PRECV_DESC RecvDesc
  45. );
  46. BOOLEAN
  47. DoVJDecompression(
  48. PBUNDLECB BundleCB,
  49. PRECV_DESC RecvDesc
  50. );
  51. BOOLEAN
  52. DoDecompDecryptProcessing(
  53. PBUNDLECB BundleCB,
  54. PUCHAR *DataPointer,
  55. PLONG DataLength
  56. );
  57. VOID
  58. DoCompressionReset(
  59. PBUNDLECB BundleCB
  60. );
  61. VOID
  62. FlushRecvDescWindow(
  63. PBUNDLECB BundleCB,
  64. UINT Class
  65. );
  66. VOID
  67. FindHoleInRecvList(
  68. PBUNDLECB BundleCB,
  69. PRECV_DESC RecvDesc,
  70. UINT Class
  71. );
  72. BOOLEAN
  73. GetProtocolFromPPPId(
  74. PBUNDLECB BundleCB,
  75. USHORT Id,
  76. PPROTOCOLCB *ProtocolCB
  77. );
  78. #ifdef NT
  79. NDIS_STATUS
  80. CompleteIoRecvPacket(
  81. PBUNDLECB BundleCB,
  82. PRECV_DESC RecvDesc
  83. );
  84. #endif
  85. NDIS_STATUS
  86. DetectBroadbandFraming(
  87. PLINKCB LinkCB,
  88. PRECV_DESC RecvDesc
  89. )
  90. {
  91. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  92. PBUNDLECB BundleCB = LinkCB->BundleCB;
  93. PUCHAR FramePointer;
  94. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("DetectFraming: Enter"));
  95. FramePointer = RecvDesc->CurrentBuffer;
  96. if (*FramePointer == 0xFE && *(FramePointer + 1) == 0xFE &&
  97. *(FramePointer + 2) == 0x03 && *(FramePointer + 3) == 0xCF) {
  98. LinkCB->LinkInfo.RecvFramingBits =
  99. LinkCB->LinkInfo.SendFramingBits =
  100. PPP_FRAMING | LLC_ENCAPSULATION;
  101. LinkCB->RecvHandler = ReceiveLLC;
  102. } else {
  103. LinkCB->LinkInfo.RecvFramingBits =
  104. LinkCB->LinkInfo.SendFramingBits =
  105. PPP_FRAMING | PPP_COMPRESS_ADDRESS_CONTROL;
  106. LinkCB->RecvHandler = ReceivePPP;
  107. }
  108. Status = (*LinkCB->RecvHandler)(LinkCB, RecvDesc);
  109. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("DetectFraming: Exit Status %x",Status));
  110. return (Status);
  111. }
  112. NDIS_STATUS
  113. DetectFraming(
  114. PLINKCB LinkCB,
  115. PRECV_DESC RecvDesc
  116. )
  117. {
  118. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  119. PBUNDLECB BundleCB = LinkCB->BundleCB;
  120. PUCHAR FramePointer;
  121. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("DetectFraming: Enter"));
  122. ASSERT(LinkCB->LinkInfo.RecvFramingBits == 0x00);
  123. FramePointer = RecvDesc->CurrentBuffer;
  124. //
  125. // If we are in framing detect mode figure it out
  126. //
  127. if (LinkCB->LinkInfo.RecvFramingBits == 0 ||
  128. LinkCB->LinkInfo.SendFramingBits == 0) {
  129. if (*FramePointer == 0xFF && *(FramePointer + 1) == 0x03) {
  130. LinkCB->LinkInfo.RecvFramingBits =
  131. LinkCB->LinkInfo.SendFramingBits = PPP_FRAMING;
  132. LinkCB->RecvHandler = ReceivePPP;
  133. } else if (*FramePointer == 0x01 && *(FramePointer + 1) == 0x1B &&
  134. *(FramePointer + 2) == 0x02){
  135. LinkCB->LinkInfo.RecvFramingBits =
  136. LinkCB->LinkInfo.SendFramingBits = ARAP_V2_FRAMING;
  137. LinkCB->RecvHandler = ReceiveARAP;
  138. } else if (*FramePointer == 0x16 && *(FramePointer + 1) == 0x10 &&
  139. *(FramePointer + 2) == 0x02){
  140. LinkCB->LinkInfo.RecvFramingBits =
  141. LinkCB->LinkInfo.SendFramingBits = ARAP_V1_FRAMING;
  142. LinkCB->RecvHandler = ReceiveARAP;
  143. } else if (*FramePointer == 0xFE && *(FramePointer + 1) == 0xFE &&
  144. *(FramePointer + 2) == 0x03 &&
  145. *(FramePointer + 3) == 0xCF) {
  146. LinkCB->LinkInfo.RecvFramingBits =
  147. LinkCB->LinkInfo.SendFramingBits =
  148. PPP_FRAMING | LLC_ENCAPSULATION;
  149. LinkCB->RecvHandler = ReceiveLLC;
  150. } else {
  151. LinkCB->LinkInfo.RecvFramingBits =
  152. LinkCB->LinkInfo.SendFramingBits = RAS_FRAMING;
  153. LinkCB->RecvHandler = ReceiveRAS;
  154. }
  155. if (BundleCB->FramingInfo.RecvFramingBits == 0x00) {
  156. if (LinkCB->LinkInfo.RecvFramingBits & PPP_FRAMING) {
  157. BundleCB->FramingInfo.RecvFramingBits =
  158. BundleCB->FramingInfo.SendFramingBits = PPP_FRAMING;
  159. } else if (LinkCB->LinkInfo.RecvFramingBits & ARAP_V1_FRAMING) {
  160. BundleCB->FramingInfo.RecvFramingBits =
  161. BundleCB->FramingInfo.SendFramingBits = ARAP_V1_FRAMING;
  162. } else if (LinkCB->LinkInfo.RecvFramingBits & ARAP_V2_FRAMING) {
  163. BundleCB->FramingInfo.RecvFramingBits =
  164. BundleCB->FramingInfo.SendFramingBits = ARAP_V2_FRAMING;
  165. } else if (LinkCB->LinkInfo.RecvFramingBits & RAS_FRAMING) {
  166. BundleCB->FramingInfo.RecvFramingBits =
  167. BundleCB->FramingInfo.SendFramingBits = RAS_FRAMING;
  168. } else {
  169. NdisWanDbgOut(DBG_FAILURE, DBG_RECEIVE,
  170. ("DetectFraming Failed! 0x%2.2x 0x%2.2x 0x%2.2x",
  171. FramePointer[0], FramePointer[1], FramePointer[2]));
  172. return (NDIS_STATUS_SUCCESS);
  173. }
  174. }
  175. } else {
  176. NdisWanDbgOut(DBG_FAILURE, DBG_RECEIVE,
  177. ("FramingBits set but still in detect 0x%x 0x%x",
  178. LinkCB->LinkInfo.RecvFramingBits,
  179. LinkCB->LinkInfo.SendFramingBits));
  180. return (NDIS_STATUS_SUCCESS);
  181. }
  182. Status = (*LinkCB->RecvHandler)(LinkCB, RecvDesc);
  183. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("DetectFraming: Exit Status %x",Status));
  184. return (Status);
  185. }
  186. NDIS_STATUS
  187. ReceivePPP(
  188. PLINKCB LinkCB,
  189. PRECV_DESC RecvDesc
  190. )
  191. {
  192. PBUNDLECB BundleCB = LinkCB->BundleCB;
  193. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  194. PUCHAR FramePointer = RecvDesc->CurrentBuffer;
  195. LONG FrameLength = RecvDesc->CurrentLength;
  196. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ReceivePPP: Enter"));
  197. //
  198. // Remove the address/control part of the PPP header
  199. //
  200. if (*FramePointer == 0xFF) {
  201. FramePointer += 2;
  202. FrameLength -= 2;
  203. }
  204. if (FrameLength <= 0) {
  205. Status = NDIS_STATUS_FAILURE;
  206. goto RECEIVE_PPP_EXIT;
  207. }
  208. //
  209. // If multilink framing is set and this is a multilink frame
  210. // send to the multilink processor!
  211. //
  212. if ((LinkCB->LinkInfo.RecvFramingBits & PPP_MULTILINK_FRAMING) &&
  213. ((*FramePointer == 0x3D) ||
  214. (*FramePointer == 0x00) && (*(FramePointer + 1) == 0x3D)) ) {
  215. //
  216. // Remove multilink protocol id
  217. //
  218. if (*FramePointer & 1) {
  219. FramePointer++;
  220. FrameLength--;
  221. } else {
  222. FramePointer += 2;
  223. FrameLength -= 2;
  224. }
  225. if (FrameLength <= 0) {
  226. Status = NDIS_STATUS_FAILURE;
  227. goto RECEIVE_PPP_EXIT;
  228. }
  229. RecvDesc->CurrentBuffer = FramePointer;
  230. RecvDesc->CurrentLength = FrameLength;
  231. DoMultilinkProcessing(LinkCB, RecvDesc);
  232. Status = NDIS_STATUS_PENDING;
  233. goto RECEIVE_PPP_EXIT;
  234. }
  235. RecvDesc->CurrentBuffer = FramePointer;
  236. RecvDesc->CurrentLength = FrameLength;
  237. Status = ProcessPPPFrame(BundleCB, RecvDesc);
  238. RECEIVE_PPP_EXIT:
  239. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ReceivePPP: Exit Status %x", Status));
  240. return (Status);
  241. }
  242. NDIS_STATUS
  243. ReceiveSLIP(
  244. PLINKCB LinkCB,
  245. PRECV_DESC RecvDesc
  246. )
  247. {
  248. PBUNDLECB BundleCB = LinkCB->BundleCB;
  249. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  250. PUCHAR FramePointer = RecvDesc->CurrentBuffer;
  251. ULONG FrameLength = RecvDesc->CurrentLength;
  252. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ReceiveSLIP: Enter"));
  253. ASSERT(BundleCB->FramingInfo.RecvFramingBits & SLIP_FRAMING);
  254. BundleCB->Stats.FramesReceived++;
  255. if (!DoVJDecompression(BundleCB, // Bundle
  256. RecvDesc)) { // RecvDesc
  257. goto RECEIVE_SLIP_EXIT;
  258. }
  259. Status = IndicateRecvPacket(BundleCB, RecvDesc);
  260. RECEIVE_SLIP_EXIT:
  261. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ReceiveSLIP: Exit Status %x", Status));
  262. return (Status);
  263. }
  264. NDIS_STATUS
  265. ReceiveRAS(
  266. PLINKCB LinkCB,
  267. PRECV_DESC RecvDesc
  268. )
  269. {
  270. PBUNDLECB BundleCB = LinkCB->BundleCB;
  271. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  272. PUCHAR FramePointer = RecvDesc->CurrentBuffer;
  273. LONG FrameLength = RecvDesc->CurrentLength;
  274. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ReceiveRAS: Enter"));
  275. ASSERT(BundleCB->FramingInfo.RecvFramingBits & RAS_FRAMING);
  276. BundleCB->Stats.FramesReceived++;
  277. // For normal NBF frames, first byte is always the DSAP
  278. // i.e 0xF0 followed by SSAP 0xF0 or 0xF1
  279. //
  280. //
  281. if (*FramePointer == 14) {
  282. //
  283. // Compression reset!
  284. //
  285. DoCompressionReset(BundleCB);
  286. goto RECEIVE_RAS_EXIT;
  287. }
  288. if (*FramePointer == 0xFD) {
  289. //
  290. // Skip over 0xFD
  291. //
  292. FramePointer++;
  293. FrameLength--;
  294. //
  295. // Decompress as if an NBF PPP Packet
  296. //
  297. if (!DoDecompDecryptProcessing(BundleCB,
  298. &FramePointer,
  299. &FrameLength)){
  300. //
  301. // There was an error get out!
  302. //
  303. goto RECEIVE_RAS_EXIT;
  304. }
  305. }
  306. //
  307. // Make frame look like an NBF PPP packet
  308. //
  309. RecvDesc->ProtocolID = PPP_PROTOCOL_NBF;
  310. RecvDesc->CurrentLength = FrameLength;
  311. RecvDesc->CurrentBuffer = FramePointer;
  312. Status = IndicateRecvPacket(BundleCB, RecvDesc);
  313. RECEIVE_RAS_EXIT:
  314. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ReceiveRAS: Exit Status %x",Status));
  315. return (Status);
  316. }
  317. NDIS_STATUS
  318. ReceiveARAP(
  319. PLINKCB LinkCB,
  320. PRECV_DESC RecvDesc
  321. )
  322. {
  323. PBUNDLECB BundleCB = LinkCB->BundleCB;
  324. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  325. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ReceiveARAP: Enter"));
  326. ASSERT(BundleCB->FramingInfo.RecvFramingBits & ARAP_FRAMING);
  327. BundleCB->Stats.FramesReceived++;
  328. RecvDesc->ProtocolID = PPP_PROTOCOL_APPLETALK;
  329. Status = IndicateRecvPacket(BundleCB, RecvDesc);
  330. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ReceiveARAP: Exit Status %x",Status));
  331. return (Status);
  332. }
  333. NDIS_STATUS
  334. ReceiveLLC(
  335. PLINKCB LinkCB,
  336. PRECV_DESC RecvDesc
  337. )
  338. {
  339. PBUNDLECB BundleCB = LinkCB->BundleCB;
  340. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  341. PUCHAR FramePointer = RecvDesc->CurrentBuffer;
  342. LONG FrameLength = RecvDesc->CurrentLength;
  343. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ReceiveLLC: Enter"));
  344. //
  345. // Skip over LLC
  346. //
  347. if (FrameLength < 4) {
  348. }
  349. if (*FramePointer != 0xFE || *(FramePointer + 1) != 0xFE ||
  350. *(FramePointer + 2) != 0x03 || *(FramePointer + 3) != 0xCF) {
  351. LinkCB->LinkInfo.RecvFramingBits = 0;
  352. LinkCB->RecvHandler = DetectBroadbandFraming;
  353. return (NDIS_STATUS_FAILURE);
  354. }
  355. FramePointer += 4;
  356. FrameLength -= 4;
  357. if (FrameLength <= 0) {
  358. return (NDIS_STATUS_FAILURE);
  359. }
  360. RecvDesc->CurrentBuffer = FramePointer;
  361. RecvDesc->CurrentLength = FrameLength;
  362. Status = ProcessPPPFrame(BundleCB, RecvDesc);
  363. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ReceiveLLC: Exit Status %x",Status));
  364. return (Status);
  365. }
  366. NDIS_STATUS
  367. ReceiveForward(
  368. PLINKCB LinkCB,
  369. PRECV_DESC RecvDesc
  370. )
  371. {
  372. PBUNDLECB BundleCB = LinkCB->BundleCB;
  373. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  374. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ReceiveForward: Enter"));
  375. BundleCB->Stats.FramesReceived++;
  376. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ReceiveForward: Exit Status %x",Status));
  377. return (Status);
  378. }
  379. NDIS_STATUS
  380. ProcessPPPFrame(
  381. PBUNDLECB BundleCB,
  382. PRECV_DESC RecvDesc
  383. )
  384. {
  385. USHORT PPPProtocolID;
  386. PUCHAR FramePointer = RecvDesc->CurrentBuffer;
  387. LONG FrameLength = RecvDesc->CurrentLength;
  388. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  389. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ProcessPPPFrame: Enter"));
  390. BundleCB->Stats.FramesReceived++;
  391. //
  392. // Get the PPP Protocol id
  393. // 0xC1 is SPAP - Shiva hack!
  394. //
  395. if ((*FramePointer & 1) &&
  396. (*FramePointer != 0xC1) &&
  397. (*FramePointer != 0xCF)) {
  398. //
  399. // Field is compressed
  400. //
  401. PPPProtocolID = *FramePointer;
  402. FramePointer++;
  403. FrameLength--;
  404. } else {
  405. //
  406. // Field is not compressed
  407. //
  408. PPPProtocolID = (*FramePointer << 8) | *(FramePointer + 1);
  409. FramePointer += 2;
  410. FrameLength -= 2;
  411. }
  412. if (FrameLength <= 0) {
  413. goto PROCESS_PPP_EXIT;
  414. }
  415. #if 0
  416. if (BundleCB->Stats.FramesReceived == 1) {
  417. if (PPPProtocolID != 0xC021) {
  418. DbgPrint("NDISWAN: Non-LCP first frame! %x %x\n",
  419. BundleCB, RecvDesc);
  420. DbgBreakPoint();
  421. }
  422. }
  423. #endif
  424. //
  425. // Is this a compressed frame?
  426. //
  427. if (PPPProtocolID == PPP_PROTOCOL_COMPRESSION) {
  428. if (!DoDecompDecryptProcessing(BundleCB,
  429. &FramePointer,
  430. &FrameLength)){
  431. goto PROCESS_PPP_EXIT;
  432. }
  433. //
  434. // Get the new PPPProtocolID
  435. //
  436. if ((*FramePointer & 1) && (FrameLength > 0)) {
  437. //
  438. // Field is compressed
  439. //
  440. PPPProtocolID = *FramePointer;
  441. FramePointer++;
  442. FrameLength--;
  443. } else if (FrameLength > 1) {
  444. PPPProtocolID = (*FramePointer << 8) | *(FramePointer + 1);
  445. FramePointer += 2;
  446. FrameLength -= 2;
  447. } else {
  448. //
  449. // Invalid frame!
  450. //
  451. NdisWanDbgOut(DBG_FAILURE, DBG_RECEIVE, ("Invalid FrameLen %d", FrameLength));
  452. goto PROCESS_PPP_EXIT;
  453. }
  454. //end of PPP_PROTOCOL_COMPRESSED
  455. } else if ((PPPProtocolID == PPP_PROTOCOL_COMP_RESET) &&
  456. (*FramePointer == 14)) {
  457. if (NdisWanCB.PromiscuousAdapter != NULL) {
  458. UCHAR Header[] = {' ', 'R', 'E', 'C', 'V', 0xFF};
  459. PUCHAR HeaderPointer;
  460. USHORT ProtocolID;
  461. RecvDesc->ProtocolID = PPPProtocolID;
  462. RecvDesc->CurrentBuffer = FramePointer;
  463. RecvDesc->CurrentLength = FrameLength;
  464. HeaderPointer =
  465. RecvDesc->StartBuffer;
  466. ProtocolID = RecvDesc->ProtocolID;
  467. //
  468. // Fill the frame out, and queue the data
  469. //
  470. NdisMoveMemory(HeaderPointer,
  471. Header,
  472. sizeof(Header));
  473. NdisMoveMemory(&HeaderPointer[6],
  474. Header,
  475. sizeof(Header));
  476. HeaderPointer[5] =
  477. HeaderPointer[11] = (UCHAR)RecvDesc->LinkCB->hLinkHandle;
  478. HeaderPointer[12] = (UCHAR)(ProtocolID >> 8);
  479. HeaderPointer[13] = (UCHAR)ProtocolID;
  480. NdisMoveMemory(HeaderPointer + 14,
  481. RecvDesc->CurrentBuffer,
  482. RecvDesc->CurrentLength);
  483. RecvDesc->CurrentBuffer = RecvDesc->StartBuffer;
  484. RecvDesc->CurrentLength += 14;
  485. //
  486. // Queue the packet on the promiscous adapter
  487. //
  488. IndicatePromiscuousRecv(BundleCB, RecvDesc, RECV_BUNDLE_PPP);
  489. }
  490. //
  491. // Compression reset!
  492. //
  493. DoCompressionReset(BundleCB);
  494. goto PROCESS_PPP_EXIT;
  495. // end of compression reset
  496. } else {
  497. //
  498. // If we have negotiated encryption and we receive non-encrypted data
  499. // that is not a ppp control packet we will dump the frame!
  500. //
  501. if ((BundleCB->RecvFlags & DO_ENCRYPTION) &&
  502. (PPPProtocolID < 0x8000)) {
  503. NdisWanDbgOut(DBG_FAILURE, DBG_RECEIVE, ("Received non-encrypted data with encryption negotiated!"));
  504. goto PROCESS_PPP_EXIT;
  505. }
  506. }
  507. RecvDesc->ProtocolID = PPPProtocolID;
  508. RecvDesc->CurrentLength = FrameLength;
  509. RecvDesc->CurrentBuffer = FramePointer;
  510. //
  511. // If this is slip or if the ProtocolID == PPP_PROTOCOL_COMPRESSED_TCP ||
  512. // ProtocolID == PPP_PROTOCOL_UNCOMPRESSED_TCP
  513. //
  514. if ((BundleCB->RecvFlags & DO_VJ) &&
  515. ((PPPProtocolID == PPP_PROTOCOL_COMPRESSED_TCP) ||
  516. (PPPProtocolID == PPP_PROTOCOL_UNCOMPRESSED_TCP))) {
  517. if (!DoVJDecompression(BundleCB, // Bundle
  518. RecvDesc)) { // RecvDesc
  519. goto PROCESS_PPP_EXIT;
  520. }
  521. }
  522. Status = IndicateRecvPacket(BundleCB, RecvDesc);
  523. PROCESS_PPP_EXIT:
  524. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ProcessPPPFrame: Exit Status 0x%x", Status));
  525. return (Status);
  526. }
  527. NDIS_STATUS
  528. IndicateRecvPacket(
  529. PBUNDLECB BundleCB,
  530. PRECV_DESC RecvDesc
  531. )
  532. {
  533. PNDIS_PACKET NdisPacket;
  534. PPROTOCOLCB ProtocolCB;
  535. PMINIPORTCB MiniportCB;
  536. USHORT PPPProtocolID = RecvDesc->ProtocolID;
  537. PUCHAR FramePointer = RecvDesc->CurrentBuffer;
  538. ULONG FrameLength = RecvDesc->CurrentLength;
  539. PUCHAR HeaderBuffer = RecvDesc->StartBuffer;
  540. NDIS_STATUS Status = NDIS_STATUS_PENDING;
  541. PCM_VCCB CmVcCB = NULL;
  542. KIRQL OldIrql;
  543. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("IndicateRecvPacket: Enter"));
  544. if ((PPPProtocolID >= 0x8000) ||
  545. (BundleCB->ulNumberOfRoutes == 0)) {
  546. //
  547. // Either this frame is an LCP, NCP or we have no routes yet.
  548. // Indicate to PPP engine.
  549. //
  550. Status = CompleteIoRecvPacket(BundleCB, RecvDesc);
  551. return (Status);
  552. }
  553. if (!GetProtocolFromPPPId(BundleCB,
  554. PPPProtocolID,
  555. &ProtocolCB)) {
  556. return (NDIS_STATUS_SUCCESS);
  557. }
  558. REF_PROTOCOLCB(ProtocolCB);
  559. if (!IsListEmpty(&ProtocolCB->VcList)) {
  560. CmVcCB = (PCM_VCCB)ProtocolCB->VcList.Flink;
  561. REF_CMVCCB(CmVcCB);
  562. }
  563. MiniportCB = ProtocolCB->MiniportCB;
  564. //
  565. // We found a valid protocol to indicate this frame to!
  566. //
  567. //
  568. // We need to get a data buffer, a couple a ndis buffer, and
  569. // a ndis packet to indicate to the protocol
  570. //
  571. //
  572. // Fill the WanHeader dest address with the transports context
  573. //
  574. ETH_COPY_NETWORK_ADDRESS(HeaderBuffer, ProtocolCB->TransportAddress);
  575. if (PPPProtocolID == PPP_PROTOCOL_NBF) {
  576. //
  577. // For nbf fill the length field
  578. //
  579. HeaderBuffer[12] = (UCHAR)(FrameLength >> 8);
  580. HeaderBuffer[13] = (UCHAR)FrameLength;
  581. if (!(BundleCB->FramingInfo.RecvFramingBits & NBF_PRESERVE_MAC_ADDRESS)) {
  582. goto USE_OUR_ADDRESS;
  583. }
  584. //
  585. // For nbf and preserve mac address option (SHIVA_FRAMING)
  586. // we keep the source address.
  587. //
  588. ETH_COPY_NETWORK_ADDRESS(&HeaderBuffer[6], FramePointer + 6);
  589. FramePointer += 12;
  590. FrameLength -= 12;
  591. //
  592. // For nbf fill the length field
  593. //
  594. HeaderBuffer[12] = (UCHAR)(FrameLength >> 8);
  595. HeaderBuffer[13] = (UCHAR)FrameLength;
  596. } else {
  597. //
  598. // For other protocols fill the protocol type
  599. //
  600. HeaderBuffer[12] = (UCHAR)(ProtocolCB->ProtocolType >> 8);
  601. HeaderBuffer[13] = (UCHAR)ProtocolCB->ProtocolType;
  602. //
  603. // Use our address for the src address
  604. //
  605. USE_OUR_ADDRESS:
  606. ETH_COPY_NETWORK_ADDRESS(&HeaderBuffer[6], ProtocolCB->NdisWanAddress);
  607. }
  608. if (FrameLength > BundleCB->FramingInfo.MaxRRecvFrameSize ||
  609. FrameLength + RecvDesc->HeaderLength > BundleCB->FramingInfo.MaxRRecvFrameSize) {
  610. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("DataLen %d + HdrLen %d > MRRU %d",
  611. FrameLength, RecvDesc->HeaderLength, BundleCB->FramingInfo.MaxRRecvFrameSize));
  612. goto INDICATE_RECV_PACKET_EXIT;
  613. }
  614. RecvDesc->HeaderLength += MAC_HEADER_LENGTH;
  615. //
  616. // Build the NdisPacket
  617. // USE RtlMoveMemory because memory ranges may overlap. NdisMoveMemory
  618. // actually does an rtlcopymemory which does not handle overlapping
  619. // src/dest ranges.
  620. //
  621. RtlMoveMemory(HeaderBuffer + RecvDesc->HeaderLength,
  622. FramePointer,
  623. FrameLength);
  624. RecvDesc->CurrentBuffer = HeaderBuffer;
  625. RecvDesc->CurrentLength =
  626. RecvDesc->HeaderLength + FrameLength;
  627. if (NdisWanCB.PromiscuousAdapter != NULL) {
  628. //
  629. // Queue the packet on the promiscous adapter
  630. //
  631. IndicatePromiscuousRecv(BundleCB,
  632. RecvDesc,
  633. RECV_BUNDLE_DATA);
  634. }
  635. NdisPacket =
  636. RecvDesc->NdisPacket;
  637. PPROTOCOL_RESERVED_FROM_NDIS(NdisPacket)->RecvDesc =
  638. RecvDesc;
  639. NdisAdjustBufferLength(RecvDesc->NdisBuffer,
  640. RecvDesc->CurrentLength);
  641. NdisRecalculatePacketCounts(NdisPacket);
  642. //
  643. // Check for non-idle data
  644. //
  645. if (ProtocolCB->NonIdleDetectFunc != NULL) {
  646. PUCHAR PHeaderBuffer = HeaderBuffer + MAC_HEADER_LENGTH;
  647. if (TRUE == ProtocolCB->NonIdleDetectFunc(PHeaderBuffer,
  648. RecvDesc->HeaderLength + FrameLength,
  649. RecvDesc->HeaderLength + FrameLength)) {
  650. NdisWanGetSystemTime(&ProtocolCB->LastNonIdleData);
  651. BundleCB->LastNonIdleData = ProtocolCB->LastNonIdleData;
  652. }
  653. } else {
  654. NdisWanGetSystemTime(&ProtocolCB->LastNonIdleData);
  655. BundleCB->LastNonIdleData = ProtocolCB->LastNonIdleData;
  656. }
  657. ReleaseBundleLock(BundleCB);
  658. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  659. INSERT_DBG_RECV(PacketTypeNdis,
  660. MiniportCB,
  661. ProtocolCB,
  662. RecvDesc->LinkCB,
  663. NdisPacket);
  664. //
  665. // Indicate the packet
  666. //
  667. if (CmVcCB != NULL) {
  668. NdisMCoIndicateReceivePacket(CmVcCB->NdisVcHandle,
  669. &NdisPacket,
  670. 1);
  671. DEREF_CMVCCB(CmVcCB);
  672. } else {
  673. NdisMIndicateReceivePacket(MiniportCB->MiniportHandle,
  674. &NdisPacket,
  675. 1);
  676. }
  677. KeLowerIrql(OldIrql);
  678. AcquireBundleLock(BundleCB);
  679. INDICATE_RECV_PACKET_EXIT:
  680. DEREF_PROTOCOLCB(ProtocolCB);
  681. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("IndicateRecvPacket: Exit Status %x",Status));
  682. return (Status);
  683. }
  684. VOID
  685. DoMultilinkProcessing(
  686. PLINKCB LinkCB,
  687. PRECV_DESC RecvDesc
  688. )
  689. /*++
  690. Routine Name:
  691. Routine Description:
  692. Arguments:
  693. 0 1 2 3 4 5 6 7 8 9 1 1 1 1 1 1
  694. 0 1 2 3 4 5
  695. +-+-+-+-+------------------------+
  696. Short Sequence Number |B|E|0|0| Sequence Number |
  697. +-+-+-+-+------------------------+
  698. | Data |
  699. +--------------------------------+
  700. +-+-+-+-+-+-+-+-+----------------+
  701. Long Sequence Number |B|E|0|0|0|0|0|0|Sequence Number |
  702. +-+-+-+-+-+-+-+-+----------------+
  703. | Sequence Number |
  704. +--------------------------------+
  705. | Data |
  706. +--------------------------------+
  707. MCML +-+-+-+-+------------------------+
  708. Short Sequence Number |B|E|Cls| Sequence Number |
  709. +-+-+-+-+------------------------+
  710. | Data |
  711. +--------------------------------+
  712. MCML +-+-+-+-+-+-+-+-+----------------+
  713. Long Sequence Number |B|E| Class |0|0|Sequence Number |
  714. +-+-+-+-+-+-+-+-+----------------+
  715. | Sequence Number |
  716. +--------------------------------+
  717. | Data |
  718. +--------------------------------+
  719. Return Values:
  720. --*/
  721. {
  722. BOOLEAN Inserted = FALSE;
  723. ULONG BundleFraming;
  724. ULONG SequenceNumber, Flags;
  725. PBUNDLECB BundleCB = LinkCB->BundleCB;
  726. PUCHAR FramePointer = RecvDesc->CurrentBuffer;
  727. LONG FrameLength = RecvDesc->CurrentLength;
  728. PRECV_DESC RecvDescHole;
  729. UINT Class = 0;
  730. PBUNDLE_RECV_INFO BundleRecvInfo;
  731. PLINK_RECV_INFO LinkRecvInfo;
  732. //
  733. // Get the flags
  734. //
  735. Flags = *FramePointer & MULTILINK_FLAG_MASK;
  736. //
  737. // Get the sequence number
  738. //
  739. if (BundleCB->FramingInfo.RecvFramingBits &
  740. PPP_SHORT_SEQUENCE_HDR_FORMAT) {
  741. //
  742. // Short sequence format
  743. //
  744. SequenceNumber =
  745. ((*FramePointer & 0x0F) << 8) | *(FramePointer + 1);
  746. if (BundleCB->FramingInfo.RecvFramingBits &
  747. PPP_MC_MULTILINK_FRAMING) {
  748. Class =
  749. ((*FramePointer & MCML_SHORTCLASS_MASK) >> 4);
  750. }
  751. FramePointer += 2;
  752. FrameLength -= 2;
  753. } else {
  754. //
  755. // Long sequence format
  756. //
  757. SequenceNumber = (*(FramePointer + 1) << 16) |
  758. (*(FramePointer + 2) << 8) |
  759. *(FramePointer + 3);
  760. if (BundleCB->FramingInfo.RecvFramingBits &
  761. PPP_MC_MULTILINK_FRAMING) {
  762. Class =
  763. ((*FramePointer & MCML_LONGCLASS_MASK) >> 2);
  764. }
  765. FramePointer += 4;
  766. FrameLength -= 4;
  767. }
  768. if (Class >= MAX_MCML) {
  769. LinkCB->Stats.FramingErrors++;
  770. BundleCB->Stats.FramingErrors++;
  771. return;
  772. }
  773. BundleRecvInfo = &BundleCB->RecvInfo[Class];
  774. LinkRecvInfo = &LinkCB->RecvInfo[Class];
  775. if (FrameLength <= 0) {
  776. LinkCB->Stats.FramingErrors++;
  777. LinkRecvInfo->FragmentsLost++;
  778. BundleCB->Stats.FramingErrors++;
  779. BundleRecvInfo->FragmentsLost++;
  780. return;
  781. }
  782. RecvDescHole = BundleRecvInfo->RecvDescHole;
  783. NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV,
  784. ("r %x %x h: %x l: %d",SequenceNumber, Flags, RecvDescHole->SequenceNumber, LinkCB->hLinkHandle));
  785. //
  786. // Is the new receive sequence number smaller that the last
  787. // sequence number received on this link? If so the increasing seq
  788. // number rule has been violated and we need to toss this one.
  789. //
  790. if (SEQ_LT(SequenceNumber,
  791. LinkRecvInfo->LastSeqNumber,
  792. BundleCB->RecvSeqTest)) {
  793. LinkCB->Stats.FramingErrors++;
  794. LinkRecvInfo->FragmentsLost++;
  795. BundleCB->Stats.FramingErrors++;
  796. BundleRecvInfo->FragmentsLost++;
  797. NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
  798. ("dl s: %x %x lr: %x", SequenceNumber, Flags,
  799. LinkRecvInfo->LastSeqNumber));
  800. NdisWanFreeRecvDesc(RecvDesc);
  801. return;
  802. }
  803. //
  804. // Is the new receive sequence number smaller than the hole? If so
  805. // we received a fragment across a slow link after it has been flushed
  806. //
  807. if (SEQ_LT(SequenceNumber,
  808. RecvDescHole->SequenceNumber,
  809. BundleCB->RecvSeqTest)) {
  810. LinkCB->Stats.FramingErrors++;
  811. LinkRecvInfo->FragmentsLost++;
  812. BundleCB->Stats.FramingErrors++;
  813. BundleRecvInfo->FragmentsLost++;
  814. NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
  815. ("db s: %x %x h: %x", SequenceNumber, Flags,
  816. RecvDescHole->SequenceNumber));
  817. NdisWanFreeRecvDesc(RecvDesc);
  818. return;
  819. }
  820. //
  821. // Initialize the recv desc
  822. //
  823. RecvDesc->Flags |= Flags;
  824. RecvDesc->SequenceNumber =
  825. LinkRecvInfo->LastSeqNumber = SequenceNumber;
  826. if (RecvDesc->CopyRequired) {
  827. PUCHAR StartData =
  828. RecvDesc->StartBuffer + MAC_HEADER_LENGTH + PROTOCOL_HEADER_LENGTH;
  829. NdisMoveMemory(StartData,
  830. FramePointer,
  831. FrameLength);
  832. FramePointer = StartData;
  833. RecvDesc->CopyRequired = FALSE;
  834. }
  835. RecvDesc->CurrentBuffer = FramePointer;
  836. RecvDesc->CurrentLength = FrameLength;
  837. //
  838. // If this fills the hole
  839. //
  840. if (SEQ_EQ(SequenceNumber, RecvDescHole->SequenceNumber)) {
  841. //
  842. // Insert the hole filler in the current holes spot
  843. //
  844. RecvDesc->Linkage.Blink = (PLIST_ENTRY)RecvDescHole->Linkage.Blink;
  845. RecvDesc->Linkage.Flink = (PLIST_ENTRY)RecvDescHole->Linkage.Flink;
  846. RecvDesc->Linkage.Blink->Flink =
  847. RecvDesc->Linkage.Flink->Blink = (PLIST_ENTRY)RecvDesc;
  848. //
  849. // Find the next hole
  850. //
  851. FindHoleInRecvList(BundleCB, RecvDesc, Class);
  852. NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV, ("r1"));
  853. } else {
  854. PRECV_DESC BeginDesc, EndDesc;
  855. //
  856. // This does not fill a hole so we need to insert it into
  857. // the list at the right spot. This spot will be someplace
  858. // between the hole and the end of the list.
  859. //
  860. BeginDesc = RecvDescHole;
  861. EndDesc = (PRECV_DESC)BeginDesc->Linkage.Flink;
  862. while ((PVOID)EndDesc != (PVOID)&BundleRecvInfo->AssemblyList) {
  863. //
  864. // Calculate the absolute delta between the begining sequence
  865. // number and the sequence number we are looking to insert.
  866. //
  867. ULONG DeltaBegin =
  868. ((RecvDesc->SequenceNumber - BeginDesc->SequenceNumber) &
  869. BundleCB->RecvSeqMask);
  870. //
  871. // Calculate the absolute delta between the begining sequence
  872. // number and the end sequence number.
  873. //
  874. ULONG DeltaEnd =
  875. ((EndDesc->SequenceNumber - BeginDesc->SequenceNumber) &
  876. BundleCB->RecvSeqMask);
  877. //
  878. // If the delta from the begin to current is less than
  879. // the delta from the end to current it is time to insert
  880. //
  881. if (DeltaBegin < DeltaEnd) {
  882. PLIST_ENTRY Flink, Blink;
  883. //
  884. // Insert the desc
  885. //
  886. RecvDesc->Linkage.Flink = (PLIST_ENTRY)EndDesc;
  887. RecvDesc->Linkage.Blink = (PLIST_ENTRY)BeginDesc;
  888. BeginDesc->Linkage.Flink =
  889. EndDesc->Linkage.Blink = (PLIST_ENTRY)RecvDesc;
  890. Inserted = TRUE;
  891. NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV, ("r2"));
  892. break;
  893. } else {
  894. //
  895. // Get next pair of descriptors
  896. //
  897. BeginDesc = EndDesc;
  898. EndDesc = (PRECV_DESC)EndDesc->Linkage.Flink;
  899. }
  900. }
  901. if (!Inserted) {
  902. //
  903. // If we are here we have fallen through and we need to
  904. // add this at the end of the list
  905. //
  906. InsertTailList(&BundleRecvInfo->AssemblyList, &RecvDesc->Linkage);
  907. NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV, ("r3"));
  908. }
  909. }
  910. //
  911. // Another recvdesc has been placed on the assembly list.
  912. //
  913. BundleRecvInfo->AssemblyCount++;
  914. //
  915. // Update the bundles minimum recv sequence number. This is
  916. // used to detect lost fragments.
  917. //
  918. UpdateMinRecvSeqNumber(BundleCB, Class);
  919. //
  920. // See if we can complete some frames!!!!
  921. //
  922. TryToAssembleFrame(BundleCB, Class);
  923. //
  924. // Check for lost fragments. If the minimum recv sequence number
  925. // over the bundle is greater than the hole sequence number we have
  926. // lost a fragment and need to flush the assembly list until we find
  927. // the first begin fragment after the hole.
  928. //
  929. if (SEQ_GT(BundleRecvInfo->MinSeqNumber,
  930. RecvDescHole->SequenceNumber,
  931. BundleCB->RecvSeqTest)) {
  932. NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
  933. ("min %x > h %x b %p",
  934. BundleRecvInfo->MinSeqNumber,
  935. RecvDescHole->SequenceNumber,
  936. BundleCB));
  937. do {
  938. //
  939. // Flush the recv desc assembly window.
  940. //
  941. FlushRecvDescWindow(BundleCB, Class);
  942. } while (SEQ_GT(BundleRecvInfo->MinSeqNumber,
  943. RecvDescHole->SequenceNumber,
  944. BundleCB->RecvSeqTest));
  945. }
  946. //
  947. // If the number of recvdesc's is starting to stack up
  948. // we may have a link that is not sending so flush
  949. //
  950. if (BundleRecvInfo->AssemblyCount >
  951. (MAX_RECVDESC_COUNT + BundleCB->ulLinkCBCount)) {
  952. NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
  953. ("%x AssemblyCount %d > %d", BundleCB,
  954. BundleRecvInfo->AssemblyCount, MAX_RECVDESC_COUNT + BundleCB->ulLinkCBCount));
  955. //
  956. // Flush the recv desc assembly window.
  957. //
  958. FlushRecvDescWindow(BundleCB, Class);
  959. }
  960. }
  961. VOID
  962. UpdateMinRecvSeqNumber(
  963. PBUNDLECB BundleCB,
  964. UINT Class
  965. )
  966. {
  967. PBUNDLE_RECV_INFO BundleRecvInfo;
  968. PLINK_RECV_INFO LinkRecvInfo;
  969. PLINKCB LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
  970. BundleRecvInfo = &BundleCB->RecvInfo[Class];
  971. LinkRecvInfo = &LinkCB->RecvInfo[Class];
  972. NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV,
  973. ("MinReceived c %x", BundleRecvInfo->MinSeqNumber));
  974. BundleRecvInfo->MinSeqNumber = LinkRecvInfo->LastSeqNumber;
  975. for (LinkCB = (PLINKCB)LinkCB->Linkage.Flink;
  976. (PVOID)LinkCB != (PVOID)&BundleCB->LinkCBList;
  977. LinkCB = (PLINKCB)LinkCB->Linkage.Flink) {
  978. LinkRecvInfo = &LinkCB->RecvInfo[Class];
  979. if (SEQ_LT(LinkRecvInfo->LastSeqNumber,
  980. BundleRecvInfo->MinSeqNumber,
  981. BundleCB->RecvSeqTest)) {
  982. BundleRecvInfo->MinSeqNumber = LinkRecvInfo->LastSeqNumber;
  983. }
  984. }
  985. NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV,
  986. ("MinReceived n %x", BundleRecvInfo->MinSeqNumber));
  987. }
  988. VOID
  989. FindHoleInRecvList(
  990. PBUNDLECB BundleCB,
  991. PRECV_DESC RecvDesc,
  992. UINT Class
  993. )
  994. /*++
  995. Routine Name:
  996. Routine Description:
  997. We want to start at the spot where the current hole was removed
  998. from and look for adjoining recv desc's in the list who have
  999. sequence numbers that differ by more than 1.
  1000. Arguments:
  1001. Return Values:
  1002. --*/
  1003. {
  1004. PRECV_DESC NextRecvDesc, RecvDescHole;
  1005. ULONG SequenceNumber;
  1006. PLIST_ENTRY RecvList;
  1007. PBUNDLE_RECV_INFO BundleRecvInfo;
  1008. BundleRecvInfo = &BundleCB->RecvInfo[Class];
  1009. RecvDescHole = BundleRecvInfo->RecvDescHole;
  1010. RecvList = &BundleRecvInfo->AssemblyList;
  1011. NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV,
  1012. ("h: %x", RecvDescHole->SequenceNumber));
  1013. if (IsListEmpty(RecvList)) {
  1014. //
  1015. // Set the new sequence number
  1016. //
  1017. RecvDescHole->SequenceNumber += 1;
  1018. RecvDescHole->SequenceNumber &= BundleCB->RecvSeqMask;
  1019. //
  1020. // Put the hole back on the list
  1021. //
  1022. InsertHeadList(RecvList, &RecvDescHole->Linkage);
  1023. } else {
  1024. //
  1025. // Walk the list looking for two descriptors that have
  1026. // sequence numbers differing by more than 1 or until we
  1027. // get to the end of the list
  1028. //
  1029. NextRecvDesc = (PRECV_DESC)RecvDesc->Linkage.Flink;
  1030. SequenceNumber = RecvDesc->SequenceNumber;
  1031. while (((PVOID)NextRecvDesc != (PVOID)RecvList) &&
  1032. (((NextRecvDesc->SequenceNumber - RecvDesc->SequenceNumber) &
  1033. BundleCB->RecvSeqMask) == 1)) {
  1034. RecvDesc = NextRecvDesc;
  1035. NextRecvDesc = (PRECV_DESC)RecvDesc->Linkage.Flink;
  1036. SequenceNumber = RecvDesc->SequenceNumber;
  1037. }
  1038. RecvDescHole->SequenceNumber = SequenceNumber + 1;
  1039. RecvDescHole->SequenceNumber &= BundleCB->RecvSeqMask;
  1040. RecvDescHole->Linkage.Flink = (PLIST_ENTRY)NextRecvDesc;
  1041. RecvDescHole->Linkage.Blink = (PLIST_ENTRY)RecvDesc;
  1042. RecvDesc->Linkage.Flink =
  1043. NextRecvDesc->Linkage.Blink =
  1044. (PLIST_ENTRY)RecvDescHole;
  1045. }
  1046. NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV, ("nh: %x", RecvDescHole->SequenceNumber));
  1047. }
  1048. VOID
  1049. FlushRecvDescWindow(
  1050. IN PBUNDLECB BundleCB,
  1051. IN UINT Class
  1052. )
  1053. /*++
  1054. Routine Name:
  1055. FlushRecvDescWindow
  1056. Routine Description:
  1057. This routine is called to flush recv desc's from the assembly list when
  1058. a fragment loss is detected. The idea is to flush fragments until we find
  1059. a begin fragment that has a sequence number >= the minimum received fragment
  1060. on the bundle.
  1061. Arguments:
  1062. --*/
  1063. {
  1064. PRECV_DESC RecvDescHole;
  1065. PRECV_DESC TempDesc=NULL;
  1066. PBUNDLE_RECV_INFO BundleRecvInfo;
  1067. BundleRecvInfo = &BundleCB->RecvInfo[Class];
  1068. RecvDescHole = BundleRecvInfo->RecvDescHole;
  1069. //
  1070. // Remove all recvdesc's until we find the hole
  1071. //
  1072. // To avoid passing a uninitialized TempDesc to FindHoleInRecvList
  1073. ASSERT(!IsListEmpty(&BundleRecvInfo->AssemblyList));
  1074. while (!IsListEmpty(&BundleRecvInfo->AssemblyList)) {
  1075. TempDesc = (PRECV_DESC)
  1076. RemoveHeadList(&BundleRecvInfo->AssemblyList);
  1077. if (TempDesc == RecvDescHole) {
  1078. break;
  1079. }
  1080. BundleRecvInfo->FragmentsLost++;
  1081. BundleRecvInfo->AssemblyCount--;
  1082. NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
  1083. ("flw %x %x h: %x", TempDesc->SequenceNumber,
  1084. TempDesc->Flags, RecvDescHole->SequenceNumber));
  1085. NdisWanFreeRecvDesc(TempDesc);
  1086. }
  1087. BundleCB->Stats.FramingErrors++;
  1088. //
  1089. // Now flush all recvdesc's until we find a begin fragment that has a
  1090. // sequence number >= M or the list is empty.
  1091. //
  1092. while (!IsListEmpty(&BundleRecvInfo->AssemblyList)) {
  1093. TempDesc = (PRECV_DESC)
  1094. BundleRecvInfo->AssemblyList.Flink;
  1095. if (TempDesc->Flags & MULTILINK_BEGIN_FRAME) {
  1096. break;
  1097. }
  1098. NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
  1099. ("flw %x %x h: %x", TempDesc->SequenceNumber,
  1100. TempDesc->Flags, RecvDescHole->SequenceNumber));
  1101. RecvDescHole->SequenceNumber = TempDesc->SequenceNumber;
  1102. RemoveHeadList(&BundleRecvInfo->AssemblyList);
  1103. BundleRecvInfo->AssemblyCount--;
  1104. BundleRecvInfo->FragmentsLost++;
  1105. NdisWanFreeRecvDesc(TempDesc);
  1106. TempDesc = NULL;
  1107. }
  1108. //
  1109. // Now reinsert the hole desc.
  1110. //
  1111. NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
  1112. ("h: %x", RecvDescHole->SequenceNumber));
  1113. FindHoleInRecvList(BundleCB, TempDesc, Class);
  1114. NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
  1115. ("nh: %x", RecvDescHole->SequenceNumber));
  1116. //
  1117. // See if we can complete some frames!!!!
  1118. //
  1119. TryToAssembleFrame(BundleCB, Class);
  1120. }
  1121. VOID
  1122. FlushAssemblyLists(
  1123. IN PBUNDLECB BundleCB
  1124. )
  1125. /*++
  1126. Routine Name:
  1127. Routine Description:
  1128. Arguments:
  1129. Return Values:
  1130. --*/
  1131. {
  1132. PRECV_DESC RecvDesc;
  1133. UINT Class;
  1134. for (Class = 0; Class < MAX_MCML; Class++) {
  1135. PBUNDLE_RECV_INFO RecvInfo = &BundleCB->RecvInfo[Class];
  1136. while (!IsListEmpty(&RecvInfo->AssemblyList)) {
  1137. RecvDesc = (PRECV_DESC)RemoveHeadList(&RecvInfo->AssemblyList);
  1138. RecvInfo->AssemblyCount--;
  1139. if (RecvDesc->Flags != MULTILINK_HOLE_FLAG) {
  1140. NdisWanFreeRecvDesc(RecvDesc);
  1141. }
  1142. }
  1143. }
  1144. }
  1145. VOID
  1146. TryToAssembleFrame(
  1147. PBUNDLECB BundleCB,
  1148. UINT Class
  1149. )
  1150. /*++
  1151. Routine Name:
  1152. TryToAssembleFrame
  1153. Routine Description:
  1154. The goal here is to walk the recv list looking for a full frame
  1155. (BeginFlag, EndFlag, no holes in between). If we do not have a
  1156. full frame we return FALSE.
  1157. If we have a full frame we remove each desc from the assembly list
  1158. copying the data into the first desc and returning all of the desc's
  1159. except the first one to the free pool. Once all of the data had been
  1160. collected we process the frame. After the frame has been processed
  1161. we return the first desc to the free pool.
  1162. Arguments:
  1163. Return Values:
  1164. --*/
  1165. {
  1166. PRECV_DESC RecvDesc, RecvDescHole;
  1167. PUCHAR DataPointer;
  1168. LINKCB LinkCB;
  1169. PBUNDLE_RECV_INFO BundleRecvInfo;
  1170. BundleRecvInfo = &BundleCB->RecvInfo[Class];
  1171. RecvDesc = (PRECV_DESC)BundleRecvInfo->AssemblyList.Flink;
  1172. RecvDescHole = BundleRecvInfo->RecvDescHole;
  1173. TryToAssembleAgain:
  1174. while ((RecvDesc != RecvDescHole) &&
  1175. (RecvDesc->Flags & MULTILINK_BEGIN_FRAME)) {
  1176. PRECV_DESC NextRecvDesc = (PRECV_DESC)RecvDesc->Linkage.Flink;
  1177. DataPointer = RecvDesc->CurrentBuffer + RecvDesc->CurrentLength;
  1178. while ((NextRecvDesc != RecvDescHole) &&
  1179. !(RecvDesc->Flags & MULTILINK_END_FRAME)) {
  1180. RemoveEntryList(&NextRecvDesc->Linkage);
  1181. BundleRecvInfo->AssemblyCount--;
  1182. ASSERT(NextRecvDesc != RecvDescHole);
  1183. ASSERT(RecvDesc != RecvDescHole);
  1184. NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV, ("c 0x%x -> 0x%x",
  1185. NextRecvDesc->SequenceNumber, RecvDesc->SequenceNumber));
  1186. NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV, ("fl 0x%x -> 0x%x",
  1187. NextRecvDesc->Flags, RecvDesc->Flags));
  1188. NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV, ("l %d -> %d",
  1189. NextRecvDesc->CurrentLength, RecvDesc->CurrentLength));
  1190. //
  1191. // Update recvdesc info
  1192. //
  1193. RecvDesc->Flags |= NextRecvDesc->Flags;
  1194. RecvDesc->SequenceNumber = NextRecvDesc->SequenceNumber;
  1195. RecvDesc->CurrentLength += NextRecvDesc->CurrentLength;
  1196. //
  1197. // Make sure we don't assemble something too big!
  1198. //
  1199. if (RecvDesc->CurrentLength > (LONG)glMRRU) {
  1200. NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
  1201. ("Max receive size exceeded!"));
  1202. //
  1203. // Return the recv desc's
  1204. //
  1205. RemoveEntryList(&RecvDesc->Linkage);
  1206. BundleRecvInfo->AssemblyCount--;
  1207. BundleCB->Stats.FramingErrors++;
  1208. NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
  1209. ("dumping %x %x h: %x", RecvDesc->SequenceNumber,
  1210. RecvDesc->Flags, RecvDescHole->SequenceNumber));
  1211. NdisWanFreeRecvDesc(RecvDesc);
  1212. NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
  1213. ("dumping %x %x h: %x", NextRecvDesc->SequenceNumber,
  1214. NextRecvDesc->Flags, RecvDescHole->SequenceNumber));
  1215. NdisWanFreeRecvDesc(NextRecvDesc);
  1216. //
  1217. // Start at the list head and flush until we find either the hole
  1218. // or a new begin fragment.
  1219. //
  1220. RecvDesc = (PRECV_DESC)BundleRecvInfo->AssemblyList.Flink;
  1221. while (RecvDesc != RecvDescHole &&
  1222. !(RecvDesc->Flags & MULTILINK_BEGIN_FRAME)) {
  1223. RemoveHeadList(&BundleRecvInfo->AssemblyList);
  1224. BundleRecvInfo->AssemblyCount--;
  1225. NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
  1226. ("dumping %x %x h: %x", RecvDesc->SequenceNumber,
  1227. RecvDesc->Flags, RecvDescHole->SequenceNumber));
  1228. NdisWanFreeRecvDesc(RecvDesc);
  1229. }
  1230. goto TryToAssembleAgain;
  1231. }
  1232. NdisMoveMemory(DataPointer,
  1233. NextRecvDesc->CurrentBuffer,
  1234. NextRecvDesc->CurrentLength);
  1235. DataPointer += NextRecvDesc->CurrentLength;
  1236. NdisWanFreeRecvDesc(NextRecvDesc);
  1237. NextRecvDesc = (PRECV_DESC)RecvDesc->Linkage.Flink;
  1238. }
  1239. //
  1240. // We hit a hole before completion of the frame.
  1241. // Get out.
  1242. //
  1243. if (!IsCompleteFrame(RecvDesc->Flags)) {
  1244. return;
  1245. }
  1246. //
  1247. // If we made it here we must have a begin flag, end flag, and
  1248. // no hole in between. Let's build a frame.
  1249. //
  1250. RecvDesc = (PRECV_DESC)
  1251. RemoveHeadList(&BundleRecvInfo->AssemblyList);
  1252. BundleRecvInfo->AssemblyCount--;
  1253. NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV, ("a %x %x", RecvDesc->SequenceNumber, RecvDesc->Flags));
  1254. RecvDesc->LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
  1255. if (NDIS_STATUS_PENDING != ProcessPPPFrame(BundleCB, RecvDesc)) {
  1256. NdisWanFreeRecvDesc(RecvDesc);
  1257. }
  1258. RecvDesc = (PRECV_DESC)BundleRecvInfo->AssemblyList.Flink;
  1259. } // end of while MULTILINK_BEGIN_FRAME
  1260. }
  1261. BOOLEAN
  1262. DoVJDecompression(
  1263. PBUNDLECB BundleCB,
  1264. PRECV_DESC RecvDesc
  1265. )
  1266. {
  1267. ULONG BundleFraming;
  1268. PUCHAR FramePointer = RecvDesc->CurrentBuffer;
  1269. LONG FrameLength = RecvDesc->CurrentLength;
  1270. UCHAR VJCompType = 0;
  1271. BOOLEAN DoDecomp = FALSE;
  1272. BOOLEAN VJDetect = FALSE;
  1273. BundleFraming = BundleCB->FramingInfo.RecvFramingBits;
  1274. if (BundleFraming & SLIP_FRAMING) {
  1275. VJCompType = *FramePointer & 0xF0;
  1276. //
  1277. // If the packet is compressed the header has to be atleast 3 bytes long.
  1278. // If this is a regular IP packet we do not decompress it.
  1279. //
  1280. if ((FrameLength > 2) && (VJCompType != TYPE_IP)) {
  1281. if (VJCompType & 0x80) {
  1282. VJCompType = TYPE_COMPRESSED_TCP;
  1283. } else if (VJCompType == TYPE_UNCOMPRESSED_TCP) {
  1284. *FramePointer &= 0x4F;
  1285. }
  1286. //
  1287. // If framing is set for detection, in order for this to be a good
  1288. // frame for detection we need a type of UNCOMPRESSED_TCP and a
  1289. // frame that is atleast 40 bytes long.
  1290. //
  1291. VJDetect = ((BundleFraming & SLIP_VJ_AUTODETECT) &&
  1292. (VJCompType == TYPE_UNCOMPRESSED_TCP) &&
  1293. (FrameLength > 39));
  1294. if ((BundleFraming & SLIP_VJ_COMPRESSION) || VJDetect) {
  1295. //
  1296. // If VJ compression is set or if we are in
  1297. // autodetect and this looks like a reasonable
  1298. // frame
  1299. //
  1300. DoDecomp = TRUE;
  1301. }
  1302. }
  1303. // end of SLIP_FRAMING
  1304. } else {
  1305. //
  1306. // Must be PPP framing
  1307. //
  1308. if (RecvDesc->ProtocolID == PPP_PROTOCOL_COMPRESSED_TCP) {
  1309. VJCompType = TYPE_COMPRESSED_TCP;
  1310. } else {
  1311. VJCompType = TYPE_UNCOMPRESSED_TCP;
  1312. }
  1313. DoDecomp = TRUE;
  1314. }
  1315. if (DoDecomp) {
  1316. PUCHAR HeaderBuffer;
  1317. LONG PostCompSize, PreCompSize;
  1318. PreCompSize = RecvDesc->CurrentLength;
  1319. HeaderBuffer =
  1320. RecvDesc->StartBuffer + MAC_HEADER_LENGTH;
  1321. if ((PostCompSize = sl_uncompress_tcp(&RecvDesc->CurrentBuffer,
  1322. &RecvDesc->CurrentLength,
  1323. HeaderBuffer,
  1324. &RecvDesc->HeaderLength,
  1325. VJCompType,
  1326. BundleCB->VJCompress)) == 0) {
  1327. NdisWanDbgOut(DBG_FAILURE, DBG_RECEIVE, ("Error in sl_uncompress_tcp!"));
  1328. return(FALSE);
  1329. }
  1330. if (VJDetect) {
  1331. BundleCB->FramingInfo.RecvFramingBits |= SLIP_VJ_COMPRESSION;
  1332. BundleCB->FramingInfo.SendFramingBits |= SLIP_VJ_COMPRESSION;
  1333. }
  1334. ASSERT(PostCompSize == RecvDesc->HeaderLength + RecvDesc->CurrentLength);
  1335. #if DBG
  1336. if (VJCompType == TYPE_COMPRESSED_TCP) {
  1337. ASSERT(RecvDesc->HeaderLength > 0);
  1338. NdisWanDbgOut(DBG_TRACE, DBG_RECV_VJ,("rvj b %d a %d",(RecvDesc->HeaderLength - (PostCompSize-PreCompSize)), RecvDesc->HeaderLength));
  1339. }
  1340. #endif
  1341. //
  1342. // Calculate how much expansion we had
  1343. //
  1344. BundleCB->Stats.BytesReceivedCompressed +=
  1345. (RecvDesc->HeaderLength - (PostCompSize - PreCompSize));
  1346. BundleCB->Stats.BytesReceivedUncompressed += RecvDesc->HeaderLength;
  1347. }
  1348. RecvDesc->ProtocolID = PPP_PROTOCOL_IP;
  1349. return(TRUE);
  1350. }
  1351. #define SEQ_TYPE_IN_ORDER 1
  1352. #define SEQ_TYPE_AFTER_EXPECTED 2
  1353. #define SEQ_TYPE_BEFORE_EXPECTED 3
  1354. BOOLEAN
  1355. DoDecompDecryptProcessing(
  1356. PBUNDLECB BundleCB,
  1357. PUCHAR *DataPointer,
  1358. PLONG DataLength
  1359. )
  1360. {
  1361. USHORT Coherency, CurrCoherency;
  1362. ULONG Flags;
  1363. PWAN_STATS BundleStats;
  1364. PUCHAR FramePointer = *DataPointer;
  1365. LONG FrameLength = *DataLength;
  1366. ULONG PacketSeqType;
  1367. LONG OutOfOrderDepth;
  1368. LONG NumberMissed = 0;
  1369. Flags = BundleCB->RecvFlags;
  1370. BundleStats = &BundleCB->Stats;
  1371. if (Flags & (DO_COMPRESSION | DO_ENCRYPTION)) {
  1372. PUCHAR SessionKey = BundleCB->RecvCryptoInfo.SessionKey;
  1373. ULONG SessionKeyLength = BundleCB->RecvCryptoInfo.SessionKeyLength;
  1374. PVOID RecvRC4Key = BundleCB->RecvCryptoInfo.RC4Key;
  1375. PVOID RecvCompressContext = BundleCB->RecvCompressContext;
  1376. BOOLEAN SyncCoherency = FALSE;
  1377. //
  1378. // Get the coherency counter
  1379. //
  1380. Coherency = (*FramePointer << 8) | *(FramePointer + 1);
  1381. FramePointer += 2;
  1382. FrameLength -= 2;
  1383. if (FrameLength <= 0) {
  1384. goto RESYNC;
  1385. }
  1386. if (!(Flags & DO_HISTORY_LESS))
  1387. {
  1388. // history-based
  1389. if (SEQ_LT(Coherency & 0x0FFF,
  1390. BundleCB->RCoherencyCounter & 0x0FFF,
  1391. 0x0800)) {
  1392. //
  1393. // We received a sequence number that is less then the
  1394. // expected sequence number so we must be way out of sync
  1395. //
  1396. NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_RECEIVE,
  1397. ("Recv old frame!!!! b %p rc %x < ec %x!!!!", BundleCB, Coherency & 0x0FFF,
  1398. BundleCB->RCoherencyCounter & 0x0FFF));
  1399. goto RESYNC;
  1400. }
  1401. }
  1402. else
  1403. {
  1404. // history-less
  1405. if((Coherency & 0x0FFF) == (BundleCB->RCoherencyCounter & 0x0FFF))
  1406. {
  1407. PacketSeqType = SEQ_TYPE_IN_ORDER;
  1408. }
  1409. else
  1410. {
  1411. if (SEQ_GT(Coherency & 0x0FFF,
  1412. BundleCB->RCoherencyCounter & 0x0FFF,
  1413. 0x0800))
  1414. {
  1415. PacketSeqType = SEQ_TYPE_BEFORE_EXPECTED;
  1416. NumberMissed = ((Coherency & 0x0FFF) - (BundleCB->RCoherencyCounter & 0x0FFF)) & 0x0FFF;
  1417. ASSERT(NumberMissed > 0);
  1418. }
  1419. else
  1420. {
  1421. OutOfOrderDepth = ((BundleCB->RCoherencyCounter & 0x0FFF) - (Coherency & 0x0FFF)) & 0x0FFF;
  1422. if(OutOfOrderDepth <= (LONG)glMaxOutOfOrderDepth)
  1423. {
  1424. PacketSeqType = SEQ_TYPE_AFTER_EXPECTED;
  1425. }
  1426. else
  1427. {
  1428. //
  1429. // We received a sequence number that is either too earlier or too later
  1430. //
  1431. NdisWanDbgOut(DBG_FAILURE, DBG_RECEIVE,
  1432. ("Recv frame way out of order! b %p rc %x < ec %x!!!!", BundleCB, Coherency & 0x0FFF,
  1433. BundleCB->RCoherencyCounter & 0x0FFF));
  1434. return (FALSE);
  1435. }
  1436. }
  1437. }
  1438. }
  1439. //
  1440. // See if this is a flush packet
  1441. //
  1442. if (Coherency & (PACKET_FLUSHED << 8)) {
  1443. NdisWanDbgOut(DBG_INFO, DBG_RECEIVE,
  1444. ("Recv Packet Flushed 0x%x", (Coherency & 0x0FFF)));
  1445. SyncCoherency = TRUE;
  1446. if ((Flags & DO_ENCRYPTION) &&
  1447. !(Flags & DO_HISTORY_LESS)) {
  1448. //
  1449. // Re-Init the rc4 receive table
  1450. //
  1451. rc4_key(RecvRC4Key,
  1452. SessionKeyLength,
  1453. SessionKey);
  1454. }
  1455. if (Flags & DO_COMPRESSION) {
  1456. //
  1457. // Initialize the decompression history table
  1458. //
  1459. initrecvcontext(RecvCompressContext);
  1460. }
  1461. } // end of packet flushed
  1462. //
  1463. // If we are in history-less mode and we get out of sync
  1464. // we need to recreate all of the interim encryption
  1465. // keys that we missed, cache the keys
  1466. // When a packet comes in later, look for the cached key
  1467. //
  1468. if ((Flags & DO_HISTORY_LESS) &&
  1469. PacketSeqType != SEQ_TYPE_IN_ORDER) {
  1470. ULONG count;
  1471. LONG index;
  1472. PCACHED_KEY pKey;
  1473. if(PacketSeqType == SEQ_TYPE_AFTER_EXPECTED)
  1474. {
  1475. if (Coherency & (PACKET_ENCRYPTED << 8))
  1476. {
  1477. // This packet is encrypted
  1478. if (!(Flags & DO_ENCRYPTION)) {
  1479. //
  1480. // We are not configured to decrypt
  1481. //
  1482. return (FALSE);
  1483. }
  1484. // Find the cached key for this packet
  1485. pKey = BundleCB->RecvCryptoInfo.pCurrKey;
  1486. for(count = 0; count < glCachedKeyCount; count++)
  1487. {
  1488. // Walk through the keys
  1489. if(pKey > (PCACHED_KEY)BundleCB->RecvCryptoInfo.CachedKeyBuffer)
  1490. {
  1491. pKey = (PCACHED_KEY)((PUCHAR)pKey - (sizeof(USHORT)+ SessionKeyLength));
  1492. }
  1493. else
  1494. {
  1495. pKey = (PCACHED_KEY)BundleCB->RecvCryptoInfo.pLastKey;
  1496. }
  1497. if(pKey->Coherency == (Coherency & 0x0FFF))
  1498. {
  1499. //
  1500. // Re-Init the rc4 receive table
  1501. //
  1502. rc4_key(RecvRC4Key,
  1503. SessionKeyLength,
  1504. pKey->SessionKey);
  1505. pKey->Coherency = 0xffff; // avoid duplication
  1506. //
  1507. // Decrypt the data!
  1508. //
  1509. rc4(RecvRC4Key,
  1510. FrameLength,
  1511. FramePointer);
  1512. goto DECOMPRESS_DATA;
  1513. }
  1514. }
  1515. // Can't recover this packet, drop it
  1516. return (FALSE);
  1517. }
  1518. goto DECOMPRESS_DATA;
  1519. }
  1520. // This packet comes earlier than expected
  1521. SyncCoherency = TRUE;
  1522. if (Flags & DO_ENCRYPTION) {
  1523. #ifdef DBG_ECP
  1524. DbgPrint("NDISWAN: Missed %d frames, regening keys...\n", NumberMissed);
  1525. DbgPrint("NDISWAN: resync b %p rc %x ec %x\n", BundleCB, Coherency & 0x0FFF,
  1526. BundleCB->RCoherencyCounter & 0x0FFF);
  1527. #endif
  1528. CurrCoherency = BundleCB->RCoherencyCounter & 0x0FFF;
  1529. while (NumberMissed--) {
  1530. if (Flags & DO_LEGACY_ENCRYPTION) {
  1531. //
  1532. // Change the session key
  1533. //
  1534. SessionKey[3] += 1;
  1535. SessionKey[4] += 3;
  1536. SessionKey[5] += 13;
  1537. SessionKey[6] += 57;
  1538. SessionKey[7] += 19;
  1539. } else {
  1540. //
  1541. // Change the session key
  1542. //
  1543. GetNewKeyFromSHA(&BundleCB->RecvCryptoInfo);
  1544. }
  1545. //
  1546. // We use rc4 to scramble and recover a new key
  1547. //
  1548. //
  1549. // Re-initialize the rc4 receive table to the
  1550. // intermediate value
  1551. //
  1552. rc4_key(RecvRC4Key, SessionKeyLength, SessionKey);
  1553. //
  1554. // Scramble the existing session key
  1555. //
  1556. rc4(RecvRC4Key, SessionKeyLength, SessionKey);
  1557. if (Flags & DO_40_ENCRYPTION) {
  1558. //
  1559. // If this is 40 bit encryption we need to fix
  1560. // the first 3 bytes of the key.
  1561. //
  1562. SessionKey[0] = 0xD1;
  1563. SessionKey[1] = 0x26;
  1564. SessionKey[2] = 0x9E;
  1565. } else if (Flags & DO_56_ENCRYPTION) {
  1566. //
  1567. // If this is 56 bit encryption we need to fix
  1568. // the first byte of the key.
  1569. //
  1570. SessionKey[0] = 0xD1;
  1571. }
  1572. if(NumberMissed < (LONG)glCachedKeyCount)
  1573. {
  1574. BundleCB->RecvCryptoInfo.pCurrKey->Coherency = CurrCoherency;
  1575. NdisMoveMemory(BundleCB->RecvCryptoInfo.pCurrKey->SessionKey,
  1576. SessionKey,
  1577. SessionKeyLength);
  1578. if(BundleCB->RecvCryptoInfo.pCurrKey < BundleCB->RecvCryptoInfo.pLastKey)
  1579. {
  1580. BundleCB->RecvCryptoInfo.pCurrKey = (PCACHED_KEY)((PUCHAR)BundleCB->RecvCryptoInfo.pCurrKey +
  1581. sizeof(USHORT) + SessionKeyLength);
  1582. ASSERT(BundleCB->RecvCryptoInfo.pCurrKey <= BundleCB->RecvCryptoInfo.pLastKey);
  1583. }
  1584. else
  1585. {
  1586. BundleCB->RecvCryptoInfo.pCurrKey = (PCACHED_KEY)BundleCB->RecvCryptoInfo.CachedKeyBuffer;
  1587. }
  1588. }
  1589. NdisWanDbgOut(DBG_TRACE, DBG_CCP,
  1590. ("RC4 Recv encryption KeyLength %d", BundleCB->RecvCryptoInfo.SessionKeyLength));
  1591. NdisWanDbgOut(DBG_TRACE, DBG_CCP,
  1592. ("RC4 Recv encryption Key %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x",
  1593. BundleCB->RecvCryptoInfo.SessionKey[0],
  1594. BundleCB->RecvCryptoInfo.SessionKey[1],
  1595. BundleCB->RecvCryptoInfo.SessionKey[2],
  1596. BundleCB->RecvCryptoInfo.SessionKey[3],
  1597. BundleCB->RecvCryptoInfo.SessionKey[4],
  1598. BundleCB->RecvCryptoInfo.SessionKey[5],
  1599. BundleCB->RecvCryptoInfo.SessionKey[6],
  1600. BundleCB->RecvCryptoInfo.SessionKey[7],
  1601. BundleCB->RecvCryptoInfo.SessionKey[8],
  1602. BundleCB->RecvCryptoInfo.SessionKey[9],
  1603. BundleCB->RecvCryptoInfo.SessionKey[10],
  1604. BundleCB->RecvCryptoInfo.SessionKey[11],
  1605. BundleCB->RecvCryptoInfo.SessionKey[12],
  1606. BundleCB->RecvCryptoInfo.SessionKey[13],
  1607. BundleCB->RecvCryptoInfo.SessionKey[14],
  1608. BundleCB->RecvCryptoInfo.SessionKey[15]));
  1609. // Re-initialize the rc4 receive table to the
  1610. // scrambled session key
  1611. //
  1612. rc4_key(RecvRC4Key, SessionKeyLength, SessionKey);
  1613. if(CurrCoherency < (USHORT)0x0FFF)
  1614. {
  1615. ++CurrCoherency;
  1616. }
  1617. else
  1618. {
  1619. CurrCoherency = 0;
  1620. }
  1621. }
  1622. }
  1623. }
  1624. if (SyncCoherency) {
  1625. if ((BundleCB->RCoherencyCounter & 0x0FFF) >
  1626. (Coherency & 0x0FFF)) {
  1627. BundleCB->RCoherencyCounter += 0x1000;
  1628. }
  1629. BundleCB->RCoherencyCounter &= 0xF000;
  1630. BundleCB->RCoherencyCounter |= (Coherency & 0x0FFF);
  1631. }
  1632. if ((Coherency & 0x0FFF) == (BundleCB->RCoherencyCounter & 0x0FFF)) {
  1633. //
  1634. // We are still in sync
  1635. //
  1636. BundleCB->RCoherencyCounter++;
  1637. if (Coherency & (PACKET_ENCRYPTED << 8)) {
  1638. //
  1639. // This packet is encrypted
  1640. //
  1641. if (!(Flags & DO_ENCRYPTION)) {
  1642. //
  1643. // We are not configured to decrypt
  1644. //
  1645. return (FALSE);
  1646. }
  1647. //
  1648. // Check for history less
  1649. //
  1650. if ((Flags & DO_HISTORY_LESS) ||
  1651. (BundleCB->RCoherencyCounter - BundleCB->LastRC4Reset)
  1652. >= 0x100) {
  1653. //
  1654. // It is time to change encryption keys
  1655. //
  1656. //
  1657. // Always align last reset on 0x100 boundary so as not to
  1658. // propagate error!
  1659. //
  1660. BundleCB->LastRC4Reset =
  1661. BundleCB->RCoherencyCounter & 0xFF00;
  1662. //
  1663. // Prevent ushort rollover
  1664. //
  1665. if ((BundleCB->LastRC4Reset & 0xF000) == 0xF000) {
  1666. BundleCB->LastRC4Reset &= 0x0FFF;
  1667. BundleCB->RCoherencyCounter &= 0x0FFF;
  1668. }
  1669. if (Flags & DO_LEGACY_ENCRYPTION) {
  1670. //
  1671. // Change the session key
  1672. //
  1673. SessionKey[3] += 1;
  1674. SessionKey[4] += 3;
  1675. SessionKey[5] += 13;
  1676. SessionKey[6] += 57;
  1677. SessionKey[7] += 19;
  1678. } else {
  1679. //
  1680. // Change the session key
  1681. //
  1682. GetNewKeyFromSHA(&BundleCB->RecvCryptoInfo);
  1683. }
  1684. //
  1685. // We use rc4 to scramble and recover a new key
  1686. //
  1687. //
  1688. // Re-initialize the rc4 receive table to the
  1689. // intermediate value
  1690. //
  1691. rc4_key(RecvRC4Key, SessionKeyLength, SessionKey);
  1692. //
  1693. // Scramble the existing session key
  1694. //
  1695. rc4(RecvRC4Key, SessionKeyLength, SessionKey);
  1696. //
  1697. // If this is 40 bit encryption we need to fix
  1698. // the first 3 bytes of the key.
  1699. //
  1700. if (Flags & DO_40_ENCRYPTION) {
  1701. //
  1702. // If this is 40 bit encryption we need to fix
  1703. // the first 3 bytes of the key.
  1704. //
  1705. SessionKey[0] = 0xD1;
  1706. SessionKey[1] = 0x26;
  1707. SessionKey[2] = 0x9E;
  1708. } else if (Flags & DO_56_ENCRYPTION) {
  1709. //
  1710. // If this is 56 bit encryption we need to fix
  1711. // the first byte of the key.
  1712. //
  1713. SessionKey[0] = 0xD1;
  1714. }
  1715. NdisWanDbgOut(DBG_TRACE, DBG_CCP,
  1716. ("RC4 Recv encryption KeyLength %d", BundleCB->RecvCryptoInfo.SessionKeyLength));
  1717. NdisWanDbgOut(DBG_TRACE, DBG_CCP,
  1718. ("RC4 Recv encryption Key %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x",
  1719. BundleCB->RecvCryptoInfo.SessionKey[0],
  1720. BundleCB->RecvCryptoInfo.SessionKey[1],
  1721. BundleCB->RecvCryptoInfo.SessionKey[2],
  1722. BundleCB->RecvCryptoInfo.SessionKey[3],
  1723. BundleCB->RecvCryptoInfo.SessionKey[4],
  1724. BundleCB->RecvCryptoInfo.SessionKey[5],
  1725. BundleCB->RecvCryptoInfo.SessionKey[6],
  1726. BundleCB->RecvCryptoInfo.SessionKey[7],
  1727. BundleCB->RecvCryptoInfo.SessionKey[8],
  1728. BundleCB->RecvCryptoInfo.SessionKey[9],
  1729. BundleCB->RecvCryptoInfo.SessionKey[10],
  1730. BundleCB->RecvCryptoInfo.SessionKey[11],
  1731. BundleCB->RecvCryptoInfo.SessionKey[12],
  1732. BundleCB->RecvCryptoInfo.SessionKey[13],
  1733. BundleCB->RecvCryptoInfo.SessionKey[14],
  1734. BundleCB->RecvCryptoInfo.SessionKey[15]));
  1735. // Re-initialize the rc4 receive table to the
  1736. // scrambled session key
  1737. //
  1738. rc4_key(RecvRC4Key, SessionKeyLength, SessionKey);
  1739. } // end of reset encryption key
  1740. //
  1741. // Decrypt the data!
  1742. //
  1743. rc4(RecvRC4Key,
  1744. FrameLength,
  1745. FramePointer);
  1746. } // end of encryption
  1747. DECOMPRESS_DATA:
  1748. if (Coherency & (PACKET_COMPRESSED << 8)) {
  1749. //
  1750. // This packet is compressed!
  1751. //
  1752. if (!(Flags & DO_COMPRESSION)) {
  1753. //
  1754. // We are not configured to decompress
  1755. //
  1756. return (FALSE);
  1757. }
  1758. //
  1759. // Add up bundle stats
  1760. //
  1761. BundleStats->BytesReceivedCompressed += FrameLength;
  1762. if (decompress(FramePointer,
  1763. FrameLength,
  1764. ((Coherency & (PACKET_AT_FRONT << 8)) >> 8),
  1765. &FramePointer,
  1766. &FrameLength,
  1767. RecvCompressContext) == FALSE) {
  1768. #if DBG
  1769. DbgPrint("dce1 %x\n", Coherency);
  1770. #endif
  1771. //
  1772. // Error decompressing!
  1773. //
  1774. if (!(Flags & DO_HISTORY_LESS)) {
  1775. BundleCB->RCoherencyCounter--;
  1776. }
  1777. goto RESYNC;
  1778. }
  1779. if (FrameLength <= 0 ||
  1780. FrameLength > (LONG)glMRRU) {
  1781. #if DBG
  1782. DbgPrint("dce2 %d %x\n", FrameLength, Coherency);
  1783. #endif
  1784. //
  1785. // Error decompressing!
  1786. //
  1787. if (!(Flags & DO_HISTORY_LESS)) {
  1788. BundleCB->RCoherencyCounter--;
  1789. }
  1790. goto RESYNC;
  1791. }
  1792. BundleStats->BytesReceivedUncompressed += FrameLength;
  1793. } // end of compression
  1794. } else { // end of insync
  1795. RESYNC:
  1796. NdisWanDbgOut(DBG_FAILURE, DBG_RECEIVE, ("oos r %x, e %x\n", (Coherency & 0x0FFF),
  1797. (BundleCB->RCoherencyCounter & 0x0FFF)));
  1798. if (!(Flags & DO_HISTORY_LESS)) {
  1799. //
  1800. // We are out of sync!
  1801. //
  1802. do {
  1803. PLINKCB LinkCB;
  1804. PNDISWAN_IO_PACKET IoPacket;
  1805. if (BundleCB->ulLinkCBCount == 0) {
  1806. break;
  1807. }
  1808. NdisWanAllocateMemory(&IoPacket,
  1809. sizeof(NDISWAN_IO_PACKET) + 100,
  1810. IOPACKET_TAG);
  1811. if (IoPacket == NULL) {
  1812. break;
  1813. }
  1814. LinkCB =
  1815. (PLINKCB)BundleCB->LinkCBList.Flink;
  1816. NdisDprAcquireSpinLock(&LinkCB->Lock);
  1817. if (LinkCB->State != LINK_UP) {
  1818. NdisDprReleaseSpinLock(&LinkCB->Lock);
  1819. NdisWanFreeMemory(IoPacket);
  1820. break;
  1821. }
  1822. REF_LINKCB(LinkCB);
  1823. NdisDprReleaseSpinLock(&LinkCB->Lock);
  1824. IoPacket->hHandle = BundleCB->hBundleHandle;
  1825. IoPacket->usHandleType = BUNDLEHANDLE;
  1826. IoPacket->usHeaderSize = 0;
  1827. IoPacket->usPacketSize = 6;
  1828. IoPacket->usPacketFlags = 0;
  1829. IoPacket->PacketData[0] = 0x80;
  1830. IoPacket->PacketData[1] = 0xFD;
  1831. IoPacket->PacketData[2] = 14;
  1832. IoPacket->PacketData[3] = (UCHAR)BundleCB->CCPIdentifier++;
  1833. IoPacket->PacketData[4] = 0x00;
  1834. IoPacket->PacketData[5] = 0x04;
  1835. LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
  1836. BuildIoPacket(LinkCB, BundleCB, IoPacket, FALSE);
  1837. NdisWanFreeMemory(IoPacket);
  1838. } while (FALSE);
  1839. }
  1840. return (FALSE);
  1841. } // end of out of sync
  1842. } else { // end of DoCompEncrypt
  1843. //
  1844. // For some reason we were not able to
  1845. // decrypt/decompress!
  1846. //
  1847. return (FALSE);
  1848. }
  1849. *DataPointer = FramePointer;
  1850. *DataLength = FrameLength;
  1851. return (TRUE);
  1852. }
  1853. VOID
  1854. DoCompressionReset(
  1855. PBUNDLECB BundleCB
  1856. )
  1857. {
  1858. if (BundleCB->RecvCompInfo.MSCompType != 0) {
  1859. //
  1860. // The next outgoing packet will flush
  1861. //
  1862. BundleCB->Flags |= RECV_PACKET_FLUSH;
  1863. }
  1864. }
  1865. VOID
  1866. NdisWanReceiveComplete(
  1867. IN NDIS_HANDLE NdisLinkContext
  1868. )
  1869. /*++
  1870. Routine Name:
  1871. Routine Description:
  1872. Arguments:
  1873. Return Values:
  1874. --*/
  1875. {
  1876. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("NdisWanReceiveComplete: Enter"));
  1877. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("NdisWanReceiveComplete: Exit"));
  1878. }
  1879. BOOLEAN
  1880. IpIsDataFrame(
  1881. PUCHAR HeaderBuffer,
  1882. ULONG HeaderBufferLength,
  1883. ULONG TotalLength
  1884. )
  1885. {
  1886. UINT tcpheaderlength ;
  1887. UINT ipheaderlength ;
  1888. UCHAR *tcppacket;
  1889. UCHAR *ippacket = HeaderBuffer;
  1890. UCHAR SrcPort, DstPort;
  1891. IPV4Header UNALIGNED *ipheader = (IPV4Header UNALIGNED *) HeaderBuffer;
  1892. #define TYPE_IGMP 2
  1893. if (ipheader->ip_p == TYPE_IGMP) {
  1894. if (gbIGMPIdle) {
  1895. return FALSE;
  1896. }
  1897. return TRUE;
  1898. }
  1899. SrcPort = (UCHAR) *(ippacket + ((*ippacket & 0x0f)*4) + 1);
  1900. DstPort = (UCHAR) *(ippacket + ((*ippacket & 0x0f)*4) + 3);
  1901. if (DstPort == 53) {
  1902. //
  1903. // UDP/TCP port 53 - DNS
  1904. //
  1905. return FALSE;
  1906. }
  1907. #define TYPE_UDP 17
  1908. #define UDPPACKET_SRC_PORT_137(x) ((UCHAR) *(x + ((*x & 0x0f)*4) + 1) == 137)
  1909. #define UDPPACKET_SRC_PORT_138(x) ((UCHAR) *(x + ((*x & 0x0f)*4) + 1) == 138)
  1910. if (ipheader->ip_p == TYPE_UDP) {
  1911. if ((SrcPort == 137) ||
  1912. (SrcPort == 138)) {
  1913. //
  1914. // UDP port 137 - NETBIOS Name Service
  1915. // UDP port 138 - NETBIOS Datagram Service
  1916. //
  1917. return FALSE ;
  1918. } else {
  1919. return TRUE ;
  1920. }
  1921. }
  1922. #define TYPE_TCP 6
  1923. #define TCPPACKET_SRC_OR_DEST_PORT_139(x,y) (((UCHAR) *(x + y + 1) == 139) || ((UCHAR) *(x + y + 3) == 139))
  1924. //
  1925. // TCP packets with SRC | DEST == 139 which are ACKs (0 data) or Session Alives
  1926. // are considered as idle
  1927. //
  1928. if (ipheader->ip_p == TYPE_TCP) {
  1929. ipheaderlength = ((UCHAR)*ippacket & 0x0f)*4 ;
  1930. tcppacket = ippacket + ipheaderlength ;
  1931. tcpheaderlength = (*(tcppacket + 10) >> 4)*4 ;
  1932. //
  1933. // If this is a PPTP keepalive packet then ignore
  1934. //
  1935. if (DstPort == 1723) {
  1936. UNALIGNED PPTP_HEADER *PptpHeader;
  1937. PptpHeader = (UNALIGNED PPTP_HEADER*)(tcppacket+tcpheaderlength);
  1938. if (PptpHeader->PacketType == 1 &&
  1939. (PptpHeader->MessageType == 5 ||
  1940. PptpHeader->MessageType == 6)) {
  1941. return FALSE;
  1942. }
  1943. return TRUE;
  1944. }
  1945. if (!((SrcPort == 139) || (DstPort == 139)))
  1946. return TRUE ;
  1947. //
  1948. // NetBT traffic
  1949. //
  1950. //
  1951. // if zero length tcp packet - this is an ACK on 139 - filter this.
  1952. //
  1953. if (TotalLength == (ipheaderlength + tcpheaderlength))
  1954. return FALSE ;
  1955. //
  1956. // Session alives are also filtered.
  1957. //
  1958. if ((UCHAR) *(tcppacket+tcpheaderlength) == 0x85)
  1959. return FALSE ;
  1960. //
  1961. // If this is a PPTP keep alive then ignore
  1962. //
  1963. }
  1964. //
  1965. // all other ip traffic is valid traffic
  1966. //
  1967. return TRUE ;
  1968. }
  1969. BOOLEAN
  1970. IpxIsDataFrame(
  1971. PUCHAR HeaderBuffer,
  1972. ULONG HeaderBufferLength,
  1973. ULONG TotalLength
  1974. )
  1975. {
  1976. /*++
  1977. Routine Description:
  1978. This routine is called when a frame is received on a WAN
  1979. line. It returns TRUE unless:
  1980. - The frame is from the RIP socket
  1981. - The frame is from the SAP socket
  1982. - The frame is a netbios keep alive
  1983. - The frame is an NCP keep alive
  1984. Arguments:
  1985. HeaderBuffer - points to a contiguous buffer starting at the IPX header.
  1986. HeaderBufferLength - Length of the header buffer (could be same as totallength)
  1987. TotalLength - the total length of the frame
  1988. Return Value:
  1989. TRUE - if this is a connection-based packet.
  1990. FALSE - otherwise.
  1991. --*/
  1992. IPX_HEADER UNALIGNED * IpxHeader = (IPX_HEADER UNALIGNED *)HeaderBuffer;
  1993. USHORT SourceSocket;
  1994. //
  1995. // First get the source socket.
  1996. //
  1997. SourceSocket = IpxHeader->SourceSocket;
  1998. //
  1999. // Not connection-based
  2000. //
  2001. if ((SourceSocket == RIP_SOCKET) ||
  2002. (SourceSocket == SAP_SOCKET)) {
  2003. return FALSE;
  2004. }
  2005. //
  2006. // See if there are at least two more bytes to look at.
  2007. //
  2008. if (TotalLength >= sizeof(IPX_HEADER) + 2) {
  2009. if (SourceSocket == NB_SOCKET) {
  2010. UCHAR ConnectionControlFlag;
  2011. UCHAR DataStreamType;
  2012. USHORT TotalDataLength;
  2013. //
  2014. // ConnectionControlFlag and DataStreamType will always follow
  2015. // IpxHeader
  2016. //
  2017. ConnectionControlFlag = ((PUCHAR)(IpxHeader+1))[0];
  2018. DataStreamType = ((PUCHAR)(IpxHeader+1))[1];
  2019. //
  2020. // If this is a SYS packet with or without a request for ACK and
  2021. // has session data in it.
  2022. //
  2023. if (((ConnectionControlFlag == 0x80) || (ConnectionControlFlag == 0xc0)) &&
  2024. (DataStreamType == 0x06)) {
  2025. //
  2026. // TotalDataLength is in the same buffer.
  2027. //
  2028. TotalDataLength = ((USHORT UNALIGNED *)(IpxHeader+1))[4];
  2029. //
  2030. // KeepAlive - return FALSE
  2031. //
  2032. if (TotalDataLength == 0) {
  2033. return FALSE;
  2034. }
  2035. }
  2036. } else {
  2037. //
  2038. // Now see if it is an NCP keep alive. It can be from rip or from
  2039. // NCP on this machine
  2040. //
  2041. if (TotalLength == sizeof(IPX_HEADER) + 2) {
  2042. UCHAR KeepAliveSignature = ((PUCHAR)(IpxHeader+1))[1];
  2043. if ((KeepAliveSignature == '?') ||
  2044. (KeepAliveSignature == 'Y')) {
  2045. return FALSE;
  2046. }
  2047. }
  2048. }
  2049. }
  2050. //
  2051. // This was a normal packet, so return TRUE
  2052. //
  2053. return TRUE;
  2054. }
  2055. BOOLEAN
  2056. NbfIsDataFrame(
  2057. PUCHAR HeaderBuffer,
  2058. ULONG HeaderBufferLength,
  2059. ULONG TotalLength
  2060. )
  2061. {
  2062. /*++
  2063. Routine Description:
  2064. This routine looks at a data packet from the net to deterimine if there is
  2065. any data flowing on the connection.
  2066. Arguments:
  2067. HeaderBuffer - Pointer to the dlc header for this packet.
  2068. HeaderBufferLength - Length of the header buffer (could be same as totallength)
  2069. TotalLength - the total length of the frame
  2070. Return Value:
  2071. True if this is a frame that indicates data traffic on the connection.
  2072. False otherwise.
  2073. --*/
  2074. PDLC_FRAME DlcHeader = (PDLC_FRAME)HeaderBuffer;
  2075. BOOLEAN Command = (BOOLEAN)!(DlcHeader->Ssap & DLC_SSAP_RESPONSE);
  2076. PNBF_HDR_CONNECTION nbfHeader;
  2077. if (TotalLength < sizeof(PDLC_FRAME)) {
  2078. return(FALSE);
  2079. }
  2080. if (!(DlcHeader->Byte1 & DLC_I_INDICATOR)) {
  2081. //
  2082. // We have an I frame.
  2083. //
  2084. if (TotalLength < 4 + sizeof(NBF_HDR_CONNECTION)) {
  2085. //
  2086. // It's a runt I-frame.
  2087. //
  2088. return(FALSE);
  2089. }
  2090. nbfHeader = (PNBF_HDR_CONNECTION) ((PUCHAR)DlcHeader + 4);
  2091. switch (nbfHeader->Command) {
  2092. case NBF_CMD_DATA_FIRST_MIDDLE:
  2093. case NBF_CMD_DATA_ONLY_LAST:
  2094. case NBF_CMD_DATA_ACK:
  2095. case NBF_CMD_SESSION_CONFIRM:
  2096. case NBF_CMD_SESSION_INITIALIZE:
  2097. case NBF_CMD_NO_RECEIVE:
  2098. case NBF_CMD_RECEIVE_OUTSTANDING:
  2099. case NBF_CMD_RECEIVE_CONTINUE:
  2100. return(TRUE);
  2101. break;
  2102. default:
  2103. return(FALSE);
  2104. break;
  2105. }
  2106. }
  2107. return(FALSE);
  2108. }
  2109. VOID
  2110. IndicatePromiscuousRecv(
  2111. PBUNDLECB BundleCB,
  2112. PRECV_DESC RecvDesc,
  2113. RECV_TYPE RecvType
  2114. )
  2115. {
  2116. UCHAR Header1[] = {' ', 'W', 'A', 'N', 'R', 0xFF, ' ', 'W', 'A', 'N', 'R', 0xFF};
  2117. PUCHAR HeaderBuffer, DataBuffer;
  2118. ULONG HeaderLength, DataLength;
  2119. PNDIS_BUFFER NdisBuffer;
  2120. PNDIS_PACKET NdisPacket;
  2121. PRECV_DESC LocalRecvDesc;
  2122. PLINKCB LinkCB = RecvDesc->LinkCB;
  2123. KIRQL OldIrql;
  2124. PMINIPORTCB Adapter;
  2125. NdisAcquireSpinLock(&NdisWanCB.Lock);
  2126. Adapter = NdisWanCB.PromiscuousAdapter;
  2127. NdisReleaseSpinLock(&NdisWanCB.Lock);
  2128. if (Adapter == NULL) {
  2129. return;
  2130. }
  2131. DataLength = (RecvDesc->CurrentLength > (LONG)glLargeDataBufferSize) ?
  2132. glLargeDataBufferSize : RecvDesc->CurrentLength;
  2133. LocalRecvDesc =
  2134. NdisWanAllocateRecvDesc(DataLength + MAC_HEADER_LENGTH);
  2135. if (LocalRecvDesc == NULL) {
  2136. return;
  2137. }
  2138. HeaderBuffer =
  2139. LocalRecvDesc->StartBuffer;
  2140. HeaderLength = 0;
  2141. switch (RecvType) {
  2142. case RECV_LINK:
  2143. NdisMoveMemory(HeaderBuffer, Header1, sizeof(Header1));
  2144. HeaderBuffer[5] =
  2145. HeaderBuffer[11] = (UCHAR)LinkCB->hLinkHandle;
  2146. HeaderBuffer[12] = (UCHAR)(DataLength >> 8);
  2147. HeaderBuffer[13] = (UCHAR)DataLength;
  2148. HeaderLength = MAC_HEADER_LENGTH;
  2149. break;
  2150. case RECV_BUNDLE_PPP:
  2151. case RECV_BUNDLE_DATA:
  2152. break;
  2153. }
  2154. DataBuffer = HeaderBuffer + HeaderLength;
  2155. NdisMoveMemory(DataBuffer,
  2156. RecvDesc->CurrentBuffer,
  2157. DataLength);
  2158. LocalRecvDesc->CurrentBuffer = HeaderBuffer;
  2159. LocalRecvDesc->CurrentLength = HeaderLength + DataLength;
  2160. if (LocalRecvDesc->CurrentLength > 1514) {
  2161. LocalRecvDesc->CurrentLength = 1514;
  2162. }
  2163. //
  2164. // Get an ndis packet
  2165. //
  2166. NdisPacket =
  2167. LocalRecvDesc->NdisPacket;
  2168. PPROTOCOL_RESERVED_FROM_NDIS(NdisPacket)->RecvDesc = LocalRecvDesc;
  2169. //
  2170. // Attach the buffers
  2171. //
  2172. NdisAdjustBufferLength(LocalRecvDesc->NdisBuffer,
  2173. LocalRecvDesc->CurrentLength);
  2174. NdisRecalculatePacketCounts(NdisPacket);
  2175. ReleaseBundleLock(BundleCB);
  2176. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  2177. NDIS_SET_PACKET_STATUS(NdisPacket, NDIS_STATUS_RESOURCES);
  2178. INSERT_DBG_RECV(PacketTypeNdis,
  2179. Adapter,
  2180. NULL,
  2181. RecvDesc->LinkCB,
  2182. NdisPacket);
  2183. //
  2184. // Indicate the packet
  2185. // This assumes that bloodhound is always a legacy transport
  2186. //
  2187. NdisMIndicateReceivePacket(Adapter->MiniportHandle,
  2188. &NdisPacket,
  2189. 1);
  2190. KeLowerIrql(OldIrql);
  2191. AcquireBundleLock(BundleCB);
  2192. #if DBG
  2193. {
  2194. NDIS_STATUS Status;
  2195. Status = NDIS_GET_PACKET_STATUS(NdisPacket);
  2196. ASSERT(Status == NDIS_STATUS_RESOURCES);
  2197. REMOVE_DBG_RECV(PacketTypeNdis, Adapter, NdisPacket);
  2198. }
  2199. #endif
  2200. {
  2201. NdisWanFreeRecvDesc(LocalRecvDesc);
  2202. }
  2203. }
  2204. BOOLEAN
  2205. GetProtocolFromPPPId(
  2206. PBUNDLECB BundleCB,
  2207. USHORT Id,
  2208. PPROTOCOLCB *ProtocolCB
  2209. )
  2210. {
  2211. PPROTOCOLCB ppcb;
  2212. BOOLEAN Found;
  2213. *ProtocolCB = NULL;
  2214. ppcb = (PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
  2215. Found = FALSE;
  2216. while ((PVOID)ppcb != (PVOID)&BundleCB->ProtocolCBList) {
  2217. if (ppcb->State == PROTOCOL_ROUTED) {
  2218. if (ppcb->PPPProtocolID == Id) {
  2219. *ProtocolCB = ppcb;
  2220. Found = TRUE;
  2221. break;
  2222. }
  2223. }
  2224. ppcb = (PPROTOCOLCB)ppcb->Linkage.Flink;
  2225. }
  2226. return (Found);
  2227. }
  2228. #ifdef NT
  2229. NDIS_STATUS
  2230. CompleteIoRecvPacket(
  2231. PBUNDLECB BundleCB,
  2232. PRECV_DESC RecvDesc
  2233. )
  2234. {
  2235. KIRQL Irql;
  2236. USHORT ProtocolID;
  2237. UCHAR Header[] = {' ', 'R', 'E', 'C', 'V', 0xFF};
  2238. PNDISWAN_IO_PACKET IoPacket;
  2239. PIO_STACK_LOCATION IrpSp;
  2240. PIRP Irp;
  2241. LONG CopySize, BufferLength, DataLength;
  2242. PLIST_ENTRY Entry;
  2243. PUCHAR HeaderPointer;
  2244. PLINKCB LinkCB = RecvDesc->LinkCB;
  2245. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("CompleteIoRecvPacket: Enter"));
  2246. HeaderPointer =
  2247. RecvDesc->StartBuffer;
  2248. ProtocolID = RecvDesc->ProtocolID;
  2249. //
  2250. // Fill the frame out, and queue the data
  2251. //
  2252. NdisMoveMemory(HeaderPointer,
  2253. Header,
  2254. sizeof(Header));
  2255. NdisMoveMemory(&HeaderPointer[6],
  2256. Header,
  2257. sizeof(Header));
  2258. HeaderPointer[5] =
  2259. HeaderPointer[11] = (UCHAR)LinkCB->hLinkHandle;
  2260. HeaderPointer[12] = (UCHAR)(ProtocolID >> 8);
  2261. HeaderPointer[13] = (UCHAR)ProtocolID;
  2262. NdisMoveMemory(HeaderPointer + 14,
  2263. RecvDesc->CurrentBuffer,
  2264. RecvDesc->CurrentLength);
  2265. RecvDesc->CurrentBuffer = RecvDesc->StartBuffer;
  2266. RecvDesc->CurrentLength += 14;
  2267. #if DBG
  2268. if (gbDumpRecv) {
  2269. INT i;
  2270. DbgPrint("RecvData:");
  2271. for (i = 0; i < RecvDesc->CurrentLength; i++) {
  2272. if (i % 16 == 0) {
  2273. DbgPrint("\n");
  2274. }
  2275. DbgPrint("%2.2x ", RecvDesc->CurrentBuffer[i]);
  2276. }
  2277. DbgPrint("\n");
  2278. }
  2279. #endif
  2280. ReleaseBundleLock(BundleCB);
  2281. //
  2282. // See if someone has registered a recv context
  2283. // for this link or if there are any irps around
  2284. // to complete take this receive
  2285. //
  2286. NdisAcquireSpinLock(&IoRecvList.Lock);
  2287. NdisDprAcquireSpinLock(&LinkCB->Lock);
  2288. Entry = IoRecvList.IrpList.Flink;
  2289. Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
  2290. if ((LinkCB->hLinkContext == NULL) ||
  2291. (LinkCB->RecvDescCount > 0) ||
  2292. (IoRecvList.ulIrpCount == 0) ||
  2293. !IoSetCancelRoutine(Irp, NULL)) {
  2294. NDIS_STATUS Status;
  2295. //
  2296. // We will only buffer 5 packets for each link to avoid
  2297. // chewing up tons of non-paged memory if rasman is not
  2298. // reading at all.
  2299. //
  2300. if ((LinkCB->State == LINK_UP) &&
  2301. (LinkCB->RecvDescCount < 5)) {
  2302. InsertTailList(&IoRecvList.DescList,
  2303. &RecvDesc->Linkage);
  2304. LinkCB->RecvDescCount++;
  2305. IoRecvList.ulDescCount++;
  2306. if (IoRecvList.ulDescCount > IoRecvList.ulMaxDescCount) {
  2307. IoRecvList.ulMaxDescCount = IoRecvList.ulDescCount;
  2308. }
  2309. Status = NDIS_STATUS_PENDING;
  2310. } else {
  2311. Status = NDIS_STATUS_FAILURE;
  2312. }
  2313. NdisDprReleaseSpinLock(&LinkCB->Lock);
  2314. NdisReleaseSpinLock(&IoRecvList.Lock);
  2315. AcquireBundleLock(BundleCB);
  2316. return(Status);
  2317. }
  2318. RemoveHeadList(&IoRecvList.IrpList);
  2319. IoRecvList.ulIrpCount--;
  2320. INSERT_RECV_EVENT('a');
  2321. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  2322. BufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  2323. DataLength = BufferLength - sizeof(NDISWAN_IO_PACKET) + 1;
  2324. CopySize = (RecvDesc->CurrentLength > DataLength) ?
  2325. DataLength : RecvDesc->CurrentLength;
  2326. IoPacket = Irp->AssociatedIrp.SystemBuffer;
  2327. IoPacket->hHandle = LinkCB->hLinkContext;
  2328. IoPacket->usHandleType = LINKHANDLE;
  2329. IoPacket->usHeaderSize = 14;
  2330. IoPacket->usPacketSize = (USHORT)CopySize;
  2331. IoPacket->usPacketFlags = 0;
  2332. #if DBG
  2333. if (gbDumpRecv) {
  2334. INT i;
  2335. for (i = 0; i < RecvDesc->CurrentLength; i++) {
  2336. if (i % 16 == 0) {
  2337. DbgPrint("\n");
  2338. }
  2339. DbgPrint("%x ", RecvDesc->CurrentBuffer[i]);
  2340. }
  2341. DbgPrint("\n");
  2342. }
  2343. #endif
  2344. NdisMoveMemory(IoPacket->PacketData,
  2345. RecvDesc->CurrentBuffer,
  2346. CopySize);
  2347. Irp->IoStatus.Status = STATUS_SUCCESS;
  2348. Irp->IoStatus.Information = sizeof(NDISWAN_IO_PACKET) - 1 + CopySize;
  2349. IoRecvList.LastPacketNumber = IoPacket->PacketNumber;
  2350. IoRecvList.LastIrp = Irp;
  2351. IoRecvList.LastIrpStatus = STATUS_SUCCESS;
  2352. IoRecvList.LastCopySize = (ULONG)Irp->IoStatus.Information;
  2353. ASSERT((LONG_PTR)Irp->IoStatus.Information > 0);
  2354. NdisDprReleaseSpinLock(&LinkCB->Lock);
  2355. NdisReleaseSpinLock(&IoRecvList.Lock);
  2356. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  2357. AcquireBundleLock(BundleCB);
  2358. if (NdisWanCB.PromiscuousAdapter != NULL) {
  2359. IndicatePromiscuousRecv(BundleCB, RecvDesc, RECV_BUNDLE_PPP);
  2360. }
  2361. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("CompleteIoRecvPacket: Exit"));
  2362. return(NDIS_STATUS_SUCCESS);
  2363. }
  2364. #endif // end ifdef NT