nsiproxy: Implement IP compartment get_all_paramters.
[wine.git] / dlls / nsi / tests / nsi.c
blob598e7124afdc9a375a175441a4a7ad9af1645229
1 /*
2 * Network Store Interface tests
4 * Copyright 2021 Huw Davies
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "winsock2.h"
22 #include "winternl.h"
23 #include "ws2ipdef.h"
24 #include "iphlpapi.h"
25 #include "netioapi.h"
26 #include "iptypes.h"
27 #include "netiodef.h"
28 #include "wine/nsi.h"
29 #include "wine/test.h"
31 static int bounded( ULONG64 val, ULONG64 lo, ULONG64 hi )
33 return lo <= val && val <= hi;
36 static void test_nsi_api( void )
38 DWORD rw_sizes[] = { FIELD_OFFSET(struct nsi_ndis_ifinfo_rw, name2), FIELD_OFFSET(struct nsi_ndis_ifinfo_rw, unk),
39 sizeof(struct nsi_ndis_ifinfo_rw) };
40 struct nsi_ndis_ifinfo_rw *rw_tbl, *rw, get_rw, *enum_rw_tbl, *enum_rw;
41 struct nsi_ndis_ifinfo_dynamic *dyn_tbl, *dyn, get_dyn, *enum_dyn_tbl, *enum_dyn;
42 struct nsi_ndis_ifinfo_static *stat_tbl, *stat, get_stat, *enum_stat_tbl, *enum_stat;
43 struct nsi_get_all_parameters_ex get_all_params;
44 struct nsi_get_parameter_ex get_param;
45 struct nsi_enumerate_all_ex enum_params;
46 DWORD err, count, i, rw_size, enum_count;
47 NET_LUID *luid_tbl, *enum_luid_tbl;
49 /* Use the NDIS ifinfo table to test various api */
50 for (i = 0; i < ARRAY_SIZE(rw_sizes); i++)
52 err = NsiAllocateAndGetTable( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, (void **)&luid_tbl, sizeof(*luid_tbl),
53 (void **)&rw_tbl, rw_sizes[i], (void **)&dyn_tbl, sizeof(*dyn_tbl),
54 (void **)&stat_tbl, sizeof(*stat_tbl), &count, 0 );
55 if (!err) break;
57 ok( !err, "got %d\n", err );
58 rw_size = rw_sizes[i];
60 for (i = 0; i < count; i++)
62 winetest_push_context( "%d", i );
63 rw = (struct nsi_ndis_ifinfo_rw *)((BYTE *)rw_tbl + i * rw_size);
64 dyn = dyn_tbl + i;
65 stat = stat_tbl + i;
67 err = NsiGetAllParameters( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, luid_tbl + i, sizeof(*luid_tbl),
68 &get_rw, rw_size, &get_dyn, sizeof(get_dyn), &get_stat, sizeof(get_stat) );
69 ok( !err, "got %d\n", err );
70 /* test a selection of members */
71 ok( IsEqualGUID( &get_rw.network_guid, &rw->network_guid ), "mismatch\n" );
72 ok( get_rw.alias.Length == rw->alias.Length, "mismatch\n" );
73 ok( !memcmp( get_rw.alias.String, rw->alias.String, rw->alias.Length ), "mismatch\n" );
74 ok( get_rw.phys_addr.Length == rw->phys_addr.Length, "mismatch\n" );
75 ok( !memcmp( get_rw.phys_addr.Address, rw->phys_addr.Address, IF_MAX_PHYS_ADDRESS_LENGTH ), "mismatch\n" );
76 ok( get_dyn.oper_status == dyn->oper_status, "mismatch\n" );
77 ok( get_stat.if_index == stat->if_index, "mismatch\n" );
78 ok( IsEqualGUID( &get_stat.if_guid, &stat->if_guid ), "mismatch\n" );
80 memset( &get_rw, 0xcc, sizeof(get_rw) );
81 memset( &get_dyn, 0xcc, sizeof(get_dyn) );
82 memset( &get_stat, 0xcc, sizeof(get_stat) );
84 memset( &get_all_params, 0, sizeof(get_all_params) );
85 get_all_params.first_arg = 1;
86 get_all_params.module = &NPI_MS_NDIS_MODULEID;
87 get_all_params.table = NSI_NDIS_IFINFO_TABLE;
88 get_all_params.key = luid_tbl + i;
89 get_all_params.key_size = sizeof(*luid_tbl);
90 get_all_params.rw_data = &get_rw;
91 get_all_params.rw_size = rw_size;
92 get_all_params.dynamic_data = &get_dyn;
93 get_all_params.dynamic_size = sizeof(get_dyn);
94 get_all_params.static_data = &get_stat;
95 get_all_params.static_size = sizeof(get_stat);
97 err = NsiGetAllParametersEx( &get_all_params );
98 ok( !err, "got %d\n", err );
99 /* test a selection of members */
100 ok( IsEqualGUID( &get_rw.network_guid, &rw->network_guid ), "mismatch\n" );
101 ok( get_rw.alias.Length == rw->alias.Length, "mismatch\n" );
102 ok( !memcmp( get_rw.alias.String, rw->alias.String, rw->alias.Length ), "mismatch\n" );
103 ok( get_rw.phys_addr.Length == rw->phys_addr.Length, "mismatch\n" );
104 ok( !memcmp( get_rw.phys_addr.Address, rw->phys_addr.Address, IF_MAX_PHYS_ADDRESS_LENGTH ), "mismatch\n" );
105 ok( get_dyn.oper_status == dyn->oper_status, "mismatch\n" );
106 ok( get_stat.if_index == stat->if_index, "mismatch\n" );
107 ok( IsEqualGUID( &get_stat.if_guid, &stat->if_guid ), "mismatch\n" );
109 memset( &get_rw, 0xcc, sizeof(get_rw) );
110 memset( &get_dyn, 0xcc, sizeof(get_dyn) );
111 memset( &get_stat, 0xcc, sizeof(get_stat) );
113 err = NsiGetParameter( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, luid_tbl + i, sizeof(*luid_tbl),
114 NSI_PARAM_TYPE_RW, &get_rw.alias, sizeof(get_rw.alias),
115 FIELD_OFFSET(struct nsi_ndis_ifinfo_rw, alias) );
116 ok( !err, "got %d\n", err );
117 ok( get_rw.alias.Length == rw->alias.Length, "mismatch\n" );
118 ok( !memcmp( get_rw.alias.String, rw->alias.String, rw->alias.Length ), "mismatch\n" );
120 err = NsiGetParameter( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, luid_tbl + i, sizeof(*luid_tbl),
121 NSI_PARAM_TYPE_STATIC, &get_stat.if_index, sizeof(get_stat.if_index),
122 FIELD_OFFSET(struct nsi_ndis_ifinfo_static, if_index) );
123 ok( !err, "got %d\n", err );
124 ok( get_stat.if_index == stat->if_index, "mismatch\n" );
126 err = NsiGetParameter( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, luid_tbl + i, sizeof(*luid_tbl),
127 NSI_PARAM_TYPE_STATIC, &get_stat.if_guid, sizeof(get_stat.if_guid),
128 FIELD_OFFSET(struct nsi_ndis_ifinfo_static, if_guid) );
129 ok( !err, "got %d\n", err );
130 ok( IsEqualGUID( &get_stat.if_guid, &stat->if_guid ), "mismatch\n" );
132 memset( &get_rw, 0xcc, sizeof(get_rw) );
133 memset( &get_dyn, 0xcc, sizeof(get_dyn) );
134 memset( &get_stat, 0xcc, sizeof(get_stat) );
136 memset( &get_param, 0, sizeof(get_param) );
137 get_param.first_arg = 1;
138 get_param.module = &NPI_MS_NDIS_MODULEID;
139 get_param.table = NSI_NDIS_IFINFO_TABLE;
140 get_param.key = luid_tbl + i;
141 get_param.key_size = sizeof(*luid_tbl);
143 get_param.param_type = NSI_PARAM_TYPE_RW;
144 get_param.data = &get_rw.alias;
145 get_param.data_size = sizeof(get_rw.alias);
146 get_param.data_offset = FIELD_OFFSET(struct nsi_ndis_ifinfo_rw, alias);
147 err = NsiGetParameterEx( &get_param );
148 ok( !err, "got %d\n", err );
149 ok( get_rw.alias.Length == rw->alias.Length, "mismatch\n" );
150 ok( !memcmp( get_rw.alias.String, rw->alias.String, rw->alias.Length ), "mismatch\n" );
152 get_param.param_type = NSI_PARAM_TYPE_STATIC;
153 get_param.data = &get_stat.if_index;
154 get_param.data_size = sizeof(get_stat.if_index);
155 get_param.data_offset = FIELD_OFFSET(struct nsi_ndis_ifinfo_static, if_index);
156 err = NsiGetParameterEx( &get_param );
157 ok( !err, "got %d\n", err );
158 ok( get_stat.if_index == stat->if_index, "mismatch\n" );
160 get_param.param_type = NSI_PARAM_TYPE_STATIC;
161 get_param.data = &get_stat.if_guid;
162 get_param.data_size = sizeof(get_stat.if_guid);
163 get_param.data_offset = FIELD_OFFSET(struct nsi_ndis_ifinfo_static, if_guid);
164 err = NsiGetParameterEx( &get_param );
165 ok( !err, "got %d\n", err );
166 ok( IsEqualGUID( &get_stat.if_guid, &stat->if_guid ), "mismatch\n" );
167 winetest_pop_context();
170 enum_count = 0;
171 err = NsiEnumerateObjectsAllParameters( 1, 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE,
172 NULL, 0, NULL, 0,
173 NULL, 0, NULL, 0, &enum_count );
174 ok( !err, "got %d\n", err );
175 ok( enum_count == count, "mismatch\n" );
177 enum_luid_tbl = malloc( count * sizeof(*enum_luid_tbl) );
178 enum_rw_tbl = malloc( count * rw_size );
179 enum_dyn_tbl = malloc( count * sizeof(*enum_dyn_tbl) );
180 enum_stat_tbl = malloc( count * sizeof(*enum_stat_tbl) );
182 err = NsiEnumerateObjectsAllParameters( 1, 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE,
183 enum_luid_tbl, sizeof(*enum_luid_tbl), enum_rw_tbl, rw_size,
184 enum_dyn_tbl, sizeof(*enum_dyn_tbl), enum_stat_tbl, sizeof(*enum_stat_tbl),
185 &enum_count );
186 ok( !err, "got %d\n", err );
187 ok( enum_count == count, "mismatch\n" );
189 for (i = 0; i < count; i++)
191 winetest_push_context( "%d", i );
192 rw = (struct nsi_ndis_ifinfo_rw *)((BYTE *)rw_tbl + i * rw_size);
193 enum_rw = (struct nsi_ndis_ifinfo_rw *)((BYTE *)enum_rw_tbl + i * rw_size);
194 dyn = dyn_tbl + i;
195 enum_dyn = enum_dyn_tbl + i;
196 stat = stat_tbl + i;
197 enum_stat = enum_stat_tbl + i;
199 /* test a selection of members */
200 ok( enum_luid_tbl[i].Value == luid_tbl[i].Value, "mismatch\n" );
201 ok( IsEqualGUID( &enum_rw->network_guid, &rw->network_guid ), "mismatch\n" );
202 ok( enum_rw->alias.Length == rw->alias.Length, "mismatch\n" );
203 ok( !memcmp( enum_rw->alias.String, rw->alias.String, rw->alias.Length ), "mismatch\n" );
204 ok( enum_rw->phys_addr.Length == rw->phys_addr.Length, "mismatch\n" );
205 ok( !memcmp( enum_rw->phys_addr.Address, rw->phys_addr.Address, IF_MAX_PHYS_ADDRESS_LENGTH ), "mismatch\n" );
206 ok( enum_dyn->oper_status == dyn->oper_status, "mismatch\n" );
207 ok( enum_stat->if_index == stat->if_index, "mismatch\n" );
208 ok( IsEqualGUID( &enum_stat->if_guid, &stat->if_guid ), "mismatch\n" );
209 winetest_pop_context();
212 if (count > 0)
214 enum_count--;
215 memset( enum_luid_tbl, 0xcc, count * sizeof(*enum_luid_tbl) );
217 err = NsiEnumerateObjectsAllParameters( 1, 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE,
218 enum_luid_tbl, sizeof(*enum_luid_tbl), enum_rw_tbl, rw_size,
219 enum_dyn_tbl, sizeof(*enum_dyn_tbl), enum_stat_tbl, sizeof(*enum_stat_tbl),
220 &enum_count );
221 ok( err == ERROR_MORE_DATA, "got %d\n", err );
222 ok( enum_count == count - 1, "mismatch\n" );
224 for (i = 0; i < enum_count; i++) /* for simplicity just check the luids */
225 ok( enum_luid_tbl[i].Value == luid_tbl[i].Value, "%d: mismatch\n", i );
228 memset( &enum_params, 0, sizeof(enum_params) );
229 enum_params.first_arg = 1;
230 enum_params.second_arg = 1;
231 enum_params.module = &NPI_MS_NDIS_MODULEID;
232 enum_params.table = NSI_NDIS_IFINFO_TABLE;
233 enum_params.key_data = enum_luid_tbl;
234 enum_params.key_size = sizeof(*enum_luid_tbl);
235 enum_params.rw_data = enum_rw_tbl;
236 enum_params.rw_size = rw_size;
237 enum_params.dynamic_data = enum_dyn_tbl;
238 enum_params.dynamic_size = sizeof(*enum_dyn_tbl);
239 enum_params.static_data = enum_stat_tbl;
240 enum_params.static_size = sizeof(*enum_stat_tbl);
241 enum_params.count = count;
243 err = NsiEnumerateObjectsAllParametersEx( &enum_params );
244 ok( !err, "got %d\n", err );
245 ok( enum_params.count == count, "mismatch\n" );
247 free( enum_luid_tbl );
248 free( enum_rw_tbl );
249 free( enum_dyn_tbl );
250 free( enum_stat_tbl );
251 NsiFreeTable( luid_tbl, rw_tbl, dyn_tbl, stat_tbl );
254 static void test_ndis_ifinfo( void )
256 DWORD rw_sizes[] = { FIELD_OFFSET(struct nsi_ndis_ifinfo_rw, name2), FIELD_OFFSET(struct nsi_ndis_ifinfo_rw, unk),
257 sizeof(struct nsi_ndis_ifinfo_rw) };
258 struct nsi_ndis_ifinfo_rw *rw_tbl, rw_get;
259 struct nsi_ndis_ifinfo_dynamic *dyn_tbl, *dyn_tbl_2, dyn_get;
260 struct nsi_ndis_ifinfo_static *stat_tbl, stat_get;
261 DWORD err, count, i, rw_size;
262 NET_LUID *luid_tbl, *luid_tbl_2, luid_get;
263 MIB_IF_TABLE2 *table;
265 /* Contents of GetIfTable2() keyed by luids */
267 for (i = 0; i < ARRAY_SIZE(rw_sizes); i++)
269 err = NsiAllocateAndGetTable( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, (void **)&luid_tbl, sizeof(*luid_tbl),
270 (void **)&rw_tbl, rw_sizes[i], (void **)&dyn_tbl, sizeof(*dyn_tbl),
271 (void **)&stat_tbl, sizeof(*stat_tbl), &count, 0 );
272 if (!err) break;
274 ok( !err, "got %d\n", err );
275 if (err) return;
276 rw_size = rw_sizes[i];
278 err = GetIfTable2( &table );
279 ok( !err, "got %d\n", err );
280 ok( table->NumEntries == count, "table entries %d count %d\n", table->NumEntries, count );
282 /* Grab the dyn table again to provide an upper bound for the stats returned from GetIfTable2().
283 (The luids must be retrieved again otherwise NsiAllocateAndGetTable() fails). */
284 err = NsiAllocateAndGetTable( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, (void **)&luid_tbl_2, sizeof(*luid_tbl_2),
285 NULL, 0, (void **)&dyn_tbl_2, sizeof(*dyn_tbl_2),
286 NULL, 0, &count, 0 );
287 ok( !err, "got %d\n", err );
288 ok( table->NumEntries == count, "table entries %d count %d\n", table->NumEntries, count );
290 for (i = 0; i < count; i++)
292 MIB_IF_ROW2 *row = table->Table + i;
293 NET_LUID *luid = luid_tbl + i;
294 struct nsi_ndis_ifinfo_rw *rw = (struct nsi_ndis_ifinfo_rw *)((BYTE *)rw_tbl + i * rw_size);
295 struct nsi_ndis_ifinfo_dynamic *dyn = dyn_tbl + i, *dyn_2 = dyn_tbl_2 + i;
296 struct nsi_ndis_ifinfo_static *stat = stat_tbl + i;
298 winetest_push_context( "%d", i );
299 ok( row->InterfaceLuid.Value == luid->Value, "mismatch\n" );
300 ok( row->InterfaceIndex == stat->if_index, "mismatch\n" );
301 ok( IsEqualGUID( &row->InterfaceGuid, &stat->if_guid ), "mismatch\n" );
302 ok( !memcmp( row->Alias, rw->alias.String, rw->alias.Length ), "mismatch\n" );
303 ok( lstrlenW( row->Alias ) * 2 == rw->alias.Length, "mismatch\n" );
304 ok( !memcmp( row->Description, stat->descr.String, sizeof(row->Description) ), "mismatch\n" );
305 ok( lstrlenW( row->Description ) * 2 == stat->descr.Length, "mismatch\n" );
306 ok( row->PhysicalAddressLength == rw->phys_addr.Length, "mismatch\n" );
307 ok( !memcmp( row->PhysicalAddress, rw->phys_addr.Address, IF_MAX_PHYS_ADDRESS_LENGTH ), "mismatch\n" );
308 ok( row->PhysicalAddressLength == stat->perm_phys_addr.Length, "mismatch\n" );
309 ok( !memcmp( row->PermanentPhysicalAddress, stat->perm_phys_addr.Address, IF_MAX_PHYS_ADDRESS_LENGTH ),
310 "mismatch\n" );
311 ok( row->Mtu == dyn->mtu, "mismatch\n" );
312 ok( row->Type == stat->type, "mismatch\n" );
313 /* TunnelType */
314 ok( row->MediaType == stat->media_type, "mismatch\n" );
315 ok( row->PhysicalMediumType == stat->phys_medium_type, "mismatch\n" );
316 ok( row->AccessType == stat->access_type, "mismatch\n" );
317 /* DirectionType */
318 ok( row->InterfaceAndOperStatusFlags.HardwareInterface == stat->flags.hw, "mismatch\n" );
319 ok( row->InterfaceAndOperStatusFlags.FilterInterface == stat->flags.filter, "mismatch\n" );
320 ok( row->InterfaceAndOperStatusFlags.ConnectorPresent == stat->conn_present, "mismatch\n" );
321 /* NotAuthenticated */
322 ok( row->InterfaceAndOperStatusFlags.NotMediaConnected == dyn->flags.not_media_conn, "mismatch\n" );
323 /* Paused */
324 /* LowPower */
325 /* EndPointInterface */
326 ok( row->OperStatus == dyn->oper_status, "mismatch\n" );
327 ok( row->AdminStatus == rw->admin_status, "mismatch\n" );
328 ok( row->MediaConnectState == dyn->media_conn_state, "mismatch\n" );
329 ok( IsEqualGUID( &row->NetworkGuid, &rw->network_guid ), "mismatch\n" );
330 ok( row->ConnectionType == stat->conn_type, "mismatch\n" );
331 if (dyn->xmit_speed == ~0ULL) dyn->xmit_speed = 0;
332 ok( row->TransmitLinkSpeed == dyn->xmit_speed, "mismatch\n" );
333 if (dyn->rcv_speed == ~0ULL) dyn->rcv_speed = 0;
334 ok( row->ReceiveLinkSpeed == dyn->rcv_speed, "mismatch\n" );
335 ok( bounded( row->InOctets, dyn->in_octets, dyn_2->in_octets ), "mismatch\n" );
336 ok( bounded( row->InUcastPkts, dyn->in_ucast_pkts, dyn_2->in_ucast_pkts ), "mismatch\n" );
337 ok( bounded( row->InNUcastPkts, dyn->in_mcast_pkts + dyn->in_bcast_pkts,
338 dyn_2->in_mcast_pkts + dyn_2->in_bcast_pkts ), "mismatch\n" );
339 ok( bounded( row->InDiscards, dyn->in_discards, dyn_2->in_discards ), "mismatch\n" );
340 ok( bounded( row->InErrors, dyn->in_errors, dyn_2->in_errors ), "mismatch\n" );
341 /* InUnknownProtos */
342 ok( bounded( row->InUcastOctets, dyn->in_ucast_octs, dyn_2->in_ucast_octs ), "mismatch\n" );
343 ok( bounded( row->InMulticastOctets, dyn->in_mcast_octs, dyn_2->in_mcast_octs ), "mismatch\n" );
344 ok( bounded( row->InBroadcastOctets, dyn->in_bcast_octs, dyn_2->in_bcast_octs ), "mismatch\n" );
345 ok( bounded( row->OutOctets, dyn->out_octets, dyn_2->out_octets ), "mismatch\n" );
346 ok( bounded( row->OutUcastPkts, dyn->out_ucast_pkts, dyn_2->out_ucast_pkts ), "mismatch\n" );
347 ok( bounded( row->OutNUcastPkts, dyn->out_mcast_pkts + dyn->out_bcast_pkts,
348 dyn_2->out_mcast_pkts + dyn_2->out_bcast_pkts ), "mismatch\n" );
349 ok( bounded( row->OutDiscards, dyn->out_discards, dyn_2->out_discards ), "mismatch\n" );
350 ok( bounded( row->OutErrors, dyn->out_errors, dyn_2->out_errors ), "mismatch\n" );
351 ok( bounded( row->OutUcastOctets, dyn->out_ucast_octs, dyn_2->out_ucast_octs ), "mismatch\n" );
352 ok( bounded( row->OutMulticastOctets, dyn->out_mcast_octs, dyn_2->out_mcast_octs ), "mismatch\n" );
353 ok( bounded( row->OutBroadcastOctets, dyn->out_bcast_octs, dyn_2->out_bcast_octs ), "mismatch\n" );
354 /* OutQLen */
355 winetest_pop_context();
357 err = NsiGetAllParameters( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, luid_tbl, sizeof(*luid_tbl),
358 &rw_get, rw_size, &dyn_get, sizeof(dyn_get),
359 &stat_get, sizeof(stat_get) );
360 ok( !err, "got %d\n", err );
361 ok( IsEqualGUID( &stat_tbl[0].if_guid, &stat_get.if_guid ), "mismatch\n" );
363 err = NsiGetParameter( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, luid_tbl, sizeof(*luid_tbl),
364 NSI_PARAM_TYPE_STATIC, &stat_get.if_guid, sizeof(stat_get.if_guid),
365 FIELD_OFFSET(struct nsi_ndis_ifinfo_static, if_guid) );
366 ok( !err, "got %d\n", err );
367 ok( IsEqualGUID( &stat_tbl[0].if_guid, &stat_get.if_guid ), "mismatch\n" );
369 luid_get.Value = ~0u;
370 err = NsiGetAllParameters( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, &luid_get, sizeof(luid_get),
371 &rw_get, rw_size, &dyn_get, sizeof(dyn_get),
372 &stat_get, sizeof(stat_get) );
373 ok( err == ERROR_FILE_NOT_FOUND, "got %d\n", err );
375 err = NsiGetParameter( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, &luid_get, sizeof(luid_get),
376 NSI_PARAM_TYPE_STATIC, &stat_get.if_guid, sizeof(stat_get.if_guid),
377 FIELD_OFFSET(struct nsi_ndis_ifinfo_static, if_guid) );
378 ok( err == ERROR_FILE_NOT_FOUND, "got %d\n", err );
380 FreeMibTable( table );
381 NsiFreeTable( luid_tbl_2, NULL, dyn_tbl_2, NULL );
382 NsiFreeTable( luid_tbl, rw_tbl, dyn_tbl, stat_tbl );
385 static void test_ndis_index_luid( void )
387 DWORD err, count, i;
388 NET_LUID *luids, luid;
389 DWORD index;
391 /* index -> luid map. NsiAllocateAndGetTable and NsiGetAllParameters fail */
393 /* first get the luids */
394 err = NsiAllocateAndGetTable( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, (void **)&luids, sizeof(*luids),
395 NULL, 0, NULL, 0, NULL, 0, &count, 0 );
396 ok( !err, "got %d\n", err );
398 for (i = 0; i < count; i++)
400 ConvertInterfaceLuidToIndex( luids + i, &index );
401 err = NsiGetParameter( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_INDEX_LUID_TABLE, &index, sizeof(index),
402 NSI_PARAM_TYPE_STATIC, &luid, sizeof(luid), 0 );
403 ok( !err, "got %d\n", err );
404 ok( luid.Value == luids[i].Value, "%d: luid mismatch\n", i );
406 NsiFreeTable( luids, NULL, NULL, NULL );
408 index = ~0u;
409 err = NsiGetParameter( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_INDEX_LUID_TABLE, &index, sizeof(index),
410 NSI_PARAM_TYPE_STATIC, &luid, sizeof(luid), 0 );
411 ok( err == ERROR_FILE_NOT_FOUND, "got %d\n", err );
414 static void test_ip_cmpt( int family )
416 DWORD rw_sizes[] = { FIELD_OFFSET(struct nsi_ip_cmpt_rw, unk2), sizeof(struct nsi_ip_cmpt_rw) };
417 const NPI_MODULEID *mod = (family == AF_INET) ? &NPI_MS_IPV4_MODULEID : &NPI_MS_IPV6_MODULEID;
418 struct nsi_ip_cmpt_dynamic dyn;
419 struct nsi_ip_cmpt_rw rw;
420 MIB_IPSTATS table;
421 DWORD err, key, i;
423 winetest_push_context( family == AF_INET ? "AF_INET" : "AF_INET6" );
425 /* key = 0 also seems to work, but NsiAllocateAndGetTable returns
426 a single table with key == 1. Presumably this is the compartment id */
427 key = 1;
428 for (i = 0; i < ARRAY_SIZE(rw_sizes); i++)
430 err = NsiGetAllParameters( 1, mod, 2, &key, sizeof(key), &rw, rw_sizes[i], &dyn, sizeof(dyn), NULL, 0 );
431 if (!err) break;
433 ok( !err, "got %x\n", err );
435 err = GetIpStatisticsEx( &table, family );
436 ok( !err, "got %d\n", err );
437 if (err) goto err;
439 todo_wine_if(family == AF_INET6 && table.dwForwarding - 1 != rw.not_forwarding)
440 ok( table.dwForwarding - 1 == rw.not_forwarding, "%x vs %x\n", table.dwForwarding, rw.not_forwarding );
441 todo_wine_if(family == AF_INET6 && table.dwDefaultTTL != rw.default_ttl)
442 ok( table.dwDefaultTTL == rw.default_ttl, "%x vs %x\n", table.dwDefaultTTL, rw.default_ttl );
443 ok( table.dwNumIf == dyn.num_ifs, "%x vs %x\n", table.dwNumIf, dyn.num_ifs );
444 todo_wine_if(table.dwNumAddr != dyn.num_addrs)
445 ok( table.dwNumAddr == dyn.num_addrs, "%x vs %x\n", table.dwNumAddr, dyn.num_addrs );
446 todo_wine_if(family == AF_INET6 && table.dwNumRoutes != dyn.num_routes)
447 ok( table.dwNumRoutes == dyn.num_routes, "%x vs %x\n", table.dwNumRoutes, dyn.num_routes );
449 err:
450 winetest_pop_context();
454 static void test_ip_ipstats( int family )
456 const NPI_MODULEID *mod = (family == AF_INET) ? &NPI_MS_IPV4_MODULEID : &NPI_MS_IPV6_MODULEID;
457 struct nsi_ip_ipstats_dynamic dyn, dyn2;
458 struct nsi_ip_ipstats_static stat;
459 MIB_IPSTATS table;
460 DWORD err;
462 winetest_push_context( family == AF_INET ? "AF_INET" : "AF_INET6" );
464 /* The table appears to consist of a single object without a key. The rw data does exist but
465 isn't part of GetIpStatisticsEx() and isn't yet tested */
466 err = NsiGetAllParameters( 1, mod, NSI_IP_IPSTATS_TABLE, NULL, 0, NULL, 0, &dyn, sizeof(dyn), &stat, sizeof(stat) );
467 ok( !err, "got %x\n", err );
468 if (err) goto err;
470 err = GetIpStatisticsEx( &table, family );
471 ok( !err, "got %d\n", err );
473 err = NsiGetAllParameters( 1, mod, NSI_IP_IPSTATS_TABLE, NULL, 0, NULL, 0, &dyn2, sizeof(dyn2), NULL, 0 );
474 ok( !err, "got %x\n", err );
476 /* dwForwarding and dwDefaultTTL come from the compartment table */
477 ok( bounded( table.dwInReceives, dyn.in_recv, dyn2.in_recv ), "mismatch\n" );
478 ok( bounded( table.dwInHdrErrors, dyn.in_hdr_errs, dyn2.in_hdr_errs ), "mismatch\n" );
479 ok( bounded( table.dwInAddrErrors, dyn.in_addr_errs, dyn2.in_addr_errs ), "mismatch\n" );
480 ok( bounded( table.dwForwDatagrams, dyn.fwd_dgrams, dyn2.fwd_dgrams ), "mismatch\n" );
481 ok( bounded( table.dwInUnknownProtos, dyn.in_unk_protos, dyn2.in_unk_protos ), "mismatch\n" );
482 ok( bounded( table.dwInDiscards, dyn.in_discards, dyn2.in_discards ), "mismatch\n" );
483 ok( bounded( table.dwInDelivers, dyn.in_delivers, dyn2.in_delivers ), "mismatch\n" );
484 ok( bounded( table.dwOutRequests, dyn.out_reqs, dyn2.out_reqs ), "mismatch\n" );
485 ok( bounded( table.dwRoutingDiscards, dyn.routing_discards, dyn2.routing_discards ), "mismatch\n" );
486 ok( bounded( table.dwOutDiscards, dyn.out_discards, dyn2.out_discards ), "mismatch\n" );
487 ok( bounded( table.dwOutNoRoutes, dyn.out_no_routes, dyn2.out_no_routes ), "mismatch\n" );
488 ok( table.dwReasmTimeout == stat.reasm_timeout, "mismatch\n" );
489 ok( bounded( table.dwReasmReqds, dyn.reasm_reqds, dyn2.reasm_reqds ), "mismatch\n" );
490 ok( bounded( table.dwReasmOks, dyn.reasm_oks, dyn2.reasm_oks ), "mismatch\n" );
491 ok( bounded( table.dwReasmFails, dyn.reasm_fails, dyn2.reasm_fails ), "mismatch\n" );
492 ok( bounded( table.dwFragOks, dyn.frag_oks, dyn2.frag_oks ), "mismatch\n" );
493 ok( bounded( table.dwFragFails, dyn.frag_fails, dyn2.frag_fails ), "mismatch\n" );
494 ok( bounded( table.dwFragCreates, dyn.frag_creates, dyn2.frag_creates ), "mismatch\n" );
495 /* dwNumIf, dwNumAddr and dwNumRoutes come from the compartment table */
497 err:
498 winetest_pop_context();
501 static void test_ip_unicast( int family )
503 DWORD rw_sizes[] = { FIELD_OFFSET(struct nsi_ip_unicast_rw, unk[0]), FIELD_OFFSET(struct nsi_ip_unicast_rw, unk[1]),
504 sizeof(struct nsi_ip_unicast_rw) };
505 struct nsi_ipv4_unicast_key *key_tbl, *key4, get_key;
506 struct nsi_ipv6_unicast_key *key6;
507 struct nsi_ip_unicast_rw *rw_tbl, *rw, get_rw;
508 struct nsi_ip_unicast_dynamic *dyn_tbl, *dyn, get_dyn;
509 struct nsi_ip_unicast_static *stat_tbl, *stat, get_stat;
510 MIB_UNICASTIPADDRESS_TABLE *table;
511 const NPI_MODULEID *mod = (family == AF_INET) ? &NPI_MS_IPV4_MODULEID : &NPI_MS_IPV6_MODULEID;
512 DWORD err, count, i, rw_size, key_size = (family == AF_INET) ? sizeof(*key4) : sizeof(*key6);
514 winetest_push_context( family == AF_INET ? "AF_INET" : "AF_INET6" );
516 for (i = 0; i < ARRAY_SIZE(rw_sizes); i++)
518 err = NsiAllocateAndGetTable( 1, mod, NSI_IP_UNICAST_TABLE, (void **)&key_tbl, key_size,
519 (void **)&rw_tbl, rw_sizes[i], (void **)&dyn_tbl, sizeof(*dyn_tbl),
520 (void **)&stat_tbl, sizeof(*stat_tbl), &count, 0 );
521 if (!err) break;
523 ok( !err, "got %d\n", err );
524 rw_size = rw_sizes[i];
526 err = GetUnicastIpAddressTable( family, &table );
527 ok( !err, "got %d\n", err );
528 ok( table->NumEntries == count, "table entries %d count %d\n", table->NumEntries, count );
530 for (i = 0; i < count; i++)
532 MIB_UNICASTIPADDRESS_ROW *row = table->Table + i;
533 rw = (struct nsi_ip_unicast_rw *)((BYTE *)rw_tbl + i * rw_size);
534 dyn = dyn_tbl + i;
535 stat = stat_tbl + i;
536 winetest_push_context( "%d", i );
538 ok( row->Address.si_family == family, "mismatch\n" );
540 if (family == AF_INET)
542 key4 = key_tbl + i;
543 ok( !memcmp( &row->Address.Ipv4.sin_addr, &key4->addr, sizeof(struct in_addr) ), "mismatch\n" );
544 ok( row->InterfaceLuid.Value == key4->luid.Value, "mismatch\n" );
546 else
548 key6 = (struct nsi_ipv6_unicast_key *)key_tbl + i;
549 ok( !memcmp( &row->Address.Ipv6.sin6_addr, &key6->addr, sizeof(struct in6_addr) ), "mismatch\n" );
550 ok( row->InterfaceLuid.Value == key6->luid.Value, "mismatch\n" );
552 ok( row->PrefixOrigin == rw->prefix_origin, "mismatch\n" );
553 ok( row->SuffixOrigin == rw->suffix_origin, "mismatch\n" );
554 ok( row->ValidLifetime == rw->valid_lifetime, "mismatch\n" );
555 ok( row->PreferredLifetime == rw->preferred_lifetime, "mismatch\n" );
556 ok( row->OnLinkPrefixLength == rw->on_link_prefix, "mismatch\n" );
557 /* SkipAsSource */
558 ok( row->DadState == dyn->dad_state, "mismatch\n" );
559 ok( row->ScopeId.Value == dyn->scope_id, "mismatch\n" );
560 ok( row->CreationTimeStamp.QuadPart == stat->creation_time, "mismatch\n" );
561 winetest_pop_context();
564 get_key.luid.Value = ~0u;
565 get_key.addr.s_addr = 0;
566 err = NsiGetAllParameters( 1, &NPI_MS_IPV4_MODULEID, NSI_IP_UNICAST_TABLE, &get_key, sizeof(get_key),
567 &get_rw, rw_size, &get_dyn, sizeof(get_dyn), &get_stat, sizeof(get_stat) );
568 ok( err == ERROR_NOT_FOUND, "got %d\n", err );
570 FreeMibTable( table );
571 NsiFreeTable( key_tbl, rw_tbl, dyn_tbl, stat_tbl );
572 winetest_pop_context();
575 static void test_ip_neighbour( int family )
577 const NPI_MODULEID *mod = (family == AF_INET) ? &NPI_MS_IPV4_MODULEID : &NPI_MS_IPV6_MODULEID;
578 DWORD err, i, count, count2, attempt;
579 struct nsi_ipv4_neighbour_key *key_tbl, *key_tbl_2, *key4;
580 struct nsi_ipv6_neighbour_key *key6;
581 struct nsi_ip_neighbour_rw *rw_tbl, *rw;
582 struct nsi_ip_neighbour_dynamic *dyn_tbl, *dyn_tbl_2, *dyn;
583 MIB_IPNET_TABLE2 *table;
584 DWORD key_size = (family == AF_INET) ? sizeof(struct nsi_ipv4_neighbour_key) : sizeof(struct nsi_ipv6_neighbour_key);
586 winetest_push_context( family == AF_INET ? "AF_INET" : "AF_INET6" );
588 for (attempt = 0; attempt < 5; attempt++)
590 err = NsiAllocateAndGetTable( 1, mod, NSI_IP_NEIGHBOUR_TABLE, (void **)&key_tbl, key_size,
591 (void **)&rw_tbl, sizeof(*rw), (void **)&dyn_tbl, sizeof(*dyn),
592 NULL, 0, &count, 0 );
593 todo_wine_if( family == AF_INET6 )
594 ok( !err, "got %x\n", err );
595 if (err) goto err;
597 err = GetIpNetTable2( family, &table );
598 ok( !err, "got %x\n", err );
600 err = NsiAllocateAndGetTable( 1, mod, NSI_IP_NEIGHBOUR_TABLE, (void **)&key_tbl_2, key_size,
601 NULL, 0, (void **)&dyn_tbl_2, sizeof(*dyn),
602 NULL, 0, &count2, 0 );
603 ok( !err, "got %x\n", err );
604 if (count == count2 && !memcmp( dyn_tbl, dyn_tbl_2, count * sizeof(*dyn) )) break;
605 NsiFreeTable( key_tbl_2, NULL, dyn_tbl_2, NULL );
606 NsiFreeTable( key_tbl, rw_tbl, dyn_tbl, NULL );
609 ok( count == table->NumEntries, "%d vs %d\n", count, table->NumEntries );
611 for (i = 0; i < count; i++)
613 MIB_IPNET_ROW2 *row = table->Table + i;
614 rw = rw_tbl + i;
615 dyn = dyn_tbl + i;
617 if (family == AF_INET)
619 key4 = key_tbl + i;
620 ok( key4->addr.s_addr == row->Address.Ipv4.sin_addr.s_addr, "%08x vs %08x\n", key4->addr.s_addr,
621 row->Address.Ipv4.sin_addr.s_addr );
622 ok( key4->luid.Value == row->InterfaceLuid.Value, "%s vs %s\n", wine_dbgstr_longlong( key4->luid.Value ),
623 wine_dbgstr_longlong( row->InterfaceLuid.Value ) );
624 ok( key4->luid2.Value == row->InterfaceLuid.Value, "mismatch\n" );
626 else if (family == AF_INET6)
628 key6 = (struct nsi_ipv6_neighbour_key *)key_tbl + i;
629 ok( !memcmp( key6->addr.s6_addr, row->Address.Ipv6.sin6_addr.s6_addr, sizeof(IN6_ADDR) ), "mismatch\n" );
630 ok( key6->luid.Value == row->InterfaceLuid.Value, "mismatch\n" );
631 ok( key6->luid2.Value == row->InterfaceLuid.Value, "mismatch\n" );
634 ok( dyn->phys_addr_len == row->PhysicalAddressLength, "mismatch\n" );
635 ok( !memcmp( rw->phys_addr, row->PhysicalAddress, dyn->phys_addr_len ), "mismatch\n" );
636 ok( dyn->state == row->State, "%x vs %x\n", dyn->state, row->State );
637 ok( dyn->flags.is_router == row->IsRouter, "%x vs %x\n", dyn->flags.is_router, row->IsRouter );
638 ok( dyn->flags.is_unreachable == row->IsUnreachable, "%x vs %x\n", dyn->flags.is_unreachable, row->IsUnreachable );
639 ok( dyn->time == row->ReachabilityTime.LastReachable, "%x vs %x\n", dyn->time, row->ReachabilityTime.LastReachable );
642 NsiFreeTable( key_tbl_2, NULL, dyn_tbl_2, NULL );
643 NsiFreeTable( key_tbl, rw_tbl, dyn_tbl, NULL );
645 err:
646 winetest_pop_context();
649 static void test_ip_forward( int family )
651 DWORD rw_sizes[] = { FIELD_OFFSET(struct nsi_ip_forward_rw, unk),
652 FIELD_OFFSET(struct nsi_ip_forward_rw, unk2), sizeof(struct nsi_ip_forward_rw) };
653 DWORD dyn_sizes4[] = { sizeof(struct nsi_ipv4_forward_dynamic) - 3 * sizeof(DWORD),
654 sizeof(struct nsi_ipv4_forward_dynamic) };
655 DWORD dyn_sizes6[] = { sizeof(struct nsi_ipv6_forward_dynamic) - 3 * sizeof(DWORD),
656 sizeof(struct nsi_ipv6_forward_dynamic) };
657 DWORD *dyn_sizes = family == AF_INET ? dyn_sizes4 : dyn_sizes6;
658 struct nsi_ipv4_forward_key *key_tbl, *key4;
659 struct nsi_ipv6_forward_key *key6;
660 struct nsi_ip_forward_rw *rw_tbl, *rw;
661 struct nsi_ipv4_forward_dynamic *dyn_tbl, *dyn4;
662 struct nsi_ipv6_forward_dynamic *dyn6;
663 struct nsi_ip_forward_static *stat_tbl, *stat;
664 MIB_IPFORWARD_TABLE2 *table;
665 const NPI_MODULEID *mod = (family == AF_INET) ? &NPI_MS_IPV4_MODULEID : &NPI_MS_IPV6_MODULEID;
666 DWORD key_size = (family == AF_INET) ? sizeof(*key4) : sizeof(*key6);
667 DWORD err, count, i, rw_size, dyn_size;
669 winetest_push_context( family == AF_INET ? "AF_INET" : "AF_INET6" );
671 for (i = 0; i < ARRAY_SIZE(rw_sizes); i++)
673 err = NsiAllocateAndGetTable( 1, mod, NSI_IP_FORWARD_TABLE, (void **)&key_tbl, key_size,
674 (void **)&rw_tbl, rw_sizes[i], NULL, 0,
675 NULL, 0, &count, 0 );
676 if (!err) break;
678 ok( !err, "got %d\n", err );
679 if (err) { winetest_pop_context(); return; }
680 rw_size = rw_sizes[i];
681 NsiFreeTable( key_tbl, rw_tbl, NULL, NULL );
683 for (i = 0; i < ARRAY_SIZE(dyn_sizes4); i++)
685 err = NsiAllocateAndGetTable( 1, mod, NSI_IP_FORWARD_TABLE, (void **)&key_tbl, key_size,
686 (void **)&rw_tbl, rw_size, (void **)&dyn_tbl, dyn_sizes[i],
687 (void **)&stat_tbl, sizeof(*stat_tbl), &count, 0 );
688 if (!err) break;
690 ok( !err, "got %d\n", err );
691 dyn_size = dyn_sizes[i];
693 err = GetIpForwardTable2( family, &table );
694 ok( !err, "got %d\n", err );
695 ok( table->NumEntries == count, "table entries %d count %d\n", table->NumEntries, count );
697 for (i = 0; i < count; i++)
699 MIB_IPFORWARD_ROW2 *row = table->Table + i;
700 rw = (struct nsi_ip_forward_rw *)((BYTE *)rw_tbl + i * rw_size);
701 stat = stat_tbl + i;
702 winetest_push_context( "%d", i );
704 ok( row->DestinationPrefix.Prefix.si_family == family, "mismatch\n" );
706 if (family == AF_INET)
708 key4 = key_tbl + i;
709 dyn4 = (struct nsi_ipv4_forward_dynamic *)((BYTE *)dyn_tbl + i * dyn_size);
711 ok( row->InterfaceLuid.Value == key4->luid.Value, "mismatch\n" );
712 ok( row->InterfaceLuid.Value == key4->luid2.Value, "mismatch\n" );
713 ok( row->DestinationPrefix.Prefix.Ipv4.sin_addr.s_addr == key4->prefix.s_addr, "mismatch\n" );
714 ok( row->DestinationPrefix.Prefix.Ipv4.sin_port == 0, "mismatch\n" );
715 ok( row->DestinationPrefix.PrefixLength == key4->prefix_len, "mismatch\n" );
716 ok( row->NextHop.Ipv4.sin_addr.s_addr == key4->next_hop.s_addr, "mismatch\n" );
717 ok( row->NextHop.Ipv4.sin_port == 0, "mismatch\n" );
718 ok( row->Age == dyn4->age, "mismatch\n" );
720 else
722 key6 = (struct nsi_ipv6_forward_key *)key_tbl + i;
723 dyn6 = (struct nsi_ipv6_forward_dynamic *)((BYTE *)dyn_tbl + i * dyn_size);
725 ok( row->InterfaceLuid.Value == key6->luid.Value, "mismatch\n" );
726 ok( row->InterfaceLuid.Value == key6->luid2.Value, "mismatch\n" );
727 ok( !memcmp( &row->DestinationPrefix.Prefix.Ipv6.sin6_addr, &key6->prefix, sizeof(key6->prefix) ),
728 "mismatch\n" );
729 ok( row->DestinationPrefix.Prefix.Ipv6.sin6_port == 0, "mismatch\n" );
730 ok( row->DestinationPrefix.Prefix.Ipv6.sin6_flowinfo == 0, "mismatch\n" );
731 ok( row->DestinationPrefix.Prefix.Ipv6.sin6_scope_id == 0, "mismatch\n" );
732 ok( row->DestinationPrefix.PrefixLength == key6->prefix_len, "mismatch\n" );
733 ok( !memcmp( &row->NextHop.Ipv6.sin6_addr, &key6->next_hop, sizeof(key6->next_hop) ), "mismatch\n" );
734 ok( row->NextHop.Ipv6.sin6_port == 0, "mismatch\n" );
735 ok( row->NextHop.Ipv6.sin6_flowinfo == 0, "mismatch\n" );
736 ok( row->NextHop.Ipv6.sin6_scope_id == 0, "mismatch\n" );
737 ok( row->Age == dyn6->age, "mismatch\n" );
740 ok( row->InterfaceIndex == stat->if_index, "mismatch\n" );
741 ok( row->SitePrefixLength == rw->site_prefix_len, "mismatch\n" );
742 ok( row->ValidLifetime == rw->valid_lifetime, "mismatch\n" );
743 ok( row->PreferredLifetime == rw->preferred_lifetime, "mismatch\n" );
745 ok( row->Metric == rw->metric, "mismatch\n" );
746 ok( row->Protocol == rw->protocol, "mismatch\n" );
747 ok( row->Loopback == rw->loopback, "mismatch\n" );
748 ok( row->AutoconfigureAddress == rw->autoconf, "mismatch\n" );
749 ok( row->Publish == rw->publish, "mismatch\n" );
750 ok( row->Immortal == rw->immortal, "mismatch\n" );
751 ok( row->Origin == stat->origin, "mismatch\n" );
753 winetest_pop_context();
756 FreeMibTable( table );
757 NsiFreeTable( key_tbl, rw_tbl, dyn_tbl, stat_tbl );
758 winetest_pop_context();
761 START_TEST( nsi )
763 test_nsi_api();
765 test_ndis_ifinfo();
766 test_ndis_index_luid();
768 test_ip_cmpt( AF_INET );
769 test_ip_cmpt( AF_INET6 );
770 test_ip_ipstats( AF_INET );
771 test_ip_ipstats( AF_INET6 );
772 test_ip_unicast( AF_INET );
773 test_ip_unicast( AF_INET6 );
774 test_ip_neighbour( AF_INET );
775 test_ip_neighbour( AF_INET6 );
776 test_ip_forward( AF_INET );
777 test_ip_forward( AF_INET6 );