|
|
//++
//
// Copyright (C) Microsoft Corporation, 1987 - 1999
//
// Module Name:
//
// winstest.c
//
// Abstract:
//
// Queries into network drivers
//
// Author:
//
// Anilth - 4-20-1998
//
// Environment:
//
// User mode only.
// Contains NT-specific code.
//
// Revision History:
//
//--
#include "precomp.h"
#include "dhcptest.h"
static const TCHAR s_szSpace12[] = _T(" "); const int c_iWaitTime = 2000;
BOOL IsNameResponse( NETDIAG_PARAMS * pParams, char* ipAddrStr ); int Probe( NETDIAG_PARAMS *pParams, TCHAR *szSrvIpAddr, SOCKET listenNameSvcSock );
//-------------------------------------------------------------------------//
//###### W I N S T e s t () #############################################//
//-------------------------------------------------------------------------//
// Abstract: //
// Queries the all the configured WINS servers to make sure that //
// they are reachable and that they have the proper name-IP mapping //
// for this workstation. //
// Arguments: //
// none //
// Return value: //
// TRUE - test passed //
// FALSE - test failed //
// Global variables used: //
// none //
//-------------------------------------------------------------------------//
HRESULT WinsTest( NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults) { IPCONFIG_TST * pIpConfig; WINS_TST * pWinsResult; PIP_ADAPTER_INFO pIpAdapter; IP_ADDR_STRING winsSrv; int nWinsSrvOk = 0; HRESULT hr = hrOK; int i; TCHAR szBuffer[256];
// IDS_WINS_STATUS_MSG " Testing the WINS server... \n"
PrintStatusMessage(pParams, 4, IDS_WINS_STATUS_MSG);
//
// try to send name queries to the WINS servers on all adapters
//
for ( i = 0; i < pResults->cNumInterfaces; i++ ) { UINT nIfWinsOk = 0;
pIpConfig = &pResults->pArrayInterface[i].IpConfig; pIpAdapter = pResults->pArrayInterface[i].IpConfig.pAdapterInfo; InitializeListHead( &pResults->pArrayInterface[i].Wins.lmsgPrimary ); InitializeListHead( &pResults->pArrayInterface[i].Wins.lmsgSecondary );
if (!pIpConfig->fActive || NETCARD_DISCONNECTED == pResults->pArrayInterface[i].dwNetCardStatus) continue;
if (!pResults->pArrayInterface[i].fNbtEnabled) continue;
PrintStatusMessage(pParams, 8, IDSSZ_GLOBAL_StringLine, pResults->pArrayInterface[i].pszFriendlyName);
pWinsResult = &pResults->pArrayInterface[i].Wins;
//
// looping through the primary WINS server list
//
winsSrv = pIpAdapter->PrimaryWinsServer; if ( ZERO_IP_ADDRESS(winsSrv.IpAddress.String) ) { if(pParams->fReallyVerbose) PrintMessage(pParams, IDS_WINS_QUERY_NO_PRIMARY, s_szSpace12); AddMessageToList(&pWinsResult->lmsgPrimary, Nd_ReallyVerbose, IDS_WINS_QUERY_NO_PRIMARY, s_szSpace12); } else { pWinsResult->fPerformed = TRUE;
while ( TRUE ) { if (pParams->fReallyVerbose) PrintMessage(pParams, IDS_WINS_QUERY_PRIMARY, s_szSpace12, winsSrv.IpAddress.String); AddMessageToList(&pWinsResult->lmsgPrimary, Nd_ReallyVerbose, IDS_WINS_QUERY_PRIMARY, s_szSpace12, winsSrv.IpAddress.String); if ( IsNameResponse(pParams, winsSrv.IpAddress.String) ) { if (pParams->fReallyVerbose) PrintMessage(pParams, IDS_GLOBAL_PASS_NL); AddMessageToList(&pWinsResult->lmsgPrimary, Nd_ReallyVerbose, IDS_GLOBAL_PASS_NL); nWinsSrvOk++; nIfWinsOk++; } else { if (pParams->fReallyVerbose) PrintMessage(pParams, IDS_GLOBAL_FAIL_NL); AddMessageToList(&pWinsResult->lmsgPrimary, Nd_ReallyVerbose, IDS_GLOBAL_FAIL_NL); } if ( winsSrv.Next == NULL ) { break; }
winsSrv = *(winsSrv.Next); } }
//
// looping through the secondary WINS server list
//
winsSrv = pIpAdapter->SecondaryWinsServer; if ( ZERO_IP_ADDRESS(winsSrv.IpAddress.String) ) { if(pParams->fReallyVerbose) PrintMessage(pParams, IDS_WINS_QUERY_NO_SECONDARY, s_szSpace12); AddMessageToList(&pWinsResult->lmsgSecondary, Nd_ReallyVerbose, IDS_WINS_QUERY_NO_SECONDARY, s_szSpace12); } else { pWinsResult->fPerformed = TRUE;
while ( TRUE ) { if (pParams->fReallyVerbose) PrintMessage(pParams, IDS_WINS_QUERY_SECONDARY, s_szSpace12, winsSrv.IpAddress.String); AddMessageToList(&pWinsResult->lmsgSecondary, Nd_ReallyVerbose, IDS_WINS_QUERY_SECONDARY, s_szSpace12, winsSrv.IpAddress.String); if ( IsNameResponse(pParams, winsSrv.IpAddress.String) ) { if (pParams->fReallyVerbose) PrintMessage(pParams, IDS_GLOBAL_PASS_NL); AddMessageToList(&pWinsResult->lmsgSecondary, Nd_ReallyVerbose, IDS_GLOBAL_PASS_NL); nWinsSrvOk++; nIfWinsOk++; } else { if (pParams->fReallyVerbose) PrintMessage(pParams, IDS_GLOBAL_FAIL_NL); AddMessageToList(&pWinsResult->lmsgSecondary, Nd_ReallyVerbose, IDS_GLOBAL_FAIL_NL); }
if ( winsSrv.Next == NULL ) { break; }
winsSrv = *(winsSrv.Next); } } if( 0 == nIfWinsOk ) pWinsResult->hr = S_FALSE; else pWinsResult->hr = S_OK;
} /* end of for loop scanning all the adapters */
//$REVIEW No global test result for WINS test
if ( nWinsSrvOk != 0) { hr = S_OK; } else { hr = S_FALSE; }
return hr; } /* END OF WINSTest() */
//-------------------------------------------------------------------------//
//###### P r o b e () ##################################################//
//-------------------------------------------------------------------------//
// Abstract: //
// Assembles and sends a name query to the DHCP server. //
// Arguments: //
// none //
// Return value: //
// TRUE if a response has been received from the server //
// FALSE otherwise //
// Global variables used: //
// g_isDebug (reading only) //
// //
// Comments: //
// This will not work for b-type nodes for which you need to set the B bit//
// and broadcast the packet instead of unicast xmission - Rajkumar //
//-------------------------------------------------------------------------//
int Probe( NETDIAG_PARAMS *pParams, TCHAR *szSrvIpAddr, SOCKET listenNameSvcSock ) {
char nbtFrameBuf[MAX_NBT_PACKET_SIZE]; NM_FRAME_HDR *pNbtHeader = (NM_FRAME_HDR *)nbtFrameBuf; NM_QUESTION_SECT *pNbtQuestion = (NM_QUESTION_SECT *)( nbtFrameBuf + sizeof(NM_FRAME_HDR) ); struct sockaddr_in destSockAddr; char *pDest, *pName; int nBytesSent = 0, i;
/* RFC 1002 section 4.2.12
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | NAME_TRN_ID |0| 0x0 |0|0|1|0|0 0|B| 0x0 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 0x0001 | 0x0000 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 0x0000 | 0x0000 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | / QUESTION_NAME / / / | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | NB (0x0020) | IN (0x0001) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ pNbtHeader->xid = NM_QRY_XID; pNbtHeader->flags = NBT_NM_OPC_QUERY | NBT_NM_OPC_REQUEST | NBT_NM_FLG_RECURS_DESRD; pNbtHeader->question_cnt = 0x0100; pNbtHeader->answer_cnt = 0; pNbtHeader->name_serv_cnt = 0; pNbtHeader->additional_cnt = 0;
// pDest is filling nbtQuestion->q_name
pNbtQuestion->q_type = NBT_NM_QTYP_NB; pNbtQuestion->q_class = NBT_NM_QCLASS_IN;
//
// translate the name
//
pDest = (char *)&(pNbtQuestion->q_name); pName = nameToQry;
// the first byte of the name is the length field = 2*16
*pDest++ = NBT_NAME_SIZE;
// step through name converting ascii to half ascii, for 32 times
for ( i = 0; i < (NBT_NAME_SIZE / 2) ; i++ ) { *pDest++ = (*pName >> 4) + 'A'; *pDest++ = (*pName++ & 0x0F) + 'A'; } *pDest++ = '\0'; *pDest = '\0';
//
// send the name query frame
//
destSockAddr.sin_family = PF_INET; destSockAddr.sin_port = htons(137); // NBT_NAME_SERVICE_PORT;
destSockAddr.sin_addr.s_addr = inet_addr( szSrvIpAddr ); for ( i = 0; i < 8 ; i++ ) { destSockAddr.sin_zero[i] = 0; }
nBytesSent = sendto( listenNameSvcSock, (PCHAR )nbtFrameBuf, sizeof(NM_FRAME_HDR) + sizeof(NM_QUESTION_SECT), 0, (struct sockaddr *)&destSockAddr, sizeof( struct sockaddr ) );
PrintDebugSz(pParams, 0, _T("\n querying name %s on server %s\n"), nameToQry, szSrvIpAddr ); PrintDebugSz(pParams, 0, _T( " bytes sent %d\n"), nBytesSent );
if ( nBytesSent == SOCKET_ERROR ) { PrintDebugSz(pParams, 0, _T(" Error %d in sendto()!\n"), WSAGetLastError() ); return FALSE; }
//
// the other thread should see the incoming frame and increment m_nMsgCnt
//
return TRUE;
} /* END OF Probe() */
//-------------------------------------------------------------------------//
//###### I s N a m e R e s p o n s e () #################################//
//-------------------------------------------------------------------------//
// Abstract: //
// Sends a NetBT name Query to the IP address provided as input param //
// Arguments: //
// ipAddrStr - IP address where the Name Query is to be sent //
// Return value: //
// TRUE - test passed //
// FALSE - test failed //
// Global variables used: //
// none //
//-------------------------------------------------------------------------//
BOOL IsNameResponse( NETDIAG_PARAMS *pParams, char* ipAddrStr ) {
DWORD optionValue; // helper var for setsockopt()
SOCKADDR_IN sockAddr; // struct holding source socket info
SOCKET listenNameSvcSock;
DWORD listeningThreadId; int iTimeout; int nBytesRcvd = 0; char MsgBuf[1500]; SOCKADDR_IN senderSockAddr; int nSockAddrSize = sizeof( senderSockAddr );
BOOL fRet = TRUE;
//
// create socket to listen to name svc responses from the WINS server
//
listenNameSvcSock = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP ); if ( listenNameSvcSock == INVALID_SOCKET ) { if (pParams->fReallyVerbose) //IDS_WINS_12406 " Failed to create a socket to listen to WINS traffic. Error = %d \n"
PrintMessage(pParams, IDS_WINS_12406, WSAGetLastError() ); return FALSE; }
optionValue = TRUE; if ( setsockopt(listenNameSvcSock, SOL_SOCKET, SO_REUSEADDR, (const char *)&optionValue, sizeof(optionValue)) ) { if (pParams->fReallyVerbose) //IDS_WINS_12407 " Failed to set the SO_REUSEADDR option for the socket. Error = %d\n"
PrintMessage(pParams, IDS_WINS_12407, WSAGetLastError() ); return FALSE; }
optionValue = FALSE; if ( setsockopt(listenNameSvcSock, SOL_SOCKET, SO_BROADCAST, (const char *)&optionValue, sizeof(optionValue)) ) { if (pParams->fReallyVerbose) //IDS_WINS_12408 " Failed to set the SO_BROADCAST option for the socket. Error = %d\n"
PrintMessage(pParams, IDS_WINS_12408, WSAGetLastError() ); return FALSE; }
iTimeout = c_iWaitTime; if ( setsockopt(listenNameSvcSock, SOL_SOCKET, SO_RCVTIMEO, (char*)&iTimeout, sizeof(iTimeout))) { if (pParams->fReallyVerbose) //IDS_WINS_12416 " Failed to set the SO_RCVTIMEO option for the socket. Error = %d\n"
PrintMessage(pParams, IDS_WINS_12416, WSAGetLastError());
return FALSE; }
sockAddr.sin_family = PF_INET; sockAddr.sin_addr.s_addr = INADDR_ANY; sockAddr.sin_port = 0; RtlZeroMemory( sockAddr.sin_zero, 8 );
if ( bind(listenNameSvcSock, (LPSOCKADDR )&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR ) { if (pParams->fReallyVerbose) //IDS_WINS_12409 "\n Failed to bind the listening socket for the socket. Error = %d\n"
PrintMessage(pParams, IDS_WINS_12409, WSAGetLastError() ); return FALSE; }
//
// let's ask the WINS server for our own name
//
Probe( pParams, ipAddrStr, listenNameSvcSock );
nBytesRcvd = recvfrom( listenNameSvcSock, MsgBuf, sizeof(MsgBuf), 0, (LPSOCKADDR )&senderSockAddr, &nSockAddrSize ); if ( nBytesRcvd == SOCKET_ERROR ) { //since we are sending UDP packets, it's not reliable. Do the query again
Probe (pParams, ipAddrStr, listenNameSvcSock); if (SOCKET_ERROR == recvfrom( listenNameSvcSock, MsgBuf, sizeof(MsgBuf), 0, (LPSOCKADDR )&senderSockAddr, &nSockAddrSize )) { fRet = FALSE; } }
//
// final clean up
//
closesocket(listenNameSvcSock); return fRet; } /* END OF IsNameResponse() */
void WinsGlobalPrint(IN NETDIAG_PARAMS *pParams, IN OUT NETDIAG_RESULT *pResults) { }
void WinsPerInterfacePrint(IN NETDIAG_PARAMS *pParams, IN OUT NETDIAG_RESULT *pResults, IN INTERFACE_RESULT *pIfResult) { // PIP_ADAPTER_INFO pIpAdapter = pIfResult->IpConfig.pAdapterInfo;
// IP_ADDR_STRING winsSrv;
if (!pIfResult->IpConfig.fActive || NETCARD_DISCONNECTED == pIfResult->dwNetCardStatus) return;
if (pParams->fVerbose || !FHrOK(pIfResult->Wins.hr)) { PrintNewLine(pParams, 1); PrintTestTitleResult(pParams, IDS_WINS_LONG, IDS_WINS_SHORT, pIfResult->Wins.fPerformed, pIfResult->Wins.hr, 8); }
PrintMessageList(pParams, &pIfResult->Wins.lmsgPrimary);
PrintMessageList(pParams, &pIfResult->Wins.lmsgSecondary);
if (pIfResult->Wins.fPerformed) { if (pIfResult->Wins.hr == hrOK) { if (pParams->fReallyVerbose) // IDS_WINS_12413 " The test was successful, at least one WINS server was found.\n"
PrintMessage(pParams, IDS_WINS_12413); } else { // IDS_WINS_12414 " The test failed. We were unable to query the WINS servers.\n"
PrintMessage(pParams, IDS_WINS_12414); } } else if (pParams->fVerbose) { if (!pIfResult->fNbtEnabled) { //IDS_WINS_NBT_DISABLED " NetBT is disable on this interface. [Test skipped].\n"
PrintMessage(pParams, IDS_WINS_NBT_DISABLED); } else { //IDS_WINS_12415 " There are no WINS servers configured for this interface.\n"
PrintMessage(pParams, IDS_WINS_12415); } } }
void WinsCleanup(IN NETDIAG_PARAMS *pParams, IN OUT NETDIAG_RESULT *pResults) { int i; for(i = 0; i < pResults->cNumInterfaces; i++) { MessageListCleanUp(&pResults->pArrayInterface[i].Wins.lmsgPrimary); MessageListCleanUp(&pResults->pArrayInterface[i].Wins.lmsgSecondary); } }
|