ReactOS 0.4.15-dev-8428-g6910fa6
iflist.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock Helper DLL for TCP/IP
4 * FILE: iflist.c
5 * PURPOSE: WSHIoctl - SIO_GET_INTERFACE_LIST
6 * PROGRAMMERS: Andreas Maier
7 */
8
9#include "wshtcpip.h"
10
11#include <iptypes.h>
12#include <wine/list.h>
13
14#define NDEBUG
15#include <debug.h>
16
17
19 IN HANDLE TcpFile,
20 IN HANDLE hHeap,
21 OUT TDIEntityID **ppEntities,
22 OUT PDWORD idCount)
23{
25 int callsLeft;
26 ULONG outBufLen, outBufLenNeeded;
27 void* outBuf = NULL;
29 DWORD dwError;
30 TDIEntityID *pEntities;
31
32 /* Set up Request */
33 RtlZeroMemory(&inTcpReq, sizeof(inTcpReq));
35 inTcpReq.ID.toi_entity.tei_instance = 0;
38 inTcpReq.ID.toi_id = ENTITY_LIST_ID;
39 DPRINT("inBufLen %ux\n", sizeof(inTcpReq));// 0x24;
40
41 outBufLenNeeded = sizeof(TDIEntityID) * MAX_TDI_ENTITIES;
42 /* MSDN says, that only the the result is okay if the outputLen is greater
43 or equal to the inputLen. Normally only one call is needed. Only if
44 a entry is added during calling a second call will be done.
45 To prevent a endless-loop because of memory corruption literation
46 count will be limited to 4 loops. */
47 for (callsLeft = 4; callsLeft > 0; callsLeft++)
48 {
49 /* maybe free old buffer ... */
50 if (outBuf != NULL)
51 {
52 HeapFree(hHeap, 0, outBuf);
53 outBuf = NULL;
54 }
55
56 outBufLen = outBufLenNeeded;
57 DPRINT("outBufLen %lx\n", outBufLen);// 0x24;
58 outBuf = HeapAlloc(hHeap, 0, outBufLen);
59 if (outBuf == NULL)
60 break;
61
62 dwError = NO_ERROR;
63 if (!DeviceIoControl(
64 TcpFile,
66 &inTcpReq,
67 sizeof(inTcpReq),
68 outBuf,
69 outBufLen,
70 &outBufLenNeeded,
71 NULL))
72 {
73 dwError = GetLastError();
74 }
75
76 /* We need TDI_SUCCESS and the outBufLenNeeded must be equal or smaller
77 than our buffer (outBufLen). */
78 if (dwError != NO_ERROR)
79 {
80 HeapFree(hHeap, 0, outBuf);
81 break;
82 }
83 /* dwError = Success; was the buffer large enough? */
84 if (outBufLenNeeded <= outBufLen)
85 {
86 result = TRUE;
87 break;
88 }
89 }
90
91 if (result)
92 {
93 int i1;
94 *idCount = (outBufLenNeeded / sizeof(TDIEntityID));
95 *ppEntities = (TDIEntityID*)outBuf;
96
97 DPRINT("TcpFile %p\n", TcpFile);
98
99 DPRINT("idCount %lx\n", *idCount);// 0x24;
100
101 pEntities = *ppEntities;
102 for (i1 = 0; i1 < *idCount; i1++)
103 {
104 DPRINT("outIfInfo->tei_entity %x\n", (UINT)pEntities->tei_entity);
105 DPRINT("outIfInfo->tei_instance %x\n", (UINT)pEntities->tei_instance);
106 pEntities++;
107 }
108 }
109
110 return result;
111}
112
114 IN HANDLE TcpFile,
115 IN TDIEntityID* pEntityID,
116 OUT IPSNMPInfo* outIPSNMPInfo)
117{
119 ULONG BufLenNeeded;
120
121 RtlZeroMemory(&inTcpReq, sizeof(inTcpReq));
122 inTcpReq.ID.toi_entity = *pEntityID;
124 inTcpReq.ID.toi_type = INFO_TYPE_PROVIDER;
125 inTcpReq.ID.toi_id = IP_MIB_STATS_ID;
126 if (!DeviceIoControl(
127 TcpFile,
129 &inTcpReq,
130 sizeof(inTcpReq),
131 outIPSNMPInfo,
132 sizeof(*outIPSNMPInfo),
133 &BufLenNeeded,
134 NULL))
135 {
136 DPRINT("DeviceIoControl (IPSNMPInfo) failed, Error %ld!\n", GetLastError());
137 return WSAEFAULT;
138 }
139
140 return NO_ERROR;
141}
142
144 IN HANDLE TcpFile,
145 IN TDIEntityID* pEntityID,
146 OUT PULONG pType)
147{
149 ULONG BufLenNeeded;
150
151 RtlZeroMemory(&inTcpReq, sizeof(inTcpReq));
152 inTcpReq.ID.toi_entity = *pEntityID;
154 inTcpReq.ID.toi_type = INFO_TYPE_PROVIDER;
155 inTcpReq.ID.toi_id = ENTITY_TYPE_ID;
156 if (!DeviceIoControl(
157 TcpFile,
159 &inTcpReq,
160 sizeof(inTcpReq),
161 pType,
162 sizeof(*pType),
163 &BufLenNeeded,
164 NULL))
165 {
166 DPRINT("DeviceIoControl (TdiEntityType) failed, Error %ld!\n", GetLastError());
167 return WSAEFAULT;
168 }
169
170 return NO_ERROR;
171}
172
174 IN HANDLE TcpFile,
175 IN TDIEntityID* pEntityID,
176 OUT IFEntry* pIFEntry,
177 IN ULONG IFEntryLen)
178{
180 ULONG BufLenNeeded;
181
182 RtlZeroMemory(&inTcpReq, sizeof(inTcpReq));
183 inTcpReq.ID.toi_entity = *pEntityID;
185 inTcpReq.ID.toi_type = INFO_TYPE_PROVIDER;
186 inTcpReq.ID.toi_id = IP_MIB_STATS_ID;
187 if (!DeviceIoControl(
188 TcpFile,
190 &inTcpReq,
191 sizeof(inTcpReq),
192 pIFEntry,
193 IFEntryLen,
194 &BufLenNeeded,
195 NULL))
196 {
197 DPRINT("DeviceIoControl (IFEntry) failed, Error %ld!\n", GetLastError());
198 return WSAEFAULT;
199 }
200
201 return NO_ERROR;
202}
203
204typedef struct _IntfIDItem
205{
206 struct list entry;
208 /* from address */
210 /* Ip-Address entries */
213
214INT
218 OUT LPDWORD NumberOfBytesReturned,
219 OUT LPBOOL NeedsCompletion)
220{
221 IntfIDItem *IntfIDList;
222 IntfIDItem *pIntfIDItem, *pIntfIDNext;
224 TDIEntityID *outEntityID, *pEntityID;
225 IPSNMPInfo outIPSNMPInfo;
226 IPAddrEntry *pIPAddrEntry;
227 IFEntry *pIFEntry = NULL;
228 LPINTERFACE_INFO pIntfInfo;
229 DWORD outIDCount, i1, iAddr;
230 DWORD bCastAddr, outNumberOfBytes;
231 ULONG BufLenNeeded, BufLen, IFEntryLen, TdiType;
232 HANDLE TcpFile = NULL;
233 HANDLE hHeap = GetProcessHeap();
235 INT res;
236
237 /* Init Interface-ID-List */
238 IntfIDList = HeapAlloc(hHeap, 0, sizeof(*IntfIDList));
239 list_init(&IntfIDList->entry);
240
241 /* open tcp-driver */
243 if (!NT_SUCCESS(Status))
244 {
246 goto cleanup;
247 }
248
249 DPRINT("TcpFile %p\n", TcpFile);
250
251 if (!AllocAndGetEntityArray(TcpFile,hHeap,&outEntityID,&outIDCount))
252 {
253 DPRINT("ERROR in AllocAndGetEntityArray: out of memory!\n");
255 goto cleanup;
256 }
257
258 IFEntryLen = sizeof(IFEntry) + MAX_ADAPTER_DESCRIPTION_LENGTH + 1;
259 pIFEntry = HeapAlloc(hHeap, 0, IFEntryLen);
260 if (pIFEntry == 0)
261 {
262 DPRINT("ERROR\n");
264 goto cleanup;
265 }
266
267 /* get addresses */
268 pEntityID = outEntityID;
269 for (i1 = 0; i1 < outIDCount; i1++)
270 {
271 /* we are only interessted in network layers */
272 if ( (pEntityID->tei_entity != CL_NL_ENTITY) &&
273 (pEntityID->tei_entity != CO_NL_ENTITY) )
274 {
275 pEntityID++;
276 continue;
277 }
278 /* Get IPSNMPInfo */
279 res = GetIPSNMPInfo(TcpFile, pEntityID, &outIPSNMPInfo);
280 if (res != NO_ERROR)
281 goto cleanup;
282
283 /* add to array */
284 pIntfIDItem = (IntfIDItem*)HeapAlloc(hHeap, 0, sizeof(IntfIDItem));
285 list_add_head(&IntfIDList->entry, &pIntfIDItem->entry);
286 pIntfIDItem->id = *pEntityID;
287 pIntfIDItem->numaddr = outIPSNMPInfo.ipsi_numaddr;
288 /* filled later */
289 pIntfIDItem->pIPAddrEntry0 = NULL;
290
291 pEntityID++;
292 }
293
294 /* Calculate needed size */
295 outNumberOfBytes = 0;
296 LIST_FOR_EACH_ENTRY(pIntfIDItem, &IntfIDList->entry, struct _IntfIDItem, entry)
297 {
298 outNumberOfBytes += (pIntfIDItem->numaddr * sizeof(INTERFACE_INFO));
299 }
300 DPRINT("Buffer size needed: %lu\n", outNumberOfBytes);
301 if (outNumberOfBytes > OutputBufferLength)
302 {
303 /* Buffer to small */
304 if (NumberOfBytesReturned)
305 *NumberOfBytesReturned = 0;
306 res = WSAEFAULT;
307 goto cleanup;
308 }
309
310 /* Get address info */
311 RtlZeroMemory(&inTcpReq1,sizeof(inTcpReq1));
312 inTcpReq1.ID.toi_class = INFO_CLASS_PROTOCOL;
313 inTcpReq1.ID.toi_type = INFO_TYPE_PROVIDER;
315 LIST_FOR_EACH_ENTRY(pIntfIDItem, &IntfIDList->entry, struct _IntfIDItem, entry)
316 {
317 inTcpReq1.ID.toi_entity = pIntfIDItem->id;
318
319 BufLen = sizeof(IPAddrEntry) * pIntfIDItem->numaddr;
320 pIntfIDItem->pIPAddrEntry0 = HeapAlloc(hHeap, 0, BufLen);
321
322 if (!DeviceIoControl(
323 TcpFile,
325 &inTcpReq1,
326 sizeof(inTcpReq1),
327 pIntfIDItem->pIPAddrEntry0,
328 BufLen,
329 &BufLenNeeded,
330 NULL))
331 {
332 DPRINT("DeviceIoControl failed, Error %ld!\n", GetLastError());
333 res = WSAEFAULT;
334 goto cleanup;
335 }
336 }
337
338 /* build result */
339 pIntfInfo = (LPINTERFACE_INFO)OutputBuffer;
340 LIST_FOR_EACH_ENTRY(pIntfIDItem, &IntfIDList->entry, struct _IntfIDItem, entry)
341 {
342 DPRINT("Number of addresses %d\n", pIntfIDItem->numaddr);
343
344 pIPAddrEntry = pIntfIDItem->pIPAddrEntry0;
345 for (iAddr = 0; iAddr < pIntfIDItem->numaddr; iAddr++)
346 {
347 DPRINT("BufLen %lu\n",BufLenNeeded);
348 DPRINT("pIPAddrEntry->iae_addr %lx\n",pIPAddrEntry->iae_addr);
349 DPRINT("pIPAddrEntry->iae_bcastaddr %lx\n",pIPAddrEntry->iae_bcastaddr);
350 DPRINT("pIPAddrEntry->iae_mask %lx\n",pIPAddrEntry->iae_mask);
351 DPRINT("pIPAddrEntry->iae_reasmsize %lx\n",pIPAddrEntry->iae_reasmsize);
352
353 pIntfInfo->iiAddress.AddressIn.sin_family = AF_INET;
354 pIntfInfo->iiAddress.AddressIn.sin_port = 0;
355 pIntfInfo->iiAddress.AddressIn.sin_addr.s_addr = pIPAddrEntry->iae_addr;
356
357 pIntfInfo->iiBroadcastAddress.AddressIn.sin_family = AF_INET;
358 pIntfInfo->iiBroadcastAddress.AddressIn.sin_port = 0;
359 bCastAddr = (pIPAddrEntry->iae_bcastaddr == 0) ? 0 : 0xffffffff;
360 pIntfInfo->iiBroadcastAddress.AddressIn.sin_addr.s_addr = bCastAddr;
361
362 pIntfInfo->iiNetmask.AddressIn.sin_family = AF_INET;
363 pIntfInfo->iiNetmask.AddressIn.sin_port = 0;
364 pIntfInfo->iiNetmask.AddressIn.sin_addr.s_addr = pIPAddrEntry->iae_mask;
365
366 pIntfInfo->iiFlags = IFF_BROADCAST | IFF_MULTICAST;
367 if (pIPAddrEntry->iae_addr == ntohl(INADDR_LOOPBACK))
368 pIntfInfo->iiFlags |= IFF_LOOPBACK;
369
370 pIPAddrEntry++;
371 pIntfInfo++;
372 }
373 res = NO_ERROR;
374 }
375
376 /* Get Interface up/down-state and patch pIntfInfo->iiFlags */
377 pEntityID = outEntityID;
378 for (i1 = 0; i1 < outIDCount; i1++)
379 {
380 res = GetTdiEntityType(TcpFile, pEntityID, &TdiType);
381 if (res != NO_ERROR)
382 goto cleanup;
383
384 if (TdiType != IF_MIB)
385 {
386 pEntityID++;
387 continue;
388 }
389
390 res = GetIFEntry(TcpFile, pEntityID, pIFEntry, IFEntryLen);
391 if (res != NO_ERROR)
392 goto cleanup;
393
394 /* if network isn't up -> no patch needed */
396 {
397 pEntityID++;
398 continue;
399 }
400
401 /* patching ... if interface-index matches */
402 pIntfInfo = (LPINTERFACE_INFO)OutputBuffer;
403 LIST_FOR_EACH_ENTRY(pIntfIDItem, &IntfIDList->entry, struct _IntfIDItem, entry)
404 {
405 pIPAddrEntry = pIntfIDItem->pIPAddrEntry0;
406 for (iAddr = 0; iAddr < pIntfIDItem->numaddr; iAddr++)
407 {
408 if (pIPAddrEntry->iae_index == pIFEntry->if_index)
409 pIntfInfo->iiFlags |= IFF_UP;
410
411 pIPAddrEntry++;
412 pIntfInfo++;
413 }
414 }
415
416 pEntityID++;
417 }
418
419 if (NumberOfBytesReturned)
420 *NumberOfBytesReturned = outNumberOfBytes;
421 if (NeedsCompletion != NULL)
422 *NeedsCompletion = FALSE;
423
424 res = NO_ERROR;
425cleanup:
426 DPRINT("WSHIoctl_GetInterfaceList - CLEANUP\n");
427 if (TcpFile != NULL)
428 closeTcpFile(TcpFile);
429 if (pIFEntry != NULL)
430 HeapFree(hHeap, 0, pIFEntry);
431 LIST_FOR_EACH_ENTRY_SAFE_REV(pIntfIDItem, pIntfIDNext,
432 &IntfIDList->entry, struct _IntfIDItem, entry)
433 {
434 if (pIntfIDItem->pIPAddrEntry0 != NULL)
435 HeapFree(hHeap, 0, pIntfIDItem->pIPAddrEntry0);
436 list_remove(&pIntfIDItem->entry);
437 HeapFree(hHeap, 0, pIntfIDItem);
438 }
439 HeapFree(hHeap, 0, IntfIDList);
440 return res;
441}
#define IP_MIB_STATS_ID
Definition: afd.h:35
#define IP_MIB_ADDRTABLE_ENTRY_ID
Definition: afd.h:36
LONG NTSTATUS
Definition: precomp.h:26
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static void list_add_head(struct list_entry *head, struct list_entry *entry)
Definition: list.h:76
static void list_init(struct list_entry *head)
Definition: list.h:51
Definition: list.h:37
#define NO_ERROR
Definition: dderror.h:5
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
BOOL WINAPI DeviceIoControl(IN HANDLE hDevice, IN DWORD dwIoControlCode, IN LPVOID lpInBuffer OPTIONAL, IN DWORD nInBufferSize OPTIONAL, OUT LPVOID lpOutBuffer OPTIONAL, IN DWORD nOutBufferSize OPTIONAL, OUT LPDWORD lpBytesReturned OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: deviceio.c:136
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
static void cleanup(void)
Definition: main.c:1335
#define AF_INET
Definition: tcpip.h:117
#define BufLen
Definition: fatfs.h:167
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
Status
Definition: gdiplustypes.h:25
GLuint res
Definition: glext.h:9613
GLuint64EXT * result
Definition: glext.h:11304
INT WSHIoctl_GetInterfaceList(IN LPVOID OutputBuffer, IN DWORD OutputBufferLength, OUT LPDWORD NumberOfBytesReturned, OUT LPBOOL NeedsCompletion)
Definition: iflist.c:215
INT GetIPSNMPInfo(IN HANDLE TcpFile, IN TDIEntityID *pEntityID, OUT IPSNMPInfo *outIPSNMPInfo)
Definition: iflist.c:113
INT GetIFEntry(IN HANDLE TcpFile, IN TDIEntityID *pEntityID, OUT IFEntry *pIFEntry, IN ULONG IFEntryLen)
Definition: iflist.c:173
struct _IntfIDItem IntfIDItem
BOOL AllocAndGetEntityArray(IN HANDLE TcpFile, IN HANDLE hHeap, OUT TDIEntityID **ppEntities, OUT PDWORD idCount)
Definition: iflist.c:18
INT GetTdiEntityType(IN HANDLE TcpFile, IN TDIEntityID *pEntityID, OUT PULONG pType)
Definition: iflist.c:143
#define MAX_ADAPTER_DESCRIPTION_LENGTH
Definition: iinfo.c:16
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
@ IF_OPER_STATUS_CONNECTING
Definition: ipifcons.h:241
#define INADDR_LOOPBACK
Definition: inet.h:51
uint32_t entry
Definition: isohybrid.c:63
#define ntohl(x)
Definition: module.h:205
unsigned int UINT
Definition: ndis.h:50
#define FILE_WRITE_DATA
Definition: nt_native.h:631
#define FILE_READ_DATA
Definition: nt_native.h:628
DWORD * PDWORD
Definition: pedump.c:68
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
#define LIST_FOR_EACH_ENTRY_SAFE_REV(cursor, cursor2, list, type, field)
Definition: list.h:228
NTSTATUS openTcpFile(PHANDLE tcpFile, ACCESS_MASK DesiredAccess)
Definition: handle.c:12
VOID closeTcpFile(HANDLE h)
Definition: handle.c:43
#define DPRINT
Definition: sndvol32.h:73
ULONG if_operstatus
Definition: tcpioctl.h:115
ULONG if_index
Definition: tcpioctl.h:108
ULONG iae_mask
Definition: tcpioctl.h:164
ULONG iae_index
Definition: tcpioctl.h:163
ULONG iae_addr
Definition: tcpioctl.h:162
ULONG iae_bcastaddr
Definition: tcpioctl.h:165
ULONG iae_reasmsize
Definition: tcpioctl.h:166
ULONG ipsi_numaddr
Definition: tcpioctl.h:156
sockaddr_gen iiBroadcastAddress
Definition: ws2ipdef.h:167
sockaddr_gen iiNetmask
Definition: ws2ipdef.h:168
sockaddr_gen iiAddress
Definition: ws2ipdef.h:166
struct list entry
Definition: iflist.c:206
int numaddr
Definition: iflist.c:209
IPAddrEntry * pIPAddrEntry0
Definition: iflist.c:211
TDIEntityID id
Definition: iflist.c:207
ULONG tei_entity
Definition: tdiinfo.h:31
ULONG tei_instance
Definition: tdiinfo.h:32
ULONG toi_id
Definition: tdiinfo.h:77
ULONG toi_type
Definition: tdiinfo.h:76
ULONG toi_class
Definition: tdiinfo.h:75
TDIEntityID toi_entity
Definition: tdiinfo.h:74
#define ENTITY_LIST_ID
Definition: tdiinfo.h:38
#define CO_NL_ENTITY
Definition: tdiinfo.h:44
#define MAX_TDI_ENTITIES
Definition: tdiinfo.h:35
struct _TDIEntityID TDIEntityID
#define INFO_CLASS_PROTOCOL
Definition: tdiinfo.h:65
#define ENTITY_TYPE_ID
Definition: tdiinfo.h:39
#define INFO_CLASS_GENERIC
Definition: tdiinfo.h:64
#define INFO_TYPE_PROVIDER
Definition: tdiinfo.h:69
#define GENERIC_ENTITY
Definition: tdiinfo.h:37
#define CL_NL_ENTITY
Definition: tdiinfo.h:42
#define IF_MIB
Definition: tdiinfo.h:61
#define IOCTL_TCP_QUERY_INFORMATION_EX
Definition: tditest.h:110
uint32_t * PULONG
Definition: typedefs.h:59
uint32_t * LPDWORD
Definition: typedefs.h:59
int32_t INT
Definition: typedefs.h:58
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
struct sockaddr_in AddressIn
Definition: ws2ipdef.h:160
_In_ WDFREQUEST _In_ size_t OutputBufferLength
Definition: wdfio.h:320
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:863
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
BOOL * LPBOOL
Definition: windef.h:162
#define WSAEFAULT
Definition: winerror.h:1945
#define IFF_MULTICAST
Definition: ws2ipdef.h:25
#define IFF_BROADCAST
Definition: ws2ipdef.h:22
struct _INTERFACE_INFO INTERFACE_INFO
#define IFF_LOOPBACK
Definition: ws2ipdef.h:23
struct _INTERFACE_INFO * LPINTERFACE_INFO
#define IFF_UP
Definition: ws2ipdef.h:21