771 lines
26 KiB
C++
771 lines
26 KiB
C++
// Copyright (C) Micorosoft Confidential 1997
|
|
// Author: RameshV
|
|
// Description: Option related registry handling -- common between NT and VxD
|
|
|
|
|
|
#include <wininetp.h>
|
|
#include "aproxp.h"
|
|
|
|
#ifndef OPTREG_H
|
|
#define OPTREG_H
|
|
|
|
|
|
// function definitions
|
|
|
|
|
|
POPTION // option from which more appends can occur
|
|
DhcpAppendSendOptions( // append all configured options
|
|
IN OUT PDHCP_CONTEXT DhcpContext, // this is the context to append for
|
|
IN PLIST_ENTRY SendOptionsList,
|
|
IN LPBYTE ClassName, // current class
|
|
IN DWORD ClassLen, // len of above in bytes
|
|
IN LPBYTE BufStart, // start of buffer
|
|
IN LPBYTE BufEnd, // how far can we go in this buffer
|
|
IN OUT LPBYTE SentOptions, // BoolArray[OPTION_END+1] to avoid repeating options
|
|
IN OUT LPBYTE VSentOptions, // to avoid repeating vendor specific options
|
|
IN OUT LPBYTE VendorOpt, // Buffer[OPTION_END+1] Holding Vendor specific options
|
|
OUT LPDWORD VendorOptLen // the # of bytes filled into that
|
|
);
|
|
|
|
DWORD // status
|
|
DhcpDestroyOptionsList( // destroy a list of options, freeing up memory
|
|
IN OUT PLIST_ENTRY OptionsList, // this is the list of options to destroy
|
|
IN PLIST_ENTRY ClassesList // this is where to remove classes off
|
|
);
|
|
|
|
DWORD // win32 status
|
|
DhcpClearAllOptions( // remove all turds from off registry
|
|
IN OUT PDHCP_CONTEXT DhcpContext // the context to clear for
|
|
);
|
|
|
|
|
|
#endif OPTREG_H
|
|
|
|
// internal private function that takes the lock on OPTIONS_LIST
|
|
|
|
DWORD // status
|
|
DhcpRegClearOptDefs( // clear all standard options
|
|
IN LPTSTR AdapterName // clear for this adapter
|
|
);
|
|
|
|
|
|
|
|
// options related lists
|
|
|
|
|
|
|
|
LIST_ENTRY DhcpGlobalRecvFromList;
|
|
LPSTR DhcpGlobalClientClassInfo = NULL;
|
|
|
|
|
|
LPBYTE // ptr to buf loc where more appends can occur
|
|
DhcpAppendParamRequestList( // append the param request list option
|
|
IN PDHCP_CONTEXT DhcpContext, // the context to append for
|
|
IN PLIST_ENTRY SendOptionsList,// look thru this list
|
|
IN LPBYTE ClassName, // which class does this belong to?
|
|
IN DWORD ClassLen, // size of above in bytes
|
|
IN LPBYTE BufStart, // where to start adding this option
|
|
IN LPBYTE BufEnd // limit for this option
|
|
) {
|
|
BYTE Buffer[OPTION_END+1];
|
|
LPBYTE Tmp;
|
|
DWORD FirstSize;
|
|
DWORD Size;
|
|
PLIST_ENTRY ThisEntry;
|
|
PDHCP_OPTION ThisOpt;
|
|
DWORD i, j;
|
|
|
|
Size = FirstSize = 0;
|
|
Buffer[Size++] = OPTION_SUBNET_MASK; // standard requested options
|
|
Buffer[Size++] = OPTION_DOMAIN_NAME;
|
|
Buffer[Size++] = OPTION_ROUTER_ADDRESS;
|
|
Buffer[Size++] = OPTION_DOMAIN_NAME_SERVERS;
|
|
Buffer[Size++] = OPTION_NETBIOS_NAME_SERVER;
|
|
Buffer[Size++] = OPTION_NETBIOS_NODE_TYPE;
|
|
Buffer[Size++] = OPTION_NETBIOS_SCOPE_OPTION;
|
|
Buffer[Size++] = OPTION_VENDOR_SPEC_INFO;
|
|
Buffer[Size++] = OPTION_USER_CLASS;
|
|
Buffer[Size++] = OPTION_WPAD_URL;
|
|
|
|
ThisEntry = SendOptionsList->Flink;
|
|
while( ThisEntry != SendOptionsList ) {
|
|
ThisOpt = CONTAINING_RECORD(ThisEntry, DHCP_OPTION, OptionList);
|
|
ThisEntry = ThisEntry->Flink;
|
|
|
|
if( ThisOpt->IsVendor) continue;
|
|
|
|
if( ThisOpt->ClassLen ) {
|
|
if( ThisOpt->ClassLen != ClassLen ) continue;
|
|
if( ThisOpt->ClassName != ClassName )
|
|
continue; // this option is not used for this client
|
|
}
|
|
|
|
if( OPTION_PARAMETER_REQUEST_LIST != ThisOpt->OptionId ) {
|
|
//
|
|
// only if the option is param_request_list do we request..
|
|
//
|
|
continue;
|
|
}
|
|
|
|
for( i = 0; i < ThisOpt->DataLen ; i ++ ) {
|
|
for( j = 0; j < Size; j ++ )
|
|
if( ThisOpt->Data[i] == Buffer[j] ) break;
|
|
if( j < Size ) continue; // option already plugged in
|
|
Buffer[Size++] = ThisOpt->Data[i]; // add this option
|
|
}
|
|
|
|
if( 0 == FirstSize ) FirstSize = Size;
|
|
}
|
|
|
|
if( 0 == FirstSize ) FirstSize = Size;
|
|
|
|
Tmp = BufStart;
|
|
BufStart = (LPBYTE)DhcpAppendOption( // now add the param request list
|
|
(POPTION)BufStart,
|
|
(BYTE)OPTION_PARAMETER_REQUEST_LIST,
|
|
Buffer,
|
|
(BYTE)Size,
|
|
BufEnd
|
|
);
|
|
|
|
if( Tmp == BufStart ) { // did not really add the option
|
|
BufStart = (LPBYTE)DhcpAppendOption( // now try adding the first request we saw instead of everything
|
|
(POPTION)BufStart,
|
|
(BYTE)OPTION_PARAMETER_REQUEST_LIST,
|
|
Buffer,
|
|
(BYTE)FirstSize,
|
|
BufEnd
|
|
);
|
|
}
|
|
|
|
return BufStart;
|
|
}
|
|
|
|
POPTION // option from which more appends can occur
|
|
DhcpAppendSendOptions( // append all configured options
|
|
IN OUT PDHCP_CONTEXT DhcpContext, // this is the context to append for
|
|
IN PLIST_ENTRY SendOptionsList,
|
|
IN LPBYTE ClassName, // current class
|
|
IN DWORD ClassLen, // len of above in bytes
|
|
IN LPBYTE BufStart, // start of buffer
|
|
IN LPBYTE BufEnd, // how far can we go in this buffer
|
|
IN OUT LPBYTE SentOptions, // BoolArray[OPTION_END+1] to avoid repeating options
|
|
IN OUT LPBYTE VSentOptions, // to avoid repeating vendor specific options
|
|
IN OUT LPBYTE VendorOpt, // Buffer[OPTION_END+1] Holding Vendor specific options
|
|
OUT LPDWORD VendorOptLen // the # of bytes filled into that
|
|
) {
|
|
PLIST_ENTRY ThisEntry;
|
|
PDHCP_OPTION ThisOpt;
|
|
|
|
DhcpAssert(FALSE == SentOptions[OPTION_PARAMETER_REQUEST_LIST]);
|
|
BufStart = DhcpAppendParamRequestList(
|
|
DhcpContext,
|
|
SendOptionsList,
|
|
ClassName,
|
|
ClassLen,
|
|
BufStart,
|
|
BufEnd
|
|
);
|
|
SentOptions[OPTION_PARAMETER_REQUEST_LIST] = TRUE;
|
|
|
|
ThisEntry = SendOptionsList->Flink;
|
|
while( ThisEntry != SendOptionsList ) {
|
|
ThisOpt = CONTAINING_RECORD(ThisEntry, DHCP_OPTION, OptionList);
|
|
ThisEntry = ThisEntry->Flink;
|
|
|
|
if( ThisOpt->IsVendor ? VSentOptions[ThisOpt->OptionId] : SentOptions[ThisOpt->OptionId] )
|
|
continue;
|
|
|
|
// if( ThisOpt->IsVendor) continue; // No vendor specific information this round through
|
|
if( ThisOpt->ClassLen ) {
|
|
if( ThisOpt->ClassLen != ClassLen ) continue;
|
|
if( ThisOpt->ClassName != ClassName )
|
|
continue; // this option is not used for this client
|
|
}
|
|
|
|
if( !ThisOpt->IsVendor ) { // easy to add non-vendor spec options
|
|
SentOptions[ThisOpt->OptionId] = TRUE;
|
|
BufStart = (LPBYTE)DhcpAppendOption(
|
|
(POPTION)BufStart,
|
|
ThisOpt->OptionId,
|
|
ThisOpt->Data,
|
|
(BYTE)ThisOpt->DataLen,
|
|
BufEnd
|
|
);
|
|
} else { // ENCAPSULATE vendor specific options
|
|
if( SentOptions[OPTION_VENDOR_SPEC_INFO] )
|
|
continue; // Vendor spec info already added
|
|
|
|
VSentOptions[ThisOpt->OptionId] = TRUE;
|
|
|
|
if( ThisOpt->DataLen + 2 + *VendorOptLen > OPTION_END )
|
|
continue; // this option overflows the buffer
|
|
|
|
VendorOpt[(*VendorOptLen)++] = ThisOpt->OptionId;
|
|
VendorOpt[(*VendorOptLen)++] = (BYTE)ThisOpt->DataLen;
|
|
memcpy(&VendorOpt[*VendorOptLen], ThisOpt->Data, ThisOpt->DataLen);
|
|
(*VendorOptLen) += ThisOpt->DataLen;
|
|
}
|
|
}
|
|
return (POPTION)BufStart;
|
|
}
|
|
|
|
|
|
DWORD // status
|
|
DhcpDestroyOptionsList( // destroy a list of options, freeing up memory
|
|
IN OUT PLIST_ENTRY OptionsList, // this is the list of options to destroy
|
|
IN PLIST_ENTRY ClassesList // this is where to remove classes off
|
|
) {
|
|
PLIST_ENTRY ThisEntry;
|
|
PDHCP_OPTION ThisOption;
|
|
DWORD Error;
|
|
DWORD LastError;
|
|
|
|
LastError = ERROR_SUCCESS;
|
|
while(!IsListEmpty(OptionsList) ) { // for each element of this list
|
|
ThisEntry = RemoveHeadList(OptionsList);
|
|
ThisOption = CONTAINING_RECORD(ThisEntry, DHCP_OPTION, OptionList);
|
|
|
|
if( NULL != ThisOption->ClassName ) { // if there is a class, deref it
|
|
Error = DhcpDelClass(
|
|
ClassesList,
|
|
ThisOption->ClassName,
|
|
ThisOption->ClassLen
|
|
);
|
|
if( ERROR_SUCCESS != Error ) {
|
|
DhcpAssert( ERROR_SUCCESS == Error);
|
|
LastError = Error;
|
|
}
|
|
}
|
|
|
|
DhcpFreeMemory(ThisOption); // now really free this
|
|
}
|
|
return LastError;
|
|
}
|
|
|
|
DWORD // win32 status
|
|
DhcpClearAllOptions( // clear all the options information
|
|
IN OUT PDHCP_CONTEXT DhcpContext // the context to clear for
|
|
) {
|
|
PLIST_ENTRY ThisEntry;
|
|
PDHCP_OPTION ThisOption;
|
|
DWORD LocalError;
|
|
|
|
//(void) DhcpRegClearOptDefs(DhcpContext->AdapterName));
|
|
|
|
ThisEntry = DhcpContext->RecdOptionsList.Flink;
|
|
while(ThisEntry != &DhcpContext->RecdOptionsList) {
|
|
ThisOption = CONTAINING_RECORD(ThisEntry, DHCP_OPTION, OptionList);
|
|
ThisEntry = ThisEntry->Flink;
|
|
|
|
// bug bug, need to return space?
|
|
ThisOption->Data = NULL;
|
|
ThisOption->DataLen = 0;
|
|
|
|
//LocalError = DhcpMarkParamChangeRequests(
|
|
// DhcpContext->AdapterName,
|
|
// ThisOption->OptionId,
|
|
// ThisOption->IsVendor,
|
|
// ThisOption->ClassName
|
|
//);
|
|
DhcpAssert(ERROR_SUCCESS == LocalError);
|
|
}
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
POPTION // buffer after filling option
|
|
DhcpAppendClassIdOption( // fill class id if exists
|
|
IN OUT PDHCP_CONTEXT DhcpContext, // the context to fillfor
|
|
OUT LPBYTE BufStart, // start of message buffer
|
|
IN LPBYTE BufEnd // end of message buffer
|
|
) {
|
|
DWORD Size;
|
|
|
|
Size = (DWORD)(BufEnd - BufStart);
|
|
|
|
if( DhcpContext->ClassId ) {
|
|
DhcpAssert(DhcpContext->ClassIdLength);
|
|
BufStart = (LPBYTE)DhcpAppendOption(
|
|
(POPTION)BufStart,
|
|
OPTION_USER_CLASS,
|
|
DhcpContext->ClassId,
|
|
(BYTE)DhcpContext->ClassIdLength,
|
|
BufEnd
|
|
);
|
|
}
|
|
|
|
return (POPTION) BufStart;
|
|
}
|
|
|
|
LPOPTION
|
|
DhcpAppendOption(
|
|
LPOPTION Option,
|
|
BYTE OptionType,
|
|
PVOID OptionValue,
|
|
ULONG OptionLength,
|
|
LPBYTE OptionEnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function writes a DHCP option to message buffer.
|
|
|
|
Arguments:
|
|
|
|
Option - A pointer to a message buffer.
|
|
|
|
OptionType - The option number to append.
|
|
|
|
OptionValue - A pointer to the option data.
|
|
|
|
OptionLength - The lenght, in bytes, of the option data.
|
|
|
|
OptionEnd - End of Option Buffer.
|
|
|
|
Return Value:
|
|
|
|
A pointer to the end of the appended option.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
|
|
if ( OptionType == OPTION_END ) {
|
|
|
|
//
|
|
// we should alway have atleast one BYTE space in the buffer
|
|
// to append this option.
|
|
//
|
|
|
|
DhcpAssert( (LPBYTE)Option < OptionEnd );
|
|
|
|
|
|
Option->OptionType = OPTION_END;
|
|
return( (LPOPTION) ((LPBYTE)(Option) + 1) );
|
|
|
|
}
|
|
|
|
if ( OptionType == OPTION_PAD ) {
|
|
|
|
//
|
|
// add this option only iff we have enough space in the buffer.
|
|
//
|
|
|
|
if(((LPBYTE)Option + 1) < (OptionEnd - 1) ) {
|
|
Option->OptionType = OPTION_PAD;
|
|
return( (LPOPTION) ((LPBYTE)(Option) + 1) );
|
|
}
|
|
|
|
DhcpPrint(("DhcpAppendOption failed to append Option "
|
|
"%ld, Buffer too small.\n", OptionType ));
|
|
return Option;
|
|
}
|
|
|
|
|
|
//
|
|
// add this option only iff we have enough space in the buffer.
|
|
//
|
|
|
|
if(((LPBYTE)Option + 2 + OptionLength) >= (OptionEnd - 1) ) {
|
|
DhcpPrint(("DhcpAppendOption failed to append Option "
|
|
"%ld, Buffer too small.\n", OptionType ));
|
|
return Option;
|
|
}
|
|
|
|
if( OptionLength <= 0xFF ) {
|
|
// simple option.. no need to use OPTION_MSFT_CONTINUED
|
|
Option->OptionType = OptionType;
|
|
Option->OptionLength = (BYTE)OptionLength;
|
|
memcpy( Option->OptionValue, OptionValue, OptionLength );
|
|
return( (LPOPTION) ((LPBYTE)(Option) + Option->OptionLength + 2) );
|
|
}
|
|
|
|
// option size is > 0xFF --> need to continue it using multiple ones..
|
|
// there are OptionLenght / 0xFF occurances using 0xFF+2 bytes + one
|
|
// using 2 + (OptionLength % 0xFF ) space..
|
|
|
|
// check to see if we have the space first..
|
|
|
|
if( 2 + (OptionLength%0xFF) + 0x101*(OptionLength/0xFF)
|
|
+ (LPBYTE)Option >= (OptionEnd - 1) ) {
|
|
DhcpPrint(("DhcpAppendOption failed to append Option "
|
|
"%ld, Buffer too small.\n", OptionType ));
|
|
return Option;
|
|
}
|
|
|
|
// first finish off all chunks of 0xFF size that we can do..
|
|
|
|
i = OptionLength/0xFF;
|
|
while(i) {
|
|
Option->OptionType = OptionType;
|
|
Option->OptionLength = 0xFF;
|
|
memcpy(Option->OptionValue, OptionValue, 0xFF);
|
|
OptionValue = 0xFF+(LPBYTE)OptionValue;
|
|
Option = (LPOPTION)(0x101 + (LPBYTE)Option);
|
|
OptionType = OPTION_MSFT_CONTINUED; // all but the first use this ...
|
|
OptionLength -= 0xFF;
|
|
}
|
|
|
|
// now finish off the remaining stuff..
|
|
DhcpAssert(OptionLength <= 0xFF);
|
|
Option->OptionType = OPTION_MSFT_CONTINUED;
|
|
Option->OptionLength = (BYTE)OptionLength;
|
|
memcpy(Option->OptionValue, OptionValue, OptionLength);
|
|
Option = (LPOPTION)(2 + OptionLength + (LPBYTE)Option);
|
|
DhcpAssert((LPBYTE)Option < OptionEnd);
|
|
|
|
return Option;
|
|
}
|
|
|
|
|
|
LPBYTE
|
|
DhcpAppendMagicCookie(
|
|
LPBYTE Option,
|
|
LPBYTE OptionEnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine appends magic cookie to a DHCP message.
|
|
|
|
Arguments:
|
|
|
|
Option - A pointer to the place to append the magic cookie.
|
|
|
|
OptionEnd - End of Option buffer.
|
|
|
|
Return Value:
|
|
|
|
A pointer to the end of the appended cookie.
|
|
|
|
Note : The magic cookie is :
|
|
|
|
--------------------
|
|
| 99 | 130 | 83 | 99 |
|
|
--------------------
|
|
|
|
--*/
|
|
{
|
|
DhcpAssert( (Option + 4) < (OptionEnd - 1) );
|
|
if( (Option + 4) < (OptionEnd - 1) ) {
|
|
*Option++ = (BYTE)DHCP_MAGIC_COOKIE_BYTE1;
|
|
*Option++ = (BYTE)DHCP_MAGIC_COOKIE_BYTE2;
|
|
*Option++ = (BYTE)DHCP_MAGIC_COOKIE_BYTE3;
|
|
*Option++ = (BYTE)DHCP_MAGIC_COOKIE_BYTE4;
|
|
}
|
|
|
|
return( Option );
|
|
}
|
|
|
|
LPOPTION
|
|
DhcpAppendClientIDOption(
|
|
LPOPTION Option,
|
|
BYTE ClientHWType,
|
|
LPBYTE ClientHWAddr,
|
|
BYTE ClientHWAddrLength,
|
|
LPBYTE OptionEnd
|
|
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine appends client ID option to a DHCP message.
|
|
|
|
History:
|
|
8/26/96 Frankbee Removed 16 byte limitation on the hardware
|
|
address
|
|
|
|
Arguments:
|
|
|
|
Option - A pointer to the place to append the option request.
|
|
|
|
ClientHWType - Client hardware type.
|
|
|
|
ClientHWAddr - Client hardware address
|
|
|
|
ClientHWAddrLength - Client hardware address length.
|
|
|
|
OptionEnd - End of Option buffer.
|
|
|
|
Return Value:
|
|
|
|
A pointer to the end of the newly appended option.
|
|
|
|
Note : The client ID option will look like as below in the message:
|
|
|
|
-----------------------------------------------------------------
|
|
| OpNum | Len | HWType | HWA1 | HWA2 | ..... | HWAn |
|
|
-----------------------------------------------------------------
|
|
|
|
--*/
|
|
{
|
|
#pragma warning(disable : 4200) // disable 0-sized array warning
|
|
|
|
struct _CLIENT_ID {
|
|
BYTE bHardwareAddressType;
|
|
BYTE pbHardwareAddress[0];
|
|
} *pClientID;
|
|
|
|
|
|
LPOPTION lpNewOption;
|
|
|
|
pClientID = (_CLIENT_ID *) DhcpAllocateMemory( sizeof( struct _CLIENT_ID ) + ClientHWAddrLength );
|
|
|
|
//
|
|
// currently there is no way to indicate failure. simply return unmodified option
|
|
// list
|
|
//
|
|
|
|
if ( !pClientID )
|
|
return Option;
|
|
|
|
pClientID->bHardwareAddressType = ClientHWType;
|
|
memcpy( pClientID->pbHardwareAddress, ClientHWAddr, ClientHWAddrLength );
|
|
|
|
lpNewOption = DhcpAppendOption(
|
|
Option,
|
|
OPTION_CLIENT_ID,
|
|
(LPBYTE)pClientID,
|
|
(BYTE)(ClientHWAddrLength + sizeof(BYTE)),
|
|
OptionEnd );
|
|
|
|
DhcpFreeMemory( pClientID );
|
|
|
|
return lpNewOption;
|
|
}
|
|
|
|
// data locks on ClassesList must be taken before calling this function
|
|
PDHCP_CLASSES PRIVATE // the required classes struct
|
|
DhcpFindClass( // find a specified class
|
|
IN OUT PLIST_ENTRY ClassesList, // list of classes to srch in
|
|
IN LPBYTE Data, // non-NULL data bytes
|
|
IN DWORD Len // # of bytes of above, > 0
|
|
) {
|
|
PLIST_ENTRY ThisEntry;
|
|
PDHCP_CLASSES ThisClass;
|
|
|
|
ThisEntry = ClassesList->Flink; // first element in list
|
|
while( ThisEntry != ClassesList ) { // search the full list
|
|
ThisClass = CONTAINING_RECORD( ThisEntry, DHCP_CLASSES, ClassList );
|
|
ThisEntry = ThisEntry->Flink;
|
|
|
|
if( ThisClass->ClassLen == Len ) { // lengths must match
|
|
if( ThisClass->ClassName == Data ) // data ptrs can match OR data can match
|
|
return ThisClass;
|
|
if( 0 == memcmp(ThisClass->ClassName, Data, Len) )
|
|
return ThisClass;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
// locks on ClassesList should be taken when using this function
|
|
LPBYTE // data bytes, or NULL
|
|
DhcpAddClass( // add a new class
|
|
IN OUT PLIST_ENTRY ClassesList, // list to add to
|
|
IN LPBYTE Data, // input class name
|
|
IN DWORD Len // # of bytes of above
|
|
) {
|
|
PDHCP_CLASSES Class;
|
|
DWORD MemSize; // amt of memory reqd
|
|
|
|
if( NULL == ClassesList ) { // invalid parameter
|
|
DhcpAssert( NULL != ClassesList );
|
|
return NULL;
|
|
}
|
|
|
|
if( 0 == Len || NULL == Data ) { // invalid parameters
|
|
DhcpAssert(0 != Len && NULL != Data );
|
|
return NULL;
|
|
}
|
|
|
|
Class = DhcpFindClass(ClassesList,Data,Len); // already there in list?
|
|
if(NULL != Class) { // yes, found
|
|
Class->RefCount++; // increase ref-count
|
|
return Class->ClassName;
|
|
}
|
|
|
|
MemSize = sizeof(*Class)+Len; // amt of memory reqd
|
|
Class = (PDHCP_CLASSES) DhcpAllocateMemory(MemSize);
|
|
if( NULL == Class ) { // not enough memory
|
|
DhcpAssert( NULL != Class);
|
|
return NULL;
|
|
}
|
|
|
|
Class->ClassLen = Len;
|
|
Class->RefCount = 1;
|
|
Class->ClassName = ((LPBYTE)Class) + sizeof(*Class);
|
|
memcpy(Class->ClassName, Data, Len);
|
|
|
|
InsertHeadList(ClassesList, &Class->ClassList);
|
|
|
|
return Class->ClassName;
|
|
}
|
|
|
|
// locks on ClassesList must be taken before calling this function
|
|
DWORD // status
|
|
DhcpDelClass( // de-refernce a class
|
|
IN OUT PLIST_ENTRY ClassesList, // the list to delete off
|
|
IN LPBYTE Data, // the data ptr
|
|
IN DWORD Len // the # of bytes of above
|
|
) {
|
|
PDHCP_CLASSES Class;
|
|
|
|
if( NULL == ClassesList ) {
|
|
DhcpAssert( NULL != ClassesList );
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if( 0 == Len || NULL == Data ) { // invalid parameter
|
|
DhcpAssert( 0 != Len && NULL != Data );
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
Class = DhcpFindClass(ClassesList,Data,Len);
|
|
if( NULL == Class ) { // did not find this class?
|
|
DhcpAssert( NULL != Class );
|
|
return ERROR_FILE_NOT_FOUND;
|
|
}
|
|
|
|
Class->RefCount --;
|
|
if( 0 == Class->RefCount ) { // all references removed
|
|
RemoveEntryList( &Class->ClassList ); // remove this from the list
|
|
DhcpFreeMemory(Class); // free it
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
// locks on ClassesList must be taken before calling this function
|
|
VOID // always succeed
|
|
DhcpFreeAllClasses( // free each elt of the list
|
|
IN OUT PLIST_ENTRY ClassesList // input list of classes
|
|
) {
|
|
PDHCP_CLASSES ThisClass;
|
|
PLIST_ENTRY ThisEntry;
|
|
|
|
if( NULL == ClassesList ) {
|
|
DhcpAssert( NULL != ClassesList && "DhcpFreeAllClasses" );
|
|
return ;
|
|
}
|
|
|
|
while( !IsListEmpty(ClassesList) ) {
|
|
ThisEntry = RemoveHeadList(ClassesList);
|
|
ThisClass = CONTAINING_RECORD(ThisEntry, DHCP_CLASSES, ClassList);
|
|
|
|
if( ThisClass->RefCount ) {
|
|
DhcpPrint(("Freeing with refcount = %ld\n", ThisClass->RefCount));
|
|
}
|
|
|
|
DhcpFreeMemory(ThisClass);
|
|
}
|
|
|
|
InitializeListHead(ClassesList);
|
|
}
|
|
|
|
|
|
// exported functions, options
|
|
|
|
|
|
// data locks need to be taken on OptionsList before calling this function
|
|
PDHCP_OPTION // the reqd structure or NULL
|
|
DhcpFindOption( // find a specific option
|
|
IN OUT PLIST_ENTRY OptionsList, // the list of options to search
|
|
IN BYTE OptionId, // the option id to search for
|
|
IN BOOL IsVendor, // is it vendor specific?
|
|
IN LPBYTE ClassName, // is there a class associated?
|
|
IN DWORD ClassLen // # of bytes of above parameter
|
|
) {
|
|
PLIST_ENTRY ThisEntry;
|
|
PDHCP_OPTION ThisOption;
|
|
|
|
if( NULL == OptionsList ) {
|
|
DhcpAssert( NULL != OptionsList );
|
|
return NULL;
|
|
}
|
|
|
|
ThisEntry = OptionsList->Flink;
|
|
while( ThisEntry != OptionsList ) { // search the set of options
|
|
ThisOption = CONTAINING_RECORD( ThisEntry, DHCP_OPTION, OptionList );
|
|
ThisEntry = ThisEntry->Flink;
|
|
|
|
if( ThisOption->OptionId != OptionId ) continue;
|
|
if( ThisOption->IsVendor != IsVendor ) continue;
|
|
if( ThisOption->ClassLen != ClassLen ) continue;
|
|
if( ClassLen && ThisOption->ClassName != ClassName )
|
|
continue; // mismatched so far
|
|
|
|
return ThisOption; // found the option
|
|
}
|
|
|
|
return NULL; // did not find any match
|
|
}
|
|
|
|
// locks on OptionsList need to be taken before calling this function
|
|
DWORD // status
|
|
DhcpDelOption( // remove a particular option
|
|
IN PDHCP_OPTION ThisOption // option to delete
|
|
) {
|
|
if( NULL == ThisOption) // nope, did not find this option
|
|
return ERROR_FILE_NOT_FOUND;
|
|
|
|
RemoveEntryList( &ThisOption->OptionList); // found it. remove and free
|
|
DhcpFreeMemory(ThisOption);
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
// locks on OptionsList need to be taken before calling this function
|
|
DWORD // status
|
|
DhcpAddOption( // add a new option
|
|
IN OUT PLIST_ENTRY OptionsList, // list to add to
|
|
IN BYTE OptionId, // option id to add
|
|
IN BOOL IsVendor, // is it vendor specific?
|
|
IN LPBYTE ClassName, // what is the class?
|
|
IN DWORD ClassLen, // size of above in bytes
|
|
IN LPBYTE Data, // data for this option
|
|
IN DWORD DataLen, // # of bytes of above
|
|
IN time_t ExpiryTime // when the option expires
|
|
) {
|
|
PDHCP_OPTION ThisOption;
|
|
DWORD MemSize;
|
|
|
|
if( NULL == OptionsList ) {
|
|
DhcpAssert( NULL != OptionsList && "DhcpAddOption" );
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if( 0 != ClassLen && NULL == ClassName ) {
|
|
DhcpAssert( 0 == ClassLen || NULL != ClassName && "DhcpAddOption" );
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if( 0 != DataLen && NULL == Data ) {
|
|
DhcpAssert( 0 == DataLen || NULL != Data && "DhcpAddOption" );
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
MemSize = sizeof(DHCP_OPTION) + DataLen ;
|
|
ThisOption = (PDHCP_OPTION) DhcpAllocateMemory(MemSize);
|
|
if( NULL == ThisOption ) // could not allocate memory
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
ThisOption->OptionId = OptionId;
|
|
ThisOption->IsVendor = IsVendor;
|
|
ThisOption->ClassName = ClassName;
|
|
ThisOption->ClassLen = ClassLen;
|
|
ThisOption->ExpiryTime = ExpiryTime;
|
|
ThisOption->DataLen = DataLen;
|
|
ThisOption->Data = ((LPBYTE)ThisOption) + sizeof(DHCP_OPTION);
|
|
memcpy(ThisOption->Data, Data, DataLen);
|
|
|
|
InsertHeadList( OptionsList, &ThisOption->OptionList );
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
// end of file
|