[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