Commit 9e919b8a authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

inetmib1: Sort the tables keyed by IP address, and use bsearch to find entries in them.

parent 67794694
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "config.h" #include "config.h"
#include <assert.h> #include <assert.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h>
#include <limits.h> #include <limits.h>
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
...@@ -317,26 +318,35 @@ struct GenericTable ...@@ -317,26 +318,35 @@ struct GenericTable
BYTE entries[1]; BYTE entries[1];
}; };
/* Finds the index in table whose IP address (at offset addressOffset within the static DWORD oidToIpAddr(AsnObjectIdentifier *oid)
* entry) matches that given the OID, which is assumed to have at least 4 IDs.
*/
static UINT findOIDIPAddressInTable(AsnObjectIdentifier *oid,
struct GenericTable *table, size_t tableEntrySize, size_t addressOffset)
{ {
DWORD addr; assert(oid && oid->idLength >= 4);
UINT i, index = 0;
/* Map the IDs to an IP address in little-endian order */ /* Map the IDs to an IP address in little-endian order */
addr = (BYTE)oid->ids[3] << 24 | (BYTE)oid->ids[2] << 16 | return (BYTE)oid->ids[3] << 24 | (BYTE)oid->ids[2] << 16 |
(BYTE)oid->ids[1] << 8 | (BYTE)oid->ids[0]; (BYTE)oid->ids[1] << 8 | (BYTE)oid->ids[0];
/* Find the item whose address matches */ }
for (i = 0; !index && i < table->numEntries; i++)
{ typedef void (*oidToKeyFunc)(AsnObjectIdentifier *oid, void *dst);
DWORD tableAddr = typedef int (*compareFunc)(const void *key, const void *value);
*(DWORD *)(table->entries + i * tableEntrySize + addressOffset);
static UINT findValueInTable(AsnObjectIdentifier *oid,
struct GenericTable *table, size_t tableEntrySize, oidToKeyFunc makeKey,
compareFunc compare)
{
UINT index = 0;
void *key = HeapAlloc(GetProcessHeap(), 0, tableEntrySize);
if (addr == tableAddr) if (key)
index = i + 1; {
void *value;
makeKey(oid, key);
value = bsearch(key, table->entries, table->numEntries, tableEntrySize,
compare);
if (value)
index = ((BYTE *)value - (BYTE *)table->entries) / tableEntrySize
+ 1;
HeapFree(GetProcessHeap(), 0, key);
} }
return index; return index;
} }
...@@ -352,7 +362,8 @@ static UINT findOIDIPAddressInTable(AsnObjectIdentifier *oid, ...@@ -352,7 +362,8 @@ static UINT findOIDIPAddressInTable(AsnObjectIdentifier *oid,
*/ */
static AsnInteger32 getItemAndIpAddressInstanceFromOid(AsnObjectIdentifier *oid, static AsnInteger32 getItemAndIpAddressInstanceFromOid(AsnObjectIdentifier *oid,
AsnObjectIdentifier *base, BYTE bPduType, struct GenericTable *table, AsnObjectIdentifier *base, BYTE bPduType, struct GenericTable *table,
size_t tableEntrySize, size_t addressOffset, UINT *item, UINT *instance) size_t tableEntrySize, oidToKeyFunc makeKey, compareFunc compare,
UINT *item, UINT *instance)
{ {
AsnInteger32 ret = SNMP_ERRORSTATUS_NOERROR; AsnInteger32 ret = SNMP_ERRORSTATUS_NOERROR;
...@@ -398,8 +409,8 @@ static AsnInteger32 getItemAndIpAddressInstanceFromOid(AsnObjectIdentifier *oid, ...@@ -398,8 +409,8 @@ static AsnInteger32 getItemAndIpAddressInstanceFromOid(AsnObjectIdentifier *oid,
AsnObjectIdentifier ipOid = { 4, oid->ids + base->idLength + 1 AsnObjectIdentifier ipOid = { 4, oid->ids + base->idLength + 1
}; };
*instance = findOIDIPAddressInTable(&ipOid, table, *instance = findValueInTable(&ipOid, table, tableEntrySize,
tableEntrySize, addressOffset) + 1; makeKey, compare) + 1;
if (*instance > table->numEntries) if (*instance > table->numEntries)
ret = SNMP_ERRORSTATUS_NOSUCHNAME; ret = SNMP_ERRORSTATUS_NOSUCHNAME;
} }
...@@ -419,8 +430,8 @@ static AsnInteger32 getItemAndIpAddressInstanceFromOid(AsnObjectIdentifier *oid, ...@@ -419,8 +430,8 @@ static AsnInteger32 getItemAndIpAddressInstanceFromOid(AsnObjectIdentifier *oid,
AsnObjectIdentifier ipOid = { 4, oid->ids + base->idLength + 1 AsnObjectIdentifier ipOid = { 4, oid->ids + base->idLength + 1
}; };
*instance = findOIDIPAddressInTable(&ipOid, table, *instance = findValueInTable(&ipOid, table, tableEntrySize,
tableEntrySize, addressOffset); makeKey, compare);
if (!*instance) if (!*instance)
ret = SNMP_ERRORSTATUS_NOSUCHNAME; ret = SNMP_ERRORSTATUS_NOSUCHNAME;
} }
...@@ -632,16 +643,30 @@ static struct structToAsnValue mib2IpAddrMap[] = { ...@@ -632,16 +643,30 @@ static struct structToAsnValue mib2IpAddrMap[] = {
static void mib2IpAddrInit(void) static void mib2IpAddrInit(void)
{ {
DWORD size = 0, ret = GetIpAddrTable(NULL, &size, FALSE); DWORD size = 0, ret = GetIpAddrTable(NULL, &size, TRUE);
if (ret == ERROR_INSUFFICIENT_BUFFER) if (ret == ERROR_INSUFFICIENT_BUFFER)
{ {
ipAddrTable = HeapAlloc(GetProcessHeap(), 0, size); ipAddrTable = HeapAlloc(GetProcessHeap(), 0, size);
if (ipAddrTable) if (ipAddrTable)
GetIpAddrTable(ipAddrTable, &size, FALSE); GetIpAddrTable(ipAddrTable, &size, TRUE);
} }
} }
static void oidToIpAddrRow(AsnObjectIdentifier *oid, void *dst)
{
MIB_IPADDRROW *row = dst;
row->dwAddr = oidToIpAddr(oid);
}
static int compareIpAddrRow(const void *a, const void *b)
{
const MIB_IPADDRROW *key = a, *value = b;
return key->dwAddr - value->dwAddr;
}
static BOOL mib2IpAddrQuery(BYTE bPduType, SnmpVarBind *pVarBind, static BOOL mib2IpAddrQuery(BYTE bPduType, SnmpVarBind *pVarBind,
AsnInteger32 *pErrorStatus) AsnInteger32 *pErrorStatus)
{ {
...@@ -657,7 +682,7 @@ static BOOL mib2IpAddrQuery(BYTE bPduType, SnmpVarBind *pVarBind, ...@@ -657,7 +682,7 @@ static BOOL mib2IpAddrQuery(BYTE bPduType, SnmpVarBind *pVarBind,
case SNMP_PDU_GETNEXT: case SNMP_PDU_GETNEXT:
*pErrorStatus = getItemAndIpAddressInstanceFromOid(&pVarBind->name, *pErrorStatus = getItemAndIpAddressInstanceFromOid(&pVarBind->name,
&myOid, bPduType, (struct GenericTable *)ipAddrTable, &myOid, bPduType, (struct GenericTable *)ipAddrTable,
sizeof(MIB_IPADDRROW), FIELD_OFFSET(MIB_IPADDRROW, dwAddr), &item, sizeof(MIB_IPADDRROW), oidToIpAddrRow, compareIpAddrRow, &item,
&tableIndex); &tableIndex);
if (!*pErrorStatus) if (!*pErrorStatus)
{ {
...@@ -701,16 +726,30 @@ static struct structToAsnValue mib2IpRouteMap[] = { ...@@ -701,16 +726,30 @@ static struct structToAsnValue mib2IpRouteMap[] = {
static void mib2IpRouteInit(void) static void mib2IpRouteInit(void)
{ {
DWORD size = 0, ret = GetIpForwardTable(NULL, &size, FALSE); DWORD size = 0, ret = GetIpForwardTable(NULL, &size, TRUE);
if (ret == ERROR_INSUFFICIENT_BUFFER) if (ret == ERROR_INSUFFICIENT_BUFFER)
{ {
ipRouteTable = HeapAlloc(GetProcessHeap(), 0, size); ipRouteTable = HeapAlloc(GetProcessHeap(), 0, size);
if (ipRouteTable) if (ipRouteTable)
GetIpForwardTable(ipRouteTable, &size, FALSE); GetIpForwardTable(ipRouteTable, &size, TRUE);
} }
} }
static void oidToIpForwardRow(AsnObjectIdentifier *oid, void *dst)
{
MIB_IPFORWARDROW *row = dst;
row->dwForwardDest = oidToIpAddr(oid);
}
static int compareIpForwardRow(const void *a, const void *b)
{
const MIB_IPFORWARDROW *key = a, *value = b;
return key->dwForwardDest - value->dwForwardDest;
}
static BOOL mib2IpRouteQuery(BYTE bPduType, SnmpVarBind *pVarBind, static BOOL mib2IpRouteQuery(BYTE bPduType, SnmpVarBind *pVarBind,
AsnInteger32 *pErrorStatus) AsnInteger32 *pErrorStatus)
{ {
...@@ -726,8 +765,8 @@ static BOOL mib2IpRouteQuery(BYTE bPduType, SnmpVarBind *pVarBind, ...@@ -726,8 +765,8 @@ static BOOL mib2IpRouteQuery(BYTE bPduType, SnmpVarBind *pVarBind,
case SNMP_PDU_GETNEXT: case SNMP_PDU_GETNEXT:
*pErrorStatus = getItemAndIpAddressInstanceFromOid(&pVarBind->name, *pErrorStatus = getItemAndIpAddressInstanceFromOid(&pVarBind->name,
&myOid, bPduType, (struct GenericTable *)ipRouteTable, &myOid, bPduType, (struct GenericTable *)ipRouteTable,
sizeof(MIB_IPFORWARDROW), sizeof(MIB_IPFORWARDROW), oidToIpForwardRow, compareIpForwardRow,
FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardDest), &item, &tableIndex); &item, &tableIndex);
if (!*pErrorStatus) if (!*pErrorStatus)
{ {
assert(tableIndex); assert(tableIndex);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment