1 /* 2 * PROJECT: ReactOS netstat utility 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: base/applications/network/netstat/netstat.c 5 * PURPOSE: display IP stack statistics 6 * COPYRIGHT: Copyright 2005 Ged Murphy <gedmurphy@gmail.com> 7 */ 8 /* 9 * TODO: 10 * sort function return values. 11 * implement -b, -o and -v 12 * clean up GetIpHostName 13 * command line parser needs more work 14 */ 15 16 #define WIN32_NO_STATUS 17 #include <stdarg.h> 18 #include <windef.h> 19 #include <winbase.h> 20 #define _INC_WINDOWS 21 #include <winsock2.h> 22 #include <tchar.h> 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <iphlpapi.h> 26 27 #include "netstat.h" 28 29 enum ProtoType {IP, TCP, UDP, ICMP} Protocol; 30 DWORD Interval; /* time to pause between printing output */ 31 32 /* TCP endpoint states */ 33 TCHAR TcpState[][32] = { 34 _T("???"), 35 _T("CLOSED"), 36 _T("LISTENING"), 37 _T("SYN_SENT"), 38 _T("SYN_RCVD"), 39 _T("ESTABLISHED"), 40 _T("FIN_WAIT1"), 41 _T("FIN_WAIT2"), 42 _T("CLOSE_WAIT"), 43 _T("CLOSING"), 44 _T("LAST_ACK"), 45 _T("TIME_WAIT"), 46 _T("DELETE_TCB") 47 }; 48 49 /* 50 * format message string and display output 51 */ 52 DWORD DoFormatMessage(DWORD ErrorCode) 53 { 54 LPVOID lpMsgBuf; 55 DWORD RetVal; 56 57 if ((RetVal = FormatMessage( 58 FORMAT_MESSAGE_ALLOCATE_BUFFER | 59 FORMAT_MESSAGE_FROM_SYSTEM | 60 FORMAT_MESSAGE_IGNORE_INSERTS, 61 NULL, 62 ErrorCode, 63 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ 64 (LPTSTR) &lpMsgBuf, 65 0, 66 NULL ))) 67 { 68 _tprintf(_T("%s"), (LPTSTR)lpMsgBuf); 69 70 LocalFree(lpMsgBuf); 71 /* return number of TCHAR's stored in output buffer 72 * excluding '\0' - as FormatMessage does*/ 73 return RetVal; 74 } 75 else 76 return 0; 77 } 78 79 /* 80 * 81 * Parse command line parameters and set any options 82 * 83 */ 84 BOOL ParseCmdline(int argc, char* argv[]) 85 { 86 LPSTR Proto; 87 CHAR c; 88 INT i; 89 90 if ((argc == 1) || (_istdigit(*argv[1]))) 91 bNoOptions = TRUE; 92 93 /* Parse command line for options we have been given. */ 94 for (i = 1; i < argc; i++) 95 { 96 if ((argc > 1) && (argv[i][0] == '-' || argv[i][0] == '/')) 97 { 98 while ((c = *++argv[i]) != '\0') 99 { 100 switch (tolower(c)) 101 { 102 case 'a' : 103 bDoShowAllCons = TRUE; 104 break; 105 case 'b' : 106 bDoShowProcName = TRUE; 107 break; 108 case 'e' : 109 bDoShowEthStats = TRUE; 110 break; 111 case 'n' : 112 bDoShowNumbers = TRUE; 113 break; 114 case 'p' : 115 bDoShowProtoCons = TRUE; 116 Proto = argv[i+1]; 117 if (!_stricmp("IP", Proto)) 118 Protocol = IP; 119 else if (!_stricmp("ICMP", Proto)) 120 Protocol = ICMP; 121 else if (!_stricmp("TCP", Proto)) 122 Protocol = TCP; 123 else if (!_stricmp("UDP", Proto)) 124 Protocol = UDP; 125 else 126 { 127 Usage(); 128 return EXIT_FAILURE; 129 } 130 break; 131 case 'r' : 132 bDoShowRouteTable = TRUE; 133 break; 134 case 's' : 135 bDoShowProtoStats = TRUE; 136 break; 137 case 'o' : 138 bDoShowProcessId = TRUE; 139 break; 140 case 'v' : 141 _tprintf(_T("got v\n")); 142 bDoDispSeqComp = TRUE; 143 break; 144 default : 145 Usage(); 146 return EXIT_FAILURE; 147 } 148 } 149 } 150 else if (_istdigit(*argv[i])) 151 { 152 if (_stscanf(argv[i], "%lu", &Interval) != EOF) 153 bLoopOutput = TRUE; 154 else 155 return EXIT_FAILURE; 156 } 157 // else 158 // { 159 // Usage(); 160 // EXIT_FAILURE; 161 // } 162 } 163 164 return EXIT_SUCCESS; 165 } 166 167 /* 168 * Display table header 169 */ 170 VOID DisplayTableHeader() 171 { 172 _tprintf(_T("\n Proto Local Address Foreign Address State")); 173 if (bDoShowProcessId) 174 _tprintf(_T(" Process\n")); 175 else 176 _tprintf(_T("\n")); 177 } 178 179 180 /* 181 * Simulate Microsofts netstat utility output 182 */ 183 BOOL DisplayOutput() 184 { 185 if (bNoOptions) 186 { 187 DisplayTableHeader(); 188 ShowTcpTable(); 189 return EXIT_SUCCESS; 190 } 191 192 if (bDoShowRouteTable) 193 { 194 /* mingw doesn't have lib for _tsystem */ 195 if (system("route print") == -1) 196 { 197 _tprintf(_T("cannot find 'route.exe'\n")); 198 return EXIT_FAILURE; 199 } 200 return EXIT_SUCCESS; 201 } 202 203 if (bDoShowEthStats) 204 { 205 ShowEthernetStatistics(); 206 return EXIT_SUCCESS; 207 } 208 209 if (bDoShowProtoCons) 210 { 211 switch (Protocol) 212 { 213 case IP : 214 if (bDoShowProtoStats) 215 { 216 ShowIpStatistics(); 217 return EXIT_SUCCESS; 218 } 219 break; 220 case ICMP : 221 if (bDoShowProtoStats) 222 { 223 ShowIcmpStatistics(); 224 return EXIT_SUCCESS; 225 } 226 break; 227 case TCP : 228 if (bDoShowProtoStats) 229 ShowTcpStatistics(); 230 _tprintf(_T("\nActive Connections\n")); 231 DisplayTableHeader(); 232 ShowTcpTable(); 233 break; 234 case UDP : 235 if (bDoShowProtoStats) 236 ShowUdpStatistics(); 237 _tprintf(_T("\nActive Connections\n")); 238 DisplayTableHeader(); 239 ShowUdpTable(); 240 break; 241 default : 242 break; 243 } 244 } 245 else if (bDoShowProtoStats) 246 { 247 ShowIpStatistics(); 248 ShowIcmpStatistics(); 249 ShowTcpStatistics(); 250 ShowUdpStatistics(); 251 return EXIT_SUCCESS; 252 } 253 else 254 { 255 _tprintf(_T("\nActive Connections\n")); 256 DisplayTableHeader(); 257 ShowTcpTable(); 258 if (bDoShowAllCons) 259 ShowUdpTable(); 260 } 261 return EXIT_SUCCESS; 262 } 263 264 VOID ShowIpStatistics() 265 { 266 PMIB_IPSTATS pIpStats; 267 DWORD dwRetVal; 268 269 pIpStats = (MIB_IPSTATS*) HeapAlloc(GetProcessHeap(), 0, sizeof(MIB_IPSTATS)); 270 271 if ((dwRetVal = GetIpStatistics(pIpStats)) == NO_ERROR) 272 { 273 _tprintf(_T("\nIPv4 Statistics\n\n")); 274 _tprintf(_T(" %-34s = %lu\n"), _T("Packets Received"), pIpStats->dwInReceives); 275 _tprintf(_T(" %-34s = %lu\n"), _T("Received Header Errors"), pIpStats->dwInHdrErrors); 276 _tprintf(_T(" %-34s = %lu\n"), _T("Received Address Errors"), pIpStats->dwInAddrErrors); 277 _tprintf(_T(" %-34s = %lu\n"), _T("Datagrams Forwarded"), pIpStats->dwForwDatagrams); 278 _tprintf(_T(" %-34s = %lu\n"), _T("Unknown Protocols Received"), pIpStats->dwInUnknownProtos); 279 _tprintf(_T(" %-34s = %lu\n"), _T("Received Packets Discarded"), pIpStats->dwInDiscards); 280 _tprintf(_T(" %-34s = %lu\n"), _T("Received Packets Delivered"), pIpStats->dwInDelivers); 281 _tprintf(_T(" %-34s = %lu\n"), _T("Output Requests"), pIpStats->dwOutRequests); 282 _tprintf(_T(" %-34s = %lu\n"), _T("Routing Discards"), pIpStats->dwRoutingDiscards); 283 _tprintf(_T(" %-34s = %lu\n"), _T("Discarded Output Packets"), pIpStats->dwOutDiscards); 284 _tprintf(_T(" %-34s = %lu\n"), _T("Output Packets No Route"), pIpStats->dwOutNoRoutes); 285 _tprintf(_T(" %-34s = %lu\n"), _T("Reassembly Required"), pIpStats->dwReasmReqds); 286 _tprintf(_T(" %-34s = %lu\n"), _T("Reassembly Succesful"), pIpStats->dwReasmOks); 287 _tprintf(_T(" %-34s = %lu\n"), _T("Reassembly Failures"), pIpStats->dwReasmFails); 288 // _tprintf(_T(" %-34s = %lu\n"), _T("Datagrams successfully fragmented"), NULL); /* FIXME: what is this one? */ 289 _tprintf(_T(" %-34s = %lu\n"), _T("Datagrams Failing Fragmentation"), pIpStats->dwFragFails); 290 _tprintf(_T(" %-34s = %lu\n"), _T("Fragments Created"), pIpStats->dwFragCreates); 291 } 292 else 293 DoFormatMessage(dwRetVal); 294 295 HeapFree(GetProcessHeap(), 0, pIpStats); 296 } 297 298 VOID ShowIcmpStatistics() 299 { 300 PMIB_ICMP pIcmpStats; 301 DWORD dwRetVal; 302 303 pIcmpStats = (MIB_ICMP*) HeapAlloc(GetProcessHeap(), 0, sizeof(MIB_ICMP)); 304 305 if ((dwRetVal = GetIcmpStatistics(pIcmpStats)) == NO_ERROR) 306 { 307 _tprintf(_T("\nICMPv4 Statistics\n\n")); 308 _tprintf(_T(" Received Sent\n")); 309 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Messages"), 310 pIcmpStats->stats.icmpInStats.dwMsgs, pIcmpStats->stats.icmpOutStats.dwMsgs); 311 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Errors"), 312 pIcmpStats->stats.icmpInStats.dwErrors, pIcmpStats->stats.icmpOutStats.dwErrors); 313 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Destination Unreachable"), 314 pIcmpStats->stats.icmpInStats.dwDestUnreachs, pIcmpStats->stats.icmpOutStats.dwDestUnreachs); 315 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Time Exceeded"), 316 pIcmpStats->stats.icmpInStats.dwTimeExcds, pIcmpStats->stats.icmpOutStats.dwTimeExcds); 317 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Parameter Problems"), 318 pIcmpStats->stats.icmpInStats.dwParmProbs, pIcmpStats->stats.icmpOutStats.dwParmProbs); 319 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Source Quenches"), 320 pIcmpStats->stats.icmpInStats.dwSrcQuenchs, pIcmpStats->stats.icmpOutStats.dwSrcQuenchs); 321 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Redirects"), 322 pIcmpStats->stats.icmpInStats.dwRedirects, pIcmpStats->stats.icmpOutStats.dwRedirects); 323 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Echos"), 324 pIcmpStats->stats.icmpInStats.dwEchos, pIcmpStats->stats.icmpOutStats.dwEchos); 325 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Echo Replies"), 326 pIcmpStats->stats.icmpInStats.dwEchoReps, pIcmpStats->stats.icmpOutStats.dwEchoReps); 327 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Timestamps"), 328 pIcmpStats->stats.icmpInStats.dwTimestamps, pIcmpStats->stats.icmpOutStats.dwTimestamps); 329 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Timestamp Replies"), 330 pIcmpStats->stats.icmpInStats.dwTimestampReps, pIcmpStats->stats.icmpOutStats.dwTimestampReps); 331 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Address Masks"), 332 pIcmpStats->stats.icmpInStats.dwAddrMasks, pIcmpStats->stats.icmpOutStats.dwAddrMasks); 333 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Address Mask Replies"), 334 pIcmpStats->stats.icmpInStats.dwAddrMaskReps, pIcmpStats->stats.icmpOutStats.dwAddrMaskReps); 335 } 336 else 337 DoFormatMessage(dwRetVal); 338 339 HeapFree(GetProcessHeap(), 0, pIcmpStats); 340 341 } 342 343 VOID ShowTcpStatistics() 344 { 345 PMIB_TCPSTATS pTcpStats; 346 DWORD dwRetVal; 347 348 pTcpStats = (MIB_TCPSTATS*) HeapAlloc(GetProcessHeap(), 0, sizeof(MIB_TCPSTATS)); 349 350 if ((dwRetVal = GetTcpStatistics(pTcpStats)) == NO_ERROR) 351 { 352 _tprintf(_T("\nTCP Statistics for IPv4\n\n")); 353 _tprintf(_T(" %-35s = %lu\n"), _T("Active Opens"), pTcpStats->dwActiveOpens); 354 _tprintf(_T(" %-35s = %lu\n"), _T("Passive Opens"), pTcpStats->dwPassiveOpens); 355 _tprintf(_T(" %-35s = %lu\n"), _T("Failed Connection Attempts"), pTcpStats->dwAttemptFails); 356 _tprintf(_T(" %-35s = %lu\n"), _T("Reset Connections"), pTcpStats->dwEstabResets); 357 _tprintf(_T(" %-35s = %lu\n"), _T("Current Connections"), pTcpStats->dwCurrEstab); 358 _tprintf(_T(" %-35s = %lu\n"), _T("Segments Received"), pTcpStats->dwInSegs); 359 _tprintf(_T(" %-35s = %lu\n"), _T("Segments Sent"), pTcpStats->dwOutSegs); 360 _tprintf(_T(" %-35s = %lu\n"), _T("Segments Retransmitted"), pTcpStats->dwRetransSegs); 361 } 362 else 363 DoFormatMessage(dwRetVal); 364 365 HeapFree(GetProcessHeap(), 0, pTcpStats); 366 } 367 368 VOID ShowUdpStatistics() 369 { 370 PMIB_UDPSTATS pUdpStats; 371 DWORD dwRetVal; 372 373 pUdpStats = (MIB_UDPSTATS*) HeapAlloc(GetProcessHeap(), 0, sizeof(MIB_UDPSTATS)); 374 375 if ((dwRetVal = GetUdpStatistics(pUdpStats)) == NO_ERROR) 376 { 377 _tprintf(_T("\nUDP Statistics for IPv4\n\n")); 378 _tprintf(_T(" %-21s = %lu\n"), _T("Datagrams Received"), pUdpStats->dwInDatagrams); 379 _tprintf(_T(" %-21s = %lu\n"), _T("No Ports"), pUdpStats->dwNoPorts); 380 _tprintf(_T(" %-21s = %lu\n"), _T("Receive Errors"), pUdpStats->dwInErrors); 381 _tprintf(_T(" %-21s = %lu\n"), _T("Datagrams Sent"), pUdpStats->dwOutDatagrams); 382 } 383 else 384 DoFormatMessage(dwRetVal); 385 386 HeapFree(GetProcessHeap(), 0, pUdpStats); 387 } 388 389 VOID ShowEthernetStatistics() 390 { 391 PMIB_IFTABLE pIfTable; 392 DWORD dwSize = 0; 393 DWORD dwRetVal = 0; 394 395 pIfTable = (MIB_IFTABLE*) HeapAlloc(GetProcessHeap(), 0, sizeof(MIB_IFTABLE)); 396 397 if (GetIfTable(pIfTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) 398 { 399 HeapFree(GetProcessHeap(), 0, pIfTable); 400 pIfTable = (MIB_IFTABLE*) HeapAlloc(GetProcessHeap(), 0, dwSize); 401 402 if ((dwRetVal = GetIfTable(pIfTable, &dwSize, 0)) == NO_ERROR) 403 { 404 _tprintf(_T("Interface Statistics\n\n")); 405 _tprintf(_T(" Received Sent\n\n")); 406 _tprintf(_T("%-20s %14lu %15lu\n"), _T("Bytes"), 407 pIfTable->table[0].dwInOctets, pIfTable->table[0].dwOutOctets); 408 _tprintf(_T("%-20s %14lu %15lu\n"), _T("Unicast packets"), 409 pIfTable->table[0].dwInUcastPkts, pIfTable->table[0].dwOutUcastPkts); 410 _tprintf(_T("%-20s %14lu %15lu\n"), _T("Non-unicast packets"), 411 pIfTable->table[0].dwInNUcastPkts, pIfTable->table[0].dwOutNUcastPkts); 412 _tprintf(_T("%-20s %14lu %15lu\n"), _T("Discards"), 413 pIfTable->table[0].dwInDiscards, pIfTable->table[0].dwOutDiscards); 414 _tprintf(_T("%-20s %14lu %15lu\n"), _T("Errors"), 415 pIfTable->table[0].dwInErrors, pIfTable->table[0].dwOutErrors); 416 _tprintf(_T("%-20s %14lu\n"), _T("Unknown Protocols"), 417 pIfTable->table[0].dwInUnknownProtos); 418 } 419 else 420 DoFormatMessage(dwRetVal); 421 } 422 HeapFree(GetProcessHeap(), 0, pIfTable); 423 } 424 425 VOID ShowTcpTable() 426 { 427 PMIB_TCPTABLE_OWNER_PID tcpTable; 428 DWORD error, dwSize; 429 DWORD i; 430 CHAR HostIp[HOSTNAMELEN], HostPort[PORTNAMELEN]; 431 CHAR RemoteIp[HOSTNAMELEN], RemotePort[PORTNAMELEN]; 432 CHAR Host[ADDRESSLEN]; 433 CHAR Remote[ADDRESSLEN]; 434 CHAR PID[64]; 435 436 /* Get the table of TCP endpoints */ 437 dwSize = sizeof (MIB_TCPTABLE_OWNER_PID); 438 /* Should also work when we get new connections between 2 GetTcpTable() 439 * calls: */ 440 do 441 { 442 tcpTable = (PMIB_TCPTABLE_OWNER_PID) HeapAlloc(GetProcessHeap(), 0, dwSize); 443 error = GetExtendedTcpTable(tcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0); 444 if ( error != NO_ERROR ) 445 HeapFree(GetProcessHeap(), 0, tcpTable); 446 } 447 while ( error == ERROR_INSUFFICIENT_BUFFER ); 448 449 if (error != NO_ERROR) 450 { 451 printf("Failed to snapshot TCP endpoints.\n"); 452 DoFormatMessage(error); 453 exit(EXIT_FAILURE); 454 } 455 456 /* Dump the TCP table */ 457 for (i = 0; i < tcpTable->dwNumEntries; i++) 458 { 459 /* If we aren't showing all connections, only display established, close wait 460 * and time wait. This is the default output for netstat */ 461 if (bDoShowAllCons || (tcpTable->table[i].dwState == MIB_TCP_STATE_ESTAB) 462 || (tcpTable->table[i].dwState == MIB_TCP_STATE_CLOSE_WAIT) 463 || (tcpTable->table[i].dwState == MIB_TCP_STATE_TIME_WAIT)) 464 { 465 /* I've split this up so it's easier to follow */ 466 GetIpHostName(TRUE, tcpTable->table[i].dwLocalAddr, HostIp, HOSTNAMELEN); 467 GetPortName(tcpTable->table[i].dwLocalPort, "tcp", HostPort, PORTNAMELEN); 468 sprintf(Host, "%s:%s", HostIp, HostPort); 469 470 if (tcpTable->table[i].dwState == MIB_TCP_STATE_LISTEN) 471 { 472 sprintf(Remote, "%s:0", HostIp); 473 } 474 else 475 { 476 GetIpHostName(FALSE, tcpTable->table[i].dwRemoteAddr, RemoteIp, HOSTNAMELEN); 477 GetPortName(tcpTable->table[i].dwRemotePort, "tcp", RemotePort, PORTNAMELEN); 478 sprintf(Remote, "%s:%s", RemoteIp, RemotePort); 479 } 480 481 if (bDoShowProcessId) 482 { 483 sprintf(PID, "%ld", tcpTable->table[i].dwOwningPid); 484 } 485 else 486 { 487 PID[0] = 0; 488 } 489 490 _tprintf(_T(" %-6s %-22s %-22s %-11s %s\n"), _T("TCP"), 491 Host, Remote, TcpState[tcpTable->table[i].dwState], PID); 492 } 493 } 494 HeapFree(GetProcessHeap(), 0, tcpTable); 495 } 496 497 VOID ShowUdpTable() 498 { 499 PMIB_UDPTABLE_OWNER_PID udpTable; 500 DWORD error, dwSize; 501 DWORD i; 502 CHAR HostIp[HOSTNAMELEN], HostPort[PORTNAMELEN]; 503 CHAR Host[ADDRESSLEN]; 504 CHAR PID[64]; 505 506 /* Get the table of UDP endpoints */ 507 dwSize = 0; 508 error = GetExtendedUdpTable(NULL, &dwSize, TRUE, AF_INET, UDP_TABLE_OWNER_PID, 0); 509 if (error != ERROR_INSUFFICIENT_BUFFER) 510 { 511 printf("Failed to snapshot UDP endpoints.\n"); 512 DoFormatMessage(error); 513 exit(EXIT_FAILURE); 514 } 515 udpTable = (PMIB_UDPTABLE_OWNER_PID) HeapAlloc(GetProcessHeap(), 0, dwSize); 516 error = GetExtendedUdpTable(udpTable, &dwSize, TRUE, AF_INET, UDP_TABLE_OWNER_PID, 0); 517 if (error) 518 { 519 printf("Failed to snapshot UDP endpoints table.\n"); 520 DoFormatMessage(error); 521 HeapFree(GetProcessHeap(), 0, udpTable); 522 exit(EXIT_FAILURE); 523 } 524 525 /* Dump the UDP table */ 526 for (i = 0; i < udpTable->dwNumEntries; i++) 527 { 528 529 /* I've split this up so it's easier to follow */ 530 GetIpHostName(TRUE, udpTable->table[i].dwLocalAddr, HostIp, HOSTNAMELEN); 531 GetPortName(udpTable->table[i].dwLocalPort, "tcp", HostPort, PORTNAMELEN); 532 533 sprintf(Host, "%s:%s", HostIp, HostPort); 534 535 if (bDoShowProcessId) 536 { 537 sprintf(PID, "%ld", udpTable->table[i].dwOwningPid); 538 } 539 else 540 { 541 PID[0] = 0; 542 } 543 544 _tprintf(_T(" %-6s %-22s %-34s %s\n"), _T("UDP"), Host, _T("*:*"), PID); 545 } 546 547 HeapFree(GetProcessHeap(), 0, udpTable); 548 } 549 550 /* 551 * Translate port numbers into their text equivalent if there is one 552 */ 553 PCHAR 554 GetPortName(UINT Port, PCSTR Proto, CHAR Name[], INT NameLen) 555 { 556 struct servent *pServent; 557 558 if (bDoShowNumbers) 559 { 560 sprintf(Name, "%d", htons((WORD)Port)); 561 return Name; 562 } 563 /* Try to translate to a name */ 564 if ((pServent = getservbyport(Port, Proto))) 565 strcpy(Name, pServent->s_name ); 566 else 567 sprintf(Name, "%d", htons((WORD)Port)); 568 return Name; 569 } 570 571 /* 572 * convert addresses into dotted decimal or hostname 573 */ 574 PCHAR 575 GetIpHostName(BOOL Local, UINT IpAddr, CHAR Name[], int NameLen) 576 { 577 // struct hostent *phostent; 578 UINT nIpAddr; 579 580 /* display dotted decimal */ 581 nIpAddr = htonl(IpAddr); 582 if (bDoShowNumbers) { 583 sprintf(Name, "%d.%d.%d.%d", 584 (nIpAddr >> 24) & 0xFF, 585 (nIpAddr >> 16) & 0xFF, 586 (nIpAddr >> 8) & 0xFF, 587 (nIpAddr) & 0xFF); 588 return Name; 589 } 590 591 Name[0] = _T('\0'); 592 593 /* try to resolve the name */ 594 if (!IpAddr) { 595 if (!Local) { 596 sprintf(Name, "%d.%d.%d.%d", 597 (nIpAddr >> 24) & 0xFF, 598 (nIpAddr >> 16) & 0xFF, 599 (nIpAddr >> 8) & 0xFF, 600 (nIpAddr) & 0xFF); 601 } else { 602 if (gethostname(Name, NameLen) != 0) 603 DoFormatMessage(WSAGetLastError()); 604 } 605 } else if (IpAddr == 0x0100007f) { 606 if (Local) { 607 if (gethostname(Name, NameLen) != 0) 608 DoFormatMessage(WSAGetLastError()); 609 } else { 610 _tcsncpy(Name, _T("localhost"), 10); 611 } 612 // } else if (phostent = gethostbyaddr((char*)&ipaddr, sizeof(nipaddr), PF_INET)) { 613 // strcpy(name, phostent->h_name); 614 } else { 615 sprintf(Name, "%d.%d.%d.%d", 616 ((nIpAddr >> 24) & 0x000000FF), 617 ((nIpAddr >> 16) & 0x000000FF), 618 ((nIpAddr >> 8) & 0x000000FF), 619 ((nIpAddr) & 0x000000FF)); 620 } 621 return Name; 622 } 623 624 VOID Usage() 625 { 626 _tprintf(_T("\nDisplays current TCP/IP protocol statistics and network connections.\n\n" 627 "NETSTAT [-a] [-e] [-n] [-p proto] [-r] [-s] [interval]\n\n" 628 " -a Displays all connections and listening ports.\n" 629 " -e Displays Ethernet statistics. May be combined with -s\n" 630 " option\n" 631 " -n Displays address and port numbers in numeric form.\n" 632 " -p proto Shows connections for protocol 'proto' TCP or UDP.\n" 633 " If used with the -s option to display\n" 634 " per-protocol statistics, 'proto' may be TCP, UDP, or IP.\n" 635 " -r Displays the current routing table.\n" 636 " -s Displays per-protocol statistics. By default, Statistics are\n" 637 " shown for IP, ICMP, TCP and UDP;\n" 638 " the -p option may be used to specify a subset of the default.\n" 639 " -o Displays the process ID for each connection.\n" 640 " interval Redisplays selected statistics every 'interval' seconds.\n" 641 " Press CTRL+C to stop redisplaying. By default netstat will\n" 642 " print the current information only once.\n")); 643 } 644 645 /* 646 * 647 * Parse command line parameters and set any options 648 * Run display output, looping over set intervals if a number is given 649 * 650 */ 651 int main(int argc, char *argv[]) 652 { 653 WSADATA wsaData; 654 655 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) 656 { 657 _tprintf(_T("WSAStartup() failed : %d\n"), WSAGetLastError()); 658 return -1; 659 } 660 661 if (ParseCmdline(argc, argv)) 662 return -1; 663 664 if (bLoopOutput) 665 { 666 while (1) 667 { 668 if (DisplayOutput()) 669 return -1; 670 Sleep(Interval*1000); 671 } 672 } 673 674 if (DisplayOutput()) 675 return -1; 676 else 677 return 0; 678 } 679