Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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