Source code of Windows XP (NT5)
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.

5057 lines
104 KiB

  1. /*++
  2. Copyright (c) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. dnsup.c
  5. Abstract:
  6. Domain Name System (DNS) Update Client
  7. Main program.
  8. Author:
  9. Jim Gilroy (jamesg) October, 1996
  10. Environment:
  11. User Mode - Win32
  12. Revision History:
  13. --*/
  14. #include "..\dnsapi\local.h"
  15. #if 0
  16. #include <windows.h>
  17. #include <winsock2.h>
  18. #include <stdlib.h>
  19. #include <stdio.h> // printf()
  20. #include <string.h> // strtoul()
  21. #include <windns.h>
  22. #include <dnsapi.h>
  23. #include "dnslib.h"
  24. #include "..\resolver\idl\resrpc.h"
  25. #include "dnsapip.h"
  26. #include "dnslibp.h"
  27. #endif
  28. #include "svcguid.h" // RnR guids
  29. // Use dnslib memory routines
  30. #if 0
  31. #define ALLOCATE_HEAP(iSize) Dns_Alloc(iSize)
  32. #define ALLOCATE_HEAP_ZERO(iSize) Dns_AllocZero(iSize)
  33. #define REALLOCATE_HEAP(pMem,iSize) Dns_Realloc((pMem),(iSize))
  34. #define FREE_HEAP(pMem) Dns_Free(pMem)
  35. #endif
  36. // Debug flag
  37. DWORD LocalDebugFlag;
  38. //
  39. // Printing
  40. //
  41. #define dnsup_PrintRoutine ((PRINT_ROUTINE) fprintf)
  42. #define dnsup_PrintContext ((PPRINT_CONTEXT) stdout)
  43. //
  44. // Special names and buffers
  45. //
  46. PCHAR SingleLongName = "longname";
  47. CHAR SeLongName[] = "longname";
  48. PCHAR LongName = ( "longname"
  49. ".label22222222222222222222222222222222222222222222222222"
  50. ".label33333333333333333333333333333333333333333333333333"
  51. ".label44444444444444444444444444444444444444444444444444"
  52. ".label55555555555555555555555555555555555555555555555555"
  53. ".label66666666666666666666666666666666666666666666666666.");
  54. #define LONG_LABEL_NAME ("longlabel" \
  55. ".longlabel2222222222222222222222222222222222222222222222222222222222")
  56. CHAR NameBuffer[ DNS_MAX_NAME_BUFFER_LENGTH ];
  57. CHAR AddressBuffer[ sizeof(DNS_IP6_ADDRESS) ];
  58. //
  59. // Quit or Exit status
  60. //
  61. #define ERROR_DNSUP_QUIT ((DNS_STATUS)(0x87654321))
  62. //
  63. // Command table setup
  64. //
  65. typedef DNS_STATUS (* COMMAND_FUNCTION)( DWORD Argc, CHAR** Argv);
  66. typedef struct _COMMAND_INFO
  67. {
  68. PSTR pszCommandName;
  69. PSTR pszDescription;
  70. COMMAND_FUNCTION pCommandFunction;
  71. }
  72. COMMAND_INFO, *LPCOMMAND_INFO;
  73. //
  74. // Note, command table is at bottom of file to
  75. // avoid need for prototyping all the functions
  76. //
  77. extern COMMAND_INFO GlobalCommandInfo[];
  78. COMMAND_FUNCTION
  79. GetCommandFunction(
  80. IN PSTR pszCommandName
  81. )
  82. {
  83. DWORD i;
  84. //
  85. // find command in list matching string
  86. //
  87. i = 0;
  88. while( GlobalCommandInfo[i].pszCommandName )
  89. {
  90. if( _stricmp(
  91. pszCommandName,
  92. GlobalCommandInfo[i].pszCommandName ) == 0 )
  93. {
  94. return( GlobalCommandInfo[i].pCommandFunction );
  95. }
  96. i++;
  97. }
  98. return( NULL );
  99. }
  100. //
  101. // Print utils
  102. //
  103. VOID
  104. PrintCommands(
  105. VOID
  106. )
  107. {
  108. DWORD i;
  109. //
  110. // print all commands in list
  111. //
  112. i = 0;
  113. while( GlobalCommandInfo[i].pszCommandName )
  114. {
  115. printf(
  116. " %10s (%s)\n",
  117. GlobalCommandInfo[i].pszCommandName,
  118. GlobalCommandInfo[i].pszDescription );
  119. i++;
  120. }
  121. }
  122. VOID
  123. PrintDnsQueryFlags(
  124. VOID
  125. )
  126. {
  127. DWORD i;
  128. //
  129. // print query flags
  130. //
  131. printf(
  132. "DNS Query flags:\n"
  133. "\tDNS_QUERY_STANDARD = 0x%x\n"
  134. "\tDNS_QUERY_ACCEPT_PARTIAL_UDP = 0x%x\n"
  135. "\tDNS_QUERY_USE_TCP_ONLY = 0x%x\n"
  136. "\tDNS_QUERY_NO_RECURSION = 0x%x\n"
  137. "\tDNS_QUERY_BYPASS_CACHE = 0x%x\n"
  138. "\tDNS_QUERY_NO_WIRE_QUERY = 0x%x\n"
  139. "\tDNS_QUERY_NO_HOSTS_FILE = 0x%x\n"
  140. "\tDNS_QUERY_NO_LOCAL_NAME = 0x%x\n",
  141. DNS_QUERY_STANDARD ,
  142. DNS_QUERY_ACCEPT_PARTIAL_UDP ,
  143. DNS_QUERY_USE_TCP_ONLY ,
  144. DNS_QUERY_NO_RECURSION ,
  145. DNS_QUERY_BYPASS_CACHE ,
  146. DNS_QUERY_NO_WIRE_QUERY ,
  147. DNS_QUERY_NO_HOSTS_FILE ,
  148. DNS_QUERY_NO_LOCAL_NAME
  149. );
  150. }
  151. //
  152. // Optional DNS server list to use
  153. //
  154. // Overides default list on this client for some commands
  155. //
  156. PIP_ARRAY pDnsServerArray = NULL;
  157. DNS_STATUS
  158. readNameServers(
  159. IN PIP_ARRAY * ppIpServers,
  160. IN DWORD * pArgc,
  161. IN PSTR ** pArgv
  162. )
  163. {
  164. DWORD argc = *pArgc;
  165. PCHAR * argv = *pArgv;
  166. PCHAR * startArgv;
  167. PCHAR arg;
  168. CHAR ch;
  169. IP_ADDRESS ipserver;
  170. PIP_ARRAY aipservers = NULL;
  171. DWORD countServers = 0;
  172. DWORD i;
  173. //
  174. // -n / -N denotes DNS server
  175. // server IP immediate follows (in same arg)
  176. //
  177. startArgv = argv;
  178. while ( argc )
  179. {
  180. arg = argv[0];
  181. if ( '-' == *arg++ )
  182. {
  183. ch = *arg++;
  184. if ( ch == 'n' || ch == 'N' )
  185. {
  186. countServers++;
  187. argc--;
  188. argv++;
  189. continue;
  190. }
  191. }
  192. break;
  193. }
  194. //
  195. // found servers
  196. // - allocate IP array
  197. // - parse servers into it
  198. // - reset callers Argc, Argv
  199. //
  200. if ( countServers )
  201. {
  202. *pArgc = argc;
  203. *pArgv = argv;
  204. argv = startArgv;
  205. aipservers = DnsCreateIpArray( countServers );
  206. if ( ! aipservers )
  207. {
  208. return( ERROR_OUTOFMEMORY );
  209. }
  210. for (i=0; i<(INT)countServers; i++)
  211. {
  212. arg = (*argv++) + 2;
  213. if ( *arg == '.' )
  214. {
  215. arg = "127.0.0.1";
  216. }
  217. ipserver = inet_addr( arg );
  218. if ( ipserver == INADDR_NONE )
  219. {
  220. printf( "ERROR: name server IP (in arg %s) is bogus\n", arg );
  221. return( ERROR_INVALID_PARAMETER );
  222. }
  223. IF_DNSDBG( INIT )
  224. {
  225. DNS_PRINT((
  226. "Read name server address from arg %s.\n",
  227. arg ));
  228. }
  229. aipservers->AddrArray[i] = ipserver;
  230. }
  231. DnsDbg_IpArray(
  232. "Name servers to register with\n",
  233. NULL,
  234. aipservers );
  235. }
  236. *ppIpServers = aipservers;
  237. return( ERROR_SUCCESS );
  238. }
  239. DNS_STATUS
  240. ProcessCommandLine(
  241. IN INT Argc,
  242. IN CHAR ** Argv
  243. )
  244. /*++
  245. Routine Description:
  246. Process command in Argc\Argv form.
  247. Arguments:
  248. Argc -- arg count
  249. Argv -- argument list
  250. Argv[0] -- dnsup
  251. Argv[1] -- Command to execute
  252. Argv[2...] -- arguments to command
  253. Return Value:
  254. Return from the desired command.
  255. Usually a pass through of the return code from DNS Update API call.
  256. --*/
  257. {
  258. DNS_STATUS status;
  259. COMMAND_FUNCTION pcommandFunction;
  260. PCHAR pcommand;
  261. if ( Argc < 1 )
  262. {
  263. goto Usage;
  264. }
  265. DNS_PRINT(( "Argc = %d\n", Argc ));
  266. //
  267. // check for server list
  268. //
  269. status = readNameServers(
  270. & pDnsServerArray,
  271. & Argc,
  272. & Argv );
  273. if ( status != ERROR_SUCCESS )
  274. {
  275. goto Usage;
  276. }
  277. //
  278. // next param is command
  279. // - optionally decorated with leading "-"
  280. //
  281. if ( Argc < 1 )
  282. {
  283. goto Usage;
  284. }
  285. pcommand = Argv[0];
  286. if ( *pcommand == '-' )
  287. {
  288. pcommand++;
  289. }
  290. pcommandFunction = GetCommandFunction( pcommand );
  291. if ( ! pcommandFunction )
  292. {
  293. status = ERROR_INVALID_PARAMETER;
  294. printf( "Unknown Command Specified -- type dnsup -?.\n" );
  295. goto Usage;
  296. }
  297. //
  298. // dispatch to processor for this command
  299. // - skip over command argv
  300. Argc--;
  301. Argv++;
  302. status = pcommandFunction( Argc, Argv );
  303. if ( status == ERROR_SUCCESS ||
  304. status == ERROR_DNSUP_QUIT )
  305. {
  306. printf( "Command successfully completed.\n" );
  307. }
  308. else
  309. {
  310. printf( "Command failed, %d (%ul)\n", status, status );
  311. }
  312. return( status );
  313. Usage:
  314. printf(
  315. "DnsUp command line:\n"
  316. "\t[-n<Server IP List>] -<Command> [Command Parameters].\n"
  317. "\t<Server IP List> is a list of one or more DNS server IP addresses\n"
  318. "\t\toverriding the default list on this client\n"
  319. "Commands:\n"
  320. );
  321. PrintCommands();
  322. return( ERROR_INVALID_PARAMETER );
  323. }
  324. VOID
  325. InteractiveLoop(
  326. VOID
  327. )
  328. /*++
  329. Routine Description:
  330. Interactive loop.
  331. Arguments:
  332. None
  333. Return Value:
  334. None
  335. --*/
  336. {
  337. #define MAX_ARG_COUNT 50
  338. DNS_STATUS status;
  339. INT argc;
  340. CHAR * argv[ MAX_ARG_COUNT ];
  341. CHAR lineBuffer[500];
  342. //
  343. // loop taking command params
  344. //
  345. while ( 1 )
  346. {
  347. printf( "\n> " );
  348. // read next command line
  349. gets( lineBuffer );
  350. argc = Dns_TokenizeString(
  351. lineBuffer,
  352. argv,
  353. MAX_ARG_COUNT );
  354. DNS_PRINT(( "argc = %d\n", argc ));
  355. IF_DNSDBG( INIT )
  356. {
  357. DnsDbg_Argv(
  358. NULL,
  359. argv,
  360. argc,
  361. FALSE // not unicode
  362. );
  363. }
  364. // process next command line
  365. status = ProcessCommandLine(
  366. argc,
  367. argv );
  368. if ( status == ERROR_DNSUP_QUIT )
  369. {
  370. break;
  371. }
  372. }
  373. }
  374. LONG
  375. __cdecl
  376. main(
  377. IN INT Argc,
  378. IN CHAR ** Argv
  379. )
  380. /*++
  381. Routine Description:
  382. DnsUp program entry point.
  383. Executes specified command corresponding to a DNS update API operation.
  384. Arguments:
  385. Argc -- arg count
  386. Argv -- argument list
  387. Argv[0] -- dnsup
  388. Argv[1] -- Command to execute
  389. Argv[2...] -- arguments to command
  390. Return Value:
  391. Zero if successful.
  392. 1 on error.
  393. --*/
  394. {
  395. DNS_STATUS status;
  396. //
  397. // initialize debug
  398. //
  399. Dns_StartDebugEx(
  400. 0, // no flag value
  401. "dnsup.flag", // read flag from file
  402. NULL, //&LocalDebugFlag,
  403. "dnsup.log", // log to file
  404. 0, // no wrap limit
  405. FALSE, // don't use existing global
  406. FALSE,
  407. TRUE // make this file global
  408. );
  409. DNS_PRINT(( "*pDnsDebugFlag = %08x\n", *pDnsDebugFlag ));
  410. //DNS_PRINT(( "LocalDebugFlag = %08x\n", LocalDebugFlag ));
  411. if ( Argc < 1 )
  412. {
  413. goto Usage;
  414. }
  415. DNS_PRINT(( "Argc = %d\n", Argc ));
  416. // skip "dnsup" argument
  417. Argc--;
  418. Argv++;
  419. //
  420. // interactive mode?
  421. // - if no command, just open interactively
  422. //
  423. if ( Argc == 0 )
  424. {
  425. InteractiveLoop();
  426. status = ERROR_SUCCESS;
  427. }
  428. else
  429. {
  430. status = ProcessCommandLine(
  431. Argc,
  432. Argv );
  433. }
  434. Dns_EndDebug();
  435. return( status != ERROR_SUCCESS );
  436. Usage:
  437. Dns_EndDebug();
  438. printf(
  439. "usage: DnsUp [-n<Server IP List>] -<Command> [Command Parameters].\n"
  440. "\t<Server IP List> is a list of one or more DNS server IP addresses\n"
  441. "\t\toverriding the default list on this client\n"
  442. "Commands:\n"
  443. );
  444. PrintCommands();
  445. return(1);
  446. }
  447. //
  448. // Command processing
  449. //
  450. PDNS_RECORD
  451. buildRecordList(
  452. IN DWORD Argc,
  453. IN PSTR * Argv
  454. )
  455. /*++
  456. Routine Description:
  457. Build record list from Argc \ Argv list.
  458. Arguments:
  459. Argc -- arg count
  460. Argv -- argument list
  461. Return Value:
  462. Ptr to list of records built.
  463. NULL on parsing error.
  464. --*/
  465. {
  466. PCHAR arg;
  467. PCHAR pszname;
  468. WORD type;
  469. BOOLEAN fadd;
  470. BOOLEAN section;
  471. CHAR ch;
  472. PDNS_RECORD prr;
  473. DNS_RRSET rrset;
  474. INT recordArgc;
  475. PCHAR * recordArgv;
  476. //
  477. // loop through remaining arguments building appropriate record types
  478. //
  479. DNS_RRSET_INIT( rrset );
  480. recordArgc = (-3);
  481. pszname = NULL;
  482. while ( Argc-- && (arg = *Argv++) )
  483. {
  484. //
  485. // if previous arg started new record, first parameter is name
  486. //
  487. if ( recordArgc == (-2) )
  488. {
  489. pszname = arg;
  490. type = 0;
  491. recordArgc++;
  492. continue;
  493. }
  494. //
  495. // second parameter is type
  496. //
  497. else if ( recordArgc == (-1) )
  498. {
  499. type = DnsRecordTypeForName( arg, 0 );
  500. if ( type == 0 )
  501. {
  502. printf( "ERROR: unknown type %s.\n", arg );
  503. goto Failed;
  504. }
  505. recordArgc++;
  506. continue;
  507. }
  508. //
  509. // check for end of existing record \ start of new record
  510. //
  511. ch = *arg;
  512. if ( ch == '+' || ch == '-' )
  513. {
  514. // build old record (if any)
  515. if ( pszname != NULL )
  516. {
  517. prr = Dns_RecordBuild_A(
  518. & rrset,
  519. pszname,
  520. type,
  521. fadd,
  522. section,
  523. recordArgc,
  524. recordArgv );
  525. if ( !prr )
  526. {
  527. printf( "ERROR: building record.\n" );
  528. goto Failed;
  529. }
  530. if ( fadd && section == DNSREC_UPDATE )
  531. {
  532. prr->dwTtl = 3600;
  533. }
  534. }
  535. fadd = ( ch == '+' );
  536. recordArgc = (-2);
  537. //
  538. // second character in new arg, indicates section
  539. // - for update ADD records use 3600 TTL instead of zero
  540. //
  541. ch = *++arg;
  542. if ( ch == 0 )
  543. {
  544. section = DNSREC_QUESTION;
  545. }
  546. else if ( ch == 'p' )
  547. {
  548. section = DNSREC_PREREQ;
  549. }
  550. else if ( ch == 'u' )
  551. {
  552. section = DNSREC_UPDATE;
  553. }
  554. else if ( ch == 'a' )
  555. {
  556. section = DNSREC_ADDITIONAL;
  557. }
  558. else
  559. {
  560. printf( "ERROR: unknown section id %d.\n", ch );
  561. goto Failed;
  562. }
  563. continue;
  564. }
  565. // catch bad starting record (no +/-)
  566. else if ( recordArgc < 0 )
  567. {
  568. printf( "ERROR: bad start of record arg %s\n", arg );
  569. goto Failed;
  570. }
  571. //
  572. // anything else is data, save in argv format
  573. // - save starting point
  574. // - count records
  575. else if ( recordArgc == 0 )
  576. {
  577. recordArgv = --Argv;
  578. Argv++;
  579. }
  580. recordArgc++;
  581. continue;
  582. }
  583. //
  584. // build any final record
  585. //
  586. if ( pszname != NULL )
  587. {
  588. prr = Dns_RecordBuild_A(
  589. & rrset,
  590. pszname,
  591. type,
  592. fadd,
  593. section,
  594. recordArgc,
  595. recordArgv );
  596. if ( !prr )
  597. {
  598. printf( "ERROR: building record.\n" );
  599. goto Failed;
  600. }
  601. if ( fadd && section == DNSREC_UPDATE )
  602. {
  603. prr->dwTtl = 3600;
  604. }
  605. }
  606. IF_DNSDBG( INIT )
  607. {
  608. DnsDbg_RecordSet(
  609. "Record set:\n",
  610. rrset.pFirstRR );
  611. }
  612. return( rrset.pFirstRR );
  613. Failed:
  614. printf( "ERROR: building records from arguments.\n" );
  615. SetLastError( ERROR_INVALID_PARAMETER );
  616. return( NULL );
  617. }
  618. PCHAR
  619. getNamePointer(
  620. IN PSTR pszName
  621. )
  622. /*++
  623. Routine Description:
  624. Get name pointer.
  625. This may be legit pointer or tag
  626. Tags:
  627. - null
  628. - blank
  629. - badptr
  630. - badname
  631. - longname
  632. - longlabel
  633. - buffer
  634. Arguments:
  635. Argc -- arg count
  636. Argv -- argument list
  637. Return Value:
  638. Ptr to list of records built.
  639. NULL on parsing error.
  640. --*/
  641. {
  642. PCHAR pname = pszName;
  643. //
  644. // check special case names
  645. //
  646. if ( _stricmp( pname, "null" ) == 0 )
  647. {
  648. pname = NULL;
  649. }
  650. else if ( _stricmp( pname, "blank" ) == 0 )
  651. {
  652. pname = "";
  653. }
  654. else if ( _stricmp( pname, "badname" ) == 0 )
  655. {
  656. pname = "..badname..";
  657. }
  658. else if ( _stricmp( pname, "longname" ) == 0 )
  659. {
  660. //pname = LONG_NAME;
  661. pname = LongName;
  662. }
  663. else if ( _stricmp( pname, "longlabel" ) == 0 )
  664. {
  665. pname = LONG_LABEL_NAME;
  666. }
  667. else if ( _stricmp( pname, "badptr" ) == 0 )
  668. {
  669. pname = (PCHAR) (-1);
  670. }
  671. else if ( _stricmp( pname, "buffer" ) == 0 )
  672. {
  673. pname = (PCHAR) NameBuffer;
  674. }
  675. return( pname );
  676. }
  677. BOOL
  678. getAddressPointer(
  679. IN PSTR pAddrString,
  680. OUT PCHAR * ppAddr,
  681. OUT PDWORD pLength,
  682. OUT PDWORD pFamily
  683. )
  684. /*++
  685. Routine Description:
  686. Get address from address string argument.
  687. Wraps up special arguments (NULL, badptr), with string
  688. to address conversion.
  689. Arguments:
  690. pAddrString -- address as string
  691. pAddr -- ptr to recv address
  692. pLength -- ptr to recv length of returned address
  693. pFamily -- ptr to recv family (socket family) of returned address
  694. Return Value:
  695. TRUE if valid address converted.
  696. FALSE if special ptr or pass through.
  697. --*/
  698. {
  699. PCHAR paddr;
  700. INT length = sizeof(IP4_ADDRESS);
  701. INT family = AF_INET;
  702. BOOL result = FALSE;
  703. //
  704. // first check for special cases
  705. // - default to AF_INET
  706. //
  707. if ( _stricmp( pAddrString, "null" ) == 0 )
  708. {
  709. paddr = NULL;
  710. }
  711. else if ( _stricmp( pAddrString, "blank" ) == 0 )
  712. {
  713. paddr = "";
  714. length = 0;
  715. }
  716. else if ( _stricmp( pAddrString, "badptr" ) == 0 )
  717. {
  718. paddr = (PCHAR) (-1);
  719. }
  720. //
  721. // not-special -- treat as address string
  722. // - use type and length on successful conversion
  723. // - just return pAddrString and it's length if not successful
  724. //
  725. else
  726. {
  727. family = 0; // any family
  728. length = sizeof(AddressBuffer);
  729. result = Dns_StringToAddress_A(
  730. AddressBuffer,
  731. & length,
  732. pAddrString,
  733. & family );
  734. if ( result )
  735. {
  736. paddr = AddressBuffer;
  737. }
  738. else
  739. {
  740. paddr = pAddrString;
  741. length = strlen( pAddrString );
  742. family = AF_INET;
  743. }
  744. }
  745. *ppAddr = paddr;
  746. *pLength = length;
  747. *pFamily = family;
  748. return( result );
  749. }
  750. BOOL
  751. getSockaddrFromString(
  752. IN OUT PSOCKADDR * ppSockaddr,
  753. IN OUT PDWORD pSockaddrLength,
  754. IN PSTR pAddrString
  755. )
  756. /*++
  757. Routine Description:
  758. Get sockaddr from address string argument.
  759. Wraps up special arguments (NULL, badptr), with string
  760. to address conversion.
  761. Arguments:
  762. ppSockaddr -- addr of ptr to sockaddr buffer
  763. on return may be set to point at dummy sockaddr
  764. pSockaddrLength -- addr with sockaddr buffer length
  765. receives sockaddr length
  766. pAddrString -- address as string
  767. Return Value:
  768. TRUE if parsed sockaddr string
  769. Note this does not mean it is a valid sockaddr.
  770. FALSE if special ptr or pass through.
  771. --*/
  772. {
  773. PCHAR paddr = NULL;
  774. DWORD addrLength;
  775. DWORD family;
  776. DWORD flags = 0;
  777. DNS_STATUS status;
  778. //
  779. // convert address string
  780. //
  781. // if valid string => write into given sockaddr
  782. // if invalid => set sockaddr ptr to dummy sockaddr
  783. //
  784. if ( getAddressPointer(
  785. pAddrString,
  786. & paddr,
  787. & addrLength,
  788. & family ) )
  789. {
  790. status = Dns_AddressToSockaddr(
  791. *ppSockaddr,
  792. pSockaddrLength,
  793. TRUE, // clear sockaddr
  794. paddr,
  795. addrLength,
  796. family );
  797. if ( status != NO_ERROR )
  798. {
  799. DNS_ASSERT( FALSE );
  800. return FALSE;
  801. }
  802. }
  803. else // special bogus address, use it directly
  804. {
  805. *ppSockaddr = (PSOCKADDR) paddr;
  806. }
  807. return TRUE;
  808. }
  809. //
  810. // Command functions
  811. //
  812. DNS_STATUS
  813. ProcessQuit(
  814. IN DWORD Argc,
  815. IN PSTR * Argv
  816. )
  817. {
  818. //
  819. // alert command processor to break iteractive loop
  820. //
  821. return( ERROR_DNSUP_QUIT );
  822. }
  823. //
  824. // Update routines
  825. //
  826. // DCR: could add context handle interface to update routines
  827. //
  828. DNS_STATUS
  829. ProcessUpdate(
  830. IN DWORD Argc,
  831. IN PSTR * Argv
  832. )
  833. {
  834. DNS_STATUS status;
  835. DWORD flags = 0;
  836. PCHAR arg;
  837. PDNS_RECORD prr = NULL;
  838. PDNS_MSG_BUF pmsgRecv = NULL;
  839. HANDLE hCreds=NULL;
  840. //
  841. // flags?
  842. //
  843. if ( Argc < 1 )
  844. {
  845. goto Usage;
  846. }
  847. arg = Argv[0];
  848. if ( strncmp( arg, "-f", 2 ) == 0 )
  849. {
  850. flags = strtoul( arg+2, NULL, 16 );
  851. Argc--;
  852. Argv++;
  853. }
  854. //
  855. // build update packet RRs
  856. //
  857. prr = buildRecordList(
  858. Argc,
  859. Argv );
  860. if ( !prr )
  861. {
  862. status = GetLastError();
  863. if ( status != ERROR_SUCCESS )
  864. {
  865. printf( "ERROR: building records from arguments\n" );
  866. goto Usage;
  867. }
  868. }
  869. //
  870. // build \ send update
  871. //
  872. status = DnsUpdate(
  873. prr,
  874. flags,
  875. NULL, // no UPDATE adapter list specified
  876. hCreds,
  877. &pmsgRecv
  878. );
  879. if ( pmsgRecv )
  880. {
  881. DnsPrint_Message(
  882. dnsup_PrintRoutine,
  883. dnsup_PrintContext,
  884. "Update response:\n",
  885. pmsgRecv );
  886. }
  887. Dns_RecordListFree( prr );
  888. FREE_HEAP( pmsgRecv );
  889. if ( status != ERROR_SUCCESS )
  890. {
  891. printf(
  892. "DnsUpdate failed, %x %s.\n",
  893. status,
  894. DnsStatusString(status) );
  895. }
  896. else
  897. {
  898. printf( "Update successfully completed.\n" );
  899. }
  900. return( status );
  901. Usage:
  902. Dns_RecordListFree( prr );
  903. printf(
  904. "DnsUpdate\n"
  905. "usage:\n"
  906. " DnsUp -u [-f<Flags>] [<Record> | ...]\n"
  907. " <Record> record for update packet\n"
  908. " <Record> == (-,+)(p,u,a) <Name> <Type> [Data | ...]\n"
  909. " (-,+) - add or delete, exist or no-exist flag\n"
  910. " (p,u,a) - prereq, update or additional section\n"
  911. " <Name> - RR owner name\n"
  912. " <Type> - record type (ex A, SRV, PTR, TXT, CNAME, etc.)\n"
  913. " <Data> - data strings (type specific), if any\n"
  914. );
  915. return( ERROR_INVALID_PARAMETER );
  916. }
  917. DNS_STATUS
  918. ProcessUpdateTest(
  919. IN DWORD Argc,
  920. IN PSTR * Argv
  921. )
  922. {
  923. DNS_STATUS status;
  924. DWORD flags = 0;
  925. PCHAR pszzone = NULL;
  926. PCHAR arg;
  927. PDNS_RECORD prr = NULL;
  928. PDNS_MSG_BUF pmsg = NULL;
  929. PDNS_MSG_BUF pmsgRecv = NULL;
  930. IP_ADDRESS ipserver;
  931. PIP_ARRAY aipservers = NULL;
  932. PSTR pszserverName = NULL;
  933. HANDLE hCreds = NULL;
  934. //
  935. // optional name server to query?
  936. //
  937. aipservers = pDnsServerArray;
  938. if ( !aipservers )
  939. {
  940. aipservers = DnsQueryConfigAlloc(
  941. DnsConfigDnsServerList,
  942. NULL );
  943. }
  944. if ( !aipservers )
  945. {
  946. printf( "Update failed: no DNS server list available.\n" );
  947. return( GetLastError() );
  948. }
  949. //
  950. // flags?
  951. //
  952. if ( Argc < 1 )
  953. {
  954. goto Usage;
  955. }
  956. arg = Argv[0];
  957. if ( strncmp( arg, "-f", 2 ) == 0 )
  958. {
  959. flags = strtoul( arg+2, NULL, 16 );
  960. Argc--;
  961. Argv++;
  962. }
  963. //
  964. // security -- then need target server name
  965. // presence of server name automatically turns on security
  966. //
  967. if ( Argc < 1 )
  968. {
  969. goto Usage;
  970. }
  971. arg = Argv[0];
  972. if ( strncmp( arg, "-s", 2 ) == 0 )
  973. {
  974. pszserverName = arg+2;
  975. flags |= DNS_UPDATE_SECURITY_ONLY;
  976. Argc--;
  977. Argv++;
  978. }
  979. //
  980. // name of zone to update
  981. //
  982. if ( Argc < 1 )
  983. {
  984. goto Usage;
  985. }
  986. arg = Argv[0];
  987. if ( *arg != '-' && *arg != '+' )
  988. {
  989. pszzone = arg;
  990. DNSDBG( INIT, (
  991. "Read update zone name %s\n",
  992. pszzone ));
  993. Argc--;
  994. Argv++;
  995. }
  996. //
  997. // build update packet RRs
  998. //
  999. prr = buildRecordList(
  1000. Argc,
  1001. Argv );
  1002. if ( !prr )
  1003. {
  1004. status = GetLastError();
  1005. if ( status != ERROR_SUCCESS )
  1006. {
  1007. printf( "ERROR: building records from arguments\n" );
  1008. goto Usage;
  1009. }
  1010. }
  1011. //
  1012. // build \ send update
  1013. //
  1014. status = Dns_UpdateLibEx(
  1015. prr,
  1016. flags,
  1017. pszzone,
  1018. pszserverName,
  1019. aipservers,
  1020. NULL,
  1021. &pmsgRecv
  1022. );
  1023. if ( pmsgRecv )
  1024. {
  1025. DnsPrint_Message(
  1026. dnsup_PrintRoutine,
  1027. dnsup_PrintContext,
  1028. "Update response:\n",
  1029. pmsgRecv );
  1030. }
  1031. DnsApiFree( aipservers );
  1032. Dns_RecordListFree( prr );
  1033. FREE_HEAP( pmsg );
  1034. FREE_HEAP( pmsgRecv );
  1035. if( status != ERROR_SUCCESS )
  1036. {
  1037. printf(
  1038. "DnsUpdateEx failed, %x %s.\n",
  1039. status,
  1040. DnsStatusString(status) );
  1041. }
  1042. else
  1043. {
  1044. printf( "Update successfully completed.\n" );
  1045. }
  1046. return( status );
  1047. Usage:
  1048. FREE_HEAP( aipservers );
  1049. Dns_RecordListFree( prr );
  1050. FREE_HEAP( pmsg );
  1051. FREE_HEAP( pmsgRecv );
  1052. printf(
  1053. "UpdateTest -- Dns_UpdateLibEx\n"
  1054. "usage:\n"
  1055. " DnsUp [-n<DNS IP>|...] -ut [-f<Flags>] [-s<ServerName>] [<ZoneName>] [<Record> | ...]\n"
  1056. " <DNS IP> optional IP address of server to send update to.\n"
  1057. " <ServerName> name of DNS server we are sending update to;\n"
  1058. " presence of server name automatically turns on update security\n"
  1059. " <ZoneName> name of zone to update\n"
  1060. " <Record> record for update packet\n"
  1061. " <Record> == (-,+)(p,u,a) <Name> <Type> [Data | ...]\n"
  1062. " (-,+) - add or delete, exist or no-exist flag\n"
  1063. " (p,u,a) - prereq, update or additional section\n"
  1064. " <Name> - RR owner name\n"
  1065. " <Type> - record type (ex A, SRV, PTR, TXT, CNAME, etc.)\n"
  1066. " <Data> - data strings (type specific), if any\n"
  1067. );
  1068. return( ERROR_INVALID_PARAMETER );
  1069. }
  1070. DNS_STATUS
  1071. ProcessDhcpTest(
  1072. IN DWORD Argc,
  1073. IN PSTR * Argv
  1074. )
  1075. {
  1076. DNS_STATUS status;
  1077. REGISTER_HOST_ENTRY hostEntry;
  1078. REGISTER_HOST_STATUS hostStatus;
  1079. HANDLE doneEvent;
  1080. //
  1081. // create completion event
  1082. //
  1083. doneEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  1084. //
  1085. // build dumpy DHCP update
  1086. //
  1087. hostEntry.Addr.ipAddr = 0x01010101;
  1088. hostEntry.dwOptions = REGISTER_HOST_A;
  1089. hostStatus.hDoneEvent = doneEvent;
  1090. //
  1091. // send to DHCP DynDNS update routine
  1092. //
  1093. status = DnsAsyncRegisterHostAddrs(
  1094. L"El59x1",
  1095. L"testdhcpname",
  1096. &hostEntry,
  1097. 1, // address count
  1098. NULL, // no regkey with previous
  1099. 0,
  1100. L"nttest.microsoft.com",
  1101. & hostStatus,
  1102. 60, // TTL
  1103. 0
  1104. );
  1105. if( status != ERROR_SUCCESS )
  1106. {
  1107. printf(
  1108. "DnsAsynRegisterHostAddrs_W() %s.\n",
  1109. status,
  1110. DnsStatusString(status) );
  1111. return( status );
  1112. }
  1113. printf( "DHCP DynDNS registration successfully completed.\n" );
  1114. WaitForSingleObject(
  1115. doneEvent,
  1116. INFINITE );
  1117. return( status );
  1118. }
  1119. //
  1120. // Query routines
  1121. //
  1122. DNS_STATUS
  1123. ProcessQueryEx(
  1124. IN DWORD Argc,
  1125. IN PSTR * Argv
  1126. )
  1127. {
  1128. DNS_STATUS status;
  1129. PCHAR pszname;
  1130. WORD type;
  1131. DWORD flags = 0;
  1132. PDNS_MSG_BUF pmsgRecv = NULL;
  1133. HANDLE hevent = NULL;
  1134. DNS_QUERY_INFO queryInfo;
  1135. //
  1136. // name to query
  1137. //
  1138. if ( Argc < 2 || Argc > 4 )
  1139. {
  1140. goto Usage;
  1141. }
  1142. pszname = Argv[0];
  1143. Argc--;
  1144. Argv++;
  1145. //
  1146. // type
  1147. //
  1148. type = DnsRecordTypeForName( Argv[0], 0 );
  1149. if ( type == 0 )
  1150. {
  1151. goto Usage;
  1152. }
  1153. Argc--;
  1154. Argv++;
  1155. //
  1156. // flags and options
  1157. //
  1158. while ( Argc )
  1159. {
  1160. if ( _stricmp( Argv[0], "-a" ) == 0 )
  1161. {
  1162. hevent = CreateEvent( NULL, FALSE, FALSE, NULL );
  1163. }
  1164. else
  1165. {
  1166. flags = strtoul( Argv[0], NULL, 16 );
  1167. }
  1168. Argc--;
  1169. Argv++;
  1170. }
  1171. //
  1172. // query
  1173. //
  1174. RtlZeroMemory(
  1175. & queryInfo,
  1176. sizeof(queryInfo) );
  1177. queryInfo.pName = pszname;
  1178. queryInfo.Type = type;
  1179. queryInfo.Flags = flags;
  1180. queryInfo.pDnsServers = pDnsServerArray;
  1181. queryInfo.hEvent = hevent;
  1182. status = DnsQueryEx( &queryInfo );
  1183. if ( status == ERROR_IO_PENDING )
  1184. {
  1185. printf(
  1186. "DnsQueryEx() running asynchronously.\n"
  1187. "\tEvent = %p\n",
  1188. hevent );
  1189. WaitForSingleObject( hevent, INFINITE );
  1190. printf( "DnsQueryEx() async completion.\n" );
  1191. status = queryInfo.Status;
  1192. }
  1193. if ( status == ERROR_SUCCESS ||
  1194. status == DNS_ERROR_RCODE_NAME_ERROR ||
  1195. status == DNS_INFO_NO_RECORDS )
  1196. {
  1197. printf(
  1198. "DnsQueryEx() completed => %s.\n"
  1199. "\tstatus = %d\n",
  1200. DnsStatusString( status ),
  1201. status );
  1202. DnsPrint_QueryInfo(
  1203. dnsup_PrintRoutine,
  1204. dnsup_PrintContext,
  1205. "DnsQueryEx() result",
  1206. &queryInfo );
  1207. }
  1208. else
  1209. {
  1210. printf(
  1211. "DnsQueryEx() failed, %x %s.\n",
  1212. status,
  1213. DnsStatusString(status) );
  1214. DNS_ASSERT( !queryInfo.pAnswerRecords );
  1215. DNS_ASSERT( !queryInfo.pAliasRecords );
  1216. DNS_ASSERT( !queryInfo.pAdditionalRecords );
  1217. DNS_ASSERT( !queryInfo.pAuthorityRecords );
  1218. }
  1219. return( status );
  1220. Usage:
  1221. printf(
  1222. "DnsQueryEx\n"
  1223. "usage:\n"
  1224. " DnsUp [-n<DNS IP>|...] -qex <Name> <Type> <Flags> [-a]\n"
  1225. " <DNS IP> optional IP address of DNS server to query.\n"
  1226. " <Name> DNS name to query\n"
  1227. " <Type> type of query\n"
  1228. " <Flags> flags to use in query (in hex)\n"
  1229. " -a to indicate asynchronous operation\n"
  1230. );
  1231. return( ERROR_INVALID_PARAMETER );
  1232. }
  1233. DNS_STATUS
  1234. ProcessQueryCompare(
  1235. IN DWORD Argc,
  1236. IN PSTR * Argv
  1237. )
  1238. {
  1239. DNS_STATUS status;
  1240. PCHAR pszname;
  1241. WORD type;
  1242. PIP_ARRAY aipservers;
  1243. PDNS_MSG_BUF pmsgRecv = NULL;
  1244. PDNS_RECORD prrQuery;
  1245. PDNS_RECORD prrParsed;
  1246. PDNS_RECORD prrQueryDiff;
  1247. PDNS_RECORD prrParsedDiff;
  1248. //
  1249. // optional name server to query?
  1250. //
  1251. aipservers = pDnsServerArray;
  1252. //
  1253. // name to query
  1254. //
  1255. if ( Argc < 2 )
  1256. {
  1257. goto Usage;
  1258. }
  1259. pszname = Argv[0];
  1260. Argc--;
  1261. Argv++;
  1262. //
  1263. // type
  1264. //
  1265. type = DnsRecordTypeForName( Argv[0], 0 );
  1266. if ( type == 0 )
  1267. {
  1268. goto Usage;
  1269. }
  1270. Argc--;
  1271. Argv++;
  1272. //
  1273. // build expected RR set
  1274. //
  1275. prrParsed = buildRecordList(
  1276. Argc,
  1277. Argv );
  1278. if ( !prrParsed )
  1279. {
  1280. status = GetLastError();
  1281. if ( status != ERROR_SUCCESS )
  1282. {
  1283. printf( "ERROR: building records from arguments\n" );
  1284. goto Usage;
  1285. }
  1286. }
  1287. DnsPrint_RecordSet(
  1288. dnsup_PrintRoutine,
  1289. dnsup_PrintContext,
  1290. "Parsed comparison record list:\n",
  1291. prrParsed );
  1292. //
  1293. // query
  1294. //
  1295. // DCR: waiting for new DnsQueryEx()
  1296. //
  1297. return( ERROR_CALL_NOT_IMPLEMENTED );
  1298. #if 0
  1299. status = DnsQueryEx(
  1300. & pmsgRecv,
  1301. & prrQuery,
  1302. pszname,
  1303. type,
  1304. 0, // currently no flag support
  1305. aipservers,
  1306. NULL
  1307. );
  1308. if( status != ERROR_SUCCESS )
  1309. {
  1310. printf(
  1311. "DnsQueryEx() failed, %x %s.\n",
  1312. status,
  1313. DnsStatusString(status) );
  1314. if ( DnsIsStatusRcode(status) )
  1315. {
  1316. DnsPrint_Message(
  1317. dnsup_PrintRoutine,
  1318. dnsup_PrintContext,
  1319. "Query response:\n",
  1320. pmsgRecv );
  1321. }
  1322. return( status );
  1323. }
  1324. DnsPrint_RecordSet(
  1325. dnsup_PrintRoutine,
  1326. dnsup_PrintContext,
  1327. "Query response records:\n",
  1328. prrQuery );
  1329. //
  1330. // compare with records received
  1331. //
  1332. DnsRecordSetCompare(
  1333. prrQuery,
  1334. prrParsed,
  1335. & prrQueryDiff,
  1336. & prrParsedDiff );
  1337. DnsPrint_RecordSet(
  1338. dnsup_PrintRoutine,
  1339. dnsup_PrintContext,
  1340. "Unmatch records in query response:\n",
  1341. prrQueryDiff );
  1342. DnsPrint_RecordSet(
  1343. dnsup_PrintRoutine,
  1344. dnsup_PrintContext,
  1345. "Unmatch records in parsed list:\n",
  1346. prrParsedDiff );
  1347. return( ERROR_SUCCESS );
  1348. #endif
  1349. Usage:
  1350. printf(
  1351. "Query compare\n"
  1352. "usage:\n"
  1353. " DnsUp [-n<DNS IP>|...] -qc <Name> <Type> [<Record> | ...]\n"
  1354. " <DNS IP> optional IP address of DNS server to update.\n"
  1355. " <Name> DNS name to query\n"
  1356. " <Type> type of query\n"
  1357. " <Record> record in list to compare\n"
  1358. " <Record> == (-,+) <Name> <Type> [Data | ...]\n"
  1359. " (-,+) - add or delete, exist or no-exist flag\n"
  1360. " <Name> - RR owner name\n"
  1361. " <Type> - record type\n"
  1362. " <Data> - data strings (type specific), if any\n"
  1363. );
  1364. return( ERROR_INVALID_PARAMETER );
  1365. }
  1366. DNS_STATUS
  1367. ProcessQuery(
  1368. IN DWORD Argc,
  1369. IN PSTR * Argv
  1370. )
  1371. {
  1372. DNS_STATUS status;
  1373. PCHAR pszname;
  1374. WORD type;
  1375. DWORD flags = 0;
  1376. PDNS_RECORD precord = NULL;
  1377. PDNS_MSG_BUF pmsgRecv = NULL;
  1378. PDNS_MSG_BUF * ppmsgRecv = NULL;
  1379. PIP_ARRAY aipservers = NULL;
  1380. //
  1381. // name to query
  1382. //
  1383. if ( Argc < 2 || Argc > 3 )
  1384. {
  1385. goto Usage;
  1386. }
  1387. pszname = getNamePointer( Argv[0] );
  1388. Argc--;
  1389. Argv++;
  1390. //
  1391. // type
  1392. //
  1393. type = DnsRecordTypeForName( Argv[0], 0 );
  1394. if ( type == 0 )
  1395. {
  1396. goto Usage;
  1397. }
  1398. Argc--;
  1399. Argv++;
  1400. //
  1401. // flags
  1402. //
  1403. if ( Argc )
  1404. {
  1405. flags = strtoul( Argv[0], NULL, 16 );
  1406. Argc--;
  1407. Argv++;
  1408. }
  1409. if ( Argc )
  1410. {
  1411. goto Usage;
  1412. }
  1413. //
  1414. // only if flag has BYPASS_CACHE set can we
  1415. // 1) send to specific servers
  1416. // 2) receive message buffer itself
  1417. //
  1418. aipservers = pDnsServerArray;
  1419. if ( flags & DNS_QUERY_BYPASS_CACHE )
  1420. {
  1421. ppmsgRecv = & pmsgRecv;
  1422. }
  1423. //
  1424. // query
  1425. //
  1426. status = DnsQuery(
  1427. pszname,
  1428. type,
  1429. flags,
  1430. aipservers,
  1431. & precord,
  1432. ppmsgRecv );
  1433. if( status != ERROR_SUCCESS )
  1434. {
  1435. printf(
  1436. "DnsQuery() failed, %x %s.\n",
  1437. status,
  1438. DnsStatusString(status) );
  1439. if ( DnsIsStatusRcode(status) && pmsgRecv )
  1440. {
  1441. DnsPrint_Message(
  1442. dnsup_PrintRoutine,
  1443. dnsup_PrintContext,
  1444. "Query response:\n",
  1445. pmsgRecv );
  1446. }
  1447. }
  1448. else
  1449. {
  1450. printf( "DnsQuery() successfully completed.\n" );
  1451. if ( pmsgRecv )
  1452. {
  1453. DnsPrint_Message(
  1454. dnsup_PrintRoutine,
  1455. dnsup_PrintContext,
  1456. "Query response:\n",
  1457. pmsgRecv );
  1458. }
  1459. DnsPrint_RecordSet(
  1460. dnsup_PrintRoutine,
  1461. dnsup_PrintContext,
  1462. "Query response records:\n",
  1463. precord );
  1464. }
  1465. DnsRecordListFree( precord, DnsFreeRecordListDeep );
  1466. return( status );
  1467. Usage:
  1468. printf(
  1469. "DnsQuery\n"
  1470. "usage:\n"
  1471. " DnsUp [-n<DNS IP>|...] -q <Name> <Type> [<Flags>]\n"
  1472. " <DNS IP> optional IP address of DNS server to query.\n"
  1473. " <Name> DNS name to query\n"
  1474. " <Type> type of query\n"
  1475. " <Flags> flags to use in query (in hex)\n"
  1476. "\n"
  1477. " Note for DnsQuery() to use specific server or to return\n"
  1478. " a DNS message buffer, BYPASS_CACHE flag MUST be set.\n"
  1479. );
  1480. PrintDnsQueryFlags();
  1481. return( ERROR_INVALID_PARAMETER );
  1482. }
  1483. DNS_STATUS
  1484. ProcessQueryMultiple(
  1485. IN DWORD Argc,
  1486. IN PSTR * Argv
  1487. )
  1488. {
  1489. DNS_STATUS status;
  1490. PCHAR pszname1;
  1491. WORD type1;
  1492. PCHAR pszname2;
  1493. WORD type2;
  1494. DWORD flags = 0;
  1495. PDNS_RECORD precord = NULL;
  1496. PDNS_MSG_BUF pmsgRecv = NULL;
  1497. PDNS_MSG_BUF * ppmsgRecv = NULL;
  1498. PIP_ARRAY aipservers = NULL;
  1499. //
  1500. // optional name server to query?
  1501. //
  1502. if ( Argc < 4 || Argc > 5 )
  1503. {
  1504. goto Usage;
  1505. }
  1506. //
  1507. // first name to query
  1508. //
  1509. pszname1 = Argv[0];
  1510. Argc--;
  1511. Argv++;
  1512. //
  1513. // first type
  1514. //
  1515. type1 = DnsRecordTypeForName( Argv[0], 0 );
  1516. if ( type1 == 0 )
  1517. {
  1518. goto Usage;
  1519. }
  1520. Argc--;
  1521. Argv++;
  1522. //
  1523. // second name to query
  1524. //
  1525. pszname2 = Argv[0];
  1526. Argc--;
  1527. Argv++;
  1528. //
  1529. // second type
  1530. //
  1531. type2 = DnsRecordTypeForName( Argv[0], 0 );
  1532. if ( type2 == 0 )
  1533. {
  1534. goto Usage;
  1535. }
  1536. Argc--;
  1537. Argv++;
  1538. //
  1539. // flags
  1540. //
  1541. if ( Argc )
  1542. {
  1543. flags = strtoul( Argv[0], NULL, 16 );
  1544. Argc--;
  1545. Argv++;
  1546. }
  1547. if ( Argc )
  1548. {
  1549. goto Usage;
  1550. }
  1551. //
  1552. // only if flag has BYPASS_CACHE set can we
  1553. // 1) send to specific servers
  1554. // 2) receive message buffer itself
  1555. //
  1556. if ( flags & DNS_QUERY_BYPASS_CACHE )
  1557. {
  1558. aipservers = pDnsServerArray;
  1559. ppmsgRecv = & pmsgRecv;
  1560. }
  1561. //
  1562. // make first query
  1563. //
  1564. status = DnsQuery(
  1565. pszname1,
  1566. type1,
  1567. flags,
  1568. aipservers,
  1569. & precord,
  1570. ppmsgRecv );
  1571. if( status != ERROR_SUCCESS )
  1572. {
  1573. printf(
  1574. "DnsQuery() failed, %x %s.\n",
  1575. status,
  1576. DnsStatusString(status) );
  1577. if ( DnsIsStatusRcode(status) && pmsgRecv )
  1578. {
  1579. DnsPrint_Message(
  1580. dnsup_PrintRoutine,
  1581. dnsup_PrintContext,
  1582. "Query response:\n",
  1583. pmsgRecv );
  1584. }
  1585. }
  1586. else
  1587. {
  1588. printf( "DnsQuery() successfully completed.\n" );
  1589. if ( pmsgRecv )
  1590. {
  1591. DnsPrint_Message(
  1592. dnsup_PrintRoutine,
  1593. dnsup_PrintContext,
  1594. "Query response:\n",
  1595. pmsgRecv );
  1596. }
  1597. DnsPrint_RecordSet(
  1598. dnsup_PrintRoutine,
  1599. dnsup_PrintContext,
  1600. "Query response records:\n",
  1601. precord );
  1602. }
  1603. DnsRecordListFree( precord, DnsFreeRecordListDeep );
  1604. //
  1605. // make second query
  1606. //
  1607. status = DnsQuery(
  1608. pszname2,
  1609. type2,
  1610. flags,
  1611. aipservers,
  1612. & precord,
  1613. ppmsgRecv );
  1614. if( status != ERROR_SUCCESS )
  1615. {
  1616. printf(
  1617. "DnsQuery() failed, %x %s.\n",
  1618. status,
  1619. DnsStatusString(status) );
  1620. if ( DnsIsStatusRcode(status) && pmsgRecv )
  1621. {
  1622. DnsPrint_Message(
  1623. dnsup_PrintRoutine,
  1624. dnsup_PrintContext,
  1625. "Query response:\n",
  1626. pmsgRecv );
  1627. }
  1628. }
  1629. else
  1630. {
  1631. printf( "DnsQuery() successfully completed.\n" );
  1632. if ( pmsgRecv )
  1633. {
  1634. DnsPrint_Message(
  1635. dnsup_PrintRoutine,
  1636. dnsup_PrintContext,
  1637. "Query response:\n",
  1638. pmsgRecv );
  1639. }
  1640. DnsPrint_RecordSet(
  1641. dnsup_PrintRoutine,
  1642. dnsup_PrintContext,
  1643. "Query response records:\n",
  1644. precord );
  1645. }
  1646. DnsRecordListFree( precord, DnsFreeRecordListDeep );
  1647. return( status );
  1648. Usage:
  1649. printf(
  1650. "Multiple DnsQuery()s\n"
  1651. "usage:\n"
  1652. " DnsUp [-n<DNS IP>|...] -qm <Name1> <Type1> <Name2> <Type2> [<Flags>]\n"
  1653. " <DNS IP> optional IP address of DNS server to query.\n"
  1654. " <Name1> DNS name to query\n"
  1655. " <Type1> type of query\n"
  1656. " <Name2> DNS name to query\n"
  1657. " <Type2> type of query\n"
  1658. " <Flags> flags to use in query (in hex)\n"
  1659. "\n"
  1660. " Note for DnsQuery() to use specific server or to return\n"
  1661. " a DNS message buffer, BYPASS_CACHE flag MUST be set.\n"
  1662. );
  1663. PrintDnsQueryFlags();
  1664. return( ERROR_INVALID_PARAMETER );
  1665. }
  1666. DNS_STATUS
  1667. ProcessQueryTest(
  1668. IN DWORD Argc,
  1669. IN PSTR * Argv
  1670. )
  1671. {
  1672. DNS_STATUS status;
  1673. PCHAR pszname;
  1674. WORD type;
  1675. DWORD flags = 0;
  1676. PDNS_RECORD precord = NULL;
  1677. PDNS_MSG_BUF pmsgRecv = NULL;
  1678. PIP_ARRAY aipservers = NULL;
  1679. //
  1680. // optional name server to query?
  1681. //
  1682. aipservers = pDnsServerArray;
  1683. //
  1684. // name to query
  1685. //
  1686. if ( Argc < 2 || Argc > 3 )
  1687. {
  1688. goto Usage;
  1689. }
  1690. pszname = Argv[0];
  1691. Argc--;
  1692. Argv++;
  1693. //
  1694. // type
  1695. //
  1696. type = DnsRecordTypeForName( Argv[0], 0 );
  1697. if ( type == 0 )
  1698. {
  1699. goto Usage;
  1700. }
  1701. Argc--;
  1702. Argv++;
  1703. //
  1704. // flags
  1705. //
  1706. if ( Argc )
  1707. {
  1708. flags = strtoul( Argv[0], NULL, 16 );
  1709. Argc--;
  1710. Argv++;
  1711. }
  1712. if ( Argc )
  1713. {
  1714. goto Usage;
  1715. }
  1716. //
  1717. // query
  1718. //
  1719. status = QueryDirectEx(
  1720. & pmsgRecv,
  1721. & precord,
  1722. NULL, // no header
  1723. 0, // no header counts
  1724. pszname,
  1725. type,
  1726. NULL, // no records
  1727. flags,
  1728. aipservers,
  1729. NULL
  1730. );
  1731. if( status != ERROR_SUCCESS )
  1732. {
  1733. printf(
  1734. "QueryDirectEx() failed, %x %s.\n",
  1735. status,
  1736. DnsStatusString(status) );
  1737. if ( DnsIsStatusRcode(status) )
  1738. {
  1739. DnsPrint_Message(
  1740. dnsup_PrintRoutine,
  1741. dnsup_PrintContext,
  1742. "Query response:\n",
  1743. pmsgRecv );
  1744. }
  1745. }
  1746. else
  1747. {
  1748. printf( "QueryDirectEx() successfully completed.\n" );
  1749. DnsPrint_Message(
  1750. dnsup_PrintRoutine,
  1751. dnsup_PrintContext,
  1752. "Query response:\n",
  1753. pmsgRecv );
  1754. DnsPrint_RecordSet(
  1755. dnsup_PrintRoutine,
  1756. dnsup_PrintContext,
  1757. "Query response records:\n",
  1758. precord );
  1759. }
  1760. DnsRecordListFree( precord, DnsFreeRecordListDeep );
  1761. return( status );
  1762. Usage:
  1763. printf(
  1764. "QueryDirectEx()\n"
  1765. "usage:\n"
  1766. " DnsUp [-n<DNS IP>|...] -qt <Name> <Type> [<Flags>]\n"
  1767. " QueryTest -- uses dnslib.lib QueryDirectEx()\n"
  1768. " <DNS IP> optional IP address of DNS server to query.\n"
  1769. " <Name> DNS name to query\n"
  1770. " <Type> type of query\n"
  1771. " <Flags> flags to use in query (in hex)\n"
  1772. );
  1773. return( ERROR_INVALID_PARAMETER );
  1774. }
  1775. #if 0
  1776. DNS_STATUS
  1777. ProcessUpdateMultiple(
  1778. IN DWORD Argc,
  1779. IN PSTR * Argv
  1780. )
  1781. {
  1782. DNS_STATUS status;
  1783. DWORD flags = 0;
  1784. PCHAR pszzone = NULL;
  1785. PCHAR pszname = NULL;
  1786. IP_ADDRESS ip;
  1787. IP_ADDRESS hostIp;
  1788. DWORD countIp;
  1789. DWORD i;
  1790. PCHAR arg;
  1791. PDNS_RECORD prr = NULL;
  1792. PDNS_MSG_BUF pmsg = NULL;
  1793. PDNS_MSG_BUF pmsgRecv = NULL;
  1794. IP_ADDRESS ipserver;
  1795. PIP_ARRAY aipservers = NULL;
  1796. PIP_ARRAY ipArray = NULL;
  1797. PSTR pszserverName = NULL;
  1798. HANDLE hCreds=NULL;
  1799. //
  1800. // optional name server to query?
  1801. //
  1802. aipservers = pDnsServerArray;
  1803. if ( !aipservers )
  1804. {
  1805. aipservers = Dns_GetDnsServerList( FALSE );
  1806. }
  1807. if ( !aipservers )
  1808. {
  1809. printf( "Update failed: no DNS server list available.\n" );
  1810. return( GetLastError() );
  1811. }
  1812. //
  1813. // flags?
  1814. //
  1815. if ( Argc < 1 )
  1816. {
  1817. goto Usage;
  1818. }
  1819. arg = Argv[0];
  1820. if ( strncmp( arg, "-f", 2 ) == 0 )
  1821. {
  1822. flags = strtoul( arg+2, NULL, 16 );
  1823. Argc--;
  1824. Argv++;
  1825. }
  1826. //
  1827. // security -- then need target server name
  1828. // presence of server name automatically turns on security
  1829. //
  1830. if ( Argc < 1 )
  1831. {
  1832. goto Usage;
  1833. }
  1834. arg = Argv[0];
  1835. if ( strncmp( arg, "-s", 2 ) == 0 )
  1836. {
  1837. pszserverName = arg+2;
  1838. flags |= DNS_UPDATE_SECURITY_ON;
  1839. Argc--;
  1840. Argv++;
  1841. }
  1842. //
  1843. // name of zone to update
  1844. //
  1845. if ( Argc < 1 )
  1846. {
  1847. goto Usage;
  1848. }
  1849. pszzone = Argv[0];
  1850. DNSDBG( INIT, (
  1851. "Read update zone name %s\n",
  1852. pszzone ));
  1853. Argc--;
  1854. Argv++;
  1855. //
  1856. // name to update
  1857. //
  1858. if ( Argc < 1 )
  1859. {
  1860. goto Usage;
  1861. }
  1862. pszname = Argv[0];
  1863. DNSDBG( INIT, (
  1864. "Read update host name %s\n",
  1865. pszname ));
  1866. Argc--;
  1867. Argv++;
  1868. //
  1869. // start IP
  1870. //
  1871. if ( Argc < 1 )
  1872. {
  1873. goto Usage;
  1874. }
  1875. ip = inet_addr( Argv[0] );
  1876. if ( ip == (-1) )
  1877. {
  1878. goto Usage;
  1879. }
  1880. Argc--;
  1881. Argv++;
  1882. //
  1883. // IP count
  1884. //
  1885. if ( Argc < 1 )
  1886. {
  1887. goto Usage;
  1888. }
  1889. countIp = strtoul( Argv[0], NULL, 10 );
  1890. Argc--;
  1891. Argv++;
  1892. //
  1893. // build update record list
  1894. // - allocate and generate IP array
  1895. // - then create DNS records
  1896. //
  1897. ipArray = Dns_CreateIpArray( countIp );
  1898. if ( !ipArray )
  1899. {
  1900. status = GetLastError();
  1901. if ( status != ERROR_SUCCESS )
  1902. {
  1903. printf( "ERROR: creating IP array\n" );
  1904. goto Usage;
  1905. }
  1906. goto Usage;
  1907. }
  1908. hostIp = ntohl( ip );
  1909. for ( i=0; i<countIp; i++ )
  1910. {
  1911. ipArray->AddrArray[i] = htonl( hostIp );
  1912. hostIp++;
  1913. }
  1914. prr = Dns_HostUpdateRRSet(
  1915. pszname,
  1916. ipArray,
  1917. 3600 );
  1918. if ( !prr )
  1919. {
  1920. status = GetLastError();
  1921. if ( status != ERROR_SUCCESS )
  1922. {
  1923. printf( "ERROR: building records from arguments\n" );
  1924. goto Usage;
  1925. }
  1926. }
  1927. //
  1928. // build \ send update
  1929. //
  1930. status = Dns_UpdateLibEx(
  1931. prr,
  1932. flags,
  1933. pszzone,
  1934. pszserverName,
  1935. aipservers,
  1936. hCreds,
  1937. &pmsgRecv
  1938. );
  1939. if ( pmsgRecv )
  1940. {
  1941. DnsPrint_Message(
  1942. dnsup_PrintRoutine,
  1943. dnsup_PrintContext,
  1944. "Update response:\n",
  1945. pmsgRecv );
  1946. }
  1947. FREE_HEAP( aipservers );
  1948. Dns_RecordListFree( prr );
  1949. FREE_HEAP( pmsg );
  1950. FREE_HEAP( pmsgRecv );
  1951. if( status != ERROR_SUCCESS )
  1952. {
  1953. printf(
  1954. "Dns_UpdateLibEx failed, %x %s.\n",
  1955. status,
  1956. DnsStatusString(status) );
  1957. }
  1958. else
  1959. {
  1960. printf( "Update successfully completed.\n" );
  1961. }
  1962. return( status );
  1963. Usage:
  1964. FREE_HEAP( aipservers );
  1965. Dns_RecordListFree( prr );
  1966. FREE_HEAP( pmsg );
  1967. FREE_HEAP( pmsgRecv );
  1968. printf(
  1969. "usage:\n"
  1970. " DnsUp [-n<DNS IP>|...] -um [-f<Flags>] [-s<ServerName>] <ZoneName>\n"
  1971. " <HostName> <Starting IP> <IP Count>\n"
  1972. " <DNS IP> optional IP address of server to send update to.\n"
  1973. " <ServerName> name of DNS server we are sending update to;\n"
  1974. " presence of server name automatically turns on update security\n"
  1975. " <ZoneName> name of zone to update\n"
  1976. " <HostName> name of host to update\n"
  1977. " <Starting IP> first IP (in dotted decimal) in range to update\n"
  1978. " <IP Count> count of IPs to send in update; IP address in update will\n"
  1979. " be the next <IP count> after <Starting IP>\n"
  1980. );
  1981. return( ERROR_INVALID_PARAMETER );
  1982. }
  1983. #endif
  1984. DNS_STATUS
  1985. ProcessIQuery(
  1986. IN DWORD Argc,
  1987. IN PSTR * Argv
  1988. )
  1989. {
  1990. DNS_STATUS status;
  1991. DWORD flags = 0;
  1992. PCHAR arg;
  1993. PDNS_RECORD prr = NULL;
  1994. PDNS_MSG_BUF pmsg = NULL;
  1995. PDNS_MSG_BUF pmsgRecv = NULL;
  1996. IP_ADDRESS ipserver;
  1997. PIP_ARRAY aipservers = NULL;
  1998. DNS_HEADER header;
  1999. //
  2000. // setup header
  2001. // - zero flags
  2002. *(PDWORD) &header = 0;
  2003. header.Xid = (WORD) GetCurrentTimeInSeconds();
  2004. header.Opcode = DNS_OPCODE_IQUERY;
  2005. //
  2006. // optional name server to query?
  2007. //
  2008. aipservers = pDnsServerArray;
  2009. if ( !aipservers )
  2010. {
  2011. aipservers = DnsQueryConfigAlloc(
  2012. DnsConfigDnsServerList,
  2013. NULL );
  2014. }
  2015. if ( !aipservers )
  2016. {
  2017. printf( "Update failed: no DNS server list available.\n" );
  2018. return( GetLastError() );
  2019. }
  2020. //
  2021. // flags?
  2022. //
  2023. if ( Argc < 1 )
  2024. {
  2025. goto Usage;
  2026. }
  2027. arg = Argv[0];
  2028. if ( strncmp( arg, "-f", 2 ) == 0 )
  2029. {
  2030. flags = strtoul( arg+2, NULL, 16 );
  2031. Argc--;
  2032. Argv++;
  2033. }
  2034. //
  2035. // build update packet RRs
  2036. //
  2037. prr = buildRecordList(
  2038. Argc,
  2039. Argv );
  2040. if ( !prr )
  2041. {
  2042. status = GetLastError();
  2043. if ( status != ERROR_SUCCESS )
  2044. {
  2045. printf( "ERROR: building records from arguments\n" );
  2046. goto Usage;
  2047. }
  2048. }
  2049. //
  2050. // build \ send update
  2051. //
  2052. status = QueryDirectEx(
  2053. & pmsgRecv,
  2054. NULL, // no response records
  2055. & header, // header with IQUERY set
  2056. TRUE, // no copy header count fields
  2057. NULL, // no question
  2058. 0, // no question type
  2059. prr, // record list built
  2060. 0, // flags
  2061. aipservers, // server IP list
  2062. NULL // no adapter list
  2063. );
  2064. if ( pmsgRecv )
  2065. {
  2066. DnsPrint_Message(
  2067. dnsup_PrintRoutine,
  2068. dnsup_PrintContext,
  2069. "IQUERY response:\n",
  2070. pmsgRecv );
  2071. }
  2072. FREE_HEAP( aipservers );
  2073. Dns_RecordListFree( prr );
  2074. FREE_HEAP( pmsg );
  2075. FREE_HEAP( pmsgRecv );
  2076. if( status != ERROR_SUCCESS )
  2077. {
  2078. printf(
  2079. "QueryDirectExEx failed, %x %s.\n",
  2080. status,
  2081. DnsStatusString(status) );
  2082. }
  2083. else
  2084. {
  2085. printf( "IQUERY successfully completed.\n" );
  2086. }
  2087. return( status );
  2088. Usage:
  2089. FREE_HEAP( aipservers );
  2090. Dns_RecordListFree( prr );
  2091. FREE_HEAP( pmsg );
  2092. FREE_HEAP( pmsgRecv );
  2093. printf(
  2094. "usage:\n"
  2095. " DnsUp [-n<DNS IP>|...] -iq [-f<Flags>] [<Record> | ...]\n"
  2096. " <DNS IP> optional IP address of server to send update to.\n"
  2097. " <ServerName> name of DNS server we are sending update to;\n"
  2098. " presence of server name automatically turns on update security\n"
  2099. " <ZoneName> name of zone to update\n"
  2100. " <Record> record for update packet\n"
  2101. " <Record> == (-,+)(p,u,a) <Name> <Type> [Data | ...]\n"
  2102. " (-,+) - add or delete, exist or no-exist flag\n"
  2103. " (p,u,a) - prereq, update or additional section\n"
  2104. " <Name> - RR owner name\n"
  2105. " <Type> - record type\n"
  2106. " <Data> - data strings (type specific), if any\n"
  2107. );
  2108. return( ERROR_INVALID_PARAMETER );
  2109. }
  2110. DNS_STATUS
  2111. ProcessValidateName(
  2112. IN DWORD Argc,
  2113. IN PSTR * Argv
  2114. )
  2115. {
  2116. DNS_STATUS status;
  2117. PCHAR pszname;
  2118. DWORD format;
  2119. //
  2120. // name to validate
  2121. //
  2122. if ( Argc != 2 )
  2123. {
  2124. goto Usage;
  2125. }
  2126. pszname = Argv[0];
  2127. Argc--;
  2128. Argv++;
  2129. //
  2130. // name format
  2131. //
  2132. if ( Argc )
  2133. {
  2134. format = strtoul( Argv[0], NULL, 10 );
  2135. }
  2136. //
  2137. // validate
  2138. //
  2139. status = DnsValidateName_A(
  2140. pszname,
  2141. format );
  2142. printf(
  2143. "DnsValidateName( %s, %d ) status = %d %s.\n",
  2144. pszname,
  2145. format,
  2146. status,
  2147. DnsStatusString(status) );
  2148. return( status );
  2149. Usage:
  2150. printf(
  2151. "DnsValidateName\n"
  2152. "usage:\n"
  2153. " DnsUp -vn <Name> <Format>\n"
  2154. " <Name> DNS name to validate\n"
  2155. " <Format> format of name\n"
  2156. "\tDomainName -- %d\n"
  2157. "\tDomainLabel -- %d\n"
  2158. "\tHostnameFull -- %d\n"
  2159. "\tHostnameLabel -- %d\n"
  2160. "\tWildcard -- %d\n"
  2161. "\tSrvRecord -- %d\n",
  2162. DnsNameDomain,
  2163. DnsNameDomainLabel,
  2164. DnsNameHostnameFull,
  2165. DnsNameHostnameLabel,
  2166. DnsNameWildcard,
  2167. DnsNameSrvRecord
  2168. );
  2169. return( ERROR_INVALID_PARAMETER );
  2170. }
  2171. DNS_STATUS
  2172. ProcessNameCompare(
  2173. IN DWORD Argc,
  2174. IN PSTR * Argv
  2175. )
  2176. {
  2177. BOOL result;
  2178. PCHAR pszname1;
  2179. PCHAR pszname2;
  2180. //
  2181. // names to compare
  2182. //
  2183. if ( Argc != 2 )
  2184. {
  2185. goto Usage;
  2186. }
  2187. pszname1 = Argv[0];
  2188. pszname2 = Argv[1];
  2189. //
  2190. // compare
  2191. //
  2192. result = DnsNameCompare_A(
  2193. pszname1,
  2194. pszname2 );
  2195. printf(
  2196. "DnsNameCompare( %s, %s ) result = %s.\n",
  2197. pszname1,
  2198. pszname2,
  2199. result ? "TRUE" : "FALSE"
  2200. );
  2201. return( ERROR_SUCCESS );
  2202. Usage:
  2203. printf(
  2204. "DnsNameCompare\n"
  2205. "usage:\n"
  2206. " DnsUp -nc <Name1> <Name2>\n"
  2207. " <Name1> <Name2> DNS names to compare.\n"
  2208. );
  2209. return( ERROR_INVALID_PARAMETER );
  2210. }
  2211. DNS_STATUS
  2212. ProcessNameCompareEx(
  2213. IN DWORD Argc,
  2214. IN PSTR * Argv
  2215. )
  2216. {
  2217. DNS_STATUS status;
  2218. PCHAR pszname1;
  2219. PCHAR pszname2;
  2220. //
  2221. // names to compare
  2222. //
  2223. if ( Argc != 2 )
  2224. {
  2225. goto Usage;
  2226. }
  2227. pszname1 = Argv[0];
  2228. pszname2 = Argv[1];
  2229. //
  2230. // compare
  2231. //
  2232. status = DnsNameCompareEx_A(
  2233. pszname1,
  2234. pszname2,
  2235. 0 );
  2236. printf(
  2237. "DnsNameCompareEx( %s, %s ) result = %d.\n",
  2238. pszname1,
  2239. pszname2,
  2240. status
  2241. );
  2242. return( ERROR_SUCCESS );
  2243. Usage:
  2244. printf(
  2245. "DnsNameCompareEx\n"
  2246. "usage:\n"
  2247. " DnsUp -cnx <Name1> <Name2>\n"
  2248. " <Name1> <Name2> DNS names to compare.\n"
  2249. "Compare Result:\n"
  2250. "\tNot Equal -- %d\n"
  2251. "\tEqual -- %d\n"
  2252. "\tLeft is Ancestor -- %d\n"
  2253. "\tRight is Ancestor -- %d\n"
  2254. "\tInvalid Name -- %d\n",
  2255. DnsNameCompareNotEqual,
  2256. DnsNameCompareEqual,
  2257. DnsNameCompareLeftParent,
  2258. DnsNameCompareRightParent,
  2259. DnsNameCompareInvalid
  2260. );
  2261. return( ERROR_INVALID_PARAMETER );
  2262. }
  2263. DNS_STATUS
  2264. ProcessStringTranslate(
  2265. IN DWORD Argc,
  2266. IN PSTR * Argv
  2267. )
  2268. {
  2269. DNS_STATUS status;
  2270. WCHAR unicodeString[ DNS_MAX_NAME_LENGTH ];
  2271. WCHAR unicodeStandard[ DNS_MAX_NAME_LENGTH ];
  2272. BYTE utf8Standard[ DNS_MAX_NAME_LENGTH ];
  2273. PWCHAR punicode;
  2274. PCHAR putf8;
  2275. DWORD unicodeLength;
  2276. DWORD utf8Length;
  2277. DWORD unicodeLengthStandard;
  2278. //
  2279. // string translate
  2280. //
  2281. if ( Argc < 1 )
  2282. {
  2283. goto Usage;
  2284. }
  2285. //
  2286. // read in unicode characters
  2287. //
  2288. unicodeLength = 0;
  2289. while ( Argc )
  2290. {
  2291. unicodeString[ unicodeLength++] = (WORD) strtoul( Argv[0], NULL, 16 );
  2292. Argc--;
  2293. Argv++;
  2294. }
  2295. unicodeString[ unicodeLength ] = 0;
  2296. DnsPrint_UnicodeStringBytes(
  2297. dnsup_PrintRoutine,
  2298. dnsup_PrintContext,
  2299. "DnsStringTranslate().\n"
  2300. "Input string",
  2301. unicodeString,
  2302. unicodeLength );
  2303. //
  2304. // convert to UTF8 -- my way and their way
  2305. //
  2306. putf8 = Dns_StringCopyAllocate(
  2307. (PCHAR) unicodeString,
  2308. 0,
  2309. DnsCharSetUnicode,
  2310. DnsCharSetUtf8 );
  2311. if ( !putf8 )
  2312. {
  2313. return( DNS_ERROR_NO_MEMORY );
  2314. }
  2315. utf8Length = WideCharToMultiByte(
  2316. CP_UTF8,
  2317. 0, // no flags
  2318. (PWCHAR) unicodeString,
  2319. (-1), // null terminated
  2320. utf8Standard,
  2321. MAXWORD, // assuming adequate length
  2322. NULL,
  2323. NULL );
  2324. DnsPrint_Utf8StringBytes(
  2325. dnsup_PrintRoutine,
  2326. dnsup_PrintContext,
  2327. "My UTF8",
  2328. putf8,
  2329. strlen(putf8) );
  2330. DnsPrint_Utf8StringBytes(
  2331. dnsup_PrintRoutine,
  2332. dnsup_PrintContext,
  2333. "Standard UTF8",
  2334. utf8Standard,
  2335. strlen(utf8Standard) );
  2336. //
  2337. // convert back to unicode
  2338. //
  2339. punicode = Dns_StringCopyAllocate(
  2340. (PCHAR) utf8Standard,
  2341. 0,
  2342. DnsCharSetUtf8,
  2343. DnsCharSetUnicode );
  2344. unicodeLengthStandard = MultiByteToWideChar(
  2345. CP_UTF8,
  2346. 0, // no flags
  2347. (PCHAR) utf8Standard,
  2348. (-1), // null terminated
  2349. (PWCHAR) unicodeStandard,
  2350. MAXWORD // assuming adequate length
  2351. );
  2352. DnsPrint_UnicodeStringBytes(
  2353. dnsup_PrintRoutine,
  2354. dnsup_PrintContext,
  2355. "My unicode",
  2356. punicode,
  2357. wcslen(punicode) );
  2358. DnsPrint_UnicodeStringBytes(
  2359. dnsup_PrintRoutine,
  2360. dnsup_PrintContext,
  2361. "Standard unicode",
  2362. unicodeStandard,
  2363. wcslen(unicodeStandard) );
  2364. status = ERROR_SUCCESS;
  2365. return( status );
  2366. Usage:
  2367. printf(
  2368. "usage:\n"
  2369. " DnsUp -s [unicode chars in hex]\n"
  2370. );
  2371. return( ERROR_INVALID_PARAMETER );
  2372. }
  2373. DNS_STATUS
  2374. ProcessQueryConfig(
  2375. IN DWORD Argc,
  2376. IN PSTR * Argv
  2377. )
  2378. {
  2379. #define CONFIG_BUF_SIZE (100)
  2380. DNS_STATUS status;
  2381. DNS_CONFIG_TYPE config;
  2382. PCHAR psznext;
  2383. PCHAR pendString;
  2384. PWSTR pwsadapter = NULL;
  2385. DWORD flag = 0;
  2386. BOOL ballocated = FALSE;
  2387. BOOL bsleep = FALSE;
  2388. DWORD bufLength = 0;
  2389. DWORD sentBufLength;
  2390. PBYTE pbuffer = NULL;
  2391. PBYTE pallocResult;
  2392. BYTE buffer[ CONFIG_BUF_SIZE ];
  2393. //
  2394. // query config
  2395. //
  2396. if ( Argc < 1 )
  2397. {
  2398. goto Usage;
  2399. }
  2400. // config value
  2401. config = strtoul( Argv[0], &pendString, 10 );
  2402. Argc--;
  2403. Argv++;
  2404. // flag?
  2405. while ( Argc )
  2406. {
  2407. psznext = Argv[0];
  2408. // flag
  2409. if ( !_stricmp( psznext, "-f" ) ||
  2410. !_stricmp( psznext, "/f" ) )
  2411. {
  2412. Argc--;
  2413. Argv++;
  2414. flag = strtoul( Argv[0], &pendString, 16 );
  2415. Argc--;
  2416. Argv++;
  2417. if ( flag & DNS_CONFIG_FLAG_ALLOC )
  2418. {
  2419. bufLength = sizeof(PVOID);
  2420. pbuffer = buffer;
  2421. }
  2422. continue;
  2423. }
  2424. // length input
  2425. if ( !_stricmp( psznext, "-l" ) ||
  2426. !_stricmp( psznext, "/l" ) )
  2427. {
  2428. Argc--;
  2429. Argv++;
  2430. bufLength = strtoul( Argv[0], &pendString, 16 );
  2431. Argc--;
  2432. Argv++;
  2433. continue;
  2434. }
  2435. // sleep?
  2436. if ( !_stricmp( psznext, "-s" ) ||
  2437. !_stricmp( psznext, "/s" ) )
  2438. {
  2439. Argc--;
  2440. Argv++;
  2441. bsleep = TRUE;
  2442. continue;
  2443. }
  2444. // buffer
  2445. if ( !_stricmp( psznext, "-b" ) ||
  2446. !_stricmp( psznext, "/b" ) )
  2447. {
  2448. Argc--;
  2449. Argv++;
  2450. pbuffer = buffer;
  2451. bufLength = CONFIG_BUF_SIZE;
  2452. continue;
  2453. }
  2454. // adapter name
  2455. else
  2456. {
  2457. pwsadapter = DnsStringCopyAllocateEx(
  2458. Argv[0],
  2459. 0,
  2460. DnsCharSetAnsi, // ANSI in
  2461. DnsCharSetUnicode // unicode out
  2462. );
  2463. continue;
  2464. }
  2465. }
  2466. //
  2467. // query DNS config
  2468. //
  2469. sentBufLength = bufLength;
  2470. status = DnsQueryConfig(
  2471. config,
  2472. flag,
  2473. pwsadapter,
  2474. NULL,
  2475. pbuffer,
  2476. & bufLength );
  2477. if ( status == ERROR_SUCCESS )
  2478. {
  2479. printf(
  2480. "DnsQueryConfig() successful.\n"
  2481. "\tflag = 0x%.8X\n"
  2482. "\tadapter = %s\n"
  2483. "\tsent length = %d\n"
  2484. "\tlength required = %d\n",
  2485. flag,
  2486. pwsadapter,
  2487. sentBufLength,
  2488. bufLength );
  2489. if ( !pbuffer )
  2490. {
  2491. return( status );
  2492. }
  2493. printf(
  2494. "\tbuffer = %02x %02x %02x %02x ...\n",
  2495. pbuffer[0],
  2496. pbuffer[1],
  2497. pbuffer[2],
  2498. pbuffer[3] );
  2499. if ( flag & DNS_CONFIG_FLAG_ALLOC )
  2500. {
  2501. pbuffer = * (PVOID *) pbuffer;
  2502. }
  2503. switch( config )
  2504. {
  2505. case DnsConfigPrimaryDomainName_W:
  2506. printf(
  2507. "Primary domain name = %S\n",
  2508. pbuffer );
  2509. break;
  2510. case DnsConfigPrimaryDomainName_A:
  2511. case DnsConfigPrimaryDomainName_UTF8:
  2512. printf(
  2513. "Primary domain name = %s\n",
  2514. pbuffer );
  2515. break;
  2516. case DnsConfigDnsServerList:
  2517. DnsPrint_IpArray(
  2518. dnsup_PrintRoutine,
  2519. dnsup_PrintContext,
  2520. "DNS server list",
  2521. NULL,
  2522. (PIP_ARRAY) pbuffer );
  2523. break;
  2524. case DnsConfigPrimaryHostNameRegistrationEnabled:
  2525. printf(
  2526. "Is Primary registration enabled = %d\n",
  2527. *(PBOOL)pbuffer );
  2528. break;
  2529. case DnsConfigAdapterHostNameRegistrationEnabled:
  2530. printf(
  2531. "Is Adapter registration enabled = %d\n",
  2532. *(PBOOL)pbuffer );
  2533. break;
  2534. case DnsConfigAddressRegistrationMaxCount:
  2535. printf(
  2536. "Max IP registration count = %d\n",
  2537. *(PDWORD)pbuffer );
  2538. break;
  2539. default:
  2540. printf( "Unknown config %d", config );
  2541. }
  2542. }
  2543. else if ( status == ERROR_MORE_DATA )
  2544. {
  2545. printf(
  2546. "DnsQueryConfig() ERROR_MORE_DATA.\n"
  2547. "\tsent length = %d\n"
  2548. "\tlength required = %d\n",
  2549. sentBufLength,
  2550. bufLength );
  2551. }
  2552. else
  2553. {
  2554. printf(
  2555. "DnsQueryConfig() failed status = %d (0x%.8X).\n",
  2556. status, status );
  2557. }
  2558. if ( bsleep )
  2559. {
  2560. printf( "Sleeping" );
  2561. Sleep( MAXDWORD );
  2562. }
  2563. return( status );
  2564. Usage:
  2565. printf(
  2566. "usage:\n"
  2567. " DnsUp -config <Config> [-f <flag>] [-b] [-l <length>] [<adapter name>]\n"
  2568. );
  2569. return( ERROR_INVALID_PARAMETER );
  2570. }
  2571. DNS_STATUS
  2572. ProcessReplaceRecordSet(
  2573. IN DWORD Argc,
  2574. IN PSTR * Argv
  2575. )
  2576. {
  2577. DNS_STATUS status;
  2578. DWORD flags = 0;
  2579. PCHAR arg;
  2580. PDNS_RECORD prr = NULL;
  2581. HANDLE hCreds=NULL;
  2582. //
  2583. // flags?
  2584. //
  2585. if ( Argc < 1 )
  2586. {
  2587. goto Usage;
  2588. }
  2589. arg = Argv[0];
  2590. if ( strncmp( arg, "-f", 2 ) == 0 )
  2591. {
  2592. flags = strtoul( arg+2, NULL, 16 );
  2593. Argc--;
  2594. Argv++;
  2595. }
  2596. //
  2597. // build update packet RRs
  2598. //
  2599. prr = buildRecordList(
  2600. Argc,
  2601. Argv );
  2602. if ( !prr )
  2603. {
  2604. status = GetLastError();
  2605. if ( status != ERROR_SUCCESS )
  2606. {
  2607. printf( "ERROR: building records from arguments\n" );
  2608. goto Usage;
  2609. }
  2610. }
  2611. //
  2612. // build \ send update
  2613. //
  2614. status = DnsReplaceRecordSetA(
  2615. prr,
  2616. flags,
  2617. hCreds,
  2618. NULL, // no adapter list specified
  2619. NULL // reserved
  2620. );
  2621. Dns_RecordListFree( prr );
  2622. if ( status != ERROR_SUCCESS )
  2623. {
  2624. printf(
  2625. "DnsReplaceRecordSet failed, %x %s.\n",
  2626. status,
  2627. DnsStatusString(status) );
  2628. }
  2629. else
  2630. {
  2631. printf( "ReplaceRecordSet successfully completed.\n" );
  2632. }
  2633. return( status );
  2634. Usage:
  2635. Dns_RecordListFree( prr );
  2636. printf(
  2637. "usage:\n"
  2638. " DnsUp -rs [-f<Flags>] [<Record> | ...]\n"
  2639. " <Record> record for update packet\n"
  2640. " <Record> == (+)(u) <Name> <Type> [Data | ...]\n"
  2641. " <Name> - RR owner name\n"
  2642. " <Type> - record type (ex A, SRV, PTR, TXT, CNAME, etc.)\n"
  2643. " <Data> - data strings (type specific), if any\n"
  2644. );
  2645. return( ERROR_INVALID_PARAMETER );
  2646. }
  2647. DNS_STATUS
  2648. ProcessModifyRecordsInSet(
  2649. IN DWORD Argc,
  2650. IN PSTR * Argv
  2651. )
  2652. {
  2653. DNS_STATUS status;
  2654. DWORD flags = 0;
  2655. PCHAR arg;
  2656. PDNS_RECORD prr;
  2657. PDNS_RECORD prrAdd = NULL;
  2658. PDNS_RECORD prrDelete = NULL;
  2659. HANDLE hCreds=NULL;
  2660. INT addCount;
  2661. DNS_RRSET rrsetDelete;
  2662. DNS_RRSET rrsetAdd;
  2663. DNS_RRSET_INIT( rrsetAdd );
  2664. DNS_RRSET_INIT( rrsetDelete );
  2665. //
  2666. // flags?
  2667. //
  2668. if ( Argc < 1 )
  2669. {
  2670. goto Usage;
  2671. }
  2672. // flag?
  2673. arg = Argv[0];
  2674. if ( strncmp( arg, "-f", 2 ) == 0 )
  2675. {
  2676. flags = strtoul( arg+2, NULL, 16 );
  2677. Argc--;
  2678. Argv++;
  2679. }
  2680. //
  2681. // build update add RRs
  2682. //
  2683. prr = buildRecordList(
  2684. Argc,
  2685. Argv );
  2686. if ( !prr )
  2687. {
  2688. status = GetLastError();
  2689. if ( status != ERROR_SUCCESS )
  2690. {
  2691. printf( "ERROR: building records from arguments\n" );
  2692. goto Usage;
  2693. }
  2694. }
  2695. //
  2696. // build separate Add and Delete lists
  2697. //
  2698. while ( prr )
  2699. {
  2700. if ( prr->Flags.S.Delete )
  2701. {
  2702. DNS_RRSET_ADD( rrsetDelete, prr );
  2703. }
  2704. else
  2705. {
  2706. DNS_RRSET_ADD( rrsetAdd, prr );
  2707. }
  2708. prr = prr->pNext;
  2709. }
  2710. DNS_RRSET_TERMINATE( rrsetAdd );
  2711. DNS_RRSET_TERMINATE( rrsetDelete );
  2712. //
  2713. // build \ send update
  2714. //
  2715. status = DnsModifyRecordsInSet_A(
  2716. rrsetAdd.pFirstRR,
  2717. rrsetDelete.pFirstRR,
  2718. flags,
  2719. hCreds,
  2720. NULL, // no adapter list specified
  2721. NULL // reserved
  2722. );
  2723. Dns_RecordListFree( rrsetAdd.pFirstRR );
  2724. Dns_RecordListFree( rrsetDelete.pFirstRR );
  2725. if ( status != ERROR_SUCCESS )
  2726. {
  2727. printf(
  2728. "DnsModifyRecordsInSet failed, %x %s.\n",
  2729. status,
  2730. DnsStatusString(status) );
  2731. }
  2732. else
  2733. {
  2734. printf( "ModifyRecordsInSet successfully completed.\n" );
  2735. }
  2736. return( status );
  2737. Usage:
  2738. Dns_RecordListFree( rrsetAdd.pFirstRR );
  2739. Dns_RecordListFree( rrsetDelete.pFirstRR );
  2740. printf(
  2741. "usage:\n"
  2742. " DnsUp -mr [-f<Flags>] [<Record> | ...]\n"
  2743. " <Record> == (-,+)(u) <Name> <Type> [Data | ...]\n"
  2744. " (-,+) - add or delete, exist or no-exist flag\n"
  2745. " <Name> - RR owner name\n"
  2746. " <Type> - record type (ex A, SRV, PTR, TXT, CNAME, etc.)\n"
  2747. " <Data> - data strings (type specific), if any\n"
  2748. );
  2749. return( ERROR_INVALID_PARAMETER );
  2750. }
  2751. //
  2752. // Winsock \ RnR
  2753. //
  2754. //
  2755. // Protocol array for WSAQUERYSET
  2756. //
  2757. // DCR: may want to default to NULL instead?
  2758. //
  2759. AFPROTOCOLS g_ProtocolArray[2] =
  2760. {
  2761. { AF_INET, IPPROTO_UDP },
  2762. { AF_INET, IPPROTO_TCP }
  2763. };
  2764. //
  2765. // Service GUIDs
  2766. //
  2767. GUID HostNameGuid = SVCID_HOSTNAME;
  2768. GUID HostAddrByNameGuid = SVCID_INET_HOSTADDRBYNAME;
  2769. GUID AddressGuid = SVCID_INET_HOSTADDRBYINETSTRING;
  2770. GUID IANAGuid = SVCID_INET_SERVICEBYNAME;
  2771. typedef struct _GuidStringMap
  2772. {
  2773. LPGUID pGuid;
  2774. LPSTR pString;
  2775. };
  2776. struct _GuidStringMap GuidMapTable[] =
  2777. {
  2778. & HostNameGuid , "HostName" ,
  2779. & HostAddrByNameGuid , "AddrByName" ,
  2780. & HostAddrByNameGuid , "HostAddrByName" ,
  2781. & AddressGuid , "HostAddrByInetString" ,
  2782. & IANAGuid , "ServiceByName" ,
  2783. & IANAGuid , "Iana" ,
  2784. NULL , "NULL" ,
  2785. NULL , NULL ,
  2786. };
  2787. PGUID
  2788. guidForString(
  2789. IN PSTR pszGuidName
  2790. )
  2791. /*++
  2792. Routine Description:
  2793. Get GUID for string.
  2794. This is to allow simple specification of command line for GUIDs.
  2795. Arguments:
  2796. pszGuidName -- name of desired GUID
  2797. (see table above for current names of common guids)
  2798. Return Value:
  2799. Ptr to desired GUID if found.
  2800. Errors default to hostname (host lookup) GUID.
  2801. --*/
  2802. {
  2803. DWORD i;
  2804. PCHAR pname;
  2805. //
  2806. // if no guid name, use host name guid
  2807. //
  2808. if ( !pszGuidName )
  2809. {
  2810. return &HostNameGuid;
  2811. }
  2812. //
  2813. // find guid matching name in table
  2814. //
  2815. i = 0;
  2816. while ( pname = GuidMapTable[i].pString )
  2817. {
  2818. if ( _stricmp( pname, pszGuidName ) == 0 )
  2819. {
  2820. return GuidMapTable[i].pGuid;
  2821. }
  2822. i++;
  2823. }
  2824. // default to HostName guid
  2825. return &HostNameGuid;
  2826. }
  2827. //
  2828. // Parsing utility
  2829. //
  2830. typedef struct _RnRParseBlob
  2831. {
  2832. HANDLE Handle;
  2833. PCHAR pBuffer;
  2834. PWSAQUERYSET pQuerySet;
  2835. PGUID pGuid;
  2836. PSTR pName;
  2837. DWORD Flags;
  2838. DWORD NameSpace;
  2839. DWORD BufferLength;
  2840. }
  2841. RNR_PARSE_BLOB, *PRNR_PARSE_BLOB;
  2842. VOID
  2843. printRnRArgHelp(
  2844. VOID
  2845. )
  2846. /*++
  2847. Routine Description:
  2848. Print RnR argument usage.
  2849. Arguments:
  2850. None
  2851. Return Value:
  2852. None
  2853. --*/
  2854. {
  2855. //
  2856. // describe standard RnR lookup arguements
  2857. //
  2858. // DCR: add flag, ptr validity check
  2859. // DCR: add "already set" check for names and guids
  2860. // DCR: fix zero flag case below
  2861. //
  2862. printf(
  2863. "\tRnR Arguments:\n"
  2864. "\t\t-h<handle> -- ptr in hex to lookup handle\n"
  2865. "\t\t-b<buffer> -- ptr in hex to result buffer to use\n"
  2866. "\t\t-l<buf length> -- buffer length to use\n"
  2867. "\t\t-f<flag> -- RnR control flag in hex or LUP_X mneumonic\n"
  2868. "\t\t may be multiple flags specified\n"
  2869. "\t\t-q<query set> -- ptr in hex to existing WSAQUERYSET struct\n"
  2870. "\t\t-i<name space> -- name space id NS_X mneumonic\n"
  2871. "\t\t-a<name> -- ANSI lookup name\n"
  2872. "\t\t-g<guid> -- NS GUID mneumonic:\n"
  2873. "\t\t HostName\n"
  2874. "\t\t HostAddrByName\n"
  2875. "\t\t HostAddrByInetString\n"
  2876. "\t\t ServiceByName\n"
  2877. );
  2878. }
  2879. DNS_STATUS
  2880. parseForRnr(
  2881. IN DWORD Argc,
  2882. IN PSTR * Argv,
  2883. OUT PRNR_PARSE_BLOB pBlob
  2884. )
  2885. /*++
  2886. Routine Description:
  2887. Parse RnR routine command line params.
  2888. This is to simplify avoid duplicate parsing for various RnR
  2889. functions.
  2890. Arguments:
  2891. Argc -- argc
  2892. Argv -- argument array
  2893. pBlob -- ptr to RnR parsing blob to be filled by function
  2894. Return Value:
  2895. ERROR_SUCCESS if successful parsing.
  2896. ErrorCode on parsing error.
  2897. (Note, currently errors are ignored and whatever parsing is possible
  2898. is completed.)
  2899. --*/
  2900. {
  2901. PCHAR parg;
  2902. //
  2903. // init parse blob
  2904. //
  2905. RtlZeroMemory(
  2906. pBlob,
  2907. sizeof(RNR_PARSE_BLOB) );
  2908. //
  2909. // read arguments
  2910. //
  2911. // DCR: add flag, ptr validity check
  2912. // DCR: add "already set" check for names and guids
  2913. // DCR: fix zero flag case below
  2914. //
  2915. while ( Argc )
  2916. {
  2917. parg = Argv[0];
  2918. if ( strncmp( parg, "-h", 2 ) == 0 )
  2919. {
  2920. pBlob->Handle = (PVOID) (ULONG_PTR) strtoul( parg+2, NULL, 16 );
  2921. }
  2922. else if ( strncmp( parg, "-f", 2 ) == 0 )
  2923. {
  2924. DWORD thisFlag;
  2925. thisFlag = strtoul( parg+2, NULL, 16 );
  2926. if ( thisFlag == 0 )
  2927. {
  2928. thisFlag = Dns_RnrLupFlagForString( parg+2, 0 );
  2929. }
  2930. pBlob->Flags |= thisFlag;
  2931. }
  2932. else if ( strncmp( parg, "-b", 2 ) == 0 )
  2933. {
  2934. pBlob->pBuffer = (PBYTE) (ULONG_PTR) strtoul( parg+2, NULL, 16 );
  2935. }
  2936. else if ( strncmp( parg, "-l", 2 ) == 0 )
  2937. {
  2938. pBlob->BufferLength = strtoul( parg+2, NULL, 10 );
  2939. }
  2940. else if ( strncmp( parg, "-a", 2 ) == 0 )
  2941. {
  2942. pBlob->pName = parg+2;
  2943. }
  2944. else if ( strncmp( parg, "-g", 2 ) == 0 )
  2945. {
  2946. pBlob->pGuid = guidForString( parg+2 );
  2947. }
  2948. else if ( strncmp( parg, "-i", 2 ) == 0 )
  2949. {
  2950. pBlob->NameSpace = Dns_RnrNameSpaceIdForString(
  2951. parg+2,
  2952. 0 // length unknown
  2953. );
  2954. }
  2955. else if ( strncmp( parg, "-q", 2 ) == 0 )
  2956. {
  2957. pBlob->pQuerySet = (PWSAQUERYSET) (ULONG_PTR) strtoul( parg+2, NULL, 16 );
  2958. }
  2959. else if ( *parg=='?' || strncmp( parg, "-?", 2 ) == 0 )
  2960. {
  2961. goto Usage;
  2962. }
  2963. else
  2964. {
  2965. printf( "Unknown Arg = %s\n", parg );
  2966. goto Usage;
  2967. }
  2968. Argc--;
  2969. Argv++;
  2970. }
  2971. return( ERROR_SUCCESS );
  2972. Usage:
  2973. printRnRArgHelp();
  2974. return( ERROR_INVALID_PARAMETER );
  2975. }
  2976. PWSAQUERYSET
  2977. buildWsaQuerySet(
  2978. IN PRNR_PARSE_BLOB pBlob
  2979. )
  2980. /*++
  2981. Routine Description:
  2982. Create (allocate) a query set.
  2983. Arguments:
  2984. pBlob -- ptr to blob of parsing info
  2985. Return Value:
  2986. Ptr to new WSAQUERYSET struct.
  2987. NULL on allocation failure.
  2988. --*/
  2989. {
  2990. PWSAQUERYSET pwsaq;
  2991. //
  2992. // allocate
  2993. //
  2994. pwsaq = ALLOCATE_HEAP_ZERO( sizeof(WSAQUERYSET) );
  2995. if ( !pwsaq )
  2996. {
  2997. return( NULL );
  2998. }
  2999. //
  3000. // basic
  3001. // - default GUID to hostname lookup
  3002. //
  3003. pwsaq->dwSize = sizeof(WSAQUERYSET);
  3004. pwsaq->dwNumberOfProtocols = 2;
  3005. pwsaq->lpafpProtocols = g_ProtocolArray;
  3006. pwsaq->lpServiceClassId = & HostNameGuid;
  3007. //
  3008. // tack on info from blob
  3009. // - keep parsing generic by casting name to TSTR
  3010. //
  3011. if ( pBlob )
  3012. {
  3013. pwsaq->dwNameSpace = pBlob->NameSpace;
  3014. pwsaq->lpszServiceInstanceName = (LPTSTR) pBlob->pName;
  3015. pwsaq->lpServiceClassId = pBlob->pGuid;
  3016. }
  3017. return (PWSAQUERYSET) pwsaq;
  3018. }
  3019. DNS_STATUS
  3020. ProcessLookupServiceBegin(
  3021. IN DWORD Argc,
  3022. IN PSTR * Argv
  3023. )
  3024. {
  3025. DNS_STATUS status;
  3026. HANDLE handle = NULL;
  3027. PWSAQUERYSET pquerySet = NULL;
  3028. PWSAQUERYSET pquerySetLocal = NULL;
  3029. RNR_PARSE_BLOB blob;
  3030. //
  3031. // WSALookupServiceBegin
  3032. //
  3033. //
  3034. // parse args
  3035. //
  3036. status = parseForRnr( Argc, Argv, &blob );
  3037. if ( status != ERROR_SUCCESS )
  3038. {
  3039. goto Usage;
  3040. }
  3041. //
  3042. // setup query set
  3043. //
  3044. pquerySet = blob.pQuerySet;
  3045. if ( !pquerySet )
  3046. {
  3047. pquerySet = buildWsaQuerySet( &blob );
  3048. pquerySetLocal = pquerySet;
  3049. }
  3050. IF_DNSDBG( INIT )
  3051. {
  3052. DnsDbg_WsaQuerySet(
  3053. "Query set to WLSBegin",
  3054. pquerySet,
  3055. FALSE // currently ANSI
  3056. );
  3057. }
  3058. DnsPrint_WsaQuerySet(
  3059. dnsup_PrintRoutine,
  3060. dnsup_PrintContext,
  3061. "QuerySet to LookupServiceBegin",
  3062. (PWSAQUERYSET) pquerySet,
  3063. FALSE // ANSI call
  3064. );
  3065. //
  3066. // force winsock start
  3067. //
  3068. Dns_InitializeWinsock();
  3069. //
  3070. // call
  3071. //
  3072. status = WSALookupServiceBeginA(
  3073. pquerySet,
  3074. blob.Flags,
  3075. & handle );
  3076. if ( status != ERROR_SUCCESS )
  3077. {
  3078. status = GetLastError();
  3079. printf(
  3080. "WSALookupServiceBegin( %p, %08x, %p ) failed, %d %s.\n",
  3081. pquerySet,
  3082. blob.Flags,
  3083. & handle,
  3084. status,
  3085. DnsStatusString(status) );
  3086. if ( pquerySetLocal )
  3087. {
  3088. FREE_HEAP( pquerySetLocal );
  3089. }
  3090. }
  3091. else
  3092. {
  3093. printf(
  3094. "WSALookupServiceBegin() succeeded.\n"
  3095. "\thandle = %p\n"
  3096. "\tqueryset = %p\n",
  3097. handle,
  3098. pquerySet );
  3099. }
  3100. return( status );
  3101. Usage:
  3102. printf(
  3103. "WSALookupServiceBegin\n"
  3104. "usage:\n"
  3105. " DnsUp -lsb [RnR args]\n"
  3106. " note handle arg does not apply\n"
  3107. );
  3108. printRnRArgHelp();
  3109. return( ERROR_INVALID_PARAMETER );
  3110. }
  3111. DNS_STATUS
  3112. ProcessLookupServiceNext(
  3113. IN DWORD Argc,
  3114. IN PSTR * Argv
  3115. )
  3116. {
  3117. DNS_STATUS status;
  3118. HANDLE handle = NULL;
  3119. PCHAR pbuf = NULL;
  3120. PCHAR pbufLocal = NULL;
  3121. DWORD bufLength;
  3122. RNR_PARSE_BLOB blob;
  3123. //
  3124. // WSALookupServiceNext
  3125. //
  3126. //
  3127. // parse args
  3128. //
  3129. status = parseForRnr( Argc, Argv, &blob );
  3130. if ( status != ERROR_SUCCESS )
  3131. {
  3132. goto Usage;
  3133. }
  3134. //
  3135. // if no handle need to do WLSBegin
  3136. //
  3137. handle = blob.Handle;
  3138. if ( !handle )
  3139. {
  3140. goto Usage;
  3141. }
  3142. //
  3143. // setup buffer
  3144. //
  3145. bufLength = blob.BufferLength;
  3146. pbuf = blob.pBuffer;
  3147. if ( !pbuf && bufLength )
  3148. {
  3149. pbuf = ALLOCATE_HEAP( blob.BufferLength );
  3150. if ( !pbuf )
  3151. {
  3152. status = DNS_ERROR_NO_MEMORY;
  3153. }
  3154. pbufLocal = pbuf;
  3155. }
  3156. //
  3157. // call
  3158. //
  3159. printf(
  3160. "Enter WSALookupServiceNext()\n"
  3161. "\thandle = %p\n"
  3162. "\tflag = %08x\n"
  3163. "\tlength = %p (%d)\n"
  3164. "\tbuffer = %p\n",
  3165. handle,
  3166. blob.Flags,
  3167. &bufLength, bufLength,
  3168. pbuf );
  3169. status = WSALookupServiceNextA(
  3170. handle,
  3171. blob.Flags,
  3172. & bufLength,
  3173. (PWSAQUERYSETA) pbuf );
  3174. if ( status != ERROR_SUCCESS )
  3175. {
  3176. status = GetLastError();
  3177. printf(
  3178. "WSALookupServiceNext( h=%p, f=%08x, len=%d, buf=%p ) failed, %d %s.\n",
  3179. handle,
  3180. blob.Flags,
  3181. bufLength,
  3182. pbuf,
  3183. status,
  3184. DnsStatusString(status) );
  3185. if ( pbufLocal )
  3186. {
  3187. FREE_HEAP( pbufLocal );
  3188. }
  3189. }
  3190. else
  3191. {
  3192. printf(
  3193. "WSALookupServiceNext() succeeded.\n"
  3194. "\thandle = %p\n"
  3195. "\tbuf length = %d\n"
  3196. "\tpbuffer = %p\n",
  3197. handle,
  3198. bufLength,
  3199. pbuf );
  3200. if ( pbuf )
  3201. {
  3202. DnsPrint_WsaQuerySet(
  3203. dnsup_PrintRoutine,
  3204. dnsup_PrintContext,
  3205. "Result from LookupServiceNext",
  3206. (PWSAQUERYSET) pbuf,
  3207. FALSE // ANSI call
  3208. );
  3209. }
  3210. }
  3211. return( status );
  3212. Usage:
  3213. printf(
  3214. "WSALookupServiceNext\n"
  3215. "usage:\n"
  3216. " DnsUp -lsn [RnR args]\n"
  3217. " valid WSALookupServiceNext args:\n"
  3218. " <handle> <flags> <buffer> <buf length>\n"
  3219. " <handle> is required, call WSALookupServiceBegin\n"
  3220. " to get handle to use with this function\n"
  3221. );
  3222. printRnRArgHelp();
  3223. return( ERROR_INVALID_PARAMETER );
  3224. }
  3225. DNS_STATUS
  3226. ProcessLookupServiceEnd(
  3227. IN DWORD Argc,
  3228. IN PSTR * Argv
  3229. )
  3230. {
  3231. DNS_STATUS status;
  3232. HANDLE handle;
  3233. //
  3234. // WSALookupServiceEnd <handle>
  3235. //
  3236. if ( Argc < 1 )
  3237. {
  3238. goto Usage;
  3239. }
  3240. // read handle
  3241. //
  3242. // DCR: need QWORD read to handle win64 case
  3243. handle = (HANDLE) (UINT_PTR) strtoul( Argv[0], NULL, 16 );
  3244. //
  3245. // call
  3246. //
  3247. status = WSALookupServiceEnd( handle );
  3248. if ( status != ERROR_SUCCESS )
  3249. {
  3250. printf(
  3251. "WSALookupServiceEnd( %p ) failed, %d %s.\n",
  3252. handle,
  3253. status,
  3254. DnsStatusString(status) );
  3255. }
  3256. else
  3257. {
  3258. printf(
  3259. "WSALookupServiceEnd( %p ) succeeded.\n",
  3260. handle );
  3261. }
  3262. Dns_CleanupWinsock();
  3263. return( status );
  3264. Usage:
  3265. printf(
  3266. "WSALookupServiceEnd\n"
  3267. "usage:\n"
  3268. " DnsUp -lse -h<handle>\n"
  3269. " <handle> - lookup handle to close in hex.\n"
  3270. " handle is from prior WSALookupServiceBegin call.\n"
  3271. );
  3272. return( ERROR_INVALID_PARAMETER );
  3273. }
  3274. DNS_STATUS
  3275. ProcessGetHostName(
  3276. IN DWORD Argc,
  3277. IN PSTR * Argv
  3278. )
  3279. {
  3280. DNS_STATUS status;
  3281. CHAR nameBuffer[ DNS_MAX_NAME_BUFFER_LENGTH ];
  3282. DWORD length = DNS_MAX_NAME_BUFFER_LENGTH;
  3283. PCHAR pname = nameBuffer;
  3284. INT result;
  3285. //
  3286. // gethostname [-n<name>] [-l<length>]
  3287. //
  3288. if ( Argc > 2 )
  3289. {
  3290. goto Usage;
  3291. }
  3292. //
  3293. // get optional name or length
  3294. // - defaults to full size buffer above
  3295. //
  3296. while ( Argc )
  3297. {
  3298. PCHAR arg = Argv[0];
  3299. if ( strncmp( arg, "-n", 2 ) == 0 )
  3300. {
  3301. pname = getNamePointer( arg+2 );
  3302. Argc--;
  3303. Argv++;
  3304. }
  3305. else if ( strncmp( arg, "-l", 2 ) == 0 )
  3306. {
  3307. length = strtoul( arg+2, NULL, 10 );
  3308. Argc--;
  3309. Argv++;
  3310. }
  3311. else
  3312. {
  3313. goto Usage;
  3314. }
  3315. }
  3316. //
  3317. // force winsock start
  3318. //
  3319. Dns_InitializeWinsock();
  3320. //
  3321. // call
  3322. //
  3323. result = gethostname( (PSTR)pname, length );
  3324. if ( result != 0 )
  3325. {
  3326. status = GetLastError();
  3327. printf(
  3328. "gethostname(), %d (%x) %s.\n",
  3329. status, status,
  3330. DnsStatusString(status) );
  3331. }
  3332. else
  3333. {
  3334. printf(
  3335. "gethostname() successfully completed.\n"
  3336. "\tname = %s\n",
  3337. pname );
  3338. }
  3339. return( status );
  3340. Usage:
  3341. printf(
  3342. "gethostname\n"
  3343. "usage:\n"
  3344. " DnsUp -ghn [-n<Name>] [-l<length>]\n"
  3345. " <Name> - one of special names.\n"
  3346. " <Length> - buffer length to pass in\n"
  3347. " Defaults to valid name buffer of full DNS name length\n"
  3348. );
  3349. return( ERROR_INVALID_PARAMETER );
  3350. }
  3351. DNS_STATUS
  3352. ProcessGetHostByName(
  3353. IN DWORD Argc,
  3354. IN PSTR * Argv
  3355. )
  3356. {
  3357. DNS_STATUS status;
  3358. PCHAR pname;
  3359. PHOSTENT phost;
  3360. //
  3361. // gethostbyname <name>
  3362. //
  3363. if ( Argc != 1 )
  3364. {
  3365. goto Usage;
  3366. }
  3367. // name
  3368. pname = getNamePointer( Argv[0] );
  3369. //
  3370. // force winsock start
  3371. //
  3372. Dns_InitializeWinsock();
  3373. //
  3374. // call
  3375. //
  3376. phost = gethostbyname( (PCSTR)pname );
  3377. status = GetLastError();
  3378. if ( !phost )
  3379. {
  3380. printf(
  3381. "gethostbyname(), %x %s.\n",
  3382. status,
  3383. DnsStatusString(status) );
  3384. }
  3385. else
  3386. {
  3387. printf( "gethostbyname successfully completed.\n" );
  3388. DnsPrint_Hostent(
  3389. dnsup_PrintRoutine,
  3390. dnsup_PrintContext,
  3391. NULL, // default header
  3392. phost,
  3393. FALSE // ANSI
  3394. );
  3395. }
  3396. return( status );
  3397. Usage:
  3398. printf(
  3399. "gethostbyname\n"
  3400. "usage:\n"
  3401. " DnsUp -ghbn <Name>\n"
  3402. " <Name> - DNS name to query.\n"
  3403. " \"NULL\" for null input.\n"
  3404. " \"blank\" for blank (empty string)\n"
  3405. );
  3406. return( ERROR_INVALID_PARAMETER );
  3407. }
  3408. DNS_STATUS
  3409. ProcessGetHostByAddr(
  3410. IN DWORD Argc,
  3411. IN PSTR * Argv
  3412. )
  3413. {
  3414. DNS_STATUS status;
  3415. PCHAR pname;
  3416. PCHAR paddr;
  3417. PHOSTENT phost;
  3418. IP6_ADDRESS ip6;
  3419. INT length;
  3420. INT family;
  3421. //
  3422. // gethostbyaddr <ip> [len] [family]
  3423. //
  3424. if ( Argc < 1 || Argc > 3 )
  3425. {
  3426. goto Usage;
  3427. }
  3428. //
  3429. // address
  3430. //
  3431. pname = getNamePointer( Argv[0] );
  3432. Argc--;
  3433. Argv++;
  3434. length = sizeof(IP6_ADDRESS);
  3435. family = 0;
  3436. if ( pname
  3437. &&
  3438. Dns_StringToAddress_A(
  3439. (PCHAR) & ip6,
  3440. & length,
  3441. pname,
  3442. & family ) )
  3443. {
  3444. paddr = (PCHAR) &ip6;
  3445. }
  3446. else
  3447. {
  3448. paddr = pname;
  3449. length = sizeof(IP4_ADDRESS);
  3450. family = AF_INET;
  3451. }
  3452. // length -- optional
  3453. if ( Argc )
  3454. {
  3455. length = strtoul( Argv[0], NULL, 10 );
  3456. Argc--;
  3457. Argv++;
  3458. }
  3459. // family -- optional
  3460. if ( Argc )
  3461. {
  3462. family = strtoul( Argv[0], NULL, 10 );
  3463. Argc--;
  3464. Argv++;
  3465. }
  3466. //
  3467. // force winsock start
  3468. //
  3469. Dns_InitializeWinsock();
  3470. //
  3471. // call
  3472. //
  3473. printf(
  3474. "calling gethostbyaddr( %p, %d, %d )\n",
  3475. paddr,
  3476. length,
  3477. family );
  3478. phost = gethostbyaddr(
  3479. (PSTR)paddr,
  3480. length,
  3481. family );
  3482. status = GetLastError();
  3483. if ( !phost )
  3484. {
  3485. printf(
  3486. "gethostbyaddr(), %d %s.\n",
  3487. status,
  3488. DnsStatusString(status) );
  3489. }
  3490. else
  3491. {
  3492. printf( "gethostbyaddr successfully completed.\n" );
  3493. DnsPrint_Hostent(
  3494. dnsup_PrintRoutine,
  3495. dnsup_PrintContext,
  3496. NULL, // default header
  3497. phost,
  3498. FALSE // ANSI
  3499. );
  3500. }
  3501. return( status );
  3502. Usage:
  3503. printf(
  3504. "gethostbyaddr\n"
  3505. "usage:\n"
  3506. " DnsUp -ghba <Address> [<length>] [<family>]\n"
  3507. " <Name> - DNS name to query.\n"
  3508. " \"null\" for null input.\n"
  3509. " \"blank\" for blank (empty string)\n"
  3510. " [length] - length of address\n"
  3511. " defaults to sizeof(IP_ADDRESS)\n"
  3512. " [family] - address family\n"
  3513. " AF_INET = %d\n"
  3514. " AF_INET6 = %d\n"
  3515. " AF_ATM = %d\n"
  3516. " defaults to AF_INET\n",
  3517. AF_INET,
  3518. AF_INET6,
  3519. AF_ATM );
  3520. return( ERROR_INVALID_PARAMETER );
  3521. }
  3522. DNS_STATUS
  3523. ProcessGetAddrInfo(
  3524. IN DWORD Argc,
  3525. IN PSTR * Argv
  3526. )
  3527. {
  3528. DNS_STATUS status;
  3529. PCHAR pname;
  3530. PSTR pservice = NULL;
  3531. PADDRINFO phint = NULL;
  3532. PADDRINFO paddrInfo = NULL;
  3533. ADDRINFO hintAddrInfo;
  3534. BOOL fhint = FALSE;
  3535. INT result;
  3536. //
  3537. // getaddrinfo <name> [service] [hints]
  3538. //
  3539. if ( Argc < 1 )
  3540. {
  3541. goto Usage;
  3542. }
  3543. //
  3544. // name
  3545. //
  3546. pname = getNamePointer( Argv[0] );
  3547. Argc--;
  3548. Argv++;
  3549. //
  3550. // setup hints
  3551. // - default flags to include canonnical name
  3552. //
  3553. RtlZeroMemory(
  3554. & hintAddrInfo,
  3555. sizeof(hintAddrInfo) );
  3556. hintAddrInfo.ai_flags = AI_CANONNAME;
  3557. //
  3558. // get optional service name or hints
  3559. //
  3560. while ( Argc )
  3561. {
  3562. PCHAR arg = Argv[0];
  3563. if ( strncmp( arg, "-s", 2 ) == 0 )
  3564. {
  3565. pservice = getNamePointer( arg+2 );
  3566. Argc--;
  3567. Argv++;
  3568. }
  3569. if ( strncmp( arg, "-h", 2 ) == 0 )
  3570. {
  3571. fhint = TRUE;
  3572. Argc--;
  3573. Argv++;
  3574. }
  3575. else if ( strncmp( arg, "-f", 2 ) == 0 )
  3576. {
  3577. hintAddrInfo.ai_flags = strtoul( arg+2, NULL, 16 );
  3578. fhint = TRUE;
  3579. Argc--;
  3580. Argv++;
  3581. }
  3582. else if ( strncmp( arg, "-m", 2 ) == 0 )
  3583. {
  3584. hintAddrInfo.ai_family = strtoul( arg+2, NULL, 10 );
  3585. fhint = TRUE;
  3586. Argc--;
  3587. Argv++;
  3588. }
  3589. else if ( strncmp( arg, "-t", 2 ) == 0 )
  3590. {
  3591. hintAddrInfo.ai_socktype = strtoul( arg+2, NULL, 10 );
  3592. fhint = TRUE;
  3593. Argc--;
  3594. Argv++;
  3595. }
  3596. else if ( strncmp( arg, "-p", 2 ) == 0 )
  3597. {
  3598. hintAddrInfo.ai_protocol = strtoul( arg+2, NULL, 10 );
  3599. fhint = TRUE;
  3600. Argc--;
  3601. Argv++;
  3602. }
  3603. else if ( strncmp( arg, "-l", 2 ) == 0 )
  3604. {
  3605. hintAddrInfo.ai_addrlen = strtoul( arg+2, NULL, 10 );
  3606. fhint = TRUE;
  3607. Argc--;
  3608. Argv++;
  3609. }
  3610. else
  3611. {
  3612. goto Usage;
  3613. }
  3614. }
  3615. //
  3616. // setup hints
  3617. //
  3618. if ( fhint )
  3619. {
  3620. phint = &hintAddrInfo;
  3621. }
  3622. //
  3623. // force winsock start
  3624. //
  3625. Dns_InitializeWinsock();
  3626. //
  3627. // call
  3628. //
  3629. printf(
  3630. "calling getaddrinfo()\n"
  3631. "\tpname = %s\n"
  3632. "\tpservice = %s\n"
  3633. "\tphint = %p\n"
  3634. "\tpaddrinfo buf = %p\n",
  3635. pname,
  3636. pservice,
  3637. phint,
  3638. paddrInfo );
  3639. if ( phint )
  3640. {
  3641. DnsPrint_AddrInfo(
  3642. dnsup_PrintRoutine,
  3643. dnsup_PrintContext,
  3644. "hint addrinfo",
  3645. 1, // indent
  3646. phint
  3647. );
  3648. }
  3649. result = getaddrinfo(
  3650. pname,
  3651. pservice,
  3652. phint,
  3653. & paddrInfo );
  3654. status = GetLastError();
  3655. if ( result != NO_ERROR )
  3656. {
  3657. printf(
  3658. "getaddrinfo(), %x %s.\n",
  3659. status,
  3660. DnsStatusString(status) );
  3661. }
  3662. else
  3663. {
  3664. printf( "getaddrinfo successfully completed.\n" );
  3665. DnsPrint_AddrInfo(
  3666. dnsup_PrintRoutine,
  3667. dnsup_PrintContext,
  3668. NULL, // default header
  3669. 0, // no indent
  3670. paddrInfo
  3671. );
  3672. freeaddrinfo( paddrInfo );
  3673. }
  3674. return( status );
  3675. Usage:
  3676. printf(
  3677. "getaddrinfo\n"
  3678. "usage:\n"
  3679. " DnsUp -gai <Name> [-s<Service>] [-h] [-f<flags>] [-m<family>]\n"
  3680. " [-p<Protocol>] [-t<SockType>] [-l<length>]\n"
  3681. " <Name> - DNS name to query.\n"
  3682. " \"null\" for null input.\n"
  3683. " \"blank\" for blank (empty string)\n"
  3684. " <Service> - service name to query for.\n"
  3685. " [-h] - use hints (this allows empty hint buffer\n"
  3686. " <flags> - hint flags\n"
  3687. " AI_PASSIVE = %0x\n"
  3688. " AI_CANONNAME = %0x\n"
  3689. " AI_NUMERICHOST = %0x\n"
  3690. " <family> - hint family\n"
  3691. " AF_INET = %d\n"
  3692. " AF_INET6 = %d\n"
  3693. " AF_ATM = %d\n"
  3694. " <socktype> - hint socket type\n"
  3695. " <protocol> - hint protocol\n"
  3696. " <length> - hint address length\n",
  3697. AI_PASSIVE,
  3698. AI_CANONNAME,
  3699. AI_NUMERICHOST,
  3700. AF_INET,
  3701. AF_INET6,
  3702. AF_ATM );
  3703. return( ERROR_INVALID_PARAMETER );
  3704. }
  3705. DNS_STATUS
  3706. ProcessGetNameInfo(
  3707. IN DWORD Argc,
  3708. IN PSTR * Argv
  3709. )
  3710. {
  3711. DNS_STATUS status;
  3712. BOOL result;
  3713. PCHAR paddr = NULL;
  3714. DWORD addrLength;
  3715. DWORD family;
  3716. DWORD flags = 0;
  3717. SOCKADDR_IN6 sockaddr;
  3718. CHAR hostBuffer[ DNS_MAX_NAME_BUFFER_LENGTH ];
  3719. CHAR serviceBuffer[ DNS_MAX_NAME_BUFFER_LENGTH ];
  3720. PSOCKADDR_IN6 psockaddr = &sockaddr;
  3721. PCHAR pservice = serviceBuffer;
  3722. PCHAR phost = hostBuffer;
  3723. DWORD sockaddrLength = sizeof(sockaddr);
  3724. DWORD serviceLength = sizeof(hostBuffer);
  3725. DWORD hostLength = DNS_MAX_NAME_BUFFER_LENGTH;
  3726. //
  3727. // getnameinfo <address> [sockaddr fields | args]
  3728. //
  3729. if ( Argc < 1 )
  3730. {
  3731. goto Usage;
  3732. }
  3733. //
  3734. // address
  3735. //
  3736. RtlZeroMemory(
  3737. psockaddr,
  3738. sizeof(*psockaddr) );
  3739. #if 0
  3740. if ( getAddressPointer(
  3741. Argv[0],
  3742. & paddr,
  3743. & addrLength,
  3744. & family ) )
  3745. {
  3746. sockaddr.sin6_family = (SHORT) family;
  3747. if ( family == AF_INET )
  3748. {
  3749. RtlCopyMemory(
  3750. & ((PSOCKADDR_IN)psockaddr)->sin_addr,
  3751. paddr,
  3752. addrLength );
  3753. sockaddrLength = sizeof(SOCKADDR_IN);
  3754. }
  3755. else // IP6
  3756. {
  3757. RtlCopyMemory(
  3758. & psockaddr->sin6_addr,
  3759. paddr,
  3760. addrLength );
  3761. sockaddrLength = sizeof(SOCKADDR_IN6);
  3762. }
  3763. }
  3764. else // special bogus address, use it directly
  3765. {
  3766. psockaddr = (PSOCKADDR_IN6) paddr;
  3767. }
  3768. #endif
  3769. if ( getAddressPointer(
  3770. Argv[0],
  3771. & paddr,
  3772. & addrLength,
  3773. & family ) )
  3774. {
  3775. status = Dns_AddressToSockaddr(
  3776. (PSOCKADDR) &sockaddr,
  3777. & sockaddrLength,
  3778. TRUE, // clear
  3779. paddr,
  3780. addrLength,
  3781. family );
  3782. if ( status != NO_ERROR )
  3783. {
  3784. goto Usage;
  3785. }
  3786. }
  3787. else // special bogus address, use it directly
  3788. {
  3789. psockaddr = (PSOCKADDR_IN6) paddr;
  3790. }
  3791. Argc--;
  3792. Argv++;
  3793. //
  3794. // get sockaddr fields or optional arguments
  3795. // - note, if using bogus sockaddr, the sockaddr tweaks are lost
  3796. //
  3797. while ( Argc )
  3798. {
  3799. PCHAR arg = Argv[0];
  3800. // flags
  3801. if ( strncmp( arg, "-f", 2 ) == 0 )
  3802. {
  3803. flags = strtoul( arg+2, NULL, 16 );
  3804. Argc--;
  3805. Argv++;
  3806. }
  3807. // sockaddr subfields
  3808. else if ( strncmp( arg, "-m", 2 ) == 0 )
  3809. {
  3810. sockaddr.sin6_family = (SHORT) strtoul( arg+2, NULL, 10 );
  3811. Argc--;
  3812. Argv++;
  3813. }
  3814. else if ( strncmp( arg, "-p", 2 ) == 0 )
  3815. {
  3816. sockaddr.sin6_port = (SHORT) strtoul( arg+2, NULL, 10 );
  3817. Argc--;
  3818. Argv++;
  3819. }
  3820. // tweak out params
  3821. else if ( strncmp( arg, "-sl", 3 ) == 0 )
  3822. {
  3823. serviceLength = strtoul( arg+3, NULL, 10 );
  3824. Argc--;
  3825. Argv++;
  3826. }
  3827. else if ( _strnicmp( arg, "-snull", 5 ) == 0 )
  3828. {
  3829. pservice = NULL;
  3830. Argc--;
  3831. Argv++;
  3832. }
  3833. else if ( strncmp( arg, "-hl", 3 ) == 0 )
  3834. {
  3835. hostLength = strtoul( arg+3, NULL, 10 );
  3836. Argc--;
  3837. Argv++;
  3838. }
  3839. else if ( _strnicmp( arg, "-hnull", 5 ) == 0 )
  3840. {
  3841. phost = NULL;
  3842. Argc--;
  3843. Argv++;
  3844. }
  3845. else
  3846. {
  3847. goto Usage;
  3848. }
  3849. }
  3850. //
  3851. // force winsock start
  3852. //
  3853. Dns_InitializeWinsock();
  3854. //
  3855. // call
  3856. //
  3857. printf(
  3858. "Calling getnameinfo()\n"
  3859. "\tsockaddr %p\n"
  3860. "\tsockaddr len %d\n"
  3861. "\thost buffer %p\n"
  3862. "\thost buflen %d\n"
  3863. "\tservice buffer %p\n"
  3864. "\tservice buflen %d\n"
  3865. "\tflags %08x\n",
  3866. psockaddr,
  3867. sockaddrLength,
  3868. phost,
  3869. hostLength,
  3870. pservice,
  3871. serviceLength,
  3872. flags );
  3873. DnsPrint_Sockaddr(
  3874. dnsup_PrintRoutine,
  3875. dnsup_PrintContext,
  3876. "\n\tsockaddr",
  3877. 1, // indent
  3878. (PSOCKADDR) psockaddr,
  3879. sockaddrLength );
  3880. result = getnameinfo(
  3881. (PSOCKADDR) psockaddr,
  3882. sockaddrLength,
  3883. phost,
  3884. hostLength,
  3885. pservice,
  3886. serviceLength,
  3887. flags );
  3888. status = GetLastError();
  3889. if ( result != NO_ERROR )
  3890. {
  3891. printf(
  3892. "getnameinfo(), %x %s.\n",
  3893. status,
  3894. DnsStatusString(status) );
  3895. }
  3896. else
  3897. {
  3898. printf(
  3899. "getnameinfo successfully completed.\n"
  3900. "\thost = %s\n"
  3901. "\tservice = %s\n",
  3902. phost,
  3903. pservice );
  3904. }
  3905. return( status );
  3906. Usage:
  3907. printf(
  3908. "getnameinfo\n"
  3909. "usage:\n"
  3910. " DnsUp -gni <Address> [-s<Service>] [-f<flags>] [-m<family>]\n"
  3911. " [-p<port>] [-sl<length>] [-snull] [-hl<length>] [-hnull]\n"
  3912. " <Address> - Address string to query name for.\n"
  3913. " \"null\" for null input.\n"
  3914. " \"blank\" for blank (empty string)\n"
  3915. " <flags> - hint flags\n"
  3916. " AI_PASSIVE = %0x\n"
  3917. " AI_CANONNAME = %0x\n"
  3918. " AI_NUMERICHOST = %0x\n"
  3919. " <family> - sockaddr family, overrides default for address;\n"
  3920. " AF_INET = %d\n"
  3921. " AF_INET6 = %d\n"
  3922. " AF_ATM = %d\n"
  3923. " <port> - port to set in sockaddr; defaults to zero\n"
  3924. " <length> - length of out buffer\n"
  3925. " -sl<length> - length of service name buffer\n"
  3926. " -hl<length> - length of host name buffer\n"
  3927. " [-snull] - server buffer ptr NULL\n"
  3928. " [-hnull] - host buffer ptr NULL\n",
  3929. AI_PASSIVE,
  3930. AI_CANONNAME,
  3931. AI_NUMERICHOST,
  3932. AF_INET,
  3933. AF_INET6,
  3934. AF_ATM );
  3935. return( ERROR_INVALID_PARAMETER );
  3936. }
  3937. DNS_STATUS
  3938. ProcessClusterIp(
  3939. IN DWORD Argc,
  3940. IN PSTR * Argv
  3941. )
  3942. {
  3943. SOCKADDR_IN6 sockaddr;
  3944. PSOCKADDR psockaddr = (PSOCKADDR) &sockaddr;
  3945. DWORD sockaddrLength = sizeof(sockaddr);
  3946. IP_ADDRESS ip;
  3947. BOOL fadd = TRUE;
  3948. PWSTR pname = NULL;
  3949. DNS_STATUS status;
  3950. //
  3951. // -ci <Name> <IP> [-d]
  3952. //
  3953. if ( Argc < 1 )
  3954. {
  3955. goto Usage;
  3956. }
  3957. //
  3958. // name
  3959. //
  3960. pname = (PWSTR) Dns_StringCopyAllocate(
  3961. Argv[0],
  3962. 0, // unknown length
  3963. DnsCharSetAnsi,
  3964. DnsCharSetUnicode );
  3965. Argc--;
  3966. Argv++;
  3967. //
  3968. // cluster IP
  3969. //
  3970. #if 0
  3971. ip = inet_addr( Argv[0] );
  3972. if ( ip == (-1) )
  3973. {
  3974. goto Usage;
  3975. }
  3976. Argc--;
  3977. Argv++;
  3978. #endif
  3979. if ( !getSockaddrFromString(
  3980. & psockaddr,
  3981. & sockaddrLength,
  3982. Argv[0] ) )
  3983. {
  3984. goto Usage;
  3985. }
  3986. Argc--;
  3987. Argv++;
  3988. //
  3989. // optional delete flag
  3990. //
  3991. if ( Argc > 0 )
  3992. {
  3993. if ( strncmp( Argv[0], "-d", 2 ) == 0 )
  3994. {
  3995. fadd = FALSE;
  3996. Argc--;
  3997. Argv++;
  3998. }
  3999. if ( Argc != 0 )
  4000. {
  4001. goto Usage;
  4002. }
  4003. }
  4004. //
  4005. // notify resolver
  4006. //
  4007. status = DnsRegisterClusterAddress(
  4008. 0xd734453d,
  4009. pname,
  4010. psockaddr,
  4011. fadd );
  4012. FREE_HEAP( pname );
  4013. return( status );
  4014. Usage:
  4015. printf(
  4016. "Set Cluster IP\n"
  4017. "usage:\n"
  4018. " DnsUp [-ci] <Name> <IP> [-d]\n"
  4019. " <Name> is cluster name\n"
  4020. " <IP> is cluster IP\n"
  4021. " [-d] to indicate delete of cluster IP\n"
  4022. );
  4023. FREE_HEAP( pname );
  4024. return( ERROR_INVALID_PARAMETER );
  4025. }
  4026. #if 0
  4027. DNS_STATUS
  4028. ProcessAddIp(
  4029. IN DWORD Argc,
  4030. IN PSTR * Argv
  4031. )
  4032. {
  4033. IP_ADDRESS ip;
  4034. BOOL fadd = TRUE;
  4035. //
  4036. // -addip <IP>
  4037. //
  4038. if ( Argc < 1 )
  4039. {
  4040. goto Usage;
  4041. }
  4042. //
  4043. // IP to add
  4044. //
  4045. ip = inet_addr( Argv[0] );
  4046. if ( ip == (-1) )
  4047. {
  4048. goto Usage;
  4049. }
  4050. Argc--;
  4051. Argv++;
  4052. //
  4053. // optional delete flag
  4054. //
  4055. if ( Argc > 0 )
  4056. {
  4057. if ( strncmp( Argv[0], "-d", 2 ) == 0 )
  4058. {
  4059. fadd = FALSE;
  4060. Argc--;
  4061. Argv++;
  4062. }
  4063. if ( Argc != 0 )
  4064. {
  4065. goto Usage;
  4066. }
  4067. }
  4068. //
  4069. // notify resolver
  4070. //
  4071. DnsNotifyResolverClusterIp(
  4072. ip,
  4073. fadd );
  4074. return( ERROR_SUCCESS );
  4075. Usage:
  4076. printf(
  4077. "usage:\n"
  4078. " DnsUp [-ci] <IP> [-d]\n"
  4079. " <IP> is cluster IP\n"
  4080. " [-d] to indicate delete of cluster IP\n"
  4081. );
  4082. return( ERROR_INVALID_PARAMETER );
  4083. }
  4084. #endif
  4085. DNS_STATUS
  4086. ProcessSetEnvironmentVariable(
  4087. IN DWORD Argc,
  4088. IN PSTR * Argv
  4089. )
  4090. {
  4091. //
  4092. // setenv <name> <value>
  4093. //
  4094. if ( Argc < 1 || Argc > 2 )
  4095. {
  4096. goto Usage;
  4097. }
  4098. SetEnvironmentVariableA(
  4099. Argv[0],
  4100. (Argc == 2) ? Argv[1] : NULL );
  4101. return( ERROR_SUCCESS );
  4102. Usage:
  4103. printf(
  4104. "Set environment variable\n"
  4105. "usage:\n"
  4106. " DnsUp [-setenv] <name> [<value>]\n"
  4107. " <name> name of environment variable\n"
  4108. " <value> value of environment variable, if missing\n"
  4109. " then environment variable is deleted\n"
  4110. );
  4111. return( ERROR_INVALID_PARAMETER );
  4112. }
  4113. //
  4114. // Command Table
  4115. //
  4116. // Keep this down here to avoid having prototypes for
  4117. // all these functions.
  4118. //
  4119. COMMAND_INFO GlobalCommandInfo[] =
  4120. {
  4121. // query
  4122. { "qex" , "QueryEx" , ProcessQueryEx },
  4123. { "qc" , "QueryCompare" , ProcessQueryCompare },
  4124. { "q" , "Query" , ProcessQuery },
  4125. { "qm" , "QueryMulitple" , ProcessQueryMultiple },
  4126. { "qt" , "QueryTest" , ProcessQueryTest },
  4127. { "iq" , "IQuery" , ProcessIQuery },
  4128. // update
  4129. { "u" , "Update" , ProcessUpdate },
  4130. { "ut" , "UpdateTest" , ProcessUpdateTest },
  4131. //{ "um" , "UpdateMultiple" , ProcessUpdateMultiple },
  4132. { "dt" , "DhcpTest" , ProcessDhcpTest },
  4133. { "mr" , "ModifyRecordsInSet" , ProcessModifyRecordsInSet },
  4134. { "rs" , "ReplaceRecordSet" , ProcessReplaceRecordSet },
  4135. // utility
  4136. { "vn" , "ValidateName" , ProcessValidateName },
  4137. { "s" , "StringTranslate" , ProcessStringTranslate },
  4138. { "cn" , "NameCompare" , ProcessNameCompare },
  4139. { "cnx" , "NameCompareEx" , ProcessNameCompareEx },
  4140. { "config" , "QueryConfig" , ProcessQueryConfig },
  4141. // config
  4142. { "setenv" , "SetEnvironmentVariable", ProcessSetEnvironmentVariable },
  4143. // resolver
  4144. { "ci" , "ClusterIp" , ProcessClusterIp },
  4145. // RnR
  4146. { "ghn" , "gethostname" , ProcessGetHostName },
  4147. { "ghbn" , "gethostbyname" , ProcessGetHostByName },
  4148. { "ghba" , "gethostbyaddr" , ProcessGetHostByAddr },
  4149. { "gai" , "getaddrinfo" , ProcessGetAddrInfo },
  4150. { "gni" , "getnameinfo" , ProcessGetNameInfo },
  4151. { "lsb" , "LookupServiceBegin" , ProcessLookupServiceBegin },
  4152. { "lsn" , "LookupServiceNext" , ProcessLookupServiceNext },
  4153. { "lse" , "LookupServiceEnd" , ProcessLookupServiceEnd },
  4154. // quit
  4155. { "quit" , "Quit" , ProcessQuit },
  4156. { "exit" , "Quit" , ProcessQuit },
  4157. { NULL, NULL, NULL },
  4158. };
  4159. //
  4160. // End dnsup.c
  4161. //