windows-nt/Source/XPSP1/NT/net/rras/ras/ddm/rasapiif.c
2020-09-26 16:20:57 +08:00

937 lines
28 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*********************************************************************/
/** Copyright(c) 1995 Microsoft Corporation. **/
/*********************************************************************/
//***
//
// Filename: rasapiif.c
//
// Description: Handles all the RASAPI32 calls
//
// History: May 11,1996 NarenG Created original version.
//
#include "ddm.h"
#include "util.h"
#include "objects.h"
#include "rasmanif.h"
#include "rasapiif.h"
#include "handlers.h"
#include "timer.h"
#include <time.h>
#include <mprapi.h>
#include <mprapip.h>
HPORT
RasGetHport(
IN HRASCONN hRasConnSubEntry
);
DWORD
RasPortConnected(
IN HRASCONN hRasConn,
IN HRASCONN hRasConnSubEntry,
IN DEVICE_OBJECT * pDevObj,
IN HANDLE hDIMInterface
)
{
CONNECTION_OBJECT * pConnObj;
DWORD dwRetCode;
ROUTER_INTERFACE_OBJECT * pIfObject;
//
// Set this port to be notified by rasapi32 on disconnect.
//
dwRetCode = RasConnectionNotification(
hRasConnSubEntry,
gblSupervisorEvents[NUM_DDM_EVENTS
+ (gblDeviceTable.NumDeviceBuckets*2)
+ DeviceObjHashPortToBucket(pDevObj->hPort)],
RASCN_Disconnection );
if ( dwRetCode != NO_ERROR )
{
DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
"RasConnectionNotification returned %d", dwRetCode );
return( dwRetCode );
}
//
// Get handle to the connection or bundle for this link
//
dwRetCode = RasPortGetBundle(NULL, pDevObj->hPort, &(pDevObj->hConnection));
if ( dwRetCode != NO_ERROR )
{
DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
"RasPortGetBundle returned %d", dwRetCode );
return( dwRetCode );
}
do
{
pIfObject = IfObjectGetPointer( hDIMInterface );
if ( pIfObject == NULL )
{
RTASSERT( FALSE );
dwRetCode = ERROR_NO_SUCH_INTERFACE;
break;
}
//
// If this interface was disconnected by DDMDisconnectInterface,
// then do not let this device through.
//
if ( pIfObject->fFlags & IFFLAG_DISCONNECT_INITIATED )
{
dwRetCode = ERROR_PORT_DISCONNECTED;
DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
"RasPortConnected: Admin disconnected port" );
break;
}
//
// Allocate a connection object if it does not exist yet
//
pConnObj = ConnObjGetPointer( pDevObj->hConnection );
if ( pConnObj == (CONNECTION_OBJECT *)NULL )
{
RASPPPIP RasPppIp;
RASPPPIPX RasPppIpx;
DWORD dwSize;
pConnObj = ConnObjAllocateAndInit( hDIMInterface,
pDevObj->hConnection );
if ( pConnObj == (CONNECTION_OBJECT *)NULL )
{
dwRetCode = GetLastError();
break;
}
ConnObjInsertInTable( pConnObj );
//
// First get the projection info, make sure IP or IPX
// were negotiated
//
dwSize = sizeof( RasPppIpx );
RasPppIpx.dwSize = sizeof( RasPppIpx );
dwRetCode = RasGetProjectionInfo(
hRasConn,
RASP_PppIpx,
&RasPppIpx,
&dwSize );
if ( dwRetCode != NO_ERROR )
{
pConnObj->PppProjectionResult.ipx.dwError = dwRetCode;
}
else
{
pConnObj->PppProjectionResult.ipx.dwError = RasPppIpx.dwError;
ConvertStringToIpxAddress(
RasPppIpx.szIpxAddress,
pConnObj->PppProjectionResult.ipx.bLocalAddress);
}
dwSize = sizeof( RasPppIp );
RasPppIp.dwSize = sizeof( RasPppIp );
dwRetCode = RasGetProjectionInfo(
hRasConn,
RASP_PppIp,
&RasPppIp,
&dwSize );
if ( dwRetCode != NO_ERROR )
{
pConnObj->PppProjectionResult.ip.dwError = dwRetCode;
}
else
{
pConnObj->PppProjectionResult.ip.dwError = RasPppIp.dwError;
ConvertStringToIpAddress(
RasPppIp.szIpAddress,
&(pConnObj->PppProjectionResult.ip.dwLocalAddress));
ConvertStringToIpAddress(
RasPppIp.szServerIpAddress,
&(pConnObj->PppProjectionResult.ip.dwRemoteAddress));
}
if ((pConnObj->PppProjectionResult.ipx.dwError!=NO_ERROR )
&&
(pConnObj->PppProjectionResult.ip.dwError!=NO_ERROR ))
{
dwRetCode = ERROR_PPP_NO_PROTOCOLS_CONFIGURED;
break;
}
pConnObj->fFlags = CONN_OBJ_IS_PPP;
pConnObj->hPort = pDevObj->hPort;
}
else
{
//
// Make sure that we are adding a link to a connection for the
// same interface that initiated the connection.
//
if ( hDIMInterface != pConnObj->hDIMInterface )
{
dwRetCode = ERROR_INTERFACE_CONFIGURATION;
break;
}
}
pDevObj->hRasConn = hRasConnSubEntry;
GetSystemTimeAsFileTime( (FILETIME*)&(pDevObj->qwActiveTime) );
//
// Add this link to the connection block.
//
if ((dwRetCode = ConnObjAddLink(pConnObj, pDevObj)) != NO_ERROR)
{
break;
}
//
// Notify router managers that we are connected if we have
// not done so already.
//
if ( !( pConnObj->fFlags & CONN_OBJ_PROJECTIONS_NOTIFIED ) )
{
RASDIALPARAMS RasDialParams;
BOOL fPassword;
dwRetCode = IfObjectConnected(
hDIMInterface,
(HCONN)pDevObj->hConnection,
&(pConnObj->PppProjectionResult) );
if ( dwRetCode != NO_ERROR )
{
break;
}
pConnObj->fFlags |= CONN_OBJ_PROJECTIONS_NOTIFIED;
//
// Get username and domain name
//
ZeroMemory( &RasDialParams, sizeof( RasDialParams ) );
RasDialParams.dwSize = sizeof( RasDialParams );
wcscpy( RasDialParams.szEntryName, pIfObject->lpwsInterfaceName );
dwRetCode = RasGetEntryDialParams( gblpRouterPhoneBook,
&RasDialParams,
&fPassword);
if ( dwRetCode == NO_ERROR )
{
wcscpy( pConnObj->wchUserName, RasDialParams.szUserName );
wcscpy( pConnObj->wchDomainName, RasDialParams.szDomain );
ZeroMemory( &RasDialParams, sizeof( RasDialParams ) );
}
else
{
dwRetCode = NO_ERROR;
}
wcscpy( pConnObj->wchInterfaceName, pIfObject->lpwsInterfaceName );
GetSystemTimeAsFileTime( (FILETIME*)&(pDevObj->qwActiveTime) );
pConnObj->qwActiveTime = pDevObj->qwActiveTime;
pConnObj->InterfaceType = pIfObject->IfType;
pIfObject->dwLastError = NO_ERROR;
//
// If this was initiated by an admin api. Let the caller
// know that we are connected.
//
if (pIfObject->hEventNotifyCaller != INVALID_HANDLE_VALUE)
{
SetEvent( pIfObject->hEventNotifyCaller );
CloseHandle( pIfObject->hEventNotifyCaller );
pIfObject->hEventNotifyCaller = INVALID_HANDLE_VALUE;
}
}
//
// Reduce the media count for this device
//
if ( !(pDevObj->fFlags & DEV_OBJ_MARKED_AS_INUSE) )
{
if ( pDevObj->fFlags & DEV_OBJ_ALLOW_ROUTERS )
{
MediaObjRemoveFromTable( pDevObj->wchDeviceType );
}
pDevObj->fFlags |= DEV_OBJ_MARKED_AS_INUSE;
gblDeviceTable.NumDevicesInUse++;
//
// Possibly need to notify the router managers of
// unreachability
//
IfObjectNotifyAllOfReachabilityChange( FALSE,
INTERFACE_OUT_OF_RESOURCES );
}
RasSetRouterUsage( pDevObj->hPort, TRUE );
}while( FALSE );
if ( dwRetCode != NO_ERROR )
{
DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
"RasPortConnected: Cleaning up hPort=%d, error %d",
pDevObj->hPort, dwRetCode );
RasApiCleanUpPort( pDevObj );
return( dwRetCode );
}
return( NO_ERROR );
}
//**
//
// Call: RasConnectCallback
//
// Returns: None
//
// Description: Callback function that will be called by RASAPI32 for any
// state change.
//
BOOL
RasConnectCallback(
IN DWORD dwCallbackId,
IN DWORD dwSubEntryId,
IN HRASCONN hRasConn,
IN DWORD dwMsg,
IN RASCONNSTATE RasConnState,
IN DWORD dwError,
IN DWORD dwExtendedError
)
{
DWORD dwIndex;
ROUTER_INTERFACE_OBJECT * pIfObject = NULL;
DEVICE_OBJECT * pDevObj = NULL;
HANDLE hDIMInterface = (HANDLE)UlongToPtr(dwCallbackId);
HRASCONN hRasConnSubEntry;
DWORD dwRetCode;
HPORT hPort;
LPWSTR lpwsAudit[2];
if ( dwMsg != WM_RASDIALEVENT )
{
RTASSERT( dwMsg == WM_RASDIALEVENT );
return( TRUE );
}
switch( RasConnState )
{
case RASCS_Connected:
case RASCS_SubEntryConnected:
case RASCS_SubEntryDisconnected:
case RASCS_Disconnected:
case RASCS_PortOpened:
break;
default:
if ( dwError != NO_ERROR )
{
break;
}
else
{
//
// Ignore these intermediate events
//
return( TRUE );
}
}
EnterCriticalSection( &(gblDeviceTable.CriticalSection) );
EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) );
do
{
//
// Get pointer to device object and hRasConn of the device
//
dwRetCode = RasGetSubEntryHandle( hRasConn,
dwSubEntryId,
&hRasConnSubEntry );
if ( dwRetCode != NO_ERROR )
{
DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
"RasGetSubEntryHandle( 0x%x, 0x%x, 0x%x ) = %d",
hRasConn, dwSubEntryId, &hRasConnSubEntry, dwRetCode );
if ( dwError == NO_ERROR )
{
dwError = dwRetCode;
}
}
else
{
hPort = RasGetHport( hRasConnSubEntry );
if ( hPort == (HPORT)INVALID_HANDLE_VALUE )
{
RTASSERT( FALSE );
dwRetCode = ERROR_INVALID_PORT_HANDLE;
if ( dwError == NO_ERROR )
{
dwError = dwRetCode;
}
}
else
{
if ( ( pDevObj = DeviceObjGetPointer( hPort ) ) == NULL )
{
dwRetCode = ERROR_NOT_ROUTER_PORT;
}
else
{
if ( !( pDevObj->fFlags & DEV_OBJ_ALLOW_ROUTERS ) )
{
dwRetCode = ERROR_NOT_ROUTER_PORT;
}
else
{
dwRetCode = NO_ERROR;
}
}
if ( dwError == NO_ERROR )
{
dwError = dwRetCode;
}
}
}
if ( dwError == NO_ERROR )
{
switch( RasConnState )
{
case RASCS_PortOpened:
pDevObj->fFlags |= DEV_OBJ_OPENED_FOR_DIALOUT;
pDevObj->hRasConn = hRasConnSubEntry;
break;
case RASCS_Connected:
case RASCS_SubEntryConnected:
DDM_PRINT(gblDDMConfigInfo.dwTraceId, TRACE_FSM,
"RasConnectCallback:PortConnected,dwSubEntryId=%d,hPort=%d",
dwSubEntryId, hPort );
dwError = RasPortConnected( hRasConn,
hRasConnSubEntry,
pDevObj,
hDIMInterface );
break;
case RASCS_SubEntryDisconnected:
case RASCS_Disconnected:
pDevObj->fFlags &= ~DEV_OBJ_OPENED_FOR_DIALOUT;
pDevObj->hRasConn = (HRASCONN)NULL;
break;
default:
RTASSERT( FALSE );
break;
}
if ( ( RasConnState == RASCS_Connected ) ||
( RasConnState == RASCS_SubEntryConnected )||
( RasConnState == RASCS_PortOpened ) )
{
if ( dwError == NO_ERROR )
{
break;
}
}
}
else
{
if ( pDevObj != NULL )
{
pDevObj->fFlags &= ~DEV_OBJ_OPENED_FOR_DIALOUT;
pDevObj->hRasConn = (HRASCONN)NULL;
}
}
DDM_PRINT(gblDDMConfigInfo.dwTraceId, TRACE_FSM,
"RasConnectCallback:Could not connect to SubEntry %d,dwError=%d",
dwSubEntryId, dwError );
//
// Has the bundle failed to connect?
//
pIfObject = IfObjectGetPointer( hDIMInterface );
if ( pIfObject == NULL )
{
RTASSERT( FALSE );
dwError = ERROR_NO_SUCH_INTERFACE;
break;
}
--pIfObject->dwNumSubEntriesCounter;
if ( ( pIfObject->dwNumSubEntriesCounter == 0 ) ||
( RasConnState == RASCS_Disconnected ) ||
!(pIfObject->fFlags & IFFLAG_DIALMODE_DIALALL))
{
if ( pIfObject->State == RISTATE_CONNECTED )
{
//
// Interface is already connected so it doesn't matter if this
// device failed.
//
break;
}
DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
"RasConnectCallback:Could not connect to interface %ws",
pIfObject->lpwsInterfaceName );
DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
"RasConnectCallback: hanging up 0x%x", pIfObject->hRasConn);
RasHangUp( pIfObject->hRasConn );
pIfObject->hRasConn = (HRASCONN)NULL;
//
// If the admin as initiated a disconnect or we are out of
// retries
//
if ( ( pIfObject->fFlags & IFFLAG_DISCONNECT_INITIATED ) ||
( pIfObject->dwNumOfReConnectAttemptsCounter == 0 ) )
{
//
// Mark as unreachable due to connection failure the admin did
// not disconnect.
//
if ( !( pIfObject->fFlags & IFFLAG_DISCONNECT_INITIATED ) )
{
pIfObject->fFlags |= IFFLAG_CONNECTION_FAILURE;
}
IfObjectDisconnected( pIfObject );
IfObjectNotifyOfReachabilityChange(
pIfObject,
FALSE,
INTERFACE_CONNECTION_FAILURE );
//
// If we were disconnected by the admin then we should
// immediately go to the reachable state.
//
if ( pIfObject->fFlags & IFFLAG_DISCONNECT_INITIATED )
{
IfObjectNotifyOfReachabilityChange(
pIfObject,
TRUE,
INTERFACE_CONNECTION_FAILURE );
}
pIfObject->dwLastError = dwError;
if ( pDevObj != NULL )
{
lpwsAudit[0] = pIfObject->lpwsInterfaceName;
lpwsAudit[1] = pDevObj->wchPortName;
DDMLogErrorString( ROUTERLOG_CONNECTION_ATTEMPT_FAILED,
2, lpwsAudit, dwError, 2 );
}
//
// If this was initiated by an admin api. Let the caller
// know that we are not connected.
//
if (pIfObject->hEventNotifyCaller != INVALID_HANDLE_VALUE)
{
SetEvent( pIfObject->hEventNotifyCaller );
CloseHandle( pIfObject->hEventNotifyCaller );
pIfObject->hEventNotifyCaller = INVALID_HANDLE_VALUE;
}
}
else
{
//
// Otherwise we try again
//
pIfObject->dwNumOfReConnectAttemptsCounter--;
//
// Stagger the reconnectime randomly between 0 and twice the
// configured reconnect time.
//
srand( (unsigned)time( NULL ) );
TimerQInsert(
pIfObject->hDIMInterface,
rand()%((pIfObject->dwSecondsBetweenReConnectAttempts*2)+1),
ReConnectInterface );
}
}
}
while( FALSE );
LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) );
LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
return( TRUE );
}
//**
//
// Call: RasConnectionInitiate
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description: Called to initiate a demand-dial connection
//
DWORD
RasConnectionInitiate(
IN ROUTER_INTERFACE_OBJECT * pIfObject,
IN BOOL fRedialAttempt
)
{
RASDIALEXTENSIONS RasDialExtensions;
RASDIALPARAMS RasDialParams;
DWORD dwXportIndex;
DWORD dwRetCode;
RASENTRY re;
DWORD dwSize;
RASEAPUSERIDENTITY* pRasEapUserIdentity = NULL;
//
// Do not try to connect if the interface is disabled or out of resources
// or the service is paused or the interface is marked as unreachable due
// to connection failure.
//
if ( !( pIfObject->fFlags & IFFLAG_ENABLED ) )
{
return( ERROR_INTERFACE_DISABLED );
}
if ( pIfObject->fFlags & IFFLAG_OUT_OF_RESOURCES )
{
return( ERROR_INTERFACE_HAS_NO_DEVICES );
}
if ( gblDDMConfigInfo.pServiceStatus->dwCurrentState == SERVICE_PAUSED )
{
return( ERROR_SERVICE_IS_PAUSED );
}
//
// If this is not a redial attempt then we reset the reconnect attempts
// counter and unset the admin disconnected flag if it was set.
//
if ( !fRedialAttempt )
{
pIfObject->dwNumOfReConnectAttemptsCounter =
pIfObject->dwNumOfReConnectAttempts;
pIfObject->fFlags &= ~IFFLAG_DISCONNECT_INITIATED;
}
else
{
//
// Do not allow the reconnect attempt to go thru if the admin has
// disconnected this interface.
//
if ( pIfObject->fFlags & IFFLAG_DISCONNECT_INITIATED )
{
return( ERROR_INTERFACE_DISCONNECTED );
}
}
//
// Build PppInterfaceInfo structure to pass down to RasDial that will pass
// it on to PPP.
//
for ( dwXportIndex = 0;
dwXportIndex < gblDDMConfigInfo.dwNumRouterManagers;
dwXportIndex++ )
{
switch( gblRouterManagers[dwXportIndex].DdmRouterIf.dwProtocolId )
{
case PID_IPX:
if (pIfObject->Transport[dwXportIndex].fState & RITRANSPORT_ENABLED)
{
pIfObject->PppInterfaceInfo.hIPXInterface =
pIfObject->Transport[dwXportIndex].hInterface;
}
else
{
pIfObject->PppInterfaceInfo.hIPXInterface=INVALID_HANDLE_VALUE;
}
break;
case PID_IP:
if (pIfObject->Transport[dwXportIndex].fState & RITRANSPORT_ENABLED)
{
pIfObject->PppInterfaceInfo.hIPInterface =
pIfObject->Transport[dwXportIndex].hInterface;
}
else
{
pIfObject->PppInterfaceInfo.hIPInterface = INVALID_HANDLE_VALUE;
}
break;
default:
RTASSERT( FALSE );
break;
}
}
pIfObject->PppInterfaceInfo.IfType = pIfObject->IfType;
pIfObject->dwNumSubEntriesCounter = pIfObject->dwNumSubEntries;
//
// Initiate the connection
//
ZeroMemory( &RasDialExtensions, sizeof( RasDialExtensions ) );
RasDialExtensions.dwSize = sizeof( RasDialExtensions );
RasDialExtensions.dwfOptions = RDEOPT_Router;
RasDialExtensions.reserved = (ULONG_PTR)&(pIfObject->PppInterfaceInfo);
ZeroMemory( &RasDialParams, sizeof( RasDialParams ) );
RasDialParams.dwSize = sizeof( RasDialParams );
RasDialParams.dwCallbackId = PtrToUlong(pIfObject->hDIMInterface);
RasDialParams.dwSubEntry = 0;
wcscpy( RasDialParams.szCallbackNumber, TEXT("*") );
wcscpy( RasDialParams.szEntryName, pIfObject->lpwsInterfaceName );
//
// Do we need to call RasEapGetIdentity?
//
dwRetCode = RasGetEapUserIdentity(
gblpRouterPhoneBook,
pIfObject->lpwsInterfaceName,
RASEAPF_NonInteractive,
NULL,
&pRasEapUserIdentity);
if ( ERROR_INVALID_FUNCTION_FOR_ENTRY == dwRetCode )
{
//
// This entry does not require RasEapGetIdentity. Get its credentials.
//
dwRetCode = MprAdminInterfaceGetCredentialsInternal(
NULL,
pIfObject->lpwsInterfaceName,
(LPWSTR)&(RasDialParams.szUserName),
(LPWSTR)&(RasDialParams.szPassword),
(LPWSTR)&(RasDialParams.szDomain) );
if ( dwRetCode != NO_ERROR )
{
return( ERROR_NO_INTERFACE_CREDENTIALS_SET );
}
}
else if ( NO_ERROR != dwRetCode )
{
if ( ERROR_INTERACTIVE_MODE == dwRetCode )
{
dwRetCode = ERROR_NO_INTERFACE_CREDENTIALS_SET;
}
return( dwRetCode );
}
else
{
wcscpy( RasDialParams.szUserName, pRasEapUserIdentity->szUserName );
RasDialExtensions.RasEapInfo.dwSizeofEapInfo =
pRasEapUserIdentity->dwSizeofEapInfo;
RasDialExtensions.RasEapInfo.pbEapInfo =
pRasEapUserIdentity->pbEapInfo;
}
if( (0 != gblDDMConfigInfo.cDigitalIPAddresses)
|| (0 != gblDDMConfigInfo.cAnalogIPAddresses))
{
ZeroMemory(&re, sizeof(RASENTRY));
re.dwSize = sizeof(RASENTRY);
dwSize = sizeof(RASENTRY);
if(ERROR_SUCCESS == (dwRetCode = RasGetEntryProperties(
gblpRouterPhoneBook,
pIfObject->lpwsInterfaceName,
&re,
&dwSize,
NULL,
NULL)))
{
if(RASET_Vpn == re.dwType)
{
char *pszMungedPhoneNumber = NULL;
char szPhoneNumber[RAS_MaxPhoneNumber + 1];
WCHAR wszMungedPhoneNumber[RAS_MaxPhoneNumber + 1];
//
// Convert the phonenumber to ansi
//
WideCharToMultiByte(
CP_ACP,
0,
re.szLocalPhoneNumber,
-1,
szPhoneNumber,
sizeof( szPhoneNumber ),
NULL,
NULL );
//
// Munge the phonenumber
//
dwRetCode = MungePhoneNumber(
szPhoneNumber,
gblDDMConfigInfo.dwIndex,
&dwSize,
&pszMungedPhoneNumber);
if(ERROR_SUCCESS == dwRetCode)
{
//
// Change the munged phonenumber to widechar
//
MultiByteToWideChar( CP_ACP,
0,
pszMungedPhoneNumber,
-1,
wszMungedPhoneNumber,
RAS_MaxPhoneNumber + 1);
if ( wcslen( wszMungedPhoneNumber ) <= RAS_MaxPhoneNumber)
{
wcscpy( RasDialParams.szPhoneNumber,
wszMungedPhoneNumber );
DDM_PRINT(gblDDMConfigInfo.dwTraceId, TRACE_FSM,
"Munged Phone Number=%ws",
RasDialParams.szPhoneNumber);
//
// Increase the index so that we try the
// next FEP the next time this is dialed.
//
gblDDMConfigInfo.dwIndex += 1;
LocalFree( pszMungedPhoneNumber );
}
}
}
}
}
dwRetCode = RasDial( &RasDialExtensions,
gblpRouterPhoneBook,
&RasDialParams,
2,
RasConnectCallback,
&(pIfObject->hRasConn) );
//
// Zero out these since they contained sensitive password information
//
ZeroMemory( &RasDialParams, sizeof( RasDialParams ) );
RasFreeEapUserIdentity( pRasEapUserIdentity );
if ( dwRetCode != NO_ERROR )
{
return( dwRetCode );
}
pIfObject->State = RISTATE_CONNECTING;
pIfObject->fFlags |= IFFLAG_LOCALLY_INITIATED;
return( NO_ERROR );
}