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
24 WINE_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
isIpEntity(HANDLE tcpFile,TDIEntityID * ent)60 BOOL isIpEntity( HANDLE tcpFile, TDIEntityID *ent ) {
61 return (ent->tei_entity == CL_NL_ENTITY ||
62 ent->tei_entity == CO_NL_ENTITY);
63 }
64
getNthIpEntity(HANDLE tcpFile,DWORD index,TDIEntityID * ent)65 NTSTATUS 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
tdiGetMibForIpEntity(HANDLE tcpFile,TDIEntityID * ent,IPSNMPInfo * entry)95 NTSTATUS tdiGetMibForIpEntity
96 ( HANDLE tcpFile, TDIEntityID *ent, IPSNMPInfo *entry ) {
97 TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT;
98 NTSTATUS status = STATUS_SUCCESS;
99 DWORD returnSize;
100
101 memset( entry, 0, sizeof( *entry ) );
102
103 TRACE("TdiGetMibForIpEntity(tcpFile 0x%p, entityId 0x%x)\n",
104 tcpFile, ent->tei_instance);
105
106 req.ID.toi_class = INFO_CLASS_PROTOCOL;
107 req.ID.toi_type = INFO_TYPE_PROVIDER;
108 req.ID.toi_id = IP_MIB_STATS_ID;
109 req.ID.toi_entity = *ent;
110
111 status = DeviceIoControl(tcpFile,
112 IOCTL_TCP_QUERY_INFORMATION_EX,
113 &req,
114 sizeof(req),
115 entry,
116 sizeof(*entry),
117 &returnSize,
118 NULL);
119
120 TRACE("TdiGetMibForIpEntity() => status = 0x%08lx, entry = {\n"
121 " ipsi_forwarding ............ %lu\n"
122 " ipsi_defaultttl ............ %lu\n"
123 " ipsi_inreceives ............ %lu\n"
124 " ipsi_indelivers ............ %lu\n"
125 " ipsi_outrequests ........... %lu\n"
126 " ipsi_routingdiscards ....... %lu\n"
127 " ipsi_outdiscards ........... %lu\n"
128 " ipsi_outnoroutes ........... %lu\n"
129 " ipsi_numif ................. %lu\n"
130 " ipsi_numaddr ............... %lu\n"
131 " ipsi_numroutes ............. %lu\n"
132 "}\n",
133 status,
134 entry->ipsi_forwarding,
135 entry->ipsi_defaultttl,
136 entry->ipsi_inreceives,
137 entry->ipsi_indelivers,
138 entry->ipsi_outrequests,
139 entry->ipsi_routingdiscards,
140 entry->ipsi_outdiscards,
141 entry->ipsi_outnoroutes,
142 entry->ipsi_numif,
143 entry->ipsi_numaddr,
144 entry->ipsi_numroutes);
145
146 return status;
147 }
148
tdiGetRoutesForIpEntity(HANDLE tcpFile,TDIEntityID * ent,IPRouteEntry ** routes,PDWORD numRoutes)149 NTSTATUS tdiGetRoutesForIpEntity
150 ( HANDLE tcpFile, TDIEntityID *ent, IPRouteEntry **routes, PDWORD numRoutes ) {
151 NTSTATUS status = STATUS_SUCCESS;
152
153 TRACE("TdiGetRoutesForIpEntity(tcpFile 0x%p, entityId 0x%x)\n",
154 tcpFile, ent->tei_instance);
155
156 status = tdiGetSetOfThings(tcpFile,
157 INFO_CLASS_PROTOCOL,
158 INFO_TYPE_PROVIDER,
159 IP_MIB_ARPTABLE_ENTRY_ID,
160 CL_NL_ENTITY,
161 ent->tei_instance,
162 0,
163 sizeof(IPRouteEntry),
164 (PVOID *)routes,
165 numRoutes);
166
167 return status;
168 }
169
tdiGetIpAddrsForIpEntity(HANDLE tcpFile,TDIEntityID * ent,IPAddrEntry ** addrs,PDWORD numAddrs)170 NTSTATUS tdiGetIpAddrsForIpEntity
171 ( HANDLE tcpFile, TDIEntityID *ent, IPAddrEntry **addrs, PDWORD numAddrs ) {
172 NTSTATUS status;
173
174 TRACE("TdiGetIpAddrsForIpEntity(tcpFile 0x%p, entityId 0x%x)\n",
175 tcpFile, ent->tei_instance);
176
177 status = tdiGetSetOfThings(tcpFile,
178 INFO_CLASS_PROTOCOL,
179 INFO_TYPE_PROVIDER,
180 IP_MIB_ADDRTABLE_ENTRY_ID,
181 CL_NL_ENTITY,
182 ent->tei_instance,
183 0,
184 sizeof(IPAddrEntry),
185 (PVOID *)addrs,
186 numAddrs);
187
188 return status;
189 }
190
getInterfaceStatsByName(const char * name,PMIB_IFROW entry)191 DWORD getInterfaceStatsByName(const char *name, PMIB_IFROW entry)
192 {
193 if (!name)
194 return ERROR_INVALID_PARAMETER;
195 if (!entry)
196 return ERROR_INVALID_PARAMETER;
197
198 return NO_ERROR;
199 }
200
getInterfaceStatsByIndex(DWORD index,PMIB_IFROW entry)201 DWORD getInterfaceStatsByIndex(DWORD index, PMIB_IFROW entry)
202 {
203 return ERROR_INVALID_PARAMETER;
204 }
205
getICMPStats(MIB_ICMP * stats)206 DWORD getICMPStats(MIB_ICMP *stats)
207 {
208 FILE *fp;
209
210 if (!stats)
211 return ERROR_INVALID_PARAMETER;
212
213 memset(stats, 0, sizeof(MIB_ICMP));
214 /* get most of these stats from /proc/net/snmp, no error if can't */
215 fp = fopen("/proc/net/snmp", "r");
216 if (fp) {
217 const char hdr[] = "Icmp:";
218 char buf[512] = { 0 }, *ptr;
219
220 do {
221 ptr = fgets(buf, sizeof(buf), fp);
222 } while (ptr && _strnicmp(buf, hdr, sizeof(hdr) - 1));
223 if (ptr) {
224 /* last line was a header, get another */
225 ptr = fgets(buf, sizeof(buf), fp);
226 if (ptr && _strnicmp(buf, hdr, sizeof(hdr) - 1) == 0) {
227 char *endPtr;
228
229 ptr += sizeof(hdr);
230 if (ptr && *ptr) {
231 stats->stats.icmpInStats.dwMsgs = strtoul(ptr, &endPtr, 10);
232 ptr = endPtr;
233 }
234 if (ptr && *ptr) {
235 stats->stats.icmpInStats.dwErrors = strtoul(ptr, &endPtr, 10);
236 ptr = endPtr;
237 }
238 if (ptr && *ptr) {
239 stats->stats.icmpInStats.dwDestUnreachs = strtoul(ptr, &endPtr, 10);
240 ptr = endPtr;
241 }
242 if (ptr && *ptr) {
243 stats->stats.icmpInStats.dwTimeExcds = strtoul(ptr, &endPtr, 10);
244 ptr = endPtr;
245 }
246 if (ptr && *ptr) {
247 stats->stats.icmpInStats.dwParmProbs = strtoul(ptr, &endPtr, 10);
248 ptr = endPtr;
249 }
250 if (ptr && *ptr) {
251 stats->stats.icmpInStats.dwSrcQuenchs = strtoul(ptr, &endPtr, 10);
252 ptr = endPtr;
253 }
254 if (ptr && *ptr) {
255 stats->stats.icmpInStats.dwRedirects = strtoul(ptr, &endPtr, 10);
256 ptr = endPtr;
257 }
258 if (ptr && *ptr) {
259 stats->stats.icmpInStats.dwEchoReps = strtoul(ptr, &endPtr, 10);
260 ptr = endPtr;
261 }
262 if (ptr && *ptr) {
263 stats->stats.icmpInStats.dwTimestamps = strtoul(ptr, &endPtr, 10);
264 ptr = endPtr;
265 }
266 if (ptr && *ptr) {
267 stats->stats.icmpInStats.dwTimestampReps = strtoul(ptr, &endPtr, 10);
268 ptr = endPtr;
269 }
270 if (ptr && *ptr) {
271 stats->stats.icmpInStats.dwAddrMasks = strtoul(ptr, &endPtr, 10);
272 ptr = endPtr;
273 }
274 if (ptr && *ptr) {
275 stats->stats.icmpInStats.dwAddrMaskReps = strtoul(ptr, &endPtr, 10);
276 ptr = endPtr;
277 }
278 if (ptr && *ptr) {
279 stats->stats.icmpOutStats.dwMsgs = strtoul(ptr, &endPtr, 10);
280 ptr = endPtr;
281 }
282 if (ptr && *ptr) {
283 stats->stats.icmpOutStats.dwErrors = strtoul(ptr, &endPtr, 10);
284 ptr = endPtr;
285 }
286 if (ptr && *ptr) {
287 stats->stats.icmpOutStats.dwDestUnreachs = strtoul(ptr, &endPtr, 10);
288 ptr = endPtr;
289 }
290 if (ptr && *ptr) {
291 stats->stats.icmpOutStats.dwTimeExcds = strtoul(ptr, &endPtr, 10);
292 ptr = endPtr;
293 }
294 if (ptr && *ptr) {
295 stats->stats.icmpOutStats.dwParmProbs = strtoul(ptr, &endPtr, 10);
296 ptr = endPtr;
297 }
298 if (ptr && *ptr) {
299 stats->stats.icmpOutStats.dwSrcQuenchs = strtoul(ptr, &endPtr, 10);
300 ptr = endPtr;
301 }
302 if (ptr && *ptr) {
303 stats->stats.icmpOutStats.dwRedirects = strtoul(ptr, &endPtr, 10);
304 ptr = endPtr;
305 }
306 if (ptr && *ptr) {
307 stats->stats.icmpOutStats.dwEchoReps = strtoul(ptr, &endPtr, 10);
308 ptr = endPtr;
309 }
310 if (ptr && *ptr) {
311 stats->stats.icmpOutStats.dwTimestamps = strtoul(ptr, &endPtr, 10);
312 ptr = endPtr;
313 }
314 if (ptr && *ptr) {
315 stats->stats.icmpOutStats.dwTimestampReps = strtoul(ptr, &endPtr, 10);
316 ptr = endPtr;
317 }
318 if (ptr && *ptr) {
319 stats->stats.icmpOutStats.dwAddrMasks = strtoul(ptr, &endPtr, 10);
320 ptr = endPtr;
321 }
322 if (ptr && *ptr) {
323 stats->stats.icmpOutStats.dwAddrMaskReps = strtoul(ptr, &endPtr, 10);
324 ptr = endPtr;
325 }
326 }
327 }
328 fclose(fp);
329 }
330 return NO_ERROR;
331 }
332
getIPStats(PMIB_IPSTATS stats,DWORD family)333 DWORD getIPStats(PMIB_IPSTATS stats, DWORD family)
334 {
335 if (!stats)
336 return ERROR_INVALID_PARAMETER;
337
338 if (family != AF_INET && family != AF_INET6)
339 return ERROR_INVALID_PARAMETER;
340
341 return NO_ERROR;
342 }
343
getTCPStats(MIB_TCPSTATS * stats,DWORD family)344 DWORD getTCPStats(MIB_TCPSTATS *stats, DWORD family)
345 {
346 if (!stats)
347 return ERROR_INVALID_PARAMETER;
348
349 if (family != AF_INET && family != AF_INET6)
350 return ERROR_INVALID_PARAMETER;
351
352 return NO_ERROR;
353 }
354
getUDPStats(MIB_UDPSTATS * stats,DWORD family)355 DWORD getUDPStats(MIB_UDPSTATS *stats, DWORD family)
356 {
357 if (!stats)
358 return ERROR_INVALID_PARAMETER;
359
360 if (family != AF_INET && family != AF_INET6)
361 return ERROR_INVALID_PARAMETER;
362
363 return NO_ERROR;
364 }
365
getNumRoutes(void)366 DWORD getNumRoutes(void)
367 {
368 DWORD numEntities, numRoutes = 0;
369 TDIEntityID *entitySet;
370 HANDLE tcpFile;
371 int i;
372 NTSTATUS status;
373
374 TRACE("called.\n");
375
376 status = openTcpFile(&tcpFile, FILE_READ_DATA);
377 if (!NT_SUCCESS(status))
378 {
379 ERR("openTcpFile returned 0x%08lx\n", status);
380 return 0;
381 }
382
383 status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
384 if (!NT_SUCCESS(status)) {
385 ERR("tdiGetEntityIDSet returned 0x%08lx\n", status);
386 closeTcpFile( tcpFile );
387 return 0;
388 }
389
390 for (i = 0; i < numEntities; i++) {
391 if (isIpEntity(tcpFile, &entitySet[i])) {
392 IPSNMPInfo isnmp;
393 memset(&isnmp, 0, sizeof(isnmp));
394 status = tdiGetMibForIpEntity(tcpFile, &entitySet[i], &isnmp);
395 if (!NT_SUCCESS(status)) {
396 ERR("tdiGetMibForIpEntity returned 0x%08lx, for i = %d\n", status, i);
397 numRoutes = 0;
398 break;
399 }
400 numRoutes += isnmp.ipsi_numroutes;
401 }
402 }
403
404 TRACE("numRoutes = %lu\n", numRoutes);
405
406 tdiFreeThingSet(entitySet);
407 closeTcpFile(tcpFile);
408
409 return numRoutes;
410 }
411
HexDump(PCHAR Data,DWORD Len)412 VOID HexDump( PCHAR Data, DWORD Len ) {
413 int i;
414
415 for( i = 0; i < Len; i++ ) {
416 if( !(i & 0xf) ) {
417 if( i ) fprintf(stderr,"\n");
418 fprintf(stderr,"%08x:", i);
419 }
420 fprintf( stderr, " %02x", Data[i] & 0xff );
421 }
422 fprintf(stderr,"\n");
423 }
424
getRouteTable(void)425 RouteTable *getRouteTable(void)
426 {
427 RouteTable *out_route_table;
428 DWORD numRoutes = getNumRoutes(), routesAdded = 0;
429 TDIEntityID ent;
430 HANDLE tcpFile;
431 NTSTATUS status = openTcpFile(&tcpFile, FILE_READ_DATA);
432 int i;
433
434 if (!NT_SUCCESS(status))
435 return 0;
436
437 TRACE("GETTING ROUTE TABLE\n");
438
439 out_route_table = HeapAlloc(GetProcessHeap(), 0,
440 sizeof(RouteTable) +
441 (sizeof(RouteEntry) * (numRoutes - 1)));
442 if (!out_route_table) {
443 closeTcpFile(tcpFile);
444 return NULL;
445 }
446
447 out_route_table->numRoutes = numRoutes;
448
449 for (i = 0; routesAdded < out_route_table->numRoutes; i++) {
450 int j;
451 IPRouteEntry *route_set;
452
453 getNthIpEntity(tcpFile, i, &ent);
454
455 tdiGetRoutesForIpEntity(tcpFile, &ent, &route_set, &numRoutes);
456 if (!route_set) {
457 closeTcpFile(tcpFile);
458 HeapFree(GetProcessHeap(), 0, out_route_table);
459 return 0;
460 }
461
462 TRACE("%lu routes in instance %d\n", numRoutes, i);
463 #if 0
464 HexDump(route_set,
465 sizeof(IPRouteEntry) *
466 snmpInfo.ipsi_numroutes);
467 #endif
468
469 for (j = 0; j < numRoutes; j++) {
470 int routeNum = j + routesAdded;
471 out_route_table->routes[routeNum].dest =
472 route_set[j].ire_dest;
473 out_route_table->routes[routeNum].mask =
474 route_set[j].ire_mask;
475 out_route_table->routes[routeNum].gateway =
476 route_set[j].ire_gw;
477 out_route_table->routes[routeNum].ifIndex =
478 route_set[j].ire_index;
479 out_route_table->routes[routeNum].metric =
480 route_set[j].ire_metric1;
481 }
482
483 if (route_set) tdiFreeThingSet(route_set);
484
485 routesAdded += numRoutes;
486 }
487
488 closeTcpFile(tcpFile);
489 TRACE("status = 0x%08lx, out_route_table = 0x%p\n", status, out_route_table);
490 return out_route_table;
491 }
492
getNumArpEntries(void)493 DWORD getNumArpEntries(void)
494 {
495 DWORD numEntities;
496 TDIEntityID *entitySet = NULL;
497 HANDLE tcpFile;
498 int i, totalNumber = 0;
499 NTSTATUS status;
500 PMIB_IPNETROW IpArpTable = NULL;
501 DWORD returnSize;
502
503 TRACE("called.\n");
504
505 status = openTcpFile(&tcpFile, FILE_READ_DATA);
506 if (!NT_SUCCESS(status))
507 {
508 ERR("openTcpFile returned 0x%08lx\n", status);
509 return 0;
510 }
511
512 status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
513
514 for (i = 0; i < numEntities; i++) {
515 if (isInterface(&entitySet[i]) && hasArp(tcpFile, &entitySet[i]))
516 {
517 status = tdiGetSetOfThings(tcpFile,
518 INFO_CLASS_PROTOCOL,
519 INFO_TYPE_PROVIDER,
520 IP_MIB_ARPTABLE_ENTRY_ID,
521 AT_ENTITY,
522 entitySet[i].tei_instance,
523 0,
524 sizeof(MIB_IPNETROW),
525 (PVOID *)&IpArpTable,
526 &returnSize);
527
528 if (status == STATUS_SUCCESS) totalNumber += returnSize;
529 if (IpArpTable) {
530 tdiFreeThingSet(IpArpTable);
531 IpArpTable = NULL;
532 }
533 }
534 }
535
536 closeTcpFile(tcpFile);
537 if (entitySet) tdiFreeThingSet(entitySet);
538 return totalNumber;
539 }
540
getArpTable(void)541 PMIB_IPNETTABLE getArpTable(void)
542 {
543 DWORD numEntities, returnSize;
544 TDIEntityID *entitySet;
545 HANDLE tcpFile;
546 int i, totalNumber, TmpIdx, CurrIdx = 0;
547 NTSTATUS status;
548 PMIB_IPNETTABLE IpArpTable = NULL;
549 PMIB_IPNETROW AdapterArpTable = NULL;
550
551 TRACE("called.\n");
552
553 totalNumber = getNumArpEntries();
554
555 status = openTcpFile(&tcpFile, FILE_READ_DATA);
556 if (!NT_SUCCESS(status))
557 {
558 ERR("openTcpFile returned 0x%08lx\n", status);
559 return 0;
560 }
561
562 IpArpTable = HeapAlloc(GetProcessHeap(), 0,
563 sizeof(DWORD) + (sizeof(MIB_IPNETROW) * totalNumber));
564 if (!IpArpTable) {
565 closeTcpFile(tcpFile);
566 return NULL;
567 }
568
569 status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
570
571 for (i = 0; i < numEntities; i++) {
572 if (isInterface(&entitySet[i]) && hasArp(tcpFile, &entitySet[i]))
573 {
574 status = tdiGetSetOfThings(tcpFile,
575 INFO_CLASS_PROTOCOL,
576 INFO_TYPE_PROVIDER,
577 IP_MIB_ARPTABLE_ENTRY_ID,
578 AT_ENTITY,
579 entitySet[i].tei_instance,
580 0,
581 sizeof(MIB_IPNETROW),
582 (PVOID *)&AdapterArpTable,
583 &returnSize);
584
585 if (status == STATUS_SUCCESS) {
586 for (TmpIdx = 0; TmpIdx < returnSize; TmpIdx++, CurrIdx++)
587 IpArpTable->table[CurrIdx] = AdapterArpTable[TmpIdx];
588 tdiFreeThingSet(AdapterArpTable);
589 }
590 }
591 }
592
593 closeTcpFile(tcpFile);
594 tdiFreeThingSet(entitySet);
595 IpArpTable->dwNumEntries = CurrIdx;
596 return IpArpTable;
597 }
598
599 struct _TABLE_CALL
600 {
601 DWORD TOIID;
602 SIZE_T UdpSize;
603 SIZE_T TcpSize;
604 SIZE_T UdpOffset;
605 SIZE_T TcpOffset;
606 } UdpTcpTableCall[] = {
607 {IP_MIB_ARPTABLE_ENTRY_ID, sizeof(MIB_UDPROW), sizeof(MIB_TCPROW), FIELD_OFFSET(MIB_UDPTABLE, table), FIELD_OFFSET(MIB_TCPTABLE, table)},
608 {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)},
609 {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)},
610 };
611
612 #define Add2Ptr(PTR, INC) (PVOID)((ULONG_PTR)(PTR) + (INC))
613
getNumUdpEntries(void)614 DWORD getNumUdpEntries(void)
615 {
616 DWORD numEntities;
617 TDIEntityID *entitySet = NULL;
618 HANDLE tcpFile;
619 int i, totalNumber = 0;
620 NTSTATUS status;
621 PMIB_UDPROW IpUdpTable = NULL;
622 DWORD returnSize;
623
624 TRACE("called.\n");
625
626 status = openTcpFile(&tcpFile, FILE_READ_DATA);
627 if (!NT_SUCCESS(status))
628 {
629 ERR("openTcpFile returned 0x%08lx\n", status);
630 return 0;
631 }
632
633 status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
634
635 for (i = 0; i < numEntities; i++) {
636 if (entitySet[i].tei_entity == CL_TL_ENTITY && hasArp(tcpFile, &entitySet[i]))
637 {
638 status = tdiGetSetOfThings(tcpFile,
639 INFO_CLASS_PROTOCOL,
640 INFO_TYPE_PROVIDER,
641 IP_MIB_ARPTABLE_ENTRY_ID,
642 CL_TL_ENTITY,
643 entitySet[i].tei_instance,
644 0,
645 sizeof(MIB_UDPROW),
646 (PVOID *)&IpUdpTable,
647 &returnSize);
648
649 if (status == STATUS_SUCCESS) totalNumber += returnSize;
650 if (IpUdpTable) {
651 tdiFreeThingSet(IpUdpTable);
652 IpUdpTable = NULL;
653 }
654 }
655 }
656
657 closeTcpFile(tcpFile);
658 if (entitySet) tdiFreeThingSet(entitySet);
659 return totalNumber;
660 }
661
getUdpTable(CLASS_TABLE Class)662 PVOID getUdpTable(CLASS_TABLE Class)
663 {
664 DWORD numEntities, returnSize;
665 TDIEntityID *entitySet;
666 HANDLE tcpFile;
667 int i, totalNumber, TmpIdx, CurrIdx = 0;
668 NTSTATUS status;
669 PMIB_UDPTABLE IpUdpTable = NULL;
670 PVOID AdapterUdpTable = NULL;
671
672 TRACE("called.\n");
673
674 totalNumber = getNumUdpEntries();
675
676 status = openTcpFile(&tcpFile, FILE_READ_DATA);
677 if (!NT_SUCCESS(status))
678 {
679 ERR("openTcpFile returned 0x%08lx\n", status);
680 return 0;
681 }
682
683 IpUdpTable = HeapAlloc(GetProcessHeap(), 0,
684 UdpTcpTableCall[Class].UdpOffset + (UdpTcpTableCall[Class].UdpSize * totalNumber));
685 if (!IpUdpTable) {
686 closeTcpFile(tcpFile);
687 return NULL;
688 }
689
690 status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
691
692 for (i = 0; i < numEntities; i++) {
693 if (entitySet[i].tei_entity == CL_TL_ENTITY && hasArp(tcpFile, &entitySet[i]))
694 {
695 status = tdiGetSetOfThings(tcpFile,
696 INFO_CLASS_PROTOCOL,
697 INFO_TYPE_PROVIDER,
698 UdpTcpTableCall[Class].TOIID,
699 CL_TL_ENTITY,
700 entitySet[i].tei_instance,
701 0,
702 UdpTcpTableCall[Class].UdpSize,
703 &AdapterUdpTable,
704 &returnSize);
705
706 if (status == STATUS_SUCCESS) {
707 for (TmpIdx = 0; TmpIdx < returnSize; TmpIdx++, CurrIdx++)
708 CopyMemory(Add2Ptr(IpUdpTable, UdpTcpTableCall[Class].UdpOffset + UdpTcpTableCall[Class].UdpSize * CurrIdx),
709 Add2Ptr(AdapterUdpTable, UdpTcpTableCall[Class].UdpSize * TmpIdx),
710 UdpTcpTableCall[Class].UdpSize);
711 tdiFreeThingSet(AdapterUdpTable);
712 }
713 }
714 }
715
716 closeTcpFile(tcpFile);
717 tdiFreeThingSet(entitySet);
718 IpUdpTable->dwNumEntries = CurrIdx;
719 return IpUdpTable;
720 }
721
getNumTcpEntries(void)722 DWORD getNumTcpEntries(void)
723 {
724 DWORD numEntities;
725 TDIEntityID *entitySet = NULL;
726 HANDLE tcpFile;
727 int i, totalNumber = 0;
728 NTSTATUS status;
729 PMIB_TCPROW IpTcpTable = NULL;
730 DWORD returnSize;
731
732 TRACE("called.\n");
733
734 status = openTcpFile(&tcpFile, FILE_READ_DATA);
735 if (!NT_SUCCESS(status))
736 {
737 ERR("openTcpFile returned 0x%08lx\n", status);
738 return 0;
739 }
740
741 status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
742
743 for (i = 0; i < numEntities; i++) {
744 if (entitySet[i].tei_entity == CO_TL_ENTITY && hasArp(tcpFile, &entitySet[i]))
745 {
746 status = tdiGetSetOfThings(tcpFile,
747 INFO_CLASS_PROTOCOL,
748 INFO_TYPE_PROVIDER,
749 IP_MIB_ARPTABLE_ENTRY_ID,
750 CO_TL_ENTITY,
751 entitySet[i].tei_instance,
752 0,
753 sizeof(MIB_TCPROW),
754 (PVOID *)&IpTcpTable,
755 &returnSize);
756
757 if (status == STATUS_SUCCESS) totalNumber += returnSize;
758 if (IpTcpTable) {
759 tdiFreeThingSet(IpTcpTable);
760 IpTcpTable = NULL;
761 }
762 }
763 }
764
765 closeTcpFile(tcpFile);
766 if (entitySet) tdiFreeThingSet(entitySet);
767 return totalNumber;
768 }
769
getTcpTable(CLASS_TABLE Class)770 PVOID getTcpTable(CLASS_TABLE Class)
771 {
772 DWORD numEntities, returnSize;
773 TDIEntityID *entitySet;
774 HANDLE tcpFile;
775 int i, totalNumber, TmpIdx, CurrIdx = 0;
776 NTSTATUS status;
777 PMIB_TCPTABLE IpTcpTable = NULL;
778 PVOID AdapterTcpTable = NULL;
779
780 TRACE("called.\n");
781
782 totalNumber = getNumTcpEntries();
783
784 status = openTcpFile(&tcpFile, FILE_READ_DATA);
785 if (!NT_SUCCESS(status))
786 {
787 ERR("openTcpFile returned 0x%08lx\n", status);
788 return 0;
789 }
790
791 IpTcpTable = HeapAlloc(GetProcessHeap(), 0,
792 UdpTcpTableCall[Class].TcpOffset + (UdpTcpTableCall[Class].TcpSize * totalNumber));
793 if (!IpTcpTable) {
794 closeTcpFile(tcpFile);
795 return NULL;
796 }
797
798 status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
799
800 for (i = 0; i < numEntities; i++) {
801 if (entitySet[i].tei_entity == CO_TL_ENTITY && hasArp(tcpFile, &entitySet[i]))
802 {
803 status = tdiGetSetOfThings(tcpFile,
804 INFO_CLASS_PROTOCOL,
805 INFO_TYPE_PROVIDER,
806 UdpTcpTableCall[Class].TOIID,
807 CO_TL_ENTITY,
808 entitySet[i].tei_instance,
809 0,
810 UdpTcpTableCall[Class].TcpSize,
811 &AdapterTcpTable,
812 &returnSize);
813
814 if (status == STATUS_SUCCESS) {
815 for (TmpIdx = 0; TmpIdx < returnSize; TmpIdx++, CurrIdx++)
816 CopyMemory(Add2Ptr(IpTcpTable, UdpTcpTableCall[Class].TcpOffset + UdpTcpTableCall[Class].TcpSize * CurrIdx),
817 Add2Ptr(AdapterTcpTable, UdpTcpTableCall[Class].TcpSize * TmpIdx),
818 UdpTcpTableCall[Class].TcpSize);
819 tdiFreeThingSet(AdapterTcpTable);
820 }
821 }
822 }
823
824 closeTcpFile(tcpFile);
825 tdiFreeThingSet(entitySet);
826 IpTcpTable->dwNumEntries = CurrIdx;
827 return IpTcpTable;
828 }
829