Reactos
1/* Copyright (C) 2003 Art Yerkes
2 * A reimplementation of ifenum.c by Juan Lang
3 *
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.
8 *
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.
13 *
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 Street, Fifth Floor, Boston, MA 02110-1301 USA
17 *
18 * This file is implemented on the IOCTL_TCP_QUERY_INFORMATION_EX ioctl on
19 * tcpip.sys
20 */
21
22#include "iphlpapi_private.h"
23
24WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
25
26#ifndef TCPS_ESTABLISHED
27# define TCPS_ESTABLISHED TCP_ESTABLISHED
28#endif
29#ifndef TCPS_SYN_SENT
30# define TCPS_SYN_SENT TCP_SYN_SENT
31#endif
32#ifndef TCPS_SYN_RECEIVED
33# define TCPS_SYN_RECEIVED TCP_SYN_RECV
34#endif
35#ifndef TCPS_FIN_WAIT_1
36# define TCPS_FIN_WAIT_1 TCP_FIN_WAIT1
37#endif
38#ifndef TCPS_FIN_WAIT_2
39# define TCPS_FIN_WAIT_2 TCP_FIN_WAIT2
40#endif
41#ifndef TCPS_TIME_WAIT
42# define TCPS_TIME_WAIT TCP_TIME_WAIT
43#endif
44#ifndef TCPS_CLOSED
45# define TCPS_CLOSED TCP_CLOSE
46#endif
47#ifndef TCPS_CLOSE_WAIT
48# define TCPS_CLOSE_WAIT TCP_CLOSE_WAIT
49#endif
50#ifndef TCPS_LAST_ACK
51# define TCPS_LAST_ACK TCP_LAST_ACK
52#endif
53#ifndef TCPS_LISTEN
54# define TCPS_LISTEN TCP_LISTEN
55#endif
56#ifndef TCPS_CLOSING
57# define TCPS_CLOSING TCP_CLOSING
58#endif
59
60BOOL isIpEntity( HANDLE tcpFile, TDIEntityID *ent ) {
61 return (ent->tei_entity == CL_NL_ENTITY ||
62 ent->tei_entity == CO_NL_ENTITY);
63}
64
65NTSTATUS getNthIpEntity( HANDLE tcpFile, DWORD index, TDIEntityID *ent ) {
66 DWORD numEntities = 0;
67 DWORD numRoutes = 0;
68 TDIEntityID *entitySet = 0;
69 NTSTATUS status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities );
70 int i;
71
72 if( !NT_SUCCESS(status) )
73 return status;
74
75 for( i = 0; i < numEntities; i++ ) {
76 if( isIpEntity( tcpFile, &entitySet[i] ) ) {
77 TRACE("Entity %d is an IP Entity\n", i);
78 if( numRoutes == index ) break;
79 else numRoutes++;
80 }
81 }
82
83 if( numRoutes == index && i < numEntities ) {
84 TRACE("Index %lu is entity #%d - %04x:%08x\n", index, i,
85 entitySet[i].tei_entity, entitySet[i].tei_instance);
86 memcpy( ent, &entitySet[i], sizeof(*ent) );
87 tdiFreeThingSet( entitySet );
88 return STATUS_SUCCESS;
89 } else {
90 tdiFreeThingSet( entitySet );
91 return STATUS_UNSUCCESSFUL;
92 }
93}
94
95static NTSTATUS
96tdiGetMibForIpEntity(
97 _In_ HANDLE tcpFile,
98 _In_ TDIEntityID *ent,
99 _Out_ MIB_IPSTATS *entry)
100{
101 TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT;
102 NTSTATUS Status;
103 DWORD returnSize;
104
105 ZeroMemory(entry, sizeof(*entry));
106
107 TRACE("TdiGetMibForIpEntity(tcpFile 0x%p, entityId 0x%x)\n",
108 tcpFile, ent->tei_instance);
109
110 req.ID.toi_class = INFO_CLASS_PROTOCOL;
111 req.ID.toi_type = INFO_TYPE_PROVIDER;
112 req.ID.toi_id = IP_MIB_STATS_ID;
113 req.ID.toi_entity = *ent;
114
115 Status = DeviceIoControl(tcpFile,
116 IOCTL_TCP_QUERY_INFORMATION_EX,
117 &req,
118 sizeof(req),
119 entry,
120 sizeof(*entry),
121 &returnSize,
122 NULL);
123
124 TRACE("TdiGetMibForIpEntity() => status = 0x%08lx, entry = {\n"
125 " ipsi_forwarding ............ %lu\n"
126 " ipsi_defaultttl ............ %lu\n"
127 " ipsi_inreceives ............ %lu\n"
128 " ipsi_indelivers ............ %lu\n"
129 " ipsi_outrequests ........... %lu\n"
130 " ipsi_routingdiscards ....... %lu\n"
131 " ipsi_outdiscards ........... %lu\n"
132 " ipsi_outnoroutes ........... %lu\n"
133 " ipsi_numif ................. %lu\n"
134 " ipsi_numaddr ............... %lu\n"
135 " ipsi_numroutes ............. %lu\n"
136 "}\n",
137 Status,
138 entry->dwForwarding,
139 entry->dwDefaultTTL,
140 entry->dwInReceives,
141 entry->dwInDelivers,
142 entry->dwOutRequests,
143 entry->dwRoutingDiscards,
144 entry->dwOutDiscards,
145 entry->dwOutNoRoutes,
146 entry->dwNumIf,
147 entry->dwNumAddr,
148 entry->dwNumRoutes);
149
150 return Status;
151}
152
153static NTSTATUS
154tdiGetMibForTcpEntity(
155 _In_ HANDLE tcpFile,
156 _In_ TDIEntityID *ent,
157 _Out_ MIB_TCPSTATS *entry)
158{
159 TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT;
160 NTSTATUS Status;
161 DWORD returnSize;
162
163 ZeroMemory(entry, sizeof(*entry));
164
165 TRACE("TdiGetMibForTcpEntity(tcpFile 0x%p, entityId 0x%x)\n",
166 tcpFile, ent->tei_instance);
167
168 req.ID.toi_class = INFO_CLASS_PROTOCOL;
169 req.ID.toi_type = INFO_TYPE_PROVIDER;
170 req.ID.toi_id = TCP_MIB_STAT_ID;
171 req.ID.toi_entity = *ent;
172
173 Status = DeviceIoControl(tcpFile,
174 IOCTL_TCP_QUERY_INFORMATION_EX,
175 &req,
176 sizeof(req),
177 entry,
178 sizeof(*entry),
179 &returnSize,
180 NULL);
181
182 TRACE("TdiGetMibForTcpEntity() => status = 0x%08lx, entry = {\n"
183 " dwInSegs ............. %lu\n"
184 " dwOutSegs ............ %lu\n"
185 " dwNumConns ........... %lu\n"
186 "}\n",
187 Status,
188 entry->dwInSegs,
189 entry->dwOutSegs,
190 entry->dwNumConns);
191
192 return Status;
193}
194
195static NTSTATUS
196tdiGetMibForUdpEntity(
197 _In_ HANDLE tcpFile,
198 _In_ TDIEntityID *ent,
199 _Out_ MIB_UDPSTATS *entry)
200{
201 TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT;
202 NTSTATUS Status;
203 DWORD returnSize;
204
205 ZeroMemory(entry, sizeof(*entry));
206
207 TRACE("TdiGetMibForUdpEntity(tcpFile 0x%p, entityId 0x%x)\n",
208 tcpFile, ent->tei_instance);
209
210 req.ID.toi_class = INFO_CLASS_PROTOCOL;
211 req.ID.toi_type = INFO_TYPE_PROVIDER;
212 req.ID.toi_id = UDP_MIB_STAT_ID;
213 req.ID.toi_entity = *ent;
214
215 Status = DeviceIoControl(tcpFile,
216 IOCTL_TCP_QUERY_INFORMATION_EX,
217 &req,
218 sizeof(req),
219 entry,
220 sizeof(*entry),
221 &returnSize,
222 NULL);
223
224 TRACE("TdiGetMibForUdpEntity() => status = 0x%08lx, entry = {\n"
225 " dwInDatagrams ....... %lu\n"
226 " dwOutDatagrams ...... %lu\n"
227 " dwNumAddrs .......... %lu\n"
228 "}\n",
229 Status,
230 entry->dwInDatagrams,
231 entry->dwOutDatagrams,
232 entry->dwNumAddrs);
233
234 return Status;
235}
236
237NTSTATUS tdiGetRoutesForIpEntity
238( HANDLE tcpFile, TDIEntityID *ent, IPRouteEntry **routes, PDWORD numRoutes ) {
239 NTSTATUS status = STATUS_SUCCESS;
240
241 TRACE("TdiGetRoutesForIpEntity(tcpFile 0x%p, entityId 0x%x)\n",
242 tcpFile, ent->tei_instance);
243
244 status = tdiGetSetOfThings(tcpFile,
245 INFO_CLASS_PROTOCOL,
246 INFO_TYPE_PROVIDER,
247 IP_MIB_ARPTABLE_ENTRY_ID,
248 CL_NL_ENTITY,
249 ent->tei_instance,
250 0,
251 sizeof(IPRouteEntry),
252 (PVOID *)routes,
253 numRoutes);
254
255 return status;
256}
257
258NTSTATUS tdiGetIpAddrsForIpEntity
259( HANDLE tcpFile, TDIEntityID *ent, IPAddrEntry **addrs, PDWORD numAddrs ) {
260 NTSTATUS status;
261
262 TRACE("TdiGetIpAddrsForIpEntity(tcpFile 0x%p, entityId 0x%x)\n",
263 tcpFile, ent->tei_instance);
264
265 status = tdiGetSetOfThings(tcpFile,
266 INFO_CLASS_PROTOCOL,
267 INFO_TYPE_PROVIDER,
268 IP_MIB_ADDRTABLE_ENTRY_ID,
269 CL_NL_ENTITY,
270 ent->tei_instance,
271 0,
272 sizeof(IPAddrEntry),
273 (PVOID *)addrs,
274 numAddrs);
275
276 return status;
277}
278
279DWORD getInterfaceStatsByName(const char *name, PMIB_IFROW entry)
280{
281 if (!name)
282 return ERROR_INVALID_PARAMETER;
283 if (!entry)
284 return ERROR_INVALID_PARAMETER;
285
286 return NO_ERROR;
287}
288
289DWORD getInterfaceStatsByIndex(DWORD index, PMIB_IFROW entry)
290{
291 return ERROR_INVALID_PARAMETER;
292}
293
294DWORD getICMPStats(MIB_ICMP *stats)
295{
296 FILE *fp;
297
298 if (!stats)
299 return ERROR_INVALID_PARAMETER;
300
301 memset(stats, 0, sizeof(MIB_ICMP));
302 /* get most of these stats from /proc/net/snmp, no error if can't */
303 fp = fopen("/proc/net/snmp", "r");
304 if (fp) {
305 const char hdr[] = "Icmp:";
306 char buf[512] = { 0 }, *ptr;
307
308 do {
309 ptr = fgets(buf, sizeof(buf), fp);
310 } while (ptr && _strnicmp(buf, hdr, sizeof(hdr) - 1));
311 if (ptr) {
312 /* last line was a header, get another */
313 ptr = fgets(buf, sizeof(buf), fp);
314 if (ptr && _strnicmp(buf, hdr, sizeof(hdr) - 1) == 0) {
315 char *endPtr;
316
317 ptr += sizeof(hdr);
318 if (ptr && *ptr) {
319 stats->stats.icmpInStats.dwMsgs = strtoul(ptr, &endPtr, 10);
320 ptr = endPtr;
321 }
322 if (ptr && *ptr) {
323 stats->stats.icmpInStats.dwErrors = strtoul(ptr, &endPtr, 10);
324 ptr = endPtr;
325 }
326 if (ptr && *ptr) {
327 stats->stats.icmpInStats.dwDestUnreachs = strtoul(ptr, &endPtr, 10);
328 ptr = endPtr;
329 }
330 if (ptr && *ptr) {
331 stats->stats.icmpInStats.dwTimeExcds = strtoul(ptr, &endPtr, 10);
332 ptr = endPtr;
333 }
334 if (ptr && *ptr) {
335 stats->stats.icmpInStats.dwParmProbs = strtoul(ptr, &endPtr, 10);
336 ptr = endPtr;
337 }
338 if (ptr && *ptr) {
339 stats->stats.icmpInStats.dwSrcQuenchs = strtoul(ptr, &endPtr, 10);
340 ptr = endPtr;
341 }
342 if (ptr && *ptr) {
343 stats->stats.icmpInStats.dwRedirects = strtoul(ptr, &endPtr, 10);
344 ptr = endPtr;
345 }
346 if (ptr && *ptr) {
347 stats->stats.icmpInStats.dwEchoReps = strtoul(ptr, &endPtr, 10);
348 ptr = endPtr;
349 }
350 if (ptr && *ptr) {
351 stats->stats.icmpInStats.dwTimestamps = strtoul(ptr, &endPtr, 10);
352 ptr = endPtr;
353 }
354 if (ptr && *ptr) {
355 stats->stats.icmpInStats.dwTimestampReps = strtoul(ptr, &endPtr, 10);
356 ptr = endPtr;
357 }
358 if (ptr && *ptr) {
359 stats->stats.icmpInStats.dwAddrMasks = strtoul(ptr, &endPtr, 10);
360 ptr = endPtr;
361 }
362 if (ptr && *ptr) {
363 stats->stats.icmpInStats.dwAddrMaskReps = strtoul(ptr, &endPtr, 10);
364 ptr = endPtr;
365 }
366 if (ptr && *ptr) {
367 stats->stats.icmpOutStats.dwMsgs = strtoul(ptr, &endPtr, 10);
368 ptr = endPtr;
369 }
370 if (ptr && *ptr) {
371 stats->stats.icmpOutStats.dwErrors = strtoul(ptr, &endPtr, 10);
372 ptr = endPtr;
373 }
374 if (ptr && *ptr) {
375 stats->stats.icmpOutStats.dwDestUnreachs = strtoul(ptr, &endPtr, 10);
376 ptr = endPtr;
377 }
378 if (ptr && *ptr) {
379 stats->stats.icmpOutStats.dwTimeExcds = strtoul(ptr, &endPtr, 10);
380 ptr = endPtr;
381 }
382 if (ptr && *ptr) {
383 stats->stats.icmpOutStats.dwParmProbs = strtoul(ptr, &endPtr, 10);
384 ptr = endPtr;
385 }
386 if (ptr && *ptr) {
387 stats->stats.icmpOutStats.dwSrcQuenchs = strtoul(ptr, &endPtr, 10);
388 ptr = endPtr;
389 }
390 if (ptr && *ptr) {
391 stats->stats.icmpOutStats.dwRedirects = strtoul(ptr, &endPtr, 10);
392 ptr = endPtr;
393 }
394 if (ptr && *ptr) {
395 stats->stats.icmpOutStats.dwEchoReps = strtoul(ptr, &endPtr, 10);
396 ptr = endPtr;
397 }
398 if (ptr && *ptr) {
399 stats->stats.icmpOutStats.dwTimestamps = strtoul(ptr, &endPtr, 10);
400 ptr = endPtr;
401 }
402 if (ptr && *ptr) {
403 stats->stats.icmpOutStats.dwTimestampReps = strtoul(ptr, &endPtr, 10);
404 ptr = endPtr;
405 }
406 if (ptr && *ptr) {
407 stats->stats.icmpOutStats.dwAddrMasks = strtoul(ptr, &endPtr, 10);
408 ptr = endPtr;
409 }
410 if (ptr && *ptr) {
411 stats->stats.icmpOutStats.dwAddrMaskReps = strtoul(ptr, &endPtr, 10);
412 ptr = endPtr;
413 }
414 }
415 }
416 fclose(fp);
417 }
418 return NO_ERROR;
419}
420
421DWORD getIPStats(
422 _In_ HANDLE TcpFile,
423 _Out_ PMIB_IPSTATS pStats)
424{
425 TDIEntityID ent;
426 NTSTATUS Status;
427
428 ent.tei_entity = CL_NL_ENTITY;
429 ent.tei_instance = 0;
430
431 Status = tdiGetMibForIpEntity(TcpFile, &ent, pStats);
432
433 if (!NT_SUCCESS(Status))
434 return RtlNtStatusToDosError(Status);
435
436 return NO_ERROR;
437}
438
439DWORD getTCPStats(
440 _In_ HANDLE TcpFile,
441 _Out_ MIB_TCPSTATS *pStats)
442{
443 TDIEntityID ent;
444 NTSTATUS Status;
445
446 ent.tei_entity = CO_TL_ENTITY;
447 ent.tei_instance = 0;
448
449 Status = tdiGetMibForTcpEntity(TcpFile, &ent, pStats);
450
451 if (!NT_SUCCESS(Status))
452 return RtlNtStatusToDosError(Status);
453
454 return NO_ERROR;
455}
456
457DWORD getUDPStats(
458 _In_ HANDLE TcpFile,
459 _Out_ MIB_UDPSTATS *pStats)
460{
461 TDIEntityID ent;
462 NTSTATUS Status;
463
464 ent.tei_entity = CL_TL_ENTITY;
465 ent.tei_instance = 0;
466
467 Status = tdiGetMibForUdpEntity(TcpFile, &ent, pStats);
468
469 if (!NT_SUCCESS(Status))
470 return RtlNtStatusToDosError(Status);
471
472 return NO_ERROR;
473}
474
475DWORD getNumRoutes(void)
476{
477 DWORD numEntities, numRoutes = 0;
478 TDIEntityID *entitySet;
479 HANDLE tcpFile;
480 int i;
481 NTSTATUS status;
482
483 TRACE("called.\n");
484
485 status = openTcpFile(&tcpFile, FILE_READ_DATA);
486 if (!NT_SUCCESS(status))
487 {
488 ERR("openTcpFile returned 0x%08lx\n", status);
489 return 0;
490 }
491
492 status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
493 if (!NT_SUCCESS(status)) {
494 ERR("tdiGetEntityIDSet returned 0x%08lx\n", status);
495 closeTcpFile( tcpFile );
496 return 0;
497 }
498
499 for (i = 0; i < numEntities; i++) {
500 if (isIpEntity(tcpFile, &entitySet[i])) {
501 MIB_IPSTATS ipstats;
502 memset(&ipstats, 0, sizeof(ipstats));
503 status = tdiGetMibForIpEntity(tcpFile, &entitySet[i], &ipstats);
504 if (!NT_SUCCESS(status)) {
505 ERR("tdiGetMibForIpEntity returned 0x%08lx, for i = %d\n", status, i);
506 numRoutes = 0;
507 break;
508 }
509 numRoutes += ipstats.dwNumRoutes;
510 }
511 }
512
513 TRACE("numRoutes = %lu\n", numRoutes);
514
515 tdiFreeThingSet(entitySet);
516 closeTcpFile(tcpFile);
517
518 return numRoutes;
519}
520
521VOID HexDump( PCHAR Data, DWORD Len ) {
522 int i;
523
524 for( i = 0; i < Len; i++ ) {
525 if( !(i & 0xf) ) {
526 if( i ) fprintf(stderr,"\n");
527 fprintf(stderr,"%08x:", i);
528 }
529 fprintf( stderr, " %02x", Data[i] & 0xff );
530 }
531 fprintf(stderr,"\n");
532}
533
534RouteTable *getRouteTable(void)
535{
536 RouteTable *out_route_table;
537 DWORD numRoutes = getNumRoutes(), routesAdded = 0;
538 TDIEntityID ent;
539 HANDLE tcpFile;
540 NTSTATUS status = openTcpFile(&tcpFile, FILE_READ_DATA);
541 int i;
542
543 if (!NT_SUCCESS(status))
544 return 0;
545
546 TRACE("GETTING ROUTE TABLE\n");
547
548 out_route_table = HeapAlloc(GetProcessHeap(), 0,
549 sizeof(RouteTable) +
550 (sizeof(RouteEntry) * (numRoutes - 1)));
551 if (!out_route_table) {
552 closeTcpFile(tcpFile);
553 return NULL;
554 }
555
556 out_route_table->numRoutes = numRoutes;
557
558 for (i = 0; routesAdded < out_route_table->numRoutes; i++) {
559 int j;
560 IPRouteEntry *route_set;
561
562 getNthIpEntity(tcpFile, i, &ent);
563
564 tdiGetRoutesForIpEntity(tcpFile, &ent, &route_set, &numRoutes);
565 if (!route_set) {
566 closeTcpFile(tcpFile);
567 HeapFree(GetProcessHeap(), 0, out_route_table);
568 return 0;
569 }
570
571 TRACE("%lu routes in instance %d\n", numRoutes, i);
572#if 0
573 HexDump(route_set,
574 sizeof(IPRouteEntry) *
575 snmpInfo.ipsi_numroutes);
576#endif
577
578 for (j = 0; j < numRoutes; j++) {
579 int routeNum = j + routesAdded;
580 out_route_table->routes[routeNum].dest =
581 route_set[j].ire_dest;
582 out_route_table->routes[routeNum].mask =
583 route_set[j].ire_mask;
584 out_route_table->routes[routeNum].gateway =
585 route_set[j].ire_gw;
586 out_route_table->routes[routeNum].ifIndex =
587 route_set[j].ire_index;
588 out_route_table->routes[routeNum].metric =
589 route_set[j].ire_metric1;
590 }
591
592 if (route_set) tdiFreeThingSet(route_set);
593
594 routesAdded += numRoutes;
595 }
596
597 closeTcpFile(tcpFile);
598 TRACE("status = 0x%08lx, out_route_table = 0x%p\n", status, out_route_table);
599 return out_route_table;
600}
601
602DWORD getNumArpEntries(void)
603{
604 DWORD numEntities;
605 TDIEntityID *entitySet = NULL;
606 HANDLE tcpFile;
607 int i, totalNumber = 0;
608 NTSTATUS status;
609 PMIB_IPNETROW IpArpTable = NULL;
610 DWORD returnSize;
611
612 TRACE("called.\n");
613
614 status = openTcpFile(&tcpFile, FILE_READ_DATA);
615 if (!NT_SUCCESS(status))
616 {
617 ERR("openTcpFile returned 0x%08lx\n", status);
618 return 0;
619 }
620
621 status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
622
623 for (i = 0; i < numEntities; i++) {
624 if (isInterface(&entitySet[i]) && hasArp(tcpFile, &entitySet[i]))
625 {
626 status = tdiGetSetOfThings(tcpFile,
627 INFO_CLASS_PROTOCOL,
628 INFO_TYPE_PROVIDER,
629 IP_MIB_ARPTABLE_ENTRY_ID,
630 AT_ENTITY,
631 entitySet[i].tei_instance,
632 0,
633 sizeof(MIB_IPNETROW),
634 (PVOID *)&IpArpTable,
635 &returnSize);
636
637 if (status == STATUS_SUCCESS) totalNumber += returnSize;
638 if (IpArpTable) {
639 tdiFreeThingSet(IpArpTable);
640 IpArpTable = NULL;
641 }
642 }
643 }
644
645 closeTcpFile(tcpFile);
646 if (entitySet) tdiFreeThingSet(entitySet);
647 return totalNumber;
648}
649
650PMIB_IPNETTABLE getArpTable(void)
651{
652 DWORD numEntities, returnSize;
653 TDIEntityID *entitySet;
654 HANDLE tcpFile;
655 int i, totalNumber, TmpIdx, CurrIdx = 0;
656 NTSTATUS status;
657 PMIB_IPNETTABLE IpArpTable = NULL;
658 PMIB_IPNETROW AdapterArpTable = NULL;
659
660 TRACE("called.\n");
661
662 totalNumber = getNumArpEntries();
663
664 status = openTcpFile(&tcpFile, FILE_READ_DATA);
665 if (!NT_SUCCESS(status))
666 {
667 ERR("openTcpFile returned 0x%08lx\n", status);
668 return 0;
669 }
670
671 IpArpTable = HeapAlloc(GetProcessHeap(), 0,
672 sizeof(DWORD) + (sizeof(MIB_IPNETROW) * totalNumber));
673 if (!IpArpTable) {
674 closeTcpFile(tcpFile);
675 return NULL;
676 }
677
678 status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
679
680 for (i = 0; i < numEntities; i++) {
681 if (isInterface(&entitySet[i]) && hasArp(tcpFile, &entitySet[i]))
682 {
683 status = tdiGetSetOfThings(tcpFile,
684 INFO_CLASS_PROTOCOL,
685 INFO_TYPE_PROVIDER,
686 IP_MIB_ARPTABLE_ENTRY_ID,
687 AT_ENTITY,
688 entitySet[i].tei_instance,
689 0,
690 sizeof(MIB_IPNETROW),
691 (PVOID *)&AdapterArpTable,
692 &returnSize);
693
694 if (status == STATUS_SUCCESS) {
695 for (TmpIdx = 0; TmpIdx < returnSize; TmpIdx++, CurrIdx++)
696 IpArpTable->table[CurrIdx] = AdapterArpTable[TmpIdx];
697 tdiFreeThingSet(AdapterArpTable);
698 }
699 }
700 }
701
702 closeTcpFile(tcpFile);
703 tdiFreeThingSet(entitySet);
704 IpArpTable->dwNumEntries = CurrIdx;
705 return IpArpTable;
706}
707
708struct _TABLE_CALL
709{
710 DWORD TOIID;
711 SIZE_T UdpSize;
712 SIZE_T TcpSize;
713 SIZE_T UdpOffset;
714 SIZE_T TcpOffset;
715} UdpTcpTableCall[] = {
716 {IP_MIB_ARPTABLE_ENTRY_ID, sizeof(MIB_UDPROW), sizeof(MIB_TCPROW), FIELD_OFFSET(MIB_UDPTABLE, table), FIELD_OFFSET(MIB_TCPTABLE, table)},
717 {IP_MIB_ADDRTABLE_ENTRY_ID, sizeof(MIB_UDPROW_OWNER_PID), sizeof(MIB_TCPROW_OWNER_PID), FIELD_OFFSET(MIB_UDPTABLE_OWNER_PID, table), FIELD_OFFSET(MIB_TCPTABLE_OWNER_PID, table)},
718 {IP_SPECIFIC_MODULE_ENTRY_ID, sizeof(MIB_UDPROW_OWNER_MODULE), sizeof(MIB_TCPROW_OWNER_MODULE), FIELD_OFFSET(MIB_UDPTABLE_OWNER_MODULE, table), FIELD_OFFSET(MIB_TCPTABLE_OWNER_MODULE, table)},
719};
720
721#define Add2Ptr(PTR, INC) (PVOID)((ULONG_PTR)(PTR) + (INC))
722
723DWORD getNumUdpEntries(void)
724{
725 DWORD numEntities;
726 TDIEntityID *entitySet = NULL;
727 HANDLE tcpFile;
728 int i, totalNumber = 0;
729 NTSTATUS status;
730 PMIB_UDPROW IpUdpTable = NULL;
731 DWORD returnSize;
732
733 TRACE("called.\n");
734
735 status = openTcpFile(&tcpFile, FILE_READ_DATA);
736 if (!NT_SUCCESS(status))
737 {
738 ERR("openTcpFile returned 0x%08lx\n", status);
739 return 0;
740 }
741
742 status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
743
744 for (i = 0; i < numEntities; i++) {
745 if (entitySet[i].tei_entity == CL_TL_ENTITY && hasArp(tcpFile, &entitySet[i]))
746 {
747 status = tdiGetSetOfThings(tcpFile,
748 INFO_CLASS_PROTOCOL,
749 INFO_TYPE_PROVIDER,
750 IP_MIB_ARPTABLE_ENTRY_ID,
751 CL_TL_ENTITY,
752 entitySet[i].tei_instance,
753 0,
754 sizeof(MIB_UDPROW),
755 (PVOID *)&IpUdpTable,
756 &returnSize);
757
758 if (status == STATUS_SUCCESS) totalNumber += returnSize;
759 if (IpUdpTable) {
760 tdiFreeThingSet(IpUdpTable);
761 IpUdpTable = NULL;
762 }
763 }
764 }
765
766 closeTcpFile(tcpFile);
767 if (entitySet) tdiFreeThingSet(entitySet);
768 return totalNumber;
769}
770
771PVOID getUdpTable(CLASS_TABLE Class)
772{
773 DWORD numEntities, returnSize;
774 TDIEntityID *entitySet;
775 HANDLE tcpFile;
776 int i, totalNumber, TmpIdx, CurrIdx = 0;
777 NTSTATUS status;
778 PMIB_UDPTABLE IpUdpTable = NULL;
779 PVOID AdapterUdpTable = NULL;
780
781 TRACE("called.\n");
782
783 totalNumber = getNumUdpEntries();
784
785 status = openTcpFile(&tcpFile, FILE_READ_DATA);
786 if (!NT_SUCCESS(status))
787 {
788 ERR("openTcpFile returned 0x%08lx\n", status);
789 return 0;
790 }
791
792 IpUdpTable = HeapAlloc(GetProcessHeap(), 0,
793 UdpTcpTableCall[Class].UdpOffset + (UdpTcpTableCall[Class].UdpSize * totalNumber));
794 if (!IpUdpTable) {
795 closeTcpFile(tcpFile);
796 return NULL;
797 }
798
799 status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
800
801 for (i = 0; i < numEntities; i++) {
802 if (entitySet[i].tei_entity == CL_TL_ENTITY && hasArp(tcpFile, &entitySet[i]))
803 {
804 status = tdiGetSetOfThings(tcpFile,
805 INFO_CLASS_PROTOCOL,
806 INFO_TYPE_PROVIDER,
807 UdpTcpTableCall[Class].TOIID,
808 CL_TL_ENTITY,
809 entitySet[i].tei_instance,
810 0,
811 UdpTcpTableCall[Class].UdpSize,
812 &AdapterUdpTable,
813 &returnSize);
814
815 if (status == STATUS_SUCCESS) {
816 for (TmpIdx = 0; TmpIdx < returnSize; TmpIdx++, CurrIdx++)
817 CopyMemory(Add2Ptr(IpUdpTable, UdpTcpTableCall[Class].UdpOffset + UdpTcpTableCall[Class].UdpSize * CurrIdx),
818 Add2Ptr(AdapterUdpTable, UdpTcpTableCall[Class].UdpSize * TmpIdx),
819 UdpTcpTableCall[Class].UdpSize);
820 tdiFreeThingSet(AdapterUdpTable);
821 }
822 }
823 }
824
825 closeTcpFile(tcpFile);
826 tdiFreeThingSet(entitySet);
827 IpUdpTable->dwNumEntries = CurrIdx;
828 return IpUdpTable;
829}
830
831DWORD getNumTcpEntries(void)
832{
833 DWORD numEntities;
834 TDIEntityID *entitySet = NULL;
835 HANDLE tcpFile;
836 int i, totalNumber = 0;
837 NTSTATUS status;
838 PMIB_TCPROW IpTcpTable = NULL;
839 DWORD returnSize;
840
841 TRACE("called.\n");
842
843 status = openTcpFile(&tcpFile, FILE_READ_DATA);
844 if (!NT_SUCCESS(status))
845 {
846 ERR("openTcpFile returned 0x%08lx\n", status);
847 return 0;
848 }
849
850 status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
851
852 for (i = 0; i < numEntities; i++) {
853 if (entitySet[i].tei_entity == CO_TL_ENTITY && hasArp(tcpFile, &entitySet[i]))
854 {
855 status = tdiGetSetOfThings(tcpFile,
856 INFO_CLASS_PROTOCOL,
857 INFO_TYPE_PROVIDER,
858 IP_MIB_ARPTABLE_ENTRY_ID,
859 CO_TL_ENTITY,
860 entitySet[i].tei_instance,
861 0,
862 sizeof(MIB_TCPROW),
863 (PVOID *)&IpTcpTable,
864 &returnSize);
865
866 if (status == STATUS_SUCCESS) totalNumber += returnSize;
867 if (IpTcpTable) {
868 tdiFreeThingSet(IpTcpTable);
869 IpTcpTable = NULL;
870 }
871 }
872 }
873
874 closeTcpFile(tcpFile);
875 if (entitySet) tdiFreeThingSet(entitySet);
876 return totalNumber;
877}
878
879PVOID getTcpTable(CLASS_TABLE Class)
880{
881 DWORD numEntities, returnSize;
882 TDIEntityID *entitySet;
883 HANDLE tcpFile;
884 int i, totalNumber, TmpIdx, CurrIdx = 0;
885 NTSTATUS status;
886 PMIB_TCPTABLE IpTcpTable = NULL;
887 PVOID AdapterTcpTable = NULL;
888
889 TRACE("called.\n");
890
891 totalNumber = getNumTcpEntries();
892
893 status = openTcpFile(&tcpFile, FILE_READ_DATA);
894 if (!NT_SUCCESS(status))
895 {
896 ERR("openTcpFile returned 0x%08lx\n", status);
897 return 0;
898 }
899
900 IpTcpTable = HeapAlloc(GetProcessHeap(), 0,
901 UdpTcpTableCall[Class].TcpOffset + (UdpTcpTableCall[Class].TcpSize * totalNumber));
902 if (!IpTcpTable) {
903 closeTcpFile(tcpFile);
904 return NULL;
905 }
906
907 status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
908
909 for (i = 0; i < numEntities; i++) {
910 if (entitySet[i].tei_entity == CO_TL_ENTITY && hasArp(tcpFile, &entitySet[i]))
911 {
912 status = tdiGetSetOfThings(tcpFile,
913 INFO_CLASS_PROTOCOL,
914 INFO_TYPE_PROVIDER,
915 UdpTcpTableCall[Class].TOIID,
916 CO_TL_ENTITY,
917 entitySet[i].tei_instance,
918 0,
919 UdpTcpTableCall[Class].TcpSize,
920 &AdapterTcpTable,
921 &returnSize);
922
923 if (status == STATUS_SUCCESS) {
924 for (TmpIdx = 0; TmpIdx < returnSize; TmpIdx++, CurrIdx++)
925 CopyMemory(Add2Ptr(IpTcpTable, UdpTcpTableCall[Class].TcpOffset + UdpTcpTableCall[Class].TcpSize * CurrIdx),
926 Add2Ptr(AdapterTcpTable, UdpTcpTableCall[Class].TcpSize * TmpIdx),
927 UdpTcpTableCall[Class].TcpSize);
928 tdiFreeThingSet(AdapterTcpTable);
929 }
930 }
931 }
932
933 closeTcpFile(tcpFile);
934 tdiFreeThingSet(entitySet);
935 IpTcpTable->dwNumEntries = CurrIdx;
936 return IpTcpTable;
937}