553 lines
13 KiB
C
553 lines
13 KiB
C
|
//++
|
||
|
//
|
||
|
// 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);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|