[ros-dev] [ros-diffs] [lsuggs] 43700: First push of nslookup implementation.
Alex Ionescu
ionucu at videotron.ca
Sat Oct 24 08:52:26 CEST 2009
Please revert this, it is implemented ass-half-backwards and does not
use the correct DNSAPI services provided by Windows.
Best regards,
Alex Ionescu
On Fri, Oct 23, 2009 at 7:25 PM, <lsuggs at svn.reactos.org> wrote:
> Author: lsuggs
> Date: Fri Oct 23 19:25:05 2009
> New Revision: 43700
>
> URL: http://svn.reactos.org/svn/reactos?rev=43700&view=rev
> Log:
> First push of nslookup implementation.
>
> Added:
> trunk/reactos/base/applications/network/nslookup/ (with props)
> trunk/reactos/base/applications/network/nslookup/nslookup.c (with props)
> trunk/reactos/base/applications/network/nslookup/nslookup.h (with props)
> trunk/reactos/base/applications/network/nslookup/nslookup.rbuild (with props)
> trunk/reactos/base/applications/network/nslookup/nslookup.rc (with props)
> trunk/reactos/base/applications/network/nslookup/utility.c (with props)
> Modified:
> trunk/reactos/base/applications/network/network.rbuild
> trunk/reactos/boot/bootdata/packages/reactos.dff
>
> Modified: trunk/reactos/base/applications/network/network.rbuild
> URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/network/network.rbuild?rev=43700&r1=43699&r2=43700&view=diff
> ==============================================================================
> --- trunk/reactos/base/applications/network/network.rbuild [iso-8859-1] (original)
> +++ trunk/reactos/base/applications/network/network.rbuild [iso-8859-1] Fri Oct 23 19:25:05 2009
> @@ -22,6 +22,9 @@
> <directory name="netstat">
> <xi:include href="netstat/netstat.rbuild" />
> </directory>
> + <directory name="nslookup">
> + <xi:include href="nslookup/nslookup.rbuild" />
> + </directory>
> <directory name="ping">
> <xi:include href="ping/ping.rbuild" />
> </directory>
>
> Propchange: trunk/reactos/base/applications/network/nslookup/
> ------------------------------------------------------------------------------
> --- bugtraq:logregex (added)
> +++ bugtraq:logregex Fri Oct 23 19:25:05 2009
> @@ -1,0 +1,2 @@
> +([Ii]ssue|[Bb]ug)s? #?(\d+)(,? ?#?(\d+))*(,? ?(and |or )?#?(\d+))?
> +(\d+)
>
> Propchange: trunk/reactos/base/applications/network/nslookup/
> ------------------------------------------------------------------------------
> bugtraq:message = See issue #%BUGID% for more details.
>
> Propchange: trunk/reactos/base/applications/network/nslookup/
> ------------------------------------------------------------------------------
> bugtraq:url = http://www.reactos.org/bugzilla/show_bug.cgi?id=%BUGID%
>
> Propchange: trunk/reactos/base/applications/network/nslookup/
> ------------------------------------------------------------------------------
> tsvn:logminsize = 10
>
> Added: trunk/reactos/base/applications/network/nslookup/nslookup.c
> URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/network/nslookup/nslookup.c?rev=43700&view=auto
> ==============================================================================
> --- trunk/reactos/base/applications/network/nslookup/nslookup.c (added)
> +++ trunk/reactos/base/applications/network/nslookup/nslookup.c [iso-8859-1] Fri Oct 23 19:25:05 2009
> @@ -1,0 +1,858 @@
> +/*
> + * PROJECT: ReactOS nslookup utility
> + * LICENSE: GPL - See COPYING in the top level directory
> + * FILE: applications/network/nslookup/nslookup.c
> + * PURPOSE: Perform DNS lookups
> + * COPYRIGHT: Copyright 2009 Lucas Suggs <lucas.suggs at gmail.com>
> + */
> +
> +#include <windows.h>
> +#include <windns.h>
> +#include <winsock2.h>
> +#include <tchar.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <iphlpapi.h>
> +#include "nslookup.h"
> +
> +STATE State;
> +HANDLE ProcessHeap;
> +ULONG RequestID;
> +
> +void PrintState()
> +{
> + _tprintf( _T("Default Server: (null)\n\n") );
> + _tprintf( _T("Set options:\n") );
> +
> + _tprintf( _T(" ") );
> + if( !State.debug ) _tprintf( _T("no") );
> + _tprintf( _T("debug\n") );
> +
> + _tprintf( _T(" ") );
> + if( !State.defname ) _tprintf( _T("no") );
> + _tprintf( _T("defname\n") );
> +
> + _tprintf( _T(" ") );
> + if( !State.search ) _tprintf( _T("no") );
> + _tprintf( _T("search\n") );
> +
> + _tprintf( _T(" ") );
> + if( !State.recurse ) _tprintf( _T("no") );
> + _tprintf( _T("recurse\n") );
> +
> + _tprintf( _T(" ") );
> + if( !State.d2 ) _tprintf( _T("no") );
> + _tprintf( _T("d2\n") );
> +
> + _tprintf( _T(" ") );
> + if( !State.vc ) _tprintf( _T("no") );
> + _tprintf( _T("vc\n") );
> +
> + _tprintf( _T(" ") );
> + if( !State.ignoretc ) _tprintf( _T("no") );
> + _tprintf( _T("ignoretc\n") );
> +
> + _tprintf( _T(" port=%d\n"), State.port );
> + _tprintf( _T(" type=%s\n"), State.type );
> + _tprintf( _T(" class=%s\n"), State.Class );
> + _tprintf( _T(" timeout=%d\n"), (int)State.timeout );
> + _tprintf( _T(" retry=%d\n"), (int)State.retry );
> + _tprintf( _T(" root=%s\n"), State.root );
> + _tprintf( _T(" domain=%s\n"), State.domain );
> +
> + _tprintf( _T(" ") );
> + if( !State.MSxfr ) _tprintf( _T("no") );
> + _tprintf( _T("MSxfr\n") );
> +
> + _tprintf( _T(" IXFRversion=%d\n"), (int)State.ixfrver );
> +
> + _tprintf( _T(" srchlist=%s\n\n"), State.srchlist[0] );
> +}
> +
> +void PrintUsage()
> +{
> + _tprintf( _T("Usage:\n"
> + " nslookup [-opt ...] # interactive mode using"
> + " default server\n nslookup [-opt ...] - server #"
> + " interactive mode using 'server'\n nslookup [-opt ...]"
> + " host # just look up 'host' using default server\n"
> + " nslookup [-opt ...] host server # just look up 'host'"
> + " using 'server'\n") );
> +}
> +
> +BOOL PerformInternalLookup( PCHAR pAddr, PCHAR pResult )
> +{
> + /* Needed to issue DNS packets and parse them. */
> + PCHAR Buffer = NULL, RecBuffer = NULL;
> + CHAR pResolve[256];
> + ULONG BufferLength = 0, RecBufferLength = 512;
> + int i = 0, j = 0, k = 0, d = 0;
> + BOOL bOk = FALSE;
> +
> + /* Makes things easier when parsing the response packet. */
> + UCHAR Header1, Header2;
> + USHORT NumQuestions;
> + USHORT NumAnswers;
> + USHORT NumAuthority;
> + USHORT NumAdditional;
> + USHORT Type;
> +
> + if( (strlen( pAddr ) + 1) > 255 ) return FALSE;
> +
> + Type = TYPE_A;
> + if( IsValidIP( pAddr ) ) Type = TYPE_PTR;
> +
> + /* If it's a PTR lookup then append the ARPA sig to the end. */
> + if( Type == TYPE_PTR )
> + {
> + ReverseIP( pAddr, pResolve );
> + strcat( pResolve, ARPA_SIG );
> + }
> + else
> + {
> + strcpy( pResolve, pAddr );
> + }
> +
> + /* Base header length + length of QNAME + length of QTYPE and QCLASS */
> + BufferLength = 12 + (strlen( pResolve ) + 2) + 4;
> +
> + /* Allocate memory for the buffer. */
> + Buffer = HeapAlloc( ProcessHeap, 0, BufferLength );
> + if( !Buffer )
> + {
> + _tprintf( _T("ERROR: Out of memory\n") );
> + goto cleanup;
> + }
> +
> + /* Allocate the receiving buffer. */
> + RecBuffer = HeapAlloc( ProcessHeap, 0, RecBufferLength );
> + if( !RecBuffer )
> + {
> + _tprintf( _T("ERROR: Out of memory\n") );
> + goto cleanup;
> + }
> +
> + /* Insert the ID field. */
> + ((PSHORT)&Buffer[i])[0] = htons( RequestID );
> + i += 2;
> +
> + /* Bits 0-7 of the second 16 are all 0, except for when recursion is
> + desired. */
> + Buffer[i] = 0x00;
> + if( State.recurse) Buffer[i] |= 0x01;
> + i += 1;
> +
> + /* Bits 8-15 of the second 16 are 0 for a query. */
> + Buffer[i] = 0x00;
> + i += 1;
> +
> + /* Only 1 question. */
> + ((PSHORT)&Buffer[i])[0] = htons( 1 );
> + i += 2;
> +
> + /* We aren't sending a response, so 0 out the rest of the header. */
> + Buffer[i] = 0x00;
> + Buffer[i + 1] = 0x00;
> + Buffer[i + 2] = 0x00;
> + Buffer[i + 3] = 0x00;
> + Buffer[i + 4] = 0x00;
> + Buffer[i + 5] = 0x00;
> + i += 6;
> +
> + /* Walk through the query address. Split each section delimited by '.'.
> + Format of the QNAME section is length|data, etc. Last one is null */
> + j = i;
> + i += 1;
> +
> + for( k = 0; k < strlen( pResolve ); k += 1 )
> + {
> + if( pResolve[k] != '.' )
> + {
> + Buffer[i] = pResolve[k];
> + i += 1;
> + }
> + else
> + {
> + Buffer[j] = (i - j) - 1;
> + j = i;
> + i += 1;
> + }
> + }
> +
> + Buffer[j] = (i - j) - 1;
> + Buffer[i] = 0x00;
> + i += 1;
> +
> + /* QTYPE */
> + ((PSHORT)&Buffer[i])[0] = htons( Type );
> + i += 2;
> +
> + /* QCLASS */
> + ((PSHORT)&Buffer[i])[0] = htons( CLASS_IN );
> +
> + /* Ship the request off to the DNS server. */
> + bOk = SendRequest( Buffer,
> + BufferLength,
> + RecBuffer,
> + &RecBufferLength );
> + if( !bOk ) goto cleanup;
> +
> + /* Start parsing the received packet. */
> + Header1 = RecBuffer[2];
> + Header2 = RecBuffer[3];
> + NumQuestions = ntohs( ((PSHORT)&RecBuffer[4])[0] );
> + NumAnswers = ntohs( ((PSHORT)&RecBuffer[6])[0] );
> + NumAuthority = ntohs( ((PUSHORT)&RecBuffer[8])[0] );
> + NumAdditional = ntohs( ((PUSHORT)&RecBuffer[10])[0] );
> +
> + k = 12;
> +
> + /* We don't care about the questions section, blow through it. */
> + if( NumQuestions )
> + {
> + for( i = 0; i < NumQuestions; i += 1 )
> + {
> + /* Quick way to skip the domain name section. */
> + k += ExtractName( RecBuffer, pResult, k, 0 );
> + k += 4;
> + }
> + }
> +
> + /* Skip the answer name. */
> + k += ExtractName( RecBuffer, pResult, k, 0 );
> +
> + Type = ntohs( ((PUSHORT)&RecBuffer[k])[0] );
> + k += 8;
> +
> + d = ntohs( ((PUSHORT)&RecBuffer[k])[0] );
> + k += 2;
> +
> + if( TYPE_PTR == Type )
> + {
> + k += ExtractName( RecBuffer, pResult, k, d );
> + }
> + else if( TYPE_A == Type )
> + {
> + k += ExtractIP( RecBuffer, pResult, k );
> + }
> +
> +cleanup:
> + /* Free memory. */
> + if( Buffer ) HeapFree( ProcessHeap, 0, Buffer );
> + if( RecBuffer ) HeapFree( ProcessHeap, 0, RecBuffer );
> +
> + RequestID += 1;
> +
> + return bOk;
> +}
> +
> +void PerformLookup( PCHAR pAddr )
> +{
> + /* Needed to issue DNS packets and parse them. */
> + PCHAR Buffer = NULL, RecBuffer = NULL;
> + CHAR pResolve[256];
> + CHAR pResult[256];
> + ULONG BufferLength = 0, RecBufferLength = 512;
> + int i = 0, j = 0, k = 0, d = 0;
> + BOOL bOk = FALSE;
> +
> + /* Makes things easier when parsing the response packet. */
> + UCHAR Header1, Header2;
> + USHORT NumQuestions;
> + USHORT NumAnswers;
> + USHORT NumAuthority;
> + USHORT NumAdditional;
> + USHORT Type;
> +
> + if( (strlen( pAddr ) + 1) > 255 ) return;
> +
> + _tprintf( _T("Server: %s\n"), State.DefaultServer );
> + _tprintf( _T("Address: %s\n\n"), State.DefaultServerAddress );
> +
> + if( !strcmp( TypeA, State.type )
> + || !strcmp( TypeAAAA, State.type )
> + || !strcmp( TypeBoth, State.type ) )
> + {
> + Type = TYPE_A;
> + if( IsValidIP( pAddr ) ) Type = TYPE_PTR;
> + }
> + else
> + Type = TypeNametoTypeID( State.type );
> +
> + /* If it's a PTR lookup then append the ARPA sig to the end. */
> + if( (Type == TYPE_PTR) && IsValidIP( pAddr ) )
> + {
> + ReverseIP( pAddr, pResolve );
> + strcat( pResolve, ARPA_SIG );
> + }
> + else
> + {
> + strcpy( pResolve, pAddr );
> + }
> +
> + /* Base header length + length of QNAME + length of QTYPE and QCLASS */
> + BufferLength = 12 + (strlen( pResolve ) + 2) + 4;
> +
> + /* Allocate memory for the buffer. */
> + Buffer = HeapAlloc( ProcessHeap, 0, BufferLength );
> + if( !Buffer )
> + {
> + _tprintf( _T("ERROR: Out of memory\n") );
> + goto cleanup;
> + }
> +
> + /* Allocate memory for the return buffer. */
> + RecBuffer = HeapAlloc( ProcessHeap, 0, RecBufferLength );
> + if( !RecBuffer )
> + {
> + _tprintf( _T("ERROR: Out of memory\n") );
> + goto cleanup;
> + }
> +
> + /* Insert the ID field. */
> + ((PSHORT)&Buffer[i])[0] = htons( RequestID );
> + i += 2;
> +
> + /* Bits 0-7 of the second 16 are all 0, except for when recursion is
> + desired. */
> + Buffer[i] = 0x00;
> + if( State.recurse) Buffer[i] |= 0x01;
> + i += 1;
> +
> + /* Bits 8-15 of the second 16 are 0 for a query. */
> + Buffer[i] = 0x00;
> + i += 1;
> +
> + /* Only 1 question. */
> + ((PSHORT)&Buffer[i])[0] = htons( 1 );
> + i += 2;
> +
> + /* We aren't sending a response, so 0 out the rest of the header. */
> + Buffer[i] = 0x00;
> + Buffer[i + 1] = 0x00;
> + Buffer[i + 2] = 0x00;
> + Buffer[i + 3] = 0x00;
> + Buffer[i + 4] = 0x00;
> + Buffer[i + 5] = 0x00;
> + i += 6;
> +
> + /* Walk through the query address. Split each section delimited by '.'.
> + Format of the QNAME section is length|data, etc. Last one is null */
> + j = i;
> + i += 1;
> +
> + for( k = 0; k < strlen( pResolve ); k += 1 )
> + {
> + if( pResolve[k] != '.' )
> + {
> + Buffer[i] = pResolve[k];
> + i += 1;
> + }
> + else
> + {
> + Buffer[j] = (i - j) - 1;
> + j = i;
> + i += 1;
> + }
> + }
> +
> + Buffer[j] = (i - j) - 1;
> + Buffer[i] = 0x00;
> + i += 1;
> +
> + /* QTYPE */
> + ((PSHORT)&Buffer[i])[0] = htons( Type );
> + i += 2;
> +
> + /* QCLASS */
> + ((PSHORT)&Buffer[i])[0] = htons( ClassNametoClassID( State.Class ) );
> +
> + /* Ship off the request to the DNS server. */
> + bOk = SendRequest( Buffer,
> + BufferLength,
> + RecBuffer,
> + &RecBufferLength );
> + if( !bOk ) goto cleanup;
> +
> + /* Start parsing the received packet. */
> + Header1 = RecBuffer[2];
> + Header2 = RecBuffer[3];
> + NumQuestions = ntohs( ((PSHORT)&RecBuffer[4])[0] );
> + NumAnswers = ntohs( ((PSHORT)&RecBuffer[6])[0] );
> + NumAuthority = ntohs( ((PUSHORT)&RecBuffer[8])[0] );
> + NumAdditional = ntohs( ((PUSHORT)&RecBuffer[10])[0] );
> + Type = 0;
> +
> + /* Check the RCODE for failure. */
> + d = Header2 & 0x0F;
> + if( d != RCODE_NOERROR )
> + {
> + switch( d )
> + {
> + case RCODE_NXDOMAIN:
> + _tprintf( _T("*** %s can't find %s: Non-existant domain\n"), State.DefaultServer, pAddr );
> + break;
> +
> + case RCODE_REFUSED:
> + _tprintf( _T("*** %s can't find %s: Query refused\n"), State.DefaultServer, pAddr );
> + break;
> +
> + default:
> + _tprintf( _T("*** %s can't find %s: Unknown RCODE\n"), State.DefaultServer, pAddr );
> + }
> +
> + goto cleanup;
> + }
> +
> + k = 12;
> +
> + if( NumQuestions )
> + {
> + /* Blow through the questions section since we don't care about it. */
> + for( i = 0; i < NumQuestions; i += 1 )
> + {
> + k += ExtractName( RecBuffer, pResult, k, 0 );
> + k += 4;
> + }
> + }
> +
> + if( NumAnswers )
> + {
> + /* Skip the name. */
> + k += ExtractName( RecBuffer, pResult, k, 0 );
> +
> + Type = ntohs( ((PUSHORT)&RecBuffer[k])[0] );
> + k += 8;
> +
> + d = ntohs( ((PUSHORT)&RecBuffer[k])[0] );
> + k += 2;
> +
> + if( TYPE_PTR == Type )
> + {
> + k += ExtractName( RecBuffer, pResult, k, d );
> + }
> + else if( TYPE_A == Type )
> + {
> + k += ExtractIP( RecBuffer, pResult, k );
> + }
> + }
> +
> + /* FIXME: This'll need to support more than PTR and A at some point. */
> + if( !strcmp( State.type, TypePTR ) )
> + {
> + if( TYPE_PTR == Type )
> + {
> + _tprintf( _T("%s name = %s\n"), pResolve, pResult );
> + }
> + else
> + {
> + }
> + }
> + else if( !strcmp( State.type, TypeA )
> + || !strcmp( State.type, TypeAAAA )
> + || !strcmp( State.type, TypeBoth ) )
> + {
> + if( (TYPE_A == Type) /*|| (TYPE_AAAA == Type)*/ )
> + {
> + if( 0 == NumAuthority )
> + _tprintf( _T("Non-authoritative answer:\n") );
> +
> + _tprintf( _T("Name: %s\n"), pAddr );
> + _tprintf( _T("Address: %s\n\n"), pResult );
> + }
> + else
> + {
> + _tprintf( _T("Name: %s\n"), pResult );
> + _tprintf( _T("Address: %s\n\n"), pAddr );
> + }
> + }
> +
> +cleanup:
> + /* Free memory. */
> + if( Buffer ) HeapFree( ProcessHeap, 0, Buffer );
> + if( RecBuffer ) HeapFree( ProcessHeap, 0, RecBuffer );
> +
> + RequestID += 1;
> +}
> +
> +BOOL ParseCommandLine( int argc, char* argv[] )
> +{
> + int i;
> + BOOL NoMoreOptions = FALSE;
> + BOOL Interactive = FALSE;
> + CHAR AddrToResolve[256];
> + CHAR Server[256];
> +
> + RtlZeroMemory( AddrToResolve, 256 );
> + RtlZeroMemory( Server, 256 );
> +
> + if( 2 == argc )
> + {
> + /* In the Windows nslookup, usage is only displayed if /? is the only
> + option specified on the command line. */
> + if( !strncmp( "/?", argv[1], 2 ) )
> + {
> + PrintUsage();
> + return 0;
> + }
> + }
> +
> + if( argc > 1 )
> + {
> + for( i = 1; i < argc; i += 1 )
> + {
> + if( NoMoreOptions )
> + {
> + strncpy( Server, argv[i], 255 );
> +
> + /* Determine which one to resolve. This is based on whether the
> + DNS server provided was an IP or an FQDN. */
> + if( IsValidIP( Server ) )
> + {
> + strncpy( State.DefaultServerAddress, Server, 16 );
> +
> + PerformInternalLookup( State.DefaultServerAddress,
> + State.DefaultServer );
> + }
> + else
> + {
> + strncpy( State.DefaultServer, Server, 255 );
> +
> + PerformInternalLookup( State.DefaultServer,
> + State.DefaultServerAddress );
> + }
> +
> + if( Interactive ) return 1;
> +
> + PerformLookup( AddrToResolve );
> +
> + return 0;
> + }
> + else
> + {
> + if( !strncmp( "-all", argv[i], 4 ) )
> + {
> + PrintState();
> + }
> + else if( !strncmp( "-type=", argv[i], 6 ) )
> + {
> + if( !strncmp( TypeA, &argv[i][6], strlen( TypeA ) ) )
> + {
> + State.type = TypeA;
> + }
> + else if( !strncmp( TypeAAAA, &argv[i][6], strlen( TypeAAAA ) ) )
> + {
> + State.type = TypeAAAA;
> + }
> + else if( !strncmp( TypeBoth, &argv[i][6], strlen( TypeBoth ) ) )
> + {
> + State.type = TypeBoth;
> + }
> + else if( !strncmp( TypeAny, &argv[i][6], strlen( TypeAny ) ) )
> + {
> + State.type = TypeAny;
> + }
> + else if( !strncmp( TypeCNAME, &argv[i][6], strlen( TypeCNAME ) ) )
> + {
> + State.type = TypeCNAME;
> + }
> + else if( !strncmp( TypeMX, &argv[i][6], strlen( TypeMX ) ) )
> + {
> + State.type = TypeMX;
> + }
> + else if( !strncmp( TypeNS, &argv[i][6], strlen( TypeNS ) ) )
> + {
> + State.type = TypeNS;
> + }
> + else if( !strncmp( TypePTR, &argv[i][6], strlen( TypePTR ) ) )
> + {
> + State.type = TypePTR;
> + }
> + else if( !strncmp( TypeSOA, &argv[i][6], strlen( TypeSOA ) ) )
> + {
> + State.type = TypeSOA;
> + }
> + else if( !strncmp( TypeSRV, &argv[i][6], strlen( TypeSRV ) ) )
> + {
> + State.type = TypeSRV;
> + }
> + else
> + {
> + _tprintf( _T("unknown query type: %s"), &argv[i][6] );
> + }
> + }
> + else if( !strncmp( "-domain=", argv[i], 8 ) )
> + {
> + strcpy( State.domain, &argv[i][8] );
> + }
> + else if( !strncmp( "-srchlist=", argv[i], 10 ) )
> + {
> + }
> + else if( !strncmp( "-root=", argv[i], 6 ) )
> + {
> + strcpy( State.root, &argv[i][6] );
> + }
> + else if( !strncmp( "-retry=", argv[i], 7 ) )
> + {
> + }
> + else if( !strncmp( "-timeout=", argv[i], 9 ) )
> + {
> + }
> + else if( !strncmp( "-querytype=", argv[i], 11 ) )
> + {
> + if( !strncmp( TypeA, &argv[i][11], strlen( TypeA ) ) )
> + {
> + State.type = TypeA;
> + }
> + else if( !strncmp( TypeAAAA, &argv[i][11], strlen( TypeAAAA ) ) )
> + {
> + State.type = TypeAAAA;
> + }
> + else if( !strncmp( TypeBoth, &argv[i][11], strlen( TypeBoth ) ) )
> + {
> + State.type = TypeBoth;
> + }
> + else if( !strncmp( TypeAny, &argv[i][11], strlen( TypeAny ) ) )
> + {
> + State.type = TypeAny;
> + }
> + else if( !strncmp( TypeCNAME, &argv[i][11], strlen( TypeCNAME ) ) )
> + {
> + State.type = TypeCNAME;
> + }
> + else if( !strncmp( TypeMX, &argv[i][11], strlen( TypeMX ) ) )
> + {
> + State.type = TypeMX;
> + }
> + else if( !strncmp( TypeNS, &argv[i][11], strlen( TypeNS ) ) )
> + {
> + State.type = TypeNS;
> + }
> + else if( !strncmp( TypePTR, &argv[i][11], strlen( TypePTR ) ) )
> + {
> + State.type = TypePTR;
> + }
> + else if( !strncmp( TypeSOA, &argv[i][11], strlen( TypeSOA ) ) )
> + {
> + State.type = TypeSOA;
> + }
> + else if( !strncmp( TypeSRV, &argv[i][11], strlen( TypeSRV ) ) )
> + {
> + State.type = TypeSRV;
> + }
> + else
> + {
> + _tprintf( _T("unknown query type: %s"), &argv[i][6] );
> + }
> + }
> + else if( !strncmp( "-class=", argv[i], 7 ) )
> + {
> + if( !strncmp( ClassIN, &argv[i][7], strlen( ClassIN ) ) )
> + {
> + State.Class = ClassIN;
> + }
> + else if( !strncmp( ClassAny, &argv[i][7], strlen( ClassAny ) ) )
> + {
> + State.Class = ClassAny;
> + }
> + else
> + {
> + _tprintf( _T("unknown query class: %s"), &argv[i][7] );
> + }
> + }
> + else if( !strncmp( "-ixfrver=", argv[i], 9 ) )
> + {
> + }
> + else if( !strncmp( "-debug", argv[i], 6 ) )
> + {
> + State.debug = TRUE;
> + }
> + else if( !strncmp( "-nodebug", argv[i], 8 ) )
> + {
> + State.debug = FALSE;
> + State.d2 = FALSE;
> + }
> + else if( !strncmp( "-d2", argv[i], 3 ) )
> + {
> + State.d2 = TRUE;
> + State.debug = TRUE;
> + }
> + else if( !strncmp( "-nod2", argv[i], 5 ) )
> + {
> + if( State.debug ) _tprintf( _T("d2 mode disabled; still in debug mode\n") );
> +
> + State.d2 = FALSE;
> + }
> + else if( !strncmp( "-defname", argv[i], 8 ) )
> + {
> + State.defname = TRUE;
> + }
> + else if( !strncmp( "-noddefname", argv[i], 10 ) )
> + {
> + State.defname = FALSE;
> + }
> + else if( !strncmp( "-recurse", argv[i], 8 ) )
> + {
> + State.recurse = TRUE;
> + }
> + else if( !strncmp( "-norecurse", argv[i], 10 ) )
> + {
> + State.recurse = FALSE;
> + }
> + else if( !strncmp( "-search", argv[i], 7 ) )
> + {
> + State.search = TRUE;
> + }
> + else if( !strncmp( "-nosearch", argv[i], 9 ) )
> + {
> + State.search = FALSE;
> + }
> + else if( !strncmp( "-vc", argv[i], 3 ) )
> + {
> + State.vc = TRUE;
> + }
> + else if( !strncmp( "-novc", argv[i], 5 ) )
> + {
> + State.vc = FALSE;
> + }
> + else if( !strncmp( "-msxfr", argv[i], 6 ) )
> + {
> + State.MSxfr = TRUE;
> + }
> + else if( !strncmp( "-nomsxfr", argv[i], 8 ) )
> + {
> + State.MSxfr = FALSE;
> + }
> + else if( !strncmp( "-", argv[i], 1 ) && (strlen( argv[i] ) == 1) )
> + {
> + /* Since we received just the plain - switch, we are going
> + to be entering interactive mode. We also will not be
> + parsing any more options. */
> + NoMoreOptions = TRUE;
> + Interactive = TRUE;
> + }
> + else
> + {
> + /* Grab the address to resolve. No more options accepted
> + past this point. */
> + strncpy( AddrToResolve, argv[i], 255 );
> + NoMoreOptions = TRUE;
> + }
> + }
> + }
> +
> + if( NoMoreOptions && !Interactive )
> + {
> + /* Get the FQDN of the DNS server. */
> + PerformInternalLookup( State.DefaultServerAddress,
> + State.DefaultServer );
> +
> + PerformLookup( AddrToResolve );
> +
> + return 0;
> + }
> + }
> +
> + /* Get the FQDN of the DNS server. */
> + PerformInternalLookup( State.DefaultServerAddress,
> + State.DefaultServer );
> +
> + return 1;
> +}
> +
> +void InteractiveMode()
> +{
> + _tprintf( _T("Default Server: %s\n"), State.DefaultServer );
> + _tprintf( _T("Address: %s\n\n"), State.DefaultServerAddress );
> +
> + /* TODO: Implement interactive mode. */
> +
> + _tprintf( _T("ERROR: Feature not implemented.\n") );
> +}
> +
> +int main( int argc, char* argv[] )
> +{
> + int i;
> + ULONG Status;
> + PFIXED_INFO pNetInfo = NULL;
> + ULONG NetBufLen = 0;
> + WSADATA wsaData;
> +
> + ProcessHeap = GetProcessHeap();
> + RequestID = 1;
> +
> + /* Set up the initial state. */
> + State.debug = FALSE;
> + State.defname = TRUE;
> + State.search = TRUE;
> + State.recurse = TRUE;
> + State.d2 = FALSE;
> + State.vc = FALSE;
> + State.ignoretc = FALSE;
> + State.port = 53;
> + State.type = TypeBoth;
> + State.Class = ClassIN;
> + State.timeout = 2;
> + State.retry = 1;
> + State.MSxfr = TRUE;
> + State.ixfrver = 1;
> +
> + RtlZeroMemory( State.root, 256 );
> + RtlZeroMemory( State.domain, 256 );
> + for( i = 0; i < 6; i += 1 ) RtlZeroMemory( State.srchlist[i], 256 );
> + RtlZeroMemory( State.DefaultServer, 256 );
> + RtlZeroMemory( State.DefaultServerAddress, 16 );
> +
> + strncpy( State.root, DEFAULT_ROOT, strlen( DEFAULT_ROOT ) );
> +
> + /* We don't know how long of a buffer it will want to return. So we'll
> + pass an empty one now and let it fail only once, instead of guessing. */
> + Status = GetNetworkParams( pNetInfo, &NetBufLen );
> + if( Status == ERROR_BUFFER_OVERFLOW )
> + {
> + pNetInfo = (PFIXED_INFO)HeapAlloc( ProcessHeap, 0, NetBufLen );
> + if( pNetInfo == NULL )
> + {
> + _tprintf( _T("ERROR: Out of memory\n") );
> +
> + return -1;
> + }
> +
> + /* For real this time. */
> + Status = GetNetworkParams( pNetInfo, &NetBufLen );
> + if( Status != NO_ERROR )
> + {
> + _tprintf( _T("Error in GetNetworkParams call\n") );
> +
> + HeapFree( ProcessHeap, 0, pNetInfo );
> +
> + return -2;
> + }
> + }
> +
> + strncpy( State.domain, pNetInfo->DomainName, 255 );
> + strncpy( State.srchlist[0], pNetInfo->DomainName, 255 );
> + strncpy( State.DefaultServerAddress,
> + pNetInfo->DnsServerList.IpAddress.String,
> + 15 );
> +
> + HeapFree( ProcessHeap, 0, pNetInfo );
> +
> + WSAStartup( MAKEWORD(2,2), &wsaData );
> +
> + switch( ParseCommandLine( argc, argv ) )
> + {
> + case 0:
> + /* This means that it was a /? parameter. */
> + break;
> +
> + default:
> + /* Anything else means we enter interactive mode. The only exception
> + to this is when the host to resolve was provided on the command
> + line. */
> + InteractiveMode();
> + }
> +
> + WSACleanup();
> + return 0;
> +}
>
> Propchange: trunk/reactos/base/applications/network/nslookup/nslookup.c
> ------------------------------------------------------------------------------
> svn:eol-style = native
>
> Added: trunk/reactos/base/applications/network/nslookup/nslookup.h
> URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/network/nslookup/nslookup.h?rev=43700&view=auto
> ==============================================================================
> --- trunk/reactos/base/applications/network/nslookup/nslookup.h (added)
> +++ trunk/reactos/base/applications/network/nslookup/nslookup.h [iso-8859-1] Fri Oct 23 19:25:05 2009
> @@ -1,0 +1,104 @@
> +#define TypeA "A"
> +#define TypeAAAA "AAAA"
> +#define TypeBoth "A+AAAA"
> +#define TypeAny "ANY"
> +#define TypeCNAME "CNAME"
> +#define TypeMX "MX"
> +#define TypeNS "NS"
> +#define TypePTR "PTR"
> +#define TypeSOA "SOA"
> +#define TypeSRV "SRV"
> +
> +#define TYPE_A 0x01
> +#define TYPE_NS 0x02
> +#define TYPE_CNAME 0x05
> +#define TYPE_SOA 0x06
> +#define TYPE_WKS 0x0B
> +#define TYPE_PTR 0x0C
> +#define TYPE_MX 0x0F
> +#define TYPE_ANY 0xFF
> +
> +#define ClassIN "IN"
> +#define ClassAny "ANY"
> +
> +#define CLASS_IN 0x01
> +#define CLASS_ANY 0xFF
> +
> +#define OPCODE_QUERY 0x00
> +#define OPCODE_IQUERY 0x01
> +#define OPCODE_STATUS 0x02
> +
> +#define OpcodeQuery "QUERY"
> +#define OpcodeIQuery "IQUERY"
> +#define OpcodeStatus "STATUS"
> +#define OpcodeReserved "RESERVED"
> +
> +#define RCODE_NOERROR 0x00
> +#define RCODE_FORMERR 0x01
> +#define RCODE_FAILURE 0x02
> +#define RCODE_NXDOMAIN 0x03
> +#define RCODE_NOTIMP 0x04
> +#define RCODE_REFUSED 0x05
> +
> +#define RCodeNOERROR "NOERROR"
> +#define RCodeFORMERR "FORMERR"
> +#define RCodeFAILURE "FAILURE"
> +#define RCodeNXDOMAIN "NXDOMAIN"
> +#define RCodeNOTIMP "NOTIMP"
> +#define RCodeREFUSED "REFUSED"
> +#define RCodeReserved "RESERVED"
> +
> +#define DEFAULT_ROOT "A.ROOT-SERVERS.NET."
> +#define ARPA_SIG ".in-addr.arpa"
> +
> +typedef struct _STATE
> +{
> + BOOL debug;
> + BOOL defname;
> + BOOL d2;
> + BOOL recurse;
> + BOOL search;
> + BOOL vc;
> + BOOL ignoretc;
> + BOOL MSxfr;
> + CHAR domain[256];
> + CHAR srchlist[6][256];
> + CHAR root[256];
> + DWORD retry;
> + DWORD timeout;
> + DWORD ixfrver;
> + PCHAR type;
> + PCHAR Class;
> + USHORT port;
> + CHAR DefaultServer[256];
> + CHAR DefaultServerAddress[16];
> +} STATE, *PSTATE;
> +
> +/* nslookup.c */
> +
> +extern STATE State;
> +extern HANDLE ProcessHeap;
> +
> +/* utility.c */
> +
> +BOOL SendRequest( PCHAR pInBuffer,
> + ULONG InBufferLength,
> + PCHAR pOutBuffer,
> + PULONG pOutBufferLength );
> +
> +int ExtractName( PCHAR pBuffer,
> + PCHAR pOutput,
> + USHORT Offset,
> + UCHAR Limit );
> +
> +void ReverseIP( PCHAR pIP, PCHAR pReturn );
> +BOOL IsValidIP( PCHAR pInput );
> +int ExtractIP( PCHAR pBuffer, PCHAR pOutput, USHORT Offset );
> +void PrintD2( PCHAR pBuffer, DWORD BufferLength );
> +void PrintDebug( PCHAR pBuffer, DWORD BufferLength );
> +PCHAR OpcodeIDtoOpcodeName( UCHAR Opcode );
> +PCHAR RCodeIDtoRCodeName( UCHAR RCode );
> +PCHAR TypeIDtoTypeName( USHORT TypeID );
> +USHORT TypeNametoTypeID( PCHAR TypeName );
> +PCHAR ClassIDtoClassName( USHORT ClassID );
> +USHORT ClassNametoClassID( PCHAR ClassName );
>
> Propchange: trunk/reactos/base/applications/network/nslookup/nslookup.h
> ------------------------------------------------------------------------------
> svn:eol-style = native
>
> Added: trunk/reactos/base/applications/network/nslookup/nslookup.rbuild
> URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/network/nslookup/nslookup.rbuild?rev=43700&view=auto
> ==============================================================================
> --- trunk/reactos/base/applications/network/nslookup/nslookup.rbuild (added)
> +++ trunk/reactos/base/applications/network/nslookup/nslookup.rbuild [iso-8859-1] Fri Oct 23 19:25:05 2009
> @@ -1,0 +1,13 @@
> +<?xml version="1.0"?>
> +<!DOCTYPE module SYSTEM "../../../../tools/rbuild/project.dtd">
> +<module name="nslookup" type="win32cui" installbase="system32" installname="nslookup.exe">
> + <include base="nslookup">.</include>
> + <library>kernel32</library>
> + <library>user32</library>
> + <library>ws2_32</library>
> + <library>snmpapi</library>
> + <library>iphlpapi</library>
> + <file>nslookup.c</file>
> + <file>utility.c</file>
> + <file>nslookup.rc</file>
> +</module>
>
> Propchange: trunk/reactos/base/applications/network/nslookup/nslookup.rbuild
> ------------------------------------------------------------------------------
> svn:eol-style = native
>
> Added: trunk/reactos/base/applications/network/nslookup/nslookup.rc
> URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/network/nslookup/nslookup.rc?rev=43700&view=auto
> ==============================================================================
> --- trunk/reactos/base/applications/network/nslookup/nslookup.rc (added)
> +++ trunk/reactos/base/applications/network/nslookup/nslookup.rc [iso-8859-1] Fri Oct 23 19:25:05 2009
> @@ -1,0 +1,5 @@
> +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS TCP/IPv4 Win32 nslookup\0"
> +#define REACTOS_STR_INTERNAL_NAME "nslookup\0"
> +#define REACTOS_STR_ORIGINAL_FILENAME "nslookup.exe\0"
> +#define REACTOS_STR_ORIGINAL_COPYRIGHT "Lucas Suggs (lucas.suggs at gmail.com)\0"
> +#include <reactos/version.rc>
>
> Propchange: trunk/reactos/base/applications/network/nslookup/nslookup.rc
> ------------------------------------------------------------------------------
> svn:eol-style = native
>
> Added: trunk/reactos/base/applications/network/nslookup/utility.c
> URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/network/nslookup/utility.c?rev=43700&view=auto
> ==============================================================================
> --- trunk/reactos/base/applications/network/nslookup/utility.c (added)
> +++ trunk/reactos/base/applications/network/nslookup/utility.c [iso-8859-1] Fri Oct 23 19:25:05 2009
> @@ -1,0 +1,852 @@
> +/*
> + * PROJECT: ReactOS nslookup utility
> + * LICENSE: GPL - See COPYING in the top level directory
> + * FILE: applications/network/nslookup/utility.c
> + * PURPOSE: Support functions for nslookup.c
> + * COPYRIGHT: Copyright 2009 Lucas Suggs <lucas.suggs at gmail.com>
> + */
> +
> +#include <windows.h>
> +#include <tchar.h>
> +#include <stdio.h>
> +#include "nslookup.h"
> +
> +BOOL SendRequest( PCHAR pInBuffer,
> + ULONG InBufferLength,
> + PCHAR pOutBuffer,
> + PULONG pOutBufferLength )
> +{
> + int j;
> + USHORT RequestID, ResponseID;
> + BOOL bWait;
> + SOCKET s;
> + SOCKADDR_IN RecAddr, RecAddr2, SendAddr;
> + int SendAddrLen = sizeof(SendAddr);
> +
> + RtlZeroMemory( &RecAddr, sizeof(SOCKADDR_IN) );
> + RtlZeroMemory( &RecAddr2, sizeof(SOCKADDR_IN) );
> + RtlZeroMemory( &SendAddr, sizeof(SOCKADDR_IN) );
> +
> + /* Pull the request ID from the buffer. */
> + RequestID = ntohs( ((PSHORT)&pInBuffer[0])[0] );
> +
> + /* If D2 flags is enabled, then display D2 information. */
> + if( State.d2 ) PrintD2( pInBuffer, InBufferLength );
> +
> + /* Create the sockets for both send and receive. */
> + s = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
> +
> + /* Set up the structure to tell it where we are going. */
> + RecAddr.sin_family = AF_INET;
> + RecAddr.sin_port = htons( State.port );
> + RecAddr.sin_addr.s_addr = inet_addr( State.DefaultServerAddress );
> +
> + /* Set up the structure to tell it what port to listen on. */
> + RecAddr2.sin_family = AF_INET;
> + RecAddr2.sin_port = htons( State.port );
> + RecAddr2.sin_addr.s_addr = htonl( INADDR_ANY );
> +
> + /* Bind the receive socket. */
> + bind( s, (SOCKADDR*)&RecAddr2, sizeof(RecAddr2) );
> +
> + /* Send the datagram to the DNS server. */
> + j = sendto( s,
> + pInBuffer,
> + InBufferLength,
> + 0,
> + (SOCKADDR*)&RecAddr,
> + sizeof(RecAddr) );
> + if( j == SOCKET_ERROR )
> + {
> + switch( WSAGetLastError() )
> + {
> + case WSANOTINITIALISED:
> + _tprintf( _T("sendto() failed with WSANOTINITIALIZED\n") );
> + break;
> + case WSAENETDOWN:
> + _tprintf( _T("sendto() failed with WSAENETDOWN\n") );
> + break;
> + case WSAEACCES:
> + _tprintf( _T("sendto() failed with WSAEACCES\n") );
> + break;
> + case WSAEINVAL:
> + _tprintf( _T("sendto() failed with WSAEINVAL\n") );
> + break;
> + case WSAEINTR:
> + _tprintf( _T("sendto() failed with WSAEINTR\n") );
> + break;
> + case WSAEINPROGRESS:
> + _tprintf( _T("sendto() failed with WSAEINPROGRESS\n") );
> + break;
> + case WSAEFAULT:
> + _tprintf( _T("sendto() failed with WSAEFAULT\n") );
> + break;
> + case WSAENETRESET:
> + _tprintf( _T("sendto() failed with WSAENETRESET\n") );
> + break;
> + case WSAENOBUFS:
> + _tprintf( _T("sendto() failed with WSAENOBUFS\n") );
> + break;
> + case WSAENOTCONN:
> + _tprintf( _T("sendto() failed with WSAENOTCONN\n") );
> + break;
> + case WSAENOTSOCK:
> + _tprintf( _T("sendto() failed with WSAENOTSOCK\n") );
> + break;
> + case WSAEOPNOTSUPP:
> + _tprintf( _T("sendto() failed with WSAEOPNOTSUPP\n") );
> + break;
> + case WSAESHUTDOWN:
> + _tprintf( _T("sendto() failed with WSAESHUTDOWN\n") );
> + break;
> + case WSAEWOULDBLOCK:
> + _tprintf( _T("sendto() failed with WSAEWOULDBLOCK\n") );
> + break;
> + case WSAEMSGSIZE:
> + _tprintf( _T("sendto() failed with WSAEMSGSIZE\n") );
> + break;
> + case WSAEHOSTUNREACH:
> + _tprintf( _T("sendto() failed with WSAEHOSTUNREACH\n") );
> + break;
> + case WSAECONNABORTED:
> + _tprintf( _T("sendto() failed with WSAECONNABORTED\n") );
> + break;
> + case WSAECONNRESET:
> + _tprintf( _T("sendto() failed with WSAECONNRESET\n") );
> + break;
> + case WSAEADDRNOTAVAIL:
> + _tprintf( _T("sendto() failed with WSAEADDRNOTAVAIL\n") );
> + break;
> + case WSAEAFNOSUPPORT:
> + _tprintf( _T("sendto() failed with WSAEAFNOSUPPORT\n") );
> + break;
> + case WSAEDESTADDRREQ:
> + _tprintf( _T("sendto() failed with WSAEDESTADDRREQ\n") );
> + break;
> + case WSAENETUNREACH:
> + _tprintf( _T("sendto() failed with WSAENETUNREACH\n") );
> + break;
> + case WSAETIMEDOUT:
> + _tprintf( _T("sendto() failed with WSAETIMEDOUT\n") );
> + break;
> + default:
> + _tprintf( _T("sendto() failed with unknown error\n") );
> + }
> +
> + return FALSE;
> + }
> +
> + bWait = TRUE;
> +
> + while( bWait )
> + {
> + /* Wait for the DNS reply. */
> + j = recvfrom( s,
> + pOutBuffer,
> + *pOutBufferLength,
> + 0,
> + (SOCKADDR*)&SendAddr,
> + &SendAddrLen );
> + if( j == SOCKET_ERROR )
> + {
> + switch( WSAGetLastError() )
> + {
> + case WSANOTINITIALISED:
> + _tprintf( _T("recvfrom() failed with WSANOTINITIALIZED\n") );
> + break;
> + case WSAENETDOWN:
> + _tprintf( _T("recvfrom() failed with WSAENETDOWN\n") );
> + break;
> + case WSAEACCES:
> + _tprintf( _T("recvfrom() failed with WSAEACCES\n") );
> + break;
> + case WSAEINVAL:
> + _tprintf( _T("recvfrom() failed with WSAEINVAL\n") );
> + break;
> + case WSAEINTR:
> + _tprintf( _T("recvfrom() failed with WSAEINTR\n") );
> + break;
> + case WSAEINPROGRESS:
> + _tprintf( _T("recvfrom() failed with WSAEINPROGRESS\n") );
> + break;
> + case WSAEFAULT:
> + _tprintf( _T("recvfrom() failed with WSAEFAULT\n") );
> + break;
> + case WSAENETRESET:
> + _tprintf( _T("recvfrom() failed with WSAENETRESET\n") );
> + break;
> + case WSAENOBUFS:
> + _tprintf( _T("recvfrom() failed with WSAENOBUFS\n") );
> + break;
> + case WSAENOTCONN:
> + _tprintf( _T("recvfrom() failed with WSAENOTCONN\n") );
> + break;
> + case WSAENOTSOCK:
> + _tprintf( _T("recvfrom() failed with WSAENOTSOCK\n") );
> + break;
> + case WSAEOPNOTSUPP:
> + _tprintf( _T("recvfrom() failed with WSAEOPNOTSUPP\n") );
> + break;
> + case WSAESHUTDOWN:
> + _tprintf( _T("recvfrom() failed with WSAESHUTDOWN\n") );
> + break;
> + case WSAEWOULDBLOCK:
> + _tprintf( _T("recvfrom() failed with WSAEWOULDBLOCK\n") );
> + break;
> + case WSAEMSGSIZE:
> + _tprintf( _T("recvfrom() failed with WSAEMSGSIZE\n") );
> + break;
> + case WSAEHOSTUNREACH:
> + _tprintf( _T("recvfrom() failed with WSAEHOSTUNREACH\n") );
> + break;
> + case WSAECONNABORTED:
> + _tprintf( _T("recvfrom() failed with WSAECONNABORTED\n") );
> + break;
> + case WSAECONNRESET:
> + _tprintf( _T("recvfrom() failed with WSAECONNRESET\n") );
> + break;
> + case WSAEADDRNOTAVAIL:
> + _tprintf( _T("recvfrom() failed with WSAEADDRNOTAVAIL\n") );
> + break;
> + case WSAEAFNOSUPPORT:
> + _tprintf( _T("recvfrom() failed with WSAEAFNOSUPPORT\n") );
> + break;
> + case WSAEDESTADDRREQ:
> + _tprintf( _T("recvfrom() failed with WSAEDESTADDRREQ\n") );
> + break;
> + case WSAENETUNREACH:
> + _tprintf( _T("recvfrom() failed with WSAENETUNREACH\n") );
> + break;
> + case WSAETIMEDOUT:
> + _tprintf( _T("recvfrom() failed with WSAETIMEDOUT\n") );
> + break;
> + default:
> + _tprintf( _T("recvfrom() failed with unknown error\n") );
> + }
> +
> + return FALSE;
> + }
> +
> + ResponseID = ntohs( ((PSHORT)&pOutBuffer[0])[0] );
> +
> + if( ResponseID == RequestID ) bWait = FALSE;
> + }
> +
> + /* We don't need the sockets anymore. */
> + closesocket( s );
> +
> + /* If debug information then display debug information. */
> + if( State.debug ) PrintDebug( pOutBuffer, j );
> +
> + /* Return the real output buffer length. */
> + *pOutBufferLength = j;
> +
> + return TRUE;
> +}
> +
> +void ReverseIP( PCHAR pIP, PCHAR pReturn )
> +{
> + int i;
> + int j;
> + int k = 0;
> +
> + j = strlen( pIP ) - 1;
> + i = j;
> +
> + /* We have A.B.C.D
> + We will turn this into D.C.B.A and stick it in pReturn */
> +
> + /* A */
> + for( ; i > 0; i -= 1 ) if( '.' == pIP[i] ) break;
> +
> + strncpy( &pReturn[k], &pIP[i + 1], (j - i) );
> + k += (j - i);
> +
> + pReturn[k] = '.';
> + k += 1;
> +
> + i -= 1;
> + j = i;
> +
> + /* B */
> + for( ; i > 0; i -= 1 ) if( '.' == pIP[i] ) break;
> +
> + strncpy( &pReturn[k], &pIP[i + 1], (j - i) );
> + k += (j - i);
> +
> + pReturn[k] = '.';
> + k += 1;
> +
> + i -= 1;
> + j = i;
> +
> + /* C */
> + for( ; i > 0; i -= 1 ) if( '.' == pIP[i] ) break;
> +
> + strncpy( &pReturn[k], &pIP[i + 1], (j - i) );
> + k += (j - i);
> +
> + pReturn[k] = '.';
> + k += 1;
> +
> + i -= 1;
> + j = i;
> +
> + /* D */
> + for( ; i > 0; i -= 1 );
> +
> + strncpy( &pReturn[k], &pIP[i], (j - i) + 1 );
> + k += (j - i) + 1;
> +
> + pReturn[k] = '\0';
> +}
> +
> +BOOL IsValidIP( PCHAR pInput )
> +{
> + int i = 0, l = 0, b = 0, c = 1;
> +
> + /* Max length of an IP, e.g. 255.255.255.255, is 15 characters. */
> + l = strlen( pInput );
> + if( l > 15 ) return FALSE;
> +
> + /* 'b' is the count of the current segment. It gets reset after seeing a
> + '.'. */
> + for( ; i < l; i += 1 )
> + {
> + if( '.' == pInput[i] )
> + {
> + if( !b ) return FALSE;
> + if( b > 3 ) return FALSE;
> +
> + b = 0;
> + c += 1;
> + }
> + else
> + {
> + b += 1;
> +
> + if( (pInput[i] < '0') || (pInput[i] > '9') ) return FALSE;
> + }
> + }
> +
> + if( b > 3 ) return FALSE;
> +
> + /* 'c' is the number of segments seen. If it's less than 4, then it's not
> + a valid IP. */
> + if( c < 4 ) return FALSE;
> +
> + return TRUE;
> +}
> +
> +int ExtractName( PCHAR pBuffer, PCHAR pOutput, USHORT Offset, UCHAR Limit )
> +{
> + int c = 0, d = 0, i = 0, j = 0, k = 0, l = 0, m = 0;
> +
> + i = Offset;
> +
> + /* If Limit == 0, then we assume "no" limit. */
> + d = Limit;
> + if( 0 == Limit ) d = 255;
> +
> + while( d > 0 )
> + {
> + l = pBuffer[i] & 0xFF;
> + i += 1;
> + if( !m ) c += 1;
> +
> + if( 0xC0 == l )
> + {
> + if( !m ) c += 1;
> + m = 1;
> + d += (255 - Limit);
> + i = pBuffer[i];
> + }
> + else
> + {
> + for( j = 0; j < l; j += 1 )
> + {
> + pOutput[k] = pBuffer[i];
> +
> + i += 1;
> + if( !m ) c += 1;
> + k += 1;
> + d -= 1;
> + }
> +
> + d -= 1;
> +
> + if( !pBuffer[i] || (d < 1) ) break;
> +
> + pOutput[k] = '.';
> + k += 1;
> + }
> + };
> +
> + if( !m )
> + {
> + if( !Limit ) c += 1;
> + }
> +
> + pOutput[k] = '\0';
> +
> + return c;
> +}
> +
> +int ExtractIP( PCHAR pBuffer, PCHAR pOutput, USHORT Offset )
> +{
> + int c = 0, l = 0, i = 0, v = 0;
> +
> + i = Offset;
> +
> + v = (UCHAR)pBuffer[i];
> + l += 1;
> + i += 1;
> +
> + sprintf( &pOutput[c], "%d.", v );
> + c += strlen( &pOutput[c] );
> +
> + v = (UCHAR)pBuffer[i];
> + l += 1;
> + i += 1;
> +
> + sprintf( &pOutput[c], "%d.", v );
> + c += strlen( &pOutput[c] );
> +
> + v = (UCHAR)pBuffer[i];
> + l += 1;
> + i += 1;
> +
> + sprintf( &pOutput[c], "%d.", v );
> + c += strlen( &pOutput[c] );
> +
> + v = (UCHAR)pBuffer[i];
> + l += 1;
> + i += 1;
> +
> + sprintf( &pOutput[c], "%d", v );
> + c += strlen( &pOutput[c] );
> +
> + pOutput[c] = '\0';
> +
> + return l;
> +}
> +
> +void PrintD2( PCHAR pBuffer, DWORD BufferLength )
> +{
> + USHORT RequestID;
> + UCHAR Header1, Header2;
> + USHORT NumQuestions, NumAnswers, NumAuthority, NumAdditional;
> + USHORT Type, Class;
> + CHAR pName[255];
> + int i = 0, k = 0;
> +
> + RequestID = ntohs( ((PUSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + Header1 = pBuffer[i];
> + i += 1;
> +
> + Header2 = pBuffer[i];
> + i += 1;
> +
> + NumQuestions = ntohs( ((PSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + NumAnswers = ntohs( ((PSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + NumAuthority = ntohs( ((PUSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + NumAdditional = ntohs( ((PUSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + _tprintf( _T("------------\n") );
> + _tprintf( _T("SendRequest(), len %d\n"), (int)BufferLength );
> + _tprintf( _T(" HEADER:\n") );
> + _tprintf( _T(" opcode = %s, id = %d, rcode = %s\n"),
> + OpcodeIDtoOpcodeName( (Header1 & 0x78) >> 3 ),
> + (int)RequestID,
> + RCodeIDtoRCodeName( Header2 & 0x0F ) );
> +
> + _tprintf( _T(" header flags: query") );
> + if( Header1 & 0x01 ) _tprintf( _T(", want recursion") );
> + _tprintf( _T("\n") );
> +
> + _tprintf( _T(" questions = %d, answers = %d,"
> + " authority records = %d, additional = %d\n\n"),
> + (int)NumQuestions,
> + (int)NumAnswers,
> + (int)NumAuthority,
> + (int)NumAdditional );
> +
> + if( NumQuestions )
> + {
> + _tprintf( _T(" QUESTIONS:\n") );
> +
> + for( k = 0; k < NumQuestions; k += 1 )
> + {
> + i += ExtractName( pBuffer, pName, i, 0 );
> +
> + _tprintf( _T(" %s"), pName );
> +
> + Type = ntohs( ((PUSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + Class = ntohs( ((PUSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + _tprintf( _T(", type = %s, class = %s\n"),
> + TypeIDtoTypeName( Type ),
> + ClassIDtoClassName( Class ) );
> + }
> + }
> +
> + _tprintf( _T("\n------------\n") );
> +}
> +
> +void PrintDebug( PCHAR pBuffer, DWORD BufferLength )
> +{
> + USHORT ResponseID;
> + UCHAR Header1, Header2;
> + USHORT NumQuestions, NumAnswers, NumAuthority, NumAdditional;
> + USHORT Type, Class;
> + ULONG TTL;
> + CHAR pName[255];
> + int d = 0, i = 0, k = 0;
> +
> + ResponseID = ntohs( ((PUSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + Header1 = pBuffer[i];
> + i += 1;
> +
> + Header2 = pBuffer[i];
> + i += 1;
> +
> + NumQuestions = ntohs( ((PSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + NumAnswers = ntohs( ((PSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + NumAuthority = ntohs( ((PUSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + NumAdditional = ntohs( ((PUSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + _tprintf( _T("------------\n") );
> + _tprintf( _T("Got answer (%d bytes):\n"), (int)BufferLength );
> + _tprintf( _T(" HEADER:\n") );
> + _tprintf( _T(" opcode = %s, id = %d, rcode = %s\n"),
> + OpcodeIDtoOpcodeName( (Header1 & 0x78) >> 3 ),
> + (int)ResponseID,
> + RCodeIDtoRCodeName( Header2 & 0x0F ) );
> +
> + _tprintf( _T(" header flags: response") );
> + if( Header1 & 0x01 ) _tprintf( _T(", want recursion") );
> + if( Header2 & 0x80 ) _tprintf( _T(", recursion avail.") );
> + _tprintf( _T("\n") );
> +
> + _tprintf( _T(" questions = %d, answers = %d, "
> + "authority records = %d, additional = %d\n\n"),
> + (int)NumQuestions,
> + (int)NumAnswers,
> + (int)NumAuthority,
> + (int)NumAdditional );
> +
> + if( NumQuestions )
> + {
> + _tprintf( _T(" QUESTIONS:\n") );
> +
> + for( k = 0; k < NumQuestions; k += 1 )
> + {
> + i += ExtractName( pBuffer, pName, i, 0 );
> +
> + _tprintf( _T(" %s"), pName );
> +
> + Type = ntohs( ((PUSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + Class = ntohs( ((PUSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + _tprintf( _T(", type = %s, class = %s\n"),
> + TypeIDtoTypeName( Type ),
> + ClassIDtoClassName( Class ) );
> + }
> + }
> +
> + if( NumAnswers )
> + {
> + _tprintf( _T(" ANSWERS:\n") );
> +
> + for( k = 0; k < NumAnswers; k += 1 )
> + {
> + _tprintf( _T(" -> ") );
> +
> + /* Print out the name. */
> + i += ExtractName( pBuffer, pName, i, 0 );
> +
> + _tprintf( _T("%s\n"), pName );
> +
> + /* Print out the type, class and data length. */
> + Type = ntohs( ((PUSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + Class = ntohs( ((PUSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + TTL = ntohl( ((PULONG)&pBuffer[i])[0] );
> + i += 4;
> +
> + d = ntohs( ((PUSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + _tprintf( _T(" type = %s, class = %s, dlen = %d\n"),
> + TypeIDtoTypeName( Type ),
> + ClassIDtoClassName( Class ),
> + d );
> +
> + /* Print out the answer. */
> + if( TYPE_A == Type )
> + {
> + i += ExtractIP( pBuffer, pName, i );
> +
> + _tprintf( _T(" internet address = %s\n"), pName );
> + }
> + else
> + {
> + i += ExtractName( pBuffer, pName, i, d );
> +
> + _tprintf( _T(" name = %s\n"), pName );
> + }
> +
> + _tprintf( _T(" ttl = %d ()\n"), (int)TTL );
> + }
> + }
> +
> + if( NumAuthority )
> + {
> + _tprintf( _T(" AUTHORITY RECORDS:\n") );
> +
> + for( k = 0; k < NumAuthority; k += 1 )
> + {
> + /* Print out the zone name. */
> + i += ExtractName( pBuffer, pName, i, 0 );
> +
> + _tprintf( _T(" -> %s\n"), pName );
> +
> + /* Print out the type, class, data length and TTL. */
> + Type = ntohs( ((PUSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + Class = ntohs( ((PUSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + TTL = ntohl( ((PULONG)&pBuffer[i])[0] );
> + i += 4;
> +
> + d = ntohs( ((PUSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + _tprintf( _T(" type = %s, class = %s, dlen = %d\n"),
> + TypeIDtoTypeName( Type ),
> + ClassIDtoClassName( Class ),
> + d );
> +
> + /* TODO: There might be more types? */
> + if( TYPE_NS == Type )
> + {
> + /* Print out the NS. */
> + i += ExtractName( pBuffer, pName, i, d );
> +
> + _tprintf( _T(" nameserver = %s\n"), pName );
> +
> + _tprintf( _T(" ttl = %d ()\n"), (int)TTL );
> + }
> + else if( TYPE_SOA == Type )
> + {
> + _tprintf( _T(" ttl = %d ()\n"), (int)TTL );
> +
> + /* Print out the primary NS. */
> + i += ExtractName( pBuffer, pName, i, 0 );
> +
> + _tprintf( _T(" primary name server = %s\n"), pName );
> +
> + /* Print out the responsible mailbox. */
> + i += ExtractName( pBuffer, pName, i, 0 );
> +
> + _tprintf( _T(" responsible mail addr = %s\n"), pName );
> +
> + /* Print out the serial, refresh, retry, expire and default TTL. */
> + _tprintf( _T(" serial = ()\n") );
> + _tprintf( _T(" refresh = ()\n") );
> + _tprintf( _T(" retry = ()\n") );
> + _tprintf( _T(" expire = ()\n") );
> + _tprintf( _T(" default TTL = ()\n") );
> + i += 20;
> + }
> + }
> + }
> +
> + if( NumAdditional )
> + {
> + _tprintf( _T(" ADDITIONAL:\n") );
> +
> + for( k = 0; k < NumAdditional; k += 1 )
> + {
> + /* Print the name. */
> + i += ExtractName( pBuffer, pName, i, 0 );
> +
> + _tprintf( _T(" -> %s\n"), pName );
> +
> + /* Print out the type, class, data length and TTL. */
> + Type = ntohs( ((PUSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + Class = ntohs( ((PUSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + TTL = ntohl( ((PULONG)&pBuffer[i])[0] );
> + i += 4;
> +
> + d = ntohs( ((PUSHORT)&pBuffer[i])[0] );
> + i += 2;
> +
> + _tprintf( _T(" type = %s, class = %s, dlen = %d\n"),
> + TypeIDtoTypeName( Type ),
> + ClassIDtoClassName( Class ),
> + d );
> +
> + /* TODO: There might be more types? */
> + if( TYPE_A == Type )
> + {
> + /* Print out the NS. */
> + i += ExtractIP( pBuffer, pName, i );
> +
> + _tprintf( _T(" internet address = %s\n"), pName );
> +
> + _tprintf( _T(" ttl = %d ()\n"), (int)TTL );
> + }
> + }
> + }
> +
> + _tprintf( _T("\n------------\n") );
> +}
> +
> +PCHAR OpcodeIDtoOpcodeName( UCHAR Opcode )
> +{
> + switch( Opcode & 0x0F )
> + {
> + case OPCODE_QUERY:
> + return OpcodeQuery;
> +
> + case OPCODE_IQUERY:
> + return OpcodeIQuery;
> +
> + case OPCODE_STATUS:
> + return OpcodeStatus;
> +
> + default:
> + return OpcodeReserved;
> + }
> +}
> +
> +PCHAR RCodeIDtoRCodeName( UCHAR RCode )
> +{
> + switch( RCode & 0x0F )
> + {
> + case RCODE_NOERROR:
> + return RCodeNOERROR;
> +
> + case RCODE_FORMERR:
> + return RCodeFORMERR;
> +
> + case RCODE_FAILURE:
> + return RCodeFAILURE;
> +
> + case RCODE_NXDOMAIN:
> + return RCodeNXDOMAIN;
> +
> + case RCODE_NOTIMP:
> + return RCodeNOTIMP;
> +
> + case RCODE_REFUSED:
> + return RCodeREFUSED;
> +
> + default:
> + return RCodeReserved;
> + }
> +}
> +
> +PCHAR TypeIDtoTypeName( USHORT TypeID )
> +{
> + switch( TypeID )
> + {
> + case TYPE_A:
> + return TypeA;
> +
> + case TYPE_NS:
> + return TypeNS;
> +
> + case TYPE_CNAME:
> + return TypeCNAME;
> +
> + case TYPE_SOA:
> + return TypeSOA;
> +
> + case TYPE_WKS:
> + return TypeSRV;
> +
> + case TYPE_PTR:
> + return TypePTR;
> +
> + case TYPE_MX:
> + return TypeMX;
> +
> + case TYPE_ANY:
> + return TypeAny;
> +
> + default:
> + return "Unknown";
> + }
> +}
> +
> +USHORT TypeNametoTypeID( PCHAR TypeName )
> +{
> + if( !strncmp( TypeName, TypeA, strlen( TypeA ) ) ) return TYPE_A;
> + if( !strncmp( TypeName, TypeNS, strlen( TypeNS ) ) ) return TYPE_NS;
> + if( !strncmp( TypeName, TypeCNAME, strlen( TypeCNAME ) ) ) return TYPE_CNAME;
> + if( !strncmp( TypeName, TypeSOA, strlen( TypeSOA ) ) ) return TYPE_SOA;
> + if( !strncmp( TypeName, TypeSRV, strlen( TypeSRV ) ) ) return TYPE_WKS;
> + if( !strncmp( TypeName, TypePTR, strlen( TypePTR ) ) ) return TYPE_PTR;
> + if( !strncmp( TypeName, TypeMX, strlen( TypeMX ) ) ) return TYPE_MX;
> + if( !strncmp( TypeName, TypeAny, strlen( TypeAny ) ) ) return TYPE_ANY;
> +
> + return 0;
> +}
> +
> +PCHAR ClassIDtoClassName( USHORT ClassID )
> +{
> + switch( ClassID )
> + {
> + case CLASS_IN:
> + return ClassIN;
> +
> + case CLASS_ANY:
> + return ClassAny;
> +
> + default:
> + return "Unknown";
> + }
> +}
> +
> +USHORT ClassNametoClassID( PCHAR ClassName )
> +{
> + if( !strncmp( ClassName, ClassIN, strlen( ClassIN ) ) ) return CLASS_IN;
> + if( !strncmp( ClassName, ClassAny, strlen( ClassAny ) ) ) return CLASS_ANY;
> +
> + return 0;
> +}
>
> Propchange: trunk/reactos/base/applications/network/nslookup/utility.c
> ------------------------------------------------------------------------------
> svn:eol-style = native
>
> Modified: trunk/reactos/boot/bootdata/packages/reactos.dff
> URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/bootdata/packages/reactos.dff?rev=43700&r1=43699&r2=43700&view=diff
> ==============================================================================
> --- trunk/reactos/boot/bootdata/packages/reactos.dff [iso-8859-1] (original)
> +++ trunk/reactos/boot/bootdata/packages/reactos.dff [iso-8859-1] Fri Oct 23 19:25:05 2009
> @@ -64,6 +64,7 @@
> base\applications\network\ftp\ftp.exe 1
> base\applications\network\ipconfig\ipconfig.exe 1
> base\applications\network\netstat\netstat.exe 1
> +base\applications\network\nslookup\nslookup.exe 1
> base\applications\network\ping\ping.exe 1
> base\applications\network\telnet\telnet.exe 1
> base\applications\network\tracert\tracert.exe 1
>
>
>
More information about the Ros-dev
mailing list