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