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 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));
52 static void testQuery(void)
54 BOOL (WINAPI *pQuery)(BYTE, SnmpVarBindList *, AsnInteger32 *,
58 AsnInteger32 error, index;
59 UINT bogus[] = { 1,2,3,4 };
60 UINT mib2System[] = { 1,3,6,1,2,1,1 };
61 UINT mib2If[] = { 1,3,6,1,2,1,2 };
62 UINT mib2IfTable[] = { 1,3,6,1,2,1,2,2 };
63 UINT mib2IfDescr[] = { 1,3,6,1,2,1,2,2,1,2 };
64 UINT mib2IfAdminStatus[] = { 1,3,6,1,2,1,2,2,1,7 };
65 UINT mib2IfOperStatus[] = { 1,3,6,1,2,1,2,2,1,8 };
66 UINT mib2IpAddr[] = { 1,3,6,1,2,1,4,20,1,1 };
67 UINT mib2IpRouteTable[] = { 1,3,6,1,2,1,4,21,1,1 };
68 UINT mib2UdpTable[] = { 1,3,6,1,2,1,7,5,1,1 };
69 SnmpVarBind vars[3], vars2[3];
72 pQuery = (void *)GetProcAddress(inetmib1, "SnmpExtensionQuery");
75 skip("couldn't find SnmpExtensionQuery\n");
79 ret = pQuery(0, NULL, NULL, NULL);
80 ret = pQuery(0, NULL, &error, NULL);
81 ret = pQuery(0, NULL, NULL, &index);
82 ret = pQuery(0, &list, NULL, NULL);
83 ret = pQuery(0, &list, &error, NULL);
86 /* An empty list succeeds */
90 ret = pQuery(SNMP_PDU_GET, &list, &error, &index);
91 ok(ret, "SnmpExtensionQuery failed: %d\n", GetLastError());
92 ok(error == SNMP_ERRORSTATUS_NOERROR,
93 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error);
94 ok(index == 0, "expected index 0, got %d\n", index);
96 /* Oddly enough, this "succeeds," even though the OID is clearly
99 vars[0].name.idLength = sizeof(bogus) / sizeof(bogus[0]);
100 vars[0].name.ids = bogus;
101 vars[0].value.asnType = 0;
104 SetLastError(0xdeadbeef);
107 ret = pQuery(SNMP_PDU_GET, &list, &error, &index);
108 ok(ret, "SnmpExtensionQuery failed: %d\n", GetLastError());
109 ok(error == SNMP_ERRORSTATUS_NOERROR,
110 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error);
111 ok(index == 0, "expected index 0, got %d\n", index);
112 /* The OID isn't changed either: */
113 ok(!strcmp("1.2.3.4", SnmpUtilOidToA(&vars[0].name)),
114 "expected 1.2.3.4, got %s\n", SnmpUtilOidToA(&vars[0].name));
116 /* The table is not an accessible variable, so it fails */
117 vars[0].name.idLength = sizeof(mib2IfTable) / sizeof(mib2IfTable[0]);
118 vars[0].name.ids = mib2IfTable;
119 SetLastError(0xdeadbeef);
122 ret = pQuery(SNMP_PDU_GET, &list, &error, &index);
123 ok(ret, "SnmpExtensionQuery failed: %d\n", GetLastError());
124 ok(error == SNMP_ERRORSTATUS_NOSUCHNAME,
125 "expected SNMP_ERRORSTATUS_NOSUCHNAME, got %d\n", error);
126 /* The index is 1-based rather than 0-based */
127 ok(index == 1, "expected index 1, got %d\n", index);
129 /* A Get fails on something that specifies a table (but not a particular
132 vars[0].name.idLength = sizeof(mib2IfDescr) / sizeof(mib2IfDescr[0]);
133 vars[0].name.ids = mib2IfDescr;
134 vars[1].name.idLength =
135 sizeof(mib2IfAdminStatus) / sizeof(mib2IfAdminStatus[0]);
136 vars[1].name.ids = mib2IfAdminStatus;
137 vars[2].name.idLength =
138 sizeof(mib2IfOperStatus) / sizeof(mib2IfOperStatus[0]);
139 vars[2].name.ids = mib2IfOperStatus;
141 SetLastError(0xdeadbeef);
144 ret = pQuery(SNMP_PDU_GET, &list, &error, &index);
145 ok(ret, "SnmpExtensionQuery failed: %d\n", GetLastError());
146 ok(error == SNMP_ERRORSTATUS_NOSUCHNAME,
147 "expected SNMP_ERRORSTATUS_NOSUCHNAME, got %d\n", error);
148 ok(index == 1, "expected index 1, got %d\n", index);
149 /* but a GetNext succeeds with the same values, because GetNext gets the
150 * entry after the specified OID, not the entry specified by it. The
151 * successor to the table is the first entry in the table.
152 * The OIDs need to be allocated, because GetNext modifies them to indicate
155 SnmpUtilOidCpy(&vars2[0].name, &vars[0].name);
156 SnmpUtilOidCpy(&vars2[1].name, &vars[1].name);
157 SnmpUtilOidCpy(&vars2[2].name, &vars[2].name);
162 SetLastError(0xdeadbeef);
165 ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index);
166 ok(ret, "SnmpExtensionQuery failed: %d\n", GetLastError());
167 ok(error == SNMP_ERRORSTATUS_NOERROR,
168 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error);
169 ok(index == 0, "expected index 0, got %d\n", index);
174 else if (SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name,
175 vars[0].name.idLength))
177 else if (SnmpUtilOidNCmp(&vars2[1].name, &vars[1].name,
178 vars[1].name.idLength))
180 else if (SnmpUtilOidNCmp(&vars2[2].name, &vars[2].name,
181 vars[2].name.idLength))
187 /* Check the OIDs. For these types of values (display strings and
188 * integers) they should increase by 1 for each element of the table
189 * according to RFC 1158. Windows sometimes has a weird value in the
190 * table, so allow any value as long as it's greater than the previous
193 ok(vars2[0].name.idLength == vars[0].name.idLength + 1,
194 "expected length %d, got %d\n", vars[0].name.idLength + 1,
195 vars2[0].name.idLength);
196 lastID = vars2[0].name.ids[vars2[0].name.idLength - 1];
197 ok(lastID == entry + 1 || broken(lastID > entry),
198 "expected %d, got %d\n", entry + 1, lastID);
199 ok(vars2[1].name.idLength == vars[1].name.idLength + 1,
200 "expected length %d, got %d\n", vars[1].name.idLength + 1,
201 vars2[1].name.idLength);
202 lastID = vars2[1].name.ids[vars2[1].name.idLength - 1];
203 ok(lastID == entry + 1 || broken(lastID > entry),
204 "expected %d, got %d\n", entry + 1, lastID);
205 ok(vars2[2].name.idLength == vars[2].name.idLength + 1,
206 "expected length %d, got %d\n", vars[2].name.idLength + 1,
207 vars2[2].name.idLength);
208 lastID = vars2[2].name.ids[vars2[2].name.idLength - 1];
209 ok(lastID == entry + 1 || broken(lastID > entry),
210 "expected %d, got %d\n", entry + 1, lastID);
212 /* Check the types while we're at it */
213 ok(vars2[0].value.asnType == ASN_OCTETSTRING,
214 "expected ASN_OCTETSTRING, got %02x\n", vars2[0].value.asnType);
215 ok(vars2[1].value.asnType == ASN_INTEGER,
216 "expected ASN_INTEGER, got %02x\n", vars2[1].value.asnType);
217 ok(vars2[2].value.asnType == ASN_INTEGER,
218 "expected ASN_INTEGER, got %02x\n", vars2[2].value.asnType);
219 /* Check that the operational status of an interface correctly
220 * follows the MIB2 definition of it, rather than the values
221 * defined for IPHlpApi's dwOperStatus field.
223 ok(vars2[2].value.asnValue.unsigned32 <= 2,
224 "expected a value of 0, 1, or 2, got %u\n",
225 vars2[2].value.asnValue.unsigned32);
228 SnmpUtilVarBindFree(&vars2[0]);
229 SnmpUtilVarBindFree(&vars2[1]);
230 SnmpUtilVarBindFree(&vars2[2]);
232 /* Even though SnmpExtensionInit says this DLL supports the MIB2 system
233 * variables, the first variable it returns a value for is the first
236 vars[0].name.idLength = sizeof(mib2System) / sizeof(mib2System[0]);
237 vars[0].name.ids = mib2System;
238 SnmpUtilOidCpy(&vars2[0].name, &vars[0].name);
239 vars2[0].value.asnType = 0;
243 ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index);
244 ok(ret, "SnmpExtensionQuery failed: %d\n", GetLastError());
245 ok(error == SNMP_ERRORSTATUS_NOERROR,
246 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error);
247 ok(index == 0, "expected index 0, got %d\n", index);
248 vars[0].name.idLength = sizeof(mib2If) / sizeof(mib2If[0]);
249 vars[0].name.ids = mib2If;
250 ok(!SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name, vars[0].name.idLength),
251 "expected 1.3.6.1.2.1.2, got %s\n", SnmpUtilOidToA(&vars2[0].name));
252 SnmpUtilVarBindFree(&vars2[0]);
254 /* Check the type and OIDs of the IP address table */
255 vars[0].name.idLength = sizeof(mib2IpAddr) / sizeof(mib2IpAddr[0]);
256 vars[0].name.ids = mib2IpAddr;
257 SnmpUtilOidCpy(&vars2[0].name, &vars[0].name);
258 vars2[0].value.asnType = 0;
263 ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index);
264 ok(ret, "SnmpExtensionQuery failed: %d\n", GetLastError());
265 ok(error == SNMP_ERRORSTATUS_NOERROR,
266 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error);
267 ok(index == 0, "expected index 0, got %d\n", index);
272 else if (SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name,
273 vars[0].name.idLength))
277 /* Make sure the size of the OID is right.
278 * FIXME: don't know if IPv6 addrs are shared with this table.
279 * Don't think so, but I'm not certain.
281 ok(vars2[0].name.idLength == vars[0].name.idLength + 4,
282 "expected length %d, got %d\n", vars[0].name.idLength + 4,
283 vars2[0].name.idLength);
284 /* Make sure the type is right */
285 ok(vars2[0].value.asnType == ASN_IPADDRESS,
286 "expected type ASN_IPADDRESS, got %02x\n",
287 vars2[0].value.asnType);
288 if (vars2[0].value.asnType == ASN_IPADDRESS)
292 /* This looks uglier than it is: the base OID for the IP
293 * address, 1.3.6.1.2.1.4.20.1.1, is appended with the IP
294 * address of the entry. So e.g. the loopback address is
295 * identified in MIB2 as 1.3.6.1.2.1.4.20.1.1.127.0.0.1
297 for (i = 0; i < vars2[0].value.asnValue.address.length; i++)
299 ok(vars2[0].value.asnValue.address.stream[i] ==
300 vars2[0].name.ids[vars2[0].name.idLength - 4 + i],
301 "expected ident byte %d to be %d, got %d\n", i,
302 vars2[0].value.asnValue.address.stream[i],
303 vars2[0].name.ids[vars2[0].name.idLength - 4 + i]);
308 SnmpUtilVarBindFree(&vars2[0]);
310 /* Check the type and OIDs of the IP route table */
311 vars[0].name.idLength = DEFINE_SIZEOF(mib2IpRouteTable);
312 vars[0].name.ids = mib2IpRouteTable;
313 SnmpUtilOidCpy(&vars2[0].name, &vars[0].name);
314 vars2[0].value.asnType = 0;
319 ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index);
320 ok(ret, "SnmpExtensionQuery failed: %d\n", GetLastError());
321 ok(error == SNMP_ERRORSTATUS_NOERROR,
322 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error);
323 ok(index == 0, "expected index 0, got %d\n", index);
328 else if (SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name,
329 vars[0].name.idLength))
333 /* Make sure the size of the OID is right.
334 * FIXME: don't know if IPv6 addrs are shared with this table.
335 * Don't think so, but I'm not certain.
337 ok(vars2[0].name.idLength = vars[0].name.idLength + 4,
338 "expected length %d, got %d\n", vars[0].name.idLength + 4,
339 vars2[0].name.idLength);
340 /* Make sure the type is right */
341 ok(vars2[0].value.asnType == ASN_IPADDRESS,
342 "expected type ASN_IPADDRESS, got %02x\n",
343 vars2[0].value.asnType);
344 if (vars2[0].value.asnType == ASN_IPADDRESS)
348 /* The base OID for the route table, 1.3.6.1.2.1.4.21.1.1, is
349 * appended with the dest IP address of the entry. So e.g. a
350 * route entry for 224.0.0.0 is identified in MIB2 as
351 * 1.3.6.1.2.1.4.21.1.1.224.0.0.0
353 for (i = 0; i < vars2[0].value.asnValue.address.length; i++)
355 ok(vars2[0].value.asnValue.address.stream[i] ==
356 vars2[0].name.ids[vars2[0].name.idLength - 4 + i],
357 "expected ident byte %d to be %d, got %d\n", i,
358 vars2[0].value.asnValue.address.stream[i],
359 vars2[0].name.ids[vars2[0].name.idLength - 4 + i]);
364 SnmpUtilVarBindFree(&vars2[0]);
366 /* Check the type and OIDs of the UDP table */
367 vars[0].name.idLength = DEFINE_SIZEOF(mib2UdpTable);
368 vars[0].name.ids = mib2UdpTable;
369 SnmpUtilOidCpy(&vars2[0].name, &vars[0].name);
370 vars2[0].value.asnType = 0;
375 ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index);
376 ok(ret, "SnmpExtensionQuery failed: %d\n", GetLastError());
377 /* FIXME: error and index aren't checked here because the UDP table is
378 * the last OID currently supported by Wine, so the last GetNext fails.
379 * todo_wine is also not effective because it will succeed for all but
380 * the last GetNext. Remove the if (0) if any later OID is supported
384 ok(error == SNMP_ERRORSTATUS_NOERROR,
385 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error);
386 ok(index == 0, "expected index 0, got %d\n", index);
392 else if (SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name,
393 vars[0].name.idLength))
397 /* Make sure the size of the OID is right. */
398 ok(vars2[0].name.idLength == vars[0].name.idLength + 5,
399 "expected length %d, got %d\n", vars[0].name.idLength + 5,
400 vars2[0].name.idLength);
401 /* Make sure the type is right */
402 ok(vars2[0].value.asnType == ASN_IPADDRESS,
403 "expected type ASN_IPADDRESS, got %02x\n",
404 vars2[0].value.asnType);
405 if (vars2[0].value.asnType == ASN_IPADDRESS)
409 /* Again with the ugly: the base OID for the UDP table,
410 * 1.3.6.1.2.1.7.5.1, is appended with the local IP address and
411 * port number of the entry. So e.g. an entry for
412 * 192.168.1.1:4000 is identified in MIB2 as
413 * 1.3.6.1.2.1.7.5.1.192.168.1.1.4000
415 for (i = 0; i < vars2[0].value.asnValue.address.length; i++)
417 ok(vars2[0].value.asnValue.address.stream[i] ==
418 vars2[0].name.ids[vars2[0].name.idLength - 5 + i],
419 "expected ident byte %d to be %d, got %d\n", i,
420 vars2[0].value.asnValue.address.stream[i],
421 vars2[0].name.ids[vars2[0].name.idLength - 5 + i]);
426 SnmpUtilVarBindFree(&vars2[0]);
431 inetmib1 = LoadLibraryA("inetmib1");