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 BOOL (WINAPI
*pSnmpExtensionInit
)(DWORD
, HANDLE
*, AsnObjectIdentifier
*);
27 static BOOL (WINAPI
*pSnmpExtensionQuery
)(BYTE
, SnmpVarBindList
*, AsnInteger32
*, AsnInteger32
*);
29 static HMODULE
init_test_functions(void)
31 HMODULE mod
= LoadLibraryA("inetmib1");
33 ok(mod
!= NULL
, "failed to load inetmib1.dll\n");
35 if (!mod
) return NULL
;
37 pSnmpExtensionInit
= (void *)GetProcAddress(mod
, "SnmpExtensionInit");
38 pSnmpExtensionQuery
= (void *)GetProcAddress(mod
, "SnmpExtensionQuery");
43 static void uninit_test_functions(HMODULE mod
)
48 static void testInit(void)
52 AsnObjectIdentifier oid
;
54 if (!pSnmpExtensionInit
)
56 win_skip("no SnmpExtensionInit\n");
60 if (0) /* crashes on native */
62 ret
= pSnmpExtensionInit(0, NULL
, NULL
);
63 ret
= pSnmpExtensionInit(0, NULL
, &oid
);
64 ret
= pSnmpExtensionInit(0, &event
, NULL
);
67 ret
= pSnmpExtensionInit(0, &event
, &oid
);
68 ok(ret
, "SnmpExtensionInit failed: %d\n", GetLastError());
69 ok(!strcmp("1.3.6.1.2.1.1", SnmpUtilOidToA(&oid
)),
70 "Expected 1.3.6.1.2.1.1, got %s\n", SnmpUtilOidToA(&oid
));
75 /* Fails when called on win8, documentation suggests that
76 extension itself is responsible for freeing this oid */
77 SnmpUtilOidFree(&oid
);
81 static void testQuery(void)
83 BOOL ret
, moreData
, noChange
;
85 AsnInteger32 error
, index
;
86 UINT bogus
[] = { 1,2,3,4 };
87 UINT mib2System
[] = { 1,3,6,1,2,1,1 };
88 UINT mib2If
[] = { 1,3,6,1,2,1,2 };
89 UINT mib2IfTable
[] = { 1,3,6,1,2,1,2,2 };
90 UINT mib2IfDescr
[] = { 1,3,6,1,2,1,2,2,1,2 };
91 UINT mib2IfAdminStatus
[] = { 1,3,6,1,2,1,2,2,1,7 };
92 UINT mib2IfOperStatus
[] = { 1,3,6,1,2,1,2,2,1,8 };
93 UINT mib2IpAddr
[] = { 1,3,6,1,2,1,4,20,1,1 };
94 UINT mib2IpRouteTable
[] = { 1,3,6,1,2,1,4,21,1,1 };
95 UINT mib2UdpTable
[] = { 1,3,6,1,2,1,7,5,1,1 };
96 SnmpVarBind vars
[3], vars2
[3], vars3
[3];
99 if (!pSnmpExtensionQuery
)
101 win_skip("couldn't find SnmpExtensionQuery\n");
105 if (0) /* crashes on native */
107 ret
= pSnmpExtensionQuery(0, NULL
, NULL
, NULL
);
108 ret
= pSnmpExtensionQuery(0, NULL
, &error
, NULL
);
109 ret
= pSnmpExtensionQuery(0, NULL
, NULL
, &index
);
110 ret
= pSnmpExtensionQuery(0, &list
, NULL
, NULL
);
111 ret
= pSnmpExtensionQuery(0, &list
, &error
, NULL
);
113 /* An empty list succeeds */
117 ret
= pSnmpExtensionQuery(SNMP_PDU_GET
, &list
, &error
, &index
);
118 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
119 ok(error
== SNMP_ERRORSTATUS_NOERROR
,
120 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error
);
121 ok(index
== 0, "expected index 0, got %d\n", index
);
123 /* Oddly enough, this "succeeds," even though the OID is clearly
126 vars
[0].name
.idLength
= sizeof(bogus
) / sizeof(bogus
[0]);
127 vars
[0].name
.ids
= bogus
;
128 vars
[0].value
.asnType
= 0;
131 SetLastError(0xdeadbeef);
134 ret
= pSnmpExtensionQuery(SNMP_PDU_GET
, &list
, &error
, &index
);
135 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
136 ok(error
== SNMP_ERRORSTATUS_NOERROR
||
137 broken(error
== ERROR_FILE_NOT_FOUND
) /* NT4 */,
138 "expected SNMP_ERRORSTATUS_NOERROR or ERROR_FILE_NOT_FOUND, got %d\n",
140 if (error
== SNMP_ERRORSTATUS_NOERROR
)
141 ok(index
== 0, "expected index 0, got %d\n", index
);
142 else if (error
== ERROR_FILE_NOT_FOUND
)
143 ok(index
== 1, "expected index 1, got %d\n", index
);
144 /* The OID isn't changed either: */
145 ok(!strcmp("1.2.3.4", SnmpUtilOidToA(&vars
[0].name
)),
146 "expected 1.2.3.4, got %s\n", SnmpUtilOidToA(&vars
[0].name
));
148 /* The table is not an accessible variable, so it fails */
149 vars
[0].name
.idLength
= sizeof(mib2IfTable
) / sizeof(mib2IfTable
[0]);
150 vars
[0].name
.ids
= mib2IfTable
;
151 SetLastError(0xdeadbeef);
154 ret
= pSnmpExtensionQuery(SNMP_PDU_GET
, &list
, &error
, &index
);
155 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
156 ok(error
== SNMP_ERRORSTATUS_NOSUCHNAME
,
157 "expected SNMP_ERRORSTATUS_NOSUCHNAME, got %d\n", error
);
158 /* The index is 1-based rather than 0-based */
159 ok(index
== 1, "expected index 1, got %d\n", index
);
161 /* A Get fails on something that specifies a table (but not a particular
164 vars
[0].name
.idLength
= sizeof(mib2IfDescr
) / sizeof(mib2IfDescr
[0]);
165 vars
[0].name
.ids
= mib2IfDescr
;
166 vars
[1].name
.idLength
=
167 sizeof(mib2IfAdminStatus
) / sizeof(mib2IfAdminStatus
[0]);
168 vars
[1].name
.ids
= mib2IfAdminStatus
;
169 vars
[2].name
.idLength
=
170 sizeof(mib2IfOperStatus
) / sizeof(mib2IfOperStatus
[0]);
171 vars
[2].name
.ids
= mib2IfOperStatus
;
173 SetLastError(0xdeadbeef);
176 ret
= pSnmpExtensionQuery(SNMP_PDU_GET
, &list
, &error
, &index
);
177 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
178 ok(error
== SNMP_ERRORSTATUS_NOSUCHNAME
,
179 "expected SNMP_ERRORSTATUS_NOSUCHNAME, got %d\n", error
);
180 ok(index
== 1, "expected index 1, got %d\n", index
);
181 /* but a GetNext succeeds with the same values, because GetNext gets the
182 * entry after the specified OID, not the entry specified by it. The
183 * successor to the table is the first entry in the table.
184 * The OIDs need to be allocated, because GetNext modifies them to indicate
187 SnmpUtilOidCpy(&vars2
[0].name
, &vars
[0].name
);
188 SnmpUtilOidCpy(&vars2
[1].name
, &vars
[1].name
);
189 SnmpUtilOidCpy(&vars2
[2].name
, &vars
[2].name
);
195 SetLastError(0xdeadbeef);
198 ret
= pSnmpExtensionQuery(SNMP_PDU_GETNEXT
, &list
, &error
, &index
);
199 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
200 ok(error
== SNMP_ERRORSTATUS_NOERROR
,
201 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error
);
202 ok(index
== 0, "expected index 0, got %d\n", index
);
207 else if (SnmpUtilOidNCmp(&vars2
[0].name
, &vars
[0].name
,
208 vars
[0].name
.idLength
))
210 else if (SnmpUtilOidNCmp(&vars2
[1].name
, &vars
[1].name
,
211 vars
[1].name
.idLength
))
213 else if (SnmpUtilOidNCmp(&vars2
[2].name
, &vars
[2].name
,
214 vars
[2].name
.idLength
))
216 else if (!SnmpUtilOidCmp(&vars
[0].name
, &vars2
[0].name
) ||
217 !SnmpUtilOidCmp(&vars
[1].name
, &vars2
[1].name
) ||
218 !SnmpUtilOidCmp(&vars
[2].name
, &vars2
[2].name
))
220 /* If the OID isn't modified, the function isn't implemented on this
221 * platform, skip the remaining tests.
229 /* Check the OIDs. For these types of values (display strings and
230 * integers) they should increase by 1 for each element of the table
231 * according to RFC 1158. Windows sometimes has a weird value in the
232 * table, so allow any value as long as it's greater than the previous
235 ok(vars2
[0].name
.idLength
== vars
[0].name
.idLength
+ 1,
236 "expected length %d, got %d\n", vars
[0].name
.idLength
+ 1,
237 vars2
[0].name
.idLength
);
238 lastID
= vars2
[0].name
.ids
[vars2
[0].name
.idLength
- 1];
239 ok(lastID
== entry
+ 1 || broken(lastID
> entry
),
240 "expected %d, got %d\n", entry
+ 1, lastID
);
241 ok(vars2
[1].name
.idLength
== vars
[1].name
.idLength
+ 1,
242 "expected length %d, got %d\n", vars
[1].name
.idLength
+ 1,
243 vars2
[1].name
.idLength
);
244 lastID
= vars2
[1].name
.ids
[vars2
[1].name
.idLength
- 1];
245 ok(lastID
== entry
+ 1 || broken(lastID
> entry
),
246 "expected %d, got %d\n", entry
+ 1, lastID
);
247 ok(vars2
[2].name
.idLength
== vars
[2].name
.idLength
+ 1,
248 "expected length %d, got %d\n", vars
[2].name
.idLength
+ 1,
249 vars2
[2].name
.idLength
);
250 lastID
= vars2
[2].name
.ids
[vars2
[2].name
.idLength
- 1];
251 ok(lastID
== entry
+ 1 || broken(lastID
> entry
),
252 "expected %d, got %d\n", entry
+ 1, lastID
);
254 /* Check the types while we're at it */
255 ok(vars2
[0].value
.asnType
== ASN_OCTETSTRING
,
256 "expected ASN_OCTETSTRING, got %02x\n", vars2
[0].value
.asnType
);
257 ok(vars2
[1].value
.asnType
== ASN_INTEGER
,
258 "expected ASN_INTEGER, got %02x\n", vars2
[1].value
.asnType
);
259 ok(vars2
[2].value
.asnType
== ASN_INTEGER
,
260 "expected ASN_INTEGER, got %02x\n", vars2
[2].value
.asnType
);
263 skip("no change in OID, no MIB2 IF table implementation\n");
264 } while (moreData
&& !noChange
);
265 SnmpUtilVarBindFree(&vars2
[0]);
266 SnmpUtilVarBindFree(&vars2
[1]);
267 SnmpUtilVarBindFree(&vars2
[2]);
269 /* Even though SnmpExtensionInit says this DLL supports the MIB2 system
270 * variables, on recent systems (at least Win2k) the first variable it
271 * returns a value for is the first interface.
273 vars
[0].name
.idLength
= sizeof(mib2System
) / sizeof(mib2System
[0]);
274 vars
[0].name
.ids
= mib2System
;
275 SnmpUtilOidCpy(&vars2
[0].name
, &vars
[0].name
);
276 vars2
[0].value
.asnType
= 0;
280 ret
= pSnmpExtensionQuery(SNMP_PDU_GETNEXT
, &list
, &error
, &index
);
281 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
282 ok(error
== SNMP_ERRORSTATUS_NOERROR
,
283 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error
);
284 ok(index
== 0, "expected index 0, got %d\n", index
);
285 vars3
[0].name
.idLength
= sizeof(mib2If
) / sizeof(mib2If
[0]);
286 vars3
[0].name
.ids
= mib2If
;
287 ok(!SnmpUtilOidNCmp(&vars2
[0].name
, &vars
[0].name
, vars
[0].name
.idLength
) ||
288 !SnmpUtilOidNCmp(&vars2
[0].name
, &vars3
[0].name
, vars3
[0].name
.idLength
),
289 "expected 1.3.6.1.2.1.1 or 1.3.6.1.2.1.2, got %s\n",
290 SnmpUtilOidToA(&vars2
[0].name
));
291 SnmpUtilVarBindFree(&vars2
[0]);
293 /* Check the type and OIDs of the IP address table */
294 vars
[0].name
.idLength
= sizeof(mib2IpAddr
) / sizeof(mib2IpAddr
[0]);
295 vars
[0].name
.ids
= mib2IpAddr
;
296 SnmpUtilOidCpy(&vars2
[0].name
, &vars
[0].name
);
297 vars2
[0].value
.asnType
= 0;
302 ret
= pSnmpExtensionQuery(SNMP_PDU_GETNEXT
, &list
, &error
, &index
);
303 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
304 ok(error
== SNMP_ERRORSTATUS_NOERROR
,
305 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error
);
306 ok(index
== 0, "expected index 0, got %d\n", index
);
311 else if (SnmpUtilOidNCmp(&vars2
[0].name
, &vars
[0].name
,
312 vars
[0].name
.idLength
))
314 else if (!SnmpUtilOidCmp(&vars2
[0].name
, &vars
[0].name
))
316 /* If the OID isn't modified, the function isn't implemented on this
317 * platform, skip the remaining tests.
323 /* Make sure the size of the OID is right.
324 * FIXME: don't know if IPv6 addrs are shared with this table.
325 * Don't think so, but I'm not certain.
327 ok(vars2
[0].name
.idLength
== vars
[0].name
.idLength
+ 4,
328 "expected length %d, got %d\n", vars
[0].name
.idLength
+ 4,
329 vars2
[0].name
.idLength
);
330 /* Make sure the type is right */
331 ok(vars2
[0].value
.asnType
== ASN_IPADDRESS
,
332 "expected type ASN_IPADDRESS, got %02x\n",
333 vars2
[0].value
.asnType
);
334 if (vars2
[0].value
.asnType
== ASN_IPADDRESS
)
338 /* This looks uglier than it is: the base OID for the IP
339 * address, 1.3.6.1.2.1.4.20.1.1, is appended with the IP
340 * address of the entry. So e.g. the loopback address is
341 * identified in MIB2 as 1.3.6.1.2.1.4.20.1.1.127.0.0.1
343 for (i
= 0; i
< vars2
[0].value
.asnValue
.address
.length
; i
++)
345 ok(vars2
[0].value
.asnValue
.address
.stream
[i
] ==
346 vars2
[0].name
.ids
[vars2
[0].name
.idLength
- 4 + i
],
347 "expected ident byte %d to be %d, got %d\n", i
,
348 vars2
[0].value
.asnValue
.address
.stream
[i
],
349 vars2
[0].name
.ids
[vars2
[0].name
.idLength
- 4 + i
]);
354 skip("no change in OID, no MIB2 IP address table implementation\n");
355 } while (moreData
&& !noChange
);
356 SnmpUtilVarBindFree(&vars2
[0]);
358 /* Check the type and OIDs of the IP route table */
359 vars
[0].name
.idLength
= DEFINE_SIZEOF(mib2IpRouteTable
);
360 vars
[0].name
.ids
= mib2IpRouteTable
;
361 SnmpUtilOidCpy(&vars2
[0].name
, &vars
[0].name
);
362 vars2
[0].value
.asnType
= 0;
368 ret
= pSnmpExtensionQuery(SNMP_PDU_GETNEXT
, &list
, &error
, &index
);
369 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
370 ok(error
== SNMP_ERRORSTATUS_NOERROR
,
371 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error
);
372 ok(index
== 0, "expected index 0, got %d\n", index
);
377 else if (SnmpUtilOidNCmp(&vars2
[0].name
, &vars
[0].name
,
378 vars
[0].name
.idLength
))
380 else if (!SnmpUtilOidCmp(&vars2
[0].name
, &vars
[0].name
))
382 /* If the OID isn't modified, the function isn't implemented on this
383 * platform, skip the remaining tests.
389 /* Make sure the size of the OID is right.
390 * FIXME: don't know if IPv6 addrs are shared with this table.
391 * Don't think so, but I'm not certain.
393 ok(vars2
[0].name
.idLength
== vars
[0].name
.idLength
+ 4,
394 "expected length %d, got %d\n", vars
[0].name
.idLength
+ 4,
395 vars2
[0].name
.idLength
);
396 /* Make sure the type is right */
397 ok(vars2
[0].value
.asnType
== ASN_IPADDRESS
,
398 "expected type ASN_IPADDRESS, got %02x\n",
399 vars2
[0].value
.asnType
);
400 if (vars2
[0].value
.asnType
== ASN_IPADDRESS
)
404 /* The base OID for the route table, 1.3.6.1.2.1.4.21.1.1, is
405 * appended with the dest IP address of the entry. So e.g. a
406 * route entry for 224.0.0.0 is identified in MIB2 as
407 * 1.3.6.1.2.1.4.21.1.1.224.0.0.0
409 for (i
= 0; i
< vars2
[0].value
.asnValue
.address
.length
; i
++)
411 ok(vars2
[0].value
.asnValue
.address
.stream
[i
] ==
412 vars2
[0].name
.ids
[vars2
[0].name
.idLength
- 4 + i
],
413 "expected ident byte %d to be %d, got %d\n", i
,
414 vars2
[0].value
.asnValue
.address
.stream
[i
],
415 vars2
[0].name
.ids
[vars2
[0].name
.idLength
- 4 + i
]);
420 skip("no change in OID, no MIB2 IP route table implementation\n");
421 } while (moreData
&& !noChange
);
422 SnmpUtilVarBindFree(&vars2
[0]);
424 /* Check the type and OIDs of the UDP table */
425 vars
[0].name
.idLength
= DEFINE_SIZEOF(mib2UdpTable
);
426 vars
[0].name
.ids
= mib2UdpTable
;
427 SnmpUtilOidCpy(&vars2
[0].name
, &vars
[0].name
);
428 vars2
[0].value
.asnType
= 0;
434 ret
= pSnmpExtensionQuery(SNMP_PDU_GETNEXT
, &list
, &error
, &index
);
435 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
436 /* FIXME: error and index aren't checked here because the UDP table is
437 * the last OID currently supported by Wine, so the last GetNext fails.
438 * todo_wine is also not effective because it will succeed for all but
439 * the last GetNext. Remove the if (0) if any later OID is supported
443 ok(error
== SNMP_ERRORSTATUS_NOERROR
,
444 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error
);
445 ok(index
== 0, "expected index 0, got %d\n", index
);
451 else if (SnmpUtilOidNCmp(&vars2
[0].name
, &vars
[0].name
,
452 vars
[0].name
.idLength
))
454 else if (!SnmpUtilOidCmp(&vars2
[0].name
, &vars
[0].name
))
456 /* If the OID isn't modified, the function isn't implemented on this
457 * platform, skip the remaining tests.
463 /* Make sure the size of the OID is right. */
464 ok(vars2
[0].name
.idLength
== vars
[0].name
.idLength
+ 5,
465 "expected length %d, got %d\n", vars
[0].name
.idLength
+ 5,
466 vars2
[0].name
.idLength
);
467 /* Make sure the type is right */
468 ok(vars2
[0].value
.asnType
== ASN_IPADDRESS
,
469 "expected type ASN_IPADDRESS, got %02x\n",
470 vars2
[0].value
.asnType
);
471 if (vars2
[0].value
.asnType
== ASN_IPADDRESS
)
475 /* Again with the ugly: the base OID for the UDP table,
476 * 1.3.6.1.2.1.7.5.1, is appended with the local IP address and
477 * port number of the entry. So e.g. an entry for
478 * 192.168.1.1:4000 is identified in MIB2 as
479 * 1.3.6.1.2.1.7.5.1.192.168.1.1.4000
481 for (i
= 0; i
< vars2
[0].value
.asnValue
.address
.length
; i
++)
483 ok(vars2
[0].value
.asnValue
.address
.stream
[i
] ==
484 vars2
[0].name
.ids
[vars2
[0].name
.idLength
- 5 + i
],
485 "expected ident byte %d to be %d, got %d\n", i
,
486 vars2
[0].value
.asnValue
.address
.stream
[i
],
487 vars2
[0].name
.ids
[vars2
[0].name
.idLength
- 5 + i
]);
492 skip("no change in OID, no MIB2 UDP table implementation\n");
493 } while (moreData
&& !noChange
);
494 SnmpUtilVarBindFree(&vars2
[0]);
501 if (!(mod
= init_test_functions()))
507 uninit_test_functions(mod
);