ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

nslookup.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:     ReactOS nslookup utility
00003  * LICENSE:     GPL - See COPYING in the top level directory
00004  * FILE:        applications/network/nslookup/nslookup.c
00005  * PURPOSE:     Perform DNS lookups
00006  * COPYRIGHT:   Copyright 2009 Lucas Suggs <lucas.suggs@gmail.com>
00007  */
00008 
00009 #include "nslookup.h"
00010 
00011 STATE   State;
00012 HANDLE  ProcessHeap;
00013 ULONG   RequestID;
00014 
00015 void PrintState()
00016 {
00017     _tprintf( _T("Default Server:  (null)\n\n") );
00018     _tprintf( _T("Set options:\n") );
00019 
00020     _tprintf( _T("  ") );
00021     if( !State.debug ) _tprintf( _T("no") );
00022     _tprintf( _T("debug\n") );
00023 
00024     _tprintf( _T("  ") );
00025     if( !State.defname ) _tprintf( _T("no") );
00026     _tprintf( _T("defname\n") );
00027 
00028     _tprintf( _T("  ") );
00029     if( !State.search ) _tprintf( _T("no") );
00030     _tprintf( _T("search\n") );
00031 
00032     _tprintf( _T("  ") );
00033     if( !State.recurse ) _tprintf( _T("no") );
00034     _tprintf( _T("recurse\n") );
00035 
00036     _tprintf( _T("  ") );
00037     if( !State.d2 ) _tprintf( _T("no") );
00038     _tprintf( _T("d2\n") );
00039 
00040     _tprintf( _T("  ") );
00041     if( !State.vc ) _tprintf( _T("no") );
00042     _tprintf( _T("vc\n") );
00043 
00044     _tprintf( _T("  ") );
00045     if( !State.ignoretc ) _tprintf( _T("no") );
00046     _tprintf( _T("ignoretc\n") );
00047 
00048     _tprintf( _T("  port=%d\n"), State.port );
00049     _tprintf( _T("  type=%s\n"), State.type );
00050     _tprintf( _T("  class=%s\n"), State.Class );
00051     _tprintf( _T("  timeout=%d\n"), (int)State.timeout );
00052     _tprintf( _T("  retry=%d\n"), (int)State.retry );
00053     _tprintf( _T("  root=%s\n"), State.root );
00054     _tprintf( _T("  domain=%s\n"), State.domain );
00055 
00056     _tprintf( _T("  ") );
00057     if( !State.MSxfr ) _tprintf( _T("no") );
00058     _tprintf( _T("MSxfr\n") );
00059 
00060     _tprintf( _T("  IXFRversion=%d\n"), (int)State.ixfrver );
00061 
00062     _tprintf( _T("  srchlist=%s\n\n"), State.srchlist[0] );
00063 }
00064 
00065 void PrintUsage()
00066 {
00067     _tprintf( _T("Usage:\n"
00068                  "   nslookup [-opt ...]             # interactive mode using"
00069                  " default server\n   nslookup [-opt ...] - server    #"
00070                  " interactive mode using 'server'\n   nslookup [-opt ...]"
00071                  " host        # just look up 'host' using default server\n"
00072                  "   nslookup [-opt ...] host server # just look up 'host'"
00073                  " using 'server'\n") );
00074 }
00075 
00076 BOOL PerformInternalLookup( PCHAR pAddr, PCHAR pResult )
00077 {
00078     /* Needed to issue DNS packets and parse them. */
00079     PCHAR Buffer = NULL, RecBuffer = NULL;
00080     CHAR pResolve[256];
00081     ULONG BufferLength = 0, RecBufferLength = 512;
00082     int i = 0, j = 0, k = 0, d = 0;
00083     BOOL bOk = FALSE;
00084 
00085     /* Makes things easier when parsing the response packet. */
00086     USHORT NumQuestions;
00087     USHORT Type;
00088 
00089     if( (strlen( pAddr ) + 1) > 255 ) return FALSE;
00090 
00091     Type = TYPE_A;
00092     if( IsValidIP( pAddr ) ) Type = TYPE_PTR;
00093 
00094     /* If it's a PTR lookup then append the ARPA sig to the end. */
00095     if( Type == TYPE_PTR )
00096     {
00097         ReverseIP( pAddr, pResolve );
00098         strcat( pResolve, ARPA_SIG );
00099     }
00100     else
00101     {
00102         strcpy( pResolve, pAddr );
00103     }
00104 
00105     /* Base header length + length of QNAME + length of QTYPE and QCLASS */
00106     BufferLength = 12 + (strlen( pResolve ) + 2) + 4;
00107 
00108     /* Allocate memory for the buffer. */
00109     Buffer = HeapAlloc( ProcessHeap, 0, BufferLength );
00110     if( !Buffer )
00111     {
00112         _tprintf( _T("ERROR: Out of memory\n") );
00113         goto cleanup;
00114     }
00115 
00116     /* Allocate the receiving buffer. */
00117     RecBuffer = HeapAlloc( ProcessHeap, 0, RecBufferLength );
00118     if( !RecBuffer )
00119     {
00120         _tprintf( _T("ERROR: Out of memory\n") );
00121         goto cleanup;
00122     }
00123 
00124     /* Insert the ID field. */
00125     ((PSHORT)&Buffer[i])[0] = htons( RequestID );
00126     i += 2;
00127 
00128     /* Bits 0-7 of the second 16 are all 0, except for when recursion is
00129        desired. */
00130     Buffer[i] = 0x00;
00131     if( State.recurse) Buffer[i] |= 0x01;
00132     i += 1;
00133 
00134     /* Bits 8-15 of the second 16 are 0 for a query. */
00135     Buffer[i] = 0x00;
00136     i += 1;
00137 
00138     /* Only 1 question. */
00139     ((PSHORT)&Buffer[i])[0] = htons( 1 );
00140     i += 2;
00141 
00142     /* We aren't sending a response, so 0 out the rest of the header. */
00143     Buffer[i] = 0x00;
00144     Buffer[i + 1] = 0x00;
00145     Buffer[i + 2] = 0x00;
00146     Buffer[i + 3] = 0x00;
00147     Buffer[i + 4] = 0x00;
00148     Buffer[i + 5] = 0x00;
00149     i += 6;
00150 
00151     /* Walk through the query address. Split each section delimited by '.'.
00152        Format of the QNAME section is length|data, etc. Last one is null */
00153     j = i;
00154     i += 1;
00155 
00156     for( k = 0; k < strlen( pResolve ); k += 1 )
00157     {
00158         if( pResolve[k] != '.' )
00159         {
00160             Buffer[i] = pResolve[k];
00161             i += 1;
00162         }
00163         else
00164         {
00165             Buffer[j] = (i - j) - 1;
00166             j = i;
00167             i += 1;
00168         }
00169     }
00170 
00171     Buffer[j] = (i - j) - 1;
00172     Buffer[i] = 0x00;
00173     i += 1;
00174 
00175     /* QTYPE */
00176     ((PSHORT)&Buffer[i])[0] = htons( Type );
00177     i += 2;
00178 
00179     /* QCLASS */
00180     ((PSHORT)&Buffer[i])[0] = htons( CLASS_IN );
00181 
00182     /* Ship the request off to the DNS server. */
00183     bOk = SendRequest( Buffer,
00184                        BufferLength,
00185                        RecBuffer,
00186                        &RecBufferLength );
00187     if( !bOk ) goto cleanup;
00188 
00189     /* Start parsing the received packet. */
00190     NumQuestions = ntohs( ((PSHORT)&RecBuffer[4])[0] );
00191 
00192     k = 12;
00193 
00194     /* We don't care about the questions section, blow through it. */
00195     if( NumQuestions )
00196     {
00197         for( i = 0; i < NumQuestions; i += 1 )
00198         {
00199             /* Quick way to skip the domain name section. */
00200             k += ExtractName( RecBuffer, pResult, k, 0 );
00201             k += 4;
00202         }
00203     }
00204 
00205     /* Skip the answer name. */
00206     k += ExtractName( RecBuffer, pResult, k, 0 );
00207 
00208     Type = ntohs( ((PUSHORT)&RecBuffer[k])[0] );
00209     k += 8;
00210 
00211     d = ntohs( ((PUSHORT)&RecBuffer[k])[0] );
00212     k += 2;
00213 
00214     if( TYPE_PTR == Type )
00215     {
00216         k += ExtractName( RecBuffer, pResult, k, d );
00217     }
00218     else if( TYPE_A == Type )
00219     {
00220         k += ExtractIP( RecBuffer, pResult, k );
00221     }
00222 
00223 cleanup:
00224     /* Free memory. */
00225     if( Buffer ) HeapFree( ProcessHeap, 0, Buffer );
00226     if( RecBuffer ) HeapFree( ProcessHeap, 0, RecBuffer );
00227 
00228     RequestID += 1;
00229 
00230     return bOk;
00231 }
00232 
00233 void PerformLookup( PCHAR pAddr )
00234 {
00235     /* Needed to issue DNS packets and parse them. */
00236     PCHAR Buffer = NULL, RecBuffer = NULL;
00237     CHAR pResolve[256];
00238     CHAR pResult[256];
00239     ULONG BufferLength = 0, RecBufferLength = 512;
00240     int i = 0, j = 0, k = 0, d = 0;
00241     BOOL bOk = FALSE;
00242 
00243     /* Makes things easier when parsing the response packet. */
00244     UCHAR Header2;
00245     USHORT NumQuestions;
00246     USHORT NumAnswers;
00247     USHORT NumAuthority;
00248     USHORT Type;
00249 
00250     if( (strlen( pAddr ) + 1) > 255 ) return;
00251 
00252     _tprintf( _T("Server:  %s\n"), State.DefaultServer );
00253     _tprintf( _T("Address:  %s\n\n"), State.DefaultServerAddress );
00254 
00255     if( !strcmp( TypeA, State.type )
00256         || !strcmp( TypeAAAA, State.type )
00257         || !strcmp( TypeBoth, State.type ) )
00258     {
00259         Type = TYPE_A;
00260         if( IsValidIP( pAddr ) ) Type = TYPE_PTR;
00261     }
00262     else
00263         Type = TypeNametoTypeID( State.type );
00264 
00265     /* If it's a PTR lookup then append the ARPA sig to the end. */
00266     if( (Type == TYPE_PTR) && IsValidIP( pAddr ) )
00267     {
00268         ReverseIP( pAddr, pResolve );
00269         strcat( pResolve, ARPA_SIG );
00270     }
00271     else
00272     {
00273         strcpy( pResolve, pAddr );
00274     }
00275 
00276     /* Base header length + length of QNAME + length of QTYPE and QCLASS */
00277     BufferLength = 12 + (strlen( pResolve ) + 2) + 4;
00278 
00279     /* Allocate memory for the buffer. */
00280     Buffer = HeapAlloc( ProcessHeap, 0, BufferLength );
00281     if( !Buffer )
00282     {
00283         _tprintf( _T("ERROR: Out of memory\n") );
00284         goto cleanup;
00285     }
00286 
00287     /* Allocate memory for the return buffer. */
00288     RecBuffer = HeapAlloc( ProcessHeap, 0, RecBufferLength );
00289     if( !RecBuffer )
00290     {
00291         _tprintf( _T("ERROR: Out of memory\n") );
00292         goto cleanup;
00293     }
00294 
00295     /* Insert the ID field. */
00296     ((PSHORT)&Buffer[i])[0] = htons( RequestID );
00297     i += 2;
00298 
00299     /* Bits 0-7 of the second 16 are all 0, except for when recursion is
00300     desired. */
00301     Buffer[i] = 0x00;
00302     if( State.recurse) Buffer[i] |= 0x01;
00303     i += 1;
00304 
00305     /* Bits 8-15 of the second 16 are 0 for a query. */
00306     Buffer[i] = 0x00;
00307     i += 1;
00308 
00309     /* Only 1 question. */
00310     ((PSHORT)&Buffer[i])[0] = htons( 1 );
00311     i += 2;
00312 
00313     /* We aren't sending a response, so 0 out the rest of the header. */
00314     Buffer[i] = 0x00;
00315     Buffer[i + 1] = 0x00;
00316     Buffer[i + 2] = 0x00;
00317     Buffer[i + 3] = 0x00;
00318     Buffer[i + 4] = 0x00;
00319     Buffer[i + 5] = 0x00;
00320     i += 6;
00321 
00322     /* Walk through the query address. Split each section delimited by '.'.
00323        Format of the QNAME section is length|data, etc. Last one is null */
00324     j = i;
00325     i += 1;
00326 
00327     for( k = 0; k < strlen( pResolve ); k += 1 )
00328     {
00329         if( pResolve[k] != '.' )
00330         {
00331             Buffer[i] = pResolve[k];
00332             i += 1;
00333         }
00334         else
00335         {
00336             Buffer[j] = (i - j) - 1;
00337             j = i;
00338             i += 1;
00339         }
00340     }
00341 
00342     Buffer[j] = (i - j) - 1;
00343     Buffer[i] = 0x00;
00344     i += 1;
00345 
00346     /* QTYPE */
00347     ((PSHORT)&Buffer[i])[0] = htons( Type );
00348     i += 2;
00349 
00350     /* QCLASS */
00351     ((PSHORT)&Buffer[i])[0] = htons( ClassNametoClassID( State.Class ) );
00352 
00353     /* Ship off the request to the DNS server. */
00354     bOk = SendRequest( Buffer,
00355                        BufferLength,
00356                        RecBuffer,
00357                        &RecBufferLength );
00358     if( !bOk ) goto cleanup;
00359 
00360     /* Start parsing the received packet. */
00361     Header2 = RecBuffer[3];
00362     NumQuestions = ntohs( ((PSHORT)&RecBuffer[4])[0] );
00363     NumAnswers = ntohs( ((PSHORT)&RecBuffer[6])[0] );
00364     NumAuthority = ntohs( ((PUSHORT)&RecBuffer[8])[0] );
00365     Type = 0;
00366 
00367     /* Check the RCODE for failure. */
00368     d = Header2 & 0x0F;
00369     if( d != RCODE_NOERROR )
00370     {
00371         switch( d )
00372         {
00373         case RCODE_NXDOMAIN:
00374             _tprintf( _T("*** %s can't find %s: Non-existant domain\n"), State.DefaultServer, pAddr );
00375             break;
00376             
00377         case RCODE_REFUSED:
00378             _tprintf( _T("*** %s can't find %s: Query refused\n"), State.DefaultServer, pAddr );
00379             break;
00380 
00381         default:
00382             _tprintf( _T("*** %s can't find %s: Unknown RCODE\n"), State.DefaultServer, pAddr );
00383         }
00384             
00385         goto cleanup;
00386     }
00387 
00388     k = 12;
00389 
00390     if( NumQuestions )
00391     {
00392         /* Blow through the questions section since we don't care about it. */
00393         for( i = 0; i < NumQuestions; i += 1 )
00394         {
00395             k += ExtractName( RecBuffer, pResult, k, 0 );
00396             k += 4;
00397         }
00398     }
00399 
00400     if( NumAnswers )
00401     {
00402         /* Skip the name. */
00403         k += ExtractName( RecBuffer, pResult, k, 0 );
00404 
00405         Type = ntohs( ((PUSHORT)&RecBuffer[k])[0] );
00406         k += 8;
00407 
00408         d = ntohs( ((PUSHORT)&RecBuffer[k])[0] );
00409         k += 2;
00410 
00411         if( TYPE_PTR == Type )
00412         {
00413             k += ExtractName( RecBuffer, pResult, k, d );
00414         }
00415         else if( TYPE_A == Type )
00416         {
00417             k += ExtractIP( RecBuffer, pResult, k );
00418         }
00419     }
00420 
00421     /* FIXME: This'll need to support more than PTR and A at some point. */
00422     if( !strcmp( State.type, TypePTR ) )
00423     {
00424         if( TYPE_PTR == Type )
00425         {
00426             _tprintf( _T("%s     name = %s\n"), pResolve, pResult );
00427         }
00428         else
00429         {
00430         }
00431     }
00432     else if( !strcmp( State.type, TypeA )
00433           || !strcmp( State.type, TypeAAAA )
00434           || !strcmp( State.type, TypeBoth ) )
00435     {
00436         if( (TYPE_A == Type) /*|| (TYPE_AAAA == Type)*/ )
00437         {
00438             if( 0 == NumAuthority )
00439                 _tprintf( _T("Non-authoritative answer:\n") );
00440 
00441             _tprintf( _T("Name:    %s\n"), pAddr );
00442             _tprintf( _T("Address:  %s\n\n"), pResult );
00443         }
00444         else
00445         {
00446             _tprintf( _T("Name:    %s\n"), pResult );
00447             _tprintf( _T("Address:  %s\n\n"), pAddr );
00448         }
00449     }
00450 
00451 cleanup:
00452     /* Free memory. */
00453     if( Buffer ) HeapFree( ProcessHeap, 0, Buffer );
00454     if( RecBuffer ) HeapFree( ProcessHeap, 0, RecBuffer );
00455 
00456     RequestID += 1;
00457 }
00458 
00459 BOOL ParseCommandLine( int argc, char* argv[] )
00460 {
00461     int i;
00462     BOOL NoMoreOptions = FALSE;
00463     BOOL Interactive = FALSE;
00464     CHAR AddrToResolve[256];
00465     CHAR Server[256];
00466 
00467     RtlZeroMemory( AddrToResolve, 256 );
00468     RtlZeroMemory( Server, 256 );
00469 
00470     if( 2 == argc )
00471     {
00472         /* In the Windows nslookup, usage is only displayed if /? is the only
00473            option specified on the command line. */
00474         if( !strncmp( "/?", argv[1], 2 ) )
00475         {
00476             PrintUsage();
00477             return 0;
00478         }
00479     }
00480 
00481     if( argc > 1 )
00482     {
00483         for( i = 1; i < argc; i += 1 )
00484         {
00485             if( NoMoreOptions )
00486             {
00487                 strncpy( Server, argv[i], 255 );
00488 
00489                 /* Determine which one to resolve. This is based on whether the
00490                    DNS server provided was an IP or an FQDN. */
00491                 if( IsValidIP( Server ) )
00492                 {
00493                     strncpy( State.DefaultServerAddress, Server, 16 );
00494 
00495                     PerformInternalLookup( State.DefaultServerAddress,
00496                                            State.DefaultServer );
00497                 }
00498                 else
00499                 {
00500                     strncpy( State.DefaultServer, Server, 255 );
00501 
00502                     PerformInternalLookup( State.DefaultServer,
00503                                            State.DefaultServerAddress );
00504                 }
00505 
00506                 if( Interactive ) return 1;
00507 
00508                 PerformLookup( AddrToResolve );
00509 
00510                 return 0;
00511             }
00512             else
00513             {
00514                 if( !strncmp( "-all", argv[i], 4 ) )
00515                 {
00516                     PrintState();
00517                 }
00518                 else if( !strncmp( "-type=", argv[i], 6 ) )
00519                 {
00520                     if( !strncmp( TypeA, &argv[i][6], strlen( TypeA ) ) )
00521                     {
00522                         State.type = TypeA;
00523                     }
00524                     else if( !strncmp( TypeAAAA, &argv[i][6], strlen( TypeAAAA ) ) )
00525                     {
00526                         State.type = TypeAAAA;
00527                     }
00528                     else if( !strncmp( TypeBoth, &argv[i][6], strlen( TypeBoth ) ) )
00529                     {
00530                         State.type = TypeBoth;
00531                     }
00532                     else if( !strncmp( TypeAny, &argv[i][6], strlen( TypeAny ) ) )
00533                     {
00534                         State.type = TypeAny;
00535                     }
00536                     else if( !strncmp( TypeCNAME, &argv[i][6], strlen( TypeCNAME ) ) )
00537                     {
00538                         State.type = TypeCNAME;
00539                     }
00540                     else if( !strncmp( TypeMX, &argv[i][6], strlen( TypeMX ) ) )
00541                     {
00542                         State.type = TypeMX;
00543                     }
00544                     else if( !strncmp( TypeNS, &argv[i][6], strlen( TypeNS ) ) )
00545                     {
00546                         State.type = TypeNS;
00547                     }
00548                     else if( !strncmp( TypePTR, &argv[i][6], strlen( TypePTR ) ) )
00549                     {
00550                         State.type = TypePTR;
00551                     }
00552                     else if( !strncmp( TypeSOA, &argv[i][6], strlen( TypeSOA ) ) )
00553                     {
00554                         State.type = TypeSOA;
00555                     }
00556                     else if( !strncmp( TypeSRV, &argv[i][6], strlen( TypeSRV ) ) )
00557                     {
00558                         State.type = TypeSRV;
00559                     }
00560                     else
00561                     {
00562                         _tprintf( _T("unknown query type: %s"), &argv[i][6] );
00563                     }
00564                 }
00565                 else if( !strncmp( "-domain=", argv[i], 8 ) )
00566                 {
00567                     strcpy( State.domain, &argv[i][8] );
00568                 }
00569                 else if( !strncmp( "-srchlist=", argv[i], 10 ) )
00570                 {
00571                 }
00572                 else if( !strncmp( "-root=", argv[i], 6 ) )
00573                 {
00574                     strcpy( State.root, &argv[i][6] );
00575                 }
00576                 else if( !strncmp( "-retry=", argv[i], 7 ) )
00577                 {
00578                 }
00579                 else if( !strncmp( "-timeout=", argv[i], 9 ) )
00580                 {
00581                 }
00582                 else if( !strncmp( "-querytype=", argv[i], 11 ) )
00583                 {
00584                     if( !strncmp( TypeA, &argv[i][11], strlen( TypeA ) ) )
00585                     {
00586                         State.type = TypeA;
00587                     }
00588                     else if( !strncmp( TypeAAAA, &argv[i][11], strlen( TypeAAAA ) ) )
00589                     {
00590                         State.type = TypeAAAA;
00591                     }
00592                     else if( !strncmp( TypeBoth, &argv[i][11], strlen( TypeBoth ) ) )
00593                     {
00594                         State.type = TypeBoth;
00595                     }
00596                     else if( !strncmp( TypeAny, &argv[i][11], strlen( TypeAny ) ) )
00597                     {
00598                         State.type = TypeAny;
00599                     }
00600                     else if( !strncmp( TypeCNAME, &argv[i][11], strlen( TypeCNAME ) ) )
00601                     {
00602                         State.type = TypeCNAME;
00603                     }
00604                     else if( !strncmp( TypeMX, &argv[i][11], strlen( TypeMX ) ) )
00605                     {
00606                         State.type = TypeMX;
00607                     }
00608                     else if( !strncmp( TypeNS, &argv[i][11], strlen( TypeNS ) ) )
00609                     {
00610                         State.type = TypeNS;
00611                     }
00612                     else if( !strncmp( TypePTR, &argv[i][11], strlen( TypePTR ) ) )
00613                     {
00614                         State.type = TypePTR;
00615                     }
00616                     else if( !strncmp( TypeSOA, &argv[i][11], strlen( TypeSOA ) ) )
00617                     {
00618                         State.type = TypeSOA;
00619                     }
00620                     else if( !strncmp( TypeSRV, &argv[i][11], strlen( TypeSRV ) ) )
00621                     {
00622                         State.type = TypeSRV;
00623                     }
00624                     else
00625                     {
00626                         _tprintf( _T("unknown query type: %s"), &argv[i][6] );
00627                     }
00628                 }
00629                 else if( !strncmp( "-class=", argv[i], 7 ) )
00630                 {
00631                     if( !strncmp( ClassIN, &argv[i][7], strlen( ClassIN ) ) )
00632                     {
00633                         State.Class = ClassIN;
00634                     }
00635                     else if( !strncmp( ClassAny, &argv[i][7], strlen( ClassAny ) ) )
00636                     {
00637                         State.Class = ClassAny;
00638                     }
00639                     else
00640                     {
00641                         _tprintf( _T("unknown query class: %s"), &argv[i][7] );
00642                     }
00643                 }
00644                 else if( !strncmp( "-ixfrver=", argv[i], 9 ) )
00645                 {
00646                 }
00647                 else if( !strncmp( "-debug", argv[i], 6 ) )
00648                 {
00649                     State.debug = TRUE;
00650                 }
00651                 else if( !strncmp( "-nodebug", argv[i], 8 ) )
00652                 {
00653                     State.debug = FALSE;
00654                     State.d2 = FALSE;
00655                 }
00656                 else if( !strncmp( "-d2", argv[i], 3 ) )
00657                 {
00658                     State.d2 = TRUE;
00659                     State.debug = TRUE;
00660                 }
00661                 else if( !strncmp( "-nod2", argv[i], 5 ) )
00662                 {
00663                     if( State.debug ) _tprintf( _T("d2 mode disabled; still in debug mode\n") );
00664 
00665                     State.d2 = FALSE;
00666                 }
00667                 else if( !strncmp( "-defname", argv[i], 8 ) )
00668                 {
00669                     State.defname = TRUE;
00670                 }
00671                 else if( !strncmp( "-noddefname", argv[i], 10 ) )
00672                 {
00673                     State.defname = FALSE;
00674                 }
00675                 else if( !strncmp( "-recurse", argv[i], 8 ) )
00676                 {
00677                     State.recurse = TRUE;
00678                 }
00679                 else if( !strncmp( "-norecurse", argv[i], 10 ) )
00680                 {
00681                     State.recurse = FALSE;
00682                 }
00683                 else if( !strncmp( "-search", argv[i], 7 ) )
00684                 {
00685                     State.search = TRUE;
00686                 }
00687                 else if( !strncmp( "-nosearch", argv[i], 9 ) )
00688                 {
00689                     State.search = FALSE;
00690                 }
00691                 else if( !strncmp( "-vc", argv[i], 3 ) )
00692                 {
00693                     State.vc = TRUE;
00694                 }
00695                 else if( !strncmp( "-novc", argv[i], 5 ) )
00696                 {
00697                     State.vc = FALSE;
00698                 }
00699                 else if( !strncmp( "-msxfr", argv[i], 6 ) )
00700                 {
00701                     State.MSxfr = TRUE;
00702                 }
00703                 else if( !strncmp( "-nomsxfr", argv[i], 8 ) )
00704                 {
00705                     State.MSxfr = FALSE;
00706                 }
00707                 else if( !strncmp( "-", argv[i], 1 ) && (strlen( argv[i] ) == 1) )
00708                 {
00709                     /* Since we received just the plain - switch, we are going
00710                        to be entering interactive mode. We also will not be
00711                        parsing any more options. */
00712                     NoMoreOptions = TRUE;
00713                     Interactive = TRUE;
00714                 }
00715                 else
00716                 {
00717                     /* Grab the address to resolve. No more options accepted
00718                        past this point. */
00719                     strncpy( AddrToResolve, argv[i], 255 );
00720                     NoMoreOptions = TRUE;
00721                 }
00722             }
00723         }
00724 
00725         if( NoMoreOptions && !Interactive )
00726         {
00727             /* Get the FQDN of the DNS server. */
00728             PerformInternalLookup( State.DefaultServerAddress,
00729                                    State.DefaultServer );
00730 
00731             PerformLookup( AddrToResolve );
00732 
00733             return 0;
00734         }
00735     }
00736 
00737     /* Get the FQDN of the DNS server. */
00738     PerformInternalLookup( State.DefaultServerAddress,
00739                            State.DefaultServer );
00740 
00741     return 1;
00742 }
00743 
00744 void InteractiveMode()
00745 {
00746     _tprintf( _T("Default Server:  %s\n"), State.DefaultServer );
00747     _tprintf( _T("Address:  %s\n\n"), State.DefaultServerAddress );
00748 
00749     /* TODO: Implement interactive mode. */
00750 
00751     _tprintf( _T("ERROR: Feature not implemented.\n") );
00752 }
00753 
00754 int main( int argc, char* argv[] )
00755 {
00756     int i;
00757     ULONG Status;
00758     PFIXED_INFO pNetInfo = NULL;
00759     ULONG NetBufLen = 0;
00760     WSADATA wsaData;
00761 
00762     ProcessHeap = GetProcessHeap();
00763     RequestID = 1;
00764 
00765     /* Set up the initial state. */
00766     State.debug = FALSE;
00767     State.defname = TRUE;
00768     State.search = TRUE;
00769     State.recurse = TRUE;
00770     State.d2 = FALSE;
00771     State.vc = FALSE;
00772     State.ignoretc = FALSE;
00773     State.port = 53;
00774     State.type = TypeBoth;
00775     State.Class = ClassIN;
00776     State.timeout = 2;
00777     State.retry = 1;
00778     State.MSxfr = TRUE;
00779     State.ixfrver = 1;
00780 
00781     RtlZeroMemory( State.root, 256 );
00782     RtlZeroMemory( State.domain, 256 );
00783     for( i = 0; i < 6; i += 1 ) RtlZeroMemory( State.srchlist[i], 256 );
00784     RtlZeroMemory( State.DefaultServer, 256 );
00785     RtlZeroMemory( State.DefaultServerAddress, 16 );
00786 
00787     memcpy( State.root, DEFAULT_ROOT, sizeof(DEFAULT_ROOT) );
00788 
00789     /* We don't know how long of a buffer it will want to return. So we'll
00790        pass an empty one now and let it fail only once, instead of guessing. */
00791     Status = GetNetworkParams( pNetInfo, &NetBufLen );
00792     if( Status == ERROR_BUFFER_OVERFLOW )
00793     {
00794         pNetInfo = (PFIXED_INFO)HeapAlloc( ProcessHeap, 0, NetBufLen );
00795         if( pNetInfo == NULL )
00796         {
00797             _tprintf( _T("ERROR: Out of memory\n") );
00798 
00799             return -1;
00800         }
00801 
00802         /* For real this time. */
00803         Status = GetNetworkParams( pNetInfo, &NetBufLen );
00804         if( Status != NO_ERROR )
00805         {
00806             _tprintf( _T("Error in GetNetworkParams call\n") );
00807 
00808             HeapFree( ProcessHeap, 0, pNetInfo );
00809 
00810             return -2;
00811         }
00812     }
00813 
00814     strncpy( State.domain, pNetInfo->DomainName, 255 );
00815     strncpy( State.srchlist[0], pNetInfo->DomainName, 255 );
00816     strncpy( State.DefaultServerAddress,
00817              pNetInfo->DnsServerList.IpAddress.String,
00818              15 );
00819 
00820     HeapFree( ProcessHeap, 0, pNetInfo );
00821 
00822     WSAStartup( MAKEWORD(2,2), &wsaData );
00823 
00824     switch( ParseCommandLine( argc, argv ) )
00825     {
00826     case 0:
00827         /* This means that it was a /? parameter. */
00828         break;
00829 
00830     default:
00831         /* Anything else means we enter interactive mode. The only exception
00832            to this is when the host to resolve was provided on the command
00833            line. */
00834         InteractiveMode();
00835     }
00836 
00837     WSACleanup();
00838     return 0;
00839 }

Generated on Sat May 26 2012 04:16:10 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.