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

592 lines
16 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. continue;
  181. }
  182. //
  183. // Don't insert the device into the hash table if the device
  184. // doesn't support incoming/router calls.
  185. //
  186. // Note:
  187. // Per DCR 349087 we need to enable outbound-only DoD on
  188. // PPPoE connections. These ports are identified as
  189. // having usage CALL_OUTBOUND_ROUTER.
  190. //
  191. if ((pRasmanPort->P_ConfiguredUsage &
  192. (CALL_IN | CALL_ROUTER | CALL_OUTBOUND_ROUTER)))
  193. {
  194. pDevObj = DeviceObjAllocAndInitialize( hPort, pRasmanPort );
  195. if ( pDevObj == (DEVICE_OBJECT *)NULL )
  196. {
  197. dwRetCode = GetLastError();
  198. DDMLogError(ROUTERLOG_NOT_ENOUGH_MEMORY,0,
  199. NULL,dwRetCode);
  200. break;
  201. }
  202. //
  203. // Insert into the device hash table
  204. //
  205. DeviceObjInsertInTable( pDevObj );
  206. if (RAS_DEVICE_CLASS( pDevObj->dwDeviceType ) != RDT_Direct)
  207. {
  208. *pfWANDeviceInstalled = TRUE;
  209. }
  210. }
  211. }
  212. }
  213. } while ( FALSE );
  214. if ( pBuffer != NULL )
  215. {
  216. LOCAL_FREE( pBuffer );
  217. }
  218. return( dwRetCode );
  219. }
  220. //***
  221. //
  222. // Function: RmReceiveFrame
  223. //
  224. // Descr:
  225. //
  226. //***
  227. DWORD
  228. RmReceiveFrame(
  229. IN PDEVICE_OBJECT pDevObj
  230. )
  231. {
  232. DWORD dwRetCode;
  233. DWORD dwBucketIndex = DeviceObjHashPortToBucket( pDevObj->hPort );
  234. RTASSERT( pDevObj->pRasmanRecvBuffer != NULL );
  235. dwRetCode = RasPortReceive(
  236. pDevObj->hPort,
  237. pDevObj->pRasmanRecvBuffer ,
  238. &(pDevObj->dwRecvBufferLen),
  239. 0L, //no timeout
  240. gblSupervisorEvents[NUM_DDM_EVENTS
  241. + gblDeviceTable.NumDeviceBuckets
  242. + dwBucketIndex] );
  243. if ( ( dwRetCode == NO_ERROR ) || ( dwRetCode == PENDING ) )
  244. {
  245. pDevObj->fFlags |= DEV_OBJ_RECEIVE_ACTIVE;
  246. dwRetCode = NO_ERROR;
  247. }
  248. return( dwRetCode );
  249. }
  250. //***
  251. //
  252. // Function: RmListen
  253. //
  254. // Descr:
  255. //
  256. //***
  257. DWORD
  258. RmListen(
  259. IN PDEVICE_OBJECT pDevObj
  260. )
  261. {
  262. DWORD dwRetCode = NO_ERROR;
  263. DWORD dwBucketIndex = DeviceObjHashPortToBucket( pDevObj->hPort );
  264. RTASSERT(pDevObj->ConnectionState == DISCONNECTED);
  265. //
  266. // If this is an L2TP tunnel port type and we have to use
  267. // IPSEC, then go ahead and set the filter
  268. //
  269. if ( RAS_DEVICE_TYPE( pDevObj->dwDeviceType ) == RDT_Tunnel_L2tp )
  270. {
  271. dwRetCode = RasEnableIpSec(
  272. pDevObj->hPort,
  273. TRUE,
  274. TRUE,
  275. (gblDDMConfigInfo.dwServerFlags & PPPCFG_RequireIPSEC)
  276. ? RAS_L2TP_REQUIRE_ENCRYPTION
  277. : RAS_L2TP_OPTIONAL_ENCRYPTION);
  278. // RTASSERT( dwRetCode == NO_ERROR );
  279. DDMTRACE2( "Enabled IPSec on port %d, dwRetCode = %d",
  280. pDevObj->hPort, dwRetCode );
  281. //
  282. // Log the non certificate errorlog only once
  283. //
  284. if ( dwRetCode == ERROR_NO_CERTIFICATE )
  285. {
  286. if ( !( gblDDMConfigInfo.fFlags & DDM_NO_CERTIFICATE_LOGGED ) )
  287. {
  288. DDMLogWarning( ROUTERLOG_NO_IPSEC_CERT, 0, NULL );
  289. gblDDMConfigInfo.fFlags |= DDM_NO_CERTIFICATE_LOGGED;
  290. }
  291. return( dwRetCode );
  292. }
  293. if( (dwRetCode != NO_ERROR)
  294. && !(pDevObj->fFlags & DEV_OBJ_IPSEC_ERROR_LOGGED))
  295. {
  296. WCHAR wchPortName[MAX_PORT_NAME+1];
  297. LPWSTR lpwsAuditStr[1];
  298. RASMAN_INFO rInfo;
  299. DWORD rc;
  300. ZeroMemory(&rInfo, sizeof(RASMAN_INFO));
  301. rc = RasGetInfo(NULL, pDevObj->hPort, &rInfo);
  302. if(rc != NO_ERROR)
  303. {
  304. return (NO_ERROR);
  305. }
  306. MultiByteToWideChar( CP_ACP,
  307. 0,
  308. rInfo.RI_szPortName,
  309. -1,
  310. wchPortName,
  311. MAX_PORT_NAME+1 );
  312. lpwsAuditStr[0] = wchPortName;
  313. DDMLogWarningString(ROUTERLOG_IPSEC_FILTER_FAILURE,
  314. 1, lpwsAuditStr, dwRetCode, 1);
  315. pDevObj->fFlags |= DEV_OBJ_IPSEC_ERROR_LOGGED;
  316. }
  317. else
  318. {
  319. //
  320. // Clear the flag so that if we hit this error again
  321. // we do an eventlog
  322. //
  323. pDevObj->fFlags &= ~DEV_OBJ_IPSEC_ERROR_LOGGED;
  324. }
  325. }
  326. if (( dwRetCode == NO_ERROR ) &&
  327. ( RAS_DEVICE_TYPE( pDevObj->dwDeviceType ) != RDT_PPPoE ))
  328. {
  329. pDevObj->ConnectionState = LISTENING;
  330. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  331. "RmListen: Listen posted on port %d", pDevObj->hPort);
  332. dwRetCode = RasPortListen(
  333. pDevObj->hPort,
  334. INFINITE,
  335. gblSupervisorEvents[NUM_DDM_EVENTS + dwBucketIndex] );
  336. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  337. "RasPortListen dwRetCode=%d", dwRetCode);
  338. RTASSERT((dwRetCode == SUCCESS) || (dwRetCode == PENDING));
  339. if ( dwRetCode == PENDING )
  340. {
  341. dwRetCode = NO_ERROR;
  342. }
  343. }
  344. return( dwRetCode );
  345. }
  346. //***
  347. //
  348. // Function: RmConnect
  349. //
  350. // Descr:
  351. //
  352. //***
  353. DWORD
  354. RmConnect(
  355. IN PDEVICE_OBJECT pDevObj,
  356. IN char *cbphno // callback number
  357. )
  358. {
  359. RASMAN_DEVICEINFO devinfo;
  360. RAS_PARAMS *paramp;
  361. char *phnokeyname;
  362. DWORD rc;
  363. DWORD dwBucketIndex;
  364. CHAR chDeviceType[MAX_DEVICETYPE_NAME+1];
  365. CHAR chDeviceName[MAX_DEVICE_NAME+1];
  366. CHAR *pszMungedPhNo = NULL;
  367. DWORD dwSizeofMungedPhNo;
  368. WideCharToMultiByte( CP_ACP,
  369. 0,
  370. pDevObj->wchDeviceType,
  371. -1,
  372. chDeviceType,
  373. sizeof( chDeviceType ),
  374. NULL,
  375. NULL );
  376. WideCharToMultiByte( CP_ACP,
  377. 0,
  378. pDevObj->wchDeviceName,
  379. -1,
  380. chDeviceName,
  381. sizeof( chDeviceName ),
  382. NULL,
  383. NULL );
  384. dwBucketIndex = DeviceObjHashPortToBucket( pDevObj->hPort );
  385. phnokeyname = MXS_PHONENUMBER_KEY;
  386. RTASSERT(pDevObj->ConnectionState == DISCONNECTED);
  387. pDevObj->ConnectionState = CONNECTING;
  388. // set up the deviceinfo structure for callback
  389. devinfo.DI_NumOfParams = 1;
  390. paramp = &devinfo.DI_Params[0];
  391. strcpy(paramp->P_Key, phnokeyname);
  392. paramp->P_Type = String;
  393. paramp->P_Attributes = 0;
  394. pszMungedPhNo = cbphno;
  395. dwSizeofMungedPhNo = strlen(cbphno);
  396. //
  397. // Munge the phonenumber if required
  398. //
  399. if( (RDT_Tunnel == RAS_DEVICE_CLASS(pDevObj->dwDeviceType))
  400. && ( (0 != gblDDMConfigInfo.cDigitalIPAddresses)
  401. || (0 != gblDDMConfigInfo.cAnalogIPAddresses)))
  402. {
  403. //
  404. // Munge cbphno
  405. //
  406. rc = MungePhoneNumber(
  407. cbphno,
  408. pDevObj->dwIndex,
  409. &dwSizeofMungedPhNo,
  410. &pszMungedPhNo);
  411. if(ERROR_SUCCESS != rc)
  412. {
  413. //
  414. // fall back to whatever was passed
  415. //
  416. pszMungedPhNo = cbphno;
  417. dwSizeofMungedPhNo = strlen(cbphno);
  418. }
  419. }
  420. paramp->P_Value.String.Length = dwSizeofMungedPhNo;
  421. paramp->P_Value.String.Data = pszMungedPhNo;
  422. rc = RasDeviceSetInfo(pDevObj->hPort, chDeviceType, chDeviceName, &devinfo);
  423. if ( rc != SUCCESS )
  424. {
  425. RTASSERT( FALSE );
  426. return( rc );
  427. }
  428. rc = RasDeviceConnect(
  429. pDevObj->hPort,
  430. chDeviceType,
  431. chDeviceName,
  432. 120,
  433. gblSupervisorEvents[NUM_DDM_EVENTS+dwBucketIndex]
  434. );
  435. RTASSERT ((rc == PENDING) || (rc == SUCCESS));
  436. if ( rc == PENDING )
  437. {
  438. rc = NO_ERROR;
  439. }
  440. return( rc );
  441. }
  442. //***
  443. //
  444. // Function: RmDisconnect
  445. //
  446. // Descr:
  447. //
  448. //***
  449. DWORD
  450. RmDisconnect(
  451. IN PDEVICE_OBJECT pDevObj
  452. )
  453. {
  454. DWORD dwRetCode;
  455. DWORD dwBucketIndex = DeviceObjHashPortToBucket( pDevObj->hPort );
  456. if (pDevObj->ConnectionState == DISCONNECTED)
  457. {
  458. return(0);
  459. }
  460. else
  461. {
  462. pDevObj->ConnectionState = DISCONNECTING;
  463. }
  464. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  465. "RmDisconnect:Disconnect posted on port %d", pDevObj->hPort);
  466. dwRetCode = RasPortDisconnect(
  467. pDevObj->hPort,
  468. gblSupervisorEvents[NUM_DDM_EVENTS+dwBucketIndex] );
  469. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  470. "RasPortDisconnect rc=%li", dwRetCode );
  471. if ((dwRetCode != PENDING) && (dwRetCode != SUCCESS))
  472. {
  473. DbgPrint("RmDisconnect: dwRetCode = 0x%lx\n",dwRetCode);
  474. }
  475. if ( dwRetCode == PENDING )
  476. {
  477. dwRetCode = NO_ERROR;
  478. }
  479. return( dwRetCode );
  480. }