2 * Copyright 2008 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(inetmib1
);
35 static void copyInt(AsnAny
*value
, void *src
)
37 value
->asnType
= ASN_INTEGER
;
38 value
->asnValue
.number
= *(DWORD
*)src
;
41 static void setStringValue(AsnAny
*value
, BYTE type
, DWORD len
, BYTE
*str
)
45 strValue
.asnType
= type
;
46 strValue
.asnValue
.string
.stream
= str
;
47 strValue
.asnValue
.string
.length
= len
;
48 strValue
.asnValue
.string
.dynamic
= TRUE
;
49 SnmpUtilAsnAnyCpy(value
, &strValue
);
52 static void copyLengthPrecededString(AsnAny
*value
, void *src
)
54 DWORD len
= *(DWORD
*)src
;
56 setStringValue(value
, ASN_OCTETSTRING
, len
, (BYTE
*)src
+ sizeof(DWORD
));
59 typedef void (*copyValueFunc
)(AsnAny
*value
, void *src
);
61 struct structToAsnValue
67 static AsnInteger32
mapStructEntryToValue(struct structToAsnValue
*map
,
68 UINT mapLen
, void *record
, UINT id
, BYTE bPduType
, SnmpVarBind
*pVarBind
)
70 /* OIDs are 1-based */
72 return SNMP_ERRORSTATUS_NOSUCHNAME
;
75 return SNMP_ERRORSTATUS_NOSUCHNAME
;
77 return SNMP_ERRORSTATUS_NOSUCHNAME
;
78 map
[id
].copy(&pVarBind
->value
, (BYTE
*)record
+ map
[id
].offset
);
79 return SNMP_ERRORSTATUS_NOERROR
;
82 static void copyIpAddr(AsnAny
*value
, void *src
)
84 setStringValue(value
, ASN_IPADDRESS
, sizeof(DWORD
), src
);
87 static UINT mib2
[] = { 1,3,6,1,2,1 };
88 static UINT mib2System
[] = { 1,3,6,1,2,1,1 };
90 typedef BOOL (*varqueryfunc
)(BYTE bPduType
, SnmpVarBind
*pVarBind
,
91 AsnInteger32
*pErrorStatus
);
93 struct mibImplementation
95 AsnObjectIdentifier name
;
98 void (*cleanup
)(void);
101 static UINT mib2IfNumber
[] = { 1,3,6,1,2,1,2,1 };
102 static PMIB_IFTABLE ifTable
;
104 static void mib2IfNumberInit(void)
106 DWORD size
= 0, ret
= GetIfTable(NULL
, &size
, FALSE
);
108 if (ret
== ERROR_INSUFFICIENT_BUFFER
)
110 MIB_IFTABLE
*table
= HeapAlloc(GetProcessHeap(), 0, size
);
113 if (!GetIfTable(table
, &size
, FALSE
)) ifTable
= table
;
114 else HeapFree(GetProcessHeap(), 0, table
);
119 static void mib2IfNumberCleanup(void)
121 HeapFree(GetProcessHeap(), 0, ifTable
);
124 static BOOL
mib2IfNumberQuery(BYTE bPduType
, SnmpVarBind
*pVarBind
,
125 AsnInteger32
*pErrorStatus
)
127 AsnObjectIdentifier numberOid
= DEFINE_OID(mib2IfNumber
);
130 TRACE("(0x%02x, %s, %p)\n", bPduType
, SnmpUtilOidToA(&pVarBind
->name
),
136 case SNMP_PDU_GETNEXT
:
137 if ((bPduType
== SNMP_PDU_GET
&&
138 !SnmpUtilOidNCmp(&pVarBind
->name
, &numberOid
, numberOid
.idLength
))
139 || SnmpUtilOidNCmp(&pVarBind
->name
, &numberOid
, numberOid
.idLength
)
142 DWORD numIfs
= ifTable
? ifTable
->dwNumEntries
: 0;
144 copyInt(&pVarBind
->value
, &numIfs
);
145 if (bPduType
== SNMP_PDU_GETNEXT
)
147 SnmpUtilOidFree(&pVarBind
->name
);
148 SnmpUtilOidCpy(&pVarBind
->name
, &numberOid
);
150 *pErrorStatus
= SNMP_ERRORSTATUS_NOERROR
;
154 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
155 /* Caller deals with OID if bPduType == SNMP_PDU_GETNEXT, so don't
156 * need to set it here.
161 *pErrorStatus
= SNMP_ERRORSTATUS_READONLY
;
165 FIXME("0x%02x: unsupported PDU type\n", bPduType
);
166 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
171 static void copyOperStatus(AsnAny
*value
, void *src
)
173 value
->asnType
= ASN_INTEGER
;
174 /* The IPHlpApi definition of operational status differs from the MIB2 one,
175 * so map it to the MIB2 value.
177 switch (*(DWORD
*)src
)
179 case MIB_IF_OPER_STATUS_OPERATIONAL
:
180 value
->asnValue
.number
= MIB_IF_ADMIN_STATUS_UP
;
182 case MIB_IF_OPER_STATUS_CONNECTING
:
183 case MIB_IF_OPER_STATUS_CONNECTED
:
184 value
->asnValue
.number
= MIB_IF_ADMIN_STATUS_TESTING
;
187 value
->asnValue
.number
= MIB_IF_ADMIN_STATUS_DOWN
;
191 /* Given an OID and a base OID that it must begin with, finds the item and
192 * integer instance from the OID. E.g., given an OID foo.1.2 and a base OID
193 * foo, returns item 1 and instance 2.
194 * If bPduType is not SNMP_PDU_GETNEXT and either the item or instance is
195 * missing, returns SNMP_ERRORSTATUS_NOSUCHNAME.
196 * If bPduType is SNMP_PDU_GETNEXT, returns the successor to the item and
197 * instance, or item 1, instance 1 if either is missing.
199 static AsnInteger32
getItemAndIntegerInstanceFromOid(AsnObjectIdentifier
*oid
,
200 AsnObjectIdentifier
*base
, BYTE bPduType
, UINT
*item
, UINT
*instance
)
202 AsnInteger32 ret
= SNMP_ERRORSTATUS_NOERROR
;
206 case SNMP_PDU_GETNEXT
:
207 if (SnmpUtilOidNCmp(oid
, base
, base
->idLength
) < 0)
212 else if (!SnmpUtilOidNCmp(oid
, base
, base
->idLength
))
214 if (oid
->idLength
== base
->idLength
||
215 oid
->idLength
== base
->idLength
+ 1)
217 /* Either the table or an item within the table is specified,
218 * but the instance is not. Get the first instance.
221 if (oid
->idLength
== base
->idLength
+ 1)
222 *item
= oid
->ids
[base
->idLength
];
228 *item
= oid
->ids
[base
->idLength
];
229 *instance
= oid
->ids
[base
->idLength
+ 1] + 1;
233 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
236 if (!SnmpUtilOidNCmp(oid
, base
, base
->idLength
))
238 if (oid
->idLength
== base
->idLength
||
239 oid
->idLength
== base
->idLength
+ 1)
241 /* Either the table or an item within the table is specified,
242 * but the instance is not.
244 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
248 *item
= oid
->ids
[base
->idLength
];
249 *instance
= oid
->ids
[base
->idLength
+ 1];
253 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
258 /* Given an OID and a base OID that it must begin with, finds the item from the
259 * OID. E.g., given an OID foo.1 and a base OID foo, returns item 1.
260 * If bPduType is not SNMP_PDU_GETNEXT and the item is missing, returns
261 * SNMP_ERRORSTATUS_NOSUCHNAME.
262 * If bPduType is SNMP_PDU_GETNEXT, returns the successor to the item, or item
263 * 1 if the item is missing.
265 static AsnInteger32
getItemFromOid(AsnObjectIdentifier
*oid
,
266 AsnObjectIdentifier
*base
, BYTE bPduType
, UINT
*item
)
268 AsnInteger32 ret
= SNMP_ERRORSTATUS_NOERROR
;
272 case SNMP_PDU_GETNEXT
:
273 if (SnmpUtilOidNCmp(oid
, base
, base
->idLength
) < 0)
275 else if (!SnmpUtilOidNCmp(oid
, base
, base
->idLength
))
277 if (oid
->idLength
== base
->idLength
)
279 /* The item is missing, assume the first item */
283 *item
= oid
->ids
[base
->idLength
] + 1;
286 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
289 if (!SnmpUtilOidNCmp(oid
, base
, base
->idLength
))
291 if (oid
->idLength
== base
->idLength
)
293 /* The item is missing */
294 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
298 *item
= oid
->ids
[base
->idLength
];
300 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
304 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
315 static DWORD
oidToIpAddr(AsnObjectIdentifier
*oid
)
317 assert(oid
&& oid
->idLength
>= 4);
318 /* Map the IDs to an IP address in little-endian order */
319 return (BYTE
)oid
->ids
[3] << 24 | (BYTE
)oid
->ids
[2] << 16 |
320 (BYTE
)oid
->ids
[1] << 8 | (BYTE
)oid
->ids
[0];
323 typedef void (*oidToKeyFunc
)(AsnObjectIdentifier
*oid
, void *dst
);
324 typedef int (*compareFunc
)(const void *key
, const void *value
);
326 /* Finds the first value in the table that matches key. Returns its 1-based
327 * index if found, or 0 if not found.
329 static UINT
findValueInTable(const void *key
,
330 struct GenericTable
*table
, size_t tableEntrySize
, compareFunc compare
)
335 value
= bsearch(key
, table
->entries
, table
->numEntries
, tableEntrySize
,
338 index
= ((BYTE
*)value
- (BYTE
*)table
->entries
) / tableEntrySize
+ 1;
342 /* Finds the first value in the table that matches oid, using makeKey to
343 * convert the oid to a key for comparison. Returns the value's 1-based
344 * index if found, or 0 if not found.
346 static UINT
findOidInTable(AsnObjectIdentifier
*oid
,
347 struct GenericTable
*table
, size_t tableEntrySize
, oidToKeyFunc makeKey
,
351 void *key
= HeapAlloc(GetProcessHeap(), 0, tableEntrySize
);
356 index
= findValueInTable(key
, table
, tableEntrySize
, compare
);
357 HeapFree(GetProcessHeap(), 0, key
);
362 /* Finds the first successor to the value in the table that does matches oid,
363 * using makeKey to convert the oid to a key for comparison. A successor is
364 * a value that does not match oid, so if multiple entries match an oid, only
365 * the first will ever be returned using this method.
366 * Returns the successor's 1-based index if found, or 0 if not found.
368 static UINT
findNextOidInTable(AsnObjectIdentifier
*oid
,
369 struct GenericTable
*table
, size_t tableEntrySize
, oidToKeyFunc makeKey
,
373 void *key
= HeapAlloc(GetProcessHeap(), 0, tableEntrySize
);
378 index
= findValueInTable(key
, table
, tableEntrySize
, compare
);
381 /* Not found in table. If it's less than the first entry, return
382 * the first index. Otherwise just return 0 and let the caller
383 * handle finding the successor.
385 if (compare(key
, table
->entries
) < 0)
390 /* Skip any entries that match the same key. This enumeration will
391 * be incomplete, but it's what Windows appears to do if there are
392 * multiple entries with the same index in a table, and it avoids
395 for (++index
; index
<= table
->numEntries
&& compare(key
,
396 &table
->entries
[tableEntrySize
* index
]) == 0; ++index
)
399 HeapFree(GetProcessHeap(), 0, key
);
404 /* Given an OID and a base OID that it must begin with, finds the item and
405 * element of the table whose value matches the instance from the OID.
406 * The OID is converted to a key with the function makeKey, and compared
407 * against entries in the table with the function compare.
408 * If bPduType is not SNMP_PDU_GETNEXT and either the item or instance is
409 * missing, returns SNMP_ERRORSTATUS_NOSUCHNAME.
410 * If bPduType is SNMP_PDU_GETNEXT, returns the successor to the item and
411 * instance, or item 1, instance 1 if either is missing.
413 static AsnInteger32
getItemAndInstanceFromTable(AsnObjectIdentifier
*oid
,
414 AsnObjectIdentifier
*base
, UINT instanceLen
, BYTE bPduType
,
415 struct GenericTable
*table
, size_t tableEntrySize
, oidToKeyFunc makeKey
,
416 compareFunc compare
, UINT
*item
, UINT
*instance
)
418 AsnInteger32 ret
= SNMP_ERRORSTATUS_NOERROR
;
421 return SNMP_ERRORSTATUS_NOSUCHNAME
;
425 case SNMP_PDU_GETNEXT
:
426 if (SnmpUtilOidNCmp(oid
, base
, base
->idLength
) < 0)
428 /* Return the first item and instance from the table */
432 else if (!SnmpUtilOidNCmp(oid
, base
, base
->idLength
) &&
433 oid
->idLength
< base
->idLength
+ instanceLen
+ 1)
435 /* Either the table or an item is specified, but the instance is
439 if (oid
->idLength
>= base
->idLength
+ 1)
441 *item
= oid
->ids
[base
->idLength
];
448 else if (!SnmpUtilOidNCmp(oid
, base
, base
->idLength
) &&
449 oid
->idLength
== base
->idLength
+ instanceLen
+ 1)
451 *item
= oid
->ids
[base
->idLength
];
459 AsnObjectIdentifier instanceOid
= { instanceLen
,
460 oid
->ids
+ base
->idLength
+ 1 };
462 *instance
= findNextOidInTable(&instanceOid
, table
,
463 tableEntrySize
, makeKey
, compare
);
464 if (!*instance
|| *instance
> table
->numEntries
)
465 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
469 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
472 if (!SnmpUtilOidNCmp(oid
, base
, base
->idLength
) &&
473 oid
->idLength
== base
->idLength
+ instanceLen
+ 1)
475 *item
= oid
->ids
[base
->idLength
];
477 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
480 AsnObjectIdentifier instanceOid
= { instanceLen
,
481 oid
->ids
+ base
->idLength
+ 1 };
483 *instance
= findOidInTable(&instanceOid
, table
, tableEntrySize
,
486 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
490 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
495 static INT
setOidWithItem(AsnObjectIdentifier
*dst
, AsnObjectIdentifier
*base
,
499 AsnObjectIdentifier oid
;
502 SnmpUtilOidFree(dst
);
503 ret
= SnmpUtilOidCpy(dst
, base
);
509 ret
= SnmpUtilOidAppend(dst
, &oid
);
514 static INT
setOidWithItemAndIpAddr(AsnObjectIdentifier
*dst
,
515 AsnObjectIdentifier
*base
, UINT item
, DWORD addr
)
519 AsnObjectIdentifier oid
;
522 ret
= setOidWithItem(dst
, base
, item
);
527 for (ptr
= (BYTE
*)&addr
; ret
&& ptr
< (BYTE
*)&addr
+ sizeof(DWORD
);
531 ret
= SnmpUtilOidAppend(dst
, &oid
);
537 static INT
setOidWithItemAndInteger(AsnObjectIdentifier
*dst
,
538 AsnObjectIdentifier
*base
, UINT item
, UINT instance
)
540 AsnObjectIdentifier oid
;
543 ret
= setOidWithItem(dst
, base
, item
);
548 ret
= SnmpUtilOidAppend(dst
, &oid
);
553 static struct structToAsnValue mib2IfEntryMap
[] = {
554 { FIELD_OFFSET(MIB_IFROW
, dwIndex
), copyInt
},
555 { FIELD_OFFSET(MIB_IFROW
, dwDescrLen
), copyLengthPrecededString
},
556 { FIELD_OFFSET(MIB_IFROW
, dwType
), copyInt
},
557 { FIELD_OFFSET(MIB_IFROW
, dwMtu
), copyInt
},
558 { FIELD_OFFSET(MIB_IFROW
, dwSpeed
), copyInt
},
559 { FIELD_OFFSET(MIB_IFROW
, dwPhysAddrLen
), copyLengthPrecededString
},
560 { FIELD_OFFSET(MIB_IFROW
, dwAdminStatus
), copyInt
},
561 { FIELD_OFFSET(MIB_IFROW
, dwOperStatus
), copyOperStatus
},
562 { FIELD_OFFSET(MIB_IFROW
, dwLastChange
), copyInt
},
563 { FIELD_OFFSET(MIB_IFROW
, dwInOctets
), copyInt
},
564 { FIELD_OFFSET(MIB_IFROW
, dwInUcastPkts
), copyInt
},
565 { FIELD_OFFSET(MIB_IFROW
, dwInNUcastPkts
), copyInt
},
566 { FIELD_OFFSET(MIB_IFROW
, dwInDiscards
), copyInt
},
567 { FIELD_OFFSET(MIB_IFROW
, dwInErrors
), copyInt
},
568 { FIELD_OFFSET(MIB_IFROW
, dwInUnknownProtos
), copyInt
},
569 { FIELD_OFFSET(MIB_IFROW
, dwOutOctets
), copyInt
},
570 { FIELD_OFFSET(MIB_IFROW
, dwOutUcastPkts
), copyInt
},
571 { FIELD_OFFSET(MIB_IFROW
, dwOutNUcastPkts
), copyInt
},
572 { FIELD_OFFSET(MIB_IFROW
, dwOutDiscards
), copyInt
},
573 { FIELD_OFFSET(MIB_IFROW
, dwOutErrors
), copyInt
},
574 { FIELD_OFFSET(MIB_IFROW
, dwOutQLen
), copyInt
},
577 static UINT mib2IfEntry
[] = { 1,3,6,1,2,1,2,2,1 };
579 static BOOL
mib2IfEntryQuery(BYTE bPduType
, SnmpVarBind
*pVarBind
,
580 AsnInteger32
*pErrorStatus
)
582 AsnObjectIdentifier entryOid
= DEFINE_OID(mib2IfEntry
);
585 TRACE("(0x%02x, %s, %p)\n", bPduType
, SnmpUtilOidToA(&pVarBind
->name
),
591 case SNMP_PDU_GETNEXT
:
594 /* There is no interface present, so let the caller deal
595 * with finding the successor.
597 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
601 UINT tableIndex
= 0, item
= 0;
603 *pErrorStatus
= getItemAndIntegerInstanceFromOid(&pVarBind
->name
,
604 &entryOid
, bPduType
, &item
, &tableIndex
);
609 if (tableIndex
> ifTable
->dwNumEntries
)
610 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
613 *pErrorStatus
= mapStructEntryToValue(mib2IfEntryMap
,
614 DEFINE_SIZEOF(mib2IfEntryMap
),
615 &ifTable
->table
[tableIndex
- 1], item
, bPduType
,
617 if (bPduType
== SNMP_PDU_GETNEXT
)
618 ret
= setOidWithItemAndInteger(&pVarBind
->name
,
619 &entryOid
, item
, tableIndex
);
625 *pErrorStatus
= SNMP_ERRORSTATUS_READONLY
;
629 FIXME("0x%02x: unsupported PDU type\n", bPduType
);
630 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
635 static UINT mib2Ip
[] = { 1,3,6,1,2,1,4 };
636 static MIB_IPSTATS ipStats
;
638 static void mib2IpStatsInit(void)
640 GetIpStatistics(&ipStats
);
643 static struct structToAsnValue mib2IpMap
[] = {
644 { FIELD_OFFSET(MIB_IPSTATS
, dwForwarding
), copyInt
}, /* 1 */
645 { FIELD_OFFSET(MIB_IPSTATS
, dwDefaultTTL
), copyInt
}, /* 2 */
646 { FIELD_OFFSET(MIB_IPSTATS
, dwInReceives
), copyInt
}, /* 3 */
647 { FIELD_OFFSET(MIB_IPSTATS
, dwInHdrErrors
), copyInt
}, /* 4 */
648 { FIELD_OFFSET(MIB_IPSTATS
, dwInAddrErrors
), copyInt
}, /* 5 */
649 { FIELD_OFFSET(MIB_IPSTATS
, dwForwDatagrams
), copyInt
}, /* 6 */
650 { FIELD_OFFSET(MIB_IPSTATS
, dwInUnknownProtos
), copyInt
}, /* 7 */
651 { FIELD_OFFSET(MIB_IPSTATS
, dwInDiscards
), copyInt
}, /* 8 */
652 { FIELD_OFFSET(MIB_IPSTATS
, dwInDelivers
), copyInt
}, /* 9 */
653 { FIELD_OFFSET(MIB_IPSTATS
, dwOutRequests
), copyInt
}, /* 10 */
654 { FIELD_OFFSET(MIB_IPSTATS
, dwOutDiscards
), copyInt
}, /* 11 */
655 { FIELD_OFFSET(MIB_IPSTATS
, dwOutNoRoutes
), copyInt
}, /* 12 */
656 { FIELD_OFFSET(MIB_IPSTATS
, dwReasmTimeout
), copyInt
}, /* 13 */
657 { FIELD_OFFSET(MIB_IPSTATS
, dwReasmReqds
), copyInt
}, /* 14 */
658 { FIELD_OFFSET(MIB_IPSTATS
, dwReasmOks
), copyInt
}, /* 15 */
659 { FIELD_OFFSET(MIB_IPSTATS
, dwReasmFails
), copyInt
}, /* 16 */
660 { FIELD_OFFSET(MIB_IPSTATS
, dwFragOks
), copyInt
}, /* 17 */
661 { FIELD_OFFSET(MIB_IPSTATS
, dwFragFails
), copyInt
}, /* 18 */
662 { FIELD_OFFSET(MIB_IPSTATS
, dwFragCreates
), copyInt
}, /* 19 */
663 { 0, NULL
}, /* 20: not used, IP addr table */
664 { 0, NULL
}, /* 21: not used, route table */
665 { 0, NULL
}, /* 22: not used, net to media (ARP) table */
666 { FIELD_OFFSET(MIB_IPSTATS
, dwRoutingDiscards
), copyInt
}, /* 23 */
669 static BOOL
mib2IpStatsQuery(BYTE bPduType
, SnmpVarBind
*pVarBind
,
670 AsnInteger32
*pErrorStatus
)
672 AsnObjectIdentifier myOid
= DEFINE_OID(mib2Ip
);
676 TRACE("(0x%02x, %s, %p)\n", bPduType
, SnmpUtilOidToA(&pVarBind
->name
),
682 case SNMP_PDU_GETNEXT
:
683 *pErrorStatus
= getItemFromOid(&pVarBind
->name
, &myOid
, bPduType
,
687 *pErrorStatus
= mapStructEntryToValue(mib2IpMap
,
688 DEFINE_SIZEOF(mib2IpMap
), &ipStats
, item
, bPduType
, pVarBind
);
689 if (!*pErrorStatus
&& bPduType
== SNMP_PDU_GETNEXT
)
690 ret
= setOidWithItem(&pVarBind
->name
, &myOid
, item
);
694 *pErrorStatus
= SNMP_ERRORSTATUS_READONLY
;
698 FIXME("0x%02x: unsupported PDU type\n", bPduType
);
699 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
704 static UINT mib2IpAddr
[] = { 1,3,6,1,2,1,4,20,1 };
705 static PMIB_IPADDRTABLE ipAddrTable
;
707 static struct structToAsnValue mib2IpAddrMap
[] = {
708 { FIELD_OFFSET(MIB_IPADDRROW
, dwAddr
), copyIpAddr
},
709 { FIELD_OFFSET(MIB_IPADDRROW
, dwIndex
), copyInt
},
710 { FIELD_OFFSET(MIB_IPADDRROW
, dwMask
), copyIpAddr
},
711 { FIELD_OFFSET(MIB_IPADDRROW
, dwBCastAddr
), copyInt
},
712 { FIELD_OFFSET(MIB_IPADDRROW
, dwReasmSize
), copyInt
},
715 static void mib2IpAddrInit(void)
717 DWORD size
= 0, ret
= GetIpAddrTable(NULL
, &size
, TRUE
);
719 if (ret
== ERROR_INSUFFICIENT_BUFFER
)
721 MIB_IPADDRTABLE
*table
= HeapAlloc(GetProcessHeap(), 0, size
);
724 if (!GetIpAddrTable(table
, &size
, TRUE
)) ipAddrTable
= table
;
725 else HeapFree(GetProcessHeap(), 0, table
);
730 static void mib2IpAddrCleanup(void)
732 HeapFree(GetProcessHeap(), 0, ipAddrTable
);
735 static void oidToIpAddrRow(AsnObjectIdentifier
*oid
, void *dst
)
737 MIB_IPADDRROW
*row
= dst
;
739 row
->dwAddr
= oidToIpAddr(oid
);
742 static int compareIpAddrRow(const void *a
, const void *b
)
744 const MIB_IPADDRROW
*key
= a
, *value
= b
;
746 return key
->dwAddr
- value
->dwAddr
;
749 static BOOL
mib2IpAddrQuery(BYTE bPduType
, SnmpVarBind
*pVarBind
,
750 AsnInteger32
*pErrorStatus
)
752 AsnObjectIdentifier myOid
= DEFINE_OID(mib2IpAddr
);
753 UINT tableIndex
= 0, item
= 0;
756 TRACE("(0x%02x, %s, %p)\n", bPduType
, SnmpUtilOidToA(&pVarBind
->name
),
762 case SNMP_PDU_GETNEXT
:
763 *pErrorStatus
= getItemAndInstanceFromTable(&pVarBind
->name
,
764 &myOid
, 4, bPduType
, (struct GenericTable
*)ipAddrTable
,
765 sizeof(MIB_IPADDRROW
), oidToIpAddrRow
, compareIpAddrRow
, &item
,
771 *pErrorStatus
= mapStructEntryToValue(mib2IpAddrMap
,
772 DEFINE_SIZEOF(mib2IpAddrMap
),
773 &ipAddrTable
->table
[tableIndex
- 1], item
, bPduType
, pVarBind
);
774 if (!*pErrorStatus
&& bPduType
== SNMP_PDU_GETNEXT
)
775 ret
= setOidWithItemAndIpAddr(&pVarBind
->name
, &myOid
, item
,
776 ipAddrTable
->table
[tableIndex
- 1].dwAddr
);
780 *pErrorStatus
= SNMP_ERRORSTATUS_READONLY
;
784 FIXME("0x%02x: unsupported PDU type\n", bPduType
);
785 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
790 static UINT mib2IpRoute
[] = { 1,3,6,1,2,1,4,21,1 };
791 static PMIB_IPFORWARDTABLE ipRouteTable
;
793 static struct structToAsnValue mib2IpRouteMap
[] = {
794 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardDest
), copyIpAddr
},
795 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardIfIndex
), copyInt
},
796 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardMetric1
), copyInt
},
797 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardMetric2
), copyInt
},
798 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardMetric3
), copyInt
},
799 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardMetric4
), copyInt
},
800 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardNextHop
), copyIpAddr
},
801 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardType
), copyInt
},
802 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardProto
), copyInt
},
803 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardAge
), copyInt
},
804 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardMask
), copyIpAddr
},
805 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardMetric5
), copyInt
},
808 static void mib2IpRouteInit(void)
810 DWORD size
= 0, ret
= GetIpForwardTable(NULL
, &size
, TRUE
);
812 if (ret
== ERROR_INSUFFICIENT_BUFFER
)
814 MIB_IPFORWARDTABLE
*table
= HeapAlloc(GetProcessHeap(), 0, size
);
817 if (!GetIpForwardTable(table
, &size
, TRUE
)) ipRouteTable
= table
;
818 else HeapFree(GetProcessHeap(), 0, table
);
823 static void mib2IpRouteCleanup(void)
825 HeapFree(GetProcessHeap(), 0, ipRouteTable
);
828 static void oidToIpForwardRow(AsnObjectIdentifier
*oid
, void *dst
)
830 MIB_IPFORWARDROW
*row
= dst
;
832 row
->dwForwardDest
= oidToIpAddr(oid
);
835 static int compareIpForwardRow(const void *a
, const void *b
)
837 const MIB_IPFORWARDROW
*key
= a
, *value
= b
;
839 return key
->dwForwardDest
- value
->dwForwardDest
;
842 static BOOL
mib2IpRouteQuery(BYTE bPduType
, SnmpVarBind
*pVarBind
,
843 AsnInteger32
*pErrorStatus
)
845 AsnObjectIdentifier myOid
= DEFINE_OID(mib2IpRoute
);
846 UINT tableIndex
= 0, item
= 0;
849 TRACE("(0x%02x, %s, %p)\n", bPduType
, SnmpUtilOidToA(&pVarBind
->name
),
855 case SNMP_PDU_GETNEXT
:
856 *pErrorStatus
= getItemAndInstanceFromTable(&pVarBind
->name
,
857 &myOid
, 4, bPduType
, (struct GenericTable
*)ipRouteTable
,
858 sizeof(MIB_IPFORWARDROW
), oidToIpForwardRow
, compareIpForwardRow
,
864 *pErrorStatus
= mapStructEntryToValue(mib2IpRouteMap
,
865 DEFINE_SIZEOF(mib2IpRouteMap
),
866 &ipRouteTable
->table
[tableIndex
- 1], item
, bPduType
, pVarBind
);
867 if (!*pErrorStatus
&& bPduType
== SNMP_PDU_GETNEXT
)
868 ret
= setOidWithItemAndIpAddr(&pVarBind
->name
, &myOid
, item
,
869 ipRouteTable
->table
[tableIndex
- 1].dwForwardDest
);
873 *pErrorStatus
= SNMP_ERRORSTATUS_READONLY
;
877 FIXME("0x%02x: unsupported PDU type\n", bPduType
);
878 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
883 static UINT mib2IpNet
[] = { 1,3,6,1,2,1,4,22,1 };
884 static PMIB_IPNETTABLE ipNetTable
;
886 static struct structToAsnValue mib2IpNetMap
[] = {
887 { FIELD_OFFSET(MIB_IPNETROW
, dwIndex
), copyInt
},
888 { FIELD_OFFSET(MIB_IPNETROW
, dwPhysAddrLen
), copyLengthPrecededString
},
889 { FIELD_OFFSET(MIB_IPNETROW
, dwAddr
), copyIpAddr
},
890 { FIELD_OFFSET(MIB_IPNETROW
, dwType
), copyInt
},
893 static void mib2IpNetInit(void)
895 DWORD size
= 0, ret
= GetIpNetTable(NULL
, &size
, FALSE
);
897 if (ret
== ERROR_INSUFFICIENT_BUFFER
)
899 MIB_IPNETTABLE
*table
= HeapAlloc(GetProcessHeap(), 0, size
);
902 if (!GetIpNetTable(table
, &size
, FALSE
)) ipNetTable
= table
;
903 else HeapFree(GetProcessHeap(), 0, table
);
908 static void mib2IpNetCleanup(void)
910 HeapFree(GetProcessHeap(), 0, ipNetTable
);
913 static BOOL
mib2IpNetQuery(BYTE bPduType
, SnmpVarBind
*pVarBind
,
914 AsnInteger32
*pErrorStatus
)
916 AsnObjectIdentifier myOid
= DEFINE_OID(mib2IpNet
);
919 TRACE("(0x%02x, %s, %p)\n", bPduType
, SnmpUtilOidToA(&pVarBind
->name
),
925 case SNMP_PDU_GETNEXT
:
927 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
930 UINT tableIndex
= 0, item
= 0;
932 *pErrorStatus
= getItemAndIntegerInstanceFromOid(&pVarBind
->name
,
933 &myOid
, bPduType
, &item
, &tableIndex
);
938 if (tableIndex
> ipNetTable
->dwNumEntries
)
939 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
942 *pErrorStatus
= mapStructEntryToValue(mib2IpNetMap
,
943 DEFINE_SIZEOF(mib2IpNetMap
),
944 &ipNetTable
[tableIndex
- 1], item
, bPduType
, pVarBind
);
945 if (!*pErrorStatus
&& bPduType
== SNMP_PDU_GETNEXT
)
946 ret
= setOidWithItemAndInteger(&pVarBind
->name
, &myOid
,
953 *pErrorStatus
= SNMP_ERRORSTATUS_READONLY
;
957 FIXME("0x%02x: unsupported PDU type\n", bPduType
);
958 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
963 static UINT mib2Icmp
[] = { 1,3,6,1,2,1,5 };
964 static MIB_ICMP icmpStats
;
966 static void mib2IcmpInit(void)
968 GetIcmpStatistics(&icmpStats
);
971 static struct structToAsnValue mib2IcmpMap
[] = {
972 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwMsgs
), copyInt
},
973 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwErrors
), copyInt
},
974 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwDestUnreachs
), copyInt
},
975 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwTimeExcds
), copyInt
},
976 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwParmProbs
), copyInt
},
977 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwSrcQuenchs
), copyInt
},
978 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwRedirects
), copyInt
},
979 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwEchos
), copyInt
},
980 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwEchoReps
), copyInt
},
981 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwTimestamps
), copyInt
},
982 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwTimestampReps
), copyInt
},
983 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwAddrMasks
), copyInt
},
984 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwAddrMaskReps
), copyInt
},
985 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwMsgs
), copyInt
},
986 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwErrors
), copyInt
},
987 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwDestUnreachs
), copyInt
},
988 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwTimeExcds
), copyInt
},
989 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwParmProbs
), copyInt
},
990 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwSrcQuenchs
), copyInt
},
991 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwRedirects
), copyInt
},
992 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwEchos
), copyInt
},
993 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwEchoReps
), copyInt
},
994 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwTimestamps
), copyInt
},
995 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwTimestampReps
), copyInt
},
996 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwAddrMasks
), copyInt
},
997 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwAddrMaskReps
), copyInt
},
1000 static BOOL
mib2IcmpQuery(BYTE bPduType
, SnmpVarBind
*pVarBind
,
1001 AsnInteger32
*pErrorStatus
)
1003 AsnObjectIdentifier myOid
= DEFINE_OID(mib2Icmp
);
1007 TRACE("(0x%02x, %s, %p)\n", bPduType
, SnmpUtilOidToA(&pVarBind
->name
),
1013 case SNMP_PDU_GETNEXT
:
1014 *pErrorStatus
= getItemFromOid(&pVarBind
->name
, &myOid
, bPduType
,
1018 *pErrorStatus
= mapStructEntryToValue(mib2IcmpMap
,
1019 DEFINE_SIZEOF(mib2IcmpMap
), &icmpStats
, item
, bPduType
,
1021 if (!*pErrorStatus
&& bPduType
== SNMP_PDU_GETNEXT
)
1022 ret
= setOidWithItem(&pVarBind
->name
, &myOid
, item
);
1026 *pErrorStatus
= SNMP_ERRORSTATUS_READONLY
;
1030 FIXME("0x%02x: unsupported PDU type\n", bPduType
);
1031 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
1036 static UINT mib2Tcp
[] = { 1,3,6,1,2,1,6 };
1037 static MIB_TCPSTATS tcpStats
;
1039 static void mib2TcpInit(void)
1041 GetTcpStatistics(&tcpStats
);
1044 static struct structToAsnValue mib2TcpMap
[] = {
1045 { FIELD_OFFSET(MIB_TCPSTATS
, dwRtoAlgorithm
), copyInt
},
1046 { FIELD_OFFSET(MIB_TCPSTATS
, dwRtoMin
), copyInt
},
1047 { FIELD_OFFSET(MIB_TCPSTATS
, dwRtoMax
), copyInt
},
1048 { FIELD_OFFSET(MIB_TCPSTATS
, dwMaxConn
), copyInt
},
1049 { FIELD_OFFSET(MIB_TCPSTATS
, dwActiveOpens
), copyInt
},
1050 { FIELD_OFFSET(MIB_TCPSTATS
, dwPassiveOpens
), copyInt
},
1051 { FIELD_OFFSET(MIB_TCPSTATS
, dwAttemptFails
), copyInt
},
1052 { FIELD_OFFSET(MIB_TCPSTATS
, dwEstabResets
), copyInt
},
1053 { FIELD_OFFSET(MIB_TCPSTATS
, dwCurrEstab
), copyInt
},
1054 { FIELD_OFFSET(MIB_TCPSTATS
, dwInSegs
), copyInt
},
1055 { FIELD_OFFSET(MIB_TCPSTATS
, dwOutSegs
), copyInt
},
1056 { FIELD_OFFSET(MIB_TCPSTATS
, dwRetransSegs
), copyInt
},
1057 { FIELD_OFFSET(MIB_TCPSTATS
, dwInErrs
), copyInt
},
1058 { FIELD_OFFSET(MIB_TCPSTATS
, dwOutRsts
), copyInt
},
1059 { FIELD_OFFSET(MIB_TCPSTATS
, dwNumConns
), copyInt
},
1062 static BOOL
mib2TcpQuery(BYTE bPduType
, SnmpVarBind
*pVarBind
,
1063 AsnInteger32
*pErrorStatus
)
1065 AsnObjectIdentifier myOid
= DEFINE_OID(mib2Tcp
);
1069 TRACE("(0x%02x, %s, %p)\n", bPduType
, SnmpUtilOidToA(&pVarBind
->name
),
1075 case SNMP_PDU_GETNEXT
:
1076 *pErrorStatus
= getItemFromOid(&pVarBind
->name
, &myOid
, bPduType
,
1080 *pErrorStatus
= mapStructEntryToValue(mib2TcpMap
,
1081 DEFINE_SIZEOF(mib2TcpMap
), &tcpStats
, item
, bPduType
, pVarBind
);
1082 if (!*pErrorStatus
&& bPduType
== SNMP_PDU_GETNEXT
)
1083 ret
= setOidWithItem(&pVarBind
->name
, &myOid
, item
);
1087 *pErrorStatus
= SNMP_ERRORSTATUS_READONLY
;
1091 FIXME("0x%02x: unsupported PDU type\n", bPduType
);
1092 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
1097 static UINT mib2Udp
[] = { 1,3,6,1,2,1,7 };
1098 static MIB_UDPSTATS udpStats
;
1100 static void mib2UdpInit(void)
1102 GetUdpStatistics(&udpStats
);
1105 static struct structToAsnValue mib2UdpMap
[] = {
1106 { FIELD_OFFSET(MIB_UDPSTATS
, dwInDatagrams
), copyInt
},
1107 { FIELD_OFFSET(MIB_UDPSTATS
, dwNoPorts
), copyInt
},
1108 { FIELD_OFFSET(MIB_UDPSTATS
, dwInErrors
), copyInt
},
1109 { FIELD_OFFSET(MIB_UDPSTATS
, dwOutDatagrams
), copyInt
},
1112 static BOOL
mib2UdpQuery(BYTE bPduType
, SnmpVarBind
*pVarBind
,
1113 AsnInteger32
*pErrorStatus
)
1115 AsnObjectIdentifier myOid
= DEFINE_OID(mib2Udp
);
1119 TRACE("(0x%02x, %s, %p)\n", bPduType
, SnmpUtilOidToA(&pVarBind
->name
),
1125 case SNMP_PDU_GETNEXT
:
1126 *pErrorStatus
= getItemFromOid(&pVarBind
->name
, &myOid
, bPduType
,
1130 *pErrorStatus
= mapStructEntryToValue(mib2UdpMap
,
1131 DEFINE_SIZEOF(mib2UdpMap
), &udpStats
, item
, bPduType
, pVarBind
);
1132 if (!*pErrorStatus
&& bPduType
== SNMP_PDU_GETNEXT
)
1133 ret
= setOidWithItem(&pVarBind
->name
, &myOid
, item
);
1137 *pErrorStatus
= SNMP_ERRORSTATUS_READONLY
;
1141 FIXME("0x%02x: unsupported PDU type\n", bPduType
);
1142 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
1147 static UINT mib2UdpEntry
[] = { 1,3,6,1,2,1,7,5,1 };
1148 static PMIB_UDPTABLE udpTable
;
1150 static void mib2UdpEntryInit(void)
1152 DWORD size
= 0, ret
= GetUdpTable(NULL
, &size
, TRUE
);
1154 if (ret
== ERROR_INSUFFICIENT_BUFFER
)
1156 MIB_UDPTABLE
*table
= HeapAlloc(GetProcessHeap(), 0, size
);
1159 if (!GetUdpTable(table
, &size
, TRUE
)) udpTable
= table
;
1160 else HeapFree(GetProcessHeap(), 0, table
);
1165 static void mib2UdpEntryCleanup(void)
1167 HeapFree(GetProcessHeap(), 0, udpTable
);
1170 static struct structToAsnValue mib2UdpEntryMap
[] = {
1171 { FIELD_OFFSET(MIB_UDPROW
, dwLocalAddr
), copyIpAddr
},
1172 { FIELD_OFFSET(MIB_UDPROW
, dwLocalPort
), copyInt
},
1175 static void oidToUdpRow(AsnObjectIdentifier
*oid
, void *dst
)
1177 MIB_UDPROW
*row
= dst
;
1179 assert(oid
&& oid
->idLength
>= 5);
1180 row
->dwLocalAddr
= oidToIpAddr(oid
);
1181 row
->dwLocalPort
= oid
->ids
[4];
1184 static int compareUdpRow(const void *a
, const void *b
)
1186 const MIB_UDPROW
*key
= a
, *value
= b
;
1189 ret
= key
->dwLocalAddr
- value
->dwLocalAddr
;
1191 ret
= key
->dwLocalPort
- value
->dwLocalPort
;
1195 static BOOL
mib2UdpEntryQuery(BYTE bPduType
, SnmpVarBind
*pVarBind
,
1196 AsnInteger32
*pErrorStatus
)
1198 AsnObjectIdentifier myOid
= DEFINE_OID(mib2UdpEntry
);
1201 TRACE("(0x%02x, %s, %p)\n", bPduType
, SnmpUtilOidToA(&pVarBind
->name
),
1207 case SNMP_PDU_GETNEXT
:
1209 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
1212 UINT tableIndex
= 0, item
= 0;
1214 *pErrorStatus
= getItemAndInstanceFromTable(&pVarBind
->name
, &myOid
,
1215 5, bPduType
, (struct GenericTable
*)udpTable
,
1216 sizeof(MIB_UDPROW
), oidToUdpRow
, compareUdpRow
, &item
,
1222 *pErrorStatus
= mapStructEntryToValue(mib2UdpEntryMap
,
1223 DEFINE_SIZEOF(mib2UdpEntryMap
),
1224 &udpTable
->table
[tableIndex
- 1], item
, bPduType
, pVarBind
);
1225 if (!*pErrorStatus
&& bPduType
== SNMP_PDU_GETNEXT
)
1227 AsnObjectIdentifier oid
;
1229 ret
= setOidWithItemAndIpAddr(&pVarBind
->name
, &myOid
, item
,
1230 udpTable
->table
[tableIndex
- 1].dwLocalAddr
);
1234 oid
.ids
= &udpTable
->table
[tableIndex
- 1].dwLocalPort
;
1235 ret
= SnmpUtilOidAppend(&pVarBind
->name
, &oid
);
1242 *pErrorStatus
= SNMP_ERRORSTATUS_READONLY
;
1246 FIXME("0x%02x: unsupported PDU type\n", bPduType
);
1247 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
1252 /* This list MUST BE lexicographically sorted */
1253 static struct mibImplementation supportedIDs
[] = {
1254 { DEFINE_OID(mib2IfNumber
), mib2IfNumberInit
, mib2IfNumberQuery
,
1255 mib2IfNumberCleanup
},
1256 { DEFINE_OID(mib2IfEntry
), NULL
, mib2IfEntryQuery
, NULL
},
1257 { DEFINE_OID(mib2Ip
), mib2IpStatsInit
, mib2IpStatsQuery
, NULL
},
1258 { DEFINE_OID(mib2IpAddr
), mib2IpAddrInit
, mib2IpAddrQuery
,
1259 mib2IpAddrCleanup
},
1260 { DEFINE_OID(mib2IpRoute
), mib2IpRouteInit
, mib2IpRouteQuery
,
1261 mib2IpRouteCleanup
},
1262 { DEFINE_OID(mib2IpNet
), mib2IpNetInit
, mib2IpNetQuery
, mib2IpNetCleanup
},
1263 { DEFINE_OID(mib2Icmp
), mib2IcmpInit
, mib2IcmpQuery
, NULL
},
1264 { DEFINE_OID(mib2Tcp
), mib2TcpInit
, mib2TcpQuery
, NULL
},
1265 { DEFINE_OID(mib2Udp
), mib2UdpInit
, mib2UdpQuery
, NULL
},
1266 { DEFINE_OID(mib2UdpEntry
), mib2UdpEntryInit
, mib2UdpEntryQuery
,
1267 mib2UdpEntryCleanup
},
1269 static UINT minSupportedIDLength
;
1271 /*****************************************************************************
1272 * SnmpExtensionInit [INETMIB1.@]
1274 BOOL WINAPI
SnmpExtensionInit(DWORD dwUptimeReference
,
1275 HANDLE
*phSubagentTrapEvent
, AsnObjectIdentifier
*pFirstSupportedRegion
)
1277 AsnObjectIdentifier myOid
= DEFINE_OID(mib2System
);
1280 TRACE("(%d, %p, %p)\n", dwUptimeReference
, phSubagentTrapEvent
,
1281 pFirstSupportedRegion
);
1283 minSupportedIDLength
= UINT_MAX
;
1284 for (i
= 0; i
< sizeof(supportedIDs
) / sizeof(supportedIDs
[0]); i
++)
1286 if (supportedIDs
[i
].init
)
1287 supportedIDs
[i
].init();
1288 if (supportedIDs
[i
].name
.idLength
< minSupportedIDLength
)
1289 minSupportedIDLength
= supportedIDs
[i
].name
.idLength
;
1291 *phSubagentTrapEvent
= NULL
;
1292 SnmpUtilOidCpy(pFirstSupportedRegion
, &myOid
);
1296 static void cleanup(void)
1300 for (i
= 0; i
< sizeof(supportedIDs
) / sizeof(supportedIDs
[0]); i
++)
1301 if (supportedIDs
[i
].cleanup
)
1302 supportedIDs
[i
].cleanup();
1305 static struct mibImplementation
*findSupportedQuery(UINT
*ids
, UINT idLength
,
1306 UINT
*matchingIndex
)
1308 int indexHigh
= DEFINE_SIZEOF(supportedIDs
) - 1, indexLow
= 0, i
;
1309 struct mibImplementation
*impl
= NULL
;
1310 AsnObjectIdentifier oid1
= { idLength
, ids
};
1314 for (i
= (indexLow
+ indexHigh
) / 2; !impl
&& indexLow
<= indexHigh
;
1315 i
= (indexLow
+ indexHigh
) / 2)
1319 cmp
= SnmpUtilOidNCmp(&oid1
, &supportedIDs
[i
].name
, idLength
);
1322 impl
= &supportedIDs
[i
];
1333 /*****************************************************************************
1334 * SnmpExtensionQuery [INETMIB1.@]
1336 BOOL WINAPI
SnmpExtensionQuery(BYTE bPduType
, SnmpVarBindList
*pVarBindList
,
1337 AsnInteger32
*pErrorStatus
, AsnInteger32
*pErrorIndex
)
1339 AsnObjectIdentifier mib2oid
= DEFINE_OID(mib2
);
1340 AsnInteger32 error
= SNMP_ERRORSTATUS_NOERROR
, errorIndex
= 0;
1344 TRACE("(0x%02x, %p, %p, %p)\n", bPduType
, pVarBindList
,
1345 pErrorStatus
, pErrorIndex
);
1347 for (i
= 0; !error
&& i
< pVarBindList
->len
; i
++)
1349 /* Ignore any OIDs not in MIB2 */
1350 if (!SnmpUtilOidNCmp(&pVarBindList
->list
[i
].name
, &mib2oid
,
1353 struct mibImplementation
*impl
= NULL
;
1354 UINT len
, matchingIndex
= 0;
1356 TRACE("%s\n", SnmpUtilOidToA(&pVarBindList
->list
[i
].name
));
1357 /* Search for an implementation matching as many octets as possible
1359 for (len
= pVarBindList
->list
[i
].name
.idLength
;
1360 len
>= minSupportedIDLength
&& !impl
; len
--)
1361 impl
= findSupportedQuery(pVarBindList
->list
[i
].name
.ids
, len
,
1363 if (impl
&& impl
->query
)
1364 ret
= impl
->query(bPduType
, &pVarBindList
->list
[i
], &error
);
1366 error
= SNMP_ERRORSTATUS_NOSUCHNAME
;
1367 if (error
== SNMP_ERRORSTATUS_NOSUCHNAME
&&
1368 bPduType
== SNMP_PDU_GETNEXT
)
1370 /* GetNext is special: it finds the successor to the given OID,
1371 * so we have to continue until an implementation handles the
1372 * query or we exhaust the table of supported OIDs.
1374 for (matchingIndex
++; error
== SNMP_ERRORSTATUS_NOSUCHNAME
&&
1375 matchingIndex
< DEFINE_SIZEOF(supportedIDs
);
1378 error
= SNMP_ERRORSTATUS_NOERROR
;
1379 impl
= &supportedIDs
[matchingIndex
];
1381 ret
= impl
->query(bPduType
, &pVarBindList
->list
[i
],
1384 error
= SNMP_ERRORSTATUS_NOSUCHNAME
;
1386 /* If the query still isn't resolved, set the OID to the
1387 * successor to the last entry in the table.
1389 if (error
== SNMP_ERRORSTATUS_NOSUCHNAME
)
1391 SnmpUtilOidFree(&pVarBindList
->list
[i
].name
);
1392 ret
= SnmpUtilOidCpy(&pVarBindList
->list
[i
].name
,
1393 &supportedIDs
[matchingIndex
- 1].name
);
1394 pVarBindList
->list
[i
].name
.ids
[
1395 pVarBindList
->list
[i
].name
.idLength
- 1] += 1;
1402 *pErrorStatus
= error
;
1403 *pErrorIndex
= errorIndex
;
1407 /*****************************************************************************
1408 * DllMain [INETMIB1.@]
1410 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
1412 TRACE("(0x%p, %d, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
1416 case DLL_PROCESS_ATTACH
:
1417 DisableThreadLibraryCalls(hinstDLL
);
1419 case DLL_PROCESS_DETACH
: