922 lines
19 KiB
C
922 lines
19 KiB
C
/*++
|
|
|
|
Copyright (c) 1992-1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
registry.c
|
|
|
|
Abstract:
|
|
|
|
This file contains the code to read the registry.
|
|
|
|
Author:
|
|
|
|
Jameel Hyder (jameelh@microsoft.com) July 1996
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <precomp.h>
|
|
#define _FILENUM_ FILENUM_REGISTRY
|
|
|
|
NTSTATUS
|
|
ArpSReadGlobalConfiguration(
|
|
IN PUNICODE_STRING RegistryPath
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read the global registry.
|
|
|
|
Arguments:
|
|
|
|
RegistryPath - Pointer to the service section in the registry.
|
|
|
|
Return Value:
|
|
|
|
Error code from registry apis.
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
NDIS_HANDLE ConfigHandle;
|
|
|
|
//
|
|
// Open the per-adapter registry config
|
|
//
|
|
NdisOpenProtocolConfiguration(&Status,
|
|
&ConfigHandle,
|
|
RegistryPath);
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
NDIS_STRING ArpsBufString = NDIS_STRING_CONST("ArpBuffers");
|
|
NDIS_STRING FlushString = NDIS_STRING_CONST("FlushTime");
|
|
PNDIS_CONFIGURATION_PARAMETER Param;
|
|
|
|
//
|
|
// Read number of configured buffers
|
|
//
|
|
NdisReadConfiguration(&Status,
|
|
&Param,
|
|
ConfigHandle,
|
|
&ArpsBufString,
|
|
NdisParameterInteger);
|
|
if ((Status == NDIS_STATUS_SUCCESS) &&
|
|
(Param->ParameterType == NdisParameterInteger))
|
|
{
|
|
ArpSBuffers = Param->ParameterData.IntegerData;
|
|
}
|
|
|
|
//
|
|
// Should we save cache in a file ?
|
|
//
|
|
NdisReadConfiguration(&Status,
|
|
&Param,
|
|
ConfigHandle,
|
|
&FlushString,
|
|
NdisParameterInteger);
|
|
if ((Status == NDIS_STATUS_SUCCESS) &&
|
|
(Param->ParameterType == NdisParameterInteger))
|
|
{
|
|
ArpSFlushTime = (USHORT)(Param->ParameterData.IntegerData * MULTIPLIER);
|
|
}
|
|
|
|
NdisCloseConfiguration(ConfigHandle);
|
|
}
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
ArpSReadAdapterConfigFromRegistry(
|
|
IN PINTF pIntF,
|
|
OUT PATMARPS_CONFIG pConfig
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read configuration for the specified interface.
|
|
|
|
Arguments:
|
|
|
|
pIntF - Interface
|
|
pConfig - Place to return information read in.
|
|
|
|
Return Value:
|
|
|
|
Error code from registry apis.
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
NDIS_HANDLE ConfigHandle;
|
|
|
|
//
|
|
// Open the per-adapter registry config
|
|
//
|
|
NdisOpenProtocolConfiguration(&Status,
|
|
&ConfigHandle,
|
|
&pIntF->ConfigString);
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
NDIS_STRING RegdAddrsString = NDIS_STRING_CONST("RegisteredAddresses");
|
|
NDIS_STRING SelString = NDIS_STRING_CONST("Selector");
|
|
NDIS_STRING McsString = NDIS_STRING_CONST("MulticastAddresses");
|
|
PNDIS_CONFIGURATION_PARAMETER Param;
|
|
PWSTR p;
|
|
UINT i, Length;
|
|
|
|
//
|
|
// Read the value, if present for the selector byte to be used for the registered sap
|
|
// for the std. address (as opposed to added addresses).
|
|
//
|
|
pConfig->SelByte = 0;
|
|
NdisReadConfiguration(&Status,
|
|
&Param,
|
|
ConfigHandle,
|
|
&SelString,
|
|
NdisParameterInteger);
|
|
if ((Status == NDIS_STATUS_SUCCESS) &&
|
|
(Param->ParameterType == NdisParameterInteger) &&
|
|
(Param->ParameterData.IntegerData <= 0xFF))
|
|
{
|
|
pConfig->SelByte = (UCHAR)(Param->ParameterData.IntegerData);
|
|
DBGPRINT(DBG_LEVEL_INFO,
|
|
("Selector byte for interface %Z is %d\n",
|
|
&pIntF->InterfaceName, pConfig->SelByte));
|
|
}
|
|
|
|
//
|
|
// Read registered addresses here. On an interface there can be a set of
|
|
// atm addresses registered. These need to be added and SAPs registered on
|
|
// them.
|
|
//
|
|
pConfig->NumAllocedRegdAddresses = 0;
|
|
pConfig->RegAddresses = NULL;
|
|
NdisReadConfiguration(&Status,
|
|
&Param,
|
|
ConfigHandle,
|
|
&RegdAddrsString,
|
|
NdisParameterMultiString);
|
|
if ((Status == NDIS_STATUS_SUCCESS) && (Param->ParameterType == NdisParameterMultiString))
|
|
{
|
|
NDIS_STRING String;
|
|
|
|
//
|
|
// Param now contains a list of atm addresses. Convert them into the right format and store
|
|
// it in the intf structure. First determine the number of addresses.
|
|
//
|
|
for (p = Param->ParameterData.StringData.Buffer, i = 0;
|
|
*p != L'\0';
|
|
i++)
|
|
{
|
|
RtlInitUnicodeString(&String, p);
|
|
DBGPRINT(DBG_LEVEL_INFO,
|
|
("Configured address for interface %Z - %Z\n",
|
|
&pIntF->InterfaceName, &String));
|
|
|
|
p = (PWSTR)((PUCHAR)p + String.Length + sizeof(WCHAR));
|
|
}
|
|
|
|
if (i)
|
|
{
|
|
//
|
|
// Allocate space for the addresses
|
|
//
|
|
pConfig->RegAddresses = (PATM_ADDRESS)ALLOC_NP_MEM(sizeof(ATM_ADDRESS) * i, POOL_TAG_ADDR);
|
|
if (pConfig->RegAddresses == NULL)
|
|
{
|
|
LOG_ERROR(NDIS_STATUS_RESOURCES);
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT(DBG_LEVEL_INFO,
|
|
("%d addresses registered for %Z\n", i, &pIntF->InterfaceName));
|
|
|
|
ZERO_MEM(pConfig->RegAddresses, sizeof(ATM_ADDRESS) * i);
|
|
for (i = 0, p = Param->ParameterData.StringData.Buffer;
|
|
*p != L'\0';
|
|
NOTHING)
|
|
{
|
|
RtlInitUnicodeString(&String, p);
|
|
NdisConvertStringToAtmAddress(&Status, &String, &pConfig->RegAddresses[i]);
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
i++;
|
|
pConfig->NumAllocedRegdAddresses ++;
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT(DBG_LEVEL_ERROR,
|
|
("ArpSReadAdapterConfiguration: Failed to convert address %Z\n",
|
|
&String));
|
|
}
|
|
p = (PWSTR)((PUCHAR)p + String.Length + sizeof(WCHAR));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pConfig->pMcsList = NULL;
|
|
NdisReadConfiguration(&Status,
|
|
&Param,
|
|
ConfigHandle,
|
|
&McsString,
|
|
NdisParameterMultiString);
|
|
if ((Status == NDIS_STATUS_SUCCESS) && (Param->ParameterType == NdisParameterMultiString))
|
|
{
|
|
NDIS_STRING String;
|
|
|
|
//
|
|
// Param now contains a list of Multicast IP Address ranges.
|
|
// Each string is of the form "M.M.M.M-N.N.N.N"
|
|
// Read them in.
|
|
//
|
|
for (p = Param->ParameterData.StringData.Buffer, i = 0;
|
|
*p != L'\0';
|
|
i++)
|
|
{
|
|
RtlInitUnicodeString(&String, p);
|
|
DBGPRINT(DBG_LEVEL_INFO,
|
|
("Configured Multicast range for interface %Z - %Z\n",
|
|
&pIntF->InterfaceName, &String));
|
|
|
|
p = (PWSTR)((PUCHAR)p + String.Length + sizeof(WCHAR));
|
|
}
|
|
|
|
//
|
|
// Allocate space for the addresses
|
|
//
|
|
pConfig->pMcsList = (PMCS_ENTRY)ALLOC_NP_MEM(sizeof(MCS_ENTRY) * i, POOL_TAG_MARS);
|
|
if (pConfig->pMcsList == (PMCS_ENTRY)NULL)
|
|
{
|
|
LOG_ERROR(NDIS_STATUS_RESOURCES);
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT(DBG_LEVEL_INFO,
|
|
("%d Multicast ranges configured on %Z\n", i, &pIntF->InterfaceName));
|
|
|
|
ZERO_MEM(pConfig->pMcsList, sizeof(MCS_ENTRY) * i);
|
|
for (i = 0, p = Param->ParameterData.StringData.Buffer;
|
|
*p != L'\0';
|
|
NOTHING)
|
|
{
|
|
RtlInitUnicodeString(&String, p);
|
|
ArpSConvertStringToIpPair(&Status, &String, &pConfig->pMcsList[i]);
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
if (i > 0)
|
|
{
|
|
pConfig->pMcsList[i-1].Next = &(pConfig->pMcsList[i]);
|
|
}
|
|
i++;
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT(DBG_LEVEL_ERROR,
|
|
("ArpSReadAdapterConfiguration: Failed to convert IP Range %Z\n",
|
|
&String));
|
|
}
|
|
p = (PWSTR)((PUCHAR)p + String.Length + sizeof(WCHAR));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Close the configuration handle
|
|
//
|
|
NdisCloseConfiguration(ConfigHandle);
|
|
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
ArpSReadAdapterConfiguration(
|
|
IN PINTF pIntF
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read the registry for parameters for the specified Interface.
|
|
This could be in response to a reconfiguration event, in which
|
|
case handle existing values/structures.
|
|
|
|
Arguments:
|
|
|
|
pIntF - Interface to be read in.
|
|
|
|
Return Value:
|
|
|
|
Error code from registry apis.
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
ATMARPS_CONFIG AtmArpSConfig;
|
|
KIRQL OldIrql;
|
|
|
|
ULONG PrevNumAllocedRegdAddresses;
|
|
PATM_ADDRESS PrevRegAddresses;
|
|
PMCS_ENTRY PrevMcsList;
|
|
|
|
Status = ArpSReadAdapterConfigFromRegistry(pIntF, &AtmArpSConfig);
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
//
|
|
// Copy them into the interface structure. We could be handling a
|
|
// parameter reconfig, so any space used to store old information.
|
|
//
|
|
|
|
ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
|
|
|
|
//
|
|
// Selector Byte:
|
|
//
|
|
pIntF->SelByte = AtmArpSConfig.SelByte;
|
|
|
|
//
|
|
// List of addresses to be registered with the switch.
|
|
// Take out the old list first. We'll have to delete those
|
|
// addresses (deregister them from the switch).
|
|
//
|
|
PrevNumAllocedRegdAddresses = pIntF->NumAllocedRegdAddresses;
|
|
PrevRegAddresses = pIntF->RegAddresses;
|
|
|
|
//
|
|
// Get the new list in:
|
|
//
|
|
pIntF->NumAllocedRegdAddresses = AtmArpSConfig.NumAllocedRegdAddresses;
|
|
pIntF->RegAddresses = AtmArpSConfig.RegAddresses;
|
|
pIntF->NumAddressesRegd = 0; // reset count of addresses regd with switch
|
|
|
|
//
|
|
// Take out the old MCS list and insert the new one.
|
|
//
|
|
PrevMcsList = pIntF->pMcsList;
|
|
pIntF->pMcsList = AtmArpSConfig.pMcsList;
|
|
|
|
RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
|
|
|
|
//
|
|
// Deregister all previously registered addresses with the switch.
|
|
//
|
|
if (PrevNumAllocedRegdAddresses)
|
|
{
|
|
ArpSDeleteIntFAddresses(pIntF, PrevNumAllocedRegdAddresses, PrevRegAddresses);
|
|
|
|
//
|
|
// Register the new list of addresses with the switch.
|
|
//
|
|
ArpSQueryAndSetAddresses(pIntF);
|
|
}
|
|
|
|
//
|
|
// Free unused memory.
|
|
//
|
|
if (PrevMcsList)
|
|
{
|
|
FREE_MEM(PrevMcsList);
|
|
}
|
|
|
|
if (PrevRegAddresses)
|
|
{
|
|
FREE_MEM(PrevRegAddresses);
|
|
}
|
|
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
ArpSConvertStringToIpPair(
|
|
OUT PNDIS_STATUS pStatus,
|
|
IN PNDIS_STRING pString,
|
|
IN PMCS_ENTRY pMcsEntry
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Extract a pair of IP addresses that identify a range of multicast addresses
|
|
that this MCS serves, from the given string.
|
|
|
|
Arguments:
|
|
|
|
pStatus - Place to return status
|
|
pString - Points to string containing "<IP1>-<IP2>"
|
|
pMcsEntry - Entry to read into.
|
|
|
|
Return Value:
|
|
|
|
None. *pStatus is set to indicate the status of this call.
|
|
|
|
--*/
|
|
{
|
|
PWSTR pMin, pMax;
|
|
IPADDR Min, Max;
|
|
ULONG Length;
|
|
ULONG i;
|
|
|
|
ARPS_PAGED_CODE();
|
|
|
|
Length = pString->Length;
|
|
|
|
*pStatus = NDIS_STATUS_FAILURE;
|
|
|
|
do
|
|
{
|
|
//
|
|
// Locate the '-' and replace it with a NULL char.
|
|
//
|
|
pMin = pString->Buffer;
|
|
pMax = pString->Buffer;
|
|
|
|
for (i = 0; i < Length; i++, pMax++)
|
|
{
|
|
if (*pMax == L'-')
|
|
{
|
|
*pMax++ = L'\0';
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == Length)
|
|
{
|
|
break; // Didn't find '-'
|
|
}
|
|
|
|
if (IPConvertStringToAddress(pMin, &Min) &&
|
|
IPConvertStringToAddress(pMax, &Max))
|
|
{
|
|
DBGPRINT(DBG_LEVEL_INFO, ("MCS pair: "));
|
|
ArpSDumpIpAddr(Min, " to ");
|
|
ArpSDumpIpAddr(Max, "\n");
|
|
|
|
pMcsEntry->GrpAddrPair.MinAddr = Min;
|
|
pMcsEntry->GrpAddrPair.MaxAddr = Max;
|
|
*pStatus = NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
break;
|
|
}
|
|
while (FALSE);
|
|
|
|
}
|
|
|
|
|
|
#define IP_ADDRESS_STRING_LENGTH (16+2) // +2 for double NULL on MULTI_SZ
|
|
|
|
|
|
BOOLEAN
|
|
IPConvertStringToAddress(
|
|
IN PWCHAR AddressString,
|
|
OUT PULONG IpAddress
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
This function converts an Internet standard 4-octet dotted decimal
|
|
IP address string into a numeric IP address. Unlike inet_addr(), this
|
|
routine does not support address strings of less than 4 octets nor does
|
|
it support octal and hexadecimal octets.
|
|
|
|
Copied from tcpip\ip\ntip.c
|
|
|
|
Arguments
|
|
|
|
AddressString - IP address in dotted decimal notation
|
|
IpAddress - Pointer to a variable to hold the resulting address
|
|
|
|
Return Value:
|
|
|
|
TRUE if the address string was converted. FALSE otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
UNICODE_STRING unicodeString;
|
|
STRING aString;
|
|
UCHAR dataBuffer[IP_ADDRESS_STRING_LENGTH];
|
|
NTSTATUS status;
|
|
PUCHAR addressPtr, cp, startPointer, endPointer;
|
|
ULONG digit, multiplier;
|
|
int i;
|
|
|
|
|
|
ARPS_PAGED_CODE();
|
|
|
|
aString.Length = 0;
|
|
aString.MaximumLength = IP_ADDRESS_STRING_LENGTH;
|
|
aString.Buffer = dataBuffer;
|
|
|
|
RtlInitUnicodeString(&unicodeString, AddressString);
|
|
|
|
status = RtlUnicodeStringToAnsiString(
|
|
&aString,
|
|
&unicodeString,
|
|
FALSE
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
return(FALSE);
|
|
}
|
|
|
|
*IpAddress = 0;
|
|
addressPtr = (PUCHAR) IpAddress;
|
|
startPointer = dataBuffer;
|
|
endPointer = dataBuffer;
|
|
i = 3;
|
|
|
|
while (i >= 0) {
|
|
//
|
|
// Collect the characters up to a '.' or the end of the string.
|
|
//
|
|
while ((*endPointer != '.') && (*endPointer != '\0')) {
|
|
endPointer++;
|
|
}
|
|
|
|
if (startPointer == endPointer) {
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Convert the number.
|
|
//
|
|
|
|
for ( cp = (endPointer - 1), multiplier = 1, digit = 0;
|
|
cp >= startPointer;
|
|
cp--, multiplier *= 10
|
|
) {
|
|
|
|
if ((*cp < '0') || (*cp > '9') || (multiplier > 100)) {
|
|
return(FALSE);
|
|
}
|
|
|
|
digit += (multiplier * ((ULONG) (*cp - '0')));
|
|
}
|
|
|
|
if (digit > 255) {
|
|
return(FALSE);
|
|
}
|
|
|
|
addressPtr[i] = (UCHAR) digit;
|
|
|
|
//
|
|
// We are finished if we have found and converted 4 octets and have
|
|
// no other characters left in the string.
|
|
//
|
|
if ( (i-- == 0) &&
|
|
((*endPointer == '\0') || (*endPointer == ' '))
|
|
) {
|
|
return(TRUE);
|
|
}
|
|
|
|
if (*endPointer == '\0') {
|
|
return(FALSE);
|
|
}
|
|
|
|
startPointer = ++endPointer;
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
ArpSReadArpCache(
|
|
IN PINTF pIntF
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read the per-adapter Arp Cache. TBD.
|
|
|
|
Arguments:
|
|
|
|
pIntF - Per adapter arp cache.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
HANDLE FileHandle;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
NTSTATUS Status;
|
|
LARGE_INTEGER Offset;
|
|
ULONG Space, NumEntries;
|
|
PDISK_HEADER DskHdr;
|
|
PUCHAR Buffer;
|
|
PDISK_ENTRY pDskEntry;
|
|
PARP_ENTRY ArpEntry;
|
|
|
|
Buffer = ALLOC_PG_MEM(DISK_BUFFER_SIZE);
|
|
if (Buffer == NULL)
|
|
{
|
|
LOG_ERROR(NDIS_STATUS_RESOURCES);
|
|
return;
|
|
}
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&pIntF->FileName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
Status = ZwCreateFile(&FileHandle,
|
|
SYNCHRONIZE | FILE_READ_DATA,
|
|
&ObjectAttributes,
|
|
&IoStatus,
|
|
NULL,
|
|
0,
|
|
0,
|
|
FILE_OPEN,
|
|
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE | FILE_SEQUENTIAL_ONLY,
|
|
NULL,
|
|
0);
|
|
|
|
if (Status == STATUS_SUCCESS)
|
|
{
|
|
do
|
|
{
|
|
//
|
|
// First read the disk header and validate it
|
|
//
|
|
Offset.QuadPart = 0;
|
|
Status = ZwReadFile(FileHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
Buffer,
|
|
DISK_BUFFER_SIZE,
|
|
&Offset,
|
|
NULL);
|
|
if (Status != STATUS_SUCCESS)
|
|
{
|
|
LOG_ERROR(Status);
|
|
break;
|
|
}
|
|
|
|
DskHdr = (PDISK_HEADER)Buffer;
|
|
if ((IoStatus.Information < sizeof(DISK_HEADER)) ||
|
|
(DskHdr->Signature != DISK_HDR_SIGNATURE) ||
|
|
(DskHdr->Version != DISK_HDR_VERSION))
|
|
{
|
|
LOG_ERROR(STATUS_INVALID_LEVEL);
|
|
break;
|
|
}
|
|
|
|
NumEntries = DskHdr->NumberOfArpEntries;
|
|
Space = (ULONG) IoStatus.Information - sizeof(DISK_HEADER);
|
|
pDskEntry = (PDISK_ENTRY)(Buffer + sizeof(DISK_HEADER));
|
|
Offset.QuadPart = sizeof(DISK_HEADER);
|
|
while (NumEntries > 0)
|
|
{
|
|
UINT Consumed;
|
|
|
|
if ((Space < sizeof(DISK_ENTRY)) ||
|
|
(Space < (sizeof(DISK_ENTRY) + pDskEntry->AtmAddr.SubAddrLen)))
|
|
{
|
|
Status = ZwReadFile(FileHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
Buffer,
|
|
DISK_BUFFER_SIZE,
|
|
&Offset,
|
|
NULL);
|
|
if (Status != STATUS_SUCCESS)
|
|
{
|
|
LOG_ERROR(Status);
|
|
break;
|
|
}
|
|
|
|
pDskEntry = (PDISK_ENTRY)Buffer;
|
|
if ((IoStatus.Information < sizeof(DISK_ENTRY)) ||
|
|
(IoStatus.Information < (sizeof(DISK_ENTRY) + pDskEntry->AtmAddr.SubAddrLen)))
|
|
{
|
|
LOG_ERROR(STATUS_INVALID_LEVEL);
|
|
break;
|
|
}
|
|
Space = (ULONG) IoStatus.Information - sizeof(DISK_HEADER);
|
|
}
|
|
|
|
ArpEntry = ArpSAddArpEntryFromDisk(pIntF, pDskEntry);
|
|
ASSERT (ArpEntry != NULL);
|
|
|
|
Consumed = (sizeof(DISK_ENTRY) + SIZE_4N(pDskEntry->AtmAddr.SubAddrLen));
|
|
(PUCHAR)pDskEntry += Consumed;
|
|
Offset.QuadPart += Consumed;
|
|
Space -= Consumed;
|
|
NumEntries --;
|
|
}
|
|
} while (FALSE);
|
|
|
|
ZwClose(FileHandle);
|
|
}
|
|
|
|
FREE_MEM(Buffer);
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
ArpSWriteArpCache(
|
|
IN PINTF pIntF,
|
|
IN PTIMER Timer,
|
|
IN BOOLEAN TimerShuttingDown
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write the per-adapter Arp Cache. TBD.
|
|
|
|
Arguments:
|
|
|
|
pIntF - Per adapter arp cache.
|
|
Timer - FlushTimer
|
|
TimerShuttingDown - Do not requeue when set.
|
|
|
|
Return Value:
|
|
|
|
TRUE to requeue unless TimerShuttingDown is set
|
|
|
|
--*/
|
|
{
|
|
HANDLE FileHandle;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
NTSTATUS Status;
|
|
LARGE_INTEGER Offset;
|
|
ULONG Space, i;
|
|
PDISK_HEADER DskHdr;
|
|
PUCHAR Buffer;
|
|
PDISK_ENTRY pDskEntry;
|
|
PARP_ENTRY ArpEntry;
|
|
TIME SystemTime, LocalTime;
|
|
ULONG CurrentTime;
|
|
|
|
Buffer = ALLOC_PG_MEM(DISK_BUFFER_SIZE);
|
|
if (Buffer == NULL)
|
|
{
|
|
LOG_ERROR(NDIS_STATUS_RESOURCES);
|
|
return (!TimerShuttingDown);
|
|
}
|
|
|
|
KeQuerySystemTime(&SystemTime);
|
|
|
|
ExSystemTimeToLocalTime(&SystemTime, &LocalTime);
|
|
|
|
// Convert this to number of seconds since 1980
|
|
if (!RtlTimeToSecondsSince1980(&LocalTime, &CurrentTime))
|
|
{
|
|
// Could not convert! Bail out.
|
|
LOG_ERROR(NDIS_STATUS_BUFFER_OVERFLOW);
|
|
FREE_MEM(Buffer);
|
|
return (!TimerShuttingDown);
|
|
}
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&pIntF->FileName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
Status = ZwCreateFile(&FileHandle,
|
|
SYNCHRONIZE | FILE_WRITE_DATA,
|
|
&ObjectAttributes,
|
|
&IoStatus,
|
|
NULL,
|
|
0,
|
|
0,
|
|
FILE_OVERWRITE_IF,
|
|
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE | FILE_SEQUENTIAL_ONLY,
|
|
NULL,
|
|
0);
|
|
if (Status == STATUS_SUCCESS)
|
|
{
|
|
do
|
|
{
|
|
Offset.QuadPart = 0;
|
|
Space = DISK_BUFFER_SIZE - sizeof(DISK_HEADER);
|
|
DskHdr = (PDISK_HEADER)Buffer;
|
|
pDskEntry = (PDISK_ENTRY)(Buffer + sizeof(DISK_HEADER));
|
|
DskHdr->Signature = DISK_HDR_SIGNATURE;
|
|
DskHdr->Version = DISK_HDR_VERSION;
|
|
DskHdr->NumberOfArpEntries = pIntF->NumCacheEntries;
|
|
DskHdr->TimeStamp = CurrentTime;
|
|
|
|
for (i =0; i < ARP_TABLE_SIZE; i++)
|
|
{
|
|
for (ArpEntry = pIntF->ArpCache[i];
|
|
ArpEntry != NULL;
|
|
ArpEntry = ArpEntry->Next)
|
|
{
|
|
UINT Size;
|
|
|
|
Size = sizeof(DISK_ENTRY) + ((ArpEntry->HwAddr.SubAddress != NULL) ?
|
|
SIZE_4N(ArpEntry->HwAddr.SubAddress->NumberOfDigits) : 0);
|
|
if (Space < Size)
|
|
{
|
|
Status = ZwWriteFile(FileHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
Buffer,
|
|
DISK_BUFFER_SIZE - Space,
|
|
&Offset,
|
|
NULL);
|
|
if (Status != STATUS_SUCCESS)
|
|
{
|
|
LOG_ERROR(Status);
|
|
break;
|
|
}
|
|
|
|
Space = DISK_BUFFER_SIZE;
|
|
pDskEntry = (PDISK_ENTRY)Buffer;
|
|
Offset.QuadPart += (DISK_BUFFER_SIZE - Space);
|
|
}
|
|
|
|
pDskEntry->IpAddr = ArpEntry->IpAddr;
|
|
pDskEntry->AtmAddr.AddrType = (UCHAR)ArpEntry->HwAddr.Address.AddressType;
|
|
pDskEntry->AtmAddr.AddrLen = (UCHAR)ArpEntry->HwAddr.Address.NumberOfDigits;
|
|
COPY_MEM(pDskEntry->AtmAddr.Address,
|
|
ArpEntry->HwAddr.Address.Address,
|
|
pDskEntry->AtmAddr.AddrLen);
|
|
|
|
pDskEntry->AtmAddr.SubAddrLen = 0;
|
|
if (ArpEntry->HwAddr.SubAddress != NULL)
|
|
{
|
|
pDskEntry->AtmAddr.SubAddrLen = (UCHAR)ArpEntry->HwAddr.SubAddress->NumberOfDigits;
|
|
pDskEntry->AtmAddr.SubAddrType = (UCHAR)ArpEntry->HwAddr.SubAddress->AddressType;
|
|
COPY_MEM((PUCHAR)pDskEntry + sizeof(DISK_ENTRY),
|
|
ArpEntry->HwAddr.SubAddress->Address,
|
|
pDskEntry->AtmAddr.SubAddrLen);
|
|
}
|
|
|
|
Space -= Size;
|
|
(PUCHAR)pDskEntry += Size;
|
|
}
|
|
|
|
if (Status != STATUS_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
} while (FALSE);
|
|
|
|
if ((Status == STATUS_SUCCESS) && (Space < DISK_BUFFER_SIZE))
|
|
{
|
|
Status = ZwWriteFile(FileHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
Buffer,
|
|
DISK_BUFFER_SIZE - Space,
|
|
&Offset,
|
|
NULL);
|
|
}
|
|
|
|
ZwClose(FileHandle);
|
|
}
|
|
|
|
FREE_MEM(Buffer);
|
|
|
|
return (!TimerShuttingDown);
|
|
}
|
|
|
|
|