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.

2999 lines
76 KiB

  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. Module Name:
  4. Send.c
  5. Abstract:
  6. This file contains the procedures for doing a send from a protocol, bound
  7. to the upper interface of NdisWan, to a Wan Miniport link, bound to the
  8. lower interfaceof NdisWan. The upper interface of NdisWan conforms to the
  9. NDIS 3.1 Miniport specification. The lower interface of NdisWan conforms
  10. to the NDIS 3.1 Extentions for Wan Miniport drivers.
  11. Author:
  12. Tony Bell (TonyBe) June 06, 1995
  13. Environment:
  14. Kernel Mode
  15. Revision History:
  16. TonyBe 06/06/95 Created
  17. --*/
  18. #include "wan.h"
  19. #ifdef DBG_SENDARRAY
  20. UCHAR SendArray[MAX_BYTE_DEPTH] = {0};
  21. ULONG __si = 0;
  22. #endif
  23. #define __FILE_SIG__ SEND_FILESIG
  24. //
  25. // Local function prototypes
  26. //
  27. USHORT
  28. DoVJHeaderCompression(
  29. PBUNDLECB BundleCB,
  30. PNDIS_PACKET NdisPacket,
  31. PUCHAR *CurrentBuffer,
  32. PULONG CurrentLength,
  33. PULONG PacketOffset
  34. );
  35. VOID
  36. DoCompressionEncryption(
  37. PBUNDLECB BundleCB,
  38. PHEADER_FRAMING_INFO FramingInfo,
  39. PSEND_DESC *SendDesc
  40. );
  41. VOID
  42. FragmentAndQueue(
  43. PBUNDLECB BundleCB,
  44. PHEADER_FRAMING_INFO FramingInfo,
  45. PSEND_DESC SendDesc,
  46. PLIST_ENTRY LinkCBList,
  47. ULONG SendingLinks
  48. );
  49. ULONG
  50. GetSendingLinks(
  51. PBUNDLECB BundleCB,
  52. INT Class,
  53. PLIST_ENTRY lcbList
  54. );
  55. VOID
  56. GetNextProtocol(
  57. PBUNDLECB BundleCB,
  58. PPROTOCOLCB *ProtocolCB,
  59. PULONG SendMask
  60. );
  61. VOID
  62. BuildLinkHeader(
  63. PHEADER_FRAMING_INFO FramingInfo,
  64. PSEND_DESC SendDesc
  65. );
  66. //
  67. // end of local function prototypes
  68. //
  69. VOID
  70. NdisWanQueueSend(
  71. IN PMINIPORTCB MiniportCB,
  72. IN PNDIS_PACKET NdisPacket
  73. )
  74. {
  75. PNDIS_BUFFER NdisBuffer;
  76. UINT BufferCount, PacketLength;
  77. PETH_HEADER EthernetHeader;
  78. BOOLEAN SendOnWire = FALSE;
  79. BOOLEAN CompletePacket = FALSE;
  80. ULONG BufferLength;
  81. PUCHAR DestAddr, SrcAddr;
  82. PBUNDLECB BundleCB = NULL;
  83. PPROTOCOLCB ProtocolCB = NULL;
  84. PCM_VCCB CmVcCB = NULL;
  85. INT Class;
  86. PPACKET_QUEUE PacketQueue;
  87. NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("NdisWanQueueSend: Enter"));
  88. NdisWanInterlockedInc(&glSendCount);
  89. NdisQueryPacket(NdisPacket,
  90. NULL,
  91. &BufferCount,
  92. &NdisBuffer,
  93. &PacketLength);
  94. NdisQueryBuffer(NdisBuffer,
  95. &EthernetHeader,
  96. &BufferLength);
  97. CmVcCB = PMINIPORT_RESERVED_FROM_NDIS(NdisPacket)->CmVcCB;
  98. if (BufferCount == 0 || BufferLength < 14) {
  99. //
  100. // Malformed packet!
  101. //
  102. CompletePacket = TRUE;
  103. goto QUEUE_SEND_EXIT;
  104. }
  105. //
  106. // Check the ndis packet flags to make sure this is not just a loopback
  107. // packet. If it is we will just complete it back to the stack per
  108. // winse 22881.
  109. //
  110. if (NdisGetPacketFlags(NdisPacket) & NDIS_FLAGS_LOOPBACK_ONLY) {
  111. //
  112. // Complete the packet back to the stack without sending on
  113. // the wire. We might need to do loopback for these packets
  114. // at somepoint.
  115. //
  116. CompletePacket = TRUE;
  117. goto QUEUE_SEND_EXIT;
  118. }
  119. DestAddr = EthernetHeader->DestAddr;
  120. SrcAddr = EthernetHeader->SrcAddr;
  121. //
  122. // Is this destined for the wire or is it self directed?
  123. // If SendOnWire is FALSE this is a self directed packet.
  124. //
  125. ETH_COMPARE_NETWORK_ADDRESSES_EQ(DestAddr, SrcAddr, &SendOnWire);
  126. //
  127. // Do we need to do loopback? We can check for both multicast
  128. // and broadcast with one check because we don't differentiate
  129. // between the two.
  130. //
  131. if (!SendOnWire || (DestAddr[0] & 1)) {
  132. NdisWanIndicateLoopbackPacket(MiniportCB, NdisPacket);
  133. }
  134. //
  135. // We don't want to send packets from bloodhound
  136. //
  137. if (!SendOnWire ||
  138. (MiniportCB == NdisWanCB.PromiscuousAdapter)) {
  139. CompletePacket = TRUE;
  140. goto QUEUE_SEND_EXIT;
  141. }
  142. //
  143. // We play special tricks with NBF because NBF is
  144. // guaranteed to have a one-to-one mapping between
  145. // an adapter and a bundle. We need to do this because
  146. // we may need the mac address information.
  147. //
  148. if (MiniportCB->ProtocolType == PROTOCOL_NBF) {
  149. ProtocolCB = MiniportCB->NbfProtocolCB;
  150. if (ProtocolCB == NULL) {
  151. //
  152. // This should just fall through and complete successfully.
  153. //
  154. NdisWanDbgOut(DBG_TRACE, DBG_SEND,
  155. ("NdisWanSend: Invalid ProtocolCB %x! Miniport %p, ProtoType %x",
  156. ProtocolCB, MiniportCB, MiniportCB->ProtocolType));
  157. CompletePacket = TRUE;
  158. goto QUEUE_SEND_EXIT;
  159. }
  160. BundleCB = ProtocolCB->BundleCB;
  161. if (BundleCB == NULL) {
  162. //
  163. // This should just fall through and complete successfully.
  164. //
  165. NdisWanDbgOut(DBG_FAILURE, DBG_SEND,
  166. ("NdisWanSend: Invalid Bundle!"));
  167. NdisWanDbgOut(DBG_FAILURE, DBG_SEND,
  168. ("NdisWanSend: MiniportCB: 0x%p, ProtocolType: 0x%x!", MiniportCB, MiniportCB->ProtocolType));
  169. CompletePacket = TRUE;
  170. goto QUEUE_SEND_EXIT;
  171. }
  172. AcquireBundleLock(BundleCB);
  173. if (BundleCB->State != BUNDLE_UP) {
  174. //
  175. // This should just fall through and complete successfully.
  176. //
  177. NdisWanDbgOut(DBG_FAILURE, DBG_SEND,
  178. ("NdisWanSend: Invalid BundleState 0x%x", BundleCB->State));
  179. NdisWanDbgOut(DBG_FAILURE, DBG_SEND,
  180. ("NdisWanSend: MiniportCB: 0x%p, ProtocolType: 0x%x!", MiniportCB, MiniportCB->ProtocolType));
  181. CompletePacket = TRUE;
  182. ReleaseBundleLock(BundleCB);
  183. BundleCB = NULL;
  184. goto QUEUE_SEND_EXIT;
  185. }
  186. REF_BUNDLECB(BundleCB);
  187. } else {
  188. ULONG_PTR BIndex, PIndex;
  189. //
  190. // Get the ProtocolCB from the DestAddr
  191. //
  192. GetNdisWanIndices(DestAddr, BIndex, PIndex);
  193. if (!IsBundleValid((NDIS_HANDLE)BIndex,
  194. TRUE,
  195. &BundleCB)) {
  196. //
  197. // This should just fall through and complete successfully.
  198. //
  199. NdisWanDbgOut(DBG_FAILURE, DBG_SEND,
  200. ("NdisWanSend: BundleCB is not valid!, BundleHandle: 0x%x", BIndex));
  201. NdisWanDbgOut(DBG_FAILURE, DBG_SEND,
  202. ("NdisWanSend: MiniportCB: 0x%p, ProtocolType: 0x%x!", MiniportCB, MiniportCB->ProtocolType));
  203. CompletePacket = TRUE;
  204. goto QUEUE_SEND_EXIT;
  205. }
  206. AcquireBundleLock(BundleCB);
  207. PROTOCOLCB_FROM_PROTOCOLH(BundleCB, ProtocolCB, PIndex);
  208. }
  209. if (ProtocolCB == NULL ||
  210. ProtocolCB == RESERVED_PROTOCOLCB) {
  211. //
  212. // This should just fall through and complete successfully.
  213. //
  214. NdisWanDbgOut(DBG_TRACE, DBG_SEND,
  215. ("NdisWanSend: Invalid ProtocolCB %x! Miniport %p, ProtoType %x",
  216. ProtocolCB, MiniportCB, MiniportCB->ProtocolType));
  217. CompletePacket = TRUE;
  218. ReleaseBundleLock(BundleCB);
  219. goto QUEUE_SEND_EXIT;
  220. }
  221. if (ProtocolCB->State != PROTOCOL_ROUTED) {
  222. NdisWanDbgOut(DBG_FAILURE, DBG_SEND,("NdisWanSend: Problem with route!"));
  223. NdisWanDbgOut(DBG_FAILURE, DBG_SEND,
  224. ("NdisWanSend: ProtocolCB: 0x%p, State: 0x%x",
  225. ProtocolCB, ProtocolCB->State));
  226. CompletePacket = TRUE;
  227. ReleaseBundleLock(BundleCB);
  228. goto QUEUE_SEND_EXIT;
  229. }
  230. //
  231. // For the packet that we are inserting
  232. //
  233. REF_PROTOCOLCB(ProtocolCB);
  234. NdisInterlockedIncrement(&ProtocolCB->OutstandingFrames);
  235. //
  236. // Queue the packet on the ProtocolCB NdisPacketQueue
  237. //
  238. Class = (CmVcCB != NULL) ? CmVcCB->FlowClass : 0;
  239. NDIS_SET_PACKET_STATUS(NdisPacket, NDIS_STATUS_PENDING);
  240. ASSERT(Class <= MAX_MCML);
  241. PacketQueue = &ProtocolCB->PacketQueue[Class];
  242. INSERT_DBG_SEND(PacketTypeNdis,
  243. MiniportCB,
  244. ProtocolCB,
  245. NULL,
  246. NdisPacket);
  247. InsertTailPacketQueue(PacketQueue, NdisPacket, PacketLength);
  248. #ifdef DBG_SENDARRAY
  249. {
  250. if (Class < MAX_MCML) {
  251. SendArray[__si] = 'P';
  252. } else {
  253. SendArray[__si] = 'Q';
  254. }
  255. if (++__si == MAX_BYTE_DEPTH) {
  256. __si = 0;
  257. }
  258. }
  259. #endif
  260. if (PacketQueue->ByteDepth > PacketQueue->MaxByteDepth) {
  261. //
  262. // We have queue more then we should so lets flush
  263. // This alogrithm should be fancied up at some point
  264. // to use Random Early Detection!!!!!
  265. //
  266. NdisPacket =
  267. RemoveHeadPacketQueue(PacketQueue);
  268. if (NdisPacket != NULL) {
  269. PacketQueue->DumpedPacketCount++;
  270. PacketQueue->DumpedByteCount +=
  271. (NdisPacket->Private.TotalLength - 14);
  272. ReleaseBundleLock(BundleCB);
  273. CompleteNdisPacket(ProtocolCB->MiniportCB,
  274. ProtocolCB,
  275. NdisPacket);
  276. AcquireBundleLock(BundleCB);
  277. }
  278. }
  279. //
  280. // If we are cleared to send data then
  281. // try to process the protocol queues
  282. //
  283. if (!(BundleCB->Flags & PAUSE_DATA)) {
  284. SendPacketOnBundle(ProtocolCB->BundleCB);
  285. } else {
  286. ReleaseBundleLock(BundleCB);
  287. }
  288. QUEUE_SEND_EXIT:
  289. if (CompletePacket) {
  290. NDIS_SET_PACKET_STATUS(NdisPacket, NDIS_STATUS_SUCCESS);
  291. if (CmVcCB != NULL) {
  292. NdisMCoSendComplete(NDIS_STATUS_SUCCESS,
  293. CmVcCB->NdisVcHandle,
  294. NdisPacket);
  295. DEREF_CMVCCB(CmVcCB);
  296. } else {
  297. NdisMSendComplete(MiniportCB->MiniportHandle,
  298. NdisPacket,
  299. NDIS_STATUS_SUCCESS);
  300. }
  301. NdisWanInterlockedInc(&glSendCompleteCount);
  302. }
  303. //
  304. // Deref for ref applied in IsBundleValid
  305. //
  306. DEREF_BUNDLECB(BundleCB);
  307. NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("NdisWanQueueSend: Exit"));
  308. }
  309. VOID
  310. SendPacketOnBundle(
  311. PBUNDLECB BundleCB
  312. )
  313. /*++
  314. Routine Name:
  315. Routine Description:
  316. Called with bundle lock held but returns with lock released!!!
  317. Arguments:
  318. Return Values:
  319. --*/
  320. {
  321. NDIS_STATUS Status = NDIS_STATUS_PENDING;
  322. ULONG SendMask;
  323. PPROTOCOLCB ProtocolCB, IOProtocolCB;
  324. BOOLEAN PPPSent;
  325. NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("SendPacketOnBundle: Enter"));
  326. //
  327. // Are we already involved in a send on this bundlecb?
  328. //
  329. if (BundleCB->Flags & IN_SEND) {
  330. //
  331. // If so flag that we should try back later
  332. // and get the out.
  333. //
  334. BundleCB->Flags |= TRY_SEND_AGAIN;
  335. ReleaseBundleLock(BundleCB);
  336. return;
  337. }
  338. BundleCB->Flags |= IN_SEND;
  339. IOProtocolCB = BundleCB->IoProtocolCB;
  340. TryAgain:
  341. SendMask = BundleCB->SendMask;
  342. //
  343. // If the bundle is not up we will not send!
  344. //
  345. if (BundleCB->State != BUNDLE_UP) {
  346. goto TryNoMore;
  347. }
  348. do {
  349. BOOLEAN PacketSent = FALSE;
  350. BOOLEAN CouldSend;
  351. //
  352. // First try to send from the PPP send queue
  353. //
  354. do {
  355. CouldSend =
  356. SendFromPPP(BundleCB, IOProtocolCB, &PPPSent);
  357. } while (PPPSent);
  358. //
  359. // If we could not send a PPP frame get out
  360. //
  361. if (!CouldSend) {
  362. break;
  363. }
  364. //
  365. // This will force round-robin sends
  366. //
  367. GetNextProtocol(BundleCB, &ProtocolCB, &SendMask);
  368. if (ProtocolCB != NULL) {
  369. REF_PROTOCOLCB(ProtocolCB);
  370. if (BundleCB->Flags & QOS_ENABLED) {
  371. if (BundleCB->Flags & SEND_FRAGMENT) {
  372. SendQosFrag:
  373. //
  374. // Send a single fragment from the fragment queue
  375. //
  376. CouldSend =
  377. SendFromFragQueue(BundleCB,
  378. TRUE,
  379. &PacketSent);
  380. if (CouldSend) {
  381. BundleCB->Flags &= ~(SEND_FRAGMENT);
  382. }
  383. }
  384. //
  385. // If we sent a fragment let the completion
  386. // handler send the next frame.
  387. //
  388. if (!PacketSent) {
  389. //
  390. // Now try the protocol's packet queues
  391. //
  392. if (SendMask != 0) {
  393. INT Class;
  394. INT i;
  395. for (i = 0; i <= MAX_MCML; i++) {
  396. CouldSend =
  397. SendFromProtocol(BundleCB,
  398. ProtocolCB,
  399. &Class,
  400. &SendMask,
  401. &PacketSent);
  402. if (!CouldSend) {
  403. break;
  404. }
  405. BundleCB->Flags |= (SEND_FRAGMENT);
  406. if (PacketSent) {
  407. break;
  408. }
  409. }
  410. if (!PacketSent ||
  411. (PacketSent && (Class != MAX_MCML))) {
  412. goto SendQosFrag;
  413. }
  414. }
  415. }
  416. } else {
  417. //
  418. // Now try the protocol's packet queues
  419. //
  420. if (SendMask != 0) {
  421. INT Class;
  422. INT i;
  423. for (i = 0; i <= MAX_MCML; i++) {
  424. CouldSend =
  425. SendFromProtocol(BundleCB,
  426. ProtocolCB,
  427. &Class,
  428. &SendMask,
  429. &PacketSent);
  430. }
  431. }
  432. SendFromFragQueue(BundleCB,
  433. FALSE,
  434. &PacketSent);
  435. }
  436. DEREF_PROTOCOLCB(ProtocolCB);
  437. }
  438. } while ((SendMask != 0) &&
  439. (BundleCB->State == BUNDLE_UP));
  440. TryNoMore:
  441. //
  442. // Did someone try to do a send while we were already
  443. // sending on this bundle?
  444. //
  445. if (BundleCB->Flags & TRY_SEND_AGAIN) {
  446. //
  447. // If so clear the flag and try another send.
  448. //
  449. BundleCB->Flags &= ~TRY_SEND_AGAIN;
  450. goto TryAgain;
  451. }
  452. #ifdef DBG_SENDARRAY
  453. {
  454. SendArray[__si] = 'Z';
  455. if (++__si == MAX_BYTE_DEPTH) {
  456. __si = 0;
  457. }
  458. }
  459. #endif
  460. //
  461. // Clear the in send flag.
  462. //
  463. BundleCB->Flags &= ~IN_SEND;
  464. ReleaseBundleLock(BundleCB);
  465. NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("SendPacketOnBundle: Exit"));
  466. }
  467. BOOLEAN
  468. SendFromPPP(
  469. PBUNDLECB BundleCB,
  470. PPROTOCOLCB ProtocolCB,
  471. PBOOLEAN PacketSent
  472. )
  473. {
  474. PLINKCB LinkCB;
  475. PNDIS_PACKET NdisPacket;
  476. PPACKET_QUEUE PacketQueue;
  477. INT SendingClass;
  478. BOOLEAN CouldSend;
  479. ULONG BytesSent;
  480. PacketQueue = &ProtocolCB->PacketQueue[MAX_MCML];
  481. CouldSend = TRUE;
  482. *PacketSent = FALSE;
  483. while (!IsPacketQueueEmpty(PacketQueue)) {
  484. LIST_ENTRY LinkCBList;
  485. ULONG SendingLinks;
  486. NdisPacket = PacketQueue->HeadQueue;
  487. LinkCB =
  488. PPROTOCOL_RESERVED_FROM_NDIS(NdisPacket)->LinkCB;
  489. NdisAcquireSpinLock(&LinkCB->Lock);
  490. if (LinkCB->State != LINK_UP) {
  491. NdisReleaseSpinLock(&LinkCB->Lock);
  492. NdisReleaseSpinLock(&BundleCB->Lock);
  493. DEREF_LINKCB(LinkCB);
  494. NdisAcquireSpinLock(&BundleCB->Lock);
  495. //
  496. // The link has gone down since this send was
  497. // queued so destroy the packet
  498. //
  499. RemoveHeadPacketQueue(PacketQueue);
  500. FreeIoNdisPacket(NdisPacket);
  501. continue;
  502. }
  503. if (!LinkCB->SendWindowOpen) {
  504. //
  505. // We can not send from the I/O queue because the send
  506. // window for this link is closed. We will not send
  507. // any data until the link has resources!
  508. //
  509. CouldSend = FALSE;
  510. NdisReleaseSpinLock(&LinkCB->Lock);
  511. break;
  512. }
  513. NdisReleaseSpinLock(&LinkCB->Lock);
  514. //
  515. // Build the linkcb send list
  516. //
  517. InitializeListHead(&LinkCBList);
  518. InsertHeadList(&LinkCBList, &LinkCB->SendLinkage);
  519. SendingLinks = 1;
  520. //
  521. // We are sending this packet so take it off of the list
  522. //
  523. RemoveHeadPacketQueue(PacketQueue);
  524. SendingClass = MAX_MCML;
  525. ASSERT(NdisPacket != NULL);
  526. ASSERT(ProtocolCB != NULL);
  527. //
  528. // We we get here we should have a valid NdisPacket with at least one link
  529. // that is accepting sends
  530. //
  531. //
  532. // We will get the packet into a contiguous buffer, and do framing,
  533. // compression and encryption.
  534. //
  535. REF_BUNDLECB(BundleCB);
  536. BytesSent = FramePacket(BundleCB,
  537. ProtocolCB,
  538. NdisPacket,
  539. &LinkCBList,
  540. SendingLinks,
  541. SendingClass);
  542. *PacketSent = TRUE;
  543. }
  544. return (CouldSend);
  545. }
  546. BOOLEAN
  547. SendFromProtocol(
  548. PBUNDLECB BundleCB,
  549. PPROTOCOLCB ProtocolCB,
  550. PINT RetClass,
  551. PULONG SendMask,
  552. PBOOLEAN PacketSent
  553. )
  554. {
  555. ULONG BytesSent;
  556. BOOLEAN CouldSend;
  557. PNDIS_PACKET NdisPacket;
  558. PPACKET_QUEUE PacketQueue;
  559. INT Class;
  560. LIST_ENTRY LinkCBList;
  561. ULONG SendingLinks;
  562. CouldSend = TRUE;
  563. *PacketSent = FALSE;
  564. InitializeListHead(&LinkCBList);
  565. ASSERT(ProtocolCB != NULL);
  566. do {
  567. Class = ProtocolCB->NextPacketClass;
  568. *RetClass = Class;
  569. *SendMask &= ~(ProtocolCB->SendMaskBit);
  570. PacketQueue =
  571. &ProtocolCB->PacketQueue[Class];
  572. if (IsPacketQueueEmpty(PacketQueue)) {
  573. break;
  574. }
  575. if (BundleCB->Flags & QOS_ENABLED) {
  576. if ((Class < MAX_MCML) &&
  577. (PacketQueue->OutstandingFrags != 0)) {
  578. break;
  579. }
  580. } else {
  581. if (BundleCB->SendingLinks == 0) {
  582. break;
  583. }
  584. }
  585. //
  586. // Build a list of linkcb's that can be sent over
  587. //
  588. SendingLinks =
  589. GetSendingLinks(BundleCB, Class, &LinkCBList);
  590. //
  591. // If there are no links/resources available
  592. // to send over then get out
  593. //
  594. if (SendingLinks == 0) {
  595. CouldSend = FALSE;
  596. break;
  597. }
  598. NdisPacket =
  599. RemoveHeadPacketQueue(PacketQueue);
  600. ASSERT(NdisPacket != NULL);
  601. *PacketSent = TRUE;
  602. if (!(BundleCB->Flags & QOS_ENABLED)) {
  603. *SendMask |= ProtocolCB->SendMaskBit;
  604. }
  605. //
  606. // We we get here we should have a valid NdisPacket with at least one link
  607. // that is accepting sends
  608. //
  609. //
  610. // We will get the packet into a contiguous buffer, and do framing,
  611. // compression and encryption.
  612. //
  613. REF_BUNDLECB(BundleCB);
  614. BytesSent = FramePacket(BundleCB,
  615. ProtocolCB,
  616. NdisPacket,
  617. &LinkCBList,
  618. SendingLinks,
  619. Class);
  620. #ifdef DBG_SENDARRAY
  621. {
  622. if (Class < MAX_MCML) {
  623. SendArray[__si] = 'p';
  624. } else {
  625. SendArray[__si] = 'q';
  626. }
  627. if (++__si == MAX_BYTE_DEPTH) {
  628. __si = 0;
  629. }
  630. }
  631. #endif
  632. } while (FALSE);
  633. if (CouldSend) {
  634. ProtocolCB->NextPacketClass += 1;
  635. if (ProtocolCB->NextPacketClass > MAX_MCML) {
  636. ProtocolCB->NextPacketClass = 0;
  637. }
  638. }
  639. //
  640. // If there are any LinkCB's still on the send list
  641. // we have to remove the reference from them
  642. //
  643. if (!IsListEmpty(&LinkCBList)) {
  644. PLIST_ENTRY le;
  645. PLINKCB lcb;
  646. ReleaseBundleLock(BundleCB);
  647. //
  648. // unroll the loop so that the correct link
  649. // is setup for the next link to xmit
  650. //
  651. le = RemoveHeadList(&LinkCBList);
  652. lcb = CONTAINING_RECORD(le, LINKCB, SendLinkage);
  653. BundleCB->NextLinkToXmit = lcb;
  654. DEREF_LINKCB(lcb);
  655. while (!IsListEmpty(&LinkCBList)) {
  656. le = RemoveHeadList(&LinkCBList);
  657. lcb = CONTAINING_RECORD(le, LINKCB, SendLinkage);
  658. DEREF_LINKCB(lcb);
  659. }
  660. AcquireBundleLock(BundleCB);
  661. }
  662. return (CouldSend);
  663. }
  664. BOOLEAN
  665. SendFromFragQueue(
  666. PBUNDLECB BundleCB,
  667. BOOLEAN SendOne,
  668. PBOOLEAN FragSent
  669. )
  670. {
  671. ULONG i;
  672. BOOLEAN CouldSend;
  673. CouldSend = TRUE;
  674. *FragSent = FALSE;
  675. for (i = 0; i < MAX_MCML; i++) {
  676. PSEND_DESC SendDesc;
  677. PSEND_FRAG_INFO FragInfo;
  678. PLINKCB LinkCB;
  679. FragInfo =
  680. &BundleCB->SendFragInfo[BundleCB->NextFragClass];
  681. BundleCB->NextFragClass += 1;
  682. if (BundleCB->NextFragClass == MAX_MCML) {
  683. BundleCB->NextFragClass = 0;
  684. }
  685. if (FragInfo->FragQueueDepth == 0) {
  686. continue;
  687. }
  688. SendDesc = (PSEND_DESC)FragInfo->FragQueue.Flink;
  689. LinkCB = SendDesc->LinkCB;
  690. while ((PVOID)SendDesc != (PVOID)&FragInfo->FragQueue) {
  691. ULONG BytesSent;
  692. if (!LinkCB->SendWindowOpen) {
  693. //
  694. // We can't send on this link!
  695. //
  696. CouldSend = FALSE;
  697. SendDesc = (PSEND_DESC)SendDesc->Linkage.Flink;
  698. LinkCB = SendDesc->LinkCB;
  699. FragInfo->WinClosedCount++;
  700. continue;
  701. }
  702. CouldSend = TRUE;
  703. RemoveEntryList(&SendDesc->Linkage);
  704. FragInfo->FragQueueDepth--;
  705. *FragSent = TRUE;
  706. ASSERT((LONG)FragInfo->FragQueueDepth >= 0);
  707. BytesSent =
  708. (*LinkCB->SendHandler)(SendDesc);
  709. #ifdef DBG_SENDARRAY
  710. {
  711. SendArray[__si] = 0x40 + (UCHAR)LinkCB->hLinkHandle;
  712. if (++__si == MAX_BYTE_DEPTH) {
  713. __si = 0;
  714. }
  715. }
  716. #endif
  717. //
  718. // Update the bandwidth on demand sample array with the latest send.
  719. // If we need to notify someone of a bandwidth event do it.
  720. //
  721. if (BundleCB->Flags & BOND_ENABLED) {
  722. UpdateBandwidthOnDemand(BundleCB->SUpperBonDInfo, BytesSent);
  723. CheckUpperThreshold(BundleCB);
  724. UpdateBandwidthOnDemand(BundleCB->SLowerBonDInfo, BytesSent);
  725. CheckLowerThreshold(BundleCB);
  726. }
  727. SendDesc =
  728. (PSEND_DESC)FragInfo->FragQueue.Flink;
  729. LinkCB = SendDesc->LinkCB;
  730. //
  731. // If we are only supposed to send a single
  732. // fragment then we need to get out
  733. //
  734. if (SendOne) {
  735. break;
  736. }
  737. }
  738. //
  739. // If we are only supposed to send a single
  740. // fragment then we need to get out
  741. //
  742. if (SendOne) {
  743. break;
  744. }
  745. }
  746. return (CouldSend);
  747. }
  748. UINT
  749. FramePacket(
  750. PBUNDLECB BundleCB,
  751. PPROTOCOLCB ProtocolCB,
  752. PNDIS_PACKET NdisPacket,
  753. PLIST_ENTRY LinkCBList,
  754. ULONG SendingLinks,
  755. INT Class
  756. )
  757. {
  758. ULONG Flags, BytesSent;
  759. ULONG PacketOffset = 0, CurrentLength = 0;
  760. PUCHAR CurrentData;
  761. PLINKCB LinkCB = NULL;
  762. USHORT PPPProtocolID;
  763. PSEND_DESC SendDesc;
  764. HEADER_FRAMING_INFO FramingInfoBuffer;
  765. PHEADER_FRAMING_INFO FramingInfo = &FramingInfoBuffer;
  766. NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("SendPacket: Enter"));
  767. ASSERT(!IsListEmpty(LinkCBList));
  768. Flags = BundleCB->SendFlags;
  769. PPPProtocolID =
  770. ProtocolCB->PPPProtocolID;
  771. //
  772. // If this is a directed PPP packet then send to
  773. // the link indicated in the packet
  774. //
  775. if (PPPProtocolID == PPP_PROTOCOL_PRIVATE_IO) {
  776. Flags |= IO_PROTOCOLID;
  777. Flags &= ~(DO_COMPRESSION | DO_ENCRYPTION | DO_MULTILINK);
  778. }
  779. //
  780. // Did the last receive cause us to flush?
  781. //
  782. if ((Flags & (DO_COMPRESSION | DO_ENCRYPTION)) &&
  783. (BundleCB->Flags & RECV_PACKET_FLUSH)) {
  784. BundleCB->Flags &= ~RECV_PACKET_FLUSH;
  785. Flags |= DO_FLUSH;
  786. }
  787. Flags |= FIRST_FRAGMENT;
  788. if (Class == MAX_MCML) {
  789. Flags &= ~(DO_COMPRESSION | DO_ENCRYPTION | DO_MULTILINK);
  790. }
  791. //
  792. // Get a linkcb to send over
  793. //
  794. {
  795. PLIST_ENTRY Entry;
  796. Entry = RemoveHeadList(LinkCBList);
  797. LinkCB =
  798. CONTAINING_RECORD(Entry, LINKCB, SendLinkage);
  799. }
  800. //
  801. // Get a send desc
  802. //
  803. {
  804. ULONG PacketLength;
  805. NdisQueryPacket(NdisPacket,
  806. NULL,
  807. NULL,
  808. NULL,
  809. &PacketLength);
  810. SendDesc =
  811. NdisWanAllocateSendDesc(LinkCB, PacketLength);
  812. if (SendDesc == NULL) {
  813. ASSERT(SendDesc != NULL);
  814. ReleaseBundleLock(BundleCB);
  815. NDIS_SET_PACKET_STATUS(NdisPacket, NDIS_STATUS_RESOURCES);
  816. CompleteNdisPacket(ProtocolCB->MiniportCB,
  817. ProtocolCB,
  818. NdisPacket);
  819. AcquireBundleLock(BundleCB);
  820. goto FramePacketExit;
  821. }
  822. }
  823. BundleCB->OutstandingFrames++;
  824. SendDesc->ProtocolCB = ProtocolCB;
  825. SendDesc->OriginalPacket = NdisPacket;
  826. SendDesc->Class = Class;
  827. NdisWanDbgOut(DBG_TRACE, DBG_SEND,
  828. ("SendDesc: %p NdisPacket: %p", SendDesc, NdisPacket));
  829. //
  830. // Build a PPP Header in the buffer and update
  831. // current pointer
  832. //
  833. FramingInfo->FramingBits =
  834. LinkCB->LinkInfo.SendFramingBits;
  835. FramingInfo->Flags = Flags;
  836. FramingInfo->Class = Class;
  837. BuildLinkHeader(FramingInfo, SendDesc);
  838. CurrentData =
  839. SendDesc->StartBuffer + FramingInfo->HeaderLength;
  840. //
  841. // If we are in promiscuous mode we should indicate this
  842. // baby back up.
  843. //
  844. if (NdisWanCB.PromiscuousAdapter != NULL) {
  845. IndicatePromiscuousSendPacket(LinkCB, NdisPacket);
  846. }
  847. //
  848. // Copy MAC Header into buffer if needed and update
  849. // current pointer
  850. //
  851. if ((Flags & SAVE_MAC_ADDRESS) &&
  852. (PPPProtocolID == PPP_PROTOCOL_NBF)) {
  853. ULONG BytesCopied;
  854. NdisWanCopyFromPacketToBuffer(NdisPacket,
  855. PacketOffset,
  856. 12,
  857. CurrentData,
  858. &BytesCopied);
  859. ASSERT(BytesCopied == 12);
  860. CurrentData += BytesCopied;
  861. CurrentLength += BytesCopied;
  862. }
  863. //
  864. // We are beyond the mac header
  865. // (also skip the length/protocoltype field)
  866. //
  867. if (Flags & IO_PROTOCOLID) {
  868. PacketOffset = 12;
  869. } else {
  870. PacketOffset = 14;
  871. }
  872. if ((Flags & DO_VJ) &&
  873. PPPProtocolID == PPP_PROTOCOL_IP) {
  874. //
  875. // Do protocol header compression into buffer and
  876. // update current pointer.
  877. //
  878. PPPProtocolID =
  879. DoVJHeaderCompression(BundleCB,
  880. NdisPacket,
  881. &CurrentData,
  882. &CurrentLength,
  883. &PacketOffset);
  884. }
  885. //
  886. // Copy the rest of the data!
  887. //
  888. {
  889. ULONG BytesCopied;
  890. NdisWanCopyFromPacketToBuffer(NdisPacket,
  891. PacketOffset,
  892. 0xFFFFFFFF,
  893. CurrentData,
  894. &BytesCopied);
  895. SendDesc->DataLength =
  896. CurrentLength + BytesCopied;
  897. }
  898. AddPPPProtocolID(FramingInfo, PPPProtocolID);
  899. if (Flags & (DO_COMPRESSION | DO_ENCRYPTION)) {
  900. DoCompressionEncryption(BundleCB,
  901. FramingInfo,
  902. &SendDesc);
  903. }
  904. //
  905. // At this point we have our framinginfo structure initialized,
  906. // SendDesc->StartData pointing to the begining of the frame,
  907. // FramingInfo.HeaderLength is the length of the header,
  908. // SendDesc->DataLength is the length of the data.
  909. //
  910. if (Flags & DO_MULTILINK) {
  911. //
  912. // Fragment the data and place fragments
  913. // on bundles frag queue.
  914. //
  915. FragmentAndQueue(BundleCB,
  916. FramingInfo,
  917. SendDesc,
  918. LinkCBList,
  919. SendingLinks);
  920. BytesSent = 0;
  921. } else {
  922. //
  923. // This send descriptor is not to be fragmented
  924. // so just send it!
  925. //
  926. SendDesc->HeaderLength = FramingInfo->HeaderLength;
  927. InterlockedExchange(&(PMINIPORT_RESERVED_FROM_NDIS(NdisPacket)->RefCount), 1);
  928. BytesSent =
  929. (*LinkCB->SendHandler)(SendDesc);
  930. }
  931. if ((BundleCB->Flags & BOND_ENABLED) &&
  932. (BytesSent != 0)) {
  933. //
  934. // Update the bandwidth on demand sample array with the latest send.
  935. // If we need to notify someone of a bandwidth event do it.
  936. //
  937. UpdateBandwidthOnDemand(BundleCB->SUpperBonDInfo, BytesSent);
  938. CheckUpperThreshold(BundleCB);
  939. UpdateBandwidthOnDemand(BundleCB->SLowerBonDInfo, BytesSent);
  940. CheckLowerThreshold(BundleCB);
  941. }
  942. FramePacketExit:
  943. NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("SendPacket: Exit - BytesSent %d", BytesSent));
  944. return (BytesSent);
  945. }
  946. UINT
  947. SendOnLegacyLink(
  948. PSEND_DESC SendDesc
  949. )
  950. {
  951. UINT SendLength;
  952. PLINKCB LinkCB = SendDesc->LinkCB;
  953. PBUNDLECB BundleCB = LinkCB->BundleCB;
  954. PPROTOCOLCB ProtocolCB = SendDesc->ProtocolCB;
  955. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  956. PNDIS_WAN_PACKET WanPacket = SendDesc->WanPacket;
  957. NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("SendOnLegacyLink: LinkCB: 0x%p, SendDesc: 0x%p, WanPacket: 0x%p", LinkCB, SendDesc, WanPacket));
  958. LinkCB->OutstandingFrames++;
  959. if (LinkCB->SendWindow == LinkCB->OutstandingFrames) {
  960. LinkCB->SendWindowOpen = FALSE;
  961. BundleCB->SendingLinks--;
  962. }
  963. #if 0
  964. if (LinkCB->Stats.FramesTransmitted == 0) {
  965. PUCHAR pd;
  966. if (*(WanPacket->CurrentBuffer) != 0xFF) {
  967. pd = WanPacket->CurrentBuffer;
  968. } else {
  969. pd = (WanPacket->CurrentBuffer + 2);
  970. }
  971. if (*(pd) != 0xC0 ||
  972. *(pd+1) != 0x21 ||
  973. *(pd+2) != 0x01) {
  974. DbgPrint("NDISWAN: SLL-FirstFrame not LCP ConfigReq bcb %p, lcb %p\n",
  975. BundleCB, LinkCB);
  976. DbgBreakPoint();
  977. }
  978. }
  979. #endif
  980. SendLength =
  981. WanPacket->CurrentLength =
  982. SendDesc->HeaderLength + SendDesc->DataLength;
  983. WanPacket->ProtocolReserved1 = (PVOID)SendDesc;
  984. //
  985. // DoStats
  986. //
  987. LinkCB->Stats.FramesTransmitted++;
  988. BundleCB->Stats.FramesTransmitted++;
  989. LinkCB->Stats.BytesTransmitted += SendLength;
  990. BundleCB->Stats.BytesTransmitted += SendLength;
  991. INSERT_DBG_SEND(PacketTypeWan,
  992. LinkCB->OpenCB,
  993. ProtocolCB,
  994. LinkCB,
  995. WanPacket);
  996. ReleaseBundleLock(BundleCB);
  997. //
  998. // If the link is up send the packet
  999. //
  1000. NdisAcquireSpinLock(&LinkCB->Lock);
  1001. if (LinkCB->State == LINK_UP) {
  1002. KIRQL OldIrql;
  1003. NdisReleaseSpinLock(&LinkCB->Lock);
  1004. if (gbSniffLink &&
  1005. (NdisWanCB.PromiscuousAdapter != NULL)) {
  1006. IndicatePromiscuousSendDesc(LinkCB, SendDesc, SEND_LINK);
  1007. }
  1008. //
  1009. // There is a problem in ndis right now where
  1010. // the miniport lock is not acquired before sending
  1011. // to the wan miniport. This opens a window when
  1012. // the miniport does a sendcomplete from within
  1013. // it's send handler since sendcomplete expects
  1014. // to be running at dpc.
  1015. //
  1016. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  1017. WanMiniportSend(&Status,
  1018. LinkCB->OpenCB->BindingHandle,
  1019. LinkCB->NdisLinkHandle,
  1020. WanPacket);
  1021. KeLowerIrql(OldIrql);
  1022. } else {
  1023. NdisReleaseSpinLock(&LinkCB->Lock);
  1024. }
  1025. NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("SendOnLegacyLink: Status: 0x%x", Status));
  1026. //
  1027. // If we get something other than pending back we need to
  1028. // do the send complete.
  1029. //
  1030. if (Status != NDIS_STATUS_PENDING) {
  1031. ProtoWanSendComplete(NULL,
  1032. WanPacket,
  1033. NDIS_STATUS_SUCCESS);
  1034. }
  1035. AcquireBundleLock(BundleCB);
  1036. return (SendLength);
  1037. }
  1038. UINT
  1039. SendOnLink(
  1040. PSEND_DESC SendDesc
  1041. )
  1042. {
  1043. PLINKCB LinkCB;
  1044. PBUNDLECB BundleCB;
  1045. PPROTOCOLCB ProtocolCB;
  1046. PNDIS_PACKET NdisPacket;
  1047. PNDIS_BUFFER NdisBuffer;
  1048. UINT SendLength;
  1049. NDIS_STATUS Status;
  1050. LinkCB =
  1051. SendDesc->LinkCB;
  1052. ProtocolCB =
  1053. SendDesc->ProtocolCB;
  1054. NdisPacket =
  1055. SendDesc->NdisPacket;
  1056. NdisBuffer =
  1057. SendDesc->NdisBuffer;
  1058. BundleCB =
  1059. LinkCB->BundleCB;
  1060. NdisWanDbgOut(DBG_TRACE, DBG_SEND,
  1061. ("SendOnLink: LinkCB: 0x%p, NdisPacket: 0x%p",
  1062. LinkCB, NdisPacket));
  1063. LinkCB->OutstandingFrames++;
  1064. if (LinkCB->SendWindow == LinkCB->OutstandingFrames) {
  1065. LinkCB->SendWindowOpen = FALSE;
  1066. BundleCB->SendingLinks--;
  1067. }
  1068. PPROTOCOL_RESERVED_FROM_NDIS(NdisPacket)->SendDesc = SendDesc;
  1069. INSERT_DBG_SEND(PacketTypeNdis,
  1070. LinkCB->OpenCB,
  1071. ProtocolCB,
  1072. LinkCB,
  1073. NdisPacket);
  1074. SendLength =
  1075. SendDesc->HeaderLength + SendDesc->DataLength;
  1076. //
  1077. // Fixup the bufferlength and chain at front
  1078. //
  1079. NdisAdjustBufferLength(NdisBuffer, SendLength);
  1080. NdisRecalculatePacketCounts(NdisPacket);
  1081. //
  1082. // Do Stats
  1083. //
  1084. LinkCB->Stats.FramesTransmitted++;
  1085. BundleCB->Stats.FramesTransmitted++;
  1086. LinkCB->Stats.BytesTransmitted += SendLength;
  1087. BundleCB->Stats.BytesTransmitted += SendLength;
  1088. ReleaseBundleLock(BundleCB);
  1089. //
  1090. // If the link is up send the packet
  1091. //
  1092. NdisAcquireSpinLock(&LinkCB->Lock);
  1093. LinkCB->VcRefCount++;
  1094. if (LinkCB->State == LINK_UP) {
  1095. NdisReleaseSpinLock(&LinkCB->Lock);
  1096. if (gbSniffLink &&
  1097. (NdisWanCB.PromiscuousAdapter != NULL)) {
  1098. IndicatePromiscuousSendDesc(LinkCB, SendDesc, SEND_LINK);
  1099. }
  1100. NdisCoSendPackets(LinkCB->NdisLinkHandle,
  1101. &NdisPacket,
  1102. 1);
  1103. } else {
  1104. NdisReleaseSpinLock(&LinkCB->Lock);
  1105. ProtoCoSendComplete(NDIS_STATUS_SUCCESS,
  1106. LinkCB->hLinkHandle,
  1107. NdisPacket);
  1108. }
  1109. AcquireBundleLock(BundleCB);
  1110. NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("SendOnLink: Exit"));
  1111. return (SendLength);
  1112. }
  1113. USHORT
  1114. DoVJHeaderCompression(
  1115. PBUNDLECB BundleCB,
  1116. PNDIS_PACKET NdisPacket,
  1117. PUCHAR *CurrentBuffer,
  1118. PULONG CurrentLength,
  1119. PULONG PacketOffset
  1120. )
  1121. {
  1122. UCHAR CompType = TYPE_IP;
  1123. PUCHAR Header = *CurrentBuffer;
  1124. ULONG CopyLength;
  1125. ULONG HeaderLength;
  1126. ULONG PreCompHeaderLen = 0, PostCompHeaderLen = 0;
  1127. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1128. ASSERT(BundleCB->FramingInfo.SendFramingBits &
  1129. (SLIP_VJ_COMPRESSION | PPP_FRAMING));
  1130. NdisQueryPacket(NdisPacket,
  1131. NULL,
  1132. NULL,
  1133. NULL,
  1134. &CopyLength);
  1135. CopyLength -= *PacketOffset;
  1136. if (CopyLength > PROTOCOL_HEADER_LENGTH) {
  1137. CopyLength = PROTOCOL_HEADER_LENGTH;
  1138. }
  1139. NdisWanCopyFromPacketToBuffer(NdisPacket,
  1140. *PacketOffset,
  1141. CopyLength,
  1142. Header,
  1143. &HeaderLength);
  1144. ASSERT(CopyLength == HeaderLength);
  1145. *PacketOffset += HeaderLength;
  1146. //
  1147. // Are we compressing TCP/IP headers? There is a nasty
  1148. // hack in VJs implementation for attempting to detect
  1149. // interactive TCP/IP sessions. That is, telnet, login,
  1150. // klogin, eklogin, and ftp sessions. If detected,
  1151. // the traffic gets put on a higher TypeOfService (TOS). We do
  1152. // no such hack for RAS. Also, connection ID compression
  1153. // is negotiated, but we always don't compress it.
  1154. //
  1155. CompType =
  1156. sl_compress_tcp(&Header,
  1157. &HeaderLength,
  1158. &PreCompHeaderLen,
  1159. &PostCompHeaderLen,
  1160. BundleCB->VJCompress,
  1161. 0);
  1162. if (BundleCB->FramingInfo.SendFramingBits & SLIP_FRAMING) {
  1163. Header[0] |= CompType;
  1164. }
  1165. #if DBG
  1166. if (CompType == TYPE_COMPRESSED_TCP) {
  1167. NdisWanDbgOut(DBG_TRACE, DBG_SEND_VJ,("svj b %d a %d",PreCompHeaderLen, PostCompHeaderLen));
  1168. }
  1169. #endif
  1170. BundleCB->Stats.BytesTransmittedUncompressed +=
  1171. PreCompHeaderLen;
  1172. BundleCB->Stats.BytesTransmittedCompressed +=
  1173. PostCompHeaderLen;
  1174. if (CompType == TYPE_COMPRESSED_TCP) {
  1175. PNDIS_BUFFER MyBuffer;
  1176. //
  1177. // Source/Dest overlap so must use RtlMoveMemory
  1178. //
  1179. RtlMoveMemory(*CurrentBuffer, Header, HeaderLength);
  1180. *CurrentBuffer += HeaderLength;
  1181. *CurrentLength += HeaderLength;
  1182. return (PPP_PROTOCOL_COMPRESSED_TCP);
  1183. }
  1184. *CurrentBuffer += HeaderLength;
  1185. *CurrentLength += HeaderLength;
  1186. switch (CompType) {
  1187. case TYPE_IP:
  1188. return (PPP_PROTOCOL_IP);
  1189. case TYPE_UNCOMPRESSED_TCP:
  1190. return (PPP_PROTOCOL_UNCOMPRESSED_TCP);
  1191. default:
  1192. DbgBreakPoint();
  1193. }
  1194. return (PPP_PROTOCOL_IP);
  1195. }
  1196. VOID
  1197. DoCompressionEncryption(
  1198. PBUNDLECB BundleCB,
  1199. PHEADER_FRAMING_INFO FramingInfo,
  1200. PSEND_DESC *SendDesc
  1201. )
  1202. {
  1203. ULONG Flags = FramingInfo->Flags;
  1204. PSEND_DESC SendDesc1 = *SendDesc;
  1205. PLINKCB LinkCB = SendDesc1->LinkCB;
  1206. PUCHAR DataBuffer, DataBuffer1;
  1207. ULONG DataLength;
  1208. union {
  1209. USHORT uShort;
  1210. UCHAR uChar[2];
  1211. }CoherencyCounter;
  1212. NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("DoCompressionEncryption: Enter"));
  1213. //
  1214. // If we are compressing/encrypting, the ProtocolID
  1215. // is part of the compressed data so fix the pointer
  1216. // and the length;
  1217. //
  1218. FramingInfo->HeaderLength -=
  1219. FramingInfo->ProtocolID.Length;
  1220. SendDesc1->DataLength += FramingInfo->ProtocolID.Length;
  1221. DataBuffer = DataBuffer1 =
  1222. SendDesc1->StartBuffer + FramingInfo->HeaderLength;
  1223. DataLength =
  1224. SendDesc1->DataLength;
  1225. //
  1226. // Get the coherency counter
  1227. //
  1228. CoherencyCounter.uShort = BundleCB->SCoherencyCounter;
  1229. CoherencyCounter.uChar[1] &= 0x0F;
  1230. //
  1231. // Bump the coherency count
  1232. //
  1233. BundleCB->SCoherencyCounter++;
  1234. if (Flags & DO_COMPRESSION) {
  1235. PSEND_DESC SendDesc2;
  1236. PUCHAR DataBuffer2;
  1237. //
  1238. // We need to get the max size here to protect
  1239. // against expansion of the data
  1240. //
  1241. SendDesc2 =
  1242. NdisWanAllocateSendDesc(LinkCB, glLargeDataBufferSize);
  1243. if (SendDesc2 == NULL) {
  1244. //
  1245. // Just don't compress!
  1246. //
  1247. BundleCB->SCoherencyCounter--;
  1248. return;
  1249. }
  1250. DataBuffer2 =
  1251. SendDesc2->StartBuffer + FramingInfo->HeaderLength;
  1252. BundleCB->Stats.BytesTransmittedUncompressed += DataLength;
  1253. if (Flags & DO_FLUSH ||
  1254. Flags & DO_HISTORY_LESS) {
  1255. //
  1256. // Init the compression history table and tree
  1257. //
  1258. initsendcontext(BundleCB->SendCompressContext);
  1259. }
  1260. //
  1261. // We are doing the copy to get things into a contiguous buffer before
  1262. // compression occurs
  1263. //
  1264. CoherencyCounter.uChar[1] |=
  1265. compress(DataBuffer1,
  1266. DataBuffer2,
  1267. &DataLength,
  1268. BundleCB->SendCompressContext);
  1269. if (CoherencyCounter.uChar[1] & PACKET_FLUSHED) {
  1270. NdisWanFreeSendDesc(SendDesc2);
  1271. //
  1272. // If encryption is enabled this will force a
  1273. // reinit of the table
  1274. //
  1275. Flags |= DO_FLUSH;
  1276. } else {
  1277. //
  1278. // We compressed the packet so now the data is in
  1279. // the CopyBuffer. We need to copy the PPP header
  1280. // from DataBuffer to CopyBuffer. The header
  1281. // includes everything except for the protocolid field.
  1282. //
  1283. NdisMoveMemory(SendDesc2->StartBuffer,
  1284. SendDesc1->StartBuffer,
  1285. FramingInfo->HeaderLength);
  1286. FramingInfo->ProtocolID.Length = 0;
  1287. UpdateFramingInfo(FramingInfo, SendDesc2->StartBuffer);
  1288. SendDesc2->DataLength = DataLength;
  1289. SendDesc2->ProtocolCB = SendDesc1->ProtocolCB;
  1290. SendDesc2->OriginalPacket = SendDesc1->OriginalPacket;
  1291. SendDesc2->Class = SendDesc1->Class;
  1292. NdisWanFreeSendDesc(SendDesc1);
  1293. *SendDesc = SendDesc2;
  1294. DataBuffer = DataBuffer2;
  1295. }
  1296. BundleCB->Stats.BytesTransmittedCompressed += DataLength;
  1297. }
  1298. //
  1299. // If encryption is enabled encrypt the data in the
  1300. // buffer. Encryption is done inplace so additional
  1301. // buffers are not needed.
  1302. //
  1303. // Do data encryption
  1304. //
  1305. if (Flags & DO_ENCRYPTION) {
  1306. PUCHAR SessionKey = BundleCB->SendCryptoInfo.SessionKey;
  1307. ULONG SessionKeyLength = BundleCB->SendCryptoInfo.SessionKeyLength;
  1308. PVOID SendRC4Key = BundleCB->SendCryptoInfo.RC4Key;
  1309. //
  1310. // We may need to reinit the rc4 table
  1311. //
  1312. if ((Flags & DO_FLUSH) &&
  1313. !(Flags & DO_HISTORY_LESS)) {
  1314. rc4_key(SendRC4Key, SessionKeyLength, SessionKey);
  1315. }
  1316. //
  1317. // Mark this as being encrypted
  1318. //
  1319. CoherencyCounter.uChar[1] |= PACKET_ENCRYPTED;
  1320. //
  1321. // If we are in history-less mode we will
  1322. // change the RC4 session key for every
  1323. // packet, otherwise every 256 frames
  1324. // change the RC4 session key
  1325. //
  1326. if ((Flags & DO_HISTORY_LESS) ||
  1327. (BundleCB->SCoherencyCounter & 0xFF) == 0) {
  1328. if (Flags & DO_LEGACY_ENCRYPTION) {
  1329. //
  1330. // Simple munge for legacy encryption
  1331. //
  1332. SessionKey[3] += 1;
  1333. SessionKey[4] += 3;
  1334. SessionKey[5] += 13;
  1335. SessionKey[6] += 57;
  1336. SessionKey[7] += 19;
  1337. } else {
  1338. //
  1339. // Use SHA to get new sessionkey
  1340. //
  1341. GetNewKeyFromSHA(&BundleCB->SendCryptoInfo);
  1342. }
  1343. //
  1344. // We use rc4 to scramble and recover a new key
  1345. //
  1346. //
  1347. // Re-initialize the rc4 receive table to the
  1348. // intermediate value
  1349. //
  1350. rc4_key(SendRC4Key, SessionKeyLength, SessionKey);
  1351. //
  1352. // Scramble the existing session key
  1353. //
  1354. rc4(SendRC4Key, SessionKeyLength, SessionKey);
  1355. if (Flags & DO_40_ENCRYPTION) {
  1356. //
  1357. // If this is 40 bit encryption we need to fix
  1358. // the first 3 bytes of the key.
  1359. //
  1360. SessionKey[0] = 0xD1;
  1361. SessionKey[1] = 0x26;
  1362. SessionKey[2] = 0x9E;
  1363. } else if (Flags & DO_56_ENCRYPTION) {
  1364. //
  1365. // If this is 56 bit encryption we need to fix
  1366. // the first byte of the key.
  1367. //
  1368. SessionKey[0] = 0xD1;
  1369. }
  1370. NdisWanDbgOut(DBG_TRACE, DBG_CCP,
  1371. ("RC4 Send encryption KeyLength %d", BundleCB->SendCryptoInfo.SessionKeyLength));
  1372. NdisWanDbgOut(DBG_TRACE, DBG_CCP,
  1373. ("RC4 Send encryption Key %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x",
  1374. BundleCB->SendCryptoInfo.SessionKey[0],
  1375. BundleCB->SendCryptoInfo.SessionKey[1],
  1376. BundleCB->SendCryptoInfo.SessionKey[2],
  1377. BundleCB->SendCryptoInfo.SessionKey[3],
  1378. BundleCB->SendCryptoInfo.SessionKey[4],
  1379. BundleCB->SendCryptoInfo.SessionKey[5],
  1380. BundleCB->SendCryptoInfo.SessionKey[6],
  1381. BundleCB->SendCryptoInfo.SessionKey[7],
  1382. BundleCB->SendCryptoInfo.SessionKey[8],
  1383. BundleCB->SendCryptoInfo.SessionKey[9],
  1384. BundleCB->SendCryptoInfo.SessionKey[10],
  1385. BundleCB->SendCryptoInfo.SessionKey[11],
  1386. BundleCB->SendCryptoInfo.SessionKey[12],
  1387. BundleCB->SendCryptoInfo.SessionKey[13],
  1388. BundleCB->SendCryptoInfo.SessionKey[14],
  1389. BundleCB->SendCryptoInfo.SessionKey[15]));
  1390. //
  1391. // Re-initialize the rc4 receive table to the
  1392. // scrambled session key
  1393. //
  1394. rc4_key(SendRC4Key, SessionKeyLength, SessionKey);
  1395. }
  1396. //
  1397. // Encrypt the data
  1398. //
  1399. rc4(SendRC4Key, DataLength, DataBuffer);
  1400. }
  1401. //
  1402. // Did the last receive cause us to flush?
  1403. //
  1404. if (Flags & (DO_FLUSH | DO_HISTORY_LESS)) {
  1405. CoherencyCounter.uChar[1] |= PACKET_FLUSHED;
  1406. }
  1407. //
  1408. // Add the coherency bytes to the frame
  1409. //
  1410. AddCompressionInfo(FramingInfo, CoherencyCounter.uShort);
  1411. ASSERT(((CoherencyCounter.uShort + 1) & 0x0FFF) ==
  1412. (BundleCB->SCoherencyCounter & 0x0FFF));
  1413. NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("DoCompressionEncryption: Exit"));
  1414. }
  1415. VOID
  1416. FragmentAndQueue(
  1417. PBUNDLECB BundleCB,
  1418. PHEADER_FRAMING_INFO FramingInfo,
  1419. PSEND_DESC SendDesc,
  1420. PLIST_ENTRY LinkCBList,
  1421. ULONG SendingLinks
  1422. )
  1423. {
  1424. ULONG DataLeft;
  1425. ULONG FragmentsSent;
  1426. ULONG FragmentsLeft;
  1427. ULONG Flags;
  1428. PLINKCB LinkCB;
  1429. PUCHAR DataBuffer;
  1430. ULONG DataLength;
  1431. PPROTOCOLCB ProtocolCB;
  1432. PNDIS_PACKET NdisPacket;
  1433. PSEND_FRAG_INFO FragInfo;
  1434. INT Class;
  1435. #if DBG
  1436. ULONG MaxFragments;
  1437. #endif
  1438. Class = SendDesc->Class;
  1439. ASSERT(Class >= 0 && Class < MAX_MCML);
  1440. FragInfo =
  1441. &BundleCB->SendFragInfo[Class];
  1442. DataBuffer =
  1443. SendDesc->StartBuffer + FramingInfo->HeaderLength;
  1444. DataLeft =
  1445. DataLength = SendDesc->DataLength;
  1446. FragmentsSent = 0;
  1447. Flags = FramingInfo->Flags;
  1448. LinkCB = SendDesc->LinkCB;
  1449. ProtocolCB = SendDesc->ProtocolCB;
  1450. NdisPacket = SendDesc->OriginalPacket;
  1451. if (BundleCB->Flags & QOS_ENABLED) {
  1452. FragmentsLeft =
  1453. (DataLength/FragInfo->MaxFragSize == 0) ?
  1454. 1 : DataLength/FragInfo->MaxFragSize;
  1455. if (DataLength > FragInfo->MaxFragSize * FragmentsLeft) {
  1456. FragmentsLeft += 1;
  1457. }
  1458. if (FragmentsLeft > BundleCB->SendResources) {
  1459. FragmentsLeft = BundleCB->SendResources;
  1460. }
  1461. } else {
  1462. FragmentsLeft = SendingLinks;
  1463. }
  1464. #if DBG
  1465. MaxFragments = FragmentsLeft;
  1466. #endif
  1467. //
  1468. // For all fragments we loop fixing up the multilink header
  1469. // if multilink is on, fixing up pointers in the wanpacket,
  1470. // and queuing the wanpackets for further processing.
  1471. //
  1472. while (DataLeft) {
  1473. ULONG FragDataLength;
  1474. if (!(Flags & FIRST_FRAGMENT)) {
  1475. PLIST_ENTRY Entry;
  1476. //
  1477. // We had more than one fragment, get the next
  1478. // link to send over and a wanpacket from the
  1479. // link.
  1480. //
  1481. //
  1482. // Get a linkcb to send over
  1483. //
  1484. if (IsListEmpty(LinkCBList)) {
  1485. ULONG Count;
  1486. Count =
  1487. GetSendingLinks(BundleCB, Class, LinkCBList);
  1488. if (Count == 0) {
  1489. //
  1490. //
  1491. //
  1492. DbgPrint("NDISWAN: FragmentAndQueue LinkCBCount %d\n", Count);
  1493. continue;
  1494. }
  1495. }
  1496. Entry = RemoveHeadList(LinkCBList);
  1497. LinkCB =
  1498. CONTAINING_RECORD(Entry, LINKCB, SendLinkage);
  1499. SendDesc =
  1500. NdisWanAllocateSendDesc(LinkCB, DataLeft + 6);
  1501. if (SendDesc == NULL) {
  1502. //
  1503. //
  1504. //
  1505. InsertTailList(LinkCBList, &LinkCB->SendLinkage);
  1506. DbgPrint("NDISWAN: FragmentAndQueue SendDesc == NULL! LinkCB: 0x%p\n", LinkCB);
  1507. continue;
  1508. }
  1509. SendDesc->ProtocolCB = ProtocolCB;
  1510. SendDesc->OriginalPacket = NdisPacket;
  1511. SendDesc->Class = Class;
  1512. //
  1513. // Get new framing information and build a new
  1514. // header for the new link.
  1515. //
  1516. FramingInfo->FramingBits =
  1517. LinkCB->LinkInfo.SendFramingBits;
  1518. FramingInfo->Flags = Flags;
  1519. BuildLinkHeader(FramingInfo, SendDesc);
  1520. }
  1521. if (FragmentsLeft > 1) {
  1522. //
  1523. // Calculate the length of this fragment
  1524. //
  1525. FragDataLength = (DataLength * LinkCB->SBandwidth / 100);
  1526. if (BundleCB->Flags & QOS_ENABLED) {
  1527. FragDataLength = (FragDataLength > FragInfo->MaxFragSize) ?
  1528. FragInfo->MaxFragSize : FragDataLength;
  1529. } else {
  1530. FragDataLength = (FragDataLength < FragInfo->MinFragSize) ?
  1531. FragInfo->MinFragSize : FragDataLength;
  1532. }
  1533. if ((FragDataLength > DataLeft) ||
  1534. ((LONG)DataLeft - FragDataLength < FragInfo->MinFragSize)) {
  1535. //
  1536. // This will leave a fragment of less than min frag size
  1537. // so send all of the data
  1538. //
  1539. FragDataLength = DataLeft;
  1540. FragmentsLeft = 1;
  1541. }
  1542. } else {
  1543. //
  1544. // We either have one fragment left or this link has
  1545. // more than 85 percent of the bundle so send what
  1546. // data is left
  1547. //
  1548. FragDataLength = DataLeft;
  1549. FragmentsLeft = 1;
  1550. }
  1551. if (!(Flags & FIRST_FRAGMENT)) {
  1552. //
  1553. // Copy the data to the new buffer from the old buffer.
  1554. //
  1555. NdisMoveMemory(SendDesc->StartBuffer + FramingInfo->HeaderLength,
  1556. DataBuffer,
  1557. FragDataLength);
  1558. }
  1559. //
  1560. // Update the data pointer and the length left to send
  1561. //
  1562. DataBuffer += FragDataLength;
  1563. DataLeft -= FragDataLength;
  1564. {
  1565. UCHAR MultilinkFlags = 0;
  1566. //
  1567. // Multlink is on so create flags for this
  1568. // fragment.
  1569. //
  1570. if (Flags & FIRST_FRAGMENT) {
  1571. MultilinkFlags = MULTILINK_BEGIN_FRAME;
  1572. Flags &= ~FIRST_FRAGMENT;
  1573. }
  1574. if (FragmentsLeft == 1) {
  1575. MultilinkFlags |= MULTILINK_END_FRAME;
  1576. }
  1577. //
  1578. // Add the multilink header information and
  1579. // take care of the sequence number.
  1580. //
  1581. AddMultilinkInfo(FramingInfo,
  1582. MultilinkFlags,
  1583. FragInfo->SeqNumber,
  1584. BundleCB->SendSeqMask);
  1585. NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_SEND, ("sf %x %x %d",
  1586. FragInfo->SeqNumber, MultilinkFlags, FragDataLength));
  1587. FragInfo->SeqNumber++;
  1588. }
  1589. //
  1590. // Setup the SEND_DESC
  1591. //
  1592. SendDesc->HeaderLength = FramingInfo->HeaderLength;
  1593. SendDesc->DataLength = FragDataLength;
  1594. SendDesc->Flags |= SEND_DESC_FRAG;
  1595. //
  1596. // Queue for further processing.
  1597. //
  1598. InsertTailList(&FragInfo->FragQueue, &SendDesc->Linkage);
  1599. FragInfo->FragQueueDepth++;
  1600. FragmentsSent++;
  1601. FragmentsLeft--;
  1602. } // end of the fragment loop
  1603. ASSERT(FragmentsLeft == 0);
  1604. InterlockedExchangeAdd(&ProtocolCB->PacketQueue[Class].OutstandingFrags, (LONG)FragmentsSent);
  1605. #ifdef DBG_SENDARRAY
  1606. {
  1607. SendArray[__si] = '0' + (UCHAR)FragmentsSent;
  1608. if (++__si == MAX_BYTE_DEPTH) {
  1609. __si = 0;
  1610. }
  1611. }
  1612. #endif
  1613. //
  1614. // Get the mac reserved structure from the ndispacket. This
  1615. // is where we will keep the reference count on the packet.
  1616. //
  1617. ASSERT(((LONG)FragmentsSent > 0) && (FragmentsSent <= MaxFragments));
  1618. InterlockedExchange(&(PMINIPORT_RESERVED_FROM_NDIS(SendDesc->OriginalPacket)->RefCount), FragmentsSent);
  1619. NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("NdisPacket: 0x%p RefCount %d", SendDesc->OriginalPacket, FragmentsSent));
  1620. }
  1621. ULONG
  1622. GetSendingLinks(
  1623. PBUNDLECB BundleCB,
  1624. INT Class,
  1625. PLIST_ENTRY lcbList
  1626. )
  1627. {
  1628. ULONG SendingLinks;
  1629. PLINKCB LinkCB, StartLinkCB, LastLinkCB;
  1630. StartLinkCB = LinkCB = LastLinkCB =
  1631. BundleCB->NextLinkToXmit;
  1632. SendingLinks = 0;
  1633. //
  1634. // If this is a fragmented send...
  1635. // If QOS is enabled we just need some send resources
  1636. // If QOS is not enabled we need sending links
  1637. // If this is a non-fragmented send...
  1638. // We need sending links
  1639. //
  1640. if (LinkCB != NULL) {
  1641. if (Class == MAX_MCML) {
  1642. do {
  1643. NdisDprAcquireSpinLock(&LinkCB->Lock);
  1644. if ((LinkCB->State == LINK_UP) &&
  1645. LinkCB->LinkActive &&
  1646. LinkCB->SendWindowOpen) {
  1647. InsertTailList(lcbList, &LinkCB->SendLinkage);
  1648. REF_LINKCB(LinkCB);
  1649. SendingLinks += 1;
  1650. LastLinkCB = LinkCB;
  1651. }
  1652. NdisDprReleaseSpinLock(&LinkCB->Lock);
  1653. LinkCB = (PLINKCB)LinkCB->Linkage.Flink;
  1654. if ((PVOID)LinkCB == (PVOID)&BundleCB->LinkCBList) {
  1655. LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
  1656. }
  1657. } while (LinkCB != StartLinkCB);
  1658. } else {
  1659. if (BundleCB->Flags& QOS_ENABLED) {
  1660. do {
  1661. NdisDprAcquireSpinLock(&LinkCB->Lock);
  1662. if ((LinkCB->State == LINK_UP) &&
  1663. LinkCB->LinkActive &&
  1664. (LinkCB->SendResources != 0)) {
  1665. InsertTailList(lcbList, &LinkCB->SendLinkage);
  1666. REF_LINKCB(LinkCB);
  1667. SendingLinks += 1;
  1668. LastLinkCB = LinkCB;
  1669. }
  1670. NdisDprReleaseSpinLock(&LinkCB->Lock);
  1671. LinkCB = (PLINKCB)LinkCB->Linkage.Flink;
  1672. if ((PVOID)LinkCB == (PVOID)&BundleCB->LinkCBList) {
  1673. LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
  1674. }
  1675. } while (LinkCB != StartLinkCB);
  1676. } else {
  1677. do {
  1678. NdisDprAcquireSpinLock(&LinkCB->Lock);
  1679. if ((LinkCB->State == LINK_UP) &&
  1680. LinkCB->LinkActive &&
  1681. LinkCB->SendWindowOpen) {
  1682. InsertTailList(lcbList, &LinkCB->SendLinkage);
  1683. REF_LINKCB(LinkCB);
  1684. SendingLinks += 1;
  1685. LastLinkCB = LinkCB;
  1686. }
  1687. NdisDprReleaseSpinLock(&LinkCB->Lock);
  1688. LinkCB = (PLINKCB)LinkCB->Linkage.Flink;
  1689. if ((PVOID)LinkCB == (PVOID)&BundleCB->LinkCBList) {
  1690. LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
  1691. }
  1692. } while (LinkCB != StartLinkCB);
  1693. }
  1694. }
  1695. BundleCB->NextLinkToXmit =
  1696. (LastLinkCB->Linkage.Flink == &BundleCB->LinkCBList) ?
  1697. (PLINKCB)BundleCB->LinkCBList.Flink :
  1698. (PLINKCB)LastLinkCB->Linkage.Flink;
  1699. }
  1700. #ifdef DBG_SENDARRAY
  1701. {
  1702. if (SendingLinks == 0) {
  1703. SendArray[__si] = 'g';
  1704. } else {
  1705. SendArray[__si] = 'G';
  1706. }
  1707. if (++__si == MAX_BYTE_DEPTH) {
  1708. __si = 0;
  1709. }
  1710. }
  1711. #endif
  1712. return (SendingLinks);
  1713. }
  1714. VOID
  1715. GetNextProtocol(
  1716. PBUNDLECB BundleCB,
  1717. PPROTOCOLCB *ProtocolCB,
  1718. PULONG SendMask
  1719. )
  1720. {
  1721. PLIST_ENTRY ppcblist;
  1722. PPROTOCOLCB ppcb;
  1723. ULONG mask;
  1724. ULONG i;
  1725. BOOLEAN Found;
  1726. *ProtocolCB = NULL;
  1727. mask = *SendMask;
  1728. *SendMask = 0;
  1729. ppcb = BundleCB->NextProtocol;
  1730. if (ppcb == NULL) {
  1731. return;
  1732. }
  1733. //
  1734. // There is a window where we could have set the initial
  1735. // send mask and had a protocol removed without clearing
  1736. // it's send bit. If we 'and' the temp mask with the
  1737. // bundle's mask we should clear out any bits that are
  1738. // left dangling.
  1739. //
  1740. mask &= BundleCB->SendMask;
  1741. //
  1742. // Starting with the next flagged protocol
  1743. // see if it can send. If not clear its
  1744. // sendbit from the mask and go to the next.
  1745. // If none can send mask will be 0 and
  1746. // protocol will be NULL. We know that there
  1747. // are only ulnumberofroutes in table so only
  1748. // look for that many.
  1749. //
  1750. i = BundleCB->ulNumberOfRoutes;
  1751. Found = FALSE;
  1752. do {
  1753. if (ppcb->State == PROTOCOL_ROUTED) {
  1754. *ProtocolCB = ppcb;
  1755. Found = TRUE;
  1756. } else {
  1757. mask &= ~ppcb->SendMaskBit;
  1758. }
  1759. ppcb = (PPROTOCOLCB)ppcb->Linkage.Flink;
  1760. if ((PVOID)ppcb == (PVOID)&BundleCB->ProtocolCBList) {
  1761. ppcb = (PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
  1762. }
  1763. if (Found) {
  1764. BundleCB->NextProtocol = ppcb;
  1765. break;
  1766. }
  1767. } while ( --i );
  1768. if (*ProtocolCB != NULL) {
  1769. *SendMask = mask;
  1770. }
  1771. }
  1772. NDIS_STATUS
  1773. BuildIoPacket(
  1774. IN PLINKCB LinkCB,
  1775. IN PBUNDLECB BundleCB,
  1776. IN PNDISWAN_IO_PACKET pWanIoPacket,
  1777. IN BOOLEAN SendImmediate
  1778. )
  1779. /*++
  1780. Routine Name:
  1781. Routine Description:
  1782. Arguments:
  1783. Return Values:
  1784. --*/
  1785. {
  1786. NDIS_STATUS Status = NDIS_STATUS_RESOURCES;
  1787. ULONG Stage = 0;
  1788. ULONG DataLength;
  1789. PUCHAR DataBuffer, pSrcAddr, pDestAddr;
  1790. PNDIS_PACKET NdisPacket;
  1791. PNDIS_BUFFER NdisBuffer;
  1792. PPROTOCOLCB IoProtocolCB;
  1793. PSEND_DESC SendDesc;
  1794. UCHAR SendHeader[] = {' ', 'S', 'E', 'N', 'D', 0xFF};
  1795. NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("BuildIoPacket: Enter!"));
  1796. //
  1797. // Some time in the future this should be redone so that
  1798. // there is a pool of packets and buffers attached to a
  1799. // BundleCB. This pool could be grown and shrunk as needed
  1800. // but some minimum number would live for the lifetime of
  1801. // the BundleCB.
  1802. //
  1803. // Allocate needed resources
  1804. //
  1805. {
  1806. ULONG SizeNeeded;
  1807. //
  1808. // Need max of 18 bytes; 4 bytes for ppp/llc header and
  1809. // 14 for MAC address
  1810. //
  1811. SizeNeeded = 18;
  1812. //
  1813. // The header will either be given to us or
  1814. // it will be added by us (ethernet mac header)
  1815. //
  1816. SizeNeeded += (pWanIoPacket->usHeaderSize > 0) ?
  1817. pWanIoPacket->usHeaderSize : MAC_HEADER_LENGTH;
  1818. //
  1819. // Amount of data we need to send
  1820. //
  1821. SizeNeeded += pWanIoPacket->usPacketSize;
  1822. Status =
  1823. AllocateIoNdisPacket(SizeNeeded,
  1824. &NdisPacket,
  1825. &NdisBuffer,
  1826. &DataBuffer);
  1827. if (Status != NDIS_STATUS_SUCCESS) {
  1828. NdisWanDbgOut(DBG_FAILURE, DBG_SEND,
  1829. ("BuildIoPacket: Error Allocating IoNdisPacket!"));
  1830. DEREF_LINKCB(LinkCB);
  1831. return (NDIS_STATUS_RESOURCES);
  1832. }
  1833. }
  1834. PPROTOCOL_RESERVED_FROM_NDIS(NdisPacket)->LinkCB = LinkCB;
  1835. //
  1836. // We only support ethernet headers right now so the supplied header
  1837. // either has to be ethernet or none at all!
  1838. //
  1839. pDestAddr = &DataBuffer[0];
  1840. pSrcAddr = &DataBuffer[6];
  1841. //
  1842. // If no header build a header
  1843. //
  1844. if (pWanIoPacket->usHeaderSize == 0) {
  1845. //
  1846. // Header will look like " S XXYYYY" where
  1847. // XX is the ProtocolCB index and YYYY is the
  1848. // BundleCB index. Both the Src and Dst addresses
  1849. // look the same.
  1850. //
  1851. NdisMoveMemory(pDestAddr,
  1852. SendHeader,
  1853. sizeof(SendHeader));
  1854. NdisMoveMemory(pSrcAddr,
  1855. SendHeader,
  1856. sizeof(SendHeader));
  1857. //
  1858. // Fill the BundleCB Index for the Src and Dest Address
  1859. //
  1860. pDestAddr[5] = pSrcAddr[5] =
  1861. (UCHAR)LinkCB->hLinkHandle;
  1862. DataLength = 12;
  1863. } else {
  1864. //
  1865. // Header supplied so go ahead and move it.
  1866. //
  1867. NdisMoveMemory(pDestAddr,
  1868. pWanIoPacket->PacketData,
  1869. pWanIoPacket->usHeaderSize);
  1870. DataLength = pWanIoPacket->usHeaderSize;
  1871. }
  1872. //
  1873. // Copy the data to the buffer
  1874. //
  1875. NdisMoveMemory(&DataBuffer[12],
  1876. &pWanIoPacket->PacketData[pWanIoPacket->usHeaderSize],
  1877. pWanIoPacket->usPacketSize);
  1878. DataLength += pWanIoPacket->usPacketSize;
  1879. //
  1880. // Adjust buffer length and chain buffer to ndis packet
  1881. //
  1882. NdisAdjustBufferLength(NdisBuffer, DataLength);
  1883. NdisRecalculatePacketCounts(NdisPacket);
  1884. //
  1885. // Queue the packet on the bundlecb
  1886. //
  1887. IoProtocolCB = BundleCB->IoProtocolCB;
  1888. ASSERT(IoProtocolCB != NULL);
  1889. if (SendImmediate) {
  1890. InsertHeadPacketQueue(&IoProtocolCB->PacketQueue[MAX_MCML],
  1891. NdisPacket, DataLength);
  1892. } else {
  1893. InsertTailPacketQueue(&IoProtocolCB->PacketQueue[MAX_MCML],
  1894. NdisPacket, DataLength);
  1895. }
  1896. InterlockedIncrement(&IoProtocolCB->OutstandingFrames);
  1897. //
  1898. // Try to send
  1899. //
  1900. // Called with lock held and returns with
  1901. // lock released
  1902. //
  1903. SendPacketOnBundle(BundleCB);
  1904. AcquireBundleLock(BundleCB);
  1905. NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("BuildIoPacket: Exit\n"));
  1906. return (NDIS_STATUS_SUCCESS);
  1907. }
  1908. VOID
  1909. BuildLinkHeader(
  1910. PHEADER_FRAMING_INFO FramingInfo,
  1911. PSEND_DESC SendDesc
  1912. )
  1913. /*++
  1914. Routine Name:
  1915. Routine Description:
  1916. Arguments:
  1917. Return Values:
  1918. --*/
  1919. {
  1920. ULONG LinkFraming = FramingInfo->FramingBits;
  1921. ULONG Flags = FramingInfo->Flags;
  1922. PUCHAR CurrentPointer = SendDesc->StartBuffer;
  1923. FramingInfo->HeaderLength =
  1924. FramingInfo->AddressControl.Length =
  1925. FramingInfo->Multilink.Length =
  1926. FramingInfo->Compression.Length =
  1927. FramingInfo->ProtocolID.Length = 0;
  1928. if (LinkFraming & PPP_FRAMING) {
  1929. if (!(LinkFraming & PPP_COMPRESS_ADDRESS_CONTROL)) {
  1930. //
  1931. // If there is no address/control compression
  1932. // we need a pointer and a length
  1933. //
  1934. if (LinkFraming & LLC_ENCAPSULATION) {
  1935. FramingInfo->AddressControl.Pointer = CurrentPointer;
  1936. *CurrentPointer++ = 0xFE;
  1937. *CurrentPointer++ = 0xFE;
  1938. *CurrentPointer++ = 0x03;
  1939. *CurrentPointer++ = 0xCF;
  1940. FramingInfo->AddressControl.Length = 4;
  1941. FramingInfo->HeaderLength += FramingInfo->AddressControl.Length;
  1942. } else {
  1943. FramingInfo->AddressControl.Pointer = CurrentPointer;
  1944. *CurrentPointer++ = 0xFF;
  1945. *CurrentPointer++ = 0x03;
  1946. FramingInfo->AddressControl.Length = 2;
  1947. FramingInfo->HeaderLength += FramingInfo->AddressControl.Length;
  1948. }
  1949. }
  1950. if (!(Flags & IO_PROTOCOLID)) {
  1951. //
  1952. // If this is not from our private I/O interface we will
  1953. // build the rest of the header.
  1954. //
  1955. if ((Flags & DO_MULTILINK) && (LinkFraming & PPP_MULTILINK_FRAMING)) {
  1956. //
  1957. // We are doing multilink so we need a pointer
  1958. // and a length
  1959. //
  1960. FramingInfo->Multilink.Pointer = CurrentPointer;
  1961. if (!(LinkFraming & PPP_COMPRESS_PROTOCOL_FIELD)) {
  1962. //
  1963. // No protocol compression
  1964. //
  1965. *CurrentPointer++ = 0x00;
  1966. FramingInfo->Multilink.Length++;
  1967. }
  1968. *CurrentPointer++ = 0x3D;
  1969. FramingInfo->Multilink.Length++;
  1970. if (!(LinkFraming & PPP_SHORT_SEQUENCE_HDR_FORMAT)) {
  1971. //
  1972. // We are using long sequence number
  1973. //
  1974. FramingInfo->Multilink.Length += 2;
  1975. CurrentPointer += 2;
  1976. }
  1977. FramingInfo->Multilink.Length += 2;
  1978. CurrentPointer += 2;
  1979. FramingInfo->HeaderLength += FramingInfo->Multilink.Length;
  1980. }
  1981. if (Flags & FIRST_FRAGMENT) {
  1982. if (Flags & (DO_COMPRESSION | DO_ENCRYPTION)) {
  1983. //
  1984. // We are doing compression/encryption so we need
  1985. // a pointer and a length
  1986. //
  1987. FramingInfo->Compression.Pointer = CurrentPointer;
  1988. //
  1989. // It appears that legacy ras (< NT 4.0) requires that
  1990. // the PPP protocol field in a compressed packet not
  1991. // be compressed, ie has to have the leading 0x00
  1992. //
  1993. if (!(LinkFraming & PPP_COMPRESS_PROTOCOL_FIELD)) {
  1994. //
  1995. // No protocol compression
  1996. //
  1997. *CurrentPointer++ = 0x00;
  1998. FramingInfo->Compression.Length++;
  1999. }
  2000. *CurrentPointer++ = 0xFD;
  2001. FramingInfo->Compression.Length++;
  2002. //
  2003. // Add coherency bytes
  2004. //
  2005. FramingInfo->Compression.Length += 2;
  2006. CurrentPointer += 2;
  2007. FramingInfo->HeaderLength += FramingInfo->Compression.Length;
  2008. }
  2009. FramingInfo->ProtocolID.Pointer = CurrentPointer;
  2010. if (!(LinkFraming & PPP_COMPRESS_PROTOCOL_FIELD) ||
  2011. (Flags & (DO_COMPRESSION | DO_ENCRYPTION))) {
  2012. FramingInfo->ProtocolID.Length++;
  2013. CurrentPointer++;
  2014. }
  2015. FramingInfo->ProtocolID.Length++;
  2016. FramingInfo->HeaderLength += FramingInfo->ProtocolID.Length;
  2017. CurrentPointer++;
  2018. }
  2019. }
  2020. } else if ((LinkFraming & RAS_FRAMING)) {
  2021. //
  2022. // If this is old ras framing:
  2023. //
  2024. // Alter the framing so that 0xFF 0x03 is not added
  2025. // and that the first byte is 0xFD not 0x00 0xFD
  2026. //
  2027. // So basically, a RAS compression looks like
  2028. // <0xFD> <2 BYTE COHERENCY> <NBF DATA FIELD>
  2029. //
  2030. // Whereas uncompressed looks like
  2031. // <NBF DATA FIELD> which always starts with 0xF0
  2032. //
  2033. // If this is ppp framing:
  2034. //
  2035. // A compressed frame will look like (before address/control
  2036. // - multilink is added)
  2037. // <0x00> <0xFD> <2 Byte Coherency> <Compressed Data>
  2038. //
  2039. if (Flags & (DO_COMPRESSION | DO_ENCRYPTION)) {
  2040. FramingInfo->Compression.Pointer = CurrentPointer;
  2041. *CurrentPointer++ = 0xFD;
  2042. FramingInfo->Compression.Length++;
  2043. //
  2044. // Coherency bytes
  2045. //
  2046. FramingInfo->Compression.Length += 2;
  2047. CurrentPointer += 2;
  2048. FramingInfo->HeaderLength += FramingInfo->Compression.Length;
  2049. }
  2050. }
  2051. }
  2052. VOID
  2053. IndicatePromiscuousSendPacket(
  2054. PLINKCB LinkCB,
  2055. PNDIS_PACKET NdisPacket
  2056. )
  2057. {
  2058. PNDIS_BUFFER NdisBuffer;
  2059. PNDIS_PACKET LocalNdisPacket;
  2060. NDIS_STATUS Status;
  2061. PRECV_DESC RecvDesc;
  2062. PBUNDLECB BundleCB = LinkCB->BundleCB;
  2063. KIRQL OldIrql;
  2064. PMINIPORTCB Adapter;
  2065. ULONG PacketLength;
  2066. NdisAcquireSpinLock(&NdisWanCB.Lock);
  2067. Adapter = NdisWanCB.PromiscuousAdapter;
  2068. NdisReleaseSpinLock(&NdisWanCB.Lock);
  2069. if (Adapter == NULL) {
  2070. return;
  2071. }
  2072. NdisQueryPacket(NdisPacket,
  2073. NULL,
  2074. NULL,
  2075. NULL,
  2076. &PacketLength);
  2077. RecvDesc =
  2078. NdisWanAllocateRecvDesc(PacketLength);
  2079. if (RecvDesc == NULL) {
  2080. return;
  2081. }
  2082. //
  2083. // Get an ndis packet
  2084. //
  2085. LocalNdisPacket =
  2086. RecvDesc->NdisPacket;
  2087. NdisWanCopyFromPacketToBuffer(NdisPacket,
  2088. 0,
  2089. 0xFFFFFFFF,
  2090. RecvDesc->StartBuffer,
  2091. &RecvDesc->CurrentLength);
  2092. PPROTOCOL_RESERVED_FROM_NDIS(LocalNdisPacket)->RecvDesc = RecvDesc;
  2093. //
  2094. // Attach the buffers
  2095. //
  2096. NdisAdjustBufferLength(RecvDesc->NdisBuffer,
  2097. RecvDesc->CurrentLength);
  2098. NdisRecalculatePacketCounts(LocalNdisPacket);
  2099. ReleaseBundleLock(BundleCB);
  2100. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  2101. NDIS_SET_PACKET_STATUS(LocalNdisPacket, NDIS_STATUS_RESOURCES);
  2102. INSERT_DBG_RECV(PacketTypeNdis,
  2103. Adapter,
  2104. NULL,
  2105. LinkCB,
  2106. LocalNdisPacket);
  2107. //
  2108. // Indicate the packet
  2109. // This assumes that bloodhound is always a legacy transport
  2110. //
  2111. NdisMIndicateReceivePacket(Adapter->MiniportHandle,
  2112. &LocalNdisPacket,
  2113. 1);
  2114. KeLowerIrql(OldIrql);
  2115. Status = NDIS_GET_PACKET_STATUS(LocalNdisPacket);
  2116. ASSERT(Status == NDIS_STATUS_RESOURCES);
  2117. REMOVE_DBG_RECV(PacketTypeNdis, Adapter, LocalNdisPacket);
  2118. {
  2119. PNDIS_BUFFER NdisBuffer;
  2120. NdisWanFreeRecvDesc(RecvDesc);
  2121. }
  2122. AcquireBundleLock(BundleCB);
  2123. }
  2124. VOID
  2125. IndicatePromiscuousSendDesc(
  2126. PLINKCB LinkCB,
  2127. PSEND_DESC SendDesc,
  2128. SEND_TYPE SendType
  2129. )
  2130. {
  2131. UCHAR Header1[] = {' ', 'W', 'A', 'N', 'S', 0xFF, ' ', 'W', 'A', 'N', 'S', 0xFF};
  2132. PUCHAR HeaderBuffer, DataBuffer;
  2133. ULONG HeaderLength, DataLength;
  2134. PNDIS_BUFFER NdisBuffer;
  2135. PNDIS_PACKET NdisPacket;
  2136. NDIS_STATUS Status;
  2137. PBUNDLECB BundleCB = LinkCB->BundleCB;
  2138. PRECV_DESC RecvDesc;
  2139. KIRQL OldIrql;
  2140. PMINIPORTCB Adapter;
  2141. AcquireBundleLock(BundleCB);
  2142. NdisAcquireSpinLock(&NdisWanCB.Lock);
  2143. Adapter = NdisWanCB.PromiscuousAdapter;
  2144. NdisReleaseSpinLock(&NdisWanCB.Lock);
  2145. if (Adapter == NULL) {
  2146. ReleaseBundleLock(BundleCB);
  2147. return;
  2148. }
  2149. DataLength =
  2150. SendDesc->HeaderLength + SendDesc->DataLength;
  2151. RecvDesc =
  2152. NdisWanAllocateRecvDesc(DataLength + MAC_HEADER_LENGTH);
  2153. if (RecvDesc == NULL) {
  2154. ReleaseBundleLock(BundleCB);
  2155. return;
  2156. }
  2157. HeaderBuffer = RecvDesc->StartBuffer;
  2158. HeaderLength = 0;
  2159. switch (SendType) {
  2160. case SEND_LINK:
  2161. NdisMoveMemory(HeaderBuffer, Header1, sizeof(Header1));
  2162. HeaderBuffer[5] =
  2163. HeaderBuffer[11] = (UCHAR)LinkCB->hLinkHandle;
  2164. HeaderBuffer[12] = (UCHAR)(DataLength >> 8);
  2165. HeaderBuffer[13] = (UCHAR)DataLength;
  2166. HeaderLength = MAC_HEADER_LENGTH;
  2167. break;
  2168. case SEND_BUNDLE_PPP:
  2169. case SEND_BUNDLE_DATA:
  2170. break;
  2171. }
  2172. DataBuffer = HeaderBuffer + HeaderLength;
  2173. NdisMoveMemory(DataBuffer,
  2174. SendDesc->StartBuffer,
  2175. DataLength);
  2176. RecvDesc->CurrentBuffer = HeaderBuffer;
  2177. RecvDesc->CurrentLength = HeaderLength + DataLength;
  2178. if (RecvDesc->CurrentLength > 1514) {
  2179. RecvDesc->CurrentLength = 1514;
  2180. }
  2181. //
  2182. // Get an ndis packet
  2183. //
  2184. NdisPacket =
  2185. RecvDesc->NdisPacket;
  2186. PPROTOCOL_RESERVED_FROM_NDIS(NdisPacket)->RecvDesc = RecvDesc;
  2187. //
  2188. // Attach the buffers
  2189. //
  2190. NdisAdjustBufferLength(RecvDesc->NdisBuffer,
  2191. RecvDesc->CurrentLength);
  2192. NdisRecalculatePacketCounts(NdisPacket);
  2193. ReleaseBundleLock(BundleCB);
  2194. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  2195. NDIS_SET_PACKET_STATUS(NdisPacket, NDIS_STATUS_RESOURCES);
  2196. INSERT_DBG_RECV(PacketTypeNdis, Adapter, NULL, LinkCB, NdisPacket);
  2197. //
  2198. // Indicate the packet
  2199. // This assumes that bloodhound is always a legacy transport
  2200. //
  2201. NdisMIndicateReceivePacket(Adapter->MiniportHandle,
  2202. &NdisPacket,
  2203. 1);
  2204. KeLowerIrql(OldIrql);
  2205. Status = NDIS_GET_PACKET_STATUS(NdisPacket);
  2206. ASSERT(Status == NDIS_STATUS_RESOURCES);
  2207. REMOVE_DBG_RECV(PacketTypeNdis, Adapter, NdisPacket);
  2208. {
  2209. PNDIS_BUFFER NdisBuffer;
  2210. NdisWanFreeRecvDesc(RecvDesc);
  2211. }
  2212. }
  2213. VOID
  2214. CompleteNdisPacket(
  2215. PMINIPORTCB MiniportCB,
  2216. PPROTOCOLCB ProtocolCB,
  2217. PNDIS_PACKET NdisPacket
  2218. )
  2219. {
  2220. PBUNDLECB BundleCB = ProtocolCB->BundleCB;
  2221. PCM_VCCB CmVcCB;
  2222. InterlockedDecrement(&ProtocolCB->OutstandingFrames);
  2223. if (ProtocolCB->ProtocolType == PROTOCOL_PRIVATE_IO) {
  2224. //
  2225. // If this is a packet that we created we need to free
  2226. // the resources
  2227. //
  2228. FreeIoNdisPacket(NdisPacket);
  2229. return;
  2230. }
  2231. AcquireBundleLock(BundleCB);
  2232. DEREF_PROTOCOLCB(ProtocolCB);
  2233. ReleaseBundleLock(BundleCB);
  2234. REMOVE_DBG_SEND(PacketTypeNdis, MiniportCB, NdisPacket);
  2235. CmVcCB =
  2236. PMINIPORT_RESERVED_FROM_NDIS(NdisPacket)->CmVcCB;
  2237. if (CmVcCB != NULL) {
  2238. NdisMCoSendComplete(NDIS_STATUS_SUCCESS,
  2239. CmVcCB->NdisVcHandle,
  2240. NdisPacket);
  2241. DEREF_CMVCCB(CmVcCB);
  2242. } else {
  2243. NdisMSendComplete(MiniportCB->MiniportHandle,
  2244. NdisPacket,
  2245. NDIS_STATUS_SUCCESS);
  2246. }
  2247. //
  2248. // Increment global count
  2249. //
  2250. NdisWanInterlockedInc(&glSendCompleteCount);
  2251. }
  2252. #if DBG
  2253. VOID
  2254. InsertDbgPacket(
  2255. PDBG_PKT_CONTEXT DbgContext
  2256. )
  2257. {
  2258. PDBG_PACKET DbgPacket, temp;
  2259. PBUNDLECB BundleCB = DbgContext->BundleCB;
  2260. PPROTOCOLCB ProtocolCB = DbgContext->ProtocolCB;
  2261. PLINKCB LinkCB = DbgContext->LinkCB;
  2262. DbgPacket =
  2263. NdisAllocateFromNPagedLookasideList(&DbgPacketDescList);
  2264. if (DbgPacket == NULL) {
  2265. return;
  2266. }
  2267. DbgPacket->Packet = DbgContext->Packet;
  2268. DbgPacket->PacketType = DbgContext->PacketType;
  2269. DbgPacket->BundleCB = BundleCB;
  2270. if (BundleCB) {
  2271. DbgPacket->BundleState = BundleCB->State;
  2272. DbgPacket->BundleFlags = BundleCB->Flags;
  2273. }
  2274. DbgPacket->ProtocolCB = ProtocolCB;
  2275. if (ProtocolCB) {
  2276. DbgPacket->ProtocolState = ProtocolCB->State;
  2277. }
  2278. DbgPacket->LinkCB = LinkCB;
  2279. if (LinkCB) {
  2280. DbgPacket->LinkState = LinkCB->State;
  2281. }
  2282. DbgPacket->SendCount = glSendCount;
  2283. NdisAcquireSpinLock(DbgContext->ListLock);
  2284. temp = (PDBG_PACKET)DbgContext->ListHead->Flink;
  2285. while ((PVOID)temp != (PVOID)DbgContext->ListHead) {
  2286. if (temp->Packet == DbgPacket->Packet) {
  2287. DbgPrint("NDISWAN: Packet on list twice l %x desc %x pkt %x\n",
  2288. DbgContext->ListHead, DbgPacket, DbgPacket->Packet);
  2289. DbgBreakPoint();
  2290. }
  2291. temp = (PDBG_PACKET)temp->Linkage.Flink;
  2292. }
  2293. InsertTailList(DbgContext->ListHead, &DbgPacket->Linkage);
  2294. NdisReleaseSpinLock(DbgContext->ListLock);
  2295. }
  2296. BOOLEAN
  2297. RemoveDbgPacket(
  2298. PDBG_PKT_CONTEXT DbgContext
  2299. )
  2300. {
  2301. PDBG_PACKET DbgPacket = NULL;
  2302. BOOLEAN Found = FALSE;
  2303. NdisAcquireSpinLock(DbgContext->ListLock);
  2304. if (!IsListEmpty(DbgContext->ListHead)) {
  2305. for (DbgPacket = (PDBG_PACKET)DbgContext->ListHead->Flink;
  2306. (PVOID)DbgPacket != (PVOID)DbgContext->ListHead;
  2307. DbgPacket = (PDBG_PACKET)DbgPacket->Linkage.Flink) {
  2308. if (DbgPacket->Packet == DbgContext->Packet) {
  2309. RemoveEntryList(&DbgPacket->Linkage);
  2310. NdisFreeToNPagedLookasideList(&DbgPacketDescList,
  2311. DbgPacket);
  2312. Found = TRUE;
  2313. break;
  2314. }
  2315. }
  2316. }
  2317. ASSERT(Found == TRUE);
  2318. NdisReleaseSpinLock(DbgContext->ListLock);
  2319. return (Found);
  2320. }
  2321. #endif