/********************************************************************/ /* Copyright(c) 1992 Microsoft Corporation */ /********************************************************************/ //*** // // Filename: rasmanif.c // // Description: This module contains the i/f procedures with the // RasManager // // Author: Stefan Solomon (stefans) May 26, 1992. // // Revision History: // //*** #include "ddm.h" #include "util.h" #include "objects.h" #include #include #include #include #include "rasmanif.h" #include "handlers.h" //*** // // Function: RmInit // // Description: Called only at service start time. // Does RasPortEnum, allocates global memory for the // Device Table, opens every dialin port and copies the port // handle and port name into the dcb struct. // Finally, deallocates the buffers (for port enum) and returns. // // Returns: NO_ERROR - Success // otherwise - Failure // //*** DWORD RmInit( OUT BOOL * pfWANDeviceInstalled ) { DWORD dwIndex; DWORD dwRetCode; HPORT hPort; PDEVICE_OBJECT pDevObj; BYTE * pBuffer = NULL; DWORD dwBufferSize = 0; DWORD dwNumEntries = 0; RASMAN_PORT* pRasmanPort; *pfWANDeviceInstalled = FALSE; do { // // get the buffer size needed for RasPortEnum // dwRetCode = RasPortEnum( NULL, NULL, &dwBufferSize, &dwNumEntries ); if ( dwRetCode == ERROR_BUFFER_TOO_SMALL ) { // // If there are ports installed, allocate buffer to get them // if (( pBuffer = (BYTE *)LOCAL_ALLOC( LPTR, dwBufferSize ) ) == NULL) { // // can't allocate the enum buffer // dwRetCode = GetLastError(); DDMLogError( ROUTERLOG_NOT_ENOUGH_MEMORY, 0, NULL, dwRetCode); break; } // // get the real enum data // dwRetCode = RasPortEnum( NULL, pBuffer, &dwBufferSize, &dwNumEntries ); if ( dwRetCode != NO_ERROR ) { // // can't enumerate ports // DDMLogErrorString(ROUTERLOG_CANT_ENUM_PORTS,0,NULL,dwRetCode,0); break; } } else if ( dwRetCode == NO_ERROR ) { // // Otherwise there were no ports installed // dwNumEntries = 0; } else { DDMLogErrorString(ROUTERLOG_CANT_ENUM_PORTS,0,NULL,dwRetCode,0); break; } // // Allocate device hash table // if ( dwNumEntries < MIN_DEVICE_TABLE_SIZE ) { gblDeviceTable.NumDeviceBuckets = MIN_DEVICE_TABLE_SIZE; } else if ( dwNumEntries > MAX_DEVICE_TABLE_SIZE ) { gblDeviceTable.NumDeviceBuckets = MAX_DEVICE_TABLE_SIZE; } else { gblDeviceTable.NumDeviceBuckets = dwNumEntries; } gblDeviceTable.DeviceBucket = (PDEVICE_OBJECT *)LOCAL_ALLOC( LPTR, gblDeviceTable.NumDeviceBuckets * sizeof( PDEVICE_OBJECT ) ); if ( gblDeviceTable.DeviceBucket == (PDEVICE_OBJECT *)NULL ) { dwRetCode = GetLastError(); DDMLogError( ROUTERLOG_NOT_ENOUGH_MEMORY, 0, NULL, dwRetCode); break; } // // Set number of connection buckets to number of device buckets. // Since Number of devices >= Number of connections. // gblDeviceTable.NumConnectionBuckets = gblDeviceTable.NumDeviceBuckets; // // Allocate bundle or connection table // gblDeviceTable.ConnectionBucket = (PCONNECTION_OBJECT*)LOCAL_ALLOC(LPTR, gblDeviceTable.NumConnectionBuckets * sizeof( PCONNECTION_OBJECT ) ); if ( gblDeviceTable.ConnectionBucket == (PCONNECTION_OBJECT *)NULL ) { dwRetCode = GetLastError(); DDMLogError(ROUTERLOG_NOT_ENOUGH_MEMORY, 0, NULL, dwRetCode); break; } // // For each device object, try to open the port. // If port can't be opened, skip and go to next port. // for ( dwIndex = 0, pRasmanPort = (RASMAN_PORT *)pBuffer; dwIndex < dwNumEntries; dwIndex++, pRasmanPort++) { // // only ports enabled for incoming or router connections // are added to the device table // if (pRasmanPort->P_ConfiguredUsage & (CALL_IN | CALL_ROUTER | CALL_IN_ONLY | CALL_OUTBOUND_ROUTER)) { dwRetCode = RasPortOpen(pRasmanPort->P_PortName, &hPort, NULL); if ( dwRetCode != NO_ERROR ) { // // Failed to open an port on which incoming // connections are enabled. Log an error and // continue to the next port // WCHAR wchPortName[MAX_PORT_NAME+1]; LPWSTR lpwsAuditStr[1]; MultiByteToWideChar( CP_ACP, 0, pRasmanPort->P_PortName, -1, wchPortName, MAX_PORT_NAME+1 ); // // Log an error // lpwsAuditStr[0] = wchPortName; DDMLogErrorString( ROUTERLOG_UNABLE_TO_OPEN_PORT, 1, lpwsAuditStr, dwRetCode, 1 ); dwRetCode = NO_ERROR; continue; } // // Don't insert the device into the hash table if the device // doesn't support incoming/router calls. // // Note: // Per DCR 349087 we need to enable outbound-only DoD on // PPPoE connections. These ports are identified as // having usage CALL_OUTBOUND_ROUTER. // if ((pRasmanPort->P_ConfiguredUsage & (CALL_IN | CALL_ROUTER | CALL_OUTBOUND_ROUTER))) { pDevObj = DeviceObjAllocAndInitialize( hPort, pRasmanPort ); if ( pDevObj == (DEVICE_OBJECT *)NULL ) { dwRetCode = GetLastError(); DDMLogError(ROUTERLOG_NOT_ENOUGH_MEMORY,0, NULL,dwRetCode); break; } // // Insert into the device hash table // DeviceObjInsertInTable( pDevObj ); if (RAS_DEVICE_CLASS( pDevObj->dwDeviceType ) != RDT_Direct) { *pfWANDeviceInstalled = TRUE; } } } } } while ( FALSE ); if ( pBuffer != NULL ) { LOCAL_FREE( pBuffer ); } return( dwRetCode ); } //*** // // Function: RmReceiveFrame // // Descr: // //*** DWORD RmReceiveFrame( IN PDEVICE_OBJECT pDevObj ) { DWORD dwRetCode; DWORD dwBucketIndex = DeviceObjHashPortToBucket( pDevObj->hPort ); RTASSERT( pDevObj->pRasmanRecvBuffer != NULL ); dwRetCode = RasPortReceive( pDevObj->hPort, pDevObj->pRasmanRecvBuffer , &(pDevObj->dwRecvBufferLen), 0L, //no timeout gblSupervisorEvents[NUM_DDM_EVENTS + gblDeviceTable.NumDeviceBuckets + dwBucketIndex] ); if ( ( dwRetCode == NO_ERROR ) || ( dwRetCode == PENDING ) ) { pDevObj->fFlags |= DEV_OBJ_RECEIVE_ACTIVE; dwRetCode = NO_ERROR; } return( dwRetCode ); } //*** // // Function: RmListen // // Descr: // //*** DWORD RmListen( IN PDEVICE_OBJECT pDevObj ) { DWORD dwRetCode = NO_ERROR; DWORD dwBucketIndex = DeviceObjHashPortToBucket( pDevObj->hPort ); //RTASSERT(pDevObj->ConnectionState == DISCONNECTED); // // If this is an L2TP tunnel port type and we have to use // IPSEC, then go ahead and set the filter // if ( RAS_DEVICE_TYPE( pDevObj->dwDeviceType ) == RDT_Tunnel_L2tp ) { dwRetCode = RasEnableIpSec( pDevObj->hPort, TRUE, TRUE, (gblDDMConfigInfo.dwServerFlags & PPPCFG_RequireIPSEC) ? RAS_L2TP_REQUIRE_ENCRYPTION : RAS_L2TP_OPTIONAL_ENCRYPTION); // RTASSERT( dwRetCode == NO_ERROR ); DDMTRACE2( "Enabled IPSec on port %d, dwRetCode = %d", pDevObj->hPort, dwRetCode ); // // Log the non certificate errorlog only once // if ( dwRetCode == ERROR_NO_CERTIFICATE ) { if ( !( gblDDMConfigInfo.fFlags & DDM_NO_CERTIFICATE_LOGGED ) ) { DDMLogWarning( ROUTERLOG_NO_IPSEC_CERT, 0, NULL ); gblDDMConfigInfo.fFlags |= DDM_NO_CERTIFICATE_LOGGED; } return( dwRetCode ); } if( (dwRetCode != NO_ERROR) && !(pDevObj->fFlags & DEV_OBJ_IPSEC_ERROR_LOGGED)) { WCHAR wchPortName[MAX_PORT_NAME+1]; LPWSTR lpwsAuditStr[1]; RASMAN_INFO rInfo; DWORD rc; ZeroMemory(&rInfo, sizeof(RASMAN_INFO)); rc = RasGetInfo(NULL, pDevObj->hPort, &rInfo); if(rc != NO_ERROR) { return (NO_ERROR); } MultiByteToWideChar( CP_ACP, 0, rInfo.RI_szPortName, -1, wchPortName, MAX_PORT_NAME+1 ); lpwsAuditStr[0] = wchPortName; DDMLogWarningString(ROUTERLOG_IPSEC_FILTER_FAILURE, 1, lpwsAuditStr, dwRetCode, 1); pDevObj->fFlags |= DEV_OBJ_IPSEC_ERROR_LOGGED; } else { // // Clear the flag so that if we hit this error again // we do an eventlog // pDevObj->fFlags &= ~DEV_OBJ_IPSEC_ERROR_LOGGED; } } if (( dwRetCode == NO_ERROR ) && (( RAS_DEVICE_TYPE( pDevObj->dwDeviceType ) != RDT_PPPoE ) || (RAS_DEVICE_TYPE(pDevObj->dwDeviceType) == RDT_PPPoE) && (pDevObj->fFlags & DEV_OBJ_ALLOW_CLIENTS)) ) { pDevObj->ConnectionState = LISTENING; DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "RmListen: Listen posted on port %d", pDevObj->hPort); dwRetCode = RasPortListen( pDevObj->hPort, INFINITE, gblSupervisorEvents[NUM_DDM_EVENTS + dwBucketIndex] ); DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "RasPortListen dwRetCode=%d", dwRetCode); RTASSERT((dwRetCode == SUCCESS) || (dwRetCode == PENDING)); if ( dwRetCode == PENDING ) { dwRetCode = NO_ERROR; } } else if ((dwRetCode == NO_ERROR) && (RAS_DEVICE_TYPE(pDevObj->dwDeviceType) == RDT_PPPoE)) { pDevObj->DeviceState = DEV_OBJ_CLOSED; } return( dwRetCode ); } //*** // // Function: RmConnect // // Descr: // //*** DWORD RmConnect( IN PDEVICE_OBJECT pDevObj, IN char *cbphno // callback number ) { RASMAN_DEVICEINFO devinfo; RAS_PARAMS *paramp; char *phnokeyname; DWORD rc; DWORD dwBucketIndex; CHAR chDeviceType[MAX_DEVICETYPE_NAME+1]; CHAR chDeviceName[MAX_DEVICE_NAME+1]; CHAR *pszMungedPhNo = NULL; DWORD dwSizeofMungedPhNo; WideCharToMultiByte( CP_ACP, 0, pDevObj->wchDeviceType, -1, chDeviceType, sizeof( chDeviceType ), NULL, NULL ); WideCharToMultiByte( CP_ACP, 0, pDevObj->wchDeviceName, -1, chDeviceName, sizeof( chDeviceName ), NULL, NULL ); dwBucketIndex = DeviceObjHashPortToBucket( pDevObj->hPort ); phnokeyname = MXS_PHONENUMBER_KEY; RTASSERT(pDevObj->ConnectionState == DISCONNECTED); pDevObj->ConnectionState = CONNECTING; // set up the deviceinfo structure for callback devinfo.DI_NumOfParams = 1; paramp = &devinfo.DI_Params[0]; strcpy(paramp->P_Key, phnokeyname); paramp->P_Type = String; paramp->P_Attributes = 0; pszMungedPhNo = cbphno; dwSizeofMungedPhNo = strlen(cbphno) + 1; // // Munge the phonenumber if required // if( (RDT_Tunnel == RAS_DEVICE_CLASS(pDevObj->dwDeviceType)) && ( (0 != gblDDMConfigInfo.cDigitalIPAddresses) || (0 != gblDDMConfigInfo.cAnalogIPAddresses))) { // // Munge cbphno // rc = MungePhoneNumber( cbphno, pDevObj->dwIndex, &dwSizeofMungedPhNo, &pszMungedPhNo); if(ERROR_SUCCESS != rc) { // // fall back to whatever was passed // pszMungedPhNo = cbphno; dwSizeofMungedPhNo = strlen(cbphno); } } else if(RDT_Modem == RAS_DEVICE_TYPE(pDevObj->dwDeviceType)) { BOOL fPulse = FALSE; // // Check to see if we need to pulsedial. Error returned // can be ignored - theres nothing much we can do anyway. // We default to Tone. // (void) RasIsPulseDial(pDevObj->hPort, &fPulse); if(fPulse) { // // +2 is for '\0' and 'P' // dwSizeofMungedPhNo = strlen(cbphno) + 2; pszMungedPhNo = LocalAlloc(LPTR, dwSizeofMungedPhNo); if(NULL == pszMungedPhNo) { rc = GetLastError(); return rc; } sprintf(pszMungedPhNo, "P%s", cbphno); } } paramp->P_Value.String.Length = dwSizeofMungedPhNo; paramp->P_Value.String.Data = pszMungedPhNo; rc = RasDeviceSetInfo(pDevObj->hPort, chDeviceType, chDeviceName, &devinfo); if(pszMungedPhNo != cbphno) { LocalFree(pszMungedPhNo); } if ( rc != SUCCESS ) { RTASSERT( FALSE ); return( rc ); } #if 0 DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "RmConnect:Connecting to %s, size %d", pszMungedPhNo, dwSizeofMungedPhNo); #endif rc = RasDeviceConnect( pDevObj->hPort, chDeviceType, chDeviceName, 120, gblSupervisorEvents[NUM_DDM_EVENTS+dwBucketIndex] ); RTASSERT ((rc == PENDING) || (rc == SUCCESS)); if ( rc == PENDING ) { rc = NO_ERROR; } return( rc ); } //*** // // Function: RmDisconnect // // Descr: // //*** DWORD RmDisconnect( IN PDEVICE_OBJECT pDevObj ) { DWORD dwRetCode; DWORD dwBucketIndex = DeviceObjHashPortToBucket( pDevObj->hPort ); if (pDevObj->ConnectionState == DISCONNECTED) { return(0); } else { pDevObj->ConnectionState = DISCONNECTING; } DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "RmDisconnect:Disconnect posted on port %d", pDevObj->hPort); dwRetCode = RasPortDisconnect( pDevObj->hPort, gblSupervisorEvents[NUM_DDM_EVENTS+dwBucketIndex] ); DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "RasPortDisconnect rc=%li", dwRetCode ); if ((dwRetCode != PENDING) && (dwRetCode != SUCCESS)) { // DbgPrint("RmDisconnect: dwRetCode = 0x%lx\n",dwRetCode); } if ( dwRetCode == PENDING ) { dwRetCode = NO_ERROR; } return( dwRetCode ); }