Added bit counting and inverting functions to address.

Broke out some functions in info.c -- They still don't work properly but
are improving.
Added setting of netmask in datalink/lan.c from the registry, broke out
registry reading function.

svn path=/trunk/; revision=8661
This commit is contained in:
Art Yerkes 2004-03-12 04:21:59 +00:00
parent 29d063166b
commit 7b9bc747c8
7 changed files with 308 additions and 127 deletions

View file

@ -15,7 +15,6 @@
#include <receive.h>
#include <arp.h>
NDIS_HANDLE NdisProtocolHandle = (NDIS_HANDLE)NULL;
BOOLEAN ProtocolRegistered = FALSE;
LIST_ENTRY AdapterListHead;
@ -590,6 +589,72 @@ VOID LANTransmit(
}
}
static NTSTATUS
OpenRegistryKey( PNDIS_STRING RegistryPath, PHANDLE RegHandle ) {
OBJECT_ATTRIBUTES Attributes;
NTSTATUS Status;
InitializeObjectAttributes(&Attributes, RegistryPath, OBJ_CASE_INSENSITIVE, 0, 0);
Status = ZwOpenKey(RegHandle, GENERIC_READ, &Attributes);
return Status;
}
static NTSTATUS ReadIPAddressFromRegistry( HANDLE RegHandle,
PWCHAR RegistryValue,
PIP_ADDRESS *Address ) {
UNICODE_STRING ValueName;
UNICODE_STRING UnicodeAddress;
NTSTATUS Status;
ULONG ResultLength;
UCHAR buf[1024];
PKEY_VALUE_PARTIAL_INFORMATION Information = (PKEY_VALUE_PARTIAL_INFORMATION)buf;
ANSI_STRING AnsiAddress;
ULONG AnsiLen;
RtlInitUnicodeString(&ValueName, RegistryValue);
Status =
ZwQueryValueKey(RegHandle,
&ValueName,
KeyValuePartialInformation,
Information,
sizeof(buf),
&ResultLength);
if (!NT_SUCCESS(Status))
return Status;
/* IP address is stored as a REG_MULTI_SZ - we only pay attention to the first one though */
TI_DbgPrint(MIN_TRACE, ("Information DataLength: 0x%x\n", Information->DataLength));
UnicodeAddress.Buffer = (PWCHAR)&Information->Data;
UnicodeAddress.Length = Information->DataLength;
UnicodeAddress.MaximumLength = Information->DataLength;
AnsiLen = RtlUnicodeStringToAnsiSize(&UnicodeAddress);
if(!AnsiLen)
return STATUS_NO_MEMORY;
AnsiAddress.Buffer = ExAllocatePoolWithTag(PagedPool, AnsiLen, 0x01020304);
if(!AnsiAddress.Buffer)
return STATUS_NO_MEMORY;
AnsiAddress.Length = AnsiLen;
AnsiAddress.MaximumLength = AnsiLen;
Status = RtlUnicodeStringToAnsiString(&AnsiAddress, &UnicodeAddress, FALSE);
if (!NT_SUCCESS(Status)) {
ExFreePool(AnsiAddress.Buffer);
return STATUS_UNSUCCESSFUL;
}
AnsiAddress.Buffer[AnsiAddress.Length] = 0;
*Address = AddrBuildIPv4(inet_addr(AnsiAddress.Buffer));
if (!Address) {
ExFreePool(AnsiAddress.Buffer);
return STATUS_UNSUCCESSFUL;
}
return *Address ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
}
VOID BindAdapter(
PLAN_ADAPTER Adapter,
@ -605,11 +670,14 @@ VOID BindAdapter(
{
INT i;
PIP_INTERFACE IF;
PIP_ADDRESS Address;
PIP_ADDRESS Address = 0;
PIP_ADDRESS Netmask = 0;
PNDIS_PACKET Packet;
NDIS_STATUS NdisStatus;
LLIP_BIND_INFO BindInfo;
ULONG Lookahead = LOOKAHEAD_SIZE;
NTSTATUS Status;
HANDLE RegHandle = 0;
TI_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
@ -655,100 +723,59 @@ VOID BindAdapter(
return;
}
{
/*
* Query per-adapter configuration from the registry
* In case anyone is curious: there *is* an Ndis configuration api
* for this sort of thing, but it doesn't really support things like
* REG_MULTI_SZ very well, and there is a note in the DDK that says that
* protocol drivers developed for win2k and above just use the native
* services (ZwOpenKey, etc).
*/
OBJECT_ATTRIBUTES Attributes;
HANDLE RegHandle;
NTSTATUS Status;
UNICODE_STRING ValueName;
UCHAR buf[1024];
PKEY_VALUE_PARTIAL_INFORMATION Information = (PKEY_VALUE_PARTIAL_INFORMATION)buf;
ULONG ResultLength;
ANSI_STRING AnsiAddress;
UNICODE_STRING UnicodeAddress;
ULONG AnsiLen;
InitializeObjectAttributes(&Attributes, RegistryPath, OBJ_CASE_INSENSITIVE, 0, 0);
Status = ZwOpenKey(&RegHandle, GENERIC_READ, &Attributes);
if(!NT_SUCCESS(Status))
{
TI_DbgPrint(MIN_TRACE, ("Unable to open protocol-specific registry key: 0x%x\n", Status));
/* XXX how do we proceed? No ip address, no parameters... do we guess? */
FreeTDPackets(Adapter);
IPDestroyInterface(Adapter->Context);
return;
}
RtlInitUnicodeString(&ValueName, L"IPAddress");
ZwQueryValueKey(RegHandle, &ValueName, KeyValuePartialInformation, Information, sizeof(buf), &ResultLength);
ZwClose(RegHandle);
/* IP address is stored as a REG_MULTI_SZ - we only pay attention to the first one though */
TI_DbgPrint(MIN_TRACE, ("Information DataLength: 0x%x\n", Information->DataLength));
UnicodeAddress.Buffer = (PWCHAR)&Information->Data;
UnicodeAddress.Length = Information->DataLength;
UnicodeAddress.MaximumLength = Information->DataLength;
AnsiLen = RtlUnicodeStringToAnsiSize(&UnicodeAddress);
if(!AnsiLen)
{
TI_DbgPrint(MIN_TRACE, ("Unable to calculate address length\n"));
FreeTDPackets(Adapter);
IPDestroyInterface(Adapter->Context);
return;
}
AnsiAddress.Buffer = ExAllocatePoolWithTag(PagedPool, AnsiLen, 0x01020304);
if(!AnsiAddress.Buffer)
{
TI_DbgPrint(MIN_TRACE, ("ExAllocatePoolWithTag() failed.\n"));
FreeTDPackets(Adapter);
IPDestroyInterface(Adapter->Context);
return;
}
AnsiAddress.Length = AnsiLen;
AnsiAddress.MaximumLength = AnsiLen;
Status = RtlUnicodeStringToAnsiString(&AnsiAddress, &UnicodeAddress, FALSE);
if (!NT_SUCCESS(Status))
{
TI_DbgPrint(MIN_TRACE, ("RtlUnicodeStringToAnsiString() failed with Status 0x%lx.\n", Status));
FreeTDPackets(Adapter);
IPDestroyInterface(Adapter->Context);
return;
}
AnsiAddress.Buffer[AnsiAddress.Length] = 0;
Address = AddrBuildIPv4(inet_addr(AnsiAddress.Buffer));
if (!Address) {
TI_DbgPrint(MIN_TRACE, ("AddrBuildIPv4() failed.\n"));
FreeTDPackets(Adapter);
IPDestroyInterface(Adapter->Context);
return;
}
TI_DbgPrint(MID_TRACE, ("--> Our IP address on this interface: '%s'\n", A2S(Address)));
}
/*
* Query per-adapter configuration from the registry
* In case anyone is curious: there *is* an Ndis configuration api
* for this sort of thing, but it doesn't really support things like
* REG_MULTI_SZ very well, and there is a note in the DDK that says that
* protocol drivers developed for win2k and above just use the native
* services (ZwOpenKey, etc).
*/
Status = OpenRegistryKey( RegistryPath, &RegHandle );
if(NT_SUCCESS(Status))
Status = ReadIPAddressFromRegistry( RegHandle, L"IPAddress",
&Address );
if(NT_SUCCESS(Status))
Status = ReadIPAddressFromRegistry( RegHandle, L"SubnetMask",
&Netmask );
if(!NT_SUCCESS(Status) || !Address || !Netmask)
{
TI_DbgPrint(MIN_TRACE, ("Unable to open protocol-specific registry key: 0x%x\n", Status));
/* XXX how do we proceed? No ip address, no parameters... do we guess? */
if(RegHandle)
ZwClose(RegHandle);
if(Address) Address->Free(Address);
if(Netmask) Netmask->Free(Netmask);
FreeTDPackets(Adapter);
IPDestroyInterface(IF);
return;
}
TI_DbgPrint
(MID_TRACE,
("--> Our IP address on this interface: '%s'\n",
A2S(Address)));
TI_DbgPrint
(MID_TRACE,
("--> Our net mask on this interface: '%s'\n",
A2S(Netmask)));
/* Create a net table entry for this interface */
if (!IPCreateNTE(IF, Address, 8)) {
if (!IPCreateNTE(IF, Address, AddrCountPrefixBits(Netmask))) {
Netmask->Free(Netmask);
TI_DbgPrint(MIN_TRACE, ("IPCreateNTE() failed.\n"));
FreeTDPackets(Adapter);
IPDestroyInterface(IF);
return;
}
Netmask->Free(Netmask);
/* Reference the interface for the NTE. The reference
for the address is just passed on to the NTE */
ReferenceObject(IF);

View file

@ -78,6 +78,10 @@ PADDRESS_FILE AddrSearchNext(
unsigned long PASCAL inet_addr(const char*);
ULONG IPv4NToHl( ULONG Address );
UINT AddrCountPrefixBits( PIP_ADDRESS Netmask );
#endif /* __ADDRESS_H */
/* EOF */

View file

@ -7,6 +7,8 @@
#ifndef __INFO_H
#define __INFO_H
#define MAX_PHYSADDR_LEN 8
#define MAX_IFDESCR_LEN 256
typedef struct IPSNMP_INFO {
ULONG Forwarding;
@ -60,7 +62,31 @@ typedef struct IPROUTE_ENTRY {
ULONG Info;
} IPROUTE_ENTRY, *PIPROUTE_ENTRY;
typedef struct IFENTRY {
ULONG Index;
ULONG Type;
ULONG Mtu;
ULONG Speed;
ULONG PhysAddrLen;
UCHAR PhysAddr[MAX_PHYSADDR_LEN];
ULONG AdminStatus;
ULONG OperStatus;
ULONG LastChange;
ULONG InOctets;
ULONG InUcastPackets;
ULONG InDiscards;
ULONG InErrors;
ULONG InUnknownProtos;
ULONG OutOctets;
ULONG OutUcastPackets;
ULONG OutDiscards;
ULONG OutErrors;
ULONG OutQLen;
ULONG DescrLen;
} IFENTRY, *PIFENTRY;
#define IP_MIB_STATS_ID 1
#define IF_MIB_STATS_ID 1
#ifndef IP_MIB_ADDRTABLE_ENTRY_ID
#define IP_MIB_ADDRTABLE_ENTRY_ID 0x102
#endif

View file

@ -264,6 +264,8 @@ NTSTATUS IPStartup(
NTSTATUS IPShutdown(
VOID);
#endif /* __IP_H */
/* EOF */

View file

@ -125,6 +125,7 @@ extern NDIS_HANDLE GlobalBufferPool;
extern KSPIN_LOCK EntityListLock;
extern TDIEntityID *EntityList;
extern ULONG EntityCount;
extern ULONG EntityMax;
extern UDP_STATISTICS UDPStats;
#endif /* __TCPIP_H */

View file

@ -54,6 +54,35 @@ PCHAR A2S(
#endif /* DBG */
ULONG IPv4NToHl( ULONG Address ) {
return
((Address & 0xff) << 24) |
((Address & 0xff00) << 8) |
((Address >> 8) & 0xff00) |
((Address >> 24) & 0xff);
}
UINT AddrCountPrefixBits( PIP_ADDRESS Netmask ) {
UINT Prefix = 0;
if( Netmask->Type == IP_ADDRESS_V4 ) {
ULONG BitTest = 0x80000000;
/* The mask has been read in network order. Put it in host order
* in order to scan it. */
ULONG TestMask = IPv4NToHl(Netmask->Address.IPv4Address);
while( (BitTest & TestMask) == BitTest ) {
Prefix++;
BitTest >>= 1;
}
return Prefix;
} else {
TI_DbgPrint(DEBUG_DATALINK, ("Don't know address type %d\n",
Netmask->Type));
return 0;
}
}
VOID IPAddressFree(
PVOID Object)

View file

@ -201,6 +201,127 @@ TDI_STATUS IPTdiQueryInformationEx(
return TDI_INVALID_PARAMETER;
}
TDI_STATUS InfoTdiQueryListEntities(PNDIS_BUFFER Buffer,
UINT BufSize,
PUINT BufferSize)
{
UINT Count, Size, Temp;
KIRQL OldIrql;
PLIST_ENTRY CurrentIFEntry;
/* Count Adapters */
KeAcquireSpinLock(&InterfaceListLock, &OldIrql);
CurrentIFEntry = InterfaceListHead.Flink;
Count = EntityCount;
while( CurrentIFEntry != &InterfaceListHead ) {
Count++;
CurrentIFEntry = CurrentIFEntry->Flink;
}
KeReleaseSpinLock(&InterfaceListLock, OldIrql);
Size = Count * sizeof(TDIEntityID);
*BufferSize = Size;
if (BufSize < Size)
{
/* The buffer is too small to contain requested data */
return TDI_BUFFER_TOO_SMALL;
}
DbgPrint("About to copy %d TDIEntityIDs (%d bytes) to user\n",
Count, Size);
KeAcquireSpinLock(&EntityListLock, &OldIrql);
/* Update entity list */
for( Temp = EntityCount; Temp < Count; Temp++ ) {
EntityList[Temp].tei_entity = IF_ENTITY;
EntityList[Temp].tei_instance = Temp - EntityCount;
}
EntityMax = Count;
/* Return entity list */
Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)EntityList, Size);
KeReleaseSpinLock(&EntityListLock, OldIrql);
*BufferSize = Size;
return TDI_SUCCESS;
}
TDI_STATUS InfoTdiQueryGetInterfaceMIB(TDIObjectID *ID,
PNDIS_BUFFER Buffer,
UINT BufSize,
PUINT BufferSize) {
PIFENTRY OutData;
UINT ListedIfIndex, Count, Size;
PLIST_ENTRY CurrentADEEntry;
PADDRESS_ENTRY CurrentADE;
PLIST_ENTRY CurrentIFEntry;
PIP_INTERFACE CurrentIF;
PCHAR IFDescr;
KIRQL OldIrql;
OutData = ExAllocatePool( NonPagedPool,
sizeof(IFENTRY) + MAX_IFDESCR_LEN );
if( !OutData ) return STATUS_NO_MEMORY;
RtlZeroMemory( OutData,sizeof(IFENTRY) + MAX_IFDESCR_LEN );
KeAcquireSpinLock(&EntityListLock, &OldIrql);
ListedIfIndex = ID->toi_entity.tei_instance - EntityCount;
if( ListedIfIndex > EntityMax ) {
KeReleaseSpinLock(&EntityListLock,OldIrql);
return TDI_INVALID_REQUEST;
}
CurrentIFEntry = InterfaceListHead.Flink;
for( Count = 0; Count < ListedIfIndex; Count++ )
CurrentIFEntry = CurrentIFEntry->Flink;
CurrentIF = CONTAINING_RECORD(CurrentIFEntry, IP_INTERFACE, ListEntry);
CurrentADEEntry = CurrentIF->ADEListHead.Flink;
if( CurrentADEEntry == &CurrentIF->ADEListHead ) {
KeReleaseSpinLock( &EntityListLock, OldIrql );
return TDI_INVALID_REQUEST;
}
CurrentADE = CONTAINING_RECORD(CurrentADEEntry, ADDRESS_ENTRY, ListEntry);
OutData->Index = Count + 1; /* XXX - arty What goes here?? */
OutData->Type = CurrentADE->Type;
OutData->Mtu = CurrentIF->MTU;
OutData->Speed = 10000000; /* XXX - arty Not sure */
memcpy(OutData->PhysAddr,
CurrentIF->Address,CurrentIF->AddressLength);
OutData->PhysAddrLen = CurrentIF->AddressLength;
OutData->AdminStatus = TRUE;
OutData->OperStatus = TRUE;
IFDescr = (PCHAR)&OutData[1];
strcpy(IFDescr,"ethernet adapter");
OutData->DescrLen = strlen(IFDescr);
IFDescr = IFDescr + strlen(IFDescr);
Size = IFDescr - (PCHAR)OutData;
KeReleaseSpinLock(&InterfaceListLock, OldIrql);
*BufferSize = Size;
if( BufSize < Size ) {
return TDI_BUFFER_TOO_SMALL;
} else {
CopyBufferToBufferChain(Buffer, 0, (PUCHAR)&OutData, Size);
return TDI_SUCCESS;
}
}
TDI_STATUS InfoTdiQueryInformationEx(
PTDI_REQUEST Request,
TDIObjectID *ID,
@ -250,47 +371,18 @@ TDI_STATUS InfoTdiQueryInformationEx(
return TDI_INVALID_PARAMETER;
}
/* Count Adapters */
KeAcquireSpinLock(&InterfaceListLock, &OldIrql);
return InfoTdiQueryListEntities(Buffer, BufSize, BufferSize);
}
CurrentIFEntry = InterfaceListHead.Flink;
Count = EntityCount;
/* Get an IFENTRY */
if (ID->toi_class == INFO_CLASS_PROTOCOL &&
ID->toi_type == INFO_TYPE_PROVIDER &&
ID->toi_id == IF_MIB_STATS_ID)
{
if(ID->toi_entity.tei_entity != IF_ENTITY)
return TDI_INVALID_REQUEST;
while( CurrentIFEntry != &InterfaceListHead ) {
Count++;
CurrentIFEntry = CurrentIFEntry->Flink;
}
KeReleaseSpinLock(&InterfaceListLock, OldIrql);
Size = Count * sizeof(TDIEntityID);
*BufferSize = Size;
if (BufSize < Size)
{
/* The buffer is too small to contain requested data */
return TDI_BUFFER_TOO_SMALL;
}
DbgPrint("About to copy %d TDIEntityIDs (%d bytes) to user\n",
Count, Size);
KeAcquireSpinLock(&EntityListLock, &OldIrql);
/* Update entity list */
for( Temp = EntityCount; Temp < Count; Temp++ ) {
EntityList[Temp].tei_entity = IF_ENTITY;
EntityList[Temp].tei_instance = Temp - EntityCount;
}
/* Return entity list */
Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)EntityList, Size);
KeReleaseSpinLock(&EntityListLock, OldIrql);
*BufferSize = Size;
return TDI_SUCCESS;
return InfoTdiQueryGetInterfaceMIB(ID, Buffer, BufSize, BufferSize);
}
if ((Entity != CL_TL_ENTITY) && (Entity != CO_TL_ENTITY))