1525 lines
41 KiB
C
1525 lines
41 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1996 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
ioctl.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Handler routines for Internal IOCTLs, including IOCTL_ARP1394_REQUEST.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Who When What
|
||
|
-------- -------- ----------------------------------------------
|
||
|
josephj 11-20-97 Created
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include <precomp.h>
|
||
|
// #include "ioctl.h"
|
||
|
|
||
|
//
|
||
|
// File-specific debugging defaults.
|
||
|
//
|
||
|
#define TM_CURRENT TM_NT
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
arpDoClientCommand(
|
||
|
PARP1394_IOCTL_COMMAND pCmd,
|
||
|
UINT BufLen
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
arpDoEthernetCommand(
|
||
|
PARP1394_IOCTL_COMMAND pCmd,
|
||
|
UINT BufLen
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlGetArpCache(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_GET_ARPCACHE pGetCacheCmd,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlAddArpEntry(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_ADD_ARP_ENTRY pAddArpEntryCmd,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlDelArpEntry(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_DEL_ARP_ENTRY pDelArpEntryCmd,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlPurgeArpCache(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_PURGE_ARPCACHE pPurgeCmd,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlGetPacketStats(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_GET_PACKET_STATS pStatsCmd,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlGetTaskStats(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_GET_TASK_STATS pStatsCmd,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
);
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlGetArpStats(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_GET_ARPCACHE_STATS pStatsCmd,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlGetCallStats(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_GET_CALL_STATS pStatsCmd,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlResetStats(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_RESET_STATS pResetStatsCmd,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlReinitIf(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_REINIT_INTERFACE pReinitCmd,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
);
|
||
|
|
||
|
PARP1394_INTERFACE
|
||
|
arpGetIfByIp(
|
||
|
IN OUT IP_ADDRESS *pLocalIpAddress, // OPTIONAL
|
||
|
PRM_STACK_RECORD pSR
|
||
|
);
|
||
|
|
||
|
UINT
|
||
|
arpGetStatsDuration(
|
||
|
PARP1394_INTERFACE pIF
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlSendPacket(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_SEND_PACKET pSendPacket,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlRecvPacket(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_RECV_PACKET pRecvPacket,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlGetNicInfo(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_NICINFO pIoctlNicInfo,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlGetEuidNodeMacInfo(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_EUID_NODE_MAC_INFO pEuidInfo,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
);
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
ArpHandleIoctlRequest(
|
||
|
IN PIRP pIrp,
|
||
|
IN PIO_STACK_LOCATION pIrpSp
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Private IOCTL interface to the ARP1394 administration utility.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
|
||
|
PUCHAR pBuf;
|
||
|
UINT BufLen;
|
||
|
ULONG Code;
|
||
|
|
||
|
ENTER("Ioctl", 0x4e96d522)
|
||
|
|
||
|
pIrp->IoStatus.Information = 0;
|
||
|
pBuf = pIrp->AssociatedIrp.SystemBuffer;
|
||
|
BufLen = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
|
||
|
Code = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
|
||
|
|
||
|
TR_WARN(("Code = 0x%p\n", Code));
|
||
|
|
||
|
if (Code == ARP_IOCTL_CLIENT_OPERATION && pBuf != NULL)
|
||
|
{
|
||
|
PARP1394_IOCTL_COMMAND pCmd;
|
||
|
pCmd = (PARP1394_IOCTL_COMMAND) pBuf;
|
||
|
|
||
|
if ( (pCmd->Hdr.Op >= ARP1394_IOCTL_OP_ETHERNET_FIRST)
|
||
|
&& (pCmd->Hdr.Op <= ARP1394_IOCTL_OP_ETHERNET_LAST))
|
||
|
{
|
||
|
// This is an ethernet-emulation related ioctl request (from
|
||
|
// NIC1394.SYS). We handle these differently.
|
||
|
//
|
||
|
NtStatus = arpDoEthernetCommand(pCmd, BufLen);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
NtStatus = arpDoClientCommand(pCmd, BufLen);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// All commands return stuff in pCmd itself...
|
||
|
//
|
||
|
if (NtStatus == STATUS_SUCCESS)
|
||
|
{
|
||
|
pIrp->IoStatus.Information = BufLen;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TR_WARN(("Unrecognized code.\n"));
|
||
|
}
|
||
|
|
||
|
EXIT()
|
||
|
return NtStatus;
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
arpDoClientCommand(
|
||
|
PARP1394_IOCTL_COMMAND pCmd,
|
||
|
UINT BufLen
|
||
|
)
|
||
|
{
|
||
|
ENTER("arpDoClientCommand", 0xd7985f1b)
|
||
|
NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
|
||
|
PARP1394_INTERFACE pIF;
|
||
|
RM_DECLARE_STACK_RECORD(sr)
|
||
|
|
||
|
do
|
||
|
{
|
||
|
IP_ADDRESS IpAddress;
|
||
|
|
||
|
pIF = NULL;
|
||
|
|
||
|
if (pCmd == NULL)
|
||
|
{
|
||
|
TR_WARN(("Invalid buffer %p\n", pCmd));
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
if (BufLen<sizeof(pCmd->Hdr))
|
||
|
{
|
||
|
TR_WARN(("Buffer too small (%lu)\n", BufLen));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (pCmd->Hdr.Version != ARP1394_IOCTL_VERSION)
|
||
|
{
|
||
|
TR_WARN(("Incorrect version 0x%08lx\n", pCmd->Hdr.Version));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
IpAddress = (IP_ADDRESS) pCmd->Hdr.IfIpAddress;
|
||
|
|
||
|
// IpAddress could be all-zeros, in which case we'll get the first IF,
|
||
|
// and IpAddress will be set to one of the local IP addresses of this IF.
|
||
|
// NOTE: pIF is tmpref'd.
|
||
|
//
|
||
|
pIF = arpGetIfByIp(&IpAddress, &sr);
|
||
|
|
||
|
if (pIF == NULL)
|
||
|
{
|
||
|
TR_WARN(("Couldn't find IF with IP 0x%0x8lx\n", IpAddress));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
pCmd->Hdr.IfIpAddress = IpAddress;
|
||
|
|
||
|
switch(pCmd->Hdr.Op)
|
||
|
{
|
||
|
case ARP1394_IOCTL_OP_GET_ARPCACHE:
|
||
|
{
|
||
|
PARP1394_IOCTL_GET_ARPCACHE pGetArpCache = &pCmd->GetArpCache;
|
||
|
if (BufLen >= sizeof(*pGetArpCache))
|
||
|
{
|
||
|
//
|
||
|
// Check if there is enough space for all the arp entries.
|
||
|
//
|
||
|
ULONG EntrySpace;
|
||
|
EntrySpace = BufLen - FIELD_OFFSET(
|
||
|
ARP1394_IOCTL_GET_ARPCACHE,
|
||
|
Entries
|
||
|
);
|
||
|
if ((EntrySpace/sizeof(pGetArpCache->Entries[0])) >
|
||
|
pGetArpCache->NumEntriesAvailable)
|
||
|
{
|
||
|
//
|
||
|
// Yes, there is enough space.
|
||
|
//
|
||
|
NtStatus = arpIoctlGetArpCache(pIF, pGetArpCache, &sr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ARP1394_IOCTL_OP_ADD_STATIC_ENTRY:
|
||
|
{
|
||
|
PARP1394_IOCTL_ADD_ARP_ENTRY pAddCmd = &pCmd->AddArpEntry;
|
||
|
if (BufLen >= sizeof(*pAddCmd))
|
||
|
{
|
||
|
NtStatus = arpIoctlAddArpEntry(pIF, pAddCmd, &sr);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ARP1394_IOCTL_OP_DEL_STATIC_ENTRY:
|
||
|
{
|
||
|
PARP1394_IOCTL_DEL_ARP_ENTRY pDelCmd = &pCmd->DelArpEntry;
|
||
|
if (BufLen >= sizeof(*pDelCmd))
|
||
|
{
|
||
|
NtStatus = arpIoctlDelArpEntry(pIF, pDelCmd, &sr);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ARP1394_IOCTL_OP_PURGE_ARPCACHE:
|
||
|
{
|
||
|
PARP1394_IOCTL_PURGE_ARPCACHE pPurge = &pCmd->PurgeArpCache;
|
||
|
if (BufLen >= sizeof(*pPurge))
|
||
|
{
|
||
|
NtStatus = arpIoctlPurgeArpCache(pIF, pPurge, &sr);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ARP1394_IOCTL_OP_GET_PACKET_STATS:
|
||
|
{
|
||
|
PARP1394_IOCTL_GET_PACKET_STATS pStats = &pCmd->GetPktStats;
|
||
|
if (BufLen >= sizeof(*pStats))
|
||
|
{
|
||
|
NtStatus = arpIoctlGetPacketStats(pIF, pStats, &sr);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ARP1394_IOCTL_OP_GET_TASK_STATS:
|
||
|
{
|
||
|
PARP1394_IOCTL_GET_TASK_STATS pStats = &pCmd->GetTaskStats;
|
||
|
if (BufLen >= sizeof(*pStats))
|
||
|
{
|
||
|
NtStatus = arpIoctlGetTaskStats(pIF, pStats, &sr);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ARP1394_IOCTL_OP_GET_ARPCACHE_STATS:
|
||
|
{
|
||
|
PARP1394_IOCTL_GET_ARPCACHE_STATS pStats = &pCmd->GetArpStats;
|
||
|
if (BufLen >= sizeof(*pStats))
|
||
|
{
|
||
|
NtStatus = arpIoctlGetArpStats(pIF, pStats, &sr);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ARP1394_IOCTL_OP_GET_CALL_STATS:
|
||
|
{
|
||
|
PARP1394_IOCTL_GET_CALL_STATS pStats = &pCmd->GetCallStats;
|
||
|
if (BufLen >= sizeof(*pStats))
|
||
|
{
|
||
|
NtStatus = arpIoctlGetCallStats(pIF, pStats, &sr);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ARP1394_IOCTL_OP_RESET_STATS:
|
||
|
{
|
||
|
PARP1394_IOCTL_RESET_STATS pResetStats = &pCmd->ResetStats;
|
||
|
if (BufLen >= sizeof(*pResetStats))
|
||
|
{
|
||
|
NtStatus = arpIoctlResetStats(pIF, pResetStats, &sr);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ARP1394_IOCTL_OP_REINIT_INTERFACE:
|
||
|
{
|
||
|
PARP1394_IOCTL_REINIT_INTERFACE pReinitIf = &pCmd->ReinitInterface;
|
||
|
if (BufLen >= sizeof(*pReinitIf))
|
||
|
{
|
||
|
NtStatus = arpIoctlReinitIf(pIF, pReinitIf, &sr);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ARP1394_IOCTL_OP_SEND_PACKET:
|
||
|
{
|
||
|
ARP1394_IOCTL_SEND_PACKET *pSendPacket = &pCmd->SendPacket;
|
||
|
if (BufLen >= sizeof(*pSendPacket))
|
||
|
{
|
||
|
NtStatus = arpIoctlSendPacket(pIF, pSendPacket, &sr);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ARP1394_IOCTL_OP_RECV_PACKET:
|
||
|
{
|
||
|
ARP1394_IOCTL_RECV_PACKET *pRecvPacket = &pCmd->RecvPacket;
|
||
|
if (BufLen >= sizeof(*pRecvPacket))
|
||
|
{
|
||
|
NtStatus = arpIoctlRecvPacket(pIF, pRecvPacket, &sr);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ARP1394_IOCTL_OP_GET_NICINFO:
|
||
|
{
|
||
|
ARP1394_IOCTL_NICINFO *pIoctlNicInfo = &pCmd->IoctlNicInfo;
|
||
|
if (BufLen >= sizeof(*pIoctlNicInfo))
|
||
|
{
|
||
|
NtStatus = arpIoctlGetNicInfo(pIF, pIoctlNicInfo, &sr);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case ARP1394_IOCTL_OP_GET_EUID_NODE_MAC_TABLE:
|
||
|
{
|
||
|
PARP1394_IOCTL_EUID_NODE_MAC_INFO pIoctlEuidInfo = &pCmd->EuidNodeMacInfo;
|
||
|
if (BufLen >= sizeof(*pIoctlEuidInfo))
|
||
|
{
|
||
|
NtStatus = arpIoctlGetEuidNodeMacInfo(pIF, pIoctlEuidInfo, &sr);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
TR_WARN(("Unknown op %lu\n", pCmd->Hdr.Op));
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
} while (FALSE);
|
||
|
|
||
|
if (NtStatus != STATUS_SUCCESS)
|
||
|
{
|
||
|
TR_WARN(("Command unsuccessful. NtStatus = 0x%lx\n", NtStatus));
|
||
|
}
|
||
|
|
||
|
if (pIF != NULL)
|
||
|
{
|
||
|
RmTmpDereferenceObject(&pIF->Hdr, &sr);
|
||
|
}
|
||
|
|
||
|
RM_ASSERT_CLEAR(&sr);
|
||
|
EXIT()
|
||
|
|
||
|
return NtStatus;
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
arpDoEthernetCommand(
|
||
|
PARP1394_IOCTL_COMMAND pCmd,
|
||
|
UINT BufLen
|
||
|
)
|
||
|
{
|
||
|
ENTER("arpDoEthernetCommand", 0xa723f233)
|
||
|
PARP1394_IOCTL_ETHERNET_NOTIFICATION pNotif;
|
||
|
PARP1394_ADAPTER pAdapter = NULL;
|
||
|
RM_DECLARE_STACK_RECORD(sr)
|
||
|
|
||
|
pNotif = (PARP1394_IOCTL_ETHERNET_NOTIFICATION) pCmd;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
|
||
|
NDIS_STRING DeviceName;
|
||
|
|
||
|
if (BufLen<sizeof(*pNotif))
|
||
|
{
|
||
|
TR_WARN(("Buffer too small (%lu)\n", BufLen));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (pNotif->Hdr.Version != ARP1394_IOCTL_VERSION)
|
||
|
{
|
||
|
TR_WARN(("Incorrect version 0x%08lx\n", pCmd->Hdr.Version));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
NdisInitUnicodeString(&DeviceName, pNotif->AdapterName);
|
||
|
|
||
|
if (pNotif->Hdr.Op == ARP1394_IOCTL_OP_ETHERNET_START_EMULATION)
|
||
|
{
|
||
|
//
|
||
|
// ArpNdBindAdapter will try to create the adapter in "Bridge
|
||
|
// mode" if it passed in a NULL bind context.
|
||
|
// It will of course fail if the adapter exists.
|
||
|
//
|
||
|
ArpNdBindAdapter(
|
||
|
&NdisStatus,
|
||
|
NULL, // BindContext
|
||
|
&DeviceName, // pDeviceName
|
||
|
NULL, // SystemSpecific1
|
||
|
NULL // SystemSpecific2
|
||
|
);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// The remaining operations concern an existing adapter which has been
|
||
|
// created in "bridge" mode. Let's look up this adapter based on it's
|
||
|
// name.
|
||
|
//
|
||
|
|
||
|
NdisStatus = RmLookupObjectInGroup(
|
||
|
&ArpGlobals.adapters.Group,
|
||
|
0, // Flags
|
||
|
(PVOID) &DeviceName, // pKey
|
||
|
NULL, // pvCreateParams
|
||
|
&(PRM_OBJECT_HEADER) pAdapter, // pObj
|
||
|
NULL, // pfCreated
|
||
|
&sr
|
||
|
);
|
||
|
if (FAIL(NdisStatus))
|
||
|
{
|
||
|
TR_WARN(("Couldn't find adapter object\n"));
|
||
|
pAdapter = NULL;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (!ARP_BRIDGE_ENABLED(pAdapter))
|
||
|
{
|
||
|
TR_WARN((
|
||
|
"Ignoring Ethernet Emulation Ioctl Op 0x%x"
|
||
|
" because adapter 0x%p is not in bridge mode.\n",
|
||
|
pNotif->Hdr.Op,
|
||
|
pAdapter));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// OK -- we've found the adapter and the adapter is in bridged mode.
|
||
|
// Let's look at the specific command.
|
||
|
//
|
||
|
|
||
|
switch(pNotif->Hdr.Op)
|
||
|
{
|
||
|
|
||
|
case ARP1394_IOCTL_OP_ETHERNET_STOP_EMULATION:
|
||
|
{
|
||
|
// Calling ArpNdUnbindAdapter with NULL UnbindContext prevents
|
||
|
// it from trying to call NdisCompleteUnbindAdapter.
|
||
|
//
|
||
|
ArpNdUnbindAdapter(
|
||
|
&NdisStatus,
|
||
|
(NDIS_HANDLE) pAdapter,
|
||
|
NULL // UnbindContext
|
||
|
);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ARP1394_IOCTL_OP_ETHERNET_ADD_MULTICAST_ADDRESS:
|
||
|
{
|
||
|
// TODO: unimplemented.
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ARP1394_IOCTL_OP_ETHERNET_DEL_MULTICAST_ADDRESS:
|
||
|
{
|
||
|
// TODO: unimplemented.
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ARP1394_IOCTL_OP_ETHERNET_ENABLE_PROMISCUOUS_MODE:
|
||
|
{
|
||
|
// TODO: unimplemented.
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ARP1394_IOCTL_OP_ETHERNET_DISABLE_PROMISCUOUS_MODE:
|
||
|
{
|
||
|
// TODO: unimplemented.
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
TR_WARN(("Unknown op %lu\n", pCmd->Hdr.Op));
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
if (pAdapter != NULL)
|
||
|
{
|
||
|
RmTmpDereferenceObject(&pAdapter->Hdr, &sr);
|
||
|
}
|
||
|
|
||
|
RM_ASSERT_CLEAR(&sr);
|
||
|
EXIT()
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlGetArpCache(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_GET_ARPCACHE pGetCacheCmd,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
)
|
||
|
{
|
||
|
ENTER("GetArpCache", 0xa64453c7)
|
||
|
NTSTATUS NtStatus;
|
||
|
TR_WARN(("GET ARP CACHE\n"));
|
||
|
|
||
|
pGetCacheCmd->NumEntriesUsed = 0;
|
||
|
NtStatus = STATUS_UNSUCCESSFUL;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
PARP1394_ADAPTER pAdapter;
|
||
|
PARP1394_ARP_ENTRY pEntry;
|
||
|
ARPCB_REMOTE_IP * pRemoteIp;
|
||
|
NDIS_STATUS Status;
|
||
|
UINT EntriesAvailable;
|
||
|
UINT EntriesUsed;
|
||
|
UINT CurIndex;
|
||
|
UINT Index;
|
||
|
|
||
|
|
||
|
LOCKOBJ(pIF, pSR);
|
||
|
|
||
|
pAdapter = (ARP1394_ADAPTER*) RM_PARENT_OBJECT(pIF);
|
||
|
pGetCacheCmd->NumEntriesInArpCache = pIF->RemoteIpGroup.HashTable.NumItems;
|
||
|
pGetCacheCmd->LocalHwAddress.UniqueID= pAdapter->info.LocalUniqueID;
|
||
|
pGetCacheCmd->LocalHwAddress.Off_Low = pIF->recvinfo.offset.Off_Low;
|
||
|
pGetCacheCmd->LocalHwAddress.Off_High= pIF->recvinfo.offset.Off_High;
|
||
|
|
||
|
//
|
||
|
// Pick up pGetCacheCmd->NumEntriesAvailable arp entries starting
|
||
|
// from the (pGetCacheCmd->Index)'th one.
|
||
|
//
|
||
|
|
||
|
pRemoteIp = NULL;
|
||
|
EntriesAvailable = pGetCacheCmd->NumEntriesAvailable;
|
||
|
EntriesUsed = 0;
|
||
|
Index = pGetCacheCmd->Index;
|
||
|
pEntry = pGetCacheCmd->Entries;
|
||
|
CurIndex = 0;
|
||
|
|
||
|
// Get the 1st entry...
|
||
|
//
|
||
|
Status = RmGetNextObjectInGroup(
|
||
|
&pIF->RemoteIpGroup,
|
||
|
NULL,
|
||
|
&(PRM_OBJECT_HEADER)pRemoteIp,
|
||
|
pSR
|
||
|
);
|
||
|
if (FAIL(Status))
|
||
|
{
|
||
|
// Presumably there are no entries.
|
||
|
pRemoteIp = NULL;
|
||
|
}
|
||
|
|
||
|
while (pRemoteIp != NULL)
|
||
|
{
|
||
|
ARPCB_REMOTE_IP * pNextRemoteIp = NULL;
|
||
|
|
||
|
if (EntriesUsed >= EntriesAvailable)
|
||
|
{
|
||
|
//
|
||
|
// out of space; Update the context, and set special return value.
|
||
|
//
|
||
|
RmTmpDereferenceObject(&pRemoteIp->Hdr, pSR);
|
||
|
pRemoteIp = NULL;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// If this entry is within the range asked for, we copy the IP and
|
||
|
// HW address over onto pEntry...
|
||
|
//
|
||
|
if (CurIndex >= Index)
|
||
|
{
|
||
|
ARP_ZEROSTRUCT(pEntry);
|
||
|
pEntry->IpAddress = pRemoteIp->Key.IpAddress;
|
||
|
if (CHECK_REMOTEIP_RESOLVE_STATE(pRemoteIp, ARPREMOTEIP_RESOLVED))
|
||
|
{
|
||
|
ARPCB_DEST *pDest = pRemoteIp->pDest;
|
||
|
|
||
|
TR_INFO(("ReadNext: found Remote IP Entry 0x%x, Addr %d.%d.%d.%d\n",
|
||
|
pRemoteIp,
|
||
|
((PUCHAR)(&(pRemoteIp->IpAddress)))[0],
|
||
|
((PUCHAR)(&(pRemoteIp->IpAddress)))[1],
|
||
|
((PUCHAR)(&(pRemoteIp->IpAddress)))[2],
|
||
|
((PUCHAR)(&(pRemoteIp->IpAddress)))[3]
|
||
|
));
|
||
|
|
||
|
// We assert that
|
||
|
// IF lock is the same as pRemoteIp's and pDest's lock,
|
||
|
// and that lock is locked.
|
||
|
// We implicitly assert that pDest is non-NULl as well.
|
||
|
//
|
||
|
ASSERTEX(pRemoteIp->Hdr.pLock == pDest->Hdr.pLock, pRemoteIp);
|
||
|
RM_DBG_ASSERT_LOCKED(&pRemoteIp->Hdr, pSR);
|
||
|
|
||
|
pEntry->HwAddress.UniqueID = pDest->Params.HwAddr.FifoAddress.UniqueID;
|
||
|
pEntry->HwAddress.Off_Low = pDest->Params.HwAddr.FifoAddress.Off_Low;
|
||
|
pEntry->HwAddress.Off_High = pDest->Params.HwAddr.FifoAddress.Off_High;
|
||
|
|
||
|
if (CHECK_REMOTEIP_SDTYPE(pRemoteIp, ARPREMOTEIP_STATIC))
|
||
|
{
|
||
|
// TODO
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// TODO
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// TODO
|
||
|
}
|
||
|
|
||
|
pEntry++;
|
||
|
EntriesUsed++;
|
||
|
}
|
||
|
|
||
|
// Lookup next entry's IP address and save it in our context.
|
||
|
//
|
||
|
Status = RmGetNextObjectInGroup(
|
||
|
&pIF->RemoteIpGroup,
|
||
|
&pRemoteIp->Hdr,
|
||
|
&(PRM_OBJECT_HEADER)pNextRemoteIp,
|
||
|
pSR
|
||
|
);
|
||
|
|
||
|
if (FAIL(Status))
|
||
|
{
|
||
|
//
|
||
|
// we're presumably done.
|
||
|
//
|
||
|
pNextRemoteIp = NULL;
|
||
|
}
|
||
|
|
||
|
// TmpDeref pRemoteIp and move on to the next one.
|
||
|
//
|
||
|
RmTmpDereferenceObject(&pRemoteIp->Hdr, pSR);
|
||
|
pRemoteIp = pNextRemoteIp;
|
||
|
|
||
|
}
|
||
|
|
||
|
ASSERT(pRemoteIp == NULL);
|
||
|
UNLOCKOBJ(pIF, pSR);
|
||
|
|
||
|
ASSERT(EntriesUsed <= pGetCacheCmd->NumEntriesAvailable);
|
||
|
pGetCacheCmd->NumEntriesUsed = EntriesUsed;
|
||
|
NtStatus = STATUS_SUCCESS;
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
EXIT()
|
||
|
return NtStatus;
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlAddArpEntry(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_ADD_ARP_ENTRY pAddArpEntryCmd,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
)
|
||
|
{
|
||
|
ENTER("AddArpEntry", 0xcda56c6f)
|
||
|
NTSTATUS NtStatus;
|
||
|
|
||
|
TR_WARN(("ADD ARP ENTRY\n"));
|
||
|
NtStatus = STATUS_UNSUCCESSFUL;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
NDIS_STATUS Status;
|
||
|
NIC1394_FIFO_ADDRESS FifoAddress;
|
||
|
|
||
|
LOCKOBJ(pIF, pSR);
|
||
|
|
||
|
FifoAddress.UniqueID = pAddArpEntryCmd->HwAddress.UniqueID;
|
||
|
FifoAddress.Off_Low = pAddArpEntryCmd->HwAddress.Off_Low;
|
||
|
FifoAddress.Off_High = pAddArpEntryCmd->HwAddress.Off_High;
|
||
|
|
||
|
//
|
||
|
// TODO -- we hardcode the Off_Low and Off_High values for now...
|
||
|
//
|
||
|
FifoAddress.Off_Low = 0x0;
|
||
|
FifoAddress.Off_High = 0x100;
|
||
|
|
||
|
// Actually add the entry...
|
||
|
//
|
||
|
Status = arpAddOneStaticArpEntry(
|
||
|
pIF,
|
||
|
pAddArpEntryCmd->IpAddress,
|
||
|
&FifoAddress,
|
||
|
pSR
|
||
|
);
|
||
|
|
||
|
UNLOCKOBJ(pIF, pSR);
|
||
|
|
||
|
if (!FAIL(Status))
|
||
|
{
|
||
|
NtStatus = STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
|
||
|
EXIT()
|
||
|
return NtStatus;
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlDelArpEntry(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_DEL_ARP_ENTRY pDelArpEntryCmd,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
)
|
||
|
{
|
||
|
ENTER("DelArpEntry", 0x3427306a)
|
||
|
NTSTATUS NtStatus;
|
||
|
|
||
|
TR_WARN(("DEL ARP ENTRY\n"));
|
||
|
NtStatus = STATUS_UNSUCCESSFUL;
|
||
|
|
||
|
NtStatus = arpDelArpEntry(pIF,pDelArpEntryCmd->IpAddress,pSR);
|
||
|
EXIT()
|
||
|
return NtStatus;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlPurgeArpCache(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_PURGE_ARPCACHE pPurgeCmd,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
)
|
||
|
{
|
||
|
ENTER("PurgeArpCache", 0x2bebb833)
|
||
|
TR_WARN(("PURGE ARP CACHE\n"));
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlGetPacketStats(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_GET_PACKET_STATS pStatsCmd,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
)
|
||
|
{
|
||
|
ENTER("GetPacketStats", 0xe7c75fdb)
|
||
|
NTSTATUS NtStatus;
|
||
|
|
||
|
TR_WARN(("GET PACKET STATS\n"));
|
||
|
NtStatus = STATUS_UNSUCCESSFUL;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
NDIS_STATUS Status;
|
||
|
|
||
|
pStatsCmd->StatsDuration = arpGetStatsDuration(pIF);
|
||
|
|
||
|
pStatsCmd->TotSends = pIF->stats.sendpkts.TotSends;
|
||
|
pStatsCmd->FastSends = pIF->stats.sendpkts.FastSends;
|
||
|
pStatsCmd->MediumSends = pIF->stats.sendpkts.MediumSends;
|
||
|
pStatsCmd->SlowSends = pIF->stats.sendpkts.SlowSends;
|
||
|
pStatsCmd->BackFills = pIF->stats.sendpkts.BackFills;
|
||
|
// TODO: report pIF->sendinfo.HeaderPool.stats.TotAllocFails
|
||
|
pStatsCmd->HeaderBufUses =
|
||
|
pIF->sendinfo.HeaderPool.stats.TotBufAllocs
|
||
|
+ pIF->sendinfo.HeaderPool.stats.TotCacheAllocs;
|
||
|
pStatsCmd->HeaderBufCacheHits =
|
||
|
pIF->sendinfo.HeaderPool.stats.TotCacheAllocs;
|
||
|
|
||
|
pStatsCmd->TotRecvs = pIF->stats.recvpkts.TotRecvs;
|
||
|
pStatsCmd->NoCopyRecvs = pIF->stats.recvpkts.NoCopyRecvs;
|
||
|
pStatsCmd->CopyRecvs = pIF->stats.recvpkts.CopyRecvs;
|
||
|
pStatsCmd->ResourceRecvs = pIF->stats.recvpkts.ResourceRecvs;
|
||
|
|
||
|
pStatsCmd->SendFifoCounts = pIF->stats.sendpkts.SendFifoCounts;
|
||
|
pStatsCmd->RecvFifoCounts = pIF->stats.recvpkts.RecvFifoCounts;
|
||
|
|
||
|
pStatsCmd->SendChannelCounts = pIF->stats.sendpkts.SendChannelCounts;
|
||
|
pStatsCmd->RecvChannelCounts = pIF->stats.recvpkts.RecvChannelCounts;
|
||
|
|
||
|
NtStatus = STATUS_SUCCESS;
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
EXIT()
|
||
|
return NtStatus;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlGetTaskStats(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_GET_TASK_STATS pStatsCmd,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
)
|
||
|
{
|
||
|
ENTER("GetTaskStats", 0x4abc46b5)
|
||
|
TR_WARN(("GET TASK STATS\n"));
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlGetArpStats(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_GET_ARPCACHE_STATS pStatsCmd,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
)
|
||
|
{
|
||
|
ENTER("GetArpStats", 0x5482de10)
|
||
|
TR_WARN(("GET ARP STATS\n"));
|
||
|
|
||
|
pStatsCmd->StatsDuration = arpGetStatsDuration(pIF);
|
||
|
pStatsCmd->TotalQueries = pIF->stats.arpcache.TotalQueries;
|
||
|
pStatsCmd->SuccessfulQueries = pIF->stats.arpcache.SuccessfulQueries;
|
||
|
pStatsCmd->FailedQueries = pIF->stats.arpcache.FailedQueries;
|
||
|
pStatsCmd->TotalResponses = pIF->stats.arpcache.TotalResponses;
|
||
|
pStatsCmd->TotalLookups = pIF->stats.arpcache.TotalLookups;
|
||
|
pStatsCmd->TraverseRatio = RM_HASH_TABLE_TRAVERSE_RATIO(
|
||
|
&(pIF->RemoteIpGroup.HashTable)
|
||
|
);
|
||
|
|
||
|
EXIT()
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlGetCallStats(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_GET_CALL_STATS pStatsCmd,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
)
|
||
|
{
|
||
|
ENTER("GetCallStats", 0xf81ed4cf)
|
||
|
TR_WARN(("GET CALL STATS\n"));
|
||
|
|
||
|
//
|
||
|
// FIFO-related call stats.
|
||
|
//
|
||
|
pStatsCmd->TotalSendFifoMakeCalls =
|
||
|
pIF->stats.calls.TotalSendFifoMakeCalls;
|
||
|
pStatsCmd->SuccessfulSendFifoMakeCalls =
|
||
|
pIF->stats.calls.SuccessfulSendFifoMakeCalls;
|
||
|
pStatsCmd->FailedSendFifoMakeCalls =
|
||
|
pIF->stats.calls.FailedSendFifoMakeCalls;
|
||
|
pStatsCmd->IncomingClosesOnSendFifos =
|
||
|
pIF->stats.calls.IncomingClosesOnSendFifos;
|
||
|
|
||
|
//
|
||
|
// Channel-related call stats.
|
||
|
//
|
||
|
pStatsCmd->TotalChannelMakeCalls =
|
||
|
pIF->stats.calls.TotalChannelMakeCalls;
|
||
|
pStatsCmd->SuccessfulChannelMakeCalls =
|
||
|
pIF->stats.calls.SuccessfulChannelMakeCalls;
|
||
|
pStatsCmd->FailedChannelMakeCalls =
|
||
|
pIF->stats.calls.FailedChannelMakeCalls;
|
||
|
pStatsCmd->IncomingClosesOnChannels =
|
||
|
pIF->stats.calls.IncomingClosesOnChannels;
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlResetStats(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_RESET_STATS pResetStatsCmd,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS NtStatus;
|
||
|
ENTER("ResetStats", 0xfa50cfc9)
|
||
|
TR_WARN(("RESET STATS\n"));
|
||
|
|
||
|
NtStatus = STATUS_UNSUCCESSFUL;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
NDIS_STATUS Status;
|
||
|
NIC1394_FIFO_ADDRESS FifoAddress;
|
||
|
|
||
|
|
||
|
LOCKOBJ(pIF, pSR);
|
||
|
arpResetIfStats(pIF, pSR);
|
||
|
UNLOCKOBJ(pIF, pSR);
|
||
|
NtStatus = STATUS_SUCCESS;
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
EXIT()
|
||
|
return NtStatus;
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlReinitIf(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_REINIT_INTERFACE pReinitIfCmd,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
)
|
||
|
{
|
||
|
ENTER("ReinitIf", 0xed00187a)
|
||
|
NTSTATUS NtStatus;
|
||
|
|
||
|
TR_WARN(("REINIT IF\n"));
|
||
|
NtStatus = STATUS_UNSUCCESSFUL;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
NDIS_STATUS Status;
|
||
|
NIC1394_FIFO_ADDRESS FifoAddress;
|
||
|
|
||
|
|
||
|
Status = arpTryReconfigureIf(pIF, NULL, pSR);
|
||
|
|
||
|
if (PEND(Status) || !FAIL(Status))
|
||
|
{
|
||
|
NtStatus = STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
EXIT()
|
||
|
return NtStatus;
|
||
|
}
|
||
|
|
||
|
|
||
|
PARP1394_INTERFACE
|
||
|
arpGetIfByIp(
|
||
|
IN OUT IP_ADDRESS *pLocalIpAddress, // OPTIONAL
|
||
|
PRM_STACK_RECORD pSR
|
||
|
)
|
||
|
/*++
|
||
|
Routine Description:
|
||
|
|
||
|
Find and return the 1st (and usually only) interface which has
|
||
|
*pLocalIpAddress as a local IP address.
|
||
|
|
||
|
If pLocalIpAddress is NULL, or *pLocalIpAddress is 0, return the
|
||
|
first interface.
|
||
|
|
||
|
Tmpref the interface before returning it.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ENTER("arpGetIfByIp", 0xe9667c54)
|
||
|
PARP1394_ADAPTER pAdapter = NULL;
|
||
|
PARP1394_INTERFACE pIF = NULL;
|
||
|
PARP1394_INTERFACE pFirstIF = NULL;
|
||
|
NDIS_STATUS Status;
|
||
|
IP_ADDRESS LocalIpAddress = 0;
|
||
|
|
||
|
if (pLocalIpAddress != NULL)
|
||
|
{
|
||
|
LocalIpAddress = *pLocalIpAddress;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// We iterate through all adapters, and for each adapter we look
|
||
|
// for the specified ip address in the IF's LocalIp group.
|
||
|
//
|
||
|
|
||
|
// Get the 1st adapter...
|
||
|
//
|
||
|
Status = RmGetNextObjectInGroup(
|
||
|
&ArpGlobals.adapters.Group,
|
||
|
NULL,
|
||
|
&(PRM_OBJECT_HEADER)pAdapter,
|
||
|
pSR
|
||
|
);
|
||
|
|
||
|
if (FAIL(Status))
|
||
|
{
|
||
|
pAdapter = NULL;
|
||
|
}
|
||
|
|
||
|
while (pAdapter != NULL)
|
||
|
{
|
||
|
ARP1394_ADAPTER * pNextAdapter = NULL;
|
||
|
|
||
|
|
||
|
// Check if this adapter's interface has the local ip address.
|
||
|
//
|
||
|
LOCKOBJ(pAdapter, pSR);
|
||
|
ASSERT(pIF==NULL);
|
||
|
pIF = pAdapter->pIF;
|
||
|
if (pIF != NULL)
|
||
|
{
|
||
|
RmTmpReferenceObject(&pIF->Hdr, pSR);
|
||
|
if (pFirstIF == NULL)
|
||
|
{
|
||
|
pFirstIF = pIF;
|
||
|
RmTmpReferenceObject(&pFirstIF->Hdr, pSR);
|
||
|
}
|
||
|
}
|
||
|
UNLOCKOBJ(pAdapter, pSR);
|
||
|
|
||
|
if (pIF != NULL)
|
||
|
{
|
||
|
PARPCB_LOCAL_IP pLocalIp;
|
||
|
LOCKOBJ(pIF, pSR);
|
||
|
|
||
|
if (LocalIpAddress != 0)
|
||
|
{
|
||
|
Status = RmLookupObjectInGroup(
|
||
|
&pIF->LocalIpGroup,
|
||
|
0, // Flags
|
||
|
(PVOID) ULongToPtr (LocalIpAddress), // pKey
|
||
|
NULL, // pvCreateParams
|
||
|
&(PRM_OBJECT_HEADER)pLocalIp,
|
||
|
NULL, // pfCreated
|
||
|
pSR
|
||
|
);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
PARPCB_LOCAL_IP pPrevLocalIp = NULL;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
Status = RmGetNextObjectInGroup(
|
||
|
&pIF->LocalIpGroup,
|
||
|
&(pPrevLocalIp)->Hdr,
|
||
|
&(PRM_OBJECT_HEADER)pLocalIp,
|
||
|
pSR
|
||
|
);
|
||
|
if (pPrevLocalIp != NULL)
|
||
|
{
|
||
|
RmTmpDereferenceObject(&pPrevLocalIp->Hdr, pSR);
|
||
|
}
|
||
|
pPrevLocalIp = pLocalIp;
|
||
|
|
||
|
//
|
||
|
// we need to keep looking until we find a UNICAST
|
||
|
// local ip address!
|
||
|
//
|
||
|
|
||
|
} while (!FAIL(Status) && pLocalIp->IpAddressType!=LLIP_ADDR_LOCAL);
|
||
|
}
|
||
|
|
||
|
UNLOCKOBJ(pIF, pSR);
|
||
|
|
||
|
if (FAIL(Status))
|
||
|
{
|
||
|
// This IF is not the one, sorry...
|
||
|
//
|
||
|
RmTmpDereferenceObject(&pIF->Hdr, pSR);
|
||
|
pIF = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Found a local IP address (either matching or first one).
|
||
|
// Let's get out of here...
|
||
|
//
|
||
|
if (pLocalIpAddress != NULL)
|
||
|
{
|
||
|
*pLocalIpAddress = pLocalIp->IpAddress;
|
||
|
}
|
||
|
RmTmpDereferenceObject(&pLocalIp->Hdr, pSR);
|
||
|
RmTmpDereferenceObject(&pAdapter->Hdr, pSR);
|
||
|
pLocalIp = NULL;
|
||
|
pAdapter = NULL;
|
||
|
//
|
||
|
// Note: we keep the reference on pIF, which we return.
|
||
|
//
|
||
|
break; // break out of the enclosing while(adapters-left) loop.
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Lookup next adapter.
|
||
|
//
|
||
|
Status = RmGetNextObjectInGroup(
|
||
|
&ArpGlobals.adapters.Group,
|
||
|
&pAdapter->Hdr,
|
||
|
&(PRM_OBJECT_HEADER)pNextAdapter,
|
||
|
pSR
|
||
|
);
|
||
|
|
||
|
if (FAIL(Status))
|
||
|
{
|
||
|
//
|
||
|
// we're presumably done.
|
||
|
//
|
||
|
pNextAdapter = NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
// TmpDeref pAdapter and move on to the next one.
|
||
|
//
|
||
|
RmTmpDereferenceObject(&pAdapter->Hdr, pSR);
|
||
|
pAdapter = pNextAdapter;
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If LocalipAddress ==0 AND
|
||
|
// if we couldn't find any IF with any local IP address
|
||
|
// (this would be because we haven't started an IF as yet)
|
||
|
// we return the first IF we find.
|
||
|
//
|
||
|
if (LocalIpAddress == 0 && pIF == NULL)
|
||
|
{
|
||
|
pIF = pFirstIF;
|
||
|
pFirstIF = NULL;
|
||
|
}
|
||
|
|
||
|
if (pFirstIF != NULL)
|
||
|
{
|
||
|
RmTmpDereferenceObject(&pFirstIF->Hdr, pSR);
|
||
|
}
|
||
|
|
||
|
return pIF;
|
||
|
}
|
||
|
|
||
|
UINT
|
||
|
arpGetStatsDuration(
|
||
|
PARP1394_INTERFACE pIF
|
||
|
)
|
||
|
/*++
|
||
|
Return duration in seconds since start of statistics gathering.
|
||
|
--*/
|
||
|
{
|
||
|
LARGE_INTEGER liCurrent;
|
||
|
|
||
|
// Get the current time (in 100-nanosecond units).
|
||
|
//
|
||
|
NdisGetCurrentSystemTime(&liCurrent);
|
||
|
|
||
|
// Compute the difference since the start of stats collection.
|
||
|
//
|
||
|
liCurrent.QuadPart -= pIF->stats.StatsResetTime.QuadPart;
|
||
|
|
||
|
// Convert to seconds.
|
||
|
//
|
||
|
liCurrent.QuadPart /= 10000000;
|
||
|
|
||
|
// return low part.
|
||
|
//
|
||
|
return liCurrent.LowPart;
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlSendPacket(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_SEND_PACKET pSendPacket,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
)
|
||
|
/*++
|
||
|
Send the pSendPacket->PacketSize bytes of data in pSendPacket->Data as
|
||
|
a single packet on the broadcast channel. The encap header is expected
|
||
|
to be already in the packet.
|
||
|
--*/
|
||
|
{
|
||
|
ENTER("IoctlSendPacket", 0x59746279)
|
||
|
NTSTATUS NtStatus;
|
||
|
|
||
|
RM_ASSERT_NOLOCKS(pSR);
|
||
|
|
||
|
TR_WARN(("SEND PACKET\n"));
|
||
|
NtStatus = STATUS_UNSUCCESSFUL;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
NDIS_STATUS Status;
|
||
|
PNDIS_PACKET pNdisPacket;
|
||
|
PVOID pPktData;
|
||
|
UINT Size = pSendPacket->PacketSize;
|
||
|
|
||
|
//
|
||
|
// Validate contents of pSendPacket.
|
||
|
//
|
||
|
if (Size > sizeof(pSendPacket->Data))
|
||
|
{
|
||
|
TR_WARN(("PacketSize value %lu is too large.\n", Size));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Allocate a control packet and copy over the contents.
|
||
|
//
|
||
|
Status = arpAllocateControlPacket(
|
||
|
pIF,
|
||
|
Size,
|
||
|
ARP1394_PACKET_FLAGS_IOCTL,
|
||
|
&pNdisPacket,
|
||
|
&pPktData,
|
||
|
pSR
|
||
|
);
|
||
|
|
||
|
if (FAIL(Status))
|
||
|
{
|
||
|
TR_WARN(("Couldn't allocate send packet.\n"));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
NdisMoveMemory(pPktData, pSendPacket->Data, Size);
|
||
|
|
||
|
ARP_FASTREADLOCK_IF_SEND_LOCK(pIF);
|
||
|
|
||
|
// Actually send the packet (this will silently fail and free the pkt
|
||
|
// if we're not in a position to send the pkt.)
|
||
|
//
|
||
|
arpSendControlPkt(
|
||
|
pIF, // LOCKIN NOLOCKOUT (IF send lk)
|
||
|
pNdisPacket,
|
||
|
pIF->pBroadcastDest,
|
||
|
pSR
|
||
|
);
|
||
|
|
||
|
NtStatus = STATUS_SUCCESS;
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
RM_ASSERT_NOLOCKS(pSR);
|
||
|
|
||
|
EXIT()
|
||
|
return NtStatus;
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlRecvPacket(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_RECV_PACKET pRecvPacket,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
)
|
||
|
{
|
||
|
ENTER("IoctlRecvPacket", 0x59746279)
|
||
|
NTSTATUS NtStatus;
|
||
|
|
||
|
RM_ASSERT_NOLOCKS(pSR);
|
||
|
|
||
|
TR_WARN(("RECV PACKET\n"));
|
||
|
NtStatus = STATUS_UNSUCCESSFUL;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
NDIS_STATUS Status;
|
||
|
PNDIS_PACKET pNdisPacket;
|
||
|
PVOID pPktData;
|
||
|
UINT Size = pRecvPacket->PacketSize;
|
||
|
|
||
|
//
|
||
|
// Validate contents of pRecvPacket.
|
||
|
//
|
||
|
if (Size > sizeof(pRecvPacket->Data))
|
||
|
{
|
||
|
TR_WARN(("PacketSize value %lu is too large.\n", Size));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Allocate a control packet and copy over the contents.
|
||
|
//
|
||
|
Status = arpAllocateControlPacket(
|
||
|
pIF,
|
||
|
Size,
|
||
|
ARP1394_PACKET_FLAGS_IOCTL,
|
||
|
&pNdisPacket,
|
||
|
&pPktData,
|
||
|
pSR
|
||
|
);
|
||
|
|
||
|
if (FAIL(Status))
|
||
|
{
|
||
|
TR_WARN(("Couldn't allocate recv packet.\n"));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
NdisMoveMemory(pPktData, pRecvPacket->Data, Size);
|
||
|
|
||
|
//
|
||
|
// Set the packet flags to STATUS_RESOURCES, so that our receive-
|
||
|
// indicate handler will return synchronously.
|
||
|
//
|
||
|
NDIS_SET_PACKET_STATUS (pNdisPacket, NDIS_STATUS_RESOURCES);
|
||
|
|
||
|
//
|
||
|
// Call our internal common receive packet handler.
|
||
|
//
|
||
|
arpProcessReceivedPacket(
|
||
|
pIF,
|
||
|
pNdisPacket,
|
||
|
TRUE // IsChannel
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// Now we free the packet.
|
||
|
//
|
||
|
arpFreeControlPacket(
|
||
|
pIF,
|
||
|
pNdisPacket,
|
||
|
pSR
|
||
|
);
|
||
|
|
||
|
NtStatus = STATUS_SUCCESS;
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
RM_ASSERT_NOLOCKS(pSR);
|
||
|
|
||
|
EXIT()
|
||
|
return NtStatus;
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlGetNicInfo(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_NICINFO pIoctlNicInfo,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
)
|
||
|
{
|
||
|
ENTER("IoctlGetNicInfo", 0x637c44e0)
|
||
|
NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
|
||
|
ARP_NDIS_REQUEST ArpNdisRequest;
|
||
|
PARP1394_ADAPTER pAdapter;
|
||
|
|
||
|
pAdapter = (ARP1394_ADAPTER*) RM_PARENT_OBJECT(pIF);
|
||
|
|
||
|
do
|
||
|
{
|
||
|
NDIS_STATUS Status;
|
||
|
|
||
|
if (pIoctlNicInfo->Info.Hdr.Version != NIC1394_NICINFO_VERSION)
|
||
|
{
|
||
|
TR_WARN(("NicInfo version mismatch. Want 0x%lx, got 0x%lx.\n",
|
||
|
NIC1394_NICINFO_VERSION, pIoctlNicInfo->Info.Hdr.Version));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Copy over all the fields.
|
||
|
//
|
||
|
|
||
|
Status = arpPrepareAndSendNdisRequest(
|
||
|
pAdapter,
|
||
|
&ArpNdisRequest,
|
||
|
NULL, // pTask (NULL==BLOCK)
|
||
|
0, // unused
|
||
|
OID_1394_NICINFO,
|
||
|
&pIoctlNicInfo->Info,
|
||
|
sizeof(pIoctlNicInfo->Info),
|
||
|
NdisRequestQueryInformation,
|
||
|
pSR
|
||
|
);
|
||
|
|
||
|
if (FAIL(Status))
|
||
|
{
|
||
|
TR_WARN(("NdisRequest failed with error 0x%08lx.\n", Status));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (pIoctlNicInfo->Info.Hdr.Version != NIC1394_NICINFO_VERSION)
|
||
|
{
|
||
|
TR_WARN(("Unexpected NIC NicInfo version 0x%lx returned.\n",
|
||
|
pIoctlNicInfo->Info.Hdr.Version));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
NtStatus = NDIS_STATUS_SUCCESS;
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
return NtStatus;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
arpIoctlGetEuidNodeMacInfo(
|
||
|
PARP1394_INTERFACE pIF,
|
||
|
PARP1394_IOCTL_EUID_NODE_MAC_INFO pEuidInfo,
|
||
|
PRM_STACK_RECORD pSR
|
||
|
)
|
||
|
{
|
||
|
ENTER("IoctlGetNicInfo", 0x34db9cf4)
|
||
|
NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
|
||
|
ARP_NDIS_REQUEST ArpNdisRequest;
|
||
|
PARP1394_ADAPTER pAdapter;
|
||
|
|
||
|
pAdapter = (ARP1394_ADAPTER*) RM_PARENT_OBJECT(pIF);
|
||
|
|
||
|
do
|
||
|
{
|
||
|
NDIS_STATUS Status;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Copy over all the fields.
|
||
|
//
|
||
|
|
||
|
Status = arpPrepareAndSendNdisRequest(
|
||
|
pAdapter,
|
||
|
&ArpNdisRequest,
|
||
|
NULL, // pTask (NULL==BLOCK)
|
||
|
0, // unused
|
||
|
OID_1394_QUERY_EUID_NODE_MAP,
|
||
|
&pEuidInfo->Map,
|
||
|
sizeof(pEuidInfo->Map),
|
||
|
NdisRequestQueryInformation,
|
||
|
pSR
|
||
|
);
|
||
|
|
||
|
if (FAIL(Status))
|
||
|
{
|
||
|
TR_WARN(("NdisRequest failed with error 0x%08lx.\n", Status));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
NtStatus = NDIS_STATUS_SUCCESS;
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
return NtStatus;
|
||
|
}
|
||
|
|
||
|
|