Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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