mirror of
https://github.com/reactos/reactos.git
synced 2024-08-17 00:48:51 +00:00
855 lines
23 KiB
C
855 lines
23 KiB
C
/*
|
|
* PROJECT: ReactOS nslookup utility
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: base/applications/network/nslookup/utility.c
|
|
* PURPOSE: Support functions for nslookup.c
|
|
* COPYRIGHT: Copyright 2009 Lucas Suggs <lucas.suggs@gmail.com>
|
|
*/
|
|
|
|
#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 );
|
|
|
|
if (s == INVALID_SOCKET)
|
|
return FALSE;
|
|
|
|
/* 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") );
|
|
}
|
|
|
|
closesocket( s );
|
|
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") );
|
|
}
|
|
|
|
closesocket( s );
|
|
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;
|
|
}
|