Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1019 lines
25 KiB

/*++
Copyright (c) 1989-1996 Microsoft Corporation
Module Name:
DNS.c
Abstract:
VxD-specific DNS routines.
This stuff will all be obsolete when we get proper services for
Windows. Then we will just call Winsock for DNS name resolution.
Author:
Earle R. Horton (ERH) 13-Feb-1996
Revision History:
--*/
#include "nbtprocs.h"
//----------------------------------------------------------------------------
ULONG
DoDnsResolveDirect(
PNCB pncb,
PUCHAR pzDnsName,
PULONG pIpAddress
)
{
PDNS_DIRECT_WORK_ITEM_CONTEXT pContext;
PUCHAR pch;
tDEVICECONTEXT *pDeviceContext;
ULONG status;
CTELockHandle OldIrq;
pDeviceContext = GetDeviceContext( pncb ) ;
if ( pDeviceContext == NULL )
{
return NRC_BRIDGE ;
}
//
// If the primary DNS server is not defined, just return error.
// Return command timed out here.
//
if ( (!pDeviceContext->lDnsServerAddress) ||
( pDeviceContext->lDnsServerAddress == LOOP_BACK) )
{
return( NRC_NOCALL );
}
pContext = CTEAllocMem( sizeof(DNS_DIRECT_WORK_ITEM_CONTEXT) );
if ( pContext == NULL )
{
return NRC_NORESOURCES;
}
CTEZeroMemory( pContext, sizeof(DNS_DIRECT_WORK_ITEM_CONTEXT) );
pContext->pDeviceContext = pDeviceContext;
pContext->pNCB = pncb;
pContext->pzDnsName = pzDnsName;
pContext->pIpAddress = pIpAddress;
pContext->TransactId = htons(GetTransactId() + DIRECT_DNS_NAME_QUERY_BASE );
pContext->pchDomainName = NbtConfig.pDomainName;
pContext->Flags = DNS_DIRECT_DNS_SERVER;
for ( pch = &pzDnsName[0] ; *pch++ != '\0' ; )
{
if ( pch[0] == '.' )
{
pContext->Flags |= DNS_DIRECT_NAME_HAS_DOTS;
pContext->pchDomainName = NULL;
}
}
//
// Put on the pending name queries list again so that when the query
// response comes in from DNS we can find the context.
//
CTESpinLock(&NbtConfig.JointLock,OldIrq);
InsertTailList(&NbtConfig.DNSDirectNameQueries,
&pContext->Linkage
);
CTESpinFree(&NbtConfig.JointLock,OldIrq);
status = UdpSendDNSBcastDirect( pContext,
(ULONG)pNbtGlobConfig->uRetryTimeout,
(ULONG)pNbtGlobConfig->uNumRetries
);
pncb->ncb_retcode = pncb->ncb_cmd_cplt = status ;
if ( status != NRC_PENDING )
{
pncb->ncb_retcode = pncb->ncb_cmd_cplt = status ;
DnsUnlinkAndCompleteDirect( pContext );
}
else
{
status = NRC_GOODRET;
}
return status;
}
//----------------------------------------------------------------------------
NTSTATUS
UdpSendDNSBcastDirect(
IN PDNS_DIRECT_WORK_ITEM_CONTEXT pContext,
IN ULONG Timeout,
IN ULONG Retries
)
/*++
Routine Description:
This routine sends a name query directed to the name server.
Arguments:
Return Value:
NTSTATUS - success or not
History:
Adapted from UdpSendNSBcast() in "udpsend.c."
Earle R. Horton (earleh) March 18, 1996
--*/
{
NTSTATUS status;
tNAMEHDR *pNameHdr;
ULONG uLength;
ULONG uSentSize;
CTELockHandle OldIrq;
ULONG IpAddress;
tTIMERQENTRY *pTimerQEntry;
TDI_REQUEST TdiRequest;
PDNS_DIRECT_SEND_CONTEXT pSendContext;
pSendContext = CreateSendContextDirect(
pContext->pzDnsName,
pContext->pchDomainName,
(PVOID)&pNameHdr,
&uLength,
pContext);
if (pSendContext == NULL)
{
IF_DBG(NBT_DEBUG_NAMESRV)
KdPrint(("Nbt:Failed to Create Pdu to send to DNS.\n"));
return( NRC_NORES );
}
CTESpinLock(&NbtConfig.JointLock,OldIrq);
TdiRequest.Handle.AddressHandle = (PVOID)pContext->pDeviceContext->pNameServerFileObject;
// the completion routine is setup to free the pDgramTracker memory block
TdiRequest.RequestNotifyObject = SendDNSBcastDoneDirect;
TdiRequest.RequestContext = (PVOID)pSendContext;
// start the timer now...We didn't start it before because it could
// have expired during the dgram setup, perhaps before the Context was
// fully setup.
//
if (Timeout)
{
status = StartTimer(
Timeout,
pContext,
NULL,
DnsCompletionDirect,
NULL,
NULL,
(USHORT)Retries,
&pTimerQEntry
);
if (!NT_SUCCESS(status))
{
// we need to differentiate the timer failing versus lack
// of resources
CTESpinFree(&NbtConfig.JointLock,OldIrq);
CTEMemFree(pSendContext);
return( NRC_NORES );
}
//
// Cross link the nameaddr and the timer so we can stop the timer
// when the name query response occurs
//
pTimerQEntry->pCacheEntry = pContext;
pContext->pTimer = pTimerQEntry;
}
//
// in the event that DHCP has just removed the IP address, just cancel
// the request
//
if (pContext->pDeviceContext->IpAddress == 0)
{
StopTimer ( pContext->pTimer, NULL, NULL );
pContext->Flags |= DNS_DIRECT_CANCELLED;
}
CTESpinFree(&NbtConfig.JointLock,OldIrq);
(VOID) TdiSendDatagram(
&TdiRequest,
&pSendContext->SendInfo,
uLength,
&uSentSize,
&pSendContext->SendBuffer,
NBT_NAME_SERVICE
);
return( NRC_PENDING );
}
//----------------------------------------------------------------------------
VOID
SendDNSBcastDoneDirect(
IN PVOID pSendContext,
IN NTSTATUS status,
IN ULONG lInfo
)
{
CTEMemFree(pSendContext);
}
//----------------------------------------------------------------------------
BOOL
DoDnsCancelDirect(
PNCB pncb
)
{
PLIST_ENTRY pHead;
PLIST_ENTRY pEntry;
PDNS_DIRECT_WORK_ITEM_CONTEXT
pContext;
CTELockHandle OldIrq;
BOOL RetVal = FALSE;
pHead = pEntry = &NbtConfig.DNSDirectNameQueries;
CTESpinLock(&NbtConfig.JointLock,OldIrq);
while ((pEntry = pEntry->Flink) != pHead)
{
pContext = CONTAINING_RECORD(pEntry,DNS_DIRECT_WORK_ITEM_CONTEXT,Linkage);
if ( pContext->pNCB == pncb )
{
StopTimer ( pContext->pTimer, NULL, NULL );
pContext->Flags |= DNS_DIRECT_CANCELLED;
RetVal = TRUE;
break;
}
}
CTESpinFree(&NbtConfig.JointLock,OldIrq);
return RetVal;
}
//----------------------------------------------------------------------------
/*++
Routine Description:
This routine is called by the timer code when the timer expires. It must
decide if another name query should be sent to the DNS server, and if not,
then it completes the request.
Arguments:
Notes:
--*/
VOID
DnsCompletionDirect(
PVOID pvContext,
PVOID pvContext2,
tTIMERQENTRY *pTimerQEntry
)
{
PDNS_DIRECT_WORK_ITEM_CONTEXT pContext;
tDEVICECONTEXT *pDeviceContext;
NTSTATUS status;
CTELockHandle OldIrq;
PCHAR pchDomainName;
USHORT Flags;
BOOL fOneMoreTry;
KdPrint(("DnsCompletion entered\r\n"));
pContext = (PDNS_DIRECT_WORK_ITEM_CONTEXT)pvContext;
// if the client completion routine is not set anymore, then the
// timer has been cancelled or completed and this routine should
// just clean up its buffers associated with the tracker (and return)
//
if (!pTimerQEntry)
{
// complete the request
LOCATION(0x52);
DnsUnlinkAndCompleteDirect( pContext );
return;
}
//
// to prevent a client from stopping the timer and deleting the
// pContext, grab the lock and check if the timer has been stopped
//
CTESpinLock(&NbtConfig.JointLock,OldIrq);
pDeviceContext = pContext->pDeviceContext;
if (pTimerQEntry->Flags & TIMER_RETIMED)
{
//
// Got a wait ACK from the server.
//
pTimerQEntry->Flags &= ~TIMER_RETIMED;
pTimerQEntry->Flags |= TIMER_RESTART;
//
// if we are not bound to this card than use a very short timeout
//
if (
(!pDeviceContext->pNameServerFileObject)
|| (pContext->Flags & DNS_DIRECT_CANCELLED)
)
{
pTimerQEntry->DeltaTime = 10;
}
CTESpinFree(&NbtConfig.JointLock,OldIrq);
return;
}
// If done with all the (3) retries with primary, try secondary DNS srvr
// If secondary not defined, or done with secondary as well, stop.
//
fOneMoreTry = TRUE;
if (!(--pTimerQEntry->Retries))
{
//
// if backup server is not defined, or if it is defined but we just
// finished trying backup server, go back and try primary server for
// "other domains"
// e.g. DNSDomains was defined as "msft.dom2.com,msft.dom3.com,msft.dom"
// We were pointing at msft.dom2.com. Now, we are done with that (and
// didn't get a response), so try msft.dom3.com
//
if ( ( !pDeviceContext->lDnsBackupServer ) ||
( pDeviceContext->lDnsBackupServer == LOOP_BACK ) ||
( pContext->Flags & DNS_DIRECT_DNS_BACKUP) )
{
//
// if we just got done trying primary domain name, try all the
// "other domains" specified
//
if (pContext->pchDomainName == NbtConfig.pDomainName)
{
pContext->pchDomainName = NbtConfig.pDNSDomains;
if ( pContext->pchDomainName )
{
pContext->Flags &= ~DNS_DIRECT_DNS_BACKUP;
pContext->Flags |= DNS_DIRECT_DNS_SERVER;
pTimerQEntry->Retries = NbtConfig.uNumRetries;
}
else
{
fOneMoreTry = FALSE;
}
}
//
// if we had already started on "other domains", advance to the
// next domain within "other domains"
//
else if ( pContext->pchDomainName )
{
pchDomainName = pContext->pchDomainName;
while( *pchDomainName != ',' && // dom names separated by comma
*pchDomainName != ' ' && // or space
*pchDomainName != '\0' )
{
pchDomainName++;
}
if ( *pchDomainName == '\0' )
fOneMoreTry = FALSE;
else
{
pchDomainName++;
pContext->pchDomainName = pchDomainName;
pContext->Flags &= ~DNS_DIRECT_DNS_BACKUP;
pContext->Flags |= DNS_DIRECT_DNS_SERVER;
pTimerQEntry->Retries = NbtConfig.uNumRetries;
}
}
else
{
fOneMoreTry = FALSE;
}
}
// ok, prepare to try the backup server
else
{
pTimerQEntry->Retries = NbtConfig.uNumRetries;
pContext->Flags &= ~DNS_DIRECT_DNS_SERVER;
pContext->Flags |= DNS_DIRECT_DNS_BACKUP;
}
}
// we aren't done yet: send one more query and restart the timer
if (fOneMoreTry)
{
CTESpinFree(&NbtConfig.JointLock,OldIrq);
status = UdpSendDNSBcastDirect( pContext, 0, 0 );
pTimerQEntry->Flags |= TIMER_RESTART;
KdPrint(("One more DNS query sent out\r\n"));
}
// yup, all done: didn't find the name!
else
{
pTimerQEntry->Flags |= TIMER_RESTART;
StopTimer(pTimerQEntry,NULL,NULL);
CTESpinFree(&NbtConfig.JointLock,OldIrq);
}
}
//----------------------------------------------------------------------------
/*++
Routine Description:
This routine "actually" completes the request, either by completing the
asociated NCB with some kind of failure, or passing it off to the
main NCB processing code.
Arguments:
Notes:
--*/
VOID
DnsActualCompletionDirect(
IN NBT_WORK_ITEM_CONTEXT * pnbtContext
)
{
PDNS_DIRECT_WORK_ITEM_CONTEXT pContext = pnbtContext->pClientContext;
uchar errNCB = NRC_GOODRET ;
NCB * pNCB = pContext->pNCB;
if ( pNCB->ncb_cmd_cplt == NRC_PENDING )
{
//
// Failed to resolve the name, or request was cancelled.
//
if ( pContext->pIpAddress[0] == 0 )
{
errNCB = NRC_CMDTMO;
}
else if ( pContext->Flags & DNS_DIRECT_CANCELLED )
{
errNCB = NRC_CMDCAN;
}
else
{
errNCB = VNBT_NCB_X ( pContext->pNCB, NULL, pContext->pIpAddress, NULL, 0 );
}
if ( errNCB != NRC_GOODRET )
{
pNCB->ncb_retcode = pNCB->ncb_cmd_cplt = errNCB ;
//
// call the post-routine only if the post-routine has been specified!
//
if ( pNCB->ncb_post )
{
typedef void (CALLBACK * VXDNCBPost )( void ) ;
VXDNCBPost ncbpost = (VXDNCBPost) pNCB->ncb_post ;
//
// Clients are expecting EBX to point to the NCB (instead of
// pushing it on the stack...). The post routine may trash
// ebp also, so save it.
//
_asm pushad ;
_asm mov ebx, pNCB ;
ncbpost() ;
_asm popad ;
}
}
}
CTEMemFree(pContext);
CTEMemFree(pnbtContext);
}
//----------------------------------------------------------------------------
VOID
DnsUnlinkAndCompleteDirect(
IN PDNS_DIRECT_WORK_ITEM_CONTEXT pContext
)
/*++
Routine Description:
This routine unlinks and completes the request.
Arguments:
Notes:
--*/
{
RemoveEntryList(&pContext->Linkage);
VxdScheduleDelayedCall ( NULL,
pContext,
NULL,
DnsActualCompletionDirect,
pContext->pDeviceContext
);
}
//----------------------------------------------------------------------------
VOID
ProcessDnsResponseDirect(
IN tDEVICECONTEXT *pDeviceContext,
IN PVOID pSrcAddress,
IN tNAMEHDR UNALIGNED *pNameHdr,
IN LONG lNumBytes,
IN USHORT OpCodeFlags
)
/*++
Routine Description:
This function sets the state of the name being resolved appropriately
depending on whether DNS sends a positive or a negative response to our
query; calls the client completion routine and stops any more DNS queries
from going.
Arguments:
Return Value:
NTSTATUS - STATUS_SUCCESS or STATUS_UNSUCCESSFUL
--*/
{
NTSTATUS status;
tDNS_QUERYRESP UNALIGNED *pQuery;
PLIST_ENTRY pHead;
PLIST_ENTRY pEntry;
PDNS_DIRECT_WORK_ITEM_CONTEXT
pContext;
COMPLETIONCLIENT pClientCompletion;
PVOID Context;
PTRANSPORT_ADDRESS pSourceAddress;
ULONG SrcAddress;
ULONG IpAddress;
tTIMERQENTRY *pTimer = NULL;
CTELockHandle OldIrq1;
LONG lNameSize;
LONG lTraversedSoFar=0;
CHAR pJunkBuf[NETBIOS_NAME_SIZE];
PUCHAR pchQry;
// make sure this is a response
if ( !(OpCodeFlags & OP_RESPONSE) )
{
CDbgPrint(DBGFLAG_ERROR,("ProcessDnsResponseDirect: Bad OpCodeFlags\r\n"));
return;
}
pSourceAddress = (PTRANSPORT_ADDRESS)pSrcAddress;
SrcAddress = ntohl(((PTDI_ADDRESS_IP)&pSourceAddress->Address[0].Address[0])->in_addr);
CTESpinLock(&NbtConfig.JointLock,OldIrq1);
if ( ( pContext = FindContextDirect( pNameHdr->TransactId ) ) != NULL )
{
pContext->Flags |= DNS_DIRECT_ANSWERED;
if ( pTimer = pContext->pTimer )
{
//
// If the response we received doesn't resolve the name, we silently return,
// but make sure reties is set to 1 so that when timer fires again, we don't
// send another name query to the same server but instead timeout the
// attempt on this server
//
pTimer->Retries = 1;
}
//
// check the pdu size for errors
//
if (lNumBytes < DNS_MINIMUM_QUERYRESPONSE)
{
CDbgPrint(DBGFLAG_ERROR,("ProcessDnsResponseDirect: Bad lNumBytes\r\n"));
goto done;
}
//
// BUGBUG: should we require authoritative responses from DNS servers?
//
//
// if it's a negative response, quit now!
//
if (IS_NEG_RESPONSE(OpCodeFlags))
{
goto done;
}
//
// if there is no answer section, return!
//
if ( !pNameHdr->AnCount )
{
CDbgPrint(DBGFLAG_ERROR,("ProcessDnsResponseDirect: No answer section\r\n"));
goto done;
}
//
// lNameSize is the length of the entire name, excluding the length byte
// for the first label (including length bytes of subsequent labels) and
// including the trailing 0 (tNAMEHDR struc takes care for 1st byte)
//
DnsExtractName( (PCHAR)&pNameHdr->NameRR.NameLength,
lNumBytes,
pJunkBuf,
&lNameSize
);
pchQry = (PUCHAR)&pNameHdr->NameRR.NetBiosName[lNameSize];
lTraversedSoFar += lNameSize;
//
// if the Question section is returned with the response then we have
// a little more work to do! In this case, pQuery is pointing at the
// beginning of the QTYPE field (end of the QNAME)
//
if ( pNameHdr->QdCount )
{
pchQry += sizeof(tQUESTIONMODS);
lTraversedSoFar += sizeof(tQUESTIONMODS);
// most common case: 1st byte will be 0xC0, which means next byte points
// to the actual name. We don't care about the name, so we skip over
// both the bytes
//
if ( (*pchQry) == PTR_TO_NAME )
{
pchQry += sizeof(tDNS_LABEL);
lTraversedSoFar += sizeof(tDNS_LABEL);
}
//
// if some implementation doesn't optimize and copies the whole name
// again, skip over the length of the name
//
else
{
pchQry += (lNameSize+1); // +1 because of the 1st length byte!
lTraversedSoFar += (lNameSize+1);
}
}
pQuery = (tDNS_QUERYRESP *)pchQry;
//
// if this rr is telling us about canonical name, skip over it and go to
// where the ipaddr is
//
if (ntohs(pQuery->RrType) == DNS_CNAME)
{
//
// since this is CNAME, there is no ipaddr. Instead, the data is the
// canonical name whose length we are adding, and subtract ipaddr's len
//
pchQry += (sizeof(tDNS_QUERYRESP) - sizeof(ULONG));
pchQry += ntohs(pQuery->Length);
lTraversedSoFar += ntohs(pQuery->Length) + sizeof(tDNS_QUERYRESP) - sizeof(ULONG);
ASSERT(lNumBytes > lTraversedSoFar);
// most common case: 1st byte will be 0xC0, which means next byte points
// to the actual name. We don't care about the name, so we skip over
// both the bytes
//
if ( (*pchQry) == PTR_TO_NAME )
{
pchQry += sizeof(tDNS_LABEL);
lTraversedSoFar += sizeof(tDNS_LABEL);
}
//
// if some implementation doesn't optimize and copies the whole name
// again, skip over the length of the name
//
else
{
// we have already taken the name out. we are calling this routine
// just to see how big the canonical name is (i.e.lNameSize), to skip
// past it
//
DnsExtractName( pchQry,
lNumBytes-lTraversedSoFar,
pJunkBuf,
&lNameSize
);
//
// lNameSize is the length of the entire name, excluding the length byte
// for the first label (including length bytes of subsequent labels) and
// including the trailing 0 (tNAMEHDR struc takes care for 1st byte)
//
pchQry += lNameSize+1; // +1 for the length byte of first label
}
pQuery = (tDNS_QUERYRESP *)pchQry;
}
// if we came this far, it's a positive response. do the needful.
IpAddress = ntohl(pQuery->IpAddress);
if ( !NbtWouldLoopback( IpAddress ) )
{
pContext->pIpAddress[0] = IpAddress;
}
else
{
pContext->Flags |= DNS_DIRECT_CANCELLED;
}
//
// Set the backup name server to be the main name server
// if we got a response from it.
//
if ( SrcAddress == pContext->pDeviceContext->lDnsBackupServer )
{
pContext->pDeviceContext->lDnsBackupServer =
pContext->pDeviceContext->lDnsServerAddress;
pContext->pDeviceContext->lDnsServerAddress = SrcAddress;
}
StopTimer(pTimer,NULL,NULL);
}
done:
CTESpinFree(&NbtConfig.JointLock,OldIrq1);
return;
}
//----------------------------------------------------------------------------
PDNS_DIRECT_SEND_CONTEXT
CreateSendContextDirect(
IN PCHAR pName,
IN PCHAR pchDomainName,
OUT PVOID *pHdrs,
OUT PULONG pLength,
IN PDNS_DIRECT_WORK_ITEM_CONTEXT pContext
)
/*++
Routine Description:
This routine builds a name query pdu
Arguments:
Return Value:
PDNS_DIRECT_SEND_CONTEXT - a pointer to a data structure used for the datagram
send that must be freed by the datagram send completion routine
--*/
{
tNAMEHDR *pNameHdr;
ULONG uLength;
ULONG uDomainNameSize;
tGENERALRR *pGeneral;
CTELockHandle OldIrq;
PDNS_DIRECT_SEND_CONTEXT
pSendContext;
uDomainNameSize = domnamelen(pchDomainName) + 1; // +1 for len byte
if (uDomainNameSize > 1)
{
uDomainNameSize++; // for the null byte
}
// size is size of the namehdr structure -1 for the NetbiosName[1]
// + the 32 bytes for the half ascii name +
// scope + size of the General RR structure
uLength = sizeof(DNS_DIRECT_SEND_CONTEXT) - 1
+ uDomainNameSize
+ sizeof(ULONG)
+ strlen(pName)
+ 1;
// Note that this memory must be deallocated when the send completes in
// SendDNSBcastDoneDirect()
pSendContext = NbtAllocMem((USHORT)uLength ,NBT_TAG('X'));
if (pSendContext)
{
CTEZeroMemory((PVOID)pSendContext,uLength);
pNameHdr = &pSendContext->NameHdr;
pNameHdr->TransactId = pContext->TransactId;
pNameHdr->QdCount = 1;
pNameHdr->AnCount = 0;
pNameHdr->NsCount = 0;
*pHdrs = (PVOID)pNameHdr;
*pLength = uLength = uLength - ( sizeof(DNS_DIRECT_SEND_CONTEXT) - sizeof(tNAMEHDR) );
// copy the netbios name ... adding the scope too
if ( pContext->Flags & DNS_DIRECT_NAME_HAS_DOTS )
{
char * p;
for ( p = pName ; *p != '.' ; p++ );
p[0] = '\0';
pGeneral = (tGENERALRR *)DnsStoreName(
(PCHAR)&pNameHdr->NameRR.NameLength,
pName,
&p[1],
eDIRECT_DNS_NAME_QUERY);
p[0] = '.';
}
else
{
pGeneral = (tGENERALRR *)DnsStoreName(
(PCHAR)&pNameHdr->NameRR.NameLength,
pName,
pContext->pchDomainName,
eDIRECT_DNS_NAME_QUERY);
}
pGeneral->Question.QuestionTypeClass = htonl(QUEST_DNSINTERNET);
pNameHdr->OpCodeFlags = (FL_RECURDESIRE);
pNameHdr->ArCount = 0;
pSendContext->SendBuffer.pDgramHdr = pNameHdr;
pSendContext->SendBuffer.HdrLength = uLength;
pSendContext->SendBuffer.pBuffer = NULL;
pSendContext->SendBuffer.Length = 0;
pSendContext->SendInfo.RemoteAddressLength = sizeof(pSendContext->NameServerAddress);
pSendContext->SendInfo.RemoteAddress = (PTRANSPORT_ADDRESS)&pSendContext->NameServerAddress;
pSendContext->NameServerAddress.TAAddressCount = 1;
pSendContext->NameServerAddress.Address[0].AddressLength = sizeof(TDI_ADDRESS_IP);
pSendContext->NameServerAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
pSendContext->NameServerAddress.Address[0].Address[0].sin_port = htons(NbtConfig.DnsServerPort);
if ( pContext->Flags & DNS_DIRECT_DNS_SERVER )
{
pSendContext->NameServerAddress.Address[0].Address[0].in_addr = htonl(pContext->pDeviceContext->lDnsServerAddress);
}
else
{
pSendContext->NameServerAddress.Address[0].Address[0].in_addr = htonl(pContext->pDeviceContext->lDnsBackupServer);
}
}
return(pSendContext);
}
//----------------------------------------------------------------------------
PDNS_DIRECT_WORK_ITEM_CONTEXT
FindContextDirect(
USHORT TransactionId
)
/*++
Routine Description:
This routine find the DNS_DIRECT_WORK_ITEM_CONTEXT having the given
TransactId
Arguments:
Return Value:
PDNS_DIRECT_SEND_CONTEXT - a pointer to the pContext having the given
TransactId, or NULL
Notes:
Called with NbtConfig.JointLock held
--*/
{
PLIST_ENTRY pHead;
PLIST_ENTRY pEntry;
PDNS_DIRECT_WORK_ITEM_CONTEXT
pContext;
pHead = pEntry = &NbtConfig.DNSDirectNameQueries;
while ((pEntry = pEntry->Flink) != pHead)
{
pContext = CONTAINING_RECORD(pEntry,DNS_DIRECT_WORK_ITEM_CONTEXT,Linkage);
if ( pContext->TransactId == TransactionId )
{
return pContext;
}
}
return NULL;
}
//----------------------------------------------------------------------------
VOID
IpToAscii(
IN DWORD IpAddress,
IN OUT PCHAR pcAscii
)
/*++
Routine Description:
This routine converts an IP address to a NetBIOS name.
Arguments:
DWORD IP address
PCHAR String pointer allocated for 16 bytes
Return Value:
Note
Notes:
This is a gigantic hack designed to get "net use \\<dnsname>"
working under Windows 95 OPK2 without destabilizing the existing
code base over much.
--*/
{
PCHAR pcIpAddressBytes = ( (PCHAR) &IpAddress ) + 3;
PCHAR pcIp = pcAscii;
int i,j,k,l,m;
memset ( pcAscii, 0x20, NETBIOS_NAME_SIZE );
for ( i = 4 ; i-- > 0 ; )
{
j = *pcIpAddressBytes-- & 0x000000FF;
k = j/100;
l = (j%100)/10;
m = j%10;
if ( k )
{
*pcIp++ = k + '0';
*pcIp++ = l + '0';
}
else if ( l )
{
*pcIp++ = l + '0';
}
*pcIp++ = m + '0';
if ( i )
{
*pcIp++ = '.';
}
}
}