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.

5053 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 "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 = Dns_GetDnsServerList( FALSE );
  941. }
  942. if ( !aipservers )
  943. {
  944. printf( "Update failed: no DNS server list available.\n" );
  945. return( GetLastError() );
  946. }
  947. //
  948. // flags?
  949. //
  950. if ( Argc < 1 )
  951. {
  952. goto Usage;
  953. }
  954. arg = Argv[0];
  955. if ( strncmp( arg, "-f", 2 ) == 0 )
  956. {
  957. flags = strtoul( arg+2, NULL, 16 );
  958. Argc--;
  959. Argv++;
  960. }
  961. //
  962. // security -- then need target server name
  963. // presence of server name automatically turns on security
  964. //
  965. if ( Argc < 1 )
  966. {
  967. goto Usage;
  968. }
  969. arg = Argv[0];
  970. if ( strncmp( arg, "-s", 2 ) == 0 )
  971. {
  972. pszserverName = arg+2;
  973. flags |= DNS_UPDATE_SECURITY_ONLY;
  974. Argc--;
  975. Argv++;
  976. }
  977. //
  978. // name of zone to update
  979. //
  980. if ( Argc < 1 )
  981. {
  982. goto Usage;
  983. }
  984. arg = Argv[0];
  985. if ( *arg != '-' && *arg != '+' )
  986. {
  987. pszzone = arg;
  988. DNSDBG( INIT, (
  989. "Read update zone name %s\n",
  990. pszzone ));
  991. Argc--;
  992. Argv++;
  993. }
  994. //
  995. // build update packet RRs
  996. //
  997. prr = buildRecordList(
  998. Argc,
  999. Argv );
  1000. if ( !prr )
  1001. {
  1002. status = GetLastError();
  1003. if ( status != ERROR_SUCCESS )
  1004. {
  1005. printf( "ERROR: building records from arguments\n" );
  1006. goto Usage;
  1007. }
  1008. }
  1009. //
  1010. // build \ send update
  1011. //
  1012. status = Dns_UpdateLibEx(
  1013. prr,
  1014. flags,
  1015. pszzone,
  1016. pszserverName,
  1017. aipservers,
  1018. NULL,
  1019. &pmsgRecv
  1020. );
  1021. if ( pmsgRecv )
  1022. {
  1023. DnsPrint_Message(
  1024. dnsup_PrintRoutine,
  1025. dnsup_PrintContext,
  1026. "Update response:\n",
  1027. pmsgRecv );
  1028. }
  1029. FREE_HEAP( aipservers );
  1030. Dns_RecordListFree( prr );
  1031. FREE_HEAP( pmsg );
  1032. FREE_HEAP( pmsgRecv );
  1033. if( status != ERROR_SUCCESS )
  1034. {
  1035. printf(
  1036. "DnsUpdateEx failed, %x %s.\n",
  1037. status,
  1038. DnsStatusString(status) );
  1039. }
  1040. else
  1041. {
  1042. printf( "Update successfully completed.\n" );
  1043. }
  1044. return( status );
  1045. Usage:
  1046. FREE_HEAP( aipservers );
  1047. Dns_RecordListFree( prr );
  1048. FREE_HEAP( pmsg );
  1049. FREE_HEAP( pmsgRecv );
  1050. printf(
  1051. "UpdateTest -- Dns_UpdateLibEx\n"
  1052. "usage:\n"
  1053. " DnsUp [-n<DNS IP>|...] -ut [-f<Flags>] [-s<ServerName>] [<ZoneName>] [<Record> | ...]\n"
  1054. " <DNS IP> optional IP address of server to send update to.\n"
  1055. " <ServerName> name of DNS server we are sending update to;\n"
  1056. " presence of server name automatically turns on update security\n"
  1057. " <ZoneName> name of zone to update\n"
  1058. " <Record> record for update packet\n"
  1059. " <Record> == (-,+)(p,u,a) <Name> <Type> [Data | ...]\n"
  1060. " (-,+) - add or delete, exist or no-exist flag\n"
  1061. " (p,u,a) - prereq, update or additional section\n"
  1062. " <Name> - RR owner name\n"
  1063. " <Type> - record type (ex A, SRV, PTR, TXT, CNAME, etc.)\n"
  1064. " <Data> - data strings (type specific), if any\n"
  1065. );
  1066. return( ERROR_INVALID_PARAMETER );
  1067. }
  1068. DNS_STATUS
  1069. ProcessDhcpTest(
  1070. IN DWORD Argc,
  1071. IN PSTR * Argv
  1072. )
  1073. {
  1074. DNS_STATUS status;
  1075. REGISTER_HOST_ENTRY hostEntry;
  1076. REGISTER_HOST_STATUS hostStatus;
  1077. HANDLE doneEvent;
  1078. //
  1079. // create completion event
  1080. //
  1081. doneEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  1082. //
  1083. // build dumpy DHCP update
  1084. //
  1085. hostEntry.Addr.ipAddr = 0x01010101;
  1086. hostEntry.dwOptions = REGISTER_HOST_A;
  1087. hostStatus.hDoneEvent = doneEvent;
  1088. //
  1089. // send to DHCP DynDNS update routine
  1090. //
  1091. status = DnsAsyncRegisterHostAddrs(
  1092. L"El59x1",
  1093. L"testdhcpname",
  1094. &hostEntry,
  1095. 1, // address count
  1096. NULL, // no regkey with previous
  1097. 0,
  1098. L"nttest.microsoft.com",
  1099. & hostStatus,
  1100. 60, // TTL
  1101. 0
  1102. );
  1103. if( status != ERROR_SUCCESS )
  1104. {
  1105. printf(
  1106. "DnsAsynRegisterHostAddrs_W() %s.\n",
  1107. status,
  1108. DnsStatusString(status) );
  1109. return( status );
  1110. }
  1111. printf( "DHCP DynDNS registration successfully completed.\n" );
  1112. WaitForSingleObject(
  1113. doneEvent,
  1114. INFINITE );
  1115. return( status );
  1116. }
  1117. //
  1118. // Query routines
  1119. //
  1120. DNS_STATUS
  1121. ProcessQueryEx(
  1122. IN DWORD Argc,
  1123. IN PSTR * Argv
  1124. )
  1125. {
  1126. DNS_STATUS status;
  1127. PCHAR pszname;
  1128. WORD type;
  1129. DWORD flags = 0;
  1130. PDNS_MSG_BUF pmsgRecv = NULL;
  1131. HANDLE hevent = NULL;
  1132. DNS_QUERY_INFO queryInfo;
  1133. //
  1134. // name to query
  1135. //
  1136. if ( Argc < 2 || Argc > 4 )
  1137. {
  1138. goto Usage;
  1139. }
  1140. pszname = Argv[0];
  1141. Argc--;
  1142. Argv++;
  1143. //
  1144. // type
  1145. //
  1146. type = DnsRecordTypeForName( Argv[0], 0 );
  1147. if ( type == 0 )
  1148. {
  1149. goto Usage;
  1150. }
  1151. Argc--;
  1152. Argv++;
  1153. //
  1154. // flags and options
  1155. //
  1156. while ( Argc )
  1157. {
  1158. if ( _stricmp( Argv[0], "-a" ) == 0 )
  1159. {
  1160. hevent = CreateEvent( NULL, FALSE, FALSE, NULL );
  1161. }
  1162. else
  1163. {
  1164. flags = strtoul( Argv[0], NULL, 16 );
  1165. }
  1166. Argc--;
  1167. Argv++;
  1168. }
  1169. //
  1170. // query
  1171. //
  1172. RtlZeroMemory(
  1173. & queryInfo,
  1174. sizeof(queryInfo) );
  1175. queryInfo.pName = pszname;
  1176. queryInfo.Type = type;
  1177. queryInfo.Flags = flags;
  1178. queryInfo.pDnsServers = pDnsServerArray;
  1179. queryInfo.hEvent = hevent;
  1180. status = DnsQueryEx( &queryInfo );
  1181. if ( status == ERROR_IO_PENDING )
  1182. {
  1183. printf(
  1184. "DnsQueryEx() running asynchronously.\n"
  1185. "\tEvent = %p\n",
  1186. hevent );
  1187. WaitForSingleObject( hevent, INFINITE );
  1188. printf( "DnsQueryEx() async completion.\n" );
  1189. status = queryInfo.Status;
  1190. }
  1191. if ( status == ERROR_SUCCESS ||
  1192. status == DNS_ERROR_RCODE_NAME_ERROR ||
  1193. status == DNS_INFO_NO_RECORDS )
  1194. {
  1195. printf(
  1196. "DnsQueryEx() completed => %s.\n"
  1197. "\tstatus = %d\n",
  1198. DnsStatusString( status ),
  1199. status );
  1200. DnsPrint_QueryInfo(
  1201. dnsup_PrintRoutine,
  1202. dnsup_PrintContext,
  1203. "DnsQueryEx() result",
  1204. &queryInfo );
  1205. }
  1206. else
  1207. {
  1208. printf(
  1209. "DnsQueryEx() failed, %x %s.\n",
  1210. status,
  1211. DnsStatusString(status) );
  1212. DNS_ASSERT( !queryInfo.pAnswerRecords );
  1213. DNS_ASSERT( !queryInfo.pAliasRecords );
  1214. DNS_ASSERT( !queryInfo.pAdditionalRecords );
  1215. DNS_ASSERT( !queryInfo.pAuthorityRecords );
  1216. }
  1217. return( status );
  1218. Usage:
  1219. printf(
  1220. "DnsQueryEx\n"
  1221. "usage:\n"
  1222. " DnsUp [-n<DNS IP>|...] -qex <Name> <Type> <Flags> [-a]\n"
  1223. " <DNS IP> optional IP address of DNS server to query.\n"
  1224. " <Name> DNS name to query\n"
  1225. " <Type> type of query\n"
  1226. " <Flags> flags to use in query (in hex)\n"
  1227. " -a to indicate asynchronous operation\n"
  1228. );
  1229. return( ERROR_INVALID_PARAMETER );
  1230. }
  1231. DNS_STATUS
  1232. ProcessQueryCompare(
  1233. IN DWORD Argc,
  1234. IN PSTR * Argv
  1235. )
  1236. {
  1237. DNS_STATUS status;
  1238. PCHAR pszname;
  1239. WORD type;
  1240. PIP_ARRAY aipservers;
  1241. PDNS_MSG_BUF pmsgRecv = NULL;
  1242. PDNS_RECORD prrQuery;
  1243. PDNS_RECORD prrParsed;
  1244. PDNS_RECORD prrQueryDiff;
  1245. PDNS_RECORD prrParsedDiff;
  1246. //
  1247. // optional name server to query?
  1248. //
  1249. aipservers = pDnsServerArray;
  1250. //
  1251. // name to query
  1252. //
  1253. if ( Argc < 2 )
  1254. {
  1255. goto Usage;
  1256. }
  1257. pszname = Argv[0];
  1258. Argc--;
  1259. Argv++;
  1260. //
  1261. // type
  1262. //
  1263. type = DnsRecordTypeForName( Argv[0], 0 );
  1264. if ( type == 0 )
  1265. {
  1266. goto Usage;
  1267. }
  1268. Argc--;
  1269. Argv++;
  1270. //
  1271. // build expected RR set
  1272. //
  1273. prrParsed = buildRecordList(
  1274. Argc,
  1275. Argv );
  1276. if ( !prrParsed )
  1277. {
  1278. status = GetLastError();
  1279. if ( status != ERROR_SUCCESS )
  1280. {
  1281. printf( "ERROR: building records from arguments\n" );
  1282. goto Usage;
  1283. }
  1284. }
  1285. DnsPrint_RecordSet(
  1286. dnsup_PrintRoutine,
  1287. dnsup_PrintContext,
  1288. "Parsed comparison record list:\n",
  1289. prrParsed );
  1290. //
  1291. // query
  1292. //
  1293. // DCR: waiting for new DnsQueryEx()
  1294. //
  1295. return( ERROR_CALL_NOT_IMPLEMENTED );
  1296. #if 0
  1297. status = DnsQueryEx(
  1298. & pmsgRecv,
  1299. & prrQuery,
  1300. pszname,
  1301. type,
  1302. 0, // currently no flag support
  1303. aipservers,
  1304. NULL
  1305. );
  1306. if( status != ERROR_SUCCESS )
  1307. {
  1308. printf(
  1309. "DnsQueryEx() failed, %x %s.\n",
  1310. status,
  1311. DnsStatusString(status) );
  1312. if ( DnsIsStatusRcode(status) )
  1313. {
  1314. DnsPrint_Message(
  1315. dnsup_PrintRoutine,
  1316. dnsup_PrintContext,
  1317. "Query response:\n",
  1318. pmsgRecv );
  1319. }
  1320. return( status );
  1321. }
  1322. DnsPrint_RecordSet(
  1323. dnsup_PrintRoutine,
  1324. dnsup_PrintContext,
  1325. "Query response records:\n",
  1326. prrQuery );
  1327. //
  1328. // compare with records received
  1329. //
  1330. DnsRecordSetCompare(
  1331. prrQuery,
  1332. prrParsed,
  1333. & prrQueryDiff,
  1334. & prrParsedDiff );
  1335. DnsPrint_RecordSet(
  1336. dnsup_PrintRoutine,
  1337. dnsup_PrintContext,
  1338. "Unmatch records in query response:\n",
  1339. prrQueryDiff );
  1340. DnsPrint_RecordSet(
  1341. dnsup_PrintRoutine,
  1342. dnsup_PrintContext,
  1343. "Unmatch records in parsed list:\n",
  1344. prrParsedDiff );
  1345. return( ERROR_SUCCESS );
  1346. #endif
  1347. Usage:
  1348. printf(
  1349. "Query compare\n"
  1350. "usage:\n"
  1351. " DnsUp [-n<DNS IP>|...] -qc <Name> <Type> [<Record> | ...]\n"
  1352. " <DNS IP> optional IP address of DNS server to update.\n"
  1353. " <Name> DNS name to query\n"
  1354. " <Type> type of query\n"
  1355. " <Record> record in list to compare\n"
  1356. " <Record> == (-,+) <Name> <Type> [Data | ...]\n"
  1357. " (-,+) - add or delete, exist or no-exist flag\n"
  1358. " <Name> - RR owner name\n"
  1359. " <Type> - record type\n"
  1360. " <Data> - data strings (type specific), if any\n"
  1361. );
  1362. return( ERROR_INVALID_PARAMETER );
  1363. }
  1364. DNS_STATUS
  1365. ProcessQuery(
  1366. IN DWORD Argc,
  1367. IN PSTR * Argv
  1368. )
  1369. {
  1370. DNS_STATUS status;
  1371. PCHAR pszname;
  1372. WORD type;
  1373. DWORD flags = 0;
  1374. PDNS_RECORD precord = NULL;
  1375. PDNS_MSG_BUF pmsgRecv = NULL;
  1376. PDNS_MSG_BUF * ppmsgRecv = NULL;
  1377. PIP_ARRAY aipservers = NULL;
  1378. //
  1379. // name to query
  1380. //
  1381. if ( Argc < 2 || Argc > 3 )
  1382. {
  1383. goto Usage;
  1384. }
  1385. pszname = getNamePointer( Argv[0] );
  1386. Argc--;
  1387. Argv++;
  1388. //
  1389. // type
  1390. //
  1391. type = DnsRecordTypeForName( Argv[0], 0 );
  1392. if ( type == 0 )
  1393. {
  1394. goto Usage;
  1395. }
  1396. Argc--;
  1397. Argv++;
  1398. //
  1399. // flags
  1400. //
  1401. if ( Argc )
  1402. {
  1403. flags = strtoul( Argv[0], NULL, 16 );
  1404. Argc--;
  1405. Argv++;
  1406. }
  1407. if ( Argc )
  1408. {
  1409. goto Usage;
  1410. }
  1411. //
  1412. // only if flag has BYPASS_CACHE set can we
  1413. // 1) send to specific servers
  1414. // 2) receive message buffer itself
  1415. //
  1416. aipservers = pDnsServerArray;
  1417. if ( flags & DNS_QUERY_BYPASS_CACHE )
  1418. {
  1419. ppmsgRecv = & pmsgRecv;
  1420. }
  1421. //
  1422. // query
  1423. //
  1424. status = DnsQuery(
  1425. pszname,
  1426. type,
  1427. flags,
  1428. aipservers,
  1429. & precord,
  1430. ppmsgRecv );
  1431. if( status != ERROR_SUCCESS )
  1432. {
  1433. printf(
  1434. "DnsQuery() failed, %x %s.\n",
  1435. status,
  1436. DnsStatusString(status) );
  1437. if ( DnsIsStatusRcode(status) && pmsgRecv )
  1438. {
  1439. DnsPrint_Message(
  1440. dnsup_PrintRoutine,
  1441. dnsup_PrintContext,
  1442. "Query response:\n",
  1443. pmsgRecv );
  1444. }
  1445. }
  1446. else
  1447. {
  1448. printf( "DnsQuery() successfully completed.\n" );
  1449. if ( pmsgRecv )
  1450. {
  1451. DnsPrint_Message(
  1452. dnsup_PrintRoutine,
  1453. dnsup_PrintContext,
  1454. "Query response:\n",
  1455. pmsgRecv );
  1456. }
  1457. DnsPrint_RecordSet(
  1458. dnsup_PrintRoutine,
  1459. dnsup_PrintContext,
  1460. "Query response records:\n",
  1461. precord );
  1462. }
  1463. DnsRecordListFree( precord, DnsFreeRecordListDeep );
  1464. return( status );
  1465. Usage:
  1466. printf(
  1467. "DnsQuery\n"
  1468. "usage:\n"
  1469. " DnsUp [-n<DNS IP>|...] -q <Name> <Type> [<Flags>]\n"
  1470. " <DNS IP> optional IP address of DNS server to query.\n"
  1471. " <Name> DNS name to query\n"
  1472. " <Type> type of query\n"
  1473. " <Flags> flags to use in query (in hex)\n"
  1474. "\n"
  1475. " Note for DnsQuery() to use specific server or to return\n"
  1476. " a DNS message buffer, BYPASS_CACHE flag MUST be set.\n"
  1477. );
  1478. PrintDnsQueryFlags();
  1479. return( ERROR_INVALID_PARAMETER );
  1480. }
  1481. DNS_STATUS
  1482. ProcessQueryMultiple(
  1483. IN DWORD Argc,
  1484. IN PSTR * Argv
  1485. )
  1486. {
  1487. DNS_STATUS status;
  1488. PCHAR pszname1;
  1489. WORD type1;
  1490. PCHAR pszname2;
  1491. WORD type2;
  1492. DWORD flags = 0;
  1493. PDNS_RECORD precord = NULL;
  1494. PDNS_MSG_BUF pmsgRecv = NULL;
  1495. PDNS_MSG_BUF * ppmsgRecv = NULL;
  1496. PIP_ARRAY aipservers = NULL;
  1497. //
  1498. // optional name server to query?
  1499. //
  1500. if ( Argc < 4 || Argc > 5 )
  1501. {
  1502. goto Usage;
  1503. }
  1504. //
  1505. // first name to query
  1506. //
  1507. pszname1 = Argv[0];
  1508. Argc--;
  1509. Argv++;
  1510. //
  1511. // first type
  1512. //
  1513. type1 = DnsRecordTypeForName( Argv[0], 0 );
  1514. if ( type1 == 0 )
  1515. {
  1516. goto Usage;
  1517. }
  1518. Argc--;
  1519. Argv++;
  1520. //
  1521. // second name to query
  1522. //
  1523. pszname2 = Argv[0];
  1524. Argc--;
  1525. Argv++;
  1526. //
  1527. // second type
  1528. //
  1529. type2 = DnsRecordTypeForName( Argv[0], 0 );
  1530. if ( type2 == 0 )
  1531. {
  1532. goto Usage;
  1533. }
  1534. Argc--;
  1535. Argv++;
  1536. //
  1537. // flags
  1538. //
  1539. if ( Argc )
  1540. {
  1541. flags = strtoul( Argv[0], NULL, 16 );
  1542. Argc--;
  1543. Argv++;
  1544. }
  1545. if ( Argc )
  1546. {
  1547. goto Usage;
  1548. }
  1549. //
  1550. // only if flag has BYPASS_CACHE set can we
  1551. // 1) send to specific servers
  1552. // 2) receive message buffer itself
  1553. //
  1554. if ( flags & DNS_QUERY_BYPASS_CACHE )
  1555. {
  1556. aipservers = pDnsServerArray;
  1557. ppmsgRecv = & pmsgRecv;
  1558. }
  1559. //
  1560. // make first query
  1561. //
  1562. status = DnsQuery(
  1563. pszname1,
  1564. type1,
  1565. flags,
  1566. aipservers,
  1567. & precord,
  1568. ppmsgRecv );
  1569. if( status != ERROR_SUCCESS )
  1570. {
  1571. printf(
  1572. "DnsQuery() failed, %x %s.\n",
  1573. status,
  1574. DnsStatusString(status) );
  1575. if ( DnsIsStatusRcode(status) && pmsgRecv )
  1576. {
  1577. DnsPrint_Message(
  1578. dnsup_PrintRoutine,
  1579. dnsup_PrintContext,
  1580. "Query response:\n",
  1581. pmsgRecv );
  1582. }
  1583. }
  1584. else
  1585. {
  1586. printf( "DnsQuery() successfully completed.\n" );
  1587. if ( pmsgRecv )
  1588. {
  1589. DnsPrint_Message(
  1590. dnsup_PrintRoutine,
  1591. dnsup_PrintContext,
  1592. "Query response:\n",
  1593. pmsgRecv );
  1594. }
  1595. DnsPrint_RecordSet(
  1596. dnsup_PrintRoutine,
  1597. dnsup_PrintContext,
  1598. "Query response records:\n",
  1599. precord );
  1600. }
  1601. DnsRecordListFree( precord, DnsFreeRecordListDeep );
  1602. //
  1603. // make second query
  1604. //
  1605. status = DnsQuery(
  1606. pszname2,
  1607. type2,
  1608. flags,
  1609. aipservers,
  1610. & precord,
  1611. ppmsgRecv );
  1612. if( status != ERROR_SUCCESS )
  1613. {
  1614. printf(
  1615. "DnsQuery() failed, %x %s.\n",
  1616. status,
  1617. DnsStatusString(status) );
  1618. if ( DnsIsStatusRcode(status) && pmsgRecv )
  1619. {
  1620. DnsPrint_Message(
  1621. dnsup_PrintRoutine,
  1622. dnsup_PrintContext,
  1623. "Query response:\n",
  1624. pmsgRecv );
  1625. }
  1626. }
  1627. else
  1628. {
  1629. printf( "DnsQuery() successfully completed.\n" );
  1630. if ( pmsgRecv )
  1631. {
  1632. DnsPrint_Message(
  1633. dnsup_PrintRoutine,
  1634. dnsup_PrintContext,
  1635. "Query response:\n",
  1636. pmsgRecv );
  1637. }
  1638. DnsPrint_RecordSet(
  1639. dnsup_PrintRoutine,
  1640. dnsup_PrintContext,
  1641. "Query response records:\n",
  1642. precord );
  1643. }
  1644. DnsRecordListFree( precord, DnsFreeRecordListDeep );
  1645. return( status );
  1646. Usage:
  1647. printf(
  1648. "Multiple DnsQuery()s\n"
  1649. "usage:\n"
  1650. " DnsUp [-n<DNS IP>|...] -qm <Name1> <Type1> <Name2> <Type2> [<Flags>]\n"
  1651. " <DNS IP> optional IP address of DNS server to query.\n"
  1652. " <Name1> DNS name to query\n"
  1653. " <Type1> type of query\n"
  1654. " <Name2> DNS name to query\n"
  1655. " <Type2> type of query\n"
  1656. " <Flags> flags to use in query (in hex)\n"
  1657. "\n"
  1658. " Note for DnsQuery() to use specific server or to return\n"
  1659. " a DNS message buffer, BYPASS_CACHE flag MUST be set.\n"
  1660. );
  1661. PrintDnsQueryFlags();
  1662. return( ERROR_INVALID_PARAMETER );
  1663. }
  1664. DNS_STATUS
  1665. ProcessQueryTest(
  1666. IN DWORD Argc,
  1667. IN PSTR * Argv
  1668. )
  1669. {
  1670. DNS_STATUS status;
  1671. PCHAR pszname;
  1672. WORD type;
  1673. DWORD flags = 0;
  1674. PDNS_RECORD precord = NULL;
  1675. PDNS_MSG_BUF pmsgRecv = NULL;
  1676. PIP_ARRAY aipservers = NULL;
  1677. //
  1678. // optional name server to query?
  1679. //
  1680. aipservers = pDnsServerArray;
  1681. //
  1682. // name to query
  1683. //
  1684. if ( Argc < 2 || Argc > 3 )
  1685. {
  1686. goto Usage;
  1687. }
  1688. pszname = Argv[0];
  1689. Argc--;
  1690. Argv++;
  1691. //
  1692. // type
  1693. //
  1694. type = DnsRecordTypeForName( Argv[0], 0 );
  1695. if ( type == 0 )
  1696. {
  1697. goto Usage;
  1698. }
  1699. Argc--;
  1700. Argv++;
  1701. //
  1702. // flags
  1703. //
  1704. if ( Argc )
  1705. {
  1706. flags = strtoul( Argv[0], NULL, 16 );
  1707. Argc--;
  1708. Argv++;
  1709. }
  1710. if ( Argc )
  1711. {
  1712. goto Usage;
  1713. }
  1714. //
  1715. // query
  1716. //
  1717. status = QueryDirectEx(
  1718. & pmsgRecv,
  1719. & precord,
  1720. NULL, // no header
  1721. 0, // no header counts
  1722. pszname,
  1723. type,
  1724. NULL, // no records
  1725. flags,
  1726. aipservers,
  1727. NULL
  1728. );
  1729. if( status != ERROR_SUCCESS )
  1730. {
  1731. printf(
  1732. "QueryDirectEx() failed, %x %s.\n",
  1733. status,
  1734. DnsStatusString(status) );
  1735. if ( DnsIsStatusRcode(status) )
  1736. {
  1737. DnsPrint_Message(
  1738. dnsup_PrintRoutine,
  1739. dnsup_PrintContext,
  1740. "Query response:\n",
  1741. pmsgRecv );
  1742. }
  1743. }
  1744. else
  1745. {
  1746. printf( "QueryDirectEx() successfully completed.\n" );
  1747. DnsPrint_Message(
  1748. dnsup_PrintRoutine,
  1749. dnsup_PrintContext,
  1750. "Query response:\n",
  1751. pmsgRecv );
  1752. DnsPrint_RecordSet(
  1753. dnsup_PrintRoutine,
  1754. dnsup_PrintContext,
  1755. "Query response records:\n",
  1756. precord );
  1757. }
  1758. DnsRecordListFree( precord, DnsFreeRecordListDeep );
  1759. return( status );
  1760. Usage:
  1761. printf(
  1762. "QueryDirectEx()\n"
  1763. "usage:\n"
  1764. " DnsUp [-n<DNS IP>|...] -qt <Name> <Type> [<Flags>]\n"
  1765. " QueryTest -- uses dnslib.lib QueryDirectEx()\n"
  1766. " <DNS IP> optional IP address of DNS server to query.\n"
  1767. " <Name> DNS name to query\n"
  1768. " <Type> type of query\n"
  1769. " <Flags> flags to use in query (in hex)\n"
  1770. );
  1771. return( ERROR_INVALID_PARAMETER );
  1772. }
  1773. #if 0
  1774. DNS_STATUS
  1775. ProcessUpdateMultiple(
  1776. IN DWORD Argc,
  1777. IN PSTR * Argv
  1778. )
  1779. {
  1780. DNS_STATUS status;
  1781. DWORD flags = 0;
  1782. PCHAR pszzone = NULL;
  1783. PCHAR pszname = NULL;
  1784. IP_ADDRESS ip;
  1785. IP_ADDRESS hostIp;
  1786. DWORD countIp;
  1787. DWORD i;
  1788. PCHAR arg;
  1789. PDNS_RECORD prr = NULL;
  1790. PDNS_MSG_BUF pmsg = NULL;
  1791. PDNS_MSG_BUF pmsgRecv = NULL;
  1792. IP_ADDRESS ipserver;
  1793. PIP_ARRAY aipservers = NULL;
  1794. PIP_ARRAY ipArray = NULL;
  1795. PSTR pszserverName = NULL;
  1796. HANDLE hCreds=NULL;
  1797. //
  1798. // optional name server to query?
  1799. //
  1800. aipservers = pDnsServerArray;
  1801. if ( !aipservers )
  1802. {
  1803. aipservers = Dns_GetDnsServerList( FALSE );
  1804. }
  1805. if ( !aipservers )
  1806. {
  1807. printf( "Update failed: no DNS server list available.\n" );
  1808. return( GetLastError() );
  1809. }
  1810. //
  1811. // flags?
  1812. //
  1813. if ( Argc < 1 )
  1814. {
  1815. goto Usage;
  1816. }
  1817. arg = Argv[0];
  1818. if ( strncmp( arg, "-f", 2 ) == 0 )
  1819. {
  1820. flags = strtoul( arg+2, NULL, 16 );
  1821. Argc--;
  1822. Argv++;
  1823. }
  1824. //
  1825. // security -- then need target server name
  1826. // presence of server name automatically turns on security
  1827. //
  1828. if ( Argc < 1 )
  1829. {
  1830. goto Usage;
  1831. }
  1832. arg = Argv[0];
  1833. if ( strncmp( arg, "-s", 2 ) == 0 )
  1834. {
  1835. pszserverName = arg+2;
  1836. flags |= DNS_UPDATE_SECURITY_ON;
  1837. Argc--;
  1838. Argv++;
  1839. }
  1840. //
  1841. // name of zone to update
  1842. //
  1843. if ( Argc < 1 )
  1844. {
  1845. goto Usage;
  1846. }
  1847. pszzone = Argv[0];
  1848. DNSDBG( INIT, (
  1849. "Read update zone name %s\n",
  1850. pszzone ));
  1851. Argc--;
  1852. Argv++;
  1853. //
  1854. // name to update
  1855. //
  1856. if ( Argc < 1 )
  1857. {
  1858. goto Usage;
  1859. }
  1860. pszname = Argv[0];
  1861. DNSDBG( INIT, (
  1862. "Read update host name %s\n",
  1863. pszname ));
  1864. Argc--;
  1865. Argv++;
  1866. //
  1867. // start IP
  1868. //
  1869. if ( Argc < 1 )
  1870. {
  1871. goto Usage;
  1872. }
  1873. ip = inet_addr( Argv[0] );
  1874. if ( ip == (-1) )
  1875. {
  1876. goto Usage;
  1877. }
  1878. Argc--;
  1879. Argv++;
  1880. //
  1881. // IP count
  1882. //
  1883. if ( Argc < 1 )
  1884. {
  1885. goto Usage;
  1886. }
  1887. countIp = strtoul( Argv[0], NULL, 10 );
  1888. Argc--;
  1889. Argv++;
  1890. //
  1891. // build update record list
  1892. // - allocate and generate IP array
  1893. // - then create DNS records
  1894. //
  1895. ipArray = Dns_CreateIpArray( countIp );
  1896. if ( !ipArray )
  1897. {
  1898. status = GetLastError();
  1899. if ( status != ERROR_SUCCESS )
  1900. {
  1901. printf( "ERROR: creating IP array\n" );
  1902. goto Usage;
  1903. }
  1904. goto Usage;
  1905. }
  1906. hostIp = ntohl( ip );
  1907. for ( i=0; i<countIp; i++ )
  1908. {
  1909. ipArray->AddrArray[i] = htonl( hostIp );
  1910. hostIp++;
  1911. }
  1912. prr = Dns_HostUpdateRRSet(
  1913. pszname,
  1914. ipArray,
  1915. 3600 );
  1916. if ( !prr )
  1917. {
  1918. status = GetLastError();
  1919. if ( status != ERROR_SUCCESS )
  1920. {
  1921. printf( "ERROR: building records from arguments\n" );
  1922. goto Usage;
  1923. }
  1924. }
  1925. //
  1926. // build \ send update
  1927. //
  1928. status = Dns_UpdateLibEx(
  1929. prr,
  1930. flags,
  1931. pszzone,
  1932. pszserverName,
  1933. aipservers,
  1934. hCreds,
  1935. &pmsgRecv
  1936. );
  1937. if ( pmsgRecv )
  1938. {
  1939. DnsPrint_Message(
  1940. dnsup_PrintRoutine,
  1941. dnsup_PrintContext,
  1942. "Update response:\n",
  1943. pmsgRecv );
  1944. }
  1945. FREE_HEAP( aipservers );
  1946. Dns_RecordListFree( prr );
  1947. FREE_HEAP( pmsg );
  1948. FREE_HEAP( pmsgRecv );
  1949. if( status != ERROR_SUCCESS )
  1950. {
  1951. printf(
  1952. "Dns_UpdateLibEx failed, %x %s.\n",
  1953. status,
  1954. DnsStatusString(status) );
  1955. }
  1956. else
  1957. {
  1958. printf( "Update successfully completed.\n" );
  1959. }
  1960. return( status );
  1961. Usage:
  1962. FREE_HEAP( aipservers );
  1963. Dns_RecordListFree( prr );
  1964. FREE_HEAP( pmsg );
  1965. FREE_HEAP( pmsgRecv );
  1966. printf(
  1967. "usage:\n"
  1968. " DnsUp [-n<DNS IP>|...] -um [-f<Flags>] [-s<ServerName>] <ZoneName>\n"
  1969. " <HostName> <Starting IP> <IP Count>\n"
  1970. " <DNS IP> optional IP address of server to send update to.\n"
  1971. " <ServerName> name of DNS server we are sending update to;\n"
  1972. " presence of server name automatically turns on update security\n"
  1973. " <ZoneName> name of zone to update\n"
  1974. " <HostName> name of host to update\n"
  1975. " <Starting IP> first IP (in dotted decimal) in range to update\n"
  1976. " <IP Count> count of IPs to send in update; IP address in update will\n"
  1977. " be the next <IP count> after <Starting IP>\n"
  1978. );
  1979. return( ERROR_INVALID_PARAMETER );
  1980. }
  1981. #endif
  1982. DNS_STATUS
  1983. ProcessIQuery(
  1984. IN DWORD Argc,
  1985. IN PSTR * Argv
  1986. )
  1987. {
  1988. DNS_STATUS status;
  1989. DWORD flags = 0;
  1990. PCHAR arg;
  1991. PDNS_RECORD prr = NULL;
  1992. PDNS_MSG_BUF pmsg = NULL;
  1993. PDNS_MSG_BUF pmsgRecv = NULL;
  1994. IP_ADDRESS ipserver;
  1995. PIP_ARRAY aipservers = NULL;
  1996. DNS_HEADER header;
  1997. //
  1998. // setup header
  1999. // - zero flags
  2000. *(PDWORD) &header = 0;
  2001. header.Xid = (WORD) GetCurrentTimeInSeconds();
  2002. header.Opcode = DNS_OPCODE_IQUERY;
  2003. //
  2004. // optional name server to query?
  2005. //
  2006. aipservers = pDnsServerArray;
  2007. if ( !aipservers )
  2008. {
  2009. aipservers = Dns_GetDnsServerList( FALSE );
  2010. }
  2011. if ( !aipservers )
  2012. {
  2013. printf( "Update failed: no DNS server list available.\n" );
  2014. return( GetLastError() );
  2015. }
  2016. //
  2017. // flags?
  2018. //
  2019. if ( Argc < 1 )
  2020. {
  2021. goto Usage;
  2022. }
  2023. arg = Argv[0];
  2024. if ( strncmp( arg, "-f", 2 ) == 0 )
  2025. {
  2026. flags = strtoul( arg+2, NULL, 16 );
  2027. Argc--;
  2028. Argv++;
  2029. }
  2030. //
  2031. // build update packet RRs
  2032. //
  2033. prr = buildRecordList(
  2034. Argc,
  2035. Argv );
  2036. if ( !prr )
  2037. {
  2038. status = GetLastError();
  2039. if ( status != ERROR_SUCCESS )
  2040. {
  2041. printf( "ERROR: building records from arguments\n" );
  2042. goto Usage;
  2043. }
  2044. }
  2045. //
  2046. // build \ send update
  2047. //
  2048. status = QueryDirectEx(
  2049. & pmsgRecv,
  2050. NULL, // no response records
  2051. & header, // header with IQUERY set
  2052. TRUE, // no copy header count fields
  2053. NULL, // no question
  2054. 0, // no question type
  2055. prr, // record list built
  2056. 0, // flags
  2057. aipservers, // server IP list
  2058. NULL // no adapter list
  2059. );
  2060. if ( pmsgRecv )
  2061. {
  2062. DnsPrint_Message(
  2063. dnsup_PrintRoutine,
  2064. dnsup_PrintContext,
  2065. "IQUERY response:\n",
  2066. pmsgRecv );
  2067. }
  2068. FREE_HEAP( aipservers );
  2069. Dns_RecordListFree( prr );
  2070. FREE_HEAP( pmsg );
  2071. FREE_HEAP( pmsgRecv );
  2072. if( status != ERROR_SUCCESS )
  2073. {
  2074. printf(
  2075. "QueryDirectExEx failed, %x %s.\n",
  2076. status,
  2077. DnsStatusString(status) );
  2078. }
  2079. else
  2080. {
  2081. printf( "IQUERY successfully completed.\n" );
  2082. }
  2083. return( status );
  2084. Usage:
  2085. FREE_HEAP( aipservers );
  2086. Dns_RecordListFree( prr );
  2087. FREE_HEAP( pmsg );
  2088. FREE_HEAP( pmsgRecv );
  2089. printf(
  2090. "usage:\n"
  2091. " DnsUp [-n<DNS IP>|...] -iq [-f<Flags>] [<Record> | ...]\n"
  2092. " <DNS IP> optional IP address of server to send update to.\n"
  2093. " <ServerName> name of DNS server we are sending update to;\n"
  2094. " presence of server name automatically turns on update security\n"
  2095. " <ZoneName> name of zone to update\n"
  2096. " <Record> record for update packet\n"
  2097. " <Record> == (-,+)(p,u,a) <Name> <Type> [Data | ...]\n"
  2098. " (-,+) - add or delete, exist or no-exist flag\n"
  2099. " (p,u,a) - prereq, update or additional section\n"
  2100. " <Name> - RR owner name\n"
  2101. " <Type> - record type\n"
  2102. " <Data> - data strings (type specific), if any\n"
  2103. );
  2104. return( ERROR_INVALID_PARAMETER );
  2105. }
  2106. DNS_STATUS
  2107. ProcessValidateName(
  2108. IN DWORD Argc,
  2109. IN PSTR * Argv
  2110. )
  2111. {
  2112. DNS_STATUS status;
  2113. PCHAR pszname;
  2114. DWORD format;
  2115. //
  2116. // name to validate
  2117. //
  2118. if ( Argc != 2 )
  2119. {
  2120. goto Usage;
  2121. }
  2122. pszname = Argv[0];
  2123. Argc--;
  2124. Argv++;
  2125. //
  2126. // name format
  2127. //
  2128. if ( Argc )
  2129. {
  2130. format = strtoul( Argv[0], NULL, 10 );
  2131. }
  2132. //
  2133. // validate
  2134. //
  2135. status = DnsValidateName_A(
  2136. pszname,
  2137. format );
  2138. printf(
  2139. "DnsValidateName( %s, %d ) status = %d %s.\n",
  2140. pszname,
  2141. format,
  2142. status,
  2143. DnsStatusString(status) );
  2144. return( status );
  2145. Usage:
  2146. printf(
  2147. "DnsValidateName\n"
  2148. "usage:\n"
  2149. " DnsUp -vn <Name> <Format>\n"
  2150. " <Name> DNS name to validate\n"
  2151. " <Format> format of name\n"
  2152. "\tDomainName -- %d\n"
  2153. "\tDomainLabel -- %d\n"
  2154. "\tHostnameFull -- %d\n"
  2155. "\tHostnameLabel -- %d\n"
  2156. "\tWildcard -- %d\n"
  2157. "\tSrvRecord -- %d\n",
  2158. DnsNameDomain,
  2159. DnsNameDomainLabel,
  2160. DnsNameHostnameFull,
  2161. DnsNameHostnameLabel,
  2162. DnsNameWildcard,
  2163. DnsNameSrvRecord
  2164. );
  2165. return( ERROR_INVALID_PARAMETER );
  2166. }
  2167. DNS_STATUS
  2168. ProcessNameCompare(
  2169. IN DWORD Argc,
  2170. IN PSTR * Argv
  2171. )
  2172. {
  2173. BOOL result;
  2174. PCHAR pszname1;
  2175. PCHAR pszname2;
  2176. //
  2177. // names to compare
  2178. //
  2179. if ( Argc != 2 )
  2180. {
  2181. goto Usage;
  2182. }
  2183. pszname1 = Argv[0];
  2184. pszname2 = Argv[1];
  2185. //
  2186. // compare
  2187. //
  2188. result = DnsNameCompare_A(
  2189. pszname1,
  2190. pszname2 );
  2191. printf(
  2192. "DnsNameCompare( %s, %s ) result = %s.\n",
  2193. pszname1,
  2194. pszname2,
  2195. result ? "TRUE" : "FALSE"
  2196. );
  2197. return( ERROR_SUCCESS );
  2198. Usage:
  2199. printf(
  2200. "DnsNameCompare\n"
  2201. "usage:\n"
  2202. " DnsUp -nc <Name1> <Name2>\n"
  2203. " <Name1> <Name2> DNS names to compare.\n"
  2204. );
  2205. return( ERROR_INVALID_PARAMETER );
  2206. }
  2207. DNS_STATUS
  2208. ProcessNameCompareEx(
  2209. IN DWORD Argc,
  2210. IN PSTR * Argv
  2211. )
  2212. {
  2213. DNS_STATUS status;
  2214. PCHAR pszname1;
  2215. PCHAR pszname2;
  2216. //
  2217. // names to compare
  2218. //
  2219. if ( Argc != 2 )
  2220. {
  2221. goto Usage;
  2222. }
  2223. pszname1 = Argv[0];
  2224. pszname2 = Argv[1];
  2225. //
  2226. // compare
  2227. //
  2228. status = DnsNameCompareEx_A(
  2229. pszname1,
  2230. pszname2,
  2231. 0 );
  2232. printf(
  2233. "DnsNameCompareEx( %s, %s ) result = %d.\n",
  2234. pszname1,
  2235. pszname2,
  2236. status
  2237. );
  2238. return( ERROR_SUCCESS );
  2239. Usage:
  2240. printf(
  2241. "DnsNameCompareEx\n"
  2242. "usage:\n"
  2243. " DnsUp -cnx <Name1> <Name2>\n"
  2244. " <Name1> <Name2> DNS names to compare.\n"
  2245. "Compare Result:\n"
  2246. "\tNot Equal -- %d\n"
  2247. "\tEqual -- %d\n"
  2248. "\tLeft is Ancestor -- %d\n"
  2249. "\tRight is Ancestor -- %d\n"
  2250. "\tInvalid Name -- %d\n",
  2251. DnsNameCompareNotEqual,
  2252. DnsNameCompareEqual,
  2253. DnsNameCompareLeftParent,
  2254. DnsNameCompareRightParent,
  2255. DnsNameCompareInvalid
  2256. );
  2257. return( ERROR_INVALID_PARAMETER );
  2258. }
  2259. DNS_STATUS
  2260. ProcessStringTranslate(
  2261. IN DWORD Argc,
  2262. IN PSTR * Argv
  2263. )
  2264. {
  2265. DNS_STATUS status;
  2266. WCHAR unicodeString[ DNS_MAX_NAME_LENGTH ];
  2267. WCHAR unicodeStandard[ DNS_MAX_NAME_LENGTH ];
  2268. BYTE utf8Standard[ DNS_MAX_NAME_LENGTH ];
  2269. PWCHAR punicode;
  2270. PCHAR putf8;
  2271. DWORD unicodeLength;
  2272. DWORD utf8Length;
  2273. DWORD unicodeLengthStandard;
  2274. //
  2275. // string translate
  2276. //
  2277. if ( Argc < 1 )
  2278. {
  2279. goto Usage;
  2280. }
  2281. //
  2282. // read in unicode characters
  2283. //
  2284. unicodeLength = 0;
  2285. while ( Argc )
  2286. {
  2287. unicodeString[ unicodeLength++] = (WORD) strtoul( Argv[0], NULL, 16 );
  2288. Argc--;
  2289. Argv++;
  2290. }
  2291. unicodeString[ unicodeLength ] = 0;
  2292. DnsPrint_UnicodeStringBytes(
  2293. dnsup_PrintRoutine,
  2294. dnsup_PrintContext,
  2295. "DnsStringTranslate().\n"
  2296. "Input string",
  2297. unicodeString,
  2298. unicodeLength );
  2299. //
  2300. // convert to UTF8 -- my way and their way
  2301. //
  2302. putf8 = Dns_StringCopyAllocate(
  2303. (PCHAR) unicodeString,
  2304. 0,
  2305. DnsCharSetUnicode,
  2306. DnsCharSetUtf8 );
  2307. if ( !putf8 )
  2308. {
  2309. return( DNS_ERROR_NO_MEMORY );
  2310. }
  2311. utf8Length = WideCharToMultiByte(
  2312. CP_UTF8,
  2313. 0, // no flags
  2314. (PWCHAR) unicodeString,
  2315. (-1), // null terminated
  2316. utf8Standard,
  2317. MAXWORD, // assuming adequate length
  2318. NULL,
  2319. NULL );
  2320. DnsPrint_Utf8StringBytes(
  2321. dnsup_PrintRoutine,
  2322. dnsup_PrintContext,
  2323. "My UTF8",
  2324. putf8,
  2325. strlen(putf8) );
  2326. DnsPrint_Utf8StringBytes(
  2327. dnsup_PrintRoutine,
  2328. dnsup_PrintContext,
  2329. "Standard UTF8",
  2330. utf8Standard,
  2331. strlen(utf8Standard) );
  2332. //
  2333. // convert back to unicode
  2334. //
  2335. punicode = Dns_StringCopyAllocate(
  2336. (PCHAR) utf8Standard,
  2337. 0,
  2338. DnsCharSetUtf8,
  2339. DnsCharSetUnicode );
  2340. unicodeLengthStandard = MultiByteToWideChar(
  2341. CP_UTF8,
  2342. 0, // no flags
  2343. (PCHAR) utf8Standard,
  2344. (-1), // null terminated
  2345. (PWCHAR) unicodeStandard,
  2346. MAXWORD // assuming adequate length
  2347. );
  2348. DnsPrint_UnicodeStringBytes(
  2349. dnsup_PrintRoutine,
  2350. dnsup_PrintContext,
  2351. "My unicode",
  2352. punicode,
  2353. wcslen(punicode) );
  2354. DnsPrint_UnicodeStringBytes(
  2355. dnsup_PrintRoutine,
  2356. dnsup_PrintContext,
  2357. "Standard unicode",
  2358. unicodeStandard,
  2359. wcslen(unicodeStandard) );
  2360. status = ERROR_SUCCESS;
  2361. return( status );
  2362. Usage:
  2363. printf(
  2364. "usage:\n"
  2365. " DnsUp -s [unicode chars in hex]\n"
  2366. );
  2367. return( ERROR_INVALID_PARAMETER );
  2368. }
  2369. DNS_STATUS
  2370. ProcessQueryConfig(
  2371. IN DWORD Argc,
  2372. IN PSTR * Argv
  2373. )
  2374. {
  2375. #define CONFIG_BUF_SIZE (100)
  2376. DNS_STATUS status;
  2377. DNS_CONFIG_TYPE config;
  2378. PCHAR psznext;
  2379. PCHAR pendString;
  2380. PWSTR pwsadapter = NULL;
  2381. DWORD flag = 0;
  2382. BOOL ballocated = FALSE;
  2383. BOOL bsleep = FALSE;
  2384. DWORD bufLength = 0;
  2385. DWORD sentBufLength;
  2386. PBYTE pbuffer = NULL;
  2387. PBYTE pallocResult;
  2388. BYTE buffer[ CONFIG_BUF_SIZE ];
  2389. //
  2390. // query config
  2391. //
  2392. if ( Argc < 1 )
  2393. {
  2394. goto Usage;
  2395. }
  2396. // config value
  2397. config = strtoul( Argv[0], &pendString, 10 );
  2398. Argc--;
  2399. Argv++;
  2400. // flag?
  2401. while ( Argc )
  2402. {
  2403. psznext = Argv[0];
  2404. // flag
  2405. if ( !_stricmp( psznext, "-f" ) ||
  2406. !_stricmp( psznext, "/f" ) )
  2407. {
  2408. Argc--;
  2409. Argv++;
  2410. flag = strtoul( Argv[0], &pendString, 16 );
  2411. Argc--;
  2412. Argv++;
  2413. if ( flag & DNS_CONFIG_FLAG_ALLOC )
  2414. {
  2415. bufLength = sizeof(PVOID);
  2416. pbuffer = buffer;
  2417. }
  2418. continue;
  2419. }
  2420. // length input
  2421. if ( !_stricmp( psznext, "-l" ) ||
  2422. !_stricmp( psznext, "/l" ) )
  2423. {
  2424. Argc--;
  2425. Argv++;
  2426. bufLength = strtoul( Argv[0], &pendString, 16 );
  2427. Argc--;
  2428. Argv++;
  2429. continue;
  2430. }
  2431. // sleep?
  2432. if ( !_stricmp( psznext, "-s" ) ||
  2433. !_stricmp( psznext, "/s" ) )
  2434. {
  2435. Argc--;
  2436. Argv++;
  2437. bsleep = TRUE;
  2438. continue;
  2439. }
  2440. // buffer
  2441. if ( !_stricmp( psznext, "-b" ) ||
  2442. !_stricmp( psznext, "/b" ) )
  2443. {
  2444. Argc--;
  2445. Argv++;
  2446. pbuffer = buffer;
  2447. bufLength = CONFIG_BUF_SIZE;
  2448. continue;
  2449. }
  2450. // adapter name
  2451. else
  2452. {
  2453. pwsadapter = DnsStringCopyAllocateEx(
  2454. Argv[0],
  2455. 0,
  2456. DnsCharSetAnsi, // ANSI in
  2457. DnsCharSetUnicode // unicode out
  2458. );
  2459. continue;
  2460. }
  2461. }
  2462. //
  2463. // query DNS config
  2464. //
  2465. sentBufLength = bufLength;
  2466. status = DnsQueryConfig(
  2467. config,
  2468. flag,
  2469. pwsadapter,
  2470. NULL,
  2471. pbuffer,
  2472. & bufLength );
  2473. if ( status == ERROR_SUCCESS )
  2474. {
  2475. printf(
  2476. "DnsQueryConfig() successful.\n"
  2477. "\tflag = 0x%.8X\n"
  2478. "\tadapter = %s\n"
  2479. "\tsent length = %d\n"
  2480. "\tlength required = %d\n",
  2481. flag,
  2482. pwsadapter,
  2483. sentBufLength,
  2484. bufLength );
  2485. if ( !pbuffer )
  2486. {
  2487. return( status );
  2488. }
  2489. printf(
  2490. "\tbuffer = %02x %02x %02x %02x ...\n",
  2491. pbuffer[0],
  2492. pbuffer[1],
  2493. pbuffer[2],
  2494. pbuffer[3] );
  2495. if ( flag & DNS_CONFIG_FLAG_ALLOC )
  2496. {
  2497. pbuffer = * (PVOID *) pbuffer;
  2498. }
  2499. switch( config )
  2500. {
  2501. case DnsConfigPrimaryDomainName_W:
  2502. printf(
  2503. "Primary domain name = %S\n",
  2504. pbuffer );
  2505. break;
  2506. case DnsConfigPrimaryDomainName_A:
  2507. case DnsConfigPrimaryDomainName_UTF8:
  2508. printf(
  2509. "Primary domain name = %s\n",
  2510. pbuffer );
  2511. break;
  2512. case DnsConfigDnsServerList:
  2513. DnsPrint_IpArray(
  2514. dnsup_PrintRoutine,
  2515. dnsup_PrintContext,
  2516. "DNS server list",
  2517. NULL,
  2518. (PIP_ARRAY) pbuffer );
  2519. break;
  2520. case DnsConfigPrimaryHostNameRegistrationEnabled:
  2521. printf(
  2522. "Is Primary registration enabled = %d\n",
  2523. *(PBOOL)pbuffer );
  2524. break;
  2525. case DnsConfigAdapterHostNameRegistrationEnabled:
  2526. printf(
  2527. "Is Adapter registration enabled = %d\n",
  2528. *(PBOOL)pbuffer );
  2529. break;
  2530. case DnsConfigAddressRegistrationMaxCount:
  2531. printf(
  2532. "Max IP registration count = %d\n",
  2533. *(PDWORD)pbuffer );
  2534. break;
  2535. default:
  2536. printf( "Unknown config %d", config );
  2537. }
  2538. }
  2539. else if ( status == ERROR_MORE_DATA )
  2540. {
  2541. printf(
  2542. "DnsQueryConfig() ERROR_MORE_DATA.\n"
  2543. "\tsent length = %d\n"
  2544. "\tlength required = %d\n",
  2545. sentBufLength,
  2546. bufLength );
  2547. }
  2548. else
  2549. {
  2550. printf(
  2551. "DnsQueryConfig() failed status = %d (0x%.8X).\n",
  2552. status, status );
  2553. }
  2554. if ( bsleep )
  2555. {
  2556. printf( "Sleeping" );
  2557. Sleep( MAXDWORD );
  2558. }
  2559. return( status );
  2560. Usage:
  2561. printf(
  2562. "usage:\n"
  2563. " DnsUp -config <Config> [-f <flag>] [-b] [-l <length>] [<adapter name>]\n"
  2564. );
  2565. return( ERROR_INVALID_PARAMETER );
  2566. }
  2567. DNS_STATUS
  2568. ProcessReplaceRecordSet(
  2569. IN DWORD Argc,
  2570. IN PSTR * Argv
  2571. )
  2572. {
  2573. DNS_STATUS status;
  2574. DWORD flags = 0;
  2575. PCHAR arg;
  2576. PDNS_RECORD prr = NULL;
  2577. HANDLE hCreds=NULL;
  2578. //
  2579. // flags?
  2580. //
  2581. if ( Argc < 1 )
  2582. {
  2583. goto Usage;
  2584. }
  2585. arg = Argv[0];
  2586. if ( strncmp( arg, "-f", 2 ) == 0 )
  2587. {
  2588. flags = strtoul( arg+2, NULL, 16 );
  2589. Argc--;
  2590. Argv++;
  2591. }
  2592. //
  2593. // build update packet RRs
  2594. //
  2595. prr = buildRecordList(
  2596. Argc,
  2597. Argv );
  2598. if ( !prr )
  2599. {
  2600. status = GetLastError();
  2601. if ( status != ERROR_SUCCESS )
  2602. {
  2603. printf( "ERROR: building records from arguments\n" );
  2604. goto Usage;
  2605. }
  2606. }
  2607. //
  2608. // build \ send update
  2609. //
  2610. status = DnsReplaceRecordSetA(
  2611. prr,
  2612. flags,
  2613. hCreds,
  2614. NULL, // no adapter list specified
  2615. NULL // reserved
  2616. );
  2617. Dns_RecordListFree( prr );
  2618. if ( status != ERROR_SUCCESS )
  2619. {
  2620. printf(
  2621. "DnsReplaceRecordSet failed, %x %s.\n",
  2622. status,
  2623. DnsStatusString(status) );
  2624. }
  2625. else
  2626. {
  2627. printf( "ReplaceRecordSet successfully completed.\n" );
  2628. }
  2629. return( status );
  2630. Usage:
  2631. Dns_RecordListFree( prr );
  2632. printf(
  2633. "usage:\n"
  2634. " DnsUp -rs [-f<Flags>] [<Record> | ...]\n"
  2635. " <Record> record for update packet\n"
  2636. " <Record> == (+)(u) <Name> <Type> [Data | ...]\n"
  2637. " <Name> - RR owner name\n"
  2638. " <Type> - record type (ex A, SRV, PTR, TXT, CNAME, etc.)\n"
  2639. " <Data> - data strings (type specific), if any\n"
  2640. );
  2641. return( ERROR_INVALID_PARAMETER );
  2642. }
  2643. DNS_STATUS
  2644. ProcessModifyRecordsInSet(
  2645. IN DWORD Argc,
  2646. IN PSTR * Argv
  2647. )
  2648. {
  2649. DNS_STATUS status;
  2650. DWORD flags = 0;
  2651. PCHAR arg;
  2652. PDNS_RECORD prr;
  2653. PDNS_RECORD prrAdd = NULL;
  2654. PDNS_RECORD prrDelete = NULL;
  2655. HANDLE hCreds=NULL;
  2656. INT addCount;
  2657. DNS_RRSET rrsetDelete;
  2658. DNS_RRSET rrsetAdd;
  2659. DNS_RRSET_INIT( rrsetAdd );
  2660. DNS_RRSET_INIT( rrsetDelete );
  2661. //
  2662. // flags?
  2663. //
  2664. if ( Argc < 1 )
  2665. {
  2666. goto Usage;
  2667. }
  2668. // flag?
  2669. arg = Argv[0];
  2670. if ( strncmp( arg, "-f", 2 ) == 0 )
  2671. {
  2672. flags = strtoul( arg+2, NULL, 16 );
  2673. Argc--;
  2674. Argv++;
  2675. }
  2676. //
  2677. // build update add RRs
  2678. //
  2679. prr = buildRecordList(
  2680. Argc,
  2681. Argv );
  2682. if ( !prr )
  2683. {
  2684. status = GetLastError();
  2685. if ( status != ERROR_SUCCESS )
  2686. {
  2687. printf( "ERROR: building records from arguments\n" );
  2688. goto Usage;
  2689. }
  2690. }
  2691. //
  2692. // build separate Add and Delete lists
  2693. //
  2694. while ( prr )
  2695. {
  2696. if ( prr->Flags.S.Delete )
  2697. {
  2698. DNS_RRSET_ADD( rrsetDelete, prr );
  2699. }
  2700. else
  2701. {
  2702. DNS_RRSET_ADD( rrsetAdd, prr );
  2703. }
  2704. prr = prr->pNext;
  2705. }
  2706. DNS_RRSET_TERMINATE( rrsetAdd );
  2707. DNS_RRSET_TERMINATE( rrsetDelete );
  2708. //
  2709. // build \ send update
  2710. //
  2711. status = DnsModifyRecordsInSet_A(
  2712. rrsetAdd.pFirstRR,
  2713. rrsetDelete.pFirstRR,
  2714. flags,
  2715. hCreds,
  2716. NULL, // no adapter list specified
  2717. NULL // reserved
  2718. );
  2719. Dns_RecordListFree( rrsetAdd.pFirstRR );
  2720. Dns_RecordListFree( rrsetDelete.pFirstRR );
  2721. if ( status != ERROR_SUCCESS )
  2722. {
  2723. printf(
  2724. "DnsModifyRecordsInSet failed, %x %s.\n",
  2725. status,
  2726. DnsStatusString(status) );
  2727. }
  2728. else
  2729. {
  2730. printf( "ModifyRecordsInSet successfully completed.\n" );
  2731. }
  2732. return( status );
  2733. Usage:
  2734. Dns_RecordListFree( rrsetAdd.pFirstRR );
  2735. Dns_RecordListFree( rrsetDelete.pFirstRR );
  2736. printf(
  2737. "usage:\n"
  2738. " DnsUp -mr [-f<Flags>] [<Record> | ...]\n"
  2739. " <Record> == (-,+)(u) <Name> <Type> [Data | ...]\n"
  2740. " (-,+) - add or delete, exist or no-exist flag\n"
  2741. " <Name> - RR owner name\n"
  2742. " <Type> - record type (ex A, SRV, PTR, TXT, CNAME, etc.)\n"
  2743. " <Data> - data strings (type specific), if any\n"
  2744. );
  2745. return( ERROR_INVALID_PARAMETER );
  2746. }
  2747. //
  2748. // Winsock \ RnR
  2749. //
  2750. //
  2751. // Protocol array for WSAQUERYSET
  2752. //
  2753. // DCR: may want to default to NULL instead?
  2754. //
  2755. AFPROTOCOLS g_ProtocolArray[2] =
  2756. {
  2757. { AF_INET, IPPROTO_UDP },
  2758. { AF_INET, IPPROTO_TCP }
  2759. };
  2760. //
  2761. // Service GUIDs
  2762. //
  2763. GUID HostNameGuid = SVCID_HOSTNAME;
  2764. GUID HostAddrByNameGuid = SVCID_INET_HOSTADDRBYNAME;
  2765. GUID AddressGuid = SVCID_INET_HOSTADDRBYINETSTRING;
  2766. GUID IANAGuid = SVCID_INET_SERVICEBYNAME;
  2767. typedef struct _GuidStringMap
  2768. {
  2769. LPGUID pGuid;
  2770. LPSTR pString;
  2771. };
  2772. struct _GuidStringMap GuidMapTable[] =
  2773. {
  2774. & HostNameGuid , "HostName" ,
  2775. & HostAddrByNameGuid , "AddrByName" ,
  2776. & HostAddrByNameGuid , "HostAddrByName" ,
  2777. & AddressGuid , "HostAddrByInetString" ,
  2778. & IANAGuid , "ServiceByName" ,
  2779. & IANAGuid , "Iana" ,
  2780. NULL , "NULL" ,
  2781. NULL , NULL ,
  2782. };
  2783. PGUID
  2784. guidForString(
  2785. IN PSTR pszGuidName
  2786. )
  2787. /*++
  2788. Routine Description:
  2789. Get GUID for string.
  2790. This is to allow simple specification of command line for GUIDs.
  2791. Arguments:
  2792. pszGuidName -- name of desired GUID
  2793. (see table above for current names of common guids)
  2794. Return Value:
  2795. Ptr to desired GUID if found.
  2796. Errors default to hostname (host lookup) GUID.
  2797. --*/
  2798. {
  2799. DWORD i;
  2800. PCHAR pname;
  2801. //
  2802. // if no guid name, use host name guid
  2803. //
  2804. if ( !pszGuidName )
  2805. {
  2806. return &HostNameGuid;
  2807. }
  2808. //
  2809. // find guid matching name in table
  2810. //
  2811. i = 0;
  2812. while ( pname = GuidMapTable[i].pString )
  2813. {
  2814. if ( _stricmp( pname, pszGuidName ) == 0 )
  2815. {
  2816. return GuidMapTable[i].pGuid;
  2817. }
  2818. i++;
  2819. }
  2820. // default to HostName guid
  2821. return &HostNameGuid;
  2822. }
  2823. //
  2824. // Parsing utility
  2825. //
  2826. typedef struct _RnRParseBlob
  2827. {
  2828. HANDLE Handle;
  2829. PCHAR pBuffer;
  2830. PWSAQUERYSET pQuerySet;
  2831. PGUID pGuid;
  2832. PSTR pName;
  2833. DWORD Flags;
  2834. DWORD NameSpace;
  2835. DWORD BufferLength;
  2836. }
  2837. RNR_PARSE_BLOB, *PRNR_PARSE_BLOB;
  2838. VOID
  2839. printRnRArgHelp(
  2840. VOID
  2841. )
  2842. /*++
  2843. Routine Description:
  2844. Print RnR argument usage.
  2845. Arguments:
  2846. None
  2847. Return Value:
  2848. None
  2849. --*/
  2850. {
  2851. //
  2852. // describe standard RnR lookup arguements
  2853. //
  2854. // DCR: add flag, ptr validity check
  2855. // DCR: add "already set" check for names and guids
  2856. // DCR: fix zero flag case below
  2857. //
  2858. printf(
  2859. "\tRnR Arguments:\n"
  2860. "\t\t-h<handle> -- ptr in hex to lookup handle\n"
  2861. "\t\t-b<buffer> -- ptr in hex to result buffer to use\n"
  2862. "\t\t-l<buf length> -- buffer length to use\n"
  2863. "\t\t-f<flag> -- RnR control flag in hex or LUP_X mneumonic\n"
  2864. "\t\t may be multiple flags specified\n"
  2865. "\t\t-q<query set> -- ptr in hex to existing WSAQUERYSET struct\n"
  2866. "\t\t-i<name space> -- name space id NS_X mneumonic\n"
  2867. "\t\t-a<name> -- ANSI lookup name\n"
  2868. "\t\t-g<guid> -- NS GUID mneumonic:\n"
  2869. "\t\t HostName\n"
  2870. "\t\t HostAddrByName\n"
  2871. "\t\t HostAddrByInetString\n"
  2872. "\t\t ServiceByName\n"
  2873. );
  2874. }
  2875. DNS_STATUS
  2876. parseForRnr(
  2877. IN DWORD Argc,
  2878. IN PSTR * Argv,
  2879. OUT PRNR_PARSE_BLOB pBlob
  2880. )
  2881. /*++
  2882. Routine Description:
  2883. Parse RnR routine command line params.
  2884. This is to simplify avoid duplicate parsing for various RnR
  2885. functions.
  2886. Arguments:
  2887. Argc -- argc
  2888. Argv -- argument array
  2889. pBlob -- ptr to RnR parsing blob to be filled by function
  2890. Return Value:
  2891. ERROR_SUCCESS if successful parsing.
  2892. ErrorCode on parsing error.
  2893. (Note, currently errors are ignored and whatever parsing is possible
  2894. is completed.)
  2895. --*/
  2896. {
  2897. PCHAR parg;
  2898. //
  2899. // init parse blob
  2900. //
  2901. RtlZeroMemory(
  2902. pBlob,
  2903. sizeof(RNR_PARSE_BLOB) );
  2904. //
  2905. // read arguments
  2906. //
  2907. // DCR: add flag, ptr validity check
  2908. // DCR: add "already set" check for names and guids
  2909. // DCR: fix zero flag case below
  2910. //
  2911. while ( Argc )
  2912. {
  2913. parg = Argv[0];
  2914. if ( strncmp( parg, "-h", 2 ) == 0 )
  2915. {
  2916. pBlob->Handle = (PVOID) (ULONG_PTR) strtoul( parg+2, NULL, 16 );
  2917. }
  2918. else if ( strncmp( parg, "-f", 2 ) == 0 )
  2919. {
  2920. DWORD thisFlag;
  2921. thisFlag = strtoul( parg+2, NULL, 16 );
  2922. if ( thisFlag == 0 )
  2923. {
  2924. thisFlag = Dns_RnrLupFlagForString( parg+2, 0 );
  2925. }
  2926. pBlob->Flags |= thisFlag;
  2927. }
  2928. else if ( strncmp( parg, "-b", 2 ) == 0 )
  2929. {
  2930. pBlob->pBuffer = (PBYTE) (ULONG_PTR) strtoul( parg+2, NULL, 16 );
  2931. }
  2932. else if ( strncmp( parg, "-l", 2 ) == 0 )
  2933. {
  2934. pBlob->BufferLength = strtoul( parg+2, NULL, 10 );
  2935. }
  2936. else if ( strncmp( parg, "-a", 2 ) == 0 )
  2937. {
  2938. pBlob->pName = parg+2;
  2939. }
  2940. else if ( strncmp( parg, "-g", 2 ) == 0 )
  2941. {
  2942. pBlob->pGuid = guidForString( parg+2 );
  2943. }
  2944. else if ( strncmp( parg, "-i", 2 ) == 0 )
  2945. {
  2946. pBlob->NameSpace = Dns_RnrNameSpaceIdForString(
  2947. parg+2,
  2948. 0 // length unknown
  2949. );
  2950. }
  2951. else if ( strncmp( parg, "-q", 2 ) == 0 )
  2952. {
  2953. pBlob->pQuerySet = (PWSAQUERYSET) (ULONG_PTR) strtoul( parg+2, NULL, 16 );
  2954. }
  2955. else if ( *parg=='?' || strncmp( parg, "-?", 2 ) == 0 )
  2956. {
  2957. goto Usage;
  2958. }
  2959. else
  2960. {
  2961. printf( "Unknown Arg = %s\n", parg );
  2962. goto Usage;
  2963. }
  2964. Argc--;
  2965. Argv++;
  2966. }
  2967. return( ERROR_SUCCESS );
  2968. Usage:
  2969. printRnRArgHelp();
  2970. return( ERROR_INVALID_PARAMETER );
  2971. }
  2972. PWSAQUERYSET
  2973. buildWsaQuerySet(
  2974. IN PRNR_PARSE_BLOB pBlob
  2975. )
  2976. /*++
  2977. Routine Description:
  2978. Create (allocate) a query set.
  2979. Arguments:
  2980. pBlob -- ptr to blob of parsing info
  2981. Return Value:
  2982. Ptr to new WSAQUERYSET struct.
  2983. NULL on allocation failure.
  2984. --*/
  2985. {
  2986. PWSAQUERYSET pwsaq;
  2987. //
  2988. // allocate
  2989. //
  2990. pwsaq = ALLOCATE_HEAP_ZERO( sizeof(WSAQUERYSET) );
  2991. if ( !pwsaq )
  2992. {
  2993. return( NULL );
  2994. }
  2995. //
  2996. // basic
  2997. // - default GUID to hostname lookup
  2998. //
  2999. pwsaq->dwSize = sizeof(WSAQUERYSET);
  3000. pwsaq->dwNumberOfProtocols = 2;
  3001. pwsaq->lpafpProtocols = g_ProtocolArray;
  3002. pwsaq->lpServiceClassId = & HostNameGuid;
  3003. //
  3004. // tack on info from blob
  3005. // - keep parsing generic by casting name to TSTR
  3006. //
  3007. if ( pBlob )
  3008. {
  3009. pwsaq->dwNameSpace = pBlob->NameSpace;
  3010. pwsaq->lpszServiceInstanceName = (LPTSTR) pBlob->pName;
  3011. pwsaq->lpServiceClassId = pBlob->pGuid;
  3012. }
  3013. return (PWSAQUERYSET) pwsaq;
  3014. }
  3015. DNS_STATUS
  3016. ProcessLookupServiceBegin(
  3017. IN DWORD Argc,
  3018. IN PSTR * Argv
  3019. )
  3020. {
  3021. DNS_STATUS status;
  3022. HANDLE handle = NULL;
  3023. PWSAQUERYSET pquerySet = NULL;
  3024. PWSAQUERYSET pquerySetLocal = NULL;
  3025. RNR_PARSE_BLOB blob;
  3026. //
  3027. // WSALookupServiceBegin
  3028. //
  3029. //
  3030. // parse args
  3031. //
  3032. status = parseForRnr( Argc, Argv, &blob );
  3033. if ( status != ERROR_SUCCESS )
  3034. {
  3035. goto Usage;
  3036. }
  3037. //
  3038. // setup query set
  3039. //
  3040. pquerySet = blob.pQuerySet;
  3041. if ( !pquerySet )
  3042. {
  3043. pquerySet = buildWsaQuerySet( &blob );
  3044. pquerySetLocal = pquerySet;
  3045. }
  3046. IF_DNSDBG( INIT )
  3047. {
  3048. DnsDbg_WsaQuerySet(
  3049. "Query set to WLSBegin",
  3050. pquerySet,
  3051. FALSE // currently ANSI
  3052. );
  3053. }
  3054. DnsPrint_WsaQuerySet(
  3055. dnsup_PrintRoutine,
  3056. dnsup_PrintContext,
  3057. "QuerySet to LookupServiceBegin",
  3058. (PWSAQUERYSET) pquerySet,
  3059. FALSE // ANSI call
  3060. );
  3061. //
  3062. // force winsock start
  3063. //
  3064. Dns_InitializeWinsock();
  3065. //
  3066. // call
  3067. //
  3068. status = WSALookupServiceBeginA(
  3069. pquerySet,
  3070. blob.Flags,
  3071. & handle );
  3072. if ( status != ERROR_SUCCESS )
  3073. {
  3074. status = GetLastError();
  3075. printf(
  3076. "WSALookupServiceBegin( %p, %08x, %p ) failed, %d %s.\n",
  3077. pquerySet,
  3078. blob.Flags,
  3079. & handle,
  3080. status,
  3081. DnsStatusString(status) );
  3082. if ( pquerySetLocal )
  3083. {
  3084. FREE_HEAP( pquerySetLocal );
  3085. }
  3086. }
  3087. else
  3088. {
  3089. printf(
  3090. "WSALookupServiceBegin() succeeded.\n"
  3091. "\thandle = %p\n"
  3092. "\tqueryset = %p\n",
  3093. handle,
  3094. pquerySet );
  3095. }
  3096. return( status );
  3097. Usage:
  3098. printf(
  3099. "WSALookupServiceBegin\n"
  3100. "usage:\n"
  3101. " DnsUp -lsb [RnR args]\n"
  3102. " note handle arg does not apply\n"
  3103. );
  3104. printRnRArgHelp();
  3105. return( ERROR_INVALID_PARAMETER );
  3106. }
  3107. DNS_STATUS
  3108. ProcessLookupServiceNext(
  3109. IN DWORD Argc,
  3110. IN PSTR * Argv
  3111. )
  3112. {
  3113. DNS_STATUS status;
  3114. HANDLE handle = NULL;
  3115. PCHAR pbuf = NULL;
  3116. PCHAR pbufLocal = NULL;
  3117. DWORD bufLength;
  3118. RNR_PARSE_BLOB blob;
  3119. //
  3120. // WSALookupServiceNext
  3121. //
  3122. //
  3123. // parse args
  3124. //
  3125. status = parseForRnr( Argc, Argv, &blob );
  3126. if ( status != ERROR_SUCCESS )
  3127. {
  3128. goto Usage;
  3129. }
  3130. //
  3131. // if no handle need to do WLSBegin
  3132. //
  3133. handle = blob.Handle;
  3134. if ( !handle )
  3135. {
  3136. goto Usage;
  3137. }
  3138. //
  3139. // setup buffer
  3140. //
  3141. bufLength = blob.BufferLength;
  3142. pbuf = blob.pBuffer;
  3143. if ( !pbuf && bufLength )
  3144. {
  3145. pbuf = ALLOCATE_HEAP( blob.BufferLength );
  3146. if ( !pbuf )
  3147. {
  3148. status = DNS_ERROR_NO_MEMORY;
  3149. }
  3150. pbufLocal = pbuf;
  3151. }
  3152. //
  3153. // call
  3154. //
  3155. printf(
  3156. "Enter WSALookupServiceNext()\n"
  3157. "\thandle = %p\n"
  3158. "\tflag = %08x\n"
  3159. "\tlength = %p (%d)\n"
  3160. "\tbuffer = %p\n",
  3161. handle,
  3162. blob.Flags,
  3163. &bufLength, bufLength,
  3164. pbuf );
  3165. status = WSALookupServiceNextA(
  3166. handle,
  3167. blob.Flags,
  3168. & bufLength,
  3169. (PWSAQUERYSETA) pbuf );
  3170. if ( status != ERROR_SUCCESS )
  3171. {
  3172. status = GetLastError();
  3173. printf(
  3174. "WSALookupServiceNext( h=%p, f=%08x, len=%d, buf=%p ) failed, %d %s.\n",
  3175. handle,
  3176. blob.Flags,
  3177. bufLength,
  3178. pbuf,
  3179. status,
  3180. DnsStatusString(status) );
  3181. if ( pbufLocal )
  3182. {
  3183. FREE_HEAP( pbufLocal );
  3184. }
  3185. }
  3186. else
  3187. {
  3188. printf(
  3189. "WSALookupServiceNext() succeeded.\n"
  3190. "\thandle = %p\n"
  3191. "\tbuf length = %d\n"
  3192. "\tpbuffer = %p\n",
  3193. handle,
  3194. bufLength,
  3195. pbuf );
  3196. if ( pbuf )
  3197. {
  3198. DnsPrint_WsaQuerySet(
  3199. dnsup_PrintRoutine,
  3200. dnsup_PrintContext,
  3201. "Result from LookupServiceNext",
  3202. (PWSAQUERYSET) pbuf,
  3203. FALSE // ANSI call
  3204. );
  3205. }
  3206. }
  3207. return( status );
  3208. Usage:
  3209. printf(
  3210. "WSALookupServiceNext\n"
  3211. "usage:\n"
  3212. " DnsUp -lsn [RnR args]\n"
  3213. " valid WSALookupServiceNext args:\n"
  3214. " <handle> <flags> <buffer> <buf length>\n"
  3215. " <handle> is required, call WSALookupServiceBegin\n"
  3216. " to get handle to use with this function\n"
  3217. );
  3218. printRnRArgHelp();
  3219. return( ERROR_INVALID_PARAMETER );
  3220. }
  3221. DNS_STATUS
  3222. ProcessLookupServiceEnd(
  3223. IN DWORD Argc,
  3224. IN PSTR * Argv
  3225. )
  3226. {
  3227. DNS_STATUS status;
  3228. HANDLE handle;
  3229. //
  3230. // WSALookupServiceEnd <handle>
  3231. //
  3232. if ( Argc < 1 )
  3233. {
  3234. goto Usage;
  3235. }
  3236. // read handle
  3237. //
  3238. // DCR: need QWORD read to handle win64 case
  3239. handle = (HANDLE) (UINT_PTR) strtoul( Argv[0], NULL, 16 );
  3240. //
  3241. // call
  3242. //
  3243. status = WSALookupServiceEnd( handle );
  3244. if ( status != ERROR_SUCCESS )
  3245. {
  3246. printf(
  3247. "WSALookupServiceEnd( %p ) failed, %d %s.\n",
  3248. handle,
  3249. status,
  3250. DnsStatusString(status) );
  3251. }
  3252. else
  3253. {
  3254. printf(
  3255. "WSALookupServiceEnd( %p ) succeeded.\n",
  3256. handle );
  3257. }
  3258. Dns_CleanupWinsock();
  3259. return( status );
  3260. Usage:
  3261. printf(
  3262. "WSALookupServiceEnd\n"
  3263. "usage:\n"
  3264. " DnsUp -lse -h<handle>\n"
  3265. " <handle> - lookup handle to close in hex.\n"
  3266. " handle is from prior WSALookupServiceBegin call.\n"
  3267. );
  3268. return( ERROR_INVALID_PARAMETER );
  3269. }
  3270. DNS_STATUS
  3271. ProcessGetHostName(
  3272. IN DWORD Argc,
  3273. IN PSTR * Argv
  3274. )
  3275. {
  3276. DNS_STATUS status;
  3277. CHAR nameBuffer[ DNS_MAX_NAME_BUFFER_LENGTH ];
  3278. DWORD length = DNS_MAX_NAME_BUFFER_LENGTH;
  3279. PCHAR pname = nameBuffer;
  3280. INT result;
  3281. //
  3282. // gethostname [-n<name>] [-l<length>]
  3283. //
  3284. if ( Argc > 2 )
  3285. {
  3286. goto Usage;
  3287. }
  3288. //
  3289. // get optional name or length
  3290. // - defaults to full size buffer above
  3291. //
  3292. while ( Argc )
  3293. {
  3294. PCHAR arg = Argv[0];
  3295. if ( strncmp( arg, "-n", 2 ) == 0 )
  3296. {
  3297. pname = getNamePointer( arg+2 );
  3298. Argc--;
  3299. Argv++;
  3300. }
  3301. else if ( strncmp( arg, "-l", 2 ) == 0 )
  3302. {
  3303. length = strtoul( arg+2, NULL, 10 );
  3304. Argc--;
  3305. Argv++;
  3306. }
  3307. else
  3308. {
  3309. goto Usage;
  3310. }
  3311. }
  3312. //
  3313. // force winsock start
  3314. //
  3315. Dns_InitializeWinsock();
  3316. //
  3317. // call
  3318. //
  3319. result = gethostname( (PSTR)pname, length );
  3320. if ( result != 0 )
  3321. {
  3322. status = GetLastError();
  3323. printf(
  3324. "gethostname(), %d (%x) %s.\n",
  3325. status, status,
  3326. DnsStatusString(status) );
  3327. }
  3328. else
  3329. {
  3330. printf(
  3331. "gethostname() successfully completed.\n"
  3332. "\tname = %s\n",
  3333. pname );
  3334. }
  3335. return( status );
  3336. Usage:
  3337. printf(
  3338. "gethostname\n"
  3339. "usage:\n"
  3340. " DnsUp -ghn [-n<Name>] [-l<length>]\n"
  3341. " <Name> - one of special names.\n"
  3342. " <Length> - buffer length to pass in\n"
  3343. " Defaults to valid name buffer of full DNS name length\n"
  3344. );
  3345. return( ERROR_INVALID_PARAMETER );
  3346. }
  3347. DNS_STATUS
  3348. ProcessGetHostByName(
  3349. IN DWORD Argc,
  3350. IN PSTR * Argv
  3351. )
  3352. {
  3353. DNS_STATUS status;
  3354. PCHAR pname;
  3355. PHOSTENT phost;
  3356. //
  3357. // gethostbyname <name>
  3358. //
  3359. if ( Argc != 1 )
  3360. {
  3361. goto Usage;
  3362. }
  3363. // name
  3364. pname = getNamePointer( Argv[0] );
  3365. //
  3366. // force winsock start
  3367. //
  3368. Dns_InitializeWinsock();
  3369. //
  3370. // call
  3371. //
  3372. phost = gethostbyname( (PCSTR)pname );
  3373. status = GetLastError();
  3374. if ( !phost )
  3375. {
  3376. printf(
  3377. "gethostbyname(), %x %s.\n",
  3378. status,
  3379. DnsStatusString(status) );
  3380. }
  3381. else
  3382. {
  3383. printf( "gethostbyname successfully completed.\n" );
  3384. DnsPrint_Hostent(
  3385. dnsup_PrintRoutine,
  3386. dnsup_PrintContext,
  3387. NULL, // default header
  3388. phost,
  3389. FALSE // ANSI
  3390. );
  3391. }
  3392. return( status );
  3393. Usage:
  3394. printf(
  3395. "gethostbyname\n"
  3396. "usage:\n"
  3397. " DnsUp -ghbn <Name>\n"
  3398. " <Name> - DNS name to query.\n"
  3399. " \"NULL\" for null input.\n"
  3400. " \"blank\" for blank (empty string)\n"
  3401. );
  3402. return( ERROR_INVALID_PARAMETER );
  3403. }
  3404. DNS_STATUS
  3405. ProcessGetHostByAddr(
  3406. IN DWORD Argc,
  3407. IN PSTR * Argv
  3408. )
  3409. {
  3410. DNS_STATUS status;
  3411. PCHAR pname;
  3412. PCHAR paddr;
  3413. PHOSTENT phost;
  3414. IP6_ADDRESS ip6;
  3415. INT length;
  3416. INT family;
  3417. //
  3418. // gethostbyaddr <ip> [len] [family]
  3419. //
  3420. if ( Argc < 1 || Argc > 3 )
  3421. {
  3422. goto Usage;
  3423. }
  3424. //
  3425. // address
  3426. //
  3427. pname = getNamePointer( Argv[0] );
  3428. Argc--;
  3429. Argv++;
  3430. length = sizeof(IP6_ADDRESS);
  3431. family = 0;
  3432. if ( pname
  3433. &&
  3434. Dns_StringToAddress_A(
  3435. (PCHAR) & ip6,
  3436. & length,
  3437. pname,
  3438. & family ) )
  3439. {
  3440. paddr = (PCHAR) &ip6;
  3441. }
  3442. else
  3443. {
  3444. paddr = pname;
  3445. length = sizeof(IP4_ADDRESS);
  3446. family = AF_INET;
  3447. }
  3448. // length -- optional
  3449. if ( Argc )
  3450. {
  3451. length = strtoul( Argv[0], NULL, 10 );
  3452. Argc--;
  3453. Argv++;
  3454. }
  3455. // family -- optional
  3456. if ( Argc )
  3457. {
  3458. family = strtoul( Argv[0], NULL, 10 );
  3459. Argc--;
  3460. Argv++;
  3461. }
  3462. //
  3463. // force winsock start
  3464. //
  3465. Dns_InitializeWinsock();
  3466. //
  3467. // call
  3468. //
  3469. printf(
  3470. "calling gethostbyaddr( %p, %d, %d )\n",
  3471. paddr,
  3472. length,
  3473. family );
  3474. phost = gethostbyaddr(
  3475. (PSTR)paddr,
  3476. length,
  3477. family );
  3478. status = GetLastError();
  3479. if ( !phost )
  3480. {
  3481. printf(
  3482. "gethostbyaddr(), %d %s.\n",
  3483. status,
  3484. DnsStatusString(status) );
  3485. }
  3486. else
  3487. {
  3488. printf( "gethostbyaddr successfully completed.\n" );
  3489. DnsPrint_Hostent(
  3490. dnsup_PrintRoutine,
  3491. dnsup_PrintContext,
  3492. NULL, // default header
  3493. phost,
  3494. FALSE // ANSI
  3495. );
  3496. }
  3497. return( status );
  3498. Usage:
  3499. printf(
  3500. "gethostbyaddr\n"
  3501. "usage:\n"
  3502. " DnsUp -ghba <Address> [<length>] [<family>]\n"
  3503. " <Name> - DNS name to query.\n"
  3504. " \"null\" for null input.\n"
  3505. " \"blank\" for blank (empty string)\n"
  3506. " [length] - length of address\n"
  3507. " defaults to sizeof(IP_ADDRESS)\n"
  3508. " [family] - address family\n"
  3509. " AF_INET = %d\n"
  3510. " AF_INET6 = %d\n"
  3511. " AF_ATM = %d\n"
  3512. " defaults to AF_INET\n",
  3513. AF_INET,
  3514. AF_INET6,
  3515. AF_ATM );
  3516. return( ERROR_INVALID_PARAMETER );
  3517. }
  3518. DNS_STATUS
  3519. ProcessGetAddrInfo(
  3520. IN DWORD Argc,
  3521. IN PSTR * Argv
  3522. )
  3523. {
  3524. DNS_STATUS status;
  3525. PCHAR pname;
  3526. PSTR pservice = NULL;
  3527. PADDRINFO phint = NULL;
  3528. PADDRINFO paddrInfo = NULL;
  3529. ADDRINFO hintAddrInfo;
  3530. BOOL fhint = FALSE;
  3531. INT result;
  3532. //
  3533. // getaddrinfo <name> [service] [hints]
  3534. //
  3535. if ( Argc < 1 )
  3536. {
  3537. goto Usage;
  3538. }
  3539. //
  3540. // name
  3541. //
  3542. pname = getNamePointer( Argv[0] );
  3543. Argc--;
  3544. Argv++;
  3545. //
  3546. // setup hints
  3547. // - default flags to include canonnical name
  3548. //
  3549. RtlZeroMemory(
  3550. & hintAddrInfo,
  3551. sizeof(hintAddrInfo) );
  3552. hintAddrInfo.ai_flags = AI_CANONNAME;
  3553. //
  3554. // get optional service name or hints
  3555. //
  3556. while ( Argc )
  3557. {
  3558. PCHAR arg = Argv[0];
  3559. if ( strncmp( arg, "-s", 2 ) == 0 )
  3560. {
  3561. pservice = getNamePointer( arg+2 );
  3562. Argc--;
  3563. Argv++;
  3564. }
  3565. if ( strncmp( arg, "-h", 2 ) == 0 )
  3566. {
  3567. fhint = TRUE;
  3568. Argc--;
  3569. Argv++;
  3570. }
  3571. else if ( strncmp( arg, "-f", 2 ) == 0 )
  3572. {
  3573. hintAddrInfo.ai_flags = strtoul( arg+2, NULL, 16 );
  3574. fhint = TRUE;
  3575. Argc--;
  3576. Argv++;
  3577. }
  3578. else if ( strncmp( arg, "-m", 2 ) == 0 )
  3579. {
  3580. hintAddrInfo.ai_family = strtoul( arg+2, NULL, 10 );
  3581. fhint = TRUE;
  3582. Argc--;
  3583. Argv++;
  3584. }
  3585. else if ( strncmp( arg, "-t", 2 ) == 0 )
  3586. {
  3587. hintAddrInfo.ai_socktype = strtoul( arg+2, NULL, 10 );
  3588. fhint = TRUE;
  3589. Argc--;
  3590. Argv++;
  3591. }
  3592. else if ( strncmp( arg, "-p", 2 ) == 0 )
  3593. {
  3594. hintAddrInfo.ai_protocol = strtoul( arg+2, NULL, 10 );
  3595. fhint = TRUE;
  3596. Argc--;
  3597. Argv++;
  3598. }
  3599. else if ( strncmp( arg, "-l", 2 ) == 0 )
  3600. {
  3601. hintAddrInfo.ai_addrlen = strtoul( arg+2, NULL, 10 );
  3602. fhint = TRUE;
  3603. Argc--;
  3604. Argv++;
  3605. }
  3606. else
  3607. {
  3608. goto Usage;
  3609. }
  3610. }
  3611. //
  3612. // setup hints
  3613. //
  3614. if ( fhint )
  3615. {
  3616. phint = &hintAddrInfo;
  3617. }
  3618. //
  3619. // force winsock start
  3620. //
  3621. Dns_InitializeWinsock();
  3622. //
  3623. // call
  3624. //
  3625. printf(
  3626. "calling getaddrinfo()\n"
  3627. "\tpname = %s\n"
  3628. "\tpservice = %s\n"
  3629. "\tphint = %p\n"
  3630. "\tpaddrinfo buf = %p\n",
  3631. pname,
  3632. pservice,
  3633. phint,
  3634. paddrInfo );
  3635. if ( phint )
  3636. {
  3637. DnsPrint_AddrInfo(
  3638. dnsup_PrintRoutine,
  3639. dnsup_PrintContext,
  3640. "hint addrinfo",
  3641. 1, // indent
  3642. phint
  3643. );
  3644. }
  3645. result = getaddrinfo(
  3646. pname,
  3647. pservice,
  3648. phint,
  3649. & paddrInfo );
  3650. status = GetLastError();
  3651. if ( result != NO_ERROR )
  3652. {
  3653. printf(
  3654. "getaddrinfo(), %x %s.\n",
  3655. status,
  3656. DnsStatusString(status) );
  3657. }
  3658. else
  3659. {
  3660. printf( "getaddrinfo successfully completed.\n" );
  3661. DnsPrint_AddrInfo(
  3662. dnsup_PrintRoutine,
  3663. dnsup_PrintContext,
  3664. NULL, // default header
  3665. 0, // no indent
  3666. paddrInfo
  3667. );
  3668. freeaddrinfo( paddrInfo );
  3669. }
  3670. return( status );
  3671. Usage:
  3672. printf(
  3673. "getaddrinfo\n"
  3674. "usage:\n"
  3675. " DnsUp -gai <Name> [-s<Service>] [-h] [-f<flags>] [-m<family>]\n"
  3676. " [-p<Protocol>] [-t<SockType>] [-l<length>]\n"
  3677. " <Name> - DNS name to query.\n"
  3678. " \"null\" for null input.\n"
  3679. " \"blank\" for blank (empty string)\n"
  3680. " <Service> - service name to query for.\n"
  3681. " [-h] - use hints (this allows empty hint buffer\n"
  3682. " <flags> - hint flags\n"
  3683. " AI_PASSIVE = %0x\n"
  3684. " AI_CANONNAME = %0x\n"
  3685. " AI_NUMERICHOST = %0x\n"
  3686. " <family> - hint family\n"
  3687. " AF_INET = %d\n"
  3688. " AF_INET6 = %d\n"
  3689. " AF_ATM = %d\n"
  3690. " <socktype> - hint socket type\n"
  3691. " <protocol> - hint protocol\n"
  3692. " <length> - hint address length\n",
  3693. AI_PASSIVE,
  3694. AI_CANONNAME,
  3695. AI_NUMERICHOST,
  3696. AF_INET,
  3697. AF_INET6,
  3698. AF_ATM );
  3699. return( ERROR_INVALID_PARAMETER );
  3700. }
  3701. DNS_STATUS
  3702. ProcessGetNameInfo(
  3703. IN DWORD Argc,
  3704. IN PSTR * Argv
  3705. )
  3706. {
  3707. DNS_STATUS status;
  3708. BOOL result;
  3709. PCHAR paddr = NULL;
  3710. DWORD addrLength;
  3711. DWORD family;
  3712. DWORD flags = 0;
  3713. SOCKADDR_IN6 sockaddr;
  3714. CHAR hostBuffer[ DNS_MAX_NAME_BUFFER_LENGTH ];
  3715. CHAR serviceBuffer[ DNS_MAX_NAME_BUFFER_LENGTH ];
  3716. PSOCKADDR_IN6 psockaddr = &sockaddr;
  3717. PCHAR pservice = serviceBuffer;
  3718. PCHAR phost = hostBuffer;
  3719. DWORD sockaddrLength = sizeof(sockaddr);
  3720. DWORD serviceLength = sizeof(hostBuffer);
  3721. DWORD hostLength = DNS_MAX_NAME_BUFFER_LENGTH;
  3722. //
  3723. // getnameinfo <address> [sockaddr fields | args]
  3724. //
  3725. if ( Argc < 1 )
  3726. {
  3727. goto Usage;
  3728. }
  3729. //
  3730. // address
  3731. //
  3732. RtlZeroMemory(
  3733. psockaddr,
  3734. sizeof(*psockaddr) );
  3735. #if 0
  3736. if ( getAddressPointer(
  3737. Argv[0],
  3738. & paddr,
  3739. & addrLength,
  3740. & family ) )
  3741. {
  3742. sockaddr.sin6_family = (SHORT) family;
  3743. if ( family == AF_INET )
  3744. {
  3745. RtlCopyMemory(
  3746. & ((PSOCKADDR_IN)psockaddr)->sin_addr,
  3747. paddr,
  3748. addrLength );
  3749. sockaddrLength = sizeof(SOCKADDR_IN);
  3750. }
  3751. else // IP6
  3752. {
  3753. RtlCopyMemory(
  3754. & psockaddr->sin6_addr,
  3755. paddr,
  3756. addrLength );
  3757. sockaddrLength = sizeof(SOCKADDR_IN6);
  3758. }
  3759. }
  3760. else // special bogus address, use it directly
  3761. {
  3762. psockaddr = (PSOCKADDR_IN6) paddr;
  3763. }
  3764. #endif
  3765. if ( getAddressPointer(
  3766. Argv[0],
  3767. & paddr,
  3768. & addrLength,
  3769. & family ) )
  3770. {
  3771. status = Dns_AddressToSockaddr(
  3772. (PSOCKADDR) &sockaddr,
  3773. & sockaddrLength,
  3774. TRUE, // clear
  3775. paddr,
  3776. addrLength,
  3777. family );
  3778. if ( status != NO_ERROR )
  3779. {
  3780. goto Usage;
  3781. }
  3782. }
  3783. else // special bogus address, use it directly
  3784. {
  3785. psockaddr = (PSOCKADDR_IN6) paddr;
  3786. }
  3787. Argc--;
  3788. Argv++;
  3789. //
  3790. // get sockaddr fields or optional arguments
  3791. // - note, if using bogus sockaddr, the sockaddr tweaks are lost
  3792. //
  3793. while ( Argc )
  3794. {
  3795. PCHAR arg = Argv[0];
  3796. // flags
  3797. if ( strncmp( arg, "-f", 2 ) == 0 )
  3798. {
  3799. flags = strtoul( arg+2, NULL, 16 );
  3800. Argc--;
  3801. Argv++;
  3802. }
  3803. // sockaddr subfields
  3804. else if ( strncmp( arg, "-m", 2 ) == 0 )
  3805. {
  3806. sockaddr.sin6_family = (SHORT) strtoul( arg+2, NULL, 10 );
  3807. Argc--;
  3808. Argv++;
  3809. }
  3810. else if ( strncmp( arg, "-p", 2 ) == 0 )
  3811. {
  3812. sockaddr.sin6_port = (SHORT) strtoul( arg+2, NULL, 10 );
  3813. Argc--;
  3814. Argv++;
  3815. }
  3816. // tweak out params
  3817. else if ( strncmp( arg, "-sl", 3 ) == 0 )
  3818. {
  3819. serviceLength = strtoul( arg+3, NULL, 10 );
  3820. Argc--;
  3821. Argv++;
  3822. }
  3823. else if ( _strnicmp( arg, "-snull", 5 ) == 0 )
  3824. {
  3825. pservice = NULL;
  3826. Argc--;
  3827. Argv++;
  3828. }
  3829. else if ( strncmp( arg, "-hl", 3 ) == 0 )
  3830. {
  3831. hostLength = strtoul( arg+3, NULL, 10 );
  3832. Argc--;
  3833. Argv++;
  3834. }
  3835. else if ( _strnicmp( arg, "-hnull", 5 ) == 0 )
  3836. {
  3837. phost = NULL;
  3838. Argc--;
  3839. Argv++;
  3840. }
  3841. else
  3842. {
  3843. goto Usage;
  3844. }
  3845. }
  3846. //
  3847. // force winsock start
  3848. //
  3849. Dns_InitializeWinsock();
  3850. //
  3851. // call
  3852. //
  3853. printf(
  3854. "Calling getnameinfo()\n"
  3855. "\tsockaddr %p\n"
  3856. "\tsockaddr len %d\n"
  3857. "\thost buffer %p\n"
  3858. "\thost buflen %d\n"
  3859. "\tservice buffer %p\n"
  3860. "\tservice buflen %d\n"
  3861. "\tflags %08x\n",
  3862. psockaddr,
  3863. sockaddrLength,
  3864. phost,
  3865. hostLength,
  3866. pservice,
  3867. serviceLength,
  3868. flags );
  3869. DnsPrint_Sockaddr(
  3870. dnsup_PrintRoutine,
  3871. dnsup_PrintContext,
  3872. "\n\tsockaddr",
  3873. 1, // indent
  3874. (PSOCKADDR) psockaddr,
  3875. sockaddrLength );
  3876. result = getnameinfo(
  3877. (PSOCKADDR) psockaddr,
  3878. sockaddrLength,
  3879. phost,
  3880. hostLength,
  3881. pservice,
  3882. serviceLength,
  3883. flags );
  3884. status = GetLastError();
  3885. if ( result != NO_ERROR )
  3886. {
  3887. printf(
  3888. "getnameinfo(), %x %s.\n",
  3889. status,
  3890. DnsStatusString(status) );
  3891. }
  3892. else
  3893. {
  3894. printf(
  3895. "getnameinfo successfully completed.\n"
  3896. "\thost = %s\n"
  3897. "\tservice = %s\n",
  3898. phost,
  3899. pservice );
  3900. }
  3901. return( status );
  3902. Usage:
  3903. printf(
  3904. "getnameinfo\n"
  3905. "usage:\n"
  3906. " DnsUp -gni <Address> [-s<Service>] [-f<flags>] [-m<family>]\n"
  3907. " [-p<port>] [-sl<length>] [-snull] [-hl<length>] [-hnull]\n"
  3908. " <Address> - Address string to query name for.\n"
  3909. " \"null\" for null input.\n"
  3910. " \"blank\" for blank (empty string)\n"
  3911. " <flags> - hint flags\n"
  3912. " AI_PASSIVE = %0x\n"
  3913. " AI_CANONNAME = %0x\n"
  3914. " AI_NUMERICHOST = %0x\n"
  3915. " <family> - sockaddr family, overrides default for address;\n"
  3916. " AF_INET = %d\n"
  3917. " AF_INET6 = %d\n"
  3918. " AF_ATM = %d\n"
  3919. " <port> - port to set in sockaddr; defaults to zero\n"
  3920. " <length> - length of out buffer\n"
  3921. " -sl<length> - length of service name buffer\n"
  3922. " -hl<length> - length of host name buffer\n"
  3923. " [-snull] - server buffer ptr NULL\n"
  3924. " [-hnull] - host buffer ptr NULL\n",
  3925. AI_PASSIVE,
  3926. AI_CANONNAME,
  3927. AI_NUMERICHOST,
  3928. AF_INET,
  3929. AF_INET6,
  3930. AF_ATM );
  3931. return( ERROR_INVALID_PARAMETER );
  3932. }
  3933. DNS_STATUS
  3934. ProcessClusterIp(
  3935. IN DWORD Argc,
  3936. IN PSTR * Argv
  3937. )
  3938. {
  3939. SOCKADDR_IN6 sockaddr;
  3940. PSOCKADDR psockaddr = (PSOCKADDR) &sockaddr;
  3941. DWORD sockaddrLength = sizeof(sockaddr);
  3942. IP_ADDRESS ip;
  3943. BOOL fadd = TRUE;
  3944. PWSTR pname = NULL;
  3945. DNS_STATUS status;
  3946. //
  3947. // -ci <Name> <IP> [-d]
  3948. //
  3949. if ( Argc < 1 )
  3950. {
  3951. goto Usage;
  3952. }
  3953. //
  3954. // name
  3955. //
  3956. pname = (PWSTR) Dns_StringCopyAllocate(
  3957. Argv[0],
  3958. 0, // unknown length
  3959. DnsCharSetAnsi,
  3960. DnsCharSetUnicode );
  3961. Argc--;
  3962. Argv++;
  3963. //
  3964. // cluster IP
  3965. //
  3966. #if 0
  3967. ip = inet_addr( Argv[0] );
  3968. if ( ip == (-1) )
  3969. {
  3970. goto Usage;
  3971. }
  3972. Argc--;
  3973. Argv++;
  3974. #endif
  3975. if ( !getSockaddrFromString(
  3976. & psockaddr,
  3977. & sockaddrLength,
  3978. Argv[0] ) )
  3979. {
  3980. goto Usage;
  3981. }
  3982. Argc--;
  3983. Argv++;
  3984. //
  3985. // optional delete flag
  3986. //
  3987. if ( Argc > 0 )
  3988. {
  3989. if ( strncmp( Argv[0], "-d", 2 ) == 0 )
  3990. {
  3991. fadd = FALSE;
  3992. Argc--;
  3993. Argv++;
  3994. }
  3995. if ( Argc != 0 )
  3996. {
  3997. goto Usage;
  3998. }
  3999. }
  4000. //
  4001. // notify resolver
  4002. //
  4003. status = DnsRegisterClusterAddress(
  4004. 0xd734453d,
  4005. pname,
  4006. psockaddr,
  4007. fadd );
  4008. FREE_HEAP( pname );
  4009. return( status );
  4010. Usage:
  4011. printf(
  4012. "Set Cluster IP\n"
  4013. "usage:\n"
  4014. " DnsUp [-ci] <Name> <IP> [-d]\n"
  4015. " <Name> is cluster name\n"
  4016. " <IP> is cluster IP\n"
  4017. " [-d] to indicate delete of cluster IP\n"
  4018. );
  4019. FREE_HEAP( pname );
  4020. return( ERROR_INVALID_PARAMETER );
  4021. }
  4022. #if 0
  4023. DNS_STATUS
  4024. ProcessAddIp(
  4025. IN DWORD Argc,
  4026. IN PSTR * Argv
  4027. )
  4028. {
  4029. IP_ADDRESS ip;
  4030. BOOL fadd = TRUE;
  4031. //
  4032. // -addip <IP>
  4033. //
  4034. if ( Argc < 1 )
  4035. {
  4036. goto Usage;
  4037. }
  4038. //
  4039. // IP to add
  4040. //
  4041. ip = inet_addr( Argv[0] );
  4042. if ( ip == (-1) )
  4043. {
  4044. goto Usage;
  4045. }
  4046. Argc--;
  4047. Argv++;
  4048. //
  4049. // optional delete flag
  4050. //
  4051. if ( Argc > 0 )
  4052. {
  4053. if ( strncmp( Argv[0], "-d", 2 ) == 0 )
  4054. {
  4055. fadd = FALSE;
  4056. Argc--;
  4057. Argv++;
  4058. }
  4059. if ( Argc != 0 )
  4060. {
  4061. goto Usage;
  4062. }
  4063. }
  4064. //
  4065. // notify resolver
  4066. //
  4067. DnsNotifyResolverClusterIp(
  4068. ip,
  4069. fadd );
  4070. return( ERROR_SUCCESS );
  4071. Usage:
  4072. printf(
  4073. "usage:\n"
  4074. " DnsUp [-ci] <IP> [-d]\n"
  4075. " <IP> is cluster IP\n"
  4076. " [-d] to indicate delete of cluster IP\n"
  4077. );
  4078. return( ERROR_INVALID_PARAMETER );
  4079. }
  4080. #endif
  4081. DNS_STATUS
  4082. ProcessSetEnvironmentVariable(
  4083. IN DWORD Argc,
  4084. IN PSTR * Argv
  4085. )
  4086. {
  4087. //
  4088. // setenv <name> <value>
  4089. //
  4090. if ( Argc < 1 || Argc > 2 )
  4091. {
  4092. goto Usage;
  4093. }
  4094. SetEnvironmentVariableA(
  4095. Argv[0],
  4096. (Argc == 2) ? Argv[1] : NULL );
  4097. return( ERROR_SUCCESS );
  4098. Usage:
  4099. printf(
  4100. "Set environment variable\n"
  4101. "usage:\n"
  4102. " DnsUp [-setenv] <name> [<value>]\n"
  4103. " <name> name of environment variable\n"
  4104. " <value> value of environment variable, if missing\n"
  4105. " then environment variable is deleted\n"
  4106. );
  4107. return( ERROR_INVALID_PARAMETER );
  4108. }
  4109. //
  4110. // Command Table
  4111. //
  4112. // Keep this down here to avoid having prototypes for
  4113. // all these functions.
  4114. //
  4115. COMMAND_INFO GlobalCommandInfo[] =
  4116. {
  4117. // query
  4118. { "qex" , "QueryEx" , ProcessQueryEx },
  4119. { "qc" , "QueryCompare" , ProcessQueryCompare },
  4120. { "q" , "Query" , ProcessQuery },
  4121. { "qm" , "QueryMulitple" , ProcessQueryMultiple },
  4122. { "qt" , "QueryTest" , ProcessQueryTest },
  4123. { "iq" , "IQuery" , ProcessIQuery },
  4124. // update
  4125. { "u" , "Update" , ProcessUpdate },
  4126. { "ut" , "UpdateTest" , ProcessUpdateTest },
  4127. //{ "um" , "UpdateMultiple" , ProcessUpdateMultiple },
  4128. { "dt" , "DhcpTest" , ProcessDhcpTest },
  4129. { "mr" , "ModifyRecordsInSet" , ProcessModifyRecordsInSet },
  4130. { "rs" , "ReplaceRecordSet" , ProcessReplaceRecordSet },
  4131. // utility
  4132. { "vn" , "ValidateName" , ProcessValidateName },
  4133. { "s" , "StringTranslate" , ProcessStringTranslate },
  4134. { "cn" , "NameCompare" , ProcessNameCompare },
  4135. { "cnx" , "NameCompareEx" , ProcessNameCompareEx },
  4136. { "config" , "QueryConfig" , ProcessQueryConfig },
  4137. // config
  4138. { "setenv" , "SetEnvironmentVariable", ProcessSetEnvironmentVariable },
  4139. // resolver
  4140. { "ci" , "ClusterIp" , ProcessClusterIp },
  4141. // RnR
  4142. { "ghn" , "gethostname" , ProcessGetHostName },
  4143. { "ghbn" , "gethostbyname" , ProcessGetHostByName },
  4144. { "ghba" , "gethostbyaddr" , ProcessGetHostByAddr },
  4145. { "gai" , "getaddrinfo" , ProcessGetAddrInfo },
  4146. { "gni" , "getnameinfo" , ProcessGetNameInfo },
  4147. { "lsb" , "LookupServiceBegin" , ProcessLookupServiceBegin },
  4148. { "lsn" , "LookupServiceNext" , ProcessLookupServiceNext },
  4149. { "lse" , "LookupServiceEnd" , ProcessLookupServiceEnd },
  4150. // quit
  4151. { "quit" , "Quit" , ProcessQuit },
  4152. { "exit" , "Quit" , ProcessQuit },
  4153. { NULL, NULL, NULL },
  4154. };
  4155. //
  4156. // End dnsup.c
  4157. //