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.

6258 lines
162 KiB

  1. /********************************************************************/
  2. /** Copyright(c) 1989 Microsoft Corporation. **/
  3. /********************************************************************/
  4. //***
  5. //
  6. // Filename: util.c
  7. //
  8. // Description: Contains utility routines used by the PPP engine.
  9. //
  10. // History:
  11. // Oct 31,1993. NarenG Created original version.
  12. //
  13. #define UNICODE // This file is in UNICODE
  14. #include <nt.h>
  15. #include <ntrtl.h>
  16. #include <nturtl.h> // needed for winbase.h
  17. #include <windows.h> // Win32 base API's
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <wchar.h>
  21. #include <ctype.h>
  22. #include <stdarg.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <rpc.h>
  26. #include <winsock2.h>
  27. #include <rtinfo.h>
  28. #include <iprtrmib.h>
  29. #include <ipinfoid.h>
  30. #include <lmcons.h>
  31. #include <lmwksta.h>
  32. #include <lmapibuf.h>
  33. #include <lmsname.h>
  34. #include <rasman.h>
  35. #include <rtutils.h>
  36. #include <mprapip.h>
  37. #include <mprlog.h>
  38. #include <raserror.h>
  39. #include <mprerror.h>
  40. #include <rasppp.h>
  41. #include <pppcp.h>
  42. #include <ppp.h>
  43. #include <smevents.h>
  44. #include <smaction.h>
  45. #include <timer.h>
  46. #include <util.h>
  47. #include <worker.h>
  48. #include <bap.h>
  49. #include <dsrole.h>
  50. #include <ntlsapi.h>
  51. #define INCL_RASAUTHATTRIBUTES
  52. #include <ppputil.h>
  53. #define PASSWORDMAGIC 0xA5
  54. #define CLASSA_ADDR(a) (( (*((UCHAR *)&(a))) & 0x80) == 0)
  55. #define CLASSB_ADDR(a) (( (*((UCHAR *)&(a))) & 0xc0) == 0x80)
  56. #define CLASSC_ADDR(a) (( (*((UCHAR *)&(a))) & 0xe0) == 0xc0)
  57. #define CLASSE_ADDR(a) ((( (*((UCHAR *)&(a))) & 0xf0) == 0xf0) && \
  58. ((a) != 0xffffffff))
  59. #define CLASSA_MASK 0x000000ff
  60. #define CLASSB_MASK 0x0000ffff
  61. #define CLASSC_MASK 0x00ffffff
  62. #define CLASSD_MASK 0x000000e0
  63. #define CLASSE_MASK 0xffffffff
  64. #define GetClassMask(a)\
  65. (CLASSA_ADDR((a)) ? CLASSA_MASK : \
  66. (CLASSB_ADDR((a)) ? CLASSB_MASK : \
  67. (CLASSC_ADDR((a)) ? CLASSC_MASK : CLASSE_MASK)))
  68. VOID ReverseString( CHAR* psz );
  69. //**
  70. //
  71. // Call: InitRestartCounters
  72. //
  73. // Returns: none.
  74. //
  75. // Description: Will initialize all the counters for the Control Protocol
  76. // to their initial values.
  77. //
  78. VOID
  79. InitRestartCounters(
  80. IN PCB * pPcb,
  81. IN CPCB * pCpCb
  82. )
  83. {
  84. pCpCb->ConfigRetryCount = PppConfigInfo.MaxConfigure;
  85. pCpCb->TermRetryCount = PppConfigInfo.MaxTerminate;
  86. }
  87. //**
  88. //
  89. // Call: GetPCBPointerFromhPort
  90. //
  91. // Returns: PCB * - Success
  92. // NULL - Failure
  93. //
  94. // Description: Give an HPORT, this function will return a pointer to the
  95. // port control block for it.
  96. //
  97. PCB *
  98. GetPCBPointerFromhPort(
  99. IN HPORT hPort
  100. )
  101. {
  102. PCB * pPcbWalker = NULL;
  103. DWORD dwIndex = HashPortToBucket( hPort );
  104. for ( pPcbWalker = PcbTable.PcbBuckets[dwIndex].pPorts;
  105. pPcbWalker != (PCB *)NULL;
  106. pPcbWalker = pPcbWalker->pNext
  107. )
  108. {
  109. if ( pPcbWalker->hPort == hPort )
  110. return( pPcbWalker );
  111. }
  112. return( (PCB *)NULL );
  113. }
  114. //**
  115. //
  116. // Call: GetBCBPointerFromhConnection
  117. //
  118. // Returns: BCB * - Success
  119. // NULL - Failure
  120. //
  121. // Description: Given an HCONN, this function will return a pointer to the
  122. // bundle control block for it.
  123. //
  124. BCB *
  125. GetBCBPointerFromhConnection(
  126. IN HCONN hConnection
  127. )
  128. {
  129. BCB * pBcbWalker = NULL;
  130. DWORD dwIndex = HashPortToBucket( hConnection );
  131. for ( pBcbWalker = PcbTable.BcbBuckets[dwIndex].pBundles;
  132. pBcbWalker != (BCB *)NULL;
  133. pBcbWalker = pBcbWalker->pNext
  134. )
  135. {
  136. if ( pBcbWalker->hConnection == hConnection )
  137. return( pBcbWalker );
  138. }
  139. return( (BCB *)NULL );
  140. }
  141. //**
  142. //
  143. // Call: NumLinksInBundle
  144. //
  145. // Returns: The number of links whose LCP is in the Opened state in the bundle
  146. // represented by pBcb
  147. //
  148. DWORD
  149. NumLinksInBundle(
  150. IN BCB * pBcb
  151. )
  152. {
  153. DWORD dwForIndex;
  154. PCB * pPcb;
  155. CPCB * pCpCb;
  156. DWORD dwNumLinks = 0;
  157. PPP_ASSERT( NULL != pBcb );
  158. for (dwForIndex = 0; dwForIndex < pBcb->dwPpcbArraySize; dwForIndex++)
  159. {
  160. pPcb = pBcb->ppPcb[dwForIndex];
  161. if ( NULL == pPcb )
  162. {
  163. continue;
  164. }
  165. pCpCb = GetPointerToCPCB( pPcb, LCP_INDEX );
  166. PPP_ASSERT( NULL != pCpCb );
  167. if ( FSM_OPENED == pCpCb->State )
  168. {
  169. dwNumLinks += 1;
  170. }
  171. }
  172. return( dwNumLinks );
  173. }
  174. //**
  175. //
  176. // Call: GetPCBPointerFromBCB
  177. //
  178. // Returns: PCB * - Success
  179. // NULL - Failure
  180. //
  181. // Description: Given a BCB*, this function will return a pointer to the
  182. // PCB in it with the highest dwSubEntryIndex.
  183. //
  184. PCB *
  185. GetPCBPointerFromBCB(
  186. IN BCB * pBcb
  187. )
  188. {
  189. DWORD dwForIndex;
  190. PCB * pPcb = NULL;
  191. PCB * pPcbTemp;
  192. CPCB * pCpCb;
  193. DWORD dwSubEntryIndex = 0;
  194. if ( pBcb == NULL )
  195. {
  196. return( NULL );
  197. }
  198. for (dwForIndex = 0; dwForIndex < pBcb->dwPpcbArraySize; dwForIndex++)
  199. {
  200. if ( ( pPcbTemp = pBcb->ppPcb[dwForIndex] ) != NULL )
  201. {
  202. pCpCb = GetPointerToCPCB( pPcbTemp, LCP_INDEX );
  203. PPP_ASSERT( NULL != pCpCb );
  204. if ( FSM_OPENED == pCpCb->State )
  205. {
  206. if ( pPcbTemp->dwSubEntryIndex >= dwSubEntryIndex )
  207. {
  208. pPcb = pPcbTemp;
  209. dwSubEntryIndex = pPcbTemp->dwSubEntryIndex;
  210. }
  211. }
  212. }
  213. }
  214. return( pPcb );
  215. }
  216. //**
  217. //
  218. // Call: HashPortToBucket
  219. //
  220. // Returns: Index into the PcbTable for the HPORT passed in.
  221. //
  222. // Description: Will hash the HPORT to a bucket index in the PcbTable.
  223. //
  224. DWORD
  225. HashPortToBucket(
  226. IN HPORT hPort
  227. )
  228. {
  229. return( (HandleToUlong(hPort)) % PcbTable.NumPcbBuckets );
  230. }
  231. //**
  232. //
  233. // Call: InsertWorkItemInQ
  234. //
  235. // Returns: None.
  236. //
  237. // Description: Inserts a work item in to the work item Q.
  238. //
  239. VOID
  240. InsertWorkItemInQ(
  241. IN PCB_WORK_ITEM * pWorkItem
  242. )
  243. {
  244. //
  245. // Take Mutex around work item Q
  246. //
  247. EnterCriticalSection( &(WorkItemQ.CriticalSection) );
  248. if ( WorkItemQ.pQTail != (PCB_WORK_ITEM *)NULL )
  249. {
  250. WorkItemQ.pQTail->pNext = pWorkItem;
  251. WorkItemQ.pQTail = pWorkItem;
  252. if ( ProcessLineDown == pWorkItem->Process )
  253. {
  254. //
  255. // If a lot of work items are coming in, the worker thread may get
  256. // overwhelmed and the following might happen in the work item Q:
  257. // IPCP(port 1)-LineDown(1)-LineUp(1)
  258. // We will send the reply to the IPCP packet to the wrong (ie new)
  259. // peer.
  260. // Proposed solution: Insert a LineDown at the beginning of the
  261. // queue, as well as at the end:
  262. // LineDown(1)-IPCP(port 1)-LineDown(1)-LineUp(1).
  263. // However, this will not take care of the following case:
  264. // IPCP(1)-LD(1)-LU(1)-LCP(1)-LD(1)-LU(1)-LCP(1)
  265. // We transform the above to:
  266. // LD(1)-LD(1)-IPCP(1)-LD(1)-LU(1)-LCP(1)-LD(1)-LU(1)-LCP(1)
  267. // However, the frequency of this problem will be a lot less.
  268. //
  269. PCB_WORK_ITEM * pWorkItem2;
  270. pWorkItem2 = (PCB_WORK_ITEM *)LOCAL_ALLOC( LPTR,
  271. sizeof(PCB_WORK_ITEM));
  272. if ( NULL != pWorkItem2 )
  273. {
  274. pWorkItem2->hPort = pWorkItem->hPort;
  275. pWorkItem2->Process = ProcessLineDown;
  276. PppLog( 2, "Inserting extra PPPEMSG_LineDown for hPort=%d",
  277. pWorkItem2->hPort );
  278. pWorkItem2->pNext = WorkItemQ.pQHead;
  279. WorkItemQ.pQHead = pWorkItem2;
  280. }
  281. }
  282. }
  283. else
  284. {
  285. WorkItemQ.pQHead = pWorkItem;
  286. WorkItemQ.pQTail = pWorkItem;
  287. }
  288. SetEvent( WorkItemQ.hEventNonEmpty );
  289. LeaveCriticalSection( &(WorkItemQ.CriticalSection) );
  290. }
  291. //**
  292. //
  293. // Call: NotifyCallerOfFailureOnPort
  294. //
  295. // Returns: None
  296. //
  297. // Description: Will notify the caller or initiator of the PPP connection on
  298. // the port about a failure event.
  299. //
  300. VOID
  301. NotifyCallerOfFailureOnPort(
  302. IN HPORT hPort,
  303. IN BOOL fServer,
  304. IN DWORD dwRetCode
  305. )
  306. {
  307. PPP_MESSAGE PppMsg;
  308. DWORD dwMsgId = fServer ? PPPDDMMSG_PppFailure : PPPMSG_PppFailure;
  309. ZeroMemory( &PppMsg, sizeof( PppMsg ) );
  310. PppMsg.hPort = hPort;
  311. PppMsg.dwMsgId = dwMsgId;
  312. switch( dwMsgId )
  313. {
  314. case PPPDDMMSG_PppFailure:
  315. PppMsg.ExtraInfo.DdmFailure.dwError = dwRetCode;
  316. PppConfigInfo.SendPPPMessageToDdm( &PppMsg );
  317. break;
  318. case PPPMSG_PppFailure:
  319. PppMsg.ExtraInfo.Failure.dwError = dwRetCode;
  320. PppMsg.ExtraInfo.Failure.dwExtendedError = 0;
  321. RasSendPppMessageToRasman( PppMsg.hPort, (LPBYTE) &PppMsg );
  322. break;
  323. }
  324. }
  325. //**
  326. //
  327. // Call: NotifyCallerOfFailure
  328. //
  329. // Returns: None
  330. //
  331. // Description: Will notify the caller or initiator of the PPP connection on
  332. // the port about a failure event.
  333. //
  334. VOID
  335. NotifyCallerOfFailure(
  336. IN PCB * pPcb,
  337. IN DWORD dwRetCode
  338. )
  339. {
  340. //
  341. // Discard all non-LCP packets
  342. //
  343. pPcb->PppPhase = PPP_LCP;
  344. NotifyCaller( pPcb,
  345. ( pPcb->fFlags & PCBFLAG_IS_SERVER )
  346. ? PPPDDMMSG_PppFailure
  347. : PPPMSG_PppFailure,
  348. &dwRetCode );
  349. }
  350. //**
  351. //
  352. // Call: NotifyCaller
  353. //
  354. // Returns: None.
  355. //
  356. // Description: Will notify the caller or initiater of the PPP connection
  357. // for the port about PPP events on that port.
  358. //
  359. VOID
  360. NotifyCaller(
  361. IN PCB * pPcb,
  362. IN DWORD dwMsgId,
  363. IN PVOID pData
  364. )
  365. {
  366. DWORD dwRetCode;
  367. PPP_MESSAGE PppMsg;
  368. ZeroMemory( &PppMsg, sizeof( PppMsg ) );
  369. PppLog( 2, "NotifyCaller(hPort=%d, dwMsgId=%d)", pPcb->hPort, dwMsgId );
  370. PppMsg.hPort = pPcb->hPort;
  371. PppMsg.dwMsgId = dwMsgId;
  372. switch( dwMsgId )
  373. {
  374. case PPPDDMMSG_Stopped:
  375. if ( !(pPcb->fFlags & PCBFLAG_IS_SERVER) )
  376. {
  377. return;
  378. }
  379. PppMsg.ExtraInfo.DdmStopped.dwReason = *((DWORD*)pData);
  380. PppConfigInfo.SendPPPMessageToDdm( &PppMsg );
  381. break;
  382. case PPPDDMMSG_PortCleanedUp:
  383. if ( !(pPcb->fFlags & PCBFLAG_IS_SERVER) )
  384. {
  385. return;
  386. }
  387. PppConfigInfo.SendPPPMessageToDdm( &PppMsg );
  388. break;
  389. case PPPDDMMSG_PppFailure:
  390. if ( !(pPcb->fFlags & PCBFLAG_IS_SERVER) )
  391. {
  392. return;
  393. }
  394. PppMsg.ExtraInfo.DdmFailure.dwError = *((DWORD*)pData);
  395. if ( pPcb->pBcb->szRemoteUserName[0] != (CHAR)NULL )
  396. {
  397. strcpy(PppMsg.ExtraInfo.DdmFailure.szUserName,
  398. pPcb->pBcb->szRemoteUserName);
  399. }
  400. else
  401. {
  402. PppMsg.ExtraInfo.DdmFailure.szUserName[0] = (CHAR)NULL;
  403. }
  404. if ( pPcb->pBcb->szRemoteDomain[0] != (CHAR)NULL )
  405. {
  406. strcpy(PppMsg.ExtraInfo.DdmFailure.szLogonDomain,
  407. pPcb->pBcb->szRemoteDomain);
  408. }
  409. else
  410. {
  411. PppMsg.ExtraInfo.DdmFailure.szLogonDomain[0] = (CHAR)NULL;
  412. }
  413. PppConfigInfo.SendPPPMessageToDdm( &PppMsg );
  414. break;
  415. case PPPDDMMSG_NewBundle:
  416. case PPPDDMMSG_NewLink:
  417. if ( !(pPcb->fFlags & PCBFLAG_IS_SERVER) )
  418. return;
  419. if ( dwMsgId == PPPDDMMSG_NewBundle )
  420. {
  421. PppMsg.ExtraInfo.DdmNewBundle.pClientInterface
  422. = GetClientInterfaceInfo( pPcb );
  423. }
  424. PppConfigInfo.SendPPPMessageToDdm( &PppMsg );
  425. break;
  426. case PPPDDMMSG_CallbackRequest:
  427. if ( !(pPcb->fFlags & PCBFLAG_IS_SERVER) )
  428. return;
  429. {
  430. PPPDDM_CALLBACK_REQUEST * pPppDdmCallbackRequest =
  431. ( PPPDDM_CALLBACK_REQUEST *)pData;
  432. CopyMemory( &(PppMsg.ExtraInfo.CallbackRequest),
  433. pPppDdmCallbackRequest,
  434. sizeof( PPPDDM_CALLBACK_REQUEST ) );
  435. }
  436. PppConfigInfo.SendPPPMessageToDdm( &PppMsg );
  437. break;
  438. case PPPDDMMSG_PppDone:
  439. if ( !(pPcb->fFlags & PCBFLAG_IS_SERVER) )
  440. return;
  441. PppMsg.ExtraInfo.ProjectionResult = *((PPP_PROJECTION_RESULT*)pData);
  442. PppConfigInfo.SendPPPMessageToDdm( &PppMsg );
  443. break;
  444. case PPPDDMMSG_Authenticated:
  445. //
  446. // Only server wants to know about authentication results.
  447. //
  448. if ( !(pPcb->fFlags & PCBFLAG_IS_SERVER) )
  449. return;
  450. strcpy( PppMsg.ExtraInfo.AuthResult.szUserName,
  451. pPcb->pBcb->szRemoteUserName);
  452. strcpy( PppMsg.ExtraInfo.AuthResult.szLogonDomain,
  453. pPcb->pBcb->szRemoteDomain );
  454. PppMsg.ExtraInfo.AuthResult.fAdvancedServer =
  455. pPcb->fFlags & PCBFLAG_IS_ADVANCED_SERVER;
  456. PppConfigInfo.SendPPPMessageToDdm( &PppMsg );
  457. break;
  458. case PPPMSG_PppDone:
  459. case PPPMSG_AuthRetry:
  460. case PPPMSG_Projecting:
  461. case PPPMSG_CallbackRequest:
  462. case PPPMSG_Callback:
  463. case PPPMSG_ChangePwRequest:
  464. case PPPMSG_LinkSpeed:
  465. case PPPMSG_Progress:
  466. if ( pPcb->fFlags & PCBFLAG_IS_SERVER )
  467. return;
  468. RasSendPppMessageToRasman( PppMsg.hPort, (LPBYTE) &PppMsg );
  469. break;
  470. case PPPMSG_Stopped:
  471. if ( pPcb->fFlags & PCBFLAG_IS_SERVER )
  472. return;
  473. PppMsg.dwError = *((DWORD*)pData);
  474. if(pPcb->fFlags & PCBFLAG_RECVD_TERM_REQ)
  475. {
  476. PppMsg.ExtraInfo.Stopped.dwFlags =
  477. PPP_FAILURE_REMOTE_DISCONNECT;
  478. }
  479. else
  480. {
  481. PppMsg.ExtraInfo.Stopped.dwFlags = 0;
  482. }
  483. RasSendPppMessageToRasman( PppMsg.hPort, (LPBYTE) &PppMsg );
  484. break;
  485. case PPPMSG_PppFailure:
  486. if ( pPcb->fFlags & PCBFLAG_IS_SERVER )
  487. return;
  488. PppMsg.ExtraInfo.Failure.dwError = *((DWORD*)pData);
  489. PppMsg.ExtraInfo.Failure.dwExtendedError = 0;
  490. RasSendPppMessageToRasman( PppMsg.hPort, (LPBYTE) &PppMsg );
  491. break;
  492. case PPPMSG_ProjectionResult:
  493. if ( pPcb->fFlags & PCBFLAG_IS_SERVER )
  494. return;
  495. PppMsg.ExtraInfo.ProjectionResult = *((PPP_PROJECTION_RESULT*)pData);
  496. RasSendPppMessageToRasman( PppMsg.hPort, (LPBYTE) &PppMsg );
  497. break;
  498. case PPPMSG_InvokeEapUI:
  499. if ( pPcb->fFlags & PCBFLAG_IS_SERVER )
  500. return;
  501. PppMsg.ExtraInfo.InvokeEapUI = *((PPP_INVOKE_EAP_UI*)pData);
  502. RasSendPppMessageToRasman( PppMsg.hPort, (LPBYTE)&PppMsg );
  503. break;
  504. case PPPMSG_SetCustomAuthData:
  505. if ( pPcb->fFlags & PCBFLAG_IS_SERVER )
  506. return;
  507. PppMsg.ExtraInfo.SetCustomAuthData= *((PPP_SET_CUSTOM_AUTH_DATA*)pData);
  508. RasSendPppMessageToRasman( PppMsg.hPort, (LPBYTE)&PppMsg );
  509. break;
  510. default:
  511. PPP_ASSERT( FALSE );
  512. break;
  513. }
  514. return;
  515. }
  516. //**
  517. //
  518. // Call: LogPPPEvent
  519. //
  520. // Returns: None
  521. //
  522. // Description: Will log a PPP event in the eventvwr.
  523. //
  524. VOID
  525. LogPPPEvent(
  526. IN DWORD dwEventId,
  527. IN DWORD dwData
  528. )
  529. {
  530. PppLog( 2, "EventLog EventId = %d, error = %d", dwEventId, dwData );
  531. PppLogError( dwEventId, 0, NULL, dwData );
  532. }
  533. //**
  534. //
  535. // Call: GetCpIndexFromProtocol
  536. //
  537. // Returns: Index of the CP with dwProtocol in the CpTable.
  538. // -1 if there is not CP with dwProtocol in CpTable.
  539. //
  540. // Description:
  541. //
  542. DWORD
  543. GetCpIndexFromProtocol(
  544. IN DWORD dwProtocol
  545. )
  546. {
  547. DWORD dwIndex;
  548. for ( dwIndex = 0;
  549. dwIndex < ( PppConfigInfo.NumberOfCPs + PppConfigInfo.NumberOfAPs );
  550. dwIndex++
  551. )
  552. {
  553. if ( CpTable[dwIndex].CpInfo.Protocol == dwProtocol )
  554. return( dwIndex );
  555. }
  556. return( (DWORD)-1 );
  557. }
  558. //**
  559. //
  560. // Call: IsLcpOpened
  561. //
  562. // Returns: TRUE - LCP is in the OPENED state.
  563. // FALSE - Otherwise
  564. //
  565. // Description: Uses the PppPhase value of the PORT_CONTROL_BLOCK to detect
  566. // to see if the LCP layer is in the OPENED state.
  567. //
  568. BOOL
  569. IsLcpOpened(
  570. PCB * pPcb
  571. )
  572. {
  573. if ( pPcb->PppPhase == PPP_LCP )
  574. return( FALSE );
  575. else
  576. return( TRUE );
  577. }
  578. //**
  579. //
  580. // Call: GetConfiguredInfo
  581. //
  582. // Returns: NO_ERROR - Success
  583. // Non-zero returns - Failure
  584. //
  585. // Description:
  586. //
  587. DWORD
  588. GetConfiguredInfo(
  589. IN PCB * pPcb,
  590. IN DWORD CPIndex,
  591. IN OUT PPP_PROJECTION_RESULT * pProjectionResult,
  592. OUT BOOL * pfNCPsAreDone
  593. )
  594. {
  595. DWORD dwIndex;
  596. CPCB * pCpCb;
  597. DWORD dwRetCode;
  598. pProjectionResult->ip.dwError = ERROR_PPP_NO_PROTOCOLS_CONFIGURED;
  599. pProjectionResult->at.dwError = ERROR_PPP_NO_PROTOCOLS_CONFIGURED;
  600. pProjectionResult->ipx.dwError = ERROR_PPP_NO_PROTOCOLS_CONFIGURED;
  601. pProjectionResult->nbf.dwError = ERROR_PPP_NO_PROTOCOLS_CONFIGURED;
  602. pProjectionResult->ccp.dwError = ERROR_PPP_NO_PROTOCOLS_CONFIGURED;
  603. //
  604. // Check to see if we are all done
  605. //
  606. for (dwIndex = LCP_INDEX+1; dwIndex < PppConfigInfo.NumberOfCPs; dwIndex++)
  607. {
  608. pCpCb = GetPointerToCPCB( pPcb, dwIndex );
  609. if ( pCpCb->fConfigurable )
  610. {
  611. if ( pCpCb->NcpPhase == NCP_CONFIGURING )
  612. {
  613. return( NO_ERROR );
  614. }
  615. switch( CpTable[dwIndex].CpInfo.Protocol )
  616. {
  617. case PPP_IPCP_PROTOCOL:
  618. pProjectionResult->ip.dwError = pCpCb->dwError;
  619. if ( pProjectionResult->ip.dwError == NO_ERROR )
  620. {
  621. /* Assumption is made here that the
  622. ** PPP_PROJECTION_RESULT.wszServerAddress field immediately
  623. ** follows the PPP_PROJECTION_RESULT.wszAddress field and
  624. ** that both fields are 15 + 1 WCHARs long.
  625. */
  626. dwRetCode =(CpTable[dwIndex].CpInfo.RasCpGetNegotiatedInfo)(
  627. pCpCb->pWorkBuf,
  628. &(pProjectionResult->ip));
  629. if ( dwRetCode != NO_ERROR )
  630. {
  631. PppLog( 2, "IPCP GetNegotiatedInfo returned %d",
  632. dwRetCode );
  633. pCpCb->dwError = dwRetCode;
  634. pCpCb->NcpPhase = NCP_CONFIGURING;
  635. FsmClose( pPcb, dwIndex );
  636. return( ( dwIndex == CPIndex ) ? dwRetCode : NO_ERROR );
  637. }
  638. pPcb->pBcb->nboRemoteAddress =
  639. pProjectionResult->ip.dwRemoteAddress;
  640. if ( pProjectionResult->ip.fSendVJHCompression
  641. && pProjectionResult->ip.fReceiveVJHCompression )
  642. {
  643. pPcb->pBcb->fFlags |= BCBFLAG_IPCP_VJ_NEGOTIATED;
  644. }
  645. }
  646. break;
  647. case PPP_ATCP_PROTOCOL:
  648. pProjectionResult->at.dwError = pCpCb->dwError;
  649. if ( pProjectionResult->at.dwError == NO_ERROR )
  650. {
  651. dwRetCode=(CpTable[dwIndex].CpInfo.RasCpGetNegotiatedInfo)(
  652. pCpCb->pWorkBuf,
  653. &(pProjectionResult->at) );
  654. if ( dwRetCode != NO_ERROR )
  655. {
  656. pCpCb->dwError = dwRetCode;
  657. pCpCb->NcpPhase = NCP_CONFIGURING;
  658. FsmClose( pPcb, dwIndex );
  659. return( ( dwIndex == CPIndex ) ? dwRetCode : NO_ERROR );
  660. }
  661. }
  662. break;
  663. case PPP_IPXCP_PROTOCOL:
  664. pProjectionResult->ipx.dwError = pCpCb->dwError;
  665. if ( pProjectionResult->ipx.dwError == NO_ERROR )
  666. {
  667. dwRetCode =(CpTable[dwIndex].CpInfo.RasCpGetNegotiatedInfo)(
  668. pCpCb->pWorkBuf,
  669. &(pProjectionResult->ipx) );
  670. if ( dwRetCode != NO_ERROR )
  671. {
  672. pCpCb->dwError = dwRetCode;
  673. pCpCb->NcpPhase = NCP_CONFIGURING;
  674. FsmClose( pPcb, dwIndex );
  675. return( ( dwIndex == CPIndex ) ? dwRetCode : NO_ERROR );
  676. }
  677. }
  678. break;
  679. case PPP_CCP_PROTOCOL:
  680. pProjectionResult->ccp.dwError = pCpCb->dwError;
  681. if ( pProjectionResult->ccp.dwError == NO_ERROR )
  682. {
  683. dwRetCode= (CpTable[dwIndex].CpInfo.RasCpGetNegotiatedInfo)(
  684. pCpCb->pWorkBuf,
  685. &(pProjectionResult->ccp));
  686. if ( dwRetCode != NO_ERROR )
  687. {
  688. pCpCb->dwError = dwRetCode;
  689. pCpCb->NcpPhase = NCP_CONFIGURING;
  690. FsmClose( pPcb, dwIndex );
  691. return( ( dwIndex == CPIndex ) ? dwRetCode : NO_ERROR );
  692. }
  693. if ( RAS_DEVICE_TYPE( pPcb->dwDeviceType ) !=
  694. RDT_Tunnel_L2tp )
  695. {
  696. DWORD dwEncryptionType;
  697. //
  698. // Not L2TP. In the case of L2TP, we are interested in
  699. // the IpSec encryption, not MPPE.
  700. //
  701. dwEncryptionType =
  702. pProjectionResult->ccp.dwSendProtocolData &
  703. ( MSTYPE_ENCRYPTION_40 |
  704. MSTYPE_ENCRYPTION_40F |
  705. MSTYPE_ENCRYPTION_56 |
  706. MSTYPE_ENCRYPTION_128 );
  707. switch ( dwEncryptionType )
  708. {
  709. case MSTYPE_ENCRYPTION_40:
  710. case MSTYPE_ENCRYPTION_40F:
  711. pPcb->pBcb->fFlags |= BCBFLAG_BASIC_ENCRYPTION;
  712. break;
  713. case MSTYPE_ENCRYPTION_56:
  714. pPcb->pBcb->fFlags |= BCBFLAG_STRONGER_ENCRYPTION;
  715. break;
  716. case MSTYPE_ENCRYPTION_128:
  717. pPcb->pBcb->fFlags |= BCBFLAG_STRONGEST_ENCRYPTION;
  718. break;
  719. }
  720. }
  721. }
  722. break;
  723. case PPP_NBFCP_PROTOCOL:
  724. pProjectionResult->nbf.dwError = pCpCb->dwError;
  725. //
  726. // We call this even if we have an error one the client side
  727. // since we need the failure information
  728. //
  729. if ( ( pProjectionResult->nbf.dwError == NO_ERROR ) ||
  730. ( !( pPcb->fFlags & PCBFLAG_IS_SERVER ) ) )
  731. {
  732. dwRetCode=(CpTable[dwIndex].CpInfo.RasCpGetNegotiatedInfo)(
  733. pCpCb->pWorkBuf,
  734. &(pProjectionResult->nbf) );
  735. if ( dwRetCode != NO_ERROR )
  736. {
  737. pCpCb->dwError = dwRetCode;
  738. pCpCb->NcpPhase = NCP_CONFIGURING;
  739. FsmClose( pPcb, dwIndex );
  740. return( ( dwIndex == CPIndex ) ? dwRetCode : NO_ERROR );
  741. }
  742. }
  743. break;
  744. default:
  745. break;
  746. }
  747. }
  748. else
  749. {
  750. //
  751. // The protocol may have been de-configured because CpBegin failed
  752. //
  753. if ( pCpCb->dwError != NO_ERROR )
  754. {
  755. switch( CpTable[dwIndex].CpInfo.Protocol )
  756. {
  757. case PPP_IPCP_PROTOCOL:
  758. pProjectionResult->ip.dwError = pCpCb->dwError;
  759. break;
  760. case PPP_ATCP_PROTOCOL:
  761. pProjectionResult->at.dwError = pCpCb->dwError;
  762. break;
  763. case PPP_IPXCP_PROTOCOL:
  764. pProjectionResult->ipx.dwError = pCpCb->dwError;
  765. break;
  766. case PPP_NBFCP_PROTOCOL:
  767. pProjectionResult->nbf.dwError = pCpCb->dwError;
  768. break;
  769. case PPP_CCP_PROTOCOL:
  770. pProjectionResult->ccp.dwError = pCpCb->dwError;
  771. break;
  772. default:
  773. break;
  774. }
  775. }
  776. }
  777. }
  778. if ( ( pPcb->fFlags & PCBFLAG_IS_SERVER ) &&
  779. ( pProjectionResult->nbf.dwError != NO_ERROR ))
  780. {
  781. //
  782. // If NBF was not configured copy the computername to the wszWksta
  783. // field
  784. //
  785. if ( *(pPcb->pBcb->szComputerName) == (CHAR)NULL )
  786. {
  787. pProjectionResult->nbf.wszWksta[0] = (WCHAR)NULL;
  788. }
  789. else
  790. {
  791. CHAR chComputerName[NETBIOS_NAME_LEN+1];
  792. memset( chComputerName, ' ', NETBIOS_NAME_LEN );
  793. chComputerName[NETBIOS_NAME_LEN] = (CHAR)NULL;
  794. strcpy( chComputerName,
  795. pPcb->pBcb->szComputerName + strlen(MS_RAS_WITH_MESSENGER));
  796. chComputerName[strlen(chComputerName)] = (CHAR)' ';
  797. MultiByteToWideChar(
  798. CP_ACP,
  799. 0,
  800. chComputerName,
  801. -1,
  802. pProjectionResult->nbf.wszWksta,
  803. sizeof( pProjectionResult->nbf.wszWksta ) );
  804. if ( !memcmp( MS_RAS_WITH_MESSENGER,
  805. pPcb->pBcb->szComputerName,
  806. strlen( MS_RAS_WITH_MESSENGER ) ) )
  807. {
  808. pProjectionResult->nbf.wszWksta[NETBIOS_NAME_LEN-1] = (WCHAR)3;
  809. }
  810. }
  811. }
  812. *pfNCPsAreDone = TRUE;
  813. return( NO_ERROR );
  814. }
  815. //**
  816. //
  817. // Call: AreNCPsDone
  818. //
  819. // Returns: NO_ERROR - Success
  820. // anything else - Failure
  821. //
  822. // Description: If we detect that all configurable NCPs have completed their
  823. // negotiation, then the PPP_PROJECTION_RESULT structure is also
  824. // filled in.
  825. // This is called during the FsmThisLayerFinished or FsmThisLayerUp
  826. // calls for a certain CP. The index of this CP is passed in.
  827. // If any call to that particular CP fails then an error code is
  828. // passed back. If any call to any other CP fails then the error
  829. // is stored in the dwError field for that CP but the return is
  830. // successful. This is done so that the FsmThisLayerFinshed or
  831. // FsmThisLayerUp calls know if they completed successfully for
  832. // that CP or not. Depending on this, the FSM changes the state
  833. // for that CP or not.
  834. //
  835. DWORD
  836. AreNCPsDone(
  837. IN PCB * pPcb,
  838. IN DWORD CPIndex,
  839. OUT PPP_PROJECTION_RESULT * pProjectionResult,
  840. OUT BOOL * pfNCPsAreDone
  841. )
  842. {
  843. DWORD dwRetCode;
  844. *pfNCPsAreDone = FALSE;
  845. ZeroMemory( pProjectionResult, sizeof( PPP_PROJECTION_RESULT ) );
  846. dwRetCode = GetConfiguredInfo( pPcb,
  847. CPIndex,
  848. pProjectionResult,
  849. pfNCPsAreDone );
  850. if ( dwRetCode != NO_ERROR )
  851. {
  852. return( dwRetCode );
  853. }
  854. if ( !(*pfNCPsAreDone ) )
  855. {
  856. return( NO_ERROR );
  857. }
  858. //
  859. // Now get LCP information
  860. //
  861. pProjectionResult->lcp.hportBundleMember = (HPORT)INVALID_HANDLE_VALUE;
  862. pProjectionResult->lcp.szReplyMessage = pPcb->pBcb->szReplyMessage;
  863. dwRetCode = (CpTable[LCP_INDEX].CpInfo.RasCpGetNegotiatedInfo)(
  864. pPcb->LcpCb.pWorkBuf,
  865. &(pProjectionResult->lcp));
  866. if ( RAS_DEVICE_TYPE( pPcb->dwDeviceType ) == RDT_Tunnel_L2tp )
  867. {
  868. if ( pPcb->pBcb->fFlags & BCBFLAG_BASIC_ENCRYPTION )
  869. {
  870. pProjectionResult->lcp.dwLocalOptions |= PPPLCPO_DES_56;
  871. pProjectionResult->lcp.dwRemoteOptions |= PPPLCPO_DES_56;
  872. }
  873. else if ( pPcb->pBcb->fFlags & BCBFLAG_STRONGEST_ENCRYPTION )
  874. {
  875. pProjectionResult->lcp.dwLocalOptions |= PPPLCPO_3_DES;
  876. pProjectionResult->lcp.dwRemoteOptions |= PPPLCPO_3_DES;
  877. }
  878. }
  879. pProjectionResult->lcp.dwLocalEapTypeId = pPcb->dwServerEapTypeId;
  880. pProjectionResult->lcp.dwRemoteEapTypeId = pPcb->dwClientEapTypeId;
  881. return( dwRetCode );
  882. }
  883. //**
  884. //
  885. // Call: GetUid
  886. //
  887. // Returns: A BYTE value viz. unique with the 0 - 255 range
  888. //
  889. // Description:
  890. //
  891. BYTE
  892. GetUId(
  893. IN PCB * pPcb,
  894. IN DWORD CpIndex
  895. )
  896. {
  897. BYTE UId;
  898. //
  899. // For NCPs get the UID from the BCB
  900. //
  901. if ( ( CpIndex != LCP_INDEX ) && ( CpIndex >= PppConfigInfo.NumberOfCPs ) )
  902. {
  903. UId = (BYTE)(pPcb->pBcb->UId);
  904. (pPcb->pBcb->UId)++;
  905. return( UId );
  906. }
  907. UId = (BYTE)(pPcb->UId);
  908. (pPcb->UId)++;
  909. return( UId );
  910. }
  911. //**
  912. //
  913. // Call: AlertableWaitForSingleObject
  914. //
  915. // Returns: None
  916. //
  917. // Description: Will wait infintely for a single object in alertable mode. If
  918. // the wait completes because of an IO completion it will
  919. // wait again.
  920. //
  921. VOID
  922. AlertableWaitForSingleObject(
  923. IN HANDLE hObject
  924. )
  925. {
  926. DWORD dwRetCode;
  927. do
  928. {
  929. dwRetCode = WaitForSingleObjectEx( hObject, INFINITE, TRUE );
  930. PPP_ASSERT( dwRetCode != 0xFFFFFFFF );
  931. PPP_ASSERT( dwRetCode != WAIT_TIMEOUT );
  932. }
  933. while ( dwRetCode == WAIT_IO_COMPLETION );
  934. }
  935. //**
  936. //
  937. // Call: NotifyIPCPOfNBFCPProjectiont
  938. //
  939. // Returns: TRUE - Success
  940. // FALSE - Failure
  941. //
  942. // Description: Will notify IPCPs of all the configuration information,
  943. // specifically it is looking for NBFCP information.
  944. // Will return FALSE if the IPCP was not notified
  945. // successfully.
  946. //
  947. //
  948. BOOL
  949. NotifyIPCPOfNBFCPProjection(
  950. IN PCB * pPcb,
  951. IN DWORD CpIndex
  952. )
  953. {
  954. CPCB* pCpCb;
  955. DWORD dwRetCode;
  956. PPP_PROJECTION_RESULT ProjectionResult;
  957. PPPCP_NBFCP_RESULT NbfCpResult;
  958. DWORD NBFCPIndex;
  959. DWORD IPCPIndex;
  960. NBFCPIndex = GetCpIndexFromProtocol( PPP_NBFCP_PROTOCOL );
  961. IPCPIndex = GetCpIndexFromProtocol( PPP_IPCP_PROTOCOL );
  962. //
  963. // No IPCP installed, we are done
  964. //
  965. if ( IPCPIndex == (DWORD)-1 )
  966. {
  967. return( TRUE );
  968. }
  969. if ( CpTable[CpIndex].CpInfo.Protocol == PPP_IPCP_PROTOCOL )
  970. {
  971. if ( NBFCPIndex != (DWORD)-1 )
  972. {
  973. pCpCb = GetPointerToCPCB( pPcb, NBFCPIndex );
  974. if ( pCpCb == NULL )
  975. {
  976. return( FALSE );
  977. }
  978. if ( pCpCb->fConfigurable )
  979. {
  980. if ( pCpCb->NcpPhase == NCP_CONFIGURING )
  981. {
  982. //
  983. // NBFCP is still being configured, we need to wait
  984. // until it is done
  985. //
  986. PppLog( 2, "Waiting for NBFCP to complete" );
  987. return( TRUE );
  988. }
  989. }
  990. }
  991. }
  992. if ( CpTable[CpIndex].CpInfo.Protocol == PPP_NBFCP_PROTOCOL )
  993. {
  994. pCpCb = GetPointerToCPCB( pPcb, IPCPIndex );
  995. if ( pCpCb == NULL )
  996. {
  997. return( FALSE );
  998. }
  999. if ( pCpCb->fConfigurable )
  1000. {
  1001. if ( pCpCb->NcpPhase == NCP_CONFIGURING )
  1002. {
  1003. //
  1004. // IPCP is still being configured, we need to wait
  1005. // until it is done
  1006. //
  1007. PppLog( 2, "Waiting for IPCP to complete" );
  1008. return( TRUE );
  1009. }
  1010. }
  1011. else
  1012. {
  1013. //
  1014. // IPCP not configurable, we are done.
  1015. //
  1016. return( TRUE );
  1017. }
  1018. }
  1019. //
  1020. // If we are here that means we need to notify IPCP of NBFCP projection.
  1021. // NBF may or may not be configurable, or may or may not have projected
  1022. // successfully
  1023. //
  1024. ZeroMemory( &ProjectionResult, sizeof( PPP_PROJECTION_RESULT ) );
  1025. ZeroMemory( &NbfCpResult, sizeof( NbfCpResult ) );
  1026. ProjectionResult.nbf.dwError = ERROR_PPP_NO_PROTOCOLS_CONFIGURED;
  1027. if ( NBFCPIndex != (DWORD)-1 )
  1028. {
  1029. pCpCb = GetPointerToCPCB( pPcb, NBFCPIndex );
  1030. if ( pCpCb == NULL )
  1031. {
  1032. return( FALSE );
  1033. }
  1034. if ( pCpCb->fConfigurable )
  1035. {
  1036. if ( ProjectionResult.nbf.dwError == NO_ERROR )
  1037. {
  1038. dwRetCode = (CpTable[NBFCPIndex].CpInfo.RasCpGetNegotiatedInfo)(
  1039. pCpCb->pWorkBuf,
  1040. &(ProjectionResult.nbf) );
  1041. if ( dwRetCode != NO_ERROR )
  1042. {
  1043. pCpCb->dwError = dwRetCode;
  1044. pCpCb->NcpPhase = NCP_CONFIGURING;
  1045. FsmClose( pPcb, NBFCPIndex );
  1046. return( FALSE );
  1047. }
  1048. }
  1049. }
  1050. }
  1051. //
  1052. // Notify IPCP of NBFCP projection
  1053. //
  1054. pCpCb = GetPointerToCPCB( pPcb, IPCPIndex );
  1055. if ( pCpCb == NULL )
  1056. {
  1057. return( FALSE );
  1058. }
  1059. dwRetCode = (CpTable[IPCPIndex].CpInfo.RasCpProjectionNotification)(
  1060. pCpCb->pWorkBuf,
  1061. (PVOID)&ProjectionResult );
  1062. PppLog( 2, "Notifying IPCP of projection notification" );
  1063. if ( dwRetCode != NO_ERROR )
  1064. {
  1065. PppLog( 2,"RasIPCPProjectionNotification returned %d", dwRetCode );
  1066. pCpCb->dwError = dwRetCode;
  1067. pCpCb->NcpPhase = NCP_CONFIGURING;
  1068. FsmClose( pPcb, IPCPIndex );
  1069. return( FALSE );
  1070. }
  1071. return( TRUE );
  1072. }
  1073. //**
  1074. //
  1075. // Call: CalculateRestartTimer
  1076. //
  1077. // Returns: The value of the restart timer in seconds based on the link
  1078. // speed.
  1079. //
  1080. // Description: Will get the link speed from rasman and calculate the value
  1081. // if the restart timer based on it.
  1082. //
  1083. DWORD
  1084. CalculateRestartTimer(
  1085. IN HPORT hPort
  1086. )
  1087. {
  1088. RASMAN_INFO RasmanInfo;
  1089. if ( RasGetInfo( NULL, hPort, &RasmanInfo ) != NO_ERROR )
  1090. {
  1091. return( PppConfigInfo.DefRestartTimer );
  1092. }
  1093. if ( RasmanInfo.RI_LinkSpeed <= 1200 )
  1094. {
  1095. return( 7 );
  1096. }
  1097. if ( RasmanInfo.RI_LinkSpeed <= 2400 )
  1098. {
  1099. return( 5 );
  1100. }
  1101. if ( RasmanInfo.RI_LinkSpeed <= 9600 )
  1102. {
  1103. return( 3 );
  1104. }
  1105. else
  1106. {
  1107. return( 1 );
  1108. }
  1109. }
  1110. //**
  1111. //
  1112. // Call: CheckCpsForInactivity
  1113. //
  1114. // Returns: None
  1115. //
  1116. // Description: Will call each Control protocol to get the time since last
  1117. // activity.
  1118. //
  1119. VOID
  1120. CheckCpsForInactivity(
  1121. IN PCB * pPcb,
  1122. IN DWORD dwEvent //Type of event to check against
  1123. )
  1124. {
  1125. DWORD dwRetCode;
  1126. DWORD dwIndex;
  1127. DWORD dwTimeSinceLastActivity = 0;
  1128. PppLog( 2, "Time to check Cps for Activity for port %d", pPcb->hPort );
  1129. dwRetCode = RasGetTimeSinceLastActivity( pPcb->hPort,
  1130. &dwTimeSinceLastActivity );
  1131. if ( dwRetCode != NO_ERROR )
  1132. {
  1133. PppLog(2, "RasGetTimeSinceLastActivityTime returned %d\r\n", dwRetCode);
  1134. return;
  1135. }
  1136. PppLog(2, "Port %d inactive for %d seconds",
  1137. pPcb->hPort, dwTimeSinceLastActivity );
  1138. //
  1139. // If all the stacks have been inactive for at least AutoDisconnectTime
  1140. // then we disconnect.
  1141. //
  1142. if ( dwEvent == TIMER_EVENT_AUTODISCONNECT )
  1143. {
  1144. if ( dwTimeSinceLastActivity >= pPcb->dwAutoDisconnectTime)
  1145. {
  1146. PppLog(1,"Disconnecting port %d due to inactivity.", pPcb->hPort);
  1147. if ( !( pPcb->fFlags & PCBFLAG_IS_SERVER ) )
  1148. {
  1149. HANDLE hLogHandle;
  1150. if( pPcb->pBcb->InterfaceInfo.IfType == ROUTER_IF_TYPE_FULL_ROUTER)
  1151. {
  1152. hLogHandle = RouterLogRegisterA( "RemoteAccess" );
  1153. }
  1154. else
  1155. {
  1156. hLogHandle = PppConfigInfo.hLogEvents;
  1157. }
  1158. if ( hLogHandle != NULL )
  1159. {
  1160. CHAR * pszPortName = pPcb->szPortName;
  1161. RouterLogInformationA( hLogHandle,
  1162. ROUTERLOG_CLIENT_AUTODISCONNECT,
  1163. 1,
  1164. &pszPortName,
  1165. NO_ERROR );
  1166. if ( hLogHandle != PppConfigInfo.hLogEvents )
  1167. {
  1168. RouterLogDeregisterA( hLogHandle );
  1169. }
  1170. }
  1171. }
  1172. //
  1173. // Terminate the link
  1174. //
  1175. pPcb->LcpCb.dwError = ERROR_IDLE_DISCONNECTED;
  1176. FsmClose( pPcb, LCP_INDEX );
  1177. }
  1178. else
  1179. {
  1180. InsertInTimerQ( pPcb->dwPortId,
  1181. pPcb->hPort,
  1182. 0,
  1183. 0,
  1184. FALSE,
  1185. TIMER_EVENT_AUTODISCONNECT,
  1186. pPcb->dwAutoDisconnectTime - dwTimeSinceLastActivity );
  1187. }
  1188. }
  1189. //
  1190. // Do the LCP Echo request if its pppoe
  1191. //
  1192. else if ( (RDT_PPPoE == RAS_DEVICE_TYPE(pPcb->dwDeviceType))
  1193. && (dwEvent == TIMER_EVENT_LCP_ECHO ))
  1194. {
  1195. if ( pPcb->fEchoRequestSend )
  1196. {
  1197. //
  1198. // Because the line was inactive for dwEchoTimeout, we send an echo
  1199. // request and did not get any response back in 3 seconds after that.
  1200. // So we have to disconnect the port.
  1201. //
  1202. pPcb->dwNumEchoResponseMissed ++;
  1203. if ( pPcb->dwNumEchoResponseMissed >= pPcb->dwNumMissedEchosBeforeDisconnect )
  1204. {
  1205. PppLog(1,"Missed %d consecutive echo responses. Disconnecting port %d "
  1206. "due to no echo responses.", pPcb->dwNumMissedEchosBeforeDisconnect, pPcb->hPort);
  1207. //
  1208. // Terminate the link
  1209. //
  1210. pPcb->LcpCb.dwError = ERROR_IDLE_DISCONNECTED;
  1211. pPcb->fEchoRequestSend = 0;
  1212. pPcb->dwNumEchoResponseMissed = 0;
  1213. FsmClose( pPcb, LCP_INDEX );
  1214. }
  1215. else
  1216. {
  1217. //no response yet. So send one more echo request.
  1218. FsmSendEchoRequest( pPcb, LCP_INDEX);
  1219. InsertInTimerQ( pPcb->dwPortId,
  1220. pPcb->hPort,
  1221. 0,
  1222. 0,
  1223. FALSE,
  1224. TIMER_EVENT_LCP_ECHO,
  1225. pPcb->dwLCPEchoTimeInterval
  1226. );
  1227. }
  1228. }
  1229. else
  1230. {
  1231. //
  1232. //No echo request send or we have got a response for echo already
  1233. //
  1234. //
  1235. // check to see if the the inactivity is more than EchoTimeout
  1236. //
  1237. if ( dwTimeSinceLastActivity >= pPcb->dwIdleBeforeEcho )
  1238. {
  1239. //
  1240. // call the lcp cp to make the echo request
  1241. //
  1242. if ( FsmSendEchoRequest( pPcb, LCP_INDEX) )
  1243. {
  1244. //
  1245. // send the echo requesst and set the flag
  1246. //
  1247. pPcb->fEchoRequestSend = 1;
  1248. //Setup for next echo request here.
  1249. InsertInTimerQ( pPcb->dwPortId,
  1250. pPcb->hPort,
  1251. 0,
  1252. 0,
  1253. FALSE,
  1254. TIMER_EVENT_LCP_ECHO,
  1255. pPcb->dwLCPEchoTimeInterval );
  1256. }
  1257. else
  1258. {
  1259. PppLog (1, "Send EchoRequest Failed...");
  1260. }
  1261. }
  1262. else
  1263. {
  1264. InsertInTimerQ( pPcb->dwPortId,
  1265. pPcb->hPort,
  1266. 0,
  1267. 0,
  1268. FALSE,
  1269. TIMER_EVENT_LCP_ECHO,
  1270. pPcb->dwIdleBeforeEcho - dwTimeSinceLastActivity );
  1271. }
  1272. }
  1273. }
  1274. }
  1275. //These functions are in ppputil.lib. Should be used from there
  1276. #if 0
  1277. //**
  1278. //
  1279. // Call:
  1280. //
  1281. // Returns:
  1282. //
  1283. // Description:
  1284. //
  1285. CHAR*
  1286. DecodePw(
  1287. IN CHAR chSeed,
  1288. IN OUT CHAR* pszPassword )
  1289. /* Un-obfuscate 'pszPassword' in place.
  1290. **
  1291. ** Returns the address of 'pszPassword'.
  1292. */
  1293. {
  1294. return EncodePw( chSeed, pszPassword );
  1295. }
  1296. //**
  1297. //
  1298. // Call:
  1299. //
  1300. // Returns:
  1301. //
  1302. // Description:
  1303. //
  1304. CHAR*
  1305. EncodePw(
  1306. IN CHAR chSeed,
  1307. IN OUT CHAR* pszPassword )
  1308. /* Obfuscate 'pszPassword' in place to foil memory scans for passwords.
  1309. **
  1310. ** Returns the address of 'pszPassword'.
  1311. */
  1312. {
  1313. if (pszPassword)
  1314. {
  1315. CHAR* psz;
  1316. ReverseString( pszPassword );
  1317. for (psz = pszPassword; *psz != '\0'; ++psz)
  1318. {
  1319. if (*psz != chSeed)
  1320. *psz ^= chSeed;
  1321. /*
  1322. if (*psz != (CHAR)PASSWORDMAGIC)
  1323. *psz ^= PASSWORDMAGIC;
  1324. */
  1325. }
  1326. }
  1327. return pszPassword;
  1328. }
  1329. //**
  1330. //
  1331. // Call: ReverseString
  1332. //
  1333. // Returns:
  1334. //
  1335. // Description:
  1336. //
  1337. VOID
  1338. ReverseString(
  1339. CHAR* psz )
  1340. /* Reverses order of characters in 'psz'.
  1341. */
  1342. {
  1343. CHAR* pszBegin;
  1344. CHAR* pszEnd;
  1345. for (pszBegin = psz, pszEnd = psz + strlen( psz ) - 1;
  1346. pszBegin < pszEnd;
  1347. ++pszBegin, --pszEnd)
  1348. {
  1349. CHAR ch = *pszBegin;
  1350. *pszBegin = *pszEnd;
  1351. *pszEnd = ch;
  1352. }
  1353. }
  1354. #endif
  1355. //**
  1356. //
  1357. // Call: GetLocalComputerName
  1358. //
  1359. // Returns: None
  1360. //
  1361. // Description: Will get the local computer name. Will also find out if the
  1362. // the messenger is running and set the appropriate prefix.
  1363. //
  1364. VOID
  1365. GetLocalComputerName(
  1366. IN OUT LPSTR szComputerName
  1367. )
  1368. {
  1369. SC_HANDLE ScHandle;
  1370. SC_HANDLE ScHandleService;
  1371. SERVICE_STATUS ServiceStatus;
  1372. CHAR chComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  1373. DWORD dwComputerNameLen;
  1374. *szComputerName = (CHAR)NULL;
  1375. //
  1376. // Open the local service control manager
  1377. //
  1378. ScHandle = OpenSCManager( NULL, NULL, GENERIC_READ );
  1379. if ( ScHandle == (SC_HANDLE)NULL )
  1380. {
  1381. return;
  1382. }
  1383. ScHandleService = OpenService( ScHandle,
  1384. SERVICE_MESSENGER,
  1385. SERVICE_QUERY_STATUS );
  1386. if ( ScHandleService == (SC_HANDLE)NULL )
  1387. {
  1388. CloseServiceHandle( ScHandle );
  1389. return;
  1390. }
  1391. if ( !QueryServiceStatus( ScHandleService, &ServiceStatus ) )
  1392. {
  1393. CloseServiceHandle( ScHandle );
  1394. CloseServiceHandle( ScHandleService );
  1395. return;
  1396. }
  1397. CloseServiceHandle( ScHandle );
  1398. CloseServiceHandle( ScHandleService );
  1399. if ( ServiceStatus.dwCurrentState == SERVICE_RUNNING )
  1400. {
  1401. strcpy( szComputerName, MS_RAS_WITH_MESSENGER );
  1402. }
  1403. else
  1404. {
  1405. strcpy( szComputerName, MS_RAS_WITHOUT_MESSENGER );
  1406. }
  1407. //
  1408. // Get the size of the buffer to hold local computer name
  1409. //
  1410. dwComputerNameLen = sizeof(chComputerName);
  1411. if ( !GetComputerNameA( chComputerName,
  1412. &dwComputerNameLen
  1413. )
  1414. )
  1415. {
  1416. *szComputerName = (CHAR)NULL;
  1417. return;
  1418. }
  1419. strcpy( szComputerName+strlen(szComputerName), chComputerName );
  1420. CharToOemA( szComputerName, szComputerName );
  1421. PppLog( 2, "Local identification = %s", szComputerName );
  1422. return;
  1423. }
  1424. //**
  1425. //
  1426. // Call: InitEndpointDiscriminator
  1427. //
  1428. // Returns: NO_ERROR - Success
  1429. // non-zero - Failure
  1430. //
  1431. // Description: Will obtain a unique end-point discriminator to be used to
  1432. // negotiate multi-link. This end-point discrimintator has to
  1433. // globally unique to this machine.
  1434. //
  1435. // We first try to use a Class 3 IEEE 802.1 address of any
  1436. // netcard that is in this local machine.
  1437. //
  1438. // If this fails we use the RPC UUID generator to generate a
  1439. // Class 1 discriminator.
  1440. //
  1441. // If this fails we simply use the local computer name as the
  1442. // Class 1 discriminator.
  1443. //
  1444. // Simply use a random number if all else fails.
  1445. //
  1446. // NOTE: For now we skip over NwLnkNb because it may return an
  1447. // address of 1 and not the real MAC address. There is not way
  1448. // in user mode for now to get the address.
  1449. //
  1450. DWORD
  1451. InitEndpointDiscriminator(
  1452. IN OUT BYTE EndPointDiscriminator[]
  1453. )
  1454. {
  1455. DWORD dwRetCode;
  1456. LPBYTE pBuffer;
  1457. DWORD EntriesRead;
  1458. DWORD TotalEntries;
  1459. PWCHAR pwChar;
  1460. DWORD dwIndex;
  1461. UUID Uuid;
  1462. DWORD dwComputerNameLen;
  1463. PWKSTA_TRANSPORT_INFO_0 pWkstaTransport;
  1464. //
  1465. // Enumerate all the transports used by the local rdr and then get the
  1466. // address of the first LAN transport card
  1467. //
  1468. dwRetCode = NetWkstaTransportEnum( NULL, // Local
  1469. 0, // Level
  1470. &pBuffer, // Output buffer
  1471. (DWORD)-1,// Pref. max len
  1472. &EntriesRead,
  1473. &TotalEntries,
  1474. NULL );
  1475. if ( ( dwRetCode == NO_ERROR ) && ( EntriesRead > 0 ) )
  1476. {
  1477. pWkstaTransport = (PWKSTA_TRANSPORT_INFO_0)pBuffer;
  1478. while ( EntriesRead-- > 0 )
  1479. {
  1480. if ( !pWkstaTransport->wkti0_wan_ish )
  1481. {
  1482. EndPointDiscriminator[0] = 3; // Class 3
  1483. pwChar = pWkstaTransport->wkti0_transport_address;
  1484. for ( dwIndex = 0; dwIndex < 6; dwIndex++ )
  1485. {
  1486. EndPointDiscriminator[dwIndex+1] = ( iswalpha( *pwChar )
  1487. ? *pwChar-L'A'+10
  1488. : *pwChar-L'0'
  1489. ) * 0x10
  1490. +
  1491. ( iswalpha( *(pwChar+1) )
  1492. ? *(pwChar+1)-L'A'+10
  1493. : *(pwChar+1)-L'0'
  1494. );
  1495. pwChar++;
  1496. pwChar++;
  1497. }
  1498. NetApiBufferFree( pBuffer );
  1499. return( NO_ERROR );
  1500. }
  1501. pWkstaTransport++;
  1502. }
  1503. }
  1504. if ( dwRetCode == NO_ERROR )
  1505. {
  1506. NetApiBufferFree( pBuffer );
  1507. }
  1508. EndPointDiscriminator[0] = 1; // Class 1
  1509. //
  1510. // We failed to get the mac address so try to use UUIDGEN to get an unique
  1511. // local id
  1512. //
  1513. dwRetCode = UuidCreate( &Uuid );
  1514. if ( ( dwRetCode == RPC_S_UUID_NO_ADDRESS ) ||
  1515. ( dwRetCode == RPC_S_OK ) ||
  1516. ( dwRetCode == RPC_S_UUID_LOCAL_ONLY) )
  1517. {
  1518. HostToWireFormat32( Uuid.Data1, EndPointDiscriminator+1 );
  1519. HostToWireFormat16( Uuid.Data2, EndPointDiscriminator+5 );
  1520. HostToWireFormat16( Uuid.Data3, EndPointDiscriminator+7 );
  1521. CopyMemory( EndPointDiscriminator+9, Uuid.Data4, 8 );
  1522. return( NO_ERROR );
  1523. }
  1524. //
  1525. // We failed to get the UUID so simply use the computer name
  1526. //
  1527. dwComputerNameLen = 20;
  1528. if ( !GetComputerNameA( EndPointDiscriminator+1, &dwComputerNameLen ) )
  1529. {
  1530. //
  1531. // We failed to get the computer name so use a random number
  1532. //
  1533. srand( GetCurrentTime() );
  1534. HostToWireFormat32( rand(), EndPointDiscriminator+1 );
  1535. }
  1536. return( NO_ERROR );
  1537. }
  1538. //**
  1539. //
  1540. // Call: AllocateAndInitBcb
  1541. //
  1542. // Returns: NO_ERROR - Success
  1543. // Non-zero returns - Failure
  1544. //
  1545. // Description: Allocates and initializes a Bundle control block
  1546. //
  1547. DWORD
  1548. AllocateAndInitBcb(
  1549. PCB * pPcb
  1550. )
  1551. {
  1552. DWORD dwIndex;
  1553. DWORD dwRetCode;
  1554. //
  1555. // Allocate space for NumberOfNcp - LCP - 1 already in the
  1556. // Bcb structure
  1557. //
  1558. pPcb->pBcb = (BCB *)LOCAL_ALLOC( LPTR,
  1559. sizeof( BCB ) +
  1560. ( sizeof( CPCB ) *
  1561. ( PppConfigInfo.NumberOfCPs - 2 ) ) );
  1562. if ( pPcb->pBcb == (BCB *)NULL )
  1563. {
  1564. return( GetLastError() );
  1565. }
  1566. pPcb->pBcb->dwBundleId = GetNewPortOrBundleId();
  1567. pPcb->pBcb->UId = 0;
  1568. pPcb->pBcb->dwLinkCount = 1;
  1569. pPcb->pBcb->dwAcctLinkCount = 1;
  1570. pPcb->pBcb->dwMaxLinksAllowed = 0xFFFFFFFF;
  1571. pPcb->pBcb->fFlags = 0;
  1572. pPcb->pBcb->hLicense = INVALID_HANDLE_VALUE;
  1573. pPcb->pBcb->BapCb.dwId = 0;
  1574. pPcb->pBcb->hTokenImpersonateUser = INVALID_HANDLE_VALUE;
  1575. pPcb->pBcb->chSeed = GEN_RAND_ENCODE_SEED; //random number seed for encode/decode password
  1576. //
  1577. // The most common case is to have no more than 2 links in the bundle.
  1578. //
  1579. pPcb->pBcb->ppPcb = (PPCB *)LOCAL_ALLOC( LPTR, sizeof( PPCB ) * 2 );
  1580. if ( pPcb->pBcb->ppPcb == (PPCB *) NULL )
  1581. {
  1582. LOCAL_FREE( pPcb->pBcb );
  1583. pPcb->pBcb = NULL;
  1584. return( GetLastError() );
  1585. }
  1586. pPcb->pBcb->dwPpcbArraySize = 2;
  1587. pPcb->pBcb->ppPcb[0] = pPcb;
  1588. pPcb->pBcb->ppPcb[1] = NULL;
  1589. for( dwIndex=0; dwIndex < PppConfigInfo.NumberOfCPs-1; dwIndex++ )
  1590. {
  1591. CPCB * pCpCb = &(pPcb->pBcb->CpCb[dwIndex]);
  1592. pCpCb->NcpPhase = NCP_DEAD;
  1593. }
  1594. return( NO_ERROR );
  1595. }
  1596. //**
  1597. //
  1598. // Call: DeallocateAndRemoveBcbFromTable
  1599. //
  1600. // Returns: None
  1601. //
  1602. // Description: Will remove the Bcb from the hash table
  1603. //
  1604. VOID
  1605. DeallocateAndRemoveBcbFromTable(
  1606. IN BCB * pBcb
  1607. )
  1608. {
  1609. DWORD dwIndex;
  1610. BCB * pBcbWalker = (BCB *)NULL;
  1611. BCB * pBcbTemp = (BCB *)NULL;
  1612. if ( NULL == pBcb )
  1613. {
  1614. return;
  1615. }
  1616. dwIndex = HashPortToBucket( pBcb->hConnection );
  1617. pBcbWalker = PcbTable.BcbBuckets[dwIndex].pBundles;
  1618. pBcbTemp = pBcbWalker;
  1619. while( pBcbTemp != (BCB *)NULL )
  1620. {
  1621. if ( pBcbTemp->hConnection == pBcb->hConnection )
  1622. {
  1623. if ( pBcbTemp == PcbTable.BcbBuckets[dwIndex].pBundles )
  1624. {
  1625. PcbTable.BcbBuckets[dwIndex].pBundles = pBcbTemp->pNext;
  1626. }
  1627. else
  1628. {
  1629. pBcbWalker->pNext = pBcbTemp->pNext;
  1630. }
  1631. break;
  1632. }
  1633. pBcbWalker = pBcbTemp;
  1634. pBcbTemp = pBcbWalker->pNext;
  1635. }
  1636. //
  1637. // Release the licence if there is one
  1638. //
  1639. if ( INVALID_HANDLE_VALUE != pBcb->hLicense )
  1640. {
  1641. NtLSFreeHandle( (LS_HANDLE)(pBcb->hLicense) );
  1642. }
  1643. ZeroMemory( pBcb->szPassword,
  1644. sizeof( pBcb->szPassword ) );
  1645. ZeroMemory( pBcb->szOldPassword,
  1646. sizeof( pBcb->szOldPassword ) );
  1647. //
  1648. // Close the OpenThreadToken() handle obtained from Rasman
  1649. //
  1650. if ( INVALID_HANDLE_VALUE != pBcb->hTokenImpersonateUser )
  1651. {
  1652. CloseHandle( pBcb->hTokenImpersonateUser );
  1653. }
  1654. //
  1655. // pCustomAuthConnData, pCustomAuthUserData, szPhonebookPath,
  1656. // szEntryName, and szServerPhoneNumber are allocated by RasMan
  1657. // and MUST be LocalFree'd, not LOCAL_FREE'd.
  1658. //
  1659. LocalFree( pBcb->pCustomAuthConnData );
  1660. LocalFree( pBcb->pCustomAuthUserData );
  1661. LocalFree( pBcb->EapUIData.pEapUIData );
  1662. LocalFree( pBcb->szPhonebookPath );
  1663. LocalFree( pBcb->szEntryName );
  1664. LocalFree( pBcb->BapCb.szServerPhoneNumber );
  1665. LocalFree( pBcb->BapCb.szClientPhoneNumber );
  1666. LocalFree( pBcb->szReplyMessage );
  1667. if ( NULL != pBcb->szTextualSid )
  1668. {
  1669. LOCAL_FREE( pBcb->szTextualSid );
  1670. }
  1671. if ( NULL != pBcb->szRemoteIdentity )
  1672. {
  1673. LOCAL_FREE( pBcb->szRemoteIdentity );
  1674. }
  1675. if ( NULL != pBcb->ppPcb )
  1676. {
  1677. LOCAL_FREE( pBcb->ppPcb );
  1678. }
  1679. LOCAL_FREE( pBcb );
  1680. }
  1681. //**
  1682. //
  1683. // Call: RemovePcbFromTable
  1684. //
  1685. // Returns: None
  1686. //
  1687. // Description: Will remove the Pcb from the hash table
  1688. //
  1689. VOID
  1690. RemovePcbFromTable(
  1691. IN PCB * pPcb
  1692. )
  1693. {
  1694. DWORD dwIndex = HashPortToBucket( pPcb->hPort );
  1695. PCB * pPcbWalker = (PCB *)NULL;
  1696. PCB * pPcbTemp = (PCB *)NULL;
  1697. pPcbWalker = PcbTable.PcbBuckets[dwIndex].pPorts;
  1698. pPcbTemp = pPcbWalker;
  1699. while( pPcbTemp != (PCB *)NULL )
  1700. {
  1701. if ( pPcbTemp->hPort == pPcb->hPort )
  1702. {
  1703. if ( pPcbTemp == PcbTable.PcbBuckets[dwIndex].pPorts )
  1704. {
  1705. PcbTable.PcbBuckets[dwIndex].pPorts = pPcbTemp->pNext;
  1706. }
  1707. else
  1708. {
  1709. pPcbWalker->pNext = pPcbTemp->pNext;
  1710. }
  1711. break;
  1712. }
  1713. pPcbWalker = pPcbTemp;
  1714. pPcbTemp = pPcbWalker->pNext;
  1715. }
  1716. }
  1717. //**
  1718. //
  1719. // Call: WillPortBeBundled
  1720. //
  1721. // Returns: TRUE - Port will be bundled after authentication
  1722. // FALSE - Port cannot be bundled
  1723. //
  1724. // Description: Will check to see if the usernames and discriminators match
  1725. //
  1726. BOOL
  1727. WillPortBeBundled(
  1728. IN PCB * pPcb
  1729. )
  1730. {
  1731. PCB* pPcbWalker;
  1732. DWORD dwIndex;
  1733. //
  1734. // Optimization: Have rasman tell PPP that the port will be bundled.
  1735. //
  1736. //
  1737. // Walk thru the list of PCBs
  1738. //
  1739. for ( dwIndex = 0; dwIndex < PcbTable.NumPcbBuckets; dwIndex++ )
  1740. {
  1741. for ( pPcbWalker = PcbTable.PcbBuckets[dwIndex].pPorts;
  1742. pPcbWalker != NULL;
  1743. pPcbWalker = pPcbWalker->pNext )
  1744. {
  1745. //
  1746. // Don't bundle a port with itself.
  1747. //
  1748. if ( pPcbWalker->hPort == pPcb->hPort )
  1749. {
  1750. continue;
  1751. }
  1752. //
  1753. // If the current port negotiated MRRU ie multilink.
  1754. //
  1755. if ( pPcbWalker->fFlags & PCBFLAG_CAN_BE_BUNDLED )
  1756. {
  1757. LCPCB * pLcpCb1 = (LCPCB*)(pPcbWalker->LcpCb.pWorkBuf);
  1758. LCPCB * pLcpCb2 = (LCPCB*)(pPcb->LcpCb.pWorkBuf);
  1759. if ( _stricmp(pPcbWalker->pBcb->szLocalUserName,
  1760. pPcb->pBcb->szLocalUserName) != 0 )
  1761. {
  1762. //
  1763. // Authenticator mismatch, not in our bundle
  1764. //
  1765. continue;
  1766. }
  1767. if ( ( pLcpCb1->Remote.Work.EndpointDiscr[0] != 0 ) &&
  1768. ( memcmp(pLcpCb1->Remote.Work.EndpointDiscr,
  1769. pLcpCb2->Remote.Work.EndpointDiscr,
  1770. sizeof(pLcpCb1->Remote.Work.EndpointDiscr))!=0))
  1771. {
  1772. //
  1773. // Discriminator mismatch, not in our bundle
  1774. //
  1775. continue;
  1776. }
  1777. return( TRUE );
  1778. }
  1779. }
  1780. }
  1781. return( FALSE );
  1782. }
  1783. //**
  1784. //
  1785. // Call: CanPortsBeBundled
  1786. //
  1787. // Returns: TRUE - Ports can be bundled
  1788. // FALSE - Ports cannot be bundled
  1789. //
  1790. // Description: Will check to see if the usernames and discriminators match
  1791. //
  1792. BOOL
  1793. CanPortsBeBundled(
  1794. IN PCB * pPcb1,
  1795. IN PCB * pPcb2,
  1796. IN BOOL fCheckPolicy
  1797. )
  1798. {
  1799. CPCB * pCpCb;
  1800. LCPCB * pLcpCb1 = (LCPCB*)(pPcb1->LcpCb.pWorkBuf);
  1801. LCPCB * pLcpCb2 = (LCPCB*)(pPcb2->LcpCb.pWorkBuf);
  1802. if ( fCheckPolicy
  1803. && ( PppConfigInfo.fFlags & PPPCONFIG_FLAG_WKSTA )
  1804. && ( pPcb1->fFlags & PCBFLAG_IS_SERVER )
  1805. && ( pPcb2->fFlags & PCBFLAG_IS_SERVER ) )
  1806. {
  1807. //
  1808. // RAS server policy on workstation. Allow multilinking of devices in
  1809. // the same device class only, ie all devices are dial-up, or all
  1810. // devices are VPN, or all devices are DCC (direct)
  1811. //
  1812. if ( ( pPcb1->dwDeviceType & RDT_Tunnel ) !=
  1813. ( pPcb2->dwDeviceType & RDT_Tunnel ) )
  1814. {
  1815. return( FALSE );
  1816. }
  1817. if ( ( pPcb1->dwDeviceType & RDT_Direct ) !=
  1818. ( pPcb2->dwDeviceType & RDT_Direct ) )
  1819. {
  1820. return( FALSE );
  1821. }
  1822. }
  1823. //
  1824. // If the current port is in PPP_NCP phase meaning that it is post
  1825. // authentication and callback.
  1826. //
  1827. if ( pPcb1->PppPhase == PPP_NCP )
  1828. {
  1829. if ( ( _stricmp(pPcb1->pBcb->szLocalUserName,
  1830. pPcb2->pBcb->szLocalUserName) != 0 )||
  1831. ( _stricmp(pPcb1->pBcb->szRemoteUserName,
  1832. pPcb2->pBcb->szRemoteUserName) != 0 ))
  1833. {
  1834. //
  1835. // Authenticator mismatch, not in our bundle
  1836. //
  1837. return( FALSE );
  1838. }
  1839. if ( ( pLcpCb1->Remote.Work.EndpointDiscr[0] != 0 ) &&
  1840. ( memcmp(pLcpCb1->Remote.Work.EndpointDiscr,
  1841. pLcpCb2->Remote.Work.EndpointDiscr,
  1842. sizeof(pLcpCb1->Remote.Work.EndpointDiscr))!=0))
  1843. {
  1844. //
  1845. // Discriminator mismatch, not in our bundle
  1846. //
  1847. return( FALSE );
  1848. }
  1849. if ( ( pLcpCb1->Local.Work.EndpointDiscr[0] != 0 ) &&
  1850. ( memcmp(pLcpCb1->Local.Work.EndpointDiscr,
  1851. pLcpCb2->Local.Work.EndpointDiscr,
  1852. sizeof(pLcpCb1->Local.Work.EndpointDiscr))!=0))
  1853. {
  1854. //
  1855. // Discriminator mismatch, not in our bundle
  1856. //
  1857. return( FALSE );
  1858. }
  1859. return( TRUE );
  1860. }
  1861. return( FALSE );
  1862. }
  1863. //**
  1864. //
  1865. // Call: TryToBundleWithAnotherLink
  1866. //
  1867. // Returns: NO_ERROR - Success
  1868. // Non-zero returns - Failure
  1869. //
  1870. // Description: Will search through all the PCBs for a port that can be bundled.
  1871. // We follow the criteria specified by RFC 1717.
  1872. // phPortMulttlink will point to an HPORT that this port was
  1873. // bundled with if this function returns TRUE.
  1874. //
  1875. // If the link is to be bundled, and its link discriminator is not
  1876. // unique, we return a unique discriminator in pwLinkDiscriminator.
  1877. //
  1878. DWORD
  1879. TryToBundleWithAnotherLink(
  1880. IN PCB * pPcb
  1881. )
  1882. {
  1883. DWORD dwIndex;
  1884. PCB * pPcbWalker;
  1885. BCB * pBcbOld = NULL;
  1886. DWORD dwRetCode = NO_ERROR;
  1887. DWORD dwForIndex;
  1888. PPCB * ppPcb;
  1889. DWORD CpIndex;
  1890. CPCB * pCpCb;
  1891. pPcb->hportBundleMember = (HPORT)INVALID_HANDLE_VALUE;
  1892. //
  1893. // Walk thru the list of PCBs
  1894. //
  1895. for ( dwIndex = 0; dwIndex < PcbTable.NumPcbBuckets; dwIndex++ )
  1896. {
  1897. for( pPcbWalker = PcbTable.PcbBuckets[dwIndex].pPorts;
  1898. pPcbWalker != NULL;
  1899. pPcbWalker = pPcbWalker->pNext )
  1900. {
  1901. //
  1902. // Don't bundle a port with itself.
  1903. //
  1904. if ( pPcbWalker->hPort == pPcb->hPort )
  1905. {
  1906. continue;
  1907. }
  1908. //
  1909. // If the current port negotiated MRRU ie multilink.
  1910. //
  1911. if ( ( pPcbWalker->fFlags & PCBFLAG_CAN_BE_BUNDLED ) &&
  1912. ( CanPortsBeBundled( pPcbWalker, pPcb, TRUE ) ) )
  1913. {
  1914. if ( pPcbWalker->pBcb->dwLinkCount >=
  1915. pPcbWalker->pBcb->dwMaxLinksAllowed )
  1916. {
  1917. dwRetCode = ERROR_PORT_LIMIT_REACHED;
  1918. break;
  1919. }
  1920. CpIndex = GetCpIndexFromProtocol( PPP_BACP_PROTOCOL );
  1921. if (CpIndex != (DWORD)-1)
  1922. {
  1923. pCpCb = GetPointerToCPCB( pPcbWalker, CpIndex );
  1924. if ( pCpCb->State != FSM_OPENED
  1925. && ( pPcb->pBcb->fFlags & BCBFLAG_BAP_REQUIRED ))
  1926. {
  1927. PppLog( 1, "BAP is required for this user, but BACP "
  1928. "is not open. hPort = %d", pPcb->hPort );
  1929. dwRetCode = ERROR_BAP_REQUIRED;
  1930. break;
  1931. }
  1932. }
  1933. //
  1934. // Either there was no authenticator and no discriminator,or
  1935. // there were both and there was match for both. So join the
  1936. // bundle in either case.
  1937. //
  1938. dwRetCode = RasPortBundle( pPcbWalker->hPort, pPcb->hPort );
  1939. if ( dwRetCode == NO_ERROR )
  1940. {
  1941. PppLog( 2, "Bundling this link with hPort = %d",
  1942. pPcbWalker->hPort );
  1943. pPcb->hportBundleMember = pPcbWalker->hPort;
  1944. break;
  1945. }
  1946. }
  1947. }
  1948. if ( pPcb->hportBundleMember != (HPORT)INVALID_HANDLE_VALUE )
  1949. {
  1950. break;
  1951. }
  1952. }
  1953. //
  1954. // Bundle the port
  1955. //
  1956. if ( ( dwRetCode == NO_ERROR ) &&
  1957. ( pPcb->hportBundleMember != (HPORT)INVALID_HANDLE_VALUE ) )
  1958. {
  1959. pPcbWalker->fFlags |= PCBFLAG_IS_BUNDLED;
  1960. pPcb->fFlags |= PCBFLAG_IS_BUNDLED;
  1961. pBcbOld = pPcb->pBcb;
  1962. pPcb->pBcb = pPcbWalker->pBcb;
  1963. pPcbWalker->hportBundleMember = pPcb->hPort;
  1964. pPcb->pBcb->dwLinkCount++;
  1965. pPcb->pBcb->dwAcctLinkCount++;
  1966. for ( dwForIndex = 0; dwForIndex < pPcb->pBcb->dwPpcbArraySize; dwForIndex++ )
  1967. {
  1968. //
  1969. // If there is a free space in the array of back pointers, use it
  1970. //
  1971. if ( pPcb->pBcb->ppPcb[dwForIndex] == NULL )
  1972. {
  1973. PppLog( 2, "Found slot %d for port %d in BCB back pointer array",
  1974. dwForIndex, pPcb->hPort );
  1975. pPcb->pBcb->ppPcb[dwForIndex] = pPcb;
  1976. break;
  1977. }
  1978. }
  1979. if ( dwForIndex == pPcb->pBcb->dwPpcbArraySize )
  1980. {
  1981. //
  1982. // The array of back pointers is full. ReAlloc.
  1983. //
  1984. ppPcb = (PPCB *) LOCAL_REALLOC( pPcb->pBcb->ppPcb,
  1985. 2 * pPcb->pBcb->dwPpcbArraySize * sizeof( PPCB * ) );
  1986. if (ppPcb == NULL)
  1987. {
  1988. //
  1989. // Can we really assume that pPcb->pBcb->ppPcb will be left
  1990. // intact? The documentation for HeapReAlloc does not say so.
  1991. //
  1992. pPcb->pBcb = pBcbOld;
  1993. pBcbOld = NULL;
  1994. pPcbWalker->pBcb->dwLinkCount--;
  1995. pPcbWalker->pBcb->dwAcctLinkCount--;
  1996. pPcb->fFlags &= ~PCBFLAG_IS_BUNDLED;
  1997. PppLog( 1, "Couldn't ReAlloc BCB back pointer array for port %d",
  1998. pPcb->hPort );
  1999. dwRetCode = GetLastError();
  2000. goto LDone;
  2001. }
  2002. pPcb->pBcb->ppPcb = ppPcb;
  2003. PppLog( 2, "Found slot %d for port %d in BCB back pointer array after ReAlloc",
  2004. dwForIndex, pPcb->hPort );
  2005. pPcb->pBcb->ppPcb[dwForIndex++] = pPcb;
  2006. pPcb->pBcb->dwPpcbArraySize *= 2;
  2007. //
  2008. // We are assuming that the new memory will be zeroed.
  2009. //
  2010. }
  2011. }
  2012. LDone:
  2013. DeallocateAndRemoveBcbFromTable( pBcbOld );
  2014. return( dwRetCode );
  2015. }
  2016. //**
  2017. //
  2018. // Call: AdjustHTokenImpersonateUser
  2019. //
  2020. // Returns: VOID
  2021. //
  2022. // Description: Sets hTokenImpersonateUser in pPcb by finding another link that
  2023. // pPcb is capable of bundling with and stealing its
  2024. // hTokenImpersonateUser. The original hTokenImpersonateUser may
  2025. // be INVALID_HANDLE_VALUE if this link came up because BAP called
  2026. // RasDial.
  2027. //
  2028. VOID
  2029. AdjustHTokenImpersonateUser(
  2030. IN PCB * pPcb
  2031. )
  2032. {
  2033. DWORD dwIndex;
  2034. PCB* pPcbWalker;
  2035. HANDLE hToken;
  2036. HANDLE hTokenDuplicate;
  2037. if ( INVALID_HANDLE_VALUE != pPcb->pBcb->hTokenImpersonateUser )
  2038. {
  2039. return;
  2040. }
  2041. for ( dwIndex = 0; dwIndex < PcbTable.NumPcbBuckets; dwIndex++ )
  2042. {
  2043. for( pPcbWalker = PcbTable.PcbBuckets[dwIndex].pPorts;
  2044. pPcbWalker != NULL;
  2045. pPcbWalker = pPcbWalker->pNext )
  2046. {
  2047. if ( pPcbWalker->hPort == pPcb->hPort )
  2048. {
  2049. continue;
  2050. }
  2051. hToken = pPcbWalker->pBcb->hTokenImpersonateUser;
  2052. //
  2053. // If the current port negotiated MRRU ie multilink.
  2054. //
  2055. if ( ( pPcbWalker->fFlags & PCBFLAG_CAN_BE_BUNDLED ) &&
  2056. ( CanPortsBeBundled( pPcbWalker, pPcb, FALSE ) ) &&
  2057. ( INVALID_HANDLE_VALUE != hToken ) )
  2058. {
  2059. if (DuplicateHandle(
  2060. GetCurrentProcess(),
  2061. hToken,
  2062. GetCurrentProcess(),
  2063. &hTokenDuplicate,
  2064. 0,
  2065. TRUE,
  2066. DUPLICATE_SAME_ACCESS))
  2067. {
  2068. pPcb->pBcb->hTokenImpersonateUser = hTokenDuplicate;
  2069. }
  2070. return;
  2071. }
  2072. }
  2073. }
  2074. }
  2075. //**
  2076. //
  2077. // Call: FLinkDiscriminatorIsUnique
  2078. //
  2079. // Returns: TRUE - Unique Link Discriminator
  2080. // FALSE - Non-unique Link Discriminator
  2081. //
  2082. // Description: Returns TRUE if the link discriminator of the link in pPcb is
  2083. // unique with respect to the other links in the same bundle.
  2084. // Otherwise, it returns FALSE and sets *pdwLinkDisc to a unique
  2085. // value that can be used as link discrim.
  2086. //
  2087. BOOL
  2088. FLinkDiscriminatorIsUnique(
  2089. IN PCB * pPcb,
  2090. OUT DWORD * pdwLinkDisc
  2091. )
  2092. {
  2093. DWORD dwForIndex;
  2094. DWORD dwNewDisc;
  2095. DWORD dwTempDisc;
  2096. DWORD fDiscIsUnique = TRUE;
  2097. dwNewDisc = ((LCPCB*)
  2098. (pPcb->LcpCb.pWorkBuf))->Local.Work.dwLinkDiscriminator;
  2099. *pdwLinkDisc = 0; // The highest link discriminator seen so far
  2100. for ( dwForIndex = 0;
  2101. dwForIndex < pPcb->pBcb->dwPpcbArraySize;
  2102. dwForIndex++ )
  2103. {
  2104. if ( ( pPcb->pBcb->ppPcb[dwForIndex] != NULL ) &&
  2105. ( pPcb->pBcb->ppPcb[dwForIndex] != pPcb ) )
  2106. {
  2107. dwTempDisc = ((LCPCB *)
  2108. (pPcb->pBcb->ppPcb[dwForIndex]->LcpCb.pWorkBuf))
  2109. ->Local.Work.dwLinkDiscriminator;
  2110. if ( dwTempDisc > *pdwLinkDisc )
  2111. {
  2112. *pdwLinkDisc = dwTempDisc;
  2113. }
  2114. if ( dwTempDisc == dwNewDisc )
  2115. {
  2116. fDiscIsUnique = FALSE;
  2117. }
  2118. }
  2119. }
  2120. if ( fDiscIsUnique )
  2121. {
  2122. return( TRUE );
  2123. }
  2124. if ( *pdwLinkDisc != 0xFFFF )
  2125. {
  2126. *pdwLinkDisc += 1;
  2127. return( FALSE );
  2128. }
  2129. //
  2130. // Find a unique link discriminator
  2131. //
  2132. for ( dwTempDisc = 0; // A candidate for unique discriminator
  2133. dwTempDisc < 0xFFFF;
  2134. dwTempDisc++ )
  2135. {
  2136. for ( dwForIndex = 0;
  2137. dwForIndex < pPcb->pBcb->dwPpcbArraySize;
  2138. dwForIndex++ )
  2139. {
  2140. if ( pPcb->pBcb->ppPcb[dwForIndex] != NULL )
  2141. {
  2142. if ( dwTempDisc ==
  2143. ((LCPCB *)
  2144. (pPcb->pBcb->ppPcb[dwForIndex]->LcpCb.pWorkBuf))
  2145. ->Local.Work.dwLinkDiscriminator )
  2146. {
  2147. break;
  2148. }
  2149. }
  2150. }
  2151. if ( dwForIndex == pPcb->pBcb->dwPpcbArraySize )
  2152. {
  2153. *pdwLinkDisc = dwTempDisc;
  2154. break;
  2155. }
  2156. }
  2157. if ( dwTempDisc == 0xFFFF )
  2158. {
  2159. PppLog( 1, "FLinkDiscriminatorIsUnique couldn't find a unique link "
  2160. "discriminator for port %d",
  2161. pPcb->hPort );
  2162. }
  2163. return( FALSE );
  2164. }
  2165. //**
  2166. //
  2167. // Call: CreateAccountingAttributes
  2168. //
  2169. // Returns: VOID
  2170. //
  2171. // Description:
  2172. //
  2173. VOID
  2174. CreateAccountingAttributes(
  2175. IN PCB * pPcb
  2176. )
  2177. {
  2178. CHAR szAcctSessionId[20];
  2179. CHAR szAcctMultiSessionId[20];
  2180. DWORD dwIndex = 0;
  2181. DWORD dwEncryptionType;
  2182. BYTE abEncryptionType[6];
  2183. DWORD dwRetCode;
  2184. RAS_AUTH_ATTRIBUTE * pAttributes = NULL;
  2185. RAS_AUTH_ATTRIBUTE * pClassAttribute = NULL;
  2186. RAS_AUTH_ATTRIBUTE * pFramedRouteAttribute = NULL;
  2187. RAS_AUTH_ATTRIBUTE * pDomainAttribute = NULL;
  2188. HANDLE hAttribute;
  2189. DWORD dwValue;
  2190. PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pGlobalDomainInfo;
  2191. LCPCB * pLcpCb = (LCPCB*)(pPcb->LcpCb.pWorkBuf);
  2192. RasAuthAttributeDestroy( pPcb->pAccountingAttributes );
  2193. pPcb->pAccountingAttributes = NULL;
  2194. if ( !( pPcb->fFlags & PCBFLAG_IS_SERVER ) )
  2195. {
  2196. return;
  2197. }
  2198. //
  2199. // Check to see how many class attributes we have to send if any.
  2200. //
  2201. if ( pPcb->pAuthProtocolAttributes != NULL )
  2202. {
  2203. pAttributes = pPcb->pAuthProtocolAttributes;
  2204. }
  2205. else if ( pPcb->pAuthenticatorAttributes != NULL )
  2206. {
  2207. pAttributes = pPcb->pAuthenticatorAttributes;
  2208. }
  2209. pClassAttribute = RasAuthAttributeGetFirst( raatClass,
  2210. pAttributes,
  2211. &hAttribute );
  2212. while( pClassAttribute != NULL )
  2213. {
  2214. dwIndex++;
  2215. pClassAttribute = RasAuthAttributeGetNext( &hAttribute, raatClass );
  2216. }
  2217. //
  2218. // Check to see how many Framed-Route attributes we have to send if any.
  2219. //
  2220. pFramedRouteAttribute = RasAuthAttributeGetFirst( raatFramedRoute,
  2221. pPcb->pAuthenticatorAttributes,
  2222. &hAttribute );
  2223. while( pFramedRouteAttribute != NULL )
  2224. {
  2225. dwIndex++;
  2226. pFramedRouteAttribute = RasAuthAttributeGetNext( &hAttribute,
  2227. raatFramedRoute );
  2228. }
  2229. pDomainAttribute = RasAuthAttributeGetVendorSpecific(
  2230. 311,
  2231. 10,
  2232. pAttributes );
  2233. ZeroMemory( szAcctSessionId, sizeof( szAcctSessionId ) );
  2234. _itoa(PppConfigInfo.GetNextAccountingSessionId(),szAcctSessionId, 10);
  2235. ZeroMemory( szAcctMultiSessionId, sizeof( szAcctMultiSessionId ) );
  2236. _itoa( pPcb->pBcb->dwBundleId, szAcctMultiSessionId, 10 );
  2237. //
  2238. // Allocate max total number of attributes that will be used in the
  2239. // start and stop accouting messages.
  2240. //
  2241. pPcb->pAccountingAttributes = RasAuthAttributeCreate(
  2242. PPP_NUM_ACCOUNTING_ATTRIBUTES +
  2243. dwIndex );
  2244. if ( pPcb->pAccountingAttributes == NULL )
  2245. {
  2246. return;
  2247. }
  2248. do
  2249. {
  2250. //
  2251. // First insert user attributes
  2252. //
  2253. for( dwIndex = 0;
  2254. pPcb->pUserAttributes[dwIndex].raaType != raatMinimum;
  2255. dwIndex++ )
  2256. {
  2257. dwRetCode = RasAuthAttributeInsert(
  2258. dwIndex,
  2259. pPcb->pAccountingAttributes,
  2260. pPcb->pUserAttributes[dwIndex].raaType,
  2261. FALSE,
  2262. pPcb->pUserAttributes[dwIndex].dwLength,
  2263. pPcb->pUserAttributes[dwIndex].Value );
  2264. if ( dwRetCode != NO_ERROR )
  2265. {
  2266. break;
  2267. }
  2268. }
  2269. if ( dwRetCode != NO_ERROR )
  2270. {
  2271. break;
  2272. }
  2273. //
  2274. // Now insert the class attributes if there were any
  2275. //
  2276. pClassAttribute = RasAuthAttributeGetFirst( raatClass,
  2277. pAttributes,
  2278. &hAttribute );
  2279. while( pClassAttribute != NULL )
  2280. {
  2281. dwRetCode = RasAuthAttributeInsert(
  2282. dwIndex++,
  2283. pPcb->pAccountingAttributes,
  2284. pClassAttribute->raaType,
  2285. FALSE,
  2286. pClassAttribute->dwLength,
  2287. pClassAttribute->Value );
  2288. if ( dwRetCode != NO_ERROR )
  2289. {
  2290. break;
  2291. }
  2292. pClassAttribute = RasAuthAttributeGetNext( &hAttribute,
  2293. raatClass );
  2294. }
  2295. if ( dwRetCode != NO_ERROR )
  2296. {
  2297. break;
  2298. }
  2299. //
  2300. // Now insert the Framed-Route attributes if there were any
  2301. //
  2302. pFramedRouteAttribute = RasAuthAttributeGetFirst( raatFramedRoute,
  2303. pPcb->pAuthenticatorAttributes,
  2304. &hAttribute );
  2305. while( pFramedRouteAttribute != NULL )
  2306. {
  2307. dwRetCode = RasAuthAttributeInsert(
  2308. dwIndex++,
  2309. pPcb->pAccountingAttributes,
  2310. pFramedRouteAttribute->raaType,
  2311. FALSE,
  2312. pFramedRouteAttribute->dwLength,
  2313. pFramedRouteAttribute->Value );
  2314. if ( dwRetCode != NO_ERROR )
  2315. {
  2316. break;
  2317. }
  2318. pFramedRouteAttribute = RasAuthAttributeGetNext( &hAttribute,
  2319. raatFramedRoute );
  2320. }
  2321. if ( dwRetCode != NO_ERROR )
  2322. {
  2323. break;
  2324. }
  2325. //
  2326. // Now insert the domain attribute if there was one
  2327. //
  2328. if ( pDomainAttribute != NULL )
  2329. {
  2330. dwRetCode = RasAuthAttributeInsert(
  2331. dwIndex++,
  2332. pPcb->pAccountingAttributes,
  2333. pDomainAttribute->raaType,
  2334. FALSE,
  2335. pDomainAttribute->dwLength,
  2336. pDomainAttribute->Value );
  2337. if ( dwRetCode != NO_ERROR )
  2338. {
  2339. break;
  2340. }
  2341. }
  2342. dwRetCode = RasAuthAttributeInsert(
  2343. dwIndex++,
  2344. pPcb->pAccountingAttributes,
  2345. raatAcctSessionId,
  2346. FALSE,
  2347. strlen( szAcctSessionId ),
  2348. szAcctSessionId );
  2349. if ( dwRetCode != NO_ERROR )
  2350. {
  2351. break;
  2352. }
  2353. if ( NULL != pPcb->pBcb->szRemoteIdentity )
  2354. {
  2355. dwRetCode = RasAuthAttributeInsert(
  2356. dwIndex++,
  2357. pPcb->pAccountingAttributes,
  2358. raatUserName,
  2359. FALSE,
  2360. strlen( pPcb->pBcb->szRemoteIdentity ),
  2361. pPcb->pBcb->szRemoteIdentity );
  2362. if ( dwRetCode != NO_ERROR )
  2363. {
  2364. break;
  2365. }
  2366. }
  2367. if ( 0 != pPcb->pBcb->nboRemoteAddress )
  2368. {
  2369. dwRetCode = RasAuthAttributeInsert(
  2370. dwIndex++,
  2371. pPcb->pAccountingAttributes,
  2372. raatFramedIPAddress,
  2373. FALSE,
  2374. 4,
  2375. (LPVOID)
  2376. LongToPtr(ntohl( pPcb->pBcb->nboRemoteAddress )) );
  2377. if ( dwRetCode != NO_ERROR )
  2378. {
  2379. break;
  2380. }
  2381. }
  2382. {
  2383. ULONG mru = (pLcpCb->Remote.Work.MRU > LCP_DEFAULT_MRU) ?
  2384. LCP_DEFAULT_MRU : pLcpCb->Remote.Work.MRU;
  2385. dwRetCode = RasAuthAttributeInsert(
  2386. dwIndex++,
  2387. pPcb->pAccountingAttributes,
  2388. raatFramedMTU,
  2389. FALSE,
  2390. 4,
  2391. (LPVOID)
  2392. UlongToPtr(( mru )));
  2393. }
  2394. if ( dwRetCode != NO_ERROR )
  2395. {
  2396. break;
  2397. }
  2398. if ( pPcb->pBcb->fFlags & BCBFLAG_IPCP_VJ_NEGOTIATED )
  2399. {
  2400. dwRetCode = RasAuthAttributeInsert(
  2401. dwIndex++,
  2402. pPcb->pAccountingAttributes,
  2403. raatFramedCompression,
  2404. FALSE,
  2405. 4,
  2406. (LPVOID) 1 );
  2407. // VJ TCP/IP header compression
  2408. if ( dwRetCode != NO_ERROR )
  2409. {
  2410. break;
  2411. }
  2412. }
  2413. if ( pPcb->szCallbackNumber[0] != 0 )
  2414. {
  2415. dwRetCode = RasAuthAttributeInsert(
  2416. dwIndex++,
  2417. pPcb->pAccountingAttributes,
  2418. raatCallbackNumber,
  2419. FALSE,
  2420. strlen(pPcb->szCallbackNumber),
  2421. (LPVOID)pPcb->szCallbackNumber );
  2422. if ( dwRetCode != NO_ERROR )
  2423. {
  2424. break;
  2425. }
  2426. }
  2427. if ( pPcb->dwSessionTimeout > 0 )
  2428. {
  2429. dwRetCode = RasAuthAttributeInsert(
  2430. dwIndex++,
  2431. pPcb->pAccountingAttributes,
  2432. raatSessionTimeout,
  2433. FALSE,
  2434. 4,
  2435. (LPVOID)
  2436. ULongToPtr(pPcb->dwSessionTimeout) );
  2437. if ( dwRetCode != NO_ERROR )
  2438. {
  2439. break;
  2440. }
  2441. }
  2442. if ( pPcb->dwAutoDisconnectTime > 0 )
  2443. {
  2444. dwRetCode = RasAuthAttributeInsert(
  2445. dwIndex++,
  2446. pPcb->pAccountingAttributes,
  2447. raatIdleTimeout,
  2448. FALSE,
  2449. 4,
  2450. (LPVOID)
  2451. ULongToPtr(pPcb->dwAutoDisconnectTime) );
  2452. if ( dwRetCode != NO_ERROR )
  2453. {
  2454. break;
  2455. }
  2456. }
  2457. if ( pPcb->pBcb->dwMaxLinksAllowed != 0xFFFFFFFF )
  2458. {
  2459. //
  2460. // There is a real limit
  2461. //
  2462. dwRetCode = RasAuthAttributeInsert(
  2463. dwIndex++,
  2464. pPcb->pAccountingAttributes,
  2465. raatPortLimit,
  2466. FALSE,
  2467. 4,
  2468. (LPVOID)
  2469. ULongToPtr(pPcb->pBcb->dwMaxLinksAllowed) );
  2470. if ( dwRetCode != NO_ERROR )
  2471. {
  2472. break;
  2473. }
  2474. }
  2475. dwRetCode = RasAuthAttributeInsert(
  2476. dwIndex++,
  2477. pPcb->pAccountingAttributes,
  2478. raatAcctMultiSessionId,
  2479. FALSE,
  2480. strlen(szAcctMultiSessionId),
  2481. (LPVOID)szAcctMultiSessionId );
  2482. if ( dwRetCode != NO_ERROR )
  2483. {
  2484. break;
  2485. }
  2486. dwRetCode = RasAuthAttributeInsert(
  2487. dwIndex++,
  2488. pPcb->pAccountingAttributes,
  2489. raatAcctLinkCount,
  2490. FALSE,
  2491. 4,
  2492. (LPVOID)ULongToPtr(pPcb->pBcb->dwAcctLinkCount) );
  2493. if ( dwRetCode != NO_ERROR )
  2494. {
  2495. break;
  2496. }
  2497. //
  2498. // Insert event timestamp attribute
  2499. //
  2500. dwRetCode = RasAuthAttributeInsert(
  2501. dwIndex++,
  2502. pPcb->pAccountingAttributes,
  2503. raatAcctEventTimeStamp,
  2504. FALSE,
  2505. 4,
  2506. (LPVOID)ULongToPtr(GetSecondsSince1970()) );
  2507. if ( dwRetCode != NO_ERROR )
  2508. {
  2509. break;
  2510. }
  2511. if ( PppConfigInfo.fRadiusAuthenticationUsed )
  2512. {
  2513. dwValue = 1; // RADIUS
  2514. }
  2515. else
  2516. {
  2517. dwValue = 0;
  2518. pGlobalDomainInfo = NULL;
  2519. dwRetCode = DsRoleGetPrimaryDomainInformation(
  2520. NULL,
  2521. DsRolePrimaryDomainInfoBasic,
  2522. (PBYTE *)&pGlobalDomainInfo );
  2523. if ( NO_ERROR == dwRetCode )
  2524. {
  2525. if ( ( pGlobalDomainInfo->MachineRole ==
  2526. DsRole_RoleMemberServer )
  2527. || ( pGlobalDomainInfo->MachineRole ==
  2528. DsRole_RoleMemberWorkstation ) )
  2529. {
  2530. dwValue = 3; // Remote
  2531. }
  2532. else
  2533. {
  2534. dwValue = 2; // Local
  2535. }
  2536. DsRoleFreeMemory(pGlobalDomainInfo);
  2537. }
  2538. else
  2539. {
  2540. dwRetCode = NO_ERROR;
  2541. }
  2542. }
  2543. if ( 0 != dwValue )
  2544. {
  2545. dwRetCode = RasAuthAttributeInsert(
  2546. dwIndex++,
  2547. pPcb->pAccountingAttributes,
  2548. raatAcctAuthentic,
  2549. FALSE,
  2550. 4,
  2551. (LPVOID)ULongToPtr(dwValue) );
  2552. if ( dwRetCode != NO_ERROR )
  2553. {
  2554. break;
  2555. }
  2556. }
  2557. //
  2558. // Insert encryption attribute
  2559. //
  2560. dwEncryptionType = 0;
  2561. if ( pPcb->pBcb->fFlags & BCBFLAG_BASIC_ENCRYPTION )
  2562. {
  2563. dwEncryptionType = 0x00000002;
  2564. }
  2565. else if ( pPcb->pBcb->fFlags & BCBFLAG_STRONGER_ENCRYPTION )
  2566. {
  2567. dwEncryptionType = 0x00000008;
  2568. }
  2569. else if ( pPcb->pBcb->fFlags & BCBFLAG_STRONGEST_ENCRYPTION )
  2570. {
  2571. dwEncryptionType = 0x00000004;
  2572. }
  2573. abEncryptionType[0] = 8; // Vendor-Type = MS_MPPE_EncryptionType
  2574. abEncryptionType[1] = 6; // Vendor-Length = 6
  2575. HostToWireFormat32( dwEncryptionType, abEncryptionType + 2 );
  2576. dwRetCode = RasAuthAttributeInsertVSA(
  2577. dwIndex++,
  2578. pPcb->pAccountingAttributes,
  2579. 311,
  2580. 6,
  2581. abEncryptionType );
  2582. if ( dwRetCode != NO_ERROR )
  2583. {
  2584. break;
  2585. }
  2586. } while( FALSE );
  2587. //
  2588. // Do not send accounting start if there was any error
  2589. //
  2590. if ( dwRetCode != NO_ERROR )
  2591. {
  2592. RasAuthAttributeDestroy( pPcb->pAccountingAttributes );
  2593. pPcb->pAccountingAttributes = NULL;
  2594. return;
  2595. }
  2596. //
  2597. // NULL terminate
  2598. //
  2599. pPcb->pAccountingAttributes[dwIndex].raaType = raatMinimum;
  2600. pPcb->pAccountingAttributes[dwIndex].dwLength = 0;
  2601. pPcb->pAccountingAttributes[dwIndex].Value = NULL;
  2602. }
  2603. //**
  2604. //
  2605. // Call: MakeStartAccountingCall
  2606. //
  2607. // Returns: NO_ERROR - Success
  2608. // Non-zero returns - Failure
  2609. //
  2610. // Description: Start backend authentication module accounting
  2611. //
  2612. VOID
  2613. MakeStartAccountingCall(
  2614. IN PCB * pPcb
  2615. )
  2616. {
  2617. LCPCB * pLcpCb = (LCPCB*)(pPcb->LcpCb.pWorkBuf);
  2618. RAS_AUTH_ATTRIBUTE * pAcctInterimIntervalAttribute = NULL;
  2619. RAS_AUTH_ATTRIBUTE * pAttributes = NULL;
  2620. if ( pPcb->fFlags & PCBFLAG_ACCOUNTING_STARTED )
  2621. {
  2622. //
  2623. // Already started
  2624. //
  2625. return;
  2626. }
  2627. pPcb->fFlags |= PCBFLAG_ACCOUNTING_STARTED;
  2628. if ( pLcpCb->Local.Work.AP == 0 )
  2629. {
  2630. //
  2631. // If the remote side was not authenticated then do not send an
  2632. // accounting request as per RADIUS accounting RFC 2139 sec 5.6.
  2633. //
  2634. return;
  2635. }
  2636. if ( PppConfigInfo.RasAcctProviderStartAccounting != NULL )
  2637. {
  2638. RAS_AUTH_ATTRIBUTE * pAccountingAttributes;
  2639. CreateAccountingAttributes( pPcb );
  2640. pAccountingAttributes = RasAuthAttributeCopy(
  2641. pPcb->pAccountingAttributes );
  2642. if ( NULL == pAccountingAttributes )
  2643. {
  2644. return;
  2645. }
  2646. RtlQueueWorkItem( StartAccounting,
  2647. pAccountingAttributes,
  2648. WT_EXECUTEDEFAULT );
  2649. if ( pPcb->pAuthProtocolAttributes != NULL )
  2650. {
  2651. pAttributes = pPcb->pAuthProtocolAttributes;
  2652. }
  2653. else if ( pPcb->pAuthenticatorAttributes != NULL )
  2654. {
  2655. pAttributes = pPcb->pAuthenticatorAttributes;
  2656. }
  2657. //
  2658. // See if we have to do interim accounting
  2659. //
  2660. pAcctInterimIntervalAttribute = RasAuthAttributeGet(
  2661. raatAcctInterimInterval,
  2662. pAttributes );
  2663. if ( pAcctInterimIntervalAttribute != NULL )
  2664. {
  2665. DWORD dwInterimInterval =
  2666. PtrToUlong(pAcctInterimIntervalAttribute->Value);
  2667. if ( dwInterimInterval < 60 )
  2668. {
  2669. dwInterimInterval = 60;
  2670. }
  2671. InsertInTimerQ(
  2672. pPcb->dwPortId,
  2673. pPcb->hPort,
  2674. 0,
  2675. 0,
  2676. FALSE,
  2677. TIMER_EVENT_INTERIM_ACCOUNTING,
  2678. dwInterimInterval );
  2679. }
  2680. }
  2681. return;
  2682. }
  2683. //**
  2684. //
  2685. // Call: InitializeNCPs
  2686. //
  2687. // Returns: NO_ERROR
  2688. // Non-zero return code.
  2689. //
  2690. // Description: Will run through and initialize all the NCPs that are enabled
  2691. // to run.
  2692. //
  2693. DWORD
  2694. InitializeNCPs(
  2695. IN PCB * pPcb,
  2696. IN DWORD dwConfigMask
  2697. )
  2698. {
  2699. DWORD dwIndex;
  2700. BOOL fInitSuccess = FALSE;
  2701. DWORD dwRetCode = NO_ERROR;
  2702. if ( pPcb->fFlags & PCBFLAG_NCPS_INITIALIZED )
  2703. {
  2704. return( NO_ERROR );
  2705. }
  2706. pPcb->fFlags |= PCBFLAG_NCPS_INITIALIZED;
  2707. //
  2708. // Initialize all the CPs for this port
  2709. //
  2710. for( dwIndex=LCP_INDEX+1; dwIndex < PppConfigInfo.NumberOfCPs; dwIndex++ )
  2711. {
  2712. CPCB * pCpCb = GetPointerToCPCB( pPcb, dwIndex );
  2713. pCpCb->fConfigurable = FALSE;
  2714. if ( !( CpTable[dwIndex].fFlags & PPPCP_FLAG_AVAILABLE ) )
  2715. {
  2716. PppLog( 2, "Will not initialize CP %x",
  2717. CpTable[dwIndex].CpInfo.Protocol );
  2718. continue;
  2719. }
  2720. switch( CpTable[dwIndex].CpInfo.Protocol )
  2721. {
  2722. case PPP_IPCP_PROTOCOL:
  2723. if ( dwConfigMask & PPPCFG_ProjectIp )
  2724. {
  2725. //
  2726. // Make sure we have a valid interface handle if we are not
  2727. // a client dialing out
  2728. //
  2729. if ( pPcb->pBcb->InterfaceInfo.IfType != (DWORD)-1 )
  2730. {
  2731. if (pPcb->pBcb->InterfaceInfo.hIPInterface ==
  2732. INVALID_HANDLE_VALUE )
  2733. {
  2734. break;
  2735. }
  2736. }
  2737. pCpCb->fConfigurable = TRUE;
  2738. if ( FsmInit( pPcb, dwIndex ) )
  2739. {
  2740. fInitSuccess = TRUE;
  2741. }
  2742. }
  2743. break;
  2744. case PPP_ATCP_PROTOCOL:
  2745. if ( dwConfigMask & PPPCFG_ProjectAt )
  2746. {
  2747. pCpCb->fConfigurable = TRUE;
  2748. if ( FsmInit( pPcb, dwIndex ) )
  2749. {
  2750. fInitSuccess = TRUE;
  2751. }
  2752. }
  2753. break;
  2754. case PPP_IPXCP_PROTOCOL:
  2755. if ( dwConfigMask & PPPCFG_ProjectIpx )
  2756. {
  2757. //
  2758. // Make sure we have a valid interface handle if we are not
  2759. // a client dialing out
  2760. //
  2761. if ( pPcb->pBcb->InterfaceInfo.IfType != (DWORD)-1 )
  2762. {
  2763. if ( pPcb->pBcb->InterfaceInfo.hIPXInterface ==
  2764. INVALID_HANDLE_VALUE )
  2765. {
  2766. break;
  2767. }
  2768. }
  2769. pCpCb->fConfigurable = TRUE;
  2770. if ( FsmInit( pPcb, dwIndex ) )
  2771. {
  2772. fInitSuccess = TRUE;
  2773. }
  2774. }
  2775. break;
  2776. case PPP_NBFCP_PROTOCOL:
  2777. if ( dwConfigMask & PPPCFG_ProjectNbf )
  2778. {
  2779. //
  2780. // If we are not a client dialing in or out do not enable
  2781. // NBF
  2782. //
  2783. if ( ( pPcb->pBcb->InterfaceInfo.IfType != (DWORD)-1 ) &&
  2784. ( pPcb->pBcb->InterfaceInfo.IfType !=
  2785. ROUTER_IF_TYPE_CLIENT ))
  2786. {
  2787. break;
  2788. }
  2789. pCpCb->fConfigurable = TRUE;
  2790. if ( FsmInit( pPcb, dwIndex ) )
  2791. {
  2792. fInitSuccess = TRUE;
  2793. }
  2794. }
  2795. break;
  2796. case PPP_CCP_PROTOCOL:
  2797. pCpCb->fConfigurable = TRUE;
  2798. if ( !( FsmInit( pPcb, dwIndex ) ) )
  2799. {
  2800. //
  2801. // If encryption failed to initialize and we are forcing
  2802. // encryption, then bring down the link
  2803. //
  2804. if ( dwConfigMask & ( PPPCFG_RequireEncryption |
  2805. PPPCFG_RequireStrongEncryption ) )
  2806. {
  2807. //
  2808. // We need to send an Accounting Stop if RADIUS sends
  2809. // an Access Accept but we still drop the line.
  2810. //
  2811. pPcb->fFlags |= PCBFLAG_SERVICE_UNAVAILABLE;
  2812. dwRetCode = ERROR_NO_LOCAL_ENCRYPTION;
  2813. }
  2814. }
  2815. break;
  2816. case PPP_BACP_PROTOCOL:
  2817. if ( ( dwConfigMask & PPPCFG_NegotiateBacp ) &&
  2818. ( pPcb->pBcb->fFlags & BCBFLAG_CAN_DO_BAP ) )
  2819. {
  2820. pCpCb->fConfigurable = TRUE;
  2821. if ( !( FsmInit( pPcb, dwIndex ) ) )
  2822. {
  2823. pPcb->pBcb->fFlags &= ~BCBFLAG_CAN_DO_BAP;
  2824. }
  2825. }
  2826. break;
  2827. default:
  2828. break;
  2829. }
  2830. if ( dwRetCode != NO_ERROR )
  2831. {
  2832. break;
  2833. }
  2834. }
  2835. //
  2836. // If we failed to initialize one of the CPs, or CCP failed to
  2837. // initialize and we require encryption, then we fail.
  2838. //
  2839. if ( ( !fInitSuccess ) || ( dwRetCode != NO_ERROR ) )
  2840. {
  2841. if ( dwRetCode == NO_ERROR )
  2842. {
  2843. dwRetCode = ERROR_PPP_NO_PROTOCOLS_CONFIGURED;
  2844. }
  2845. for(dwIndex=LCP_INDEX+1;dwIndex < PppConfigInfo.NumberOfCPs;dwIndex++)
  2846. {
  2847. CPCB * pCpCb = GetPointerToCPCB( pPcb, dwIndex );
  2848. if ( pCpCb->fBeginCalled == TRUE )
  2849. {
  2850. if ( pCpCb->pWorkBuf != NULL )
  2851. {
  2852. (CpTable[dwIndex].CpInfo.RasCpEnd)( pCpCb->pWorkBuf );
  2853. pCpCb->pWorkBuf = NULL;
  2854. }
  2855. pCpCb->fBeginCalled = FALSE;
  2856. pCpCb->fConfigurable = FALSE;
  2857. }
  2858. }
  2859. }
  2860. return( dwRetCode );
  2861. }
  2862. //**
  2863. //
  2864. // Call: GetPointerToCPCB
  2865. //
  2866. // Returns: Pointer to Control Protocol Control Block
  2867. //
  2868. // Description: Returns the appropriate pointer for a give CP, will return the
  2869. // (first) local side for the AP.
  2870. //
  2871. CPCB *
  2872. GetPointerToCPCB(
  2873. IN PCB * pPcb,
  2874. IN DWORD CpIndex
  2875. )
  2876. {
  2877. //
  2878. // If the C.P. is LCP or authentication, then return the pointer to the
  2879. // Pcb's CPCB
  2880. //
  2881. if ( CpIndex == (DWORD)-1 )
  2882. {
  2883. return( NULL );
  2884. }
  2885. else if ( CpIndex == LCP_INDEX )
  2886. {
  2887. return( &(pPcb->LcpCb) );
  2888. }
  2889. else if ( CpIndex >= PppConfigInfo.NumberOfCPs )
  2890. {
  2891. if ( CpTable[CpIndex].CpInfo.Protocol == PPP_CBCP_PROTOCOL )
  2892. {
  2893. return( &(pPcb->CallbackCb) );
  2894. }
  2895. if (CpTable[CpIndex].CpInfo.Protocol == pPcb->AuthenticatorCb.Protocol)
  2896. {
  2897. return( &(pPcb->AuthenticatorCb) );
  2898. }
  2899. if (CpTable[CpIndex].CpInfo.Protocol == pPcb->AuthenticateeCb.Protocol)
  2900. {
  2901. return( &(pPcb->AuthenticateeCb) );
  2902. }
  2903. }
  2904. else
  2905. {
  2906. //
  2907. // Otherwise for NCPs return the pointer to the Pcb's CPCB in its BCB.
  2908. //
  2909. return( &(pPcb->pBcb->CpCb[CpIndex-1]) );
  2910. }
  2911. return( NULL );
  2912. }
  2913. //**
  2914. //
  2915. // Call: GetNewPortOrBundleId
  2916. //
  2917. // Returns: New Id
  2918. //
  2919. // Description: Simply returns a new Id for a new port or bundle.
  2920. //
  2921. DWORD
  2922. GetNewPortOrBundleId(
  2923. VOID
  2924. )
  2925. {
  2926. return( PppConfigInfo.PortUIDGenerator++ );
  2927. }
  2928. //**
  2929. //
  2930. // Call: QueryBundleNCPSate
  2931. //
  2932. // Returns: NCP_DEAD
  2933. // NCP_CONFIGURING
  2934. // NCP_UP
  2935. // NCP_DOWN
  2936. //
  2937. // Description: Will check to see if the NCPs for a certain bundle have
  2938. // completed their negotiation, either successfully or not.
  2939. // If unsuccessfuly, then the retcode is
  2940. // ERROR_PPP_NO_PROTOCOLS_CONFIGURED
  2941. //
  2942. NCP_PHASE
  2943. QueryBundleNCPState(
  2944. IN PCB * pPcb
  2945. )
  2946. {
  2947. DWORD dwIndex;
  2948. CPCB * pCpCb;
  2949. BOOL fOneNcpConfigured = FALSE;
  2950. BOOL fAllNcpsDead = TRUE;
  2951. for (dwIndex = LCP_INDEX+1; dwIndex < PppConfigInfo.NumberOfCPs; dwIndex++)
  2952. {
  2953. pCpCb = GetPointerToCPCB( pPcb, dwIndex );
  2954. if ( pCpCb->fConfigurable )
  2955. {
  2956. if ( pCpCb->NcpPhase == NCP_CONFIGURING )
  2957. {
  2958. return( NCP_CONFIGURING );
  2959. }
  2960. if ( pCpCb->NcpPhase == NCP_UP )
  2961. {
  2962. fOneNcpConfigured = TRUE;
  2963. }
  2964. if ( pCpCb->NcpPhase != NCP_DEAD )
  2965. {
  2966. fAllNcpsDead = FALSE;
  2967. }
  2968. }
  2969. }
  2970. if ( fOneNcpConfigured )
  2971. {
  2972. return( NCP_UP );
  2973. }
  2974. if ( fAllNcpsDead )
  2975. {
  2976. return( NCP_DEAD );
  2977. }
  2978. return( NCP_DOWN );
  2979. }
  2980. //**
  2981. //
  2982. // Call: NotifyCallerOfBundledProjection
  2983. //
  2984. // Returns: None
  2985. //
  2986. // Description: Will notify the caller (i.e. supervisor or rasphone) about
  2987. // this link being bundled.
  2988. //
  2989. //
  2990. VOID
  2991. NotifyCallerOfBundledProjection(
  2992. IN PCB * pPcb
  2993. )
  2994. {
  2995. DWORD dwRetCode;
  2996. PPP_PROJECTION_RESULT ProjectionResult;
  2997. BOOL fNCPsAreDone = FALSE;
  2998. ZeroMemory( &ProjectionResult, sizeof( ProjectionResult ) );
  2999. //
  3000. // Notify the ras client and the ras server about the
  3001. // projections
  3002. //
  3003. dwRetCode = GetConfiguredInfo( pPcb,
  3004. 0, // don't care
  3005. &ProjectionResult,
  3006. &fNCPsAreDone );
  3007. if ( dwRetCode != NO_ERROR )
  3008. {
  3009. return;
  3010. }
  3011. if ( !fNCPsAreDone )
  3012. {
  3013. return;
  3014. }
  3015. //
  3016. // Now get LCP information
  3017. //
  3018. ProjectionResult.lcp.hportBundleMember = pPcb->hportBundleMember;
  3019. ProjectionResult.lcp.szReplyMessage = pPcb->pBcb->szReplyMessage;
  3020. dwRetCode = (CpTable[LCP_INDEX].CpInfo.RasCpGetNegotiatedInfo)(
  3021. pPcb->LcpCb.pWorkBuf,
  3022. &(ProjectionResult.lcp));
  3023. if ( RAS_DEVICE_TYPE( pPcb->dwDeviceType ) == RDT_Tunnel_L2tp )
  3024. {
  3025. if ( pPcb->pBcb->fFlags & BCBFLAG_BASIC_ENCRYPTION )
  3026. {
  3027. ProjectionResult.lcp.dwLocalOptions |= PPPLCPO_DES_56;
  3028. ProjectionResult.lcp.dwRemoteOptions |= PPPLCPO_DES_56;
  3029. }
  3030. else if ( pPcb->pBcb->fFlags & BCBFLAG_STRONGEST_ENCRYPTION )
  3031. {
  3032. ProjectionResult.lcp.dwLocalOptions |= PPPLCPO_3_DES;
  3033. ProjectionResult.lcp.dwRemoteOptions |= PPPLCPO_3_DES;
  3034. }
  3035. }
  3036. ProjectionResult.lcp.dwLocalEapTypeId = pPcb->dwServerEapTypeId;
  3037. ProjectionResult.lcp.dwRemoteEapTypeId = pPcb->dwClientEapTypeId;
  3038. if ( dwRetCode != NO_ERROR )
  3039. {
  3040. return;
  3041. }
  3042. if ( pPcb->fFlags & PCBFLAG_IS_SERVER )
  3043. {
  3044. NotifyCaller( pPcb, PPPDDMMSG_PppDone, &ProjectionResult );
  3045. }
  3046. else
  3047. {
  3048. NotifyCaller( pPcb, PPPMSG_ProjectionResult, &ProjectionResult);
  3049. NotifyCaller( pPcb, PPPMSG_PppDone, NULL );
  3050. }
  3051. }
  3052. //**
  3053. //
  3054. // Call: StartNegotiatingNCPs
  3055. //
  3056. // Returns: None
  3057. //
  3058. // Description: Will start NCP negogiating for the particular port or bundle
  3059. //
  3060. VOID
  3061. StartNegotiatingNCPs(
  3062. IN PCB * pPcb
  3063. )
  3064. {
  3065. DWORD dwIndex;
  3066. pPcb->PppPhase = PPP_NCP;
  3067. for (dwIndex = LCP_INDEX+1; dwIndex < PppConfigInfo.NumberOfCPs; dwIndex++)
  3068. {
  3069. CPCB * pCpCb = GetPointerToCPCB( pPcb, dwIndex );
  3070. if ( pCpCb->fConfigurable )
  3071. {
  3072. pCpCb->NcpPhase = NCP_CONFIGURING;
  3073. FsmOpen( pPcb, dwIndex );
  3074. FsmUp( pPcb, dwIndex );
  3075. }
  3076. }
  3077. }
  3078. //**
  3079. //
  3080. // Call: StartAutoDisconnectForPort
  3081. //
  3082. // Returns: NO_ERROR - Success
  3083. // Non-zero returns - Failure
  3084. //
  3085. // Description: Will insert an auto disconnect and sesison timeout item in the
  3086. // timer Q
  3087. //
  3088. VOID
  3089. StartAutoDisconnectForPort(
  3090. IN PCB * pPcb
  3091. )
  3092. {
  3093. //
  3094. // Do session timeout if there is any
  3095. //
  3096. if ( pPcb->fFlags & PCBFLAG_IS_SERVER )
  3097. {
  3098. RAS_AUTH_ATTRIBUTE * pAttribute;
  3099. RAS_AUTH_ATTRIBUTE * pUserAttributes = ( pPcb->pAuthProtocolAttributes )
  3100. ? pPcb->pAuthProtocolAttributes
  3101. : pPcb->pAuthenticatorAttributes;
  3102. pAttribute = RasAuthAttributeGet( raatSessionTimeout, pUserAttributes);
  3103. if ( pAttribute != NULL )
  3104. {
  3105. pPcb->dwSessionTimeout = PtrToUlong(pAttribute->Value);
  3106. }
  3107. else
  3108. {
  3109. pPcb->dwSessionTimeout = PppConfigInfo.dwDefaultSessionTimeout;
  3110. }
  3111. PppLog( 2, "AuthAttribute SessionTimeout = %d", pPcb->dwSessionTimeout);
  3112. if ( pPcb->dwSessionTimeout > 0 )
  3113. {
  3114. //
  3115. // Remove any previous session-disconnect time item from the
  3116. // queue if there was one.
  3117. //
  3118. RemoveFromTimerQ( pPcb->dwPortId,
  3119. 0,
  3120. 0,
  3121. FALSE,
  3122. TIMER_EVENT_SESSION_TIMEOUT );
  3123. InsertInTimerQ( pPcb->dwPortId,
  3124. pPcb->hPort,
  3125. 0,
  3126. 0,
  3127. FALSE,
  3128. TIMER_EVENT_SESSION_TIMEOUT,
  3129. pPcb->dwSessionTimeout );
  3130. }
  3131. }
  3132. //
  3133. // Do not start autodisconnect for router interfaces that have
  3134. // dialed in, the router dialing in will take care of this.
  3135. //
  3136. if ( ( pPcb->fFlags & PCBFLAG_IS_SERVER ) &&
  3137. ( pPcb->pBcb->InterfaceInfo.IfType == ROUTER_IF_TYPE_FULL_ROUTER ) )
  3138. {
  3139. return;
  3140. }
  3141. //
  3142. // If the AutoDisconnectTime is not infinte, put a timer
  3143. // element on the queue that will wake up in AutoDisconnectTime.
  3144. //
  3145. if ( pPcb->dwAutoDisconnectTime > 0 )
  3146. {
  3147. PppLog( 2, "Inserting autodisconnect in timer q for port=%d, sec=%d",
  3148. pPcb->hPort, pPcb->dwAutoDisconnectTime );
  3149. //
  3150. // Remove any previous auto-disconnect time item from the
  3151. // queue if there was one.
  3152. //
  3153. RemoveFromTimerQ( pPcb->dwPortId,
  3154. 0,
  3155. 0,
  3156. FALSE,
  3157. TIMER_EVENT_AUTODISCONNECT);
  3158. InsertInTimerQ( pPcb->dwPortId,
  3159. pPcb->hPort,
  3160. 0,
  3161. 0,
  3162. FALSE,
  3163. TIMER_EVENT_AUTODISCONNECT,
  3164. pPcb->dwAutoDisconnectTime );
  3165. }
  3166. }
  3167. //**
  3168. //
  3169. // Call: StartLCPEchoForPort
  3170. //
  3171. // Returns: None
  3172. //
  3173. //
  3174. // Description: Will insert an LCPEcho item in the timer Q
  3175. //
  3176. VOID
  3177. StartLCPEchoForPort(
  3178. IN PCB * pPcb
  3179. )
  3180. {
  3181. if ( !(pPcb->fFlags & PCBFLAG_IS_SERVER) )
  3182. {
  3183. //if this is a client.
  3184. //check to see if the connection type is broadband - PPPOE in particular
  3185. if ( (RAS_DEVICE_TYPE(pPcb->dwDeviceType) == RDT_PPPoE)
  3186. && pPcb->dwIdleBeforeEcho )
  3187. {
  3188. PppLog( 2, "LCPEchoTimeout = %d", pPcb->dwIdleBeforeEcho);
  3189. pPcb->fEchoRequestSend = 0;
  3190. pPcb->dwNumEchoResponseMissed = 0; //No responses missed yet
  3191. InsertInTimerQ( pPcb->dwPortId,
  3192. pPcb->hPort,
  3193. 0,
  3194. 0,
  3195. FALSE,
  3196. TIMER_EVENT_LCP_ECHO,
  3197. pPcb->dwIdleBeforeEcho );
  3198. }
  3199. }
  3200. return;
  3201. }
  3202. //**
  3203. //
  3204. // Call: NotifyCompletionOnBundledPorts
  3205. //
  3206. // Returns: NO_ERROR - Success
  3207. // Non-zero returns - Failure
  3208. //
  3209. // Description: Will notify all ports that are bundled with this port and
  3210. // are waiting to for negotiation to complete on the bundle.
  3211. //
  3212. VOID
  3213. NotifyCompletionOnBundledPorts(
  3214. IN PCB * pPcb
  3215. )
  3216. {
  3217. DWORD dwIndex;
  3218. PCB * pPcbWalker;
  3219. //
  3220. // Walk thru the list of PCBs
  3221. //
  3222. for ( dwIndex = 0; dwIndex < PcbTable.NumPcbBuckets; dwIndex++ )
  3223. {
  3224. for( pPcbWalker = PcbTable.PcbBuckets[dwIndex].pPorts;
  3225. pPcbWalker != NULL;
  3226. pPcbWalker = pPcbWalker->pNext )
  3227. {
  3228. if ( ( pPcbWalker->hPort != pPcb->hPort ) &&
  3229. ( pPcbWalker->fFlags & PCBFLAG_IS_BUNDLED ) &&
  3230. ( CanPortsBeBundled( pPcbWalker, pPcb, TRUE ) ) )
  3231. {
  3232. //
  3233. // In our bundle so notify the caller of completion on this
  3234. // port.
  3235. //
  3236. RemoveFromTimerQ( pPcbWalker->dwPortId,
  3237. 0,
  3238. 0,
  3239. FALSE,
  3240. TIMER_EVENT_NEGOTIATETIME );
  3241. NotifyCallerOfBundledProjection( pPcbWalker );
  3242. StartAutoDisconnectForPort( pPcbWalker );
  3243. }
  3244. }
  3245. }
  3246. }
  3247. //**
  3248. //
  3249. // Call: RemoveNonNumerals
  3250. //
  3251. // Returns: VOID
  3252. //
  3253. // Description: Removes any character that is not an ASCII digit from
  3254. // the string szString
  3255. //
  3256. VOID
  3257. RemoveNonNumerals(
  3258. IN CHAR* szString
  3259. )
  3260. {
  3261. CHAR c;
  3262. DWORD dwIndexOld;
  3263. DWORD dwIndexNew;
  3264. if (NULL == szString)
  3265. {
  3266. return;
  3267. }
  3268. for (dwIndexOld = 0, dwIndexNew = 0;
  3269. (c = szString[dwIndexOld]) != 0;
  3270. dwIndexOld++)
  3271. {
  3272. if (isdigit(c))
  3273. {
  3274. szString[dwIndexNew++] = c;
  3275. }
  3276. }
  3277. szString[dwIndexNew] = 0;
  3278. }
  3279. //**
  3280. //
  3281. // Call: GetTextualSid
  3282. //
  3283. // Returns: TRUE - Success
  3284. // FALSE - Failure
  3285. //
  3286. // Description: The GetTextualSid function will convert a binary Sid to a
  3287. // textual string. Obtained from the Knowledge Base.
  3288. // Article ID: Q131320
  3289. //
  3290. BOOL
  3291. GetTextualSid(
  3292. IN PSID pSid, // binary Sid
  3293. OUT CHAR* TextualSid, // buffer for Textual representaion of Sid
  3294. IN LPDWORD dwBufferLen // required/provided TextualSid buffersize
  3295. )
  3296. {
  3297. PSID_IDENTIFIER_AUTHORITY psia;
  3298. DWORD dwSubAuthorities;
  3299. DWORD dwSidRev=SID_REVISION;
  3300. DWORD dwCounter;
  3301. DWORD dwSidSize;
  3302. //
  3303. // test if Sid passed in is valid
  3304. //
  3305. if(!IsValidSid(pSid))
  3306. return FALSE;
  3307. //
  3308. // obtain SidIdentifierAuthority
  3309. //
  3310. psia=GetSidIdentifierAuthority(pSid);
  3311. //
  3312. // obtain sidsubauthority count
  3313. //
  3314. dwSubAuthorities=*GetSidSubAuthorityCount(pSid);
  3315. //
  3316. // compute buffer length
  3317. // S-SID_REVISION- + identifierauthority- + subauthorities- + NULL
  3318. //
  3319. dwSidSize=(15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
  3320. //
  3321. // check provided buffer length.
  3322. // If not large enough, indicate proper size and setlasterror
  3323. //
  3324. if (*dwBufferLen < dwSidSize)
  3325. {
  3326. *dwBufferLen = dwSidSize;
  3327. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  3328. return FALSE;
  3329. }
  3330. //
  3331. // prepare S-SID_REVISION-
  3332. //
  3333. dwSidSize=wsprintfA(TextualSid, "S-%lu-", dwSidRev );
  3334. //
  3335. // prepare SidIdentifierAuthority
  3336. //
  3337. if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) )
  3338. {
  3339. dwSidSize+=wsprintfA(TextualSid + lstrlenA(TextualSid),
  3340. "0x%02hx%02hx%02hx%02hx%02hx%02hx",
  3341. (USHORT)psia->Value[0],
  3342. (USHORT)psia->Value[1],
  3343. (USHORT)psia->Value[2],
  3344. (USHORT)psia->Value[3],
  3345. (USHORT)psia->Value[4],
  3346. (USHORT)psia->Value[5]);
  3347. }
  3348. else
  3349. {
  3350. dwSidSize+=wsprintfA(TextualSid + lstrlenA(TextualSid),
  3351. "%lu",
  3352. (ULONG)(psia->Value[5] ) +
  3353. (ULONG)(psia->Value[4] << 8) +
  3354. (ULONG)(psia->Value[3] << 16) +
  3355. (ULONG)(psia->Value[2] << 24) );
  3356. }
  3357. //
  3358. // loop through SidSubAuthorities
  3359. //
  3360. for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++)
  3361. {
  3362. dwSidSize+=wsprintfA(TextualSid + dwSidSize, "-%lu",
  3363. *GetSidSubAuthority(pSid, dwCounter) );
  3364. }
  3365. return TRUE;
  3366. }
  3367. //**
  3368. //
  3369. // Call: TextualSidFromPid
  3370. //
  3371. // Returns: NULL - Failure
  3372. // non-NULL - Success
  3373. //
  3374. // Description: Will LOCAL_ALLOC a Textual Sid for a user whose pid is dwPid.
  3375. //
  3376. CHAR*
  3377. TextualSidFromPid(
  3378. DWORD dwPid
  3379. )
  3380. {
  3381. #define BUF_SIZE 256
  3382. BOOL fFreeTextualSid = FALSE;
  3383. CHAR* szTextualSid = NULL;
  3384. HANDLE ProcessHandle = NULL;
  3385. HANDLE TokenHandle = INVALID_HANDLE_VALUE;
  3386. TOKEN_USER ptgUser[BUF_SIZE];
  3387. DWORD cbBuffer;
  3388. DWORD cbSid;
  3389. szTextualSid = LOCAL_ALLOC( LPTR, sizeof( CHAR ) * BUF_SIZE );
  3390. if ( NULL == szTextualSid )
  3391. {
  3392. BapTrace( "LOCAL_ALLOC() returned error %d", GetLastError() );
  3393. goto LDone;
  3394. }
  3395. fFreeTextualSid = TRUE;
  3396. ProcessHandle = OpenProcess(
  3397. PROCESS_ALL_ACCESS,
  3398. FALSE /* bInheritHandle */,
  3399. dwPid );
  3400. if ( NULL == ProcessHandle )
  3401. {
  3402. BapTrace( "OpenProcess() returned error %d", GetLastError() );
  3403. goto LDone;
  3404. }
  3405. if ( !OpenProcessToken( ProcessHandle, TOKEN_QUERY, &TokenHandle ) )
  3406. {
  3407. BapTrace( "OpenProcessToken() returned error %d", GetLastError() );
  3408. goto LDone;
  3409. }
  3410. cbBuffer = BUF_SIZE;
  3411. if ( !GetTokenInformation(
  3412. TokenHandle,
  3413. TokenUser,
  3414. ptgUser,
  3415. cbBuffer,
  3416. &cbBuffer ) ) // Look at KB article Q131320
  3417. {
  3418. BapTrace( "GetTokenInformation() returned error %d", GetLastError() );
  3419. goto LDone;
  3420. }
  3421. cbSid = BUF_SIZE;
  3422. if ( !GetTextualSid(
  3423. ptgUser->User.Sid,
  3424. szTextualSid,
  3425. &cbSid ) )
  3426. {
  3427. BapTrace( "GetTextualSid() returned error %d", GetLastError() );
  3428. goto LDone;
  3429. }
  3430. fFreeTextualSid = FALSE;
  3431. LDone:
  3432. if ( NULL != ProcessHandle )
  3433. {
  3434. CloseHandle( ProcessHandle );
  3435. }
  3436. if ( INVALID_HANDLE_VALUE != TokenHandle )
  3437. {
  3438. CloseHandle( TokenHandle );
  3439. }
  3440. if ( fFreeTextualSid )
  3441. {
  3442. LOCAL_FREE( szTextualSid );
  3443. szTextualSid = NULL;
  3444. }
  3445. return( szTextualSid );
  3446. }
  3447. //**
  3448. //
  3449. // Call: GetRouterPhoneBook
  3450. //
  3451. // Returns: NO_ERROR - Success
  3452. // Non-zero returns - Failure
  3453. //
  3454. // Description: Will LocalAlloc and set pszPhonebookPath to point to the
  3455. // full path of the router phonebook.
  3456. //
  3457. DWORD
  3458. GetRouterPhoneBook(
  3459. CHAR** pszPhonebookPath
  3460. )
  3461. {
  3462. DWORD dwSize;
  3463. DWORD cchDir = GetWindowsDirectoryA( NULL, 0 );
  3464. CHAR* szPhonebookPath;
  3465. *pszPhonebookPath = NULL;
  3466. if ( cchDir == 0 )
  3467. {
  3468. return( GetLastError() );
  3469. }
  3470. dwSize=(cchDir+lstrlenA("\\system32\\ras\\router.pbk")+1)*sizeof(CHAR);
  3471. if ( ( szPhonebookPath = LocalAlloc( LPTR, dwSize ) ) == NULL )
  3472. {
  3473. return( GetLastError() );
  3474. }
  3475. if ( GetWindowsDirectoryA( szPhonebookPath, cchDir ) == 0 )
  3476. {
  3477. LocalFree( szPhonebookPath );
  3478. return( GetLastError() );
  3479. }
  3480. if ( szPhonebookPath[cchDir-1] != '\\' )
  3481. {
  3482. lstrcatA( szPhonebookPath, "\\" );
  3483. }
  3484. lstrcatA( szPhonebookPath, "system32\\ras\\router.pbk" );
  3485. *pszPhonebookPath = szPhonebookPath;
  3486. return( NO_ERROR );
  3487. }
  3488. //**
  3489. //
  3490. // Call: GetCredentialsFromInterface
  3491. //
  3492. // Returns: NO_ERROR - Success
  3493. // Non-zero returns - Failure
  3494. //
  3495. // Description: Get the credentials for the interface called
  3496. // pPcb->pBcb->szRemoteUserName.
  3497. //
  3498. DWORD
  3499. GetCredentialsFromInterface(
  3500. PCB * pPcb
  3501. )
  3502. {
  3503. WCHAR wchUserName[UNLEN+1];
  3504. WCHAR wchPassword[PWLEN+1];
  3505. WCHAR wchDomainName[DNLEN+1];
  3506. WCHAR wchInterfaceName[UNLEN+1];
  3507. DWORD dwRetCode;
  3508. wchUserName[0] = wchPassword[0] = wchDomainName[0] = wchInterfaceName[0] =
  3509. 0;
  3510. if ( 0 == MultiByteToWideChar(
  3511. CP_ACP,
  3512. 0,
  3513. pPcb->pBcb->szRemoteUserName,
  3514. -1,
  3515. wchInterfaceName,
  3516. sizeof( wchInterfaceName ) / sizeof( WCHAR ) ) )
  3517. {
  3518. dwRetCode = GetLastError();
  3519. return( dwRetCode );
  3520. }
  3521. dwRetCode = MprAdminInterfaceGetCredentialsInternal(
  3522. NULL,
  3523. wchInterfaceName,
  3524. wchUserName,
  3525. wchPassword,
  3526. wchDomainName );
  3527. if ( NO_ERROR == dwRetCode )
  3528. {
  3529. if ( 0 == WideCharToMultiByte(
  3530. CP_ACP,
  3531. 0,
  3532. wchUserName,
  3533. -1,
  3534. pPcb->pBcb->szLocalUserName,
  3535. sizeof( pPcb->pBcb->szLocalUserName ),
  3536. NULL,
  3537. NULL ) )
  3538. {
  3539. dwRetCode = GetLastError();
  3540. return( dwRetCode );
  3541. }
  3542. if ( 0 == WideCharToMultiByte(
  3543. CP_ACP,
  3544. 0,
  3545. wchPassword,
  3546. -1,
  3547. pPcb->pBcb->szPassword,
  3548. sizeof( pPcb->pBcb->szPassword ),
  3549. NULL,
  3550. NULL ) )
  3551. {
  3552. dwRetCode = GetLastError();
  3553. return( dwRetCode );
  3554. }
  3555. if ( 0 == WideCharToMultiByte(
  3556. CP_ACP,
  3557. 0,
  3558. wchDomainName,
  3559. -1,
  3560. pPcb->pBcb->szLocalDomain,
  3561. sizeof( pPcb->pBcb->szLocalDomain ),
  3562. NULL,
  3563. NULL ) )
  3564. {
  3565. dwRetCode = GetLastError();
  3566. return( dwRetCode );
  3567. }
  3568. //
  3569. // Null out password buffer
  3570. //
  3571. ZeroMemory( wchPassword, sizeof( wchPassword ) );
  3572. EncodePw( pPcb->pBcb->chSeed, pPcb->pBcb->szPassword );
  3573. EncodePw( pPcb->pBcb->chSeed, pPcb->pBcb->szOldPassword );
  3574. }
  3575. return( dwRetCode );
  3576. }
  3577. //**
  3578. //
  3579. // Call: IsCpIndexOfAp
  3580. //
  3581. // Returns: TRUE - The CpIndex belongs to an Authentication Protocol
  3582. // FALSE - Otherwise
  3583. //
  3584. // Description:
  3585. //
  3586. BOOL
  3587. IsCpIndexOfAp(
  3588. IN DWORD CpIndex
  3589. )
  3590. {
  3591. if ( CpIndex >= PppConfigInfo.NumberOfCPs )
  3592. {
  3593. return( TRUE );
  3594. }
  3595. return( FALSE );
  3596. }
  3597. //**
  3598. //
  3599. // Call: StartAccounting
  3600. //
  3601. // Returns: None
  3602. //
  3603. // Description: Will start accounting if the back-end authentication provider
  3604. // supports it.
  3605. //
  3606. VOID
  3607. StartAccounting(
  3608. PVOID pContext
  3609. )
  3610. {
  3611. DWORD dwRetCode;
  3612. RAS_AUTH_ATTRIBUTE * pInAttributes = (RAS_AUTH_ATTRIBUTE*)pContext;
  3613. RAS_AUTH_ATTRIBUTE * pOutAttributes = NULL;
  3614. dwRetCode = (*PppConfigInfo.RasAcctProviderStartAccounting)(
  3615. pInAttributes,
  3616. &pOutAttributes );
  3617. if ( pOutAttributes != NULL )
  3618. {
  3619. PppConfigInfo.RasAuthProviderFreeAttributes( pOutAttributes );
  3620. }
  3621. RasAuthAttributeDestroy( pInAttributes );
  3622. }
  3623. //**
  3624. //
  3625. // Call: InterimAccounting
  3626. //
  3627. // Returns: None
  3628. //
  3629. // Description: Will send and interim accounting packet if the back-end
  3630. // authentication provider supports it.
  3631. //
  3632. VOID
  3633. InterimAccounting(
  3634. PVOID pContext
  3635. )
  3636. {
  3637. DWORD dwRetCode;
  3638. RAS_AUTH_ATTRIBUTE * pInAttributes = (RAS_AUTH_ATTRIBUTE*)pContext;
  3639. RAS_AUTH_ATTRIBUTE * pOutAttributes = NULL;
  3640. dwRetCode = (*PppConfigInfo.RasAcctProviderInterimAccounting)(
  3641. pInAttributes,
  3642. &pOutAttributes );
  3643. if ( pOutAttributes != NULL )
  3644. {
  3645. PppConfigInfo.RasAuthProviderFreeAttributes( pOutAttributes );
  3646. }
  3647. RasAuthAttributeDestroy( pInAttributes );
  3648. }
  3649. //**
  3650. //
  3651. // Call: StopAccounting
  3652. //
  3653. // Returns: None
  3654. //
  3655. // Description: Will stop accounting if the back-end authentication provider
  3656. // supports it.
  3657. //
  3658. VOID
  3659. StopAccounting(
  3660. PVOID pContext
  3661. )
  3662. {
  3663. DWORD dwRetCode;
  3664. PSTOP_ACCOUNTING_CONTEXT pAcctContext = (PSTOP_ACCOUNTING_CONTEXT)pContext;
  3665. RAS_AUTH_ATTRIBUTE * pInAttributes = pAcctContext->pAuthAttributes;
  3666. RAS_AUTH_ATTRIBUTE * pOutAttributes = NULL;
  3667. PPPE_MESSAGE PppMessage;
  3668. //
  3669. // It is possible that StopAccounting will be queued on a worker thread
  3670. // soon after a StartAccounting (Win2000 bug 376334). We don't want the
  3671. // StopAccounting to finish before the StartAccounting. Hence the sleep.
  3672. // The real fix is to make sure that the same thread calls both
  3673. // StartAccounting and StopAccounting.
  3674. //
  3675. PppLog ( 2, "Stopping Accounting for port %d", pAcctContext->pPcb->hPort );
  3676. Sleep( 2000 );
  3677. dwRetCode = (*PppConfigInfo.RasAcctProviderStopAccounting)(
  3678. pInAttributes,
  3679. &pOutAttributes );
  3680. if ( pOutAttributes != NULL )
  3681. {
  3682. PppConfigInfo.RasAuthProviderFreeAttributes( pOutAttributes );
  3683. }
  3684. RasAuthAttributeDestroy( pInAttributes );
  3685. ZeroMemory ( &PppMessage, sizeof(PppMessage));
  3686. PppMessage.hPort = pAcctContext->pPcb->hPort;
  3687. PppMessage.dwMsgId = PPPEMSG_PostLineDown;
  3688. PppMessage.ExtraInfo.PostLineDown.pPcb = (VOID *)pAcctContext->pPcb;
  3689. //Call PostLineDown
  3690. SendPPPMessageToEngine( &PppMessage );
  3691. LocalFree(pAcctContext);
  3692. }
  3693. //**
  3694. //
  3695. // Call: StripCRLF
  3696. //
  3697. // Returns: Strips out CR and LF characters from the string
  3698. //
  3699. // Description:
  3700. //
  3701. VOID
  3702. StripCRLF(
  3703. CHAR* psz
  3704. )
  3705. {
  3706. DWORD dw1;
  3707. DWORD dw2;
  3708. CHAR ch;
  3709. if ( NULL == psz )
  3710. {
  3711. return;
  3712. }
  3713. dw1 = 0;
  3714. dw2 = 0;
  3715. while ( ( ch = psz[dw1++] ) != 0 )
  3716. {
  3717. if ( ( ch == 0xD )
  3718. || ( ch == 0xA ) )
  3719. {
  3720. //
  3721. // Don't copy this character
  3722. //
  3723. continue;
  3724. }
  3725. psz[dw2++] = ch;
  3726. }
  3727. psz[dw2] = 0;
  3728. }
  3729. //**
  3730. //
  3731. // Call: GetUserAttributes
  3732. //
  3733. // Returns: NO_ERROR - Success
  3734. // Non-zero returns - Failure
  3735. //
  3736. // Description:
  3737. //
  3738. RAS_AUTH_ATTRIBUTE *
  3739. GetUserAttributes(
  3740. PCB * pPcb
  3741. )
  3742. {
  3743. RAS_AUTH_ATTRIBUTE * pAttributes = NULL;
  3744. DWORD dwRetCode = NO_ERROR;
  3745. DWORD dwIndex = 0;
  3746. RAS_CONNECT_INFO * pConnectInfo = NULL;
  3747. DWORD dwSize = 0;
  3748. DWORD dwNASPortType = (DWORD)-1;
  3749. DWORD dwValue;
  3750. BOOL fTunnel = FALSE;
  3751. if ( pPcb->pUserAttributes != NULL )
  3752. {
  3753. return( NULL );
  3754. }
  3755. pAttributes = RasAuthAttributeCreate( PPP_NUM_USER_ATTRIBUTES );
  3756. if ( pAttributes == NULL )
  3757. {
  3758. return( NULL );
  3759. }
  3760. do
  3761. {
  3762. if ( PppConfigInfo.szNASIdentifier[0] != 0 )
  3763. {
  3764. dwRetCode = RasAuthAttributeInsert(
  3765. dwIndex++,
  3766. pAttributes,
  3767. raatNASIdentifier,
  3768. FALSE,
  3769. strlen( PppConfigInfo.szNASIdentifier ),
  3770. (LPVOID)PppConfigInfo.szNASIdentifier );
  3771. if ( dwRetCode != NO_ERROR )
  3772. {
  3773. break;
  3774. }
  3775. }
  3776. if ( PppConfigInfo.dwNASIpAddress != 0 )
  3777. {
  3778. dwRetCode = RasAuthAttributeInsert(
  3779. dwIndex++,
  3780. pAttributes,
  3781. raatNASIPAddress,
  3782. FALSE,
  3783. 4,
  3784. (LPVOID)ULongToPtr(PppConfigInfo.dwNASIpAddress) );
  3785. }
  3786. if ( dwRetCode != NO_ERROR )
  3787. {
  3788. break;
  3789. }
  3790. dwRetCode = RasAuthAttributeInsert( dwIndex++,
  3791. pAttributes,
  3792. raatServiceType,
  3793. FALSE,
  3794. 4,
  3795. UlongToPtr
  3796. ( ( pPcb->fFlags &
  3797. PCBFLAG_THIS_IS_A_CALLBACK ) ?
  3798. 4 : // Callback Framed
  3799. 2 ) ); // Framed
  3800. if ( dwRetCode != NO_ERROR )
  3801. {
  3802. break;
  3803. }
  3804. dwRetCode = RasAuthAttributeInsert( dwIndex++,
  3805. pAttributes,
  3806. raatFramedProtocol,
  3807. FALSE,
  3808. 4,
  3809. (LPVOID)1 ); //PPP
  3810. if ( dwRetCode != NO_ERROR )
  3811. {
  3812. break;
  3813. }
  3814. dwRetCode = RasAuthAttributeInsert( dwIndex++,
  3815. pAttributes,
  3816. raatNASPort,
  3817. FALSE,
  3818. 4,
  3819. (LPVOID)pPcb->hPort );
  3820. if ( dwRetCode != NO_ERROR )
  3821. {
  3822. break;
  3823. }
  3824. {
  3825. BYTE MSRASVendor[10];
  3826. BYTE MSRASVersion[30];
  3827. BYTE bLength;
  3828. HostToWireFormat32( 311, MSRASVendor ); // Vendor-Id
  3829. MSRASVendor[4] = 9; // Vendor-Type: MS-RAS-Vendor
  3830. MSRASVendor[5] = 6; // Vendor-Length
  3831. HostToWireFormat32( 311, MSRASVendor + 6) ; // Vendor-Id
  3832. dwRetCode = RasAuthAttributeInsert( dwIndex++,
  3833. pAttributes,
  3834. raatVendorSpecific,
  3835. FALSE,
  3836. 10,
  3837. &MSRASVendor );
  3838. if ( dwRetCode != NO_ERROR )
  3839. {
  3840. break;
  3841. }
  3842. bLength = (BYTE)strlen( MS_RAS_VERSION );
  3843. RTASSERT( 30 >= 6 + bLength );
  3844. HostToWireFormat32( 311, MSRASVersion ); // Vendor-Id
  3845. MSRASVersion[4] = 18; // Vendor-Type: MS-RAS-Version
  3846. MSRASVersion[5] = 2 + bLength; // Vendor-Length
  3847. CopyMemory( MSRASVersion + 6, MS_RAS_VERSION, bLength );
  3848. dwRetCode = RasAuthAttributeInsert( dwIndex++,
  3849. pAttributes,
  3850. raatVendorSpecific,
  3851. FALSE,
  3852. 6 + bLength,
  3853. &MSRASVersion );
  3854. if ( dwRetCode != NO_ERROR )
  3855. {
  3856. break;
  3857. }
  3858. }
  3859. switch( RAS_DEVICE_TYPE( pPcb->dwDeviceType ) )
  3860. {
  3861. case RDT_Modem:
  3862. case RDT_Serial:
  3863. dwNASPortType = 0;
  3864. break;
  3865. case RDT_Isdn:
  3866. dwNASPortType = 2;
  3867. break;
  3868. case RDT_Tunnel_Pptp:
  3869. case RDT_Tunnel_L2tp:
  3870. dwNASPortType = 5;
  3871. fTunnel = TRUE;
  3872. break;
  3873. default:
  3874. dwNASPortType = (DWORD)-1;
  3875. break;
  3876. }
  3877. if ( dwNASPortType != (DWORD)-1 )
  3878. {
  3879. dwRetCode = RasAuthAttributeInsert( dwIndex++,
  3880. pAttributes,
  3881. raatNASPortType,
  3882. FALSE,
  3883. 4,
  3884. (LPVOID)ULongToPtr(dwNASPortType) );
  3885. if ( dwRetCode != NO_ERROR )
  3886. {
  3887. break;
  3888. }
  3889. }
  3890. if ( fTunnel )
  3891. {
  3892. dwValue = 0;
  3893. ((BYTE*)(&dwValue))[0] =
  3894. ( RAS_DEVICE_TYPE( pPcb->dwDeviceType ) == RDT_Tunnel_Pptp ) ?
  3895. 1 : 3;
  3896. dwRetCode = RasAuthAttributeInsert(
  3897. dwIndex++,
  3898. pAttributes,
  3899. raatTunnelType,
  3900. FALSE,
  3901. 4,
  3902. (LPVOID)ULongToPtr(dwValue) );
  3903. if ( dwRetCode != NO_ERROR )
  3904. {
  3905. break;
  3906. }
  3907. dwRetCode = RasAuthAttributeInsert(
  3908. dwIndex++,
  3909. pAttributes,
  3910. raatTunnelMediumType,
  3911. FALSE,
  3912. 4,
  3913. (LPVOID)1 ); // IP
  3914. if ( dwRetCode != NO_ERROR )
  3915. {
  3916. break;
  3917. }
  3918. }
  3919. if ( ( pPcb->fFlags & PCBFLAG_IS_SERVER )
  3920. && ( pPcb->fFlags & PCBFLAG_THIS_IS_A_CALLBACK ) )
  3921. {
  3922. //
  3923. // send the calling-station-id attrib with the number dialed
  3924. //
  3925. dwRetCode = RasAuthAttributeInsert(
  3926. dwIndex++,
  3927. pAttributes,
  3928. raatCallingStationId,
  3929. FALSE,
  3930. strlen( pPcb->szCallbackNumber ),
  3931. (VOID*) pPcb->szCallbackNumber );
  3932. if ( dwRetCode != NO_ERROR )
  3933. {
  3934. break;
  3935. }
  3936. }
  3937. if ( RasGetConnectInfo( pPcb->hPort, &dwSize, NULL )
  3938. == ERROR_BUFFER_TOO_SMALL )
  3939. {
  3940. if ( ( pConnectInfo = LOCAL_ALLOC( LPTR, dwSize ) ) != NULL )
  3941. {
  3942. if ( RasGetConnectInfo( pPcb->hPort, &dwSize, pConnectInfo )
  3943. == NO_ERROR )
  3944. {
  3945. if ( ( pConnectInfo->dwCalledIdSize > 0 )
  3946. && ( pConnectInfo->pszCalledId[0] != 0 ) )
  3947. {
  3948. dwRetCode = RasAuthAttributeInsert(
  3949. dwIndex++,
  3950. pAttributes,
  3951. raatCalledStationId,
  3952. FALSE,
  3953. strlen(pConnectInfo->pszCalledId),
  3954. (LPVOID)pConnectInfo->pszCalledId );
  3955. if ( dwRetCode != NO_ERROR )
  3956. {
  3957. break;
  3958. }
  3959. if ( fTunnel )
  3960. {
  3961. dwRetCode = RasAuthAttributeInsert(
  3962. dwIndex++,
  3963. pAttributes,
  3964. raatTunnelServerEndpoint,
  3965. FALSE,
  3966. strlen(pConnectInfo->pszCalledId),
  3967. (LPVOID)pConnectInfo->pszCalledId );
  3968. if ( dwRetCode != NO_ERROR )
  3969. {
  3970. break;
  3971. }
  3972. }
  3973. }
  3974. else if ( ( pConnectInfo->dwAltCalledIdSize > 0 )
  3975. && ( pConnectInfo->pszAltCalledId[0] != 0 ) )
  3976. {
  3977. dwRetCode = RasAuthAttributeInsert(
  3978. dwIndex++,
  3979. pAttributes,
  3980. raatCalledStationId,
  3981. FALSE,
  3982. strlen(pConnectInfo->pszAltCalledId),
  3983. (LPVOID)pConnectInfo->pszAltCalledId );
  3984. if ( dwRetCode != NO_ERROR )
  3985. {
  3986. break;
  3987. }
  3988. if ( fTunnel )
  3989. {
  3990. dwRetCode = RasAuthAttributeInsert(
  3991. dwIndex++,
  3992. pAttributes,
  3993. raatTunnelServerEndpoint,
  3994. FALSE,
  3995. strlen(pConnectInfo->pszAltCalledId),
  3996. (LPVOID)pConnectInfo->pszAltCalledId );
  3997. if ( dwRetCode != NO_ERROR )
  3998. {
  3999. break;
  4000. }
  4001. }
  4002. }
  4003. if ( ( pConnectInfo->dwCallerIdSize > 0 )
  4004. && ( pConnectInfo->pszCallerId[0] != 0 ) )
  4005. {
  4006. dwRetCode = RasAuthAttributeInsert(
  4007. dwIndex++,
  4008. pAttributes,
  4009. raatCallingStationId,
  4010. FALSE,
  4011. strlen(pConnectInfo->pszCallerId),
  4012. (LPVOID)pConnectInfo->pszCallerId );
  4013. if ( dwRetCode != NO_ERROR )
  4014. {
  4015. break;
  4016. }
  4017. if ( fTunnel )
  4018. {
  4019. dwRetCode = RasAuthAttributeInsert(
  4020. dwIndex++,
  4021. pAttributes,
  4022. raatTunnelClientEndpoint,
  4023. FALSE,
  4024. strlen(pConnectInfo->pszCallerId),
  4025. (LPVOID)pConnectInfo->pszCallerId );
  4026. if ( dwRetCode != NO_ERROR )
  4027. {
  4028. break;
  4029. }
  4030. }
  4031. }
  4032. StripCRLF( pConnectInfo->pszConnectResponse );
  4033. if ( pConnectInfo->dwConnectResponseSize > 0 )
  4034. {
  4035. dwRetCode = RasAuthAttributeInsert(
  4036. dwIndex++,
  4037. pAttributes,
  4038. raatConnectInfo,
  4039. FALSE,
  4040. strlen( pConnectInfo->pszConnectResponse),
  4041. (LPVOID)pConnectInfo->pszConnectResponse);
  4042. if ( dwRetCode != NO_ERROR )
  4043. {
  4044. break;
  4045. }
  4046. }
  4047. }
  4048. }
  4049. }
  4050. pAttributes[dwIndex].raaType = raatMinimum;
  4051. pAttributes[dwIndex].dwLength = 0;
  4052. pAttributes[dwIndex].Value = NULL;
  4053. } while( FALSE );
  4054. if ( pConnectInfo != NULL )
  4055. {
  4056. LOCAL_FREE( pConnectInfo );
  4057. }
  4058. if ( dwRetCode != NO_ERROR )
  4059. {
  4060. RasAuthAttributeDestroy( pAttributes );
  4061. return( NULL );
  4062. }
  4063. return( pAttributes );
  4064. }
  4065. //**
  4066. //
  4067. // Call: MakeStopOrInterimAccountingCall
  4068. //
  4069. // Returns: NO_ERROR - Success
  4070. // Non-zero returns - Failure
  4071. //
  4072. // Description:
  4073. //
  4074. VOID
  4075. MakeStopOrInterimAccountingCall(
  4076. IN PCB * pPcb,
  4077. IN BOOL fInterimAccounting
  4078. )
  4079. {
  4080. ULARGE_INTEGER qwCurrentTime;
  4081. ULARGE_INTEGER qwUpTime;
  4082. DWORD dwRemainder;
  4083. DWORD dwActiveTimeInSeconds;
  4084. DWORD dwRetCode;
  4085. BYTE buffer[sizeof(RAS_STATISTICS) + (MAX_STATISTICS * sizeof (ULONG))];
  4086. RAS_STATISTICS * pStats = (RAS_STATISTICS *)buffer;
  4087. DWORD dwSize = sizeof (buffer);
  4088. DWORD dwIndex;
  4089. RAS_AUTH_ATTRIBUTE * pAttribute;
  4090. RAS_AUTH_ATTRIBUTE * pAccountingAttributes;
  4091. LCPCB * pLcpCb = (LCPCB*)(pPcb->LcpCb.pWorkBuf);
  4092. PSTOP_ACCOUNTING_CONTEXT pStopAcctContext = NULL;
  4093. if ( !pLcpCb )
  4094. {
  4095. return;
  4096. }
  4097. if ( pLcpCb->Local.Work.AP == 0 )
  4098. {
  4099. //
  4100. // If the remote side was not authenticated then do not send an
  4101. // accounting request as per RADIUS accounting RFC 2139 sec 5.6.
  4102. //
  4103. RasAuthAttributeDestroy( pPcb->pAccountingAttributes );
  4104. pPcb->pAccountingAttributes = NULL;
  4105. return;
  4106. }
  4107. if ( fInterimAccounting )
  4108. {
  4109. if ( PppConfigInfo.RasAcctProviderInterimAccounting == NULL )
  4110. {
  4111. RasAuthAttributeDestroy( pPcb->pAccountingAttributes );
  4112. pPcb->pAccountingAttributes = NULL;
  4113. return;
  4114. }
  4115. }
  4116. else
  4117. {
  4118. if ( PppConfigInfo.RasAcctProviderStopAccounting == NULL )
  4119. {
  4120. RasAuthAttributeDestroy( pPcb->pAccountingAttributes );
  4121. pPcb->pAccountingAttributes = NULL;
  4122. return;
  4123. }
  4124. }
  4125. //
  4126. // If we have not sent an interim accouting packet then we need to
  4127. // create attributes
  4128. //
  4129. if ( !( pPcb->fFlags & PCBFLAG_INTERIM_ACCT_SENT ) )
  4130. {
  4131. //
  4132. // Find out where the array is terminated and then insert attributes
  4133. //
  4134. for ( dwIndex = 0;
  4135. pPcb->pAccountingAttributes[dwIndex].raaType != raatMinimum;
  4136. dwIndex++ );
  4137. //
  4138. // Undo the NULL termination
  4139. //
  4140. pPcb->pAccountingAttributes[dwIndex].raaType = raatReserved;
  4141. pPcb->pAccountingAttributes[dwIndex].dwLength = 0;
  4142. pPcb->pAccountingAttributes[dwIndex].Value = NULL;
  4143. do
  4144. {
  4145. //
  4146. // Insert session time
  4147. //
  4148. GetSystemTimeAsFileTime( (FILETIME*)&qwCurrentTime );
  4149. if ( ( qwCurrentTime.QuadPart > pPcb->qwActiveTime.QuadPart ) &&
  4150. ( pPcb->qwActiveTime.QuadPart > 0 ) )
  4151. {
  4152. qwUpTime.QuadPart =
  4153. qwCurrentTime.QuadPart - pPcb->qwActiveTime.QuadPart;
  4154. dwActiveTimeInSeconds = RtlEnlargedUnsignedDivide(
  4155. qwUpTime,(DWORD)10000000,&dwRemainder);
  4156. dwRetCode = RasAuthAttributeInsert(
  4157. dwIndex++,
  4158. pPcb->pAccountingAttributes,
  4159. raatAcctSessionTime,
  4160. FALSE,
  4161. 4,
  4162. (PVOID)ULongToPtr(dwActiveTimeInSeconds) );
  4163. if ( dwRetCode != NO_ERROR )
  4164. {
  4165. break;
  4166. }
  4167. }
  4168. //
  4169. // Insert Input and Output bytes and packets
  4170. //
  4171. dwRetCode = RasPortGetStatisticsEx(
  4172. NULL,
  4173. pPcb->hPort,
  4174. (PBYTE)pStats,
  4175. &dwSize);
  4176. if ( dwRetCode == NO_ERROR )
  4177. {
  4178. dwRetCode = RasAuthAttributeInsert(
  4179. dwIndex++,
  4180. pPcb->pAccountingAttributes,
  4181. raatAcctOutputOctets,
  4182. FALSE,
  4183. 4,
  4184. (PVOID)ULongToPtr(pStats->S_Statistics[BYTES_XMITED]));
  4185. if ( dwRetCode != NO_ERROR )
  4186. {
  4187. break;
  4188. }
  4189. dwRetCode = RasAuthAttributeInsert(
  4190. dwIndex++,
  4191. pPcb->pAccountingAttributes,
  4192. raatAcctInputOctets,
  4193. FALSE,
  4194. 4,
  4195. (PVOID)ULongToPtr(pStats->S_Statistics[BYTES_RCVED]));
  4196. if ( dwRetCode != NO_ERROR )
  4197. {
  4198. break;
  4199. }
  4200. dwRetCode = RasAuthAttributeInsert(
  4201. dwIndex++,
  4202. pPcb->pAccountingAttributes,
  4203. raatAcctOutputPackets,
  4204. FALSE,
  4205. 4,
  4206. (PVOID)ULongToPtr(pStats->S_Statistics[FRAMES_XMITED]));
  4207. if ( dwRetCode != NO_ERROR )
  4208. {
  4209. break;
  4210. }
  4211. dwRetCode = RasAuthAttributeInsert(
  4212. dwIndex++,
  4213. pPcb->pAccountingAttributes,
  4214. raatAcctInputPackets,
  4215. FALSE,
  4216. 4,
  4217. (PVOID)ULongToPtr(pStats->S_Statistics[FRAMES_RCVED]));
  4218. if ( dwRetCode != NO_ERROR )
  4219. {
  4220. break;
  4221. }
  4222. }
  4223. } while (FALSE);
  4224. if ( dwRetCode != NO_ERROR )
  4225. {
  4226. RasAuthAttributeDestroy( pPcb->pAccountingAttributes );
  4227. pPcb->pAccountingAttributes = NULL;
  4228. return;
  4229. }
  4230. //
  4231. // Null terminate the array
  4232. //
  4233. pPcb->pAccountingAttributes[dwIndex].raaType = raatMinimum;
  4234. pPcb->pAccountingAttributes[dwIndex].dwLength = 0;
  4235. pPcb->pAccountingAttributes[dwIndex].Value = NULL;
  4236. pPcb->fFlags |= PCBFLAG_INTERIM_ACCT_SENT;
  4237. }
  4238. else
  4239. {
  4240. //
  4241. // Else we need to update session time and other attributes
  4242. //
  4243. GetSystemTimeAsFileTime( (FILETIME*)&qwCurrentTime );
  4244. if ( ( qwCurrentTime.QuadPart > pPcb->qwActiveTime.QuadPart ) &&
  4245. ( pPcb->qwActiveTime.QuadPart > 0 ) )
  4246. {
  4247. qwUpTime.QuadPart =
  4248. qwCurrentTime.QuadPart - pPcb->qwActiveTime.QuadPart;
  4249. dwActiveTimeInSeconds = RtlEnlargedUnsignedDivide(
  4250. qwUpTime,(DWORD)10000000,&dwRemainder);
  4251. pAttribute = RasAuthAttributeGet( raatAcctSessionTime,
  4252. pPcb->pAccountingAttributes );
  4253. if ( pAttribute != NULL )
  4254. {
  4255. pAttribute->Value = (PVOID)ULongToPtr(dwActiveTimeInSeconds);
  4256. }
  4257. }
  4258. //
  4259. // Update Input and Output bytes and packets
  4260. //
  4261. dwRetCode = RasPortGetStatisticsEx( NULL,
  4262. pPcb->hPort,
  4263. (PBYTE)pStats,
  4264. &dwSize);
  4265. if ( dwRetCode == NO_ERROR )
  4266. {
  4267. pAttribute = RasAuthAttributeGet( raatAcctOutputOctets,
  4268. pPcb->pAccountingAttributes );
  4269. if ( pAttribute != NULL )
  4270. {
  4271. pAttribute->Value = (PVOID)(ULongToPtr(pStats->S_Statistics[BYTES_XMITED]));
  4272. }
  4273. pAttribute = RasAuthAttributeGet( raatAcctInputOctets,
  4274. pPcb->pAccountingAttributes );
  4275. if ( pAttribute != NULL )
  4276. {
  4277. pAttribute->Value = (PVOID)(ULongToPtr(pStats->S_Statistics[BYTES_RCVED]));
  4278. }
  4279. pAttribute = RasAuthAttributeGet( raatAcctOutputPackets,
  4280. pPcb->pAccountingAttributes );
  4281. if ( pAttribute != NULL )
  4282. {
  4283. pAttribute->Value = (PVOID)(ULongToPtr(pStats->S_Statistics[FRAMES_XMITED]));
  4284. }
  4285. pAttribute = RasAuthAttributeGet( raatAcctInputPackets,
  4286. pPcb->pAccountingAttributes );
  4287. if ( pAttribute != NULL )
  4288. {
  4289. pAttribute->Value = (PVOID)(ULongToPtr(pStats->S_Statistics[FRAMES_RCVED]));
  4290. }
  4291. }
  4292. }
  4293. pAttribute = RasAuthAttributeGet( raatAcctLinkCount,
  4294. pPcb->pAccountingAttributes );
  4295. if ( pAttribute != NULL )
  4296. {
  4297. pAttribute->Value = (LPVOID)(ULongToPtr(pPcb->pBcb->dwAcctLinkCount));
  4298. }
  4299. pAttribute = RasAuthAttributeGet( raatAcctEventTimeStamp,
  4300. pPcb->pAccountingAttributes );
  4301. //
  4302. // Insert event timestamp attribute
  4303. //
  4304. if ( pAttribute != NULL )
  4305. {
  4306. pAttribute->Value = (LPVOID)ULongToPtr(GetSecondsSince1970());
  4307. }
  4308. if ( !fInterimAccounting )
  4309. {
  4310. DWORD dwTerminateCause = 9;
  4311. //
  4312. // If this is a stop accounting call, then find out where the
  4313. // array is terminated and then insert stop accounting attributes
  4314. //
  4315. for ( dwIndex = 0;
  4316. pPcb->pAccountingAttributes[dwIndex].raaType != raatMinimum;
  4317. dwIndex++ );
  4318. //
  4319. // Undo the NULL termination
  4320. //
  4321. pPcb->pAccountingAttributes[dwIndex].raaType = raatReserved;
  4322. pPcb->pAccountingAttributes[dwIndex].dwLength = 0;
  4323. pPcb->pAccountingAttributes[dwIndex].Value = NULL;
  4324. //
  4325. // Insert termination cause attribute
  4326. //
  4327. if ( pPcb->LcpCb.dwError == ERROR_IDLE_DISCONNECTED )
  4328. {
  4329. dwTerminateCause = 4;
  4330. }
  4331. else if ( pPcb->LcpCb.dwError == ERROR_PPP_SESSION_TIMEOUT )
  4332. {
  4333. dwTerminateCause = 5;
  4334. }
  4335. else if ( pPcb->fFlags & PCBFLAG_SERVICE_UNAVAILABLE )
  4336. {
  4337. dwTerminateCause = 15;
  4338. }
  4339. else if ( pPcb->fFlags & PCBFLAG_DOING_CALLBACK )
  4340. {
  4341. dwTerminateCause = 16;
  4342. }
  4343. else
  4344. {
  4345. RASMAN_INFO RasmanInfo;
  4346. if ( RasGetInfo( NULL, pPcb->hPort, &RasmanInfo ) == NO_ERROR )
  4347. {
  4348. switch( RasmanInfo.RI_DisconnectReason )
  4349. {
  4350. case USER_REQUESTED:
  4351. dwTerminateCause = 6;
  4352. if ( pPcb->fFlags & PCBFLAG_RECVD_TERM_REQ )
  4353. {
  4354. //
  4355. // Even though we brought the line down, it was at the
  4356. // client's request.
  4357. //
  4358. dwTerminateCause = 1;
  4359. }
  4360. break;
  4361. case REMOTE_DISCONNECTION:
  4362. dwTerminateCause = 1;
  4363. break;
  4364. case HARDWARE_FAILURE:
  4365. dwTerminateCause = 8;
  4366. break;
  4367. default:
  4368. break;
  4369. }
  4370. }
  4371. }
  4372. dwRetCode = RasAuthAttributeInsert(
  4373. dwIndex++,
  4374. pPcb->pAccountingAttributes,
  4375. raatAcctTerminateCause,
  4376. FALSE,
  4377. 4,
  4378. (LPVOID)ULongToPtr(dwTerminateCause) );
  4379. pPcb->pAccountingAttributes[dwIndex].raaType = raatMinimum;
  4380. pPcb->pAccountingAttributes[dwIndex].dwLength = 0;
  4381. pPcb->pAccountingAttributes[dwIndex].Value = NULL;
  4382. }
  4383. if ( fInterimAccounting )
  4384. {
  4385. pAccountingAttributes = RasAuthAttributeCopy(
  4386. pPcb->pAccountingAttributes );
  4387. if ( NULL == pAccountingAttributes )
  4388. {
  4389. return;
  4390. }
  4391. }
  4392. else
  4393. {
  4394. pStopAcctContext = (PSTOP_ACCOUNTING_CONTEXT) LocalAlloc ( LPTR, sizeof(STOP_ACCOUNTING_CONTEXT));
  4395. if ( NULL == pStopAcctContext )
  4396. {
  4397. PppLog( 1, "Failed to allocate memory for Stop Accounting Context" );
  4398. return;
  4399. }
  4400. pStopAcctContext->pPcb= pPcb; //actually there is no need to pass the accounting attributes separately
  4401. //need to revisit once this is done.
  4402. pStopAcctContext->pAuthAttributes = pPcb->pAccountingAttributes;
  4403. pAccountingAttributes = pPcb->pAccountingAttributes;
  4404. }
  4405. RtlQueueWorkItem( fInterimAccounting ? InterimAccounting : StopAccounting,
  4406. fInterimAccounting ? (PVOID)pAccountingAttributes : (PVOID)pStopAcctContext,
  4407. WT_EXECUTEDEFAULT );
  4408. }
  4409. //**
  4410. //
  4411. // Call: GetClientInterfaceInfo
  4412. //
  4413. // Returns: NO_ERROR - Success
  4414. // Non-zero returns - Failure
  4415. //
  4416. // Description:
  4417. //
  4418. PBYTE
  4419. GetClientInterfaceInfo(
  4420. IN PCB * pPcb
  4421. )
  4422. {
  4423. HANDLE hAttribute;
  4424. PBYTE pClientInterface = NULL;
  4425. PBYTE pClientInterface2= NULL;
  4426. DWORD dwCount = 0;
  4427. DWORD dwRetCode = NO_ERROR;
  4428. BYTE * pbValue = NULL;
  4429. MIB_IPFORWARDROW * pStaticRoute = NULL;
  4430. MIB_IPFORWARDROW * pStaticRouteSaved= NULL;
  4431. RAS_AUTH_ATTRIBUTE * pStaticRoutes = RasAuthAttributeGetFirst(
  4432. raatFramedRoute,
  4433. pPcb->pAuthenticatorAttributes,
  4434. &hAttribute );
  4435. BYTE * pbFilter = NULL;
  4436. pbFilter = RasAuthAttributeGetConcatVendorSpecific(
  4437. 311,
  4438. 22,
  4439. pPcb->pAuthenticatorAttributes );
  4440. if ( ( pStaticRoutes == NULL ) && ( pbFilter == NULL ) )
  4441. {
  4442. return( NULL );
  4443. }
  4444. if ( pbFilter != NULL )
  4445. {
  4446. dwRetCode = MprInfoDuplicate( pbFilter,
  4447. &pClientInterface );
  4448. LocalFree( pbFilter );
  4449. pbFilter = NULL;
  4450. if ( dwRetCode != NO_ERROR )
  4451. {
  4452. return( NULL );
  4453. }
  4454. }
  4455. if ( pStaticRoutes != NULL )
  4456. {
  4457. if ( pClientInterface == NULL )
  4458. {
  4459. //
  4460. // Allocate header
  4461. //
  4462. dwRetCode = MprInfoCreate(RTR_INFO_BLOCK_VERSION,&pClientInterface);
  4463. if ( dwRetCode != NO_ERROR )
  4464. {
  4465. PppLog( 1, "Failed to allocate memory for static routes" );
  4466. return( NULL );
  4467. }
  4468. }
  4469. //
  4470. // Find out how many routes there are
  4471. //
  4472. for ( dwCount = 0; pStaticRoutes != NULL; dwCount++ )
  4473. {
  4474. pStaticRoutes=RasAuthAttributeGetNext(&hAttribute, raatFramedRoute);
  4475. }
  4476. pStaticRoute = (MIB_IPFORWARDROW*)
  4477. LOCAL_ALLOC( LPTR,
  4478. dwCount * sizeof( MIB_IPFORWARDROW ) );
  4479. pStaticRouteSaved = pStaticRoute;
  4480. if ( pStaticRoute == NULL )
  4481. {
  4482. PppLog( 1, "Failed to allocate memory for static routes" );
  4483. MprInfoDelete( pClientInterface );
  4484. return( NULL );
  4485. }
  4486. for (
  4487. pbValue = NULL,
  4488. pStaticRoutes = RasAuthAttributeGetFirst(
  4489. raatFramedRoute,
  4490. pPcb->pAuthenticatorAttributes,
  4491. &hAttribute );
  4492. pStaticRoutes != NULL;
  4493. pStaticRoute++,
  4494. pStaticRoutes = RasAuthAttributeGetNext( &hAttribute,
  4495. raatFramedRoute ) )
  4496. {
  4497. CHAR * pChar;
  4498. DWORD dwUniqueDigits = 0;
  4499. DWORD dwMask = 0;
  4500. DWORD dwIndex;
  4501. LocalFree( pbValue );
  4502. pbValue = LocalAlloc( LPTR, pStaticRoutes->dwLength + 1 );
  4503. if ( NULL == pbValue )
  4504. {
  4505. PppLog( 1, "Failed to allocate memory for static routes" );
  4506. continue;
  4507. }
  4508. CopyMemory( pbValue, (BYTE *)(pStaticRoutes->Value),
  4509. pStaticRoutes->dwLength );
  4510. pChar = strtok( (CHAR *) pbValue, "/" );
  4511. if ( pChar != NULL )
  4512. {
  4513. pStaticRoute->dwForwardDest = inet_addr( pChar );
  4514. if ( pStaticRoute->dwForwardDest == INADDR_NONE )
  4515. {
  4516. PppLog(1,
  4517. "Ignoring invalid static route - no destination IP");
  4518. continue;
  4519. }
  4520. pChar = strtok( NULL, " " );
  4521. if ( pChar == NULL )
  4522. {
  4523. PppLog( 1, "Ignoring invalid static route - no MASK");
  4524. continue;
  4525. }
  4526. dwUniqueDigits = atoi( pChar );
  4527. if ( dwUniqueDigits > 32 )
  4528. {
  4529. PppLog( 1, "Ignoring invalid static route - invalid MASK");
  4530. continue;
  4531. }
  4532. for ( dwIndex = 0; dwIndex < dwUniqueDigits; dwIndex++ )
  4533. {
  4534. dwMask |= ( 0x80000000 >> dwIndex );
  4535. }
  4536. HostToWireFormat32( dwMask,
  4537. (PBYTE)&(pStaticRoute->dwForwardMask));
  4538. }
  4539. else
  4540. {
  4541. pChar = strtok( (CHAR *) pbValue, " " );
  4542. if ( pChar == NULL )
  4543. {
  4544. PppLog(1,
  4545. "Ignoring invalid static route - no destination IP");
  4546. continue;
  4547. }
  4548. else
  4549. {
  4550. pStaticRoute->dwForwardDest = inet_addr( pChar );
  4551. pStaticRoute->dwForwardMask = GetClassMask(
  4552. pStaticRoute->dwForwardDest );
  4553. }
  4554. }
  4555. pChar = strtok( NULL, " " );
  4556. if ( pChar == NULL )
  4557. {
  4558. PppLog( 1, "Ignoring invalid static route - no next hop IP");
  4559. continue;
  4560. }
  4561. pStaticRoute->dwForwardNextHop = inet_addr( pChar );
  4562. if ( pStaticRoute->dwForwardDest == INADDR_NONE )
  4563. {
  4564. PppLog(1,"Ignoring invalid static route - invalid nexthop IP");
  4565. continue;
  4566. }
  4567. pChar = strtok( NULL, " " );
  4568. if ( pChar != NULL )
  4569. {
  4570. pStaticRoute->dwForwardMetric1 = atoi( pChar );
  4571. }
  4572. pChar = strtok( NULL, " " );
  4573. if ( pChar != NULL )
  4574. {
  4575. pStaticRoute->dwForwardMetric2 = atoi( pChar );
  4576. }
  4577. pChar = strtok( NULL, " " );
  4578. if ( pChar != NULL )
  4579. {
  4580. pStaticRoute->dwForwardMetric3 = atoi( pChar );
  4581. }
  4582. pChar = strtok( NULL, " " );
  4583. if ( pChar != NULL )
  4584. {
  4585. pStaticRoute->dwForwardMetric4 = atoi( pChar );
  4586. }
  4587. pChar = strtok( NULL, " " );
  4588. if ( pChar != NULL )
  4589. {
  4590. pStaticRoute->dwForwardMetric5 = atoi( pChar );
  4591. }
  4592. }
  4593. LocalFree( pbValue );
  4594. dwRetCode = MprInfoBlockAdd( pClientInterface,
  4595. IP_ROUTE_INFO,
  4596. sizeof( MIB_IPFORWARDROW ),
  4597. dwCount,
  4598. (PBYTE)pStaticRouteSaved,
  4599. &pClientInterface2 );
  4600. MprInfoDelete( pClientInterface );
  4601. if ( dwRetCode != NO_ERROR )
  4602. {
  4603. PppLog( 1, "MprInfoBlockAdd failed and returned %d", dwRetCode );
  4604. LOCAL_FREE( pStaticRouteSaved );
  4605. return( NULL );
  4606. }
  4607. else
  4608. {
  4609. pClientInterface = pClientInterface2;
  4610. }
  4611. LOCAL_FREE( pStaticRouteSaved );
  4612. }
  4613. return( pClientInterface );
  4614. }
  4615. //**
  4616. //
  4617. // Call: LoadParserDll
  4618. //
  4619. // Returns: VOID
  4620. //
  4621. // Description: Loads the parser DLL with the entry points PacketFromPeer,
  4622. // PacketToPeer, and PacketFree.
  4623. //
  4624. VOID
  4625. LoadParserDll(
  4626. IN HKEY hKeyPpp
  4627. )
  4628. {
  4629. LONG lRet;
  4630. DWORD dwType;
  4631. DWORD dwSize;
  4632. CHAR* pszPath = NULL;
  4633. CHAR* pszExpandedPath = NULL;
  4634. HINSTANCE hInstance = NULL;
  4635. FARPROC pPacketFromPeer;
  4636. FARPROC pPacketToPeer;
  4637. FARPROC pPacketFree;
  4638. BOOL fUnloadDLL = TRUE;
  4639. //
  4640. // Find how big the path is
  4641. //
  4642. dwSize = 0;
  4643. lRet = RegQueryValueExA(
  4644. hKeyPpp,
  4645. RAS_VALUENAME_PARSEDLLPATH,
  4646. NULL,
  4647. &dwType,
  4648. NULL,
  4649. &dwSize
  4650. );
  4651. if (ERROR_SUCCESS != lRet)
  4652. {
  4653. goto LDone;
  4654. }
  4655. if ( (REG_EXPAND_SZ != dwType)
  4656. && (REG_SZ != dwType))
  4657. {
  4658. goto LDone;
  4659. }
  4660. pszPath = LOCAL_ALLOC(LPTR, dwSize);
  4661. if (NULL == pszPath)
  4662. {
  4663. goto LDone;
  4664. }
  4665. //
  4666. // Read the path
  4667. //
  4668. lRet = RegQueryValueExA(
  4669. hKeyPpp,
  4670. RAS_VALUENAME_PARSEDLLPATH,
  4671. NULL,
  4672. &dwType,
  4673. pszPath,
  4674. &dwSize
  4675. );
  4676. if (ERROR_SUCCESS != lRet)
  4677. {
  4678. goto LDone;
  4679. }
  4680. //
  4681. // Replace the %SystemRoot% with the actual path.
  4682. //
  4683. dwSize = ExpandEnvironmentStringsA(pszPath, NULL, 0);
  4684. if (0 == dwSize)
  4685. {
  4686. goto LDone;
  4687. }
  4688. pszExpandedPath = LOCAL_ALLOC(LPTR, dwSize);
  4689. if (NULL == pszExpandedPath)
  4690. {
  4691. goto LDone;
  4692. }
  4693. dwSize = ExpandEnvironmentStringsA(
  4694. pszPath,
  4695. pszExpandedPath,
  4696. dwSize );
  4697. if (0 == dwSize)
  4698. {
  4699. goto LDone;
  4700. }
  4701. if ( (NULL != PppConfigInfo.pszParserDllPath)
  4702. && (!strcmp(pszExpandedPath, PppConfigInfo.pszParserDllPath)))
  4703. {
  4704. //
  4705. // The DLL is already loaded
  4706. //
  4707. fUnloadDLL = FALSE;
  4708. goto LDone;
  4709. }
  4710. hInstance = LoadLibraryA(pszExpandedPath);
  4711. if (NULL == hInstance)
  4712. {
  4713. goto LDone;
  4714. }
  4715. fUnloadDLL = FALSE;
  4716. pPacketFromPeer = GetProcAddress(hInstance, "PacketFromPeer");
  4717. pPacketToPeer = GetProcAddress(hInstance, "PacketToPeer");
  4718. pPacketFree = GetProcAddress(hInstance, "PacketFree");
  4719. FreeLibrary(PppConfigInfo.hInstanceParserDll);
  4720. PppConfigInfo.hInstanceParserDll = hInstance;
  4721. hInstance = NULL;
  4722. if (NULL != PppConfigInfo.pszParserDllPath)
  4723. {
  4724. LOCAL_FREE(PppConfigInfo.pszParserDllPath);
  4725. }
  4726. PppConfigInfo.pszParserDllPath = pszExpandedPath;
  4727. pszExpandedPath = NULL;
  4728. PppConfigInfo.PacketFromPeer =
  4729. (VOID(*)(HANDLE, BYTE*, DWORD, BYTE**, DWORD*)) pPacketFromPeer;
  4730. PppConfigInfo.PacketToPeer =
  4731. (VOID(*)(HANDLE, BYTE*, DWORD, BYTE**, DWORD*)) pPacketToPeer;
  4732. PppConfigInfo.PacketFree =
  4733. (VOID(*)(BYTE*)) pPacketFree;
  4734. LDone:
  4735. if (NULL != pszPath)
  4736. {
  4737. LOCAL_FREE(pszPath);
  4738. }
  4739. if (NULL != pszExpandedPath)
  4740. {
  4741. LOCAL_FREE(pszExpandedPath);
  4742. }
  4743. if (NULL != hInstance)
  4744. {
  4745. FreeLibrary(hInstance);
  4746. }
  4747. if (fUnloadDLL)
  4748. {
  4749. FreeLibrary(PppConfigInfo.hInstanceParserDll);
  4750. PppConfigInfo.hInstanceParserDll = NULL;
  4751. if (NULL != PppConfigInfo.pszParserDllPath)
  4752. {
  4753. LOCAL_FREE(PppConfigInfo.pszParserDllPath);
  4754. }
  4755. PppConfigInfo.pszParserDllPath = NULL;
  4756. PppConfigInfo.PacketFromPeer = NULL;
  4757. PppConfigInfo.PacketToPeer = NULL;
  4758. PppConfigInfo.PacketFree = NULL;
  4759. }
  4760. }
  4761. //**
  4762. //
  4763. // Call: PortSendOrDisconnect
  4764. //
  4765. // Returns: NO_ERROR - Success
  4766. // Non-zero returns - Failure
  4767. //
  4768. // Description:
  4769. //
  4770. DWORD
  4771. PortSendOrDisconnect(
  4772. IN PCB * pPcb,
  4773. IN DWORD cbPacket
  4774. )
  4775. {
  4776. DWORD dwRetCode;
  4777. BYTE* pData = NULL;
  4778. DWORD dwSize = 0;
  4779. BOOL fBufferReceivedFromParser = FALSE;
  4780. if ( NULL != PppConfigInfo.PacketToPeer )
  4781. {
  4782. PppConfigInfo.PacketToPeer(
  4783. pPcb->hPort,
  4784. (BYTE*)(pPcb->pSendBuf),
  4785. cbPacket,
  4786. &pData,
  4787. &dwSize );
  4788. }
  4789. if ( NULL == pData )
  4790. {
  4791. pData = (BYTE*)(pPcb->pSendBuf);
  4792. dwSize = cbPacket;
  4793. }
  4794. else
  4795. {
  4796. fBufferReceivedFromParser = TRUE;
  4797. }
  4798. dwRetCode = RasPortSend( pPcb->hPort,
  4799. pData,
  4800. dwSize );
  4801. if ( NO_ERROR != dwRetCode )
  4802. {
  4803. PppLog( 1, "RasPortSend on port %d failed: %d",
  4804. pPcb->hPort, dwRetCode );
  4805. pPcb->LcpCb.dwError = dwRetCode;
  4806. pPcb->fFlags |= PCBFLAG_STOPPED_MSG_SENT;
  4807. NotifyCaller( pPcb,
  4808. ( pPcb->fFlags & PCBFLAG_IS_SERVER )
  4809. ? PPPDDMMSG_Stopped
  4810. : PPPMSG_Stopped,
  4811. &(pPcb->LcpCb.dwError) );
  4812. }
  4813. if ( fBufferReceivedFromParser )
  4814. {
  4815. PPP_ASSERT( NULL != PppConfigInfo.PacketFree );
  4816. PppConfigInfo.PacketFree( pData );
  4817. }
  4818. return( dwRetCode );
  4819. }
  4820. //**
  4821. //
  4822. // Call: ReceiveViaParser
  4823. //
  4824. // Returns: VOID
  4825. //
  4826. // Description:
  4827. //
  4828. VOID
  4829. ReceiveViaParser(
  4830. IN PCB * pPcb,
  4831. IN PPP_PACKET * pPacket,
  4832. IN DWORD dwPacketLength
  4833. )
  4834. {
  4835. BYTE* pData = NULL;
  4836. DWORD dwSize = 0;
  4837. BOOL fBufferReceivedFromParser = FALSE;
  4838. if ( NULL != PppConfigInfo.PacketFromPeer )
  4839. {
  4840. PppConfigInfo.PacketFromPeer(
  4841. pPcb->hPort,
  4842. (BYTE*)pPacket,
  4843. dwPacketLength,
  4844. &pData,
  4845. &dwSize );
  4846. }
  4847. if ( NULL == pData )
  4848. {
  4849. pData = (BYTE*)pPacket;
  4850. dwSize = dwPacketLength;
  4851. }
  4852. else
  4853. {
  4854. fBufferReceivedFromParser = TRUE;
  4855. }
  4856. FsmReceive( pPcb, (PPP_PACKET*) pData, dwSize );
  4857. if ( fBufferReceivedFromParser )
  4858. {
  4859. PPP_ASSERT( NULL != PppConfigInfo.PacketFree );
  4860. PppConfigInfo.PacketFree( pData );
  4861. }
  4862. }
  4863. //**
  4864. //
  4865. // Call: GetSecondsSince1970
  4866. //
  4867. // Returns: NO_ERROR - Success
  4868. // Non-zero returns - Failure
  4869. //
  4870. // Description:
  4871. //
  4872. DWORD
  4873. GetSecondsSince1970(
  4874. VOID
  4875. )
  4876. {
  4877. SYSTEMTIME LocalTime;
  4878. TIME_FIELDS LocalTimeFields;
  4879. LARGE_INTEGER TempTime;
  4880. LARGE_INTEGER SystemTime;
  4881. DWORD RetTime;
  4882. GetLocalTime( &LocalTime );
  4883. LocalTimeFields.Year = LocalTime.wYear;
  4884. LocalTimeFields.Month = LocalTime.wMonth;
  4885. LocalTimeFields.Day = LocalTime.wDay;
  4886. LocalTimeFields.Hour = LocalTime.wHour;
  4887. LocalTimeFields.Minute = LocalTime.wMinute;
  4888. LocalTimeFields.Second = LocalTime.wSecond;
  4889. LocalTimeFields.Milliseconds = LocalTime.wMilliseconds;
  4890. LocalTimeFields.Weekday = LocalTime.wDayOfWeek;
  4891. RtlTimeFieldsToTime(&LocalTimeFields, &TempTime);
  4892. RtlLocalTimeToSystemTime(&TempTime, &SystemTime);
  4893. RtlTimeToSecondsSince1970(&SystemTime, &RetTime);
  4894. return( RetTime );
  4895. }
  4896. //**
  4897. //
  4898. // Call: IsPschedRunning
  4899. //
  4900. // Returns: TRUE iff Psched is running
  4901. //
  4902. // Description:
  4903. //
  4904. BOOL
  4905. IsPschedRunning(
  4906. VOID
  4907. )
  4908. {
  4909. SC_HANDLE hCont = NULL;
  4910. SC_HANDLE hSched = NULL;
  4911. DWORD dwErr = NO_ERROR;
  4912. SERVICE_STATUS Status;
  4913. BOOL fRet = FALSE;
  4914. //
  4915. // Initialize
  4916. //
  4917. ZeroMemory( &Status, sizeof(Status) );
  4918. do
  4919. {
  4920. hCont = OpenSCManager( NULL, NULL, GENERIC_READ );
  4921. if ( hCont == NULL )
  4922. {
  4923. dwErr = GetLastError();
  4924. PppLog( 1, "OpenSCManager failed: %d", dwErr );
  4925. break;
  4926. }
  4927. hSched = OpenService( hCont, TEXT("psched"), SERVICE_QUERY_STATUS );
  4928. if ( hSched == NULL )
  4929. {
  4930. dwErr = GetLastError();
  4931. PppLog( 1, "OpenService failed: %d", dwErr );
  4932. break;
  4933. }
  4934. if ( !QueryServiceStatus( hSched, &Status ))
  4935. {
  4936. dwErr = GetLastError();
  4937. PppLog( 1, "QueryServiceStatus failed: %d", dwErr );
  4938. break;
  4939. }
  4940. fRet = ( Status.dwCurrentState == SERVICE_RUNNING );
  4941. } while ( FALSE );
  4942. //
  4943. // Cleanup
  4944. //
  4945. if ( hSched )
  4946. {
  4947. CloseServiceHandle( hSched );
  4948. }
  4949. if ( hCont )
  4950. {
  4951. CloseServiceHandle( hCont );
  4952. }
  4953. return( fRet );
  4954. }
  4955. //**
  4956. //
  4957. // Call: LogPPPPacket
  4958. //
  4959. // Returns: None
  4960. //
  4961. // Description:
  4962. //
  4963. VOID
  4964. LogPPPPacket(
  4965. IN BOOL fReceived,
  4966. IN PCB * pPcb,
  4967. IN PPP_PACKET * pPacket,
  4968. IN DWORD cbPacket
  4969. )
  4970. {
  4971. SYSTEMTIME SystemTime;
  4972. CHAR * pchProtocol;
  4973. CHAR * pchType;
  4974. BYTE Id = 0;
  4975. BYTE bCode;
  4976. DWORD cbTracePacketSize = cbPacket;
  4977. DWORD dwUnknownPacketTraceSize;
  4978. BOOL fPrint = TRUE;
  4979. dwUnknownPacketTraceSize = PppConfigInfo.dwUnknownPacketTraceSize;
  4980. GetSystemTime( &SystemTime );
  4981. if ( cbPacket > PPP_CONFIG_HDR_LEN )
  4982. {
  4983. bCode = *(((CHAR*)pPacket)+PPP_PACKET_HDR_LEN);
  4984. if ( ( bCode == 0 ) || ( bCode > TIME_REMAINING ) )
  4985. {
  4986. pchType = "UNKNOWN";
  4987. }
  4988. else
  4989. {
  4990. pchType = FsmCodes[ bCode ];
  4991. }
  4992. Id = *(((CHAR*)pPacket)+PPP_PACKET_HDR_LEN+1);
  4993. }
  4994. else
  4995. {
  4996. pchType = "UNKNOWN";
  4997. }
  4998. if ( cbPacket > PPP_PACKET_HDR_LEN )
  4999. {
  5000. switch( WireToHostFormat16( (CHAR*)pPacket ) )
  5001. {
  5002. case PPP_LCP_PROTOCOL:
  5003. pchProtocol = "LCP";
  5004. break;
  5005. case PPP_BACP_PROTOCOL:
  5006. pchProtocol = "BACP";
  5007. break;
  5008. case PPP_BAP_PROTOCOL:
  5009. pchProtocol = "BAP";
  5010. pchType = "Protocol specific";
  5011. break;
  5012. case PPP_PAP_PROTOCOL:
  5013. pchProtocol = "PAP";
  5014. pchType = "Protocol specific";
  5015. fPrint = FALSE;
  5016. break;
  5017. case PPP_CBCP_PROTOCOL:
  5018. pchProtocol = "CBCP";
  5019. pchType = "Protocol specific";
  5020. break;
  5021. case PPP_CHAP_PROTOCOL:
  5022. pchProtocol = "CHAP";
  5023. pchType = "Protocol specific";
  5024. break;
  5025. case PPP_IPCP_PROTOCOL:
  5026. pchProtocol = "IPCP";
  5027. break;
  5028. case PPP_ATCP_PROTOCOL:
  5029. pchProtocol = "ATCP";
  5030. break;
  5031. case PPP_IPXCP_PROTOCOL:
  5032. pchProtocol = "IPXCP";
  5033. break;
  5034. case PPP_NBFCP_PROTOCOL:
  5035. pchProtocol = "NBFCP";
  5036. break;
  5037. case PPP_CCP_PROTOCOL:
  5038. pchProtocol = "CCP";
  5039. break;
  5040. case PPP_EAP_PROTOCOL:
  5041. pchProtocol = "EAP";
  5042. pchType = "Protocol specific";
  5043. if ( cbTracePacketSize > dwUnknownPacketTraceSize )
  5044. {
  5045. cbTracePacketSize = dwUnknownPacketTraceSize;
  5046. }
  5047. break;
  5048. case PPP_SPAP_NEW_PROTOCOL:
  5049. pchProtocol = "SHIVA PAP";
  5050. pchType = "Protocol specific";
  5051. break;
  5052. default:
  5053. pchProtocol = "UNKNOWN";
  5054. if ( cbTracePacketSize > dwUnknownPacketTraceSize )
  5055. {
  5056. cbTracePacketSize = dwUnknownPacketTraceSize;
  5057. }
  5058. break;
  5059. }
  5060. }
  5061. else
  5062. {
  5063. pchProtocol = "UNKNOWN";
  5064. }
  5065. PppLog( 1, "%sPPP packet %s at %0*d/%0*d/%0*d %0*d:%0*d:%0*d:%0*d",
  5066. fReceived ? ">" : "<", fReceived ? "received" : "sent",
  5067. 2, SystemTime.wMonth,
  5068. 2, SystemTime.wDay,
  5069. 2, SystemTime.wYear,
  5070. 2, SystemTime.wHour,
  5071. 2, SystemTime.wMinute,
  5072. 2, SystemTime.wSecond,
  5073. 3, SystemTime.wMilliseconds );
  5074. PppLog(1,
  5075. "%sProtocol = %s, Type = %s, Length = 0x%x, Id = 0x%x, Port = %d",
  5076. fReceived ? ">" : "<", pchProtocol, pchType, cbPacket, Id,
  5077. pPcb->hPort );
  5078. if ( fPrint )
  5079. {
  5080. TraceDumpExA( PppConfigInfo.dwTraceId,
  5081. TRACE_LEVEL_1 | TRACE_USE_MSEC,
  5082. (CHAR*)pPacket,
  5083. cbTracePacketSize,
  5084. 1,
  5085. FALSE,
  5086. fReceived ? ">" : "<" );
  5087. }
  5088. PppLog(1," " );
  5089. }
  5090. //**
  5091. //
  5092. // Call: PppLog
  5093. //
  5094. // Returns: None
  5095. //
  5096. // Description: Will print to the PPP logfile
  5097. //
  5098. VOID
  5099. PppLog(
  5100. IN DWORD DbgLevel,
  5101. ...
  5102. )
  5103. {
  5104. va_list arglist;
  5105. CHAR *Format;
  5106. char OutputBuffer[1024];
  5107. va_start( arglist, DbgLevel );
  5108. Format = va_arg( arglist, CHAR* );
  5109. vsprintf( OutputBuffer, Format, arglist );
  5110. va_end( arglist );
  5111. TracePutsExA( PppConfigInfo.dwTraceId,
  5112. (( DbgLevel == 1 ) ? TRACE_LEVEL_1 : TRACE_LEVEL_2 )
  5113. | TRACE_USE_MSEC, OutputBuffer );
  5114. }
  5115. #ifdef MEM_LEAK_CHECK
  5116. LPVOID
  5117. DebugAlloc( DWORD Flags, DWORD dwSize )
  5118. {
  5119. DWORD Index;
  5120. LPBYTE pMem = (LPBYTE)HeapAlloc( PppConfigInfo.hHeap,
  5121. HEAP_ZERO_MEMORY,dwSize+8);
  5122. if ( pMem == NULL )
  5123. return( pMem );
  5124. for( Index=0; Index < PPP_MEM_TABLE_SIZE; Index++ )
  5125. {
  5126. if ( PppMemTable[Index] == NULL )
  5127. {
  5128. PppMemTable[Index] = pMem;
  5129. break;
  5130. }
  5131. }
  5132. PPP_ASSERT( Index != PPP_MEM_TABLE_SIZE );
  5133. return( (LPVOID)pMem );
  5134. }
  5135. BOOL
  5136. DebugFree( PVOID pMem )
  5137. {
  5138. DWORD Index;
  5139. for( Index=0; Index < PPP_MEM_TABLE_SIZE; Index++ )
  5140. {
  5141. if ( PppMemTable[Index] == pMem )
  5142. {
  5143. PppMemTable[Index] = NULL;
  5144. break;
  5145. }
  5146. }
  5147. ASSERT( Index != PPP_MEM_TABLE_SIZE );
  5148. return( HeapFree( PppConfigInfo.hHeap, 0, pMem ) );
  5149. }
  5150. LPVOID
  5151. DebugReAlloc( PVOID pMem, DWORD dwSize )
  5152. {
  5153. DWORD Index;
  5154. if ( pMem == NULL )
  5155. {
  5156. PPP_ASSERT(FALSE);
  5157. }
  5158. for( Index=0; Index < PPP_MEM_TABLE_SIZE; Index++ )
  5159. {
  5160. if ( PppMemTable[Index] == pMem )
  5161. {
  5162. PppMemTable[Index] = HeapReAlloc( PppConfigInfo.hHeap,
  5163. HEAP_ZERO_MEMORY,
  5164. pMem, dwSize );
  5165. pMem = PppMemTable[Index];
  5166. break;
  5167. }
  5168. }
  5169. PPP_ASSERT( Index != PPP_MEM_TABLE_SIZE );
  5170. return( (LPVOID)pMem );
  5171. }
  5172. #endif