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
= ARRAY_SIZE(bogus
);
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
= ARRAY_SIZE(mib2IfTable
);
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
= ARRAY_SIZE(mib2IfDescr
);
165 vars
[0].name
.ids
= mib2IfDescr
;
166 vars
[1].name
.idLength
= ARRAY_SIZE(mib2IfAdminStatus
);
167 vars
[1].name
.ids
= mib2IfAdminStatus
;
168 vars
[2].name
.idLength
= ARRAY_SIZE(mib2IfOperStatus
);
169 vars
[2].name
.ids
= mib2IfOperStatus
;
171 SetLastError(0xdeadbeef);
174 ret
= pSnmpExtensionQuery(SNMP_PDU_GET
, &list
, &error
, &index
);
175 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
176 ok(error
== SNMP_ERRORSTATUS_NOSUCHNAME
,
177 "expected SNMP_ERRORSTATUS_NOSUCHNAME, got %d\n", error
);
178 ok(index
== 1, "expected index 1, got %d\n", index
);
179 /* but a GetNext succeeds with the same values, because GetNext gets the
180 * entry after the specified OID, not the entry specified by it. The
181 * successor to the table is the first entry in the table.
182 * The OIDs need to be allocated, because GetNext modifies them to indicate
185 SnmpUtilOidCpy(&vars2
[0].name
, &vars
[0].name
);
186 SnmpUtilOidCpy(&vars2
[1].name
, &vars
[1].name
);
187 SnmpUtilOidCpy(&vars2
[2].name
, &vars
[2].name
);
193 SetLastError(0xdeadbeef);
196 ret
= pSnmpExtensionQuery(SNMP_PDU_GETNEXT
, &list
, &error
, &index
);
197 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
198 ok(error
== SNMP_ERRORSTATUS_NOERROR
,
199 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error
);
200 ok(index
== 0, "expected index 0, got %d\n", index
);
205 else if (SnmpUtilOidNCmp(&vars2
[0].name
, &vars
[0].name
,
206 vars
[0].name
.idLength
))
208 else if (SnmpUtilOidNCmp(&vars2
[1].name
, &vars
[1].name
,
209 vars
[1].name
.idLength
))
211 else if (SnmpUtilOidNCmp(&vars2
[2].name
, &vars
[2].name
,
212 vars
[2].name
.idLength
))
214 else if (!SnmpUtilOidCmp(&vars
[0].name
, &vars2
[0].name
) ||
215 !SnmpUtilOidCmp(&vars
[1].name
, &vars2
[1].name
) ||
216 !SnmpUtilOidCmp(&vars
[2].name
, &vars2
[2].name
))
218 /* If the OID isn't modified, the function isn't implemented on this
219 * platform, skip the remaining tests.
227 /* Check the OIDs. For these types of values (display strings and
228 * integers) they should increase by 1 for each element of the table
229 * according to RFC 1158. Windows sometimes has a weird value in the
230 * table, so allow any value as long as it's greater than the previous
233 ok(vars2
[0].name
.idLength
== vars
[0].name
.idLength
+ 1,
234 "expected length %d, got %d\n", vars
[0].name
.idLength
+ 1,
235 vars2
[0].name
.idLength
);
236 lastID
= vars2
[0].name
.ids
[vars2
[0].name
.idLength
- 1];
237 ok(lastID
== entry
+ 1 || broken(lastID
> entry
),
238 "expected %d, got %d\n", entry
+ 1, lastID
);
239 ok(vars2
[1].name
.idLength
== vars
[1].name
.idLength
+ 1,
240 "expected length %d, got %d\n", vars
[1].name
.idLength
+ 1,
241 vars2
[1].name
.idLength
);
242 lastID
= vars2
[1].name
.ids
[vars2
[1].name
.idLength
- 1];
243 ok(lastID
== entry
+ 1 || broken(lastID
> entry
),
244 "expected %d, got %d\n", entry
+ 1, lastID
);
245 ok(vars2
[2].name
.idLength
== vars
[2].name
.idLength
+ 1,
246 "expected length %d, got %d\n", vars
[2].name
.idLength
+ 1,
247 vars2
[2].name
.idLength
);
248 lastID
= vars2
[2].name
.ids
[vars2
[2].name
.idLength
- 1];
249 ok(lastID
== entry
+ 1 || broken(lastID
> entry
),
250 "expected %d, got %d\n", entry
+ 1, lastID
);
252 /* Check the types while we're at it */
253 ok(vars2
[0].value
.asnType
== ASN_OCTETSTRING
,
254 "expected ASN_OCTETSTRING, got %02x\n", vars2
[0].value
.asnType
);
255 ok(vars2
[1].value
.asnType
== ASN_INTEGER
,
256 "expected ASN_INTEGER, got %02x\n", vars2
[1].value
.asnType
);
257 ok(vars2
[2].value
.asnType
== ASN_INTEGER
,
258 "expected ASN_INTEGER, got %02x\n", vars2
[2].value
.asnType
);
261 skip("no change in OID, no MIB2 IF table implementation\n");
262 } while (moreData
&& !noChange
);
263 SnmpUtilVarBindFree(&vars2
[0]);
264 SnmpUtilVarBindFree(&vars2
[1]);
265 SnmpUtilVarBindFree(&vars2
[2]);
267 /* Even though SnmpExtensionInit says this DLL supports the MIB2 system
268 * variables, on recent systems (at least Win2k) the first variable it
269 * returns a value for is the first interface.
271 vars
[0].name
.idLength
= ARRAY_SIZE(mib2System
);
272 vars
[0].name
.ids
= mib2System
;
273 SnmpUtilOidCpy(&vars2
[0].name
, &vars
[0].name
);
274 vars2
[0].value
.asnType
= 0;
278 ret
= pSnmpExtensionQuery(SNMP_PDU_GETNEXT
, &list
, &error
, &index
);
279 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
280 ok(error
== SNMP_ERRORSTATUS_NOERROR
,
281 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error
);
282 ok(index
== 0, "expected index 0, got %d\n", index
);
283 vars3
[0].name
.idLength
= ARRAY_SIZE(mib2If
);
284 vars3
[0].name
.ids
= mib2If
;
285 ok(!SnmpUtilOidNCmp(&vars2
[0].name
, &vars
[0].name
, vars
[0].name
.idLength
) ||
286 !SnmpUtilOidNCmp(&vars2
[0].name
, &vars3
[0].name
, vars3
[0].name
.idLength
),
287 "expected 1.3.6.1.2.1.1 or 1.3.6.1.2.1.2, got %s\n",
288 SnmpUtilOidToA(&vars2
[0].name
));
289 SnmpUtilVarBindFree(&vars2
[0]);
291 /* Check the type and OIDs of the IP address table */
292 vars
[0].name
.idLength
= ARRAY_SIZE(mib2IpAddr
);
293 vars
[0].name
.ids
= mib2IpAddr
;
294 SnmpUtilOidCpy(&vars2
[0].name
, &vars
[0].name
);
295 vars2
[0].value
.asnType
= 0;
300 ret
= pSnmpExtensionQuery(SNMP_PDU_GETNEXT
, &list
, &error
, &index
);
301 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
302 ok(error
== SNMP_ERRORSTATUS_NOERROR
,
303 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error
);
304 ok(index
== 0, "expected index 0, got %d\n", index
);
309 else if (SnmpUtilOidNCmp(&vars2
[0].name
, &vars
[0].name
,
310 vars
[0].name
.idLength
))
312 else if (!SnmpUtilOidCmp(&vars2
[0].name
, &vars
[0].name
))
314 /* If the OID isn't modified, the function isn't implemented on this
315 * platform, skip the remaining tests.
321 /* Make sure the size of the OID is right.
322 * FIXME: don't know if IPv6 addrs are shared with this table.
323 * Don't think so, but I'm not certain.
325 ok(vars2
[0].name
.idLength
== vars
[0].name
.idLength
+ 4,
326 "expected length %d, got %d\n", vars
[0].name
.idLength
+ 4,
327 vars2
[0].name
.idLength
);
328 /* Make sure the type is right */
329 ok(vars2
[0].value
.asnType
== ASN_IPADDRESS
,
330 "expected type ASN_IPADDRESS, got %02x\n",
331 vars2
[0].value
.asnType
);
332 if (vars2
[0].value
.asnType
== ASN_IPADDRESS
)
336 /* This looks uglier than it is: the base OID for the IP
337 * address, 1.3.6.1.2.1.4.20.1.1, is appended with the IP
338 * address of the entry. So e.g. the loopback address is
339 * identified in MIB2 as 1.3.6.1.2.1.4.20.1.1.127.0.0.1
341 for (i
= 0; i
< vars2
[0].value
.asnValue
.address
.length
; i
++)
343 ok(vars2
[0].value
.asnValue
.address
.stream
[i
] ==
344 vars2
[0].name
.ids
[vars2
[0].name
.idLength
- 4 + i
],
345 "expected ident byte %d to be %d, got %d\n", i
,
346 vars2
[0].value
.asnValue
.address
.stream
[i
],
347 vars2
[0].name
.ids
[vars2
[0].name
.idLength
- 4 + i
]);
352 skip("no change in OID, no MIB2 IP address table implementation\n");
353 } while (moreData
&& !noChange
);
354 SnmpUtilVarBindFree(&vars2
[0]);
356 /* Check the type and OIDs of the IP route table */
357 vars
[0].name
.idLength
= DEFINE_SIZEOF(mib2IpRouteTable
);
358 vars
[0].name
.ids
= mib2IpRouteTable
;
359 SnmpUtilOidCpy(&vars2
[0].name
, &vars
[0].name
);
360 vars2
[0].value
.asnType
= 0;
366 ret
= pSnmpExtensionQuery(SNMP_PDU_GETNEXT
, &list
, &error
, &index
);
367 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
368 ok(error
== SNMP_ERRORSTATUS_NOERROR
,
369 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error
);
370 ok(index
== 0, "expected index 0, got %d\n", index
);
375 else if (SnmpUtilOidNCmp(&vars2
[0].name
, &vars
[0].name
,
376 vars
[0].name
.idLength
))
378 else if (!SnmpUtilOidCmp(&vars2
[0].name
, &vars
[0].name
))
380 /* If the OID isn't modified, the function isn't implemented on this
381 * platform, skip the remaining tests.
387 /* Make sure the size of the OID is right.
388 * FIXME: don't know if IPv6 addrs are shared with this table.
389 * Don't think so, but I'm not certain.
391 ok(vars2
[0].name
.idLength
== vars
[0].name
.idLength
+ 4,
392 "expected length %d, got %d\n", vars
[0].name
.idLength
+ 4,
393 vars2
[0].name
.idLength
);
394 /* Make sure the type is right */
395 ok(vars2
[0].value
.asnType
== ASN_IPADDRESS
,
396 "expected type ASN_IPADDRESS, got %02x\n",
397 vars2
[0].value
.asnType
);
398 if (vars2
[0].value
.asnType
== ASN_IPADDRESS
)
402 /* The base OID for the route table, 1.3.6.1.2.1.4.21.1.1, is
403 * appended with the dest IP address of the entry. So e.g. a
404 * route entry for 224.0.0.0 is identified in MIB2 as
405 * 1.3.6.1.2.1.4.21.1.1.224.0.0.0
407 for (i
= 0; i
< vars2
[0].value
.asnValue
.address
.length
; i
++)
409 ok(vars2
[0].value
.asnValue
.address
.stream
[i
] ==
410 vars2
[0].name
.ids
[vars2
[0].name
.idLength
- 4 + i
],
411 "expected ident byte %d to be %d, got %d\n", i
,
412 vars2
[0].value
.asnValue
.address
.stream
[i
],
413 vars2
[0].name
.ids
[vars2
[0].name
.idLength
- 4 + i
]);
418 skip("no change in OID, no MIB2 IP route table implementation\n");
419 } while (moreData
&& !noChange
);
420 SnmpUtilVarBindFree(&vars2
[0]);
422 /* Check the type and OIDs of the UDP table */
423 vars
[0].name
.idLength
= DEFINE_SIZEOF(mib2UdpTable
);
424 vars
[0].name
.ids
= mib2UdpTable
;
425 SnmpUtilOidCpy(&vars2
[0].name
, &vars
[0].name
);
426 vars2
[0].value
.asnType
= 0;
432 ret
= pSnmpExtensionQuery(SNMP_PDU_GETNEXT
, &list
, &error
, &index
);
433 ok(ret
, "SnmpExtensionQuery failed: %d, %d\n", error
, index
);
434 /* FIXME: error and index aren't checked here because the UDP table is
435 * the last OID currently supported by Wine, so the last GetNext fails.
436 * todo_wine is also not effective because it will succeed for all but
437 * the last GetNext. Remove the if (0) if any later OID is supported
441 ok(error
== SNMP_ERRORSTATUS_NOERROR
,
442 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error
);
443 ok(index
== 0, "expected index 0, got %d\n", index
);
449 else if (SnmpUtilOidNCmp(&vars2
[0].name
, &vars
[0].name
,
450 vars
[0].name
.idLength
))
452 else if (!SnmpUtilOidCmp(&vars2
[0].name
, &vars
[0].name
))
454 /* If the OID isn't modified, the function isn't implemented on this
455 * platform, skip the remaining tests.
461 /* Make sure the size of the OID is right. */
462 ok(vars2
[0].name
.idLength
== vars
[0].name
.idLength
+ 5,
463 "expected length %d, got %d\n", vars
[0].name
.idLength
+ 5,
464 vars2
[0].name
.idLength
);
465 /* Make sure the type is right */
466 ok(vars2
[0].value
.asnType
== ASN_IPADDRESS
,
467 "expected type ASN_IPADDRESS, got %02x\n",
468 vars2
[0].value
.asnType
);
469 if (vars2
[0].value
.asnType
== ASN_IPADDRESS
)
473 /* Again with the ugly: the base OID for the UDP table,
474 * 1.3.6.1.2.1.7.5.1, is appended with the local IP address and
475 * port number of the entry. So e.g. an entry for
476 * 192.168.1.1:4000 is identified in MIB2 as
477 * 1.3.6.1.2.1.7.5.1.192.168.1.1.4000
479 for (i
= 0; i
< vars2
[0].value
.asnValue
.address
.length
; i
++)
481 ok(vars2
[0].value
.asnValue
.address
.stream
[i
] ==
482 vars2
[0].name
.ids
[vars2
[0].name
.idLength
- 5 + i
],
483 "expected ident byte %d to be %d, got %d\n", i
,
484 vars2
[0].value
.asnValue
.address
.stream
[i
],
485 vars2
[0].name
.ids
[vars2
[0].name
.idLength
- 5 + i
]);
490 skip("no change in OID, no MIB2 UDP table implementation\n");
491 } while (moreData
&& !noChange
);
492 SnmpUtilVarBindFree(&vars2
[0]);
499 if (!(mod
= init_test_functions()))
505 uninit_test_functions(mod
);