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.

2171 lines
67 KiB

  1. // Copyright (c) 1997, Microsoft Corporation, all rights reserved
  2. //
  3. // fsm.c
  4. // RAS L2TP WAN mini-port/call-manager driver
  5. // L2TP finite state machine routines
  6. //
  7. // 01/07/97 Steve Cobb
  8. #include "l2tpp.h"
  9. #include "fsm.tmh"
  10. //-----------------------------------------------------------------------------
  11. // Local prototypes (alphabetically)
  12. //-----------------------------------------------------------------------------
  13. VOID
  14. FsmInCallIdle(
  15. IN TUNNELCB* pTunnel,
  16. IN VCCB* pVc,
  17. IN CONTROLMSGINFO* pControl );
  18. VOID
  19. FsmInCallWaitConnect(
  20. IN TUNNELCB* pTunnel,
  21. IN VCCB* pVc,
  22. IN CONTROLMSGINFO* pControl );
  23. VOID
  24. FsmInCallEstablished(
  25. IN TUNNELCB* pTunnel,
  26. IN VCCB* pVc,
  27. IN CONTROLMSGINFO* pControl );
  28. VOID
  29. FsmInCallWaitReply(
  30. IN TUNNELCB* pTunnel,
  31. IN VCCB* pVc,
  32. IN CONTROLMSGINFO* pControl );
  33. VOID
  34. FsmOutCallBearerAnswer(
  35. IN TUNNELCB* pTunnel,
  36. IN VCCB* pVc );
  37. VOID
  38. FsmOutCallEstablished(
  39. IN TUNNELCB* pTunnel,
  40. IN VCCB* pVc,
  41. IN CONTROLMSGINFO* pControl );
  42. VOID
  43. FsmOutCallIdle(
  44. IN TUNNELCB* pTunnel,
  45. IN VCCB* pVc,
  46. IN CONTROLMSGINFO* pControl );
  47. VOID
  48. FsmOutCallWaitReply(
  49. IN TUNNELCB* pTunnel,
  50. IN VCCB* pVc,
  51. IN CONTROLMSGINFO* pControl );
  52. VOID
  53. FsmOutCallWaitConnect(
  54. IN TUNNELCB* pTunnel,
  55. IN VCCB* pVc,
  56. IN CONTROLMSGINFO* pControl );
  57. VOID
  58. FsmTunnelEstablished(
  59. IN TUNNELCB* pTunnel,
  60. IN CONTROLMSGINFO* pControl );
  61. VOID
  62. FsmTunnelIdle(
  63. IN TUNNELCB* pTunnel,
  64. IN CONTROLMSGINFO* pControl );
  65. VOID
  66. FsmTunnelWaitCtlConnect(
  67. IN TUNNELCB* pTunnel,
  68. IN CONTROLMSGINFO* pControl );
  69. VOID
  70. FsmTunnelWaitCtlReply(
  71. IN TUNNELCB* pTunnel,
  72. IN CONTROLMSGINFO* pControl );
  73. VOID
  74. GetCcAvps(
  75. IN TUNNELCB* pTunnel,
  76. IN CONTROLMSGINFO* pControl,
  77. OUT USHORT* pusResult,
  78. OUT USHORT* pusError );
  79. ULONG
  80. StatusFromResultAndError(
  81. IN USHORT usResult,
  82. IN USHORT usError );
  83. //-----------------------------------------------------------------------------
  84. // FSM interface routines
  85. //-----------------------------------------------------------------------------
  86. BOOLEAN
  87. FsmReceive(
  88. IN TUNNELCB* pTunnel,
  89. IN VCCB* pVc,
  90. IN CHAR* pBuffer,
  91. IN CONTROLMSGINFO* pControl )
  92. // Dispatches a received control message to the appropriate FSM handler.
  93. // 'PTunnel' and 'pVc' are the tunnel and VC control blocks. 'PControl'
  94. // is the exploded description of the received control message. 'PBuffer'
  95. // is the receieve buffer.
  96. //
  97. // IMPORTANT: Caller must hold 'pTunnel->lockT'.
  98. //
  99. // Returns true if the message was processed, false if
  100. // SetupVcAsynchronously was called.
  101. //
  102. {
  103. TRACE( TL_V, TM_Cm, ( "FsmReceive" ) );
  104. if (pControl->fTunnelMsg)
  105. {
  106. switch (pTunnel->state)
  107. {
  108. case CCS_Idle:
  109. {
  110. FsmTunnelIdle( pTunnel, pControl );
  111. break;
  112. }
  113. case CCS_WaitCtlReply:
  114. {
  115. FsmTunnelWaitCtlReply( pTunnel, pControl );
  116. break;
  117. }
  118. case CCS_WaitCtlConnect:
  119. {
  120. FsmTunnelWaitCtlConnect( pTunnel, pControl );
  121. break;
  122. }
  123. case CCS_Established:
  124. {
  125. FsmTunnelEstablished( pTunnel, pControl );
  126. break;
  127. }
  128. }
  129. }
  130. else
  131. {
  132. if (!pVc)
  133. {
  134. if (*(pControl->pusMsgType) == CMT_ICRQ
  135. || *(pControl->pusMsgType) == CMT_OCRQ)
  136. {
  137. ULONG ulIpAddress;
  138. // Check if the MUST AVPs are present
  139. if(!pControl->pusAssignedCallId ||
  140. !pControl->pulCallSerialNumber)
  141. {
  142. return TRUE;
  143. }
  144. // Peer wants to start a new call. Set up a VC and dispatch
  145. // the received call request to the client above. This is an
  146. // asynchronous operation that will eventually call
  147. // ReceiveControlExpected to finish processing the message.
  148. //
  149. ulIpAddress = pTunnel->address.ulIpAddress;
  150. NdisReleaseSpinLock( &pTunnel->lockT );
  151. {
  152. SetupVcAsynchronously(
  153. pTunnel, ulIpAddress, pBuffer, pControl );
  154. }
  155. NdisAcquireSpinLock( &pTunnel->lockT );
  156. return FALSE;
  157. }
  158. else
  159. {
  160. // Don't know what VC the call control message if for and it's
  161. // not a "create new call" request, so there's nothing useful
  162. // to do. Ignore it. Don't want to bring down the tunnel
  163. // because it may just be out of order. One case is where
  164. // post-ICRQ packets are received before ICRQ is processed, to
  165. // create the VC block.
  166. //
  167. TRACE( TL_A, TM_Fsm, ( "CMT %d w/o VC?", *(pControl->pusMsgType) ) );
  168. WPLOG( LL_A, LM_Fsm, ( "CMT %d w/o VC?", *(pControl->pusMsgType) ) );
  169. return TRUE;
  170. }
  171. }
  172. NdisAcquireSpinLock( &pVc->lockV );
  173. {
  174. if (ReadFlags( &pVc->ulFlags ) & VCBF_IncomingFsm)
  175. {
  176. // L2TP Incoming Call FSM for both LAC/LNS.
  177. //
  178. switch (pVc->state)
  179. {
  180. case CS_Idle:
  181. {
  182. FsmInCallIdle( pTunnel, pVc, pControl );
  183. break;
  184. }
  185. case CS_WaitReply:
  186. {
  187. FsmInCallWaitReply( pTunnel, pVc, pControl );
  188. break;
  189. }
  190. case CS_WaitConnect:
  191. {
  192. FsmInCallWaitConnect( pTunnel, pVc, pControl );
  193. break;
  194. }
  195. case CS_Established:
  196. {
  197. FsmInCallEstablished( pTunnel, pVc, pControl );
  198. break;
  199. }
  200. }
  201. }
  202. else
  203. {
  204. // L2TP Outgoing Call FSM for both LAC/LNS.
  205. //
  206. switch (pVc->state)
  207. {
  208. case CS_Idle:
  209. {
  210. FsmOutCallIdle( pTunnel, pVc, pControl );
  211. break;
  212. }
  213. case CS_WaitReply:
  214. {
  215. FsmOutCallWaitReply( pTunnel, pVc, pControl );
  216. break;
  217. }
  218. case CS_WaitConnect:
  219. {
  220. FsmOutCallWaitConnect( pTunnel, pVc, pControl );
  221. break;
  222. }
  223. case CS_WaitCsAnswer:
  224. {
  225. // Because no WAN modes are supported and locks are
  226. // held during the "null" WAN bearer answer, we should
  227. // never be in this state on a received message.
  228. //
  229. ASSERT( FALSE );
  230. break;
  231. }
  232. case CS_Established:
  233. {
  234. FsmOutCallEstablished( pTunnel, pVc, pControl );
  235. break;
  236. }
  237. }
  238. }
  239. }
  240. NdisReleaseSpinLock( &pVc->lockV );
  241. }
  242. return TRUE;
  243. }
  244. VOID
  245. FsmOpenTunnel(
  246. IN TUNNELWORK* pWork,
  247. IN TUNNELCB* pTunnel,
  248. IN VCCB* pVc,
  249. IN ULONG_PTR* punpArgs )
  250. // A PTUNNELWORK routine to handle a Control Connection (tunnel) Open
  251. // event.
  252. //
  253. // This routine is called only at PASSIVE IRQL.
  254. //
  255. {
  256. NDIS_STATUS status;
  257. ADAPTERCB* pAdapter;
  258. TRACE( TL_N, TM_Fsm, ( "FsmOpenTunnel" ) );
  259. // Unpack context information then free the work item.
  260. //
  261. pAdapter = pVc->pAdapter;
  262. FREE_TUNNELWORK( pAdapter, pWork );
  263. status = NDIS_STATUS_SUCCESS;
  264. if (!(ReadFlags( &pTunnel->ulFlags ) & TCBF_TdixReferenced))
  265. {
  266. // Set up TDI for L2TP send/receive.
  267. //
  268. status = TdixOpen( &pAdapter->tdix );
  269. if (status == NDIS_STATUS_SUCCESS)
  270. {
  271. // Set this flag so TdixClose is called as the tunnel control
  272. // block is destroyed.
  273. //
  274. SetFlags( &pTunnel->ulFlags, TCBF_TdixReferenced );
  275. }
  276. else
  277. {
  278. TRACE( TL_A, TM_Fsm, ( "TdixOpen=$%08x", status ) );
  279. WPLOG( LL_A, LM_Fsm, ( "TdixOpen=$%08x", status ) );
  280. }
  281. }
  282. NdisAcquireSpinLock( &pTunnel->lockT );
  283. {
  284. if (status == NDIS_STATUS_SUCCESS)
  285. {
  286. if (ReadFlags( &pTunnel->ulFlags ) & TCBF_Closing)
  287. {
  288. // New tunnel requests cannot be linked onto closing tunnels
  289. // as they would not be properly cleaned up.
  290. //
  291. TRACE( TL_A, TM_Fsm, ( "FOT aborted" ) );
  292. WPLOG( LL_A, LM_Fsm, ( "Can't open on an aborted tunnel" ) );
  293. status = NDIS_STATUS_TAPI_DISCONNECTMODE_UNKNOWN;
  294. }
  295. }
  296. if (status == NDIS_STATUS_SUCCESS)
  297. {
  298. if (ReadFlags( &pTunnel->ulFlags ) & TCBF_CcInTransition)
  299. {
  300. // The tunnel control channel is in the process of changing
  301. // states from Idle to Established or vice-versa. Queue our
  302. // request to be resolved when the result is known. See
  303. // TunnelTransitionComplete.
  304. //
  305. ASSERT(
  306. pVc->linkRequestingVcs.Flink == &pVc->linkRequestingVcs );
  307. InsertTailList(
  308. &pTunnel->listRequestingVcs, &pVc->linkRequestingVcs );
  309. }
  310. else
  311. {
  312. // The tunnel control channel is in the Idle or Established
  313. // states and no transition is underway.
  314. //
  315. if (pTunnel->state == CCS_Established)
  316. {
  317. // The tunnel control channel is already up, so skip ahead
  318. // to making a call to establish the data channel.
  319. //
  320. WPLOG( LL_M, LM_Fsm, ( "TUNNEL %p established, CALL %p", pTunnel, pVc) );
  321. FsmOpenCall( pTunnel, pVc );
  322. }
  323. else
  324. {
  325. // The tunnel control channel is down, so try to bring it
  326. // up.
  327. //
  328. WPLOG( LL_M, LM_Fsm, ( "TUNNEL %p idle, CALL %p", pTunnel, pVc) );
  329. FsmOpenIdleTunnel( pTunnel, pVc );
  330. }
  331. }
  332. }
  333. else
  334. {
  335. // Fail the call.
  336. //
  337. NdisAcquireSpinLock( &pVc->lockV );
  338. {
  339. pVc->status = status;
  340. CallTransitionComplete( pTunnel, pVc, CS_Idle );
  341. }
  342. NdisReleaseSpinLock( &pVc->lockV );
  343. CompleteVcs( pTunnel );
  344. }
  345. }
  346. NdisReleaseSpinLock( &pTunnel->lockT );
  347. }
  348. VOID
  349. FsmOpenIdleTunnel(
  350. IN TUNNELCB* pTunnel,
  351. IN VCCB* pVc )
  352. // Initiate the tunnel connection on 'pTunnel' requested by 'pVc', i.e.
  353. // send the initial SCCRQ which kicks off the control connection (tunnel)
  354. // FSM.
  355. //
  356. // IMPORTANT: Caller must hold 'pTunnel->lockT'.
  357. //
  358. {
  359. TRACE( TL_N, TM_Cm, ( "FsmOpenIdleTunnel" ) );
  360. ASSERT( pTunnel->state == CCS_Idle );
  361. SetFlags( &pTunnel->ulFlags, TCBF_CcInTransition );
  362. ASSERT( pVc->linkRequestingVcs.Flink == &pVc->linkRequestingVcs );
  363. InsertTailList( &pTunnel->listRequestingVcs, &pVc->linkRequestingVcs );
  364. pTunnel->state = CCS_WaitCtlReply;
  365. SendControl( pTunnel, NULL, CMT_SCCRQ, 0, 0, NULL, 0 );
  366. }
  367. VOID
  368. FsmOpenCall(
  369. IN TUNNELCB* pTunnel,
  370. IN VCCB* pVc )
  371. // Execute an "open" event for a call on 'pTunnel'/'pVc' playing the role
  372. // of the LAC/LNS indicated by the VCBF_IncomingFsm flag. The owning
  373. // tunnel must be established first.
  374. //
  375. {
  376. ULONG ulFlags;
  377. USHORT usMsgType;
  378. ulFlags = ReadFlags( &pVc->ulFlags );
  379. TRACE( TL_N, TM_Cm, ( "FsmCallOpen" ) );
  380. ASSERT( (ulFlags & VCBF_ClientOpenPending)
  381. || (ulFlags & VCBF_PeerOpenPending) );
  382. ASSERT( pVc->state == CS_Idle || pVc->state == CS_WaitTunnel );
  383. ActivateCallIdSlot( pVc );
  384. if (pVc->pAdapter->usPayloadReceiveWindow)
  385. {
  386. SetFlags( &pVc->ulFlags, VCBF_Sequencing );
  387. }
  388. usMsgType = (USHORT )((ulFlags & VCBF_IncomingFsm) ? CMT_ICRQ : CMT_OCRQ );
  389. pVc->state = CS_WaitReply;
  390. SendControl( pTunnel, pVc, usMsgType, 0, 0, NULL, 0 );
  391. }
  392. VOID
  393. FsmCloseTunnel(
  394. IN TUNNELWORK* pWork,
  395. IN TUNNELCB* pTunnel,
  396. IN VCCB* pVc,
  397. IN ULONG_PTR* punpArgs )
  398. // A PTUNNELWORK routine to close down 'pTunnel' gracefully. Arg0 and
  399. // Arg1 are the result and error codes to send in the StopCCN message.
  400. //
  401. // This routine is called only at PASSIVE IRQL.
  402. //
  403. {
  404. USHORT usResult;
  405. USHORT usError;
  406. // Unpack context information, then free the work item.
  407. //
  408. usResult = (USHORT )(punpArgs[ 0 ]);
  409. usError = (USHORT )(punpArgs[ 1 ]);
  410. FREE_TUNNELWORK( pTunnel->pAdapter, pWork );
  411. ASSERT( usResult );
  412. NdisAcquireSpinLock( &pTunnel->lockT );
  413. {
  414. if (pTunnel->state == CCS_Idle
  415. || pTunnel->state == CCS_WaitCtlReply)
  416. {
  417. TRACE( TL_I, TM_Cm,
  418. ( "FsmCloseTunnel(f=$%08x,r=%d,e=%d) now",
  419. ReadFlags( &pTunnel->ulFlags ),
  420. (UINT )usResult, (UINT )usError ) );
  421. // The tunnel's already idle so no closing exchange is necessary.
  422. // We also include the other state where we've had no response
  423. // from peer, but have sent our SCCRQ. This is a tad rude to the
  424. // remote peer as we're deciding that it's more important to
  425. // respond quickly to our cancelling user than it is to wait for a
  426. // peer who may not be responding. However, this is the trade-off
  427. // we've chosen.
  428. //
  429. CloseTunnel2( pTunnel );
  430. }
  431. else
  432. {
  433. TRACE( TL_I, TM_Cm,
  434. ( "FsmCloseTunnel(f=$%08x,r=%d,e=%d) grace",
  435. ReadFlags( &pTunnel->ulFlags ),
  436. (UINT )usResult, (UINT )usError ) );
  437. // Set flags and reference the tunnel for "graceful close". The
  438. // reference is removed when the tunnel reaches idle state.
  439. //
  440. SetFlags( &pTunnel->ulFlags,
  441. (TCBF_Closing | TCBF_FsmCloseRef | TCBF_CcInTransition) );
  442. ReferenceTunnel( pTunnel, FALSE );
  443. // Initiate the closing exchange, holding the VC until the closing
  444. // message is acknowledged.
  445. //
  446. pTunnel->state = CCS_Idle;
  447. SendControl(
  448. pTunnel, NULL, CMT_StopCCN,
  449. (ULONG )usResult, (ULONG )usError, NULL, CSF_TunnelIdleOnAck );
  450. }
  451. }
  452. NdisReleaseSpinLock( &pTunnel->lockT );
  453. }
  454. VOID
  455. FsmCloseCall(
  456. IN TUNNELWORK* pWork,
  457. IN TUNNELCB* pTunnel,
  458. IN VCCB* pVc,
  459. IN ULONG_PTR* punpArgs )
  460. // A PTUNNELWORK routine to close down the call on 'pVc' gracefully. Arg0
  461. // and Arg1 are the result and error codes to send in the CDN message.
  462. //
  463. // This routine is called only at PASSIVE IRQL.
  464. //
  465. {
  466. BOOLEAN fCompleteVcs;
  467. USHORT usResult;
  468. USHORT usError;
  469. // Unpack context information, then free the work item.
  470. //
  471. usResult = (USHORT )(punpArgs[ 0 ]);
  472. usError = (USHORT )(punpArgs[ 1 ]);
  473. FREE_TUNNELWORK( pTunnel->pAdapter, pWork );
  474. ASSERT( usResult );
  475. fCompleteVcs = FALSE;
  476. NdisAcquireSpinLock( &pTunnel->lockT );
  477. {
  478. NdisAcquireSpinLock( &pVc->lockV );
  479. {
  480. if (pVc->state == CS_Idle
  481. || pVc->state == CS_WaitTunnel
  482. || (ReadFlags( &pVc->ulFlags ) & VCBF_PeerClosePending))
  483. {
  484. TRACE( TL_I, TM_Cm,
  485. ( "FsmCloseCall(f=$%08x,r=%d,e=%d) now",
  486. ReadFlags( &pVc->ulFlags ),
  487. (UINT )usResult, (UINT )usError ) );
  488. if (usResult == CRESULT_GeneralWithError)
  489. {
  490. usResult = TRESULT_GeneralWithError;
  491. }
  492. else
  493. {
  494. usResult = TRESULT_Shutdown;
  495. usError = GERR_None;
  496. }
  497. // Slam the call closed.
  498. //
  499. fCompleteVcs = CloseCall2( pTunnel, pVc, usResult, usError );
  500. }
  501. else
  502. {
  503. TRACE( TL_I, TM_Cm,
  504. ( "FsmCloseCall(f=$%08x,r=%d,e=%d) grace",
  505. ReadFlags( &pVc->ulFlags ),
  506. (UINT )usResult, (UINT )usError ) );
  507. // Initiate the closing exchange.
  508. //
  509. pVc->status = NDIS_STATUS_TAPI_DISCONNECTMODE_NORMAL;
  510. pVc->state = CS_Idle;
  511. SendControl(
  512. pTunnel, pVc, CMT_CDN,
  513. (ULONG )usResult, (ULONG )usError, NULL, CSF_CallIdleOnAck );
  514. }
  515. }
  516. NdisReleaseSpinLock( &pVc->lockV );
  517. if (fCompleteVcs)
  518. {
  519. CompleteVcs( pTunnel );
  520. }
  521. }
  522. NdisReleaseSpinLock( &pTunnel->lockT );
  523. }
  524. VOID
  525. TunnelTransitionComplete(
  526. IN TUNNELCB* pTunnel,
  527. IN L2TPCCSTATE state )
  528. // Sets 'pTunnel's state to it's new CCS_Idle or CCS_Established 'state'
  529. // and kickstarts any MakeCall's that pended on the result. If
  530. // established, adds the host route directing IP traffic to the L2TP peer
  531. // to the LAN card rather than the WAN (tunnel) adapter.
  532. //
  533. // IMPORTANT: Caller must hold 'pTunnel->lockT'.
  534. //
  535. {
  536. NDIS_STATUS status;
  537. LIST_ENTRY list;
  538. LIST_ENTRY* pLink;
  539. ULONG ulFlags;
  540. VCCB* pVc;
  541. pTunnel->state = state;
  542. ClearFlags( &pTunnel->ulFlags, TCBF_CcInTransition );
  543. ulFlags = ReadFlags( &pTunnel->ulFlags );
  544. if (state == CCS_Established)
  545. {
  546. TRACE( TL_A, TM_Fsm, ( "TUNNEL %d UP", (ULONG )pTunnel->usTunnelId ) );
  547. WPLOG( LL_M, LM_Fsm, ( "TUNNEL %p UP, Tid %d, Peer's Tid %d",
  548. pTunnel, pTunnel->usTunnelId, pTunnel->usAssignedTunnelId ) );
  549. // The tunnel any requesting VCs wanted established was established.
  550. // Skip ahead to establishing the outgoing calls.
  551. //
  552. while (!IsListEmpty( &pTunnel->listRequestingVcs ))
  553. {
  554. pLink = RemoveHeadList( &pTunnel->listRequestingVcs );
  555. InitializeListHead( pLink );
  556. pVc = CONTAINING_RECORD( pLink, VCCB, linkRequestingVcs );
  557. FsmOpenCall( pTunnel, pVc );
  558. }
  559. // Add the host route so traffic sent to the L2TP peer goes out the
  560. // LAN card instead of looping on the WAN (tunnel) interface, when
  561. // activated.
  562. //
  563. TRACE( TL_N, TM_Recv, ( "Schedule AddHostRoute" ) );
  564. ASSERT( !(ulFlags & TCBF_HostRouteAdded) );
  565. ScheduleTunnelWork(
  566. pTunnel, NULL, AddHostRoute,
  567. 0, 0, 0, 0, FALSE, FALSE );
  568. }
  569. else
  570. {
  571. ASSERT( state == CCS_Idle );
  572. SetFlags( &pTunnel->ulFlags, TCBF_Closing );
  573. TRACE( TL_A, TM_Fsm,
  574. ( "%s TUNNEL %d DOWN",
  575. ((ulFlags & TCBF_PeerInitiated) ? "IN" : "OUT"),
  576. (ULONG )pTunnel->usTunnelId ) );
  577. WPLOG( LL_M, LM_Fsm, ( "%s TUNNEL %p DOWN, Tid %d, Peer's Tid %d",
  578. ((ulFlags & TCBF_PeerInitiated) ? "IN" : "OUT"), pTunnel,
  579. pTunnel->usTunnelId, pTunnel->usAssignedTunnelId ) );
  580. // Any VCs associated with the tunnel are abruptly terminated. This
  581. // is done by making it look like any pending operation has failed, or
  582. // if none is pending, that a bogus peer initiated close has
  583. // completed.
  584. //
  585. NdisAcquireSpinLock( &pTunnel->lockVcs );
  586. {
  587. for (pLink = pTunnel->listVcs.Flink;
  588. pLink != &pTunnel->listVcs;
  589. pLink = pLink->Flink)
  590. {
  591. pVc = CONTAINING_RECORD( pLink, VCCB, linkVcs );
  592. NdisAcquireSpinLock( &pVc->lockV );
  593. {
  594. if (pVc->status == NDIS_STATUS_SUCCESS)
  595. {
  596. if (ulFlags & TCBF_PeerNotResponding)
  597. {
  598. // Line went down because peer stopped responding
  599. // (or never responded).
  600. //
  601. pVc->status =
  602. NDIS_STATUS_TAPI_DISCONNECTMODE_NOANSWER;
  603. }
  604. else
  605. {
  606. // Line went down for unknown reason.
  607. //
  608. pVc->status =
  609. NDIS_STATUS_TAPI_DISCONNECTMODE_UNKNOWN;
  610. }
  611. }
  612. CallTransitionComplete( pTunnel, pVc, CS_Idle );
  613. }
  614. NdisReleaseSpinLock( &pVc->lockV );
  615. }
  616. }
  617. NdisReleaseSpinLock( &pTunnel->lockVcs );
  618. ASSERT( IsListEmpty( &pTunnel->listRequestingVcs ) );
  619. // Flush the outstanding send list.
  620. //
  621. while (!IsListEmpty( &pTunnel->listSendsOut ))
  622. {
  623. CONTROLSENT* pCs;
  624. pLink = RemoveHeadList( &pTunnel->listSendsOut );
  625. InitializeListHead( pLink );
  626. pCs = CONTAINING_RECORD( pLink, CONTROLSENT, linkSendsOut );
  627. TRACE( TL_I, TM_Recv, ( "Flush pCs=$%p", pCs ) );
  628. // Terminate the timer. Doesn't matter if the terminate fails as
  629. // the expire handler recognizes the context is not on the "out"
  630. // list and does nothing.
  631. //
  632. ASSERT( pCs->pTqiSendTimeout );
  633. TimerQTerminateItem( pTunnel->pTimerQ, pCs->pTqiSendTimeout );
  634. // Remove the context reference corresponding to linkage in the
  635. // "out" list. Terminate the
  636. //
  637. DereferenceControlSent( pCs );
  638. }
  639. // Flush the out of order list.
  640. //
  641. while (!IsListEmpty( &pTunnel->listOutOfOrder ))
  642. {
  643. CONTROLRECEIVED* pCr;
  644. ADAPTERCB* pAdapter;
  645. pLink = RemoveHeadList( &pTunnel->listOutOfOrder );
  646. InitializeListHead( pLink );
  647. pCr = CONTAINING_RECORD( pLink, CONTROLRECEIVED, linkOutOfOrder );
  648. TRACE( TL_I, TM_Recv, ( "Flush pCr=$%p", pCr ) );
  649. pAdapter = pTunnel->pAdapter;
  650. FreeBufferToPool( &pAdapter->poolFrameBuffers, pCr->pBuffer, TRUE );
  651. if (pCr->pVc)
  652. {
  653. DereferenceVc( pCr->pVc );
  654. }
  655. FREE_CONTROLRECEIVED( pAdapter, pCr );
  656. }
  657. // Cancel the "hello" timer if it's running.
  658. //
  659. if (pTunnel->pTqiHello)
  660. {
  661. TimerQCancelItem( pTunnel->pTimerQ, pTunnel->pTqiHello );
  662. pTunnel->pTqiHello = NULL;
  663. }
  664. if (ulFlags & TCBF_PeerInitRef)
  665. {
  666. // Remove the "peer initiation" tunnel reference.
  667. //
  668. ClearFlags( &pTunnel->ulFlags, TCBF_PeerInitRef );
  669. DereferenceTunnel( pTunnel );
  670. }
  671. if (ulFlags & TCBF_FsmCloseRef)
  672. {
  673. // Remove the "graceful close" tunnel reference.
  674. //
  675. ClearFlags( &pTunnel->ulFlags, TCBF_FsmCloseRef );
  676. DereferenceTunnel( pTunnel );
  677. }
  678. }
  679. }
  680. VOID
  681. CallTransitionComplete(
  682. IN TUNNELCB* pTunnel,
  683. IN VCCB* pVc,
  684. IN L2TPCALLSTATE state )
  685. // Sets 'pVc's state to it's new CS_Idle or CS_Established state and sets
  686. // up for reporting the result to the client.
  687. //
  688. // IMPORTANT: Caller must hold 'pTunnel->lockT' and 'pVc->lockV'.
  689. //
  690. {
  691. ULONG ulFlags;
  692. pVc->state = state;
  693. ulFlags = ReadFlags( &pVc->ulFlags );
  694. if (!(ulFlags & VCBM_Pending))
  695. {
  696. if (ulFlags & VCBF_CallClosableByPeer)
  697. {
  698. // Nothing else was pending and the call is closable so either
  699. // peer initiated a close or some fatal error occurred which will
  700. // be cleaned up as if peer initiated a close.
  701. //
  702. ASSERT( pVc->status != NDIS_STATUS_SUCCESS );
  703. SetFlags( &pVc->ulFlags, VCBF_PeerClosePending );
  704. ClearFlags( &pVc->ulFlags, VCBF_CallClosableByPeer );
  705. }
  706. else
  707. {
  708. // Nothing was pending and the call's not closable, so there's no
  709. // action required for this transition.
  710. //
  711. TRACE( TL_I, TM_Fsm, ( "Call not closable" ) );
  712. return;
  713. }
  714. }
  715. else if (ulFlags & VCBF_ClientOpenPending)
  716. {
  717. if (pVc->status != NDIS_STATUS_SUCCESS)
  718. {
  719. // A pending client open just failed and will bring down the call.
  720. // From this point on we will fail new attempts to close the call
  721. // from both client and peer.
  722. //
  723. ClearFlags( &pVc->ulFlags,
  724. (VCBF_CallClosableByClient | VCBF_CallClosableByPeer ));
  725. }
  726. }
  727. else if (ulFlags & VCBF_PeerOpenPending)
  728. {
  729. if (pVc->status != NDIS_STATUS_SUCCESS)
  730. {
  731. // A pending peer open just failed and will bring down the call.
  732. // From this point on we will fail new attempts to close the call
  733. // from the peer. Client closes must be accepted because of the
  734. // way CoNDIS loops dispatched close calls back to the CM's close
  735. // handler.
  736. //
  737. ClearFlags( &pVc->ulFlags, VCBF_CallClosableByPeer );
  738. }
  739. }
  740. // Update some call statistics.
  741. //
  742. {
  743. LARGE_INTEGER lrgTime;
  744. NdisGetCurrentSystemTime( &lrgTime );
  745. if (pVc->state == CS_Idle)
  746. {
  747. if (pVc->stats.llCallUp)
  748. {
  749. pVc->stats.ulSeconds = (ULONG )
  750. (((ULONGLONG )lrgTime.QuadPart - pVc->stats.llCallUp)
  751. / 10000000);
  752. }
  753. }
  754. else
  755. {
  756. ASSERT( pVc->state == CS_Established );
  757. pVc->stats.llCallUp = (ULONGLONG )lrgTime.QuadPart;
  758. pVc->stats.ulMinSendWindow =
  759. pVc->stats.ulMaxSendWindow =
  760. pVc->ulSendWindow;
  761. }
  762. }
  763. TRACE( TL_A, TM_Fsm, ( "CALL %d ON TUNNEL %d %s",
  764. (ULONG )pVc->usCallId, (ULONG )pTunnel->usTunnelId,
  765. ((state == CS_Established) ? "UP" : "DOWN") ) );
  766. WPLOG( LL_M, LM_Fsm, ( "CALL %p, Cid %d, ON TUNNEL %p, Tid %d %s",
  767. pVc, (ULONG )pVc->usCallId, pTunnel, (ULONG )pTunnel->usTunnelId,
  768. ((state == CS_Established) ? "UP" : "DOWN") ) );
  769. // Move the VC onto the tunnel's completing list. The VC may or may not
  770. // be on the tunnel request list, but if it is, remove it.
  771. //
  772. RemoveEntryList( &pVc->linkRequestingVcs );
  773. InitializeListHead( &pVc->linkRequestingVcs );
  774. // Check if this VC is already on the list
  775. if(!(ReadFlags(&pVc->ulFlags) & VCBF_CompPending))
  776. {
  777. ASSERT( pVc->linkCompletingVcs.Flink == &pVc->linkCompletingVcs );
  778. ASSERT( pVc->linkCompletingVcs.Blink == &pVc->linkCompletingVcs );
  779. SetFlags( &pVc->ulFlags, VCBF_CompPending );
  780. InsertTailList( &pTunnel->listCompletingVcs, &pVc->linkCompletingVcs );
  781. }
  782. }
  783. //-----------------------------------------------------------------------------
  784. // FSM utility routines (alphabetically)
  785. //-----------------------------------------------------------------------------
  786. VOID
  787. FsmInCallEstablished(
  788. IN TUNNELCB* pTunnel,
  789. IN VCCB* pVc,
  790. IN CONTROLMSGINFO* pControl )
  791. // Incoming call creation FSM Established state processing for VC 'pVc'.
  792. // 'PControl' is the exploded control message information.
  793. //
  794. // IMPORTANT: Caller must hold 'pVc->lockV' and 'pTunnel->lockT'.
  795. //
  796. {
  797. if (*(pControl->pusMsgType) == CMT_CDN)
  798. {
  799. // Call is down.
  800. //
  801. pVc->status = NDIS_STATUS_TAPI_DISCONNECTMODE_NORMAL;
  802. CallTransitionComplete( pTunnel, pVc, CS_Idle );
  803. }
  804. }
  805. VOID
  806. FsmInCallIdle(
  807. IN TUNNELCB* pTunnel,
  808. IN VCCB* pVc,
  809. IN CONTROLMSGINFO* pControl )
  810. // Incoming call creation FSM Idle state processing for VC 'pVc'.
  811. // 'PControl' is the exploded control message information.
  812. //
  813. // IMPORTANT: Caller must hold 'pVc->lockV' and 'pTunnel->lockT'.
  814. //
  815. {
  816. ADAPTERCB* pAdapter;
  817. pAdapter = pVc->pAdapter;
  818. if (*(pControl->pusMsgType) == CMT_ICRQ)
  819. {
  820. if (!(ReadFlags( &pVc->ulFlags ) & VCBF_PeerOpenPending))
  821. {
  822. // If no open is pending, the call and/or owning tunnel has been
  823. // slammed, we are in the clean up phase, and no response should
  824. // be made.
  825. //
  826. TRACE( TL_A, TM_Fsm, ( "IC aborted" ) );
  827. WPLOG( LL_A, LM_Fsm, ( "ICRQ received & we're in the cleanup phase" ) );
  828. return;
  829. }
  830. if (*pControl->pusAssignedCallId)
  831. {
  832. pVc->usAssignedCallId = *(pControl->pusAssignedCallId);
  833. }
  834. if (pVc->usResult)
  835. {
  836. // Call is down, but must hold the VC until the closing message is
  837. // acknowledged.
  838. //
  839. pVc->status = NDIS_STATUS_TAPI_DISCONNECTMODE_NORMAL;
  840. pVc->state = CS_Idle;
  841. SendControl(
  842. pTunnel, pVc, CMT_CDN,
  843. (ULONG )pVc->usResult, (ULONG )pVc->usError, NULL,
  844. CSF_CallIdleOnAck );
  845. }
  846. else
  847. {
  848. if (pAdapter->usPayloadReceiveWindow)
  849. {
  850. SetFlags( &pVc->ulFlags, VCBF_Sequencing );
  851. }
  852. // Stash call serial number.
  853. //
  854. if (pControl->pulCallSerialNumber)
  855. {
  856. pVc->pLcParams->ulCallSerialNumber =
  857. *(pControl->pulCallSerialNumber);
  858. }
  859. else
  860. {
  861. pVc->pLcParams->ulCallSerialNumber = 0;
  862. }
  863. // Stash acceptable bearer types.
  864. //
  865. pVc->pTcInfo->ulMediaMode = 0;
  866. if (pControl->pulBearerType)
  867. {
  868. if (*(pControl->pulBearerType) & BBM_Analog)
  869. {
  870. pVc->pTcInfo->ulMediaMode |= LINEMEDIAMODE_DATAMODEM;
  871. }
  872. if (*(pControl->pulBearerType) & BBM_Digital)
  873. {
  874. pVc->pTcInfo->ulMediaMode |= LINEMEDIAMODE_DIGITALDATA;
  875. }
  876. }
  877. // Stash physical channel ID.
  878. //
  879. if (pControl->pulPhysicalChannelId)
  880. {
  881. pVc->pLcParams->ulPhysicalChannelId =
  882. *(pControl->pulPhysicalChannelId);
  883. }
  884. else
  885. {
  886. pVc->pLcParams->ulPhysicalChannelId = 0xFFFFFFFF;
  887. }
  888. // Note: The phone numbers of the caller and callee as well as the
  889. // Subaddress are available at this point. Currently, the
  890. // CallerID field of the TAPI structures is used for the IP
  891. // address of the other end of the tunnel, which is used above for
  892. // the IPSEC filters. The WAN caller information may also be
  893. // useful but there is no obvious way to return both the WAN and
  894. // tunnel endpoints in the current TAPI structures.
  895. // Send response.
  896. //
  897. pVc->state = CS_WaitConnect;
  898. SendControl( pTunnel, pVc, CMT_ICRP, 0, 0, NULL, 0 );
  899. }
  900. }
  901. }
  902. VOID
  903. FsmInCallWaitConnect(
  904. IN TUNNELCB* pTunnel,
  905. IN VCCB* pVc,
  906. IN CONTROLMSGINFO* pControl )
  907. // Incoming call creation FSM WaitConnect state processing for VC 'pVc'.
  908. // 'PControl' is the exploded control message information.
  909. //
  910. // IMPORTANT: Caller must hold 'pVc->lockV' and 'pTunnel->lockT'.
  911. //
  912. {
  913. if (*(pControl->pusMsgType) == CMT_ICCN)
  914. {
  915. if (pControl->pulTxConnectSpeed)
  916. {
  917. pVc->ulConnectBps = *(pControl->pulTxConnectSpeed);
  918. }
  919. else
  920. {
  921. // Not supposed to happen, but go on with a least common
  922. // denominator if it does.
  923. //
  924. pVc->ulConnectBps = 9600;
  925. }
  926. if (pControl->pulFramingType
  927. && !(*(pControl->pulFramingType) & FBM_Sync))
  928. {
  929. // Uh oh, the call is not using synchronous framing, which is the
  930. // only one NDISWAN supports. Peer should have noticed we don't
  931. // support asynchronous during tunnel setup. Close the call.
  932. //
  933. TRACE( TL_A, TM_Fsm, ( "Sync framing?" ) );
  934. WPLOG( LL_A, LM_Fsm, ( "Sync framing?" ) );
  935. if (!(pVc->pAdapter->ulFlags & ACBF_IgnoreFramingMismatch))
  936. {
  937. ScheduleTunnelWork(
  938. pTunnel, pVc, FsmCloseCall,
  939. (ULONG_PTR )CRESULT_GeneralWithError,
  940. (ULONG_PTR )GERR_None,
  941. 0, 0, FALSE, FALSE );
  942. return;
  943. }
  944. }
  945. if (!pControl->pusRWindowSize)
  946. {
  947. // Peer did not send a receive window AVP so we're not doing Ns/Nr
  948. // flow control on the session. If we requested sequencing peer
  949. // is really supposed to send his window, but if he doesn't assume
  950. // that means he wants no sequencing. The draft/RFC is a little
  951. // ambiguous on this point.
  952. //
  953. DBG_if (ReadFlags( &pVc->ulFlags ) & VCBF_Sequencing)
  954. TRACE( TL_A, TM_Fsm, ( "No rw when we sent one?" ) );
  955. ClearFlags( &pVc->ulFlags, VCBF_Sequencing );
  956. }
  957. else
  958. {
  959. ULONG ulNew;
  960. if (*(pControl->pusRWindowSize) == 0)
  961. {
  962. // When peer sends a receive window of 0 it means he needs
  963. // sequencing to do out of order handling but doesn't want to
  964. // do flow control. (Why would anyone choose this?) We fake
  965. // "no flow control" by setting a huge send window that should
  966. // never be filled.
  967. //
  968. pVc->ulMaxSendWindow = 10000;
  969. }
  970. else
  971. {
  972. pVc->ulMaxSendWindow = *(pControl->pusRWindowSize);
  973. }
  974. // Set the initial send window to 1/2 the maximum, to "slow start"
  975. // in case the networks congested. If it's not the window will
  976. // quickly adapt to the maximum.
  977. //
  978. ulNew = pVc->ulMaxSendWindow >> 1;
  979. pVc->ulSendWindow = max( ulNew, 1 );
  980. }
  981. // Initialize the round trip time to the packet processing delay, if
  982. // any, per the draft/RFC. The PPD is in 1/10ths of seconds.
  983. //
  984. if (pControl->pusPacketProcDelay)
  985. {
  986. pVc->ulRoundTripMs =
  987. ((ULONG )*(pControl->pusPacketProcDelay)) * 100;
  988. }
  989. else if (pVc->ulRoundTripMs == 0)
  990. {
  991. pVc->ulRoundTripMs = pVc->pAdapter->ulInitialSendTimeoutMs;
  992. }
  993. // Call is up.
  994. //
  995. CallTransitionComplete( pTunnel, pVc, CS_Established );
  996. }
  997. else if (*(pControl->pusMsgType) == CMT_CDN)
  998. {
  999. // Call is down.
  1000. //
  1001. pVc->status = NDIS_STATUS_TAPI_DISCONNECTMODE_NORMAL;
  1002. CallTransitionComplete( pTunnel, pVc, CS_Idle );
  1003. }
  1004. }
  1005. VOID
  1006. FsmInCallWaitReply(
  1007. IN TUNNELCB* pTunnel,
  1008. IN VCCB* pVc,
  1009. IN CONTROLMSGINFO* pControl )
  1010. // Incoming call creation FSM WaitReply state processing for VC 'pVc'.
  1011. // 'PControl' is the exploded control message information.
  1012. //
  1013. // IMPORTANT: Caller must hold 'pVc->lockV' and 'pTunnel->lockT'.
  1014. //
  1015. {
  1016. ADAPTERCB* pAdapter;
  1017. pAdapter = pVc->pAdapter;
  1018. if (*(pControl->pusMsgType) == CMT_ICRP)
  1019. {
  1020. pVc->pMakeCall->Flags |= CALL_PARAMETERS_CHANGED;
  1021. if (pControl->pusAssignedCallId && *(pControl->pusAssignedCallId) > 0)
  1022. {
  1023. pVc->usAssignedCallId = *(pControl->pusAssignedCallId);
  1024. }
  1025. else
  1026. {
  1027. ASSERT( !"No assigned CID?" );
  1028. WPLOG( LL_A, LM_Fsm, ( "*** pVc = %p, no assigned CID", pVc ) );
  1029. ScheduleTunnelWork(
  1030. pTunnel, NULL, FsmCloseTunnel,
  1031. (ULONG_PTR )TRESULT_GeneralWithError,
  1032. (ULONG_PTR )GERR_BadCallId,
  1033. 0, 0, FALSE, FALSE );
  1034. return;
  1035. }
  1036. // Use the queried media speed to set the connect speed
  1037. //
  1038. pVc->ulConnectBps = pTunnel->ulMediaSpeed;
  1039. if (pControl->pusRWindowSize)
  1040. {
  1041. ULONG ulNew;
  1042. SetFlags( &pVc->ulFlags, VCBF_Sequencing );
  1043. if (*(pControl->pusRWindowSize) == 0)
  1044. {
  1045. // When peer sends a receive window of 0 it means he needs
  1046. // sequencing to do out of order handling but doesn't want to
  1047. // do flow control. (Why would anyone choose this?) We fake
  1048. // "no flow control" by setting a huge send window that should
  1049. // never be filled.
  1050. //
  1051. pVc->ulMaxSendWindow = 10000;
  1052. }
  1053. else
  1054. {
  1055. pVc->ulMaxSendWindow = (ULONG )*(pControl->pusRWindowSize);
  1056. }
  1057. // Set the initial send window to 1/2 the maximum, to "slow start"
  1058. // in case the networks congested. If it's not the window will
  1059. // quickly adapt to the maximum.
  1060. //
  1061. ulNew = pVc->ulMaxSendWindow >> 1;
  1062. pVc->ulSendWindow = max( ulNew, 1 );
  1063. }
  1064. // Initialize the round trip time to the packet processing delay, if
  1065. // any, per the draft/RFC. The PPD is in 1/10ths of seconds. If it's
  1066. // not here, it might show up in the InCallConn.
  1067. //
  1068. if (pControl->pusPacketProcDelay)
  1069. {
  1070. pVc->ulRoundTripMs =
  1071. ((ULONG )*(pControl->pusPacketProcDelay)) * 100;
  1072. }
  1073. // Send InCallConn and the call is up.
  1074. //
  1075. SendControl( pTunnel, pVc, CMT_ICCN, 0, 0, NULL, 0 );
  1076. CallTransitionComplete( pTunnel, pVc, CS_Established );
  1077. }
  1078. else if (*(pControl->pusMsgType) == CMT_CDN)
  1079. {
  1080. USHORT usResult;
  1081. USHORT usError;
  1082. if (pControl->pusResult)
  1083. {
  1084. usResult = *(pControl->pusResult);
  1085. if(pControl->pusError)
  1086. {
  1087. usError = *(pControl->pusError);
  1088. }
  1089. else
  1090. {
  1091. usError = GERR_None;
  1092. }
  1093. }
  1094. else
  1095. {
  1096. usResult = CRESULT_GeneralWithError;
  1097. usError = GERR_BadValue;
  1098. }
  1099. // Map the result/error to a TAPI disconnect code.
  1100. //
  1101. pVc->status = StatusFromResultAndError( usResult, usError );
  1102. // Call is down.
  1103. //
  1104. CallTransitionComplete( pTunnel, pVc, CS_Idle );
  1105. }
  1106. }
  1107. VOID
  1108. FsmOutCallBearerAnswer(
  1109. IN TUNNELCB* pTunnel,
  1110. IN VCCB* pVc )
  1111. // The bearer WAN media has answered the call initiated by an outgoing
  1112. // call request from peer. 'PVc' is the VC control block associated with
  1113. // the outgoing call.
  1114. //
  1115. // IMPORTANT: Caller must hold 'pVc->lockV' and 'pTunnel->lockT'.
  1116. //
  1117. {
  1118. ADAPTERCB* pAdapter;
  1119. ASSERT( pVc->state == CS_WaitCsAnswer );
  1120. pAdapter = pVc->pAdapter;
  1121. // Send OutCallConn, and the call is up.
  1122. //
  1123. SendControl( pTunnel, pVc, CMT_OCCN, 0, 0, NULL, 0 );
  1124. CallTransitionComplete( pTunnel, pVc, CS_Established );
  1125. }
  1126. VOID
  1127. FsmOutCallEstablished(
  1128. IN TUNNELCB* pTunnel,
  1129. IN VCCB* pVc,
  1130. IN CONTROLMSGINFO* pControl )
  1131. // Outgoing call creation FSM Established state processing for VC 'pVc'.
  1132. // 'PControl' is the exploded control message information.
  1133. //
  1134. // IMPORTANT: Caller must hold 'pVc->lockV' and 'pTunnel->lockT'.
  1135. //
  1136. {
  1137. if (*(pControl->pusMsgType) == CMT_CDN)
  1138. {
  1139. // Call is down.
  1140. //
  1141. pVc->status = NDIS_STATUS_TAPI_DISCONNECTMODE_NORMAL;
  1142. CallTransitionComplete( pTunnel, pVc, CS_Idle );
  1143. }
  1144. }
  1145. VOID
  1146. FsmOutCallIdle(
  1147. IN TUNNELCB* pTunnel,
  1148. IN VCCB* pVc,
  1149. IN CONTROLMSGINFO* pControl )
  1150. // Outgoing call creation FSM Idle state processing for VC 'pVc'.
  1151. // 'PControl' is the exploded control message information.
  1152. //
  1153. // IMPORTANT: Caller must hold 'pVc->lockV' and 'pTunnel->lockT'.
  1154. //
  1155. {
  1156. ADAPTERCB* pAdapter;
  1157. pAdapter = pVc->pAdapter;
  1158. if (*(pControl->pusMsgType) == CMT_OCRQ)
  1159. {
  1160. if (!(ReadFlags( &pVc->ulFlags ) & VCBF_PeerOpenPending))
  1161. {
  1162. // If no open is pending, the call and/or owning tunnel has been
  1163. // slammed, we are in the clean up phase, and no response should
  1164. // be made.
  1165. //
  1166. TRACE( TL_A, TM_Fsm, ( "OC aborted" ) );
  1167. WPLOG( LL_A, LM_Fsm, ( "OCRQ received & we're in the cleanup phase" ) );
  1168. return;
  1169. }
  1170. if (pControl->pusAssignedCallId)
  1171. {
  1172. pVc->usAssignedCallId = *(pControl->pusAssignedCallId);
  1173. }
  1174. if (pVc->usResult)
  1175. {
  1176. // Call is down.
  1177. //
  1178. pVc->status =
  1179. StatusFromResultAndError( pVc->usResult, pVc->usError );
  1180. pVc->state = CS_Idle;
  1181. SendControl(
  1182. pTunnel, pVc, CMT_CDN,
  1183. (ULONG )pVc->usResult, (ULONG )pVc->usError, NULL,
  1184. CSF_CallIdleOnAck );
  1185. }
  1186. else
  1187. {
  1188. // Stash the call serial number.
  1189. //
  1190. if (pControl->pulCallSerialNumber)
  1191. {
  1192. pVc->pLcParams->ulCallSerialNumber =
  1193. *(pControl->pulCallSerialNumber);
  1194. }
  1195. else
  1196. {
  1197. pVc->pLcParams->ulCallSerialNumber = 0;
  1198. }
  1199. // The minimum and maximum rates acceptable to peer must be
  1200. // dropped on the floor here and the TAPI structures for incoming
  1201. // calls do not have a way to report such information.
  1202. //
  1203. // Calculate the connect bps to report to NDISWAN and to peer.
  1204. // Since we have no WAN link and no real way to figure the link
  1205. // speed, it's just a guesstimate of the LAN speed or the maximum
  1206. // acceptable to peer, whichever is smaller.
  1207. //
  1208. if (pControl->pulMaximumBps)
  1209. {
  1210. pVc->ulConnectBps = (ULONG )*(pControl->pulMaximumBps);
  1211. }
  1212. if (pVc->ulConnectBps > pTunnel->ulMediaSpeed)
  1213. {
  1214. pVc->ulConnectBps = pTunnel->ulMediaSpeed;
  1215. }
  1216. // Stash the requested bearer types.
  1217. //
  1218. pVc->pTcInfo->ulMediaMode = 0;
  1219. if (pControl->pulBearerType)
  1220. {
  1221. if (*(pControl->pulBearerType) & BBM_Analog)
  1222. {
  1223. pVc->pTcInfo->ulMediaMode |= LINEMEDIAMODE_DATAMODEM;
  1224. }
  1225. if (*(pControl->pulBearerType) & BBM_Digital)
  1226. {
  1227. pVc->pTcInfo->ulMediaMode |= LINEMEDIAMODE_DIGITALDATA;
  1228. }
  1229. }
  1230. // Stash the maximum send window.
  1231. //
  1232. if (pControl->pusRWindowSize)
  1233. {
  1234. SetFlags( &pVc->ulFlags, VCBF_Sequencing );
  1235. if (*(pControl->pusRWindowSize) == 0)
  1236. {
  1237. // When peer sends a receive window of 0 it means he needs
  1238. // sequencing to do out of order handling but doesn't want
  1239. // to do flow control. (Why would anyone choose this?) We
  1240. // fake "no flow control" by setting a huge send window
  1241. // that should never be filled.
  1242. //
  1243. pVc->ulMaxSendWindow = 10000;
  1244. }
  1245. else
  1246. {
  1247. pVc->ulMaxSendWindow = (ULONG )*(pControl->pusRWindowSize);
  1248. }
  1249. }
  1250. // Initialize the round trip time to the packet processing delay,
  1251. // if any, per the draft/RFC. The PPD is in 1/10ths of seconds.
  1252. //
  1253. if (pControl->pusPacketProcDelay)
  1254. {
  1255. pVc->ulRoundTripMs =
  1256. ((ULONG )*(pControl->pusPacketProcDelay)) * 100;
  1257. }
  1258. else
  1259. {
  1260. pVc->ulRoundTripMs = pAdapter->ulInitialSendTimeoutMs;
  1261. }
  1262. // Note: The phone numbers of the caller and callee as well as the
  1263. // Subaddress are available at this point. Currently, the
  1264. // CallerID field of the TAPI structures is used for the IP
  1265. // address of the other end of the tunnel, which is used above for
  1266. // the IPSEC filters. The WAN caller information may also be
  1267. // useful but there is no obvious way to return both the WAN and
  1268. // tunnel endpoints in the current TAPI structures.
  1269. // Store the IP address of the peer.
  1270. pVc->state = CS_WaitCsAnswer;
  1271. SendControl( pTunnel, pVc, CMT_OCRP, 0, 0, NULL, 0 );
  1272. // For now, with only "null" WAN call handoff supported, the
  1273. // bearer answer event is also generated here.
  1274. //
  1275. FsmOutCallBearerAnswer( pTunnel, pVc );
  1276. }
  1277. }
  1278. }
  1279. VOID
  1280. FsmOutCallWaitReply(
  1281. IN TUNNELCB* pTunnel,
  1282. IN VCCB* pVc,
  1283. IN CONTROLMSGINFO* pControl )
  1284. // Outgoing call creation FSM WaitReply state processing for VC 'pVc'.
  1285. // 'PControl' is the exploded control message information.
  1286. //
  1287. // IMPORTANT: Caller must hold 'pVc->lockV' and 'pTunnel->lockT'.
  1288. //
  1289. {
  1290. if (*(pControl->pusMsgType) == CMT_OCRP)
  1291. {
  1292. pVc->pMakeCall->Flags |= CALL_PARAMETERS_CHANGED;
  1293. // Stash the assigned Call-ID.
  1294. //
  1295. if (pControl->pusAssignedCallId && *(pControl->pusAssignedCallId) > 0)
  1296. {
  1297. pVc->usAssignedCallId = *(pControl->pusAssignedCallId);
  1298. }
  1299. else
  1300. {
  1301. // Peer ignored a MUST we can't cover up, by not sending a Call-ID
  1302. // for call control and payload traffic headed his way.
  1303. //
  1304. ASSERT( !"No assigned CID?" );
  1305. ScheduleTunnelWork(
  1306. pTunnel, NULL, FsmCloseTunnel,
  1307. (ULONG_PTR )TRESULT_GeneralWithError,
  1308. (ULONG_PTR )GERR_None,
  1309. 0, 0, FALSE, FALSE );
  1310. return;
  1311. }
  1312. // Stash the physical channel ID.
  1313. //
  1314. if (pControl->pulPhysicalChannelId)
  1315. {
  1316. pVc->pLcParams->ulPhysicalChannelId =
  1317. *(pControl->pulPhysicalChannelId);
  1318. }
  1319. else
  1320. {
  1321. pVc->pLcParams->ulPhysicalChannelId = 0xFFFFFFFF;
  1322. }
  1323. pVc->state = CS_WaitConnect;
  1324. }
  1325. else if (*(pControl->pusMsgType) == CMT_CDN)
  1326. {
  1327. USHORT usResult;
  1328. USHORT usError;
  1329. if (pControl->pusResult)
  1330. {
  1331. usResult = *(pControl->pusResult);
  1332. if(pControl->pusError)
  1333. {
  1334. usError = *(pControl->pusError);
  1335. }
  1336. else
  1337. {
  1338. usError = GERR_None;
  1339. }
  1340. }
  1341. else
  1342. {
  1343. usResult = CRESULT_GeneralWithError;
  1344. usError = GERR_BadValue;
  1345. }
  1346. // Map the result/error to a TAPI disconnect code.
  1347. //
  1348. pVc->status = StatusFromResultAndError( usResult, usError );
  1349. // Call is down.
  1350. //
  1351. CallTransitionComplete( pTunnel, pVc, CS_Idle );
  1352. }
  1353. }
  1354. VOID
  1355. FsmOutCallWaitConnect(
  1356. IN TUNNELCB* pTunnel,
  1357. IN VCCB* pVc,
  1358. IN CONTROLMSGINFO* pControl )
  1359. // Outgoing call creation FSM WaitConnect state processing for VC 'pVc'.
  1360. // 'PControl' is the exploded control message information.
  1361. //
  1362. // IMPORTANT: Caller must hold 'pVc->lockV' and 'pTunnel->lockT'.
  1363. //
  1364. {
  1365. if (*(pControl->pusMsgType) == CMT_OCCN)
  1366. {
  1367. // Stash the connect BPS.
  1368. //
  1369. if (pControl->pulTxConnectSpeed)
  1370. {
  1371. pVc->ulConnectBps = *(pControl->pulTxConnectSpeed);
  1372. }
  1373. else
  1374. {
  1375. // Not supposed to happen, but try to go on with a least common
  1376. // denominator if it does.
  1377. //
  1378. pVc->ulConnectBps = 9600;
  1379. }
  1380. DBG_if (pControl->pulFramingType
  1381. && !(*(pControl->pulFramingType) & FBM_Sync))
  1382. {
  1383. // Should not happen since we said in our request we only want
  1384. // synchronous framing. If it does, go on in the hope that this
  1385. // AVP is what peer got wrong and not the framing itself.
  1386. //
  1387. ASSERT( "No sync framing?" );
  1388. }
  1389. // Stash the maximum send window.
  1390. //
  1391. if (!pControl->pusRWindowSize)
  1392. {
  1393. // Peer did not send a receive window AVP so we're not doing Ns/Nr
  1394. // flow control on the session. If we requested sequencing peer
  1395. // is really supposed to send his window, but if he doesn't assume
  1396. // that means he wants no sequencing. The draft/RFC is a little
  1397. // ambiguous on this point.
  1398. //
  1399. DBG_if (ReadFlags( &pVc->ulFlags ) & VCBF_Sequencing)
  1400. TRACE( TL_A, TM_Fsm, ( "No rw when we sent one?" ) );
  1401. ClearFlags( &pVc->ulFlags, VCBF_Sequencing );
  1402. }
  1403. else
  1404. {
  1405. ULONG ulNew;
  1406. if (*(pControl->pusRWindowSize) == 0)
  1407. {
  1408. // When peer sends a receive window of 0 it means he needs
  1409. // sequencing to do out of order handling but doesn't want to
  1410. // do flow control. (Why would anyone choose this?) We fake
  1411. // "no flow control" by setting a huge send window that should
  1412. // never be filled.
  1413. //
  1414. pVc->ulMaxSendWindow = 10000;
  1415. }
  1416. else
  1417. {
  1418. pVc->ulMaxSendWindow = *(pControl->pusRWindowSize);
  1419. }
  1420. // Set the initial send window to 1/2 the maximum, to "slow start"
  1421. // in case the networks congested. If it's not the window will
  1422. // quickly adapt to the maximum.
  1423. //
  1424. ulNew = pVc->ulMaxSendWindow << 1;
  1425. pVc->ulSendWindow = max( ulNew, 1 );
  1426. }
  1427. // Initialize the round trip time to the packet processing delay, if
  1428. // any, per the draft/RFC. The PPD is in 1/10ths of seconds.
  1429. //
  1430. if (pControl->pusPacketProcDelay)
  1431. {
  1432. pVc->ulRoundTripMs =
  1433. ((ULONG )*(pControl->pusPacketProcDelay)) * 100;
  1434. }
  1435. else
  1436. {
  1437. pVc->ulRoundTripMs = pVc->pAdapter->ulInitialSendTimeoutMs;
  1438. }
  1439. // Call is up.
  1440. //
  1441. CallTransitionComplete( pTunnel, pVc, CS_Established );
  1442. }
  1443. else if (*(pControl->pusMsgType) == CMT_CDN)
  1444. {
  1445. USHORT usResult;
  1446. USHORT usError;
  1447. if (pControl->pusResult)
  1448. {
  1449. usResult = *(pControl->pusResult);
  1450. if(pControl->pusError)
  1451. {
  1452. usError = *(pControl->pusError);
  1453. }
  1454. else
  1455. {
  1456. usError = GERR_None;
  1457. }
  1458. }
  1459. else
  1460. {
  1461. usResult = CRESULT_GeneralWithError;
  1462. usError = GERR_BadValue;
  1463. }
  1464. // Map the result/error to a TAPI disconnect code.
  1465. //
  1466. pVc->status = StatusFromResultAndError( usResult, usError );
  1467. // Call is down.
  1468. //
  1469. CallTransitionComplete( pTunnel, pVc, CS_Idle );
  1470. }
  1471. }
  1472. VOID
  1473. FsmTunnelEstablished(
  1474. IN TUNNELCB* pTunnel,
  1475. IN CONTROLMSGINFO* pControl )
  1476. // Tunnel creation FSM Established state processing for tunnel 'pTunnel'.
  1477. // 'PControl' is the exploded control message information.
  1478. //
  1479. // IMPORTANT: Caller must hold 'pTunnel->lockT'.
  1480. //
  1481. {
  1482. ADAPTERCB* pAdapter;
  1483. pAdapter = pTunnel->pAdapter;
  1484. if (*(pControl->pusMsgType) == CMT_StopCCN)
  1485. {
  1486. // Peer taking tunnel down.
  1487. //
  1488. TunnelTransitionComplete( pTunnel, CCS_Idle );
  1489. }
  1490. }
  1491. VOID
  1492. FsmTunnelIdle(
  1493. IN TUNNELCB* pTunnel,
  1494. IN CONTROLMSGINFO* pControl )
  1495. // Tunnel creation FSM Idle state processing for tunnel 'pTunnel'.
  1496. // 'PControl' is the exploded control message information.
  1497. //
  1498. // IMPORTANT: Caller must hold 'pTunnel->lockT'.
  1499. //
  1500. {
  1501. NDIS_STATUS status;
  1502. ADAPTERCB* pAdapter;
  1503. USHORT usResult;
  1504. USHORT usError;
  1505. pAdapter = pTunnel->pAdapter;
  1506. if (*(pControl->pusMsgType) == CMT_SCCRQ)
  1507. {
  1508. SetFlags( &pTunnel->ulFlags, (TCBF_PeerInitiated | TCBF_PeerInitRef) );
  1509. if (ReferenceSap( pAdapter ))
  1510. {
  1511. // A SAP is active. Because SAPs can be deregistered without
  1512. // closing active incoming tunnels, we need a reference on the
  1513. // open TDI context for the tunnel. We call TdixReference rather
  1514. // than TdixOpen, because with TDI guaranteed to be open the
  1515. // effect is the same and TdixReference can be called at DISPATCH
  1516. // IRQL while TdixOpen cannot. The reference on the SAP is then
  1517. // removed since we don't want the tunnel to prevent the SAP from
  1518. // being deregistered.
  1519. //
  1520. TdixReference( &pAdapter->tdix );
  1521. SetFlags( &pTunnel->ulFlags, TCBF_TdixReferenced );
  1522. DereferenceSap( pAdapter );
  1523. }
  1524. else
  1525. {
  1526. // No SAP is active. The only reason peer's request got this far
  1527. // is that an outgoing call or just-deregistered-SAP had TDI open.
  1528. // Discard it as if TDI had not been open.
  1529. //
  1530. TRACE( TL_I, TM_Fsm, ( "No active SAP" ) );
  1531. TunnelTransitionComplete( pTunnel, CCS_Idle );
  1532. return;
  1533. }
  1534. GetCcAvps( pTunnel, pControl, &usResult, &usError );
  1535. if (usResult)
  1536. {
  1537. // The tunnel is down, but must hold it and any VCs until the
  1538. // closing exchange is acknowledged.
  1539. //
  1540. SendControl(
  1541. pTunnel, NULL, CMT_StopCCN,
  1542. (ULONG )usResult, (ULONG )usError, NULL, CSF_TunnelIdleOnAck );
  1543. }
  1544. else
  1545. {
  1546. // Tunnel creation successfully underway. Flip the flag that
  1547. // tells MakeCall to queue requesting VCs on the result.
  1548. //
  1549. SetFlags( &pTunnel->ulFlags, TCBF_CcInTransition );
  1550. if (pControl->pchChallenge)
  1551. {
  1552. CHAR* pszPassword;
  1553. // Challenge received. Calculate the response value, based on
  1554. // the password from the registry.
  1555. //
  1556. pAdapter = pTunnel->pAdapter;
  1557. if (pAdapter->pszPassword)
  1558. {
  1559. pszPassword = pAdapter->pszPassword;
  1560. }
  1561. else
  1562. {
  1563. pszPassword = "";
  1564. }
  1565. CalculateResponse(
  1566. pControl->pchChallenge,
  1567. (ULONG )pControl->usChallengeLength,
  1568. pszPassword,
  1569. CMT_SCCRP,
  1570. pTunnel->achResponseToSend );
  1571. }
  1572. pTunnel->state = CCS_WaitCtlConnect;
  1573. SendControl(
  1574. pTunnel, NULL, CMT_SCCRP,
  1575. (pControl->pchChallenge != NULL), 0, NULL, 0 );
  1576. }
  1577. }
  1578. }
  1579. VOID
  1580. FsmTunnelWaitCtlConnect(
  1581. IN TUNNELCB* pTunnel,
  1582. IN CONTROLMSGINFO* pControl )
  1583. // Tunnel creation FSM WaitCtlConnect state processing for tunnel
  1584. // 'pTunnel'. 'PControl' is the exploded control message information.
  1585. //
  1586. // IMPORTANT: Caller must hold 'pTunnel->lockT'.
  1587. //
  1588. {
  1589. ADAPTERCB* pAdapter;
  1590. pAdapter = pTunnel->pAdapter;
  1591. if (*(pControl->pusMsgType) == CMT_SCCCN)
  1592. {
  1593. USHORT usResult;
  1594. usResult = 0;
  1595. if (pAdapter->pszPassword)
  1596. {
  1597. // We sent a challenge.
  1598. //
  1599. if (pControl->pchResponse)
  1600. {
  1601. CHAR achResponseExpected[ 16 ];
  1602. ULONG i;
  1603. // Challenge response received. Calculate the expected
  1604. // response and compare to that received.
  1605. //
  1606. CalculateResponse(
  1607. pTunnel->achChallengeToSend,
  1608. sizeof(pTunnel->achChallengeToSend),
  1609. pAdapter->pszPassword,
  1610. CMT_SCCCN,
  1611. achResponseExpected );
  1612. for (i = 0; i < 16; ++i)
  1613. {
  1614. if (achResponseExpected[ i ] != pControl->pchResponse[ i ])
  1615. {
  1616. break;
  1617. }
  1618. }
  1619. if (i < 16)
  1620. {
  1621. TRACE( TL_N, TM_Fsm, ( "Wrong challenge response" ) );
  1622. usResult = TRESULT_NotAuthorized;
  1623. }
  1624. }
  1625. else
  1626. {
  1627. // We sent a challenge and got no challenge response.
  1628. //
  1629. //
  1630. TRACE( TL_N, TM_Fsm, ( "No challenge response" ) );
  1631. usResult = TRESULT_FsmError;
  1632. }
  1633. }
  1634. if (usResult)
  1635. {
  1636. // Tunnel going down.
  1637. //
  1638. pTunnel->state = CCS_Idle;
  1639. SendControl(
  1640. pTunnel, NULL, CMT_StopCCN,
  1641. (ULONG )usResult, 0, NULL, CSF_TunnelIdleOnAck );
  1642. }
  1643. else
  1644. {
  1645. // Tunnel is up.
  1646. //
  1647. TunnelTransitionComplete( pTunnel, CCS_Established );
  1648. }
  1649. }
  1650. else if (*(pControl->pusMsgType) == CMT_StopCCN)
  1651. {
  1652. // Peer taking tunnel down.
  1653. //
  1654. TunnelTransitionComplete( pTunnel, CCS_Idle );
  1655. }
  1656. }
  1657. VOID
  1658. FsmTunnelWaitCtlReply(
  1659. IN TUNNELCB* pTunnel,
  1660. IN CONTROLMSGINFO* pControl )
  1661. // Tunnel creation FSM WaitCtlReply state processing for tunnel 'pTunnel'.
  1662. // 'PControl' is the exploded control message information.
  1663. //
  1664. // IMPORTANT: Caller must hold 'pTunnel->lockT'.
  1665. //
  1666. {
  1667. NDIS_STATUS status;
  1668. ADAPTERCB* pAdapter;
  1669. USHORT usResult;
  1670. USHORT usError;
  1671. pAdapter = pTunnel->pAdapter;
  1672. if (*(pControl->pusMsgType) == CMT_SCCRP)
  1673. {
  1674. GetCcAvps( pTunnel, pControl, &usResult, &usError );
  1675. if (pAdapter->pszPassword)
  1676. {
  1677. // We sent a challenge.
  1678. //
  1679. if (pControl->pchResponse)
  1680. {
  1681. CHAR achResponseExpected[ 16 ];
  1682. ULONG i;
  1683. // Challenge response received. Calculate the expected
  1684. // response and compare to that received.
  1685. //
  1686. CalculateResponse(
  1687. pTunnel->achChallengeToSend,
  1688. sizeof(pTunnel->achChallengeToSend),
  1689. pAdapter->pszPassword,
  1690. CMT_SCCRP,
  1691. achResponseExpected );
  1692. for (i = 0; i < 16; ++i)
  1693. {
  1694. if (achResponseExpected[ i ] != pControl->pchResponse[ i ])
  1695. {
  1696. break;
  1697. }
  1698. }
  1699. if (i < 16)
  1700. {
  1701. TRACE( TL_N, TM_Fsm, ( "Wrong challenge response" ) );
  1702. usResult = TRESULT_General;
  1703. }
  1704. }
  1705. else
  1706. {
  1707. // We sent a challenge and got no challenge response. Treat
  1708. // this as if a bad response was received.
  1709. //
  1710. TRACE( TL_N, TM_Fsm, ( "No challenge response" ) );
  1711. usResult = TRESULT_General;
  1712. }
  1713. }
  1714. if (usResult)
  1715. {
  1716. // Tunnel creation failed, so shut down.
  1717. //
  1718. pTunnel->state = CCS_Idle;
  1719. SendControl(
  1720. pTunnel, NULL, CMT_StopCCN,
  1721. (ULONG )usResult, (ULONG )usError, NULL, CSF_TunnelIdleOnAck );
  1722. }
  1723. else
  1724. {
  1725. if (pControl->pchChallenge)
  1726. {
  1727. CHAR* pszPassword;
  1728. // Challenge received. Calculate the response value, based on
  1729. // the password from the registry.
  1730. //
  1731. pAdapter = pTunnel->pAdapter;
  1732. if (pAdapter->pszPassword)
  1733. pszPassword = pAdapter->pszPassword;
  1734. else
  1735. pszPassword = "";
  1736. CalculateResponse(
  1737. pControl->pchChallenge,
  1738. (ULONG )pControl->usChallengeLength,
  1739. pszPassword,
  1740. CMT_SCCCN,
  1741. pTunnel->achResponseToSend );
  1742. }
  1743. // Tunnel is up.
  1744. //
  1745. SendControl( pTunnel, NULL, CMT_SCCCN,
  1746. (pControl->pchChallenge != NULL), 0, NULL, CSF_QueryMediaSpeed);
  1747. TunnelTransitionComplete( pTunnel, CCS_Established );
  1748. }
  1749. }
  1750. else if (*(pControl->pusMsgType) == CMT_StopCCN)
  1751. {
  1752. // Peer taking tunnel down.
  1753. //
  1754. TunnelTransitionComplete( pTunnel, CCS_Idle );
  1755. }
  1756. }
  1757. VOID
  1758. GetCcAvps(
  1759. IN TUNNELCB* pTunnel,
  1760. IN CONTROLMSGINFO* pControl,
  1761. OUT USHORT* pusResult,
  1762. OUT USHORT* pusError )
  1763. // Retrieve and interpret control connection AVPs received in the SCCRQ or
  1764. // SCCRP message in 'pControl', returning the result and error codes for
  1765. // the response in '*pusResult' and '*pusError'. 'PTunnel' is the tunnel
  1766. // control block.
  1767. //
  1768. {
  1769. ULONG ulNew;
  1770. *pusResult = 0;
  1771. *pusError = GERR_None;
  1772. if (!pControl->pusProtocolVersion
  1773. || *(pControl->pusProtocolVersion) != L2TP_ProtocolVersion)
  1774. {
  1775. // Peer wants to do a version of L2TP that doesn't match the only
  1776. // one we understand.
  1777. //
  1778. TRACE( TL_A, TM_Recv, ( "Bad protocol version?" ) );
  1779. WPLOG( LL_A, LM_Recv, ( "Bad protocol version?" ) );
  1780. *pusResult = TRESULT_BadProtocolVersion;
  1781. return;
  1782. }
  1783. // Make sure the MUST fields are really there and have valid values, then
  1784. // store them in our control blocks.
  1785. //
  1786. if (!pControl->pusAssignedTunnelId
  1787. || *(pControl->pusAssignedTunnelId) == 0
  1788. || !pControl->pulFramingCaps)
  1789. {
  1790. TRACE( TL_A, TM_Recv, ( "Missing MUSTs?" ) );
  1791. WPLOG( LL_A, LM_Recv, ( "Missing MUSTs?" ) );
  1792. *pusResult = TRESULT_GeneralWithError;
  1793. *pusError = GERR_BadValue;
  1794. return;
  1795. }
  1796. pTunnel->usAssignedTunnelId = *(pControl->pusAssignedTunnelId);
  1797. pTunnel->ulFramingCaps = *(pControl->pulFramingCaps);
  1798. if (pControl->pulBearerCaps)
  1799. {
  1800. pTunnel->ulBearerCaps = *(pControl->pulBearerCaps);
  1801. }
  1802. else
  1803. {
  1804. pTunnel->ulBearerCaps = 0;
  1805. }
  1806. if (pControl->pusRWindowSize && *(pControl->pusRWindowSize))
  1807. {
  1808. // Peer provided his receive window, which becomes our send window.
  1809. //
  1810. pTunnel->ulMaxSendWindow = (ULONG )*(pControl->pusRWindowSize);
  1811. }
  1812. else
  1813. {
  1814. // Peer provided no receive window, so use the default of 4 per the
  1815. // draft/RFC.
  1816. //
  1817. pTunnel->ulMaxSendWindow = L2TP_DefaultReceiveWindow;
  1818. }
  1819. // Set the initial send window to 1/2 the maximum, to "slow start" in case
  1820. // the network is congested. If it's not the window will quickly adapt to
  1821. // the maximum.
  1822. //
  1823. ulNew = pTunnel->ulMaxSendWindow >> 1;
  1824. pTunnel->ulSendWindow = max( ulNew, 1 );
  1825. }
  1826. ULONG
  1827. StatusFromResultAndError(
  1828. IN USHORT usResult,
  1829. IN USHORT usError )
  1830. // Map non-success L2TP result/error codes to a best-fit TAPI
  1831. // NDIS_STATUS_TAPI_DISCONNECT_* code.
  1832. //
  1833. {
  1834. ULONG ulResult;
  1835. switch (usResult)
  1836. {
  1837. case CRESULT_GeneralWithError:
  1838. {
  1839. switch (usError)
  1840. {
  1841. case GERR_TryAnother:
  1842. {
  1843. ulResult = NDIS_STATUS_TAPI_DISCONNECTMODE_BUSY;
  1844. break;
  1845. }
  1846. case GERR_BadValue:
  1847. case GERR_BadLength:
  1848. case GERR_NoControlConnection:
  1849. case GERR_NoResources:
  1850. {
  1851. ulResult = NDIS_STATUS_TAPI_DISCONNECTMODE_UNAVAIL;
  1852. break;
  1853. }
  1854. default:
  1855. {
  1856. ulResult = NDIS_STATUS_TAPI_DISCONNECTMODE_REJECT;
  1857. break;
  1858. }
  1859. }
  1860. break;
  1861. }
  1862. case CRESULT_Busy:
  1863. {
  1864. ulResult = NDIS_STATUS_TAPI_DISCONNECTMODE_BUSY;
  1865. break;
  1866. }
  1867. case CRESULT_NoCarrier:
  1868. case CRESULT_NoDialTone:
  1869. case CRESULT_Timeout:
  1870. case CRESULT_NoFacilitiesTemporary:
  1871. case CRESULT_NoFacilitiesPermanent:
  1872. case CRESULT_Administrative:
  1873. {
  1874. ulResult = NDIS_STATUS_TAPI_DISCONNECTMODE_UNAVAIL;
  1875. break;
  1876. }
  1877. case CRESULT_NoFraming:
  1878. {
  1879. ulResult = NDIS_STATUS_TAPI_DISCONNECTMODE_INCOMPATIBLE;
  1880. break;
  1881. }
  1882. case CRESULT_InvalidDestination:
  1883. {
  1884. ulResult = NDIS_STATUS_TAPI_DISCONNECTMODE_BADADDRESS;
  1885. break;
  1886. }
  1887. case CRESULT_LostCarrier:
  1888. default:
  1889. {
  1890. ulResult = NDIS_STATUS_TAPI_DISCONNECTMODE_CONGESTION;
  1891. break;
  1892. }
  1893. }
  1894. return ulResult;
  1895. }