Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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