Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1350 lines
35 KiB

/**********************************************************************/
/** Microsoft Windows **/
/** Copyright(c) Microsoft Corp., 1994 **/
/**********************************************************************/
/*
Init.c
Contains VxD initialization code
FILE HISTORY:
Johnl 24-Mar-1993 Created
*/
#include <vxdprocs.h>
#include <tdiinfo.h>
#include <ipinfo.h>
#include <llinfo.h>
#include <debug.h>
#include "local.h"
//
// Renewal timer
//
CTETimer RenewalTimer ;
//
// Event for rescheduling ProcessDhcpRequestForever
//
CTEEvent ProcessEvent ;
extern TDIDispatchTable * TdiDispatch ;
extern VOID ReleaseBlockedSockets( VOID );
#ifdef CHICAGO
extern VOID PTEXTBegin( VOID );
extern VOID PTEXTEnd( VOID );
#endif
#ifdef USE_WORKER_THREAD
BOOL ThreadRunning;
typedef VOID (* LPRING0THREADSTART)( LPVOID Param );
VOID
CreateRing0Thread(
LPRING0THREADSTART ThreadStart,
LPVOID ThreadParameter
);
VOID
DhcpRing0WorkerThread(
LPVOID Param
);
#endif // USE_WORKER_THREAD
VOID
DelayedProcessDhcpRequest(
CTEEvent * pCTEEvent,
PVOID pContext
);
#ifdef CHICAGO
DWORD
DhcpRequestAddress(
ushort IpContext
);
VOID
DhcpProcessTcpUnloadWorker(
PCHAR VxdName
);
VOID
DhcpProcessTcpLoadWorker(
PCHAR VxdName
);
DWORD
DhcpRemakeTdiDispatchPtr(
VOID
);
TDI_STATUS
IPBindingChangeNotification(
USHORT IpContext,
DWORD fNew
);
#endif // CHICAGO
#ifdef DEBUG
//
// Notifies clients every x seconds that there IP address has changed
//
CTETimer DbgNotificationTimer ;
ULONG DbgNotifyTime = 0 ; // Set to non-zero to enable (in ms)
VOID
DbgNotificationRoutine(
CTEEvent * pCTEEvent,
PVOID pContext
) ;
#endif //DEBUG
//
// Flag indicating refilling the heap is Ok
//
BOOL fInInit = TRUE ;
extern LIST_ENTRY NotifyListHead ;
extern DWORD DhcpGlobalDisplayPopups;
BOOL ScanIpEntities( BOOL ContextLookup, ushort IpContext );
TDI_STATUS FindHardwareAddr( TDIEntityID Elist[],
UINT cEntities,
IPAddrEntry * pIAE,
HARDWARE_ADDRESS * pHardwareAddress,
BYTE *pHardwareAddressType,
BOOL * pfFound,
ULONG * pIfIndex,
DWORD * pdwIpInterfaceInstance );
//
// Some debug support stuff
//
#ifdef DEBUG
DWORD DebugFlags = DEBUG_ERRORS ;
char DBOut[4096] ;
int iCurPos = 0 ;
void NbtDebugOut( char * str )
{
if ( DebugFlags & (DBGFLAG_AUX_OUTPUT | DEBUG_ERRORS ))
CTEPrint( str ) ;
if ( sizeof(DBOut) - iCurPos < 256 )
iCurPos = 0 ;
else
iCurPos += strlen( str ) + 1 ;
}
#endif
//******************* Pageable Routine Declarations ****************
#ifdef ALLOC_PRAGMA
#pragma CTEMakePageable(INIT, DhcpInit )
#pragma CTEMakePageable(INIT, VxdReadIniString )
#pragma CTEMakePageable(PAGEDHCP, ScanIpEntities )
#pragma CTEMakePageable(PAGEDHCP, FindHardwareAddr )
#pragma CTEMakePageable(PAGEDHCP, DelayedProcessDhcpRequest )
#pragma CTEMakePageable(PAGEDHCP, CTEAllocInitMem )
#pragma CTEMakePageable(PAGEDHCP, DhcpRequestAddress )
#pragma CTEMakePageable(PAGEDHCP, DhcpProcessTcpUnloadWorker )
#pragma CTEMakePageable(PAGEDHCP, DhcpProcessTcpLoadWorker )
#pragma CTEMakePageable(PAGEDHCP, IPBindingChangeNotification )
#endif ALLOC_PRAGMA
//*******************************************************************
#pragma BEGIN_INIT
/*******************************************************************
NAME: DhcpInit
SYNOPSIS: Performs all driver initialization
RETURNS: TRUE if initialization successful, FALSE otherwise
NOTES:
HISTORY:
Johnl 24-Mar-1993 Created
********************************************************************/
int DhcpInit( void )
{
NTSTATUS status ;
int i ;
DWORD TimeToSleep ;
PDHCP_CONTEXT pDhcpContext ;
PLIST_ENTRY pEntry ;
if ( CTEInitialize() )
{
DbgPrint("Init: CTEInitialize succeeded\n\r") ;
}
else
return FALSE ;
CTEInitTimer( &RenewalTimer ) ;
CTERefillMem() ;
if ( !InitFileSupport() )
{
CDbgPrint( DEBUG_ERRORS, ("Init: InitFileSupport failed\r\n")) ;
return FALSE ;
}
if ( !InitMsgSupport() )
{
CDbgPrint( DEBUG_ERRORS, ("Init: InitMsgSupport failed\r\n")) ;
return FALSE ;
}
DhcpGlobalDisplayPopups = TRUE;
InitializeListHead( &DhcpGlobalRenewList ) ;
InitializeListHead( &DhcpGlobalNICList ) ;
InitializeListHead( &LocalDhcpBinList ) ;
InitializeListHead( &NotifyListHead ) ;
//
// Get the Addresses/Leases from the configuration file from the last boot
//
if ( BuildDhcpWorkList() )
{
CDbgPrint( DEBUG_ERRORS, ("Init: Failed to build worker list\r\n")) ;
return FALSE ;
}
//
// Analyze the list, attempt to get new IP addresses as appropriate.
//
DhcpInitialize( NULL ) ;
#if !defined(CHICAGO)
//
// Find all Lanas that the IP driver wants DHCPed
//
if ( !ScanIpEntities( FALSE, 0 ) )
{
CDbgPrint( DEBUG_ERRORS, ("Init: Failed to get addresses from IP driver\r\n")) ;
return FALSE ;
}
#else // !CHICAGO
//
// register IP binding changing notification handle.
//
if ( !IPRegisterBindingChangeHandler( IPBindingChangeNotification, TRUE ) ) {
CDbgPrint( DEBUG_ERRORS, ("Init: Failed to register with IP driver\r\n")) ;
return FALSE ;
}
//
// register load and unload functions.
//
CTESetUnloadNotifyProc( DhcpProcessTcpUnloadWorker );
CTESetLoadNotifyProc( DhcpProcessTcpLoadWorker );
#endif // !CHICAGO
//
// Kickoff the renewal timer
//
ProcessDhcpRequestForever( NULL, NULL ) ;
#ifdef DEBUG
if ( DbgNotifyTime )
DbgNotificationRoutine( NULL, NULL ) ;
#endif
CTERefillMem() ;
fInInit = FALSE ;
return TRUE ;
}
#pragma END_INIT
#ifndef CHICAGO
#pragma BEGIN_INIT
#endif // !CHICAGO
/*******************************************************************
NAME: ScanIpEntities
SYNOPSIS: Scans the IP entities and the IP address tables managed
by those entities looking for either a) zero IP addresses
or b) an address with a specified IP context.
ENTRY: ContextLookup - If TRUE, then look for an address entry
with a specific IP context value. Otherwise, look
for entries with zero IP addresses.
IpContext - The IP context to search for. Ignored if
ContextLookup is not TRUE.
EXIT: Newly active IP addresses are added to the DhcpGlobalNICList
and previously configured addresses are moved from
LocalDhcpBinList to DhcpGlobalNICList.
RETURNS: TRUE if successful, FALSE otherwise.
HISTORY: 8/26/96 Frankbee moved TDIEntityID list off the stack
********************************************************************/
BOOL ScanIpEntities( BOOL ContextLookup, ushort IpContext )
{
NTSTATUS status ;
TDI_STATUS tdistatus ;
DWORD err ;
int i, j ;
PDHCP_CONTEXT pDhcpContext ;
PLIST_ENTRY pEntry ;
uchar Context[CONTEXT_SIZE] ;
TDIObjectID ID ;
TDIEntityID *EList;
DWORD dwIpInterfaceInstance;
ULONG Size ;
UINT NumReturned ;
NDIS_BUFFER ndisbuff ;
CTEPagedCode();
ASSERT( TdiDispatch != NULL );
Size = MAX_TDI_ENTITIES * sizeof( TDIEntityID );
EList = ( TDIEntityID * ) CTEAllocMem( Size );
if ( !EList )
return FALSE;
//
// The first thing to do is get the list of available entities, and make
// sure that there are some interface entities present.
//
ID.toi_entity.tei_entity = GENERIC_ENTITY;
ID.toi_entity.tei_instance = 0;
ID.toi_class = INFO_CLASS_GENERIC;
ID.toi_type = INFO_TYPE_PROVIDER;
ID.toi_id = ENTITY_LIST_ID;
InitNDISBuff( &ndisbuff, EList, Size, NULL ) ;
memset(Context, 0, CONTEXT_SIZE);
tdistatus = TdiVxdQueryInformationEx( 0,
&ID,
&ndisbuff,
&Size,
Context);
if (tdistatus != TDI_SUCCESS)
{
CDbgPrint( DEBUG_ERRORS, ("ScanIpEntities: Querying entity list failed\r\n")) ;
CTEFreeMem( EList );
return FALSE ;
}
NumReturned = (uint)Size/sizeof(TDIEntityID);
for (i = 0; i < NumReturned; i++)
{
if ( EList[i].tei_entity == CL_NL_ENTITY )
{
IPSNMPInfo IPStats ;
IPAddrEntry * pIAE ;
ULONG NLType ;
//
// Does this entity support IP?
//
ID.toi_entity.tei_entity = EList[i].tei_entity ;
ID.toi_entity.tei_instance = EList[i].tei_instance;
ID.toi_class = INFO_CLASS_GENERIC ;
ID.toi_type = INFO_TYPE_PROVIDER;
ID.toi_id = ENTITY_TYPE_ID ;
Size = sizeof( NLType );
InitNDISBuff( &ndisbuff, &NLType, Size, NULL ) ;
memset(Context, 0, CONTEXT_SIZE);
tdistatus = TdiVxdQueryInformationEx( 0,
&ID,
&ndisbuff,
&Size,
Context);
if ( tdistatus != TDI_SUCCESS )
{
CDbgPrint( DEBUG_ERRORS, ("ScanIpEntities: Getting NL type failed\r\n")) ;
continue ;
}
if ( NLType != CL_NL_IP )
continue ;
//
// We've got an IP driver so get it's address table
//
ID.toi_class = INFO_CLASS_PROTOCOL ;
ID.toi_id = IP_MIB_STATS_ID;
Size = sizeof(IPStats);
InitNDISBuff( &ndisbuff, &IPStats, Size, NULL ) ;
memset(Context, 0, CONTEXT_SIZE);
tdistatus = TdiVxdQueryInformationEx( 0,
&ID,
&ndisbuff,
&Size,
Context);
if ( tdistatus != TDI_SUCCESS )
{
CDbgPrint( DEBUG_ERRORS, ("ScanIpEntities: Getting IPStats failed\r\n")) ;
continue ;
}
if ( IPStats.ipsi_numaddr < 1 )
{
CDbgPrint( DEBUG_ERRORS, ("ScanIpEntities: No IP Addresses installed\r\n")) ;
continue ;
}
Size = sizeof(IPAddrEntry) * IPStats.ipsi_numaddr ;
if ( !(pIAE = (IPAddrEntry*) CTEAllocInitMem( (USHORT) Size )) )
{
CDbgPrint( DEBUG_ERRORS, ("ScanIpEntities: Couldn't allocate IP table buffer\r\n")) ;
CTEFreeMem( EList );
return FALSE ;
}
ID.toi_id = IP_MIB_ADDRTABLE_ENTRY_ID ;
InitNDISBuff( &ndisbuff, pIAE, Size, NULL ) ;
memset( Context, 0, CONTEXT_SIZE ) ;
tdistatus = TdiVxdQueryInformationEx( 0,
&ID,
&ndisbuff,
&Size,
Context);
if ( tdistatus != TDI_SUCCESS )
{
CDbgPrint( DEBUG_ERRORS, ("ScanIpEntities: Getting IP address table failed\r\n")) ;
CTEFreeMem( pIAE ) ;
continue ;
}
//
// ASSERT( Size/sizeof(IPAddrEntry) == IPStats.ipsi_numaddr ) ;
//
// the above assert becomes false when a new ip entry is
// added to the system between the above two
// tdi queries. It is enough just to process as many
// entries we found in the first call, since the ip entry we
// want should be within that.
//
//
// We have the IP address table for this IP driver. Look for
// DHCPable IP addresses and find the corresponding interface
// and get its hardware address
//
for ( j = 0 ; j < IPStats.ipsi_numaddr ; j++ )
{
#if defined(CHICAGO)
if(
( ContextLookup && ( pIAE[j].iae_context == IpContext ) ) ||
( pIAE[j].iae_addr == 0 ) )
#endif // defined(CHICAGO)
{
HARDWARE_ADDRESS HardwareAddress ;
BYTE HardwareAddressType;
ULONG IfIndex ;
BOOL fFound ;
tdistatus = FindHardwareAddr( EList,
NumReturned,
&pIAE[j],
&HardwareAddress,
&HardwareAddressType,
&fFound,
&IfIndex,
&dwIpInterfaceInstance ) ;
if ( tdistatus != TDI_SUCCESS )
{
CDbgPrint( DEBUG_ERRORS, ("ScanIpEntities: Hardware search failed\r\n")) ;
CTEFreeMem( pIAE ) ;
CTEFreeMem( EList );
return FALSE ;
}
else if ( !fFound )
{
CDbgPrint( DEBUG_ERRORS, ("ScanIpEntities: Warning - Couldn't find hardware address\r\n")) ;
continue ;
}
#ifdef USE_WORKER_THREAD
//
// we shouldn't be running the worker thread that performs the
// discovery/renew while we are adding another card.
//
ASSERT( ThreadRunning == FALSE );
#endif
//
// Let DhcpInitializeAdapter do the dirty work.
//
status = DhcpInitializeAdapter(
pIAE[j].iae_context,
pIAE[j].iae_addr,
IfIndex,
EList[i].tei_instance,
&HardwareAddress,
HardwareAddressType,
dwIpInterfaceInstance );
if( ContextLookup )
{
CTEFreeMem( EList );
return status == 0;
}
} // matching context or addr == 0
} // addr traversal
CTEFreeMem( pIAE ) ;
} // if IP
} // entity traversal
CTEFreeMem( EList );
return TRUE ;
}
/*******************************************************************
NAME: FindHardwareAddr
SYNOPSIS: Given an entity list and an IP Address Entry, all interfaces
are searched until a match is found.
ENTRY: EList - Filled in entity list
cEntities - Number of entities in the list
pIAE - IP Address entry to use as the key
pHardwareAddress - Physical address will be copied here
pHardwareAddressType - address type will be copied here
pfFound - TRUE if address found, FALSE otherwise
pIfIndex - Interface index of hardware address
RETURNS: TDI error
NOTES:
********************************************************************/
TDI_STATUS FindHardwareAddr( TDIEntityID EList[],
UINT cEntities,
IPAddrEntry * pIAE,
HARDWARE_ADDRESS * pHardwareAddress,
BYTE *pHardwareAddressType,
BOOL * pfFound,
ULONG * pIfIndex,
DWORD * pdwIpInterfaceInstance )
{
int i ;
uchar Context[CONTEXT_SIZE] ;
TDIObjectID ID ;
TDI_STATUS tdistatus ;
ULONG Size ;
NDIS_BUFFER ndisbuff ;
CTEPagedCode();
ASSERT( TdiDispatch != NULL );
*pfFound = FALSE ;
ID.toi_entity.tei_entity = IF_MIB ;
ID.toi_type = INFO_TYPE_PROVIDER;
for ( i = 0 ; i < cEntities ; i++ )
{
if (EList[i].tei_entity == IF_ENTITY)
{
IFEntry IFE ;
ULONG IFType ;
//
// Check and make sure the interface supports MIB-2
//
ID.toi_entity.tei_entity = EList[i].tei_entity ;
ID.toi_entity.tei_instance = EList[i].tei_instance;
ID.toi_class = INFO_CLASS_GENERIC ;
ID.toi_id = ENTITY_TYPE_ID ;
Size = sizeof( IFType );
InitNDISBuff( &ndisbuff, &IFType, Size, NULL ) ;
memset(Context, 0, CONTEXT_SIZE);
tdistatus = TdiVxdQueryInformationEx( 0,
&ID,
&ndisbuff,
&Size,
Context);
if ( tdistatus != TDI_SUCCESS )
{
CDbgPrint( DEBUG_ERRORS, ("FindHardwareAddr: Getting IF type failed\r\n")) ;
return tdistatus ;
}
if ( IFType != IF_MIB )
continue ;
//
// We've found an interface, get its index and see if it
// matches the IP Address entry
//
ID.toi_class = INFO_CLASS_PROTOCOL ;
ID.toi_id = IF_MIB_STATS_ID;
Size = sizeof(IFEntry);
memset(Context, 0, CONTEXT_SIZE);
InitNDISBuff( &ndisbuff, &IFE, Size, NULL ) ;
tdistatus = TdiVxdQueryInformationEx( 0,
&ID,
&ndisbuff,
&Size,
Context);
if ( tdistatus != TDI_SUCCESS &&
tdistatus != TDI_BUFFER_OVERFLOW )
{
CDbgPrint( DEBUG_ERRORS, ("FindHardwareAddr: Getting interface info failed\r\n")) ;
return tdistatus ;
}
if ( IFE.if_index == pIAE->iae_index )
{
ASSERT( IFE.if_physaddrlen <= sizeof( pHardwareAddress->Address )) ;
pHardwareAddress->Length =
min( sizeof( pHardwareAddress->Address ),
IFE.if_physaddrlen ) ;
memcpy( pHardwareAddress->Address,
IFE.if_physaddr,
pHardwareAddress->Length ) ;
//
// set address type.
//
switch( IFE.if_type ) {
case IF_TYPE_ETHERNET:
*pHardwareAddressType = HARDWARE_TYPE_10MB_EITHERNET;
break;
case IF_TYPE_TOKENRING:
case IF_TYPE_FDDI:
*pHardwareAddressType = HARDWARE_TYPE_IEEE_802;
break;
case IF_TYPE_OTHER:
*pHardwareAddressType = HARDWARE_ARCNET;
break;
default:
CDbgPrint( DEBUG_ERRORS, ("FindHardwareAddr: Invalid HW Type.\n"));
ASSERT( FALSE );
*pHardwareAddressType = HARDWARE_ARCNET;
break;
}
*pIfIndex = IFE.if_index ;
*pdwIpInterfaceInstance = ID.toi_entity.tei_instance;
*pfFound = TRUE ;
return TDI_SUCCESS ;
}
}
}
return TDI_SUCCESS ;
}
#ifndef CHICAGO
#pragma END_INIT
#endif // !CHICAGO
VOID
ProcessDhcpRequestForever(
CTEEvent * pCTEEvent,
PVOID pContext
)
/*++
Routine Description:
This function processes DHCP renewals. To reset the sleep time, simply
call this function again. The existing timer will be stopped and the
new sleep time will be recalculated.
BUGBUG: currently the global pointers are not producted under multi
threaded environment. We need a synchronization object to do that.
Arguments:
None.
--*/
{
//
// If we're in the midst of initializing ourselves, just
// call through directly to DelayedProcessDhcpRequest. Otherwise,
// schedule an event so we'll get called at a more friendly time.
//
if( fInInit )
{
DelayedProcessDhcpRequest( pCTEEvent, pContext );
}
else
{
#ifdef USE_WORKER_THREAD
//
// we shouldn't be running the worker thread that performs the
// discovery/renew while we are here.
//
// ASSERT( ThreadRunning == FALSE );
if( !ThreadRunning )
{
ThreadRunning = TRUE;
CreateRing0Thread( DhcpRing0WorkerThread, pContext );
}
#else // !USE_WORKER_THREAD
CTEInitEvent( &ProcessEvent, DelayedProcessDhcpRequest );
CTEScheduleEvent( &ProcessEvent, pContext );
#endif // USE_WORKER_THREAD
}
} // ProcessDhcpRequestForever
#ifdef USE_WORKER_THREAD
VOID
DhcpRing0WorkerThread(
LPVOID Param
)
/*++
Routine Description:
This is the entrypoint for the DHCP renewal worker thread. If TCP
is loaded, then this function just calls through to the common
worker function.
Arguments:
Param - Generic thread parameter. In reality, this is the DHCP
context value.
--*/
{
BOOLEAN CodeLocked = FALSE;
if ( !VxdLockCode( PTEXTBegin, PTEXTEnd ) ) {
CDbgPrint( DEBUG_ERRORS, ("DhcpRing0WorkerThread: Could not lock vdhcp code \r\n")) ;
CTEStopTimer( &RenewalTimer ) ; // Ok even if timer not running
CTEInitTimer( &RenewalTimer ) ;
// Just restart the timer which will expire in 5 seconds
if ( !CTEStartTimer( &RenewalTimer,
5 * 1000,
ProcessDhcpRequestForever,
NULL ))
{
CDbgPrint( DEBUG_ERRORS, ("DhcpRing0WorkerThread: Warning - Failed to start timer!!\r\n")) ;
}
ThreadRunning = FALSE;
} else {
CodeLocked = TRUE;
CDbgPrint( DEBUG_MISC, ("DhcpRing0WorkerThread: successfully locked vdhcp code \r\n")) ;
}
if( TdiDispatch != NULL )
{
DelayedProcessDhcpRequest( NULL, Param );
}
if ( CodeLocked ) {
if ( !VxdUnLockCode( PTEXTBegin, PTEXTEnd ) ) {
CDbgPrint( DEBUG_ERRORS, ("DhcpRing0WorkerThread: Could not unlock vdhcp code \r\n")) ;
} else {
CDbgPrint( DEBUG_MISC, ("DhcpRing0WorkerThread: successfully unlocked vdhcp code \r\n")) ;
}
}
} // DhcpRing0WorkerThread
#endif // USE_WORKER_THREAD
VOID
DelayedProcessDhcpRequest(
CTEEvent * pCTEEvent,
PVOID pContext
)
/*++
Routine Description:
This function processes DHCP renewals. To reset the sleep time, simply
call this function again. The existing timer will be stopped and the
new sleep time will be recalculated.
Arguments:
None.
--*/
{
DWORD LocalTimeToSleep ;
PDHCP_CONTEXT DhcpContext;
time_t TimeNow;
PLIST_ENTRY ListEntry;
CTEPagedCode();
LocalTimeToSleep = INFINIT_LEASE;
TimeNow = time( NULL );
//
// Loop through the list of DHCP contexts looking for any
// renewals to run. Also, reset timeToSleep to the nearest
// future renewal.
//
for( ListEntry = DhcpGlobalRenewList.Flink;
ListEntry != &DhcpGlobalRenewList;
ListEntry = ListEntry->Flink ) {
DhcpContext = CONTAINING_RECORD(
ListEntry,
DHCP_CONTEXT,
RenewalListEntry );
//
// If it is time to run this renewal function, remove the
// renewal context from the list.
//
if ( DhcpContext->RunTime <= TimeNow ) {
//
// This client has to renew NOW.
//
// This client is removed from the list for renewal,
// when the renewal is performed this entry will be
// queued again
//
RemoveEntryList( &DhcpContext->RenewalListEntry );
DhcpContext->RenewalFunction( DhcpContext, &LocalTimeToSleep );
//
// reset the traverse pointer to the begining of the list.
// Since the list has been modified above.
//
ListEntry = DhcpGlobalRenewList.Flink;
} else {
DWORD ElapseTime;
ElapseTime = DhcpContext->RunTime - TimeNow;
if ( LocalTimeToSleep > ElapseTime ) {
LocalTimeToSleep = ElapseTime;
}
}
}
//
// This list may be empty or only contain infinitely leased items
//
if ( LocalTimeToSleep == INFINIT_LEASE )
{
#ifndef CHICAGO
//
// This is S.O.P. for Chicago Plug & Play. For Snowball,
// we'll whine about it.
//
DbgPrint("DelayedProcessDhcpRequest: Infinite lease, disabling renewal list timer\r\n") ;
#endif // !CHICAGO
CTEStopTimer( &RenewalTimer ) ;
goto CommonExit;
}
DhcpPrint(( DEBUG_MISC, "DelayedProcessDhcpRequest: Sleeping for 0x%x seconds", LocalTimeToSleep )) ;
CTEStopTimer( &RenewalTimer ) ; // Ok even if timer not running
CTEInitTimer( &RenewalTimer ) ;
//
// don't sleep more than a day long.
//
if( LocalTimeToSleep > DAY_LONG_SLEEP ) {
LocalTimeToSleep = DAY_LONG_SLEEP;
}
//
// For test purposes!! Renew every thirty seconds
//
//LocalTimeToSleep = 30 ;
//
if ( !CTEStartTimer( &RenewalTimer,
LocalTimeToSleep * 1000,
ProcessDhcpRequestForever,
NULL ))
{
CDbgPrint( DEBUG_ERRORS, ("DelayedProcessDhcpRequest: Warning - Failed to start timer!!\r\n")) ;
}
CommonExit:;
#ifdef USE_WORKER_THREAD
ThreadRunning = FALSE;
#endif // USE_WORKER_THREAD
} // DelayedProcessDhcpRequest
#pragma BEGIN_INIT
/*******************************************************************
NAME: VxdReadIniString
SYNOPSIS: Vxd stub for CTEReadIniString
ENTRY: pchKey - Key value to look for in the Network section
ppchString - Pointer to buffer found string is returned in
EXIT: ppchString will point to an allocated buffer
RETURNS: STATUS_SUCCESS if found
NOTES: The client must free ppchString when done with it
HISTORY:
Johnl 30-Aug-1993 Created
********************************************************************/
CHAR * DhcpGetProfileString( LPTSTR pchKey, LPTSTR * pchDefault ) ;
NTSTATUS VxdReadIniString( LPSTR pchKey, LPSTR * ppchString )
{
char * pchTmp ;
if ( pchTmp = DhcpGetProfileString( pchKey, NULL ) )
{
if ( *ppchString = CTEAllocInitMem( (USHORT) (strlen( pchTmp ) + 1)))
{
strcpy( *ppchString, pchTmp ) ;
return STATUS_SUCCESS ;
}
else
return STATUS_INSUFFICIENT_RESOURCES ;
}
return STATUS_UNSUCCESSFUL ;
}
#pragma END_INIT
//
// Allow this to be called during non-init but don't retry if non-init
//
PVOID CTEAllocInitMem( USHORT cbBuff )
{
PVOID pv = CTEAllocMem( cbBuff ) ;
CTEPagedCode();
if ( pv )
{
return pv ;
}
else if ( fInInit )
{
CDbgPrint( DEBUG_ERRORS, ("CTEAllocInitMem: Failed allocation, trying again\r\n")) ;
CTERefillMem() ;
pv = CTEAllocMem( cbBuff ) ;
}
return pv ;
}
#ifdef DEBUG
VOID
DbgNotificationRoutine(
CTEEvent * pCTEEvent,
PVOID pContext
)
/*++
Routine Description:
This function can be used for testing the client's DHCP change of
address notification code
Arguments:
None.
--*/
{
PDHCP_CONTEXT DhcpContext;
PLIST_ENTRY ListEntry;
for( ListEntry = DhcpGlobalRenewList.Flink;
ListEntry != &DhcpGlobalRenewList;
ListEntry = ListEntry->Flink ) {
DhcpContext = CONTAINING_RECORD(
ListEntry,
DHCP_CONTEXT,
RenewalListEntry );
//
// This just sets the old address to the new address
//
NotifyClients( DhcpContext,
DhcpContext->IpAddress, // Old address
DhcpContext->IpAddress, // New address
DhcpContext->SubnetMask ) ;
}
CTEInitTimer( &DbgNotificationTimer ) ;
CTEStartTimer( &DbgNotificationTimer,
DbgNotifyTime,
DbgNotificationRoutine,
NULL ) ;
}
#endif //DEBUG
#ifdef CHICAGO
DWORD
DhcpRequestAddress(
ushort IpContext
)
/*++
Routine Description:
This function is invoked by IP when a new network adapter comes
on line and requires a DHCP lease aquisition/renewal.
Arguments:
IpContext - The IP context for the newly installed adapter.
Return Value:
DWORD - Completion status. !0 if successful, 0 if failed.
--*/
{
DWORD Result;
BOOLEAN CodeLocked = FALSE;
CTEPagedCode();
if ( !VxdLockCode( PTEXTBegin, PTEXTEnd ) ) {
CDbgPrint( DEBUG_ERRORS, ("DhcpRequestAddress: Could not lock vdhcp code \r\n")) ;
//
// we proceed regardless bcoz we can still do the work without code
// locked. And most likely if we cant lock the code the worker thread
// cant lock it either. And in that event the worker thread will
// simply reschedule itself without causing any reentrancy problems.
// see init.c DhcpRing0WorkerThread
} else {
CodeLocked = TRUE;
CDbgPrint( DEBUG_MISC, ("DhcpRequestAddress: successfully locked vdhcp code \r\n")) ;
}
Result = (DWORD)ScanIpEntities( TRUE, IpContext );
if ( CodeLocked ) {
if ( !VxdUnLockCode( PTEXTBegin, PTEXTEnd ) ) {
CDbgPrint( DEBUG_ERRORS, ("DhcpRequestAddress: Could not unlock vdhcp code \r\n")) ;
} else {
CDbgPrint( DEBUG_MISC, ("DhcpRequestAddress: successfully unlocked vdhcp code \r\n")) ;
}
}
return Result;
} // DhcpRequestAddress
VOID
DhcpProcessTcpUnloadWorker(
PCHAR VxdName
)
/*++
Routine Description:
This function is called whenever a Vxd is unloaded. We are
interested only "MSTCP" Vxd unloading. When it unloads, invalidate
the DhcpGlobalNICList and TDIDispatch pointer, and stop
renewal timer.
Arguments:
VxdName - name of the Vxd that is unloading.
Return Value:
NONE.
--*/
{
DWORD Error;
PLIST_ENTRY Entry;
CTEPagedCode();
//
// test to see that it is "MSTCP"
//
if( (VxdName == NULL) || strcmp( VxdName, "MSTCP" ) != 0 ) {
return;
}
//
// stop Renewal Timer.
//
CTEStopTimer( &RenewalTimer ) ; // Ok even if timer not running
ReleaseBlockedSockets();
//
// invalidate TDI dispatch table pointer.
//
TdiDispatch = NULL;
//
// move all DhcpGlobalNICList Entries to LocalDhcpBinList.
//
Entry = DhcpGlobalNICList.Flink;
while( Entry != &DhcpGlobalNICList ) {
PLIST_ENTRY NextEntry;
NextEntry = Entry->Flink;
RemoveEntryList( Entry );
InsertHeadList( &LocalDhcpBinList, Entry ) ;
Entry = NextEntry;
}
//
// nullify the renew list.
//
Entry = DhcpGlobalRenewList.Flink;
while( Entry != &DhcpGlobalRenewList ) {
PLIST_ENTRY NextEntry;
NextEntry = Entry->Flink;
RemoveEntryList( Entry );
Entry = NextEntry;
}
return;
} // DhcpProcessTcpUnloadWorker
VOID
DhcpProcessTcpLoadWorker(
PCHAR VxdName
)
/*++
Routine Description:
This function is called whenever a Vxd is loaded. We are
interested only "MSTCP" Vxd unloading. When it loads, recompute
the DhcpGlobalNICList and TDIDispatch pointer, and renew all leases.
Arguments:
VxdName - name of the Vxd that is unloading.
Return Value:
NONE.
--*/
{
DWORD Error;
CTEPagedCode();
//
// test to see that it is "MSTCP"
//
if( (VxdName == NULL) || strcmp( VxdName, "MSTCP" ) != 0 ) {
return;
}
//
// remake TdiDispatch pointer.
//
Error = DhcpRemakeTdiDispatchPtr();
if( Error != ERROR_SUCCESS ) {
return;
}
return;
} // DhcpProcessTcpLoadWorker
/*******************************************************************
NAME: IPBindingChangeNotification
SYNOPSIS: Called by the IP driver when a new Lana needs to be created
or destroyed for an IP address.
ENTRY: IpContext - IP context.
fNew - Are we creating or destroying this Lana?
NOTES: This routine is only used by Chicago
HISTORY:
madana 2-21-1995 Created
********************************************************************/
TDI_STATUS IPBindingChangeNotification(
USHORT IpContext,
BOOL fNew )
{
PLIST_ENTRY ListEntry;
PDHCP_CONTEXT DhcpContext;
PLOCAL_CONTEXT_INFO LocalContext;
CTEPagedCode();
//
// ignore, all creates.
//
if( fNew ) {
return TDI_SUCCESS ;
}
//
// remove the ip entry from renew list first.
//
for( ListEntry = DhcpGlobalRenewList.Flink;
ListEntry != &DhcpGlobalRenewList;
ListEntry = ListEntry->Flink ) {
DhcpContext = CONTAINING_RECORD(
ListEntry,
DHCP_CONTEXT,
RenewalListEntry );
LocalContext = (PLOCAL_CONTEXT_INFO)DhcpContext->LocalInformation;
if( LocalContext->IpContext == IpContext ) {
RemoveEntryList( &DhcpContext->RenewalListEntry );
break;
}
}
//
// remove the ip entry from the Global NIC list and add it to
// LocalDhcpBinList.
//
for( ListEntry = DhcpGlobalNICList.Flink;
ListEntry != &DhcpGlobalNICList;
ListEntry = ListEntry->Flink ) {
DhcpContext = CONTAINING_RECORD(
ListEntry,
DHCP_CONTEXT,
NicListEntry );
LocalContext = (PLOCAL_CONTEXT_INFO)DhcpContext->LocalInformation;
if( LocalContext->IpContext == IpContext ) {
RemoveEntryList( &DhcpContext->NicListEntry );
InsertTailList( &LocalDhcpBinList, &DhcpContext->NicListEntry );
break;
}
}
return TDI_SUCCESS ;
}
#endif // CHICAGO