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.

3097 lines
86 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;
  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. while (!IsListEmpty(&BundleRecvInfo->AssemblyList)) {
  1073. TempDesc = (PRECV_DESC)
  1074. RemoveHeadList(&BundleRecvInfo->AssemblyList);
  1075. if (TempDesc == RecvDescHole) {
  1076. break;
  1077. }
  1078. BundleRecvInfo->FragmentsLost++;
  1079. BundleRecvInfo->AssemblyCount--;
  1080. NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
  1081. ("flw %x %x h: %x", TempDesc->SequenceNumber,
  1082. TempDesc->Flags, RecvDescHole->SequenceNumber));
  1083. NdisWanFreeRecvDesc(TempDesc);
  1084. }
  1085. BundleCB->Stats.FramingErrors++;
  1086. //
  1087. // Now flush all recvdesc's until we find a begin fragment that has a
  1088. // sequence number >= M or the list is empty.
  1089. //
  1090. while (!IsListEmpty(&BundleRecvInfo->AssemblyList)) {
  1091. TempDesc = (PRECV_DESC)
  1092. BundleRecvInfo->AssemblyList.Flink;
  1093. if (TempDesc->Flags & MULTILINK_BEGIN_FRAME) {
  1094. break;
  1095. }
  1096. NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
  1097. ("flw %x %x h: %x", TempDesc->SequenceNumber,
  1098. TempDesc->Flags, RecvDescHole->SequenceNumber));
  1099. RecvDescHole->SequenceNumber = TempDesc->SequenceNumber;
  1100. RemoveHeadList(&BundleRecvInfo->AssemblyList);
  1101. BundleRecvInfo->AssemblyCount--;
  1102. BundleRecvInfo->FragmentsLost++;
  1103. NdisWanFreeRecvDesc(TempDesc);
  1104. TempDesc = NULL;
  1105. }
  1106. //
  1107. // Now reinsert the hole desc.
  1108. //
  1109. NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
  1110. ("h: %x", RecvDescHole->SequenceNumber));
  1111. FindHoleInRecvList(BundleCB, TempDesc, Class);
  1112. NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
  1113. ("nh: %x", RecvDescHole->SequenceNumber));
  1114. //
  1115. // See if we can complete some frames!!!!
  1116. //
  1117. TryToAssembleFrame(BundleCB, Class);
  1118. }
  1119. VOID
  1120. FlushAssemblyLists(
  1121. IN PBUNDLECB BundleCB
  1122. )
  1123. /*++
  1124. Routine Name:
  1125. Routine Description:
  1126. Arguments:
  1127. Return Values:
  1128. --*/
  1129. {
  1130. PRECV_DESC RecvDesc;
  1131. UINT Class;
  1132. for (Class = 0; Class < MAX_MCML; Class++) {
  1133. PBUNDLE_RECV_INFO RecvInfo = &BundleCB->RecvInfo[Class];
  1134. while (!IsListEmpty(&RecvInfo->AssemblyList)) {
  1135. RecvDesc = (PRECV_DESC)RemoveHeadList(&RecvInfo->AssemblyList);
  1136. RecvInfo->AssemblyCount--;
  1137. if (RecvDesc->Flags != MULTILINK_HOLE_FLAG) {
  1138. NdisWanFreeRecvDesc(RecvDesc);
  1139. }
  1140. }
  1141. }
  1142. }
  1143. VOID
  1144. TryToAssembleFrame(
  1145. PBUNDLECB BundleCB,
  1146. UINT Class
  1147. )
  1148. /*++
  1149. Routine Name:
  1150. TryToAssembleFrame
  1151. Routine Description:
  1152. The goal here is to walk the recv list looking for a full frame
  1153. (BeginFlag, EndFlag, no holes in between). If we do not have a
  1154. full frame we return FALSE.
  1155. If we have a full frame we remove each desc from the assembly list
  1156. copying the data into the first desc and returning all of the desc's
  1157. except the first one to the free pool. Once all of the data had been
  1158. collected we process the frame. After the frame has been processed
  1159. we return the first desc to the free pool.
  1160. Arguments:
  1161. Return Values:
  1162. --*/
  1163. {
  1164. PRECV_DESC RecvDesc, RecvDescHole;
  1165. PUCHAR DataPointer;
  1166. LINKCB LinkCB;
  1167. PBUNDLE_RECV_INFO BundleRecvInfo;
  1168. BundleRecvInfo = &BundleCB->RecvInfo[Class];
  1169. RecvDesc = (PRECV_DESC)BundleRecvInfo->AssemblyList.Flink;
  1170. RecvDescHole = BundleRecvInfo->RecvDescHole;
  1171. TryToAssembleAgain:
  1172. while ((RecvDesc != RecvDescHole) &&
  1173. (RecvDesc->Flags & MULTILINK_BEGIN_FRAME)) {
  1174. PRECV_DESC NextRecvDesc = (PRECV_DESC)RecvDesc->Linkage.Flink;
  1175. DataPointer = RecvDesc->CurrentBuffer + RecvDesc->CurrentLength;
  1176. while ((NextRecvDesc != RecvDescHole) &&
  1177. !(RecvDesc->Flags & MULTILINK_END_FRAME)) {
  1178. RemoveEntryList(&NextRecvDesc->Linkage);
  1179. BundleRecvInfo->AssemblyCount--;
  1180. ASSERT(NextRecvDesc != RecvDescHole);
  1181. ASSERT(RecvDesc != RecvDescHole);
  1182. NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV, ("c 0x%x -> 0x%x",
  1183. NextRecvDesc->SequenceNumber, RecvDesc->SequenceNumber));
  1184. NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV, ("fl 0x%x -> 0x%x",
  1185. NextRecvDesc->Flags, RecvDesc->Flags));
  1186. NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV, ("l %d -> %d",
  1187. NextRecvDesc->CurrentLength, RecvDesc->CurrentLength));
  1188. //
  1189. // Update recvdesc info
  1190. //
  1191. RecvDesc->Flags |= NextRecvDesc->Flags;
  1192. RecvDesc->SequenceNumber = NextRecvDesc->SequenceNumber;
  1193. RecvDesc->CurrentLength += NextRecvDesc->CurrentLength;
  1194. //
  1195. // Make sure we don't assemble something too big!
  1196. //
  1197. if (RecvDesc->CurrentLength > (LONG)glMRRU) {
  1198. NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
  1199. ("Max receive size exceeded!"));
  1200. //
  1201. // Return the recv desc's
  1202. //
  1203. RemoveEntryList(&RecvDesc->Linkage);
  1204. BundleRecvInfo->AssemblyCount--;
  1205. BundleCB->Stats.FramingErrors++;
  1206. NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
  1207. ("dumping %x %x h: %x", RecvDesc->SequenceNumber,
  1208. RecvDesc->Flags, RecvDescHole->SequenceNumber));
  1209. NdisWanFreeRecvDesc(RecvDesc);
  1210. NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
  1211. ("dumping %x %x h: %x", NextRecvDesc->SequenceNumber,
  1212. NextRecvDesc->Flags, RecvDescHole->SequenceNumber));
  1213. NdisWanFreeRecvDesc(NextRecvDesc);
  1214. //
  1215. // Start at the list head and flush until we find either the hole
  1216. // or a new begin fragment.
  1217. //
  1218. RecvDesc = (PRECV_DESC)BundleRecvInfo->AssemblyList.Flink;
  1219. while (RecvDesc != RecvDescHole &&
  1220. !(RecvDesc->Flags & MULTILINK_BEGIN_FRAME)) {
  1221. RemoveHeadList(&BundleRecvInfo->AssemblyList);
  1222. BundleRecvInfo->AssemblyCount--;
  1223. NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
  1224. ("dumping %x %x h: %x", RecvDesc->SequenceNumber,
  1225. RecvDesc->Flags, RecvDescHole->SequenceNumber));
  1226. NdisWanFreeRecvDesc(RecvDesc);
  1227. }
  1228. goto TryToAssembleAgain;
  1229. }
  1230. NdisMoveMemory(DataPointer,
  1231. NextRecvDesc->CurrentBuffer,
  1232. NextRecvDesc->CurrentLength);
  1233. DataPointer += NextRecvDesc->CurrentLength;
  1234. NdisWanFreeRecvDesc(NextRecvDesc);
  1235. NextRecvDesc = (PRECV_DESC)RecvDesc->Linkage.Flink;
  1236. }
  1237. //
  1238. // We hit a hole before completion of the frame.
  1239. // Get out.
  1240. //
  1241. if (!IsCompleteFrame(RecvDesc->Flags)) {
  1242. return;
  1243. }
  1244. //
  1245. // If we made it here we must have a begin flag, end flag, and
  1246. // no hole in between. Let's build a frame.
  1247. //
  1248. RecvDesc = (PRECV_DESC)
  1249. RemoveHeadList(&BundleRecvInfo->AssemblyList);
  1250. BundleRecvInfo->AssemblyCount--;
  1251. NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV, ("a %x %x", RecvDesc->SequenceNumber, RecvDesc->Flags));
  1252. RecvDesc->LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
  1253. if (NDIS_STATUS_PENDING != ProcessPPPFrame(BundleCB, RecvDesc)) {
  1254. NdisWanFreeRecvDesc(RecvDesc);
  1255. }
  1256. RecvDesc = (PRECV_DESC)BundleRecvInfo->AssemblyList.Flink;
  1257. } // end of while MULTILINK_BEGIN_FRAME
  1258. }
  1259. BOOLEAN
  1260. DoVJDecompression(
  1261. PBUNDLECB BundleCB,
  1262. PRECV_DESC RecvDesc
  1263. )
  1264. {
  1265. ULONG BundleFraming;
  1266. PUCHAR FramePointer = RecvDesc->CurrentBuffer;
  1267. LONG FrameLength = RecvDesc->CurrentLength;
  1268. UCHAR VJCompType = 0;
  1269. BOOLEAN DoDecomp = FALSE;
  1270. BOOLEAN VJDetect = FALSE;
  1271. BundleFraming = BundleCB->FramingInfo.RecvFramingBits;
  1272. if (BundleFraming & SLIP_FRAMING) {
  1273. VJCompType = *FramePointer & 0xF0;
  1274. //
  1275. // If the packet is compressed the header has to be atleast 3 bytes long.
  1276. // If this is a regular IP packet we do not decompress it.
  1277. //
  1278. if ((FrameLength > 2) && (VJCompType != TYPE_IP)) {
  1279. if (VJCompType & 0x80) {
  1280. VJCompType = TYPE_COMPRESSED_TCP;
  1281. } else if (VJCompType == TYPE_UNCOMPRESSED_TCP) {
  1282. *FramePointer &= 0x4F;
  1283. }
  1284. //
  1285. // If framing is set for detection, in order for this to be a good
  1286. // frame for detection we need a type of UNCOMPRESSED_TCP and a
  1287. // frame that is atleast 40 bytes long.
  1288. //
  1289. VJDetect = ((BundleFraming & SLIP_VJ_AUTODETECT) &&
  1290. (VJCompType == TYPE_UNCOMPRESSED_TCP) &&
  1291. (FrameLength > 39));
  1292. if ((BundleFraming & SLIP_VJ_COMPRESSION) || VJDetect) {
  1293. //
  1294. // If VJ compression is set or if we are in
  1295. // autodetect and this looks like a reasonable
  1296. // frame
  1297. //
  1298. DoDecomp = TRUE;
  1299. }
  1300. }
  1301. // end of SLIP_FRAMING
  1302. } else {
  1303. //
  1304. // Must be PPP framing
  1305. //
  1306. if (RecvDesc->ProtocolID == PPP_PROTOCOL_COMPRESSED_TCP) {
  1307. VJCompType = TYPE_COMPRESSED_TCP;
  1308. } else {
  1309. VJCompType = TYPE_UNCOMPRESSED_TCP;
  1310. }
  1311. DoDecomp = TRUE;
  1312. }
  1313. if (DoDecomp) {
  1314. PUCHAR HeaderBuffer;
  1315. LONG PostCompSize, PreCompSize;
  1316. PreCompSize = RecvDesc->CurrentLength;
  1317. HeaderBuffer =
  1318. RecvDesc->StartBuffer + MAC_HEADER_LENGTH;
  1319. if ((PostCompSize = sl_uncompress_tcp(&RecvDesc->CurrentBuffer,
  1320. &RecvDesc->CurrentLength,
  1321. HeaderBuffer,
  1322. &RecvDesc->HeaderLength,
  1323. VJCompType,
  1324. BundleCB->VJCompress)) == 0) {
  1325. NdisWanDbgOut(DBG_FAILURE, DBG_RECEIVE, ("Error in sl_uncompress_tcp!"));
  1326. return(FALSE);
  1327. }
  1328. if (VJDetect) {
  1329. BundleCB->FramingInfo.RecvFramingBits |= SLIP_VJ_COMPRESSION;
  1330. BundleCB->FramingInfo.SendFramingBits |= SLIP_VJ_COMPRESSION;
  1331. }
  1332. ASSERT(PostCompSize == RecvDesc->HeaderLength + RecvDesc->CurrentLength);
  1333. #if DBG
  1334. if (VJCompType == TYPE_COMPRESSED_TCP) {
  1335. ASSERT(RecvDesc->HeaderLength > 0);
  1336. NdisWanDbgOut(DBG_TRACE, DBG_RECV_VJ,("rvj b %d a %d",(RecvDesc->HeaderLength - (PostCompSize-PreCompSize)), RecvDesc->HeaderLength));
  1337. }
  1338. #endif
  1339. //
  1340. // Calculate how much expansion we had
  1341. //
  1342. BundleCB->Stats.BytesReceivedCompressed +=
  1343. (RecvDesc->HeaderLength - (PostCompSize - PreCompSize));
  1344. BundleCB->Stats.BytesReceivedUncompressed += RecvDesc->HeaderLength;
  1345. }
  1346. RecvDesc->ProtocolID = PPP_PROTOCOL_IP;
  1347. return(TRUE);
  1348. }
  1349. #define SEQ_TYPE_IN_ORDER 1
  1350. #define SEQ_TYPE_AFTER_EXPECTED 2
  1351. #define SEQ_TYPE_BEFORE_EXPECTED 3
  1352. BOOLEAN
  1353. DoDecompDecryptProcessing(
  1354. PBUNDLECB BundleCB,
  1355. PUCHAR *DataPointer,
  1356. PLONG DataLength
  1357. )
  1358. {
  1359. USHORT Coherency, CurrCoherency;
  1360. ULONG Flags;
  1361. PWAN_STATS BundleStats;
  1362. PUCHAR FramePointer = *DataPointer;
  1363. LONG FrameLength = *DataLength;
  1364. ULONG PacketSeqType;
  1365. LONG OutOfOrderDepth;
  1366. LONG NumberMissed;
  1367. Flags = BundleCB->RecvFlags;
  1368. BundleStats = &BundleCB->Stats;
  1369. if (Flags & (DO_COMPRESSION | DO_ENCRYPTION)) {
  1370. PUCHAR SessionKey = BundleCB->RecvCryptoInfo.SessionKey;
  1371. ULONG SessionKeyLength = BundleCB->RecvCryptoInfo.SessionKeyLength;
  1372. PVOID RecvRC4Key = BundleCB->RecvCryptoInfo.RC4Key;
  1373. PVOID RecvCompressContext = BundleCB->RecvCompressContext;
  1374. BOOLEAN SyncCoherency = FALSE;
  1375. //
  1376. // Get the coherency counter
  1377. //
  1378. Coherency = (*FramePointer << 8) | *(FramePointer + 1);
  1379. FramePointer += 2;
  1380. FrameLength -= 2;
  1381. if (FrameLength <= 0) {
  1382. goto RESYNC;
  1383. }
  1384. if (!(Flags & DO_HISTORY_LESS))
  1385. {
  1386. // history-based
  1387. if (SEQ_LT(Coherency & 0x0FFF,
  1388. BundleCB->RCoherencyCounter & 0x0FFF,
  1389. 0x0800)) {
  1390. //
  1391. // We received a sequence number that is less then the
  1392. // expected sequence number so we must be way out of sync
  1393. //
  1394. NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_RECEIVE,
  1395. ("Recv old frame!!!! b %p rc %x < ec %x!!!!", BundleCB, Coherency & 0x0FFF,
  1396. BundleCB->RCoherencyCounter & 0x0FFF));
  1397. goto RESYNC;
  1398. }
  1399. }
  1400. else
  1401. {
  1402. // history-less
  1403. if((Coherency & 0x0FFF) == (BundleCB->RCoherencyCounter & 0x0FFF))
  1404. {
  1405. PacketSeqType = SEQ_TYPE_IN_ORDER;
  1406. }
  1407. else
  1408. {
  1409. if (SEQ_GT(Coherency & 0x0FFF,
  1410. BundleCB->RCoherencyCounter & 0x0FFF,
  1411. 0x0800))
  1412. {
  1413. PacketSeqType = SEQ_TYPE_BEFORE_EXPECTED;
  1414. NumberMissed = ((Coherency & 0x0FFF) - (BundleCB->RCoherencyCounter & 0x0FFF)) & 0x0FFF;
  1415. ASSERT(NumberMissed > 0);
  1416. }
  1417. else
  1418. {
  1419. OutOfOrderDepth = ((BundleCB->RCoherencyCounter & 0x0FFF) - (Coherency & 0x0FFF)) & 0x0FFF;
  1420. if(OutOfOrderDepth <= (LONG)glMaxOutOfOrderDepth)
  1421. {
  1422. PacketSeqType = SEQ_TYPE_AFTER_EXPECTED;
  1423. }
  1424. else
  1425. {
  1426. //
  1427. // We received a sequence number that is either too earlier or too later
  1428. //
  1429. NdisWanDbgOut(DBG_FAILURE, DBG_RECEIVE,
  1430. ("Recv frame way out of order! b %p rc %x < ec %x!!!!", BundleCB, Coherency & 0x0FFF,
  1431. BundleCB->RCoherencyCounter & 0x0FFF));
  1432. return (FALSE);
  1433. }
  1434. }
  1435. }
  1436. }
  1437. //
  1438. // See if this is a flush packet
  1439. //
  1440. if (Coherency & (PACKET_FLUSHED << 8)) {
  1441. NdisWanDbgOut(DBG_INFO, DBG_RECEIVE,
  1442. ("Recv Packet Flushed 0x%x", (Coherency & 0x0FFF)));
  1443. SyncCoherency = TRUE;
  1444. if ((Flags & DO_ENCRYPTION) &&
  1445. !(Flags & DO_HISTORY_LESS)) {
  1446. //
  1447. // Re-Init the rc4 receive table
  1448. //
  1449. rc4_key(RecvRC4Key,
  1450. SessionKeyLength,
  1451. SessionKey);
  1452. }
  1453. if (Flags & DO_COMPRESSION) {
  1454. //
  1455. // Initialize the decompression history table
  1456. //
  1457. initrecvcontext(RecvCompressContext);
  1458. }
  1459. } // end of packet flushed
  1460. //
  1461. // If we are in history-less mode and we get out of sync
  1462. // we need to recreate all of the interim encryption
  1463. // keys that we missed, cache the keys
  1464. // When a packet comes in later, look for the cached key
  1465. //
  1466. if ((Flags & DO_HISTORY_LESS) &&
  1467. PacketSeqType != SEQ_TYPE_IN_ORDER) {
  1468. ULONG count;
  1469. LONG index;
  1470. PCACHED_KEY pKey;
  1471. if(PacketSeqType == SEQ_TYPE_AFTER_EXPECTED)
  1472. {
  1473. if (Coherency & (PACKET_ENCRYPTED << 8))
  1474. {
  1475. // This packet is encrypted
  1476. if (!(Flags & DO_ENCRYPTION)) {
  1477. //
  1478. // We are not configured to decrypt
  1479. //
  1480. return (FALSE);
  1481. }
  1482. // Find the cached key for this packet
  1483. pKey = BundleCB->RecvCryptoInfo.pCurrKey;
  1484. for(count = 0; count < glCachedKeyCount; count++)
  1485. {
  1486. // Walk through the keys
  1487. if(pKey > (PCACHED_KEY)BundleCB->RecvCryptoInfo.CachedKeyBuffer)
  1488. {
  1489. pKey = (PCACHED_KEY)((PUCHAR)pKey - (sizeof(USHORT)+ SessionKeyLength));
  1490. }
  1491. else
  1492. {
  1493. pKey = (PCACHED_KEY)BundleCB->RecvCryptoInfo.pLastKey;
  1494. }
  1495. if(pKey->Coherency == (Coherency & 0x0FFF))
  1496. {
  1497. //
  1498. // Re-Init the rc4 receive table
  1499. //
  1500. rc4_key(RecvRC4Key,
  1501. SessionKeyLength,
  1502. pKey->SessionKey);
  1503. pKey->Coherency = 0xffff; // avoid duplication
  1504. //
  1505. // Decrypt the data!
  1506. //
  1507. rc4(RecvRC4Key,
  1508. FrameLength,
  1509. FramePointer);
  1510. goto DECOMPRESS_DATA;
  1511. }
  1512. }
  1513. // Can't recover this packet, drop it
  1514. return (FALSE);
  1515. }
  1516. goto DECOMPRESS_DATA;
  1517. }
  1518. // This packet comes earlier than expected
  1519. SyncCoherency = TRUE;
  1520. if (Flags & DO_ENCRYPTION) {
  1521. #ifdef DBG_ECP
  1522. DbgPrint("NDISWAN: Missed %d frames, regening keys...\n", NumberMissed);
  1523. DbgPrint("NDISWAN: resync b %p rc %x ec %x\n", BundleCB, Coherency & 0x0FFF,
  1524. BundleCB->RCoherencyCounter & 0x0FFF);
  1525. #endif
  1526. CurrCoherency = BundleCB->RCoherencyCounter & 0x0FFF;
  1527. while (NumberMissed--) {
  1528. if (Flags & DO_LEGACY_ENCRYPTION) {
  1529. //
  1530. // Change the session key
  1531. //
  1532. SessionKey[3] += 1;
  1533. SessionKey[4] += 3;
  1534. SessionKey[5] += 13;
  1535. SessionKey[6] += 57;
  1536. SessionKey[7] += 19;
  1537. } else {
  1538. //
  1539. // Change the session key
  1540. //
  1541. GetNewKeyFromSHA(&BundleCB->RecvCryptoInfo);
  1542. }
  1543. //
  1544. // We use rc4 to scramble and recover a new key
  1545. //
  1546. //
  1547. // Re-initialize the rc4 receive table to the
  1548. // intermediate value
  1549. //
  1550. rc4_key(RecvRC4Key, SessionKeyLength, SessionKey);
  1551. //
  1552. // Scramble the existing session key
  1553. //
  1554. rc4(RecvRC4Key, SessionKeyLength, SessionKey);
  1555. if (Flags & DO_40_ENCRYPTION) {
  1556. //
  1557. // If this is 40 bit encryption we need to fix
  1558. // the first 3 bytes of the key.
  1559. //
  1560. SessionKey[0] = 0xD1;
  1561. SessionKey[1] = 0x26;
  1562. SessionKey[2] = 0x9E;
  1563. } else if (Flags & DO_56_ENCRYPTION) {
  1564. //
  1565. // If this is 56 bit encryption we need to fix
  1566. // the first byte of the key.
  1567. //
  1568. SessionKey[0] = 0xD1;
  1569. }
  1570. if(NumberMissed < (LONG)glCachedKeyCount)
  1571. {
  1572. BundleCB->RecvCryptoInfo.pCurrKey->Coherency = CurrCoherency;
  1573. NdisMoveMemory(BundleCB->RecvCryptoInfo.pCurrKey->SessionKey,
  1574. SessionKey,
  1575. SessionKeyLength);
  1576. if(BundleCB->RecvCryptoInfo.pCurrKey < BundleCB->RecvCryptoInfo.pLastKey)
  1577. {
  1578. BundleCB->RecvCryptoInfo.pCurrKey = (PCACHED_KEY)((PUCHAR)BundleCB->RecvCryptoInfo.pCurrKey +
  1579. sizeof(USHORT) + SessionKeyLength);
  1580. ASSERT(BundleCB->RecvCryptoInfo.pCurrKey <= BundleCB->RecvCryptoInfo.pLastKey);
  1581. }
  1582. else
  1583. {
  1584. BundleCB->RecvCryptoInfo.pCurrKey = (PCACHED_KEY)BundleCB->RecvCryptoInfo.CachedKeyBuffer;
  1585. }
  1586. }
  1587. NdisWanDbgOut(DBG_TRACE, DBG_CCP,
  1588. ("RC4 Recv encryption KeyLength %d", BundleCB->RecvCryptoInfo.SessionKeyLength));
  1589. NdisWanDbgOut(DBG_TRACE, DBG_CCP,
  1590. ("RC4 Recv encryption Key %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x",
  1591. BundleCB->RecvCryptoInfo.SessionKey[0],
  1592. BundleCB->RecvCryptoInfo.SessionKey[1],
  1593. BundleCB->RecvCryptoInfo.SessionKey[2],
  1594. BundleCB->RecvCryptoInfo.SessionKey[3],
  1595. BundleCB->RecvCryptoInfo.SessionKey[4],
  1596. BundleCB->RecvCryptoInfo.SessionKey[5],
  1597. BundleCB->RecvCryptoInfo.SessionKey[6],
  1598. BundleCB->RecvCryptoInfo.SessionKey[7],
  1599. BundleCB->RecvCryptoInfo.SessionKey[8],
  1600. BundleCB->RecvCryptoInfo.SessionKey[9],
  1601. BundleCB->RecvCryptoInfo.SessionKey[10],
  1602. BundleCB->RecvCryptoInfo.SessionKey[11],
  1603. BundleCB->RecvCryptoInfo.SessionKey[12],
  1604. BundleCB->RecvCryptoInfo.SessionKey[13],
  1605. BundleCB->RecvCryptoInfo.SessionKey[14],
  1606. BundleCB->RecvCryptoInfo.SessionKey[15]));
  1607. // Re-initialize the rc4 receive table to the
  1608. // scrambled session key
  1609. //
  1610. rc4_key(RecvRC4Key, SessionKeyLength, SessionKey);
  1611. if(CurrCoherency < (USHORT)0x0FFF)
  1612. {
  1613. ++CurrCoherency;
  1614. }
  1615. else
  1616. {
  1617. CurrCoherency = 0;
  1618. }
  1619. }
  1620. }
  1621. }
  1622. if (SyncCoherency) {
  1623. if ((BundleCB->RCoherencyCounter & 0x0FFF) >
  1624. (Coherency & 0x0FFF)) {
  1625. BundleCB->RCoherencyCounter += 0x1000;
  1626. }
  1627. BundleCB->RCoherencyCounter &= 0xF000;
  1628. BundleCB->RCoherencyCounter |= (Coherency & 0x0FFF);
  1629. }
  1630. if ((Coherency & 0x0FFF) == (BundleCB->RCoherencyCounter & 0x0FFF)) {
  1631. //
  1632. // We are still in sync
  1633. //
  1634. BundleCB->RCoherencyCounter++;
  1635. if (Coherency & (PACKET_ENCRYPTED << 8)) {
  1636. //
  1637. // This packet is encrypted
  1638. //
  1639. if (!(Flags & DO_ENCRYPTION)) {
  1640. //
  1641. // We are not configured to decrypt
  1642. //
  1643. return (FALSE);
  1644. }
  1645. //
  1646. // Check for history less
  1647. //
  1648. if ((Flags & DO_HISTORY_LESS) ||
  1649. (BundleCB->RCoherencyCounter - BundleCB->LastRC4Reset)
  1650. >= 0x100) {
  1651. //
  1652. // It is time to change encryption keys
  1653. //
  1654. //
  1655. // Always align last reset on 0x100 boundary so as not to
  1656. // propagate error!
  1657. //
  1658. BundleCB->LastRC4Reset =
  1659. BundleCB->RCoherencyCounter & 0xFF00;
  1660. //
  1661. // Prevent ushort rollover
  1662. //
  1663. if ((BundleCB->LastRC4Reset & 0xF000) == 0xF000) {
  1664. BundleCB->LastRC4Reset &= 0x0FFF;
  1665. BundleCB->RCoherencyCounter &= 0x0FFF;
  1666. }
  1667. if (Flags & DO_LEGACY_ENCRYPTION) {
  1668. //
  1669. // Change the session key
  1670. //
  1671. SessionKey[3] += 1;
  1672. SessionKey[4] += 3;
  1673. SessionKey[5] += 13;
  1674. SessionKey[6] += 57;
  1675. SessionKey[7] += 19;
  1676. } else {
  1677. //
  1678. // Change the session key
  1679. //
  1680. GetNewKeyFromSHA(&BundleCB->RecvCryptoInfo);
  1681. }
  1682. //
  1683. // We use rc4 to scramble and recover a new key
  1684. //
  1685. //
  1686. // Re-initialize the rc4 receive table to the
  1687. // intermediate value
  1688. //
  1689. rc4_key(RecvRC4Key, SessionKeyLength, SessionKey);
  1690. //
  1691. // Scramble the existing session key
  1692. //
  1693. rc4(RecvRC4Key, SessionKeyLength, SessionKey);
  1694. //
  1695. // If this is 40 bit encryption we need to fix
  1696. // the first 3 bytes of the key.
  1697. //
  1698. if (Flags & DO_40_ENCRYPTION) {
  1699. //
  1700. // If this is 40 bit encryption we need to fix
  1701. // the first 3 bytes of the key.
  1702. //
  1703. SessionKey[0] = 0xD1;
  1704. SessionKey[1] = 0x26;
  1705. SessionKey[2] = 0x9E;
  1706. } else if (Flags & DO_56_ENCRYPTION) {
  1707. //
  1708. // If this is 56 bit encryption we need to fix
  1709. // the first byte of the key.
  1710. //
  1711. SessionKey[0] = 0xD1;
  1712. }
  1713. NdisWanDbgOut(DBG_TRACE, DBG_CCP,
  1714. ("RC4 Recv encryption KeyLength %d", BundleCB->RecvCryptoInfo.SessionKeyLength));
  1715. NdisWanDbgOut(DBG_TRACE, DBG_CCP,
  1716. ("RC4 Recv encryption Key %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x",
  1717. BundleCB->RecvCryptoInfo.SessionKey[0],
  1718. BundleCB->RecvCryptoInfo.SessionKey[1],
  1719. BundleCB->RecvCryptoInfo.SessionKey[2],
  1720. BundleCB->RecvCryptoInfo.SessionKey[3],
  1721. BundleCB->RecvCryptoInfo.SessionKey[4],
  1722. BundleCB->RecvCryptoInfo.SessionKey[5],
  1723. BundleCB->RecvCryptoInfo.SessionKey[6],
  1724. BundleCB->RecvCryptoInfo.SessionKey[7],
  1725. BundleCB->RecvCryptoInfo.SessionKey[8],
  1726. BundleCB->RecvCryptoInfo.SessionKey[9],
  1727. BundleCB->RecvCryptoInfo.SessionKey[10],
  1728. BundleCB->RecvCryptoInfo.SessionKey[11],
  1729. BundleCB->RecvCryptoInfo.SessionKey[12],
  1730. BundleCB->RecvCryptoInfo.SessionKey[13],
  1731. BundleCB->RecvCryptoInfo.SessionKey[14],
  1732. BundleCB->RecvCryptoInfo.SessionKey[15]));
  1733. // Re-initialize the rc4 receive table to the
  1734. // scrambled session key
  1735. //
  1736. rc4_key(RecvRC4Key, SessionKeyLength, SessionKey);
  1737. } // end of reset encryption key
  1738. //
  1739. // Decrypt the data!
  1740. //
  1741. rc4(RecvRC4Key,
  1742. FrameLength,
  1743. FramePointer);
  1744. } // end of encryption
  1745. DECOMPRESS_DATA:
  1746. if (Coherency & (PACKET_COMPRESSED << 8)) {
  1747. //
  1748. // This packet is compressed!
  1749. //
  1750. if (!(Flags & DO_COMPRESSION)) {
  1751. //
  1752. // We are not configured to decompress
  1753. //
  1754. return (FALSE);
  1755. }
  1756. //
  1757. // Add up bundle stats
  1758. //
  1759. BundleStats->BytesReceivedCompressed += FrameLength;
  1760. if (decompress(FramePointer,
  1761. FrameLength,
  1762. ((Coherency & (PACKET_AT_FRONT << 8)) >> 8),
  1763. &FramePointer,
  1764. &FrameLength,
  1765. RecvCompressContext) == FALSE) {
  1766. #if DBG
  1767. DbgPrint("dce1 %x\n", Coherency);
  1768. #endif
  1769. //
  1770. // Error decompressing!
  1771. //
  1772. if (!(Flags & DO_HISTORY_LESS)) {
  1773. BundleCB->RCoherencyCounter--;
  1774. }
  1775. goto RESYNC;
  1776. }
  1777. if (FrameLength <= 0 ||
  1778. FrameLength > (LONG)glMRRU) {
  1779. #if DBG
  1780. DbgPrint("dce2 %d %x\n", FrameLength, Coherency);
  1781. #endif
  1782. //
  1783. // Error decompressing!
  1784. //
  1785. if (!(Flags & DO_HISTORY_LESS)) {
  1786. BundleCB->RCoherencyCounter--;
  1787. }
  1788. goto RESYNC;
  1789. }
  1790. BundleStats->BytesReceivedUncompressed += FrameLength;
  1791. } // end of compression
  1792. } else { // end of insync
  1793. RESYNC:
  1794. NdisWanDbgOut(DBG_FAILURE, DBG_RECEIVE, ("oos r %x, e %x\n", (Coherency & 0x0FFF),
  1795. (BundleCB->RCoherencyCounter & 0x0FFF)));
  1796. if (!(Flags & DO_HISTORY_LESS)) {
  1797. //
  1798. // We are out of sync!
  1799. //
  1800. do {
  1801. PLINKCB LinkCB;
  1802. PNDISWAN_IO_PACKET IoPacket;
  1803. if (BundleCB->ulLinkCBCount == 0) {
  1804. break;
  1805. }
  1806. NdisWanAllocateMemory(&IoPacket,
  1807. sizeof(NDISWAN_IO_PACKET) + 100,
  1808. IOPACKET_TAG);
  1809. if (IoPacket == NULL) {
  1810. break;
  1811. }
  1812. LinkCB =
  1813. (PLINKCB)BundleCB->LinkCBList.Flink;
  1814. NdisDprAcquireSpinLock(&LinkCB->Lock);
  1815. if (LinkCB->State != LINK_UP) {
  1816. NdisDprReleaseSpinLock(&LinkCB->Lock);
  1817. NdisWanFreeMemory(IoPacket);
  1818. break;
  1819. }
  1820. REF_LINKCB(LinkCB);
  1821. NdisDprReleaseSpinLock(&LinkCB->Lock);
  1822. IoPacket->hHandle = BundleCB->hBundleHandle;
  1823. IoPacket->usHandleType = BUNDLEHANDLE;
  1824. IoPacket->usHeaderSize = 0;
  1825. IoPacket->usPacketSize = 6;
  1826. IoPacket->usPacketFlags = 0;
  1827. IoPacket->PacketData[0] = 0x80;
  1828. IoPacket->PacketData[1] = 0xFD;
  1829. IoPacket->PacketData[2] = 14;
  1830. IoPacket->PacketData[3] = (UCHAR)BundleCB->CCPIdentifier++;
  1831. IoPacket->PacketData[4] = 0x00;
  1832. IoPacket->PacketData[5] = 0x04;
  1833. LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
  1834. BuildIoPacket(LinkCB, BundleCB, IoPacket, FALSE);
  1835. NdisWanFreeMemory(IoPacket);
  1836. } while (FALSE);
  1837. }
  1838. return (FALSE);
  1839. } // end of out of sync
  1840. } else { // end of DoCompEncrypt
  1841. //
  1842. // For some reason we were not able to
  1843. // decrypt/decompress!
  1844. //
  1845. return (FALSE);
  1846. }
  1847. *DataPointer = FramePointer;
  1848. *DataLength = FrameLength;
  1849. return (TRUE);
  1850. }
  1851. VOID
  1852. DoCompressionReset(
  1853. PBUNDLECB BundleCB
  1854. )
  1855. {
  1856. if (BundleCB->RecvCompInfo.MSCompType != 0) {
  1857. //
  1858. // The next outgoing packet will flush
  1859. //
  1860. BundleCB->Flags |= RECV_PACKET_FLUSH;
  1861. }
  1862. }
  1863. VOID
  1864. NdisWanReceiveComplete(
  1865. IN NDIS_HANDLE NdisLinkContext
  1866. )
  1867. /*++
  1868. Routine Name:
  1869. Routine Description:
  1870. Arguments:
  1871. Return Values:
  1872. --*/
  1873. {
  1874. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("NdisWanReceiveComplete: Enter"));
  1875. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("NdisWanReceiveComplete: Exit"));
  1876. }
  1877. BOOLEAN
  1878. IpIsDataFrame(
  1879. PUCHAR HeaderBuffer,
  1880. ULONG HeaderBufferLength,
  1881. ULONG TotalLength
  1882. )
  1883. {
  1884. UINT tcpheaderlength ;
  1885. UINT ipheaderlength ;
  1886. UCHAR *tcppacket;
  1887. UCHAR *ippacket = HeaderBuffer;
  1888. UCHAR SrcPort, DstPort;
  1889. IPV4Header UNALIGNED *ipheader = (IPV4Header UNALIGNED *) HeaderBuffer;
  1890. #define TYPE_IGMP 2
  1891. if (ipheader->ip_p == TYPE_IGMP) {
  1892. if (gbIGMPIdle) {
  1893. return FALSE;
  1894. }
  1895. return TRUE;
  1896. }
  1897. SrcPort = (UCHAR) *(ippacket + ((*ippacket & 0x0f)*4) + 1);
  1898. DstPort = (UCHAR) *(ippacket + ((*ippacket & 0x0f)*4) + 3);
  1899. if (DstPort == 53) {
  1900. //
  1901. // UDP/TCP port 53 - DNS
  1902. //
  1903. return FALSE;
  1904. }
  1905. #define TYPE_UDP 17
  1906. #define UDPPACKET_SRC_PORT_137(x) ((UCHAR) *(x + ((*x & 0x0f)*4) + 1) == 137)
  1907. #define UDPPACKET_SRC_PORT_138(x) ((UCHAR) *(x + ((*x & 0x0f)*4) + 1) == 138)
  1908. if (ipheader->ip_p == TYPE_UDP) {
  1909. if ((SrcPort == 137) ||
  1910. (SrcPort == 138)) {
  1911. //
  1912. // UDP port 137 - NETBIOS Name Service
  1913. // UDP port 138 - NETBIOS Datagram Service
  1914. //
  1915. return FALSE ;
  1916. } else {
  1917. return TRUE ;
  1918. }
  1919. }
  1920. #define TYPE_TCP 6
  1921. #define TCPPACKET_SRC_OR_DEST_PORT_139(x,y) (((UCHAR) *(x + y + 1) == 139) || ((UCHAR) *(x + y + 3) == 139))
  1922. //
  1923. // TCP packets with SRC | DEST == 139 which are ACKs (0 data) or Session Alives
  1924. // are considered as idle
  1925. //
  1926. if (ipheader->ip_p == TYPE_TCP) {
  1927. ipheaderlength = ((UCHAR)*ippacket & 0x0f)*4 ;
  1928. tcppacket = ippacket + ipheaderlength ;
  1929. tcpheaderlength = (*(tcppacket + 10) >> 4)*4 ;
  1930. //
  1931. // If this is a PPTP keepalive packet then ignore
  1932. //
  1933. if (DstPort == 1723) {
  1934. UNALIGNED PPTP_HEADER *PptpHeader;
  1935. PptpHeader = (UNALIGNED PPTP_HEADER*)(tcppacket+tcpheaderlength);
  1936. if (PptpHeader->PacketType == 1 &&
  1937. (PptpHeader->MessageType == 5 ||
  1938. PptpHeader->MessageType == 6)) {
  1939. return FALSE;
  1940. }
  1941. return TRUE;
  1942. }
  1943. if (!((SrcPort == 139) || (DstPort == 139)))
  1944. return TRUE ;
  1945. //
  1946. // NetBT traffic
  1947. //
  1948. //
  1949. // if zero length tcp packet - this is an ACK on 139 - filter this.
  1950. //
  1951. if (TotalLength == (ipheaderlength + tcpheaderlength))
  1952. return FALSE ;
  1953. //
  1954. // Session alives are also filtered.
  1955. //
  1956. if ((UCHAR) *(tcppacket+tcpheaderlength) == 0x85)
  1957. return FALSE ;
  1958. //
  1959. // If this is a PPTP keep alive then ignore
  1960. //
  1961. }
  1962. //
  1963. // all other ip traffic is valid traffic
  1964. //
  1965. return TRUE ;
  1966. }
  1967. BOOLEAN
  1968. IpxIsDataFrame(
  1969. PUCHAR HeaderBuffer,
  1970. ULONG HeaderBufferLength,
  1971. ULONG TotalLength
  1972. )
  1973. {
  1974. /*++
  1975. Routine Description:
  1976. This routine is called when a frame is received on a WAN
  1977. line. It returns TRUE unless:
  1978. - The frame is from the RIP socket
  1979. - The frame is from the SAP socket
  1980. - The frame is a netbios keep alive
  1981. - The frame is an NCP keep alive
  1982. Arguments:
  1983. HeaderBuffer - points to a contiguous buffer starting at the IPX header.
  1984. HeaderBufferLength - Length of the header buffer (could be same as totallength)
  1985. TotalLength - the total length of the frame
  1986. Return Value:
  1987. TRUE - if this is a connection-based packet.
  1988. FALSE - otherwise.
  1989. --*/
  1990. IPX_HEADER UNALIGNED * IpxHeader = (IPX_HEADER UNALIGNED *)HeaderBuffer;
  1991. USHORT SourceSocket;
  1992. //
  1993. // First get the source socket.
  1994. //
  1995. SourceSocket = IpxHeader->SourceSocket;
  1996. //
  1997. // Not connection-based
  1998. //
  1999. if ((SourceSocket == RIP_SOCKET) ||
  2000. (SourceSocket == SAP_SOCKET)) {
  2001. return FALSE;
  2002. }
  2003. //
  2004. // See if there are at least two more bytes to look at.
  2005. //
  2006. if (TotalLength >= sizeof(IPX_HEADER) + 2) {
  2007. if (SourceSocket == NB_SOCKET) {
  2008. UCHAR ConnectionControlFlag;
  2009. UCHAR DataStreamType;
  2010. USHORT TotalDataLength;
  2011. //
  2012. // ConnectionControlFlag and DataStreamType will always follow
  2013. // IpxHeader
  2014. //
  2015. ConnectionControlFlag = ((PUCHAR)(IpxHeader+1))[0];
  2016. DataStreamType = ((PUCHAR)(IpxHeader+1))[1];
  2017. //
  2018. // If this is a SYS packet with or without a request for ACK and
  2019. // has session data in it.
  2020. //
  2021. if (((ConnectionControlFlag == 0x80) || (ConnectionControlFlag == 0xc0)) &&
  2022. (DataStreamType == 0x06)) {
  2023. //
  2024. // TotalDataLength is in the same buffer.
  2025. //
  2026. TotalDataLength = ((USHORT UNALIGNED *)(IpxHeader+1))[4];
  2027. //
  2028. // KeepAlive - return FALSE
  2029. //
  2030. if (TotalDataLength == 0) {
  2031. return FALSE;
  2032. }
  2033. }
  2034. } else {
  2035. //
  2036. // Now see if it is an NCP keep alive. It can be from rip or from
  2037. // NCP on this machine
  2038. //
  2039. if (TotalLength == sizeof(IPX_HEADER) + 2) {
  2040. UCHAR KeepAliveSignature = ((PUCHAR)(IpxHeader+1))[1];
  2041. if ((KeepAliveSignature == '?') ||
  2042. (KeepAliveSignature == 'Y')) {
  2043. return FALSE;
  2044. }
  2045. }
  2046. }
  2047. }
  2048. //
  2049. // This was a normal packet, so return TRUE
  2050. //
  2051. return TRUE;
  2052. }
  2053. BOOLEAN
  2054. NbfIsDataFrame(
  2055. PUCHAR HeaderBuffer,
  2056. ULONG HeaderBufferLength,
  2057. ULONG TotalLength
  2058. )
  2059. {
  2060. /*++
  2061. Routine Description:
  2062. This routine looks at a data packet from the net to deterimine if there is
  2063. any data flowing on the connection.
  2064. Arguments:
  2065. HeaderBuffer - Pointer to the dlc header for this packet.
  2066. HeaderBufferLength - Length of the header buffer (could be same as totallength)
  2067. TotalLength - the total length of the frame
  2068. Return Value:
  2069. True if this is a frame that indicates data traffic on the connection.
  2070. False otherwise.
  2071. --*/
  2072. PDLC_FRAME DlcHeader = (PDLC_FRAME)HeaderBuffer;
  2073. BOOLEAN Command = (BOOLEAN)!(DlcHeader->Ssap & DLC_SSAP_RESPONSE);
  2074. PNBF_HDR_CONNECTION nbfHeader;
  2075. if (TotalLength < sizeof(PDLC_FRAME)) {
  2076. return(FALSE);
  2077. }
  2078. if (!(DlcHeader->Byte1 & DLC_I_INDICATOR)) {
  2079. //
  2080. // We have an I frame.
  2081. //
  2082. if (TotalLength < 4 + sizeof(NBF_HDR_CONNECTION)) {
  2083. //
  2084. // It's a runt I-frame.
  2085. //
  2086. return(FALSE);
  2087. }
  2088. nbfHeader = (PNBF_HDR_CONNECTION) ((PUCHAR)DlcHeader + 4);
  2089. switch (nbfHeader->Command) {
  2090. case NBF_CMD_DATA_FIRST_MIDDLE:
  2091. case NBF_CMD_DATA_ONLY_LAST:
  2092. case NBF_CMD_DATA_ACK:
  2093. case NBF_CMD_SESSION_CONFIRM:
  2094. case NBF_CMD_SESSION_INITIALIZE:
  2095. case NBF_CMD_NO_RECEIVE:
  2096. case NBF_CMD_RECEIVE_OUTSTANDING:
  2097. case NBF_CMD_RECEIVE_CONTINUE:
  2098. return(TRUE);
  2099. break;
  2100. default:
  2101. return(FALSE);
  2102. break;
  2103. }
  2104. }
  2105. return(FALSE);
  2106. }
  2107. VOID
  2108. IndicatePromiscuousRecv(
  2109. PBUNDLECB BundleCB,
  2110. PRECV_DESC RecvDesc,
  2111. RECV_TYPE RecvType
  2112. )
  2113. {
  2114. UCHAR Header1[] = {' ', 'W', 'A', 'N', 'R', 0xFF, ' ', 'W', 'A', 'N', 'R', 0xFF};
  2115. PUCHAR HeaderBuffer, DataBuffer;
  2116. ULONG HeaderLength, DataLength;
  2117. PNDIS_BUFFER NdisBuffer;
  2118. PNDIS_PACKET NdisPacket;
  2119. PRECV_DESC LocalRecvDesc;
  2120. PLINKCB LinkCB = RecvDesc->LinkCB;
  2121. KIRQL OldIrql;
  2122. PMINIPORTCB Adapter;
  2123. NdisAcquireSpinLock(&NdisWanCB.Lock);
  2124. Adapter = NdisWanCB.PromiscuousAdapter;
  2125. NdisReleaseSpinLock(&NdisWanCB.Lock);
  2126. if (Adapter == NULL) {
  2127. return;
  2128. }
  2129. DataLength = (RecvDesc->CurrentLength > (LONG)glLargeDataBufferSize) ?
  2130. glLargeDataBufferSize : RecvDesc->CurrentLength;
  2131. LocalRecvDesc =
  2132. NdisWanAllocateRecvDesc(DataLength + MAC_HEADER_LENGTH);
  2133. if (LocalRecvDesc == NULL) {
  2134. return;
  2135. }
  2136. HeaderBuffer =
  2137. LocalRecvDesc->StartBuffer;
  2138. HeaderLength = 0;
  2139. switch (RecvType) {
  2140. case RECV_LINK:
  2141. NdisMoveMemory(HeaderBuffer, Header1, sizeof(Header1));
  2142. HeaderBuffer[5] =
  2143. HeaderBuffer[11] = (UCHAR)LinkCB->hLinkHandle;
  2144. HeaderBuffer[12] = (UCHAR)(DataLength >> 8);
  2145. HeaderBuffer[13] = (UCHAR)DataLength;
  2146. HeaderLength = MAC_HEADER_LENGTH;
  2147. break;
  2148. case RECV_BUNDLE_PPP:
  2149. case RECV_BUNDLE_DATA:
  2150. break;
  2151. }
  2152. DataBuffer = HeaderBuffer + HeaderLength;
  2153. NdisMoveMemory(DataBuffer,
  2154. RecvDesc->CurrentBuffer,
  2155. DataLength);
  2156. LocalRecvDesc->CurrentBuffer = HeaderBuffer;
  2157. LocalRecvDesc->CurrentLength = HeaderLength + DataLength;
  2158. if (LocalRecvDesc->CurrentLength > 1514) {
  2159. LocalRecvDesc->CurrentLength = 1514;
  2160. }
  2161. //
  2162. // Get an ndis packet
  2163. //
  2164. NdisPacket =
  2165. LocalRecvDesc->NdisPacket;
  2166. PPROTOCOL_RESERVED_FROM_NDIS(NdisPacket)->RecvDesc = LocalRecvDesc;
  2167. //
  2168. // Attach the buffers
  2169. //
  2170. NdisAdjustBufferLength(LocalRecvDesc->NdisBuffer,
  2171. LocalRecvDesc->CurrentLength);
  2172. NdisRecalculatePacketCounts(NdisPacket);
  2173. ReleaseBundleLock(BundleCB);
  2174. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  2175. NDIS_SET_PACKET_STATUS(NdisPacket, NDIS_STATUS_RESOURCES);
  2176. INSERT_DBG_RECV(PacketTypeNdis,
  2177. Adapter,
  2178. NULL,
  2179. RecvDesc->LinkCB,
  2180. NdisPacket);
  2181. //
  2182. // Indicate the packet
  2183. // This assumes that bloodhound is always a legacy transport
  2184. //
  2185. NdisMIndicateReceivePacket(Adapter->MiniportHandle,
  2186. &NdisPacket,
  2187. 1);
  2188. KeLowerIrql(OldIrql);
  2189. AcquireBundleLock(BundleCB);
  2190. #if DBG
  2191. {
  2192. NDIS_STATUS Status;
  2193. Status = NDIS_GET_PACKET_STATUS(NdisPacket);
  2194. ASSERT(Status == NDIS_STATUS_RESOURCES);
  2195. REMOVE_DBG_RECV(PacketTypeNdis, Adapter, NdisPacket);
  2196. }
  2197. #endif
  2198. {
  2199. PNDIS_BUFFER NdisBuffer;
  2200. NdisWanFreeRecvDesc(LocalRecvDesc);
  2201. }
  2202. }
  2203. BOOLEAN
  2204. GetProtocolFromPPPId(
  2205. PBUNDLECB BundleCB,
  2206. USHORT Id,
  2207. PPROTOCOLCB *ProtocolCB
  2208. )
  2209. {
  2210. PPROTOCOLCB ppcb;
  2211. BOOLEAN Found;
  2212. *ProtocolCB = NULL;
  2213. ppcb = (PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
  2214. Found = FALSE;
  2215. while ((PVOID)ppcb != (PVOID)&BundleCB->ProtocolCBList) {
  2216. if (ppcb->State == PROTOCOL_ROUTED) {
  2217. if (ppcb->PPPProtocolID == Id) {
  2218. *ProtocolCB = ppcb;
  2219. Found = TRUE;
  2220. break;
  2221. }
  2222. }
  2223. ppcb = (PPROTOCOLCB)ppcb->Linkage.Flink;
  2224. }
  2225. return (Found);
  2226. }
  2227. #ifdef NT
  2228. NDIS_STATUS
  2229. CompleteIoRecvPacket(
  2230. PBUNDLECB BundleCB,
  2231. PRECV_DESC RecvDesc
  2232. )
  2233. {
  2234. KIRQL Irql;
  2235. USHORT ProtocolID;
  2236. UCHAR Header[] = {' ', 'R', 'E', 'C', 'V', 0xFF};
  2237. PNDISWAN_IO_PACKET IoPacket;
  2238. PIO_STACK_LOCATION IrpSp;
  2239. PIRP Irp;
  2240. LONG CopySize, BufferLength, DataLength;
  2241. PLIST_ENTRY Entry;
  2242. PUCHAR HeaderPointer;
  2243. PLINKCB LinkCB = RecvDesc->LinkCB;
  2244. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("CompleteIoRecvPacket: Enter"));
  2245. HeaderPointer =
  2246. RecvDesc->StartBuffer;
  2247. ProtocolID = RecvDesc->ProtocolID;
  2248. //
  2249. // Fill the frame out, and queue the data
  2250. //
  2251. NdisMoveMemory(HeaderPointer,
  2252. Header,
  2253. sizeof(Header));
  2254. NdisMoveMemory(&HeaderPointer[6],
  2255. Header,
  2256. sizeof(Header));
  2257. HeaderPointer[5] =
  2258. HeaderPointer[11] = (UCHAR)LinkCB->hLinkHandle;
  2259. HeaderPointer[12] = (UCHAR)(ProtocolID >> 8);
  2260. HeaderPointer[13] = (UCHAR)ProtocolID;
  2261. NdisMoveMemory(HeaderPointer + 14,
  2262. RecvDesc->CurrentBuffer,
  2263. RecvDesc->CurrentLength);
  2264. RecvDesc->CurrentBuffer = RecvDesc->StartBuffer;
  2265. RecvDesc->CurrentLength += 14;
  2266. #if DBG
  2267. if (gbDumpRecv) {
  2268. INT i;
  2269. DbgPrint("RecvData:");
  2270. for (i = 0; i < RecvDesc->CurrentLength; i++) {
  2271. if (i % 16 == 0) {
  2272. DbgPrint("\n");
  2273. }
  2274. DbgPrint("%2.2x ", RecvDesc->CurrentBuffer[i]);
  2275. }
  2276. DbgPrint("\n");
  2277. }
  2278. #endif
  2279. ReleaseBundleLock(BundleCB);
  2280. //
  2281. // See if someone has registered a recv context
  2282. // for this link or if there are any irps around
  2283. // to complete take this receive
  2284. //
  2285. NdisAcquireSpinLock(&IoRecvList.Lock);
  2286. NdisDprAcquireSpinLock(&LinkCB->Lock);
  2287. Entry = IoRecvList.IrpList.Flink;
  2288. Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
  2289. if ((LinkCB->hLinkContext == NULL) ||
  2290. (LinkCB->RecvDescCount > 0) ||
  2291. (IoRecvList.ulIrpCount == 0) ||
  2292. !IoSetCancelRoutine(Irp, NULL)) {
  2293. NDIS_STATUS Status;
  2294. //
  2295. // We will only buffer 5 packets for each link to avoid
  2296. // chewing up tons of non-paged memory if rasman is not
  2297. // reading at all.
  2298. //
  2299. if ((LinkCB->State == LINK_UP) &&
  2300. (LinkCB->RecvDescCount < 5)) {
  2301. InsertTailList(&IoRecvList.DescList,
  2302. &RecvDesc->Linkage);
  2303. LinkCB->RecvDescCount++;
  2304. IoRecvList.ulDescCount++;
  2305. if (IoRecvList.ulDescCount > IoRecvList.ulMaxDescCount) {
  2306. IoRecvList.ulMaxDescCount = IoRecvList.ulDescCount;
  2307. }
  2308. Status = NDIS_STATUS_PENDING;
  2309. } else {
  2310. Status = NDIS_STATUS_FAILURE;
  2311. }
  2312. NdisDprReleaseSpinLock(&LinkCB->Lock);
  2313. NdisReleaseSpinLock(&IoRecvList.Lock);
  2314. AcquireBundleLock(BundleCB);
  2315. return(Status);
  2316. }
  2317. RemoveHeadList(&IoRecvList.IrpList);
  2318. IoRecvList.ulIrpCount--;
  2319. INSERT_RECV_EVENT('a');
  2320. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  2321. BufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  2322. DataLength = BufferLength - sizeof(NDISWAN_IO_PACKET) + 1;
  2323. CopySize = (RecvDesc->CurrentLength > DataLength) ?
  2324. DataLength : RecvDesc->CurrentLength;
  2325. IoPacket = Irp->AssociatedIrp.SystemBuffer;
  2326. IoPacket->hHandle = LinkCB->hLinkContext;
  2327. IoPacket->usHandleType = LINKHANDLE;
  2328. IoPacket->usHeaderSize = 14;
  2329. IoPacket->usPacketSize = (USHORT)CopySize;
  2330. IoPacket->usPacketFlags = 0;
  2331. #if DBG
  2332. if (gbDumpRecv) {
  2333. INT i;
  2334. for (i = 0; i < RecvDesc->CurrentLength; i++) {
  2335. if (i % 16 == 0) {
  2336. DbgPrint("\n");
  2337. }
  2338. DbgPrint("%x ", RecvDesc->CurrentBuffer[i]);
  2339. }
  2340. DbgPrint("\n");
  2341. }
  2342. #endif
  2343. NdisMoveMemory(IoPacket->PacketData,
  2344. RecvDesc->CurrentBuffer,
  2345. CopySize);
  2346. Irp->IoStatus.Status = STATUS_SUCCESS;
  2347. Irp->IoStatus.Information = sizeof(NDISWAN_IO_PACKET) - 1 + CopySize;
  2348. IoRecvList.LastPacketNumber = IoPacket->PacketNumber;
  2349. IoRecvList.LastIrp = Irp;
  2350. IoRecvList.LastIrpStatus = STATUS_SUCCESS;
  2351. IoRecvList.LastCopySize = (ULONG)Irp->IoStatus.Information;
  2352. ASSERT((LONG_PTR)Irp->IoStatus.Information > 0);
  2353. NdisDprReleaseSpinLock(&LinkCB->Lock);
  2354. NdisReleaseSpinLock(&IoRecvList.Lock);
  2355. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  2356. AcquireBundleLock(BundleCB);
  2357. if (NdisWanCB.PromiscuousAdapter != NULL) {
  2358. IndicatePromiscuousRecv(BundleCB, RecvDesc, RECV_BUNDLE_PPP);
  2359. }
  2360. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("CompleteIoRecvPacket: Exit"));
  2361. return(NDIS_STATUS_SUCCESS);
  2362. }
  2363. #endif // end ifdef NT