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.

642 lines
18 KiB

  1. /********************************************************************/
  2. /* Copyright(c) 1992 Microsoft Corporation */
  3. /********************************************************************/
  4. //***
  5. //
  6. // Filename: rasmanif.c
  7. //
  8. // Description: This module contains the i/f procedures with the
  9. // RasManager
  10. //
  11. // Author: Stefan Solomon (stefans) May 26, 1992.
  12. //
  13. // Revision History:
  14. //
  15. //***
  16. #include "ddm.h"
  17. #include "util.h"
  18. #include "objects.h"
  19. #include <raserror.h>
  20. #include <ddmif.h>
  21. #include <string.h>
  22. #include <rasmxs.h>
  23. #include "rasmanif.h"
  24. #include "handlers.h"
  25. //***
  26. //
  27. // Function: RmInit
  28. //
  29. // Description: Called only at service start time.
  30. // Does RasPortEnum, allocates global memory for the
  31. // Device Table, opens every dialin port and copies the port
  32. // handle and port name into the dcb struct.
  33. // Finally, deallocates the buffers (for port enum) and returns.
  34. //
  35. // Returns: NO_ERROR - Success
  36. // otherwise - Failure
  37. //
  38. //***
  39. DWORD
  40. RmInit(
  41. OUT BOOL * pfWANDeviceInstalled
  42. )
  43. {
  44. DWORD dwIndex;
  45. DWORD dwRetCode;
  46. HPORT hPort;
  47. PDEVICE_OBJECT pDevObj;
  48. BYTE * pBuffer = NULL;
  49. DWORD dwBufferSize = 0;
  50. DWORD dwNumEntries = 0;
  51. RASMAN_PORT* pRasmanPort;
  52. *pfWANDeviceInstalled = FALSE;
  53. do
  54. {
  55. //
  56. // get the buffer size needed for RasPortEnum
  57. //
  58. dwRetCode = RasPortEnum( NULL, NULL, &dwBufferSize, &dwNumEntries );
  59. if ( dwRetCode == ERROR_BUFFER_TOO_SMALL )
  60. {
  61. //
  62. // If there are ports installed, allocate buffer to get them
  63. //
  64. if (( pBuffer = (BYTE *)LOCAL_ALLOC( LPTR, dwBufferSize ) ) == NULL)
  65. {
  66. //
  67. // can't allocate the enum buffer
  68. //
  69. dwRetCode = GetLastError();
  70. DDMLogError( ROUTERLOG_NOT_ENOUGH_MEMORY, 0, NULL, dwRetCode);
  71. break;
  72. }
  73. //
  74. // get the real enum data
  75. //
  76. dwRetCode = RasPortEnum( NULL,
  77. pBuffer,
  78. &dwBufferSize,
  79. &dwNumEntries );
  80. if ( dwRetCode != NO_ERROR )
  81. {
  82. //
  83. // can't enumerate ports
  84. //
  85. DDMLogErrorString(ROUTERLOG_CANT_ENUM_PORTS,0,NULL,dwRetCode,0);
  86. break;
  87. }
  88. }
  89. else if ( dwRetCode == NO_ERROR )
  90. {
  91. //
  92. // Otherwise there were no ports installed
  93. //
  94. dwNumEntries = 0;
  95. }
  96. else
  97. {
  98. DDMLogErrorString(ROUTERLOG_CANT_ENUM_PORTS,0,NULL,dwRetCode,0);
  99. break;
  100. }
  101. //
  102. // Allocate device hash table
  103. //
  104. if ( dwNumEntries < MIN_DEVICE_TABLE_SIZE )
  105. {
  106. gblDeviceTable.NumDeviceBuckets = MIN_DEVICE_TABLE_SIZE;
  107. }
  108. else if ( dwNumEntries > MAX_DEVICE_TABLE_SIZE )
  109. {
  110. gblDeviceTable.NumDeviceBuckets = MAX_DEVICE_TABLE_SIZE;
  111. }
  112. else
  113. {
  114. gblDeviceTable.NumDeviceBuckets = dwNumEntries;
  115. }
  116. gblDeviceTable.DeviceBucket = (PDEVICE_OBJECT *)LOCAL_ALLOC( LPTR,
  117. gblDeviceTable.NumDeviceBuckets
  118. * sizeof( PDEVICE_OBJECT ) );
  119. if ( gblDeviceTable.DeviceBucket == (PDEVICE_OBJECT *)NULL )
  120. {
  121. dwRetCode = GetLastError();
  122. DDMLogError( ROUTERLOG_NOT_ENOUGH_MEMORY, 0, NULL, dwRetCode);
  123. break;
  124. }
  125. //
  126. // Set number of connection buckets to number of device buckets.
  127. // Since Number of devices >= Number of connections.
  128. //
  129. gblDeviceTable.NumConnectionBuckets = gblDeviceTable.NumDeviceBuckets;
  130. //
  131. // Allocate bundle or connection table
  132. //
  133. gblDeviceTable.ConnectionBucket = (PCONNECTION_OBJECT*)LOCAL_ALLOC(LPTR,
  134. gblDeviceTable.NumConnectionBuckets
  135. * sizeof( PCONNECTION_OBJECT ) );
  136. if ( gblDeviceTable.ConnectionBucket == (PCONNECTION_OBJECT *)NULL )
  137. {
  138. dwRetCode = GetLastError();
  139. DDMLogError(ROUTERLOG_NOT_ENOUGH_MEMORY, 0, NULL, dwRetCode);
  140. break;
  141. }
  142. //
  143. // For each device object, try to open the port.
  144. // If port can't be opened, skip and go to next port.
  145. //
  146. for ( dwIndex = 0, pRasmanPort = (RASMAN_PORT *)pBuffer;
  147. dwIndex < dwNumEntries;
  148. dwIndex++, pRasmanPort++)
  149. {
  150. //
  151. // only ports enabled for incoming or router connections
  152. // are added to the device table
  153. //
  154. if (pRasmanPort->P_ConfiguredUsage &
  155. (CALL_IN | CALL_ROUTER | CALL_IN_ONLY |
  156. CALL_OUTBOUND_ROUTER))
  157. {
  158. dwRetCode = RasPortOpen(pRasmanPort->P_PortName, &hPort, NULL);
  159. if ( dwRetCode != NO_ERROR )
  160. {
  161. //
  162. // Failed to open an port on which incoming
  163. // connections are enabled. Log an error and
  164. // continue to the next port
  165. //
  166. WCHAR wchPortName[MAX_PORT_NAME+1];
  167. LPWSTR lpwsAuditStr[1];
  168. MultiByteToWideChar( CP_ACP,
  169. 0,
  170. pRasmanPort->P_PortName,
  171. -1,
  172. wchPortName,
  173. MAX_PORT_NAME+1 );
  174. //
  175. // Log an error
  176. //
  177. lpwsAuditStr[0] = wchPortName;
  178. DDMLogErrorString( ROUTERLOG_UNABLE_TO_OPEN_PORT, 1,
  179. lpwsAuditStr, dwRetCode, 1 );
  180. dwRetCode = NO_ERROR;
  181. continue;
  182. }
  183. //
  184. // Don't insert the device into the hash table if the device
  185. // doesn't support incoming/router calls.
  186. //
  187. // Note:
  188. // Per DCR 349087 we need to enable outbound-only DoD on
  189. // PPPoE connections. These ports are identified as
  190. // having usage CALL_OUTBOUND_ROUTER.
  191. //
  192. if ((pRasmanPort->P_ConfiguredUsage &
  193. (CALL_IN | CALL_ROUTER | CALL_OUTBOUND_ROUTER)))
  194. {
  195. pDevObj = DeviceObjAllocAndInitialize( hPort, pRasmanPort );
  196. if ( pDevObj == (DEVICE_OBJECT *)NULL )
  197. {
  198. dwRetCode = GetLastError();
  199. DDMLogError(ROUTERLOG_NOT_ENOUGH_MEMORY,0,
  200. NULL,dwRetCode);
  201. break;
  202. }
  203. //
  204. // Insert into the device hash table
  205. //
  206. DeviceObjInsertInTable( pDevObj );
  207. if (RAS_DEVICE_CLASS( pDevObj->dwDeviceType ) != RDT_Direct)
  208. {
  209. *pfWANDeviceInstalled = TRUE;
  210. }
  211. }
  212. }
  213. }
  214. } while ( FALSE );
  215. if ( pBuffer != NULL )
  216. {
  217. LOCAL_FREE( pBuffer );
  218. }
  219. return( dwRetCode );
  220. }
  221. //***
  222. //
  223. // Function: RmReceiveFrame
  224. //
  225. // Descr:
  226. //
  227. //***
  228. DWORD
  229. RmReceiveFrame(
  230. IN PDEVICE_OBJECT pDevObj
  231. )
  232. {
  233. DWORD dwRetCode;
  234. DWORD dwBucketIndex = DeviceObjHashPortToBucket( pDevObj->hPort );
  235. RTASSERT( pDevObj->pRasmanRecvBuffer != NULL );
  236. dwRetCode = RasPortReceive(
  237. pDevObj->hPort,
  238. pDevObj->pRasmanRecvBuffer ,
  239. &(pDevObj->dwRecvBufferLen),
  240. 0L, //no timeout
  241. gblSupervisorEvents[NUM_DDM_EVENTS
  242. + gblDeviceTable.NumDeviceBuckets
  243. + dwBucketIndex] );
  244. if ( ( dwRetCode == NO_ERROR ) || ( dwRetCode == PENDING ) )
  245. {
  246. pDevObj->fFlags |= DEV_OBJ_RECEIVE_ACTIVE;
  247. dwRetCode = NO_ERROR;
  248. }
  249. return( dwRetCode );
  250. }
  251. //***
  252. //
  253. // Function: RmListen
  254. //
  255. // Descr:
  256. //
  257. //***
  258. DWORD
  259. RmListen(
  260. IN PDEVICE_OBJECT pDevObj
  261. )
  262. {
  263. DWORD dwRetCode = NO_ERROR;
  264. DWORD dwBucketIndex = DeviceObjHashPortToBucket( pDevObj->hPort );
  265. //RTASSERT(pDevObj->ConnectionState == DISCONNECTED);
  266. //
  267. // If this is an L2TP tunnel port type and we have to use
  268. // IPSEC, then go ahead and set the filter
  269. //
  270. if ( RAS_DEVICE_TYPE( pDevObj->dwDeviceType ) == RDT_Tunnel_L2tp )
  271. {
  272. dwRetCode = RasEnableIpSec(
  273. pDevObj->hPort,
  274. TRUE,
  275. TRUE,
  276. (gblDDMConfigInfo.dwServerFlags & PPPCFG_RequireIPSEC)
  277. ? RAS_L2TP_REQUIRE_ENCRYPTION
  278. : RAS_L2TP_OPTIONAL_ENCRYPTION);
  279. // RTASSERT( dwRetCode == NO_ERROR );
  280. DDMTRACE2( "Enabled IPSec on port %d, dwRetCode = %d",
  281. pDevObj->hPort, dwRetCode );
  282. //
  283. // Log the non certificate errorlog only once
  284. //
  285. if ( dwRetCode == ERROR_NO_CERTIFICATE )
  286. {
  287. if ( !( gblDDMConfigInfo.fFlags & DDM_NO_CERTIFICATE_LOGGED ) )
  288. {
  289. DDMLogWarning( ROUTERLOG_NO_IPSEC_CERT, 0, NULL );
  290. gblDDMConfigInfo.fFlags |= DDM_NO_CERTIFICATE_LOGGED;
  291. }
  292. return( dwRetCode );
  293. }
  294. if( (dwRetCode != NO_ERROR)
  295. && !(pDevObj->fFlags & DEV_OBJ_IPSEC_ERROR_LOGGED))
  296. {
  297. WCHAR wchPortName[MAX_PORT_NAME+1];
  298. LPWSTR lpwsAuditStr[1];
  299. RASMAN_INFO rInfo;
  300. DWORD rc;
  301. ZeroMemory(&rInfo, sizeof(RASMAN_INFO));
  302. rc = RasGetInfo(NULL, pDevObj->hPort, &rInfo);
  303. if(rc != NO_ERROR)
  304. {
  305. return (NO_ERROR);
  306. }
  307. MultiByteToWideChar( CP_ACP,
  308. 0,
  309. rInfo.RI_szPortName,
  310. -1,
  311. wchPortName,
  312. MAX_PORT_NAME+1 );
  313. lpwsAuditStr[0] = wchPortName;
  314. DDMLogWarningString(ROUTERLOG_IPSEC_FILTER_FAILURE,
  315. 1, lpwsAuditStr, dwRetCode, 1);
  316. pDevObj->fFlags |= DEV_OBJ_IPSEC_ERROR_LOGGED;
  317. }
  318. else
  319. {
  320. //
  321. // Clear the flag so that if we hit this error again
  322. // we do an eventlog
  323. //
  324. pDevObj->fFlags &= ~DEV_OBJ_IPSEC_ERROR_LOGGED;
  325. }
  326. }
  327. if (( dwRetCode == NO_ERROR ) &&
  328. (( RAS_DEVICE_TYPE( pDevObj->dwDeviceType ) != RDT_PPPoE ) ||
  329. (RAS_DEVICE_TYPE(pDevObj->dwDeviceType) == RDT_PPPoE) &&
  330. (pDevObj->fFlags & DEV_OBJ_ALLOW_CLIENTS))
  331. )
  332. {
  333. pDevObj->ConnectionState = LISTENING;
  334. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  335. "RmListen: Listen posted on port %d", pDevObj->hPort);
  336. dwRetCode = RasPortListen(
  337. pDevObj->hPort,
  338. INFINITE,
  339. gblSupervisorEvents[NUM_DDM_EVENTS + dwBucketIndex] );
  340. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  341. "RasPortListen dwRetCode=%d", dwRetCode);
  342. RTASSERT((dwRetCode == SUCCESS) || (dwRetCode == PENDING));
  343. if ( dwRetCode == PENDING )
  344. {
  345. dwRetCode = NO_ERROR;
  346. }
  347. }
  348. else if ((dwRetCode == NO_ERROR) &&
  349. (RAS_DEVICE_TYPE(pDevObj->dwDeviceType) == RDT_PPPoE))
  350. {
  351. pDevObj->DeviceState = DEV_OBJ_CLOSED;
  352. }
  353. return( dwRetCode );
  354. }
  355. //***
  356. //
  357. // Function: RmConnect
  358. //
  359. // Descr:
  360. //
  361. //***
  362. DWORD
  363. RmConnect(
  364. IN PDEVICE_OBJECT pDevObj,
  365. IN char *cbphno // callback number
  366. )
  367. {
  368. RASMAN_DEVICEINFO devinfo;
  369. RAS_PARAMS *paramp;
  370. char *phnokeyname;
  371. DWORD rc;
  372. DWORD dwBucketIndex;
  373. CHAR chDeviceType[MAX_DEVICETYPE_NAME+1];
  374. CHAR chDeviceName[MAX_DEVICE_NAME+1];
  375. CHAR *pszMungedPhNo = NULL;
  376. DWORD dwSizeofMungedPhNo;
  377. WideCharToMultiByte( CP_ACP,
  378. 0,
  379. pDevObj->wchDeviceType,
  380. -1,
  381. chDeviceType,
  382. sizeof( chDeviceType ),
  383. NULL,
  384. NULL );
  385. WideCharToMultiByte( CP_ACP,
  386. 0,
  387. pDevObj->wchDeviceName,
  388. -1,
  389. chDeviceName,
  390. sizeof( chDeviceName ),
  391. NULL,
  392. NULL );
  393. dwBucketIndex = DeviceObjHashPortToBucket( pDevObj->hPort );
  394. phnokeyname = MXS_PHONENUMBER_KEY;
  395. RTASSERT(pDevObj->ConnectionState == DISCONNECTED);
  396. pDevObj->ConnectionState = CONNECTING;
  397. // set up the deviceinfo structure for callback
  398. devinfo.DI_NumOfParams = 1;
  399. paramp = &devinfo.DI_Params[0];
  400. strcpy(paramp->P_Key, phnokeyname);
  401. paramp->P_Type = String;
  402. paramp->P_Attributes = 0;
  403. pszMungedPhNo = cbphno;
  404. dwSizeofMungedPhNo = strlen(cbphno) + 1;
  405. //
  406. // Munge the phonenumber if required
  407. //
  408. if( (RDT_Tunnel == RAS_DEVICE_CLASS(pDevObj->dwDeviceType))
  409. && ( (0 != gblDDMConfigInfo.cDigitalIPAddresses)
  410. || (0 != gblDDMConfigInfo.cAnalogIPAddresses)))
  411. {
  412. //
  413. // Munge cbphno
  414. //
  415. rc = MungePhoneNumber(
  416. cbphno,
  417. pDevObj->dwIndex,
  418. &dwSizeofMungedPhNo,
  419. &pszMungedPhNo);
  420. if(ERROR_SUCCESS != rc)
  421. {
  422. //
  423. // fall back to whatever was passed
  424. //
  425. pszMungedPhNo = cbphno;
  426. dwSizeofMungedPhNo = strlen(cbphno);
  427. }
  428. }
  429. else if(RDT_Modem == RAS_DEVICE_TYPE(pDevObj->dwDeviceType))
  430. {
  431. BOOL fPulse = FALSE;
  432. //
  433. // Check to see if we need to pulsedial. Error returned
  434. // can be ignored - theres nothing much we can do anyway.
  435. // We default to Tone.
  436. //
  437. (void) RasIsPulseDial(pDevObj->hPort, &fPulse);
  438. if(fPulse)
  439. {
  440. //
  441. // +2 is for '\0' and 'P'
  442. //
  443. dwSizeofMungedPhNo = strlen(cbphno) + 2;
  444. pszMungedPhNo = LocalAlloc(LPTR, dwSizeofMungedPhNo);
  445. if(NULL == pszMungedPhNo)
  446. {
  447. rc = GetLastError();
  448. return rc;
  449. }
  450. sprintf(pszMungedPhNo, "P%s", cbphno);
  451. }
  452. }
  453. paramp->P_Value.String.Length = dwSizeofMungedPhNo;
  454. paramp->P_Value.String.Data = pszMungedPhNo;
  455. rc = RasDeviceSetInfo(pDevObj->hPort, chDeviceType, chDeviceName, &devinfo);
  456. if(pszMungedPhNo != cbphno)
  457. {
  458. LocalFree(pszMungedPhNo);
  459. }
  460. if ( rc != SUCCESS )
  461. {
  462. RTASSERT( FALSE );
  463. return( rc );
  464. }
  465. #if 0
  466. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  467. "RmConnect:Connecting to %s, size %d",
  468. pszMungedPhNo,
  469. dwSizeofMungedPhNo);
  470. #endif
  471. rc = RasDeviceConnect(
  472. pDevObj->hPort,
  473. chDeviceType,
  474. chDeviceName,
  475. 120,
  476. gblSupervisorEvents[NUM_DDM_EVENTS+dwBucketIndex]
  477. );
  478. RTASSERT ((rc == PENDING) || (rc == SUCCESS));
  479. if ( rc == PENDING )
  480. {
  481. rc = NO_ERROR;
  482. }
  483. return( rc );
  484. }
  485. //***
  486. //
  487. // Function: RmDisconnect
  488. //
  489. // Descr:
  490. //
  491. //***
  492. DWORD
  493. RmDisconnect(
  494. IN PDEVICE_OBJECT pDevObj
  495. )
  496. {
  497. DWORD dwRetCode;
  498. DWORD dwBucketIndex = DeviceObjHashPortToBucket( pDevObj->hPort );
  499. if (pDevObj->ConnectionState == DISCONNECTED)
  500. {
  501. return(0);
  502. }
  503. else
  504. {
  505. pDevObj->ConnectionState = DISCONNECTING;
  506. }
  507. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  508. "RmDisconnect:Disconnect posted on port %d", pDevObj->hPort);
  509. dwRetCode = RasPortDisconnect(
  510. pDevObj->hPort,
  511. gblSupervisorEvents[NUM_DDM_EVENTS+dwBucketIndex] );
  512. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  513. "RasPortDisconnect rc=%li", dwRetCode );
  514. if ((dwRetCode != PENDING) && (dwRetCode != SUCCESS))
  515. {
  516. // DbgPrint("RmDisconnect: dwRetCode = 0x%lx\n",dwRetCode);
  517. }
  518. if ( dwRetCode == PENDING )
  519. {
  520. dwRetCode = NO_ERROR;
  521. }
  522. return( dwRetCode );
  523. }