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.

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