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

/********************************************************************/
/* 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 <raserror.h>
#include <ddmif.h>
#include <string.h>
#include <rasmxs.h>
#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 );
}