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.

1069 lines
26 KiB

  1. /********************************************************************/
  2. /** Copyright(c) 1989 Microsoft Corporation. **/
  3. /********************************************************************/
  4. //***
  5. //
  6. // Filename: smevents.c
  7. //
  8. // Description: This module contain the events processing code for the
  9. // Finite State Machine for PPP.
  10. //
  11. // History:
  12. // Oct 25,1993. NarenG Created Original version.
  13. //
  14. //
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h> // needed for winbase.h
  18. #include <windows.h> // Win32 base API's
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <wchar.h>
  22. #include <rasauth.h>
  23. #include <raseapif.h>
  24. #include <lmcons.h>
  25. #include <raserror.h>
  26. #include <rasman.h>
  27. #include <rtutils.h>
  28. #include <rasppp.h>
  29. #include <pppcp.h>
  30. #include <ppp.h>
  31. #include <smaction.h>
  32. #include <smevents.h>
  33. #include <receive.h>
  34. #include <auth.h>
  35. #include <callback.h>
  36. #include <lcp.h>
  37. #include <timer.h>
  38. #include <util.h>
  39. #include <worker.h>
  40. #include <bap.h>
  41. static VOID (*ProcessPacket[])( PCB * pPcb,
  42. DWORD CpIndex,
  43. CPCB * pCpCb,
  44. PPP_CONFIG * pRecvConfig ) =
  45. {
  46. NULL,
  47. ReceiveConfigReq,
  48. ReceiveConfigAck,
  49. ReceiveConfigNakRej,
  50. ReceiveConfigNakRej,
  51. ReceiveTermReq,
  52. ReceiveTermAck,
  53. ReceiveCodeRej,
  54. NULL,
  55. ReceiveEchoReq,
  56. ReceiveEchoReply,
  57. ReceiveDiscardReq,
  58. ReceiveIdentification,
  59. ReceiveTimeRemaining
  60. };
  61. /************************************************************************/
  62. /* E V E N T P R O C E S S I N G */
  63. /************************************************************************/
  64. //**
  65. //
  66. // Call: FsmUp
  67. //
  68. // Returns: none.
  69. //
  70. // Description: This is called after a Line Up event occurs.
  71. //
  72. VOID
  73. FsmUp(
  74. IN PCB * pPcb,
  75. IN DWORD CpIndex
  76. )
  77. {
  78. CPCB * pCpCb = GetPointerToCPCB( pPcb, CpIndex );
  79. if ( pCpCb == NULL )
  80. {
  81. return;
  82. }
  83. PppLog( 2, "FsmUp event received for protocol %x on port %d",
  84. CpTable[CpIndex].CpInfo.Protocol, pPcb->hPort );
  85. if ( CpIndex == LCP_INDEX )
  86. {
  87. pPcb->PppPhase = PPP_LCP;
  88. }
  89. switch( pCpCb->State )
  90. {
  91. case FSM_INITIAL:
  92. pCpCb->State = FSM_CLOSED;
  93. break;
  94. case FSM_STARTING:
  95. InitRestartCounters( pPcb, pCpCb );
  96. if ( !FsmSendConfigReq( pPcb, CpIndex, FALSE ) )
  97. {
  98. //
  99. // If we couldn't even send the first configure request, we mark
  100. // this protocol as NOT CONFIGURABLE so that we protocol reject
  101. // this layer. We need to do this since FsmClose will not send
  102. // a terminate request in this state (as per the PPP FSM) and we
  103. // want to terminate this layer gracefully instead of simply
  104. // dropping all the clients packets and having the client
  105. // timeout.
  106. //
  107. pCpCb->fConfigurable = FALSE;
  108. return;
  109. }
  110. pCpCb->State = FSM_REQ_SENT;
  111. break;
  112. default:
  113. //
  114. // Already started
  115. //
  116. PPP_ASSERT( pCpCb->State < 10 );
  117. PppLog( 2, "Illegal transition -> FsmUp received while in %s state",
  118. FsmStates[pCpCb->State] );
  119. break;
  120. }
  121. }
  122. //**
  123. //
  124. // Call: FsmOpen
  125. //
  126. // Returns: None.
  127. //
  128. // Description: This is called after an Open event occurs.
  129. //
  130. VOID
  131. FsmOpen(
  132. IN PCB * pPcb,
  133. IN DWORD CpIndex
  134. )
  135. {
  136. CPCB * pCpCb = GetPointerToCPCB( pPcb, CpIndex );
  137. if ( pCpCb == NULL )
  138. {
  139. return;
  140. }
  141. PppLog( 2, "FsmOpen event received for protocol %x on port %d",
  142. CpTable[CpIndex].CpInfo.Protocol, pPcb->hPort );
  143. switch( pCpCb->State )
  144. {
  145. case FSM_INITIAL:
  146. if ( !FsmThisLayerStarted( pPcb, CpIndex ) )
  147. return;
  148. pCpCb->State = FSM_STARTING;
  149. break;
  150. case FSM_STARTING:
  151. case FSM_REQ_SENT:
  152. case FSM_ACK_RCVD:
  153. case FSM_ACK_SENT:
  154. break;
  155. case FSM_CLOSING:
  156. pCpCb->State = FSM_STOPPING;
  157. //
  158. // Fallthru
  159. //
  160. case FSM_OPENED:
  161. case FSM_STOPPED:
  162. case FSM_STOPPING:
  163. //
  164. // Restart option not implemented.
  165. //
  166. // FsmDown( pPcb, CpIndex );
  167. // FsmUp( pPcb, CpIndex );
  168. //
  169. break;
  170. case FSM_CLOSED:
  171. InitRestartCounters( pPcb, pCpCb );
  172. if ( !FsmSendConfigReq( pPcb, CpIndex, FALSE ) )
  173. return;
  174. pCpCb->State = FSM_REQ_SENT;
  175. break;
  176. default:
  177. PPP_ASSERT( pCpCb->State < 10 );
  178. PppLog( 2, "Illegal transition->FsmOpen received while in %s state",
  179. FsmStates[pCpCb->State] );
  180. break;
  181. }
  182. }
  183. //**
  184. //
  185. // Call: FsmDown
  186. //
  187. // Returns: None.
  188. //
  189. // Description: Will get called after the physical line goes down.
  190. //
  191. VOID
  192. FsmDown(
  193. IN PCB * pPcb,
  194. IN DWORD CpIndex
  195. )
  196. {
  197. CPCB * pCpCb = GetPointerToCPCB( pPcb, CpIndex );
  198. if ( pCpCb == NULL )
  199. {
  200. return;
  201. }
  202. PppLog( 2, "FsmDown event received for protocol %x on port %d",
  203. CpTable[CpIndex].CpInfo.Protocol, pPcb->hPort );
  204. RemoveFromTimerQ( pPcb->dwPortId,
  205. pCpCb->LastId,
  206. CpTable[CpIndex].CpInfo.Protocol,
  207. FALSE,
  208. TIMER_EVENT_TIMEOUT );
  209. switch( pCpCb->State )
  210. {
  211. case FSM_CLOSED:
  212. case FSM_CLOSING:
  213. if ( !FsmReset( pPcb, CpIndex ) )
  214. return;
  215. pCpCb->State = FSM_INITIAL;
  216. break;
  217. case FSM_OPENED:
  218. if ( !FsmThisLayerDown( pPcb, CpIndex ) )
  219. return;
  220. //
  221. // Fallthru
  222. //
  223. case FSM_REQ_SENT:
  224. case FSM_ACK_RCVD:
  225. case FSM_ACK_SENT:
  226. case FSM_STOPPING:
  227. if ( !FsmReset( pPcb, CpIndex ) )
  228. return;
  229. pCpCb->State = FSM_STARTING;
  230. break;
  231. case FSM_STOPPED:
  232. if ( !FsmThisLayerStarted( pPcb, CpIndex ) )
  233. return;
  234. if ( !FsmReset( pPcb, CpIndex ) )
  235. return;
  236. pCpCb->State = FSM_STARTING;
  237. break;
  238. case FSM_STARTING:
  239. case FSM_INITIAL:
  240. default:
  241. PPP_ASSERT( pCpCb->State < 10 );
  242. PppLog( 2, "Illegal transition->FsmDown received while in %s state",
  243. FsmStates[pCpCb->State] );
  244. break;
  245. }
  246. if ( CpIndex == LCP_INDEX )
  247. {
  248. pPcb->PppPhase = PPP_LCP;
  249. }
  250. }
  251. //**
  252. //
  253. // Call: FsmClose
  254. //
  255. // Returns: None.
  256. //
  257. // Description: Will get called when a close connection is requested.
  258. // NOTE: Call FsmThisLayerFinished in the states where we do
  259. // not have to send a Term Req. and wait for a Term Ack.
  260. // This is done so that it is guaranteed that
  261. // FsmThisLayerFinished is called in ALL states. We need
  262. // to do this since all processing of failures is done in
  263. // the FsmThisLayerFinished call.
  264. //
  265. VOID
  266. FsmClose(
  267. IN PCB * pPcb,
  268. IN DWORD CpIndex
  269. )
  270. {
  271. CPCB * pCpCb = GetPointerToCPCB( pPcb, CpIndex );
  272. if ( pCpCb == NULL )
  273. {
  274. return;
  275. }
  276. PppLog( 2, "FsmClose event received for protocol %x on port %d",
  277. CpTable[CpIndex].CpInfo.Protocol, pPcb->hPort );
  278. if ( CpIndex == LCP_INDEX )
  279. {
  280. pPcb->PppPhase = PPP_LCP;
  281. }
  282. //
  283. // We are closing this layer so remove any items from the timer Q
  284. //
  285. RemoveFromTimerQ( pPcb->dwPortId,
  286. pCpCb->LastId,
  287. CpTable[CpIndex].CpInfo.Protocol,
  288. FALSE,
  289. TIMER_EVENT_TIMEOUT );
  290. switch ( pCpCb->State )
  291. {
  292. case FSM_STARTING:
  293. pCpCb->State = FSM_INITIAL;
  294. if ( !FsmThisLayerFinished( pPcb, CpIndex, FALSE ) )
  295. return;
  296. break;
  297. case FSM_STOPPED:
  298. pCpCb->State = FSM_CLOSED;
  299. if ( !FsmThisLayerFinished( pPcb, CpIndex, FALSE ) )
  300. return;
  301. break;
  302. case FSM_STOPPING:
  303. pCpCb->State = FSM_CLOSING;
  304. if ( !FsmThisLayerFinished( pPcb, CpIndex, FALSE ) )
  305. return;
  306. break;
  307. case FSM_REQ_SENT:
  308. case FSM_OPENED:
  309. if ( !FsmThisLayerDown( pPcb, CpIndex ) )
  310. return;
  311. //
  312. // Fallthru
  313. //
  314. case FSM_ACK_RCVD:
  315. case FSM_ACK_SENT:
  316. InitRestartCounters( pPcb, pCpCb );
  317. //
  318. // May not be able to do this because the link may be down.
  319. //
  320. FsmSendTermReq( pPcb, CpIndex );
  321. pCpCb->State = FSM_CLOSING;
  322. break;
  323. case FSM_CLOSING:
  324. case FSM_CLOSED:
  325. case FSM_INITIAL:
  326. if ( !FsmThisLayerFinished( pPcb, CpIndex, FALSE ) )
  327. return;
  328. //
  329. // nothing to do
  330. //
  331. break;
  332. default:
  333. PPP_ASSERT( pCpCb->State < 10 );
  334. PppLog( 2,"Illegal transition->FsmClose received while in %s state",
  335. FsmStates[pCpCb->State] );
  336. break;
  337. }
  338. }
  339. //**
  340. //
  341. // Call: FsmTimeout
  342. //
  343. // Returns: None
  344. //
  345. // Description: Called to process a timeout while waiting for reply
  346. // from remote host.
  347. //
  348. VOID
  349. FsmTimeout(
  350. IN PCB * pPcb,
  351. IN DWORD CpIndex,
  352. IN DWORD Id,
  353. IN BOOL fAuthenticator
  354. )
  355. {
  356. CPCB * pCpCb = GetPointerToCPCB( pPcb, CpIndex );
  357. LCPCB * pLcpCb = (LCPCB*)(pPcb->LcpCb.pWorkBuf);
  358. if ( pCpCb == NULL )
  359. {
  360. //
  361. // If we got a timeout for an authentication CB that is no longer
  362. // active, we just ignore it.
  363. //
  364. return;
  365. }
  366. PppLog( 2,
  367. "Recv timeout event received for portid=%d,Id=%d,Protocol=%x,fAuth=%d",
  368. pPcb->dwPortId, Id, CpTable[CpIndex].CpInfo.Protocol, fAuthenticator );
  369. //
  370. // If we are authenticating we use the ConfigRetryCount
  371. //
  372. if ( CpIndex == GetCpIndexFromProtocol( fAuthenticator
  373. ? pLcpCb->Local.Work.AP
  374. : pLcpCb->Remote.Work.AP ) )
  375. {
  376. if ( pPcb->PppPhase == PPP_AP )
  377. {
  378. pCpCb = ( fAuthenticator )
  379. ? &(pPcb->AuthenticatorCb)
  380. : &(pPcb->AuthenticateeCb);
  381. //
  382. // Silently discard timeouts for packets with Id < pPcb->LastId
  383. //
  384. if ( Id < pCpCb->LastId )
  385. {
  386. return;
  387. }
  388. if ( pCpCb->ConfigRetryCount > 0 )
  389. {
  390. (pCpCb->ConfigRetryCount)--;
  391. ApWork( pPcb, CpIndex, NULL, NULL, fAuthenticator );
  392. }
  393. else
  394. {
  395. //
  396. // If an error has already been set, do not change it.
  397. //
  398. if ( pPcb->LcpCb.dwError == NO_ERROR )
  399. {
  400. pPcb->LcpCb.dwError = ERROR_PPP_TIMEOUT;
  401. }
  402. NotifyCallerOfFailure( pPcb, pPcb->LcpCb.dwError );
  403. }
  404. }
  405. return;
  406. }
  407. else if ( CpIndex == GetCpIndexFromProtocol( PPP_CBCP_PROTOCOL ) )
  408. {
  409. if ( pPcb->PppPhase == PPP_NEGOTIATING_CALLBACK )
  410. {
  411. //
  412. // Silently discard timeouts for packets with Id < pPcb->LastId
  413. //
  414. if ( Id < pCpCb->LastId )
  415. {
  416. return;
  417. }
  418. if ( pCpCb->ConfigRetryCount > 0 )
  419. {
  420. (pCpCb->ConfigRetryCount)--;
  421. CbWork( pPcb, CpIndex, NULL, NULL );
  422. }
  423. else
  424. {
  425. //
  426. // If an error has already been set, do not change it.
  427. //
  428. if ( pPcb->LcpCb.dwError == NO_ERROR )
  429. {
  430. pPcb->LcpCb.dwError = ERROR_PPP_TIMEOUT;
  431. }
  432. NotifyCallerOfFailure( pPcb, pPcb->LcpCb.dwError );
  433. }
  434. }
  435. }
  436. //
  437. // Silently discard timeouts for packets with Id < pPcb->LastId
  438. //
  439. if ( Id < pCpCb->LastId )
  440. {
  441. return;
  442. }
  443. switch( pCpCb->State )
  444. {
  445. case FSM_REQ_SENT:
  446. case FSM_ACK_RCVD:
  447. case FSM_ACK_SENT:
  448. if ( pCpCb->ConfigRetryCount > 0 )
  449. {
  450. (pCpCb->ConfigRetryCount)--;
  451. //
  452. // If we have not received any PPP frames from the server yet.
  453. //
  454. if ( ( CpIndex == LCP_INDEX ) &&
  455. ( pPcb->LcpCb.dwError == ERROR_PPP_NO_RESPONSE ) &&
  456. ( !(pPcb->fFlags & PCBFLAG_IS_SERVER) ) )
  457. {
  458. NotifyCaller( pPcb, PPPMSG_Progress, NULL );
  459. }
  460. // If the RestartTimer value is less then the configured
  461. // restart timer value, then bump it up by one second.
  462. //
  463. if ( pPcb->RestartTimer < PppConfigInfo.DefRestartTimer )
  464. {
  465. (pPcb->RestartTimer)++;
  466. }
  467. if ( !FsmSendConfigReq( pPcb, CpIndex, TRUE ) )
  468. return;
  469. if ( pCpCb->State != FSM_ACK_SENT )
  470. pCpCb->State = FSM_REQ_SENT;
  471. }
  472. else
  473. {
  474. PppLog( 1, "Request retry exceeded" );
  475. //
  476. // If the LCP layer exceeded its retry count
  477. //
  478. if ( pCpCb->dwError == NO_ERROR )
  479. {
  480. pCpCb->dwError = ERROR_PPP_TIMEOUT;
  481. }
  482. if ( !FsmThisLayerFinished( pPcb, CpIndex, TRUE ) )
  483. return;
  484. pCpCb->State = FSM_STOPPED;
  485. }
  486. break;
  487. case FSM_CLOSING:
  488. case FSM_STOPPING:
  489. if ( pCpCb->TermRetryCount > 0 )
  490. {
  491. (pCpCb->TermRetryCount)--;
  492. FsmSendTermReq( pPcb, CpIndex );
  493. }
  494. else
  495. {
  496. PppLog( 1, "Terminate retry exceeded" );
  497. if ( pCpCb->dwError == NO_ERROR )
  498. {
  499. pCpCb->dwError = ERROR_PPP_TIMEOUT;
  500. }
  501. if ( !FsmThisLayerFinished( pPcb, CpIndex, TRUE ) )
  502. return;
  503. pCpCb->State = ( pCpCb->State == FSM_CLOSING ) ? FSM_CLOSED
  504. : FSM_STOPPED;
  505. }
  506. break;
  507. case FSM_OPENED:
  508. case FSM_INITIAL:
  509. case FSM_STARTING:
  510. case FSM_CLOSED:
  511. case FSM_STOPPED:
  512. default:
  513. PPP_ASSERT( pCpCb->State < 10 );
  514. PppLog( 2, "Illegal transition->FsmTimeout rcvd while in %s state",
  515. FsmStates[pCpCb->State] );
  516. break;
  517. }
  518. }
  519. //**
  520. //
  521. // Call: FsmReceive
  522. //
  523. // Returns: None
  524. //
  525. // Description: Called when a PPP packet is received. Will process the
  526. // incomming packet.
  527. //
  528. VOID
  529. FsmReceive(
  530. IN PCB * pPcb,
  531. IN PPP_PACKET * pPacket,
  532. IN DWORD dwPacketLength
  533. )
  534. {
  535. DWORD dwProtocol;
  536. DWORD CpIndex;
  537. PPP_CONFIG * pRecvConfig;
  538. CPCB * pCpCb;
  539. DWORD dwLength;
  540. LCPCB * pLcpCb = (LCPCB*)(pPcb->LcpCb.pWorkBuf);
  541. LogPPPPacket( TRUE, pPcb, pPacket, dwPacketLength );
  542. //
  543. // Validate length of packet
  544. //
  545. if ( dwPacketLength < ( PPP_PACKET_HDR_LEN + PPP_CONFIG_HDR_LEN ) )
  546. {
  547. PppLog( 1, "Silently discarding badly formed packet" );
  548. return;
  549. }
  550. dwProtocol = WireToHostFormat16( pPacket->Protocol );
  551. CpIndex = GetCpIndexFromProtocol( dwProtocol );
  552. switch( pPcb->PppPhase )
  553. {
  554. case PPP_NEGOTIATING_CALLBACK:
  555. //
  556. // Silently discard any packet other than LCP and Authentication
  557. // and callback packets if we are in the callback phase
  558. //
  559. if ( CpIndex == GetCpIndexFromProtocol( PPP_CBCP_PROTOCOL ) )
  560. break;
  561. //
  562. // Fallthru
  563. //
  564. case PPP_AP:
  565. //
  566. // Silently discard any packet other than LCP and Authentication
  567. // packets if we are in the authentication phase
  568. //
  569. if ( CpIndex == GetCpIndexFromProtocol( pLcpCb->Local.Work.AP ) )
  570. break;
  571. if ( CpIndex == GetCpIndexFromProtocol( pLcpCb->Remote.Work.AP ) )
  572. break;
  573. //
  574. // If we are the authenticatee being authenticated by EAP, then if we
  575. // receive an NCP packet we should assume success. We do this by
  576. // generating a fake EAP_SUCCESS message and send it to the
  577. // authenticatee.
  578. //
  579. if ( ( pLcpCb->Remote.Work.AP == PPP_EAP_PROTOCOL )
  580. && ( pPcb->PppPhase == PPP_AP ) )
  581. {
  582. PPPAP_INPUT ApInput;
  583. switch( dwProtocol )
  584. {
  585. case PPP_CBCP_PROTOCOL:
  586. case PPP_IPCP_PROTOCOL:
  587. case PPP_ATCP_PROTOCOL:
  588. case PPP_IPXCP_PROTOCOL:
  589. case PPP_NBFCP_PROTOCOL:
  590. case PPP_CCP_PROTOCOL:
  591. case PPP_BACP_PROTOCOL:
  592. PppLog( 1,"Received and NCP or CBCP packet before EAP success");
  593. ZeroMemory( &ApInput, sizeof( ApInput ) );
  594. ApInput.fSuccessPacketReceived = TRUE;
  595. CpIndex = GetCpIndexFromProtocol( PPP_EAP_PROTOCOL );
  596. if ( pPcb->AuthenticateeCb.LastId != (DWORD)-1 )
  597. {
  598. RemoveFromTimerQ(
  599. pPcb->dwPortId,
  600. pPcb->AuthenticateeCb.LastId,
  601. pLcpCb->Remote.Work.AP,
  602. FALSE,
  603. TIMER_EVENT_TIMEOUT );
  604. }
  605. ApWork( pPcb, CpIndex, NULL, &ApInput, FALSE );
  606. //
  607. // PppPhase will now be one of PPP_LCP (if ApWork failed),
  608. // PPP_NCP, or PPP_NEGOTIATING_CALLBACK. We will not call
  609. // this function recursively again.
  610. //
  611. //
  612. // Now process the NCP we received if we have passed
  613. // authentication
  614. //
  615. if ( ( pPcb->PppPhase == PPP_NCP ) ||
  616. ( pPcb->PppPhase == PPP_NEGOTIATING_CALLBACK ) )
  617. {
  618. FsmReceive( pPcb, pPacket, dwPacketLength );
  619. }
  620. return;
  621. default:
  622. break;
  623. }
  624. }
  625. //
  626. // Fallthru
  627. //
  628. case PPP_LCP:
  629. //
  630. // Silently discard any packet other than LCP if we are in the
  631. // LCP or termination or authentication phases
  632. //
  633. if ( CpIndex != LCP_INDEX )
  634. {
  635. PppLog( 1, "Non-LCP packet received when LCP is not opened");
  636. PppLog( 1, "Packet being silently discarded" );
  637. return;
  638. }
  639. break;
  640. case PPP_NCP:
  641. //
  642. // We do not recognize this protocol
  643. //
  644. if ( CpIndex == (DWORD)-1 )
  645. {
  646. if ( dwProtocol == PPP_BAP_PROTOCOL )
  647. {
  648. CpIndex = GetCpIndexFromProtocol( PPP_BACP_PROTOCOL );
  649. if (CpIndex != (DWORD)-1)
  650. {
  651. pCpCb = GetPointerToCPCB( pPcb, CpIndex );
  652. if ( pCpCb->State == FSM_OPENED )
  653. {
  654. BapEventReceive( pPcb->pBcb, pPacket, dwPacketLength );
  655. return;
  656. }
  657. }
  658. BapTrace( "BAP packet silently discarded" );
  659. return;
  660. }
  661. //
  662. // If this is a Control Protocol then we reject it, otherwise we
  663. // we silently discard it.
  664. // We used to also check if the protocol is less than 0x0000BFFF,
  665. // but Shiva has proprietary NBFCP with id 0x0000CFEC and we need
  666. // to protocol reject it.
  667. //
  668. if ( dwProtocol >= 0x00008000 )
  669. {
  670. FsmSendProtocolRej( pPcb, pPacket, dwPacketLength );
  671. }
  672. else
  673. {
  674. PppLog( 1, "Network-layer packet rcvd.");
  675. PppLog( 1, "Packet being silently discarded" );
  676. }
  677. return;
  678. }
  679. break;
  680. default:
  681. PppLog( 1, "Packet received being silently discarded" );
  682. return;
  683. }
  684. pCpCb = GetPointerToCPCB( pPcb, CpIndex );
  685. pRecvConfig = (PPP_CONFIG*)(pPacket->Information);
  686. //
  687. // We received a PPP packet so the remote host does support it
  688. //
  689. if ( pPcb->LcpCb.dwError == ERROR_PPP_NO_RESPONSE )
  690. {
  691. pPcb->LcpCb.dwError = NO_ERROR;
  692. }
  693. //
  694. // If we received a packet for a protocol that we have but do not
  695. // wish to configure then we send a configure reject.
  696. //
  697. if ( ( pCpCb == NULL ) || !(pCpCb->fConfigurable) )
  698. {
  699. FsmSendProtocolRej( pPcb, pPacket, dwPacketLength );
  700. return;
  701. }
  702. dwLength = WireToHostFormat16( pRecvConfig->Length );
  703. if ( ( dwLength > ( dwPacketLength - PPP_PACKET_HDR_LEN ) ) ||
  704. ( dwLength < PPP_CONFIG_HDR_LEN ) )
  705. {
  706. PppLog( 1,"Silently discarding badly formed packet" );
  707. return;
  708. }
  709. //
  710. // Not in ProcessPacket table since parameters to this are different.
  711. //
  712. if ( ( CpIndex == LCP_INDEX ) && ( pRecvConfig->Code == PROT_REJ ) )
  713. {
  714. ReceiveProtocolRej( pPcb, pPacket );
  715. return;
  716. }
  717. //
  718. // Make sure that the protocol can handle the config code sent.
  719. //
  720. if ( ( pRecvConfig->Code == 0 ) ||
  721. !( pRecvConfig->Code < CpTable[CpIndex].CpInfo.Recognize ) )
  722. {
  723. ReceiveUnknownCode( pPcb, CpIndex, pCpCb, pRecvConfig );
  724. return;
  725. }
  726. //
  727. // If we received an authentication packet.
  728. //
  729. if ( CpIndex == GetCpIndexFromProtocol( pLcpCb->Local.Work.AP ) )
  730. {
  731. if ( ApIsAuthenticatorPacket( CpIndex, pRecvConfig->Code ) )
  732. {
  733. if ( pPcb->AuthenticatorCb.LastId != (DWORD)-1 )
  734. {
  735. //
  736. // If we have just received a packet we have been waiting for
  737. // then we stop the outstanding timout for it. We let the
  738. // APs do the Id matching.
  739. //
  740. if ( pRecvConfig->Id == pPcb->AuthenticatorCb.LastId )
  741. {
  742. RemoveFromTimerQ(
  743. pPcb->dwPortId,
  744. pPcb->AuthenticatorCb.LastId,
  745. pLcpCb->Local.Work.AP,
  746. TRUE,
  747. TIMER_EVENT_TIMEOUT );
  748. }
  749. }
  750. ApWork( pPcb, CpIndex, pRecvConfig, NULL, TRUE );
  751. return;
  752. }
  753. else if ( CpIndex != GetCpIndexFromProtocol( pLcpCb->Remote.Work.AP ) )
  754. {
  755. //
  756. // Silently drop invalid packet, ie. Authenticatee's packet sent
  757. // using Authenticater's protocol
  758. //
  759. PppLog( 1,
  760. "Authentication packet received being silently discarded");
  761. return;
  762. }
  763. }
  764. if ( CpIndex == GetCpIndexFromProtocol( pLcpCb->Remote.Work.AP ) )
  765. {
  766. if ( !ApIsAuthenticatorPacket( CpIndex, pRecvConfig->Code ) )
  767. {
  768. if ( pPcb->AuthenticateeCb.LastId != (DWORD)-1 )
  769. {
  770. //
  771. // If we have just received a packet we have been waiting for
  772. // then we stop the outstanding timout for it. We let the
  773. // APs do the Id matching.
  774. //
  775. if ( pRecvConfig->Id == pPcb->AuthenticateeCb.LastId )
  776. {
  777. RemoveFromTimerQ(
  778. pPcb->dwPortId,
  779. pPcb->AuthenticateeCb.LastId,
  780. pLcpCb->Remote.Work.AP,
  781. FALSE,
  782. TIMER_EVENT_TIMEOUT );
  783. }
  784. }
  785. ApWork( pPcb, CpIndex, pRecvConfig, NULL, FALSE );
  786. }
  787. else
  788. {
  789. //
  790. // Silently drop invalid packet, ie. Authenticator's packet sent
  791. // using Authenticatee's protocol
  792. //
  793. PppLog( 1,
  794. "Authentication packet received being silently discarded");
  795. }
  796. return;
  797. }
  798. if ( CpIndex == GetCpIndexFromProtocol( PPP_CBCP_PROTOCOL ) )
  799. {
  800. if ( pCpCb->LastId != (DWORD)-1 )
  801. {
  802. //
  803. // If we have just received a packet we have been waiting for
  804. // then we stop the outstanding timout for it. We let the
  805. // CBCP do the Id matching.
  806. //
  807. if ( pRecvConfig->Id == pCpCb->LastId )
  808. {
  809. RemoveFromTimerQ(
  810. pPcb->dwPortId,
  811. pCpCb->LastId,
  812. PPP_CBCP_PROTOCOL,
  813. FALSE,
  814. TIMER_EVENT_TIMEOUT );
  815. }
  816. }
  817. CbWork( pPcb, CpIndex, pRecvConfig, NULL );
  818. }
  819. else
  820. {
  821. //
  822. // Any combination of packets allowed here.
  823. //
  824. //if this is any packet and not Echo request packet,
  825. //and if the flag is set then reset the flag.
  826. if ( pRecvConfig->Code != ECHO_REPLY )
  827. {
  828. if ( pPcb->fEchoRequestSend ) pPcb->fEchoRequestSend = 0;
  829. }
  830. (*ProcessPacket[pRecvConfig->Code])(pPcb, CpIndex, pCpCb, pRecvConfig);
  831. }
  832. }