windows-nt/Source/XPSP1/NT/net/diagnostics/netdiag/ipxtest.c

553 lines
13 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
//++
//
// Copyright (C) Microsoft Corporation, 1987 - 1999
//
// Module Name:
//
// ipxtest.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 "ipxtest.h"
static HANDLE s_isnipxfd = INVALID_HANDLE;
static wchar_t isnipxname[] = L"\\Device\\NwlnkIpx";
void IPXprint_config(NETDIAG_PARAMS *pParams,
NETDIAG_RESULT *pResults
);
int do_isnipxioctl(
IN HANDLE fd,
IN int cmd,
OUT char *datap,
IN int dlen
);
HRESULT LoadIpxInterfaceInfo(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults);
void get_emsg(NETDIAG_PARAMS *pParams, int rc);
HRESULT InitIpxConfig(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults)
{
UNICODE_STRING FileString;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status;
HRESULT hr = hrOK;
PrintStatusMessage(pParams,0, IDS_IPX_STATUS_MSG);
/** Open the isnipx driver **/
RtlInitUnicodeString (&FileString, isnipxname);
InitializeObjectAttributes(
&ObjectAttributes,
&FileString,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenFile(
&pResults->Ipx.hIsnIpxFd,
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_ALERT);
pResults->Ipx.fInstalled = TRUE;
pResults->Ipx.fEnabled = TRUE;
if (!NT_SUCCESS(Status))
{
pResults->Ipx.hIsnIpxFd = INVALID_HANDLE;
// IDS_IPX_15603 "Opening \\Device\\NwlnkIpx failed\n"
PrintDebug(pParams, 4, IDS_IPX_15603);
pResults->Ipx.fInstalled = FALSE;
pResults->Ipx.fEnabled = FALSE;
// IPX is not installed, do not return the error code
// but return S_FALSE.
return S_FALSE;
}
// Fill in the IPX adapter interface data
hr = LoadIpxInterfaceInfo(pParams, pResults);
return hr;
}
IPX_TEST_FRAME* PutIpxFrame(
// returns 0-3
ULONG uFrameType,
// returns virtual net if NicId = 0
ULONG uNetworkNumber,
// adapter's MAC address
const UCHAR* pNode,
LIST_ENTRY* pListHead // if its NULL, then the new created will be head
)
{
IPX_TEST_FRAME* pFrame = NULL;
if(pListHead == NULL) return NULL;
pFrame = (IPX_TEST_FRAME*)malloc(sizeof(IPX_TEST_FRAME));
if(pFrame == NULL) return NULL;
if( pListHead->Flink == NULL && pListHead->Blink == NULL) // the head is not initilized
InitializeListHead(pListHead);
pFrame->uFrameType = uFrameType;
pFrame->uNetworkNumber = uNetworkNumber;
memcpy(&pFrame->Node[0], pNode, sizeof(pFrame->Node));
InsertTailList(pListHead, &(pFrame->list_entry));
return pFrame;
}
HRESULT LoadIpxInterfaceInfo(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults)
{
int rc;
USHORT nicid, nicidcount;
ISN_ACTION_GET_DETAILS getdetails;
HANDLE hMpr = NULL;
DWORD dwErr;
PVOID pv;
HRESULT hr = hrOK;
int i, iIpx;
INTERFACE_RESULT * pIfResults;
LPTSTR pszAdapterName = NULL;
unsigned char node[6] = {0, 0,0,0,0,1};
// Initialize the map from guid to interface name
CheckErr( MprConfigServerConnect(NULL, &hMpr) );
assert(hMpr != INVALID_HANDLE);
/** First query nicid 0 **/
getdetails.NicId = 0;
rc = do_isnipxioctl(pResults->Ipx.hIsnIpxFd, MIPX_CONFIG, (char *)&getdetails, sizeof(getdetails));
if (rc)
{
// IDS_IPX_15604 "Error querying config nwlnkipx :"
PrintDebug(pParams, 0, IDS_IPX_15604);
if (pParams->fDebugVerbose)
{
get_emsg(pParams, rc);
}
goto Error;
}
//
// The NicId 0 query returns the total number.
//
nicidcount = getdetails.NicId;
// We should have an open spot for the IPX internal interface
// ----------------------------------------------------------------
assert(pResults->cNumInterfacesAllocated > pResults->cNumInterfaces);
// Set the first IPX interface as the IPX internal
iIpx = pResults->cNumInterfaces;
// Add the internal interface
pIfResults = pResults->pArrayInterface + iIpx;
pIfResults->fActive = TRUE;
pIfResults->Ipx.fActive = TRUE;
pIfResults->pszName = StrDup(_T("Internal"));
pIfResults->pszFriendlyName = LoadAndAllocString(IDS_IPX_INTERNAL);
pIfResults->Ipx.uNicId = 0;
pIfResults->Ipx.fBindingSet = 0;
pIfResults->Ipx.uType = 0;
// multiple frame types
PutIpxFrame(0, REORDER_ULONG(getdetails.NetworkNumber), node, &(pIfResults->Ipx.list_entry_Frames));
iIpx++; // move on to the next new interface structure
pResults->cNumInterfaces++;
InitializeListHead(&pResults->Dns.lmsgOutput);
for (nicid = 1; nicid <= nicidcount; nicid++)
{
// get the next structure
getdetails.NicId = nicid;
rc = do_isnipxioctl(pResults->Ipx.hIsnIpxFd, MIPX_CONFIG, (char *)&getdetails, sizeof(getdetails)
);
if (rc)
{
continue;
}
// convert the adapter name into ASCII
pszAdapterName = StrDupTFromW(getdetails.AdapterName);
// see if this interface is already in the list
pIfResults = NULL;
for ( i=0; i<pResults->cNumInterfaces; i++)
{
if (lstrcmpi(pResults->pArrayInterface[i].pszName,
pszAdapterName) == 0)
{
pIfResults = pResults->pArrayInterface + i;
break;
}
}
// if we didn't find a match, use one of the newly allocated
// interfaces
if (pIfResults == NULL)
{
// We need a new interface result structure, grab one
// (if it is free), else allocate more.
if (pResults->cNumInterfaces >= pResults->cNumInterfacesAllocated)
{
// Need to do a realloc to get more memory
pv = Realloc(pResults->pArrayInterface,
sizeof(INTERFACE_RESULT)*(pResults->cNumInterfacesAllocated+8));
if (pv == NULL)
CheckHr( E_OUTOFMEMORY );
pResults->pArrayInterface = pv;
// Zero out the new section of memory
ZeroMemory(pResults->pArrayInterface + pResults->cNumInterfacesAllocated,
sizeof(INTERFACE_RESULT)*8);
pResults->cNumInterfacesAllocated += 8;
}
pIfResults = pResults->pArrayInterface + iIpx;
iIpx++;
pResults->cNumInterfaces++;
pIfResults->pszName = _tcsdup(pszAdapterName);
}
free(pszAdapterName);
pszAdapterName = NULL;
// Enable IPX on this interface
pIfResults->fActive = TRUE;
pIfResults->Ipx.fActive = TRUE;
pIfResults->Ipx.uNicId = nicid;
// support multiple frame types
PutIpxFrame(getdetails.FrameType, REORDER_ULONG(getdetails.NetworkNumber), &(getdetails.Node[0]), &(pIfResults->Ipx.list_entry_Frames));
// Translate the adapter name (if needed)
if (!pIfResults->pszFriendlyName)
{
if (getdetails.Type == IPX_TYPE_LAN)
{
WCHAR swzName[512];
PWCHAR pszGuid = &(getdetails.AdapterName[0]);
dwErr = MprConfigGetFriendlyName(hMpr,
pszGuid,
swzName,
sizeof(swzName));
if (dwErr == NO_ERROR)
pIfResults->pszFriendlyName = StrDupTFromW(swzName);
else
pIfResults->pszFriendlyName =
StrDupTFromW(getdetails.AdapterName);
}
else
pIfResults->pszFriendlyName =
StrDupTFromW(getdetails.AdapterName);
}
pIfResults->Ipx.fBindingSet = getdetails.BindingSet;
}
Error:
/** Close up and exit **/
// Cleanup interface map
if (hMpr)
MprConfigServerDisconnect(hMpr);
return hr;
}
HRESULT
IpxTest(NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults)
{
return hrOK;
}
int do_isnipxioctl(
IN HANDLE fd,
IN int cmd,
OUT char *datap,
IN int dlen)
{
NTSTATUS Status;
UCHAR buffer[sizeof(NWLINK_ACTION) + sizeof(ISN_ACTION_GET_DETAILS) - 1];
PNWLINK_ACTION action;
IO_STATUS_BLOCK IoStatusBlock;
int rc;
/** Fill out the structure **/
action = (PNWLINK_ACTION)buffer;
action->Header.TransportId = ISN_ACTION_TRANSPORT_ID;
action->OptionType = NWLINK_OPTION_CONTROL;
action->BufferLength = sizeof(ULONG) + dlen;
action->Option = cmd;
RtlMoveMemory(action->Data, datap, dlen);
/** Issue the ioctl **/
Status = NtDeviceIoControlFile(
fd,
NULL,
NULL,
NULL,
&IoStatusBlock,
IOCTL_TDI_ACTION,
NULL,
0,
action,
FIELD_OFFSET(NWLINK_ACTION,Data) + dlen);
if (Status != STATUS_SUCCESS) {
if (Status == STATUS_INVALID_PARAMETER) {
rc = ERANGE;
} else {
rc = EINVAL;
}
} else {
if (dlen > 0) {
RtlMoveMemory (datap, action->Data, dlen);
}
rc = 0;
}
return rc;
}
void get_emsg(NETDIAG_PARAMS *pParams, int rc)
{
/**
We have 3 defined error codes that can come back.
1 - EINVAL means that we sent down parameters wrong
(SHOULD NEVER HAPPEN)
2 - ERANGE means that the board number is invalid
(CAN HAPPEN IF USER ENTERS BAD BOARD)
3 - ENOENT means that on remove - the address given
is not in the source routing table.
**/
switch (rc) {
case EINVAL:
// IDS_IPX_15605 "we sent down parameters wrong\n"
PrintMessage(pParams, IDS_IPX_15605);
break;
case ERANGE:
// IDS_IPX_15606 "board number is invalid\n"
PrintMessage(pParams, IDS_IPX_15606);
break;
case ENOENT:
// IDS_IPX_15607 "remove - the address given is not in the source routing table\n"
PrintMessage(pParams, IDS_IPX_15607);
break;
default:
// IDS_IPX_15608 "Unknown Error\n"
PrintMessage(pParams, IDS_IPX_15608);
break;
}
return;
}
/*!--------------------------------------------------------------------------
IpxGlobalPrint
-
Author: KennT
---------------------------------------------------------------------------*/
void IpxGlobalPrint( NETDIAG_PARAMS* pParams,
NETDIAG_RESULT* pResults)
{
if (!pResults->Ipx.fInstalled)
return;
#if 0
if (pParams->fVerbose)
{
PrintNewLine(pParams, 2);
PrintTestTitleResult(pParams, IDS_IPX_LONG, IDS_IPX_SHORT, TRUE, pResults->Ipx.hr, 0);
}
#endif
}
/*!--------------------------------------------------------------------------
IpxPerInterfacePrint
-
Author: KennT
---------------------------------------------------------------------------*/
void IpxPerInterfacePrint( NETDIAG_PARAMS* pParams,
NETDIAG_RESULT* pResults,
INTERFACE_RESULT *pInterfaceResults)
{
int ids;
LPTSTR pszFrameType = NULL;
LIST_ENTRY* pEntry = NULL;
IPX_TEST_FRAME* pFrameEntry = NULL;
// no per-interface results
if (!pResults->Ipx.fInstalled)
{
if (pParams->fReallyVerbose)
// IDS_IPX_15609 " IPX test : IPX is not installed on this machine.\n"
PrintMessage(pParams, IDS_IPX_15609);
return;
}
if (!pInterfaceResults->Ipx.fActive)
return;
// IDS_IPX_15610 "\n Ipx configration\n"
PrintMessage(pParams, IDS_IPX_15610);
// support multiple frame types
// loop all the frame in the list_entry
pEntry = pInterfaceResults->Ipx.list_entry_Frames.Flink;
for ( pEntry = pInterfaceResults->Ipx.list_entry_Frames.Flink ;
pEntry != &pInterfaceResults->Ipx.list_entry_Frames ;
pEntry = pEntry->Flink )
{
pFrameEntry = CONTAINING_RECORD(pEntry, IPX_TEST_FRAME, list_entry);
ASSERT(pFrameEntry);
// network number
// IDS_IPX_15611 " Network Number : %.8x\n"
PrintMessage(pParams, IDS_IPX_15611,
pFrameEntry->uNetworkNumber);
// node
// IDS_IPX_15612 " Node : %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n"
PrintMessage(pParams, IDS_IPX_15612,
pFrameEntry->Node[0],
pFrameEntry->Node[1],
pFrameEntry->Node[2],
pFrameEntry->Node[3],
pFrameEntry->Node[4],
pFrameEntry->Node[5]);
// frame type
switch (pFrameEntry->uFrameType)
{
case 0 : ids = IDS_IPX_ETHERNET_II; break;
case 1 : ids = IDS_IPX_802_3; break;
case 2 : ids = IDS_IPX_802_2; break;
case 3 : ids = IDS_IPX_SNAP; break;
case 4 : ids = IDS_IPX_ARCNET; break;
default:
ids = IDS_IPX_UNKNOWN; break;
}
pszFrameType = LoadAndAllocString(ids);
// IDS_IPX_15613 " Frame type : %s\n"
PrintMessage(pParams, IDS_IPX_15613, pszFrameType);
Free(pszFrameType);
PrintNewLine(pParams, 1);
}
// type
PrintNewLine(pParams, 1);
}
/*!--------------------------------------------------------------------------
IpxCleanup
-
Author: KennT
---------------------------------------------------------------------------*/
void IpxCleanup( NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults)
{
int i;
LIST_ENTRY* pEntry = NULL;
IPX_TEST_FRAME* pFrameEntry = NULL;
INTERFACE_RESULT* pIfResults = NULL;
if (pResults->Ipx.hIsnIpxFd != INVALID_HANDLE)
NtClose(pResults->Ipx.hIsnIpxFd);
pResults->Ipx.hIsnIpxFd = INVALID_HANDLE;
// per interface stuff -- loop through
for ( i = 0; i < pResults->cNumInterfacesAllocated; i++)
{
pIfResults = pResults->pArrayInterface + i;
if(pIfResults->Ipx.list_entry_Frames.Flink) // there is data need to be cleaned up
{
while (!IsListEmpty(&(pIfResults->Ipx.list_entry_Frames)))
{
pEntry = RemoveHeadList(&(pIfResults->Ipx.list_entry_Frames));
// find data pointer
pFrameEntry = CONTAINING_RECORD(pEntry, IPX_TEST_FRAME, list_entry);
free(pFrameEntry);
}
}
}
}