Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5334 lines
143 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. dhcpcmd.c
  5. Abstract:
  6. This file contains program to test all DHCP APIs.
  7. Author:
  8. Madan Appiah (madana) 5-Oct-1993
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. --*/
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <windows.h>
  17. #include <winsock.h>
  18. #include <dhcp.h>
  19. #include <dhcpapi.h>
  20. #include <dhcplib.h>
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include <wchar.h>
  24. #include <string.h>
  25. #include <stdlib.h>
  26. #include <time.h>
  27. #include <jet.h> // for JET_cbColumnMost
  28. #ifdef NT5
  29. #include <mdhcsapi.h>
  30. #endif NT5
  31. #include <heapx.h>
  32. #include <ipexport.h>
  33. #include <icmpif.h>
  34. #include <icmpapi.h>
  35. #include <winnls.h>
  36. #ifdef DBG
  37. #ifdef __DHCP_USE_DEBUG_HEAP__
  38. #pragma message ( "*** DHCPCMD will use debug heap ***" )
  39. #define DhcpAllocateMemory(x) calloc(1,x)
  40. #define DhcpFreeMemory(x) free(x)
  41. #endif
  42. #endif
  43. typedef enum _COMMAND_CODE {
  44. AddIpRange,
  45. RemoveIpRange,
  46. EnumIpRanges,
  47. AddReservedIp,
  48. EnumClients,
  49. EnumClientsV5,
  50. DeleteBadClients,
  51. DeleteClient,
  52. MibCounts,
  53. ServerConfig,
  54. GetDhcpVersion,
  55. SetSuperScope,
  56. DeleteSuperScope,
  57. GetSuperScopeTable,
  58. RemoveSubscope,
  59. CheckDB,
  60. CreateSubnet,
  61. AddExcludeRange,
  62. RemoveReservedIp,
  63. RemoveExcludeRange,
  64. SetSubnetState,
  65. DeleteSubnet,
  66. CreateOption,
  67. DeleteOption,
  68. EnumOptions,
  69. SetGlobalOptionValue,
  70. SetGlobalOptionValues,
  71. RemoveGlobalOptionValue,
  72. SetSubnetOptionValue,
  73. RemoveSubnetOptionValue,
  74. SetReservedOptionValue,
  75. RemoveReservedOptionValue,
  76. GetAllOptions,
  77. GetAllOptionValues,
  78. CreateMScope,
  79. DeleteMScope,
  80. AddMScopeRange,
  81. EnumMScopeClients,
  82. ReconcileMScope,
  83. EnumMScopes,
  84. MCastMibCounts,
  85. CreateClass,
  86. DeleteClass,
  87. EnumClasses,
  88. AddServer,
  89. DelServer,
  90. EnumServers,
  91. GetServerStatus,
  92. RetryAuthorization,
  93. GetBindings,
  94. SetBinding,
  95. UnknownCommand
  96. } COMMAND_CODE, *LPCOMMAND_CODE;
  97. typedef struct _COMMAND_INFO {
  98. LPSTR CommandName;
  99. COMMAND_CODE CommandCode;
  100. } COMMAND_INFO, *LPCOMMAND_INFO;
  101. LPWSTR GlobalServerIpAddressUnicodeString = NULL;
  102. LPSTR GlobalServerIpAddressAnsiString = NULL;
  103. LPWSTR GlobalClassName = NULL;
  104. LPWSTR GlobalVendorName = NULL;
  105. BOOL GlobalIsVendor = FALSE;
  106. BOOL GlobalNoRPC = FALSE;
  107. BOOL GlobalNoDS = TRUE;
  108. DWORD GlobalClientCount;
  109. DWORD g_dwMajor = (DWORD) -1 ,
  110. g_dwMinor = (DWORD) -1; // version control
  111. #define CLASS_ID_VERSION 0x5
  112. COMMAND_INFO GlobalCommandInfo[] = {
  113. // global server stuff.
  114. {"MibCounts", MibCounts },
  115. {"GetVersion", GetDhcpVersion },
  116. {"ServerConfig", ServerConfig },
  117. // subnet stuff
  118. {"CreateSubnet", CreateSubnet },
  119. {"DeleteSubnet", DeleteSubnet },
  120. {"SetSubnetState", SetSubnetState },
  121. // ranges
  122. {"AddIpRange", AddIpRange },
  123. {"RemoveIpRange", RemoveIpRange },
  124. #ifdef NT5
  125. {"EnumIpRanges", EnumIpRanges },
  126. #endif NT5
  127. {"AddExcludeRange", AddExcludeRange },
  128. {"RemoveExcludeRange", RemoveExcludeRange },
  129. // active leases
  130. {"EnumClients", EnumClients },
  131. {"DeleteBadClients", DeleteBadClients },
  132. {"DeleteClient", DeleteClient },
  133. #ifdef NT5
  134. {"EnumClientsV5", EnumClientsV5 },
  135. #endif NT5
  136. // reservations
  137. {"AddReservedIp", AddReservedIp },
  138. {"RemoveReservedIp", RemoveReservedIp },
  139. // super-scoping
  140. {"SetSuperScope", SetSuperScope },
  141. {"DeleteSuperScope", DeleteSuperScope },
  142. {"GetSuperScopeTable", GetSuperScopeTable },
  143. {"RemoveSubscope", RemoveSubscope },
  144. // reconcile
  145. {"CheckDB", CheckDB },
  146. // options
  147. {"CreateOption", CreateOption },
  148. {"DeleteOption", DeleteOption },
  149. {"SetGlobalOptionValue", SetGlobalOptionValue },
  150. {"SetGlobalOptionValues", SetGlobalOptionValues },
  151. {"RemoveGlobalOptionValue", RemoveGlobalOptionValue },
  152. {"SetSubnetOptionValue", SetSubnetOptionValue },
  153. {"RemoveSubnetOptionValue", RemoveSubnetOptionValue },
  154. {"SetReservedOptionValue",SetReservedOptionValue },
  155. {"RemoveReservedOptionValue", RemoveReservedOptionValue },
  156. {"EnumOptions", EnumOptions},
  157. #ifdef NT5
  158. {"GetAllOptions", GetAllOptions },
  159. {"GetAllOptionValues", GetAllOptionValues },
  160. // multicast stuff
  161. {"CreateMScope", CreateMScope},
  162. {"DeleteMScope", DeleteMScope},
  163. {"AddMScopeIpRange", AddMScopeRange},
  164. {"EnumMScopeClients", EnumMScopeClients},
  165. {"ReconcileMScope", ReconcileMScope},
  166. {"EnumMScopes", EnumMScopes},
  167. {"MCastMibCounts", MCastMibCounts},
  168. // classes
  169. {"CreateClass", CreateClass},
  170. {"DeleteClass", DeleteClass},
  171. {"EnumClasses", EnumClasses},
  172. // servers
  173. {"AddServer", AddServer},
  174. {"DeleteServer", DelServer},
  175. {"EnumServers", EnumServers},
  176. {"GetServerStatus", GetServerStatus},
  177. {"RetryAuthorization", RetryAuthorization},
  178. {"GetBindings", GetBindings},
  179. {"SetBinding", SetBinding}
  180. #endif NT5
  181. };
  182. typedef enum _CONFIG_COMMAND_CODE {
  183. ConfigAPIProtocolSupport,
  184. ConfigDatabaseName,
  185. ConfigDatabasePath,
  186. ConfigBackupPath,
  187. ConfigBackupInterval,
  188. ConfigDatabaseLoggingFlag,
  189. ConfigRestoreFlag,
  190. ConfigDatabaseCleanupInterval,
  191. ConfigDebugFlag,
  192. ConfigActivityLog,
  193. ConfigPingRetries,
  194. ConfigBootFileTable,
  195. UnknownConfigCommand
  196. } CONFIG_COMMAND_CODE, *LPCONFIG_COMMAND_CODE;
  197. typedef struct _CONFIG_COMMAND_INFO {
  198. LPSTR CommandName;
  199. CONFIG_COMMAND_CODE CommandCode;
  200. } CONFIG_COMMAND_INFO, *LPCONFIG_COMMAND_INFO;
  201. CONFIG_COMMAND_INFO GlobalConfigCommandInfo[] =
  202. {
  203. {"APIProtocolSupport", ConfigAPIProtocolSupport },
  204. {"DatabaseName", ConfigDatabaseName },
  205. {"DatabasePath", ConfigDatabasePath },
  206. {"BackupPath", ConfigBackupPath },
  207. {"BackupInterval", ConfigBackupInterval },
  208. {"DatabaseLoggingFlag", ConfigDatabaseLoggingFlag },
  209. {"RestoreFlag", ConfigRestoreFlag },
  210. {"DatabaseCleanupInterval", ConfigDatabaseCleanupInterval },
  211. {"DebugFlag", ConfigDebugFlag },
  212. {"ActivityLog", ConfigActivityLog },
  213. {"PingRetries", ConfigPingRetries },
  214. {"BootFileTable", ConfigBootFileTable }
  215. };
  216. #define DHCPCMD_VERSION_MAJOR 4
  217. #define DHCPCMD_VERSION_MINOR 1
  218. #if DBG
  219. VOID
  220. DhcpPrintRoutine(
  221. IN DWORD DebugFlag,
  222. IN LPSTR Format,
  223. ...
  224. )
  225. {
  226. #define WSTRSIZE( wsz ) ( ( wcslen( wsz ) + 1 ) * sizeof( WCHAR ) )
  227. #define MAX_PRINTF_LEN 1024 // Arbitrary.
  228. va_list arglist;
  229. char OutputBuffer[MAX_PRINTF_LEN];
  230. ULONG length = 0;
  231. //
  232. // Put a the information requested by the caller onto the line
  233. //
  234. va_start(arglist, Format);
  235. length += (ULONG) vsprintf(&OutputBuffer[length], Format, arglist);
  236. va_end(arglist);
  237. DhcpAssert(length <= MAX_PRINTF_LEN);
  238. //
  239. // Output to the debug terminal,
  240. //
  241. DbgPrint( "%s", OutputBuffer);
  242. }
  243. #endif // DBG
  244. DWORD
  245. SetOptionDataType(
  246. LPSTR OptionTypeString,
  247. LPSTR OptionValueString,
  248. LPDHCP_OPTION_DATA_ELEMENT OptionData,
  249. LPWSTR *UnicodeOptionValueString
  250. )
  251. {
  252. DHCP_OPTION_DATA_TYPE OptionType;
  253. DHCP_OPTION_ID OptionValue;
  254. if( _stricmp( OptionTypeString, "BYTE") == 0 ) {
  255. OptionType = DhcpByteOption;
  256. } else if( _stricmp( OptionTypeString, "WORD") == 0 ) {
  257. OptionType = DhcpWordOption;
  258. } else if( _stricmp( OptionTypeString, "DWORD") == 0 ) {
  259. OptionType = DhcpDWordOption;
  260. } else if( _stricmp( OptionTypeString, "STRING") == 0 ) {
  261. OptionType = DhcpStringDataOption;
  262. } else if( _stricmp( OptionTypeString, "IPADDRESS") == 0 ) {
  263. OptionType = DhcpIpAddressOption;
  264. } else {
  265. printf("OptionType either Unknown or not supported, %s.\n",
  266. OptionTypeString );
  267. return( ERROR_INVALID_PARAMETER );
  268. }
  269. OptionData->OptionType = OptionType;
  270. switch( OptionType ) {
  271. case DhcpByteOption:
  272. OptionValue = strtoul( OptionValueString, NULL, 0 );
  273. if( OptionValue & ~((BYTE)-1) ) {
  274. printf("DefValue is too large (%ld).\n", OptionValue );
  275. return( ERROR_INVALID_PARAMETER );
  276. }
  277. OptionData->Element.ByteOption = (BYTE)OptionValue;
  278. break;
  279. case DhcpWordOption:
  280. OptionValue = strtoul( OptionValueString, NULL, 0 );
  281. if( OptionValue & ~((WORD)-1) ) {
  282. printf("DefValue is too large (%ld).\n", OptionValue );
  283. return( ERROR_INVALID_PARAMETER );
  284. }
  285. OptionData->Element.WordOption = (WORD)OptionValue;
  286. break;
  287. case DhcpDWordOption:
  288. OptionValue = strtoul( OptionValueString, NULL, 0 );
  289. OptionData->Element.DWordOption = (DWORD)OptionValue;
  290. break;
  291. case DhcpIpAddressOption:
  292. OptionData->Element.IpAddressOption =
  293. DhcpDottedStringToIpAddress(OptionValueString);
  294. break;
  295. case DhcpStringDataOption:
  296. *UnicodeOptionValueString =
  297. DhcpOemToUnicode( OptionValueString, NULL );
  298. if( UnicodeOptionValueString == NULL ) {
  299. return( ERROR_NOT_ENOUGH_MEMORY );
  300. }
  301. OptionData->Element.StringDataOption = *UnicodeOptionValueString;
  302. break;
  303. default:
  304. DhcpAssert(FALSE);
  305. printf("CreateOptionValue: Unknown OptionType \n");
  306. return( ERROR_INVALID_PARAMETER );
  307. break;
  308. }
  309. return( ERROR_SUCCESS );
  310. }
  311. COMMAND_CODE
  312. DecodeCommand(
  313. LPSTR CommandName
  314. )
  315. {
  316. DWORD i;
  317. DWORD NumCommands;
  318. NumCommands = sizeof(GlobalCommandInfo) / sizeof(COMMAND_INFO);
  319. DhcpAssert( NumCommands <= UnknownCommand );
  320. for( i = 0; i < NumCommands; i++) {
  321. if( _stricmp( CommandName, GlobalCommandInfo[i].CommandName ) == 0 ) {
  322. return( GlobalCommandInfo[i].CommandCode );
  323. }
  324. }
  325. return( UnknownCommand );
  326. }
  327. VOID
  328. PrintCommands(
  329. VOID
  330. )
  331. {
  332. DWORD i;
  333. DWORD NumCommands;
  334. NumCommands = sizeof(GlobalCommandInfo) / sizeof(COMMAND_INFO);
  335. DhcpAssert( NumCommands <= UnknownCommand );
  336. for( i = 0; i < NumCommands; i++) {
  337. printf( " %s\n", GlobalCommandInfo[i].CommandName );
  338. }
  339. }
  340. DWORD
  341. ProcessCreateSubnet(
  342. DWORD CommandArgc,
  343. LPSTR *CommandArgv
  344. )
  345. {
  346. DWORD Error;
  347. DHCP_SUBNET_INFO SubnetInfo;
  348. LPWSTR UnicodeSubnetName = NULL;
  349. //
  350. // Expected Parameters are : <SubnetAddress SubnetMask SubnetName>
  351. //
  352. if( CommandArgc < 3 ) {
  353. printf("usage:DhcpCmd SrvIpAddress CreateSubnet [Command Parameters].\n"
  354. "<Command Parameters> - <SubnetAddress SubnetMask SubnetName>.\n" );
  355. Error = ERROR_SUCCESS;
  356. goto Cleanup;
  357. }
  358. SubnetInfo.SubnetAddress =
  359. DhcpDottedStringToIpAddress(CommandArgv[0]);
  360. SubnetInfo.SubnetMask =
  361. DhcpDottedStringToIpAddress(CommandArgv[1]);
  362. UnicodeSubnetName = DhcpOemToUnicode( CommandArgv[2], NULL );
  363. DhcpAssert( UnicodeSubnetName != NULL );
  364. SubnetInfo.SubnetName = UnicodeSubnetName;
  365. SubnetInfo.SubnetComment = NULL;
  366. SubnetInfo.PrimaryHost.IpAddress =
  367. DhcpDottedStringToIpAddress(GlobalServerIpAddressAnsiString);
  368. SubnetInfo.PrimaryHost.NetBiosName = NULL;
  369. SubnetInfo.PrimaryHost.HostName = NULL;
  370. SubnetInfo.SubnetState = DhcpSubnetEnabled;
  371. Error = DhcpCreateSubnet(
  372. GlobalServerIpAddressUnicodeString,
  373. SubnetInfo.SubnetAddress,
  374. &SubnetInfo );
  375. Cleanup:
  376. if( UnicodeSubnetName != NULL ) {
  377. DhcpFreeMemory( UnicodeSubnetName );
  378. }
  379. return( Error );
  380. }
  381. BOOL
  382. IsValidServerVersion(
  383. DWORD dwMajor,
  384. DWORD dwMinor
  385. )
  386. {
  387. DWORD dwServerVersion = MAKEWORD( dwMinor, dwMajor );
  388. return ( dwServerVersion >=
  389. MAKEWORD( DHCPCMD_VERSION_MINOR,
  390. DHCPCMD_VERSION_MAJOR ));
  391. }
  392. DWORD
  393. ProcessAddIpRange(
  394. DWORD CommandArgc,
  395. LPSTR *CommandArgv
  396. )
  397. {
  398. DWORD Error;
  399. ULONG MajorVersion, MinorVersion;
  400. ULONG Resume;
  401. DHCP_IP_RANGE IpRange;
  402. DHCP_SUBNET_ELEMENT_DATA Element;
  403. DHCP_SUBNET_ELEMENT_TYPE ElementType;
  404. //
  405. // Expected Parameters are : <SubnetAddress IpRangeStart IpRangeEnd>
  406. //
  407. if( CommandArgc < 3 ) {
  408. printf("usage:DhcpCmd SrvIpAddress AddIpRange [Command Parameters].\n"
  409. "<Command Parameters> - <SubnetAddress IpRangeStart IpRangeEnd>.\n" );
  410. return( ERROR_SUCCESS );
  411. }
  412. IpRange.StartAddress = DhcpDottedStringToIpAddress(CommandArgv[1]);
  413. IpRange.EndAddress = DhcpDottedStringToIpAddress(CommandArgv[2]);
  414. Element.ElementType = DhcpIpRanges;
  415. Element.Element.IpRange = &IpRange;
  416. #ifdef NT5
  417. if( CommandArgc >= 4 ) {
  418. DHCP_BOOTP_IP_RANGE ThisRange = {IpRange.StartAddress, IpRange.EndAddress, 0, ~0};
  419. Element.Element.IpRange = (PVOID)&ThisRange;
  420. if( GlobalNoRPC ) {
  421. MajorVersion = CLASS_ID_VERSION;
  422. } else {
  423. Error = DhcpGetVersion(GlobalServerIpAddressUnicodeString, &MajorVersion, &MinorVersion);
  424. if( ERROR_SUCCESS != Error ) {
  425. printf("Could not determine server version\n");
  426. return Error;
  427. }
  428. }
  429. if( MajorVersion >= CLASS_ID_VERSION ) {
  430. if( CommandArgc >= 5 ) {
  431. ThisRange.MaxBootpAllowed = strtoul( CommandArgv[4], NULL, 0 ) ;
  432. }
  433. if( 0 == _stricmp(CommandArgv[3], "DHCP") ) {
  434. Element.ElementType = DhcpIpRangesDhcpOnly;
  435. } else if( 0 == _stricmp(CommandArgv[3], "BOOTP") ) {
  436. Element.ElementType = DhcpIpRangesBootpOnly;
  437. } else if( 0 == _stricmp(CommandArgv[3], "DHCPBOOTP" ) ) {
  438. Element.ElementType = DhcpIpRangesDhcpBootp;
  439. } else {
  440. printf("usage:DhcpCmd SrvIpAddress AddIpRange [Command Parameters].\n"
  441. "<CommandParameters> - <SubnetAddress IpRangeStart"
  442. " IpRangeEnd (DHCP | BOOTP | DHCPBOOTP)>\n");
  443. return ERROR_SUCCESS;
  444. }
  445. return DhcpAddSubnetElementV5(
  446. GlobalServerIpAddressUnicodeString,
  447. DhcpDottedStringToIpAddress(CommandArgv[0]),
  448. (PVOID)&Element
  449. );
  450. }
  451. }
  452. #endif
  453. Error = DhcpAddSubnetElement(
  454. GlobalServerIpAddressUnicodeString,
  455. DhcpDottedStringToIpAddress(CommandArgv[0]),
  456. &Element );
  457. return( Error );
  458. }
  459. DWORD
  460. ProcessRemoveIpRange(
  461. DWORD CommandArgc,
  462. LPSTR *CommandArgv
  463. )
  464. {
  465. DWORD Error;
  466. ULONG MajorVersion, MinorVersion;
  467. DHCP_IP_RANGE IpRange;
  468. DHCP_SUBNET_ELEMENT_DATA Element;
  469. DHCP_SUBNET_ELEMENT_TYPE ElementType;
  470. //
  471. // Expected Parameters are : <SubnetAddress IpRangeStart IpRangeEnd>
  472. //
  473. if( CommandArgc < 3 ) {
  474. printf("usage:DhcpCmd SrvIpAddress RemoveIpRange [Command Parameters].\n"
  475. "<Command Parameters> - <SubnetAddress IpRangeStart IpRangeEnd>.\n" );
  476. return( ERROR_SUCCESS );
  477. }
  478. IpRange.StartAddress = DhcpDottedStringToIpAddress(CommandArgv[1]);
  479. IpRange.EndAddress = DhcpDottedStringToIpAddress(CommandArgv[2]);
  480. Element.ElementType = DhcpIpRanges;
  481. Element.Element.IpRange = &IpRange;
  482. #ifdef NT5
  483. if( CommandArgc >= 4 ) {
  484. if( GlobalNoRPC ) {
  485. MajorVersion = CLASS_ID_VERSION;
  486. } else {
  487. Error = DhcpGetVersion(GlobalServerIpAddressUnicodeString, &MajorVersion, &MinorVersion);
  488. if( ERROR_SUCCESS != Error ) {
  489. printf("Could not determine server version\n");
  490. return Error;
  491. }
  492. }
  493. if( MajorVersion >= CLASS_ID_VERSION ) {
  494. if( 0 == _stricmp(CommandArgv[3], "DHCP") ) {
  495. Element.ElementType = DhcpIpRangesDhcpOnly;
  496. } else if( 0 == _stricmp(CommandArgv[3], "BOOTP") ) {
  497. Element.ElementType = DhcpIpRangesBootpOnly;
  498. } else if( 0 == _stricmp(CommandArgv[3], "DHCPBOOTP" ) ) {
  499. Element.ElementType = DhcpIpRangesDhcpBootp;
  500. } else {
  501. printf("usage:DhcpCmd SrvIpAddress AddIpRange [Command Parameters].\n"
  502. "<CommandParameters> - <SubnetAddress IpRangeStart"
  503. " IpRangeEnd (DHCP | BOOTP | DHCPBOOTP)>\n");
  504. return ERROR_SUCCESS;
  505. }
  506. return DhcpRemoveSubnetElementV5(
  507. GlobalServerIpAddressUnicodeString,
  508. DhcpDottedStringToIpAddress(CommandArgv[0]),
  509. (PVOID)&Element,
  510. FALSE
  511. );
  512. }
  513. }
  514. #endif
  515. Error = DhcpRemoveSubnetElement(
  516. GlobalServerIpAddressUnicodeString,
  517. DhcpDottedStringToIpAddress(CommandArgv[0]),
  518. &Element,
  519. FALSE
  520. );
  521. return( Error );
  522. }
  523. #ifdef NT5
  524. VOID
  525. PrintRange(
  526. DHCP_SUBNET_ELEMENT_TYPE Type,
  527. DHCP_IP_ADDRESS Start,
  528. DHCP_IP_ADDRESS End,
  529. ULONG BootpAllocated,
  530. ULONG MaxBootpAllowed
  531. )
  532. {
  533. printf("Range: %s -", DhcpIpAddressToDottedString( Start ) );
  534. printf("%s ", DhcpIpAddressToDottedString( End ) );
  535. switch(Type ) {
  536. case DhcpIpRanges : printf("\n"); break;
  537. case DhcpIpRangesDhcpOnly : printf("DHCP\n"); break;
  538. case DhcpIpRangesDhcpBootp:
  539. printf("DHCPBOOTP Bootp Clients leased = %d; Max Allowed BootpClients = %ld\n",
  540. BootpAllocated, MaxBootpAllowed
  541. );
  542. break;
  543. case DhcpIpRangesBootpOnly:
  544. printf("BOOTP Bootp Clients leased = %d; Max Allowed BootpClients = %ld\n",
  545. BootpAllocated, MaxBootpAllowed
  546. );
  547. break;
  548. default: printf("Unknown range type: %ld\n", Type);
  549. }
  550. }
  551. DWORD
  552. ProcessEnumIpRanges(
  553. DWORD CommandArgc,
  554. LPSTR *CommandArgv
  555. )
  556. {
  557. ULONG Error;
  558. ULONG MajorVersion, MinorVersion;
  559. ULONG nRead, nTotal, i;
  560. ULONG Resume;
  561. BOOL fIsV5Call;
  562. DHCP_SUBNET_ELEMENT_TYPE ElementType;
  563. LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V4 Elements4;
  564. LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V5 Elements5;
  565. if( CommandArgc < 1 ) {
  566. printf("usage:DhcpCmd SrvIpAddress EnumIpRanges <SubnetAddress>\n");
  567. return ERROR_SUCCESS;
  568. }
  569. Error = DhcpGetVersion(GlobalServerIpAddressUnicodeString, &MajorVersion, &MinorVersion);
  570. if( MajorVersion >= CLASS_ID_VERSION ) {
  571. fIsV5Call = TRUE;
  572. } else {
  573. fIsV5Call = FALSE;
  574. }
  575. Resume = 0;
  576. while( TRUE ) {
  577. Elements5 = NULL;
  578. Elements4 = NULL;
  579. nRead = nTotal = 0;
  580. if( fIsV5Call ) {
  581. Error = DhcpEnumSubnetElementsV5(
  582. GlobalServerIpAddressUnicodeString,
  583. DhcpDottedStringToIpAddress(CommandArgv[0]),
  584. DhcpIpRangesDhcpBootp,
  585. &Resume,
  586. ~0,
  587. &Elements5,
  588. &nRead,
  589. &nTotal
  590. );
  591. } else {
  592. Error = DhcpEnumSubnetElementsV4(
  593. GlobalServerIpAddressUnicodeString,
  594. DhcpDottedStringToIpAddress(CommandArgv[0]),
  595. DhcpIpRangesDhcpBootp,
  596. &Resume,
  597. ~0,
  598. &Elements4,
  599. &nRead,
  600. &nTotal
  601. );
  602. }
  603. if( ERROR_SUCCESS == Error || ERROR_MORE_DATA == Error ) {
  604. for( i = 0; i < nRead ; i ++ ) {
  605. if( fIsV5Call ) {
  606. PrintRange(
  607. Elements5->Elements[i].ElementType,
  608. Elements5->Elements[i].Element.IpRange->StartAddress,
  609. Elements5->Elements[i].Element.IpRange->EndAddress,
  610. Elements5->Elements[i].Element.IpRange->BootpAllocated,
  611. Elements5->Elements[i].Element.IpRange->MaxBootpAllowed
  612. );
  613. } else {
  614. PrintRange(
  615. Elements4->Elements[i].ElementType,
  616. Elements4->Elements[i].Element.IpRange->StartAddress,
  617. Elements4->Elements[i].Element.IpRange->EndAddress,
  618. 0,
  619. 0
  620. );
  621. }
  622. }
  623. }
  624. if( Elements4 ) DhcpRpcFreeMemory( Elements4 );
  625. if( Elements5 ) DhcpRpcFreeMemory( Elements5 );
  626. if( ERROR_SUCCESS == Error || ERROR_NO_MORE_ITEMS == Error ) break;
  627. if( ERROR_MORE_DATA != Error ) return Error;
  628. }
  629. return ERROR_SUCCESS;
  630. }
  631. #endif NT5
  632. #define COMMAND_ARG_TYPE 5
  633. DWORD
  634. ProcessBootpParameters(
  635. DWORD cArgs,
  636. LPSTR *ppszArgs,
  637. DHCP_IP_RESERVATION_V4 *pReservation
  638. )
  639. {
  640. DWORD dwResult = ERROR_SUCCESS;
  641. if ( cArgs > COMMAND_ARG_TYPE )
  642. {
  643. // user specified the allowed client type
  644. if ( !_stricmp( ppszArgs[ COMMAND_ARG_TYPE ], "bootp" ) )
  645. {
  646. pReservation->bAllowedClientTypes = CLIENT_TYPE_BOOTP;
  647. }
  648. else if ( !_stricmp ( ppszArgs[ COMMAND_ARG_TYPE ], "dhcp" ) )
  649. {
  650. pReservation->bAllowedClientTypes = CLIENT_TYPE_DHCP;
  651. }
  652. else if ( !_stricmp ( ppszArgs[ COMMAND_ARG_TYPE ], "both" ) )
  653. {
  654. pReservation->bAllowedClientTypes = CLIENT_TYPE_BOTH;
  655. }
  656. else
  657. {
  658. printf( "Specify BOOTP, DHCP, or BOTH for reservation type.\n" );
  659. return ERROR_INVALID_PARAMETER;
  660. }
  661. }
  662. else
  663. {
  664. // allow dhcp clients by default.
  665. pReservation->bAllowedClientTypes = CLIENT_TYPE_DHCP;
  666. return ERROR_SUCCESS;
  667. }
  668. return dwResult;
  669. }
  670. DWORD
  671. ProcessAddReservedIp(
  672. DWORD CommandArgc,
  673. LPSTR *CommandArgv
  674. )
  675. {
  676. #define MAX_ADDRESS_LENGTH 64 // 64 bytes
  677. #define COMMAND_ARG_CLIENT_COMMENT 4
  678. DWORD Error;
  679. DHCP_SUBNET_ELEMENT_DATA_V4 Element;
  680. DHCP_IP_RESERVATION_V4 ReserveElement;
  681. DHCP_CLIENT_UID ClientUID;
  682. BYTE Address[MAX_ADDRESS_LENGTH];
  683. DWORD i;
  684. DHCP_IP_ADDRESS ReservedIpAddress;
  685. //
  686. // Expected Parameters are : <SubnetAddress ReservedIp HWAddressString>
  687. //
  688. //
  689. // if the server version is 4.1 or greater, <AllowedClientTypes> and <BootFileString> can
  690. // also be supplied
  691. //
  692. if( CommandArgc < 3 ) {
  693. printf("usage:DhcpCmd SrvIpAddress AddReservedIp "
  694. "[Command Parameters].\n"
  695. "<Command Parameters> - "
  696. "<SubnetAddress ReservedIp HWAddressString [ClientName] [ClientComment]"
  697. " [DHCP | BOOTP | BOTH]>\n" );
  698. return( ERROR_SUCCESS );
  699. }
  700. //
  701. // make HardwareAddress.
  702. //
  703. ClientUID.DataLength = strlen(CommandArgv[2]);
  704. if( ClientUID.DataLength % 2 != 0 ) {
  705. //
  706. // address must be even length.
  707. //
  708. printf("ProcessAddReservedIp: address must be even length.\n");
  709. return( ERROR_INVALID_PARAMETER );
  710. }
  711. ClientUID.DataLength /= 2;
  712. DhcpAssert( ClientUID.DataLength < MAX_ADDRESS_LENGTH );
  713. i = DhcpStringToHwAddress( (LPSTR)Address, CommandArgv[2] );
  714. DhcpAssert( i == ClientUID.DataLength );
  715. ClientUID.Data = Address;
  716. //
  717. // make reserve element.
  718. //
  719. ReservedIpAddress = DhcpDottedStringToIpAddress(CommandArgv[1]);
  720. ReserveElement.ReservedIpAddress = ReservedIpAddress;
  721. ReserveElement.ReservedForClient = &ClientUID;
  722. Element.ElementType = DhcpReservedIps;
  723. Element.Element.ReservedIp = &ReserveElement;
  724. Error = ProcessBootpParameters( CommandArgc, CommandArgv, &ReserveElement );
  725. if ( ERROR_SUCCESS != Error )
  726. {
  727. return Error;
  728. }
  729. Error = DhcpAddSubnetElementV4(
  730. GlobalServerIpAddressUnicodeString,
  731. DhcpDottedStringToIpAddress(CommandArgv[0]),
  732. &Element );
  733. if( Error != ERROR_SUCCESS ) {
  734. return( Error );
  735. }
  736. //
  737. // if we are asked to set the client name, do so.
  738. //
  739. if( CommandArgc > 3 ) {
  740. DHCP_SEARCH_INFO ClientSearchInfo;
  741. LPDHCP_CLIENT_INFO_V4 ClientInfo = NULL;
  742. LPWSTR UnicodeClientName = NULL;
  743. LPWSTR UnicodeClientComment = NULL;
  744. //
  745. // set client name.
  746. //
  747. ClientSearchInfo.SearchType = DhcpClientIpAddress;
  748. ClientSearchInfo.SearchInfo.ClientIpAddress = ReservedIpAddress;
  749. do {
  750. Error = DhcpGetClientInfoV4(
  751. GlobalServerIpAddressUnicodeString,
  752. &ClientSearchInfo,
  753. &ClientInfo );
  754. if( Error != ERROR_SUCCESS ) {
  755. break;
  756. }
  757. UnicodeClientName = DhcpOemToUnicode( CommandArgv[3], NULL );
  758. if( UnicodeClientName == NULL ) {
  759. Error = ERROR_NOT_ENOUGH_MEMORY;
  760. break;
  761. }
  762. if ( ( wcslen( UnicodeClientName ) + 1 ) * sizeof(WCHAR) > JET_cbColumnMost ) {
  763. printf("ProcessAddReservedIp: Client Name too long\n");
  764. Error = ERROR_INVALID_PARAMETER;
  765. break;
  766. }
  767. //
  768. // if client comment is also given in the argument, store that
  769. // as well.
  770. //
  771. if ( CommandArgc > COMMAND_ARG_CLIENT_COMMENT ) {
  772. UnicodeClientComment = DhcpOemToUnicode( CommandArgv[COMMAND_ARG_CLIENT_COMMENT], NULL );
  773. if (!UnicodeClientComment ) {
  774. Error = ERROR_NOT_ENOUGH_MEMORY;
  775. break;
  776. }
  777. //
  778. // check the size here.
  779. //
  780. if ( ( wcslen( UnicodeClientComment ) + 1 ) * sizeof(WCHAR) > JET_cbColumnMost ) {
  781. printf("ProcessAddReservedIp: Client Comment too long\n");
  782. Error = ERROR_INVALID_PARAMETER;
  783. break;
  784. }
  785. ClientInfo->ClientComment = UnicodeClientComment;
  786. }
  787. ClientInfo->ClientName = UnicodeClientName;
  788. } while ( FALSE );
  789. if ( Error == ERROR_SUCCESS ) {
  790. Error = DhcpSetClientInfoV4(
  791. GlobalServerIpAddressUnicodeString,
  792. ClientInfo );
  793. } else {
  794. //
  795. // Cleanup.
  796. //
  797. if ( ClientInfo ) {
  798. DhcpRpcFreeMemory( ClientInfo );
  799. }
  800. if ( UnicodeClientName ) {
  801. DhcpFreeMemory( UnicodeClientName );
  802. }
  803. if ( UnicodeClientComment ) {
  804. DhcpFreeMemory( UnicodeClientComment );
  805. }
  806. }
  807. } // if( CommandArgc > 3 )
  808. return( Error );
  809. }
  810. DWORD
  811. ProcessAddExcludeRange(
  812. DWORD CommandArgc,
  813. LPSTR *CommandArgv
  814. )
  815. {
  816. DWORD Error;
  817. DHCP_IP_RANGE IpRange;
  818. DHCP_SUBNET_ELEMENT_DATA Element;
  819. //
  820. // Expected Parameters are : <SubnetAddress IpRangeStart IpRangeEnd>
  821. //
  822. if( CommandArgc < 3 ) {
  823. printf("usage:DhcpCmd SrvIpAddress AddExcludeRange [Command Parameters].\n"
  824. "<Command Parameters> - <SubnetAddress IpRangeStart IpRangeEnd>.\n" );
  825. return( ERROR_SUCCESS );
  826. }
  827. IpRange.StartAddress = DhcpDottedStringToIpAddress(CommandArgv[1]);
  828. IpRange.EndAddress = DhcpDottedStringToIpAddress(CommandArgv[2]);
  829. Element.ElementType = DhcpExcludedIpRanges;
  830. Element.Element.IpRange = &IpRange;
  831. Error = DhcpAddSubnetElement(
  832. GlobalServerIpAddressUnicodeString,
  833. DhcpDottedStringToIpAddress(CommandArgv[0]),
  834. &Element );
  835. return( Error );
  836. }
  837. DWORD
  838. ProcessRemoveExcludeRange(
  839. DWORD CommandArgc,
  840. LPSTR *CommandArgv
  841. )
  842. {
  843. DWORD Error;
  844. DHCP_SUBNET_ELEMENT_DATA Element;
  845. DHCP_IP_RANGE IpRange;
  846. //
  847. // Expected Parameters are : <SubnetAddress IpRangeStart IpRangeEnd>
  848. //
  849. if( CommandArgc < 3 ) {
  850. printf("usage:DhcpCmd SrvIpAddress RemoveExcludeRange [Command Parameters].\n"
  851. "<Command Parameters> - <SubnetAddress IpRangeStart IpRangeEnd>.\n" );
  852. return( ERROR_SUCCESS );
  853. }
  854. IpRange.StartAddress = DhcpDottedStringToIpAddress(CommandArgv[1]);
  855. IpRange.EndAddress = DhcpDottedStringToIpAddress(CommandArgv[2]);
  856. Element.ElementType = DhcpExcludedIpRanges;
  857. Element.Element.ExcludeIpRange = &IpRange;
  858. Error = DhcpRemoveSubnetElement(
  859. GlobalServerIpAddressUnicodeString,
  860. DhcpDottedStringToIpAddress(CommandArgv[0]),
  861. &Element,
  862. DhcpFullForce );
  863. return( Error );
  864. }
  865. DWORD
  866. ProcessRemoveReservedIp(
  867. DWORD CommandArgc,
  868. LPSTR *CommandArgv
  869. )
  870. {
  871. DWORD Error;
  872. DHCP_SUBNET_ELEMENT_DATA_V4 Element;
  873. DHCP_IP_RESERVATION_V4 ReserveElement;
  874. DHCP_CLIENT_UID ClientUID;
  875. BYTE Address[MAX_ADDRESS_LENGTH];
  876. DWORD i;
  877. //
  878. // Expected Parameters are : <SubnetAddress ReservedIp HWAddressString>
  879. //
  880. if( CommandArgc < 3 ) {
  881. printf("usage:DhcpCmd SrvIpAddress RemoveReservedIp "
  882. "[Command Parameters].\n"
  883. "<Command Parameters> - "
  884. "<SubnetAddress ReservedIp HWAddressString>.\n" );
  885. return( ERROR_SUCCESS );
  886. }
  887. //
  888. // make HardwareAddress.
  889. //
  890. ClientUID.DataLength = strlen(CommandArgv[2]);
  891. if( ClientUID.DataLength % 2 != 0 ) {
  892. //
  893. // address must be even length.
  894. //
  895. printf("ProcessAddReservedIp: address must be even length.\n");
  896. return( ERROR_INVALID_PARAMETER );
  897. }
  898. ClientUID.DataLength /= 2;
  899. DhcpAssert( ClientUID.DataLength < MAX_ADDRESS_LENGTH );
  900. i = DhcpStringToHwAddress( (LPSTR)Address, CommandArgv[2] );
  901. DhcpAssert( i == ClientUID.DataLength );
  902. ClientUID.Data = Address;
  903. //
  904. // make reserve element.
  905. //
  906. ReserveElement.ReservedIpAddress = DhcpDottedStringToIpAddress(CommandArgv[1]);
  907. ReserveElement.ReservedForClient = &ClientUID;
  908. Element.ElementType = DhcpReservedIps;
  909. Element.Element.ReservedIp = &ReserveElement;
  910. Error = DhcpRemoveSubnetElementV4(
  911. GlobalServerIpAddressUnicodeString,
  912. DhcpDottedStringToIpAddress(CommandArgv[0]),
  913. &Element,
  914. DhcpFullForce );
  915. return( Error );
  916. }
  917. DWORD
  918. ProcessSetSubnetState(
  919. DWORD CommandArgc,
  920. LPSTR *CommandArgv
  921. )
  922. {
  923. DWORD Error;
  924. LPDHCP_SUBNET_INFO SubnetInfo;
  925. LPWSTR UnicodeSubnetName = NULL;
  926. DWORD State;
  927. //
  928. // Expected Parameters are : <SubnetAddress SubnetMask SubnetName>
  929. //
  930. if( CommandArgc < 2 ) {
  931. printf("usage:DhcpCmd SrvIpAddress SetSubnetState [Command Parameters].\n"
  932. "<Command Parameters> - <SubnetAddress State>.\n" );
  933. Error = ERROR_SUCCESS;
  934. return( Error );
  935. }
  936. Error = DhcpGetSubnetInfo(
  937. GlobalServerIpAddressUnicodeString,
  938. DhcpDottedStringToIpAddress(CommandArgv[0]),
  939. &SubnetInfo );
  940. if( Error != ERROR_SUCCESS ) {
  941. return( Error );
  942. }
  943. State = strtoul( CommandArgv[1], NULL, 0 );
  944. if( State == 0 ) {
  945. if( SubnetInfo->SubnetState == DhcpSubnetEnabled ) {
  946. Error = ERROR_SUCCESS;
  947. goto Cleanup;
  948. }
  949. SubnetInfo->SubnetState = DhcpSubnetEnabled;
  950. }
  951. else {
  952. if( SubnetInfo->SubnetState == DhcpSubnetDisabled ) {
  953. Error = ERROR_SUCCESS;
  954. goto Cleanup;
  955. }
  956. SubnetInfo->SubnetState = DhcpSubnetDisabled;
  957. }
  958. Error = DhcpSetSubnetInfo(
  959. GlobalServerIpAddressUnicodeString,
  960. DhcpDottedStringToIpAddress(CommandArgv[0]),
  961. SubnetInfo );
  962. Cleanup:
  963. if( SubnetInfo != NULL ) {
  964. DhcpFreeMemory( SubnetInfo );
  965. }
  966. return( Error );
  967. }
  968. DWORD
  969. ProcessDeleteSubnet(
  970. IN DWORD CommandArgc,
  971. IN LPSTR CommandArgv[]
  972. )
  973. {
  974. DWORD Error;
  975. DHCP_IP_ADDRESS SubnetAddress;
  976. DHCP_FORCE_FLAG ForceFlag;
  977. //
  978. // Expected Parameters are :
  979. // <SubnetAddress ForceFlag>
  980. // <ForceFlag> : "DhcpFullForce" "DhcpNoForce"
  981. if( CommandArgc != 2 ) {
  982. printf("usage: DhcpCmd SrvIpAddress DeleteSubnet [Command Parameters].\n"
  983. "<CommandParameters> - <SubnetAddress ForceFlag>.\n");
  984. printf("<ForceFlag> : <DhcpFullForce | DhcpNoForce>.\n");
  985. Error = ERROR_SUCCESS;
  986. goto Cleanup;
  987. }
  988. SubnetAddress = DhcpDottedStringToIpAddress( CommandArgv[0] );
  989. if( 0 == _stricmp(CommandArgv[1], "DhcpFullForce" ) ) {
  990. ForceFlag = DhcpFullForce;
  991. } else if( 0 == _stricmp(CommandArgv[1], "DhcpNoForce" ) ) {
  992. ForceFlag = DhcpNoForce;
  993. } else {
  994. printf("Unknown force flag value: %s (expecting DhcpFullForce or DhcpNoForce)\n",
  995. CommandArgv[1]);
  996. Error = ERROR_INVALID_PARAMETER;
  997. goto Cleanup;
  998. }
  999. Error = DhcpDeleteSubnet(
  1000. GlobalServerIpAddressUnicodeString,
  1001. SubnetAddress,
  1002. ForceFlag
  1003. );
  1004. Cleanup:
  1005. return Error;
  1006. }
  1007. DWORD
  1008. _CreateOption(
  1009. IN LPWSTR ServerAddress,
  1010. IN DWORD Flags,
  1011. IN DHCP_OPTION_ID OptionId,
  1012. IN LPWSTR ClassName,
  1013. IN LPWSTR VendorName,
  1014. IN DHCP_OPTION *OptionInfo
  1015. )
  1016. {
  1017. DWORD MajorVersion, MinorVersion;
  1018. DWORD Error;
  1019. #ifdef NT5
  1020. if( GlobalNoRPC ) {
  1021. MajorVersion = CLASS_ID_VERSION ;
  1022. } else {
  1023. Error = DhcpGetVersion(ServerAddress, &MajorVersion, &MinorVersion);
  1024. if( ERROR_SUCCESS != Error ) {
  1025. printf("Could not determine server version.\n");
  1026. return Error;
  1027. }
  1028. }
  1029. if( MajorVersion >= CLASS_ID_VERSION ) {
  1030. return DhcpCreateOptionV5(
  1031. ServerAddress,
  1032. GlobalIsVendor ? Flags | DHCP_FLAGS_OPTION_IS_VENDOR : Flags,
  1033. OptionId,
  1034. ClassName,
  1035. VendorName,
  1036. OptionInfo
  1037. );
  1038. }
  1039. // incorrect version, just do like before..
  1040. #endif
  1041. return DhcpCreateOption(
  1042. ServerAddress,
  1043. OptionId,
  1044. OptionInfo
  1045. );
  1046. }
  1047. ProcessCreateOption(
  1048. DWORD CommandArgc,
  1049. LPSTR *CommandArgv
  1050. )
  1051. {
  1052. DWORD Error;
  1053. DHCP_OPTION OptionInfo;
  1054. DHCP_OPTION_ID OptionID;
  1055. LPWSTR UnicodeOptionName = NULL;
  1056. LPWSTR UnicodeOptionValueString = NULL;
  1057. DHCP_OPTION_DATA_ELEMENT OptionData;
  1058. //
  1059. // Expected Parameters are :
  1060. // <OptionID OptionName DefValueType DefValue>
  1061. //
  1062. if( CommandArgc < 2 ) {
  1063. printf("usage:DhcpCmd SrvIpAddress CreateOption [Command Parameters].\n"
  1064. "<Command Parameters> - <OptionID OptionName <DefValueType DefValue>>.\n");
  1065. printf("<DefValueType> : <BYTE | WORD | DWORD | STRING | IPADDRESS>.\n");
  1066. Error = ERROR_SUCCESS;
  1067. goto Cleanup;
  1068. }
  1069. OptionID = strtoul( CommandArgv[0], NULL, 0 );
  1070. OptionInfo.OptionID = OptionID;
  1071. UnicodeOptionName = DhcpOemToUnicode( CommandArgv[1], NULL );
  1072. if( UnicodeOptionName == NULL ) {
  1073. Error = ERROR_NOT_ENOUGH_MEMORY;
  1074. goto Cleanup;
  1075. }
  1076. OptionInfo.OptionName = UnicodeOptionName;
  1077. OptionInfo.OptionComment = NULL;
  1078. if( CommandArgc >= 4 ) {
  1079. Error = SetOptionDataType(
  1080. CommandArgv[2],
  1081. CommandArgv[3],
  1082. &OptionData,
  1083. &UnicodeOptionValueString
  1084. );
  1085. if( Error != ERROR_SUCCESS ) {
  1086. goto Cleanup;
  1087. }
  1088. OptionInfo.DefaultValue.NumElements = 1;
  1089. OptionInfo.DefaultValue.Elements = &OptionData;
  1090. }
  1091. else {
  1092. OptionInfo.DefaultValue.NumElements = 0;
  1093. OptionInfo.DefaultValue.Elements = NULL;
  1094. }
  1095. OptionInfo.OptionType = DhcpUnaryElementTypeOption;
  1096. Error = _CreateOption(
  1097. GlobalServerIpAddressUnicodeString,
  1098. 0,
  1099. OptionID,
  1100. GlobalClassName,
  1101. GlobalVendorName,
  1102. &OptionInfo
  1103. );
  1104. Cleanup:
  1105. if( UnicodeOptionName != NULL ) {
  1106. DhcpFreeMemory( UnicodeOptionName );
  1107. }
  1108. if( UnicodeOptionValueString != NULL ) {
  1109. DhcpFreeMemory( UnicodeOptionValueString );
  1110. }
  1111. return( Error );
  1112. }
  1113. DWORD
  1114. RemoveOption(
  1115. IN LPWSTR ServerAddress,
  1116. IN DWORD Flags,
  1117. IN DHCP_OPTION_ID OptionId,
  1118. IN LPWSTR ClassName,
  1119. IN LPWSTR VendorName
  1120. )
  1121. {
  1122. DWORD MajorVersion, MinorVersion;
  1123. DWORD Error;
  1124. #ifdef NT5
  1125. if( GlobalNoRPC ) {
  1126. MajorVersion = CLASS_ID_VERSION ;
  1127. } else {
  1128. Error = DhcpGetVersion(ServerAddress, &MajorVersion, &MinorVersion);
  1129. if( ERROR_SUCCESS != Error ) {
  1130. printf("Could not determine server version.\n");
  1131. return Error;
  1132. }
  1133. }
  1134. if( MajorVersion >= CLASS_ID_VERSION ) {
  1135. return DhcpRemoveOptionV5(
  1136. ServerAddress,
  1137. GlobalIsVendor ? Flags | DHCP_FLAGS_OPTION_IS_VENDOR : Flags,
  1138. OptionId,
  1139. ClassName,
  1140. VendorName
  1141. );
  1142. }
  1143. // incorrect version, just do like before..
  1144. #endif
  1145. return DhcpRemoveOption(
  1146. ServerAddress,
  1147. OptionId
  1148. );
  1149. }
  1150. ProcessDeleteOption(
  1151. DWORD CommandArgc,
  1152. LPSTR *CommandArgv
  1153. )
  1154. {
  1155. DWORD Error;
  1156. DHCP_OPTION_ID OptionID;
  1157. //
  1158. // Expected Parameters are :
  1159. // <OptionID>
  1160. //
  1161. if( CommandArgc != 1 ) {
  1162. printf("usage:DhcpCmd SrvIpAddress DeleteOption [Command Parameters].\n"
  1163. "<Command Parameters> - <OptionID>.\n");
  1164. Error = ERROR_SUCCESS;
  1165. goto Cleanup;
  1166. }
  1167. OptionID = strtoul( CommandArgv[0], NULL, 0 );
  1168. Error = RemoveOption(
  1169. GlobalServerIpAddressUnicodeString,
  1170. 0,
  1171. OptionID,
  1172. GlobalClassName,
  1173. GlobalVendorName
  1174. );
  1175. Cleanup:
  1176. return Error ;
  1177. }
  1178. DWORD
  1179. SetOptionValue(
  1180. IN LPWSTR ServerAddress,
  1181. IN DWORD Flags,
  1182. IN DHCP_OPTION_ID OptionId,
  1183. IN LPWSTR ClassName,
  1184. IN LPWSTR VendorName,
  1185. IN LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
  1186. IN LPDHCP_OPTION_DATA OptionValue
  1187. )
  1188. {
  1189. DWORD MajorVersion, MinorVersion;
  1190. DWORD Error;
  1191. #ifdef NT5
  1192. if( GlobalNoRPC ) {
  1193. MajorVersion = CLASS_ID_VERSION ;
  1194. } else {
  1195. Error = DhcpGetVersion(ServerAddress, &MajorVersion, &MinorVersion);
  1196. if( ERROR_SUCCESS != Error ) {
  1197. printf("Could not determine server version.\n");
  1198. return Error;
  1199. }
  1200. }
  1201. if( MajorVersion >= CLASS_ID_VERSION ) {
  1202. return DhcpSetOptionValueV5(
  1203. ServerAddress,
  1204. GlobalIsVendor ? Flags | DHCP_FLAGS_OPTION_IS_VENDOR : Flags,
  1205. OptionId,
  1206. ClassName,
  1207. VendorName,
  1208. ScopeInfo,
  1209. OptionValue
  1210. );
  1211. }
  1212. // incorrect version, just do like before..
  1213. #endif
  1214. return DhcpSetOptionValue(
  1215. ServerAddress,
  1216. OptionId,
  1217. ScopeInfo,
  1218. OptionValue
  1219. );
  1220. }
  1221. ProcessSetGlobalOptionValue(
  1222. DWORD CommandArgc,
  1223. LPSTR *CommandArgv
  1224. )
  1225. {
  1226. DWORD Error;
  1227. DHCP_OPTION_ID OptionID;
  1228. DHCP_OPTION_SCOPE_INFO ScopeInfo;
  1229. DHCP_OPTION_DATA OptionValue;
  1230. DHCP_OPTION_DATA_ELEMENT OptionData;
  1231. LPWSTR UnicodeOptionValueString = NULL;
  1232. //
  1233. // Expected Parameters are :
  1234. // <OptionID OptionType OptionValue>
  1235. //
  1236. if( CommandArgc < 3 ) {
  1237. printf("usage:DhcpCmd SrvIpAddress SetGlobalOptionValue [Command Parameters].\n"
  1238. "<Command Parameters> - <OptionID OptionType OptionValue>.\n");
  1239. Error = ERROR_SUCCESS;
  1240. goto Cleanup;
  1241. }
  1242. OptionID = strtoul( CommandArgv[0], NULL, 0 );
  1243. Error = SetOptionDataType(
  1244. CommandArgv[1],
  1245. CommandArgv[2],
  1246. &OptionData,
  1247. &UnicodeOptionValueString
  1248. );
  1249. if( Error != ERROR_SUCCESS ) {
  1250. goto Cleanup;
  1251. }
  1252. OptionValue.NumElements = 1;
  1253. OptionValue.Elements = &OptionData;
  1254. ScopeInfo.ScopeType = DhcpGlobalOptions;
  1255. ScopeInfo.ScopeInfo.GlobalScopeInfo = NULL;
  1256. Error = SetOptionValue(
  1257. GlobalServerIpAddressUnicodeString,
  1258. 0,
  1259. (DHCP_OPTION_ID)OptionID,
  1260. GlobalClassName,
  1261. GlobalVendorName,
  1262. &ScopeInfo,
  1263. &OptionValue
  1264. );
  1265. Cleanup:
  1266. if( UnicodeOptionValueString != NULL ) {
  1267. DhcpFreeMemory( UnicodeOptionValueString );
  1268. }
  1269. return( Error );
  1270. }
  1271. DWORD
  1272. SetOptionValues(
  1273. IN LPWSTR ServerAddress,
  1274. IN DWORD Flags,
  1275. IN LPWSTR ClassName,
  1276. IN LPWSTR VendorName,
  1277. IN LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
  1278. IN LPDHCP_OPTION_VALUE_ARRAY OptionValues
  1279. )
  1280. {
  1281. DWORD MajorVersion, MinorVersion;
  1282. DWORD Error;
  1283. #ifdef NT5
  1284. if( GlobalNoRPC ) {
  1285. MajorVersion = CLASS_ID_VERSION ;
  1286. } else {
  1287. Error = DhcpGetVersion(ServerAddress, &MajorVersion, &MinorVersion);
  1288. if( ERROR_SUCCESS != Error ) {
  1289. printf("Could not determine server version.\n");
  1290. return Error;
  1291. }
  1292. }
  1293. if( MajorVersion >= CLASS_ID_VERSION ) {
  1294. return DhcpSetOptionValuesV5(
  1295. ServerAddress,
  1296. GlobalIsVendor ? Flags | DHCP_FLAGS_OPTION_IS_VENDOR : Flags,
  1297. ClassName,
  1298. VendorName,
  1299. ScopeInfo,
  1300. OptionValues
  1301. );
  1302. }
  1303. // incorrect version, just do like before..
  1304. #endif
  1305. return DhcpSetOptionValues(
  1306. ServerAddress,
  1307. ScopeInfo,
  1308. OptionValues
  1309. );
  1310. }
  1311. ProcessSetGlobalOptionValues(
  1312. DWORD CommandArgc,
  1313. LPSTR *CommandArgv
  1314. )
  1315. {
  1316. #define NUM_VALUES 5
  1317. DWORD Error;
  1318. DHCP_OPTION_ID OptionID;
  1319. DHCP_OPTION_SCOPE_INFO ScopeInfo;
  1320. DHCP_OPTION_DATA OptionValue;
  1321. DHCP_OPTION_DATA_ELEMENT OptionData[NUM_VALUES];
  1322. LPWSTR UnicodeOptionValueString[NUM_VALUES];
  1323. DHCP_OPTION_VALUE_ARRAY ValuesArray;
  1324. DHCP_OPTION_VALUE Values[NUM_VALUES];
  1325. DWORD NumValue;
  1326. RtlZeroMemory( UnicodeOptionValueString, NUM_VALUES * sizeof(LPWSTR) );
  1327. //
  1328. // Expected Parameters are :
  1329. // <OptionID OptionType OptionValue>
  1330. //
  1331. if( CommandArgc < 3 ) {
  1332. printf("usage:DhcpCmd SrvIpAddress SetGlobalOptionValues [Command Parameters].\n"
  1333. "<Command Parameters> - <OptionID OptionType OptionValue> <..>.\n"); Error = ERROR_SUCCESS;
  1334. goto Cleanup;
  1335. }
  1336. for (NumValue = 0;
  1337. (CommandArgc >= 3) && (NumValue < NUM_VALUES);
  1338. NumValue++, CommandArgc -= 3, CommandArgv += 3 ) {
  1339. OptionID = strtoul( CommandArgv[0], NULL, 0 );
  1340. Error = SetOptionDataType(
  1341. CommandArgv[1],
  1342. CommandArgv[2],
  1343. &OptionData[NumValue],
  1344. &UnicodeOptionValueString[NumValue]
  1345. );
  1346. if( Error != ERROR_SUCCESS ) {
  1347. goto Cleanup;
  1348. }
  1349. Values[NumValue].OptionID = OptionID;
  1350. Values[NumValue].Value.NumElements = 1;
  1351. Values[NumValue].Value.Elements = &OptionData[NumValue];
  1352. }
  1353. ValuesArray.NumElements = NumValue;
  1354. ValuesArray.Values = Values;
  1355. ScopeInfo.ScopeType = DhcpGlobalOptions;
  1356. ScopeInfo.ScopeInfo.GlobalScopeInfo = NULL;
  1357. Error = SetOptionValues(
  1358. GlobalServerIpAddressUnicodeString,
  1359. 0,
  1360. GlobalClassName,
  1361. GlobalVendorName,
  1362. &ScopeInfo,
  1363. &ValuesArray
  1364. );
  1365. Cleanup:
  1366. for (NumValue = 0; NumValue < NUM_VALUES; NumValue++) {
  1367. if( UnicodeOptionValueString[NumValue] != NULL ) {
  1368. DhcpFreeMemory( UnicodeOptionValueString );
  1369. }
  1370. }
  1371. return( Error );
  1372. }
  1373. DWORD
  1374. RemoveOptionValue(
  1375. IN LPWSTR ServerAddress,
  1376. IN DWORD Flags,
  1377. IN DHCP_OPTION_ID OptionID,
  1378. IN LPWSTR ClassName,
  1379. IN LPWSTR VendorName,
  1380. IN LPDHCP_OPTION_SCOPE_INFO ScopeInfo
  1381. )
  1382. {
  1383. DWORD MajorVersion, MinorVersion;
  1384. DWORD Error;
  1385. #ifdef NT5
  1386. if( GlobalNoRPC ) {
  1387. MajorVersion = CLASS_ID_VERSION ;
  1388. } else {
  1389. Error = DhcpGetVersion(ServerAddress, &MajorVersion, &MinorVersion);
  1390. if( ERROR_SUCCESS != Error ) {
  1391. printf("Could not determine server version.\n");
  1392. return Error;
  1393. }
  1394. }
  1395. if( MajorVersion >= CLASS_ID_VERSION ) {
  1396. return DhcpRemoveOptionValueV5(
  1397. ServerAddress,
  1398. GlobalIsVendor ? Flags | DHCP_FLAGS_OPTION_IS_VENDOR : Flags,
  1399. OptionID,
  1400. ClassName,
  1401. VendorName,
  1402. ScopeInfo
  1403. );
  1404. }
  1405. // incorrect version, just do like before..
  1406. #endif
  1407. return DhcpRemoveOptionValue(
  1408. ServerAddress,
  1409. OptionID,
  1410. ScopeInfo
  1411. );
  1412. }
  1413. DWORD
  1414. ProcessRemoveGlobalOptionValue(
  1415. DWORD CommandArgc,
  1416. LPSTR *CommandArgv
  1417. )
  1418. {
  1419. DWORD Error;
  1420. DHCP_OPTION_ID OptionID;
  1421. DHCP_OPTION_SCOPE_INFO ScopeInfo;
  1422. //
  1423. // Expected Parameters are :
  1424. // <OptionID OptionType OptionValue>
  1425. //
  1426. if( CommandArgc != 1 ) {
  1427. printf("usage:DhcpCmd SrvIpAddress RemoveGlobalOptionValue [Command Parameters].\n"
  1428. "<Command Parameters> - <OptionID>.\n");
  1429. Error = ERROR_SUCCESS;
  1430. goto Cleanup;
  1431. }
  1432. OptionID = strtoul( CommandArgv[0], NULL, 0 );
  1433. ScopeInfo.ScopeType = DhcpGlobalOptions;
  1434. ScopeInfo.ScopeInfo.GlobalScopeInfo = NULL;
  1435. Error = RemoveOptionValue(
  1436. GlobalServerIpAddressUnicodeString,
  1437. 0,
  1438. (DHCP_OPTION_ID)OptionID,
  1439. GlobalClassName,
  1440. GlobalVendorName,
  1441. &ScopeInfo
  1442. );
  1443. Cleanup:
  1444. return Error ;
  1445. }
  1446. ProcessSetSubnetOptionValue(
  1447. DWORD CommandArgc,
  1448. LPSTR *CommandArgv
  1449. )
  1450. {
  1451. DWORD Error;
  1452. DHCP_OPTION_ID OptionID;
  1453. DHCP_OPTION_SCOPE_INFO ScopeInfo;
  1454. DHCP_OPTION_DATA OptionValue;
  1455. DHCP_OPTION_DATA_ELEMENT OptionData;
  1456. LPWSTR UnicodeOptionValueString = NULL;
  1457. //
  1458. // Expected Parameters are :
  1459. // subnet-address <OptionID OptionType OptionValue>
  1460. //
  1461. if( CommandArgc < 4 ) {
  1462. printf("usage:DhcpCmd SrvIpAddress SetSubnetOptionValue "
  1463. "[Command Parameters].\n"
  1464. "<Command Parameters> - "
  1465. "<SubnetAddress OptionID OptionType OptionValue>.\n");
  1466. Error = ERROR_SUCCESS;
  1467. goto Cleanup;
  1468. }
  1469. ScopeInfo.ScopeType = DhcpSubnetOptions;
  1470. ScopeInfo.ScopeInfo.SubnetScopeInfo = DhcpDottedStringToIpAddress( CommandArgv[0] );
  1471. OptionID = strtoul( CommandArgv[1], NULL, 0 );
  1472. Error = SetOptionDataType(
  1473. CommandArgv[2],
  1474. CommandArgv[3],
  1475. &OptionData,
  1476. &UnicodeOptionValueString );
  1477. if( Error != ERROR_SUCCESS ) {
  1478. goto Cleanup;
  1479. }
  1480. OptionValue.NumElements = 1;
  1481. OptionValue.Elements = &OptionData;
  1482. Error = SetOptionValue(
  1483. GlobalServerIpAddressUnicodeString,
  1484. 0,
  1485. (DHCP_OPTION_ID)OptionID,
  1486. GlobalClassName,
  1487. GlobalVendorName,
  1488. &ScopeInfo,
  1489. &OptionValue
  1490. );
  1491. Cleanup:
  1492. if( UnicodeOptionValueString != NULL ) {
  1493. DhcpFreeMemory( UnicodeOptionValueString );
  1494. }
  1495. return( Error );
  1496. }
  1497. ProcessRemoveSubnetOptionValue(
  1498. DWORD CommandArgc,
  1499. LPSTR *CommandArgv
  1500. )
  1501. {
  1502. DWORD Error;
  1503. DHCP_OPTION_ID OptionID;
  1504. DHCP_OPTION_SCOPE_INFO ScopeInfo;
  1505. //
  1506. // Expected Parameters are :
  1507. // subnet-address <OptionID>
  1508. //
  1509. if( CommandArgc != 2 ) {
  1510. printf("usage:DhcpCmd SrvIpAddress RemoveSubnetOptionValue "
  1511. "[Command Parameters].\n"
  1512. "<Command Parameters> - "
  1513. "<SubnetAddress OptionID>.\n");
  1514. Error = ERROR_SUCCESS;
  1515. goto Cleanup;
  1516. }
  1517. ScopeInfo.ScopeType = DhcpSubnetOptions;
  1518. ScopeInfo.ScopeInfo.SubnetScopeInfo = DhcpDottedStringToIpAddress( CommandArgv[0] );
  1519. OptionID = strtoul( CommandArgv[1], NULL, 0 );
  1520. Error = RemoveOptionValue(
  1521. GlobalServerIpAddressUnicodeString,
  1522. 0,
  1523. (DHCP_OPTION_ID)OptionID,
  1524. GlobalClassName,
  1525. GlobalVendorName,
  1526. &ScopeInfo
  1527. );
  1528. Cleanup:
  1529. return Error ;
  1530. }
  1531. ProcessSetReservedOptionValue(
  1532. DWORD CommandArgc,
  1533. LPSTR *CommandArgv
  1534. )
  1535. {
  1536. DWORD Error;
  1537. DHCP_OPTION_ID OptionID;
  1538. DHCP_OPTION_SCOPE_INFO ScopeInfo;
  1539. DHCP_OPTION_DATA OptionValue;
  1540. DHCP_OPTION_DATA_ELEMENT OptionData;
  1541. LPWSTR UnicodeOptionValueString = NULL;
  1542. //
  1543. // Expected Parameters are :
  1544. // subnet-address reservation-address <OptionID OptionType OptionValue>
  1545. //
  1546. if( CommandArgc < 5 ) {
  1547. printf("usage:DhcpCmd SrvIpAddress SetReservedOptionValue "
  1548. "[Command Parameters].\n"
  1549. "<Command Parameters> - "
  1550. "<SubnetAddress Reservation-Address OptionID OptionType OptionValue>.\n");
  1551. Error = ERROR_SUCCESS;
  1552. goto Cleanup;
  1553. }
  1554. ScopeInfo.ScopeType = DhcpReservedOptions;
  1555. ScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpSubnetAddress =
  1556. DhcpDottedStringToIpAddress(CommandArgv[0]);
  1557. ScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpAddress =
  1558. DhcpDottedStringToIpAddress( CommandArgv[1] );
  1559. OptionID = strtoul( CommandArgv[2], NULL, 0 );
  1560. Error = SetOptionDataType(
  1561. CommandArgv[3],
  1562. CommandArgv[4],
  1563. &OptionData,
  1564. &UnicodeOptionValueString
  1565. );
  1566. if( Error != ERROR_SUCCESS ) {
  1567. goto Cleanup;
  1568. }
  1569. OptionValue.NumElements = 1;
  1570. OptionValue.Elements = &OptionData;
  1571. Error = SetOptionValue(
  1572. GlobalServerIpAddressUnicodeString,
  1573. 0,
  1574. (DHCP_OPTION_ID)OptionID,
  1575. GlobalClassName,
  1576. GlobalVendorName,
  1577. &ScopeInfo,
  1578. &OptionValue
  1579. );
  1580. Cleanup:
  1581. if( UnicodeOptionValueString != NULL ) {
  1582. DhcpFreeMemory( UnicodeOptionValueString );
  1583. }
  1584. return( Error );
  1585. }
  1586. ProcessRemoveReservedOptionValue(
  1587. DWORD CommandArgc,
  1588. LPSTR *CommandArgv
  1589. )
  1590. {
  1591. DWORD Error;
  1592. DHCP_OPTION_ID OptionID;
  1593. DHCP_OPTION_SCOPE_INFO ScopeInfo;
  1594. //
  1595. // Expected Parameters are :
  1596. // subnet-address reservation-address <OptionID>
  1597. //
  1598. if( CommandArgc < 3 ) {
  1599. printf("usage:DhcpCmd SrvIpAddress RemoveReservedOptionValue "
  1600. "[Command Parameters].\n"
  1601. "<Command Parameters> - "
  1602. "<SubnetAddress Reservation-Address OptionID>.\n");
  1603. Error = ERROR_SUCCESS;
  1604. goto Cleanup;
  1605. }
  1606. ScopeInfo.ScopeType = DhcpReservedOptions;
  1607. ScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpSubnetAddress =
  1608. DhcpDottedStringToIpAddress(CommandArgv[0]);
  1609. ScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpAddress =
  1610. DhcpDottedStringToIpAddress( CommandArgv[1] );
  1611. OptionID = strtoul( CommandArgv[2], NULL, 0 );
  1612. Error = RemoveOptionValue(
  1613. GlobalServerIpAddressUnicodeString,
  1614. 0,
  1615. (DHCP_OPTION_ID)OptionID,
  1616. GlobalClassName,
  1617. GlobalVendorName,
  1618. &ScopeInfo
  1619. );
  1620. Cleanup:
  1621. return Error ;
  1622. }
  1623. VOID
  1624. PrintClientInfo(
  1625. LPDHCP_CLIENT_INFO_V4 ClientInfo
  1626. )
  1627. {
  1628. DWORD i;
  1629. DWORD DataLength;
  1630. LPBYTE Data;
  1631. SYSTEMTIME SystemTime;
  1632. FILETIME LocalTime;
  1633. char *szClientType;
  1634. printf("ClientInfo :\n");
  1635. printf("\tIP Address = %s.\n",
  1636. DhcpIpAddressToDottedString(ClientInfo->ClientIpAddress));
  1637. printf("\tSubnetMask = %s.\n",
  1638. DhcpIpAddressToDottedString(ClientInfo->SubnetMask));
  1639. DataLength = ClientInfo->ClientHardwareAddress.DataLength;
  1640. Data = ClientInfo->ClientHardwareAddress.Data;
  1641. printf("\tClient Hardware Address = ");
  1642. for( i = 0; i < DataLength; i++ ) {
  1643. if( (i+1) < DataLength ) {
  1644. printf("%.2lx-", (DWORD)Data[i]);
  1645. }
  1646. else {
  1647. printf("%.2lx", (DWORD)Data[i]);
  1648. }
  1649. }
  1650. printf(".\n");
  1651. printf("\tName = %ws.\n", ClientInfo->ClientName);
  1652. printf("\tComment = %ws.\n", ClientInfo->ClientComment);
  1653. printf("\tType = " );
  1654. switch( ClientInfo->bClientType )
  1655. {
  1656. case CLIENT_TYPE_NONE:
  1657. szClientType= "None";
  1658. break;
  1659. case CLIENT_TYPE_DHCP:
  1660. szClientType = "DHCP";
  1661. break;
  1662. case CLIENT_TYPE_BOOTP:
  1663. szClientType = "BOOTP";
  1664. break;
  1665. case CLIENT_TYPE_UNSPECIFIED:
  1666. szClientType = "Unspecified";
  1667. break;
  1668. default:
  1669. DhcpAssert( FALSE );
  1670. }
  1671. printf( "%s\n", szClientType );
  1672. printf("\tExpires = ");
  1673. if ( ClientInfo->ClientLeaseExpires.dwLowDateTime ==
  1674. DHCP_DATE_TIME_INFINIT_LOW &&
  1675. ClientInfo->ClientLeaseExpires.dwHighDateTime ==
  1676. DHCP_DATE_TIME_INFINIT_HIGH )
  1677. {
  1678. printf( "Never (lease duration is infinite.)\n" );
  1679. }
  1680. else if( FileTimeToLocalFileTime(
  1681. (FILETIME *)(&ClientInfo->ClientLeaseExpires),
  1682. &LocalTime) ) {
  1683. if( FileTimeToSystemTime( &LocalTime, &SystemTime ) ) {
  1684. printf( "%02u/%02u/%02u %02u:%02u:%02u.\n",
  1685. SystemTime.wMonth,
  1686. SystemTime.wDay,
  1687. SystemTime.wYear,
  1688. SystemTime.wHour,
  1689. SystemTime.wMinute,
  1690. SystemTime.wSecond );
  1691. }
  1692. else {
  1693. printf( "Can't convert time, %ld.\n", GetLastError() );
  1694. }
  1695. }
  1696. else {
  1697. printf( "Can't convert time, %ld.\n", GetLastError() );
  1698. }
  1699. printf("\tOwner Host IP Address = %s.\n",
  1700. DhcpIpAddressToDottedString(ClientInfo->OwnerHost.IpAddress));
  1701. printf("\tOwner Host NetBios Name = %ws.\n",
  1702. ClientInfo->OwnerHost.NetBiosName );
  1703. printf("\tOwner Host Name = %ws.\n",
  1704. ClientInfo->OwnerHost.HostName );
  1705. }
  1706. #ifdef NT5
  1707. VOID
  1708. PrintClientInfoV5(
  1709. LPDHCP_CLIENT_INFO_V5 ClientInfo
  1710. )
  1711. {
  1712. DWORD i;
  1713. DWORD DataLength;
  1714. LPBYTE Data;
  1715. SYSTEMTIME SystemTime;
  1716. FILETIME LocalTime;
  1717. char *szClientType;
  1718. printf("ClientInfo :\n");
  1719. printf("\tIP Address = %s.\n",
  1720. DhcpIpAddressToDottedString(ClientInfo->ClientIpAddress));
  1721. printf("\tSubnetMask = %s.\n",
  1722. DhcpIpAddressToDottedString(ClientInfo->SubnetMask));
  1723. DataLength = ClientInfo->ClientHardwareAddress.DataLength;
  1724. Data = ClientInfo->ClientHardwareAddress.Data;
  1725. printf("\tClient Hardware Address = ");
  1726. for( i = 0; i < DataLength; i++ ) {
  1727. if( (i+1) < DataLength ) {
  1728. printf("%.2lx-", (DWORD)Data[i]);
  1729. }
  1730. else {
  1731. printf("%.2lx", (DWORD)Data[i]);
  1732. }
  1733. }
  1734. printf(".\n");
  1735. printf("\tName = %ws.\n", ClientInfo->ClientName);
  1736. printf("\tComment = %ws.\n", ClientInfo->ClientComment);
  1737. printf("\tType = " );
  1738. switch( ClientInfo->bClientType )
  1739. {
  1740. case CLIENT_TYPE_NONE:
  1741. szClientType= "None";
  1742. break;
  1743. case CLIENT_TYPE_DHCP:
  1744. szClientType = "DHCP";
  1745. break;
  1746. case CLIENT_TYPE_BOOTP:
  1747. szClientType = "BOOTP";
  1748. break;
  1749. case CLIENT_TYPE_UNSPECIFIED:
  1750. szClientType = "Unspecified";
  1751. break;
  1752. default:
  1753. DhcpAssert( FALSE );
  1754. }
  1755. printf( "%s\n", szClientType );
  1756. printf("\tExpires = ");
  1757. if ( ClientInfo->ClientLeaseExpires.dwLowDateTime ==
  1758. DHCP_DATE_TIME_INFINIT_LOW &&
  1759. ClientInfo->ClientLeaseExpires.dwHighDateTime ==
  1760. DHCP_DATE_TIME_INFINIT_HIGH )
  1761. {
  1762. printf( "Never (lease duration is infinite.)\n" );
  1763. }
  1764. else if( FileTimeToLocalFileTime(
  1765. (FILETIME *)(&ClientInfo->ClientLeaseExpires),
  1766. &LocalTime) ) {
  1767. if( FileTimeToSystemTime( &LocalTime, &SystemTime ) ) {
  1768. printf( "%02u/%02u/%02u %02u:%02u:%02u.\n",
  1769. SystemTime.wMonth,
  1770. SystemTime.wDay,
  1771. SystemTime.wYear,
  1772. SystemTime.wHour,
  1773. SystemTime.wMinute,
  1774. SystemTime.wSecond );
  1775. }
  1776. else {
  1777. printf( "Can't convert time, %ld.\n", GetLastError() );
  1778. }
  1779. }
  1780. else {
  1781. printf( "Can't convert time, %ld.\n", GetLastError() );
  1782. }
  1783. printf("\tOwner Host IP Address = %s.\n",
  1784. DhcpIpAddressToDottedString(ClientInfo->OwnerHost.IpAddress));
  1785. printf("\tOwner Host NetBios Name = %ws.\n",
  1786. ClientInfo->OwnerHost.NetBiosName );
  1787. printf("\tOwner Host Name = %ws.\n",
  1788. ClientInfo->OwnerHost.HostName );
  1789. printf("\tState = %0x\n", ClientInfo->AddressState );
  1790. }
  1791. #endif NT5
  1792. VOID
  1793. PrintClientInfoShort(
  1794. LPDHCP_CLIENT_INFO_V4 ClientInfo
  1795. )
  1796. {
  1797. SYSTEMTIME SystemTime;
  1798. FILETIME LocalTime;
  1799. printf("%ld\t %- 16.16s %- 16.16ws ",
  1800. GlobalClientCount++,
  1801. DhcpIpAddressToDottedString(ClientInfo->ClientIpAddress),
  1802. ClientInfo->ClientName
  1803. );
  1804. if ( ClientInfo->ClientLeaseExpires.dwLowDateTime ==
  1805. DHCP_DATE_TIME_INFINIT_LOW &&
  1806. ClientInfo->ClientLeaseExpires.dwHighDateTime ==
  1807. DHCP_DATE_TIME_INFINIT_HIGH )
  1808. {
  1809. printf( "Never (lease duration is infinite.)\n" );
  1810. }
  1811. else if( FileTimeToLocalFileTime(
  1812. (FILETIME *)(&ClientInfo->ClientLeaseExpires),
  1813. &LocalTime) ) {
  1814. if( FileTimeToSystemTime( &LocalTime, &SystemTime ) ) {
  1815. printf( "%02u/%02u/%02u %02u:%02u:%02u",
  1816. SystemTime.wMonth,
  1817. SystemTime.wDay,
  1818. SystemTime.wYear,
  1819. SystemTime.wHour,
  1820. SystemTime.wMinute,
  1821. SystemTime.wSecond );
  1822. }
  1823. else {
  1824. printf( "% 18.18s", "******************" );
  1825. }
  1826. }
  1827. else {
  1828. printf( "%.18s", "******************" );
  1829. }
  1830. printf( "\n" );
  1831. }
  1832. #ifdef NT5
  1833. VOID
  1834. PrintClientInfoShortV5(
  1835. LPDHCP_CLIENT_INFO_V5 ClientInfo
  1836. )
  1837. {
  1838. SYSTEMTIME SystemTime;
  1839. FILETIME LocalTime;
  1840. printf("%ld\t %- 16.16s %- 16.16ws ",
  1841. GlobalClientCount++,
  1842. DhcpIpAddressToDottedString(ClientInfo->ClientIpAddress),
  1843. ClientInfo->ClientName
  1844. );
  1845. if ( ClientInfo->ClientLeaseExpires.dwLowDateTime ==
  1846. DHCP_DATE_TIME_INFINIT_LOW &&
  1847. ClientInfo->ClientLeaseExpires.dwHighDateTime ==
  1848. DHCP_DATE_TIME_INFINIT_HIGH )
  1849. {
  1850. printf( "Never (lease duration is infinite.)\n" );
  1851. }
  1852. else if( FileTimeToLocalFileTime(
  1853. (FILETIME *)(&ClientInfo->ClientLeaseExpires),
  1854. &LocalTime) ) {
  1855. if( FileTimeToSystemTime( &LocalTime, &SystemTime ) ) {
  1856. printf( "%02u/%02u/%02u %02u:%02u:%02u",
  1857. SystemTime.wMonth,
  1858. SystemTime.wDay,
  1859. SystemTime.wYear,
  1860. SystemTime.wHour,
  1861. SystemTime.wMinute,
  1862. SystemTime.wSecond );
  1863. }
  1864. else {
  1865. printf( "% 18.18s", "******************" );
  1866. }
  1867. }
  1868. else {
  1869. printf( "%.18s", "******************" );
  1870. }
  1871. printf( "State=%02x", ClientInfo->AddressState);
  1872. printf( "\n" );
  1873. }
  1874. #endif NT5
  1875. VOID
  1876. PrintClientInfoShort1(
  1877. LPDHCP_CLIENT_INFO_V4 ClientInfo
  1878. )
  1879. {
  1880. DWORD i;
  1881. DWORD DataLength;
  1882. LPBYTE Data;
  1883. printf("%ld\t %- 16.16s %- 16.16ws ",
  1884. GlobalClientCount++,
  1885. DhcpIpAddressToDottedString(ClientInfo->ClientIpAddress),
  1886. ClientInfo->ClientName
  1887. );
  1888. DataLength = ClientInfo->ClientHardwareAddress.DataLength;
  1889. Data = ClientInfo->ClientHardwareAddress.Data;
  1890. for( i = 0; i < DataLength; i++ ) {
  1891. printf("%.2lx", (DWORD)Data[i]);
  1892. }
  1893. printf( "\n" );
  1894. }
  1895. DWORD
  1896. DetectIpAddressConflict(
  1897. DHCP_IP_ADDRESS IpAddress,
  1898. DWORD dwRetries,
  1899. LPBOOL AddressExists
  1900. )
  1901. /*++
  1902. Routine Description:
  1903. This function pings the specific IP address and checks if it exists
  1904. The number of "ping" retries is controled by the parameter
  1905. DetectConflictRetries in the registry. When it is set to 0, this
  1906. function always sets result to FALSE.
  1907. Arguments:
  1908. IpAddress - The IP address to check
  1909. AddressExists - pointer to the variable where the result is to be stored
  1910. Return Value:
  1911. Windows Error
  1912. --*/
  1913. {
  1914. HANDLE IcmpHandle;
  1915. char ReplyBuffer [1000];
  1916. DWORD NumReplies = 0;
  1917. DWORD i,
  1918. dwResult;
  1919. DhcpAssert( dwRetries );
  1920. *AddressExists = FALSE;
  1921. IcmpHandle = IcmpCreateFile();
  1922. if (IcmpHandle == INVALID_HANDLE_VALUE)
  1923. return GetLastError();
  1924. for (i = 0; i < dwRetries; i++) {
  1925. NumReplies = IcmpSendEcho(
  1926. IcmpHandle,
  1927. (IPAddr) ntohl(IpAddress),
  1928. (LPVOID) "DHCP Server Bad Address",
  1929. (WORD)strlen("DHCP Server Bad Address"),
  1930. NULL,
  1931. ReplyBuffer,
  1932. sizeof(ReplyBuffer),
  1933. 1000
  1934. );
  1935. if (NumReplies != 0) {
  1936. break;
  1937. }
  1938. }
  1939. dwResult = GetLastError();
  1940. // IcmpSendEcho will also return 0 to indicate an error condition.
  1941. // IP_REQ_TIMED_OUT indicates no response
  1942. if ( IP_REQ_TIMED_OUT == dwResult )
  1943. dwResult = 0;
  1944. IcmpCloseHandle (IcmpHandle);
  1945. *AddressExists = (NumReplies != 0);
  1946. return dwResult;
  1947. }
  1948. BOOL
  1949. AddressCanBeDeleted(
  1950. IN DHCP_IP_ADDRESS Address
  1951. )
  1952. {
  1953. BOOL RetVal;
  1954. RetVal = TRUE;
  1955. DetectIpAddressConflict(
  1956. Address,
  1957. 3,
  1958. &RetVal
  1959. );
  1960. if( RetVal ) {
  1961. printf("This address exists, so it wont be deleted\n");
  1962. } else {
  1963. printf("This address does not exist, so it will be deleted.\n");
  1964. }
  1965. return !RetVal;
  1966. }
  1967. DWORD
  1968. ProcessDeleteClient(
  1969. DWORD CommandArgc,
  1970. LPSTR *CommandArgv
  1971. )
  1972. {
  1973. DHCP_SEARCH_INFO SrchInfo;
  1974. DWORD Error;
  1975. if( CommandArgc != 1 ) {
  1976. printf("Usage: DhcpCmd SrvIpAddress DeleteClient ClientIp\n");
  1977. return ERROR_INVALID_PARAMETER;
  1978. }
  1979. SrchInfo.SearchType = DhcpClientIpAddress;
  1980. SrchInfo.SearchInfo.ClientIpAddress = htonl(
  1981. inet_addr( CommandArgv[0]) );
  1982. Error = DhcpDeleteClientInfo(
  1983. GlobalServerIpAddressUnicodeString, &SrchInfo );
  1984. if( NO_ERROR != Error ) {
  1985. printf("DhcpDeleteClientInfo failed %ld\n", Error);
  1986. }
  1987. return Error;
  1988. }
  1989. DWORD
  1990. ProcessDeleteBadClients(
  1991. DWORD CommandArgc,
  1992. LPSTR *CommandArgv
  1993. )
  1994. {
  1995. BOOL NoPing = FALSE;
  1996. DWORD Error;
  1997. DHCP_RESUME_HANDLE ResumeHandle = 0;
  1998. LPDHCP_CLIENT_INFO_ARRAY_V4 ClientEnumInfo = NULL;
  1999. DWORD ClientsRead = 0;
  2000. DWORD ClientsTotal = 0;
  2001. DWORD i;
  2002. if( CommandArgc > 1 || (
  2003. CommandArgc == 1 && _stricmp(CommandArgv[0], "NOPING") ) ) {
  2004. printf("usage:DhcpCmd SrvIpAddress DeleteBadClients [NOPING]\n");
  2005. return ERROR_SUCCESS;
  2006. }
  2007. NoPing = (CommandArgc == 1 );
  2008. GlobalClientCount = 1;
  2009. for(;;) {
  2010. ClientEnumInfo = NULL;
  2011. Error = DhcpEnumSubnetClientsV4(
  2012. GlobalServerIpAddressUnicodeString,
  2013. 0,
  2014. &ResumeHandle,
  2015. (DWORD)(-1),
  2016. &ClientEnumInfo,
  2017. &ClientsRead,
  2018. &ClientsTotal
  2019. );
  2020. if( (Error != ERROR_SUCCESS) && (Error != ERROR_MORE_DATA) ) {
  2021. printf("DhcpEnumSubnetClients failed, %ld.\n", Error );
  2022. return( Error );
  2023. }
  2024. DhcpAssert( ClientEnumInfo != NULL );
  2025. DhcpAssert( ClientEnumInfo->NumElements == ClientsRead );
  2026. for( i = 0; i < ClientsRead; i++ ) {
  2027. if( NULL == ClientEnumInfo->Clients[i]->ClientName ) {
  2028. //
  2029. // No name? Can that be a bad client? no.
  2030. //
  2031. continue;
  2032. }
  2033. if( wcscmp(ClientEnumInfo->Clients[i]->ClientName, L"BAD_ADDRESS" ) ) {
  2034. //
  2035. // Not a bad client! ignore it.
  2036. //
  2037. continue;
  2038. }
  2039. PrintClientInfoShort1( ClientEnumInfo->Clients[i] );
  2040. if( NoPing || AddressCanBeDeleted(ClientEnumInfo->Clients[i]->ClientIpAddress) ) {
  2041. DHCP_SEARCH_INFO SrchInfo2 = {
  2042. DhcpClientIpAddress,
  2043. ClientEnumInfo->Clients[i]->ClientIpAddress
  2044. };
  2045. Error = DhcpDeleteClientInfo(
  2046. GlobalServerIpAddressUnicodeString,
  2047. &SrchInfo2
  2048. );
  2049. if( ERROR_SUCCESS != Error ) {
  2050. printf("DhcpDeleteClientInfo failed %ld, continuing. \n", Error);
  2051. }
  2052. }
  2053. }
  2054. DhcpRpcFreeMemory( ClientEnumInfo );
  2055. if( Error != ERROR_MORE_DATA ) {
  2056. break;
  2057. }
  2058. }
  2059. return(Error);
  2060. return 0;
  2061. }
  2062. #ifdef NT5
  2063. VOID
  2064. PrintClientInfoShort1V5(
  2065. LPDHCP_CLIENT_INFO_V5 ClientInfo
  2066. )
  2067. {
  2068. DWORD i;
  2069. DWORD DataLength;
  2070. LPBYTE Data;
  2071. printf("%ld\t %- 16.16s %- 16.16ws ",
  2072. GlobalClientCount++,
  2073. DhcpIpAddressToDottedString(ClientInfo->ClientIpAddress),
  2074. ClientInfo->ClientName
  2075. );
  2076. DataLength = ClientInfo->ClientHardwareAddress.DataLength;
  2077. Data = ClientInfo->ClientHardwareAddress.Data;
  2078. for( i = 0; i < DataLength; i++ ) {
  2079. printf("%.2lx", (DWORD)Data[i]);
  2080. }
  2081. printf(" State=%02x\n", ClientInfo->AddressState);
  2082. printf( "\n" );
  2083. }
  2084. DWORD
  2085. ProcessEnumClientsV5(
  2086. DWORD CommandArgc,
  2087. LPSTR *CommandArgv
  2088. )
  2089. {
  2090. DWORD Error;
  2091. DHCP_RESUME_HANDLE ResumeHandle = 0;
  2092. LPDHCP_CLIENT_INFO_ARRAY_V5 ClientEnumInfo = NULL;
  2093. DWORD ClientsRead = 0;
  2094. DWORD ClientsTotal = 0;
  2095. DWORD i;
  2096. //
  2097. // Expected Parameters are : <SubnetAddress>
  2098. //
  2099. if( CommandArgc < 1 ) {
  2100. printf("usage:DhcpCmd SrvIpAddress EnumClients [Command Parameters].\n"
  2101. "<Command Parameters> - <SubnetAddress [-v | -h] >.\n" );
  2102. return( ERROR_SUCCESS );
  2103. }
  2104. GlobalClientCount = 1;
  2105. for(;;) {
  2106. ClientEnumInfo = NULL;
  2107. Error = DhcpEnumSubnetClientsV5(
  2108. GlobalServerIpAddressUnicodeString,
  2109. DhcpDottedStringToIpAddress(CommandArgv[0]),
  2110. &ResumeHandle,
  2111. (DWORD)(-1),
  2112. &ClientEnumInfo,
  2113. &ClientsRead,
  2114. &ClientsTotal );
  2115. if( (Error != ERROR_SUCCESS) && (Error != ERROR_MORE_DATA) ) {
  2116. printf("DhcpEnumSubnetClients failed, %ld.\n", Error );
  2117. return( Error );
  2118. }
  2119. DhcpAssert( ClientEnumInfo != NULL );
  2120. DhcpAssert( ClientEnumInfo->NumElements == ClientsRead );
  2121. if( (CommandArgc > 1) && CommandArgv[1][0] == '-') {
  2122. switch (CommandArgv[1][1]) {
  2123. case 'h':
  2124. case 'H':
  2125. for( i = 0; i < ClientsRead; i++ ) {
  2126. PrintClientInfoShort1V5( ClientEnumInfo->Clients[i] );
  2127. }
  2128. break;
  2129. case 'V':
  2130. case 'v':
  2131. printf("Num Client info read = %ld.\n", ClientsRead );
  2132. printf("Total Client count = %ld.\n", ClientsTotal );
  2133. for( i = 0; i < ClientsRead; i++ ) {
  2134. PrintClientInfoV5( ClientEnumInfo->Clients[i] );
  2135. }
  2136. break;
  2137. default:
  2138. for( i = 0; i < ClientsRead; i++ ) {
  2139. PrintClientInfoShortV5( ClientEnumInfo->Clients[i] );
  2140. }
  2141. break;
  2142. }
  2143. }
  2144. else {
  2145. for( i = 0; i < ClientsRead; i++ ) {
  2146. PrintClientInfoShortV5( ClientEnumInfo->Clients[i] );
  2147. }
  2148. }
  2149. DhcpRpcFreeMemory( ClientEnumInfo );
  2150. if( Error != ERROR_MORE_DATA ) {
  2151. break;
  2152. }
  2153. }
  2154. return(Error);
  2155. }
  2156. #endif NT5
  2157. DWORD
  2158. ProcessEnumClients(
  2159. DWORD CommandArgc,
  2160. LPSTR *CommandArgv
  2161. )
  2162. {
  2163. DWORD Error;
  2164. DHCP_RESUME_HANDLE ResumeHandle = 0;
  2165. LPDHCP_CLIENT_INFO_ARRAY_V4 ClientEnumInfo = NULL;
  2166. DWORD ClientsRead = 0;
  2167. DWORD ClientsTotal = 0;
  2168. DWORD i;
  2169. //
  2170. // Expected Parameters are : <SubnetAddress>
  2171. //
  2172. if( CommandArgc < 1 ) {
  2173. printf("usage:DhcpCmd SrvIpAddress EnumClients [Command Parameters].\n"
  2174. "<Command Parameters> - <SubnetAddress [-v | -h] >.\n" );
  2175. return( ERROR_SUCCESS );
  2176. }
  2177. GlobalClientCount = 1;
  2178. for(;;) {
  2179. ClientEnumInfo = NULL;
  2180. Error = DhcpEnumSubnetClientsV4(
  2181. GlobalServerIpAddressUnicodeString,
  2182. DhcpDottedStringToIpAddress(CommandArgv[0]),
  2183. &ResumeHandle,
  2184. (DWORD)(-1),
  2185. &ClientEnumInfo,
  2186. &ClientsRead,
  2187. &ClientsTotal );
  2188. if( (Error != ERROR_SUCCESS) && (Error != ERROR_MORE_DATA) ) {
  2189. printf("DhcpEnumSubnetClients failed, %ld.\n", Error );
  2190. return( Error );
  2191. }
  2192. DhcpAssert( ClientEnumInfo != NULL );
  2193. DhcpAssert( ClientEnumInfo->NumElements == ClientsRead );
  2194. if( (CommandArgc > 1) && CommandArgv[1][0] == '-') {
  2195. switch (CommandArgv[1][1]) {
  2196. case 'h':
  2197. case 'H':
  2198. for( i = 0; i < ClientsRead; i++ ) {
  2199. PrintClientInfoShort1( ClientEnumInfo->Clients[i] );
  2200. }
  2201. break;
  2202. case 'V':
  2203. case 'v':
  2204. printf("Num Client info read = %ld.\n", ClientsRead );
  2205. printf("Total Client count = %ld.\n", ClientsTotal );
  2206. for( i = 0; i < ClientsRead; i++ ) {
  2207. PrintClientInfo( ClientEnumInfo->Clients[i] );
  2208. }
  2209. break;
  2210. default:
  2211. for( i = 0; i < ClientsRead; i++ ) {
  2212. PrintClientInfoShort( ClientEnumInfo->Clients[i] );
  2213. }
  2214. break;
  2215. }
  2216. }
  2217. else {
  2218. for( i = 0; i < ClientsRead; i++ ) {
  2219. PrintClientInfoShort( ClientEnumInfo->Clients[i] );
  2220. }
  2221. }
  2222. DhcpRpcFreeMemory( ClientEnumInfo );
  2223. if( Error != ERROR_MORE_DATA ) {
  2224. break;
  2225. }
  2226. }
  2227. return(Error);
  2228. }
  2229. DWORD
  2230. ProcessMibCounts(
  2231. DWORD CommandArgc,
  2232. LPSTR *CommandArgv
  2233. )
  2234. {
  2235. DWORD Error;
  2236. LPDHCP_MIB_INFO MibInfo = NULL;
  2237. DWORD i;
  2238. LPSCOPE_MIB_INFO ScopeInfo;
  2239. SYSTEMTIME SystemTime;
  2240. FILETIME LocalTime;
  2241. Error = DhcpGetMibInfo(
  2242. GlobalServerIpAddressUnicodeString,
  2243. &MibInfo );
  2244. if( Error != ERROR_SUCCESS ) {
  2245. return( Error );
  2246. }
  2247. DhcpAssert( MibInfo != NULL );
  2248. printf("Discovers = %d.\n", MibInfo->Discovers);
  2249. printf("Offers = %d.\n", MibInfo->Offers);
  2250. printf("Requests = %d.\n", MibInfo->Requests);
  2251. printf("Acks = %d.\n", MibInfo->Acks);
  2252. printf("Naks = %d.\n", MibInfo->Naks);
  2253. printf("Declines = %d.\n", MibInfo->Declines);
  2254. printf("Releases = %d.\n", MibInfo->Releases);
  2255. printf("ServerStartTime = ");
  2256. if( FileTimeToLocalFileTime(
  2257. (FILETIME *)(&MibInfo->ServerStartTime),
  2258. &LocalTime) ) {
  2259. if( FileTimeToSystemTime( &LocalTime, &SystemTime ) ) {
  2260. printf( "%02u/%02u/%02u %02u:%02u:%02u.\n",
  2261. SystemTime.wMonth,
  2262. SystemTime.wDay,
  2263. SystemTime.wYear,
  2264. SystemTime.wHour,
  2265. SystemTime.wMinute,
  2266. SystemTime.wSecond );
  2267. }
  2268. else {
  2269. printf( "Can't convert time, %ld.\n", GetLastError() );
  2270. }
  2271. }
  2272. else {
  2273. printf( "Can't convert time, %ld.\n", GetLastError() );
  2274. }
  2275. printf("Scopes = %d.\n", MibInfo->Scopes);
  2276. ScopeInfo = MibInfo->ScopeInfo;
  2277. for ( i = 0; i < MibInfo->Scopes; i++ ) {
  2278. printf("Subnet = %s.\n",
  2279. DhcpIpAddressToDottedString(ScopeInfo[i].Subnet));
  2280. printf("\tNumAddressesInuse = %d.\n",
  2281. ScopeInfo[i].NumAddressesInuse );
  2282. printf("\tNumAddressesFree = %d.\n",
  2283. ScopeInfo[i].NumAddressesFree );
  2284. printf("\tNumPendingOffers = %d.\n",
  2285. ScopeInfo[i].NumPendingOffers );
  2286. }
  2287. DhcpRpcFreeMemory( MibInfo );
  2288. return( ERROR_SUCCESS );
  2289. }
  2290. VOID
  2291. PrintConfigCommands(
  2292. VOID
  2293. )
  2294. {
  2295. DWORD i;
  2296. DWORD NumCommands;
  2297. NumCommands = sizeof(GlobalConfigCommandInfo) /
  2298. sizeof(CONFIG_COMMAND_INFO);
  2299. DhcpAssert( NumCommands <= UnknownConfigCommand );
  2300. for( i = 0; i < NumCommands; i++) {
  2301. printf( "\t%ld. %s\n",
  2302. i, GlobalConfigCommandInfo[i].CommandName );
  2303. }
  2304. }
  2305. CONFIG_COMMAND_CODE
  2306. DecodeConfigCommand(
  2307. LPSTR CommandName
  2308. )
  2309. {
  2310. DWORD i;
  2311. DWORD NumCommands;
  2312. NumCommands = sizeof(GlobalConfigCommandInfo) /
  2313. sizeof(CONFIG_COMMAND_INFO);
  2314. DhcpAssert( NumCommands <= UnknownConfigCommand );
  2315. for( i = 0; i < NumCommands; i++) {
  2316. if( _stricmp( CommandName,
  2317. GlobalConfigCommandInfo[i].CommandName ) == 0 ) {
  2318. return( GlobalConfigCommandInfo[i].CommandCode );
  2319. }
  2320. }
  2321. return( UnknownConfigCommand );
  2322. }
  2323. //
  2324. // this function assumes input of the following format:
  2325. //
  2326. // [generic name1],[server name1],<boot file1>;[generic name2],...
  2327. //
  2328. //
  2329. WCHAR *
  2330. ParseBootFileTable(
  2331. char *szBootFileTable,
  2332. DWORD *pcb
  2333. )
  2334. {
  2335. WCHAR *pwszOutput;
  2336. DWORD cb;
  2337. *pcb = 0;
  2338. cb = strlen( szBootFileTable ) + 2; // double null terminator
  2339. pwszOutput = DhcpAllocateMemory( cb * sizeof( WCHAR ) );
  2340. if ( pwszOutput )
  2341. {
  2342. WCHAR *pwszTemp = DhcpOemToUnicode( szBootFileTable, pwszOutput );
  2343. if ( !pwszTemp )
  2344. {
  2345. // conversion failed
  2346. DhcpFreeMemory( pwszOutput );
  2347. pwszOutput = NULL;
  2348. }
  2349. else
  2350. {
  2351. // replace ';' with '\0'
  2352. while ( *pwszTemp )
  2353. {
  2354. if ( L';' == *pwszTemp )
  2355. {
  2356. *pwszTemp = L'\0';
  2357. }
  2358. ++pwszTemp;
  2359. }
  2360. *pcb = cb * sizeof( WCHAR );
  2361. // add 2cnd null terminator
  2362. pwszOutput[ cb - 1 ] = L'\0';
  2363. }
  2364. }
  2365. return pwszOutput;
  2366. }
  2367. void PrintBootFileString(
  2368. WCHAR *wszBootFileString
  2369. )
  2370. {
  2371. WCHAR *pwszBootFile = wszBootFileString;
  2372. while( *pwszBootFile != BOOT_FILE_STRING_DELIMITER_W )
  2373. pwszBootFile++;
  2374. *pwszBootFile = L'\0';
  2375. printf( "Bootfile Server = %S\n", wszBootFileString );
  2376. printf( "Bootfile = %S\n\n", ++pwszBootFile );
  2377. }
  2378. void PrintBootTableString(
  2379. WCHAR *wszBootFileTable
  2380. )
  2381. {
  2382. while( *wszBootFileTable )
  2383. {
  2384. WCHAR *pwszDelimiter = wszBootFileTable;
  2385. DWORD cb = wcslen( wszBootFileTable ) + 1;
  2386. while( *pwszDelimiter != BOOT_FILE_STRING_DELIMITER_W )
  2387. pwszDelimiter++;
  2388. *pwszDelimiter = L'\0';
  2389. printf( "Generic Bootfile request = %S\n", wszBootFileTable );
  2390. PrintBootFileString( ++pwszDelimiter );
  2391. wszBootFileTable += cb;
  2392. }
  2393. }
  2394. DWORD ProcessRemoveSubscope(
  2395. DWORD CommandArgc,
  2396. LPSTR *CommandArgv
  2397. )
  2398. {
  2399. DHCP_IP_ADDRESS SubnetAddress;
  2400. DWORD dwResult;
  2401. if( CommandArgc < 1 )
  2402. {
  2403. printf("usage:DhcpCmd SrvIpAddress RemoveSubscope <scope ID>.\n" );
  2404. return( ERROR_SUCCESS );
  2405. }
  2406. SubnetAddress = htonl( inet_addr( CommandArgv[0] ) );
  2407. dwResult = DhcpSetSuperScopeV4(
  2408. GlobalServerIpAddressUnicodeString,
  2409. SubnetAddress,
  2410. NULL,
  2411. TRUE
  2412. );
  2413. return dwResult;
  2414. }
  2415. DWORD ProcessSetSuperScope(
  2416. DWORD CommandArgc,
  2417. LPSTR *CommandArgv
  2418. )
  2419. {
  2420. DHCP_IP_ADDRESS SubnetAddress;
  2421. WCHAR *pwszSuperScopeName;
  2422. BOOL fChangeExisting;
  2423. DWORD dwResult;
  2424. if( CommandArgc < 3 )
  2425. {
  2426. printf("usage:DhcpCmd SrvIpAddress SetSuperScope <SuperScope name> <scope ID> <1|0>\n" );
  2427. return( ERROR_SUCCESS );
  2428. }
  2429. pwszSuperScopeName = DhcpOemToUnicode( CommandArgv[0], NULL );
  2430. SubnetAddress = htonl( inet_addr( CommandArgv[1] ) );
  2431. fChangeExisting = (BOOL) ( *(CommandArgv[2]) - '0' );
  2432. dwResult = DhcpSetSuperScopeV4( GlobalServerIpAddressUnicodeString,
  2433. SubnetAddress,
  2434. pwszSuperScopeName,
  2435. fChangeExisting );
  2436. return dwResult;
  2437. }
  2438. DWORD ProcessDeleteSuperScope(
  2439. DWORD CommandArgc,
  2440. LPSTR *CommandArgv
  2441. )
  2442. {
  2443. WCHAR *pwszSuperScope;
  2444. DWORD dwResult;
  2445. if( CommandArgc < 1 ) {
  2446. printf("usage:DhcpCmd SrvIpAddress DeleteSuperScope <scope name>.\n" );
  2447. return( ERROR_SUCCESS );
  2448. }
  2449. printf( "Deleting SuperScope %s\n", CommandArgv[0] );
  2450. pwszSuperScope = DhcpOemToUnicode( CommandArgv[0], NULL );
  2451. dwResult = DhcpDeleteSuperScopeV4( GlobalServerIpAddressUnicodeString,
  2452. pwszSuperScope );
  2453. DhcpFreeMemory( pwszSuperScope );
  2454. return dwResult;
  2455. }
  2456. DWORD ProcessGetSuperScopeTable(
  2457. DWORD CommandArgc,
  2458. LPSTR *CommandArgv
  2459. )
  2460. {
  2461. DHCP_SUPER_SCOPE_TABLE *pTable = NULL;
  2462. DWORD dwResult;
  2463. dwResult = DhcpGetSuperScopeInfoV4(
  2464. GlobalServerIpAddressUnicodeString,
  2465. &pTable );
  2466. if ( ERROR_SUCCESS == dwResult )
  2467. {
  2468. DWORD n;
  2469. for ( n = 0; n < pTable->cEntries; n++ )
  2470. {
  2471. IN_ADDR InAddr;
  2472. InAddr.s_addr = htonl( pTable->pEntries[n].SubnetAddress );
  2473. printf( "Superscope name = %S\n", pTable->pEntries[n].SuperScopeName );
  2474. printf( "Subnet address = %s\n", inet_ntoa( InAddr ) );
  2475. printf( "Superscope goup number = %d\n", pTable->pEntries[n].SuperScopeNumber );
  2476. }
  2477. DhcpRpcFreeMemory( pTable );
  2478. }
  2479. return ERROR_SUCCESS;
  2480. }
  2481. DWORD
  2482. ProcessServerConfig(
  2483. DWORD CommandArgc,
  2484. LPSTR *CommandArgv
  2485. )
  2486. {
  2487. DWORD Error;
  2488. LPDHCP_SERVER_CONFIG_INFO_V4 ConfigInfo = NULL;
  2489. DWORD FieldsToSet = 0;
  2490. CONFIG_COMMAND_CODE CommandCode;
  2491. DWORD Value;
  2492. LPWSTR ValueString;
  2493. if( CommandArgc < 1 ) {
  2494. Error = DhcpServerGetConfigV4(
  2495. GlobalServerIpAddressUnicodeString,
  2496. &ConfigInfo );
  2497. if( Error != ERROR_SUCCESS ) {
  2498. return( Error );
  2499. }
  2500. DhcpAssert( ConfigInfo != NULL );
  2501. printf("APIProtocolSupport = %lx\n", ConfigInfo->APIProtocolSupport );
  2502. printf("DatabaseName = %ws\n", ConfigInfo->DatabaseName );
  2503. printf("DatabasePath = %ws\n", ConfigInfo->DatabasePath );
  2504. printf("BackupPath = %ws\n", ConfigInfo->BackupPath );
  2505. printf("BackupInterval = %ld mins.\n",
  2506. ConfigInfo->BackupInterval );
  2507. printf("DatabaseLoggingFlag = %ld\n", ConfigInfo->DatabaseLoggingFlag );
  2508. printf("RestoreFlag = %ld\n", ConfigInfo->RestoreFlag );
  2509. printf("DatabaseCleanupInterval = %ld mins.\n",
  2510. ConfigInfo->DatabaseCleanupInterval );
  2511. printf("DebugFlag = %lx\n", ConfigInfo->DebugFlag );
  2512. printf("PingRetries = %d\n", ConfigInfo->dwPingRetries );
  2513. printf("ActivityLog = %d\n", (DWORD) ConfigInfo->fAuditLog );
  2514. if ( ConfigInfo->cbBootTableString )
  2515. {
  2516. printf( "BOOTP request table:\n" );
  2517. PrintBootTableString( ConfigInfo->wszBootTableString );
  2518. }
  2519. DhcpRpcFreeMemory( ConfigInfo );
  2520. return( Error );
  2521. }
  2522. if ( CommandArgc == 1)
  2523. {
  2524. ++CommandArgc;
  2525. return ERROR_INVALID_PARAMETER;
  2526. }
  2527. else
  2528. {
  2529. ConfigInfo = DhcpAllocateMemory( sizeof(DHCP_SERVER_CONFIG_INFO_V4) );
  2530. if( ConfigInfo == NULL ) {
  2531. printf("Insufficient memory\n");
  2532. return( ERROR_NOT_ENOUGH_MEMORY );
  2533. }
  2534. RtlZeroMemory( ConfigInfo, sizeof( *ConfigInfo ) );
  2535. }
  2536. while( CommandArgc >= 2 ) {
  2537. CommandCode = DecodeConfigCommand( CommandArgv[0] );
  2538. Value = 0;
  2539. ValueString = NULL;
  2540. switch( CommandCode )
  2541. {
  2542. case ConfigDatabaseName:
  2543. case ConfigDatabasePath:
  2544. case ConfigBackupPath:
  2545. case ConfigAPIProtocolSupport:
  2546. case ConfigBackupInterval:
  2547. case ConfigDatabaseLoggingFlag:
  2548. case ConfigRestoreFlag:
  2549. case ConfigDatabaseCleanupInterval:
  2550. case ConfigDebugFlag:
  2551. case ConfigActivityLog:
  2552. case ConfigPingRetries:
  2553. Value = atoi( CommandArgv[1] );
  2554. break;
  2555. case ConfigBootFileTable:
  2556. ValueString = ParseBootFileTable( CommandArgv[1],
  2557. &Value );
  2558. break;
  2559. }
  2560. switch( CommandCode ) {
  2561. case ConfigAPIProtocolSupport:
  2562. FieldsToSet |= Set_APIProtocolSupport;
  2563. ConfigInfo->APIProtocolSupport = Value;
  2564. break;
  2565. case ConfigDatabaseName:
  2566. FieldsToSet |= Set_DatabaseName;
  2567. ConfigInfo->DatabaseName = ValueString;
  2568. break;
  2569. case ConfigDatabasePath:
  2570. FieldsToSet |= Set_DatabasePath;
  2571. ConfigInfo->DatabasePath = ValueString;
  2572. break;
  2573. case ConfigBackupPath:
  2574. FieldsToSet |= Set_BackupPath;
  2575. ConfigInfo->BackupPath = ValueString;
  2576. break;
  2577. case ConfigBackupInterval:
  2578. FieldsToSet |= Set_BackupInterval;
  2579. ConfigInfo->BackupInterval = Value;
  2580. break;
  2581. case ConfigDatabaseLoggingFlag:
  2582. FieldsToSet |= Set_DatabaseLoggingFlag;
  2583. ConfigInfo->DatabaseLoggingFlag = Value;
  2584. break;
  2585. case ConfigRestoreFlag:
  2586. FieldsToSet |= Set_RestoreFlag;
  2587. ConfigInfo->RestoreFlag = Value;
  2588. break;
  2589. case ConfigDatabaseCleanupInterval:
  2590. FieldsToSet |= Set_DatabaseCleanupInterval;
  2591. ConfigInfo->DatabaseCleanupInterval = Value;
  2592. break;
  2593. case ConfigDebugFlag:
  2594. FieldsToSet |= Set_DebugFlag;
  2595. ConfigInfo->DebugFlag = Value;
  2596. break;
  2597. case ConfigPingRetries:
  2598. FieldsToSet |= Set_PingRetries;
  2599. ConfigInfo->dwPingRetries = Value;
  2600. break;
  2601. case ConfigActivityLog:
  2602. FieldsToSet |= Set_AuditLogState;
  2603. ConfigInfo->fAuditLog = (BOOL) Value;
  2604. break;
  2605. case ConfigBootFileTable:
  2606. FieldsToSet |= Set_BootFileTable;
  2607. ConfigInfo->wszBootTableString = ValueString;
  2608. ConfigInfo->cbBootTableString = Value;
  2609. break;
  2610. case UnknownConfigCommand:
  2611. default:
  2612. printf("usage:DhcpCmd SrvIpAddress ServerConfig "
  2613. "[ConfigCommand ConfigValue]"
  2614. "[ConfigCommand ConfigValue]"
  2615. "... \n");
  2616. printf("ConfigCommands : \n");
  2617. PrintConfigCommands();
  2618. Error = ERROR_INVALID_PARAMETER;
  2619. goto Cleanup;
  2620. }
  2621. CommandArgc -= 2;
  2622. CommandArgv += 2;
  2623. }
  2624. Error = DhcpServerSetConfigV4(
  2625. GlobalServerIpAddressUnicodeString,
  2626. FieldsToSet,
  2627. ConfigInfo );
  2628. if( Error != ERROR_SUCCESS ) {
  2629. goto Cleanup;
  2630. }
  2631. Error = ProcessServerConfig( 0, NULL );
  2632. Cleanup:
  2633. if( ConfigInfo != NULL ) {
  2634. if( ConfigInfo->DatabaseName != NULL ) {
  2635. DhcpFreeMemory( ConfigInfo->DatabaseName );
  2636. }
  2637. if( ConfigInfo->DatabasePath != NULL ) {
  2638. DhcpFreeMemory( ConfigInfo->DatabasePath );
  2639. }
  2640. if( ConfigInfo->BackupPath != NULL ) {
  2641. DhcpFreeMemory( ConfigInfo->BackupPath );
  2642. }
  2643. DhcpFreeMemory( ConfigInfo );
  2644. }
  2645. return( Error );
  2646. }
  2647. DWORD
  2648. ProcessCheckDB(
  2649. DWORD CommandArgc,
  2650. LPSTR *CommandArgv
  2651. )
  2652. {
  2653. DWORD Error;
  2654. LPDHCP_SCAN_LIST ScanList = NULL;
  2655. BOOL FixFlag = FALSE;
  2656. if( CommandArgc < 1 ) {
  2657. printf("usage:DhcpCmd SrvIpAddress CheckDB [Command Parameters].\n"
  2658. "<Command Parameters> - <SubnetAddress> <[Fix]>.\n" );
  2659. return( ERROR_SUCCESS );
  2660. }
  2661. if( CommandArgc >= 2 ) {
  2662. //
  2663. // parse fix parameter.
  2664. //
  2665. if( _stricmp(CommandArgv[0], "fix") ) {
  2666. FixFlag = TRUE;
  2667. }
  2668. }
  2669. //
  2670. // scan dhcp database and registry, check consistency and get bad
  2671. // entries if any.
  2672. //
  2673. Error = DhcpScanDatabase(
  2674. GlobalServerIpAddressUnicodeString,
  2675. DhcpDottedStringToIpAddress(CommandArgv[0]),
  2676. FixFlag,
  2677. &ScanList
  2678. );
  2679. if( Error != ERROR_SUCCESS ) {
  2680. printf("DhcpScanDatabase failed, %ld.\n", Error );
  2681. return( Error );
  2682. }
  2683. //
  2684. // display bad entries.
  2685. //
  2686. if( (ScanList != NULL) &&
  2687. (ScanList->NumScanItems != 0) &&
  2688. (ScanList->ScanItems != NULL) ) {
  2689. LPDHCP_SCAN_ITEM ScanItem;
  2690. LPDHCP_SCAN_ITEM ScanItemEnd;
  2691. DWORD i = 1;
  2692. ScanItemEnd =
  2693. ScanList->ScanItems +
  2694. ScanList->NumScanItems;
  2695. for( ScanItem = ScanList->ScanItems;
  2696. ScanItem < ScanItemEnd; ScanItem++ ) {
  2697. printf("%ld %- 16.16s ",
  2698. i++,
  2699. DhcpIpAddressToDottedString(ScanItem->IpAddress) );
  2700. if( ScanItem->ScanFlag == DhcpRegistryFix ) {
  2701. printf("Fix Registry\n");
  2702. }
  2703. else if( ScanItem->ScanFlag == DhcpDatabaseFix ) {
  2704. printf("Fix Database\n");
  2705. }
  2706. else {
  2707. printf("Fix Unknown\n");
  2708. }
  2709. }
  2710. }
  2711. return( ERROR_SUCCESS );
  2712. }
  2713. VOID
  2714. PrintOptionValue(
  2715. LPDHCP_OPTION_DATA OptionValue
  2716. )
  2717. {
  2718. DWORD NumElements;
  2719. DHCP_OPTION_DATA_TYPE OptionType;
  2720. DWORD i;
  2721. printf("Option Value : \n");
  2722. NumElements = OptionValue->NumElements;
  2723. printf("\tNumber of Option Elements = %ld\n", NumElements );
  2724. if( NumElements == 0 ) {
  2725. return;
  2726. }
  2727. OptionType = OptionValue->Elements[0].OptionType;
  2728. printf("\tOption Elements Type = " );
  2729. switch( OptionType ) {
  2730. case DhcpByteOption:
  2731. printf("DhcpByteOption\n");
  2732. break;
  2733. case DhcpWordOption:
  2734. printf("DhcpWordOption\n");
  2735. break;
  2736. case DhcpDWordOption:
  2737. printf("DhcpDWordOption\n");
  2738. break;
  2739. case DhcpDWordDWordOption:
  2740. printf("DhcpDWordDWordOption\n");
  2741. break;
  2742. case DhcpIpAddressOption:
  2743. printf("DhcpIpAddressOption\n");
  2744. break;
  2745. case DhcpStringDataOption:
  2746. printf("DhcpStringDataOption\n");
  2747. break;
  2748. case DhcpBinaryDataOption:
  2749. printf("DhcpBinaryDataOption\n");
  2750. break;
  2751. case DhcpEncapsulatedDataOption:
  2752. printf("DhcpEncapsulatedDataOption\n");
  2753. break;
  2754. default:
  2755. printf("Unknown\n");
  2756. return;
  2757. }
  2758. for( i = 0; i < OptionValue->NumElements; i++ ) {
  2759. DhcpAssert( OptionType == OptionValue->Elements[i].OptionType );
  2760. printf("Option Element %ld value = ", i );
  2761. switch( OptionType ) {
  2762. case DhcpByteOption:
  2763. printf("%lx.\n", (DWORD)
  2764. OptionValue->Elements[i].Element.ByteOption );
  2765. break;
  2766. case DhcpWordOption:
  2767. printf("%lx.\n", (DWORD)
  2768. OptionValue->Elements[i].Element.WordOption );
  2769. break;
  2770. case DhcpDWordOption:
  2771. printf("%lx.\n",
  2772. OptionValue->Elements[i].Element.DWordOption );
  2773. break;
  2774. case DhcpDWordDWordOption:
  2775. printf("%lx, %lx.\n",
  2776. OptionValue->Elements[i].Element.DWordDWordOption.DWord1,
  2777. OptionValue->Elements[i].Element.DWordDWordOption.DWord2 );
  2778. break;
  2779. case DhcpIpAddressOption:
  2780. printf("%lx.\n",
  2781. OptionValue->Elements[i].Element.IpAddressOption );
  2782. break;
  2783. case DhcpStringDataOption:
  2784. printf("%ws.\n",
  2785. OptionValue->Elements[i].Element.StringDataOption );
  2786. break;
  2787. case DhcpBinaryDataOption:
  2788. case DhcpEncapsulatedDataOption: {
  2789. DWORD j;
  2790. DWORD Length;
  2791. Length = OptionValue->Elements[i].Element.BinaryDataOption.DataLength;
  2792. for( j = 0; j < Length; j++ ) {
  2793. printf("%2lx ",
  2794. OptionValue->Elements[i].Element.BinaryDataOption.Data[j] );
  2795. }
  2796. printf(".\n");
  2797. break;
  2798. }
  2799. default:
  2800. printf("PrintOptionValue: Unknown OptionType.\n");
  2801. break;
  2802. }
  2803. }
  2804. }
  2805. VOID
  2806. PrintOptionInfo(
  2807. LPDHCP_OPTION OptionInfo
  2808. )
  2809. {
  2810. printf( "Option Info : \n");
  2811. printf( "\tOptionId : %ld \n", (DWORD)OptionInfo->OptionID );
  2812. printf( "\tOptionName : %ws \n", OptionInfo->OptionName );
  2813. printf( "\tOptionComment : %ws \n", OptionInfo->OptionComment );
  2814. PrintOptionValue( &OptionInfo->DefaultValue );
  2815. printf( "\tOptionType : %ld \n", (DWORD)OptionInfo->OptionType );
  2816. }
  2817. DWORD
  2818. _EnumOptions(
  2819. IN LPWSTR ServerAddress,
  2820. IN DWORD Flags,
  2821. IN LPWSTR ClassName,
  2822. IN LPWSTR VendorName,
  2823. IN OUT DHCP_RESUME_HANDLE *ResumeHandle,
  2824. IN DWORD PreferredMaximum,
  2825. OUT LPDHCP_OPTION_ARRAY *Options,
  2826. OUT DWORD *OptionsRead,
  2827. OUT DWORD *OptionsTotal
  2828. )
  2829. {
  2830. DWORD MajorVersion, MinorVersion;
  2831. DWORD Error;
  2832. #ifdef NT5
  2833. if( GlobalNoRPC ) {
  2834. MajorVersion = CLASS_ID_VERSION ;
  2835. } else {
  2836. Error = DhcpGetVersion(ServerAddress, &MajorVersion, &MinorVersion);
  2837. if( ERROR_SUCCESS != Error ) {
  2838. printf("Could not determine server version.\n");
  2839. return Error;
  2840. }
  2841. }
  2842. if( MajorVersion >= CLASS_ID_VERSION ) {
  2843. return DhcpEnumOptionsV5(
  2844. ServerAddress,
  2845. GlobalIsVendor ? Flags | DHCP_FLAGS_OPTION_IS_VENDOR : Flags,
  2846. ClassName,
  2847. VendorName,
  2848. ResumeHandle,
  2849. PreferredMaximum,
  2850. Options,
  2851. OptionsRead,
  2852. OptionsTotal
  2853. );
  2854. }
  2855. // incorrect version, just do like before..
  2856. #endif
  2857. return DhcpEnumOptions(
  2858. ServerAddress,
  2859. ResumeHandle,
  2860. PreferredMaximum,
  2861. Options,
  2862. OptionsRead,
  2863. OptionsTotal
  2864. );
  2865. }
  2866. DWORD
  2867. ProcessEnumOptions(
  2868. DWORD CommandArgc,
  2869. LPSTR *CommandArgv
  2870. )
  2871. {
  2872. DWORD Error;
  2873. LPDHCP_OPTION_ARRAY OptionsArray = NULL;
  2874. DHCP_RESUME_HANDLE ResumeHandle = 0;
  2875. DWORD OptionsRead;
  2876. DWORD OptionsTotal;
  2877. Error = _EnumOptions(
  2878. GlobalServerIpAddressUnicodeString,
  2879. 0,
  2880. GlobalClassName,
  2881. GlobalVendorName,
  2882. &ResumeHandle,
  2883. 0xFFFFFFFF, // get all.
  2884. &OptionsArray,
  2885. &OptionsRead,
  2886. &OptionsTotal
  2887. );
  2888. if( Error != ERROR_SUCCESS ) {
  2889. printf("DhcpEnumOptions failed %ld\n", Error );
  2890. } else {
  2891. DWORD i;
  2892. LPDHCP_OPTION Options;
  2893. DWORD NumOptions;
  2894. printf("OptionsRead = %ld.\n", OptionsRead);
  2895. printf("OptionsTotal = %ld.\n", OptionsTotal);
  2896. Options = OptionsArray->Options;
  2897. NumOptions = OptionsArray->NumElements;
  2898. for( i = 0; i < NumOptions; i++, Options++ ) {
  2899. PrintOptionInfo( Options );
  2900. }
  2901. DhcpRpcFreeMemory( OptionsArray );
  2902. OptionsArray = NULL;
  2903. }
  2904. return( Error );
  2905. }
  2906. DWORD
  2907. ProcessGetVersion(
  2908. DWORD *pdwMajor,
  2909. DWORD *pdwMinor
  2910. )
  2911. {
  2912. DWORD Error = ERROR_SUCCESS;
  2913. DWORD MajorVersion;
  2914. DWORD MinorVersion;
  2915. if ( g_dwMajor == (DWORD) -1 && g_dwMinor == (DWORD) -1 ) {
  2916. Error = DhcpGetVersion(
  2917. GlobalServerIpAddressUnicodeString,
  2918. &g_dwMajor,
  2919. &g_dwMinor
  2920. );
  2921. if ( ERROR_SUCCESS == Error ) {
  2922. printf( "DHCP Server version %d.%d\n", g_dwMajor, g_dwMinor );
  2923. }
  2924. }
  2925. return Error;
  2926. }
  2927. VOID
  2928. PrintOptionArray(
  2929. IN LPDHCP_OPTION_ARRAY OptArray
  2930. )
  2931. {
  2932. DWORD i;
  2933. for( i = 0; i < OptArray->NumElements ; i ++ ) {
  2934. PrintOptionInfo( &OptArray->Options[i] );
  2935. }
  2936. }
  2937. VOID
  2938. PrintOptionValue1(
  2939. IN LPDHCP_OPTION_VALUE OptVal
  2940. )
  2941. {
  2942. printf("Option: %ld\n", OptVal->OptionID);
  2943. PrintOptionValue(&OptVal->Value);
  2944. }
  2945. VOID
  2946. PrintOptionValuesArray(
  2947. IN LPDHCP_OPTION_VALUE_ARRAY OptValArray
  2948. )
  2949. {
  2950. DWORD i;
  2951. if( NULL == OptValArray ) return;
  2952. for( i = 0; i < OptValArray->NumElements ; i ++ ) {
  2953. PrintOptionValue1( &OptValArray->Values[i] );
  2954. }
  2955. }
  2956. #ifdef NT5
  2957. #define CHKNULL(Str) ((Str)?(Str):L"<None>")
  2958. VOID
  2959. PrintAllOptions(
  2960. IN LPDHCP_ALL_OPTIONS Options
  2961. )
  2962. {
  2963. DWORD i;
  2964. printf("Options [Non Vendor specific]:\n"
  2965. "==============================\n");
  2966. PrintOptionArray(Options->NonVendorOptions);
  2967. for( i = 0; i < Options->NumVendorOptions; i ++ ) {
  2968. printf("\nOptions [Vendor:%ws]\n==============================\n",
  2969. CHKNULL( Options->VendorOptions[i].VendorName));
  2970. PrintOptionInfo(&(Options->VendorOptions[i].Option));
  2971. }
  2972. printf("\n\n");
  2973. }
  2974. DWORD
  2975. ProcessGetAllOptions(
  2976. IN DWORD CommandArgc,
  2977. IN LPSTR CommandArgv[]
  2978. )
  2979. {
  2980. DWORD Error, Major, Minor;
  2981. LPDHCP_ALL_OPTIONS Options;
  2982. if( TRUE == GlobalNoRPC ) {
  2983. Major = CLASS_ID_VERSION;
  2984. } else {
  2985. Error = DhcpGetVersion(
  2986. GlobalServerIpAddressUnicodeString,
  2987. &Major,
  2988. &Minor
  2989. );
  2990. if( ERROR_SUCCESS != Error ) {
  2991. printf("Could not get DHCP server version!\n");
  2992. return Error;
  2993. }
  2994. }
  2995. if( CLASS_ID_VERSION > Major ) {
  2996. printf("DHCP Server (major version %ld) does not support this function call.\n", Major);
  2997. return ERROR_SUCCESS;
  2998. }
  2999. Options = NULL;
  3000. Error = DhcpGetAllOptions(
  3001. GlobalServerIpAddressUnicodeString,
  3002. 0,
  3003. &Options
  3004. );
  3005. if( ERROR_SUCCESS != Error ) return Error;
  3006. if( NULL == Options ) {
  3007. printf("Server returned no options!\n");
  3008. DhcpAssert(FALSE);
  3009. } else {
  3010. PrintAllOptions(Options);
  3011. DhcpRpcFreeMemory(Options);
  3012. }
  3013. return ERROR_SUCCESS;
  3014. }
  3015. VOID
  3016. PrintAllOptionValues(
  3017. IN LPDHCP_ALL_OPTION_VALUES OptValues
  3018. )
  3019. {
  3020. DWORD i;
  3021. printf("Flags = 0x%lx, NumValues = %ld\n", OptValues->Flags, OptValues->NumElements);
  3022. for( i = 0; i < OptValues->NumElements ; i ++ ) {
  3023. printf("Options");
  3024. if( OptValues->Options[i].IsVendor ) {
  3025. printf(" for vendor <%ws>", CHKNULL(OptValues->Options[i].VendorName));
  3026. }
  3027. if( OptValues->Options[i].ClassName ) {
  3028. printf(" for user class <%ws>", OptValues->Options[i].ClassName);
  3029. }
  3030. printf(":\n");
  3031. PrintOptionValuesArray(OptValues->Options[i].OptionsArray);
  3032. }
  3033. }
  3034. DWORD
  3035. ProcessGetAllOptionValues(
  3036. IN DWORD CommandArgc,
  3037. IN LPSTR CommandArgv[]
  3038. )
  3039. {
  3040. DWORD Error, Major, Minor;
  3041. LPDHCP_ALL_OPTION_VALUES OptionValues;
  3042. DHCP_OPTION_SCOPE_INFO ScopeInfo;
  3043. // usage: getalloptionvalues [command parameters]
  3044. // [CommandParameters] = Global/Default/SubnetAddress/SubnetAddress ReservedAddress
  3045. if( CommandArgc != 1 && CommandArgc != 2 ) {
  3046. printf("Usage: Dhcpcmd SrvIpAddress GetAllOptionValues [CommandParameters]\n");
  3047. printf("<Command parameters> - < GLOBAL | DEFAULT | Subnet-Adddress | Subnet-Address Reserved Address>.\n");
  3048. return ERROR_SUCCESS;
  3049. }
  3050. if( 1 == CommandArgc ) {
  3051. if( 0 == _stricmp(CommandArgv[0], "GLOBAL") ) {
  3052. ScopeInfo.ScopeType = DhcpGlobalOptions;
  3053. } else if ( 0 == _stricmp(CommandArgv[0], "DEFAULT" )) {
  3054. ScopeInfo.ScopeType = DhcpDefaultOptions;
  3055. } else {
  3056. ScopeInfo.ScopeType = DhcpSubnetOptions;
  3057. ScopeInfo.ScopeInfo.SubnetScopeInfo = DhcpDottedStringToIpAddress(CommandArgv[0]);
  3058. }
  3059. } else {
  3060. ScopeInfo.ScopeType = DhcpReservedOptions;
  3061. ScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpSubnetAddress =
  3062. DhcpDottedStringToIpAddress(CommandArgv[0]);
  3063. ScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpAddress =
  3064. DhcpDottedStringToIpAddress( CommandArgv[1] );
  3065. }
  3066. if( TRUE == GlobalNoRPC ) {
  3067. Major = CLASS_ID_VERSION;
  3068. } else {
  3069. Error = DhcpGetVersion(
  3070. GlobalServerIpAddressUnicodeString,
  3071. &Major,
  3072. &Minor
  3073. );
  3074. if( ERROR_SUCCESS != Error ) {
  3075. printf("Could not get DHCP server version!\n");
  3076. return Error;
  3077. }
  3078. }
  3079. if( CLASS_ID_VERSION > Major ) {
  3080. printf("DHCP Server (major version %ld) does not support this function call.\n", Major);
  3081. return ERROR_SUCCESS;
  3082. }
  3083. OptionValues = NULL;
  3084. Error = DhcpGetAllOptionValues(
  3085. GlobalServerIpAddressUnicodeString,
  3086. 0,
  3087. &ScopeInfo,
  3088. &OptionValues
  3089. );
  3090. if( ERROR_SUCCESS != Error ) return Error;
  3091. if( NULL == OptionValues ) {
  3092. printf("Server returned no option values!\n");
  3093. DhcpAssert(FALSE);
  3094. } else {
  3095. PrintAllOptionValues(OptionValues);
  3096. DhcpRpcFreeMemory(OptionValues);
  3097. }
  3098. return ERROR_SUCCESS;
  3099. }
  3100. PBYTE
  3101. GetLangTag(
  3102. )
  3103. {
  3104. char b1[8], b2[8];
  3105. static char buff[80];
  3106. GetLocaleInfoA(LOCALE_SYSTEM_DEFAULT, LOCALE_SISO639LANGNAME, b1, sizeof(b1));
  3107. GetLocaleInfoA(LOCALE_SYSTEM_DEFAULT, LOCALE_SISO3166CTRYNAME, b2, sizeof(b2));
  3108. if (_stricmp(b1, b2))
  3109. sprintf(buff, "%s-%s", b1, b2);
  3110. else
  3111. strcpy(buff, b1);
  3112. return buff;
  3113. }
  3114. DWORD
  3115. ProcessCreateMScope(
  3116. DWORD CommandArgc,
  3117. LPSTR *CommandArgv
  3118. )
  3119. {
  3120. DWORD Error;
  3121. DHCP_MSCOPE_INFO MScopeInfo;
  3122. LPWSTR UnicodeMScopeName = NULL;
  3123. LPWSTR UnicodeMScopeDesc = NULL;
  3124. DWORD MScopeId;
  3125. LPWSTR UnicodeLangTag = NULL;
  3126. PBYTE LangTag;
  3127. DWORD ExpiryTimeInHours = 0;
  3128. //
  3129. // Expected Parameters are : <MScopeId MScopeName MScopeDescription ExpiryTime>
  3130. //
  3131. if( CommandArgc < 4 ) {
  3132. printf("usage:DhcpCmd SrvIpAddress CreateMScope [Command Parameters].\n"
  3133. "<Command Parameters> - <MScopeId MScopeName MScopeDescription ExpiryTimeInHours>.\n"
  3134. );
  3135. Error = ERROR_SUCCESS;
  3136. goto Cleanup;
  3137. }
  3138. MScopeId = atoi( CommandArgv[0] );
  3139. if (!MScopeId) {
  3140. Error = ERROR_SUCCESS;
  3141. goto Cleanup;
  3142. }
  3143. UnicodeMScopeName = DhcpOemToUnicode( CommandArgv[1], NULL );
  3144. DhcpAssert( UnicodeMScopeName != NULL );
  3145. UnicodeMScopeDesc = DhcpOemToUnicode( CommandArgv[2], NULL );
  3146. DhcpAssert( UnicodeMScopeName != NULL );
  3147. ExpiryTimeInHours = atoi(CommandArgv[3]);
  3148. LangTag = GetLangTag();
  3149. UnicodeLangTag = DhcpOemToUnicode(LangTag, NULL);
  3150. DhcpAssert(UnicodeLangTag);
  3151. MScopeInfo.MScopeName = UnicodeMScopeName;
  3152. MScopeInfo.MScopeId = MScopeId;
  3153. MScopeInfo.MScopeComment = UnicodeMScopeDesc;
  3154. MScopeInfo.PrimaryHost.IpAddress =
  3155. DhcpDottedStringToIpAddress(GlobalServerIpAddressAnsiString);
  3156. MScopeInfo.PrimaryHost.NetBiosName = NULL;
  3157. MScopeInfo.PrimaryHost.HostName = NULL;
  3158. MScopeInfo.MScopeState = DhcpSubnetEnabled;
  3159. MScopeInfo.MScopeFlags = 0;
  3160. MScopeInfo.MScopeAddressPolicy = 0;
  3161. MScopeInfo.TTL = 255;
  3162. MScopeInfo.LangTag = UnicodeLangTag;
  3163. MScopeInfo.ExpiryTime = DhcpCalculateTime(ExpiryTimeInHours*60*60);
  3164. Error = DhcpSetMScopeInfo(
  3165. GlobalServerIpAddressUnicodeString,
  3166. UnicodeMScopeName,
  3167. &MScopeInfo,
  3168. TRUE); // new scope
  3169. Cleanup:
  3170. if( UnicodeMScopeName != NULL ) {
  3171. DhcpFreeMemory( UnicodeMScopeName );
  3172. }
  3173. if( UnicodeMScopeDesc != NULL ) {
  3174. DhcpFreeMemory( UnicodeMScopeDesc );
  3175. }
  3176. return( Error );
  3177. }
  3178. DWORD
  3179. ProcessDeleteMScope(
  3180. DWORD CommandArgc,
  3181. LPSTR *CommandArgv
  3182. )
  3183. {
  3184. DWORD Error;
  3185. DHCP_MSCOPE_INFO MScopeInfo;
  3186. LPWSTR UnicodeMScopeName = NULL;
  3187. //
  3188. // Expected Parameters are : <MScopeName>
  3189. //
  3190. if( CommandArgc < 1 ) {
  3191. printf("usage:DhcpCmd SrvIpAddress DeleteMScope [Command Parameters].\n"
  3192. "<Command Parameters> - <MScopeName>.\n" );
  3193. Error = ERROR_SUCCESS;
  3194. goto Cleanup;
  3195. }
  3196. UnicodeMScopeName = DhcpOemToUnicode( CommandArgv[0], NULL );
  3197. DhcpAssert( UnicodeMScopeName != NULL );
  3198. Error = DhcpDeleteMScope(
  3199. GlobalServerIpAddressUnicodeString,
  3200. UnicodeMScopeName,
  3201. TRUE); // force flag
  3202. Cleanup:
  3203. if( UnicodeMScopeName != NULL ) {
  3204. DhcpFreeMemory( UnicodeMScopeName );
  3205. }
  3206. return( Error );
  3207. }
  3208. DWORD
  3209. ProcessAddMScopeIpRange(
  3210. DWORD CommandArgc,
  3211. LPSTR *CommandArgv
  3212. )
  3213. {
  3214. DWORD Error;
  3215. DHCP_IP_RANGE IpRange;
  3216. DHCP_SUBNET_ELEMENT_DATA_V4 Element;
  3217. LPWSTR UnicodeMScopeName = NULL;
  3218. //
  3219. // Expected Parameters are : <MScopeName IpRangeStart IpRangeEnd>
  3220. //
  3221. if( CommandArgc < 3 ) {
  3222. printf("usage:DhcpCmd SrvIpAddress AddMScopeIpRange [Command Parameters].\n"
  3223. "<Command Parameters> - <MScopeName IpRangeStart IpRangeEnd>.\n" );
  3224. return( ERROR_SUCCESS );
  3225. }
  3226. UnicodeMScopeName = DhcpOemToUnicode( CommandArgv[0], NULL );
  3227. DhcpAssert( UnicodeMScopeName != NULL );
  3228. IpRange.StartAddress = DhcpDottedStringToIpAddress(CommandArgv[1]);
  3229. IpRange.EndAddress = DhcpDottedStringToIpAddress(CommandArgv[2]);
  3230. Element.ElementType = DhcpIpRanges;
  3231. Element.Element.IpRange = &IpRange;
  3232. Error = DhcpAddMScopeElement(
  3233. GlobalServerIpAddressUnicodeString,
  3234. UnicodeMScopeName,
  3235. &Element );
  3236. if( UnicodeMScopeName != NULL ) DhcpFreeMemory( UnicodeMScopeName );
  3237. return( Error );
  3238. }
  3239. DWORD
  3240. ProcessReconcileMScope(
  3241. DWORD CommandArgc,
  3242. LPSTR *CommandArgv
  3243. )
  3244. {
  3245. DWORD Error;
  3246. LPWSTR UnicodeMScopeName = NULL;
  3247. LPDHCP_SCAN_LIST ScanList = NULL;
  3248. //
  3249. // Expected Parameters are : <MScopeName>
  3250. //
  3251. if( CommandArgc < 1 ) {
  3252. printf("usage:DhcpCmd SrvIpAddress ReconcileMScope [Command Parameters].\n"
  3253. "<Command Parameters> - <MScopeName>.\n" );
  3254. return( ERROR_SUCCESS );
  3255. }
  3256. UnicodeMScopeName = DhcpOemToUnicode( CommandArgv[0], NULL );
  3257. DhcpAssert( UnicodeMScopeName != NULL );
  3258. Error = DhcpScanMDatabase(
  3259. GlobalServerIpAddressUnicodeString,
  3260. UnicodeMScopeName,
  3261. TRUE, // fix bad entries.
  3262. &ScanList );
  3263. if( UnicodeMScopeName != NULL ) DhcpFreeMemory( UnicodeMScopeName );
  3264. if (ScanList) DhcpRpcFreeMemory( ScanList );
  3265. return( Error );
  3266. }
  3267. VOID
  3268. PrintMClientInfo(
  3269. LPDHCP_MCLIENT_INFO ClientInfo
  3270. )
  3271. {
  3272. DWORD i;
  3273. DWORD DataLength;
  3274. LPBYTE Data;
  3275. SYSTEMTIME SystemTime;
  3276. FILETIME LocalTime;
  3277. char *szClientType;
  3278. printf("ClientInfo :\n");
  3279. printf("\tIP Address = %s.\n",
  3280. DhcpIpAddressToDottedString(ClientInfo->ClientIpAddress));
  3281. printf("\tMScopeId = %lx.\n",
  3282. ClientInfo->MScopeId);
  3283. DataLength = ClientInfo->ClientId.DataLength;
  3284. Data = ClientInfo->ClientId.Data;
  3285. printf("\tClient Hardware Address = ");
  3286. for( i = 0; i < DataLength; i++ ) {
  3287. if( (i+1) < DataLength ) {
  3288. printf("%.2lx-", (DWORD)Data[i]);
  3289. }
  3290. else {
  3291. printf("%.2lx", (DWORD)Data[i]);
  3292. }
  3293. }
  3294. printf(".\n");
  3295. printf("\tName = %ws.\n", ClientInfo->ClientName);
  3296. printf("\tStarts = ");
  3297. if ( ClientInfo->ClientLeaseStarts.dwLowDateTime ==
  3298. DHCP_DATE_TIME_INFINIT_LOW &&
  3299. ClientInfo->ClientLeaseStarts.dwHighDateTime ==
  3300. DHCP_DATE_TIME_INFINIT_HIGH )
  3301. {
  3302. printf( "Never (lease duration is infinite.)\n" );
  3303. }
  3304. else if( FileTimeToLocalFileTime(
  3305. (FILETIME *)(&ClientInfo->ClientLeaseStarts),
  3306. &LocalTime) ) {
  3307. if( FileTimeToSystemTime( &LocalTime, &SystemTime ) ) {
  3308. printf( "%02u/%02u/%02u %02u:%02u:%02u.\n",
  3309. SystemTime.wMonth,
  3310. SystemTime.wDay,
  3311. SystemTime.wYear,
  3312. SystemTime.wHour,
  3313. SystemTime.wMinute,
  3314. SystemTime.wSecond );
  3315. }
  3316. else {
  3317. printf( "Can't convert time, %ld.\n", GetLastError() );
  3318. }
  3319. }
  3320. else {
  3321. printf( "Can't convert time, %ld.\n", GetLastError() );
  3322. }
  3323. printf("\tExpires = ");
  3324. if ( ClientInfo->ClientLeaseEnds.dwLowDateTime ==
  3325. DHCP_DATE_TIME_INFINIT_LOW &&
  3326. ClientInfo->ClientLeaseEnds.dwHighDateTime ==
  3327. DHCP_DATE_TIME_INFINIT_HIGH )
  3328. {
  3329. printf( "Never (lease duration is infinite.)\n" );
  3330. }
  3331. else if( FileTimeToLocalFileTime(
  3332. (FILETIME *)(&ClientInfo->ClientLeaseEnds),
  3333. &LocalTime) ) {
  3334. if( FileTimeToSystemTime( &LocalTime, &SystemTime ) ) {
  3335. printf( "%02u/%02u/%02u %02u:%02u:%02u.\n",
  3336. SystemTime.wMonth,
  3337. SystemTime.wDay,
  3338. SystemTime.wYear,
  3339. SystemTime.wHour,
  3340. SystemTime.wMinute,
  3341. SystemTime.wSecond );
  3342. }
  3343. else {
  3344. printf( "Can't convert time, %ld.\n", GetLastError() );
  3345. }
  3346. }
  3347. else {
  3348. printf( "Can't convert time, %ld.\n", GetLastError() );
  3349. }
  3350. printf("\tOwner Host IP Address = %s.\n",
  3351. DhcpIpAddressToDottedString(ClientInfo->OwnerHost.IpAddress));
  3352. printf("\tOwner Host NetBios Name = %ws.\n",
  3353. ClientInfo->OwnerHost.NetBiosName );
  3354. printf("\tOwner Host Name = %ws.\n",
  3355. ClientInfo->OwnerHost.HostName );
  3356. printf("\tState = %0x\n", ClientInfo->AddressState );
  3357. }
  3358. VOID
  3359. PrintMClientInfoShort(
  3360. LPDHCP_MCLIENT_INFO ClientInfo
  3361. )
  3362. {
  3363. SYSTEMTIME SystemTime;
  3364. FILETIME LocalTime;
  3365. printf("%ld\t %- 16.16s %- 16.16ws ",
  3366. GlobalClientCount++,
  3367. DhcpIpAddressToDottedString(ClientInfo->ClientIpAddress),
  3368. ClientInfo->ClientName
  3369. );
  3370. if ( ClientInfo->ClientLeaseEnds.dwLowDateTime ==
  3371. DHCP_DATE_TIME_INFINIT_LOW &&
  3372. ClientInfo->ClientLeaseEnds.dwHighDateTime ==
  3373. DHCP_DATE_TIME_INFINIT_HIGH )
  3374. {
  3375. printf( "Never (lease duration is infinite.)\n" );
  3376. }
  3377. else if( FileTimeToLocalFileTime(
  3378. (FILETIME *)(&ClientInfo->ClientLeaseEnds),
  3379. &LocalTime) ) {
  3380. if( FileTimeToSystemTime( &LocalTime, &SystemTime ) ) {
  3381. printf( "%02u/%02u/%02u %02u:%02u:%02u",
  3382. SystemTime.wMonth,
  3383. SystemTime.wDay,
  3384. SystemTime.wYear,
  3385. SystemTime.wHour,
  3386. SystemTime.wMinute,
  3387. SystemTime.wSecond );
  3388. }
  3389. else {
  3390. printf( "% 18.18s", "******************" );
  3391. }
  3392. }
  3393. else {
  3394. printf( "%.18s", "******************" );
  3395. }
  3396. printf( "\n" );
  3397. }
  3398. DWORD
  3399. ProcessEnumMScopeClients(
  3400. DWORD CommandArgc,
  3401. LPSTR *CommandArgv
  3402. )
  3403. {
  3404. DWORD Error;
  3405. DHCP_RESUME_HANDLE ResumeHandle = 0;
  3406. LPDHCP_MCLIENT_INFO_ARRAY ClientEnumInfo = NULL;
  3407. DWORD ClientsRead = 0;
  3408. DWORD ClientsTotal = 0;
  3409. DWORD i;
  3410. LPWSTR UnicodeMScopeName = NULL;
  3411. //
  3412. // Expected Parameters are : <MScopeNames>
  3413. //
  3414. if( CommandArgc < 1 ) {
  3415. printf("usage:DhcpCmd SrvIpAddress EnumClients [Command Parameters].\n"
  3416. "<Command Parameters> - <MScopeNames [-v | -h] >.\n" );
  3417. return( ERROR_SUCCESS );
  3418. }
  3419. UnicodeMScopeName = DhcpOemToUnicode( CommandArgv[0], NULL );
  3420. DhcpAssert( UnicodeMScopeName != NULL );
  3421. GlobalClientCount = 1;
  3422. for(;;) {
  3423. ClientEnumInfo = NULL;
  3424. Error = DhcpEnumMScopeClients(
  3425. GlobalServerIpAddressUnicodeString,
  3426. UnicodeMScopeName,
  3427. &ResumeHandle,
  3428. (DWORD)(-1),
  3429. &ClientEnumInfo,
  3430. &ClientsRead,
  3431. &ClientsTotal );
  3432. if( (Error != ERROR_SUCCESS) && (Error != ERROR_MORE_DATA) ) {
  3433. printf("DhcpEnumSubnetClients failed, %ld.\n", Error );
  3434. return( Error );
  3435. }
  3436. DhcpAssert( ClientEnumInfo != NULL );
  3437. DhcpAssert( ClientEnumInfo->NumElements == ClientsRead );
  3438. if( (CommandArgc > 1) && CommandArgv[1][0] == '-') {
  3439. switch (CommandArgv[1][1]) {
  3440. case 'h':
  3441. case 'H':
  3442. for( i = 0; i < ClientsRead; i++ ) {
  3443. PrintMClientInfoShort( ClientEnumInfo->Clients[i] );
  3444. }
  3445. break;
  3446. case 'V':
  3447. case 'v':
  3448. printf("Num Client info read = %ld.\n", ClientsRead );
  3449. printf("Total Client count = %ld.\n", ClientsTotal );
  3450. for( i = 0; i < ClientsRead; i++ ) {
  3451. PrintMClientInfo( ClientEnumInfo->Clients[i] );
  3452. }
  3453. break;
  3454. default:
  3455. for( i = 0; i < ClientsRead; i++ ) {
  3456. PrintMClientInfoShort( ClientEnumInfo->Clients[i] );
  3457. }
  3458. break;
  3459. }
  3460. }
  3461. else {
  3462. for( i = 0; i < ClientsRead; i++ ) {
  3463. PrintMClientInfoShort( ClientEnumInfo->Clients[i] );
  3464. }
  3465. }
  3466. DhcpRpcFreeMemory( ClientEnumInfo );
  3467. if( Error != ERROR_MORE_DATA ) {
  3468. break;
  3469. }
  3470. }
  3471. return(Error);
  3472. }
  3473. DWORD
  3474. ProcessEnumMScopes(
  3475. DWORD CommandArgc,
  3476. LPSTR *CommandArgv
  3477. )
  3478. {
  3479. DWORD Error;
  3480. DHCP_RESUME_HANDLE ResumeHandle = 0;
  3481. LPDHCP_MSCOPE_TABLE MScopeTable = NULL;
  3482. DWORD ClientsRead = 0;
  3483. DWORD ClientsTotal = 0;
  3484. DWORD i;
  3485. LPWSTR UnicodeMScopeName = NULL;
  3486. for(;;) {
  3487. MScopeTable = NULL;
  3488. Error = DhcpEnumMScopes(
  3489. GlobalServerIpAddressUnicodeString,
  3490. &ResumeHandle,
  3491. (DWORD)(-1),
  3492. &MScopeTable,
  3493. &ClientsRead,
  3494. &ClientsTotal );
  3495. if( (Error != ERROR_SUCCESS) && (Error != ERROR_MORE_DATA) ) {
  3496. printf("DhcpEnumSubnetClients failed, %ld.\n", Error );
  3497. return( Error );
  3498. }
  3499. DhcpAssert( MScopeTable != NULL );
  3500. DhcpAssert( MScopeTable->NumElements == ClientsRead );
  3501. printf("Total Client count = %ld.\n", ClientsTotal );
  3502. for( i = 0; i < ClientsRead; i++ ) {
  3503. printf("MScope %ws\n", MScopeTable->pMScopeNames[i] );
  3504. }
  3505. break;
  3506. DhcpRpcFreeMemory( MScopeTable );
  3507. if( Error != ERROR_MORE_DATA ) {
  3508. break;
  3509. }
  3510. }
  3511. return(Error);
  3512. }
  3513. DWORD
  3514. ProcessMCastMibCounts(
  3515. DWORD CommandArgc,
  3516. LPSTR *CommandArgv
  3517. )
  3518. {
  3519. DWORD Error;
  3520. LPDHCP_MCAST_MIB_INFO MibInfo = NULL;
  3521. DWORD i;
  3522. LPMSCOPE_MIB_INFO ScopeInfo;
  3523. SYSTEMTIME SystemTime;
  3524. FILETIME LocalTime;
  3525. Error = DhcpGetMCastMibInfo(
  3526. GlobalServerIpAddressUnicodeString,
  3527. &MibInfo );
  3528. if( Error != ERROR_SUCCESS ) {
  3529. return( Error );
  3530. }
  3531. DhcpAssert( MibInfo != NULL );
  3532. printf("Discovers = %d.\n", MibInfo->Discovers);
  3533. printf("Offers = %d.\n", MibInfo->Offers);
  3534. printf("Requests = %d.\n", MibInfo->Requests);
  3535. printf("Acks = %d.\n", MibInfo->Acks);
  3536. printf("Naks = %d.\n", MibInfo->Naks);
  3537. printf("Renews = %d.\n", MibInfo->Renews);
  3538. printf("Releases = %d.\n", MibInfo->Releases);
  3539. printf("ServerStartTime = ");
  3540. if( FileTimeToLocalFileTime(
  3541. (FILETIME *)(&MibInfo->ServerStartTime),
  3542. &LocalTime) ) {
  3543. if( FileTimeToSystemTime( &LocalTime, &SystemTime ) ) {
  3544. printf( "%02u/%02u/%02u %02u:%02u:%02u.\n",
  3545. SystemTime.wMonth,
  3546. SystemTime.wDay,
  3547. SystemTime.wYear,
  3548. SystemTime.wHour,
  3549. SystemTime.wMinute,
  3550. SystemTime.wSecond );
  3551. }
  3552. else {
  3553. printf( "Can't convert time, %ld.\n", GetLastError() );
  3554. }
  3555. }
  3556. else {
  3557. printf( "Can't convert time, %ld.\n", GetLastError() );
  3558. }
  3559. printf("Scopes = %d.\n", MibInfo->Scopes);
  3560. ScopeInfo = MibInfo->ScopeInfo;
  3561. for ( i = 0; i < MibInfo->Scopes; i++ ) {
  3562. printf("Scope Name = %ws.\n",
  3563. (ScopeInfo[i].MScopeName));
  3564. printf("\tNumAddressesInuse = %d.\n",
  3565. ScopeInfo[i].NumAddressesInuse );
  3566. printf("\tNumAddressesFree = %d.\n",
  3567. ScopeInfo[i].NumAddressesFree );
  3568. printf("\tNumPendingOffers = %d.\n",
  3569. ScopeInfo[i].NumPendingOffers );
  3570. }
  3571. DhcpRpcFreeMemory( MibInfo );
  3572. return( ERROR_SUCCESS );
  3573. }
  3574. DWORD
  3575. ProcessAddServer( // add a server to DS
  3576. IN DWORD CommandArgc,
  3577. IN LPSTR *CommandArgv
  3578. )
  3579. {
  3580. DWORD Err;
  3581. DWORD Address;
  3582. LPWSTR ServerName;
  3583. DHCP_SERVER_INFO Server;
  3584. // usage: AddServer <ServerName> <ServerIpAddress>
  3585. if( CommandArgc != 2 ) { // wrong usage
  3586. printf("usage:DhcpCmd SrvIpAddress AddServer <server-dns-name> <server-ip-address>\n");
  3587. return ERROR_SUCCESS;
  3588. }
  3589. if( GlobalNoDS ) {
  3590. Err = DhcpDsInit();
  3591. if( ERROR_SUCCESS != Err ) return Err;
  3592. }
  3593. ServerName = DhcpOemToUnicode( CommandArgv[0], NULL);
  3594. Address = (inet_addr(CommandArgv[1]));
  3595. printf("Adding server %ws,%s\n", ServerName, inet_ntoa(*(struct in_addr*)&Address));
  3596. Server.Version = 0;
  3597. Server.ServerName = ServerName;
  3598. Server.ServerAddress = htonl(Address);
  3599. Server.Flags = 0;
  3600. Server.State = 0;
  3601. Server.DsLocation = NULL;
  3602. Server.DsLocType = 0;
  3603. Err = DhcpAddServer(0, NULL, &Server, NULL, NULL);
  3604. DhcpFreeMemory(ServerName);
  3605. if( ERROR_SUCCESS != Err ) { // could not add the server
  3606. printf("DhcpAddServer failed %ld (0x%lx)\n", Err, Err);
  3607. }
  3608. if( GlobalNoDS ) DhcpDsCleanup();
  3609. return Err;
  3610. }
  3611. DWORD
  3612. ProcessDelServer( // delete a server from DS
  3613. IN DWORD CommandArgc,
  3614. IN LPSTR *CommandArgv
  3615. )
  3616. {
  3617. DWORD Err;
  3618. DWORD Address;
  3619. LPWSTR ServerName;
  3620. DHCP_SERVER_INFO Server;
  3621. // usage: DelServer <ServerName> <ServerIpAddress>
  3622. if( CommandArgc != 2 ) { // wrong usage
  3623. printf("usage:DhcpCmd SrvIpAddress DelServer <server-dns-name> <server-ip-address>\n");
  3624. return ERROR_SUCCESS;
  3625. }
  3626. if( GlobalNoDS ) {
  3627. Err = DhcpDsInit();
  3628. if( ERROR_SUCCESS != Err ) return Err;
  3629. }
  3630. ServerName = DhcpOemToUnicode( CommandArgv[0], NULL);
  3631. Address = (inet_addr(CommandArgv[1]));
  3632. printf("Deleting server %ws,%s\n", ServerName, inet_ntoa(*(struct in_addr*)&Address));
  3633. Server.Version = 0;
  3634. Server.ServerName = ServerName;
  3635. Server.ServerAddress = htonl(Address);
  3636. Server.Flags = 0;
  3637. Server.State = 0;
  3638. Server.DsLocation = NULL;
  3639. Server.DsLocType = 0;
  3640. Err = DhcpDeleteServer(0, NULL, &Server, NULL, NULL);
  3641. DhcpFreeMemory(ServerName);
  3642. if( ERROR_SUCCESS != Err ) { // could not add the server
  3643. printf("DhcpDeleteServer failed %ld (0x%lx)\n", Err, Err);
  3644. }
  3645. if( GlobalNoDS ) DhcpDsCleanup();
  3646. return Err;
  3647. }
  3648. VOID
  3649. PrintServerInfo( // print server information
  3650. IN LPDHCP_SERVER_INFO Server
  3651. )
  3652. {
  3653. DHCP_IP_ADDRESS ServerAddress = htonl(Server->ServerAddress);
  3654. printf("Server [%ws] Address [%s] Ds location: %ws\n",
  3655. Server->ServerName,
  3656. inet_ntoa(*(struct in_addr *)&ServerAddress),
  3657. Server->DsLocation? Server->DsLocation : L"<no-ds-location-available>"
  3658. );
  3659. }
  3660. VOID
  3661. PrintServerInfoArray( // print list of servers
  3662. IN LPDHCP_SERVER_INFO_ARRAY Servers
  3663. )
  3664. {
  3665. DWORD i;
  3666. printf("%ld Servers were found in the DS:\n", Servers->NumElements);
  3667. for( i = 0; i < Servers->NumElements; i ++ ) {
  3668. printf("\t");
  3669. PrintServerInfo(&Servers->Servers[i]);
  3670. }
  3671. printf("\n");
  3672. }
  3673. DWORD
  3674. ProcessEnumServers( // enumerate servers in DS.
  3675. IN DWORD CommandArgc, // ignored..
  3676. IN LPSTR *CommandArgv // ignored
  3677. )
  3678. {
  3679. DWORD Err;
  3680. LPDHCP_SERVER_INFO_ARRAY Servers;
  3681. if( GlobalNoDS ) {
  3682. Err = DhcpDsInit();
  3683. if( ERROR_SUCCESS != Err ) return Err;
  3684. }
  3685. Servers = NULL;
  3686. Err = DhcpEnumServers(0, NULL, &Servers, NULL, NULL);
  3687. if( ERROR_SUCCESS != Err ) {
  3688. printf("DhcpEnumServers failed %ld (0x%lx)\n", Err, Err);
  3689. if( GlobalNoDS ) DhcpDsCleanup();
  3690. return Err;
  3691. }
  3692. PrintServerInfoArray(Servers);
  3693. LocalFree(Servers);
  3694. if( GlobalNoDS ) DhcpDsCleanup();
  3695. return ERROR_SUCCESS;
  3696. }
  3697. DWORD
  3698. ProcessCreateClass( // create a new class
  3699. IN DWORD CommandArgc,
  3700. IN LPSTR *CommandArgv
  3701. )
  3702. {
  3703. DWORD Err;
  3704. DHCP_CLASS_INFO ClassInfo;
  3705. // usage: [/IsVendor] CreateClass ClassName ClassComment Ascii-Data-For-Class
  3706. if( CommandArgc != 3 ) { // wrong usage
  3707. printf("usage:DhcpCmd SrvIpAddress CreateClass [Command Parameters]\n");
  3708. printf("[Command Parameters] - ClassName ClassComment Ascii-Date-For-Class\n");
  3709. printf("/IsVendor option would cause this to be created as a vendor class.\n");
  3710. return ERROR_SUCCESS;
  3711. }
  3712. ClassInfo.ClassName = DhcpOemToUnicode(CommandArgv[0], NULL);
  3713. ClassInfo.ClassComment = DhcpOemToUnicode(CommandArgv[1], NULL);
  3714. ClassInfo.ClassDataLength = strlen(CommandArgv[2]);
  3715. ClassInfo.ClassData = (LPBYTE)CommandArgv[2];
  3716. ClassInfo.IsVendor = GlobalIsVendor;
  3717. ClassInfo.Flags = 0;
  3718. Err = DhcpCreateClass(
  3719. GlobalServerIpAddressUnicodeString,
  3720. 0,
  3721. &ClassInfo
  3722. );
  3723. DhcpFreeMemory(ClassInfo.ClassName);
  3724. DhcpFreeMemory(ClassInfo.ClassComment);
  3725. return Err;
  3726. }
  3727. DWORD
  3728. ProcessDeleteClass( // delete an existing class
  3729. IN DWORD CommandArgc,
  3730. IN LPSTR *CommandArgv
  3731. )
  3732. {
  3733. DWORD Err;
  3734. LPWSTR ClassName;
  3735. // usage: DeleteClass ClassName
  3736. if( CommandArgc != 1 ) {
  3737. printf("usage: DhcpCmd SrvIpAddress DeleteClass ClassName\n");
  3738. return ERROR_SUCCESS;
  3739. }
  3740. ClassName = DhcpOemToUnicode(CommandArgv[0], NULL);
  3741. Err = DhcpDeleteClass(
  3742. GlobalServerIpAddressUnicodeString,
  3743. 0,
  3744. ClassName
  3745. );
  3746. DhcpFreeMemory(ClassName);
  3747. return Err;
  3748. }
  3749. VOID
  3750. PrintClassInfo( // print info on a single class
  3751. IN LPDHCP_CLASS_INFO Class
  3752. )
  3753. {
  3754. DWORD i;
  3755. printf("Class [%ws]:\n\tComment: %ws\n\tFlags: 0x%lx\n\tIsVendor: %s\n",
  3756. Class->ClassName, Class->ClassComment, Class->Flags, Class->IsVendor?"TRUE":"FALSE");
  3757. printf("\tClassData: ");
  3758. for( i = 0; i < Class->ClassDataLength; i ++ )
  3759. printf("%02x ", Class->ClassData[i]);
  3760. printf("\n");
  3761. }
  3762. VOID
  3763. PrintClassInfoArray( // print array of classes
  3764. IN LPDHCP_CLASS_INFO_ARRAY Classes
  3765. )
  3766. {
  3767. DWORD i;
  3768. printf("NumClasses = %ld (0x%lx)\n", Classes->NumElements, Classes->NumElements);
  3769. for( i = 0; i < Classes->NumElements; i ++ )
  3770. PrintClassInfo(&Classes->Classes[i]);
  3771. }
  3772. DWORD
  3773. ProcessEnumClasses( // enumerate list of classes defined
  3774. IN DWORD CommandArgc,
  3775. IN LPSTR *CommandArgv
  3776. )
  3777. {
  3778. DWORD Err, nRead, nTotal;
  3779. DHCP_RESUME_HANDLE ResumeHandle;
  3780. LPDHCP_CLASS_INFO_ARRAY ClassInfoArray;
  3781. // usage: EnumClasses
  3782. ClassInfoArray = NULL;
  3783. ResumeHandle = 0;
  3784. Err = DhcpEnumClasses(
  3785. GlobalServerIpAddressUnicodeString,
  3786. 0,
  3787. &ResumeHandle,
  3788. 0xFFFFFFFF,
  3789. &ClassInfoArray,
  3790. &nRead,
  3791. &nTotal
  3792. );
  3793. if( ERROR_MORE_DATA == Err || ERROR_NO_MORE_ITEMS == Err ) {
  3794. Err = ERROR_SUCCESS;
  3795. }
  3796. if( ERROR_SUCCESS == Err ) {
  3797. PrintClassInfoArray(ClassInfoArray);
  3798. DhcpRpcFreeMemory(ClassInfoArray);
  3799. }
  3800. return Err;
  3801. }
  3802. LPSTR
  3803. AttribString(
  3804. IN ULONG AttribId
  3805. )
  3806. {
  3807. switch(AttribId) {
  3808. case DHCP_ATTRIB_BOOL_IS_ROGUE:
  3809. return "IsRogue";
  3810. case DHCP_ATTRIB_BOOL_IS_DYNBOOTP:
  3811. return "DynamicBootpEnabled" ;
  3812. case DHCP_ATTRIB_BOOL_IS_PART_OF_DSDC:
  3813. return "ServerPartOfDsEnabledDC" ;
  3814. default:
  3815. ;
  3816. }
  3817. return "UnknownAttribute";
  3818. }
  3819. VOID
  3820. PrintDhcpAttrib( // print a server attrib
  3821. IN LPDHCP_ATTRIB ServerAttrib
  3822. )
  3823. {
  3824. if( NULL == ServerAttrib ) return;
  3825. printf("Server Attrib %s [%ld]: ",
  3826. AttribString(ServerAttrib->DhcpAttribId),
  3827. ServerAttrib->DhcpAttribId );
  3828. switch( ServerAttrib->DhcpAttribType ) {
  3829. case DHCP_ATTRIB_TYPE_BOOL :
  3830. printf("%s\n", ServerAttrib->DhcpAttribBool? "TRUE" : "FALSE");
  3831. break;
  3832. case DHCP_ATTRIB_TYPE_ULONG:
  3833. printf("0x%lx\n", ServerAttrib->DhcpAttribUlong);
  3834. break;
  3835. default:
  3836. printf("unknown attrib type\n");
  3837. break;
  3838. }
  3839. }
  3840. DWORD
  3841. ProcessGetServerStatus( // what is the server status?
  3842. IN DWORD CommandArgc,
  3843. IN LPSTR *CommandArgv
  3844. )
  3845. {
  3846. DWORD Err, i;
  3847. LPDHCP_ATTRIB_ARRAY pDhcpAttribArr;
  3848. DHCP_ATTRIB_ID Attribs[] = {
  3849. DHCP_ATTRIB_BOOL_IS_ROGUE,
  3850. DHCP_ATTRIB_BOOL_IS_DYNBOOTP,
  3851. DHCP_ATTRIB_BOOL_IS_PART_OF_DSDC
  3852. };
  3853. pDhcpAttribArr = NULL;
  3854. Err = DhcpServerQueryAttributes(
  3855. GlobalServerIpAddressUnicodeString,
  3856. 0,
  3857. sizeof(Attribs)/sizeof(Attribs[0]),
  3858. Attribs,
  3859. &pDhcpAttribArr
  3860. );
  3861. if( ERROR_NOT_SUPPORTED == Err ) {
  3862. Err = ERROR_SUCCESS;
  3863. }
  3864. if( ERROR_SUCCESS != Err ) {
  3865. return Err;
  3866. }
  3867. printf("Supported Server Attributes:\n");
  3868. if( pDhcpAttribArr ) {
  3869. for( i = 0; i < pDhcpAttribArr->NumElements ; i ++ ) {
  3870. PrintDhcpAttrib(&pDhcpAttribArr->DhcpAttribs[i]);
  3871. }
  3872. DhcpRpcFreeMemory(pDhcpAttribArr);
  3873. }
  3874. return ERROR_SUCCESS;
  3875. }
  3876. DWORD
  3877. ProcessRetryAuthorization( // what is the server status?
  3878. IN DWORD CommandArgc,
  3879. IN LPSTR *CommandArgv
  3880. )
  3881. {
  3882. return DhcpServerRedoAuthorization(
  3883. GlobalServerIpAddressUnicodeString,
  3884. 0
  3885. );
  3886. }
  3887. DWORD
  3888. ProcessGetBindings(
  3889. IN DWORD CommandArgc,
  3890. IN LPSTR *CommandArgv
  3891. )
  3892. {
  3893. ULONG Error, i ;
  3894. LPDHCP_BIND_ELEMENT_ARRAY BindInfo = NULL;
  3895. Error = DhcpGetServerBindingInfo(
  3896. GlobalServerIpAddressUnicodeString,
  3897. 0,
  3898. &BindInfo
  3899. );
  3900. if( ERROR_SUCCESS != Error ) {
  3901. printf("Error: %ld (0x%lx)\n", Error, Error);
  3902. return Error;
  3903. }
  3904. for( i = 0; i < BindInfo->NumElements ; i ++ ) {
  3905. printf("%s \"%ws\"\n",
  3906. BindInfo->Elements[i].fBoundToDHCPServer ? "[BOUND] " : "[UNBOUND]" ,
  3907. BindInfo->Elements[i].IfDescription
  3908. );
  3909. }
  3910. DhcpRpcFreeMemory(BindInfo);
  3911. return ERROR_SUCCESS;
  3912. }
  3913. DWORD
  3914. ProcessSetBinding(
  3915. IN DWORD CommandArgc,
  3916. IN LPSTR *CommandArgv
  3917. )
  3918. {
  3919. ULONG Error, i ;
  3920. BOOL Bind;
  3921. LPDHCP_BIND_ELEMENT_ARRAY BindInfo = NULL;
  3922. LPWSTR AdapterName;
  3923. if( CommandArgc != 2 ) {
  3924. printf("usage: DhcpCmd SrvIpAddress SetBinding [BIND/UNBIND] AdapterName");
  3925. return ERROR_SUCCESS;
  3926. }
  3927. if( 0 == _stricmp(CommandArgv[0], "BIND") ) {
  3928. Bind = TRUE;
  3929. } else {
  3930. Bind = FALSE;
  3931. }
  3932. AdapterName = DhcpOemToUnicode(CommandArgv[1], NULL);
  3933. Error = DhcpGetServerBindingInfo(
  3934. GlobalServerIpAddressUnicodeString,
  3935. 0,
  3936. &BindInfo
  3937. );
  3938. if( ERROR_SUCCESS != Error ) {
  3939. printf("Error: %ld (0x%lx)\n", Error, Error);
  3940. return Error;
  3941. }
  3942. for( i = 0; i < BindInfo->NumElements ; i ++ ) {
  3943. if( 0 == _wcsicmp(BindInfo->Elements[i].IfDescription, AdapterName)) {
  3944. BindInfo->Elements[i].fBoundToDHCPServer = Bind;
  3945. break;
  3946. }
  3947. }
  3948. if( i == BindInfo->NumElements ) {
  3949. printf("Requested Adapter Name not present. \n"
  3950. "Use DhcpCmd SrvIpAddress GetBindings to view bindings.\n");
  3951. return ERROR_SUCCESS;
  3952. }
  3953. Error = DhcpSetServerBindingInfo(
  3954. GlobalServerIpAddressUnicodeString,
  3955. 0,
  3956. BindInfo
  3957. );
  3958. if( ERROR_SUCCESS != Error ) {
  3959. printf("Error: %ld (0x%lx)\n", Error, Error);
  3960. }
  3961. DhcpRpcFreeMemory(BindInfo);
  3962. return ERROR_SUCCESS;
  3963. }
  3964. #define CMD_OPT_INVALID 0
  3965. #define CMD_OPT_LPWSTR 1
  3966. #define CMD_OPT_BOOL 2
  3967. struct /* anonymous */ {
  3968. LPSTR CommandOptName;
  3969. DWORD CommandOptType;
  3970. LPVOID CommandOptStorage;
  3971. } CommandOpts[] = {
  3972. { "ClassName", CMD_OPT_LPWSTR, (LPVOID)&GlobalClassName },
  3973. { "VendorName", CMD_OPT_LPWSTR, (LPVOID)&GlobalVendorName },
  3974. { "IsVendor", CMD_OPT_BOOL, (LPVOID)&GlobalIsVendor },
  3975. { "NoRPC", CMD_OPT_BOOL, (LPVOID)&GlobalNoRPC },
  3976. { "NoDS", CMD_OPT_BOOL, (LPVOID)&GlobalNoDS },
  3977. { NULL, CMD_OPT_INVALID, NULL },
  3978. };
  3979. DWORD
  3980. ProcessOption( // process a given option
  3981. IN DWORD Index, // index into CommandOpts table
  3982. IN LPSTR Value // value passed for option
  3983. )
  3984. {
  3985. BOOL Val_BOOL;
  3986. LPWSTR Val_LPWSTR;
  3987. switch(CommandOpts[Index].CommandOptType ) { // see what type we need to convert to..
  3988. case CMD_OPT_BOOL:
  3989. if( NULL == Value || '\0' == *Value ) {
  3990. Val_BOOL = TRUE; // implicitly set value to TRUE
  3991. } else {
  3992. if( 0 == _stricmp(Value, "TRUE") ) { // explicitly setting TRUE
  3993. Val_BOOL = TRUE;
  3994. } else if( 0 == _stricmp(Value, "FALSE" ) ) {
  3995. Val_BOOL = FALSE; // explicitly setting it to FALSE
  3996. } else {
  3997. return ERROR_INVALID_PARAMETER; // unknown response..
  3998. }
  3999. }
  4000. *((LPBOOL)(CommandOpts[Index].CommandOptStorage)) = Val_BOOL;
  4001. break;
  4002. case CMD_OPT_LPWSTR:
  4003. if( NULL == Value ) {
  4004. Val_LPWSTR = NULL;
  4005. } else if( '\0' == *Value ) {
  4006. Val_LPWSTR = L"";
  4007. } else { // now convert this..
  4008. Val_LPWSTR = DhcpOemToUnicode(Value, NULL);
  4009. }
  4010. *((LPWSTR *)(CommandOpts[Index].CommandOptStorage)) = Val_LPWSTR;
  4011. break;
  4012. default:
  4013. return ERROR_CALL_NOT_IMPLEMENTED;
  4014. }
  4015. return ERROR_SUCCESS;
  4016. }
  4017. DWORD
  4018. ProcessOptions( // process all options..
  4019. IN OUT int *argc,
  4020. IN OUT LPSTR argv[]
  4021. )
  4022. {
  4023. DWORD Error;
  4024. int i, j, k, n;
  4025. LPSTR Arg, Val;
  4026. for( i = 1; i < *argc ; i ++ ) { // process each option
  4027. if( argv[i][0] != '/' && argv[i][0] != '-' ) {
  4028. continue; // not an option
  4029. }
  4030. Arg = argv[i]; // an option to process
  4031. Arg ++; // skip leading '/' or '-'
  4032. Val = strchr(Arg, ':'); // see if it is of form /Option:Value
  4033. if( Val ) { // yup!
  4034. *Val = '\0'; // terminate Arg..
  4035. Val++; // now Val points to value in /Option:Value
  4036. }
  4037. for( j = 0; CommandOpts[j].CommandOptName ; j ++ ) {
  4038. if( 0 == _stricmp(Arg, CommandOpts[j].CommandOptName) ) {
  4039. break; // found a match!
  4040. }
  4041. }
  4042. if( NULL == CommandOpts[j].CommandOptName ) {
  4043. if( Val ) Val[-1] = ':'; // give back the colon we stole..
  4044. continue;
  4045. }
  4046. for( k = i + 1; k < *argc ; k ++ ) { // remove this arg and slide the rest
  4047. argv[k-1] = argv[k];
  4048. }
  4049. i -- ; (*argc) --;
  4050. Error = ProcessOption( j, Val ); // now process it
  4051. if( ERROR_SUCCESS != Error ) { // ouch?
  4052. DhcpPrint((0xFFFF, "Could not process option: /%s:%s\n", Arg, Val));
  4053. return Error;
  4054. }
  4055. }
  4056. return ERROR_SUCCESS;
  4057. }
  4058. VOID
  4059. CleanupOptions(
  4060. VOID
  4061. )
  4062. {
  4063. DWORD i;
  4064. LPWSTR String;
  4065. for( i = 0; CommandOpts[i].CommandOptName ; i ++ ) {
  4066. switch(CommandOpts[i].CommandOptType ) {
  4067. case CMD_OPT_BOOL:
  4068. // nothing to free
  4069. break;
  4070. case CMD_OPT_LPWSTR:
  4071. // need to free string space used..
  4072. String = *((LPWSTR *)CommandOpts[i].CommandOptStorage);
  4073. if( NULL != String ) DhcpFreeMemory(String);
  4074. break;
  4075. }
  4076. }
  4077. // done!
  4078. }
  4079. #endif NT5
  4080. #ifdef NT5
  4081. #define OPTIONS_STRING "[Options]"
  4082. #else
  4083. #define OPTIONS_STRING
  4084. #endif
  4085. DWORD __cdecl
  4086. main(
  4087. int argc,
  4088. char **argv
  4089. )
  4090. {
  4091. DWORD Error, ThreadOptions;
  4092. COMMAND_CODE CommandCode;
  4093. DWORD CommandArgc;
  4094. LPSTR *CommandArgv;
  4095. INIT_DEBUG_HEAP( HEAPX_VERIFY );
  4096. Error = ERROR_SUCCESS;
  4097. #ifdef NT5
  4098. Error = ProcessOptions(&argc, argv);
  4099. #endif NT5
  4100. if( ERROR_SUCCESS != Error || argc < 3 ) {
  4101. printf("usage:DhcpCmd SrvIpAddress" OPTIONS_STRING "Command [Command Parameters].\n");
  4102. printf("Commands : \n");
  4103. PrintCommands();
  4104. #ifdef NT5
  4105. printf("Options: \n");
  4106. printf("\t/ClassName:<string> -- [default NULL] specify class name wherever applicable.\n");
  4107. printf("\t/VendorName:<string> -- [default NULL] specify vendor name wherever applicable.\n");
  4108. printf("\t/IsVendor:TRUE/FALSE -- [default FALSE] specify that option being referred as vendor.\n");
  4109. printf("\t/NoRPC:TRUE/FALSE -- [default FALSE] specify that no RPC calls should be made.\n");
  4110. printf("\t/NoDS:TRUE/FALSE -- [default TRUE] specify that no DS calls should be made.\n");
  4111. printf("\n\n");
  4112. #endif NT5
  4113. Error = ERROR_SUCCESS;
  4114. goto Cleanup;
  4115. }
  4116. GlobalServerIpAddressAnsiString = argv[1];
  4117. GlobalServerIpAddressUnicodeString =
  4118. DhcpOemToUnicode( GlobalServerIpAddressAnsiString, NULL );
  4119. if( GlobalServerIpAddressUnicodeString == NULL ) {
  4120. Error = ERROR_NOT_ENOUGH_MEMORY;
  4121. printf("Insufficient memory\n");
  4122. goto Cleanup;
  4123. }
  4124. GlobalServerIpAddressAnsiString = argv[1];
  4125. CommandCode = DecodeCommand( argv[2] );
  4126. if( CommandCode == UnknownCommand ) {
  4127. Error = ERROR_INVALID_PARAMETER;
  4128. printf("Unknown Command Specified.\n");
  4129. goto Cleanup;
  4130. }
  4131. if( FALSE == GlobalNoRPC ) {
  4132. Error = ProcessGetVersion( &g_dwMajor, &g_dwMinor );
  4133. if ( ERROR_SUCCESS != Error ) {
  4134. printf("Unable to determine server version.\n" );
  4135. goto Cleanup;
  4136. }
  4137. } else {
  4138. Error = ERROR_SUCCESS;
  4139. }
  4140. if ( FALSE == GlobalNoRPC && !IsValidServerVersion( g_dwMajor, g_dwMinor ) ) {
  4141. printf( "This version of %s works with Microsoft DHCP server"
  4142. " running on Windows NT Server version %d.%d or later.\n",
  4143. argv[0],
  4144. DHCPCMD_VERSION_MAJOR,
  4145. DHCPCMD_VERSION_MINOR
  4146. );
  4147. Error = ERROR_OLD_WIN_VERSION;
  4148. goto Cleanup;
  4149. }
  4150. CommandArgc = (DWORD)(argc - 3);
  4151. CommandArgv = &argv[3];
  4152. #ifdef NT5
  4153. Error = ERROR_SUCCESS;
  4154. if( FALSE == GlobalNoDS ) Error = DhcpDsInit();
  4155. if( ERROR_SUCCESS != Error && FALSE == GlobalNoDS ) {
  4156. printf("DhcpDsInit() failed %ld (0x%lx), but continuing ..\n", Error, Error);
  4157. printf("This indicates that either your machine is part of a work group\n");
  4158. printf("or that your DS is unreachable\n");
  4159. }
  4160. Error = ERROR_SUCCESS;
  4161. ThreadOptions = 0;
  4162. if( GlobalNoRPC ) ThreadOptions |= DHCP_FLAGS_DONT_DO_RPC;
  4163. if( GlobalNoDS ) ThreadOptions |= DHCP_FLAGS_DONT_ACCESS_DS;
  4164. DhcpSetThreadOptions(ThreadOptions, 0);
  4165. #endif NT5
  4166. switch( CommandCode ) {
  4167. case AddIpRange:
  4168. Error = ProcessAddIpRange( CommandArgc, CommandArgv );
  4169. break;
  4170. case RemoveIpRange:
  4171. Error = ProcessRemoveIpRange( CommandArgc, CommandArgv );
  4172. break;
  4173. #ifdef NT5
  4174. case EnumIpRanges:
  4175. Error = ProcessEnumIpRanges( CommandArgc, CommandArgv );
  4176. break;
  4177. #endif NT5
  4178. case AddReservedIp:
  4179. Error = ProcessAddReservedIp( CommandArgc, CommandArgv );
  4180. break;
  4181. case EnumClients:
  4182. Error = ProcessEnumClients( CommandArgc, CommandArgv );
  4183. break;
  4184. #ifdef NT5
  4185. case EnumClientsV5:
  4186. Error = ProcessEnumClientsV5( CommandArgc, CommandArgv );
  4187. break;
  4188. #endif NT5
  4189. case MibCounts:
  4190. Error = ProcessMibCounts( CommandArgc, CommandArgv );
  4191. break;
  4192. case ServerConfig:
  4193. Error = ProcessServerConfig( CommandArgc, CommandArgv );
  4194. break;
  4195. case GetDhcpVersion:
  4196. Error = ProcessGetVersion( &g_dwMajor, &g_dwMinor );
  4197. break;
  4198. case SetSuperScope:
  4199. Error = ProcessSetSuperScope( CommandArgc, CommandArgv );
  4200. break;
  4201. case RemoveSubscope:
  4202. Error = ProcessRemoveSubscope( CommandArgc, CommandArgv );
  4203. break;
  4204. case DeleteSuperScope:
  4205. Error = ProcessDeleteSuperScope( CommandArgc, CommandArgv );
  4206. break;
  4207. case GetSuperScopeTable:
  4208. Error = ProcessGetSuperScopeTable( CommandArgc, CommandArgv );
  4209. break;
  4210. case CheckDB:
  4211. Error = ProcessCheckDB( CommandArgc, CommandArgv );
  4212. break;
  4213. case CreateSubnet:
  4214. Error = ProcessCreateSubnet( CommandArgc, CommandArgv );
  4215. break;
  4216. case DeleteSubnet:
  4217. Error = ProcessDeleteSubnet( CommandArgc, CommandArgv );
  4218. break;
  4219. case AddExcludeRange:
  4220. Error = ProcessAddExcludeRange( CommandArgc, CommandArgv );
  4221. break;
  4222. case RemoveReservedIp:
  4223. Error = ProcessRemoveReservedIp( CommandArgc, CommandArgv );
  4224. break;
  4225. case RemoveExcludeRange:
  4226. Error = ProcessRemoveExcludeRange( CommandArgc, CommandArgv );
  4227. break;
  4228. case SetSubnetState:
  4229. Error = ProcessSetSubnetState( CommandArgc, CommandArgv );
  4230. break;
  4231. case CreateOption:
  4232. Error = ProcessCreateOption( CommandArgc, CommandArgv );
  4233. break;
  4234. case DeleteOption:
  4235. Error = ProcessDeleteOption( CommandArgc, CommandArgv );
  4236. break;
  4237. case SetGlobalOptionValue:
  4238. Error = ProcessSetGlobalOptionValue( CommandArgc, CommandArgv );
  4239. break;
  4240. case SetGlobalOptionValues:
  4241. Error = ProcessSetGlobalOptionValues( CommandArgc, CommandArgv );
  4242. break;
  4243. case RemoveGlobalOptionValue:
  4244. Error = ProcessRemoveGlobalOptionValue( CommandArgc, CommandArgv );
  4245. break;
  4246. case SetSubnetOptionValue:
  4247. Error = ProcessSetSubnetOptionValue( CommandArgc, CommandArgv );
  4248. break;
  4249. case RemoveSubnetOptionValue:
  4250. Error = ProcessRemoveSubnetOptionValue( CommandArgc, CommandArgv );
  4251. break;
  4252. case SetReservedOptionValue:
  4253. Error = ProcessSetReservedOptionValue( CommandArgc, CommandArgv );
  4254. break;
  4255. case RemoveReservedOptionValue:
  4256. Error = ProcessRemoveReservedOptionValue( CommandArgc, CommandArgv );
  4257. break;
  4258. case EnumOptions:
  4259. Error = ProcessEnumOptions( CommandArgc, CommandArgv );
  4260. break;
  4261. #ifdef NT5
  4262. case GetAllOptions:
  4263. Error = ProcessGetAllOptions( CommandArgc, CommandArgv );
  4264. break;
  4265. case GetAllOptionValues:
  4266. Error = ProcessGetAllOptionValues( CommandArgc, CommandArgv );
  4267. break;
  4268. case CreateMScope:
  4269. Error = ProcessCreateMScope( CommandArgc, CommandArgv );
  4270. break;
  4271. case DeleteMScope:
  4272. Error = ProcessDeleteMScope( CommandArgc, CommandArgv );
  4273. break;
  4274. case AddMScopeRange:
  4275. Error = ProcessAddMScopeIpRange( CommandArgc, CommandArgv );
  4276. break;
  4277. case EnumMScopeClients:
  4278. Error = ProcessEnumMScopeClients( CommandArgc, CommandArgv );
  4279. break;
  4280. case ReconcileMScope:
  4281. Error = ProcessReconcileMScope( CommandArgc, CommandArgv );
  4282. break;
  4283. case EnumMScopes:
  4284. Error = ProcessEnumMScopes( CommandArgc, CommandArgv );
  4285. break;
  4286. case MCastMibCounts:
  4287. Error = ProcessMCastMibCounts( CommandArgc, CommandArgv );
  4288. break;
  4289. case EnumServers:
  4290. Error = ProcessEnumServers( CommandArgc, CommandArgv );
  4291. break;
  4292. case AddServer:
  4293. Error = ProcessAddServer( CommandArgc, CommandArgv );
  4294. break;
  4295. case DelServer:
  4296. Error = ProcessDelServer( CommandArgc, CommandArgv );
  4297. break;
  4298. case CreateClass:
  4299. Error = ProcessCreateClass( CommandArgc, CommandArgv );
  4300. break;
  4301. case DeleteClass:
  4302. Error = ProcessDeleteClass( CommandArgc, CommandArgv );
  4303. break;
  4304. case EnumClasses:
  4305. Error = ProcessEnumClasses( CommandArgc, CommandArgv );
  4306. break;
  4307. case GetServerStatus:
  4308. Error = ProcessGetServerStatus( CommandArgc, CommandArgv );
  4309. break;
  4310. case RetryAuthorization:
  4311. Error = ProcessRetryAuthorization(CommandArgc, CommandArgv);
  4312. break;
  4313. case DeleteBadClients:
  4314. Error = ProcessDeleteBadClients(CommandArgc, CommandArgv);
  4315. break;
  4316. case DeleteClient:
  4317. Error = ProcessDeleteClient(CommandArgc, CommandArgv);
  4318. break;
  4319. case GetBindings:
  4320. Error = ProcessGetBindings(CommandArgc, CommandArgv);
  4321. break;
  4322. case SetBinding:
  4323. Error = ProcessSetBinding(CommandArgc, CommandArgv);
  4324. break;
  4325. #endif NT5
  4326. case UnknownCommand:
  4327. default:
  4328. DhcpAssert( FALSE );
  4329. Error = ERROR_INVALID_PARAMETER;
  4330. printf("Unknown Command Specified.\n");
  4331. goto Cleanup;
  4332. }
  4333. Cleanup:
  4334. #ifdef NT5
  4335. DhcpDsCleanup();
  4336. #endif NT5
  4337. if( GlobalServerIpAddressUnicodeString != NULL ) {
  4338. DhcpFreeMemory( GlobalServerIpAddressUnicodeString );
  4339. }
  4340. #ifdef NT5
  4341. CleanupOptions();
  4342. #endif NT5
  4343. if( Error != ERROR_SUCCESS ) {
  4344. printf("Command failed, %ld.\n", Error );
  4345. return(1);
  4346. }
  4347. UNINIT_DEBUG_HEAP();
  4348. printf("Command successfully completed.\n");
  4349. return(0);
  4350. }
  4351. //================================================================================
  4352. // end of file
  4353. //================================================================================