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
24 #include "wine/test.h"
26 static HMODULE inetmib1
;
28 static void testInit(void)
30 BOOL (WINAPI
*pInit
)(DWORD
, HANDLE
*, AsnObjectIdentifier
*);
33 AsnObjectIdentifier oid
;
35 pInit
= (void *)GetProcAddress(inetmib1
, "SnmpExtensionInit");
38 win_skip("no SnmpExtensionInit\n");
42 ret = pInit(0, NULL, NULL);
43 ret = pInit(0, NULL, &oid);
44 ret = pInit(0, &event, NULL);
46 ret
= pInit(0, &event
, &oid
);
47 ok(ret
, "SnmpExtensionInit failed: %d\n", GetLastError());
48 ok(!strcmp("1.3.6.1.2.1.1", SnmpUtilOidToA(&oid
)),
49 "Expected 1.3.6.1.2.1.1, got %s\n", SnmpUtilOidToA(&oid
));
51 SnmpUtilOidFree(&oid
);
54 static void testQuery(void)
56 BOOL (WINAPI
*pQuery
)(BYTE
, SnmpVarBindList
*, AsnInteger32
*,
58 BOOL ret
, moreData
, noChange
;
60 AsnInteger32 error
, index
;
61 UINT bogus
[] = { 1,2,3,4 };
62 UINT mib2System
[] = { 1,3,6,1,2,1,1 };
63 UINT mib2If
[] = { 1,3,6,1,2,1,2 };
64 UINT mib2IfTable
[] = { 1,3,6,1,2,1,2,2 };
65 UINT mib2IfDescr
[] = { 1,3,6,1,2,1,2,2,1,2 };
66 UINT mib2IfAdminStatus
[] = { 1,3,6,1,2,1,2,2,1,7 };
67 UINT mib2IfOperStatus
[] = { 1,3,6,1,2,1,2,2,1,8 };
68 UINT mib2IpAddr
[] = { 1,3,6,1,2,1,4,20,1,1 };
69 UINT mib2IpRouteTable
[] = { 1,3,6,1,2,1,4,21,1,1 };
70 UINT mib2UdpTable
[] = { 1,3,6,1,2,1,7,5,1,1 };
71 SnmpVarBind vars
[3], vars2
[3], vars3
[3];
74 pQuery
= (void *)GetProcAddress(inetmib1
, "SnmpExtensionQuery");
77 win_skip("couldn't find SnmpExtensionQuery\n");
81 ret = pQuery(0, NULL, NULL, NULL);
82 ret = pQuery(0, NULL, &error, NULL);
83 ret = pQuery(0, NULL, NULL, &index);
84 ret = pQuery(0, &list, NULL, NULL);
85 ret = pQuery(0, &list, &error, NULL);
88 /* An empty list succeeds */
92 ret
= pQuery(SNMP_PDU_GET
, &list
, &error
, &index
);
93 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
94 ok(error
== SNMP_ERRORSTATUS_NOERROR
,
95 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error
);
96 ok(index
== 0, "expected index 0, got %d\n", index
);
98 /* Oddly enough, this "succeeds," even though the OID is clearly
101 vars
[0].name
.idLength
= sizeof(bogus
) / sizeof(bogus
[0]);
102 vars
[0].name
.ids
= bogus
;
103 vars
[0].value
.asnType
= 0;
106 SetLastError(0xdeadbeef);
109 ret
= pQuery(SNMP_PDU_GET
, &list
, &error
, &index
);
110 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
111 ok(error
== SNMP_ERRORSTATUS_NOERROR
||
112 broken(error
== ERROR_FILE_NOT_FOUND
) /* NT4 */,
113 "expected SNMP_ERRORSTATUS_NOERROR or ERROR_FILE_NOT_FOUND, got %d\n",
115 if (error
== SNMP_ERRORSTATUS_NOERROR
)
116 ok(index
== 0, "expected index 0, got %d\n", index
);
117 else if (error
== ERROR_FILE_NOT_FOUND
)
118 ok(index
== 1, "expected index 1, got %d\n", index
);
119 /* The OID isn't changed either: */
120 ok(!strcmp("1.2.3.4", SnmpUtilOidToA(&vars
[0].name
)),
121 "expected 1.2.3.4, got %s\n", SnmpUtilOidToA(&vars
[0].name
));
123 /* The table is not an accessible variable, so it fails */
124 vars
[0].name
.idLength
= sizeof(mib2IfTable
) / sizeof(mib2IfTable
[0]);
125 vars
[0].name
.ids
= mib2IfTable
;
126 SetLastError(0xdeadbeef);
129 ret
= pQuery(SNMP_PDU_GET
, &list
, &error
, &index
);
130 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
131 ok(error
== SNMP_ERRORSTATUS_NOSUCHNAME
,
132 "expected SNMP_ERRORSTATUS_NOSUCHNAME, got %d\n", error
);
133 /* The index is 1-based rather than 0-based */
134 ok(index
== 1, "expected index 1, got %d\n", index
);
136 /* A Get fails on something that specifies a table (but not a particular
139 vars
[0].name
.idLength
= sizeof(mib2IfDescr
) / sizeof(mib2IfDescr
[0]);
140 vars
[0].name
.ids
= mib2IfDescr
;
141 vars
[1].name
.idLength
=
142 sizeof(mib2IfAdminStatus
) / sizeof(mib2IfAdminStatus
[0]);
143 vars
[1].name
.ids
= mib2IfAdminStatus
;
144 vars
[2].name
.idLength
=
145 sizeof(mib2IfOperStatus
) / sizeof(mib2IfOperStatus
[0]);
146 vars
[2].name
.ids
= mib2IfOperStatus
;
148 SetLastError(0xdeadbeef);
151 ret
= pQuery(SNMP_PDU_GET
, &list
, &error
, &index
);
152 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
153 ok(error
== SNMP_ERRORSTATUS_NOSUCHNAME
,
154 "expected SNMP_ERRORSTATUS_NOSUCHNAME, got %d\n", error
);
155 ok(index
== 1, "expected index 1, got %d\n", index
);
156 /* but a GetNext succeeds with the same values, because GetNext gets the
157 * entry after the specified OID, not the entry specified by it. The
158 * successor to the table is the first entry in the table.
159 * The OIDs need to be allocated, because GetNext modifies them to indicate
162 SnmpUtilOidCpy(&vars2
[0].name
, &vars
[0].name
);
163 SnmpUtilOidCpy(&vars2
[1].name
, &vars
[1].name
);
164 SnmpUtilOidCpy(&vars2
[2].name
, &vars
[2].name
);
170 SetLastError(0xdeadbeef);
173 ret
= pQuery(SNMP_PDU_GETNEXT
, &list
, &error
, &index
);
174 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
175 ok(error
== SNMP_ERRORSTATUS_NOERROR
,
176 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error
);
177 ok(index
== 0, "expected index 0, got %d\n", index
);
182 else if (SnmpUtilOidNCmp(&vars2
[0].name
, &vars
[0].name
,
183 vars
[0].name
.idLength
))
185 else if (SnmpUtilOidNCmp(&vars2
[1].name
, &vars
[1].name
,
186 vars
[1].name
.idLength
))
188 else if (SnmpUtilOidNCmp(&vars2
[2].name
, &vars
[2].name
,
189 vars
[2].name
.idLength
))
191 else if (!SnmpUtilOidCmp(&vars
[0].name
, &vars2
[0].name
) ||
192 !SnmpUtilOidCmp(&vars
[1].name
, &vars2
[1].name
) ||
193 !SnmpUtilOidCmp(&vars
[2].name
, &vars2
[2].name
))
195 /* If the OID isn't modified, the function isn't implemented on this
196 * platform, skip the remaining tests.
204 /* Check the OIDs. For these types of values (display strings and
205 * integers) they should increase by 1 for each element of the table
206 * according to RFC 1158. Windows sometimes has a weird value in the
207 * table, so allow any value as long as it's greater than the previous
210 ok(vars2
[0].name
.idLength
== vars
[0].name
.idLength
+ 1,
211 "expected length %d, got %d\n", vars
[0].name
.idLength
+ 1,
212 vars2
[0].name
.idLength
);
213 lastID
= vars2
[0].name
.ids
[vars2
[0].name
.idLength
- 1];
214 ok(lastID
== entry
+ 1 || broken(lastID
> entry
),
215 "expected %d, got %d\n", entry
+ 1, lastID
);
216 ok(vars2
[1].name
.idLength
== vars
[1].name
.idLength
+ 1,
217 "expected length %d, got %d\n", vars
[1].name
.idLength
+ 1,
218 vars2
[1].name
.idLength
);
219 lastID
= vars2
[1].name
.ids
[vars2
[1].name
.idLength
- 1];
220 ok(lastID
== entry
+ 1 || broken(lastID
> entry
),
221 "expected %d, got %d\n", entry
+ 1, lastID
);
222 ok(vars2
[2].name
.idLength
== vars
[2].name
.idLength
+ 1,
223 "expected length %d, got %d\n", vars
[2].name
.idLength
+ 1,
224 vars2
[2].name
.idLength
);
225 lastID
= vars2
[2].name
.ids
[vars2
[2].name
.idLength
- 1];
226 ok(lastID
== entry
+ 1 || broken(lastID
> entry
),
227 "expected %d, got %d\n", entry
+ 1, lastID
);
229 /* Check the types while we're at it */
230 ok(vars2
[0].value
.asnType
== ASN_OCTETSTRING
,
231 "expected ASN_OCTETSTRING, got %02x\n", vars2
[0].value
.asnType
);
232 ok(vars2
[1].value
.asnType
== ASN_INTEGER
,
233 "expected ASN_INTEGER, got %02x\n", vars2
[1].value
.asnType
);
234 ok(vars2
[2].value
.asnType
== ASN_INTEGER
,
235 "expected ASN_INTEGER, got %02x\n", vars2
[2].value
.asnType
);
238 skip("no change in OID, no MIB2 IF table implementation\n");
239 } while (moreData
&& !noChange
);
240 SnmpUtilVarBindFree(&vars2
[0]);
241 SnmpUtilVarBindFree(&vars2
[1]);
242 SnmpUtilVarBindFree(&vars2
[2]);
244 /* Even though SnmpExtensionInit says this DLL supports the MIB2 system
245 * variables, on recent systems (at least Win2k) the first variable it
246 * returns a value for is the first interface.
248 vars
[0].name
.idLength
= sizeof(mib2System
) / sizeof(mib2System
[0]);
249 vars
[0].name
.ids
= mib2System
;
250 SnmpUtilOidCpy(&vars2
[0].name
, &vars
[0].name
);
251 vars2
[0].value
.asnType
= 0;
255 ret
= pQuery(SNMP_PDU_GETNEXT
, &list
, &error
, &index
);
256 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
257 ok(error
== SNMP_ERRORSTATUS_NOERROR
,
258 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error
);
259 ok(index
== 0, "expected index 0, got %d\n", index
);
260 vars3
[0].name
.idLength
= sizeof(mib2If
) / sizeof(mib2If
[0]);
261 vars3
[0].name
.ids
= mib2If
;
262 ok(!SnmpUtilOidNCmp(&vars2
[0].name
, &vars
[0].name
, vars
[0].name
.idLength
) ||
263 !SnmpUtilOidNCmp(&vars2
[0].name
, &vars3
[0].name
, vars3
[0].name
.idLength
),
264 "expected 1.3.6.1.2.1.1 or 1.3.6.1.2.1.2, got %s\n",
265 SnmpUtilOidToA(&vars2
[0].name
));
266 SnmpUtilVarBindFree(&vars2
[0]);
268 /* Check the type and OIDs of the IP address table */
269 vars
[0].name
.idLength
= sizeof(mib2IpAddr
) / sizeof(mib2IpAddr
[0]);
270 vars
[0].name
.ids
= mib2IpAddr
;
271 SnmpUtilOidCpy(&vars2
[0].name
, &vars
[0].name
);
272 vars2
[0].value
.asnType
= 0;
277 ret
= pQuery(SNMP_PDU_GETNEXT
, &list
, &error
, &index
);
278 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
279 ok(error
== SNMP_ERRORSTATUS_NOERROR
,
280 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error
);
281 ok(index
== 0, "expected index 0, got %d\n", index
);
286 else if (SnmpUtilOidNCmp(&vars2
[0].name
, &vars
[0].name
,
287 vars
[0].name
.idLength
))
289 else if (!SnmpUtilOidCmp(&vars2
[0].name
, &vars
[0].name
))
291 /* If the OID isn't modified, the function isn't implemented on this
292 * platform, skip the remaining tests.
298 /* Make sure the size of the OID is right.
299 * FIXME: don't know if IPv6 addrs are shared with this table.
300 * Don't think so, but I'm not certain.
302 ok(vars2
[0].name
.idLength
== vars
[0].name
.idLength
+ 4,
303 "expected length %d, got %d\n", vars
[0].name
.idLength
+ 4,
304 vars2
[0].name
.idLength
);
305 /* Make sure the type is right */
306 ok(vars2
[0].value
.asnType
== ASN_IPADDRESS
,
307 "expected type ASN_IPADDRESS, got %02x\n",
308 vars2
[0].value
.asnType
);
309 if (vars2
[0].value
.asnType
== ASN_IPADDRESS
)
313 /* This looks uglier than it is: the base OID for the IP
314 * address, 1.3.6.1.2.1.4.20.1.1, is appended with the IP
315 * address of the entry. So e.g. the loopback address is
316 * identified in MIB2 as 1.3.6.1.2.1.4.20.1.1.127.0.0.1
318 for (i
= 0; i
< vars2
[0].value
.asnValue
.address
.length
; i
++)
320 ok(vars2
[0].value
.asnValue
.address
.stream
[i
] ==
321 vars2
[0].name
.ids
[vars2
[0].name
.idLength
- 4 + i
],
322 "expected ident byte %d to be %d, got %d\n", i
,
323 vars2
[0].value
.asnValue
.address
.stream
[i
],
324 vars2
[0].name
.ids
[vars2
[0].name
.idLength
- 4 + i
]);
329 skip("no change in OID, no MIB2 IP address table implementation\n");
330 } while (moreData
&& !noChange
);
331 SnmpUtilVarBindFree(&vars2
[0]);
333 /* Check the type and OIDs of the IP route table */
334 vars
[0].name
.idLength
= DEFINE_SIZEOF(mib2IpRouteTable
);
335 vars
[0].name
.ids
= mib2IpRouteTable
;
336 SnmpUtilOidCpy(&vars2
[0].name
, &vars
[0].name
);
337 vars2
[0].value
.asnType
= 0;
343 ret
= pQuery(SNMP_PDU_GETNEXT
, &list
, &error
, &index
);
344 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
345 ok(error
== SNMP_ERRORSTATUS_NOERROR
,
346 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error
);
347 ok(index
== 0, "expected index 0, got %d\n", index
);
352 else if (SnmpUtilOidNCmp(&vars2
[0].name
, &vars
[0].name
,
353 vars
[0].name
.idLength
))
355 else if (!SnmpUtilOidCmp(&vars2
[0].name
, &vars
[0].name
))
357 /* If the OID isn't modified, the function isn't implemented on this
358 * platform, skip the remaining tests.
364 /* Make sure the size of the OID is right.
365 * FIXME: don't know if IPv6 addrs are shared with this table.
366 * Don't think so, but I'm not certain.
368 ok(vars2
[0].name
.idLength
== vars
[0].name
.idLength
+ 4,
369 "expected length %d, got %d\n", vars
[0].name
.idLength
+ 4,
370 vars2
[0].name
.idLength
);
371 /* Make sure the type is right */
372 ok(vars2
[0].value
.asnType
== ASN_IPADDRESS
,
373 "expected type ASN_IPADDRESS, got %02x\n",
374 vars2
[0].value
.asnType
);
375 if (vars2
[0].value
.asnType
== ASN_IPADDRESS
)
379 /* The base OID for the route table, 1.3.6.1.2.1.4.21.1.1, is
380 * appended with the dest IP address of the entry. So e.g. a
381 * route entry for 224.0.0.0 is identified in MIB2 as
382 * 1.3.6.1.2.1.4.21.1.1.224.0.0.0
384 for (i
= 0; i
< vars2
[0].value
.asnValue
.address
.length
; i
++)
386 ok(vars2
[0].value
.asnValue
.address
.stream
[i
] ==
387 vars2
[0].name
.ids
[vars2
[0].name
.idLength
- 4 + i
],
388 "expected ident byte %d to be %d, got %d\n", i
,
389 vars2
[0].value
.asnValue
.address
.stream
[i
],
390 vars2
[0].name
.ids
[vars2
[0].name
.idLength
- 4 + i
]);
395 skip("no change in OID, no MIB2 IP route table implementation\n");
396 } while (moreData
&& !noChange
);
397 SnmpUtilVarBindFree(&vars2
[0]);
399 /* Check the type and OIDs of the UDP table */
400 vars
[0].name
.idLength
= DEFINE_SIZEOF(mib2UdpTable
);
401 vars
[0].name
.ids
= mib2UdpTable
;
402 SnmpUtilOidCpy(&vars2
[0].name
, &vars
[0].name
);
403 vars2
[0].value
.asnType
= 0;
409 ret
= pQuery(SNMP_PDU_GETNEXT
, &list
, &error
, &index
);
410 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
411 /* FIXME: error and index aren't checked here because the UDP table is
412 * the last OID currently supported by Wine, so the last GetNext fails.
413 * todo_wine is also not effective because it will succeed for all but
414 * the last GetNext. Remove the if (0) if any later OID is supported
418 ok(error
== SNMP_ERRORSTATUS_NOERROR
,
419 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error
);
420 ok(index
== 0, "expected index 0, got %d\n", index
);
426 else if (SnmpUtilOidNCmp(&vars2
[0].name
, &vars
[0].name
,
427 vars
[0].name
.idLength
))
429 else if (!SnmpUtilOidCmp(&vars2
[0].name
, &vars
[0].name
))
431 /* If the OID isn't modified, the function isn't implemented on this
432 * platform, skip the remaining tests.
438 /* Make sure the size of the OID is right. */
439 ok(vars2
[0].name
.idLength
== vars
[0].name
.idLength
+ 5,
440 "expected length %d, got %d\n", vars
[0].name
.idLength
+ 5,
441 vars2
[0].name
.idLength
);
442 /* Make sure the type is right */
443 ok(vars2
[0].value
.asnType
== ASN_IPADDRESS
,
444 "expected type ASN_IPADDRESS, got %02x\n",
445 vars2
[0].value
.asnType
);
446 if (vars2
[0].value
.asnType
== ASN_IPADDRESS
)
450 /* Again with the ugly: the base OID for the UDP table,
451 * 1.3.6.1.2.1.7.5.1, is appended with the local IP address and
452 * port number of the entry. So e.g. an entry for
453 * 192.168.1.1:4000 is identified in MIB2 as
454 * 1.3.6.1.2.1.7.5.1.192.168.1.1.4000
456 for (i
= 0; i
< vars2
[0].value
.asnValue
.address
.length
; i
++)
458 ok(vars2
[0].value
.asnValue
.address
.stream
[i
] ==
459 vars2
[0].name
.ids
[vars2
[0].name
.idLength
- 5 + i
],
460 "expected ident byte %d to be %d, got %d\n", i
,
461 vars2
[0].value
.asnValue
.address
.stream
[i
],
462 vars2
[0].name
.ids
[vars2
[0].name
.idLength
- 5 + i
]);
467 skip("no change in OID, no MIB2 UDP table implementation\n");
468 } while (moreData
&& !noChange
);
469 SnmpUtilVarBindFree(&vars2
[0]);
474 inetmib1
= LoadLibraryA("inetmib1");
477 FreeLibrary(inetmib1
);