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.

3101 lines
81 KiB

  1. // Copyright (c) 1997, Microsoft Corporation, all rights reserved
  2. //
  3. // send.c
  4. // RAS L2TP WAN mini-port/call-manager driver
  5. // Send routines
  6. //
  7. // 01/07/97 Steve Cobb
  8. #include "l2tpp.h"
  9. #ifdef PSDEBUG
  10. // List of all allocated PAYLOADSENT contexts and the lock that protects the
  11. // list. (for debug purposes only)
  12. //
  13. NDIS_SPIN_LOCK g_lockDebugPs;
  14. LIST_ENTRY g_listDebugPs;
  15. #endif
  16. // Debug counts of client oddities that should not be happening.
  17. //
  18. ULONG g_ulSendZlbWithoutHostRoute = 0;
  19. // Callback to add AVPs to an outgoing control message. 'PTunnel' is the
  20. // tunnel control block. 'PVc' is the VC control block for call control
  21. // messages or NULL for tunnel control messages. 'ulArg1', 'ulArg2', and
  22. // 'pvArg3' are caller's arguments as passed for SendControl. 'PAvpBuffer' is
  23. // the address of the buffer to receive the built AVPs. '*PulAvpLength' is
  24. // set to the length of the built AVPs.
  25. //
  26. typedef
  27. VOID
  28. (*PBUILDAVPS)(
  29. IN TUNNELCB* pTunnel,
  30. IN VCCB* pVc,
  31. IN ULONG ulArg1,
  32. IN ULONG ulArg2,
  33. IN PVOID pvArg3,
  34. IN OUT CHAR* pAvpBuffer,
  35. OUT ULONG* pulAvpLength );
  36. //-----------------------------------------------------------------------------
  37. // Local prototypes (alphabetically)
  38. //-----------------------------------------------------------------------------
  39. USHORT
  40. BuildAvpAch(
  41. IN USHORT usAttribute,
  42. IN BOOLEAN fMandatory,
  43. IN CHAR* pszValue,
  44. IN USHORT usValueLength,
  45. OUT CHAR* pAvp );
  46. USHORT
  47. BuildAvpAul(
  48. IN USHORT usAttribute,
  49. IN BOOLEAN fMandatory,
  50. IN UNALIGNED ULONG* pulValue,
  51. IN USHORT usValues,
  52. OUT CHAR* pAvp );
  53. USHORT
  54. BuildAvpFlag(
  55. IN USHORT usAttribute,
  56. IN BOOLEAN fMandatory,
  57. OUT CHAR* pAvp );
  58. USHORT
  59. BuildAvpUl(
  60. IN USHORT usAttribute,
  61. IN BOOLEAN fMandatory,
  62. IN ULONG ulValue,
  63. OUT CHAR* pAvp );
  64. USHORT
  65. BuildAvpUs(
  66. IN USHORT usAttribute,
  67. IN BOOLEAN fMandatory,
  68. IN USHORT usValue,
  69. OUT CHAR* pAvp );
  70. USHORT
  71. BuildAvp2UsAndAch(
  72. IN USHORT usAttribute,
  73. IN BOOLEAN fMandatory,
  74. IN USHORT usValue1,
  75. IN USHORT usValue2,
  76. IN CHAR* pszValue,
  77. IN USHORT usValueLength,
  78. OUT CHAR* pAvp );
  79. VOID
  80. BuildCdnAvps(
  81. IN TUNNELCB* pTunnel,
  82. IN VCCB* pVc,
  83. IN ULONG ulArg1,
  84. IN ULONG ulArg2,
  85. IN PVOID pvArg3,
  86. IN OUT CHAR* pAvpBuffer,
  87. OUT ULONG* pulAvpLength );
  88. VOID
  89. BuildHelloAvps(
  90. IN TUNNELCB* pTunnel,
  91. IN VCCB* pVc,
  92. IN ULONG ulArg1,
  93. IN ULONG ulArg2,
  94. IN PVOID pvArg3,
  95. IN OUT CHAR* pAvpBuffer,
  96. OUT ULONG* pulAvpLength );
  97. VOID
  98. BuildIccnAvps(
  99. IN TUNNELCB* pTunnel,
  100. IN VCCB* pVc,
  101. IN ULONG ulArg1,
  102. IN ULONG ulArg2,
  103. IN PVOID pvArg3,
  104. IN OUT CHAR* pAvpBuffer,
  105. OUT ULONG* pulAvpLength );
  106. VOID
  107. BuildIcrpAvps(
  108. IN TUNNELCB* pTunnel,
  109. IN VCCB* pVc,
  110. IN ULONG ulArg1,
  111. IN ULONG ulArg2,
  112. IN PVOID pvArg3,
  113. IN OUT CHAR* pAvpBuffer,
  114. OUT ULONG* pulAvpLength );
  115. VOID
  116. BuildIcrqAvps(
  117. IN TUNNELCB* pTunnel,
  118. IN VCCB* pVc,
  119. IN ULONG ulArg1,
  120. IN ULONG ulArg2,
  121. IN PVOID pvArg3,
  122. IN OUT CHAR* pAvpBuffer,
  123. OUT ULONG* pulAvpLength );
  124. ULONG
  125. BuildL2tpHeader(
  126. IN OUT CHAR* pBuffer,
  127. IN BOOLEAN fControl,
  128. IN BOOLEAN fReset,
  129. IN USHORT* pusTunnelId,
  130. IN USHORT* pusCallId,
  131. IN USHORT* pusNs,
  132. IN USHORT usNr );
  133. VOID
  134. BuildOccnAvps(
  135. IN TUNNELCB* pTunnel,
  136. IN VCCB* pVc,
  137. IN ULONG ulArg1,
  138. IN ULONG ulArg2,
  139. IN PVOID pvArg3,
  140. IN OUT CHAR* pAvpBuffer,
  141. OUT ULONG* pulAvpLength );
  142. VOID
  143. BuildOcrpAvps(
  144. IN TUNNELCB* pTunnel,
  145. IN VCCB* pVc,
  146. IN ULONG ulArg1,
  147. IN ULONG ulArg2,
  148. IN PVOID pvArg3,
  149. IN OUT CHAR* pAvpBuffer,
  150. OUT ULONG* pulAvpLength );
  151. VOID
  152. BuildOcrqAvps(
  153. IN TUNNELCB* pTunnel,
  154. IN VCCB* pVc,
  155. IN ULONG ulArg1,
  156. IN ULONG ulArg2,
  157. IN PVOID pvArg3,
  158. IN OUT CHAR* pAvpBuffer,
  159. OUT ULONG* pulAvpLength );
  160. VOID
  161. BuildScccnAvps(
  162. IN TUNNELCB* pTunnel,
  163. IN VCCB* pVc,
  164. IN ULONG ulArg1,
  165. IN ULONG ulArg2,
  166. IN PVOID pvArg3,
  167. IN OUT CHAR* pAvpBuffer,
  168. OUT ULONG* pulAvpLength );
  169. VOID
  170. BuildSccrpAvps(
  171. IN TUNNELCB* pTunnel,
  172. IN VCCB* pVc,
  173. IN ULONG ulArg1,
  174. IN ULONG ulArg2,
  175. IN PVOID pvArg3,
  176. IN OUT CHAR* pAvpBuffer,
  177. OUT ULONG* pulAvpLength );
  178. VOID
  179. BuildSccrqAvps(
  180. IN TUNNELCB* pTunnel,
  181. IN VCCB* pVc,
  182. IN ULONG ulArg1,
  183. IN ULONG ulArg2,
  184. IN PVOID pvArg3,
  185. IN OUT CHAR* pAvpBuffer,
  186. OUT ULONG* pulAvpLength );
  187. VOID
  188. BuildStopccnAvps(
  189. IN TUNNELCB* pTunnel,
  190. IN VCCB* pVc,
  191. IN ULONG ulArg1,
  192. IN ULONG ulArg2,
  193. IN PVOID pvArg3,
  194. IN OUT CHAR* pAvpBuffer,
  195. OUT ULONG* pulAvpLength );
  196. VOID
  197. BuildWenAvps(
  198. IN TUNNELCB* pTunnel,
  199. IN VCCB* pVc,
  200. IN ULONG ulArg1,
  201. IN ULONG ulArg2,
  202. IN PVOID pvArg3,
  203. IN OUT CHAR* pAvpBuffer,
  204. OUT ULONG* pulAvpLength );
  205. VOID
  206. CompletePayloadSent(
  207. IN TUNNELWORK* pWork,
  208. IN TUNNELCB* pTunnel,
  209. IN VCCB* pVc,
  210. IN ULONG_PTR* punpArgs );
  211. VOID
  212. SendControlComplete(
  213. IN TDIXCONTEXT* pTdix,
  214. IN VOID* pContext1,
  215. IN VOID* pContext2,
  216. IN CHAR* pBuffer );
  217. VOID
  218. SendHeaderComplete(
  219. IN TDIXCONTEXT* pTdix,
  220. IN VOID* pContext1,
  221. IN VOID* pContext2,
  222. IN CHAR* pBuffer );
  223. VOID
  224. SendPayloadReset(
  225. IN TUNNELWORK* pWork,
  226. IN TUNNELCB* pTunnel,
  227. IN VCCB* pVc,
  228. IN ULONG_PTR* punpArgs );
  229. VOID
  230. SendPayloadSeq(
  231. TUNNELWORK* pWork,
  232. TUNNELCB* pTunnel,
  233. VCCB* pVc,
  234. ULONG_PTR* punpArgs );
  235. VOID
  236. SendPayloadSeqComplete(
  237. IN TDIXCONTEXT* pTdix,
  238. IN VOID* pContext1,
  239. IN VOID* pContext2,
  240. IN CHAR* pBuffer );
  241. VOID
  242. SendPayloadUnseq(
  243. TUNNELWORK* pWork,
  244. TUNNELCB* pTunnel,
  245. VCCB* pVc,
  246. ULONG_PTR* punpArgs );
  247. VOID
  248. SendPayloadUnseqComplete(
  249. IN TDIXCONTEXT* pTdix,
  250. IN VOID* pContext1,
  251. IN VOID* pContext2,
  252. IN CHAR* pBuffer );
  253. VOID
  254. SendPayloadTimerEvent(
  255. IN TIMERQITEM* pItem,
  256. IN VOID* pContext,
  257. IN TIMERQEVENT event );
  258. VOID
  259. SendZlb(
  260. IN TUNNELCB* pTunnel,
  261. IN VCCB* pVc,
  262. IN USHORT usNs,
  263. IN USHORT usNr,
  264. IN BOOLEAN fReset );
  265. VOID
  266. UpdateControlHeaderNr(
  267. IN CHAR* pBuffer,
  268. IN USHORT usNr );
  269. VOID
  270. UpdateHeaderLength(
  271. IN CHAR* pBuffer,
  272. IN USHORT usLength );
  273. //-----------------------------------------------------------------------------
  274. // Send routines
  275. //-----------------------------------------------------------------------------
  276. VOID
  277. SendControl(
  278. IN TUNNELCB* pTunnel,
  279. IN VCCB* pVc,
  280. IN USHORT usMsgType,
  281. IN ULONG ulBuildAvpsArg1,
  282. IN ULONG ulBuildAvpsArg2,
  283. IN PVOID pvBuildAvpsArg3,
  284. IN ULONG ulFlags )
  285. // Build and send a control message. 'PTunnel' is the tunnel control
  286. // block, always non-NULL. 'PVc' is the VC control block, non-NULL for
  287. // call connection (as opposed to tunnel connection) messages.
  288. // 'UsMsgType' is the message type AVP value of the message to build.
  289. // 'UlBuildAvpsArgX' are the arguments passed to the PBUILDAVP handler
  290. // associated with 'usMsgType', where the meaning depends on the specific
  291. // handler. 'UlFlags' is the CSF_* flag options associated with the sent
  292. // message context, or 0 if none.
  293. //
  294. // IMPORTANT: Caller must hold 'pTunnel->lockT'. If 'pVc' is non-NULL
  295. // caller must also hold 'pVc->lockV'.
  296. //
  297. {
  298. NDIS_STATUS status;
  299. ADAPTERCB* pAdapter;
  300. NDIS_BUFFER* pNdisBuffer;
  301. PBUILDAVPS pBuildAvpsHandler;
  302. TIMERQITEM* pTqiSendTimeout;
  303. CONTROLSENT* pCs;
  304. USHORT usAssignedCallId;
  305. ULONG ulLength;
  306. ULONG ulAvpLength;
  307. CHAR* pBuffer;
  308. static PBUILDAVPS apBuildAvpHandlers[ 16 ] =
  309. {
  310. BuildSccrqAvps, // CMT_SCCRQ
  311. BuildSccrpAvps, // CMT_SCCRP
  312. BuildScccnAvps, // CMT_SCCCN
  313. BuildStopccnAvps, // CMT_StopCCN
  314. NULL, // CMT_StopCCRP (obsolete)
  315. BuildHelloAvps, // CMT_Hello
  316. BuildOcrqAvps, // CMT_OCRQ
  317. BuildOcrpAvps, // CMT_OCRP
  318. BuildOccnAvps, // CMT_OCCN
  319. BuildIcrqAvps, // CMT_ICRQ
  320. BuildIcrpAvps, // CMT_ICRP
  321. BuildIccnAvps, // CMT_ICCN
  322. NULL, // CMT_CCRQ (obsolete)
  323. BuildCdnAvps, // CMT_CDN
  324. BuildWenAvps, // CMT_WEN
  325. NULL // CMT_SLI
  326. };
  327. TRACE( TL_V, TM_Send, ( "SendControl" ) );
  328. pAdapter = pTunnel->pAdapter;
  329. pBuffer = NULL;
  330. pTqiSendTimeout = NULL;
  331. pCs = NULL;
  332. do
  333. {
  334. // Get an NDIS_BUFFER to hold the control message.
  335. //
  336. pBuffer = GetBufferFromPool( &pAdapter->poolFrameBuffers );
  337. if (!pBuffer)
  338. {
  339. ASSERT( !"GetBfP?" );
  340. status = NDIS_STATUS_RESOURCES;
  341. break;
  342. }
  343. // Get an "unacknowledged send timeout" timer event descriptor.
  344. //
  345. pTqiSendTimeout = ALLOC_TIMERQITEM( pAdapter );
  346. if (!pTqiSendTimeout)
  347. {
  348. ASSERT( !"Alloc TQI?" );
  349. status = NDIS_STATUS_RESOURCES;
  350. break;
  351. }
  352. // Get a "control message sent" context.
  353. //
  354. pCs = ALLOC_CONTROLSENT( pAdapter );
  355. if (!pCs)
  356. {
  357. ASSERT( !"Alloc PS?" );
  358. status = NDIS_STATUS_RESOURCES;
  359. break;
  360. }
  361. status = NDIS_STATUS_SUCCESS;
  362. }
  363. while (FALSE);
  364. if (status != NDIS_STATUS_SUCCESS)
  365. {
  366. if (pBuffer)
  367. {
  368. FreeBufferToPool( &pAdapter->poolFrameBuffers, pBuffer, TRUE );
  369. }
  370. if (pTqiSendTimeout)
  371. {
  372. FREE_TIMERQITEM( pAdapter, pTqiSendTimeout );
  373. }
  374. // System is probably toast but try to be orderly.
  375. //
  376. ScheduleTunnelWork(
  377. pTunnel, NULL, FsmCloseTunnel,
  378. (ULONG_PTR )TRESULT_GeneralWithError,
  379. (ULONG_PTR )GERR_NoResources,
  380. 0, 0, FALSE, FALSE );
  381. return;
  382. }
  383. // Build an L2TP control header in 'pBuffer'. The Call-ID is 0 for tunnel
  384. // control messages, or peer's assigned call ID for call control messages.
  385. //
  386. usAssignedCallId = (pVc) ? pVc->usAssignedCallId : 0;
  387. ulLength =
  388. BuildL2tpHeader(
  389. pBuffer,
  390. TRUE,
  391. FALSE,
  392. &pTunnel->usAssignedTunnelId,
  393. &usAssignedCallId,
  394. &pTunnel->usNs,
  395. pTunnel->usNr );
  396. // Call the message type's "build AVPs" handler to add AVPs to the buffer
  397. // following the header.
  398. //
  399. ASSERT( usMsgType > 0 && usMsgType <= 16 );
  400. pBuildAvpsHandler = apBuildAvpHandlers[ usMsgType - 1 ];
  401. pBuildAvpsHandler(
  402. pTunnel, pVc,
  403. ulBuildAvpsArg1, ulBuildAvpsArg2, pvBuildAvpsArg3,
  404. pBuffer + ulLength, &ulAvpLength );
  405. ulLength += ulAvpLength;
  406. UpdateHeaderLength( pBuffer, (USHORT )ulLength );
  407. // Pare down the frame buffer to the actual length used.
  408. //
  409. pNdisBuffer = NdisBufferFromBuffer( pBuffer );
  410. NdisAdjustBufferLength( pNdisBuffer, (UINT )ulLength );
  411. // Set up the "control message sent" context with the information needed
  412. // to send the message and track it's progress through retransmissions.
  413. //
  414. pCs->lRef = 0;
  415. pCs->usNs = pTunnel->usNs;
  416. pCs->usMsgType = usMsgType;
  417. TimerQInitializeItem( pTqiSendTimeout );
  418. pCs->pTqiSendTimeout = pTqiSendTimeout;
  419. pCs->ulRetransmits = 0;
  420. pCs->pBuffer = pBuffer;
  421. pCs->ulBufferLength = ulLength;
  422. pCs->pTunnel = pTunnel;
  423. pCs->pVc = pVc;
  424. pCs->ulFlags = ulFlags | CSF_Pending;
  425. pCs->pIrp = NULL;
  426. // Bump the 'Next Send' counter since this message has been assigned the
  427. // current value.
  428. //
  429. ++pTunnel->usNs;
  430. // Take a reference that is removed when the context is removed from the
  431. // "outstanding send" list. Take a VC and tunnel reference that is
  432. // removed when the context is freed.
  433. //
  434. ReferenceControlSent( pCs );
  435. ReferenceTunnel( pTunnel, FALSE );
  436. if (pCs->pVc)
  437. {
  438. ReferenceVc( pCs->pVc );
  439. }
  440. // Queue the context as "active" with transmission pending in 'Next Sent'
  441. // sort order, i.e. at the tail.
  442. //
  443. InsertTailList( &pTunnel->listSendsOut, &pCs->linkSendsOut );
  444. // See if the send window allows it to go now.
  445. //
  446. ScheduleTunnelWork(
  447. pTunnel, NULL, SendPending,
  448. 0, 0, 0, 0, FALSE, FALSE );
  449. }
  450. VOID
  451. SendPending(
  452. IN TUNNELWORK* pWork,
  453. IN TUNNELCB* pTunnel,
  454. IN VCCB* pVc,
  455. IN ULONG_PTR* punpArgs )
  456. // A PTUNNELWORK routine to try to send pending messages from the
  457. // "outstanding send" list until the send window is full.
  458. //
  459. // This routine is called only at PASSIVE IRQL.
  460. //
  461. {
  462. NDIS_STATUS status;
  463. ADAPTERCB* pAdapter;
  464. LIST_ENTRY* pLink;
  465. CONTROLSENT* pCs;
  466. ULONG ulFlags;
  467. TRACE( TL_N, TM_Send, ( "SendPending(sout=%d,sw=%d)",
  468. pTunnel->ulSendsOut, pTunnel->ulSendWindow ) );
  469. // Unpack context information then free the work item.
  470. //
  471. pAdapter = pTunnel->pAdapter;
  472. FREE_TUNNELWORK( pAdapter, pWork );
  473. NdisAcquireSpinLock( &pTunnel->lockT );
  474. {
  475. for (;;)
  476. {
  477. if (pTunnel->ulSendsOut >= pTunnel->ulSendWindow)
  478. {
  479. // The send window is closed.
  480. //
  481. break;
  482. }
  483. // Scan the "outstanding send" queue for the next send context
  484. // pending transmission. Can't save our place for the next
  485. // iteration because the lock must be released and re-acquired
  486. // below to send the packet.
  487. //
  488. for (pLink = pTunnel->listSendsOut.Flink;
  489. pLink != &pTunnel->listSendsOut;
  490. pLink = pLink->Flink)
  491. {
  492. pCs = CONTAINING_RECORD( pLink, CONTROLSENT, linkSendsOut );
  493. if (pCs->ulFlags & CSF_Pending)
  494. {
  495. break;
  496. }
  497. }
  498. if (pLink == &pTunnel->listSendsOut)
  499. {
  500. // There is nothing pending.
  501. //
  502. break;
  503. }
  504. // The send window is open and a pending send has been found.
  505. // Mark the context "not pending" and close the window by one to
  506. // account for the coming send.
  507. //
  508. ulFlags = pCs->ulFlags;
  509. pCs->ulFlags &= ~(CSF_Pending | CSF_QueryMediaSpeed);
  510. ++pTunnel->ulSendsOut;
  511. // Cancel any pending delayed acknowledge timeout, because the
  512. // acknowledge will piggyback on this packet.
  513. //
  514. if (pTunnel->pTqiDelayedAck)
  515. {
  516. TimerQCancelItem( pTunnel->pTimerQ, pTunnel->pTqiDelayedAck );
  517. pTunnel->pTqiDelayedAck = NULL;
  518. }
  519. if (pCs->ulRetransmits == 0)
  520. {
  521. LARGE_INTEGER lrgTime;
  522. // This is the original send so note the time sent.
  523. //
  524. NdisGetCurrentSystemTime( &lrgTime );
  525. pCs->llTimeSent = lrgTime.QuadPart;
  526. }
  527. else
  528. {
  529. // In the retransmission, the 'Next Send' is the same as the
  530. // original, but the 'Next Receive' field is updated.
  531. //
  532. UpdateControlHeaderNr( pCs->pBuffer, pTunnel->usNr );
  533. }
  534. // Take a reference that will be removed in the send completion
  535. // routine.
  536. //
  537. ReferenceControlSent( pCs );
  538. TRACE( TL_A, TM_CMsg, ( "%sSEND(%d) %s, +sout=%d, to=%d",
  539. ((g_ulTraceLevel <= TL_I) ? "" : "\nL2TP: "),
  540. pCs->ulRetransmits,
  541. MsgTypePszFromUs( pCs->usMsgType ),
  542. pTunnel->ulSendsOut,
  543. pTunnel->ulSendTimeoutMs ) );
  544. DUMPW( TL_A, TM_MDmp, pCs->pBuffer, pCs->ulBufferLength );
  545. NdisReleaseSpinLock( &pTunnel->lockT );
  546. // query media speed if necessary
  547. if(ulFlags & CSF_QueryMediaSpeed)
  548. {
  549. TdixGetInterfaceInfo(&pAdapter->tdix,
  550. pTunnel->myaddress.ulIpAddress,
  551. &pTunnel->ulMediaSpeed);
  552. }
  553. {
  554. FILE_OBJECT* FileObj;
  555. PTDIX_SEND_HANDLER SendFunc;
  556. // Call TDI to send the control message.
  557. //
  558. if (ReadFlags(&pTunnel->ulFlags) & TCBF_SendConnected) {
  559. ASSERT(pTunnel->pRoute != NULL);
  560. FileObj =
  561. CtrlObjFromUdpContext(&pTunnel->udpContext);
  562. SendFunc = TdixSend;
  563. } else {
  564. FileObj = NULL;
  565. SendFunc = TdixSendDatagram;
  566. }
  567. status = SendFunc(&pAdapter->tdix,
  568. FileObj,
  569. SendControlComplete,
  570. pCs,
  571. NULL,
  572. &pTunnel->address,
  573. pCs->pBuffer,
  574. pCs->ulBufferLength,
  575. &pCs->pIrp );
  576. ASSERT( status == NDIS_STATUS_PENDING );
  577. }
  578. NdisAcquireSpinLock( &pTunnel->lockT );
  579. }
  580. }
  581. NdisReleaseSpinLock( &pTunnel->lockT );
  582. }
  583. VOID
  584. SendPayload(
  585. IN VCCB* pVc,
  586. IN NDIS_PACKET* pPacket )
  587. // Sends payload packet 'pPacket' on VC 'pVc' eventually calling
  588. // NdisMCoSendComplete with the result.
  589. //
  590. // IMPORTANT: Caller must not hold any locks.
  591. //
  592. {
  593. NDIS_STATUS status;
  594. TUNNELCB* pTunnel;
  595. ADAPTERCB* pAdapter;
  596. CHAR* pBuffer;
  597. TRACE( TL_V, TM_Send, ( "SendPayload" ) );
  598. pAdapter = pVc->pAdapter;
  599. pTunnel = pVc->pTunnel;
  600. status = NDIS_STATUS_SUCCESS;
  601. if (pTunnel)
  602. {
  603. if (ReadFlags( &pTunnel->ulFlags ) & TCBF_HostRouteAdded)
  604. {
  605. // Take a reference on the call. For unsequenced sends, this is
  606. // released when the TdixSendDatagram completes. For sequenced
  607. // sends, it is released when the PAYLOADSENT context is freed.
  608. //
  609. if (ReferenceCall( pVc ))
  610. {
  611. // Get an NDIS_BUFFER to hold the L2TP header that will be
  612. // tacked onto the front of NDISWAN's PPP-framed data packet.
  613. //
  614. pBuffer = GetBufferFromPool( &pAdapter->poolHeaderBuffers );
  615. if (!pBuffer)
  616. {
  617. ASSERT( !"GetBfP?" );
  618. DereferenceCall( pVc );
  619. status = NDIS_STATUS_RESOURCES;
  620. }
  621. }
  622. else
  623. {
  624. TRACE( TL_A, TM_Send, ( "Send on inactive $%p", pVc ) );
  625. status = NDIS_STATUS_FAILURE;
  626. }
  627. }
  628. else
  629. {
  630. TRACE( TL_A, TM_Send, ( "SendPayload w/o host route?" ) );
  631. status = NDIS_STATUS_FAILURE;
  632. }
  633. }
  634. else
  635. {
  636. TRACE( TL_A, TM_Send, ( "Send $%p w/o pT?", pVc ) );
  637. status = NDIS_STATUS_FAILURE;
  638. }
  639. if (status != NDIS_STATUS_SUCCESS)
  640. {
  641. NDIS_SET_PACKET_STATUS( pPacket, status );
  642. TRACE( TL_A, TM_Send, ( "NdisMCoSendComp($%x)", status ) );
  643. NdisMCoSendComplete( status, pVc->NdisVcHandle, pPacket );
  644. TRACE( TL_N, TM_Send, ( "NdisMCoSendComp done" ) );
  645. return;
  646. }
  647. if (ReadFlags( &pVc->ulFlags ) & VCBF_Sequencing)
  648. {
  649. ScheduleTunnelWork(
  650. pTunnel, pVc, SendPayloadSeq,
  651. (ULONG_PTR )pPacket, (ULONG_PTR )pBuffer, 0, 0, FALSE, FALSE );
  652. }
  653. else
  654. {
  655. ScheduleTunnelWork(
  656. pTunnel, pVc, SendPayloadUnseq,
  657. (ULONG_PTR )pPacket, (ULONG_PTR )pBuffer, 0, 0, FALSE, FALSE );
  658. }
  659. }
  660. VOID
  661. SendPayloadSeq(
  662. TUNNELWORK* pWork,
  663. TUNNELCB* pTunnel,
  664. VCCB* pVc,
  665. ULONG_PTR* punpArgs )
  666. // A PTUNNELWORK routine to handle sending a sequenced payload packet on a
  667. // VC. Arg0 is the packet to send. Arg1 is the header buffer to fill in.
  668. //
  669. // This routine is called only at PASSIVE IRQL.
  670. //
  671. {
  672. NDIS_STATUS status;
  673. ADAPTERCB* pAdapter;
  674. PAYLOADSENT* pPs;
  675. TIMERQITEM* pTqiSendTimeout;
  676. LARGE_INTEGER lrgTime;
  677. ULONG ulLength;
  678. ULONG ulFullLength;
  679. NDIS_PACKET* pPacket;
  680. CHAR* pBuffer;
  681. NDIS_BUFFER* pNdisBuffer;
  682. USHORT usNs;
  683. TRACE( TL_V, TM_Send, ( "SendPayloadSeq" ) );
  684. // Unpack context information then free the work item.
  685. //
  686. pAdapter = pTunnel->pAdapter;
  687. pPacket = (NDIS_PACKET* )(punpArgs[ 0 ]);
  688. pBuffer = (CHAR* )(punpArgs[ 1 ]);
  689. FREE_TUNNELWORK( pAdapter, pWork );
  690. pTqiSendTimeout = NULL;
  691. pPs = NULL;
  692. do
  693. {
  694. // Get an "unacknowledged send timeout" timer event descriptor.
  695. //
  696. pTqiSendTimeout = ALLOC_TIMERQITEM( pAdapter );
  697. if (!pTqiSendTimeout)
  698. {
  699. ASSERT( !"Alloc TQI?" );
  700. status = NDIS_STATUS_RESOURCES;
  701. break;
  702. }
  703. // Get a "payload message sent" context.
  704. //
  705. pPs = ALLOC_PAYLOADSENT( pAdapter );
  706. if (!pPs)
  707. {
  708. ASSERT( !"Alloc PS?" );
  709. status = NDIS_STATUS_RESOURCES;
  710. break;
  711. }
  712. NdisAcquireSpinLock( &pVc->lockV );
  713. {
  714. // Retrieve the 'Next Send' value to assign this packet, then
  715. // bump the counter for the next guy.
  716. //
  717. usNs = pVc->usNs;
  718. ++pVc->usNs;
  719. // Build an L2TP payload header with Ns/Nr fields in
  720. // 'pBuffer'.
  721. //
  722. ulLength =
  723. BuildL2tpHeader(
  724. pBuffer,
  725. FALSE,
  726. FALSE,
  727. &pTunnel->usAssignedTunnelId,
  728. &pVc->usAssignedCallId,
  729. &usNs,
  730. pVc->usNr );
  731. // Pare down the header buffer to the actual length used then
  732. // chain it onto the PPP-framed data we got from NDISWAN.
  733. //
  734. pNdisBuffer = NdisBufferFromBuffer( pBuffer );
  735. NdisAdjustBufferLength( pNdisBuffer, (UINT )ulLength );
  736. NdisChainBufferAtFront( pPacket, pNdisBuffer );
  737. NdisQueryPacket( pPacket, NULL, NULL, NULL, &ulFullLength );
  738. UpdateHeaderLength( pBuffer, (USHORT )ulFullLength );
  739. // Cancel any pending delayed acknowledge timeout, because the
  740. // acknowledge will piggyback on this packet.
  741. //
  742. if (pVc->pTqiDelayedAck)
  743. {
  744. TimerQCancelItem( pTunnel->pTimerQ, pVc->pTqiDelayedAck );
  745. pVc->pTqiDelayedAck = NULL;
  746. }
  747. // Fill the "payload message sent" context with the information
  748. // needed to track the progress of the payload's acknowledgement.
  749. //
  750. pPs->usNs = usNs;
  751. pPs->lRef = 0;
  752. TimerQInitializeItem( pTqiSendTimeout );
  753. pPs->pTqiSendTimeout = pTqiSendTimeout;
  754. pPs->pPacket = pPacket;
  755. pPs->pBuffer = pBuffer;
  756. ReferenceTunnel( pTunnel, FALSE );
  757. pPs->pTunnel = pTunnel;
  758. ReferenceVc( pVc );
  759. pPs->pVc = pVc;
  760. pPs->status = NDIS_STATUS_FAILURE;
  761. NdisGetCurrentSystemTime( &lrgTime );
  762. pPs->llTimeSent = lrgTime.QuadPart;
  763. pPs->pIrp = NULL;
  764. // Link the payload in the "outstanding" list and take a reference
  765. // on the context corresponding to this linkage. Take a second
  766. // reference that will be removed by the send completion handler.
  767. // Take a third that will be removed by the timer event handler.
  768. //
  769. ReferencePayloadSent( pPs );
  770. InsertTailList( &pVc->listSendsOut, &pPs->linkSendsOut );
  771. ReferencePayloadSent( pPs );
  772. ReferencePayloadSent( pPs );
  773. #ifdef PSDEBUG
  774. {
  775. extern LIST_ENTRY g_listDebugPs;
  776. extern NDIS_SPIN_LOCK g_lockDebugPs;
  777. NdisAcquireSpinLock( &g_lockDebugPs );
  778. {
  779. InsertTailList( &g_listDebugPs, &pPs->linkDebugPs );
  780. }
  781. NdisReleaseSpinLock( &g_lockDebugPs );
  782. }
  783. #endif
  784. TimerQScheduleItem(
  785. pTunnel->pTimerQ,
  786. pPs->pTqiSendTimeout,
  787. pVc->ulSendTimeoutMs,
  788. SendPayloadTimerEvent,
  789. pPs );
  790. TRACE( TL_A, TM_Msg,
  791. ( "%sSEND payload, len=%d Ns=%d Nr=%d to=%d",
  792. ((g_ulTraceLevel <= TL_I) ? "" : "\nL2TP: "),
  793. ulFullLength, pPs->usNs, pVc->usNr, pVc->ulSendTimeoutMs ) );
  794. DUMPW( TL_A, TM_MDmp, pPs->pBuffer, ulLength );
  795. ++pVc->stats.ulSentDataPacketsSeq;
  796. pVc->stats.ulDataBytesSent += (ulFullLength - ulLength);
  797. pVc->stats.ulSendWindowTotal += pVc->ulSendWindow;
  798. }
  799. NdisReleaseSpinLock( &pVc->lockV );
  800. status = NDIS_STATUS_SUCCESS;
  801. }
  802. while (FALSE);
  803. if (status != NDIS_STATUS_SUCCESS)
  804. {
  805. FreeBufferToPool( &pAdapter->poolHeaderBuffers, pBuffer, TRUE );
  806. if (pTqiSendTimeout)
  807. {
  808. FREE_TIMERQITEM( pAdapter, pTqiSendTimeout );
  809. }
  810. ASSERT( !pPs );
  811. // Complete the send, indicating the failure.
  812. //
  813. NDIS_SET_PACKET_STATUS( pPacket, status );
  814. TRACE( TL_A, TM_Send, ( "NdisMCoSendComp($%x)", status ) );
  815. NdisMCoSendComplete( status, pVc->NdisVcHandle, pPacket );
  816. TRACE( TL_N, TM_Send, ( "NdisMCoSendComp done" ) );
  817. return;
  818. }
  819. // Call TDI to send the payload message.
  820. //
  821. {
  822. FILE_OBJECT* FileObj;
  823. PTDIX_SEND_HANDLER SendFunc;
  824. if (ReadFlags(&pTunnel->ulFlags) & TCBF_SendConnected) {
  825. ASSERT(pTunnel->pRoute != NULL);
  826. FileObj = PayloadObjFromUdpContext(&pTunnel->udpContext);
  827. SendFunc = TdixSend;
  828. } else {
  829. FileObj = NULL;
  830. SendFunc = TdixSendDatagram;
  831. }
  832. status = SendFunc(&pAdapter->tdix,
  833. FileObj,
  834. SendPayloadSeqComplete,
  835. pPs,
  836. NULL,
  837. &pTunnel->address,
  838. pBuffer,
  839. ulFullLength,
  840. &pPs->pIrp );
  841. }
  842. ASSERT( status == NDIS_STATUS_PENDING );
  843. }
  844. VOID
  845. SendPayloadUnseq(
  846. TUNNELWORK* pWork,
  847. TUNNELCB* pTunnel,
  848. VCCB* pVc,
  849. ULONG_PTR* punpArgs )
  850. // A PTUNNELWORK routine to handle sending an unsequenced payload packet
  851. // on a VC. Arg0 is the NDIS_PACKET. Arg1 is the header buffer to fill
  852. // in.
  853. //
  854. // This routine is called only at PASSIVE IRQL.
  855. //
  856. {
  857. NDIS_STATUS status;
  858. ADAPTERCB* pAdapter;
  859. ULONG ulLength;
  860. UINT unFullLength;
  861. NDIS_PACKET* pPacket;
  862. CHAR* pBuffer;
  863. NDIS_BUFFER* pNdisBuffer;
  864. TRACE( TL_V, TM_Send, ( "SendPayloadUnseq" ) );
  865. // Unpack context information then free the work item.
  866. //
  867. pAdapter = pTunnel->pAdapter;
  868. pPacket = (NDIS_PACKET* )(punpArgs[ 0 ]);
  869. pBuffer = (CHAR* )(punpArgs[ 1 ]);
  870. FREE_TUNNELWORK( pAdapter, pWork );
  871. NdisAcquireSpinLock( &pVc->lockV );
  872. {
  873. // Build an L2TP payload header without Ns/Nr fields in 'pBuffer'.
  874. //
  875. ulLength =
  876. BuildL2tpHeader(
  877. pBuffer,
  878. FALSE,
  879. FALSE,
  880. &pTunnel->usAssignedTunnelId,
  881. &pVc->usAssignedCallId,
  882. NULL,
  883. 0 );
  884. // Pare down the header buffer to the actual length used then
  885. // chain it onto the PPP-framed data we got from NDISWAN. Poke
  886. // the L2TP header to update the length field accounting for the
  887. // data.
  888. //
  889. pNdisBuffer = NdisBufferFromBuffer( pBuffer );
  890. NdisAdjustBufferLength( pNdisBuffer, (UINT )ulLength );
  891. NdisChainBufferAtFront( pPacket, pNdisBuffer );
  892. NdisQueryPacket( pPacket, NULL, NULL, NULL, &unFullLength );
  893. UpdateHeaderLength( pBuffer, (USHORT )unFullLength );
  894. TRACE( TL_A, TM_Msg,
  895. ( "%sSEND payload(%d), len=%d",
  896. ((g_ulTraceLevel <= TL_I) ? "" : "\nL2TP: "),
  897. ++pVc->usNs,
  898. unFullLength ) );
  899. DUMPW( TL_A, TM_MDmp, pBuffer, ulLength );
  900. ++pVc->stats.ulSentDataPacketsUnSeq;
  901. pVc->stats.ulDataBytesSent += ((ULONG )unFullLength - ulLength);
  902. }
  903. NdisReleaseSpinLock( &pVc->lockV );
  904. // Call TDI to send the payload message.
  905. //
  906. {
  907. FILE_OBJECT* FileObj;
  908. PTDIX_SEND_HANDLER SendFunc;
  909. NdisAcquireSpinLock(&pTunnel->lockT);
  910. if (pTunnel->pRoute != NULL) {
  911. FileObj = PayloadObjFromUdpContext(&pTunnel->udpContext);
  912. SendFunc = TdixSend;
  913. } else {
  914. FileObj = NULL;
  915. SendFunc = TdixSendDatagram;
  916. }
  917. NdisReleaseSpinLock(&pTunnel->lockT);
  918. status = SendFunc(&pAdapter->tdix,
  919. FileObj,
  920. SendPayloadUnseqComplete,
  921. pVc,
  922. pPacket,
  923. &pTunnel->address,
  924. pBuffer,
  925. (ULONG )unFullLength,
  926. NULL );
  927. }
  928. ASSERT( status == NDIS_STATUS_PENDING );
  929. }
  930. VOID
  931. SendControlAck(
  932. IN TUNNELWORK* pWork,
  933. IN TUNNELCB* pTunnel,
  934. IN VCCB* pVc,
  935. IN ULONG_PTR* punpArgs )
  936. // A PTUNNELWORK routine to send a control acknowledge.
  937. //
  938. // This routine is called only at PASSIVE IRQL.
  939. //
  940. {
  941. ADAPTERCB* pAdapter;
  942. TRACE( TL_N, TM_Send, ( "SendControlAck" ) );
  943. // Unpack context information then free the work item.
  944. //
  945. pAdapter = pTunnel->pAdapter;
  946. FREE_TUNNELWORK( pAdapter, pWork );
  947. SendZlb( pTunnel, NULL, pTunnel->usNs, pTunnel->usNr, FALSE );
  948. }
  949. VOID
  950. SendPayloadAck(
  951. IN TUNNELWORK* pWork,
  952. IN TUNNELCB* pTunnel,
  953. IN VCCB* pVc,
  954. IN ULONG_PTR* punpArgs )
  955. // A PTUNNELWORK routine to send a payload acknowledge.
  956. //
  957. // This routine is called only at PASSIVE IRQL.
  958. //
  959. // IMPORTANT: Caller must take a call reference before calling that is
  960. // removed by the send completion handler.
  961. //
  962. {
  963. ADAPTERCB* pAdapter;
  964. TRACE( TL_N, TM_Send, ( "SendPayloadAck" ) );
  965. // Unpack context information then free the work item.
  966. //
  967. pAdapter = pTunnel->pAdapter;
  968. FREE_TUNNELWORK( pAdapter, pWork );
  969. ASSERT( pVc );
  970. ASSERT( pVc->usAssignedCallId > 0 );
  971. SendZlb( pTunnel, pVc, pVc->usNs, pVc->usNr, FALSE );
  972. }
  973. VOID
  974. SendPayloadReset(
  975. IN TUNNELWORK* pWork,
  976. IN TUNNELCB* pTunnel,
  977. IN VCCB* pVc,
  978. IN ULONG_PTR* punpArgs )
  979. // A PTUNNELWORK routine to send a payload reset. Arg0 is the "Next Sent"
  980. // value to send in the reset message.
  981. //
  982. // This routine is called only at PASSIVE IRQL.
  983. //
  984. // IMPORTANT: Caller must take a call reference before calling that is
  985. // removed by the send completion handler.
  986. //
  987. {
  988. ADAPTERCB* pAdapter;
  989. USHORT usNs;
  990. // Unpack context information then free the work item.
  991. //
  992. pAdapter = pTunnel->pAdapter;
  993. usNs = (USHORT )(punpArgs[ 0 ]);
  994. FREE_TUNNELWORK( pAdapter, pWork );
  995. TRACE( TL_A, TM_Send, ( "Send Reset=%d", (LONG )usNs ) );
  996. ASSERT( pVc );
  997. ASSERT( pVc->usAssignedCallId > 0 );
  998. SendZlb( pTunnel, pVc, usNs, pVc->usNr, TRUE );
  999. }
  1000. VOID
  1001. ReferenceControlSent(
  1002. IN CONTROLSENT* pCs )
  1003. // Reference the control-sent context 'pCs'.
  1004. //
  1005. {
  1006. LONG lRef;
  1007. lRef = NdisInterlockedIncrement( &pCs->lRef );
  1008. TRACE( TL_N, TM_Ref, ( "RefCs to %d", lRef ) );
  1009. }
  1010. LONG
  1011. DereferenceControlSent(
  1012. IN CONTROLSENT* pCs )
  1013. // Reference the control-sent context 'pCs'.
  1014. //
  1015. // Returns the reference count of the dereferenced context.
  1016. //
  1017. {
  1018. LONG lRef;
  1019. ADAPTERCB* pAdapter;
  1020. NDIS_BUFFER* pNdisBuffer;
  1021. lRef = NdisInterlockedDecrement( &pCs->lRef );
  1022. TRACE( TL_N, TM_Ref, ( "DerefCs to %d", lRef ) );
  1023. ASSERT( lRef >= 0 );
  1024. if (lRef == 0)
  1025. {
  1026. pAdapter = pCs->pTunnel->pAdapter;
  1027. ASSERT( pCs->linkSendsOut.Flink == &pCs->linkSendsOut );
  1028. pNdisBuffer = NdisBufferFromBuffer( pCs->pBuffer );
  1029. NdisAdjustBufferLength(
  1030. pNdisBuffer, BufferSizeFromBuffer( pCs->pBuffer ) );
  1031. FreeBufferToPool(
  1032. &pAdapter->poolFrameBuffers, pCs->pBuffer, TRUE );
  1033. if (pCs->pVc)
  1034. {
  1035. DereferenceVc( pCs->pVc );
  1036. }
  1037. ASSERT( pCs->pTunnel )
  1038. DereferenceTunnel( pCs->pTunnel );
  1039. FREE_TIMERQITEM( pAdapter, pCs->pTqiSendTimeout );
  1040. FREE_CONTROLSENT( pAdapter, pCs );
  1041. }
  1042. return lRef;
  1043. }
  1044. VOID
  1045. ReferencePayloadSent(
  1046. IN PAYLOADSENT* pPs )
  1047. // Reference the payload-sent context 'pPs'.
  1048. //
  1049. {
  1050. LONG lRef;
  1051. lRef = NdisInterlockedIncrement( &pPs->lRef );
  1052. TRACE( TL_N, TM_Ref, ( "RefPs to %d", lRef ) );
  1053. }
  1054. LONG
  1055. DereferencePayloadSent(
  1056. IN PAYLOADSENT* pPs )
  1057. // Reference the payload-sent context 'pPs'.
  1058. //
  1059. // Returns the reference count of the dereferenced context.
  1060. //
  1061. {
  1062. LONG lRef;
  1063. ADAPTERCB* pAdapter;
  1064. lRef = NdisInterlockedDecrement( &pPs->lRef );
  1065. TRACE( TL_N, TM_Ref, ( "DerefPs to %d", lRef ) );
  1066. ASSERT( lRef >= 0 );
  1067. if (lRef == 0)
  1068. {
  1069. ASSERT( pPs->linkSendsOut.Flink == &pPs->linkSendsOut );
  1070. // The actual work is scheduled because it calls outside the driver
  1071. // and we don't want any lock restrictions on this routine.
  1072. //
  1073. ScheduleTunnelWork(
  1074. pPs->pTunnel, pPs->pVc, CompletePayloadSent,
  1075. (ULONG_PTR )pPs, 0, 0, 0, FALSE, FALSE );
  1076. }
  1077. return lRef;
  1078. }
  1079. //-----------------------------------------------------------------------------
  1080. // Send utility routines (alphabetically)
  1081. //-----------------------------------------------------------------------------
  1082. USHORT
  1083. BuildAvpAch(
  1084. IN USHORT usAttribute,
  1085. IN BOOLEAN fMandatory,
  1086. IN CHAR* pszValue,
  1087. IN USHORT usValueLength,
  1088. OUT CHAR* pAvp )
  1089. // Builds a byte-array-valued AVP in caller's buffer 'pAvp' with attribute
  1090. // field value 'usAttribute' and value the first 'usValueLength' bytes of
  1091. // array 'pszlValue'. 'FMandatory' indicates the M-bit should be set in
  1092. // the AVP.
  1093. //
  1094. // Returns the length of the built AVP.
  1095. //
  1096. {
  1097. UNALIGNED USHORT* pusCur;
  1098. UNALIGNED USHORT* pusBits;
  1099. USHORT usLength;
  1100. pusCur = (UNALIGNED USHORT* )pAvp;
  1101. pusBits = pusCur;
  1102. ++pusCur;
  1103. // Set Vendor ID to "IETF-defined".
  1104. //
  1105. *pusCur = 0;
  1106. ++pusCur;
  1107. // Set Attribute field.
  1108. //
  1109. *pusCur = htons( usAttribute );
  1110. ++pusCur;
  1111. // Set Value field.
  1112. //
  1113. if (usValueLength)
  1114. {
  1115. NdisMoveMemory( (CHAR* )pusCur, pszValue, (ULONG )usValueLength );
  1116. ((CHAR* )pusCur) += usValueLength;
  1117. }
  1118. // Now, go back and set bits/length field.
  1119. //
  1120. usLength = (USHORT )(((CHAR* )pusCur) - pAvp);
  1121. *pusBits = usLength;
  1122. if (fMandatory)
  1123. {
  1124. *pusBits |= ABM_M;
  1125. }
  1126. *pusBits = htons( *pusBits );
  1127. return usLength;
  1128. }
  1129. USHORT
  1130. BuildAvpAul(
  1131. IN USHORT usAttribute,
  1132. IN BOOLEAN fMandatory,
  1133. IN UNALIGNED ULONG* pulValue,
  1134. IN USHORT usValues,
  1135. OUT CHAR* pAvp )
  1136. // Builds a ULONG-array-valued AVP in caller's buffer 'pAvp' with
  1137. // attribute field value 'usAttribute' and value the first 'usValues'
  1138. // ULONGS of array 'pszlValue'. 'FMandatory' indicates the M-bit should
  1139. // be set in the AVP.
  1140. //
  1141. // Returns the length of the built AVP.
  1142. //
  1143. {
  1144. UNALIGNED USHORT* pusCur;
  1145. UNALIGNED USHORT* pusBits;
  1146. USHORT usLength;
  1147. USHORT i;
  1148. pusCur = (UNALIGNED USHORT* )pAvp;
  1149. pusBits = pusCur;
  1150. ++pusCur;
  1151. // Set Vendor ID to "IETF-defined".
  1152. //
  1153. *pusCur = 0;
  1154. ++pusCur;
  1155. // Set Attribute field.
  1156. //
  1157. *pusCur = htons( usAttribute );
  1158. ++pusCur;
  1159. // Set Value field.
  1160. //
  1161. for (i = 0; i < usValues; ++i)
  1162. {
  1163. *((UNALIGNED ULONG* )pusCur) = pulValue[ i ];
  1164. *((UNALIGNED ULONG* )pusCur) = htonl( *((UNALIGNED ULONG* )pusCur) );
  1165. pusCur += 2;
  1166. }
  1167. // Now, go back and set bits/length field.
  1168. //
  1169. usLength = (USHORT )(((CHAR* )pusCur) - pAvp);
  1170. *pusBits = usLength;
  1171. if (fMandatory)
  1172. {
  1173. *pusBits |= ABM_M;
  1174. }
  1175. *pusBits = htons( *pusBits );
  1176. return usLength;
  1177. }
  1178. USHORT
  1179. BuildAvpFlag(
  1180. IN USHORT usAttribute,
  1181. IN BOOLEAN fMandatory,
  1182. OUT CHAR* pAvp )
  1183. // Builds an empty (no data) flag AVP in caller's buffer 'pAvp' with
  1184. // attribute field value 'usAttribute'. 'FMandatory' indicates the M-bit
  1185. // should be set in the AVP.
  1186. //
  1187. // Returns the length of the built AVP.
  1188. //
  1189. {
  1190. UNALIGNED USHORT* pusCur;
  1191. UNALIGNED USHORT* pusBits;
  1192. USHORT usLength;
  1193. pusCur = (UNALIGNED USHORT* )pAvp;
  1194. pusBits = pusCur;
  1195. ++pusCur;
  1196. // Set Vendor ID to "IETF-defined".
  1197. //
  1198. *pusCur = 0;
  1199. ++pusCur;
  1200. // Set Attribute field.
  1201. //
  1202. *pusCur = htons( usAttribute );
  1203. ++pusCur;
  1204. // Now, go back and set bits/length field.
  1205. //
  1206. usLength = (USHORT )(((CHAR* )pusCur) - pAvp);
  1207. *pusBits = usLength;
  1208. if (fMandatory)
  1209. {
  1210. *pusBits |= ABM_M;
  1211. }
  1212. *pusBits = htons( *pusBits );
  1213. return usLength;
  1214. }
  1215. USHORT
  1216. BuildAvpUl(
  1217. IN USHORT usAttribute,
  1218. IN BOOLEAN fMandatory,
  1219. IN ULONG ulValue,
  1220. OUT CHAR* pAvp )
  1221. // Builds a ULONG-valued AVP in caller's buffer 'pAvp' with attribute
  1222. // field value 'usAttribute' and value 'ulValue'. 'FMandatory' indicates
  1223. // the M-bit should be set in the AVP.
  1224. //
  1225. // Returns the length of the built AVP.
  1226. //
  1227. {
  1228. UNALIGNED USHORT* pusCur;
  1229. UNALIGNED USHORT* pusBits;
  1230. USHORT usLength;
  1231. pusCur = (UNALIGNED USHORT* )pAvp;
  1232. pusBits = pusCur;
  1233. ++pusCur;
  1234. // Set Vendor ID to "IETF-defined".
  1235. //
  1236. *pusCur = 0;
  1237. ++pusCur;
  1238. // Set Attribute field.
  1239. //
  1240. *pusCur = htons( usAttribute );
  1241. ++pusCur;
  1242. // Set Value field.
  1243. //
  1244. *((UNALIGNED ULONG* )pusCur) = htonl( ulValue );
  1245. pusCur += 2;
  1246. // Now, go back and set bits/length field.
  1247. //
  1248. usLength = (USHORT )(((CHAR* )pusCur) - pAvp);
  1249. *pusBits = usLength;
  1250. if (fMandatory)
  1251. {
  1252. *pusBits |= ABM_M;
  1253. }
  1254. *pusBits = htons( *pusBits );
  1255. return usLength;
  1256. }
  1257. USHORT
  1258. BuildAvpUs(
  1259. IN USHORT usAttribute,
  1260. IN BOOLEAN fMandatory,
  1261. IN USHORT usValue,
  1262. OUT CHAR* pAvp )
  1263. // Builds a USHORT-valued AVP in caller's buffer 'pAvp' with attribute
  1264. // field value 'usAttribute' and value 'usValue'. 'FMandatory' indicates
  1265. // the M-bit should be set in the AVP.
  1266. //
  1267. // Returns the length of the built AVP.
  1268. //
  1269. {
  1270. UNALIGNED USHORT* pusCur;
  1271. UNALIGNED USHORT* pusBits;
  1272. USHORT usLength;
  1273. pusCur = (UNALIGNED USHORT* )pAvp;
  1274. pusBits = pusCur;
  1275. ++pusCur;
  1276. // Set Vendor ID to "IETF-defined".
  1277. //
  1278. *pusCur = 0;
  1279. ++pusCur;
  1280. // Set Attribute field.
  1281. //
  1282. *pusCur = htons( usAttribute );
  1283. ++pusCur;
  1284. // Set Value field.
  1285. //
  1286. *pusCur = htons( usValue );
  1287. ++pusCur;
  1288. // Now, go back and set bits/length field.
  1289. //
  1290. usLength = (USHORT )(((CHAR* )pusCur) - pAvp);
  1291. *pusBits = usLength;
  1292. if (fMandatory)
  1293. {
  1294. *pusBits |= ABM_M;
  1295. }
  1296. *pusBits = htons( *pusBits );
  1297. return usLength;
  1298. }
  1299. USHORT
  1300. BuildAvp2UsAndAch(
  1301. IN USHORT usAttribute,
  1302. IN BOOLEAN fMandatory,
  1303. IN USHORT usValue1,
  1304. IN USHORT usValue2,
  1305. IN CHAR* pszValue,
  1306. IN USHORT usValueLength,
  1307. OUT CHAR* pAvp )
  1308. // Builds an AVP consisting of 'usValue1' and 'usValue2' followed by
  1309. // message 'pszValue' of length 'usValueLength' bytes in caller's buffer
  1310. // 'pAvp' with attribute field value 'usAttribute'. 'FMandatory'
  1311. // indicates the M-bit should be set in the AVP.
  1312. //
  1313. // Returns the length of the built AVP.
  1314. //
  1315. {
  1316. UNALIGNED USHORT* pusCur;
  1317. UNALIGNED USHORT* pusBits;
  1318. USHORT usLength;
  1319. pusCur = (UNALIGNED USHORT* )pAvp;
  1320. pusBits = pusCur;
  1321. ++pusCur;
  1322. // Set Vendor ID to "IETF-defined".
  1323. //
  1324. *pusCur = 0;
  1325. ++pusCur;
  1326. // Set Attribute field.
  1327. //
  1328. *pusCur = htons( usAttribute );
  1329. ++pusCur;
  1330. // Set first USHORT value field.
  1331. //
  1332. *pusCur = htons( usValue1 );
  1333. ++pusCur;
  1334. // Set second USHORT value field.
  1335. //
  1336. *pusCur = htons( usValue2 );
  1337. ++pusCur;
  1338. // Set message value field.
  1339. //
  1340. if (usValueLength)
  1341. {
  1342. NdisMoveMemory( (CHAR* )pusCur, pszValue, (ULONG )usValueLength );
  1343. ((CHAR*)pusCur) += usValueLength;
  1344. }
  1345. // Now, go back and set bits/length field.
  1346. //
  1347. usLength = (USHORT )(((CHAR* )pusCur) - pAvp);
  1348. *pusBits = usLength;
  1349. if (fMandatory)
  1350. {
  1351. *pusBits |= ABM_M;
  1352. }
  1353. *pusBits = htons( *pusBits );
  1354. return usLength;
  1355. }
  1356. VOID
  1357. BuildCdnAvps(
  1358. IN TUNNELCB* pTunnel,
  1359. IN VCCB* pVc,
  1360. IN ULONG ulArg1,
  1361. IN ULONG ulArg2,
  1362. IN PVOID pvArg3,
  1363. IN OUT CHAR* pAvpBuffer,
  1364. OUT ULONG* pulAvpLength )
  1365. // PBUILDAVPS handler to add AVPs to an outgoing CallDisconnNotify control
  1366. // message. 'PTunnel' and 'pVc' are the tunnel/VC control blocks.
  1367. // 'ulArg1' and 'ulArg2' are the result and error codes to be returned.
  1368. // 'pvArg3' is ignored. 'PAvpBuffer' is the address of the buffer to
  1369. // receive the built AVPs. '*PulAvpLength' is set to the length of the
  1370. // built AVPs.
  1371. //
  1372. {
  1373. CHAR* pCurAvp;
  1374. ULONG ulAvpLength;
  1375. USHORT usResult;
  1376. USHORT usError;
  1377. TRACE( TL_V, TM_Send, ( "BuildCdnAvps" ) );
  1378. usResult = (USHORT )ulArg1;
  1379. usError = (USHORT )ulArg2;
  1380. pCurAvp = pAvpBuffer;
  1381. pCurAvp += BuildAvpUs(
  1382. ATTR_MsgType, TRUE, CMT_CDN, pCurAvp );
  1383. pCurAvp += BuildAvp2UsAndAch(
  1384. ATTR_Result, TRUE, usResult, usError, NULL, 0, pCurAvp );
  1385. pCurAvp += BuildAvpUs(
  1386. ATTR_AssignedCallId, TRUE, pVc->usCallId, pCurAvp );
  1387. *pulAvpLength = (ULONG )(pCurAvp - pAvpBuffer);
  1388. }
  1389. VOID
  1390. BuildHelloAvps(
  1391. IN TUNNELCB* pTunnel,
  1392. IN VCCB* pVc,
  1393. IN ULONG ulArg1,
  1394. IN ULONG ulArg2,
  1395. IN PVOID pvArg3,
  1396. IN OUT CHAR* pAvpBuffer,
  1397. OUT ULONG* pulAvpLength )
  1398. // PBUILDAVPS handler to add AVPs to an outgoing Hello control message.
  1399. // 'PTunnel' is the tunnel control block. 'PVc', 'ulArgX' and 'pvArg3' are ignored.
  1400. // 'PAvpBuffer' is the address of the buffer to receive the built AVPs.
  1401. // '*PulAvpLength' is set to the length of the built AVPs.
  1402. //
  1403. {
  1404. CHAR* pCurAvp;
  1405. ULONG ulAvpLength;
  1406. ADAPTERCB* pAdapter;
  1407. TRACE( TL_V, TM_Send, ( "BuildHelloAvps" ) );
  1408. pAdapter = pTunnel->pAdapter;
  1409. pCurAvp = pAvpBuffer;
  1410. pCurAvp += BuildAvpUs(
  1411. ATTR_MsgType, TRUE, CMT_Hello, pCurAvp );
  1412. *pulAvpLength = (ULONG )(pCurAvp - pAvpBuffer);
  1413. }
  1414. VOID
  1415. BuildIccnAvps(
  1416. IN TUNNELCB* pTunnel,
  1417. IN VCCB* pVc,
  1418. IN ULONG ulArg1,
  1419. IN ULONG ulArg2,
  1420. IN PVOID pvArg3,
  1421. IN OUT CHAR* pAvpBuffer,
  1422. OUT ULONG* pulAvpLength )
  1423. // PBUILDAVPS handler to add AVPs to an outgoing Incoming-Call-Connected
  1424. // control message. 'PTunnel' and 'pVc' are the tunnel/VC control blocks.
  1425. // 'UlArgX' and 'pvArg3' are ignored. 'PAvpBuffer' is the address of the buffer to
  1426. // receive the built AVPs. '*PulAvpLength' is set to the length of the
  1427. // built AVPs.
  1428. //
  1429. {
  1430. CHAR* pCurAvp;
  1431. ULONG ulAvpLength;
  1432. ADAPTERCB* pAdapter;
  1433. BOOLEAN fSequencing;
  1434. pAdapter = pTunnel->pAdapter;
  1435. TRACE( TL_V, TM_Send, ( "BuildIccnAvps" ) );
  1436. pCurAvp = pAvpBuffer;
  1437. pCurAvp += BuildAvpUs(
  1438. ATTR_MsgType, TRUE, CMT_ICCN, pCurAvp );
  1439. // For now, we don't support WAN link relays, so this is the estimated
  1440. // speed of the LAN relay. This could be totally wrong if, for instance,
  1441. // the tunnel is itself tunneled over a PPP link.
  1442. //
  1443. pCurAvp += BuildAvpUl(
  1444. ATTR_TxConnectSpeed, TRUE, pVc->ulConnectBps, pCurAvp );
  1445. pCurAvp += BuildAvpUl(
  1446. ATTR_FramingType, TRUE, FBM_Sync, pCurAvp );
  1447. fSequencing = !!(ReadFlags( &pVc->ulFlags ) & VCBF_Sequencing);
  1448. if (fSequencing)
  1449. {
  1450. USHORT usRWindow;
  1451. usRWindow = pAdapter->usPayloadReceiveWindow;
  1452. if (!usRWindow)
  1453. {
  1454. usRWindow = L2TP_DefaultReceiveWindow;
  1455. }
  1456. pCurAvp += BuildAvpUs(
  1457. ATTR_RWindowSize, TRUE, usRWindow, pCurAvp );
  1458. }
  1459. #if 0
  1460. // Use the LNS default PPD even when we're LAC, for now.
  1461. //
  1462. pCurAvp += BuildAvpUs(
  1463. ATTR_PacketProcDelay, TRUE, L2TP_LnsDefaultPpd, pCurAvp );
  1464. #endif
  1465. pCurAvp += BuildAvpUs(
  1466. ATTR_ProxyAuthType, FALSE, PAT_None, pCurAvp );
  1467. if (fSequencing)
  1468. {
  1469. pCurAvp += BuildAvpFlag(
  1470. ATTR_SequencingRequired, TRUE, pCurAvp );
  1471. }
  1472. *pulAvpLength = (ULONG )(pCurAvp - pAvpBuffer);
  1473. }
  1474. VOID
  1475. BuildIcrpAvps(
  1476. IN TUNNELCB* pTunnel,
  1477. IN VCCB* pVc,
  1478. IN ULONG ulArg1,
  1479. IN ULONG ulArg2,
  1480. IN PVOID pvArg3,
  1481. IN OUT CHAR* pAvpBuffer,
  1482. OUT ULONG* pulAvpLength )
  1483. // PBUILDAVPS handler to add AVPs to an outgoing Incoming-Call-Reply
  1484. // control message. 'PTunnel' and 'pVc' are the tunnel/VC control blocks.
  1485. // 'UlArgX' and 'pvArg3' are ignored. 'PAvpBuffer' is the address of the buffer to
  1486. // receive the built AVPs. '*PulAvpLength' is set to the length of the
  1487. // built AVPs.
  1488. //
  1489. {
  1490. CHAR* pCurAvp;
  1491. ULONG ulAvpLength;
  1492. ADAPTERCB* pAdapter;
  1493. pAdapter = pTunnel->pAdapter;
  1494. TRACE( TL_V, TM_Send, ( "BuildIcrpAvps" ) );
  1495. pCurAvp = pAvpBuffer;
  1496. pCurAvp += BuildAvpUs(
  1497. ATTR_MsgType, TRUE, CMT_ICRP, pCurAvp );
  1498. pCurAvp += BuildAvpUs(
  1499. ATTR_AssignedCallId, TRUE, pVc->usCallId, pCurAvp );
  1500. if (ReadFlags( &pVc->ulFlags ) & VCBF_Sequencing)
  1501. {
  1502. USHORT usRWindow;
  1503. usRWindow = pAdapter->usPayloadReceiveWindow;
  1504. if (!usRWindow)
  1505. usRWindow = L2TP_DefaultReceiveWindow;
  1506. pCurAvp += BuildAvpUs(
  1507. ATTR_RWindowSize, TRUE, usRWindow, pCurAvp );
  1508. }
  1509. #if 0
  1510. pCurAvp += BuildAvpUs(
  1511. ATTR_PacketProcDelay, TRUE, L2TP_LnsDefaultPpd, pCurAvp );
  1512. #endif
  1513. *pulAvpLength = (ULONG )(pCurAvp - pAvpBuffer);
  1514. }
  1515. VOID
  1516. BuildIcrqAvps(
  1517. IN TUNNELCB* pTunnel,
  1518. IN VCCB* pVc,
  1519. IN ULONG ulArg1,
  1520. IN ULONG ulArg2,
  1521. IN PVOID pvArg3,
  1522. IN OUT CHAR* pAvpBuffer,
  1523. OUT ULONG* pulAvpLength )
  1524. // PBUILDAVPS handler to add AVPs to an outgoing Incoming-Call-Request
  1525. // control message. 'PTunnel' and 'pVc' are the tunnel/VC control block.
  1526. // 'UlArgX' and 'pvArg3' are ignored. 'PAvpBuffer' is the address of the buffer to
  1527. // receive the built AVPs. '*PulAvpLength' is set to the length of the
  1528. // built AVPs.
  1529. //
  1530. {
  1531. CHAR* pCurAvp;
  1532. ULONG ulAvpLength;
  1533. ADAPTERCB* pAdapter;
  1534. pAdapter = pTunnel->pAdapter;
  1535. TRACE( TL_V, TM_Send, ( "BuildIcrqAvps" ) );
  1536. pCurAvp = pAvpBuffer;
  1537. pCurAvp += BuildAvpUs(
  1538. ATTR_MsgType, TRUE, CMT_ICRQ, pCurAvp );
  1539. pCurAvp += BuildAvpUs(
  1540. ATTR_AssignedCallId, TRUE, pVc->usCallId, pCurAvp );
  1541. pCurAvp += BuildAvpUl(
  1542. ATTR_CallSerialNumber, TRUE,
  1543. pVc->pLcParams->ulCallSerialNumber, pCurAvp );
  1544. {
  1545. ULONG ulBearerType;
  1546. ulBearerType = 0;
  1547. if (pVc->pTcParams->ulMediaMode & LINEMEDIAMODE_DATAMODEM)
  1548. {
  1549. ulBearerType |= BBM_Analog;
  1550. }
  1551. if (pVc->pTcParams->ulMediaMode & LINEMEDIAMODE_DIGITALDATA)
  1552. {
  1553. ulBearerType |= BBM_Digital;
  1554. }
  1555. pCurAvp += BuildAvpUl(
  1556. ATTR_BearerType, TRUE, ulBearerType, pCurAvp );
  1557. }
  1558. if (pVc->pLcParams->ulPhysicalChannelId != 0xFFFFFFFF)
  1559. {
  1560. pCurAvp += BuildAvpUl(
  1561. ATTR_PhysicalChannelId, FALSE,
  1562. pVc->pLcParams->ulPhysicalChannelId, pCurAvp );
  1563. }
  1564. *pulAvpLength = (ULONG )(pCurAvp - pAvpBuffer);
  1565. }
  1566. ULONG
  1567. BuildL2tpHeader(
  1568. IN OUT CHAR* pBuffer,
  1569. IN BOOLEAN fControl,
  1570. IN BOOLEAN fReset,
  1571. IN USHORT* pusTunnelId,
  1572. IN USHORT* pusCallId,
  1573. IN USHORT* pusNs,
  1574. IN USHORT usNr )
  1575. // Fill in caller's 'pBuffer' with an L2TP header matching caller's
  1576. // arguments. 'FControl' indicates to build a control header, otherwise a
  1577. // payload header is built. 'fReset' indicates to build a reset rather
  1578. // than a simple acknowledge. Arguments that are not to appear in the
  1579. // header are NULL. Note that 'usNr' is not a pointer because it's
  1580. // appearance in the header is tied to the appearance of 'pusNs'.
  1581. //
  1582. // Returns the total length of the header.
  1583. //
  1584. {
  1585. UNALIGNED USHORT* pusBits;
  1586. UNALIGNED USHORT* pusLength;
  1587. UNALIGNED USHORT* pusCur;
  1588. ULONG ulLength;
  1589. pusCur = (UNALIGNED USHORT* )pBuffer;
  1590. pusBits = pusCur;
  1591. ++pusCur;
  1592. pusLength = pusCur;
  1593. ++pusCur;
  1594. // Initialize header bit mask with the version, and set the length bit
  1595. // since the Length field is always sent.
  1596. //
  1597. *pusBits = HBM_L | VER_L2tp;
  1598. if (fControl)
  1599. {
  1600. ASSERT( pusTunnelId && pusCallId && pusNs && !fReset );
  1601. *pusBits |= HBM_T;
  1602. }
  1603. else if (fReset)
  1604. {
  1605. ASSERT( pusTunnelId && pusCallId && pusNs );
  1606. *pusBits |= HBM_R;
  1607. }
  1608. if (pusTunnelId)
  1609. {
  1610. // Tunnel-ID field present. Draft-05 removes the 'I' bit that used to
  1611. // indicate the Tunnel-ID is present. It is now assumed to be always
  1612. // present.
  1613. //
  1614. *pusCur = htons( *pusTunnelId );
  1615. ++pusCur;
  1616. }
  1617. if (pusCallId)
  1618. {
  1619. // Call-ID field present. Draft-05 removes the 'C' bit that used to
  1620. // indicate the Tunnel-ID is present. It is now assumed to be always
  1621. // present.
  1622. //
  1623. *pusCur = htons( *pusCallId );
  1624. ++pusCur;
  1625. }
  1626. if (pusNs)
  1627. {
  1628. // Ns and Nr fields are present.
  1629. //
  1630. *pusBits |= HBM_F;
  1631. *pusCur = htons( *pusNs );
  1632. ++pusCur;
  1633. *pusCur = htons( usNr );
  1634. ++pusCur;
  1635. }
  1636. // Fill in the header and length fields with the accumulated
  1637. // values.
  1638. //
  1639. *pusBits = htons( *pusBits );
  1640. *pusLength = (USHORT )(((CHAR* )pusCur) - pBuffer);
  1641. ulLength = (ULONG )*pusLength;
  1642. *pusLength = htons( *pusLength );
  1643. return ulLength;
  1644. }
  1645. VOID
  1646. BuildOccnAvps(
  1647. IN TUNNELCB* pTunnel,
  1648. IN VCCB* pVc,
  1649. IN ULONG ulArg1,
  1650. IN ULONG ulArg2,
  1651. IN PVOID pvArg3,
  1652. IN OUT CHAR* pAvpBuffer,
  1653. OUT ULONG* pulAvpLength )
  1654. // PBUILDAVPS handler to add AVPs to an outgoing Outgoing-Call-Connected
  1655. // control message. 'PTunnel' and 'pVc' are the tunnel/VC control blocks.
  1656. // 'UlArgX' and 'pvArg3' are ignored. 'PAvpBuffer' is the address of the buffer to
  1657. // receive the built AVPs. '*PulAvpLength' is set to the length of the
  1658. // built AVPs.
  1659. //
  1660. {
  1661. CHAR* pCurAvp;
  1662. ULONG ulAvpLength;
  1663. ADAPTERCB* pAdapter;
  1664. BOOLEAN fSequencing;
  1665. pAdapter = pTunnel->pAdapter;
  1666. TRACE( TL_V, TM_Send, ( "BuildOccnAvps" ) );
  1667. pCurAvp = pAvpBuffer;
  1668. pCurAvp += BuildAvpUs(
  1669. ATTR_MsgType, TRUE, CMT_OCCN, pCurAvp );
  1670. pCurAvp += BuildAvpUl(
  1671. ATTR_TxConnectSpeed, TRUE, pVc->ulConnectBps, pCurAvp );
  1672. pCurAvp += BuildAvpUl(
  1673. ATTR_FramingType, TRUE, FBM_Sync, pCurAvp );
  1674. fSequencing = !!(ReadFlags( &pVc->ulFlags ) & VCBF_Sequencing);
  1675. if (fSequencing)
  1676. {
  1677. USHORT usRWindow;
  1678. usRWindow = pAdapter->usPayloadReceiveWindow;
  1679. if (!usRWindow)
  1680. {
  1681. usRWindow = L2TP_DefaultReceiveWindow;
  1682. }
  1683. pCurAvp += BuildAvpUs(
  1684. ATTR_RWindowSize, TRUE, usRWindow, pCurAvp );
  1685. }
  1686. #if 0
  1687. // Use the LNS default PPD even when we're LAC, for now.
  1688. //
  1689. pCurAvp += BuildAvpUs(
  1690. ATTR_PacketProcDelay, TRUE, L2TP_LnsDefaultPpd, pCurAvp );
  1691. #endif
  1692. if (fSequencing)
  1693. {
  1694. pCurAvp += BuildAvpFlag(
  1695. ATTR_SequencingRequired, TRUE, pCurAvp );
  1696. }
  1697. *pulAvpLength = (ULONG )(pCurAvp - pAvpBuffer);
  1698. }
  1699. VOID
  1700. BuildOcrpAvps(
  1701. IN TUNNELCB* pTunnel,
  1702. IN VCCB* pVc,
  1703. IN ULONG ulArg1,
  1704. IN ULONG ulArg2,
  1705. IN PVOID pvArg3,
  1706. IN OUT CHAR* pAvpBuffer,
  1707. OUT ULONG* pulAvpLength )
  1708. // PBUILDAVPS handler to add AVPs to an outgoing Outgoing-Call-Reply
  1709. // control message. 'PTunnel' and 'pVc' are the tunnel/VC control blocks.
  1710. // 'UlArgX' and 'pvArg3' are ignored. 'PAvpBuffer' is the address of the buffer to
  1711. // receive the built AVPs. '*PulAvpLength' is set to the length of the
  1712. // built AVPs.
  1713. //
  1714. {
  1715. CHAR* pCurAvp;
  1716. ULONG ulAvpLength;
  1717. TRACE( TL_V, TM_Send, ( "BuildOcrpAvps" ) );
  1718. pCurAvp = pAvpBuffer;
  1719. pCurAvp += BuildAvpUs(
  1720. ATTR_MsgType, TRUE, CMT_OCRP, pCurAvp );
  1721. pCurAvp += BuildAvpUs(
  1722. ATTR_AssignedCallId, TRUE, pVc->usCallId, pCurAvp );
  1723. ASSERT( pVc->pLcParams );
  1724. if (pVc->pLcParams->ulPhysicalChannelId != 0xFFFFFFFF)
  1725. {
  1726. pCurAvp += BuildAvpUl(
  1727. ATTR_PhysicalChannelId, FALSE,
  1728. pVc->pLcParams->ulPhysicalChannelId, pCurAvp );
  1729. }
  1730. *pulAvpLength = (ULONG )(pCurAvp - pAvpBuffer);
  1731. }
  1732. VOID
  1733. BuildOcrqAvps(
  1734. IN TUNNELCB* pTunnel,
  1735. IN VCCB* pVc,
  1736. IN ULONG ulArg1,
  1737. IN ULONG ulArg2,
  1738. IN PVOID pvArg3,
  1739. IN OUT CHAR* pAvpBuffer,
  1740. OUT ULONG* pulAvpLength )
  1741. // PBUILDAVPS handler to add AVPs to an outgoing Outgoing-Call-Request
  1742. // control message. 'PTunnel' and 'pVc' are the tunnel/VC control block.
  1743. // 'UlArgX' are ignored. 'PAvpBuffer' is the address of the buffer to
  1744. // receive the built AVPs. '*PulAvpLength' is set to the length of the
  1745. // built AVPs.
  1746. //
  1747. {
  1748. CHAR* pCurAvp;
  1749. ULONG ulAvpLength;
  1750. ADAPTERCB* pAdapter;
  1751. pAdapter = pTunnel->pAdapter;
  1752. TRACE( TL_V, TM_Send, ( "BuildOcrqAvps" ) );
  1753. pCurAvp = pAvpBuffer;
  1754. pCurAvp += BuildAvpUs(
  1755. ATTR_MsgType, TRUE, CMT_OCRQ, pCurAvp );
  1756. pCurAvp += BuildAvpUs(
  1757. ATTR_AssignedCallId, TRUE, pVc->usCallId, pCurAvp );
  1758. pCurAvp += BuildAvpUl(
  1759. ATTR_CallSerialNumber, TRUE,
  1760. pVc->pLcParams->ulCallSerialNumber, pCurAvp );
  1761. {
  1762. ULONG ulBps;
  1763. ulBps = pVc->pTcParams->ulMinRate;
  1764. if (ulBps == 0)
  1765. {
  1766. ulBps = 1;
  1767. }
  1768. else if (ulBps > 0x7FFFFFFF)
  1769. {
  1770. ulBps = 0x7FFFFFFF;
  1771. }
  1772. pCurAvp += BuildAvpUl(
  1773. ATTR_MinimumBps, TRUE, ulBps, pCurAvp );
  1774. ulBps = pVc->pTcParams->ulMaxRate;
  1775. if (ulBps == 0)
  1776. {
  1777. ulBps = 1;
  1778. }
  1779. else if (ulBps > 0x7FFFFFFF)
  1780. {
  1781. ulBps = 0x7FFFFFFF;
  1782. }
  1783. pCurAvp += BuildAvpUl(
  1784. ATTR_MaximumBps, TRUE, ulBps, pCurAvp );
  1785. }
  1786. {
  1787. ULONG ulBearerType;
  1788. ulBearerType = 0;
  1789. if (pVc->pTcParams->ulMediaMode & LINEMEDIAMODE_DATAMODEM)
  1790. {
  1791. ulBearerType |= BBM_Analog;
  1792. }
  1793. if (pVc->pTcParams->ulMediaMode & LINEMEDIAMODE_DIGITALDATA)
  1794. {
  1795. ulBearerType |= BBM_Digital;
  1796. }
  1797. pCurAvp += BuildAvpUl(
  1798. ATTR_BearerType, TRUE, ulBearerType, pCurAvp );
  1799. }
  1800. pCurAvp += BuildAvpUl(
  1801. ATTR_FramingType, TRUE, FBM_Sync, pCurAvp );
  1802. if (ReadFlags( &pVc->ulFlags ) & VCBF_Sequencing)
  1803. {
  1804. ASSERT( pAdapter->usPayloadReceiveWindow );
  1805. pCurAvp += BuildAvpUs(
  1806. ATTR_RWindowSize, TRUE,
  1807. pAdapter->usPayloadReceiveWindow, pCurAvp );
  1808. }
  1809. #if 0
  1810. pCurAvp += BuildAvpUs(
  1811. ATTR_PacketProcDelay, TRUE, L2TP_LnsDefaultPpd, pCurAvp );
  1812. #endif
  1813. *pulAvpLength = (ULONG )(pCurAvp - pAvpBuffer);
  1814. }
  1815. VOID
  1816. BuildScccnAvps(
  1817. IN TUNNELCB* pTunnel,
  1818. IN VCCB* pVc,
  1819. IN ULONG ulArg1,
  1820. IN ULONG ulArg2,
  1821. IN PVOID pvArg3,
  1822. IN OUT CHAR* pAvpBuffer,
  1823. OUT ULONG* pulAvpLength )
  1824. // PBUILDAVPS handler to add AVPs to an outgoing Start-Cc-Connected
  1825. // control message. 'PTunnel' is the tunnel control block. 'PVc' is
  1826. // ignored. 'UlArg1' is the true if a challenge response is to be sent,
  1827. // false otherwise. 'UlArg2' and 'pvArg3' are ignored. 'PAvpBuffer' is
  1828. // the address of the buffer to receive the built AVPs. '*PulAvpLength'
  1829. // is set to the length of the built AVPs.
  1830. //
  1831. {
  1832. CHAR* pCurAvp;
  1833. ULONG ulAvpLength;
  1834. TRACE( TL_V, TM_Send, ( "BuildScccnAvps" ) );
  1835. pCurAvp = pAvpBuffer;
  1836. pCurAvp += BuildAvpUs(
  1837. ATTR_MsgType, TRUE, CMT_SCCCN, pCurAvp );
  1838. if (ulArg1)
  1839. {
  1840. pCurAvp += BuildAvpAch(
  1841. ATTR_ChallengeResponse, TRUE,
  1842. pTunnel->achResponseToSend, sizeof(pTunnel->achResponseToSend),
  1843. pCurAvp );
  1844. }
  1845. *pulAvpLength = (ULONG )(pCurAvp - pAvpBuffer);
  1846. }
  1847. VOID
  1848. BuildSccrpAvps(
  1849. IN TUNNELCB* pTunnel,
  1850. IN VCCB* pVc,
  1851. IN ULONG ulArg1,
  1852. IN ULONG ulArg2,
  1853. IN PVOID pvArg3,
  1854. IN OUT CHAR* pAvpBuffer,
  1855. OUT ULONG* pulAvpLength )
  1856. // PBUILDAVPS handler to add AVPs to an outgoing Start-Cc-Reply control
  1857. // message. 'PTunnel' is the tunnel control block. 'PVc' is ignored.
  1858. // 'UlArg1' is true if a challenge response is to be sent, false
  1859. // otherwise. 'UlArg2' and 'pvArg3' are ignored. 'PAvpBuffer' is the
  1860. // address of the buffer to receive the built AVPs. '*PulAvpLength' is
  1861. // set to the length of the built AVPs.
  1862. //
  1863. {
  1864. CHAR* pCurAvp;
  1865. ULONG ulAvpLength;
  1866. ADAPTERCB* pAdapter;
  1867. TRACE( TL_N, TM_Send, ( "BuildSccrpAvps" ) );
  1868. pAdapter = pTunnel->pAdapter;
  1869. pCurAvp = pAvpBuffer;
  1870. pCurAvp += BuildAvpUs(
  1871. ATTR_MsgType, TRUE, CMT_SCCRP, pCurAvp );
  1872. pCurAvp += BuildAvpUs(
  1873. ATTR_ProtocolVersion, TRUE, L2TP_ProtocolVersion, pCurAvp );
  1874. pCurAvp += BuildAvpUl(
  1875. ATTR_FramingCaps, TRUE, pAdapter->ulFramingCaps, pCurAvp );
  1876. pCurAvp += BuildAvpUl(
  1877. ATTR_BearerCaps, TRUE, pAdapter->ulBearerCaps, pCurAvp );
  1878. pCurAvp += BuildAvpUs(
  1879. ATTR_FirmwareRevision, FALSE, L2TP_FirmwareRevision, pCurAvp );
  1880. ASSERT( pAdapter->pszHostName );
  1881. pCurAvp += BuildAvpAch(
  1882. ATTR_HostName, TRUE,
  1883. pAdapter->pszHostName,
  1884. (USHORT )strlen( pAdapter->pszHostName ),
  1885. pCurAvp );
  1886. pCurAvp += BuildAvpAch(
  1887. ATTR_VendorName, FALSE,
  1888. L2TP_VendorName, (USHORT )strlen( L2TP_VendorName ), pCurAvp );
  1889. pCurAvp += BuildAvpUs(
  1890. ATTR_AssignedTunnelId, TRUE, pTunnel->usTunnelId, pCurAvp );
  1891. if (pAdapter->usControlReceiveWindow)
  1892. {
  1893. pCurAvp += BuildAvpUs(
  1894. ATTR_RWindowSize, TRUE,
  1895. pAdapter->usControlReceiveWindow, pCurAvp );
  1896. }
  1897. if (pAdapter->pszPassword)
  1898. {
  1899. pCurAvp += BuildAvpAch(
  1900. ATTR_Challenge, TRUE,
  1901. pTunnel->achChallengeToSend,
  1902. sizeof(pTunnel->achChallengeToSend),
  1903. pCurAvp );
  1904. }
  1905. if (ulArg1)
  1906. {
  1907. pCurAvp += BuildAvpAch(
  1908. ATTR_ChallengeResponse, TRUE,
  1909. pTunnel->achResponseToSend,
  1910. sizeof(pTunnel->achResponseToSend),
  1911. pCurAvp );
  1912. }
  1913. *pulAvpLength = (ULONG )(pCurAvp - pAvpBuffer);
  1914. }
  1915. VOID
  1916. BuildSccrqAvps(
  1917. IN TUNNELCB* pTunnel,
  1918. IN VCCB* pVc,
  1919. IN ULONG ulArg1,
  1920. IN ULONG ulArg2,
  1921. IN PVOID pvArg3,
  1922. IN OUT CHAR* pAvpBuffer,
  1923. OUT ULONG* pulAvpLength )
  1924. // PBUILDAVPS handler to add AVPs to an outgoing Start-Cc-Request control
  1925. // message. 'PTunnel' is the tunnel control block. 'PVc', 'ulArgX' and 'pvArg3'
  1926. // are ignored. 'PAvpBuffer' is the address of the buffer to receive the
  1927. // built AVPs. '*PulAvpLength' is set to the length of the built AVPs.
  1928. //
  1929. {
  1930. CHAR* pCurAvp;
  1931. ULONG ulAvpLength;
  1932. ADAPTERCB* pAdapter;
  1933. TRACE( TL_V, TM_Send, ( "BuildSccrqAvps" ) );
  1934. pAdapter = pTunnel->pAdapter;
  1935. pCurAvp = pAvpBuffer;
  1936. pCurAvp += BuildAvpUs(
  1937. ATTR_MsgType, TRUE, CMT_SCCRQ, pCurAvp );
  1938. pCurAvp += BuildAvpUs(
  1939. ATTR_ProtocolVersion, TRUE, L2TP_ProtocolVersion, pCurAvp );
  1940. pCurAvp += BuildAvpUl(
  1941. ATTR_FramingCaps, TRUE, pAdapter->ulFramingCaps, pCurAvp );
  1942. pCurAvp += BuildAvpUl(
  1943. ATTR_BearerCaps, TRUE, pAdapter->ulBearerCaps, pCurAvp );
  1944. pCurAvp += BuildAvpUs(
  1945. ATTR_FirmwareRevision, FALSE, L2TP_FirmwareRevision, pCurAvp );
  1946. if (pAdapter->pszHostName)
  1947. {
  1948. pCurAvp += BuildAvpAch(
  1949. ATTR_HostName, TRUE,
  1950. pAdapter->pszHostName,
  1951. (USHORT )strlen( pAdapter->pszHostName ),
  1952. pCurAvp );
  1953. }
  1954. pCurAvp += BuildAvpAch(
  1955. ATTR_VendorName, FALSE,
  1956. L2TP_VendorName, (USHORT )strlen( L2TP_VendorName ), pCurAvp );
  1957. pCurAvp += BuildAvpUs(
  1958. ATTR_AssignedTunnelId, TRUE, pTunnel->usTunnelId, pCurAvp );
  1959. if (pAdapter->usControlReceiveWindow)
  1960. {
  1961. pCurAvp += BuildAvpUs(
  1962. ATTR_RWindowSize, TRUE, pAdapter->usControlReceiveWindow, pCurAvp );
  1963. }
  1964. if (pAdapter->pszPassword)
  1965. {
  1966. pCurAvp += BuildAvpAch(
  1967. ATTR_Challenge, TRUE,
  1968. pTunnel->achChallengeToSend,
  1969. sizeof(pTunnel->achChallengeToSend),
  1970. pCurAvp );
  1971. }
  1972. *pulAvpLength = (ULONG )(pCurAvp - pAvpBuffer);
  1973. }
  1974. VOID
  1975. BuildStopccnAvps(
  1976. IN TUNNELCB* pTunnel,
  1977. IN VCCB* pVc,
  1978. IN ULONG ulArg1,
  1979. IN ULONG ulArg2,
  1980. IN PVOID pvArg3,
  1981. IN OUT CHAR* pAvpBuffer,
  1982. OUT ULONG* pulAvpLength )
  1983. // PBUILDAVPS handler to add AVPs to an outgoing Stop-Cc-Notify control
  1984. // message. 'PTunnel' is the tunnel control block. 'PVc' is ignored.
  1985. // 'ulArg1' and 'ulArg2' are the result and error codes to be sent.
  1986. // 'pvArg3' is ignored. 'PAvpBuffer' is the address of the buffer to
  1987. // receive the built AVPs. '*PulAvpLength' is set to the length of the
  1988. // built AVPs.
  1989. //
  1990. {
  1991. CHAR* pCurAvp;
  1992. ULONG ulAvpLength;
  1993. USHORT usResult;
  1994. USHORT usError;
  1995. TRACE( TL_V, TM_Send, ( "BuildStopCcReqAvps" ) );
  1996. usResult = (USHORT )ulArg1;
  1997. usError = (USHORT )ulArg2;
  1998. pCurAvp = pAvpBuffer;
  1999. pCurAvp += BuildAvpUs(
  2000. ATTR_MsgType, TRUE, CMT_StopCCN, pCurAvp );
  2001. pCurAvp += BuildAvpUs(
  2002. ATTR_AssignedTunnelId, TRUE, pTunnel->usTunnelId, pCurAvp );
  2003. pCurAvp += BuildAvp2UsAndAch(
  2004. ATTR_Result, TRUE, usResult, usError, NULL, 0, pCurAvp );
  2005. *pulAvpLength = (ULONG )(pCurAvp - pAvpBuffer);
  2006. }
  2007. VOID
  2008. BuildWenAvps(
  2009. IN TUNNELCB* pTunnel,
  2010. IN VCCB* pVc,
  2011. IN ULONG ulArg1,
  2012. IN ULONG ulArg2,
  2013. IN PVOID pvArg3,
  2014. IN OUT CHAR* pAvpBuffer,
  2015. OUT ULONG* pulAvpLength )
  2016. // PBUILDAVPS handler to add AVPs to an outgoing Wan-Error-Notify control
  2017. // message. 'PTunnel' and 'pVc' are the tunnel/VC control block.
  2018. // 'pvArg3' is the address of an array of 6 error ULONGs, i.e. CRC,
  2019. // framing, hardware overrun, buffer overrun, timeouts, and alignment
  2020. // errors that this routine FREE_NONPAGEDs after use. 'ulArgX' are ignored.
  2021. // 'PAvpBuffer' is the address of the buffer to
  2022. // receive the built AVPs. '*PulAvpLength' is set to the length of the
  2023. // built AVPs.
  2024. //
  2025. {
  2026. CHAR* pCurAvp;
  2027. ULONG ulAvpLength;
  2028. ADAPTERCB* pAdapter;
  2029. UNALIGNED ULONG* pul;
  2030. pAdapter = pTunnel->pAdapter;
  2031. pul = (UNALIGNED ULONG* )pvArg3;
  2032. TRACE( TL_V, TM_Send, ( "BuildWenAvps" ) );
  2033. pCurAvp = pAvpBuffer;
  2034. pCurAvp += BuildAvpUs(
  2035. ATTR_MsgType, TRUE, CMT_WEN, pCurAvp );
  2036. pCurAvp += BuildAvpAul(
  2037. ATTR_CallErrors, TRUE, pul, 6, pCurAvp );
  2038. FREE_NONPAGED( pul );
  2039. *pulAvpLength = (ULONG )(pCurAvp - pAvpBuffer);
  2040. }
  2041. VOID
  2042. CompletePayloadSent(
  2043. IN TUNNELWORK* pWork,
  2044. IN TUNNELCB* pTunnel,
  2045. IN VCCB* pVc,
  2046. IN ULONG_PTR* punpArgs )
  2047. // A PTUNNELWORK routine to complete a "sent payload". Arg0 is the
  2048. // PAYLOADSENT context which has already been de-queued from the
  2049. // "outstanding send" list.
  2050. //
  2051. // This routine is called only at PASSIVE IRQL.
  2052. //
  2053. {
  2054. NDIS_STATUS status;
  2055. ADAPTERCB* pAdapter;
  2056. PAYLOADSENT* pPs;
  2057. NDIS_BUFFER* pNdisBuffer;
  2058. // Unpack context information then free the work item.
  2059. //
  2060. pAdapter = pTunnel->pAdapter;
  2061. pPs = (PAYLOADSENT* )(punpArgs[ 0 ]);
  2062. FREE_TUNNELWORK( pAdapter, pWork );
  2063. TRACE( TL_N, TM_Send, ( "CompletePayloadSent(Ns=%d)", (UINT )pPs->usNs ) );
  2064. // Undo the adjustments made before the send so the owner of each
  2065. // component resource gets back what they originally provided for clean-up
  2066. // and recycling.
  2067. //
  2068. NdisUnchainBufferAtFront( pPs->pPacket, &pNdisBuffer );
  2069. NdisAdjustBufferLength(
  2070. pNdisBuffer, BufferSizeFromBuffer( pPs->pBuffer ) );
  2071. FreeBufferToPool( &pAdapter->poolHeaderBuffers, pPs->pBuffer, TRUE );
  2072. // Notify sending driver of the result.
  2073. //
  2074. NDIS_SET_PACKET_STATUS( pPs->pPacket, pPs->status );
  2075. TRACE( TL_N, TM_Send, ("NdisMCoSendComp(s=$%x)", pPs->status ) );
  2076. NdisMCoSendComplete( pPs->status, pPs->pVc->NdisVcHandle, pPs->pPacket );
  2077. TRACE( TL_N, TM_Send, ("NdisMCoSendComp done" ) );
  2078. DereferenceCall( pVc );
  2079. DereferenceTunnel( pPs->pTunnel );
  2080. DereferenceVc( pPs->pVc );
  2081. #ifdef PSDEBUG
  2082. {
  2083. extern LIST_ENTRY g_listDebugPs;
  2084. extern NDIS_SPIN_LOCK g_lockDebugPs;
  2085. NdisAcquireSpinLock( &g_lockDebugPs );
  2086. {
  2087. RemoveEntryList( &pPs->linkDebugPs );
  2088. InitializeListHead( &pPs->linkDebugPs );
  2089. }
  2090. NdisReleaseSpinLock( &g_lockDebugPs );
  2091. }
  2092. #endif
  2093. FREE_TIMERQITEM( pAdapter, pPs->pTqiSendTimeout );
  2094. FREE_PAYLOADSENT( pAdapter, pPs );
  2095. }
  2096. VOID
  2097. SendControlComplete(
  2098. IN TDIXCONTEXT* pTdix,
  2099. IN VOID* pContext1,
  2100. IN VOID* pContext2,
  2101. IN CHAR* pBuffer )
  2102. // PTDIXSENDCOMPLETE handler for sends that send only a single buffer from
  2103. // the 'ADAPTERCB.poolFrameBuffers' pool.
  2104. //
  2105. {
  2106. CONTROLSENT* pCs;
  2107. ULONG ulSendTimeoutMs;
  2108. TRACE( TL_V, TM_Send, ( "SendControlComp" ) );
  2109. pCs = (CONTROLSENT* )pContext1;
  2110. pCs->pIrp = NULL;
  2111. // "Instant expire" the timer if the message is longer queued as an
  2112. // outstanding send, i.e. it's been cancelled or terminated. This is the
  2113. // easiest way to clean up quickly yet reliably in this odd case.
  2114. // Accessing the link and the send timeout without locks held is
  2115. // technically not allowed, but the consequence of a misread is just a
  2116. // very slight additional delay. This is judged preferable to adding the
  2117. // cost of taking and releasing a spinlock to every send.
  2118. //
  2119. if (pCs->linkSendsOut.Flink == &pCs->linkSendsOut)
  2120. {
  2121. ulSendTimeoutMs = 0;
  2122. TRACE( TL_A, TM_Send,
  2123. ( "Instant expire pCs=$%p pT=%p", pCs, pCs->pTunnel ) );
  2124. }
  2125. else
  2126. {
  2127. ulSendTimeoutMs = pCs->pTunnel->ulSendTimeoutMs;
  2128. }
  2129. // Schedule a retransmit of the packet, should it go unacknowledged. This
  2130. // occurs here rather than in SendPending to remove any chance of having
  2131. // the same MDL chain outstanding in two separate calls to the IP stack.
  2132. //
  2133. // Note: The logical code commented out below can be omitted for
  2134. // efficiency because the ReferenceControlSent for this scheduled timer
  2135. // and the DereferenceControlSent for this completed send cancel each
  2136. // other out.
  2137. //
  2138. // ReferenceControlSent( pCs );
  2139. // DereferenceControlSent( pCs );
  2140. //
  2141. ASSERT( pCs->pTqiSendTimeout );
  2142. TimerQScheduleItem(
  2143. pCs->pTunnel->pTimerQ,
  2144. pCs->pTqiSendTimeout,
  2145. ulSendTimeoutMs,
  2146. SendControlTimerEvent,
  2147. pCs );
  2148. }
  2149. VOID
  2150. SendControlTimerEvent(
  2151. IN TIMERQITEM* pItem,
  2152. IN VOID* pContext,
  2153. IN TIMERQEVENT event )
  2154. // PTIMERQEVENT handler set to expire when it's time to give up on
  2155. // receiving an acknowledge to the sent control packet indicated by
  2156. // 'pContext'.
  2157. //
  2158. {
  2159. NDIS_STATUS status;
  2160. ADAPTERCB* pAdapter;
  2161. TUNNELCB* pTunnel;
  2162. CONTROLSENT* pCs;
  2163. TRACE( TL_N, TM_Send,
  2164. ( "SendControlTimerEvent(%s)", TimerQPszFromEvent( event ) ) );
  2165. // Unpack context information. The timer item is owned by the "control
  2166. // sent" context and freed indirectly by dereferencing below.
  2167. //
  2168. pCs = (CONTROLSENT* )pContext;
  2169. pTunnel = pCs->pTunnel;
  2170. pAdapter = pTunnel->pAdapter;
  2171. if (event == TE_Expire)
  2172. {
  2173. // Timer expired, meaning it's time to give up on ever receiving an
  2174. // acknowledge to the sent packet. Per the draft/RFC, adjustments to
  2175. // the send window and send timeouts are necessary.
  2176. //
  2177. NdisAcquireSpinLock( &pTunnel->lockT );
  2178. do
  2179. {
  2180. if (pCs->linkSendsOut.Flink == &pCs->linkSendsOut)
  2181. {
  2182. // The context is not on the out queue, so it must have been
  2183. // cancelled or terminated while the expire handling was being
  2184. // set up. Do nothing.
  2185. //
  2186. TRACE( TL_I, TM_Send,
  2187. ( "T%d: Timeout aborted", (ULONG )pTunnel->usTunnelId ) );
  2188. break;
  2189. }
  2190. AdjustTimeoutsAndSendWindowAtTimeout(
  2191. pAdapter->ulMaxSendTimeoutMs,
  2192. pTunnel->lDeviationMs,
  2193. &pTunnel->ulSendTimeoutMs,
  2194. &pTunnel->ulRoundTripMs,
  2195. &pTunnel->ulSendWindow,
  2196. &pTunnel->ulAcksSinceSendTimeout );
  2197. --pTunnel->ulSendsOut;
  2198. ++pCs->ulRetransmits;
  2199. TRACE( TL_I, TM_Send,
  2200. ( "T%d: TIMEOUT(%d) -sout=%d +retry=%d rtt=%d ato=%d sw=%d",
  2201. (ULONG )pTunnel->usTunnelId, (ULONG )pCs->usNs,
  2202. pTunnel->ulSendsOut, pCs->ulRetransmits,
  2203. pTunnel->ulRoundTripMs, pTunnel->ulSendTimeoutMs,
  2204. pTunnel->ulSendWindow ) );
  2205. // Retransmit the packet, or close the tunnel if retries are
  2206. // exhausted.
  2207. //
  2208. if (pCs->ulRetransmits > pAdapter->ulMaxRetransmits)
  2209. {
  2210. // Retries are exhausted. Give up and close the tunnel. No
  2211. // point in trying to be graceful since peer is not
  2212. // responding.
  2213. //
  2214. SetFlags( &pTunnel->ulFlags, TCBF_PeerNotResponding );
  2215. RemoveEntryList( &pCs->linkSendsOut );
  2216. InitializeListHead( &pCs->linkSendsOut );
  2217. DereferenceControlSent( pCs );
  2218. ScheduleTunnelWork(
  2219. pTunnel, NULL, CloseTunnel,
  2220. 0, 0, 0, 0, FALSE, FALSE );
  2221. }
  2222. else
  2223. {
  2224. // Retries remaining. Mark the packet as pending
  2225. // retransmission, then see if the send window allows the
  2226. // retransmit to go now.
  2227. //
  2228. pCs->ulFlags |= CSF_Pending;
  2229. ScheduleTunnelWork(
  2230. pTunnel, NULL, SendPending,
  2231. 0, 0, 0, 0, FALSE, FALSE );
  2232. }
  2233. }
  2234. while (FALSE);
  2235. NdisReleaseSpinLock( &pTunnel->lockT );
  2236. }
  2237. // Remove the reference covering the scheduled timer.
  2238. //
  2239. DereferenceControlSent( pCs );
  2240. }
  2241. VOID
  2242. SendHeaderComplete(
  2243. IN TDIXCONTEXT* pTdix,
  2244. IN VOID* pContext1,
  2245. IN VOID* pContext2,
  2246. IN CHAR* pBuffer )
  2247. // PTDIXSENDCOMPLETE handler for sends that send only a single buffer from
  2248. // the 'ADAPTERCB.poolHeaderBuffers' pool.
  2249. //
  2250. {
  2251. ADAPTERCB* pAdapter;
  2252. VCCB* pVc;
  2253. NDIS_BUFFER* pNdisBuffer;
  2254. TRACE( TL_V, TM_Send, ( "SendHeaderComp" ) );
  2255. pAdapter = (ADAPTERCB* )pContext1;
  2256. pVc = (VCCB* )pContext2;
  2257. // Undo the adjustments made before the send the buffer is ready for
  2258. // re-use.
  2259. //
  2260. pNdisBuffer = NdisBufferFromBuffer( pBuffer );
  2261. NdisAdjustBufferLength( pNdisBuffer, BufferSizeFromBuffer( pBuffer ) );
  2262. FreeBufferToPool( &pAdapter->poolHeaderBuffers, pBuffer, TRUE );
  2263. if (pVc)
  2264. {
  2265. DereferenceCall( pVc );
  2266. }
  2267. }
  2268. VOID
  2269. SendPayloadSeqComplete(
  2270. IN TDIXCONTEXT* pTdix,
  2271. IN VOID* pContext1,
  2272. IN VOID* pContext2,
  2273. IN CHAR* pBuffer )
  2274. // PTDIXSENDCOMPLETE handler for sequenced payloads.
  2275. //
  2276. {
  2277. PAYLOADSENT* pPs;
  2278. TRACE( TL_V, TM_Send, ( "SendPayloadSeqComp" ) );
  2279. pPs = (PAYLOADSENT* )pContext1;
  2280. pPs->pIrp = NULL;
  2281. DereferencePayloadSent( pPs );
  2282. }
  2283. VOID
  2284. SendPayloadUnseqComplete(
  2285. IN TDIXCONTEXT* pTdix,
  2286. IN VOID* pContext1,
  2287. IN VOID* pContext2,
  2288. IN CHAR* pBuffer )
  2289. // PTDIXSENDCOMPLETE handler for unsequenced payloads.
  2290. //
  2291. {
  2292. ADAPTERCB* pAdapter;
  2293. VCCB* pVc;
  2294. NDIS_PACKET* pPacket;
  2295. NDIS_BUFFER* pNdisBuffer;
  2296. TRACE( TL_V, TM_Send, ( "SendPayloadUnseqComp" ) );
  2297. pVc = (VCCB* )pContext1;
  2298. pPacket = (NDIS_PACKET* )pContext2;
  2299. pAdapter = pVc->pAdapter;
  2300. // Undo the adjustments made before the send so the owner of each
  2301. // component resource gets back what they originally provided for clean-up
  2302. // and recycling.
  2303. //
  2304. NdisUnchainBufferAtFront( pPacket, &pNdisBuffer );
  2305. NdisAdjustBufferLength( pNdisBuffer, BufferSizeFromBuffer( pBuffer ) );
  2306. FreeBufferToPool( &pAdapter->poolHeaderBuffers, pBuffer, TRUE );
  2307. // Notify sending driver of the result. Without sequencing, just trying
  2308. // to send it is enough to claim success.
  2309. //
  2310. NDIS_SET_PACKET_STATUS( pPacket, NDIS_STATUS_SUCCESS );
  2311. TRACE( TL_N, TM_Send, ("NdisMCoSendComp($%x)", NDIS_STATUS_SUCCESS ) );
  2312. NdisMCoSendComplete( NDIS_STATUS_SUCCESS, pVc->NdisVcHandle, pPacket );
  2313. TRACE( TL_N, TM_Send, ("NdisMCoSendComp done" ) );
  2314. DereferenceCall( pVc );
  2315. }
  2316. VOID
  2317. SendPayloadTimerEvent(
  2318. IN TIMERQITEM* pItem,
  2319. IN VOID* pContext,
  2320. IN TIMERQEVENT event )
  2321. // PTIMERQEVENT handler set to expire when it's time to give up on
  2322. // receiving an acknowledge to the sent payload packet indicated in the
  2323. // PAYLOADSENT* 'pContext'.
  2324. //
  2325. {
  2326. PAYLOADSENT* pPs;
  2327. ADAPTERCB* pAdapter;
  2328. TUNNELCB* pTunnel;
  2329. VCCB* pVc;
  2330. TRACE( TL_N, TM_Send,
  2331. ( "SendPayloadTimerEvent(%s)", TimerQPszFromEvent( event ) ) );
  2332. // Unpack context information. The timer item is owned by the "payload
  2333. // sent" context and freed indirectly by the de-referencing of that
  2334. // context below.
  2335. //
  2336. pPs = (PAYLOADSENT* )pContext;
  2337. pVc = pPs->pVc;
  2338. pTunnel = pPs->pTunnel;
  2339. pAdapter = pVc->pAdapter;
  2340. if (event == TE_Expire)
  2341. {
  2342. LONG lOldSendWindow;
  2343. LONG lSwChange;
  2344. BOOLEAN fCallActive;
  2345. LINKSTATUSINFO info;
  2346. // Timer expired, meaning it's time to give up on ever receiving an
  2347. // acknowledge to the sent packet.
  2348. //
  2349. NdisAcquireSpinLock( &pVc->lockV );
  2350. do
  2351. {
  2352. if (pPs->linkSendsOut.Flink == &pPs->linkSendsOut)
  2353. {
  2354. // The context is not on the "outstanding send" list, so it
  2355. // must have been cancelled or terminated while the expire
  2356. // handling was being set up. Do nothing.
  2357. //
  2358. TRACE( TL_I, TM_Send,
  2359. ( "C%d: Timeout aborted", (ULONG )pVc->usCallId ) );
  2360. fCallActive = FALSE;
  2361. break;
  2362. }
  2363. // This packet was not acknowledged.
  2364. //
  2365. pPs->status = NDIS_STATUS_FAILURE;
  2366. // Remove the context from the "outstanding send" list. The
  2367. // corresponding dereference occurs below.
  2368. //
  2369. RemoveEntryList( &pPs->linkSendsOut );
  2370. InitializeListHead( &pPs->linkSendsOut );
  2371. // The rest has to do with call related fields so get a reference
  2372. // now. This is removed by the "reset" send completion.
  2373. //
  2374. fCallActive = ReferenceCall( pVc );
  2375. if (fCallActive)
  2376. {
  2377. // Per the draft/RFC, adjustments to the send window and send
  2378. // timeouts are necessary when a send times out.
  2379. //
  2380. lOldSendWindow = (LONG )pVc->ulSendWindow;
  2381. AdjustTimeoutsAndSendWindowAtTimeout(
  2382. pAdapter->ulMaxSendTimeoutMs,
  2383. pVc->lDeviationMs,
  2384. &pVc->ulSendTimeoutMs,
  2385. &pVc->ulRoundTripMs,
  2386. &pVc->ulSendWindow,
  2387. &pVc->ulAcksSinceSendTimeout );
  2388. lSwChange = ((LONG )pVc->ulSendWindow) - lOldSendWindow;
  2389. TRACE( TL_I, TM_Send,
  2390. ( "C%d: TIMEOUT(%d) new rtt=%d ato=%d sw=%d(%+d)",
  2391. (ULONG )pVc->usCallId, (ULONG )pPs->usNs,
  2392. pVc->ulRoundTripMs, pVc->ulSendTimeoutMs,
  2393. pVc->ulSendWindow, lSwChange ) );
  2394. if (lSwChange != 0)
  2395. {
  2396. // The send window changed, i.e. it closed some because of
  2397. // the timeout. Update the statistics accordingly.
  2398. //
  2399. ++pVc->stats.ulSendWindowChanges;
  2400. if (pVc->ulSendWindow > pVc->stats.ulMaxSendWindow)
  2401. {
  2402. pVc->stats.ulMaxSendWindow = pVc->ulSendWindow;
  2403. }
  2404. else if (pVc->ulSendWindow < pVc->stats.ulMinSendWindow)
  2405. {
  2406. pVc->stats.ulMinSendWindow = pVc->ulSendWindow;
  2407. }
  2408. // Need to release the lock before indicating the link
  2409. // status change outside our driver, so make a "safe" copy
  2410. // of the link status information.
  2411. //
  2412. TransferLinkStatusInfo( pVc, &info );
  2413. }
  2414. // Send a zero length payload with the R-bit set to reset the
  2415. // peer's Nr to the packet after this one. The call reference
  2416. // will be removed when the send completes.
  2417. //
  2418. ScheduleTunnelWork(
  2419. pTunnel, pVc, SendPayloadReset,
  2420. (ULONG_PTR )(pPs->usNs + 1), 0, 0, 0, FALSE, FALSE );
  2421. ++pVc->stats.ulSentResets;
  2422. ++pVc->stats.ulSentPacketsTimedOut;
  2423. }
  2424. // Remove the reference for linkage in the "outstanding send"
  2425. // list.
  2426. //
  2427. DereferencePayloadSent( pPs );
  2428. }
  2429. while (FALSE);
  2430. NdisReleaseSpinLock( &pVc->lockV );
  2431. if (fCallActive && lSwChange != 0)
  2432. {
  2433. // Inform NDISWAN of the new send window since it's the component
  2434. // that actually does the throttling.
  2435. //
  2436. IndicateLinkStatus( pVc, &info );
  2437. }
  2438. }
  2439. // Remove the reference covering the scheduled timer event.
  2440. //
  2441. DereferencePayloadSent( pPs );
  2442. }
  2443. VOID
  2444. SendZlb(
  2445. IN TUNNELCB* pTunnel,
  2446. IN VCCB* pVc,
  2447. IN USHORT usNs,
  2448. IN USHORT usNr,
  2449. IN BOOLEAN fReset )
  2450. // Send a data-less packet with sequence 'usNs' and 'usNr' on 'pTunnel'.
  2451. // 'PVc' is the associated VC, or NULL if none. When 'pVc' is provided,
  2452. // 'fReset' may be set to indicate a payload reset is to be built,
  2453. // otherwise a simple acknowledge is built.
  2454. //
  2455. // This routine is called only at PASSIVE IRQL.
  2456. //
  2457. // IMPORTANT: Caller must take a call reference before calling that is
  2458. // removed by the send completion handler.
  2459. //
  2460. {
  2461. NDIS_STATUS status;
  2462. ADAPTERCB* pAdapter;
  2463. CHAR* pBuffer;
  2464. ULONG ulLength;
  2465. USHORT usAssignedCallId;
  2466. BOOLEAN fControl;
  2467. NDIS_BUFFER* pNdisBuffer;
  2468. pAdapter = pTunnel->pAdapter;
  2469. usAssignedCallId = (pVc) ? pVc->usAssignedCallId : 0;
  2470. fControl = (usAssignedCallId == 0);
  2471. ASSERT( !(fReset && fControl) );
  2472. if (!fControl && !(ReadFlags( &pTunnel->ulFlags ) & TCBF_HostRouteAdded))
  2473. {
  2474. TRACE( TL_A, TM_Send, ( "SendZlb w/o host route?" ) );
  2475. ++g_ulSendZlbWithoutHostRoute;
  2476. if (pVc)
  2477. {
  2478. DereferenceCall( pVc );
  2479. }
  2480. return;
  2481. }
  2482. // Get an NDIS_BUFFER to hold the L2TP header.
  2483. //
  2484. pBuffer = GetBufferFromPool( &pAdapter->poolHeaderBuffers );
  2485. if (!pBuffer)
  2486. {
  2487. ASSERT( "GetBfP?" );
  2488. if (pVc)
  2489. {
  2490. DereferenceCall( pVc );
  2491. }
  2492. return;
  2493. }
  2494. // Fill in 'pBuffer' with the L2TP header.
  2495. //
  2496. ulLength =
  2497. BuildL2tpHeader(
  2498. pBuffer,
  2499. fControl,
  2500. fReset,
  2501. &pTunnel->usAssignedTunnelId,
  2502. &usAssignedCallId,
  2503. &usNs,
  2504. usNr );
  2505. // Pare down the buffer to the actual length used.
  2506. //
  2507. pNdisBuffer = NdisBufferFromBuffer( pBuffer );
  2508. NdisAdjustBufferLength( pNdisBuffer, (UINT )ulLength );
  2509. // Call TDI to send the bare L2TP header.
  2510. //
  2511. TRACE( TL_A, TM_Msg,
  2512. ( "%sSEND ZLB(Nr=%d) CID=%d R=%d",
  2513. (g_ulTraceLevel <= TL_I) ? "" : "\nL2TP: ",
  2514. (ULONG )usNr, (ULONG )usAssignedCallId, (ULONG )fReset ) );
  2515. DUMPW( TL_A, TM_MDmp, pBuffer, ulLength );
  2516. {
  2517. PTDIX_SEND_HANDLER SendFunc;
  2518. FILE_OBJECT* FileObj;
  2519. if (ReadFlags(&pTunnel->ulFlags) & TCBF_SendConnected) {
  2520. ASSERT(pTunnel->pRoute != NULL);
  2521. SendFunc = TdixSend;
  2522. if (fControl)
  2523. {
  2524. FileObj =
  2525. CtrlObjFromUdpContext(&pTunnel->udpContext);
  2526. }
  2527. else
  2528. {
  2529. FileObj =
  2530. PayloadObjFromUdpContext(&pTunnel->udpContext);
  2531. }
  2532. } else {
  2533. FileObj = NULL;
  2534. SendFunc = TdixSendDatagram;
  2535. }
  2536. status =
  2537. SendFunc(
  2538. &pAdapter->tdix,
  2539. FileObj,
  2540. SendHeaderComplete,
  2541. pAdapter,
  2542. pVc,
  2543. &pTunnel->address.ulIpAddress,
  2544. pBuffer,
  2545. ulLength,
  2546. NULL );
  2547. }
  2548. ASSERT( status == NDIS_STATUS_PENDING );
  2549. }
  2550. VOID
  2551. UpdateControlHeaderNr(
  2552. IN CHAR* pBuffer,
  2553. IN USHORT usNr )
  2554. // Updates the 'Next Receive' field of control message buffer 'pBuffer'
  2555. // with the value 'usNr'.
  2556. //
  2557. {
  2558. USHORT* pusNr;
  2559. // Fortunately, the control header up to 'Next Receive' is fixed so a
  2560. // simple offset calculation can be used.
  2561. //
  2562. pusNr = ((USHORT* )pBuffer) + 5;
  2563. *pusNr = htons( usNr );
  2564. }
  2565. VOID
  2566. UpdateHeaderLength(
  2567. IN CHAR* pBuffer,
  2568. IN USHORT usLength )
  2569. // Updates the 'Length' field of the L2TP message buffer 'pBuffer' to the
  2570. // value 'usLength'.
  2571. //
  2572. {
  2573. USHORT* pusLength;
  2574. // Fortunately, the control header up to 'Length' is fixed so a simple
  2575. // offset calculation can be used.
  2576. //
  2577. pusLength = ((USHORT* )pBuffer) + 1;
  2578. *pusLength = htons( usLength );
  2579. }