835 lines
17 KiB
C
835 lines
17 KiB
C
/*++
|
||
|
||
Copyright (c) 1994 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
dhcp.c
|
||
|
||
Abstract:
|
||
|
||
This module contains DHCP specific utility routines used by the
|
||
DHCP components.
|
||
|
||
Author:
|
||
|
||
Manny Weiser (mannyw) 12-Aug-1992
|
||
|
||
Revision History:
|
||
|
||
Madan Appiah (madana) 21-Oct-1992
|
||
|
||
--*/
|
||
|
||
#include <nt.h>
|
||
#include <ntrtl.h>
|
||
#include <nturtl.h>
|
||
|
||
#include <dhcpl.h>
|
||
|
||
DWORD
|
||
NTTimeToNTPTime(PULONG pTime,
|
||
PFILETIME pft OPTIONAL);
|
||
|
||
DWORD
|
||
NTPTimeToNTFileTime(PLONG pTime, PFILETIME pft, BOOL bHostOrder);
|
||
|
||
#undef DhcpAllocateMemory
|
||
#undef DhcpFreeMemory
|
||
|
||
|
||
PVOID
|
||
DhcpAllocateMemory(
|
||
DWORD Size
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function allocates the required size of memory by calling
|
||
LocalAlloc.
|
||
|
||
Arguments:
|
||
|
||
Size - size of the memory block required.
|
||
|
||
Return Value:
|
||
|
||
Pointer to the allocated block.
|
||
|
||
--*/
|
||
{
|
||
|
||
ASSERT( Size != 0 );
|
||
|
||
return( LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, Size ) );
|
||
}
|
||
|
||
#undef DhcpFreeMemory
|
||
|
||
VOID
|
||
DhcpFreeMemory(
|
||
PVOID Memory
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function frees up the memory that was allocated by
|
||
DhcpAllocateMemory.
|
||
|
||
Arguments:
|
||
|
||
Memory - pointer to the memory block that needs to be freed up.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
{
|
||
|
||
LPVOID Ptr;
|
||
|
||
ASSERT( Memory != NULL );
|
||
Ptr = LocalFree( Memory );
|
||
|
||
ASSERT( Ptr == NULL );
|
||
}
|
||
|
||
|
||
|
||
DATE_TIME
|
||
DhcpCalculateTime(
|
||
DWORD RelativeTime
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
The function calculates the absolute time of a time RelativeTime
|
||
seconds from now.
|
||
|
||
Arguments:
|
||
|
||
RelativeTime - Relative time, in seconds.
|
||
|
||
Return Value:
|
||
|
||
The time in RelativeTime seconds from the current system time.
|
||
|
||
--*/
|
||
{
|
||
SYSTEMTIME systemTime;
|
||
ULONGLONG absoluteTime;
|
||
|
||
if( RelativeTime == INFINIT_LEASE ) {
|
||
((DATE_TIME *)&absoluteTime)->dwLowDateTime =
|
||
DHCP_DATE_TIME_INFINIT_LOW;
|
||
((DATE_TIME *)&absoluteTime)->dwHighDateTime =
|
||
DHCP_DATE_TIME_INFINIT_HIGH;
|
||
}
|
||
else {
|
||
|
||
GetSystemTime( &systemTime );
|
||
SystemTimeToFileTime(
|
||
&systemTime,
|
||
(FILETIME *)&absoluteTime );
|
||
|
||
absoluteTime = absoluteTime + RelativeTime * (ULONGLONG)10000000; }
|
||
|
||
return( *(DATE_TIME *)&absoluteTime );
|
||
}
|
||
|
||
|
||
DATE_TIME
|
||
DhcpGetDateTime(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function returns FILETIME.
|
||
|
||
Arguments:
|
||
|
||
none.
|
||
|
||
Return Value:
|
||
|
||
FILETIME.
|
||
|
||
--*/
|
||
{
|
||
SYSTEMTIME systemTime;
|
||
DATE_TIME Time;
|
||
|
||
GetSystemTime( &systemTime );
|
||
SystemTimeToFileTime( &systemTime, (FILETIME *)&Time );
|
||
|
||
return( Time );
|
||
}
|
||
|
||
VOID
|
||
DhcpNTToNTPTime(
|
||
LPDATE_TIME AbsNTTime,
|
||
DWORD Offset,
|
||
PULONG NTPTimeStamp
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
The function calculates the absolute NTP timestamp from AbsTime on
|
||
NT added by given offset.
|
||
|
||
Arguments:
|
||
|
||
AbsNTTime - AbsTime on NT. If 0, it will use current time.
|
||
|
||
RelativeOffset - offset to be added to AnsNTTime (in seconds.)
|
||
|
||
Return Value:
|
||
|
||
The time in RelativeTime seconds from the current system time.
|
||
|
||
--*/
|
||
{
|
||
ULONGLONG LocalAbsNTTime;
|
||
DWORD Error;
|
||
|
||
if ( AbsNTTime == 0 ) {
|
||
GetSystemTimeAsFileTime((FILETIME *)&LocalAbsNTTime );
|
||
} else {
|
||
LocalAbsNTTime = *(ULONGLONG *)AbsNTTime;
|
||
}
|
||
|
||
// add offset
|
||
LocalAbsNTTime += Offset * (ULONGLONG)10000000;
|
||
|
||
// now convert to NT timestamp
|
||
Error = NTTimeToNTPTime( NTPTimeStamp, (PFILETIME)&LocalAbsNTTime );
|
||
|
||
DhcpAssert( ERROR_SUCCESS == Error );
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
DhcpNTPToNTTime(
|
||
PULONG NTPTimeStamp,
|
||
DWORD Offset,
|
||
DATE_TIME *NTTime
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
The function calculates the absolute NTP timestamp from AbsTime on
|
||
NT added by given offset.
|
||
|
||
Arguments:
|
||
|
||
AbsNTTime - AbsTime on NT. If 0, it will use current time.
|
||
|
||
RelativeOffset - offset to be added to AnsNTTime (in seconds.)
|
||
|
||
Return Value:
|
||
|
||
The time in RelativeTime seconds from the current system time.
|
||
|
||
--*/
|
||
{
|
||
ULONGLONG LocalAbsNTTime;
|
||
DWORD Error;
|
||
|
||
Error = NTPTimeToNTFileTime(
|
||
NTPTimeStamp,
|
||
(FILETIME *)&LocalAbsNTTime,
|
||
FALSE // not in host order.
|
||
);
|
||
|
||
DhcpAssert( ERROR_SUCCESS == Error );
|
||
|
||
// add offset
|
||
LocalAbsNTTime += Offset * (ULONGLONG)10000000;
|
||
|
||
// now convert to NT timestamp
|
||
// MBUG
|
||
|
||
*(ULONGLONG *)NTTime = LocalAbsNTTime;
|
||
return;
|
||
}
|
||
|
||
|
||
DWORD
|
||
DhcpReportEventW(
|
||
LPWSTR Source,
|
||
DWORD EventID,
|
||
DWORD EventType,
|
||
DWORD NumStrings,
|
||
DWORD DataLength,
|
||
LPWSTR *Strings,
|
||
LPVOID Data
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function writes the specified (EventID) log at the end of the
|
||
eventlog.
|
||
|
||
Arguments:
|
||
|
||
Source - Points to a null-terminated string that specifies the name
|
||
of the module referenced. The node must exist in the
|
||
registration database, and the module name has the
|
||
following format:
|
||
|
||
\EventLog\System\Lanmanworkstation
|
||
|
||
EventID - The specific event identifier. This identifies the
|
||
message that goes with this event.
|
||
|
||
EventType - Specifies the type of event being logged. This
|
||
parameter can have one of the following
|
||
|
||
values:
|
||
|
||
Value Meaning
|
||
|
||
EVENTLOG_ERROR_TYPE Error event
|
||
EVENTLOG_WARNING_TYPE Warning event
|
||
EVENTLOG_INFORMATION_TYPE Information event
|
||
|
||
NumStrings - Specifies the number of strings that are in the array
|
||
at 'Strings'. A value of zero indicates no strings
|
||
are present.
|
||
|
||
DataLength - Specifies the number of bytes of event-specific raw
|
||
(binary) data to write to the log. If cbData is
|
||
zero, no event-specific data is present.
|
||
|
||
Strings - Points to a buffer containing an array of null-terminated
|
||
strings that are merged into the message before
|
||
displaying to the user. This parameter must be a valid
|
||
pointer (or NULL), even if cStrings is zero.
|
||
|
||
Data - Buffer containing the raw data. This parameter must be a
|
||
valid pointer (or NULL), even if cbData is zero.
|
||
|
||
|
||
Return Value:
|
||
|
||
Returns the WIN32 extended error obtained by GetLastError().
|
||
|
||
NOTE : This function works slow since it calls the open and close
|
||
eventlog source everytime.
|
||
|
||
--*/
|
||
{
|
||
HANDLE EventlogHandle;
|
||
DWORD ReturnCode;
|
||
|
||
|
||
//
|
||
// open eventlog section.
|
||
//
|
||
|
||
EventlogHandle = RegisterEventSourceW(
|
||
NULL,
|
||
Source
|
||
);
|
||
|
||
if (EventlogHandle == NULL) {
|
||
|
||
ReturnCode = GetLastError();
|
||
goto Cleanup;
|
||
}
|
||
|
||
|
||
//
|
||
// Log the error code specified
|
||
//
|
||
|
||
if( !ReportEventW(
|
||
EventlogHandle,
|
||
(WORD)EventType,
|
||
0, // event category
|
||
EventID,
|
||
NULL,
|
||
(WORD)NumStrings,
|
||
DataLength,
|
||
Strings,
|
||
Data
|
||
) ) {
|
||
|
||
ReturnCode = GetLastError();
|
||
goto Cleanup;
|
||
}
|
||
|
||
ReturnCode = NO_ERROR;
|
||
|
||
Cleanup:
|
||
|
||
if( EventlogHandle != NULL ) {
|
||
|
||
DeregisterEventSource(EventlogHandle);
|
||
}
|
||
|
||
return ReturnCode;
|
||
}
|
||
|
||
|
||
DWORD
|
||
DhcpReportEventA(
|
||
LPWSTR Source,
|
||
DWORD EventID,
|
||
DWORD EventType,
|
||
DWORD NumStrings,
|
||
DWORD DataLength,
|
||
LPSTR *Strings,
|
||
LPVOID Data
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function writes the specified (EventID) log at the end of the
|
||
eventlog.
|
||
|
||
Arguments:
|
||
|
||
Source - Points to a null-terminated string that specifies the name
|
||
of the module referenced. The node must exist in the
|
||
registration database, and the module name has the
|
||
following format:
|
||
|
||
\EventLog\System\Lanmanworkstation
|
||
|
||
EventID - The specific event identifier. This identifies the
|
||
message that goes with this event.
|
||
|
||
EventType - Specifies the type of event being logged. This
|
||
parameter can have one of the following
|
||
|
||
values:
|
||
|
||
Value Meaning
|
||
|
||
EVENTLOG_ERROR_TYPE Error event
|
||
EVENTLOG_WARNING_TYPE Warning event
|
||
EVENTLOG_INFORMATION_TYPE Information event
|
||
|
||
NumStrings - Specifies the number of strings that are in the array
|
||
at 'Strings'. A value of zero indicates no strings
|
||
are present.
|
||
|
||
DataLength - Specifies the number of bytes of event-specific raw
|
||
(binary) data to write to the log. If cbData is
|
||
zero, no event-specific data is present.
|
||
|
||
Strings - Points to a buffer containing an array of null-terminated
|
||
strings that are merged into the message before
|
||
displaying to the user. This parameter must be a valid
|
||
pointer (or NULL), even if cStrings is zero.
|
||
|
||
Data - Buffer containing the raw data. This parameter must be a
|
||
valid pointer (or NULL), even if cbData is zero.
|
||
|
||
|
||
Return Value:
|
||
|
||
Returns the WIN32 extended error obtained by GetLastError().
|
||
|
||
NOTE : This function works slow since it calls the open and close
|
||
eventlog source everytime.
|
||
|
||
--*/
|
||
{
|
||
HANDLE EventlogHandle;
|
||
DWORD ReturnCode;
|
||
|
||
|
||
//
|
||
// open eventlog section.
|
||
//
|
||
|
||
EventlogHandle = RegisterEventSourceW(
|
||
NULL,
|
||
Source
|
||
);
|
||
|
||
if (EventlogHandle == NULL) {
|
||
|
||
ReturnCode = GetLastError();
|
||
goto Cleanup;
|
||
}
|
||
|
||
|
||
//
|
||
// Log the error code specified
|
||
//
|
||
|
||
if( !ReportEventA(
|
||
EventlogHandle,
|
||
(WORD)EventType,
|
||
0, // event category
|
||
EventID,
|
||
NULL,
|
||
(WORD)NumStrings,
|
||
DataLength,
|
||
Strings,
|
||
Data
|
||
) ) {
|
||
|
||
ReturnCode = GetLastError();
|
||
goto Cleanup;
|
||
}
|
||
|
||
ReturnCode = NO_ERROR;
|
||
|
||
Cleanup:
|
||
|
||
if( EventlogHandle != NULL ) {
|
||
|
||
DeregisterEventSource(EventlogHandle);
|
||
}
|
||
|
||
return ReturnCode;
|
||
}
|
||
|
||
|
||
DWORD
|
||
DhcpLogUnknownOption(
|
||
LPWSTR Source,
|
||
DWORD EventID,
|
||
LPOPTION Option
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine logs an unknown DHCP option to event log.
|
||
|
||
Arguments:
|
||
|
||
Source - name of the app that logs this error. it should be either
|
||
"DhcpClient" or "DhcpServer".
|
||
|
||
EventID - Event identifier number.
|
||
|
||
Option - pointer to the unknown option structure.
|
||
|
||
Return Value:
|
||
|
||
Windows Error code.
|
||
|
||
--*/
|
||
{
|
||
LPWSTR Strings[2];
|
||
WCHAR StringsBuffer[ 2 * (3 + 1) ];
|
||
// for two string each is 1byte decimal number (0 - 255).
|
||
|
||
LPWSTR StringsPtr = StringsBuffer;
|
||
|
||
//
|
||
// convert option number.
|
||
//
|
||
|
||
Strings[0] = StringsPtr;
|
||
DhcpDecimalToString( StringsPtr, Option->OptionType );
|
||
StringsPtr += 3;
|
||
|
||
*StringsPtr++ = L'\0';
|
||
|
||
//
|
||
// convert option length.
|
||
//
|
||
Strings[1] = StringsPtr;
|
||
DhcpDecimalToString( StringsPtr, Option->OptionLength );
|
||
StringsPtr += 3;
|
||
|
||
*StringsPtr++ = L'\0';
|
||
|
||
|
||
//
|
||
// log error.
|
||
//
|
||
|
||
return(
|
||
DhcpReportEventW(
|
||
Source,
|
||
EventID,
|
||
EVENTLOG_WARNING_TYPE,
|
||
2,
|
||
(DWORD)Option->OptionLength,
|
||
Strings,
|
||
(PVOID)Option->OptionValue )
|
||
);
|
||
}
|
||
|
||
#if DBG
|
||
|
||
VOID
|
||
DhcpAssertFailed(
|
||
LPSTR FailedAssertion,
|
||
LPSTR FileName,
|
||
DWORD LineNumber,
|
||
LPSTR Message
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Assertion failed.
|
||
|
||
Arguments:
|
||
|
||
FailedAssertion :
|
||
|
||
FileName :
|
||
|
||
LineNumber :
|
||
|
||
Message :
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
{
|
||
#ifndef DHCP_NOASSERT
|
||
RtlAssert(
|
||
FailedAssertion,
|
||
FileName,
|
||
(ULONG) LineNumber,
|
||
(PCHAR) Message);
|
||
#endif
|
||
|
||
DhcpPrint(( 0, "Assert @ %s \n", FailedAssertion ));
|
||
DhcpPrint(( 0, "Assert Filename, %s \n", FileName ));
|
||
DhcpPrint(( 0, "Line Num. = %ld.\n", LineNumber ));
|
||
DhcpPrint(( 0, "Message is %s\n", Message ));
|
||
|
||
}
|
||
|
||
#endif
|
||
|
||
|
||
|
||
LPWSTR
|
||
DhcpRegIpAddressToKey(
|
||
DHCP_IP_ADDRESS IpAddress,
|
||
LPWSTR KeyBuffer
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function converts an IpAddress to registry key. The registry
|
||
key is unicode string of IpAddress in dotted form.
|
||
|
||
Arguments:
|
||
|
||
IpAddress : IpAddress that needs conversion. The IpAddress is in
|
||
host order.
|
||
|
||
KeyBuffer : pointer a buffer that will hold the converted
|
||
registry key. The buffer should be big enough to
|
||
converted key.
|
||
|
||
Return Value:
|
||
|
||
Pointer to the key the buffer.
|
||
|
||
--*/
|
||
{
|
||
LPSTR OemKey;
|
||
LPWSTR UnicodeKey;
|
||
DWORD NetworkOrderIpAddress;
|
||
|
||
NetworkOrderIpAddress = htonl(IpAddress);
|
||
|
||
OemKey = inet_ntoa( *(struct in_addr *)&NetworkOrderIpAddress );
|
||
UnicodeKey = DhcpOemToUnicode( OemKey, KeyBuffer );
|
||
|
||
DhcpAssert( UnicodeKey == KeyBuffer );
|
||
|
||
return( UnicodeKey );
|
||
|
||
}
|
||
|
||
|
||
|
||
DHCP_IP_ADDRESS
|
||
DhcpRegKeyToIpAddress(
|
||
LPWSTR Key
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function converts registry key to Ip Address.
|
||
|
||
Arguments:
|
||
|
||
Key : Pointer to registry key.
|
||
|
||
Return Value:
|
||
|
||
Converted IpAddress.
|
||
|
||
--*/
|
||
{
|
||
CHAR OemKeyBuffer[DHCP_IP_KEY_LEN];
|
||
LPSTR OemKey;
|
||
|
||
|
||
OemKey = DhcpUnicodeToOem( Key, OemKeyBuffer );
|
||
DhcpAssert( OemKey == OemKeyBuffer );
|
||
|
||
return( ntohl(inet_addr( OemKey )) );
|
||
}
|
||
|
||
|
||
|
||
LPWSTR
|
||
DhcpRegOptionIdToKey(
|
||
DHCP_OPTION_ID OptionId,
|
||
LPWSTR KeyBuffer
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function converts an OptionId to registry key. The registry
|
||
key is unicode string of OptionId, 3 unicode char. long and of the
|
||
form L"000".
|
||
|
||
Arguments:
|
||
|
||
IpAddress : IpAddress that needs conversion.
|
||
|
||
KeyBuffer : pointer a buffer that will hold the converted
|
||
registry key. The buffer should be at least 8 char.
|
||
long.
|
||
|
||
Return Value:
|
||
|
||
Pointer to the key the buffer.
|
||
|
||
--*/
|
||
|
||
{
|
||
int i;
|
||
|
||
for (i = 2; i >= 0; i--) {
|
||
KeyBuffer[i] = L'0' + (BYTE)(OptionId % 10 );
|
||
OptionId /= 10;
|
||
}
|
||
KeyBuffer[3] = L'\0';
|
||
|
||
return( KeyBuffer );
|
||
}
|
||
|
||
|
||
|
||
DHCP_OPTION_ID
|
||
DhcpRegKeyToOptionId(
|
||
LPWSTR Key
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function converts registry key to OptionId.
|
||
|
||
Arguments:
|
||
|
||
Key : Pointer to registry key.
|
||
|
||
Return Value:
|
||
|
||
Converted OptionId.
|
||
|
||
--*/
|
||
|
||
{
|
||
DHCP_OPTION_ID OptionId = 0;
|
||
int i;
|
||
|
||
for (i = 0; i < 3 && Key[i] != L'\0'; i++) {
|
||
OptionId = (OptionId * 10) + (Key[i] - L'0');
|
||
}
|
||
return( OptionId );
|
||
}
|
||
|
||
DWORD
|
||
DhcpStartWaitableTimer(
|
||
HANDLE TimerHandle,
|
||
DWORD SleepTime)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine starts the waitable timer. This timer fires off even
|
||
when the system is in hibernate state.
|
||
|
||
Arguments
|
||
|
||
TimerHandle - Waitable Timer Handle
|
||
|
||
SleepTime - Sleep Time in seconds.
|
||
|
||
Return Value:
|
||
|
||
Status of the operation.
|
||
|
||
--*/
|
||
{
|
||
DATE_TIME SleepTimeInNSec; // sleep time in nano seconds since Jan 1 1901
|
||
DWORD Error;
|
||
BOOL Result;
|
||
|
||
Error = STATUS_SUCCESS;
|
||
SleepTimeInNSec = DhcpCalculateTime( SleepTime );
|
||
|
||
Result = SetWaitableTimer(
|
||
TimerHandle, // handle to timer object
|
||
(LARGE_INTEGER *)&SleepTimeInNSec, // due time.
|
||
0, // not periodic
|
||
NULL, // completion routine
|
||
NULL, // completion routine arg
|
||
TRUE // resume power state when due
|
||
);
|
||
if ( !Result ) {
|
||
DhcpPrint((0, "SetWaitableTimer reported Error = %d\n",Error=GetLastError()));
|
||
}
|
||
return Error;
|
||
}
|
||
|
||
VOID
|
||
DhcpCancelWaitableTimer(
|
||
HANDLE TimerHandle
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine cancels the waitable timer.
|
||
|
||
Arguments
|
||
|
||
TimerHandle - Waitable Timer Handle
|
||
|
||
Return Value:
|
||
|
||
|
||
--*/
|
||
{
|
||
BOOL Result;
|
||
|
||
Result = CancelWaitableTimer( TimerHandle );
|
||
if ( !Result ) {
|
||
DhcpPrint((0,"SetWaitableTimer reported Error = %lx\n",GetLastError()));
|
||
}
|
||
}
|