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.

552 lines
13 KiB

  1. //++
  2. //
  3. // Copyright (C) Microsoft Corporation, 1987 - 1999
  4. //
  5. // Module Name:
  6. //
  7. // ipxtest.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 "ipxtest.h"
  27. static HANDLE s_isnipxfd = INVALID_HANDLE;
  28. static wchar_t isnipxname[] = L"\\Device\\NwlnkIpx";
  29. void IPXprint_config(NETDIAG_PARAMS *pParams,
  30. NETDIAG_RESULT *pResults
  31. );
  32. int do_isnipxioctl(
  33. IN HANDLE fd,
  34. IN int cmd,
  35. OUT char *datap,
  36. IN int dlen
  37. );
  38. HRESULT LoadIpxInterfaceInfo(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults);
  39. void get_emsg(NETDIAG_PARAMS *pParams, int rc);
  40. HRESULT InitIpxConfig(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults)
  41. {
  42. UNICODE_STRING FileString;
  43. OBJECT_ATTRIBUTES ObjectAttributes;
  44. IO_STATUS_BLOCK IoStatusBlock;
  45. NTSTATUS Status;
  46. HRESULT hr = hrOK;
  47. PrintStatusMessage(pParams,0, IDS_IPX_STATUS_MSG);
  48. /** Open the isnipx driver **/
  49. RtlInitUnicodeString (&FileString, isnipxname);
  50. InitializeObjectAttributes(
  51. &ObjectAttributes,
  52. &FileString,
  53. OBJ_CASE_INSENSITIVE,
  54. NULL,
  55. NULL);
  56. Status = NtOpenFile(
  57. &pResults->Ipx.hIsnIpxFd,
  58. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  59. &ObjectAttributes,
  60. &IoStatusBlock,
  61. FILE_SHARE_READ | FILE_SHARE_WRITE,
  62. FILE_SYNCHRONOUS_IO_ALERT);
  63. pResults->Ipx.fInstalled = TRUE;
  64. pResults->Ipx.fEnabled = TRUE;
  65. if (!NT_SUCCESS(Status))
  66. {
  67. pResults->Ipx.hIsnIpxFd = INVALID_HANDLE;
  68. // IDS_IPX_15603 "Opening \\Device\\NwlnkIpx failed\n"
  69. PrintDebug(pParams, 4, IDS_IPX_15603);
  70. pResults->Ipx.fInstalled = FALSE;
  71. pResults->Ipx.fEnabled = FALSE;
  72. // IPX is not installed, do not return the error code
  73. // but return S_FALSE.
  74. return S_FALSE;
  75. }
  76. // Fill in the IPX adapter interface data
  77. hr = LoadIpxInterfaceInfo(pParams, pResults);
  78. return hr;
  79. }
  80. IPX_TEST_FRAME* PutIpxFrame(
  81. // returns 0-3
  82. ULONG uFrameType,
  83. // returns virtual net if NicId = 0
  84. ULONG uNetworkNumber,
  85. // adapter's MAC address
  86. const UCHAR* pNode,
  87. LIST_ENTRY* pListHead // if its NULL, then the new created will be head
  88. )
  89. {
  90. IPX_TEST_FRAME* pFrame = NULL;
  91. if(pListHead == NULL) return NULL;
  92. pFrame = (IPX_TEST_FRAME*)malloc(sizeof(IPX_TEST_FRAME));
  93. if(pFrame == NULL) return NULL;
  94. if( pListHead->Flink == NULL && pListHead->Blink == NULL) // the head is not initilized
  95. InitializeListHead(pListHead);
  96. pFrame->uFrameType = uFrameType;
  97. pFrame->uNetworkNumber = uNetworkNumber;
  98. memcpy(&pFrame->Node[0], pNode, sizeof(pFrame->Node));
  99. InsertTailList(pListHead, &(pFrame->list_entry));
  100. return pFrame;
  101. }
  102. HRESULT LoadIpxInterfaceInfo(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults)
  103. {
  104. int rc;
  105. USHORT nicid, nicidcount;
  106. ISN_ACTION_GET_DETAILS getdetails;
  107. HANDLE hMpr = NULL;
  108. DWORD dwErr;
  109. PVOID pv;
  110. HRESULT hr = hrOK;
  111. int i, iIpx;
  112. INTERFACE_RESULT * pIfResults;
  113. LPTSTR pszAdapterName = NULL;
  114. unsigned char node[6] = {0, 0,0,0,0,1};
  115. // Initialize the map from guid to interface name
  116. CheckErr( MprConfigServerConnect(NULL, &hMpr) );
  117. assert(hMpr != INVALID_HANDLE);
  118. /** First query nicid 0 **/
  119. getdetails.NicId = 0;
  120. rc = do_isnipxioctl(pResults->Ipx.hIsnIpxFd, MIPX_CONFIG, (char *)&getdetails, sizeof(getdetails));
  121. if (rc)
  122. {
  123. // IDS_IPX_15604 "Error querying config nwlnkipx :"
  124. PrintDebug(pParams, 0, IDS_IPX_15604);
  125. if (pParams->fDebugVerbose)
  126. {
  127. get_emsg(pParams, rc);
  128. }
  129. goto Error;
  130. }
  131. //
  132. // The NicId 0 query returns the total number.
  133. //
  134. nicidcount = getdetails.NicId;
  135. // We should have an open spot for the IPX internal interface
  136. // ----------------------------------------------------------------
  137. assert(pResults->cNumInterfacesAllocated > pResults->cNumInterfaces);
  138. // Set the first IPX interface as the IPX internal
  139. iIpx = pResults->cNumInterfaces;
  140. // Add the internal interface
  141. pIfResults = pResults->pArrayInterface + iIpx;
  142. pIfResults->fActive = TRUE;
  143. pIfResults->Ipx.fActive = TRUE;
  144. pIfResults->pszName = StrDup(_T("Internal"));
  145. pIfResults->pszFriendlyName = LoadAndAllocString(IDS_IPX_INTERNAL);
  146. pIfResults->Ipx.uNicId = 0;
  147. pIfResults->Ipx.fBindingSet = 0;
  148. pIfResults->Ipx.uType = 0;
  149. // multiple frame types
  150. PutIpxFrame(0, REORDER_ULONG(getdetails.NetworkNumber), node, &(pIfResults->Ipx.list_entry_Frames));
  151. iIpx++; // move on to the next new interface structure
  152. pResults->cNumInterfaces++;
  153. InitializeListHead(&pResults->Dns.lmsgOutput);
  154. for (nicid = 1; nicid <= nicidcount; nicid++)
  155. {
  156. // get the next structure
  157. getdetails.NicId = nicid;
  158. rc = do_isnipxioctl(pResults->Ipx.hIsnIpxFd, MIPX_CONFIG, (char *)&getdetails, sizeof(getdetails)
  159. );
  160. if (rc)
  161. {
  162. continue;
  163. }
  164. // convert the adapter name into ASCII
  165. pszAdapterName = StrDupTFromW(getdetails.AdapterName);
  166. // see if this interface is already in the list
  167. pIfResults = NULL;
  168. for ( i=0; i<pResults->cNumInterfaces; i++)
  169. {
  170. if (lstrcmpi(pResults->pArrayInterface[i].pszName,
  171. pszAdapterName) == 0)
  172. {
  173. pIfResults = pResults->pArrayInterface + i;
  174. break;
  175. }
  176. }
  177. // if we didn't find a match, use one of the newly allocated
  178. // interfaces
  179. if (pIfResults == NULL)
  180. {
  181. // We need a new interface result structure, grab one
  182. // (if it is free), else allocate more.
  183. if (pResults->cNumInterfaces >= pResults->cNumInterfacesAllocated)
  184. {
  185. // Need to do a realloc to get more memory
  186. pv = Realloc(pResults->pArrayInterface,
  187. sizeof(INTERFACE_RESULT)*(pResults->cNumInterfacesAllocated+8));
  188. if (pv == NULL)
  189. CheckHr( E_OUTOFMEMORY );
  190. pResults->pArrayInterface = pv;
  191. // Zero out the new section of memory
  192. ZeroMemory(pResults->pArrayInterface + pResults->cNumInterfacesAllocated,
  193. sizeof(INTERFACE_RESULT)*8);
  194. pResults->cNumInterfacesAllocated += 8;
  195. }
  196. pIfResults = pResults->pArrayInterface + iIpx;
  197. iIpx++;
  198. pResults->cNumInterfaces++;
  199. pIfResults->pszName = _tcsdup(pszAdapterName);
  200. }
  201. free(pszAdapterName);
  202. pszAdapterName = NULL;
  203. // Enable IPX on this interface
  204. pIfResults->fActive = TRUE;
  205. pIfResults->Ipx.fActive = TRUE;
  206. pIfResults->Ipx.uNicId = nicid;
  207. // support multiple frame types
  208. PutIpxFrame(getdetails.FrameType, REORDER_ULONG(getdetails.NetworkNumber), &(getdetails.Node[0]), &(pIfResults->Ipx.list_entry_Frames));
  209. // Translate the adapter name (if needed)
  210. if (!pIfResults->pszFriendlyName)
  211. {
  212. if (getdetails.Type == IPX_TYPE_LAN)
  213. {
  214. WCHAR swzName[512];
  215. PWCHAR pszGuid = &(getdetails.AdapterName[0]);
  216. dwErr = MprConfigGetFriendlyName(hMpr,
  217. pszGuid,
  218. swzName,
  219. sizeof(swzName));
  220. if (dwErr == NO_ERROR)
  221. pIfResults->pszFriendlyName = StrDupTFromW(swzName);
  222. else
  223. pIfResults->pszFriendlyName =
  224. StrDupTFromW(getdetails.AdapterName);
  225. }
  226. else
  227. pIfResults->pszFriendlyName =
  228. StrDupTFromW(getdetails.AdapterName);
  229. }
  230. pIfResults->Ipx.fBindingSet = getdetails.BindingSet;
  231. }
  232. Error:
  233. /** Close up and exit **/
  234. // Cleanup interface map
  235. if (hMpr)
  236. MprConfigServerDisconnect(hMpr);
  237. return hr;
  238. }
  239. HRESULT
  240. IpxTest(NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults)
  241. {
  242. return hrOK;
  243. }
  244. int do_isnipxioctl(
  245. IN HANDLE fd,
  246. IN int cmd,
  247. OUT char *datap,
  248. IN int dlen)
  249. {
  250. NTSTATUS Status;
  251. UCHAR buffer[sizeof(NWLINK_ACTION) + sizeof(ISN_ACTION_GET_DETAILS) - 1];
  252. PNWLINK_ACTION action;
  253. IO_STATUS_BLOCK IoStatusBlock;
  254. int rc;
  255. /** Fill out the structure **/
  256. action = (PNWLINK_ACTION)buffer;
  257. action->Header.TransportId = ISN_ACTION_TRANSPORT_ID;
  258. action->OptionType = NWLINK_OPTION_CONTROL;
  259. action->BufferLength = sizeof(ULONG) + dlen;
  260. action->Option = cmd;
  261. RtlMoveMemory(action->Data, datap, dlen);
  262. /** Issue the ioctl **/
  263. Status = NtDeviceIoControlFile(
  264. fd,
  265. NULL,
  266. NULL,
  267. NULL,
  268. &IoStatusBlock,
  269. IOCTL_TDI_ACTION,
  270. NULL,
  271. 0,
  272. action,
  273. FIELD_OFFSET(NWLINK_ACTION,Data) + dlen);
  274. if (Status != STATUS_SUCCESS) {
  275. if (Status == STATUS_INVALID_PARAMETER) {
  276. rc = ERANGE;
  277. } else {
  278. rc = EINVAL;
  279. }
  280. } else {
  281. if (dlen > 0) {
  282. RtlMoveMemory (datap, action->Data, dlen);
  283. }
  284. rc = 0;
  285. }
  286. return rc;
  287. }
  288. void get_emsg(NETDIAG_PARAMS *pParams, int rc)
  289. {
  290. /**
  291. We have 3 defined error codes that can come back.
  292. 1 - EINVAL means that we sent down parameters wrong
  293. (SHOULD NEVER HAPPEN)
  294. 2 - ERANGE means that the board number is invalid
  295. (CAN HAPPEN IF USER ENTERS BAD BOARD)
  296. 3 - ENOENT means that on remove - the address given
  297. is not in the source routing table.
  298. **/
  299. switch (rc) {
  300. case EINVAL:
  301. // IDS_IPX_15605 "we sent down parameters wrong\n"
  302. PrintMessage(pParams, IDS_IPX_15605);
  303. break;
  304. case ERANGE:
  305. // IDS_IPX_15606 "board number is invalid\n"
  306. PrintMessage(pParams, IDS_IPX_15606);
  307. break;
  308. case ENOENT:
  309. // IDS_IPX_15607 "remove - the address given is not in the source routing table\n"
  310. PrintMessage(pParams, IDS_IPX_15607);
  311. break;
  312. default:
  313. // IDS_IPX_15608 "Unknown Error\n"
  314. PrintMessage(pParams, IDS_IPX_15608);
  315. break;
  316. }
  317. return;
  318. }
  319. /*!--------------------------------------------------------------------------
  320. IpxGlobalPrint
  321. -
  322. Author: KennT
  323. ---------------------------------------------------------------------------*/
  324. void IpxGlobalPrint( NETDIAG_PARAMS* pParams,
  325. NETDIAG_RESULT* pResults)
  326. {
  327. if (!pResults->Ipx.fInstalled)
  328. return;
  329. #if 0
  330. if (pParams->fVerbose)
  331. {
  332. PrintNewLine(pParams, 2);
  333. PrintTestTitleResult(pParams, IDS_IPX_LONG, IDS_IPX_SHORT, TRUE, pResults->Ipx.hr, 0);
  334. }
  335. #endif
  336. }
  337. /*!--------------------------------------------------------------------------
  338. IpxPerInterfacePrint
  339. -
  340. Author: KennT
  341. ---------------------------------------------------------------------------*/
  342. void IpxPerInterfacePrint( NETDIAG_PARAMS* pParams,
  343. NETDIAG_RESULT* pResults,
  344. INTERFACE_RESULT *pInterfaceResults)
  345. {
  346. int ids;
  347. LPTSTR pszFrameType = NULL;
  348. LIST_ENTRY* pEntry = NULL;
  349. IPX_TEST_FRAME* pFrameEntry = NULL;
  350. // no per-interface results
  351. if (!pResults->Ipx.fInstalled)
  352. {
  353. if (pParams->fReallyVerbose)
  354. // IDS_IPX_15609 " IPX test : IPX is not installed on this machine.\n"
  355. PrintMessage(pParams, IDS_IPX_15609);
  356. return;
  357. }
  358. if (!pInterfaceResults->Ipx.fActive)
  359. return;
  360. // IDS_IPX_15610 "\n Ipx configration\n"
  361. PrintMessage(pParams, IDS_IPX_15610);
  362. // support multiple frame types
  363. // loop all the frame in the list_entry
  364. pEntry = pInterfaceResults->Ipx.list_entry_Frames.Flink;
  365. for ( pEntry = pInterfaceResults->Ipx.list_entry_Frames.Flink ;
  366. pEntry != &pInterfaceResults->Ipx.list_entry_Frames ;
  367. pEntry = pEntry->Flink )
  368. {
  369. pFrameEntry = CONTAINING_RECORD(pEntry, IPX_TEST_FRAME, list_entry);
  370. ASSERT(pFrameEntry);
  371. // network number
  372. // IDS_IPX_15611 " Network Number : %.8x\n"
  373. PrintMessage(pParams, IDS_IPX_15611,
  374. pFrameEntry->uNetworkNumber);
  375. // node
  376. // IDS_IPX_15612 " Node : %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n"
  377. PrintMessage(pParams, IDS_IPX_15612,
  378. pFrameEntry->Node[0],
  379. pFrameEntry->Node[1],
  380. pFrameEntry->Node[2],
  381. pFrameEntry->Node[3],
  382. pFrameEntry->Node[4],
  383. pFrameEntry->Node[5]);
  384. // frame type
  385. switch (pFrameEntry->uFrameType)
  386. {
  387. case 0 : ids = IDS_IPX_ETHERNET_II; break;
  388. case 1 : ids = IDS_IPX_802_3; break;
  389. case 2 : ids = IDS_IPX_802_2; break;
  390. case 3 : ids = IDS_IPX_SNAP; break;
  391. case 4 : ids = IDS_IPX_ARCNET; break;
  392. default:
  393. ids = IDS_IPX_UNKNOWN; break;
  394. }
  395. pszFrameType = LoadAndAllocString(ids);
  396. // IDS_IPX_15613 " Frame type : %s\n"
  397. PrintMessage(pParams, IDS_IPX_15613, pszFrameType);
  398. Free(pszFrameType);
  399. PrintNewLine(pParams, 1);
  400. }
  401. // type
  402. PrintNewLine(pParams, 1);
  403. }
  404. /*!--------------------------------------------------------------------------
  405. IpxCleanup
  406. -
  407. Author: KennT
  408. ---------------------------------------------------------------------------*/
  409. void IpxCleanup( NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults)
  410. {
  411. int i;
  412. LIST_ENTRY* pEntry = NULL;
  413. IPX_TEST_FRAME* pFrameEntry = NULL;
  414. INTERFACE_RESULT* pIfResults = NULL;
  415. if (pResults->Ipx.hIsnIpxFd != INVALID_HANDLE)
  416. NtClose(pResults->Ipx.hIsnIpxFd);
  417. pResults->Ipx.hIsnIpxFd = INVALID_HANDLE;
  418. // per interface stuff -- loop through
  419. for ( i = 0; i < pResults->cNumInterfacesAllocated; i++)
  420. {
  421. pIfResults = pResults->pArrayInterface + i;
  422. if(pIfResults->Ipx.list_entry_Frames.Flink) // there is data need to be cleaned up
  423. {
  424. while (!IsListEmpty(&(pIfResults->Ipx.list_entry_Frames)))
  425. {
  426. pEntry = RemoveHeadList(&(pIfResults->Ipx.list_entry_Frames));
  427. // find data pointer
  428. pFrameEntry = CONTAINING_RECORD(pEntry, IPX_TEST_FRAME, list_entry);
  429. free(pFrameEntry);
  430. }
  431. }
  432. }
  433. }