windows-nt/Source/XPSP1/NT/net/dhcp/server/client/dhcpcmd.c
2020-09-26 16:20:57 +08:00

5335 lines
138 KiB
C

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
dhcpcmd.c
Abstract:
This file contains program to test all DHCP APIs.
Author:
Madan Appiah (madana) 5-Oct-1993
Environment:
User Mode - Win32
Revision History:
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <winsock.h>
#include <dhcp.h>
#include <dhcpapi.h>
#include <dhcplib.h>
#include <stdio.h>
#include <ctype.h>
#include <wchar.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <jet.h> // for JET_cbColumnMost
#ifdef NT5
#include <mdhcsapi.h>
#endif NT5
#include <heapx.h>
#include <ipexport.h>
#include <icmpif.h>
#include <icmpapi.h>
#include <winnls.h>
#ifdef DBG
#ifdef __DHCP_USE_DEBUG_HEAP__
#pragma message ( "*** DHCPCMD will use debug heap ***" )
#define DhcpAllocateMemory(x) calloc(1,x)
#define DhcpFreeMemory(x) free(x)
#endif
#endif
typedef enum _COMMAND_CODE {
AddIpRange,
RemoveIpRange,
EnumIpRanges,
AddReservedIp,
EnumClients,
EnumClientsV5,
DeleteBadClients,
DeleteClient,
MibCounts,
ServerConfig,
GetDhcpVersion,
SetSuperScope,
DeleteSuperScope,
GetSuperScopeTable,
RemoveSubscope,
CheckDB,
CreateSubnet,
AddExcludeRange,
RemoveReservedIp,
RemoveExcludeRange,
SetSubnetState,
DeleteSubnet,
CreateOption,
DeleteOption,
EnumOptions,
SetGlobalOptionValue,
SetGlobalOptionValues,
RemoveGlobalOptionValue,
SetSubnetOptionValue,
RemoveSubnetOptionValue,
SetReservedOptionValue,
RemoveReservedOptionValue,
GetAllOptions,
GetAllOptionValues,
CreateMScope,
DeleteMScope,
AddMScopeRange,
EnumMScopeClients,
ReconcileMScope,
EnumMScopes,
MCastMibCounts,
CreateClass,
DeleteClass,
EnumClasses,
AddServer,
DelServer,
EnumServers,
GetServerStatus,
RetryAuthorization,
GetBindings,
SetBinding,
UnknownCommand
} COMMAND_CODE, *LPCOMMAND_CODE;
typedef struct _COMMAND_INFO {
LPSTR CommandName;
COMMAND_CODE CommandCode;
} COMMAND_INFO, *LPCOMMAND_INFO;
LPWSTR GlobalServerIpAddressUnicodeString = NULL;
LPSTR GlobalServerIpAddressAnsiString = NULL;
LPWSTR GlobalClassName = NULL;
LPWSTR GlobalVendorName = NULL;
BOOL GlobalIsVendor = FALSE;
BOOL GlobalNoRPC = FALSE;
BOOL GlobalNoDS = TRUE;
DWORD GlobalClientCount;
DWORD g_dwMajor = (DWORD) -1 ,
g_dwMinor = (DWORD) -1; // version control
#define CLASS_ID_VERSION 0x5
COMMAND_INFO GlobalCommandInfo[] = {
// global server stuff.
{"MibCounts", MibCounts },
{"GetVersion", GetDhcpVersion },
{"ServerConfig", ServerConfig },
// subnet stuff
{"CreateSubnet", CreateSubnet },
{"DeleteSubnet", DeleteSubnet },
{"SetSubnetState", SetSubnetState },
// ranges
{"AddIpRange", AddIpRange },
{"RemoveIpRange", RemoveIpRange },
#ifdef NT5
{"EnumIpRanges", EnumIpRanges },
#endif NT5
{"AddExcludeRange", AddExcludeRange },
{"RemoveExcludeRange", RemoveExcludeRange },
// active leases
{"EnumClients", EnumClients },
{"DeleteBadClients", DeleteBadClients },
{"DeleteClient", DeleteClient },
#ifdef NT5
{"EnumClientsV5", EnumClientsV5 },
#endif NT5
// reservations
{"AddReservedIp", AddReservedIp },
{"RemoveReservedIp", RemoveReservedIp },
// super-scoping
{"SetSuperScope", SetSuperScope },
{"DeleteSuperScope", DeleteSuperScope },
{"GetSuperScopeTable", GetSuperScopeTable },
{"RemoveSubscope", RemoveSubscope },
// reconcile
{"CheckDB", CheckDB },
// options
{"CreateOption", CreateOption },
{"DeleteOption", DeleteOption },
{"SetGlobalOptionValue", SetGlobalOptionValue },
{"SetGlobalOptionValues", SetGlobalOptionValues },
{"RemoveGlobalOptionValue", RemoveGlobalOptionValue },
{"SetSubnetOptionValue", SetSubnetOptionValue },
{"RemoveSubnetOptionValue", RemoveSubnetOptionValue },
{"SetReservedOptionValue",SetReservedOptionValue },
{"RemoveReservedOptionValue", RemoveReservedOptionValue },
{"EnumOptions", EnumOptions},
#ifdef NT5
{"GetAllOptions", GetAllOptions },
{"GetAllOptionValues", GetAllOptionValues },
// multicast stuff
{"CreateMScope", CreateMScope},
{"DeleteMScope", DeleteMScope},
{"AddMScopeIpRange", AddMScopeRange},
{"EnumMScopeClients", EnumMScopeClients},
{"ReconcileMScope", ReconcileMScope},
{"EnumMScopes", EnumMScopes},
{"MCastMibCounts", MCastMibCounts},
// classes
{"CreateClass", CreateClass},
{"DeleteClass", DeleteClass},
{"EnumClasses", EnumClasses},
// servers
{"AddServer", AddServer},
{"DeleteServer", DelServer},
{"EnumServers", EnumServers},
{"GetServerStatus", GetServerStatus},
{"RetryAuthorization", RetryAuthorization},
{"GetBindings", GetBindings},
{"SetBinding", SetBinding}
#endif NT5
};
typedef enum _CONFIG_COMMAND_CODE {
ConfigAPIProtocolSupport,
ConfigDatabaseName,
ConfigDatabasePath,
ConfigBackupPath,
ConfigBackupInterval,
ConfigDatabaseLoggingFlag,
ConfigRestoreFlag,
ConfigDatabaseCleanupInterval,
ConfigDebugFlag,
ConfigActivityLog,
ConfigPingRetries,
ConfigBootFileTable,
UnknownConfigCommand
} CONFIG_COMMAND_CODE, *LPCONFIG_COMMAND_CODE;
typedef struct _CONFIG_COMMAND_INFO {
LPSTR CommandName;
CONFIG_COMMAND_CODE CommandCode;
} CONFIG_COMMAND_INFO, *LPCONFIG_COMMAND_INFO;
CONFIG_COMMAND_INFO GlobalConfigCommandInfo[] =
{
{"APIProtocolSupport", ConfigAPIProtocolSupport },
{"DatabaseName", ConfigDatabaseName },
{"DatabasePath", ConfigDatabasePath },
{"BackupPath", ConfigBackupPath },
{"BackupInterval", ConfigBackupInterval },
{"DatabaseLoggingFlag", ConfigDatabaseLoggingFlag },
{"RestoreFlag", ConfigRestoreFlag },
{"DatabaseCleanupInterval", ConfigDatabaseCleanupInterval },
{"DebugFlag", ConfigDebugFlag },
{"ActivityLog", ConfigActivityLog },
{"PingRetries", ConfigPingRetries },
{"BootFileTable", ConfigBootFileTable }
};
#define DHCPCMD_VERSION_MAJOR 4
#define DHCPCMD_VERSION_MINOR 1
#if DBG
VOID
DhcpPrintRoutine(
IN DWORD DebugFlag,
IN LPSTR Format,
...
)
{
#define WSTRSIZE( wsz ) ( ( wcslen( wsz ) + 1 ) * sizeof( WCHAR ) )
#define MAX_PRINTF_LEN 1024 // Arbitrary.
va_list arglist;
char OutputBuffer[MAX_PRINTF_LEN];
ULONG length = 0;
//
// Put a the information requested by the caller onto the line
//
va_start(arglist, Format);
length += (ULONG) vsprintf(&OutputBuffer[length], Format, arglist);
va_end(arglist);
DhcpAssert(length <= MAX_PRINTF_LEN);
//
// Output to the debug terminal,
//
DbgPrint( "%s", OutputBuffer);
}
#endif // DBG
DWORD
SetOptionDataType(
LPSTR OptionTypeString,
LPSTR OptionValueString,
LPDHCP_OPTION_DATA_ELEMENT OptionData,
LPWSTR *UnicodeOptionValueString
)
{
DHCP_OPTION_DATA_TYPE OptionType;
DHCP_OPTION_ID OptionValue;
if( _stricmp( OptionTypeString, "BYTE") == 0 ) {
OptionType = DhcpByteOption;
} else if( _stricmp( OptionTypeString, "WORD") == 0 ) {
OptionType = DhcpWordOption;
} else if( _stricmp( OptionTypeString, "DWORD") == 0 ) {
OptionType = DhcpDWordOption;
} else if( _stricmp( OptionTypeString, "STRING") == 0 ) {
OptionType = DhcpStringDataOption;
} else if( _stricmp( OptionTypeString, "IPADDRESS") == 0 ) {
OptionType = DhcpIpAddressOption;
} else {
printf("OptionType either Unknown or not supported, %s.\n",
OptionTypeString );
return( ERROR_INVALID_PARAMETER );
}
OptionData->OptionType = OptionType;
switch( OptionType ) {
case DhcpByteOption:
OptionValue = strtoul( OptionValueString, NULL, 0 );
if( OptionValue & ~((BYTE)-1) ) {
printf("DefValue is too large (%ld).\n", OptionValue );
return( ERROR_INVALID_PARAMETER );
}
OptionData->Element.ByteOption = (BYTE)OptionValue;
break;
case DhcpWordOption:
OptionValue = strtoul( OptionValueString, NULL, 0 );
if( OptionValue & ~((WORD)-1) ) {
printf("DefValue is too large (%ld).\n", OptionValue );
return( ERROR_INVALID_PARAMETER );
}
OptionData->Element.WordOption = (WORD)OptionValue;
break;
case DhcpDWordOption:
OptionValue = strtoul( OptionValueString, NULL, 0 );
OptionData->Element.DWordOption = (DWORD)OptionValue;
break;
case DhcpIpAddressOption:
OptionData->Element.IpAddressOption =
DhcpDottedStringToIpAddress(OptionValueString);
break;
case DhcpStringDataOption:
*UnicodeOptionValueString =
DhcpOemToUnicode( OptionValueString, NULL );
if( UnicodeOptionValueString == NULL ) {
return( ERROR_NOT_ENOUGH_MEMORY );
}
OptionData->Element.StringDataOption = *UnicodeOptionValueString;
break;
default:
DhcpAssert(FALSE);
printf("CreateOptionValue: Unknown OptionType \n");
return( ERROR_INVALID_PARAMETER );
break;
}
return( ERROR_SUCCESS );
}
COMMAND_CODE
DecodeCommand(
LPSTR CommandName
)
{
DWORD i;
DWORD NumCommands;
NumCommands = sizeof(GlobalCommandInfo) / sizeof(COMMAND_INFO);
DhcpAssert( NumCommands <= UnknownCommand );
for( i = 0; i < NumCommands; i++) {
if( _stricmp( CommandName, GlobalCommandInfo[i].CommandName ) == 0 ) {
return( GlobalCommandInfo[i].CommandCode );
}
}
return( UnknownCommand );
}
VOID
PrintCommands(
VOID
)
{
DWORD i;
DWORD NumCommands;
NumCommands = sizeof(GlobalCommandInfo) / sizeof(COMMAND_INFO);
DhcpAssert( NumCommands <= UnknownCommand );
for( i = 0; i < NumCommands; i++) {
printf( " %s\n", GlobalCommandInfo[i].CommandName );
}
}
DWORD
ProcessCreateSubnet(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
DHCP_SUBNET_INFO SubnetInfo;
LPWSTR UnicodeSubnetName = NULL;
//
// Expected Parameters are : <SubnetAddress SubnetMask SubnetName>
//
if( CommandArgc < 3 ) {
printf("usage:DhcpCmd SrvIpAddress CreateSubnet [Command Parameters].\n"
"<Command Parameters> - <SubnetAddress SubnetMask SubnetName>.\n" );
Error = ERROR_SUCCESS;
goto Cleanup;
}
SubnetInfo.SubnetAddress =
DhcpDottedStringToIpAddress(CommandArgv[0]);
SubnetInfo.SubnetMask =
DhcpDottedStringToIpAddress(CommandArgv[1]);
UnicodeSubnetName = DhcpOemToUnicode( CommandArgv[2], NULL );
DhcpAssert( UnicodeSubnetName != NULL );
SubnetInfo.SubnetName = UnicodeSubnetName;
SubnetInfo.SubnetComment = NULL;
SubnetInfo.PrimaryHost.IpAddress =
DhcpDottedStringToIpAddress(GlobalServerIpAddressAnsiString);
SubnetInfo.PrimaryHost.NetBiosName = NULL;
SubnetInfo.PrimaryHost.HostName = NULL;
SubnetInfo.SubnetState = DhcpSubnetEnabled;
Error = DhcpCreateSubnet(
GlobalServerIpAddressUnicodeString,
SubnetInfo.SubnetAddress,
&SubnetInfo );
Cleanup:
if( UnicodeSubnetName != NULL ) {
DhcpFreeMemory( UnicodeSubnetName );
}
return( Error );
}
BOOL
IsValidServerVersion(
DWORD dwMajor,
DWORD dwMinor
)
{
DWORD dwServerVersion = MAKEWORD( dwMinor, dwMajor );
return ( dwServerVersion >=
MAKEWORD( DHCPCMD_VERSION_MINOR,
DHCPCMD_VERSION_MAJOR ));
}
DWORD
ProcessAddIpRange(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
ULONG MajorVersion, MinorVersion;
ULONG Resume;
DHCP_IP_RANGE IpRange;
DHCP_SUBNET_ELEMENT_DATA Element;
DHCP_SUBNET_ELEMENT_TYPE ElementType;
//
// Expected Parameters are : <SubnetAddress IpRangeStart IpRangeEnd>
//
if( CommandArgc < 3 ) {
printf("usage:DhcpCmd SrvIpAddress AddIpRange [Command Parameters].\n"
"<Command Parameters> - <SubnetAddress IpRangeStart IpRangeEnd>.\n" );
return( ERROR_SUCCESS );
}
IpRange.StartAddress = DhcpDottedStringToIpAddress(CommandArgv[1]);
IpRange.EndAddress = DhcpDottedStringToIpAddress(CommandArgv[2]);
Element.ElementType = DhcpIpRanges;
Element.Element.IpRange = &IpRange;
#ifdef NT5
if( CommandArgc >= 4 ) {
DHCP_BOOTP_IP_RANGE ThisRange = {IpRange.StartAddress, IpRange.EndAddress, 0, ~0};
Element.Element.IpRange = (PVOID)&ThisRange;
if( GlobalNoRPC ) {
MajorVersion = CLASS_ID_VERSION;
} else {
Error = DhcpGetVersion(GlobalServerIpAddressUnicodeString, &MajorVersion, &MinorVersion);
if( ERROR_SUCCESS != Error ) {
printf("Could not determine server version\n");
return Error;
}
}
if( MajorVersion >= CLASS_ID_VERSION ) {
if( CommandArgc >= 5 ) {
ThisRange.MaxBootpAllowed = strtoul( CommandArgv[4], NULL, 0 ) ;
}
if( 0 == _stricmp(CommandArgv[3], "DHCP") ) {
Element.ElementType = DhcpIpRangesDhcpOnly;
} else if( 0 == _stricmp(CommandArgv[3], "BOOTP") ) {
Element.ElementType = DhcpIpRangesBootpOnly;
} else if( 0 == _stricmp(CommandArgv[3], "DHCPBOOTP" ) ) {
Element.ElementType = DhcpIpRangesDhcpBootp;
} else {
printf("usage:DhcpCmd SrvIpAddress AddIpRange [Command Parameters].\n"
"<CommandParameters> - <SubnetAddress IpRangeStart"
" IpRangeEnd (DHCP | BOOTP | DHCPBOOTP)>\n");
return ERROR_SUCCESS;
}
return DhcpAddSubnetElementV5(
GlobalServerIpAddressUnicodeString,
DhcpDottedStringToIpAddress(CommandArgv[0]),
(PVOID)&Element
);
}
}
#endif
Error = DhcpAddSubnetElement(
GlobalServerIpAddressUnicodeString,
DhcpDottedStringToIpAddress(CommandArgv[0]),
&Element );
return( Error );
}
DWORD
ProcessRemoveIpRange(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
ULONG MajorVersion, MinorVersion;
DHCP_IP_RANGE IpRange;
DHCP_SUBNET_ELEMENT_DATA Element;
DHCP_SUBNET_ELEMENT_TYPE ElementType;
//
// Expected Parameters are : <SubnetAddress IpRangeStart IpRangeEnd>
//
if( CommandArgc < 3 ) {
printf("usage:DhcpCmd SrvIpAddress RemoveIpRange [Command Parameters].\n"
"<Command Parameters> - <SubnetAddress IpRangeStart IpRangeEnd>.\n" );
return( ERROR_SUCCESS );
}
IpRange.StartAddress = DhcpDottedStringToIpAddress(CommandArgv[1]);
IpRange.EndAddress = DhcpDottedStringToIpAddress(CommandArgv[2]);
Element.ElementType = DhcpIpRanges;
Element.Element.IpRange = &IpRange;
#ifdef NT5
if( CommandArgc >= 4 ) {
if( GlobalNoRPC ) {
MajorVersion = CLASS_ID_VERSION;
} else {
Error = DhcpGetVersion(GlobalServerIpAddressUnicodeString, &MajorVersion, &MinorVersion);
if( ERROR_SUCCESS != Error ) {
printf("Could not determine server version\n");
return Error;
}
}
if( MajorVersion >= CLASS_ID_VERSION ) {
if( 0 == _stricmp(CommandArgv[3], "DHCP") ) {
Element.ElementType = DhcpIpRangesDhcpOnly;
} else if( 0 == _stricmp(CommandArgv[3], "BOOTP") ) {
Element.ElementType = DhcpIpRangesBootpOnly;
} else if( 0 == _stricmp(CommandArgv[3], "DHCPBOOTP" ) ) {
Element.ElementType = DhcpIpRangesDhcpBootp;
} else {
printf("usage:DhcpCmd SrvIpAddress AddIpRange [Command Parameters].\n"
"<CommandParameters> - <SubnetAddress IpRangeStart"
" IpRangeEnd (DHCP | BOOTP | DHCPBOOTP)>\n");
return ERROR_SUCCESS;
}
return DhcpRemoveSubnetElementV5(
GlobalServerIpAddressUnicodeString,
DhcpDottedStringToIpAddress(CommandArgv[0]),
(PVOID)&Element,
FALSE
);
}
}
#endif
Error = DhcpRemoveSubnetElement(
GlobalServerIpAddressUnicodeString,
DhcpDottedStringToIpAddress(CommandArgv[0]),
&Element,
FALSE
);
return( Error );
}
#ifdef NT5
VOID
PrintRange(
DHCP_SUBNET_ELEMENT_TYPE Type,
DHCP_IP_ADDRESS Start,
DHCP_IP_ADDRESS End,
ULONG BootpAllocated,
ULONG MaxBootpAllowed
)
{
printf("Range: %s -", DhcpIpAddressToDottedString( Start ) );
printf("%s ", DhcpIpAddressToDottedString( End ) );
switch(Type ) {
case DhcpIpRanges : printf("\n"); break;
case DhcpIpRangesDhcpOnly : printf("DHCP\n"); break;
case DhcpIpRangesDhcpBootp:
printf("DHCPBOOTP Bootp Clients leased = %d; Max Allowed BootpClients = %ld\n",
BootpAllocated, MaxBootpAllowed
);
break;
case DhcpIpRangesBootpOnly:
printf("BOOTP Bootp Clients leased = %d; Max Allowed BootpClients = %ld\n",
BootpAllocated, MaxBootpAllowed
);
break;
default: printf("Unknown range type: %ld\n", Type);
}
}
DWORD
ProcessEnumIpRanges(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
ULONG Error;
ULONG MajorVersion, MinorVersion;
ULONG nRead, nTotal, i;
ULONG Resume;
BOOL fIsV5Call;
DHCP_SUBNET_ELEMENT_TYPE ElementType;
LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V4 Elements4;
LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V5 Elements5;
if( CommandArgc < 1 ) {
printf("usage:DhcpCmd SrvIpAddress EnumIpRanges <SubnetAddress>\n");
return ERROR_SUCCESS;
}
Error = DhcpGetVersion(GlobalServerIpAddressUnicodeString, &MajorVersion, &MinorVersion);
if( MajorVersion >= CLASS_ID_VERSION ) {
fIsV5Call = TRUE;
} else {
fIsV5Call = FALSE;
}
Resume = 0;
while( TRUE ) {
Elements5 = NULL;
Elements4 = NULL;
nRead = nTotal = 0;
if( fIsV5Call ) {
Error = DhcpEnumSubnetElementsV5(
GlobalServerIpAddressUnicodeString,
DhcpDottedStringToIpAddress(CommandArgv[0]),
DhcpIpRangesDhcpBootp,
&Resume,
~0,
&Elements5,
&nRead,
&nTotal
);
} else {
Error = DhcpEnumSubnetElementsV4(
GlobalServerIpAddressUnicodeString,
DhcpDottedStringToIpAddress(CommandArgv[0]),
DhcpIpRangesDhcpBootp,
&Resume,
~0,
&Elements4,
&nRead,
&nTotal
);
}
if( ERROR_SUCCESS == Error || ERROR_MORE_DATA == Error ) {
for( i = 0; i < nRead ; i ++ ) {
if( fIsV5Call ) {
PrintRange(
Elements5->Elements[i].ElementType,
Elements5->Elements[i].Element.IpRange->StartAddress,
Elements5->Elements[i].Element.IpRange->EndAddress,
Elements5->Elements[i].Element.IpRange->BootpAllocated,
Elements5->Elements[i].Element.IpRange->MaxBootpAllowed
);
} else {
PrintRange(
Elements4->Elements[i].ElementType,
Elements4->Elements[i].Element.IpRange->StartAddress,
Elements4->Elements[i].Element.IpRange->EndAddress,
0,
0
);
}
}
}
if( Elements4 ) DhcpRpcFreeMemory( Elements4 );
if( Elements5 ) DhcpRpcFreeMemory( Elements5 );
if( ERROR_SUCCESS == Error || ERROR_NO_MORE_ITEMS == Error ) break;
if( ERROR_MORE_DATA != Error ) return Error;
}
return ERROR_SUCCESS;
}
#endif NT5
#define COMMAND_ARG_TYPE 5
DWORD
ProcessBootpParameters(
DWORD cArgs,
LPSTR *ppszArgs,
DHCP_IP_RESERVATION_V4 *pReservation
)
{
DWORD dwResult = ERROR_SUCCESS;
if ( cArgs > COMMAND_ARG_TYPE )
{
// user specified the allowed client type
if ( !_stricmp( ppszArgs[ COMMAND_ARG_TYPE ], "bootp" ) )
{
pReservation->bAllowedClientTypes = CLIENT_TYPE_BOOTP;
}
else if ( !_stricmp ( ppszArgs[ COMMAND_ARG_TYPE ], "dhcp" ) )
{
pReservation->bAllowedClientTypes = CLIENT_TYPE_DHCP;
}
else if ( !_stricmp ( ppszArgs[ COMMAND_ARG_TYPE ], "both" ) )
{
pReservation->bAllowedClientTypes = CLIENT_TYPE_BOTH;
}
else
{
printf( "Specify BOOTP, DHCP, or BOTH for reservation type.\n" );
return ERROR_INVALID_PARAMETER;
}
}
else
{
// allow dhcp clients by default.
pReservation->bAllowedClientTypes = CLIENT_TYPE_DHCP;
return ERROR_SUCCESS;
}
return dwResult;
}
DWORD
ProcessAddReservedIp(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
#define MAX_ADDRESS_LENGTH 64 // 64 bytes
#define COMMAND_ARG_CLIENT_COMMENT 4
DWORD Error;
DHCP_SUBNET_ELEMENT_DATA_V4 Element;
DHCP_IP_RESERVATION_V4 ReserveElement;
DHCP_CLIENT_UID ClientUID;
BYTE Address[MAX_ADDRESS_LENGTH];
DWORD i;
DHCP_IP_ADDRESS ReservedIpAddress;
//
// Expected Parameters are : <SubnetAddress ReservedIp HWAddressString>
//
//
// if the server version is 4.1 or greater, <AllowedClientTypes> and <BootFileString> can
// also be supplied
//
if( CommandArgc < 3 ) {
printf("usage:DhcpCmd SrvIpAddress AddReservedIp "
"[Command Parameters].\n"
"<Command Parameters> - "
"<SubnetAddress ReservedIp HWAddressString [ClientName] [ClientComment]"
" [DHCP | BOOTP | BOTH]>\n" );
return( ERROR_SUCCESS );
}
//
// make HardwareAddress.
//
ClientUID.DataLength = strlen(CommandArgv[2]);
if( ClientUID.DataLength % 2 != 0 ) {
//
// address must be even length.
//
printf("ProcessAddReservedIp: address must be even length.\n");
return( ERROR_INVALID_PARAMETER );
}
ClientUID.DataLength /= 2;
DhcpAssert( ClientUID.DataLength < MAX_ADDRESS_LENGTH );
i = DhcpStringToHwAddress( (LPSTR)Address, CommandArgv[2] );
DhcpAssert( i == ClientUID.DataLength );
ClientUID.Data = Address;
//
// make reserve element.
//
ReservedIpAddress = DhcpDottedStringToIpAddress(CommandArgv[1]);
ReserveElement.ReservedIpAddress = ReservedIpAddress;
ReserveElement.ReservedForClient = &ClientUID;
Element.ElementType = DhcpReservedIps;
Element.Element.ReservedIp = &ReserveElement;
Error = ProcessBootpParameters( CommandArgc, CommandArgv, &ReserveElement );
if ( ERROR_SUCCESS != Error )
{
return Error;
}
Error = DhcpAddSubnetElementV4(
GlobalServerIpAddressUnicodeString,
DhcpDottedStringToIpAddress(CommandArgv[0]),
&Element );
if( Error != ERROR_SUCCESS ) {
return( Error );
}
//
// if we are asked to set the client name, do so.
//
if( CommandArgc > 3 ) {
DHCP_SEARCH_INFO ClientSearchInfo;
LPDHCP_CLIENT_INFO_V4 ClientInfo = NULL;
LPWSTR UnicodeClientName = NULL;
LPWSTR UnicodeClientComment = NULL;
//
// set client name.
//
ClientSearchInfo.SearchType = DhcpClientIpAddress;
ClientSearchInfo.SearchInfo.ClientIpAddress = ReservedIpAddress;
do {
Error = DhcpGetClientInfoV4(
GlobalServerIpAddressUnicodeString,
&ClientSearchInfo,
&ClientInfo );
if( Error != ERROR_SUCCESS ) {
break;
}
UnicodeClientName = DhcpOemToUnicode( CommandArgv[3], NULL );
if( UnicodeClientName == NULL ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
break;
}
if ( ( wcslen( UnicodeClientName ) + 1 ) * sizeof(WCHAR) > JET_cbColumnMost ) {
printf("ProcessAddReservedIp: Client Name too long\n");
Error = ERROR_INVALID_PARAMETER;
break;
}
//
// if client comment is also given in the argument, store that
// as well.
//
if ( CommandArgc > COMMAND_ARG_CLIENT_COMMENT ) {
UnicodeClientComment = DhcpOemToUnicode( CommandArgv[COMMAND_ARG_CLIENT_COMMENT], NULL );
if (!UnicodeClientComment ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
break;
}
//
// check the size here.
//
if ( ( wcslen( UnicodeClientComment ) + 1 ) * sizeof(WCHAR) > JET_cbColumnMost ) {
printf("ProcessAddReservedIp: Client Comment too long\n");
Error = ERROR_INVALID_PARAMETER;
break;
}
ClientInfo->ClientComment = UnicodeClientComment;
}
ClientInfo->ClientName = UnicodeClientName;
} while ( FALSE );
if ( Error == ERROR_SUCCESS ) {
Error = DhcpSetClientInfoV4(
GlobalServerIpAddressUnicodeString,
ClientInfo );
} else {
//
// Cleanup.
//
if ( ClientInfo ) {
DhcpRpcFreeMemory( ClientInfo );
}
if ( UnicodeClientName ) {
DhcpFreeMemory( UnicodeClientName );
}
if ( UnicodeClientComment ) {
DhcpFreeMemory( UnicodeClientComment );
}
}
} // if( CommandArgc > 3 )
return( Error );
}
DWORD
ProcessAddExcludeRange(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
DHCP_IP_RANGE IpRange;
DHCP_SUBNET_ELEMENT_DATA Element;
//
// Expected Parameters are : <SubnetAddress IpRangeStart IpRangeEnd>
//
if( CommandArgc < 3 ) {
printf("usage:DhcpCmd SrvIpAddress AddExcludeRange [Command Parameters].\n"
"<Command Parameters> - <SubnetAddress IpRangeStart IpRangeEnd>.\n" );
return( ERROR_SUCCESS );
}
IpRange.StartAddress = DhcpDottedStringToIpAddress(CommandArgv[1]);
IpRange.EndAddress = DhcpDottedStringToIpAddress(CommandArgv[2]);
Element.ElementType = DhcpExcludedIpRanges;
Element.Element.IpRange = &IpRange;
Error = DhcpAddSubnetElement(
GlobalServerIpAddressUnicodeString,
DhcpDottedStringToIpAddress(CommandArgv[0]),
&Element );
return( Error );
}
DWORD
ProcessRemoveExcludeRange(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
DHCP_SUBNET_ELEMENT_DATA Element;
DHCP_IP_RANGE IpRange;
//
// Expected Parameters are : <SubnetAddress IpRangeStart IpRangeEnd>
//
if( CommandArgc < 3 ) {
printf("usage:DhcpCmd SrvIpAddress RemoveExcludeRange [Command Parameters].\n"
"<Command Parameters> - <SubnetAddress IpRangeStart IpRangeEnd>.\n" );
return( ERROR_SUCCESS );
}
IpRange.StartAddress = DhcpDottedStringToIpAddress(CommandArgv[1]);
IpRange.EndAddress = DhcpDottedStringToIpAddress(CommandArgv[2]);
Element.ElementType = DhcpExcludedIpRanges;
Element.Element.ExcludeIpRange = &IpRange;
Error = DhcpRemoveSubnetElement(
GlobalServerIpAddressUnicodeString,
DhcpDottedStringToIpAddress(CommandArgv[0]),
&Element,
DhcpFullForce );
return( Error );
}
DWORD
ProcessRemoveReservedIp(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
DHCP_SUBNET_ELEMENT_DATA_V4 Element;
DHCP_IP_RESERVATION_V4 ReserveElement;
DHCP_CLIENT_UID ClientUID;
BYTE Address[MAX_ADDRESS_LENGTH];
DWORD i;
//
// Expected Parameters are : <SubnetAddress ReservedIp HWAddressString>
//
if( CommandArgc < 3 ) {
printf("usage:DhcpCmd SrvIpAddress RemoveReservedIp "
"[Command Parameters].\n"
"<Command Parameters> - "
"<SubnetAddress ReservedIp HWAddressString>.\n" );
return( ERROR_SUCCESS );
}
//
// make HardwareAddress.
//
ClientUID.DataLength = strlen(CommandArgv[2]);
if( ClientUID.DataLength % 2 != 0 ) {
//
// address must be even length.
//
printf("ProcessAddReservedIp: address must be even length.\n");
return( ERROR_INVALID_PARAMETER );
}
ClientUID.DataLength /= 2;
DhcpAssert( ClientUID.DataLength < MAX_ADDRESS_LENGTH );
i = DhcpStringToHwAddress( (LPSTR)Address, CommandArgv[2] );
DhcpAssert( i == ClientUID.DataLength );
ClientUID.Data = Address;
//
// make reserve element.
//
ReserveElement.ReservedIpAddress = DhcpDottedStringToIpAddress(CommandArgv[1]);
ReserveElement.ReservedForClient = &ClientUID;
Element.ElementType = DhcpReservedIps;
Element.Element.ReservedIp = &ReserveElement;
Error = DhcpRemoveSubnetElementV4(
GlobalServerIpAddressUnicodeString,
DhcpDottedStringToIpAddress(CommandArgv[0]),
&Element,
DhcpFullForce );
return( Error );
}
DWORD
ProcessSetSubnetState(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
LPDHCP_SUBNET_INFO SubnetInfo;
LPWSTR UnicodeSubnetName = NULL;
DWORD State;
//
// Expected Parameters are : <SubnetAddress SubnetMask SubnetName>
//
if( CommandArgc < 2 ) {
printf("usage:DhcpCmd SrvIpAddress SetSubnetState [Command Parameters].\n"
"<Command Parameters> - <SubnetAddress State>.\n" );
Error = ERROR_SUCCESS;
return( Error );
}
Error = DhcpGetSubnetInfo(
GlobalServerIpAddressUnicodeString,
DhcpDottedStringToIpAddress(CommandArgv[0]),
&SubnetInfo );
if( Error != ERROR_SUCCESS ) {
return( Error );
}
State = strtoul( CommandArgv[1], NULL, 0 );
if( State == 0 ) {
if( SubnetInfo->SubnetState == DhcpSubnetEnabled ) {
Error = ERROR_SUCCESS;
goto Cleanup;
}
SubnetInfo->SubnetState = DhcpSubnetEnabled;
}
else {
if( SubnetInfo->SubnetState == DhcpSubnetDisabled ) {
Error = ERROR_SUCCESS;
goto Cleanup;
}
SubnetInfo->SubnetState = DhcpSubnetDisabled;
}
Error = DhcpSetSubnetInfo(
GlobalServerIpAddressUnicodeString,
DhcpDottedStringToIpAddress(CommandArgv[0]),
SubnetInfo );
Cleanup:
if( SubnetInfo != NULL ) {
DhcpFreeMemory( SubnetInfo );
}
return( Error );
}
DWORD
ProcessDeleteSubnet(
IN DWORD CommandArgc,
IN LPSTR CommandArgv[]
)
{
DWORD Error;
DHCP_IP_ADDRESS SubnetAddress;
DHCP_FORCE_FLAG ForceFlag;
//
// Expected Parameters are :
// <SubnetAddress ForceFlag>
// <ForceFlag> : "DhcpFullForce" "DhcpNoForce"
if( CommandArgc != 2 ) {
printf("usage: DhcpCmd SrvIpAddress DeleteSubnet [Command Parameters].\n"
"<CommandParameters> - <SubnetAddress ForceFlag>.\n");
printf("<ForceFlag> : <DhcpFullForce | DhcpNoForce>.\n");
Error = ERROR_SUCCESS;
goto Cleanup;
}
SubnetAddress = DhcpDottedStringToIpAddress( CommandArgv[0] );
if( 0 == _stricmp(CommandArgv[1], "DhcpFullForce" ) ) {
ForceFlag = DhcpFullForce;
} else if( 0 == _stricmp(CommandArgv[1], "DhcpNoForce" ) ) {
ForceFlag = DhcpNoForce;
} else {
printf("Unknown force flag value: %s (expecting DhcpFullForce or DhcpNoForce)\n",
CommandArgv[1]);
Error = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
Error = DhcpDeleteSubnet(
GlobalServerIpAddressUnicodeString,
SubnetAddress,
ForceFlag
);
Cleanup:
return Error;
}
DWORD
_CreateOption(
IN LPWSTR ServerAddress,
IN DWORD Flags,
IN DHCP_OPTION_ID OptionId,
IN LPWSTR ClassName,
IN LPWSTR VendorName,
IN DHCP_OPTION *OptionInfo
)
{
DWORD MajorVersion, MinorVersion;
DWORD Error;
#ifdef NT5
if( GlobalNoRPC ) {
MajorVersion = CLASS_ID_VERSION ;
} else {
Error = DhcpGetVersion(ServerAddress, &MajorVersion, &MinorVersion);
if( ERROR_SUCCESS != Error ) {
printf("Could not determine server version.\n");
return Error;
}
}
if( MajorVersion >= CLASS_ID_VERSION ) {
return DhcpCreateOptionV5(
ServerAddress,
GlobalIsVendor ? Flags | DHCP_FLAGS_OPTION_IS_VENDOR : Flags,
OptionId,
ClassName,
VendorName,
OptionInfo
);
}
// incorrect version, just do like before..
#endif
return DhcpCreateOption(
ServerAddress,
OptionId,
OptionInfo
);
}
ProcessCreateOption(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
DHCP_OPTION OptionInfo;
DHCP_OPTION_ID OptionID;
LPWSTR UnicodeOptionName = NULL;
LPWSTR UnicodeOptionValueString = NULL;
DHCP_OPTION_DATA_ELEMENT OptionData;
//
// Expected Parameters are :
// <OptionID OptionName DefValueType DefValue>
//
if( CommandArgc < 2 ) {
printf("usage:DhcpCmd SrvIpAddress CreateOption [Command Parameters].\n"
"<Command Parameters> - <OptionID OptionName <DefValueType DefValue>>.\n");
printf("<DefValueType> : <BYTE | WORD | DWORD | STRING | IPADDRESS>.\n");
Error = ERROR_SUCCESS;
goto Cleanup;
}
OptionID = strtoul( CommandArgv[0], NULL, 0 );
OptionInfo.OptionID = OptionID;
UnicodeOptionName = DhcpOemToUnicode( CommandArgv[1], NULL );
if( UnicodeOptionName == NULL ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
OptionInfo.OptionName = UnicodeOptionName;
OptionInfo.OptionComment = NULL;
if( CommandArgc >= 4 ) {
Error = SetOptionDataType(
CommandArgv[2],
CommandArgv[3],
&OptionData,
&UnicodeOptionValueString
);
if( Error != ERROR_SUCCESS ) {
goto Cleanup;
}
OptionInfo.DefaultValue.NumElements = 1;
OptionInfo.DefaultValue.Elements = &OptionData;
}
else {
OptionInfo.DefaultValue.NumElements = 0;
OptionInfo.DefaultValue.Elements = NULL;
}
OptionInfo.OptionType = DhcpUnaryElementTypeOption;
Error = _CreateOption(
GlobalServerIpAddressUnicodeString,
0,
OptionID,
GlobalClassName,
GlobalVendorName,
&OptionInfo
);
Cleanup:
if( UnicodeOptionName != NULL ) {
DhcpFreeMemory( UnicodeOptionName );
}
if( UnicodeOptionValueString != NULL ) {
DhcpFreeMemory( UnicodeOptionValueString );
}
return( Error );
}
DWORD
RemoveOption(
IN LPWSTR ServerAddress,
IN DWORD Flags,
IN DHCP_OPTION_ID OptionId,
IN LPWSTR ClassName,
IN LPWSTR VendorName
)
{
DWORD MajorVersion, MinorVersion;
DWORD Error;
#ifdef NT5
if( GlobalNoRPC ) {
MajorVersion = CLASS_ID_VERSION ;
} else {
Error = DhcpGetVersion(ServerAddress, &MajorVersion, &MinorVersion);
if( ERROR_SUCCESS != Error ) {
printf("Could not determine server version.\n");
return Error;
}
}
if( MajorVersion >= CLASS_ID_VERSION ) {
return DhcpRemoveOptionV5(
ServerAddress,
GlobalIsVendor ? Flags | DHCP_FLAGS_OPTION_IS_VENDOR : Flags,
OptionId,
ClassName,
VendorName
);
}
// incorrect version, just do like before..
#endif
return DhcpRemoveOption(
ServerAddress,
OptionId
);
}
ProcessDeleteOption(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
DHCP_OPTION_ID OptionID;
//
// Expected Parameters are :
// <OptionID>
//
if( CommandArgc != 1 ) {
printf("usage:DhcpCmd SrvIpAddress DeleteOption [Command Parameters].\n"
"<Command Parameters> - <OptionID>.\n");
Error = ERROR_SUCCESS;
goto Cleanup;
}
OptionID = strtoul( CommandArgv[0], NULL, 0 );
Error = RemoveOption(
GlobalServerIpAddressUnicodeString,
0,
OptionID,
GlobalClassName,
GlobalVendorName
);
Cleanup:
return Error ;
}
DWORD
SetOptionValue(
IN LPWSTR ServerAddress,
IN DWORD Flags,
IN DHCP_OPTION_ID OptionId,
IN LPWSTR ClassName,
IN LPWSTR VendorName,
IN LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
IN LPDHCP_OPTION_DATA OptionValue
)
{
DWORD MajorVersion, MinorVersion;
DWORD Error;
#ifdef NT5
if( GlobalNoRPC ) {
MajorVersion = CLASS_ID_VERSION ;
} else {
Error = DhcpGetVersion(ServerAddress, &MajorVersion, &MinorVersion);
if( ERROR_SUCCESS != Error ) {
printf("Could not determine server version.\n");
return Error;
}
}
if( MajorVersion >= CLASS_ID_VERSION ) {
return DhcpSetOptionValueV5(
ServerAddress,
GlobalIsVendor ? Flags | DHCP_FLAGS_OPTION_IS_VENDOR : Flags,
OptionId,
ClassName,
VendorName,
ScopeInfo,
OptionValue
);
}
// incorrect version, just do like before..
#endif
return DhcpSetOptionValue(
ServerAddress,
OptionId,
ScopeInfo,
OptionValue
);
}
ProcessSetGlobalOptionValue(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
DHCP_OPTION_ID OptionID;
DHCP_OPTION_SCOPE_INFO ScopeInfo;
DHCP_OPTION_DATA OptionValue;
DHCP_OPTION_DATA_ELEMENT OptionData;
LPWSTR UnicodeOptionValueString = NULL;
//
// Expected Parameters are :
// <OptionID OptionType OptionValue>
//
if( CommandArgc < 3 ) {
printf("usage:DhcpCmd SrvIpAddress SetGlobalOptionValue [Command Parameters].\n"
"<Command Parameters> - <OptionID OptionType OptionValue>.\n");
Error = ERROR_SUCCESS;
goto Cleanup;
}
OptionID = strtoul( CommandArgv[0], NULL, 0 );
Error = SetOptionDataType(
CommandArgv[1],
CommandArgv[2],
&OptionData,
&UnicodeOptionValueString
);
if( Error != ERROR_SUCCESS ) {
goto Cleanup;
}
OptionValue.NumElements = 1;
OptionValue.Elements = &OptionData;
ScopeInfo.ScopeType = DhcpGlobalOptions;
ScopeInfo.ScopeInfo.GlobalScopeInfo = NULL;
Error = SetOptionValue(
GlobalServerIpAddressUnicodeString,
0,
(DHCP_OPTION_ID)OptionID,
GlobalClassName,
GlobalVendorName,
&ScopeInfo,
&OptionValue
);
Cleanup:
if( UnicodeOptionValueString != NULL ) {
DhcpFreeMemory( UnicodeOptionValueString );
}
return( Error );
}
DWORD
SetOptionValues(
IN LPWSTR ServerAddress,
IN DWORD Flags,
IN LPWSTR ClassName,
IN LPWSTR VendorName,
IN LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
IN LPDHCP_OPTION_VALUE_ARRAY OptionValues
)
{
DWORD MajorVersion, MinorVersion;
DWORD Error;
#ifdef NT5
if( GlobalNoRPC ) {
MajorVersion = CLASS_ID_VERSION ;
} else {
Error = DhcpGetVersion(ServerAddress, &MajorVersion, &MinorVersion);
if( ERROR_SUCCESS != Error ) {
printf("Could not determine server version.\n");
return Error;
}
}
if( MajorVersion >= CLASS_ID_VERSION ) {
return DhcpSetOptionValuesV5(
ServerAddress,
GlobalIsVendor ? Flags | DHCP_FLAGS_OPTION_IS_VENDOR : Flags,
ClassName,
VendorName,
ScopeInfo,
OptionValues
);
}
// incorrect version, just do like before..
#endif
return DhcpSetOptionValues(
ServerAddress,
ScopeInfo,
OptionValues
);
}
ProcessSetGlobalOptionValues(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
#define NUM_VALUES 5
DWORD Error;
DHCP_OPTION_ID OptionID;
DHCP_OPTION_SCOPE_INFO ScopeInfo;
DHCP_OPTION_DATA OptionValue;
DHCP_OPTION_DATA_ELEMENT OptionData[NUM_VALUES];
LPWSTR UnicodeOptionValueString[NUM_VALUES];
DHCP_OPTION_VALUE_ARRAY ValuesArray;
DHCP_OPTION_VALUE Values[NUM_VALUES];
DWORD NumValue;
RtlZeroMemory( UnicodeOptionValueString, NUM_VALUES * sizeof(LPWSTR) );
//
// Expected Parameters are :
// <OptionID OptionType OptionValue>
//
if( CommandArgc < 3 ) {
printf("usage:DhcpCmd SrvIpAddress SetGlobalOptionValues [Command Parameters].\n"
"<Command Parameters> - <OptionID OptionType OptionValue> <..>.\n"); Error = ERROR_SUCCESS;
goto Cleanup;
}
for (NumValue = 0;
(CommandArgc >= 3) && (NumValue < NUM_VALUES);
NumValue++, CommandArgc -= 3, CommandArgv += 3 ) {
OptionID = strtoul( CommandArgv[0], NULL, 0 );
Error = SetOptionDataType(
CommandArgv[1],
CommandArgv[2],
&OptionData[NumValue],
&UnicodeOptionValueString[NumValue]
);
if( Error != ERROR_SUCCESS ) {
goto Cleanup;
}
Values[NumValue].OptionID = OptionID;
Values[NumValue].Value.NumElements = 1;
Values[NumValue].Value.Elements = &OptionData[NumValue];
}
ValuesArray.NumElements = NumValue;
ValuesArray.Values = Values;
ScopeInfo.ScopeType = DhcpGlobalOptions;
ScopeInfo.ScopeInfo.GlobalScopeInfo = NULL;
Error = SetOptionValues(
GlobalServerIpAddressUnicodeString,
0,
GlobalClassName,
GlobalVendorName,
&ScopeInfo,
&ValuesArray
);
Cleanup:
for (NumValue = 0; NumValue < NUM_VALUES; NumValue++) {
if( UnicodeOptionValueString[NumValue] != NULL ) {
DhcpFreeMemory( UnicodeOptionValueString );
}
}
return( Error );
}
DWORD
RemoveOptionValue(
IN LPWSTR ServerAddress,
IN DWORD Flags,
IN DHCP_OPTION_ID OptionID,
IN LPWSTR ClassName,
IN LPWSTR VendorName,
IN LPDHCP_OPTION_SCOPE_INFO ScopeInfo
)
{
DWORD MajorVersion, MinorVersion;
DWORD Error;
#ifdef NT5
if( GlobalNoRPC ) {
MajorVersion = CLASS_ID_VERSION ;
} else {
Error = DhcpGetVersion(ServerAddress, &MajorVersion, &MinorVersion);
if( ERROR_SUCCESS != Error ) {
printf("Could not determine server version.\n");
return Error;
}
}
if( MajorVersion >= CLASS_ID_VERSION ) {
return DhcpRemoveOptionValueV5(
ServerAddress,
GlobalIsVendor ? Flags | DHCP_FLAGS_OPTION_IS_VENDOR : Flags,
OptionID,
ClassName,
VendorName,
ScopeInfo
);
}
// incorrect version, just do like before..
#endif
return DhcpRemoveOptionValue(
ServerAddress,
OptionID,
ScopeInfo
);
}
DWORD
ProcessRemoveGlobalOptionValue(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
DHCP_OPTION_ID OptionID;
DHCP_OPTION_SCOPE_INFO ScopeInfo;
//
// Expected Parameters are :
// <OptionID OptionType OptionValue>
//
if( CommandArgc != 1 ) {
printf("usage:DhcpCmd SrvIpAddress RemoveGlobalOptionValue [Command Parameters].\n"
"<Command Parameters> - <OptionID>.\n");
Error = ERROR_SUCCESS;
goto Cleanup;
}
OptionID = strtoul( CommandArgv[0], NULL, 0 );
ScopeInfo.ScopeType = DhcpGlobalOptions;
ScopeInfo.ScopeInfo.GlobalScopeInfo = NULL;
Error = RemoveOptionValue(
GlobalServerIpAddressUnicodeString,
0,
(DHCP_OPTION_ID)OptionID,
GlobalClassName,
GlobalVendorName,
&ScopeInfo
);
Cleanup:
return Error ;
}
ProcessSetSubnetOptionValue(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
DHCP_OPTION_ID OptionID;
DHCP_OPTION_SCOPE_INFO ScopeInfo;
DHCP_OPTION_DATA OptionValue;
DHCP_OPTION_DATA_ELEMENT OptionData;
LPWSTR UnicodeOptionValueString = NULL;
//
// Expected Parameters are :
// subnet-address <OptionID OptionType OptionValue>
//
if( CommandArgc < 4 ) {
printf("usage:DhcpCmd SrvIpAddress SetSubnetOptionValue "
"[Command Parameters].\n"
"<Command Parameters> - "
"<SubnetAddress OptionID OptionType OptionValue>.\n");
Error = ERROR_SUCCESS;
goto Cleanup;
}
ScopeInfo.ScopeType = DhcpSubnetOptions;
ScopeInfo.ScopeInfo.SubnetScopeInfo = DhcpDottedStringToIpAddress( CommandArgv[0] );
OptionID = strtoul( CommandArgv[1], NULL, 0 );
Error = SetOptionDataType(
CommandArgv[2],
CommandArgv[3],
&OptionData,
&UnicodeOptionValueString );
if( Error != ERROR_SUCCESS ) {
goto Cleanup;
}
OptionValue.NumElements = 1;
OptionValue.Elements = &OptionData;
Error = SetOptionValue(
GlobalServerIpAddressUnicodeString,
0,
(DHCP_OPTION_ID)OptionID,
GlobalClassName,
GlobalVendorName,
&ScopeInfo,
&OptionValue
);
Cleanup:
if( UnicodeOptionValueString != NULL ) {
DhcpFreeMemory( UnicodeOptionValueString );
}
return( Error );
}
ProcessRemoveSubnetOptionValue(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
DHCP_OPTION_ID OptionID;
DHCP_OPTION_SCOPE_INFO ScopeInfo;
//
// Expected Parameters are :
// subnet-address <OptionID>
//
if( CommandArgc != 2 ) {
printf("usage:DhcpCmd SrvIpAddress RemoveSubnetOptionValue "
"[Command Parameters].\n"
"<Command Parameters> - "
"<SubnetAddress OptionID>.\n");
Error = ERROR_SUCCESS;
goto Cleanup;
}
ScopeInfo.ScopeType = DhcpSubnetOptions;
ScopeInfo.ScopeInfo.SubnetScopeInfo = DhcpDottedStringToIpAddress( CommandArgv[0] );
OptionID = strtoul( CommandArgv[1], NULL, 0 );
Error = RemoveOptionValue(
GlobalServerIpAddressUnicodeString,
0,
(DHCP_OPTION_ID)OptionID,
GlobalClassName,
GlobalVendorName,
&ScopeInfo
);
Cleanup:
return Error ;
}
ProcessSetReservedOptionValue(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
DHCP_OPTION_ID OptionID;
DHCP_OPTION_SCOPE_INFO ScopeInfo;
DHCP_OPTION_DATA OptionValue;
DHCP_OPTION_DATA_ELEMENT OptionData;
LPWSTR UnicodeOptionValueString = NULL;
//
// Expected Parameters are :
// subnet-address reservation-address <OptionID OptionType OptionValue>
//
if( CommandArgc < 5 ) {
printf("usage:DhcpCmd SrvIpAddress SetReservedOptionValue "
"[Command Parameters].\n"
"<Command Parameters> - "
"<SubnetAddress Reservation-Address OptionID OptionType OptionValue>.\n");
Error = ERROR_SUCCESS;
goto Cleanup;
}
ScopeInfo.ScopeType = DhcpReservedOptions;
ScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpSubnetAddress =
DhcpDottedStringToIpAddress(CommandArgv[0]);
ScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpAddress =
DhcpDottedStringToIpAddress( CommandArgv[1] );
OptionID = strtoul( CommandArgv[2], NULL, 0 );
Error = SetOptionDataType(
CommandArgv[3],
CommandArgv[4],
&OptionData,
&UnicodeOptionValueString
);
if( Error != ERROR_SUCCESS ) {
goto Cleanup;
}
OptionValue.NumElements = 1;
OptionValue.Elements = &OptionData;
Error = SetOptionValue(
GlobalServerIpAddressUnicodeString,
0,
(DHCP_OPTION_ID)OptionID,
GlobalClassName,
GlobalVendorName,
&ScopeInfo,
&OptionValue
);
Cleanup:
if( UnicodeOptionValueString != NULL ) {
DhcpFreeMemory( UnicodeOptionValueString );
}
return( Error );
}
ProcessRemoveReservedOptionValue(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
DHCP_OPTION_ID OptionID;
DHCP_OPTION_SCOPE_INFO ScopeInfo;
//
// Expected Parameters are :
// subnet-address reservation-address <OptionID>
//
if( CommandArgc < 3 ) {
printf("usage:DhcpCmd SrvIpAddress RemoveReservedOptionValue "
"[Command Parameters].\n"
"<Command Parameters> - "
"<SubnetAddress Reservation-Address OptionID>.\n");
Error = ERROR_SUCCESS;
goto Cleanup;
}
ScopeInfo.ScopeType = DhcpReservedOptions;
ScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpSubnetAddress =
DhcpDottedStringToIpAddress(CommandArgv[0]);
ScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpAddress =
DhcpDottedStringToIpAddress( CommandArgv[1] );
OptionID = strtoul( CommandArgv[2], NULL, 0 );
Error = RemoveOptionValue(
GlobalServerIpAddressUnicodeString,
0,
(DHCP_OPTION_ID)OptionID,
GlobalClassName,
GlobalVendorName,
&ScopeInfo
);
Cleanup:
return Error ;
}
VOID
PrintClientInfo(
LPDHCP_CLIENT_INFO_V4 ClientInfo
)
{
DWORD i;
DWORD DataLength;
LPBYTE Data;
SYSTEMTIME SystemTime;
FILETIME LocalTime;
char *szClientType;
printf("ClientInfo :\n");
printf("\tIP Address = %s.\n",
DhcpIpAddressToDottedString(ClientInfo->ClientIpAddress));
printf("\tSubnetMask = %s.\n",
DhcpIpAddressToDottedString(ClientInfo->SubnetMask));
DataLength = ClientInfo->ClientHardwareAddress.DataLength;
Data = ClientInfo->ClientHardwareAddress.Data;
printf("\tClient Hardware Address = ");
for( i = 0; i < DataLength; i++ ) {
if( (i+1) < DataLength ) {
printf("%.2lx-", (DWORD)Data[i]);
}
else {
printf("%.2lx", (DWORD)Data[i]);
}
}
printf(".\n");
printf("\tName = %ws.\n", ClientInfo->ClientName);
printf("\tComment = %ws.\n", ClientInfo->ClientComment);
printf("\tType = " );
switch( ClientInfo->bClientType )
{
case CLIENT_TYPE_NONE:
szClientType= "None";
break;
case CLIENT_TYPE_DHCP:
szClientType = "DHCP";
break;
case CLIENT_TYPE_BOOTP:
szClientType = "BOOTP";
break;
case CLIENT_TYPE_UNSPECIFIED:
szClientType = "Unspecified";
break;
default:
DhcpAssert( FALSE );
}
printf( "%s\n", szClientType );
printf("\tExpires = ");
if ( ClientInfo->ClientLeaseExpires.dwLowDateTime ==
DHCP_DATE_TIME_INFINIT_LOW &&
ClientInfo->ClientLeaseExpires.dwHighDateTime ==
DHCP_DATE_TIME_INFINIT_HIGH )
{
printf( "Never (lease duration is infinite.)\n" );
}
else if( FileTimeToLocalFileTime(
(FILETIME *)(&ClientInfo->ClientLeaseExpires),
&LocalTime) ) {
if( FileTimeToSystemTime( &LocalTime, &SystemTime ) ) {
printf( "%02u/%02u/%02u %02u:%02u:%02u.\n",
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wYear,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond );
}
else {
printf( "Can't convert time, %ld.\n", GetLastError() );
}
}
else {
printf( "Can't convert time, %ld.\n", GetLastError() );
}
printf("\tOwner Host IP Address = %s.\n",
DhcpIpAddressToDottedString(ClientInfo->OwnerHost.IpAddress));
printf("\tOwner Host NetBios Name = %ws.\n",
ClientInfo->OwnerHost.NetBiosName );
printf("\tOwner Host Name = %ws.\n",
ClientInfo->OwnerHost.HostName );
}
#ifdef NT5
VOID
PrintClientInfoV5(
LPDHCP_CLIENT_INFO_V5 ClientInfo
)
{
DWORD i;
DWORD DataLength;
LPBYTE Data;
SYSTEMTIME SystemTime;
FILETIME LocalTime;
char *szClientType;
printf("ClientInfo :\n");
printf("\tIP Address = %s.\n",
DhcpIpAddressToDottedString(ClientInfo->ClientIpAddress));
printf("\tSubnetMask = %s.\n",
DhcpIpAddressToDottedString(ClientInfo->SubnetMask));
DataLength = ClientInfo->ClientHardwareAddress.DataLength;
Data = ClientInfo->ClientHardwareAddress.Data;
printf("\tClient Hardware Address = ");
for( i = 0; i < DataLength; i++ ) {
if( (i+1) < DataLength ) {
printf("%.2lx-", (DWORD)Data[i]);
}
else {
printf("%.2lx", (DWORD)Data[i]);
}
}
printf(".\n");
printf("\tName = %ws.\n", ClientInfo->ClientName);
printf("\tComment = %ws.\n", ClientInfo->ClientComment);
printf("\tType = " );
switch( ClientInfo->bClientType )
{
case CLIENT_TYPE_NONE:
szClientType= "None";
break;
case CLIENT_TYPE_DHCP:
szClientType = "DHCP";
break;
case CLIENT_TYPE_BOOTP:
szClientType = "BOOTP";
break;
case CLIENT_TYPE_UNSPECIFIED:
szClientType = "Unspecified";
break;
default:
DhcpAssert( FALSE );
}
printf( "%s\n", szClientType );
printf("\tExpires = ");
if ( ClientInfo->ClientLeaseExpires.dwLowDateTime ==
DHCP_DATE_TIME_INFINIT_LOW &&
ClientInfo->ClientLeaseExpires.dwHighDateTime ==
DHCP_DATE_TIME_INFINIT_HIGH )
{
printf( "Never (lease duration is infinite.)\n" );
}
else if( FileTimeToLocalFileTime(
(FILETIME *)(&ClientInfo->ClientLeaseExpires),
&LocalTime) ) {
if( FileTimeToSystemTime( &LocalTime, &SystemTime ) ) {
printf( "%02u/%02u/%02u %02u:%02u:%02u.\n",
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wYear,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond );
}
else {
printf( "Can't convert time, %ld.\n", GetLastError() );
}
}
else {
printf( "Can't convert time, %ld.\n", GetLastError() );
}
printf("\tOwner Host IP Address = %s.\n",
DhcpIpAddressToDottedString(ClientInfo->OwnerHost.IpAddress));
printf("\tOwner Host NetBios Name = %ws.\n",
ClientInfo->OwnerHost.NetBiosName );
printf("\tOwner Host Name = %ws.\n",
ClientInfo->OwnerHost.HostName );
printf("\tState = %0x\n", ClientInfo->AddressState );
}
#endif NT5
VOID
PrintClientInfoShort(
LPDHCP_CLIENT_INFO_V4 ClientInfo
)
{
SYSTEMTIME SystemTime;
FILETIME LocalTime;
printf("%ld\t %- 16.16s %- 16.16ws ",
GlobalClientCount++,
DhcpIpAddressToDottedString(ClientInfo->ClientIpAddress),
ClientInfo->ClientName
);
if ( ClientInfo->ClientLeaseExpires.dwLowDateTime ==
DHCP_DATE_TIME_INFINIT_LOW &&
ClientInfo->ClientLeaseExpires.dwHighDateTime ==
DHCP_DATE_TIME_INFINIT_HIGH )
{
printf( "Never (lease duration is infinite.)\n" );
}
else if( FileTimeToLocalFileTime(
(FILETIME *)(&ClientInfo->ClientLeaseExpires),
&LocalTime) ) {
if( FileTimeToSystemTime( &LocalTime, &SystemTime ) ) {
printf( "%02u/%02u/%02u %02u:%02u:%02u",
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wYear,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond );
}
else {
printf( "% 18.18s", "******************" );
}
}
else {
printf( "%.18s", "******************" );
}
printf( "\n" );
}
#ifdef NT5
VOID
PrintClientInfoShortV5(
LPDHCP_CLIENT_INFO_V5 ClientInfo
)
{
SYSTEMTIME SystemTime;
FILETIME LocalTime;
printf("%ld\t %- 16.16s %- 16.16ws ",
GlobalClientCount++,
DhcpIpAddressToDottedString(ClientInfo->ClientIpAddress),
ClientInfo->ClientName
);
if ( ClientInfo->ClientLeaseExpires.dwLowDateTime ==
DHCP_DATE_TIME_INFINIT_LOW &&
ClientInfo->ClientLeaseExpires.dwHighDateTime ==
DHCP_DATE_TIME_INFINIT_HIGH )
{
printf( "Never (lease duration is infinite.)\n" );
}
else if( FileTimeToLocalFileTime(
(FILETIME *)(&ClientInfo->ClientLeaseExpires),
&LocalTime) ) {
if( FileTimeToSystemTime( &LocalTime, &SystemTime ) ) {
printf( "%02u/%02u/%02u %02u:%02u:%02u",
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wYear,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond );
}
else {
printf( "% 18.18s", "******************" );
}
}
else {
printf( "%.18s", "******************" );
}
printf( "State=%02x", ClientInfo->AddressState);
printf( "\n" );
}
#endif NT5
VOID
PrintClientInfoShort1(
LPDHCP_CLIENT_INFO_V4 ClientInfo
)
{
DWORD i;
DWORD DataLength;
LPBYTE Data;
printf("%ld\t %- 16.16s %- 16.16ws ",
GlobalClientCount++,
DhcpIpAddressToDottedString(ClientInfo->ClientIpAddress),
ClientInfo->ClientName
);
DataLength = ClientInfo->ClientHardwareAddress.DataLength;
Data = ClientInfo->ClientHardwareAddress.Data;
for( i = 0; i < DataLength; i++ ) {
printf("%.2lx", (DWORD)Data[i]);
}
printf( "\n" );
}
DWORD
DetectIpAddressConflict(
DHCP_IP_ADDRESS IpAddress,
DWORD dwRetries,
LPBOOL AddressExists
)
/*++
Routine Description:
This function pings the specific IP address and checks if it exists
The number of "ping" retries is controled by the parameter
DetectConflictRetries in the registry. When it is set to 0, this
function always sets result to FALSE.
Arguments:
IpAddress - The IP address to check
AddressExists - pointer to the variable where the result is to be stored
Return Value:
Windows Error
--*/
{
HANDLE IcmpHandle;
char ReplyBuffer [1000];
DWORD NumReplies = 0;
DWORD i,
dwResult;
DhcpAssert( dwRetries );
*AddressExists = FALSE;
IcmpHandle = IcmpCreateFile();
if (IcmpHandle == INVALID_HANDLE_VALUE)
return GetLastError();
for (i = 0; i < dwRetries; i++) {
NumReplies = IcmpSendEcho(
IcmpHandle,
(IPAddr) ntohl(IpAddress),
(LPVOID) "DHCP Server Bad Address",
(WORD)strlen("DHCP Server Bad Address"),
NULL,
ReplyBuffer,
sizeof(ReplyBuffer),
1000
);
if (NumReplies != 0) {
break;
}
}
dwResult = GetLastError();
// IcmpSendEcho will also return 0 to indicate an error condition.
// IP_REQ_TIMED_OUT indicates no response
if ( IP_REQ_TIMED_OUT == dwResult )
dwResult = 0;
IcmpCloseHandle (IcmpHandle);
*AddressExists = (NumReplies != 0);
return dwResult;
}
BOOL
AddressCanBeDeleted(
IN DHCP_IP_ADDRESS Address
)
{
BOOL RetVal;
RetVal = TRUE;
DetectIpAddressConflict(
Address,
3,
&RetVal
);
if( RetVal ) {
printf("This address exists, so it wont be deleted\n");
} else {
printf("This address does not exist, so it will be deleted.\n");
}
return !RetVal;
}
DWORD
ProcessDeleteClient(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DHCP_SEARCH_INFO SrchInfo;
DWORD Error;
if( CommandArgc != 1 ) {
printf("Usage: DhcpCmd SrvIpAddress DeleteClient ClientIp\n");
return ERROR_INVALID_PARAMETER;
}
SrchInfo.SearchType = DhcpClientIpAddress;
SrchInfo.SearchInfo.ClientIpAddress = htonl(
inet_addr( CommandArgv[0]) );
Error = DhcpDeleteClientInfo(
GlobalServerIpAddressUnicodeString, &SrchInfo );
if( NO_ERROR != Error ) {
printf("DhcpDeleteClientInfo failed %ld\n", Error);
}
return Error;
}
DWORD
ProcessDeleteBadClients(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
BOOL NoPing = FALSE;
DWORD Error;
DHCP_RESUME_HANDLE ResumeHandle = 0;
LPDHCP_CLIENT_INFO_ARRAY_V4 ClientEnumInfo = NULL;
DWORD ClientsRead = 0;
DWORD ClientsTotal = 0;
DWORD i;
if( CommandArgc > 1 || (
CommandArgc == 1 && _stricmp(CommandArgv[0], "NOPING") ) ) {
printf("usage:DhcpCmd SrvIpAddress DeleteBadClients [NOPING]\n");
return ERROR_SUCCESS;
}
NoPing = (CommandArgc == 1 );
GlobalClientCount = 1;
for(;;) {
ClientEnumInfo = NULL;
Error = DhcpEnumSubnetClientsV4(
GlobalServerIpAddressUnicodeString,
0,
&ResumeHandle,
(DWORD)(-1),
&ClientEnumInfo,
&ClientsRead,
&ClientsTotal
);
if( (Error != ERROR_SUCCESS) && (Error != ERROR_MORE_DATA) ) {
printf("DhcpEnumSubnetClients failed, %ld.\n", Error );
return( Error );
}
DhcpAssert( ClientEnumInfo != NULL );
DhcpAssert( ClientEnumInfo->NumElements == ClientsRead );
for( i = 0; i < ClientsRead; i++ ) {
if( NULL == ClientEnumInfo->Clients[i]->ClientName ) {
//
// No name? Can that be a bad client? no.
//
continue;
}
if( wcscmp(ClientEnumInfo->Clients[i]->ClientName, L"BAD_ADDRESS" ) ) {
//
// Not a bad client! ignore it.
//
continue;
}
PrintClientInfoShort1( ClientEnumInfo->Clients[i] );
if( NoPing || AddressCanBeDeleted(ClientEnumInfo->Clients[i]->ClientIpAddress) ) {
DHCP_SEARCH_INFO SrchInfo2 = {
DhcpClientIpAddress,
ClientEnumInfo->Clients[i]->ClientIpAddress
};
Error = DhcpDeleteClientInfo(
GlobalServerIpAddressUnicodeString,
&SrchInfo2
);
if( ERROR_SUCCESS != Error ) {
printf("DhcpDeleteClientInfo failed %ld, continuing. \n", Error);
}
}
}
DhcpRpcFreeMemory( ClientEnumInfo );
if( Error != ERROR_MORE_DATA ) {
break;
}
}
return(Error);
return 0;
}
#ifdef NT5
VOID
PrintClientInfoShort1V5(
LPDHCP_CLIENT_INFO_V5 ClientInfo
)
{
DWORD i;
DWORD DataLength;
LPBYTE Data;
printf("%ld\t %- 16.16s %- 16.16ws ",
GlobalClientCount++,
DhcpIpAddressToDottedString(ClientInfo->ClientIpAddress),
ClientInfo->ClientName
);
DataLength = ClientInfo->ClientHardwareAddress.DataLength;
Data = ClientInfo->ClientHardwareAddress.Data;
for( i = 0; i < DataLength; i++ ) {
printf("%.2lx", (DWORD)Data[i]);
}
printf(" State=%02x\n", ClientInfo->AddressState);
printf( "\n" );
}
DWORD
ProcessEnumClientsV5(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
DHCP_RESUME_HANDLE ResumeHandle = 0;
LPDHCP_CLIENT_INFO_ARRAY_V5 ClientEnumInfo = NULL;
DWORD ClientsRead = 0;
DWORD ClientsTotal = 0;
DWORD i;
//
// Expected Parameters are : <SubnetAddress>
//
if( CommandArgc < 1 ) {
printf("usage:DhcpCmd SrvIpAddress EnumClients [Command Parameters].\n"
"<Command Parameters> - <SubnetAddress [-v | -h] >.\n" );
return( ERROR_SUCCESS );
}
GlobalClientCount = 1;
for(;;) {
ClientEnumInfo = NULL;
Error = DhcpEnumSubnetClientsV5(
GlobalServerIpAddressUnicodeString,
DhcpDottedStringToIpAddress(CommandArgv[0]),
&ResumeHandle,
(DWORD)(-1),
&ClientEnumInfo,
&ClientsRead,
&ClientsTotal );
if( (Error != ERROR_SUCCESS) && (Error != ERROR_MORE_DATA) ) {
printf("DhcpEnumSubnetClients failed, %ld.\n", Error );
return( Error );
}
DhcpAssert( ClientEnumInfo != NULL );
DhcpAssert( ClientEnumInfo->NumElements == ClientsRead );
if( (CommandArgc > 1) && CommandArgv[1][0] == '-') {
switch (CommandArgv[1][1]) {
case 'h':
case 'H':
for( i = 0; i < ClientsRead; i++ ) {
PrintClientInfoShort1V5( ClientEnumInfo->Clients[i] );
}
break;
case 'V':
case 'v':
printf("Num Client info read = %ld.\n", ClientsRead );
printf("Total Client count = %ld.\n", ClientsTotal );
for( i = 0; i < ClientsRead; i++ ) {
PrintClientInfoV5( ClientEnumInfo->Clients[i] );
}
break;
default:
for( i = 0; i < ClientsRead; i++ ) {
PrintClientInfoShortV5( ClientEnumInfo->Clients[i] );
}
break;
}
}
else {
for( i = 0; i < ClientsRead; i++ ) {
PrintClientInfoShortV5( ClientEnumInfo->Clients[i] );
}
}
DhcpRpcFreeMemory( ClientEnumInfo );
if( Error != ERROR_MORE_DATA ) {
break;
}
}
return(Error);
}
#endif NT5
DWORD
ProcessEnumClients(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
DHCP_RESUME_HANDLE ResumeHandle = 0;
LPDHCP_CLIENT_INFO_ARRAY_V4 ClientEnumInfo = NULL;
DWORD ClientsRead = 0;
DWORD ClientsTotal = 0;
DWORD i;
//
// Expected Parameters are : <SubnetAddress>
//
if( CommandArgc < 1 ) {
printf("usage:DhcpCmd SrvIpAddress EnumClients [Command Parameters].\n"
"<Command Parameters> - <SubnetAddress [-v | -h] >.\n" );
return( ERROR_SUCCESS );
}
GlobalClientCount = 1;
for(;;) {
ClientEnumInfo = NULL;
Error = DhcpEnumSubnetClientsV4(
GlobalServerIpAddressUnicodeString,
DhcpDottedStringToIpAddress(CommandArgv[0]),
&ResumeHandle,
(DWORD)(-1),
&ClientEnumInfo,
&ClientsRead,
&ClientsTotal );
if( (Error != ERROR_SUCCESS) && (Error != ERROR_MORE_DATA) ) {
printf("DhcpEnumSubnetClients failed, %ld.\n", Error );
return( Error );
}
DhcpAssert( ClientEnumInfo != NULL );
DhcpAssert( ClientEnumInfo->NumElements == ClientsRead );
if( (CommandArgc > 1) && CommandArgv[1][0] == '-') {
switch (CommandArgv[1][1]) {
case 'h':
case 'H':
for( i = 0; i < ClientsRead; i++ ) {
PrintClientInfoShort1( ClientEnumInfo->Clients[i] );
}
break;
case 'V':
case 'v':
printf("Num Client info read = %ld.\n", ClientsRead );
printf("Total Client count = %ld.\n", ClientsTotal );
for( i = 0; i < ClientsRead; i++ ) {
PrintClientInfo( ClientEnumInfo->Clients[i] );
}
break;
default:
for( i = 0; i < ClientsRead; i++ ) {
PrintClientInfoShort( ClientEnumInfo->Clients[i] );
}
break;
}
}
else {
for( i = 0; i < ClientsRead; i++ ) {
PrintClientInfoShort( ClientEnumInfo->Clients[i] );
}
}
DhcpRpcFreeMemory( ClientEnumInfo );
if( Error != ERROR_MORE_DATA ) {
break;
}
}
return(Error);
}
DWORD
ProcessMibCounts(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
LPDHCP_MIB_INFO MibInfo = NULL;
DWORD i;
LPSCOPE_MIB_INFO ScopeInfo;
SYSTEMTIME SystemTime;
FILETIME LocalTime;
Error = DhcpGetMibInfo(
GlobalServerIpAddressUnicodeString,
&MibInfo );
if( Error != ERROR_SUCCESS ) {
return( Error );
}
DhcpAssert( MibInfo != NULL );
printf("Discovers = %d.\n", MibInfo->Discovers);
printf("Offers = %d.\n", MibInfo->Offers);
printf("Requests = %d.\n", MibInfo->Requests);
printf("Acks = %d.\n", MibInfo->Acks);
printf("Naks = %d.\n", MibInfo->Naks);
printf("Declines = %d.\n", MibInfo->Declines);
printf("Releases = %d.\n", MibInfo->Releases);
printf("ServerStartTime = ");
if( FileTimeToLocalFileTime(
(FILETIME *)(&MibInfo->ServerStartTime),
&LocalTime) ) {
if( FileTimeToSystemTime( &LocalTime, &SystemTime ) ) {
printf( "%02u/%02u/%02u %02u:%02u:%02u.\n",
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wYear,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond );
}
else {
printf( "Can't convert time, %ld.\n", GetLastError() );
}
}
else {
printf( "Can't convert time, %ld.\n", GetLastError() );
}
printf("Scopes = %d.\n", MibInfo->Scopes);
ScopeInfo = MibInfo->ScopeInfo;
for ( i = 0; i < MibInfo->Scopes; i++ ) {
printf("Subnet = %s.\n",
DhcpIpAddressToDottedString(ScopeInfo[i].Subnet));
printf("\tNumAddressesInuse = %d.\n",
ScopeInfo[i].NumAddressesInuse );
printf("\tNumAddressesFree = %d.\n",
ScopeInfo[i].NumAddressesFree );
printf("\tNumPendingOffers = %d.\n",
ScopeInfo[i].NumPendingOffers );
}
DhcpRpcFreeMemory( MibInfo );
return( ERROR_SUCCESS );
}
VOID
PrintConfigCommands(
VOID
)
{
DWORD i;
DWORD NumCommands;
NumCommands = sizeof(GlobalConfigCommandInfo) /
sizeof(CONFIG_COMMAND_INFO);
DhcpAssert( NumCommands <= UnknownConfigCommand );
for( i = 0; i < NumCommands; i++) {
printf( "\t%ld. %s\n",
i, GlobalConfigCommandInfo[i].CommandName );
}
}
CONFIG_COMMAND_CODE
DecodeConfigCommand(
LPSTR CommandName
)
{
DWORD i;
DWORD NumCommands;
NumCommands = sizeof(GlobalConfigCommandInfo) /
sizeof(CONFIG_COMMAND_INFO);
DhcpAssert( NumCommands <= UnknownConfigCommand );
for( i = 0; i < NumCommands; i++) {
if( _stricmp( CommandName,
GlobalConfigCommandInfo[i].CommandName ) == 0 ) {
return( GlobalConfigCommandInfo[i].CommandCode );
}
}
return( UnknownConfigCommand );
}
//
// this function assumes input of the following format:
//
// [generic name1],[server name1],<boot file1>;[generic name2],...
//
//
WCHAR *
ParseBootFileTable(
char *szBootFileTable,
DWORD *pcb
)
{
WCHAR *pwszOutput;
DWORD cb;
*pcb = 0;
cb = strlen( szBootFileTable ) + 2; // double null terminator
pwszOutput = DhcpAllocateMemory( cb * sizeof( WCHAR ) );
if ( pwszOutput )
{
WCHAR *pwszTemp = DhcpOemToUnicode( szBootFileTable, pwszOutput );
if ( !pwszTemp )
{
// conversion failed
DhcpFreeMemory( pwszOutput );
pwszOutput = NULL;
}
else
{
// replace ';' with '\0'
while ( *pwszTemp )
{
if ( L';' == *pwszTemp )
{
*pwszTemp = L'\0';
}
++pwszTemp;
}
*pcb = cb * sizeof( WCHAR );
// add 2cnd null terminator
pwszOutput[ cb - 1 ] = L'\0';
}
}
return pwszOutput;
}
void PrintBootFileString(
WCHAR *wszBootFileString
)
{
WCHAR *pwszBootFile = wszBootFileString;
while( *pwszBootFile != BOOT_FILE_STRING_DELIMITER_W )
pwszBootFile++;
*pwszBootFile = L'\0';
printf( "Bootfile Server = %S\n", wszBootFileString );
printf( "Bootfile = %S\n\n", ++pwszBootFile );
}
void PrintBootTableString(
WCHAR *wszBootFileTable
)
{
while( *wszBootFileTable )
{
WCHAR *pwszDelimiter = wszBootFileTable;
DWORD cb = wcslen( wszBootFileTable ) + 1;
while( *pwszDelimiter != BOOT_FILE_STRING_DELIMITER_W )
pwszDelimiter++;
*pwszDelimiter = L'\0';
printf( "Generic Bootfile request = %S\n", wszBootFileTable );
PrintBootFileString( ++pwszDelimiter );
wszBootFileTable += cb;
}
}
DWORD ProcessRemoveSubscope(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DHCP_IP_ADDRESS SubnetAddress;
DWORD dwResult;
if( CommandArgc < 1 )
{
printf("usage:DhcpCmd SrvIpAddress RemoveSubscope <scope ID>.\n" );
return( ERROR_SUCCESS );
}
SubnetAddress = htonl( inet_addr( CommandArgv[0] ) );
dwResult = DhcpSetSuperScopeV4(
GlobalServerIpAddressUnicodeString,
SubnetAddress,
NULL,
TRUE
);
return dwResult;
}
DWORD ProcessSetSuperScope(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DHCP_IP_ADDRESS SubnetAddress;
WCHAR *pwszSuperScopeName;
BOOL fChangeExisting;
DWORD dwResult;
if( CommandArgc < 3 )
{
printf("usage:DhcpCmd SrvIpAddress SetSuperScope <SuperScope name> <scope ID> <1|0>\n" );
return( ERROR_SUCCESS );
}
pwszSuperScopeName = DhcpOemToUnicode( CommandArgv[0], NULL );
SubnetAddress = htonl( inet_addr( CommandArgv[1] ) );
fChangeExisting = (BOOL) ( *(CommandArgv[2]) - '0' );
dwResult = DhcpSetSuperScopeV4( GlobalServerIpAddressUnicodeString,
SubnetAddress,
pwszSuperScopeName,
fChangeExisting );
return dwResult;
}
DWORD ProcessDeleteSuperScope(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
WCHAR *pwszSuperScope;
DWORD dwResult;
if( CommandArgc < 1 ) {
printf("usage:DhcpCmd SrvIpAddress DeleteSuperScope <scope name>.\n" );
return( ERROR_SUCCESS );
}
printf( "Deleting SuperScope %s\n", CommandArgv[0] );
pwszSuperScope = DhcpOemToUnicode( CommandArgv[0], NULL );
dwResult = DhcpDeleteSuperScopeV4( GlobalServerIpAddressUnicodeString,
pwszSuperScope );
DhcpFreeMemory( pwszSuperScope );
return dwResult;
}
DWORD ProcessGetSuperScopeTable(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DHCP_SUPER_SCOPE_TABLE *pTable = NULL;
DWORD dwResult;
dwResult = DhcpGetSuperScopeInfoV4(
GlobalServerIpAddressUnicodeString,
&pTable );
if ( ERROR_SUCCESS == dwResult )
{
DWORD n;
for ( n = 0; n < pTable->cEntries; n++ )
{
IN_ADDR InAddr;
InAddr.s_addr = htonl( pTable->pEntries[n].SubnetAddress );
printf( "Superscope name = %S\n", pTable->pEntries[n].SuperScopeName );
printf( "Subnet address = %s\n", inet_ntoa( InAddr ) );
printf( "Superscope goup number = %d\n", pTable->pEntries[n].SuperScopeNumber );
}
DhcpRpcFreeMemory( pTable );
}
return ERROR_SUCCESS;
}
DWORD
ProcessServerConfig(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
LPDHCP_SERVER_CONFIG_INFO_V4 ConfigInfo = NULL;
DWORD FieldsToSet = 0;
CONFIG_COMMAND_CODE CommandCode;
DWORD Value;
LPWSTR ValueString;
if( CommandArgc < 1 ) {
Error = DhcpServerGetConfigV4(
GlobalServerIpAddressUnicodeString,
&ConfigInfo );
if( Error != ERROR_SUCCESS ) {
return( Error );
}
DhcpAssert( ConfigInfo != NULL );
printf("APIProtocolSupport = %lx\n", ConfigInfo->APIProtocolSupport );
printf("DatabaseName = %ws\n", ConfigInfo->DatabaseName );
printf("DatabasePath = %ws\n", ConfigInfo->DatabasePath );
printf("BackupPath = %ws\n", ConfigInfo->BackupPath );
printf("BackupInterval = %ld mins.\n",
ConfigInfo->BackupInterval );
printf("DatabaseLoggingFlag = %ld\n", ConfigInfo->DatabaseLoggingFlag );
printf("RestoreFlag = %ld\n", ConfigInfo->RestoreFlag );
printf("DatabaseCleanupInterval = %ld mins.\n",
ConfigInfo->DatabaseCleanupInterval );
printf("DebugFlag = %lx\n", ConfigInfo->DebugFlag );
printf("PingRetries = %d\n", ConfigInfo->dwPingRetries );
printf("ActivityLog = %d\n", (DWORD) ConfigInfo->fAuditLog );
if ( ConfigInfo->cbBootTableString )
{
printf( "BOOTP request table:\n" );
PrintBootTableString( ConfigInfo->wszBootTableString );
}
DhcpRpcFreeMemory( ConfigInfo );
return( Error );
}
if ( CommandArgc == 1)
{
++CommandArgc;
return ERROR_INVALID_PARAMETER;
}
else
{
ConfigInfo = DhcpAllocateMemory( sizeof(DHCP_SERVER_CONFIG_INFO_V4) );
if( ConfigInfo == NULL ) {
printf("Insufficient memory\n");
return( ERROR_NOT_ENOUGH_MEMORY );
}
RtlZeroMemory( ConfigInfo, sizeof( *ConfigInfo ) );
}
while( CommandArgc >= 2 ) {
CommandCode = DecodeConfigCommand( CommandArgv[0] );
Value = 0;
ValueString = NULL;
switch( CommandCode )
{
case ConfigDatabaseName:
case ConfigDatabasePath:
case ConfigBackupPath:
case ConfigAPIProtocolSupport:
case ConfigBackupInterval:
case ConfigDatabaseLoggingFlag:
case ConfigRestoreFlag:
case ConfigDatabaseCleanupInterval:
case ConfigDebugFlag:
case ConfigActivityLog:
case ConfigPingRetries:
Value = atoi( CommandArgv[1] );
break;
case ConfigBootFileTable:
ValueString = ParseBootFileTable( CommandArgv[1],
&Value );
break;
}
switch( CommandCode ) {
case ConfigAPIProtocolSupport:
FieldsToSet |= Set_APIProtocolSupport;
ConfigInfo->APIProtocolSupport = Value;
break;
case ConfigDatabaseName:
FieldsToSet |= Set_DatabaseName;
ConfigInfo->DatabaseName = ValueString;
break;
case ConfigDatabasePath:
FieldsToSet |= Set_DatabasePath;
ConfigInfo->DatabasePath = ValueString;
break;
case ConfigBackupPath:
FieldsToSet |= Set_BackupPath;
ConfigInfo->BackupPath = ValueString;
break;
case ConfigBackupInterval:
FieldsToSet |= Set_BackupInterval;
ConfigInfo->BackupInterval = Value;
break;
case ConfigDatabaseLoggingFlag:
FieldsToSet |= Set_DatabaseLoggingFlag;
ConfigInfo->DatabaseLoggingFlag = Value;
break;
case ConfigRestoreFlag:
FieldsToSet |= Set_RestoreFlag;
ConfigInfo->RestoreFlag = Value;
break;
case ConfigDatabaseCleanupInterval:
FieldsToSet |= Set_DatabaseCleanupInterval;
ConfigInfo->DatabaseCleanupInterval = Value;
break;
case ConfigDebugFlag:
FieldsToSet |= Set_DebugFlag;
ConfigInfo->DebugFlag = Value;
break;
case ConfigPingRetries:
FieldsToSet |= Set_PingRetries;
ConfigInfo->dwPingRetries = Value;
break;
case ConfigActivityLog:
FieldsToSet |= Set_AuditLogState;
ConfigInfo->fAuditLog = (BOOL) Value;
break;
case ConfigBootFileTable:
FieldsToSet |= Set_BootFileTable;
ConfigInfo->wszBootTableString = ValueString;
ConfigInfo->cbBootTableString = Value;
break;
case UnknownConfigCommand:
default:
printf("usage:DhcpCmd SrvIpAddress ServerConfig "
"[ConfigCommand ConfigValue]"
"[ConfigCommand ConfigValue]"
"... \n");
printf("ConfigCommands : \n");
PrintConfigCommands();
Error = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
CommandArgc -= 2;
CommandArgv += 2;
}
Error = DhcpServerSetConfigV4(
GlobalServerIpAddressUnicodeString,
FieldsToSet,
ConfigInfo );
if( Error != ERROR_SUCCESS ) {
goto Cleanup;
}
Error = ProcessServerConfig( 0, NULL );
Cleanup:
if( ConfigInfo != NULL ) {
if( ConfigInfo->DatabaseName != NULL ) {
DhcpFreeMemory( ConfigInfo->DatabaseName );
}
if( ConfigInfo->DatabasePath != NULL ) {
DhcpFreeMemory( ConfigInfo->DatabasePath );
}
if( ConfigInfo->BackupPath != NULL ) {
DhcpFreeMemory( ConfigInfo->BackupPath );
}
DhcpFreeMemory( ConfigInfo );
}
return( Error );
}
DWORD
ProcessCheckDB(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
LPDHCP_SCAN_LIST ScanList = NULL;
BOOL FixFlag = FALSE;
if( CommandArgc < 1 ) {
printf("usage:DhcpCmd SrvIpAddress CheckDB [Command Parameters].\n"
"<Command Parameters> - <SubnetAddress> <[Fix]>.\n" );
return( ERROR_SUCCESS );
}
if( CommandArgc >= 2 ) {
//
// parse fix parameter.
//
if( _stricmp(CommandArgv[0], "fix") ) {
FixFlag = TRUE;
}
}
//
// scan dhcp database and registry, check consistency and get bad
// entries if any.
//
Error = DhcpScanDatabase(
GlobalServerIpAddressUnicodeString,
DhcpDottedStringToIpAddress(CommandArgv[0]),
FixFlag,
&ScanList
);
if( Error != ERROR_SUCCESS ) {
printf("DhcpScanDatabase failed, %ld.\n", Error );
return( Error );
}
//
// display bad entries.
//
if( (ScanList != NULL) &&
(ScanList->NumScanItems != 0) &&
(ScanList->ScanItems != NULL) ) {
LPDHCP_SCAN_ITEM ScanItem;
LPDHCP_SCAN_ITEM ScanItemEnd;
DWORD i = 1;
ScanItemEnd =
ScanList->ScanItems +
ScanList->NumScanItems;
for( ScanItem = ScanList->ScanItems;
ScanItem < ScanItemEnd; ScanItem++ ) {
printf("%ld %- 16.16s ",
i++,
DhcpIpAddressToDottedString(ScanItem->IpAddress) );
if( ScanItem->ScanFlag == DhcpRegistryFix ) {
printf("Fix Registry\n");
}
else if( ScanItem->ScanFlag == DhcpDatabaseFix ) {
printf("Fix Database\n");
}
else {
printf("Fix Unknown\n");
}
}
}
return( ERROR_SUCCESS );
}
VOID
PrintOptionValue(
LPDHCP_OPTION_DATA OptionValue
)
{
DWORD NumElements;
DHCP_OPTION_DATA_TYPE OptionType;
DWORD i;
printf("Option Value : \n");
NumElements = OptionValue->NumElements;
printf("\tNumber of Option Elements = %ld\n", NumElements );
if( NumElements == 0 ) {
return;
}
OptionType = OptionValue->Elements[0].OptionType;
printf("\tOption Elements Type = " );
switch( OptionType ) {
case DhcpByteOption:
printf("DhcpByteOption\n");
break;
case DhcpWordOption:
printf("DhcpWordOption\n");
break;
case DhcpDWordOption:
printf("DhcpDWordOption\n");
break;
case DhcpDWordDWordOption:
printf("DhcpDWordDWordOption\n");
break;
case DhcpIpAddressOption:
printf("DhcpIpAddressOption\n");
break;
case DhcpStringDataOption:
printf("DhcpStringDataOption\n");
break;
case DhcpBinaryDataOption:
printf("DhcpBinaryDataOption\n");
break;
case DhcpEncapsulatedDataOption:
printf("DhcpEncapsulatedDataOption\n");
break;
default:
printf("Unknown\n");
return;
}
for( i = 0; i < OptionValue->NumElements; i++ ) {
DhcpAssert( OptionType == OptionValue->Elements[i].OptionType );
printf("Option Element %ld value = ", i );
switch( OptionType ) {
case DhcpByteOption:
printf("%lx.\n", (DWORD)
OptionValue->Elements[i].Element.ByteOption );
break;
case DhcpWordOption:
printf("%lx.\n", (DWORD)
OptionValue->Elements[i].Element.WordOption );
break;
case DhcpDWordOption:
printf("%lx.\n",
OptionValue->Elements[i].Element.DWordOption );
break;
case DhcpDWordDWordOption:
printf("%lx, %lx.\n",
OptionValue->Elements[i].Element.DWordDWordOption.DWord1,
OptionValue->Elements[i].Element.DWordDWordOption.DWord2 );
break;
case DhcpIpAddressOption:
printf("%lx.\n",
OptionValue->Elements[i].Element.IpAddressOption );
break;
case DhcpStringDataOption:
printf("%ws.\n",
OptionValue->Elements[i].Element.StringDataOption );
break;
case DhcpBinaryDataOption:
case DhcpEncapsulatedDataOption: {
DWORD j;
DWORD Length;
Length = OptionValue->Elements[i].Element.BinaryDataOption.DataLength;
for( j = 0; j < Length; j++ ) {
printf("%2lx ",
OptionValue->Elements[i].Element.BinaryDataOption.Data[j] );
}
printf(".\n");
break;
}
default:
printf("PrintOptionValue: Unknown OptionType.\n");
break;
}
}
}
VOID
PrintOptionInfo(
LPDHCP_OPTION OptionInfo
)
{
printf( "Option Info : \n");
printf( "\tOptionId : %ld \n", (DWORD)OptionInfo->OptionID );
printf( "\tOptionName : %ws \n", OptionInfo->OptionName );
printf( "\tOptionComment : %ws \n", OptionInfo->OptionComment );
PrintOptionValue( &OptionInfo->DefaultValue );
printf( "\tOptionType : %ld \n", (DWORD)OptionInfo->OptionType );
}
DWORD
_EnumOptions(
IN LPWSTR ServerAddress,
IN DWORD Flags,
IN LPWSTR ClassName,
IN LPWSTR VendorName,
IN OUT DHCP_RESUME_HANDLE *ResumeHandle,
IN DWORD PreferredMaximum,
OUT LPDHCP_OPTION_ARRAY *Options,
OUT DWORD *OptionsRead,
OUT DWORD *OptionsTotal
)
{
DWORD MajorVersion, MinorVersion;
DWORD Error;
#ifdef NT5
if( GlobalNoRPC ) {
MajorVersion = CLASS_ID_VERSION ;
} else {
Error = DhcpGetVersion(ServerAddress, &MajorVersion, &MinorVersion);
if( ERROR_SUCCESS != Error ) {
printf("Could not determine server version.\n");
return Error;
}
}
if( MajorVersion >= CLASS_ID_VERSION ) {
return DhcpEnumOptionsV5(
ServerAddress,
GlobalIsVendor ? Flags | DHCP_FLAGS_OPTION_IS_VENDOR : Flags,
ClassName,
VendorName,
ResumeHandle,
PreferredMaximum,
Options,
OptionsRead,
OptionsTotal
);
}
// incorrect version, just do like before..
#endif
return DhcpEnumOptions(
ServerAddress,
ResumeHandle,
PreferredMaximum,
Options,
OptionsRead,
OptionsTotal
);
}
DWORD
ProcessEnumOptions(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
LPDHCP_OPTION_ARRAY OptionsArray = NULL;
DHCP_RESUME_HANDLE ResumeHandle = 0;
DWORD OptionsRead;
DWORD OptionsTotal;
Error = _EnumOptions(
GlobalServerIpAddressUnicodeString,
0,
GlobalClassName,
GlobalVendorName,
&ResumeHandle,
0xFFFFFFFF, // get all.
&OptionsArray,
&OptionsRead,
&OptionsTotal
);
if( Error != ERROR_SUCCESS ) {
printf("DhcpEnumOptions failed %ld\n", Error );
} else {
DWORD i;
LPDHCP_OPTION Options;
DWORD NumOptions;
printf("OptionsRead = %ld.\n", OptionsRead);
printf("OptionsTotal = %ld.\n", OptionsTotal);
Options = OptionsArray->Options;
NumOptions = OptionsArray->NumElements;
for( i = 0; i < NumOptions; i++, Options++ ) {
PrintOptionInfo( Options );
}
DhcpRpcFreeMemory( OptionsArray );
OptionsArray = NULL;
}
return( Error );
}
DWORD
ProcessGetVersion(
DWORD *pdwMajor,
DWORD *pdwMinor
)
{
DWORD Error = ERROR_SUCCESS;
DWORD MajorVersion;
DWORD MinorVersion;
if ( g_dwMajor == (DWORD) -1 && g_dwMinor == (DWORD) -1 ) {
Error = DhcpGetVersion(
GlobalServerIpAddressUnicodeString,
&g_dwMajor,
&g_dwMinor
);
if ( ERROR_SUCCESS == Error ) {
printf( "DHCP Server version %d.%d\n", g_dwMajor, g_dwMinor );
}
}
return Error;
}
VOID
PrintOptionArray(
IN LPDHCP_OPTION_ARRAY OptArray
)
{
DWORD i;
for( i = 0; i < OptArray->NumElements ; i ++ ) {
PrintOptionInfo( &OptArray->Options[i] );
}
}
VOID
PrintOptionValue1(
IN LPDHCP_OPTION_VALUE OptVal
)
{
printf("Option: %ld\n", OptVal->OptionID);
PrintOptionValue(&OptVal->Value);
}
VOID
PrintOptionValuesArray(
IN LPDHCP_OPTION_VALUE_ARRAY OptValArray
)
{
DWORD i;
if( NULL == OptValArray ) return;
for( i = 0; i < OptValArray->NumElements ; i ++ ) {
PrintOptionValue1( &OptValArray->Values[i] );
}
}
#ifdef NT5
#define CHKNULL(Str) ((Str)?(Str):L"<None>")
VOID
PrintAllOptions(
IN LPDHCP_ALL_OPTIONS Options
)
{
DWORD i;
printf("Options [Non Vendor specific]:\n"
"==============================\n");
PrintOptionArray(Options->NonVendorOptions);
for( i = 0; i < Options->NumVendorOptions; i ++ ) {
printf("\nOptions [Vendor:%ws]\n==============================\n",
CHKNULL( Options->VendorOptions[i].VendorName));
PrintOptionInfo(&(Options->VendorOptions[i].Option));
}
printf("\n\n");
}
DWORD
ProcessGetAllOptions(
IN DWORD CommandArgc,
IN LPSTR CommandArgv[]
)
{
DWORD Error, Major, Minor;
LPDHCP_ALL_OPTIONS Options;
if( TRUE == GlobalNoRPC ) {
Major = CLASS_ID_VERSION;
} else {
Error = DhcpGetVersion(
GlobalServerIpAddressUnicodeString,
&Major,
&Minor
);
if( ERROR_SUCCESS != Error ) {
printf("Could not get DHCP server version!\n");
return Error;
}
}
if( CLASS_ID_VERSION > Major ) {
printf("DHCP Server (major version %ld) does not support this function call.\n", Major);
return ERROR_SUCCESS;
}
Options = NULL;
Error = DhcpGetAllOptions(
GlobalServerIpAddressUnicodeString,
0,
&Options
);
if( ERROR_SUCCESS != Error ) return Error;
if( NULL == Options ) {
printf("Server returned no options!\n");
DhcpAssert(FALSE);
} else {
PrintAllOptions(Options);
DhcpRpcFreeMemory(Options);
}
return ERROR_SUCCESS;
}
VOID
PrintAllOptionValues(
IN LPDHCP_ALL_OPTION_VALUES OptValues
)
{
DWORD i;
printf("Flags = 0x%lx, NumValues = %ld\n", OptValues->Flags, OptValues->NumElements);
for( i = 0; i < OptValues->NumElements ; i ++ ) {
printf("Options");
if( OptValues->Options[i].IsVendor ) {
printf(" for vendor <%ws>", CHKNULL(OptValues->Options[i].VendorName));
}
if( OptValues->Options[i].ClassName ) {
printf(" for user class <%ws>", OptValues->Options[i].ClassName);
}
printf(":\n");
PrintOptionValuesArray(OptValues->Options[i].OptionsArray);
}
}
DWORD
ProcessGetAllOptionValues(
IN DWORD CommandArgc,
IN LPSTR CommandArgv[]
)
{
DWORD Error, Major, Minor;
LPDHCP_ALL_OPTION_VALUES OptionValues;
DHCP_OPTION_SCOPE_INFO ScopeInfo;
// usage: getalloptionvalues [command parameters]
// [CommandParameters] = Global/Default/SubnetAddress/SubnetAddress ReservedAddress
if( CommandArgc != 1 && CommandArgc != 2 ) {
printf("Usage: Dhcpcmd SrvIpAddress GetAllOptionValues [CommandParameters]\n");
printf("<Command parameters> - < GLOBAL | DEFAULT | Subnet-Adddress | Subnet-Address Reserved Address>.\n");
return ERROR_SUCCESS;
}
if( 1 == CommandArgc ) {
if( 0 == _stricmp(CommandArgv[0], "GLOBAL") ) {
ScopeInfo.ScopeType = DhcpGlobalOptions;
} else if ( 0 == _stricmp(CommandArgv[0], "DEFAULT" )) {
ScopeInfo.ScopeType = DhcpDefaultOptions;
} else {
ScopeInfo.ScopeType = DhcpSubnetOptions;
ScopeInfo.ScopeInfo.SubnetScopeInfo = DhcpDottedStringToIpAddress(CommandArgv[0]);
}
} else {
ScopeInfo.ScopeType = DhcpReservedOptions;
ScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpSubnetAddress =
DhcpDottedStringToIpAddress(CommandArgv[0]);
ScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpAddress =
DhcpDottedStringToIpAddress( CommandArgv[1] );
}
if( TRUE == GlobalNoRPC ) {
Major = CLASS_ID_VERSION;
} else {
Error = DhcpGetVersion(
GlobalServerIpAddressUnicodeString,
&Major,
&Minor
);
if( ERROR_SUCCESS != Error ) {
printf("Could not get DHCP server version!\n");
return Error;
}
}
if( CLASS_ID_VERSION > Major ) {
printf("DHCP Server (major version %ld) does not support this function call.\n", Major);
return ERROR_SUCCESS;
}
OptionValues = NULL;
Error = DhcpGetAllOptionValues(
GlobalServerIpAddressUnicodeString,
0,
&ScopeInfo,
&OptionValues
);
if( ERROR_SUCCESS != Error ) return Error;
if( NULL == OptionValues ) {
printf("Server returned no option values!\n");
DhcpAssert(FALSE);
} else {
PrintAllOptionValues(OptionValues);
DhcpRpcFreeMemory(OptionValues);
}
return ERROR_SUCCESS;
}
PBYTE
GetLangTag(
)
{
char b1[8], b2[8];
static char buff[80];
GetLocaleInfoA(LOCALE_SYSTEM_DEFAULT, LOCALE_SISO639LANGNAME, b1, sizeof(b1));
GetLocaleInfoA(LOCALE_SYSTEM_DEFAULT, LOCALE_SISO3166CTRYNAME, b2, sizeof(b2));
if (_stricmp(b1, b2))
sprintf(buff, "%s-%s", b1, b2);
else
strcpy(buff, b1);
return buff;
}
DWORD
ProcessCreateMScope(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
DHCP_MSCOPE_INFO MScopeInfo;
LPWSTR UnicodeMScopeName = NULL;
LPWSTR UnicodeMScopeDesc = NULL;
DWORD MScopeId;
LPWSTR UnicodeLangTag = NULL;
PBYTE LangTag;
DWORD ExpiryTimeInHours = 0;
//
// Expected Parameters are : <MScopeId MScopeName MScopeDescription ExpiryTime>
//
if( CommandArgc < 4 ) {
printf("usage:DhcpCmd SrvIpAddress CreateMScope [Command Parameters].\n"
"<Command Parameters> - <MScopeId MScopeName MScopeDescription ExpiryTimeInHours>.\n"
);
Error = ERROR_SUCCESS;
goto Cleanup;
}
MScopeId = atoi( CommandArgv[0] );
if (!MScopeId) {
Error = ERROR_SUCCESS;
goto Cleanup;
}
UnicodeMScopeName = DhcpOemToUnicode( CommandArgv[1], NULL );
DhcpAssert( UnicodeMScopeName != NULL );
UnicodeMScopeDesc = DhcpOemToUnicode( CommandArgv[2], NULL );
DhcpAssert( UnicodeMScopeName != NULL );
ExpiryTimeInHours = atoi(CommandArgv[3]);
LangTag = GetLangTag();
UnicodeLangTag = DhcpOemToUnicode(LangTag, NULL);
DhcpAssert(UnicodeLangTag);
MScopeInfo.MScopeName = UnicodeMScopeName;
MScopeInfo.MScopeId = MScopeId;
MScopeInfo.MScopeComment = UnicodeMScopeDesc;
MScopeInfo.PrimaryHost.IpAddress =
DhcpDottedStringToIpAddress(GlobalServerIpAddressAnsiString);
MScopeInfo.PrimaryHost.NetBiosName = NULL;
MScopeInfo.PrimaryHost.HostName = NULL;
MScopeInfo.MScopeState = DhcpSubnetEnabled;
MScopeInfo.MScopeFlags = 0;
MScopeInfo.MScopeAddressPolicy = 0;
MScopeInfo.TTL = 255;
MScopeInfo.LangTag = UnicodeLangTag;
MScopeInfo.ExpiryTime = DhcpCalculateTime(ExpiryTimeInHours*60*60);
Error = DhcpSetMScopeInfo(
GlobalServerIpAddressUnicodeString,
UnicodeMScopeName,
&MScopeInfo,
TRUE); // new scope
Cleanup:
if( UnicodeMScopeName != NULL ) {
DhcpFreeMemory( UnicodeMScopeName );
}
if( UnicodeMScopeDesc != NULL ) {
DhcpFreeMemory( UnicodeMScopeDesc );
}
return( Error );
}
DWORD
ProcessDeleteMScope(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
DHCP_MSCOPE_INFO MScopeInfo;
LPWSTR UnicodeMScopeName = NULL;
//
// Expected Parameters are : <MScopeName>
//
if( CommandArgc < 1 ) {
printf("usage:DhcpCmd SrvIpAddress DeleteMScope [Command Parameters].\n"
"<Command Parameters> - <MScopeName>.\n" );
Error = ERROR_SUCCESS;
goto Cleanup;
}
UnicodeMScopeName = DhcpOemToUnicode( CommandArgv[0], NULL );
DhcpAssert( UnicodeMScopeName != NULL );
Error = DhcpDeleteMScope(
GlobalServerIpAddressUnicodeString,
UnicodeMScopeName,
TRUE); // force flag
Cleanup:
if( UnicodeMScopeName != NULL ) {
DhcpFreeMemory( UnicodeMScopeName );
}
return( Error );
}
DWORD
ProcessAddMScopeIpRange(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
DHCP_IP_RANGE IpRange;
DHCP_SUBNET_ELEMENT_DATA_V4 Element;
LPWSTR UnicodeMScopeName = NULL;
//
// Expected Parameters are : <MScopeName IpRangeStart IpRangeEnd>
//
if( CommandArgc < 3 ) {
printf("usage:DhcpCmd SrvIpAddress AddMScopeIpRange [Command Parameters].\n"
"<Command Parameters> - <MScopeName IpRangeStart IpRangeEnd>.\n" );
return( ERROR_SUCCESS );
}
UnicodeMScopeName = DhcpOemToUnicode( CommandArgv[0], NULL );
DhcpAssert( UnicodeMScopeName != NULL );
IpRange.StartAddress = DhcpDottedStringToIpAddress(CommandArgv[1]);
IpRange.EndAddress = DhcpDottedStringToIpAddress(CommandArgv[2]);
Element.ElementType = DhcpIpRanges;
Element.Element.IpRange = &IpRange;
Error = DhcpAddMScopeElement(
GlobalServerIpAddressUnicodeString,
UnicodeMScopeName,
&Element );
if( UnicodeMScopeName != NULL ) DhcpFreeMemory( UnicodeMScopeName );
return( Error );
}
DWORD
ProcessReconcileMScope(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
LPWSTR UnicodeMScopeName = NULL;
LPDHCP_SCAN_LIST ScanList = NULL;
//
// Expected Parameters are : <MScopeName>
//
if( CommandArgc < 1 ) {
printf("usage:DhcpCmd SrvIpAddress ReconcileMScope [Command Parameters].\n"
"<Command Parameters> - <MScopeName>.\n" );
return( ERROR_SUCCESS );
}
UnicodeMScopeName = DhcpOemToUnicode( CommandArgv[0], NULL );
DhcpAssert( UnicodeMScopeName != NULL );
Error = DhcpScanMDatabase(
GlobalServerIpAddressUnicodeString,
UnicodeMScopeName,
TRUE, // fix bad entries.
&ScanList );
if( UnicodeMScopeName != NULL ) DhcpFreeMemory( UnicodeMScopeName );
if (ScanList) DhcpRpcFreeMemory( ScanList );
return( Error );
}
VOID
PrintMClientInfo(
LPDHCP_MCLIENT_INFO ClientInfo
)
{
DWORD i;
DWORD DataLength;
LPBYTE Data;
SYSTEMTIME SystemTime;
FILETIME LocalTime;
char *szClientType;
printf("ClientInfo :\n");
printf("\tIP Address = %s.\n",
DhcpIpAddressToDottedString(ClientInfo->ClientIpAddress));
printf("\tMScopeId = %lx.\n",
ClientInfo->MScopeId);
DataLength = ClientInfo->ClientId.DataLength;
Data = ClientInfo->ClientId.Data;
printf("\tClient Hardware Address = ");
for( i = 0; i < DataLength; i++ ) {
if( (i+1) < DataLength ) {
printf("%.2lx-", (DWORD)Data[i]);
}
else {
printf("%.2lx", (DWORD)Data[i]);
}
}
printf(".\n");
printf("\tName = %ws.\n", ClientInfo->ClientName);
printf("\tStarts = ");
if ( ClientInfo->ClientLeaseStarts.dwLowDateTime ==
DHCP_DATE_TIME_INFINIT_LOW &&
ClientInfo->ClientLeaseStarts.dwHighDateTime ==
DHCP_DATE_TIME_INFINIT_HIGH )
{
printf( "Never (lease duration is infinite.)\n" );
}
else if( FileTimeToLocalFileTime(
(FILETIME *)(&ClientInfo->ClientLeaseStarts),
&LocalTime) ) {
if( FileTimeToSystemTime( &LocalTime, &SystemTime ) ) {
printf( "%02u/%02u/%02u %02u:%02u:%02u.\n",
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wYear,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond );
}
else {
printf( "Can't convert time, %ld.\n", GetLastError() );
}
}
else {
printf( "Can't convert time, %ld.\n", GetLastError() );
}
printf("\tExpires = ");
if ( ClientInfo->ClientLeaseEnds.dwLowDateTime ==
DHCP_DATE_TIME_INFINIT_LOW &&
ClientInfo->ClientLeaseEnds.dwHighDateTime ==
DHCP_DATE_TIME_INFINIT_HIGH )
{
printf( "Never (lease duration is infinite.)\n" );
}
else if( FileTimeToLocalFileTime(
(FILETIME *)(&ClientInfo->ClientLeaseEnds),
&LocalTime) ) {
if( FileTimeToSystemTime( &LocalTime, &SystemTime ) ) {
printf( "%02u/%02u/%02u %02u:%02u:%02u.\n",
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wYear,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond );
}
else {
printf( "Can't convert time, %ld.\n", GetLastError() );
}
}
else {
printf( "Can't convert time, %ld.\n", GetLastError() );
}
printf("\tOwner Host IP Address = %s.\n",
DhcpIpAddressToDottedString(ClientInfo->OwnerHost.IpAddress));
printf("\tOwner Host NetBios Name = %ws.\n",
ClientInfo->OwnerHost.NetBiosName );
printf("\tOwner Host Name = %ws.\n",
ClientInfo->OwnerHost.HostName );
printf("\tState = %0x\n", ClientInfo->AddressState );
}
VOID
PrintMClientInfoShort(
LPDHCP_MCLIENT_INFO ClientInfo
)
{
SYSTEMTIME SystemTime;
FILETIME LocalTime;
printf("%ld\t %- 16.16s %- 16.16ws ",
GlobalClientCount++,
DhcpIpAddressToDottedString(ClientInfo->ClientIpAddress),
ClientInfo->ClientName
);
if ( ClientInfo->ClientLeaseEnds.dwLowDateTime ==
DHCP_DATE_TIME_INFINIT_LOW &&
ClientInfo->ClientLeaseEnds.dwHighDateTime ==
DHCP_DATE_TIME_INFINIT_HIGH )
{
printf( "Never (lease duration is infinite.)\n" );
}
else if( FileTimeToLocalFileTime(
(FILETIME *)(&ClientInfo->ClientLeaseEnds),
&LocalTime) ) {
if( FileTimeToSystemTime( &LocalTime, &SystemTime ) ) {
printf( "%02u/%02u/%02u %02u:%02u:%02u",
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wYear,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond );
}
else {
printf( "% 18.18s", "******************" );
}
}
else {
printf( "%.18s", "******************" );
}
printf( "\n" );
}
DWORD
ProcessEnumMScopeClients(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
DHCP_RESUME_HANDLE ResumeHandle = 0;
LPDHCP_MCLIENT_INFO_ARRAY ClientEnumInfo = NULL;
DWORD ClientsRead = 0;
DWORD ClientsTotal = 0;
DWORD i;
LPWSTR UnicodeMScopeName = NULL;
//
// Expected Parameters are : <MScopeNames>
//
if( CommandArgc < 1 ) {
printf("usage:DhcpCmd SrvIpAddress EnumClients [Command Parameters].\n"
"<Command Parameters> - <MScopeNames [-v | -h] >.\n" );
return( ERROR_SUCCESS );
}
UnicodeMScopeName = DhcpOemToUnicode( CommandArgv[0], NULL );
DhcpAssert( UnicodeMScopeName != NULL );
GlobalClientCount = 1;
for(;;) {
ClientEnumInfo = NULL;
Error = DhcpEnumMScopeClients(
GlobalServerIpAddressUnicodeString,
UnicodeMScopeName,
&ResumeHandle,
(DWORD)(-1),
&ClientEnumInfo,
&ClientsRead,
&ClientsTotal );
if( (Error != ERROR_SUCCESS) && (Error != ERROR_MORE_DATA) ) {
printf("DhcpEnumSubnetClients failed, %ld.\n", Error );
return( Error );
}
DhcpAssert( ClientEnumInfo != NULL );
DhcpAssert( ClientEnumInfo->NumElements == ClientsRead );
if( (CommandArgc > 1) && CommandArgv[1][0] == '-') {
switch (CommandArgv[1][1]) {
case 'h':
case 'H':
for( i = 0; i < ClientsRead; i++ ) {
PrintMClientInfoShort( ClientEnumInfo->Clients[i] );
}
break;
case 'V':
case 'v':
printf("Num Client info read = %ld.\n", ClientsRead );
printf("Total Client count = %ld.\n", ClientsTotal );
for( i = 0; i < ClientsRead; i++ ) {
PrintMClientInfo( ClientEnumInfo->Clients[i] );
}
break;
default:
for( i = 0; i < ClientsRead; i++ ) {
PrintMClientInfoShort( ClientEnumInfo->Clients[i] );
}
break;
}
}
else {
for( i = 0; i < ClientsRead; i++ ) {
PrintMClientInfoShort( ClientEnumInfo->Clients[i] );
}
}
DhcpRpcFreeMemory( ClientEnumInfo );
if( Error != ERROR_MORE_DATA ) {
break;
}
}
return(Error);
}
DWORD
ProcessEnumMScopes(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
DHCP_RESUME_HANDLE ResumeHandle = 0;
LPDHCP_MSCOPE_TABLE MScopeTable = NULL;
DWORD ClientsRead = 0;
DWORD ClientsTotal = 0;
DWORD i;
LPWSTR UnicodeMScopeName = NULL;
for(;;) {
MScopeTable = NULL;
Error = DhcpEnumMScopes(
GlobalServerIpAddressUnicodeString,
&ResumeHandle,
(DWORD)(-1),
&MScopeTable,
&ClientsRead,
&ClientsTotal );
if( (Error != ERROR_SUCCESS) && (Error != ERROR_MORE_DATA) ) {
printf("DhcpEnumSubnetClients failed, %ld.\n", Error );
return( Error );
}
DhcpAssert( MScopeTable != NULL );
DhcpAssert( MScopeTable->NumElements == ClientsRead );
printf("Total Client count = %ld.\n", ClientsTotal );
for( i = 0; i < ClientsRead; i++ ) {
printf("MScope %ws\n", MScopeTable->pMScopeNames[i] );
}
break;
DhcpRpcFreeMemory( MScopeTable );
if( Error != ERROR_MORE_DATA ) {
break;
}
}
return(Error);
}
DWORD
ProcessMCastMibCounts(
DWORD CommandArgc,
LPSTR *CommandArgv
)
{
DWORD Error;
LPDHCP_MCAST_MIB_INFO MibInfo = NULL;
DWORD i;
LPMSCOPE_MIB_INFO ScopeInfo;
SYSTEMTIME SystemTime;
FILETIME LocalTime;
Error = DhcpGetMCastMibInfo(
GlobalServerIpAddressUnicodeString,
&MibInfo );
if( Error != ERROR_SUCCESS ) {
return( Error );
}
DhcpAssert( MibInfo != NULL );
printf("Discovers = %d.\n", MibInfo->Discovers);
printf("Offers = %d.\n", MibInfo->Offers);
printf("Requests = %d.\n", MibInfo->Requests);
printf("Acks = %d.\n", MibInfo->Acks);
printf("Naks = %d.\n", MibInfo->Naks);
printf("Renews = %d.\n", MibInfo->Renews);
printf("Releases = %d.\n", MibInfo->Releases);
printf("ServerStartTime = ");
if( FileTimeToLocalFileTime(
(FILETIME *)(&MibInfo->ServerStartTime),
&LocalTime) ) {
if( FileTimeToSystemTime( &LocalTime, &SystemTime ) ) {
printf( "%02u/%02u/%02u %02u:%02u:%02u.\n",
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wYear,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond );
}
else {
printf( "Can't convert time, %ld.\n", GetLastError() );
}
}
else {
printf( "Can't convert time, %ld.\n", GetLastError() );
}
printf("Scopes = %d.\n", MibInfo->Scopes);
ScopeInfo = MibInfo->ScopeInfo;
for ( i = 0; i < MibInfo->Scopes; i++ ) {
printf("Scope Name = %ws.\n",
(ScopeInfo[i].MScopeName));
printf("\tNumAddressesInuse = %d.\n",
ScopeInfo[i].NumAddressesInuse );
printf("\tNumAddressesFree = %d.\n",
ScopeInfo[i].NumAddressesFree );
printf("\tNumPendingOffers = %d.\n",
ScopeInfo[i].NumPendingOffers );
}
DhcpRpcFreeMemory( MibInfo );
return( ERROR_SUCCESS );
}
DWORD
ProcessAddServer( // add a server to DS
IN DWORD CommandArgc,
IN LPSTR *CommandArgv
)
{
DWORD Err;
DWORD Address;
LPWSTR ServerName;
DHCP_SERVER_INFO Server;
// usage: AddServer <ServerName> <ServerIpAddress>
if( CommandArgc != 2 ) { // wrong usage
printf("usage:DhcpCmd SrvIpAddress AddServer <server-dns-name> <server-ip-address>\n");
return ERROR_SUCCESS;
}
if( GlobalNoDS ) {
Err = DhcpDsInit();
if( ERROR_SUCCESS != Err ) return Err;
}
ServerName = DhcpOemToUnicode( CommandArgv[0], NULL);
Address = (inet_addr(CommandArgv[1]));
printf("Adding server %ws,%s\n", ServerName, inet_ntoa(*(struct in_addr*)&Address));
Server.Version = 0;
Server.ServerName = ServerName;
Server.ServerAddress = htonl(Address);
Server.Flags = 0;
Server.State = 0;
Server.DsLocation = NULL;
Server.DsLocType = 0;
Err = DhcpAddServer(0, NULL, &Server, NULL, NULL);
DhcpFreeMemory(ServerName);
if( ERROR_SUCCESS != Err ) { // could not add the server
printf("DhcpAddServer failed %ld (0x%lx)\n", Err, Err);
}
if( GlobalNoDS ) DhcpDsCleanup();
return Err;
}
DWORD
ProcessDelServer( // delete a server from DS
IN DWORD CommandArgc,
IN LPSTR *CommandArgv
)
{
DWORD Err;
DWORD Address;
LPWSTR ServerName;
DHCP_SERVER_INFO Server;
// usage: DelServer <ServerName> <ServerIpAddress>
if( CommandArgc != 2 ) { // wrong usage
printf("usage:DhcpCmd SrvIpAddress DelServer <server-dns-name> <server-ip-address>\n");
return ERROR_SUCCESS;
}
if( GlobalNoDS ) {
Err = DhcpDsInit();
if( ERROR_SUCCESS != Err ) return Err;
}
ServerName = DhcpOemToUnicode( CommandArgv[0], NULL);
Address = (inet_addr(CommandArgv[1]));
printf("Deleting server %ws,%s\n", ServerName, inet_ntoa(*(struct in_addr*)&Address));
Server.Version = 0;
Server.ServerName = ServerName;
Server.ServerAddress = htonl(Address);
Server.Flags = 0;
Server.State = 0;
Server.DsLocation = NULL;
Server.DsLocType = 0;
Err = DhcpDeleteServer(0, NULL, &Server, NULL, NULL);
DhcpFreeMemory(ServerName);
if( ERROR_SUCCESS != Err ) { // could not add the server
printf("DhcpDeleteServer failed %ld (0x%lx)\n", Err, Err);
}
if( GlobalNoDS ) DhcpDsCleanup();
return Err;
}
VOID
PrintServerInfo( // print server information
IN LPDHCP_SERVER_INFO Server
)
{
DHCP_IP_ADDRESS ServerAddress = htonl(Server->ServerAddress);
printf("Server [%ws] Address [%s] Ds location: %ws\n",
Server->ServerName,
inet_ntoa(*(struct in_addr *)&ServerAddress),
Server->DsLocation? Server->DsLocation : L"<no-ds-location-available>"
);
}
VOID
PrintServerInfoArray( // print list of servers
IN LPDHCP_SERVER_INFO_ARRAY Servers
)
{
DWORD i;
printf("%ld Servers were found in the DS:\n", Servers->NumElements);
for( i = 0; i < Servers->NumElements; i ++ ) {
printf("\t");
PrintServerInfo(&Servers->Servers[i]);
}
printf("\n");
}
DWORD
ProcessEnumServers( // enumerate servers in DS.
IN DWORD CommandArgc, // ignored..
IN LPSTR *CommandArgv // ignored
)
{
DWORD Err;
LPDHCP_SERVER_INFO_ARRAY Servers;
if( GlobalNoDS ) {
Err = DhcpDsInit();
if( ERROR_SUCCESS != Err ) return Err;
}
Servers = NULL;
Err = DhcpEnumServers(0, NULL, &Servers, NULL, NULL);
if( ERROR_SUCCESS != Err ) {
printf("DhcpEnumServers failed %ld (0x%lx)\n", Err, Err);
if( GlobalNoDS ) DhcpDsCleanup();
return Err;
}
PrintServerInfoArray(Servers);
LocalFree(Servers);
if( GlobalNoDS ) DhcpDsCleanup();
return ERROR_SUCCESS;
}
DWORD
ProcessCreateClass( // create a new class
IN DWORD CommandArgc,
IN LPSTR *CommandArgv
)
{
DWORD Err;
DHCP_CLASS_INFO ClassInfo;
// usage: [/IsVendor] CreateClass ClassName ClassComment Ascii-Data-For-Class
if( CommandArgc != 3 ) { // wrong usage
printf("usage:DhcpCmd SrvIpAddress CreateClass [Command Parameters]\n");
printf("[Command Parameters] - ClassName ClassComment Ascii-Date-For-Class\n");
printf("/IsVendor option would cause this to be created as a vendor class.\n");
return ERROR_SUCCESS;
}
ClassInfo.ClassName = DhcpOemToUnicode(CommandArgv[0], NULL);
ClassInfo.ClassComment = DhcpOemToUnicode(CommandArgv[1], NULL);
ClassInfo.ClassDataLength = strlen(CommandArgv[2]);
ClassInfo.ClassData = (LPBYTE)CommandArgv[2];
ClassInfo.IsVendor = GlobalIsVendor;
ClassInfo.Flags = 0;
Err = DhcpCreateClass(
GlobalServerIpAddressUnicodeString,
0,
&ClassInfo
);
DhcpFreeMemory(ClassInfo.ClassName);
DhcpFreeMemory(ClassInfo.ClassComment);
return Err;
}
DWORD
ProcessDeleteClass( // delete an existing class
IN DWORD CommandArgc,
IN LPSTR *CommandArgv
)
{
DWORD Err;
LPWSTR ClassName;
// usage: DeleteClass ClassName
if( CommandArgc != 1 ) {
printf("usage: DhcpCmd SrvIpAddress DeleteClass ClassName\n");
return ERROR_SUCCESS;
}
ClassName = DhcpOemToUnicode(CommandArgv[0], NULL);
Err = DhcpDeleteClass(
GlobalServerIpAddressUnicodeString,
0,
ClassName
);
DhcpFreeMemory(ClassName);
return Err;
}
VOID
PrintClassInfo( // print info on a single class
IN LPDHCP_CLASS_INFO Class
)
{
DWORD i;
printf("Class [%ws]:\n\tComment: %ws\n\tFlags: 0x%lx\n\tIsVendor: %s\n",
Class->ClassName, Class->ClassComment, Class->Flags, Class->IsVendor?"TRUE":"FALSE");
printf("\tClassData: ");
for( i = 0; i < Class->ClassDataLength; i ++ )
printf("%02x ", Class->ClassData[i]);
printf("\n");
}
VOID
PrintClassInfoArray( // print array of classes
IN LPDHCP_CLASS_INFO_ARRAY Classes
)
{
DWORD i;
printf("NumClasses = %ld (0x%lx)\n", Classes->NumElements, Classes->NumElements);
for( i = 0; i < Classes->NumElements; i ++ )
PrintClassInfo(&Classes->Classes[i]);
}
DWORD
ProcessEnumClasses( // enumerate list of classes defined
IN DWORD CommandArgc,
IN LPSTR *CommandArgv
)
{
DWORD Err, nRead, nTotal;
DHCP_RESUME_HANDLE ResumeHandle;
LPDHCP_CLASS_INFO_ARRAY ClassInfoArray;
// usage: EnumClasses
ClassInfoArray = NULL;
ResumeHandle = 0;
Err = DhcpEnumClasses(
GlobalServerIpAddressUnicodeString,
0,
&ResumeHandle,
0xFFFFFFFF,
&ClassInfoArray,
&nRead,
&nTotal
);
if( ERROR_MORE_DATA == Err || ERROR_NO_MORE_ITEMS == Err ) {
Err = ERROR_SUCCESS;
}
if( ERROR_SUCCESS == Err ) {
PrintClassInfoArray(ClassInfoArray);
DhcpRpcFreeMemory(ClassInfoArray);
}
return Err;
}
LPSTR
AttribString(
IN ULONG AttribId
)
{
switch(AttribId) {
case DHCP_ATTRIB_BOOL_IS_ROGUE:
return "IsRogue";
case DHCP_ATTRIB_BOOL_IS_DYNBOOTP:
return "DynamicBootpEnabled" ;
case DHCP_ATTRIB_BOOL_IS_PART_OF_DSDC:
return "ServerPartOfDsEnabledDC" ;
default:
;
}
return "UnknownAttribute";
}
VOID
PrintDhcpAttrib( // print a server attrib
IN LPDHCP_ATTRIB ServerAttrib
)
{
if( NULL == ServerAttrib ) return;
printf("Server Attrib %s [%ld]: ",
AttribString(ServerAttrib->DhcpAttribId),
ServerAttrib->DhcpAttribId );
switch( ServerAttrib->DhcpAttribType ) {
case DHCP_ATTRIB_TYPE_BOOL :
printf("%s\n", ServerAttrib->DhcpAttribBool? "TRUE" : "FALSE");
break;
case DHCP_ATTRIB_TYPE_ULONG:
printf("0x%lx\n", ServerAttrib->DhcpAttribUlong);
break;
default:
printf("unknown attrib type\n");
break;
}
}
DWORD
ProcessGetServerStatus( // what is the server status?
IN DWORD CommandArgc,
IN LPSTR *CommandArgv
)
{
DWORD Err, i;
LPDHCP_ATTRIB_ARRAY pDhcpAttribArr;
DHCP_ATTRIB_ID Attribs[] = {
DHCP_ATTRIB_BOOL_IS_ROGUE,
DHCP_ATTRIB_BOOL_IS_DYNBOOTP,
DHCP_ATTRIB_BOOL_IS_PART_OF_DSDC
};
pDhcpAttribArr = NULL;
Err = DhcpServerQueryAttributes(
GlobalServerIpAddressUnicodeString,
0,
sizeof(Attribs)/sizeof(Attribs[0]),
Attribs,
&pDhcpAttribArr
);
if( ERROR_NOT_SUPPORTED == Err ) {
Err = ERROR_SUCCESS;
}
if( ERROR_SUCCESS != Err ) {
return Err;
}
printf("Supported Server Attributes:\n");
if( pDhcpAttribArr ) {
for( i = 0; i < pDhcpAttribArr->NumElements ; i ++ ) {
PrintDhcpAttrib(&pDhcpAttribArr->DhcpAttribs[i]);
}
DhcpRpcFreeMemory(pDhcpAttribArr);
}
return ERROR_SUCCESS;
}
DWORD
ProcessRetryAuthorization( // what is the server status?
IN DWORD CommandArgc,
IN LPSTR *CommandArgv
)
{
return DhcpServerRedoAuthorization(
GlobalServerIpAddressUnicodeString,
0
);
}
DWORD
ProcessGetBindings(
IN DWORD CommandArgc,
IN LPSTR *CommandArgv
)
{
ULONG Error, i ;
LPDHCP_BIND_ELEMENT_ARRAY BindInfo = NULL;
Error = DhcpGetServerBindingInfo(
GlobalServerIpAddressUnicodeString,
0,
&BindInfo
);
if( ERROR_SUCCESS != Error ) {
printf("Error: %ld (0x%lx)\n", Error, Error);
return Error;
}
for( i = 0; i < BindInfo->NumElements ; i ++ ) {
printf("%s \"%ws\"\n",
BindInfo->Elements[i].fBoundToDHCPServer ? "[BOUND] " : "[UNBOUND]" ,
BindInfo->Elements[i].IfDescription
);
}
DhcpRpcFreeMemory(BindInfo);
return ERROR_SUCCESS;
}
DWORD
ProcessSetBinding(
IN DWORD CommandArgc,
IN LPSTR *CommandArgv
)
{
ULONG Error, i ;
BOOL Bind;
LPDHCP_BIND_ELEMENT_ARRAY BindInfo = NULL;
LPWSTR AdapterName;
if( CommandArgc != 2 ) {
printf("usage: DhcpCmd SrvIpAddress SetBinding [BIND/UNBIND] AdapterName");
return ERROR_SUCCESS;
}
if( 0 == _stricmp(CommandArgv[0], "BIND") ) {
Bind = TRUE;
} else {
Bind = FALSE;
}
AdapterName = DhcpOemToUnicode(CommandArgv[1], NULL);
Error = DhcpGetServerBindingInfo(
GlobalServerIpAddressUnicodeString,
0,
&BindInfo
);
if( ERROR_SUCCESS != Error ) {
printf("Error: %ld (0x%lx)\n", Error, Error);
return Error;
}
for( i = 0; i < BindInfo->NumElements ; i ++ ) {
if( 0 == _wcsicmp(BindInfo->Elements[i].IfDescription, AdapterName)) {
BindInfo->Elements[i].fBoundToDHCPServer = Bind;
break;
}
}
if( i == BindInfo->NumElements ) {
printf("Requested Adapter Name not present. \n"
"Use DhcpCmd SrvIpAddress GetBindings to view bindings.\n");
return ERROR_SUCCESS;
}
Error = DhcpSetServerBindingInfo(
GlobalServerIpAddressUnicodeString,
0,
BindInfo
);
if( ERROR_SUCCESS != Error ) {
printf("Error: %ld (0x%lx)\n", Error, Error);
}
DhcpRpcFreeMemory(BindInfo);
return ERROR_SUCCESS;
}
#define CMD_OPT_INVALID 0
#define CMD_OPT_LPWSTR 1
#define CMD_OPT_BOOL 2
struct /* anonymous */ {
LPSTR CommandOptName;
DWORD CommandOptType;
LPVOID CommandOptStorage;
} CommandOpts[] = {
{ "ClassName", CMD_OPT_LPWSTR, (LPVOID)&GlobalClassName },
{ "VendorName", CMD_OPT_LPWSTR, (LPVOID)&GlobalVendorName },
{ "IsVendor", CMD_OPT_BOOL, (LPVOID)&GlobalIsVendor },
{ "NoRPC", CMD_OPT_BOOL, (LPVOID)&GlobalNoRPC },
{ "NoDS", CMD_OPT_BOOL, (LPVOID)&GlobalNoDS },
{ NULL, CMD_OPT_INVALID, NULL },
};
DWORD
ProcessOption( // process a given option
IN DWORD Index, // index into CommandOpts table
IN LPSTR Value // value passed for option
)
{
BOOL Val_BOOL;
LPWSTR Val_LPWSTR;
switch(CommandOpts[Index].CommandOptType ) { // see what type we need to convert to..
case CMD_OPT_BOOL:
if( NULL == Value || '\0' == *Value ) {
Val_BOOL = TRUE; // implicitly set value to TRUE
} else {
if( 0 == _stricmp(Value, "TRUE") ) { // explicitly setting TRUE
Val_BOOL = TRUE;
} else if( 0 == _stricmp(Value, "FALSE" ) ) {
Val_BOOL = FALSE; // explicitly setting it to FALSE
} else {
return ERROR_INVALID_PARAMETER; // unknown response..
}
}
*((LPBOOL)(CommandOpts[Index].CommandOptStorage)) = Val_BOOL;
break;
case CMD_OPT_LPWSTR:
if( NULL == Value ) {
Val_LPWSTR = NULL;
} else if( '\0' == *Value ) {
Val_LPWSTR = L"";
} else { // now convert this..
Val_LPWSTR = DhcpOemToUnicode(Value, NULL);
}
*((LPWSTR *)(CommandOpts[Index].CommandOptStorage)) = Val_LPWSTR;
break;
default:
return ERROR_CALL_NOT_IMPLEMENTED;
}
return ERROR_SUCCESS;
}
DWORD
ProcessOptions( // process all options..
IN OUT int *argc,
IN OUT LPSTR argv[]
)
{
DWORD Error;
int i, j, k, n;
LPSTR Arg, Val;
for( i = 1; i < *argc ; i ++ ) { // process each option
if( argv[i][0] != '/' && argv[i][0] != '-' ) {
continue; // not an option
}
Arg = argv[i]; // an option to process
Arg ++; // skip leading '/' or '-'
Val = strchr(Arg, ':'); // see if it is of form /Option:Value
if( Val ) { // yup!
*Val = '\0'; // terminate Arg..
Val++; // now Val points to value in /Option:Value
}
for( j = 0; CommandOpts[j].CommandOptName ; j ++ ) {
if( 0 == _stricmp(Arg, CommandOpts[j].CommandOptName) ) {
break; // found a match!
}
}
if( NULL == CommandOpts[j].CommandOptName ) {
if( Val ) Val[-1] = ':'; // give back the colon we stole..
continue;
}
for( k = i + 1; k < *argc ; k ++ ) { // remove this arg and slide the rest
argv[k-1] = argv[k];
}
i -- ; (*argc) --;
Error = ProcessOption( j, Val ); // now process it
if( ERROR_SUCCESS != Error ) { // ouch?
DhcpPrint((0xFFFF, "Could not process option: /%s:%s\n", Arg, Val));
return Error;
}
}
return ERROR_SUCCESS;
}
VOID
CleanupOptions(
VOID
)
{
DWORD i;
LPWSTR String;
for( i = 0; CommandOpts[i].CommandOptName ; i ++ ) {
switch(CommandOpts[i].CommandOptType ) {
case CMD_OPT_BOOL:
// nothing to free
break;
case CMD_OPT_LPWSTR:
// need to free string space used..
String = *((LPWSTR *)CommandOpts[i].CommandOptStorage);
if( NULL != String ) DhcpFreeMemory(String);
break;
}
}
// done!
}
#endif NT5
#ifdef NT5
#define OPTIONS_STRING "[Options]"
#else
#define OPTIONS_STRING
#endif
DWORD __cdecl
main(
int argc,
char **argv
)
{
DWORD Error, ThreadOptions;
COMMAND_CODE CommandCode;
DWORD CommandArgc;
LPSTR *CommandArgv;
INIT_DEBUG_HEAP( HEAPX_VERIFY );
Error = ERROR_SUCCESS;
#ifdef NT5
Error = ProcessOptions(&argc, argv);
#endif NT5
if( ERROR_SUCCESS != Error || argc < 3 ) {
printf("usage:DhcpCmd SrvIpAddress" OPTIONS_STRING "Command [Command Parameters].\n");
printf("Commands : \n");
PrintCommands();
#ifdef NT5
printf("Options: \n");
printf("\t/ClassName:<string> -- [default NULL] specify class name wherever applicable.\n");
printf("\t/VendorName:<string> -- [default NULL] specify vendor name wherever applicable.\n");
printf("\t/IsVendor:TRUE/FALSE -- [default FALSE] specify that option being referred as vendor.\n");
printf("\t/NoRPC:TRUE/FALSE -- [default FALSE] specify that no RPC calls should be made.\n");
printf("\t/NoDS:TRUE/FALSE -- [default TRUE] specify that no DS calls should be made.\n");
printf("\n\n");
#endif NT5
Error = ERROR_SUCCESS;
goto Cleanup;
}
GlobalServerIpAddressAnsiString = argv[1];
GlobalServerIpAddressUnicodeString =
DhcpOemToUnicode( GlobalServerIpAddressAnsiString, NULL );
if( GlobalServerIpAddressUnicodeString == NULL ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
printf("Insufficient memory\n");
goto Cleanup;
}
GlobalServerIpAddressAnsiString = argv[1];
CommandCode = DecodeCommand( argv[2] );
if( CommandCode == UnknownCommand ) {
Error = ERROR_INVALID_PARAMETER;
printf("Unknown Command Specified.\n");
goto Cleanup;
}
if( FALSE == GlobalNoRPC ) {
Error = ProcessGetVersion( &g_dwMajor, &g_dwMinor );
if ( ERROR_SUCCESS != Error ) {
printf("Unable to determine server version.\n" );
goto Cleanup;
}
} else {
Error = ERROR_SUCCESS;
}
if ( FALSE == GlobalNoRPC && !IsValidServerVersion( g_dwMajor, g_dwMinor ) ) {
printf( "This version of %s works with Microsoft DHCP server"
" running on Windows NT Server version %d.%d or later.\n",
argv[0],
DHCPCMD_VERSION_MAJOR,
DHCPCMD_VERSION_MINOR
);
Error = ERROR_OLD_WIN_VERSION;
goto Cleanup;
}
CommandArgc = (DWORD)(argc - 3);
CommandArgv = &argv[3];
#ifdef NT5
Error = ERROR_SUCCESS;
if( FALSE == GlobalNoDS ) Error = DhcpDsInit();
if( ERROR_SUCCESS != Error && FALSE == GlobalNoDS ) {
printf("DhcpDsInit() failed %ld (0x%lx), but continuing ..\n", Error, Error);
printf("This indicates that either your machine is part of a work group\n");
printf("or that your DS is unreachable\n");
}
Error = ERROR_SUCCESS;
ThreadOptions = 0;
if( GlobalNoRPC ) ThreadOptions |= DHCP_FLAGS_DONT_DO_RPC;
if( GlobalNoDS ) ThreadOptions |= DHCP_FLAGS_DONT_ACCESS_DS;
DhcpSetThreadOptions(ThreadOptions, 0);
#endif NT5
switch( CommandCode ) {
case AddIpRange:
Error = ProcessAddIpRange( CommandArgc, CommandArgv );
break;
case RemoveIpRange:
Error = ProcessRemoveIpRange( CommandArgc, CommandArgv );
break;
#ifdef NT5
case EnumIpRanges:
Error = ProcessEnumIpRanges( CommandArgc, CommandArgv );
break;
#endif NT5
case AddReservedIp:
Error = ProcessAddReservedIp( CommandArgc, CommandArgv );
break;
case EnumClients:
Error = ProcessEnumClients( CommandArgc, CommandArgv );
break;
#ifdef NT5
case EnumClientsV5:
Error = ProcessEnumClientsV5( CommandArgc, CommandArgv );
break;
#endif NT5
case MibCounts:
Error = ProcessMibCounts( CommandArgc, CommandArgv );
break;
case ServerConfig:
Error = ProcessServerConfig( CommandArgc, CommandArgv );
break;
case GetDhcpVersion:
Error = ProcessGetVersion( &g_dwMajor, &g_dwMinor );
break;
case SetSuperScope:
Error = ProcessSetSuperScope( CommandArgc, CommandArgv );
break;
case RemoveSubscope:
Error = ProcessRemoveSubscope( CommandArgc, CommandArgv );
break;
case DeleteSuperScope:
Error = ProcessDeleteSuperScope( CommandArgc, CommandArgv );
break;
case GetSuperScopeTable:
Error = ProcessGetSuperScopeTable( CommandArgc, CommandArgv );
break;
case CheckDB:
Error = ProcessCheckDB( CommandArgc, CommandArgv );
break;
case CreateSubnet:
Error = ProcessCreateSubnet( CommandArgc, CommandArgv );
break;
case DeleteSubnet:
Error = ProcessDeleteSubnet( CommandArgc, CommandArgv );
break;
case AddExcludeRange:
Error = ProcessAddExcludeRange( CommandArgc, CommandArgv );
break;
case RemoveReservedIp:
Error = ProcessRemoveReservedIp( CommandArgc, CommandArgv );
break;
case RemoveExcludeRange:
Error = ProcessRemoveExcludeRange( CommandArgc, CommandArgv );
break;
case SetSubnetState:
Error = ProcessSetSubnetState( CommandArgc, CommandArgv );
break;
case CreateOption:
Error = ProcessCreateOption( CommandArgc, CommandArgv );
break;
case DeleteOption:
Error = ProcessDeleteOption( CommandArgc, CommandArgv );
break;
case SetGlobalOptionValue:
Error = ProcessSetGlobalOptionValue( CommandArgc, CommandArgv );
break;
case SetGlobalOptionValues:
Error = ProcessSetGlobalOptionValues( CommandArgc, CommandArgv );
break;
case RemoveGlobalOptionValue:
Error = ProcessRemoveGlobalOptionValue( CommandArgc, CommandArgv );
break;
case SetSubnetOptionValue:
Error = ProcessSetSubnetOptionValue( CommandArgc, CommandArgv );
break;
case RemoveSubnetOptionValue:
Error = ProcessRemoveSubnetOptionValue( CommandArgc, CommandArgv );
break;
case SetReservedOptionValue:
Error = ProcessSetReservedOptionValue( CommandArgc, CommandArgv );
break;
case RemoveReservedOptionValue:
Error = ProcessRemoveReservedOptionValue( CommandArgc, CommandArgv );
break;
case EnumOptions:
Error = ProcessEnumOptions( CommandArgc, CommandArgv );
break;
#ifdef NT5
case GetAllOptions:
Error = ProcessGetAllOptions( CommandArgc, CommandArgv );
break;
case GetAllOptionValues:
Error = ProcessGetAllOptionValues( CommandArgc, CommandArgv );
break;
case CreateMScope:
Error = ProcessCreateMScope( CommandArgc, CommandArgv );
break;
case DeleteMScope:
Error = ProcessDeleteMScope( CommandArgc, CommandArgv );
break;
case AddMScopeRange:
Error = ProcessAddMScopeIpRange( CommandArgc, CommandArgv );
break;
case EnumMScopeClients:
Error = ProcessEnumMScopeClients( CommandArgc, CommandArgv );
break;
case ReconcileMScope:
Error = ProcessReconcileMScope( CommandArgc, CommandArgv );
break;
case EnumMScopes:
Error = ProcessEnumMScopes( CommandArgc, CommandArgv );
break;
case MCastMibCounts:
Error = ProcessMCastMibCounts( CommandArgc, CommandArgv );
break;
case EnumServers:
Error = ProcessEnumServers( CommandArgc, CommandArgv );
break;
case AddServer:
Error = ProcessAddServer( CommandArgc, CommandArgv );
break;
case DelServer:
Error = ProcessDelServer( CommandArgc, CommandArgv );
break;
case CreateClass:
Error = ProcessCreateClass( CommandArgc, CommandArgv );
break;
case DeleteClass:
Error = ProcessDeleteClass( CommandArgc, CommandArgv );
break;
case EnumClasses:
Error = ProcessEnumClasses( CommandArgc, CommandArgv );
break;
case GetServerStatus:
Error = ProcessGetServerStatus( CommandArgc, CommandArgv );
break;
case RetryAuthorization:
Error = ProcessRetryAuthorization(CommandArgc, CommandArgv);
break;
case DeleteBadClients:
Error = ProcessDeleteBadClients(CommandArgc, CommandArgv);
break;
case DeleteClient:
Error = ProcessDeleteClient(CommandArgc, CommandArgv);
break;
case GetBindings:
Error = ProcessGetBindings(CommandArgc, CommandArgv);
break;
case SetBinding:
Error = ProcessSetBinding(CommandArgc, CommandArgv);
break;
#endif NT5
case UnknownCommand:
default:
DhcpAssert( FALSE );
Error = ERROR_INVALID_PARAMETER;
printf("Unknown Command Specified.\n");
goto Cleanup;
}
Cleanup:
#ifdef NT5
DhcpDsCleanup();
#endif NT5
if( GlobalServerIpAddressUnicodeString != NULL ) {
DhcpFreeMemory( GlobalServerIpAddressUnicodeString );
}
#ifdef NT5
CleanupOptions();
#endif NT5
if( Error != ERROR_SUCCESS ) {
printf("Command failed, %ld.\n", Error );
return(1);
}
UNINIT_DEBUG_HEAP();
printf("Command successfully completed.\n");
return(0);
}
//================================================================================
// end of file
//================================================================================