/*++ 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include // for JET_cbColumnMost #ifdef NT5 #include #endif NT5 #include #include #include #include #include #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 : // if( CommandArgc < 3 ) { printf("usage:DhcpCmd SrvIpAddress CreateSubnet [Command Parameters].\n" " - .\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 : // if( CommandArgc < 3 ) { printf("usage:DhcpCmd SrvIpAddress AddIpRange [Command Parameters].\n" " - .\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" " - \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 : // if( CommandArgc < 3 ) { printf("usage:DhcpCmd SrvIpAddress RemoveIpRange [Command Parameters].\n" " - .\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" " - \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 \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 : // // // if the server version is 4.1 or greater, and can // also be supplied // if( CommandArgc < 3 ) { printf("usage:DhcpCmd SrvIpAddress AddReservedIp " "[Command Parameters].\n" " - " "\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 : // if( CommandArgc < 3 ) { printf("usage:DhcpCmd SrvIpAddress AddExcludeRange [Command Parameters].\n" " - .\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 : // if( CommandArgc < 3 ) { printf("usage:DhcpCmd SrvIpAddress RemoveExcludeRange [Command Parameters].\n" " - .\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 : // if( CommandArgc < 3 ) { printf("usage:DhcpCmd SrvIpAddress RemoveReservedIp " "[Command Parameters].\n" " - " ".\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 : // if( CommandArgc < 2 ) { printf("usage:DhcpCmd SrvIpAddress SetSubnetState [Command Parameters].\n" " - .\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 : // // : "DhcpFullForce" "DhcpNoForce" if( CommandArgc != 2 ) { printf("usage: DhcpCmd SrvIpAddress DeleteSubnet [Command Parameters].\n" " - .\n"); printf(" : .\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 : // // if( CommandArgc < 2 ) { printf("usage:DhcpCmd SrvIpAddress CreateOption [Command Parameters].\n" " - >.\n"); printf(" : .\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 : // // if( CommandArgc != 1 ) { printf("usage:DhcpCmd SrvIpAddress DeleteOption [Command Parameters].\n" " - .\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 : // // if( CommandArgc < 3 ) { printf("usage:DhcpCmd SrvIpAddress SetGlobalOptionValue [Command Parameters].\n" " - .\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 : // // if( CommandArgc < 3 ) { printf("usage:DhcpCmd SrvIpAddress SetGlobalOptionValues [Command Parameters].\n" " - <..>.\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 : // // if( CommandArgc != 1 ) { printf("usage:DhcpCmd SrvIpAddress RemoveGlobalOptionValue [Command Parameters].\n" " - .\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 // if( CommandArgc < 4 ) { printf("usage:DhcpCmd SrvIpAddress SetSubnetOptionValue " "[Command Parameters].\n" " - " ".\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 // if( CommandArgc != 2 ) { printf("usage:DhcpCmd SrvIpAddress RemoveSubnetOptionValue " "[Command Parameters].\n" " - " ".\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 // if( CommandArgc < 5 ) { printf("usage:DhcpCmd SrvIpAddress SetReservedOptionValue " "[Command Parameters].\n" " - " ".\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 // if( CommandArgc < 3 ) { printf("usage:DhcpCmd SrvIpAddress RemoveReservedOptionValue " "[Command Parameters].\n" " - " ".\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 : // if( CommandArgc < 1 ) { printf("usage:DhcpCmd SrvIpAddress EnumClients [Command Parameters].\n" " - .\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 : // if( CommandArgc < 1 ) { printf("usage:DhcpCmd SrvIpAddress EnumClients [Command Parameters].\n" " - .\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],;[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 .\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 <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 .\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" " - <[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"") 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(" - < 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 : // if( CommandArgc < 4 ) { printf("usage:DhcpCmd SrvIpAddress CreateMScope [Command Parameters].\n" " - .\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 : // if( CommandArgc < 1 ) { printf("usage:DhcpCmd SrvIpAddress DeleteMScope [Command Parameters].\n" " - .\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 : // if( CommandArgc < 3 ) { printf("usage:DhcpCmd SrvIpAddress AddMScopeIpRange [Command Parameters].\n" " - .\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 : // if( CommandArgc < 1 ) { printf("usage:DhcpCmd SrvIpAddress ReconcileMScope [Command Parameters].\n" " - .\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 : // if( CommandArgc < 1 ) { printf("usage:DhcpCmd SrvIpAddress EnumClients [Command Parameters].\n" " - .\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 if( CommandArgc != 2 ) { // wrong usage printf("usage:DhcpCmd SrvIpAddress AddServer \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 if( CommandArgc != 2 ) { // wrong usage printf("usage:DhcpCmd SrvIpAddress DelServer \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"" ); } 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: -- [default NULL] specify class name wherever applicable.\n"); printf("\t/VendorName: -- [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 //================================================================================