1c2c66affSColin Finck /* Copyright (C) 2003 Art Yerkes
2c2c66affSColin Finck  * A reimplementation of ifenum.c by Juan Lang
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
5c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
6c2c66affSColin Finck  * License as published by the Free Software Foundation; either
7c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
8c2c66affSColin Finck  *
9c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
10c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12c2c66affSColin Finck  * Lesser General Public License for more details.
13c2c66affSColin Finck  *
14c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
15c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
16c2c66affSColin Finck  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17c2c66affSColin Finck  *
18c2c66affSColin Finck  * This file is implemented on the IOCTL_TCP_QUERY_INFORMATION_EX ioctl on
19c2c66affSColin Finck  * tcpip.sys
20c2c66affSColin Finck  */
21c2c66affSColin Finck 
22c2c66affSColin Finck #include "iphlpapi_private.h"
23c2c66affSColin Finck 
24c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
25c2c66affSColin Finck 
26c2c66affSColin Finck #ifndef TCPS_ESTABLISHED
27c2c66affSColin Finck # define TCPS_ESTABLISHED TCP_ESTABLISHED
28c2c66affSColin Finck #endif
29c2c66affSColin Finck #ifndef TCPS_SYN_SENT
30c2c66affSColin Finck # define TCPS_SYN_SENT TCP_SYN_SENT
31c2c66affSColin Finck #endif
32c2c66affSColin Finck #ifndef TCPS_SYN_RECEIVED
33c2c66affSColin Finck # define TCPS_SYN_RECEIVED TCP_SYN_RECV
34c2c66affSColin Finck #endif
35c2c66affSColin Finck #ifndef TCPS_FIN_WAIT_1
36c2c66affSColin Finck # define TCPS_FIN_WAIT_1 TCP_FIN_WAIT1
37c2c66affSColin Finck #endif
38c2c66affSColin Finck #ifndef TCPS_FIN_WAIT_2
39c2c66affSColin Finck # define TCPS_FIN_WAIT_2 TCP_FIN_WAIT2
40c2c66affSColin Finck #endif
41c2c66affSColin Finck #ifndef TCPS_TIME_WAIT
42c2c66affSColin Finck # define TCPS_TIME_WAIT TCP_TIME_WAIT
43c2c66affSColin Finck #endif
44c2c66affSColin Finck #ifndef TCPS_CLOSED
45c2c66affSColin Finck # define TCPS_CLOSED TCP_CLOSE
46c2c66affSColin Finck #endif
47c2c66affSColin Finck #ifndef TCPS_CLOSE_WAIT
48c2c66affSColin Finck # define TCPS_CLOSE_WAIT TCP_CLOSE_WAIT
49c2c66affSColin Finck #endif
50c2c66affSColin Finck #ifndef TCPS_LAST_ACK
51c2c66affSColin Finck # define TCPS_LAST_ACK TCP_LAST_ACK
52c2c66affSColin Finck #endif
53c2c66affSColin Finck #ifndef TCPS_LISTEN
54c2c66affSColin Finck # define TCPS_LISTEN TCP_LISTEN
55c2c66affSColin Finck #endif
56c2c66affSColin Finck #ifndef TCPS_CLOSING
57c2c66affSColin Finck # define TCPS_CLOSING TCP_CLOSING
58c2c66affSColin Finck #endif
59c2c66affSColin Finck 
60c2c66affSColin Finck BOOL isIpEntity( HANDLE tcpFile, TDIEntityID *ent ) {
61c2c66affSColin Finck     return (ent->tei_entity == CL_NL_ENTITY ||
62c2c66affSColin Finck             ent->tei_entity == CO_NL_ENTITY);
63c2c66affSColin Finck }
64c2c66affSColin Finck 
65c2c66affSColin Finck NTSTATUS getNthIpEntity( HANDLE tcpFile, DWORD index, TDIEntityID *ent ) {
66c2c66affSColin Finck     DWORD numEntities = 0;
67c2c66affSColin Finck     DWORD numRoutes = 0;
68c2c66affSColin Finck     TDIEntityID *entitySet = 0;
69c2c66affSColin Finck     NTSTATUS status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities );
70c2c66affSColin Finck     int i;
71c2c66affSColin Finck 
72c2c66affSColin Finck     if( !NT_SUCCESS(status) )
73c2c66affSColin Finck         return status;
74c2c66affSColin Finck 
75c2c66affSColin Finck     for( i = 0; i < numEntities; i++ ) {
76c2c66affSColin Finck         if( isIpEntity( tcpFile, &entitySet[i] ) ) {
77c2c66affSColin Finck             TRACE("Entity %d is an IP Entity\n", i);
78c2c66affSColin Finck             if( numRoutes == index ) break;
79c2c66affSColin Finck             else numRoutes++;
80c2c66affSColin Finck         }
81c2c66affSColin Finck     }
82c2c66affSColin Finck 
83c2c66affSColin Finck     if( numRoutes == index && i < numEntities ) {
846c935922SSerge Gautherie         TRACE("Index %lu is entity #%d - %04x:%08x\n", index, i,
85c2c66affSColin Finck               entitySet[i].tei_entity, entitySet[i].tei_instance);
86c2c66affSColin Finck         memcpy( ent, &entitySet[i], sizeof(*ent) );
87c2c66affSColin Finck         tdiFreeThingSet( entitySet );
88c2c66affSColin Finck         return STATUS_SUCCESS;
89c2c66affSColin Finck     } else {
90c2c66affSColin Finck         tdiFreeThingSet( entitySet );
91c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
92c2c66affSColin Finck     }
93c2c66affSColin Finck }
94c2c66affSColin Finck 
95c2c66affSColin Finck NTSTATUS tdiGetMibForIpEntity
96c2c66affSColin Finck ( HANDLE tcpFile, TDIEntityID *ent, IPSNMPInfo *entry ) {
97c2c66affSColin Finck     TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT;
98c2c66affSColin Finck     NTSTATUS status = STATUS_SUCCESS;
99c2c66affSColin Finck     DWORD returnSize;
100c2c66affSColin Finck 
101c2c66affSColin Finck     memset( entry, 0, sizeof( *entry ) );
102c2c66affSColin Finck 
1036c935922SSerge Gautherie     TRACE("TdiGetMibForIpEntity(tcpFile 0x%p, entityId 0x%x)\n",
1046c935922SSerge Gautherie           tcpFile, ent->tei_instance);
105c2c66affSColin Finck 
106c2c66affSColin Finck     req.ID.toi_class                = INFO_CLASS_PROTOCOL;
107c2c66affSColin Finck     req.ID.toi_type                 = INFO_TYPE_PROVIDER;
108c2c66affSColin Finck     req.ID.toi_id                   = IP_MIB_STATS_ID;
109c2c66affSColin Finck     req.ID.toi_entity               = *ent;
110c2c66affSColin Finck 
111c2c66affSColin Finck     status = DeviceIoControl( tcpFile,
112c2c66affSColin Finck                               IOCTL_TCP_QUERY_INFORMATION_EX,
113c2c66affSColin Finck                               &req,
114c2c66affSColin Finck                               sizeof(req),
115c2c66affSColin Finck                               entry,
116c2c66affSColin Finck                               sizeof(*entry),
117c2c66affSColin Finck                               &returnSize,
118c2c66affSColin Finck                               NULL );
119c2c66affSColin Finck 
1206c935922SSerge Gautherie     TRACE("TdiGetMibForIpEntity() => status = 0x%08lx, entry = {\n"
1216c935922SSerge Gautherie            "  ipsi_forwarding ............ %lu\n"
1226c935922SSerge Gautherie            "  ipsi_defaultttl ............ %lu\n"
1236c935922SSerge Gautherie            "  ipsi_inreceives ............ %lu\n"
1246c935922SSerge Gautherie            "  ipsi_indelivers ............ %lu\n"
1256c935922SSerge Gautherie            "  ipsi_outrequests ........... %lu\n"
1266c935922SSerge Gautherie            "  ipsi_routingdiscards ....... %lu\n"
1276c935922SSerge Gautherie            "  ipsi_outdiscards ........... %lu\n"
1286c935922SSerge Gautherie            "  ipsi_outnoroutes ........... %lu\n"
1296c935922SSerge Gautherie            "  ipsi_numif ................. %lu\n"
1306c935922SSerge Gautherie            "  ipsi_numaddr ............... %lu\n"
1316c935922SSerge Gautherie            "  ipsi_numroutes ............. %lu\n"
1326c935922SSerge Gautherie            "}\n",
1336c935922SSerge Gautherie           status,
134c2c66affSColin Finck           entry->ipsi_forwarding,
135c2c66affSColin Finck           entry->ipsi_defaultttl,
136c2c66affSColin Finck           entry->ipsi_inreceives,
137c2c66affSColin Finck           entry->ipsi_indelivers,
138c2c66affSColin Finck           entry->ipsi_outrequests,
139c2c66affSColin Finck           entry->ipsi_routingdiscards,
140c2c66affSColin Finck           entry->ipsi_outdiscards,
141c2c66affSColin Finck           entry->ipsi_outnoroutes,
142c2c66affSColin Finck           entry->ipsi_numif,
143c2c66affSColin Finck           entry->ipsi_numaddr,
1446c935922SSerge Gautherie           entry->ipsi_numroutes);
145c2c66affSColin Finck 
146c2c66affSColin Finck     return status;
147c2c66affSColin Finck }
148c2c66affSColin Finck 
149c2c66affSColin Finck NTSTATUS tdiGetRoutesForIpEntity
150c2c66affSColin Finck ( HANDLE tcpFile, TDIEntityID *ent, IPRouteEntry **routes, PDWORD numRoutes ) {
151c2c66affSColin Finck     NTSTATUS status = STATUS_SUCCESS;
152c2c66affSColin Finck 
1536c935922SSerge Gautherie     TRACE("TdiGetRoutesForIpEntity(tcpFile 0x%p, entityId 0x%x)\n",
1546c935922SSerge Gautherie           tcpFile, ent->tei_instance);
155c2c66affSColin Finck 
156c2c66affSColin Finck     status = tdiGetSetOfThings( tcpFile,
157c2c66affSColin Finck                                 INFO_CLASS_PROTOCOL,
158c2c66affSColin Finck                                 INFO_TYPE_PROVIDER,
159c2c66affSColin Finck                                 IP_MIB_ARPTABLE_ENTRY_ID,
160c2c66affSColin Finck                                 CL_NL_ENTITY,
161c2c66affSColin Finck 				ent->tei_instance,
162c2c66affSColin Finck                                 0,
163c2c66affSColin Finck                                 sizeof(IPRouteEntry),
164c2c66affSColin Finck                                 (PVOID *)routes,
165c2c66affSColin Finck                                 numRoutes);
166c2c66affSColin Finck 
167c2c66affSColin Finck     return status;
168c2c66affSColin Finck }
169c2c66affSColin Finck 
170c2c66affSColin Finck NTSTATUS tdiGetIpAddrsForIpEntity
171c2c66affSColin Finck ( HANDLE tcpFile, TDIEntityID *ent, IPAddrEntry **addrs, PDWORD numAddrs ) {
172c2c66affSColin Finck     NTSTATUS status;
173c2c66affSColin Finck 
1746c935922SSerge Gautherie     TRACE("TdiGetIpAddrsForIpEntity(tcpFile 0x%p, entityId 0x%x)\n",
1756c935922SSerge Gautherie           tcpFile, ent->tei_instance);
176c2c66affSColin Finck 
177c2c66affSColin Finck     status = tdiGetSetOfThings( tcpFile,
178c2c66affSColin Finck                                 INFO_CLASS_PROTOCOL,
179c2c66affSColin Finck                                 INFO_TYPE_PROVIDER,
180c2c66affSColin Finck                                 IP_MIB_ADDRTABLE_ENTRY_ID,
181c2c66affSColin Finck                                 CL_NL_ENTITY,
182c2c66affSColin Finck 				ent->tei_instance,
183c2c66affSColin Finck                                 0,
184c2c66affSColin Finck                                 sizeof(IPAddrEntry),
185c2c66affSColin Finck                                 (PVOID *)addrs,
186c2c66affSColin Finck                                 numAddrs );
187c2c66affSColin Finck 
188c2c66affSColin Finck     return status;
189c2c66affSColin Finck }
190c2c66affSColin Finck 
191c2c66affSColin Finck DWORD getInterfaceStatsByName(const char *name, PMIB_IFROW entry)
192c2c66affSColin Finck {
193c2c66affSColin Finck   if (!name)
194c2c66affSColin Finck     return ERROR_INVALID_PARAMETER;
195c2c66affSColin Finck   if (!entry)
196c2c66affSColin Finck     return ERROR_INVALID_PARAMETER;
197c2c66affSColin Finck 
198c2c66affSColin Finck   return NO_ERROR;
199c2c66affSColin Finck }
200c2c66affSColin Finck 
201c2c66affSColin Finck DWORD getInterfaceStatsByIndex(DWORD index, PMIB_IFROW entry)
202c2c66affSColin Finck {
203c2c66affSColin Finck     return ERROR_INVALID_PARAMETER;
204c2c66affSColin Finck }
205c2c66affSColin Finck 
206c2c66affSColin Finck DWORD getICMPStats(MIB_ICMP *stats)
207c2c66affSColin Finck {
208c2c66affSColin Finck   FILE *fp;
209c2c66affSColin Finck 
210c2c66affSColin Finck   if (!stats)
211c2c66affSColin Finck     return ERROR_INVALID_PARAMETER;
212c2c66affSColin Finck 
213c2c66affSColin Finck   memset(stats, 0, sizeof(MIB_ICMP));
214c2c66affSColin Finck   /* get most of these stats from /proc/net/snmp, no error if can't */
215c2c66affSColin Finck   fp = fopen("/proc/net/snmp", "r");
216c2c66affSColin Finck   if (fp) {
217c2c66affSColin Finck     const char hdr[] = "Icmp:";
218c2c66affSColin Finck     char buf[512] = { 0 }, *ptr;
219c2c66affSColin Finck 
220c2c66affSColin Finck     do {
221c2c66affSColin Finck       ptr = fgets(buf, sizeof(buf), fp);
222c2c66affSColin Finck     } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
223c2c66affSColin Finck     if (ptr) {
224c2c66affSColin Finck       /* last line was a header, get another */
225c2c66affSColin Finck       ptr = fgets(buf, sizeof(buf), fp);
226c2c66affSColin Finck       if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) {
227c2c66affSColin Finck         char *endPtr;
228c2c66affSColin Finck 
229c2c66affSColin Finck         ptr += sizeof(hdr);
230c2c66affSColin Finck         if (ptr && *ptr) {
231c2c66affSColin Finck           stats->stats.icmpInStats.dwMsgs = strtoul(ptr, &endPtr, 10);
232c2c66affSColin Finck           ptr = endPtr;
233c2c66affSColin Finck         }
234c2c66affSColin Finck         if (ptr && *ptr) {
235c2c66affSColin Finck           stats->stats.icmpInStats.dwErrors = strtoul(ptr, &endPtr, 10);
236c2c66affSColin Finck           ptr = endPtr;
237c2c66affSColin Finck         }
238c2c66affSColin Finck         if (ptr && *ptr) {
239c2c66affSColin Finck           stats->stats.icmpInStats.dwDestUnreachs = strtoul(ptr, &endPtr, 10);
240c2c66affSColin Finck           ptr = endPtr;
241c2c66affSColin Finck         }
242c2c66affSColin Finck         if (ptr && *ptr) {
243c2c66affSColin Finck           stats->stats.icmpInStats.dwTimeExcds = strtoul(ptr, &endPtr, 10);
244c2c66affSColin Finck           ptr = endPtr;
245c2c66affSColin Finck         }
246c2c66affSColin Finck         if (ptr && *ptr) {
247c2c66affSColin Finck           stats->stats.icmpInStats.dwParmProbs = strtoul(ptr, &endPtr, 10);
248c2c66affSColin Finck           ptr = endPtr;
249c2c66affSColin Finck         }
250c2c66affSColin Finck         if (ptr && *ptr) {
251c2c66affSColin Finck           stats->stats.icmpInStats.dwSrcQuenchs = strtoul(ptr, &endPtr, 10);
252c2c66affSColin Finck           ptr = endPtr;
253c2c66affSColin Finck         }
254c2c66affSColin Finck         if (ptr && *ptr) {
255c2c66affSColin Finck           stats->stats.icmpInStats.dwRedirects = strtoul(ptr, &endPtr, 10);
256c2c66affSColin Finck           ptr = endPtr;
257c2c66affSColin Finck         }
258c2c66affSColin Finck         if (ptr && *ptr) {
259c2c66affSColin Finck           stats->stats.icmpInStats.dwEchoReps = strtoul(ptr, &endPtr, 10);
260c2c66affSColin Finck           ptr = endPtr;
261c2c66affSColin Finck         }
262c2c66affSColin Finck         if (ptr && *ptr) {
263c2c66affSColin Finck           stats->stats.icmpInStats.dwTimestamps = strtoul(ptr, &endPtr, 10);
264c2c66affSColin Finck           ptr = endPtr;
265c2c66affSColin Finck         }
266c2c66affSColin Finck         if (ptr && *ptr) {
267c2c66affSColin Finck           stats->stats.icmpInStats.dwTimestampReps = strtoul(ptr, &endPtr, 10);
268c2c66affSColin Finck           ptr = endPtr;
269c2c66affSColin Finck         }
270c2c66affSColin Finck         if (ptr && *ptr) {
271c2c66affSColin Finck           stats->stats.icmpInStats.dwAddrMasks = strtoul(ptr, &endPtr, 10);
272c2c66affSColin Finck           ptr = endPtr;
273c2c66affSColin Finck         }
274c2c66affSColin Finck         if (ptr && *ptr) {
275c2c66affSColin Finck           stats->stats.icmpInStats.dwAddrMaskReps = strtoul(ptr, &endPtr, 10);
276c2c66affSColin Finck           ptr = endPtr;
277c2c66affSColin Finck         }
278c2c66affSColin Finck         if (ptr && *ptr) {
279c2c66affSColin Finck           stats->stats.icmpOutStats.dwMsgs = strtoul(ptr, &endPtr, 10);
280c2c66affSColin Finck           ptr = endPtr;
281c2c66affSColin Finck         }
282c2c66affSColin Finck         if (ptr && *ptr) {
283c2c66affSColin Finck           stats->stats.icmpOutStats.dwErrors = strtoul(ptr, &endPtr, 10);
284c2c66affSColin Finck           ptr = endPtr;
285c2c66affSColin Finck         }
286c2c66affSColin Finck         if (ptr && *ptr) {
287c2c66affSColin Finck           stats->stats.icmpOutStats.dwDestUnreachs = strtoul(ptr, &endPtr, 10);
288c2c66affSColin Finck           ptr = endPtr;
289c2c66affSColin Finck         }
290c2c66affSColin Finck         if (ptr && *ptr) {
291c2c66affSColin Finck           stats->stats.icmpOutStats.dwTimeExcds = strtoul(ptr, &endPtr, 10);
292c2c66affSColin Finck           ptr = endPtr;
293c2c66affSColin Finck         }
294c2c66affSColin Finck         if (ptr && *ptr) {
295c2c66affSColin Finck           stats->stats.icmpOutStats.dwParmProbs = strtoul(ptr, &endPtr, 10);
296c2c66affSColin Finck           ptr = endPtr;
297c2c66affSColin Finck         }
298c2c66affSColin Finck         if (ptr && *ptr) {
299c2c66affSColin Finck           stats->stats.icmpOutStats.dwSrcQuenchs = strtoul(ptr, &endPtr, 10);
300c2c66affSColin Finck           ptr = endPtr;
301c2c66affSColin Finck         }
302c2c66affSColin Finck         if (ptr && *ptr) {
303c2c66affSColin Finck           stats->stats.icmpOutStats.dwRedirects = strtoul(ptr, &endPtr, 10);
304c2c66affSColin Finck           ptr = endPtr;
305c2c66affSColin Finck         }
306c2c66affSColin Finck         if (ptr && *ptr) {
307c2c66affSColin Finck           stats->stats.icmpOutStats.dwEchoReps = strtoul(ptr, &endPtr, 10);
308c2c66affSColin Finck           ptr = endPtr;
309c2c66affSColin Finck         }
310c2c66affSColin Finck         if (ptr && *ptr) {
311c2c66affSColin Finck           stats->stats.icmpOutStats.dwTimestamps = strtoul(ptr, &endPtr, 10);
312c2c66affSColin Finck           ptr = endPtr;
313c2c66affSColin Finck         }
314c2c66affSColin Finck         if (ptr && *ptr) {
315c2c66affSColin Finck           stats->stats.icmpOutStats.dwTimestampReps = strtoul(ptr, &endPtr, 10);
316c2c66affSColin Finck           ptr = endPtr;
317c2c66affSColin Finck         }
318c2c66affSColin Finck         if (ptr && *ptr) {
319c2c66affSColin Finck           stats->stats.icmpOutStats.dwAddrMasks = strtoul(ptr, &endPtr, 10);
320c2c66affSColin Finck           ptr = endPtr;
321c2c66affSColin Finck         }
322c2c66affSColin Finck         if (ptr && *ptr) {
323c2c66affSColin Finck           stats->stats.icmpOutStats.dwAddrMaskReps = strtoul(ptr, &endPtr, 10);
324c2c66affSColin Finck           ptr = endPtr;
325c2c66affSColin Finck         }
326c2c66affSColin Finck       }
327c2c66affSColin Finck     }
328c2c66affSColin Finck     fclose(fp);
329c2c66affSColin Finck   }
330c2c66affSColin Finck   return NO_ERROR;
331c2c66affSColin Finck }
332c2c66affSColin Finck 
333c2c66affSColin Finck DWORD getIPStats(PMIB_IPSTATS stats, DWORD family)
334c2c66affSColin Finck {
335c2c66affSColin Finck   if (!stats)
336c2c66affSColin Finck     return ERROR_INVALID_PARAMETER;
337c2c66affSColin Finck   return NO_ERROR;
338c2c66affSColin Finck }
339c2c66affSColin Finck 
340c2c66affSColin Finck DWORD getTCPStats(MIB_TCPSTATS *stats, DWORD family)
341c2c66affSColin Finck {
342c2c66affSColin Finck   if (!stats)
343c2c66affSColin Finck     return ERROR_INVALID_PARAMETER;
344c2c66affSColin Finck   return NO_ERROR;
345c2c66affSColin Finck }
346c2c66affSColin Finck 
347c2c66affSColin Finck DWORD getUDPStats(MIB_UDPSTATS *stats, DWORD family)
348c2c66affSColin Finck {
349c2c66affSColin Finck   if (!stats)
350c2c66affSColin Finck     return ERROR_INVALID_PARAMETER;
351c2c66affSColin Finck   return NO_ERROR;
352c2c66affSColin Finck }
353c2c66affSColin Finck 
354c2c66affSColin Finck static DWORD getNumWithOneHeader(const char *filename)
355c2c66affSColin Finck {
356c2c66affSColin Finck     return 0;
357c2c66affSColin Finck }
358c2c66affSColin Finck 
359c2c66affSColin Finck DWORD getNumRoutes(void)
360c2c66affSColin Finck {
361c2c66affSColin Finck     DWORD numEntities, numRoutes = 0;
362c2c66affSColin Finck     TDIEntityID *entitySet;
363c2c66affSColin Finck     HANDLE tcpFile;
364c2c66affSColin Finck     int i;
365c2c66affSColin Finck     NTSTATUS status;
366c2c66affSColin Finck 
367c2c66affSColin Finck     TRACE("called.\n");
368c2c66affSColin Finck 
369c2c66affSColin Finck     status = openTcpFile( &tcpFile, FILE_READ_DATA );
370c2c66affSColin Finck     if( !NT_SUCCESS(status) ) {
3716c935922SSerge Gautherie         ERR("openTcpFile returned 0x%08lx\n", status);
372c2c66affSColin Finck         return 0;
373c2c66affSColin Finck     }
374c2c66affSColin Finck 
375c2c66affSColin Finck     status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities );
376c2c66affSColin Finck     if( !NT_SUCCESS(status) ) {
3776c935922SSerge Gautherie         ERR("tdiGetEntityIDSet returned 0x%08lx\n", status);
378c2c66affSColin Finck         closeTcpFile( tcpFile );
379c2c66affSColin Finck         return 0;
380c2c66affSColin Finck     }
381c2c66affSColin Finck 
382c2c66affSColin Finck     for( i = 0; i < numEntities; i++ ) {
383c2c66affSColin Finck         if( isIpEntity( tcpFile, &entitySet[i] ) ) {
384c2c66affSColin Finck             IPSNMPInfo isnmp;
385c2c66affSColin Finck             memset( &isnmp, 0, sizeof( isnmp ) );
386c2c66affSColin Finck             status = tdiGetMibForIpEntity( tcpFile, &entitySet[i], &isnmp );
387c2c66affSColin Finck             if( !NT_SUCCESS(status) ) {
3886c935922SSerge Gautherie                 ERR("tdiGetMibForIpEntity returned 0x%08lx, for i = %d", status, i);
389b6c060ceSSerge Gautherie                 numRoutes = 0;
390b6c060ceSSerge Gautherie                 break;
391c2c66affSColin Finck             }
392c2c66affSColin Finck             numRoutes += isnmp.ipsi_numroutes;
393c2c66affSColin Finck         }
394c2c66affSColin Finck     }
395c2c66affSColin Finck 
3966c935922SSerge Gautherie     TRACE("numRoutes = %lu\n", numRoutes);
397c2c66affSColin Finck 
398182a3107SThomas Faber     tdiFreeThingSet( entitySet );
399c2c66affSColin Finck     closeTcpFile( tcpFile );
400c2c66affSColin Finck 
401c2c66affSColin Finck     return numRoutes;
402c2c66affSColin Finck }
403c2c66affSColin Finck 
404c2c66affSColin Finck VOID HexDump( PCHAR Data, DWORD Len ) {
405c2c66affSColin Finck     int i;
406c2c66affSColin Finck 
407c2c66affSColin Finck     for( i = 0; i < Len; i++ ) {
408c2c66affSColin Finck         if( !(i & 0xf) ) {
409c2c66affSColin Finck             if( i ) fprintf(stderr,"\n");
410c2c66affSColin Finck             fprintf(stderr,"%08x:", i);
411c2c66affSColin Finck         }
412c2c66affSColin Finck         fprintf( stderr, " %02x", Data[i] & 0xff );
413c2c66affSColin Finck     }
414c2c66affSColin Finck     fprintf(stderr,"\n");
415c2c66affSColin Finck }
416c2c66affSColin Finck 
417c2c66affSColin Finck RouteTable *getRouteTable(void)
418c2c66affSColin Finck {
419c2c66affSColin Finck     RouteTable *out_route_table;
420c2c66affSColin Finck     DWORD numRoutes = getNumRoutes(), routesAdded = 0;
421c2c66affSColin Finck     TDIEntityID ent;
422c2c66affSColin Finck     HANDLE tcpFile;
423c2c66affSColin Finck     NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA );
424c2c66affSColin Finck     int i;
425c2c66affSColin Finck 
426c2c66affSColin Finck     if( !NT_SUCCESS(status) )
427c2c66affSColin Finck         return 0;
428c2c66affSColin Finck 
429c2c66affSColin Finck     TRACE("GETTING ROUTE TABLE\n");
430c2c66affSColin Finck 
431c2c66affSColin Finck     out_route_table = HeapAlloc( GetProcessHeap(), 0,
432c2c66affSColin Finck                                  sizeof(RouteTable) +
433c2c66affSColin Finck                                  (sizeof(RouteEntry) * (numRoutes - 1)) );
434c2c66affSColin Finck     if (!out_route_table) {
435c2c66affSColin Finck         closeTcpFile(tcpFile);
436c2c66affSColin Finck         return NULL;
437c2c66affSColin Finck     }
438c2c66affSColin Finck 
439c2c66affSColin Finck     out_route_table->numRoutes = numRoutes;
440c2c66affSColin Finck 
441c2c66affSColin Finck     for( i = 0; routesAdded < out_route_table->numRoutes; i++ ) {
442c2c66affSColin Finck         int j;
443c2c66affSColin Finck         IPRouteEntry *route_set;
444c2c66affSColin Finck 
445c2c66affSColin Finck         getNthIpEntity( tcpFile, i, &ent );
446c2c66affSColin Finck 
447c2c66affSColin Finck         tdiGetRoutesForIpEntity( tcpFile, &ent, &route_set, &numRoutes );
448c2c66affSColin Finck 
449c2c66affSColin Finck         if( !route_set ) {
450c2c66affSColin Finck             closeTcpFile( tcpFile );
451c2c66affSColin Finck             HeapFree( GetProcessHeap(), 0, out_route_table );
452c2c66affSColin Finck             return 0;
453c2c66affSColin Finck         }
454c2c66affSColin Finck 
4556c935922SSerge Gautherie         TRACE("%lu routes in instance %d\n", numRoutes, i);
456c2c66affSColin Finck #if 0
457c2c66affSColin Finck         HexDump( route_set,
458c2c66affSColin Finck                  sizeof( IPRouteEntry ) *
459c2c66affSColin Finck                  snmpInfo.ipsi_numroutes );
460c2c66affSColin Finck #endif
461c2c66affSColin Finck 
462c2c66affSColin Finck         for( j = 0; j < numRoutes; j++ ) {
463c2c66affSColin Finck             int routeNum = j + routesAdded;
464c2c66affSColin Finck             out_route_table->routes[routeNum].dest =
465c2c66affSColin Finck                 route_set[j].ire_dest;
466c2c66affSColin Finck             out_route_table->routes[routeNum].mask =
467c2c66affSColin Finck                 route_set[j].ire_mask;
468c2c66affSColin Finck             out_route_table->routes[routeNum].gateway =
469c2c66affSColin Finck                 route_set[j].ire_gw;
470c2c66affSColin Finck             out_route_table->routes[routeNum].ifIndex =
471c2c66affSColin Finck                 route_set[j].ire_index;
472c2c66affSColin Finck             out_route_table->routes[routeNum].metric =
473c2c66affSColin Finck                 route_set[j].ire_metric1;
474c2c66affSColin Finck         }
475c2c66affSColin Finck 
476c2c66affSColin Finck         if( route_set ) tdiFreeThingSet( route_set );
477c2c66affSColin Finck 
478c2c66affSColin Finck         routesAdded += numRoutes;
479c2c66affSColin Finck     }
480c2c66affSColin Finck 
481c2c66affSColin Finck     closeTcpFile( tcpFile );
482c2c66affSColin Finck 
4836c935922SSerge Gautherie     TRACE("status = 0x%08lx, out_route_table = 0x%p\n", status, out_route_table);
484c2c66affSColin Finck 
485c2c66affSColin Finck     return out_route_table;
486c2c66affSColin Finck }
487c2c66affSColin Finck 
488c2c66affSColin Finck DWORD getNumArpEntries(void)
489c2c66affSColin Finck {
490c2c66affSColin Finck     DWORD numEntities;
491c2c66affSColin Finck     TDIEntityID *entitySet = NULL;
492c2c66affSColin Finck     HANDLE tcpFile;
493c2c66affSColin Finck     int i, totalNumber = 0;
494c2c66affSColin Finck     NTSTATUS status;
495c2c66affSColin Finck     PMIB_IPNETROW IpArpTable = NULL;
496c2c66affSColin Finck     DWORD returnSize;
497c2c66affSColin Finck 
498c2c66affSColin Finck     TRACE("called.\n");
499c2c66affSColin Finck 
500c2c66affSColin Finck     status = openTcpFile( &tcpFile, FILE_READ_DATA );
501c2c66affSColin Finck     if( !NT_SUCCESS(status) ) {
5026c935922SSerge Gautherie         ERR("openTcpFile returned 0x%08lx\n", status);
503c2c66affSColin Finck         return 0;
504c2c66affSColin Finck     }
505c2c66affSColin Finck 
506c2c66affSColin Finck     status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities );
507c2c66affSColin Finck 
508c2c66affSColin Finck     for( i = 0; i < numEntities; i++ ) {
509c2c66affSColin Finck         if( isInterface( &entitySet[i] ) &&
510c2c66affSColin Finck 	    hasArp( tcpFile, &entitySet[i] ) ) {
511c2c66affSColin Finck 
512c2c66affSColin Finck 	    status = tdiGetSetOfThings( tcpFile,
513c2c66affSColin Finck 					INFO_CLASS_PROTOCOL,
514c2c66affSColin Finck 					INFO_TYPE_PROVIDER,
515c2c66affSColin Finck 					IP_MIB_ARPTABLE_ENTRY_ID,
516c2c66affSColin Finck 					AT_ENTITY,
517c2c66affSColin Finck 					entitySet[i].tei_instance,
518c2c66affSColin Finck 					0,
519c2c66affSColin Finck 					sizeof(MIB_IPNETROW),
520c2c66affSColin Finck 					(PVOID *)&IpArpTable,
521c2c66affSColin Finck 					&returnSize );
522c2c66affSColin Finck 
523c2c66affSColin Finck 	    if( status == STATUS_SUCCESS ) totalNumber += returnSize;
524c2c66affSColin Finck 		if( IpArpTable ) {
525c2c66affSColin Finck 			tdiFreeThingSet( IpArpTable );
526c2c66affSColin Finck 			IpArpTable = NULL;
527c2c66affSColin Finck 		}
528c2c66affSColin Finck 	}
529c2c66affSColin Finck     }
530c2c66affSColin Finck 
531c2c66affSColin Finck     closeTcpFile( tcpFile );
532c2c66affSColin Finck     if( IpArpTable ) tdiFreeThingSet( IpArpTable );
533c2c66affSColin Finck     if( entitySet ) tdiFreeThingSet( entitySet );
534c2c66affSColin Finck     return totalNumber;
535c2c66affSColin Finck }
536c2c66affSColin Finck 
537c2c66affSColin Finck PMIB_IPNETTABLE getArpTable(void)
538c2c66affSColin Finck {
539c2c66affSColin Finck     DWORD numEntities, returnSize;
540c2c66affSColin Finck     TDIEntityID *entitySet;
541c2c66affSColin Finck     HANDLE tcpFile;
542c2c66affSColin Finck     int i, totalNumber, TmpIdx, CurrIdx = 0;
543c2c66affSColin Finck     NTSTATUS status;
544c2c66affSColin Finck     PMIB_IPNETTABLE IpArpTable = NULL;
545c2c66affSColin Finck     PMIB_IPNETROW AdapterArpTable = NULL;
546c2c66affSColin Finck 
547c2c66affSColin Finck     TRACE("called.\n");
548c2c66affSColin Finck 
549c2c66affSColin Finck     totalNumber = getNumArpEntries();
550c2c66affSColin Finck 
551c2c66affSColin Finck     status = openTcpFile( &tcpFile, FILE_READ_DATA );
552c2c66affSColin Finck     if( !NT_SUCCESS(status) ) {
5536c935922SSerge Gautherie         ERR("openTcpFile returned 0x%08lx\n", status);
554c2c66affSColin Finck         return 0;
555c2c66affSColin Finck     }
556c2c66affSColin Finck 
557c2c66affSColin Finck     IpArpTable = HeapAlloc
558c2c66affSColin Finck 	( GetProcessHeap(), 0,
559c2c66affSColin Finck 	  sizeof(DWORD) + (sizeof(MIB_IPNETROW) * totalNumber) );
560c2c66affSColin Finck     if (!IpArpTable) {
561c2c66affSColin Finck         closeTcpFile(tcpFile);
562c2c66affSColin Finck         return NULL;
563c2c66affSColin Finck     }
564c2c66affSColin Finck 
565c2c66affSColin Finck     status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities );
566c2c66affSColin Finck 
567c2c66affSColin Finck     for( i = 0; i < numEntities; i++ ) {
568c2c66affSColin Finck         if( isInterface( &entitySet[i] ) &&
569c2c66affSColin Finck 	    hasArp( tcpFile, &entitySet[i] ) ) {
570c2c66affSColin Finck 
571c2c66affSColin Finck 	    status = tdiGetSetOfThings( tcpFile,
572c2c66affSColin Finck 					INFO_CLASS_PROTOCOL,
573c2c66affSColin Finck 					INFO_TYPE_PROVIDER,
574c2c66affSColin Finck 					IP_MIB_ARPTABLE_ENTRY_ID,
575c2c66affSColin Finck 					AT_ENTITY,
576c2c66affSColin Finck 					entitySet[i].tei_instance,
577c2c66affSColin Finck 					0,
578c2c66affSColin Finck 					sizeof(MIB_IPNETROW),
579c2c66affSColin Finck 					(PVOID *)&AdapterArpTable,
580c2c66affSColin Finck 					&returnSize );
581c2c66affSColin Finck 
582c2c66affSColin Finck             if( status == STATUS_SUCCESS ) {
583c2c66affSColin Finck                 for( TmpIdx = 0; TmpIdx < returnSize; TmpIdx++, CurrIdx++ )
584c2c66affSColin Finck                     IpArpTable->table[CurrIdx] = AdapterArpTable[TmpIdx];
585c2c66affSColin Finck                 tdiFreeThingSet( AdapterArpTable );
586c2c66affSColin Finck             }
587c2c66affSColin Finck         }
588c2c66affSColin Finck     }
589c2c66affSColin Finck 
590c2c66affSColin Finck     closeTcpFile( tcpFile );
591c2c66affSColin Finck 
592c2c66affSColin Finck     tdiFreeThingSet( entitySet );
593c2c66affSColin Finck     IpArpTable->dwNumEntries = CurrIdx;
594c2c66affSColin Finck 
595c2c66affSColin Finck     return IpArpTable;
596c2c66affSColin Finck }
597c2c66affSColin Finck 
598c2c66affSColin Finck DWORD getNumUdpEntries(void)
599c2c66affSColin Finck {
600c2c66affSColin Finck   return getNumWithOneHeader("/proc/net/udp");
601c2c66affSColin Finck }
602c2c66affSColin Finck 
603c2c66affSColin Finck PMIB_UDPTABLE getUdpTable(void)
604c2c66affSColin Finck {
605c2c66affSColin Finck   DWORD numEntries = getNumUdpEntries();
606c2c66affSColin Finck   PMIB_UDPTABLE ret;
607c2c66affSColin Finck 
608c2c66affSColin Finck   ret = (PMIB_UDPTABLE)calloc(1, sizeof(MIB_UDPTABLE) +
609c2c66affSColin Finck    (numEntries - 1) * sizeof(MIB_UDPROW));
610c2c66affSColin Finck   if (ret) {
611c2c66affSColin Finck     FILE *fp;
612c2c66affSColin Finck 
613c2c66affSColin Finck     /* get from /proc/net/udp, no error if can't */
614c2c66affSColin Finck     fp = fopen("/proc/net/udp", "r");
615c2c66affSColin Finck     if (fp) {
616c2c66affSColin Finck       char buf[512] = { 0 }, *ptr;
617c2c66affSColin Finck 
618c2c66affSColin Finck       /* skip header line */
619c2c66affSColin Finck       ptr = fgets(buf, sizeof(buf), fp);
620c2c66affSColin Finck       while (ptr && ret->dwNumEntries < numEntries) {
621c2c66affSColin Finck         ptr = fgets(buf, sizeof(buf), fp);
622c2c66affSColin Finck         if (ptr) {
623c2c66affSColin Finck           char *endPtr;
624c2c66affSColin Finck 
625c2c66affSColin Finck           if (ptr && *ptr) {
626c2c66affSColin Finck             strtoul(ptr, &endPtr, 16); /* skip */
627c2c66affSColin Finck             ptr = endPtr;
628c2c66affSColin Finck           }
629c2c66affSColin Finck           if (ptr && *ptr) {
630c2c66affSColin Finck             ptr++;
631c2c66affSColin Finck             ret->table[ret->dwNumEntries].dwLocalAddr = strtoul(ptr, &endPtr,
632c2c66affSColin Finck              16);
633c2c66affSColin Finck             ptr = endPtr;
634c2c66affSColin Finck           }
635c2c66affSColin Finck           if (ptr && *ptr) {
636c2c66affSColin Finck             ptr++;
637c2c66affSColin Finck             ret->table[ret->dwNumEntries].dwLocalPort = strtoul(ptr, &endPtr,
638c2c66affSColin Finck              16);
639c2c66affSColin Finck             ptr = endPtr;
640c2c66affSColin Finck           }
641c2c66affSColin Finck           ret->dwNumEntries++;
642c2c66affSColin Finck         }
643c2c66affSColin Finck       }
644c2c66affSColin Finck       fclose(fp);
645c2c66affSColin Finck     }
646c2c66affSColin Finck   }
647c2c66affSColin Finck   return ret;
648c2c66affSColin Finck }
649c2c66affSColin Finck 
650c2c66affSColin Finck DWORD getNumTcpEntries(void)
651c2c66affSColin Finck {
652*67820479SPierre Schweitzer     DWORD numEntities;
653*67820479SPierre Schweitzer     TDIEntityID *entitySet = NULL;
654*67820479SPierre Schweitzer     HANDLE tcpFile;
655*67820479SPierre Schweitzer     int i, totalNumber = 0;
656*67820479SPierre Schweitzer     NTSTATUS status;
657*67820479SPierre Schweitzer     PMIB_TCPROW IpTcpTable = NULL;
658*67820479SPierre Schweitzer     DWORD returnSize;
659*67820479SPierre Schweitzer 
660*67820479SPierre Schweitzer     TRACE("called.\n");
661*67820479SPierre Schweitzer 
662*67820479SPierre Schweitzer     status = openTcpFile( &tcpFile, FILE_READ_DATA );
663*67820479SPierre Schweitzer     if( !NT_SUCCESS(status) ) {
664*67820479SPierre Schweitzer         ERR("openTcpFile returned 0x%08lx\n", status);
665*67820479SPierre Schweitzer         return 0;
666*67820479SPierre Schweitzer     }
667*67820479SPierre Schweitzer 
668*67820479SPierre Schweitzer     status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities );
669*67820479SPierre Schweitzer 
670*67820479SPierre Schweitzer     for( i = 0; i < numEntities; i++ ) {
671*67820479SPierre Schweitzer         if( isInterface( &entitySet[i] ) &&
672*67820479SPierre Schweitzer 	    hasArp( tcpFile, &entitySet[i] ) ) {
673*67820479SPierre Schweitzer 
674*67820479SPierre Schweitzer 	    status = tdiGetSetOfThings( tcpFile,
675*67820479SPierre Schweitzer 					INFO_CLASS_PROTOCOL,
676*67820479SPierre Schweitzer 					INFO_TYPE_PROVIDER,
677*67820479SPierre Schweitzer 					IP_MIB_ARPTABLE_ENTRY_ID,
678*67820479SPierre Schweitzer 					CO_TL_ENTITY,
679*67820479SPierre Schweitzer 					entitySet[i].tei_instance,
680*67820479SPierre Schweitzer 					0,
681*67820479SPierre Schweitzer 					sizeof(MIB_TCPROW),
682*67820479SPierre Schweitzer 					(PVOID *)&IpTcpTable,
683*67820479SPierre Schweitzer 					&returnSize );
684*67820479SPierre Schweitzer 
685*67820479SPierre Schweitzer 	    if( status == STATUS_SUCCESS ) totalNumber += returnSize;
686*67820479SPierre Schweitzer 		if( IpTcpTable ) {
687*67820479SPierre Schweitzer 			tdiFreeThingSet( IpTcpTable );
688*67820479SPierre Schweitzer 			IpTcpTable = NULL;
689*67820479SPierre Schweitzer 		}
690*67820479SPierre Schweitzer 	}
691*67820479SPierre Schweitzer     }
692*67820479SPierre Schweitzer 
693*67820479SPierre Schweitzer     closeTcpFile( tcpFile );
694*67820479SPierre Schweitzer     if( IpTcpTable ) tdiFreeThingSet( IpTcpTable );
695*67820479SPierre Schweitzer     if( entitySet ) tdiFreeThingSet( entitySet );
696*67820479SPierre Schweitzer     return totalNumber;
697c2c66affSColin Finck }
698c2c66affSColin Finck 
699c2c66affSColin Finck PMIB_TCPTABLE getTcpTable(void)
700c2c66affSColin Finck {
701*67820479SPierre Schweitzer     DWORD numEntities, returnSize;
702*67820479SPierre Schweitzer     TDIEntityID *entitySet;
703*67820479SPierre Schweitzer     HANDLE tcpFile;
704*67820479SPierre Schweitzer     int i, totalNumber, TmpIdx, CurrIdx = 0;
705*67820479SPierre Schweitzer     NTSTATUS status;
706*67820479SPierre Schweitzer     PMIB_TCPTABLE IpTcpTable = NULL;
707*67820479SPierre Schweitzer     PMIB_TCPROW AdapterTcpTable = NULL;
708*67820479SPierre Schweitzer 
709*67820479SPierre Schweitzer     TRACE("called.\n");
710*67820479SPierre Schweitzer 
711*67820479SPierre Schweitzer     totalNumber = getNumTcpEntries();
712*67820479SPierre Schweitzer 
713*67820479SPierre Schweitzer     status = openTcpFile( &tcpFile, FILE_READ_DATA );
714*67820479SPierre Schweitzer     if( !NT_SUCCESS(status) ) {
715*67820479SPierre Schweitzer         ERR("openTcpFile returned 0x%08lx\n", status);
716c2c66affSColin Finck         return 0;
717c2c66affSColin Finck     }
718*67820479SPierre Schweitzer 
719*67820479SPierre Schweitzer     IpTcpTable = HeapAlloc
720*67820479SPierre Schweitzer 	( GetProcessHeap(), 0,
721*67820479SPierre Schweitzer 	  sizeof(DWORD) + (sizeof(MIB_TCPROW) * totalNumber) );
722*67820479SPierre Schweitzer     if (!IpTcpTable) {
723*67820479SPierre Schweitzer         closeTcpFile(tcpFile);
724*67820479SPierre Schweitzer         return NULL;
725*67820479SPierre Schweitzer     }
726*67820479SPierre Schweitzer 
727*67820479SPierre Schweitzer     status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities );
728*67820479SPierre Schweitzer 
729*67820479SPierre Schweitzer     for( i = 0; i < numEntities; i++ ) {
730*67820479SPierre Schweitzer         if( isInterface( &entitySet[i] ) &&
731*67820479SPierre Schweitzer 	    hasArp( tcpFile, &entitySet[i] ) ) {
732*67820479SPierre Schweitzer 
733*67820479SPierre Schweitzer 	    status = tdiGetSetOfThings( tcpFile,
734*67820479SPierre Schweitzer 					INFO_CLASS_PROTOCOL,
735*67820479SPierre Schweitzer 					INFO_TYPE_PROVIDER,
736*67820479SPierre Schweitzer 					IP_MIB_ARPTABLE_ENTRY_ID,
737*67820479SPierre Schweitzer 					CO_TL_ENTITY,
738*67820479SPierre Schweitzer 					entitySet[i].tei_instance,
739*67820479SPierre Schweitzer 					0,
740*67820479SPierre Schweitzer 					sizeof(MIB_TCPROW),
741*67820479SPierre Schweitzer 					(PVOID *)&AdapterTcpTable,
742*67820479SPierre Schweitzer 					&returnSize );
743*67820479SPierre Schweitzer 
744*67820479SPierre Schweitzer             if( status == STATUS_SUCCESS ) {
745*67820479SPierre Schweitzer                 for( TmpIdx = 0; TmpIdx < returnSize; TmpIdx++, CurrIdx++ )
746*67820479SPierre Schweitzer                     IpTcpTable->table[CurrIdx] = AdapterTcpTable[TmpIdx];
747*67820479SPierre Schweitzer                 tdiFreeThingSet( AdapterTcpTable );
748*67820479SPierre Schweitzer             }
749*67820479SPierre Schweitzer         }
750*67820479SPierre Schweitzer     }
751*67820479SPierre Schweitzer 
752*67820479SPierre Schweitzer     closeTcpFile( tcpFile );
753*67820479SPierre Schweitzer 
754*67820479SPierre Schweitzer     tdiFreeThingSet( entitySet );
755*67820479SPierre Schweitzer     IpTcpTable->dwNumEntries = CurrIdx;
756*67820479SPierre Schweitzer 
757*67820479SPierre Schweitzer     return IpTcpTable;
758*67820479SPierre Schweitzer }
759