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 ifTable
= HeapAlloc(GetProcessHeap(), 0, size
);
112 GetIfTable(ifTable
, &size
, FALSE
);
116 static void mib2IfNumberCleanup(void)
118 HeapFree(GetProcessHeap(), 0, ifTable
);
121 static BOOL
mib2IfNumberQuery(BYTE bPduType
, SnmpVarBind
*pVarBind
,
122 AsnInteger32
*pErrorStatus
)
124 AsnObjectIdentifier numberOid
= DEFINE_OID(mib2IfNumber
);
126 TRACE("(0x%02x, %s, %p)\n", bPduType
, SnmpUtilOidToA(&pVarBind
->name
),
132 case SNMP_PDU_GETNEXT
:
133 if ((bPduType
== SNMP_PDU_GET
&&
134 !SnmpUtilOidNCmp(&pVarBind
->name
, &numberOid
, numberOid
.idLength
))
135 || SnmpUtilOidNCmp(&pVarBind
->name
, &numberOid
, numberOid
.idLength
)
138 DWORD numIfs
= ifTable
? ifTable
->dwNumEntries
: 0;
140 copyInt(&pVarBind
->value
, &numIfs
);
141 if (bPduType
== SNMP_PDU_GETNEXT
)
142 SnmpUtilOidCpy(&pVarBind
->name
, &numberOid
);
143 *pErrorStatus
= SNMP_ERRORSTATUS_NOERROR
;
147 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
148 /* Caller deals with OID if bPduType == SNMP_PDU_GETNEXT, so don't
149 * need to set it here.
154 *pErrorStatus
= SNMP_ERRORSTATUS_READONLY
;
157 FIXME("0x%02x: unsupported PDU type\n", bPduType
);
158 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
163 static void copyOperStatus(AsnAny
*value
, void *src
)
165 value
->asnType
= ASN_INTEGER
;
166 /* The IPHlpApi definition of operational status differs from the MIB2 one,
167 * so map it to the MIB2 value.
169 switch (*(DWORD
*)src
)
171 case MIB_IF_OPER_STATUS_OPERATIONAL
:
172 value
->asnValue
.number
= MIB_IF_ADMIN_STATUS_UP
;
174 case MIB_IF_OPER_STATUS_CONNECTING
:
175 case MIB_IF_OPER_STATUS_CONNECTED
:
176 value
->asnValue
.number
= MIB_IF_ADMIN_STATUS_TESTING
;
179 value
->asnValue
.number
= MIB_IF_ADMIN_STATUS_DOWN
;
183 /* Given an OID and a base OID that it must begin with, finds the item and
184 * integer instance from the OID. E.g., given an OID foo.1.2 and a base OID
185 * foo, returns item 1 and instance 2.
186 * If bPduType is not SNMP_PDU_GETNEXT and either the item or instance is
187 * missing, returns SNMP_ERRORSTATUS_NOSUCHNAME.
188 * If bPduType is SNMP_PDU_GETNEXT, returns the successor to the item and
189 * instance, or item 1, instance 1 if either is missing.
191 static AsnInteger32
getItemAndIntegerInstanceFromOid(AsnObjectIdentifier
*oid
,
192 AsnObjectIdentifier
*base
, BYTE bPduType
, UINT
*item
, UINT
*instance
)
194 AsnInteger32 ret
= SNMP_ERRORSTATUS_NOERROR
;
198 case SNMP_PDU_GETNEXT
:
199 if (SnmpUtilOidNCmp(oid
, base
, base
->idLength
) < 0)
204 else if (!SnmpUtilOidNCmp(oid
, base
, base
->idLength
))
206 if (oid
->idLength
== base
->idLength
||
207 oid
->idLength
== base
->idLength
+ 1)
209 /* Either the table or an item within the table is specified,
210 * but the instance is not. Get the first instance.
213 if (oid
->idLength
== base
->idLength
+ 1)
214 *item
= oid
->ids
[base
->idLength
];
220 *item
= oid
->ids
[base
->idLength
];
221 *instance
= oid
->ids
[base
->idLength
+ 1] + 1;
225 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
228 if (!SnmpUtilOidNCmp(oid
, base
, base
->idLength
))
230 if (oid
->idLength
== base
->idLength
||
231 oid
->idLength
== base
->idLength
+ 1)
233 /* Either the table or an item within the table is specified,
234 * but the instance is not.
236 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
240 *item
= oid
->ids
[base
->idLength
];
241 *instance
= oid
->ids
[base
->idLength
+ 1];
245 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
250 /* Given an OID and a base OID that it must begin with, finds the item from the
251 * OID. E.g., given an OID foo.1 and a base OID foo, returns item 1.
252 * If bPduType is not SNMP_PDU_GETNEXT and the item is missing, returns
253 * SNMP_ERRORSTATUS_NOSUCHNAME.
254 * If bPduType is SNMP_PDU_GETNEXT, returns the successor to the item, or item
255 * 1 if the item is missing.
257 static AsnInteger32
getItemFromOid(AsnObjectIdentifier
*oid
,
258 AsnObjectIdentifier
*base
, BYTE bPduType
, UINT
*item
)
260 AsnInteger32 ret
= SNMP_ERRORSTATUS_NOERROR
;
264 case SNMP_PDU_GETNEXT
:
265 if (SnmpUtilOidNCmp(oid
, base
, base
->idLength
) < 0)
267 else if (!SnmpUtilOidNCmp(oid
, base
, base
->idLength
))
269 if (oid
->idLength
== base
->idLength
)
271 /* The item is missing, assume the first item */
275 *item
= oid
->ids
[base
->idLength
] + 1;
278 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
281 if (!SnmpUtilOidNCmp(oid
, base
, base
->idLength
))
283 if (oid
->idLength
== base
->idLength
)
285 /* The item is missing */
286 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
290 *item
= oid
->ids
[base
->idLength
];
292 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
296 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
307 static DWORD
oidToIpAddr(AsnObjectIdentifier
*oid
)
309 assert(oid
&& oid
->idLength
>= 4);
310 /* Map the IDs to an IP address in little-endian order */
311 return (BYTE
)oid
->ids
[3] << 24 | (BYTE
)oid
->ids
[2] << 16 |
312 (BYTE
)oid
->ids
[1] << 8 | (BYTE
)oid
->ids
[0];
315 typedef void (*oidToKeyFunc
)(AsnObjectIdentifier
*oid
, void *dst
);
316 typedef int (*compareFunc
)(const void *key
, const void *value
);
318 static UINT
findValueInTable(AsnObjectIdentifier
*oid
,
319 struct GenericTable
*table
, size_t tableEntrySize
, oidToKeyFunc makeKey
,
323 void *key
= HeapAlloc(GetProcessHeap(), 0, tableEntrySize
);
330 value
= bsearch(key
, table
->entries
, table
->numEntries
, tableEntrySize
,
333 index
= ((BYTE
*)value
- (BYTE
*)table
->entries
) / tableEntrySize
335 HeapFree(GetProcessHeap(), 0, key
);
340 /* Given an OID and a base OID that it must begin with, finds the item and
341 * element of the table whose value matches the instance from the OID.
342 * The OID is converted to a key with the function makeKey, and compared
343 * against entries in the table with the function compare.
344 * If bPduType is not SNMP_PDU_GETNEXT and either the item or instance is
345 * missing, returns SNMP_ERRORSTATUS_NOSUCHNAME.
346 * If bPduType is SNMP_PDU_GETNEXT, returns the successor to the item and
347 * instance, or item 1, instance 1 if either is missing.
349 static AsnInteger32
getItemAndInstanceFromTable(AsnObjectIdentifier
*oid
,
350 AsnObjectIdentifier
*base
, UINT instanceLen
, BYTE bPduType
,
351 struct GenericTable
*table
, size_t tableEntrySize
, oidToKeyFunc makeKey
,
352 compareFunc compare
, UINT
*item
, UINT
*instance
)
354 AsnInteger32 ret
= SNMP_ERRORSTATUS_NOERROR
;
357 return SNMP_ERRORSTATUS_NOSUCHNAME
;
361 case SNMP_PDU_GETNEXT
:
362 if (SnmpUtilOidNCmp(oid
, base
, base
->idLength
) < 0)
364 /* Return the first item and instance from the table */
368 else if (!SnmpUtilOidNCmp(oid
, base
, base
->idLength
) &&
369 oid
->idLength
< base
->idLength
+ instanceLen
+ 1)
371 /* Either the table or an item is specified, but the instance is
375 if (oid
->idLength
>= base
->idLength
+ 1)
377 *item
= oid
->ids
[base
->idLength
];
384 else if (!SnmpUtilOidNCmp(oid
, base
, base
->idLength
) &&
385 oid
->idLength
== base
->idLength
+ instanceLen
+ 1)
387 *item
= oid
->ids
[base
->idLength
];
395 AsnObjectIdentifier ipOid
= { instanceLen
,
396 oid
->ids
+ base
->idLength
+ 1 };
398 *instance
= findValueInTable(&ipOid
, table
, tableEntrySize
,
399 makeKey
, compare
) + 1;
400 if (*instance
> table
->numEntries
)
401 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
405 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
408 if (!SnmpUtilOidNCmp(oid
, base
, base
->idLength
) &&
409 oid
->idLength
== base
->idLength
+ instanceLen
+ 1)
411 *item
= oid
->ids
[base
->idLength
];
413 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
416 AsnObjectIdentifier ipOid
= { instanceLen
,
417 oid
->ids
+ base
->idLength
+ 1 };
419 *instance
= findValueInTable(&ipOid
, table
, tableEntrySize
,
422 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
426 ret
= SNMP_ERRORSTATUS_NOSUCHNAME
;
431 static void setOidWithItem(AsnObjectIdentifier
*dst
, AsnObjectIdentifier
*base
,
435 AsnObjectIdentifier oid
;
437 SnmpUtilOidCpy(dst
, base
);
441 SnmpUtilOidAppend(dst
, &oid
);
444 static void setOidWithItemAndIpAddr(AsnObjectIdentifier
*dst
,
445 AsnObjectIdentifier
*base
, UINT item
, DWORD addr
)
449 AsnObjectIdentifier oid
;
451 setOidWithItem(dst
, base
, item
);
454 for (ptr
= (BYTE
*)&addr
; ptr
< (BYTE
*)&addr
+ sizeof(DWORD
); ptr
++)
457 SnmpUtilOidAppend(dst
, &oid
);
461 static void setOidWithItemAndInteger(AsnObjectIdentifier
*dst
,
462 AsnObjectIdentifier
*base
, UINT item
, UINT instance
)
464 AsnObjectIdentifier oid
;
466 setOidWithItem(dst
, base
, item
);
469 SnmpUtilOidAppend(dst
, &oid
);
472 static struct structToAsnValue mib2IfEntryMap
[] = {
473 { FIELD_OFFSET(MIB_IFROW
, dwIndex
), copyInt
},
474 { FIELD_OFFSET(MIB_IFROW
, dwDescrLen
), copyLengthPrecededString
},
475 { FIELD_OFFSET(MIB_IFROW
, dwType
), copyInt
},
476 { FIELD_OFFSET(MIB_IFROW
, dwMtu
), copyInt
},
477 { FIELD_OFFSET(MIB_IFROW
, dwSpeed
), copyInt
},
478 { FIELD_OFFSET(MIB_IFROW
, dwPhysAddrLen
), copyLengthPrecededString
},
479 { FIELD_OFFSET(MIB_IFROW
, dwAdminStatus
), copyInt
},
480 { FIELD_OFFSET(MIB_IFROW
, dwOperStatus
), copyOperStatus
},
481 { FIELD_OFFSET(MIB_IFROW
, dwLastChange
), copyInt
},
482 { FIELD_OFFSET(MIB_IFROW
, dwInOctets
), copyInt
},
483 { FIELD_OFFSET(MIB_IFROW
, dwInUcastPkts
), copyInt
},
484 { FIELD_OFFSET(MIB_IFROW
, dwInNUcastPkts
), copyInt
},
485 { FIELD_OFFSET(MIB_IFROW
, dwInDiscards
), copyInt
},
486 { FIELD_OFFSET(MIB_IFROW
, dwInErrors
), copyInt
},
487 { FIELD_OFFSET(MIB_IFROW
, dwInUnknownProtos
), copyInt
},
488 { FIELD_OFFSET(MIB_IFROW
, dwOutOctets
), copyInt
},
489 { FIELD_OFFSET(MIB_IFROW
, dwOutUcastPkts
), copyInt
},
490 { FIELD_OFFSET(MIB_IFROW
, dwOutNUcastPkts
), copyInt
},
491 { FIELD_OFFSET(MIB_IFROW
, dwOutDiscards
), copyInt
},
492 { FIELD_OFFSET(MIB_IFROW
, dwOutErrors
), copyInt
},
493 { FIELD_OFFSET(MIB_IFROW
, dwOutQLen
), copyInt
},
496 static UINT mib2IfEntry
[] = { 1,3,6,1,2,1,2,2,1 };
498 static BOOL
mib2IfEntryQuery(BYTE bPduType
, SnmpVarBind
*pVarBind
,
499 AsnInteger32
*pErrorStatus
)
501 AsnObjectIdentifier entryOid
= DEFINE_OID(mib2IfEntry
);
503 TRACE("(0x%02x, %s, %p)\n", bPduType
, SnmpUtilOidToA(&pVarBind
->name
),
509 case SNMP_PDU_GETNEXT
:
512 /* There is no interface present, so let the caller deal
513 * with finding the successor.
515 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
519 UINT tableIndex
= 0, item
= 0;
521 *pErrorStatus
= getItemAndIntegerInstanceFromOid(&pVarBind
->name
,
522 &entryOid
, bPduType
, &item
, &tableIndex
);
527 if (tableIndex
> ifTable
->dwNumEntries
)
528 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
531 *pErrorStatus
= mapStructEntryToValue(mib2IfEntryMap
,
532 DEFINE_SIZEOF(mib2IfEntryMap
),
533 &ifTable
->table
[tableIndex
- 1], item
, bPduType
,
535 if (bPduType
== SNMP_PDU_GETNEXT
)
536 setOidWithItemAndInteger(&pVarBind
->name
, &entryOid
,
543 *pErrorStatus
= SNMP_ERRORSTATUS_READONLY
;
546 FIXME("0x%02x: unsupported PDU type\n", bPduType
);
547 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
552 static UINT mib2Ip
[] = { 1,3,6,1,2,1,4 };
553 static MIB_IPSTATS ipStats
;
555 static void mib2IpStatsInit(void)
557 GetIpStatistics(&ipStats
);
560 static struct structToAsnValue mib2IpMap
[] = {
561 { FIELD_OFFSET(MIB_IPSTATS
, dwForwarding
), copyInt
}, /* 1 */
562 { FIELD_OFFSET(MIB_IPSTATS
, dwDefaultTTL
), copyInt
}, /* 2 */
563 { FIELD_OFFSET(MIB_IPSTATS
, dwInReceives
), copyInt
}, /* 3 */
564 { FIELD_OFFSET(MIB_IPSTATS
, dwInHdrErrors
), copyInt
}, /* 4 */
565 { FIELD_OFFSET(MIB_IPSTATS
, dwInAddrErrors
), copyInt
}, /* 5 */
566 { FIELD_OFFSET(MIB_IPSTATS
, dwForwDatagrams
), copyInt
}, /* 6 */
567 { FIELD_OFFSET(MIB_IPSTATS
, dwInUnknownProtos
), copyInt
}, /* 7 */
568 { FIELD_OFFSET(MIB_IPSTATS
, dwInDiscards
), copyInt
}, /* 8 */
569 { FIELD_OFFSET(MIB_IPSTATS
, dwInDelivers
), copyInt
}, /* 9 */
570 { FIELD_OFFSET(MIB_IPSTATS
, dwOutRequests
), copyInt
}, /* 10 */
571 { FIELD_OFFSET(MIB_IPSTATS
, dwOutDiscards
), copyInt
}, /* 11 */
572 { FIELD_OFFSET(MIB_IPSTATS
, dwOutNoRoutes
), copyInt
}, /* 12 */
573 { FIELD_OFFSET(MIB_IPSTATS
, dwReasmTimeout
), copyInt
}, /* 13 */
574 { FIELD_OFFSET(MIB_IPSTATS
, dwReasmReqds
), copyInt
}, /* 14 */
575 { FIELD_OFFSET(MIB_IPSTATS
, dwReasmOks
), copyInt
}, /* 15 */
576 { FIELD_OFFSET(MIB_IPSTATS
, dwReasmFails
), copyInt
}, /* 16 */
577 { FIELD_OFFSET(MIB_IPSTATS
, dwFragOks
), copyInt
}, /* 17 */
578 { FIELD_OFFSET(MIB_IPSTATS
, dwFragFails
), copyInt
}, /* 18 */
579 { FIELD_OFFSET(MIB_IPSTATS
, dwFragCreates
), copyInt
}, /* 19 */
580 { 0, NULL
}, /* 20: not used, IP addr table */
581 { 0, NULL
}, /* 21: not used, route table */
582 { 0, NULL
}, /* 22: not used, net to media (ARP) table */
583 { FIELD_OFFSET(MIB_IPSTATS
, dwRoutingDiscards
), copyInt
}, /* 23 */
586 static BOOL
mib2IpStatsQuery(BYTE bPduType
, SnmpVarBind
*pVarBind
,
587 AsnInteger32
*pErrorStatus
)
589 AsnObjectIdentifier myOid
= DEFINE_OID(mib2Ip
);
592 TRACE("(0x%02x, %s, %p)\n", bPduType
, SnmpUtilOidToA(&pVarBind
->name
),
598 case SNMP_PDU_GETNEXT
:
599 *pErrorStatus
= getItemFromOid(&pVarBind
->name
, &myOid
, bPduType
,
603 *pErrorStatus
= mapStructEntryToValue(mib2IpMap
,
604 DEFINE_SIZEOF(mib2IpMap
), &ipStats
, item
, bPduType
, pVarBind
);
605 if (!*pErrorStatus
&& bPduType
== SNMP_PDU_GETNEXT
)
606 setOidWithItem(&pVarBind
->name
, &myOid
, item
);
610 *pErrorStatus
= SNMP_ERRORSTATUS_READONLY
;
613 FIXME("0x%02x: unsupported PDU type\n", bPduType
);
614 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
619 static UINT mib2IpAddr
[] = { 1,3,6,1,2,1,4,20,1 };
620 static PMIB_IPADDRTABLE ipAddrTable
;
622 static struct structToAsnValue mib2IpAddrMap
[] = {
623 { FIELD_OFFSET(MIB_IPADDRROW
, dwAddr
), copyIpAddr
},
624 { FIELD_OFFSET(MIB_IPADDRROW
, dwIndex
), copyInt
},
625 { FIELD_OFFSET(MIB_IPADDRROW
, dwMask
), copyIpAddr
},
626 { FIELD_OFFSET(MIB_IPADDRROW
, dwBCastAddr
), copyInt
},
627 { FIELD_OFFSET(MIB_IPADDRROW
, dwReasmSize
), copyInt
},
630 static void mib2IpAddrInit(void)
632 DWORD size
= 0, ret
= GetIpAddrTable(NULL
, &size
, TRUE
);
634 if (ret
== ERROR_INSUFFICIENT_BUFFER
)
636 ipAddrTable
= HeapAlloc(GetProcessHeap(), 0, size
);
638 GetIpAddrTable(ipAddrTable
, &size
, TRUE
);
642 static void mib2IpAddrCleanup(void)
644 HeapFree(GetProcessHeap(), 0, ipAddrTable
);
647 static void oidToIpAddrRow(AsnObjectIdentifier
*oid
, void *dst
)
649 MIB_IPADDRROW
*row
= dst
;
651 row
->dwAddr
= oidToIpAddr(oid
);
654 static int compareIpAddrRow(const void *a
, const void *b
)
656 const MIB_IPADDRROW
*key
= a
, *value
= b
;
658 return key
->dwAddr
- value
->dwAddr
;
661 static BOOL
mib2IpAddrQuery(BYTE bPduType
, SnmpVarBind
*pVarBind
,
662 AsnInteger32
*pErrorStatus
)
664 AsnObjectIdentifier myOid
= DEFINE_OID(mib2IpAddr
);
665 UINT tableIndex
= 0, item
= 0;
667 TRACE("(0x%02x, %s, %p)\n", bPduType
, SnmpUtilOidToA(&pVarBind
->name
),
673 case SNMP_PDU_GETNEXT
:
674 *pErrorStatus
= getItemAndInstanceFromTable(&pVarBind
->name
,
675 &myOid
, 4, bPduType
, (struct GenericTable
*)ipAddrTable
,
676 sizeof(MIB_IPADDRROW
), oidToIpAddrRow
, compareIpAddrRow
, &item
,
682 *pErrorStatus
= mapStructEntryToValue(mib2IpAddrMap
,
683 DEFINE_SIZEOF(mib2IpAddrMap
),
684 &ipAddrTable
->table
[tableIndex
- 1], item
, bPduType
, pVarBind
);
685 if (!*pErrorStatus
&& bPduType
== SNMP_PDU_GETNEXT
)
686 setOidWithItemAndIpAddr(&pVarBind
->name
, &myOid
, item
,
687 ipAddrTable
->table
[tableIndex
- 1].dwAddr
);
691 *pErrorStatus
= SNMP_ERRORSTATUS_READONLY
;
694 FIXME("0x%02x: unsupported PDU type\n", bPduType
);
695 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
700 static UINT mib2IpRoute
[] = { 1,3,6,1,2,1,4,21,1 };
701 static PMIB_IPFORWARDTABLE ipRouteTable
;
703 static struct structToAsnValue mib2IpRouteMap
[] = {
704 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardDest
), copyIpAddr
},
705 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardIfIndex
), copyInt
},
706 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardMetric1
), copyInt
},
707 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardMetric2
), copyInt
},
708 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardMetric3
), copyInt
},
709 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardMetric4
), copyInt
},
710 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardNextHop
), copyIpAddr
},
711 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardType
), copyInt
},
712 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardProto
), copyInt
},
713 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardAge
), copyInt
},
714 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardMask
), copyIpAddr
},
715 { FIELD_OFFSET(MIB_IPFORWARDROW
, dwForwardMetric5
), copyInt
},
718 static void mib2IpRouteInit(void)
720 DWORD size
= 0, ret
= GetIpForwardTable(NULL
, &size
, TRUE
);
722 if (ret
== ERROR_INSUFFICIENT_BUFFER
)
724 ipRouteTable
= HeapAlloc(GetProcessHeap(), 0, size
);
726 GetIpForwardTable(ipRouteTable
, &size
, TRUE
);
730 static void mib2IpRouteCleanup(void)
732 HeapFree(GetProcessHeap(), 0, ipRouteTable
);
735 static void oidToIpForwardRow(AsnObjectIdentifier
*oid
, void *dst
)
737 MIB_IPFORWARDROW
*row
= dst
;
739 row
->dwForwardDest
= oidToIpAddr(oid
);
742 static int compareIpForwardRow(const void *a
, const void *b
)
744 const MIB_IPFORWARDROW
*key
= a
, *value
= b
;
746 return key
->dwForwardDest
- value
->dwForwardDest
;
749 static BOOL
mib2IpRouteQuery(BYTE bPduType
, SnmpVarBind
*pVarBind
,
750 AsnInteger32
*pErrorStatus
)
752 AsnObjectIdentifier myOid
= DEFINE_OID(mib2IpRoute
);
753 UINT tableIndex
= 0, item
= 0;
755 TRACE("(0x%02x, %s, %p)\n", bPduType
, SnmpUtilOidToA(&pVarBind
->name
),
761 case SNMP_PDU_GETNEXT
:
762 *pErrorStatus
= getItemAndInstanceFromTable(&pVarBind
->name
,
763 &myOid
, 4, bPduType
, (struct GenericTable
*)ipRouteTable
,
764 sizeof(MIB_IPFORWARDROW
), oidToIpForwardRow
, compareIpForwardRow
,
770 *pErrorStatus
= mapStructEntryToValue(mib2IpRouteMap
,
771 DEFINE_SIZEOF(mib2IpRouteMap
),
772 &ipRouteTable
->table
[tableIndex
- 1], item
, bPduType
, pVarBind
);
773 if (!*pErrorStatus
&& bPduType
== SNMP_PDU_GETNEXT
)
774 setOidWithItemAndIpAddr(&pVarBind
->name
, &myOid
, item
,
775 ipRouteTable
->table
[tableIndex
- 1].dwForwardDest
);
779 *pErrorStatus
= SNMP_ERRORSTATUS_READONLY
;
782 FIXME("0x%02x: unsupported PDU type\n", bPduType
);
783 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
788 static UINT mib2IpNet
[] = { 1,3,6,1,2,1,4,22,1 };
789 static PMIB_IPNETTABLE ipNetTable
;
791 static struct structToAsnValue mib2IpNetMap
[] = {
792 { FIELD_OFFSET(MIB_IPNETROW
, dwIndex
), copyInt
},
793 { FIELD_OFFSET(MIB_IPNETROW
, dwPhysAddrLen
), copyLengthPrecededString
},
794 { FIELD_OFFSET(MIB_IPNETROW
, dwAddr
), copyIpAddr
},
795 { FIELD_OFFSET(MIB_IPNETROW
, dwType
), copyInt
},
798 static void mib2IpNetInit(void)
800 DWORD size
= 0, ret
= GetIpNetTable(NULL
, &size
, FALSE
);
802 if (ret
== ERROR_INSUFFICIENT_BUFFER
)
804 ipNetTable
= HeapAlloc(GetProcessHeap(), 0, size
);
806 GetIpNetTable(ipNetTable
, &size
, FALSE
);
810 static void mib2IpNetCleanup(void)
812 HeapFree(GetProcessHeap(), 0, ipNetTable
);
815 static BOOL
mib2IpNetQuery(BYTE bPduType
, SnmpVarBind
*pVarBind
,
816 AsnInteger32
*pErrorStatus
)
818 AsnObjectIdentifier myOid
= DEFINE_OID(mib2IpNet
);
820 TRACE("(0x%02x, %s, %p)\n", bPduType
, SnmpUtilOidToA(&pVarBind
->name
),
826 case SNMP_PDU_GETNEXT
:
828 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
831 UINT tableIndex
= 0, item
= 0;
833 *pErrorStatus
= getItemAndIntegerInstanceFromOid(&pVarBind
->name
,
834 &myOid
, bPduType
, &item
, &tableIndex
);
839 if (tableIndex
> ipNetTable
->dwNumEntries
)
840 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
843 *pErrorStatus
= mapStructEntryToValue(mib2IpNetMap
,
844 DEFINE_SIZEOF(mib2IpNetMap
),
845 &ipNetTable
[tableIndex
- 1], item
, bPduType
, pVarBind
);
846 if (!*pErrorStatus
&& bPduType
== SNMP_PDU_GETNEXT
)
847 setOidWithItemAndInteger(&pVarBind
->name
, &myOid
, item
,
854 *pErrorStatus
= SNMP_ERRORSTATUS_READONLY
;
857 FIXME("0x%02x: unsupported PDU type\n", bPduType
);
858 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
863 static UINT mib2Icmp
[] = { 1,3,6,1,2,1,5 };
864 static MIB_ICMP icmpStats
;
866 static void mib2IcmpInit(void)
868 GetIcmpStatistics(&icmpStats
);
871 static struct structToAsnValue mib2IcmpMap
[] = {
872 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwMsgs
), copyInt
},
873 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwErrors
), copyInt
},
874 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwDestUnreachs
), copyInt
},
875 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwTimeExcds
), copyInt
},
876 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwParmProbs
), copyInt
},
877 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwSrcQuenchs
), copyInt
},
878 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwRedirects
), copyInt
},
879 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwEchos
), copyInt
},
880 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwEchoReps
), copyInt
},
881 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwTimestamps
), copyInt
},
882 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwTimestampReps
), copyInt
},
883 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwAddrMasks
), copyInt
},
884 { FIELD_OFFSET(MIBICMPINFO
, icmpInStats
.dwAddrMaskReps
), copyInt
},
885 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwMsgs
), copyInt
},
886 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwErrors
), copyInt
},
887 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwDestUnreachs
), copyInt
},
888 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwTimeExcds
), copyInt
},
889 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwParmProbs
), copyInt
},
890 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwSrcQuenchs
), copyInt
},
891 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwRedirects
), copyInt
},
892 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwEchos
), copyInt
},
893 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwEchoReps
), copyInt
},
894 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwTimestamps
), copyInt
},
895 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwTimestampReps
), copyInt
},
896 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwAddrMasks
), copyInt
},
897 { FIELD_OFFSET(MIBICMPINFO
, icmpOutStats
.dwAddrMaskReps
), copyInt
},
900 static BOOL
mib2IcmpQuery(BYTE bPduType
, SnmpVarBind
*pVarBind
,
901 AsnInteger32
*pErrorStatus
)
903 AsnObjectIdentifier myOid
= DEFINE_OID(mib2Icmp
);
906 TRACE("(0x%02x, %s, %p)\n", bPduType
, SnmpUtilOidToA(&pVarBind
->name
),
912 case SNMP_PDU_GETNEXT
:
913 *pErrorStatus
= getItemFromOid(&pVarBind
->name
, &myOid
, bPduType
,
917 *pErrorStatus
= mapStructEntryToValue(mib2IcmpMap
,
918 DEFINE_SIZEOF(mib2IcmpMap
), &icmpStats
, item
, bPduType
,
920 if (!*pErrorStatus
&& bPduType
== SNMP_PDU_GETNEXT
)
921 setOidWithItem(&pVarBind
->name
, &myOid
, item
);
925 *pErrorStatus
= SNMP_ERRORSTATUS_READONLY
;
928 FIXME("0x%02x: unsupported PDU type\n", bPduType
);
929 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
934 static UINT mib2Tcp
[] = { 1,3,6,1,2,1,6 };
935 static MIB_TCPSTATS tcpStats
;
937 static void mib2TcpInit(void)
939 GetTcpStatistics(&tcpStats
);
942 static struct structToAsnValue mib2TcpMap
[] = {
943 { FIELD_OFFSET(MIB_TCPSTATS
, dwRtoAlgorithm
), copyInt
},
944 { FIELD_OFFSET(MIB_TCPSTATS
, dwRtoMin
), copyInt
},
945 { FIELD_OFFSET(MIB_TCPSTATS
, dwRtoMax
), copyInt
},
946 { FIELD_OFFSET(MIB_TCPSTATS
, dwMaxConn
), copyInt
},
947 { FIELD_OFFSET(MIB_TCPSTATS
, dwActiveOpens
), copyInt
},
948 { FIELD_OFFSET(MIB_TCPSTATS
, dwPassiveOpens
), copyInt
},
949 { FIELD_OFFSET(MIB_TCPSTATS
, dwAttemptFails
), copyInt
},
950 { FIELD_OFFSET(MIB_TCPSTATS
, dwEstabResets
), copyInt
},
951 { FIELD_OFFSET(MIB_TCPSTATS
, dwCurrEstab
), copyInt
},
952 { FIELD_OFFSET(MIB_TCPSTATS
, dwInSegs
), copyInt
},
953 { FIELD_OFFSET(MIB_TCPSTATS
, dwOutSegs
), copyInt
},
954 { FIELD_OFFSET(MIB_TCPSTATS
, dwRetransSegs
), copyInt
},
955 { FIELD_OFFSET(MIB_TCPSTATS
, dwInErrs
), copyInt
},
956 { FIELD_OFFSET(MIB_TCPSTATS
, dwOutRsts
), copyInt
},
957 { FIELD_OFFSET(MIB_TCPSTATS
, dwNumConns
), copyInt
},
960 static BOOL
mib2TcpQuery(BYTE bPduType
, SnmpVarBind
*pVarBind
,
961 AsnInteger32
*pErrorStatus
)
963 AsnObjectIdentifier myOid
= DEFINE_OID(mib2Tcp
);
966 TRACE("(0x%02x, %s, %p)\n", bPduType
, SnmpUtilOidToA(&pVarBind
->name
),
972 case SNMP_PDU_GETNEXT
:
973 *pErrorStatus
= getItemFromOid(&pVarBind
->name
, &myOid
, bPduType
,
977 *pErrorStatus
= mapStructEntryToValue(mib2TcpMap
,
978 DEFINE_SIZEOF(mib2TcpMap
), &tcpStats
, item
, bPduType
, pVarBind
);
979 if (!*pErrorStatus
&& bPduType
== SNMP_PDU_GETNEXT
)
980 setOidWithItem(&pVarBind
->name
, &myOid
, item
);
984 *pErrorStatus
= SNMP_ERRORSTATUS_READONLY
;
987 FIXME("0x%02x: unsupported PDU type\n", bPduType
);
988 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
993 static UINT mib2Udp
[] = { 1,3,6,1,2,1,7 };
994 static MIB_UDPSTATS udpStats
;
996 static void mib2UdpInit(void)
998 GetUdpStatistics(&udpStats
);
1001 static struct structToAsnValue mib2UdpMap
[] = {
1002 { FIELD_OFFSET(MIB_UDPSTATS
, dwInDatagrams
), copyInt
},
1003 { FIELD_OFFSET(MIB_UDPSTATS
, dwNoPorts
), copyInt
},
1004 { FIELD_OFFSET(MIB_UDPSTATS
, dwInErrors
), copyInt
},
1005 { FIELD_OFFSET(MIB_UDPSTATS
, dwOutDatagrams
), copyInt
},
1008 static BOOL
mib2UdpQuery(BYTE bPduType
, SnmpVarBind
*pVarBind
,
1009 AsnInteger32
*pErrorStatus
)
1011 AsnObjectIdentifier myOid
= DEFINE_OID(mib2Udp
);
1014 TRACE("(0x%02x, %s, %p)\n", bPduType
, SnmpUtilOidToA(&pVarBind
->name
),
1020 case SNMP_PDU_GETNEXT
:
1021 *pErrorStatus
= getItemFromOid(&pVarBind
->name
, &myOid
, bPduType
,
1025 *pErrorStatus
= mapStructEntryToValue(mib2UdpMap
,
1026 DEFINE_SIZEOF(mib2UdpMap
), &udpStats
, item
, bPduType
, pVarBind
);
1027 if (!*pErrorStatus
&& bPduType
== SNMP_PDU_GETNEXT
)
1028 setOidWithItem(&pVarBind
->name
, &myOid
, item
);
1032 *pErrorStatus
= SNMP_ERRORSTATUS_READONLY
;
1035 FIXME("0x%02x: unsupported PDU type\n", bPduType
);
1036 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
1041 static UINT mib2UdpEntry
[] = { 1,3,6,1,2,1,7,5,1 };
1042 static PMIB_UDPTABLE udpTable
;
1044 static void mib2UdpEntryInit(void)
1046 DWORD size
= 0, ret
= GetUdpTable(NULL
, &size
, TRUE
);
1048 if (ret
== ERROR_INSUFFICIENT_BUFFER
)
1050 udpTable
= HeapAlloc(GetProcessHeap(), 0, size
);
1052 GetUdpTable(udpTable
, &size
, TRUE
);
1056 static void mib2UdpEntryCleanup(void)
1058 HeapFree(GetProcessHeap(), 0, udpTable
);
1061 static struct structToAsnValue mib2UdpEntryMap
[] = {
1062 { FIELD_OFFSET(MIB_UDPROW
, dwLocalAddr
), copyIpAddr
},
1063 { FIELD_OFFSET(MIB_UDPROW
, dwLocalPort
), copyInt
},
1066 static void oidToUdpRow(AsnObjectIdentifier
*oid
, void *dst
)
1068 MIB_UDPROW
*row
= dst
;
1070 assert(oid
&& oid
->idLength
>= 5);
1071 row
->dwLocalAddr
= oidToIpAddr(oid
);
1072 row
->dwLocalPort
= oid
->ids
[4];
1075 static int compareUdpRow(const void *a
, const void *b
)
1077 const MIB_UDPROW
*key
= a
, *value
= b
;
1080 ret
= key
->dwLocalAddr
- value
->dwLocalAddr
;
1082 ret
= key
->dwLocalPort
- value
->dwLocalPort
;
1086 static BOOL
mib2UdpEntryQuery(BYTE bPduType
, SnmpVarBind
*pVarBind
,
1087 AsnInteger32
*pErrorStatus
)
1089 AsnObjectIdentifier myOid
= DEFINE_OID(mib2UdpEntry
);
1091 TRACE("(0x%02x, %s, %p)\n", bPduType
, SnmpUtilOidToA(&pVarBind
->name
),
1097 case SNMP_PDU_GETNEXT
:
1099 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
1102 UINT tableIndex
= 0, item
= 0;
1104 *pErrorStatus
= getItemAndInstanceFromTable(&pVarBind
->name
, &myOid
,
1105 5, bPduType
, (struct GenericTable
*)udpTable
,
1106 sizeof(MIB_UDPROW
), oidToUdpRow
, compareUdpRow
, &item
,
1112 *pErrorStatus
= mapStructEntryToValue(mib2UdpEntryMap
,
1113 DEFINE_SIZEOF(mib2UdpEntryMap
),
1114 &udpTable
->table
[tableIndex
- 1], item
, bPduType
, pVarBind
);
1115 if (!*pErrorStatus
&& bPduType
== SNMP_PDU_GETNEXT
)
1117 AsnObjectIdentifier oid
;
1119 setOidWithItemAndIpAddr(&pVarBind
->name
, &myOid
, item
,
1120 udpTable
->table
[tableIndex
- 1].dwLocalAddr
);
1122 oid
.ids
= &udpTable
->table
[tableIndex
- 1].dwLocalPort
;
1123 SnmpUtilOidAppend(&pVarBind
->name
, &oid
);
1129 *pErrorStatus
= SNMP_ERRORSTATUS_READONLY
;
1132 FIXME("0x%02x: unsupported PDU type\n", bPduType
);
1133 *pErrorStatus
= SNMP_ERRORSTATUS_NOSUCHNAME
;
1138 /* This list MUST BE lexicographically sorted */
1139 static struct mibImplementation supportedIDs
[] = {
1140 { DEFINE_OID(mib2IfNumber
), mib2IfNumberInit
, mib2IfNumberQuery
,
1141 mib2IfNumberCleanup
},
1142 { DEFINE_OID(mib2IfEntry
), NULL
, mib2IfEntryQuery
, NULL
},
1143 { DEFINE_OID(mib2Ip
), mib2IpStatsInit
, mib2IpStatsQuery
, NULL
},
1144 { DEFINE_OID(mib2IpAddr
), mib2IpAddrInit
, mib2IpAddrQuery
,
1145 mib2IpAddrCleanup
},
1146 { DEFINE_OID(mib2IpRoute
), mib2IpRouteInit
, mib2IpRouteQuery
,
1147 mib2IpRouteCleanup
},
1148 { DEFINE_OID(mib2IpNet
), mib2IpNetInit
, mib2IpNetQuery
, mib2IpNetCleanup
},
1149 { DEFINE_OID(mib2Icmp
), mib2IcmpInit
, mib2IcmpQuery
, NULL
},
1150 { DEFINE_OID(mib2Tcp
), mib2TcpInit
, mib2TcpQuery
, NULL
},
1151 { DEFINE_OID(mib2Udp
), mib2UdpInit
, mib2UdpQuery
, NULL
},
1152 { DEFINE_OID(mib2UdpEntry
), mib2UdpEntryInit
, mib2UdpEntryQuery
,
1153 mib2UdpEntryCleanup
},
1155 static UINT minSupportedIDLength
;
1157 BOOL WINAPI
SnmpExtensionInit(DWORD dwUptimeReference
,
1158 HANDLE
*phSubagentTrapEvent
, AsnObjectIdentifier
*pFirstSupportedRegion
)
1160 AsnObjectIdentifier myOid
= DEFINE_OID(mib2System
);
1163 TRACE("(%d, %p, %p)\n", dwUptimeReference
, phSubagentTrapEvent
,
1164 pFirstSupportedRegion
);
1166 minSupportedIDLength
= UINT_MAX
;
1167 for (i
= 0; i
< sizeof(supportedIDs
) / sizeof(supportedIDs
[0]); i
++)
1169 if (supportedIDs
[i
].init
)
1170 supportedIDs
[i
].init();
1171 if (supportedIDs
[i
].name
.idLength
< minSupportedIDLength
)
1172 minSupportedIDLength
= supportedIDs
[i
].name
.idLength
;
1174 *phSubagentTrapEvent
= NULL
;
1175 SnmpUtilOidCpy(pFirstSupportedRegion
, &myOid
);
1179 static void cleanup(void)
1183 for (i
= 0; i
< sizeof(supportedIDs
) / sizeof(supportedIDs
[0]); i
++)
1184 if (supportedIDs
[i
].cleanup
)
1185 supportedIDs
[i
].cleanup();
1188 static struct mibImplementation
*findSupportedQuery(UINT
*ids
, UINT idLength
,
1189 UINT
*matchingIndex
)
1191 int indexHigh
= DEFINE_SIZEOF(supportedIDs
) - 1, indexLow
= 0, i
;
1192 struct mibImplementation
*impl
= NULL
;
1193 AsnObjectIdentifier oid1
= { idLength
, ids
};
1197 for (i
= (indexLow
+ indexHigh
) / 2; !impl
&& indexLow
<= indexHigh
;
1198 i
= (indexLow
+ indexHigh
) / 2)
1202 cmp
= SnmpUtilOidNCmp(&oid1
, &supportedIDs
[i
].name
, idLength
);
1205 impl
= &supportedIDs
[i
];
1216 BOOL WINAPI
SnmpExtensionQuery(BYTE bPduType
, SnmpVarBindList
*pVarBindList
,
1217 AsnInteger32
*pErrorStatus
, AsnInteger32
*pErrorIndex
)
1219 AsnObjectIdentifier mib2oid
= DEFINE_OID(mib2
);
1220 AsnInteger32 error
= SNMP_ERRORSTATUS_NOERROR
, errorIndex
= 0;
1223 TRACE("(0x%02x, %p, %p, %p)\n", bPduType
, pVarBindList
,
1224 pErrorStatus
, pErrorIndex
);
1226 for (i
= 0; !error
&& i
< pVarBindList
->len
; i
++)
1228 /* Ignore any OIDs not in MIB2 */
1229 if (!SnmpUtilOidNCmp(&pVarBindList
->list
[i
].name
, &mib2oid
,
1232 struct mibImplementation
*impl
= NULL
;
1233 UINT len
, matchingIndex
= 0;
1235 TRACE("%s\n", SnmpUtilOidToA(&pVarBindList
->list
[i
].name
));
1236 /* Search for an implementation matching as many octets as possible
1238 for (len
= pVarBindList
->list
[i
].name
.idLength
;
1239 len
>= minSupportedIDLength
&& !impl
; len
--)
1240 impl
= findSupportedQuery(pVarBindList
->list
[i
].name
.ids
, len
,
1242 if (impl
&& impl
->query
)
1243 impl
->query(bPduType
, &pVarBindList
->list
[i
], &error
);
1245 error
= SNMP_ERRORSTATUS_NOSUCHNAME
;
1246 if (error
== SNMP_ERRORSTATUS_NOSUCHNAME
&&
1247 bPduType
== SNMP_PDU_GETNEXT
)
1249 /* GetNext is special: it finds the successor to the given OID,
1250 * so we have to continue until an implementation handles the
1251 * query or we exhaust the table of supported OIDs.
1253 for (; error
== SNMP_ERRORSTATUS_NOSUCHNAME
&&
1254 matchingIndex
< DEFINE_SIZEOF(supportedIDs
);
1257 error
= SNMP_ERRORSTATUS_NOERROR
;
1258 impl
= &supportedIDs
[matchingIndex
];
1260 impl
->query(bPduType
, &pVarBindList
->list
[i
], &error
);
1262 error
= SNMP_ERRORSTATUS_NOSUCHNAME
;
1264 /* If the query still isn't resolved, set the OID to the
1265 * successor to the last entry in the table.
1267 if (error
== SNMP_ERRORSTATUS_NOSUCHNAME
)
1269 SnmpUtilOidFree(&pVarBindList
->list
[i
].name
);
1270 SnmpUtilOidCpy(&pVarBindList
->list
[i
].name
,
1271 &supportedIDs
[matchingIndex
- 1].name
);
1272 pVarBindList
->list
[i
].name
.ids
[
1273 pVarBindList
->list
[i
].name
.idLength
- 1] += 1;
1280 *pErrorStatus
= error
;
1281 *pErrorIndex
= errorIndex
;
1285 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
1287 TRACE("(0x%p, %d, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
1291 case DLL_PROCESS_ATTACH
:
1292 DisableThreadLibraryCalls(hinstDLL
);
1294 case DLL_PROCESS_DETACH
: