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 60 BOOL isIpEntity( HANDLE tcpFile, TDIEntityID *ent ) { 61 return (ent->tei_entity == CL_NL_ENTITY || 62 ent->tei_entity == CO_NL_ENTITY); 63 } 64 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 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 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 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 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 201 DWORD getInterfaceStatsByIndex(DWORD index, PMIB_IFROW entry) 202 { 203 return ERROR_INVALID_PARAMETER; 204 } 205 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 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 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 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 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 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 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 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 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 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 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 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 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