Source code of Windows XP (NT5)
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.

518 lines
19 KiB

  1. //++
  2. //
  3. // Copyright (C) Microsoft Corporation, 1987 - 1999
  4. //
  5. // Module Name:
  6. //
  7. // winstest.c
  8. //
  9. // Abstract:
  10. //
  11. // Queries into network drivers
  12. //
  13. // Author:
  14. //
  15. // Anilth - 4-20-1998
  16. //
  17. // Environment:
  18. //
  19. // User mode only.
  20. // Contains NT-specific code.
  21. //
  22. // Revision History:
  23. //
  24. //--
  25. #include "precomp.h"
  26. #include "dhcptest.h"
  27. static const TCHAR s_szSpace12[] = _T(" ");
  28. const int c_iWaitTime = 2000;
  29. BOOL IsNameResponse( NETDIAG_PARAMS * pParams, char* ipAddrStr );
  30. int Probe( NETDIAG_PARAMS *pParams, TCHAR *szSrvIpAddr, SOCKET listenNameSvcSock );
  31. //-------------------------------------------------------------------------//
  32. //###### W I N S T e s t () #############################################//
  33. //-------------------------------------------------------------------------//
  34. // Abstract: //
  35. // Queries the all the configured WINS servers to make sure that //
  36. // they are reachable and that they have the proper name-IP mapping //
  37. // for this workstation. //
  38. // Arguments: //
  39. // none //
  40. // Return value: //
  41. // TRUE - test passed //
  42. // FALSE - test failed //
  43. // Global variables used: //
  44. // none //
  45. //-------------------------------------------------------------------------//
  46. HRESULT WinsTest( NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults)
  47. {
  48. IPCONFIG_TST * pIpConfig;
  49. WINS_TST * pWinsResult;
  50. PIP_ADAPTER_INFO pIpAdapter;
  51. IP_ADDR_STRING winsSrv;
  52. int nWinsSrvOk = 0;
  53. HRESULT hr = hrOK;
  54. int i;
  55. TCHAR szBuffer[256];
  56. // IDS_WINS_STATUS_MSG " Testing the WINS server... \n"
  57. PrintStatusMessage(pParams, 4, IDS_WINS_STATUS_MSG);
  58. //
  59. // try to send name queries to the WINS servers on all adapters
  60. //
  61. for ( i = 0; i < pResults->cNumInterfaces; i++ )
  62. {
  63. UINT nIfWinsOk = 0;
  64. pIpConfig = &pResults->pArrayInterface[i].IpConfig;
  65. pIpAdapter = pResults->pArrayInterface[i].IpConfig.pAdapterInfo;
  66. InitializeListHead( &pResults->pArrayInterface[i].Wins.lmsgPrimary );
  67. InitializeListHead( &pResults->pArrayInterface[i].Wins.lmsgSecondary );
  68. if (!pIpConfig->fActive ||
  69. NETCARD_DISCONNECTED == pResults->pArrayInterface[i].dwNetCardStatus)
  70. continue;
  71. if (!pResults->pArrayInterface[i].fNbtEnabled)
  72. continue;
  73. PrintStatusMessage(pParams, 8, IDSSZ_GLOBAL_StringLine, pResults->pArrayInterface[i].pszFriendlyName);
  74. pWinsResult = &pResults->pArrayInterface[i].Wins;
  75. //
  76. // looping through the primary WINS server list
  77. //
  78. winsSrv = pIpAdapter->PrimaryWinsServer;
  79. if ( ZERO_IP_ADDRESS(winsSrv.IpAddress.String) )
  80. {
  81. if(pParams->fReallyVerbose)
  82. PrintMessage(pParams, IDS_WINS_QUERY_NO_PRIMARY,
  83. s_szSpace12);
  84. AddMessageToList(&pWinsResult->lmsgPrimary,
  85. Nd_ReallyVerbose, IDS_WINS_QUERY_NO_PRIMARY,
  86. s_szSpace12);
  87. }
  88. else
  89. {
  90. pWinsResult->fPerformed = TRUE;
  91. while ( TRUE )
  92. {
  93. if (pParams->fReallyVerbose)
  94. PrintMessage(pParams, IDS_WINS_QUERY_PRIMARY,
  95. s_szSpace12,
  96. winsSrv.IpAddress.String);
  97. AddMessageToList(&pWinsResult->lmsgPrimary,
  98. Nd_ReallyVerbose,
  99. IDS_WINS_QUERY_PRIMARY,
  100. s_szSpace12,
  101. winsSrv.IpAddress.String);
  102. if ( IsNameResponse(pParams, winsSrv.IpAddress.String) )
  103. {
  104. if (pParams->fReallyVerbose)
  105. PrintMessage(pParams, IDS_GLOBAL_PASS_NL);
  106. AddMessageToList(&pWinsResult->lmsgPrimary,
  107. Nd_ReallyVerbose,
  108. IDS_GLOBAL_PASS_NL);
  109. nWinsSrvOk++;
  110. nIfWinsOk++;
  111. }
  112. else
  113. {
  114. if (pParams->fReallyVerbose)
  115. PrintMessage(pParams, IDS_GLOBAL_FAIL_NL);
  116. AddMessageToList(&pWinsResult->lmsgPrimary,
  117. Nd_ReallyVerbose,
  118. IDS_GLOBAL_FAIL_NL);
  119. }
  120. if ( winsSrv.Next == NULL )
  121. {
  122. break;
  123. }
  124. winsSrv = *(winsSrv.Next);
  125. }
  126. }
  127. //
  128. // looping through the secondary WINS server list
  129. //
  130. winsSrv = pIpAdapter->SecondaryWinsServer;
  131. if ( ZERO_IP_ADDRESS(winsSrv.IpAddress.String) )
  132. {
  133. if(pParams->fReallyVerbose)
  134. PrintMessage(pParams, IDS_WINS_QUERY_NO_SECONDARY,
  135. s_szSpace12);
  136. AddMessageToList(&pWinsResult->lmsgSecondary,
  137. Nd_ReallyVerbose, IDS_WINS_QUERY_NO_SECONDARY,
  138. s_szSpace12);
  139. }
  140. else
  141. {
  142. pWinsResult->fPerformed = TRUE;
  143. while ( TRUE )
  144. {
  145. if (pParams->fReallyVerbose)
  146. PrintMessage(pParams, IDS_WINS_QUERY_SECONDARY,
  147. s_szSpace12,
  148. winsSrv.IpAddress.String);
  149. AddMessageToList(&pWinsResult->lmsgSecondary,
  150. Nd_ReallyVerbose,
  151. IDS_WINS_QUERY_SECONDARY,
  152. s_szSpace12,
  153. winsSrv.IpAddress.String);
  154. if ( IsNameResponse(pParams, winsSrv.IpAddress.String) )
  155. {
  156. if (pParams->fReallyVerbose)
  157. PrintMessage(pParams, IDS_GLOBAL_PASS_NL);
  158. AddMessageToList(&pWinsResult->lmsgSecondary,
  159. Nd_ReallyVerbose,
  160. IDS_GLOBAL_PASS_NL);
  161. nWinsSrvOk++;
  162. nIfWinsOk++;
  163. }
  164. else
  165. {
  166. if (pParams->fReallyVerbose)
  167. PrintMessage(pParams, IDS_GLOBAL_FAIL_NL);
  168. AddMessageToList(&pWinsResult->lmsgSecondary,
  169. Nd_ReallyVerbose,
  170. IDS_GLOBAL_FAIL_NL);
  171. }
  172. if ( winsSrv.Next == NULL ) { break; }
  173. winsSrv = *(winsSrv.Next);
  174. }
  175. }
  176. if( 0 == nIfWinsOk )
  177. pWinsResult->hr = S_FALSE;
  178. else
  179. pWinsResult->hr = S_OK;
  180. } /* end of for loop scanning all the adapters */
  181. //$REVIEW No global test result for WINS test
  182. if ( nWinsSrvOk != 0)
  183. {
  184. hr = S_OK;
  185. }
  186. else
  187. {
  188. hr = S_FALSE;
  189. }
  190. return hr;
  191. } /* END OF WINSTest() */
  192. //-------------------------------------------------------------------------//
  193. //###### P r o b e () ##################################################//
  194. //-------------------------------------------------------------------------//
  195. // Abstract: //
  196. // Assembles and sends a name query to the DHCP server. //
  197. // Arguments: //
  198. // none //
  199. // Return value: //
  200. // TRUE if a response has been received from the server //
  201. // FALSE otherwise //
  202. // Global variables used: //
  203. // g_isDebug (reading only) //
  204. // //
  205. // Comments: //
  206. // This will not work for b-type nodes for which you need to set the B bit//
  207. // and broadcast the packet instead of unicast xmission - Rajkumar //
  208. //-------------------------------------------------------------------------//
  209. int Probe( NETDIAG_PARAMS *pParams, TCHAR *szSrvIpAddr, SOCKET listenNameSvcSock ) {
  210. char nbtFrameBuf[MAX_NBT_PACKET_SIZE];
  211. NM_FRAME_HDR *pNbtHeader = (NM_FRAME_HDR *)nbtFrameBuf;
  212. NM_QUESTION_SECT *pNbtQuestion = (NM_QUESTION_SECT *)( nbtFrameBuf + sizeof(NM_FRAME_HDR) );
  213. struct sockaddr_in destSockAddr;
  214. char *pDest, *pName;
  215. int nBytesSent = 0, i;
  216. /* RFC 1002 section 4.2.12
  217. 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
  218. 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
  219. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  220. | NAME_TRN_ID |0| 0x0 |0|0|1|0|0 0|B| 0x0 |
  221. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  222. | 0x0001 | 0x0000 |
  223. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  224. | 0x0000 | 0x0000 |
  225. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  226. | |
  227. / QUESTION_NAME /
  228. / /
  229. | |
  230. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  231. | NB (0x0020) | IN (0x0001) |
  232. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  233. */
  234. pNbtHeader->xid = NM_QRY_XID;
  235. pNbtHeader->flags = NBT_NM_OPC_QUERY |
  236. NBT_NM_OPC_REQUEST |
  237. NBT_NM_FLG_RECURS_DESRD;
  238. pNbtHeader->question_cnt = 0x0100;
  239. pNbtHeader->answer_cnt = 0;
  240. pNbtHeader->name_serv_cnt = 0;
  241. pNbtHeader->additional_cnt = 0;
  242. // pDest is filling nbtQuestion->q_name
  243. pNbtQuestion->q_type = NBT_NM_QTYP_NB;
  244. pNbtQuestion->q_class = NBT_NM_QCLASS_IN;
  245. //
  246. // translate the name
  247. //
  248. pDest = (char *)&(pNbtQuestion->q_name);
  249. pName = nameToQry;
  250. // the first byte of the name is the length field = 2*16
  251. *pDest++ = NBT_NAME_SIZE;
  252. // step through name converting ascii to half ascii, for 32 times
  253. for ( i = 0; i < (NBT_NAME_SIZE / 2) ; i++ ) {
  254. *pDest++ = (*pName >> 4) + 'A';
  255. *pDest++ = (*pName++ & 0x0F) + 'A';
  256. }
  257. *pDest++ = '\0';
  258. *pDest = '\0';
  259. //
  260. // send the name query frame
  261. //
  262. destSockAddr.sin_family = PF_INET;
  263. destSockAddr.sin_port = htons(137); // NBT_NAME_SERVICE_PORT;
  264. destSockAddr.sin_addr.s_addr = inet_addr( szSrvIpAddr );
  265. for ( i = 0; i < 8 ; i++ ) { destSockAddr.sin_zero[i] = 0; }
  266. nBytesSent = sendto( listenNameSvcSock,
  267. (PCHAR )nbtFrameBuf,
  268. sizeof(NM_FRAME_HDR) + sizeof(NM_QUESTION_SECT),
  269. 0,
  270. (struct sockaddr *)&destSockAddr,
  271. sizeof( struct sockaddr )
  272. );
  273. PrintDebugSz(pParams, 0, _T("\n querying name %s on server %s\n"), nameToQry, szSrvIpAddr );
  274. PrintDebugSz(pParams, 0, _T( " bytes sent %d\n"), nBytesSent );
  275. if ( nBytesSent == SOCKET_ERROR )
  276. {
  277. PrintDebugSz(pParams, 0, _T(" Error %d in sendto()!\n"), WSAGetLastError() );
  278. return FALSE;
  279. }
  280. //
  281. // the other thread should see the incoming frame and increment m_nMsgCnt
  282. //
  283. return TRUE;
  284. } /* END OF Probe() */
  285. //-------------------------------------------------------------------------//
  286. //###### I s N a m e R e s p o n s e () #################################//
  287. //-------------------------------------------------------------------------//
  288. // Abstract: //
  289. // Sends a NetBT name Query to the IP address provided as input param //
  290. // Arguments: //
  291. // ipAddrStr - IP address where the Name Query is to be sent //
  292. // Return value: //
  293. // TRUE - test passed //
  294. // FALSE - test failed //
  295. // Global variables used: //
  296. // none //
  297. //-------------------------------------------------------------------------//
  298. BOOL IsNameResponse( NETDIAG_PARAMS *pParams, char* ipAddrStr ) {
  299. DWORD optionValue; // helper var for setsockopt()
  300. SOCKADDR_IN sockAddr; // struct holding source socket info
  301. SOCKET listenNameSvcSock;
  302. DWORD listeningThreadId;
  303. int iTimeout;
  304. int nBytesRcvd = 0;
  305. char MsgBuf[1500];
  306. SOCKADDR_IN senderSockAddr;
  307. int nSockAddrSize = sizeof( senderSockAddr );
  308. BOOL fRet = TRUE;
  309. //
  310. // create socket to listen to name svc responses from the WINS server
  311. //
  312. listenNameSvcSock = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
  313. if ( listenNameSvcSock == INVALID_SOCKET ) {
  314. if (pParams->fReallyVerbose)
  315. //IDS_WINS_12406 " Failed to create a socket to listen to WINS traffic. Error = %d \n"
  316. PrintMessage(pParams, IDS_WINS_12406, WSAGetLastError() );
  317. return FALSE;
  318. }
  319. optionValue = TRUE;
  320. if ( setsockopt(listenNameSvcSock, SOL_SOCKET, SO_REUSEADDR, (const char *)&optionValue, sizeof(optionValue)) ) {
  321. if (pParams->fReallyVerbose)
  322. //IDS_WINS_12407 " Failed to set the SO_REUSEADDR option for the socket. Error = %d\n"
  323. PrintMessage(pParams, IDS_WINS_12407, WSAGetLastError() );
  324. return FALSE;
  325. }
  326. optionValue = FALSE;
  327. if ( setsockopt(listenNameSvcSock, SOL_SOCKET, SO_BROADCAST, (const char *)&optionValue, sizeof(optionValue)) ) {
  328. if (pParams->fReallyVerbose)
  329. //IDS_WINS_12408 " Failed to set the SO_BROADCAST option for the socket. Error = %d\n"
  330. PrintMessage(pParams, IDS_WINS_12408, WSAGetLastError() );
  331. return FALSE;
  332. }
  333. iTimeout = c_iWaitTime;
  334. if ( setsockopt(listenNameSvcSock, SOL_SOCKET, SO_RCVTIMEO, (char*)&iTimeout, sizeof(iTimeout)))
  335. {
  336. if (pParams->fReallyVerbose)
  337. //IDS_WINS_12416 " Failed to set the SO_RCVTIMEO option for the socket. Error = %d\n"
  338. PrintMessage(pParams, IDS_WINS_12416, WSAGetLastError());
  339. return FALSE;
  340. }
  341. sockAddr.sin_family = PF_INET;
  342. sockAddr.sin_addr.s_addr = INADDR_ANY;
  343. sockAddr.sin_port = 0;
  344. RtlZeroMemory( sockAddr.sin_zero, 8 );
  345. if ( bind(listenNameSvcSock, (LPSOCKADDR )&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR ) {
  346. if (pParams->fReallyVerbose)
  347. //IDS_WINS_12409 "\n Failed to bind the listening socket for the socket. Error = %d\n"
  348. PrintMessage(pParams, IDS_WINS_12409, WSAGetLastError() );
  349. return FALSE;
  350. }
  351. //
  352. // let's ask the WINS server for our own name
  353. //
  354. Probe( pParams, ipAddrStr, listenNameSvcSock );
  355. nBytesRcvd = recvfrom( listenNameSvcSock, MsgBuf, sizeof(MsgBuf), 0, (LPSOCKADDR )&senderSockAddr, &nSockAddrSize );
  356. if ( nBytesRcvd == SOCKET_ERROR )
  357. {
  358. //since we are sending UDP packets, it's not reliable. Do the query again
  359. Probe (pParams, ipAddrStr, listenNameSvcSock);
  360. if (SOCKET_ERROR == recvfrom( listenNameSvcSock, MsgBuf,
  361. sizeof(MsgBuf),
  362. 0,
  363. (LPSOCKADDR )&senderSockAddr,
  364. &nSockAddrSize ))
  365. {
  366. fRet = FALSE;
  367. }
  368. }
  369. //
  370. // final clean up
  371. //
  372. closesocket(listenNameSvcSock);
  373. return fRet;
  374. } /* END OF IsNameResponse() */
  375. void WinsGlobalPrint(IN NETDIAG_PARAMS *pParams,
  376. IN OUT NETDIAG_RESULT *pResults)
  377. {
  378. }
  379. void WinsPerInterfacePrint(IN NETDIAG_PARAMS *pParams,
  380. IN OUT NETDIAG_RESULT *pResults,
  381. IN INTERFACE_RESULT *pIfResult)
  382. {
  383. // PIP_ADAPTER_INFO pIpAdapter = pIfResult->IpConfig.pAdapterInfo;
  384. // IP_ADDR_STRING winsSrv;
  385. if (!pIfResult->IpConfig.fActive ||
  386. NETCARD_DISCONNECTED == pIfResult->dwNetCardStatus)
  387. return;
  388. if (pParams->fVerbose || !FHrOK(pIfResult->Wins.hr))
  389. {
  390. PrintNewLine(pParams, 1);
  391. PrintTestTitleResult(pParams, IDS_WINS_LONG, IDS_WINS_SHORT, pIfResult->Wins.fPerformed,
  392. pIfResult->Wins.hr, 8);
  393. }
  394. PrintMessageList(pParams, &pIfResult->Wins.lmsgPrimary);
  395. PrintMessageList(pParams, &pIfResult->Wins.lmsgSecondary);
  396. if (pIfResult->Wins.fPerformed)
  397. {
  398. if (pIfResult->Wins.hr == hrOK)
  399. {
  400. if (pParams->fReallyVerbose)
  401. // IDS_WINS_12413 " The test was successful, at least one WINS server was found.\n"
  402. PrintMessage(pParams, IDS_WINS_12413);
  403. }
  404. else
  405. {
  406. // IDS_WINS_12414 " The test failed. We were unable to query the WINS servers.\n"
  407. PrintMessage(pParams, IDS_WINS_12414);
  408. }
  409. }
  410. else if (pParams->fVerbose)
  411. {
  412. if (!pIfResult->fNbtEnabled)
  413. {
  414. //IDS_WINS_NBT_DISABLED " NetBT is disable on this interface. [Test skipped].\n"
  415. PrintMessage(pParams, IDS_WINS_NBT_DISABLED);
  416. }
  417. else
  418. {
  419. //IDS_WINS_12415 " There are no WINS servers configured for this interface.\n"
  420. PrintMessage(pParams, IDS_WINS_12415);
  421. }
  422. }
  423. }
  424. void WinsCleanup(IN NETDIAG_PARAMS *pParams,
  425. IN OUT NETDIAG_RESULT *pResults)
  426. {
  427. int i;
  428. for(i = 0; i < pResults->cNumInterfaces; i++)
  429. {
  430. MessageListCleanUp(&pResults->pArrayInterface[i].Wins.lmsgPrimary);
  431. MessageListCleanUp(&pResults->pArrayInterface[i].Wins.lmsgSecondary);
  432. }
  433. }