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, -t and -v 12 * clean up GetIpHostName 13 * command line parser needs more work 14 */ 15 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <wchar.h> 19 20 #define WIN32_NO_STATUS 21 #include <windef.h> 22 #include <winbase.h> 23 #define _INC_WINDOWS 24 #include <winsock2.h> 25 #include <iphlpapi.h> 26 27 #include <conutils.h> 28 29 #include "netstat.h" 30 #include "resource.h" 31 32 enum ProtoType {IP, TCP, UDP, ICMP} Protocol; 33 DWORD Interval; /* time to pause between printing output */ 34 35 /* TCP endpoint states */ 36 PCWSTR TcpState[] = { 37 L"???", 38 L"CLOSED", 39 L"LISTENING", 40 L"SYN_SENT", 41 L"SYN_RCVD", 42 L"ESTABLISHED", 43 L"FIN_WAIT1", 44 L"FIN_WAIT2", 45 L"CLOSE_WAIT", 46 L"CLOSING", 47 L"LAST_ACK", 48 L"TIME_WAIT", 49 L"DELETE_TCB" 50 }; 51 52 /* 53 * format message string and display output 54 */ 55 VOID DoFormatMessage(DWORD ErrorCode) 56 { 57 if (ErrorCode == ERROR_SUCCESS) 58 return; 59 60 ConMsgPuts(StdErr, FORMAT_MESSAGE_FROM_SYSTEM, 61 NULL, ErrorCode, LANG_USER_DEFAULT); 62 } 63 64 /* 65 * 66 * Parse command line parameters and set any options 67 * 68 */ 69 BOOL ParseCmdline(int argc, wchar_t* argv[]) 70 { 71 LPWSTR Proto; 72 WCHAR c; 73 INT i; 74 75 if ((argc == 1) || (iswdigit(*argv[1]))) 76 bNoOptions = TRUE; 77 78 /* Parse command line for options we have been given. */ 79 for (i = 1; i < argc; i++) 80 { 81 if ((argc > 1) && (argv[i][0] == L'-' || argv[i][0] == L'/')) 82 { 83 while ((c = *++argv[i]) != L'\0') 84 { 85 switch (towlower(c)) 86 { 87 case L'a': 88 bDoShowAllCons = TRUE; 89 break; 90 case L'b': 91 // UNIMPLEMENTED. 92 ConPuts(StdErr, L"'b' option is FIXME (Accepted option though unimplemented feature).\n"); 93 bDoShowProcName = TRUE; 94 break; 95 case L'e': 96 bDoShowEthStats = TRUE; 97 break; 98 case L'n': 99 bDoShowNumbers = TRUE; 100 break; 101 case L'o': 102 bDoShowProcessId = TRUE; 103 break; 104 case L'p': 105 bDoShowProtoCons = TRUE; 106 Proto = argv[i+1]; 107 if (!_wcsicmp(L"IP", Proto)) 108 Protocol = IP; 109 else if (!_wcsicmp(L"ICMP", Proto)) 110 Protocol = ICMP; 111 else if (!_wcsicmp(L"TCP", Proto)) 112 Protocol = TCP; 113 else if (!_wcsicmp(L"UDP", Proto)) 114 Protocol = UDP; 115 else 116 { 117 ConResPuts(StdErr, IDS_USAGE); 118 return FALSE; 119 } 120 break; 121 case L'r': 122 bDoShowRouteTable = TRUE; 123 break; 124 case L's': 125 bDoShowProtoStats = TRUE; 126 break; 127 case L't': 128 // UNIMPLEMENTED. 129 ConPuts(StdErr, L"'t' option is FIXME (Accepted option though unimplemented feature).\n"); 130 break; 131 case L'v': 132 // UNIMPLEMENTED. 133 ConPuts(StdErr, L"'v' option is FIXME (Accepted option though unimplemented feature).\n"); 134 bDoDispSeqComp = TRUE; 135 break; 136 default : 137 ConResPuts(StdErr, IDS_USAGE); 138 return FALSE; 139 } 140 } 141 } 142 else if (iswdigit(*argv[i]) != 0) 143 { 144 if (swscanf(argv[i], L"%lu", &Interval) != EOF) 145 bLoopOutput = TRUE; 146 else 147 return FALSE; 148 } 149 // else 150 // { 151 // ConResPrintf(StdErr, IDS_USAGE); 152 // return FALSE; 153 // } 154 } 155 156 return TRUE; 157 } 158 159 /* 160 * Display table header 161 */ 162 VOID DisplayTableHeader(VOID) 163 { 164 ConResPuts(StdOut, IDS_DISPLAY_THEADER); 165 if (bDoShowProcessId) 166 ConResPuts(StdOut, IDS_DISPLAY_PROCESS); 167 else 168 ConPuts(StdOut, L"\n"); 169 } 170 171 /* 172 * Simulate Microsofts netstat utility output 173 */ 174 BOOL DisplayOutput(VOID) 175 { 176 if (bNoOptions) 177 { 178 ConResPuts(StdOut, IDS_ACTIVE_CONNECT); 179 DisplayTableHeader(); 180 return ShowTcpTable(); 181 } 182 183 if (bDoShowRouteTable) 184 { 185 if (_wsystem(L"route print") == -1) 186 { 187 ConResPuts(StdErr, IDS_ERROR_ROUTE); 188 return FALSE; 189 } 190 return TRUE; 191 } 192 193 if (bDoShowEthStats) 194 { 195 ShowEthernetStatistics(); 196 return TRUE; 197 } 198 199 if (bDoShowProtoCons) 200 { 201 switch (Protocol) 202 { 203 case IP: 204 if (bDoShowProtoStats) 205 ShowIpStatistics(); 206 return TRUE; 207 case ICMP: 208 if (bDoShowProtoStats) 209 ShowIcmpStatistics(); 210 return TRUE; 211 case TCP: 212 if (bDoShowProtoStats) 213 ShowTcpStatistics(); 214 ConResPuts(StdOut, IDS_ACTIVE_CONNECT); 215 DisplayTableHeader(); 216 return ShowTcpTable(); 217 case UDP: 218 if (bDoShowProtoStats) 219 ShowUdpStatistics(); 220 ConResPuts(StdOut, IDS_ACTIVE_CONNECT); 221 DisplayTableHeader(); 222 return (bDoShowAllCons ? ShowUdpTable() : TRUE); 223 default: 224 break; 225 } 226 } 227 else if (bDoShowProtoStats) 228 { 229 ShowIpStatistics(); 230 ShowIcmpStatistics(); 231 ShowTcpStatistics(); 232 ShowUdpStatistics(); 233 return TRUE; 234 } 235 else 236 { 237 ConResPuts(StdOut, IDS_ACTIVE_CONNECT); 238 DisplayTableHeader(); 239 if (ShowTcpTable() && bDoShowAllCons) 240 ShowUdpTable(); 241 } 242 243 return TRUE; 244 } 245 246 VOID ShowIpStatistics(VOID) 247 { 248 PMIB_IPSTATS pIpStats; 249 DWORD dwRetVal; 250 251 pIpStats = (MIB_IPSTATS*) HeapAlloc(GetProcessHeap(), 0, sizeof(MIB_IPSTATS)); 252 253 if ((dwRetVal = GetIpStatistics(pIpStats)) == NO_ERROR) 254 { 255 ConResPuts(StdOut, IDS_IP4_STAT_HEADER); 256 ConResPrintf(StdOut, IDS_IP_PACK_REC, pIpStats->dwInReceives); 257 ConResPrintf(StdOut, IDS_IP_HEAD_REC_ERROR, pIpStats->dwInHdrErrors); 258 ConResPrintf(StdOut, IDS_IP_ADDR_REC_ERROR, pIpStats->dwInAddrErrors); 259 ConResPrintf(StdOut, IDS_IP_DATAG_FWD, pIpStats->dwForwDatagrams); 260 ConResPrintf(StdOut, IDS_IP_UNKNOWN_PRO_REC, pIpStats->dwInUnknownProtos); 261 ConResPrintf(StdOut, IDS_IP_REC_PACK_DISCARD, pIpStats->dwInDiscards); 262 ConResPrintf(StdOut, IDS_IP_REC_PACK_DELIVER, pIpStats->dwInDelivers); 263 ConResPrintf(StdOut, IDS_IP_OUT_REQUEST, pIpStats->dwOutRequests); 264 ConResPrintf(StdOut, IDS_IP_ROUTE_DISCARD, pIpStats->dwRoutingDiscards); 265 ConResPrintf(StdOut, IDS_IP_DISCARD_OUT_PACK, pIpStats->dwOutDiscards); 266 ConResPrintf(StdOut, IDS_IP_OUT_PACKET_NO_ROUTE, pIpStats->dwOutNoRoutes); 267 ConResPrintf(StdOut, IDS_IP_REASSEMBLE_REQUIRED, pIpStats->dwReasmReqds); 268 ConResPrintf(StdOut, IDS_IP_REASSEMBLE_SUCCESS, pIpStats->dwReasmOks); 269 ConResPrintf(StdOut, IDS_IP_REASSEMBLE_FAILURE, pIpStats->dwReasmFails); 270 ConResPrintf(StdOut, IDS_IP_DATAG_FRAG_SUCCESS, pIpStats->dwFragOks); 271 ConResPrintf(StdOut, IDS_IP_DATAG_FRAG_FAILURE, pIpStats->dwFragFails); 272 ConResPrintf(StdOut, IDS_IP_DATAG_FRAG_CREATE, pIpStats->dwFragCreates); 273 } 274 else 275 { 276 DoFormatMessage(dwRetVal); 277 } 278 279 HeapFree(GetProcessHeap(), 0, pIpStats); 280 } 281 282 VOID ShowIcmpStatistics(VOID) 283 { 284 PMIB_ICMP pIcmpStats; 285 DWORD dwRetVal; 286 287 pIcmpStats = (MIB_ICMP*) HeapAlloc(GetProcessHeap(), 0, sizeof(MIB_ICMP)); 288 289 if ((dwRetVal = GetIcmpStatistics(pIcmpStats)) == NO_ERROR) 290 { 291 ConResPuts(StdOut, IDS_ICMP4_STAT_HEADER); 292 ConResPuts(StdOut, IDS_ICMP_THEADER); 293 ConResPrintf(StdOut, IDS_ICMP_MSG, 294 pIcmpStats->stats.icmpInStats.dwMsgs, pIcmpStats->stats.icmpOutStats.dwMsgs); 295 ConResPrintf(StdOut, IDS_ICMP_ERROR, 296 pIcmpStats->stats.icmpInStats.dwErrors, pIcmpStats->stats.icmpOutStats.dwErrors); 297 ConResPrintf(StdOut, IDS_ICMP_DEST_UNREACH, 298 pIcmpStats->stats.icmpInStats.dwDestUnreachs, pIcmpStats->stats.icmpOutStats.dwDestUnreachs); 299 ConResPrintf(StdOut, IDS_ICMP_TIME_EXCEED, 300 pIcmpStats->stats.icmpInStats.dwTimeExcds, pIcmpStats->stats.icmpOutStats.dwTimeExcds); 301 ConResPrintf(StdOut, IDS_ICMP_PARAM_PROBLEM, 302 pIcmpStats->stats.icmpInStats.dwParmProbs, pIcmpStats->stats.icmpOutStats.dwParmProbs); 303 ConResPrintf(StdOut, IDS_ICMP_SRC_QUENCHES, 304 pIcmpStats->stats.icmpInStats.dwSrcQuenchs, pIcmpStats->stats.icmpOutStats.dwSrcQuenchs); 305 ConResPrintf(StdOut, IDS_ICMP_REDIRECT, 306 pIcmpStats->stats.icmpInStats.dwRedirects, pIcmpStats->stats.icmpOutStats.dwRedirects); 307 ConResPrintf(StdOut, IDS_ICMP_ECHO, 308 pIcmpStats->stats.icmpInStats.dwEchos, pIcmpStats->stats.icmpOutStats.dwEchos); 309 ConResPrintf(StdOut, IDS_ICMP_ECHO_REPLY, 310 pIcmpStats->stats.icmpInStats.dwEchoReps, pIcmpStats->stats.icmpOutStats.dwEchoReps); 311 ConResPrintf(StdOut, IDS_ICMP_TIMESTAMP, 312 pIcmpStats->stats.icmpInStats.dwTimestamps, pIcmpStats->stats.icmpOutStats.dwTimestamps); 313 ConResPrintf(StdOut, IDS_ICMP_TIMESTAMP_REPLY, 314 pIcmpStats->stats.icmpInStats.dwTimestampReps, pIcmpStats->stats.icmpOutStats.dwTimestampReps); 315 ConResPrintf(StdOut, IDS_ICMP_ADDRESSS_MASK, 316 pIcmpStats->stats.icmpInStats.dwAddrMasks, pIcmpStats->stats.icmpOutStats.dwAddrMasks); 317 ConResPrintf(StdOut, IDS_ICMP_ADDRESSS_MASK_REPLY, 318 pIcmpStats->stats.icmpInStats.dwAddrMaskReps, pIcmpStats->stats.icmpOutStats.dwAddrMaskReps); 319 } 320 else 321 { 322 DoFormatMessage(dwRetVal); 323 } 324 325 HeapFree(GetProcessHeap(), 0, pIcmpStats); 326 327 } 328 329 VOID ShowTcpStatistics(VOID) 330 { 331 MIB_TCPSTATS tcpStats; 332 DWORD dwRetVal; 333 334 if ((dwRetVal = GetTcpStatistics(&tcpStats)) == NO_ERROR) 335 { 336 ConResPuts(StdOut, IDS_TCP4_HEADER); 337 ConResPrintf(StdOut, IDS_TCP_ACTIVE_OPEN, tcpStats.dwActiveOpens); 338 ConResPrintf(StdOut, IDS_TCP_PASS_OPEN, tcpStats.dwPassiveOpens); 339 ConResPrintf(StdOut, IDS_TCP_FAIL_CONNECT, tcpStats.dwAttemptFails); 340 ConResPrintf(StdOut, IDS_TCP_RESET_CONNECT, tcpStats.dwEstabResets); 341 ConResPrintf(StdOut, IDS_TCP_CURRENT_CONNECT, tcpStats.dwCurrEstab); 342 ConResPrintf(StdOut, IDS_TCP_SEG_RECEIVE, tcpStats.dwInSegs); 343 ConResPrintf(StdOut, IDS_TCP_SEG_SENT, tcpStats.dwOutSegs); 344 ConResPrintf(StdOut, IDS_TCP_SEG_RETRANSMIT, tcpStats.dwRetransSegs); 345 } 346 else 347 { 348 DoFormatMessage(dwRetVal); 349 } 350 } 351 352 VOID ShowUdpStatistics(VOID) 353 { 354 MIB_UDPSTATS udpStats; 355 DWORD dwRetVal; 356 357 if ((dwRetVal = GetUdpStatistics(&udpStats)) == NO_ERROR) 358 { 359 ConResPuts(StdOut, IDS_UDP_IP4_HEADER); 360 ConResPrintf(StdOut, IDS_UDP_DATAG_RECEIVE, udpStats.dwInDatagrams); 361 ConResPrintf(StdOut, IDS_UDP_NO_PORT, udpStats.dwNoPorts); 362 ConResPrintf(StdOut, IDS_UDP_RECEIVE_ERROR, udpStats.dwInErrors); 363 ConResPrintf(StdOut, IDS_UDP_DATAG_SEND, udpStats.dwOutDatagrams); 364 } 365 else 366 { 367 DoFormatMessage(dwRetVal); 368 } 369 } 370 371 VOID ShowEthernetStatistics(VOID) 372 { 373 PMIB_IFTABLE pIfTable; 374 DWORD dwSize = 0; 375 DWORD dwRetVal = 0; 376 377 pIfTable = (MIB_IFTABLE*) HeapAlloc(GetProcessHeap(), 0, sizeof(MIB_IFTABLE)); 378 379 if (GetIfTable(pIfTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) 380 { 381 HeapFree(GetProcessHeap(), 0, pIfTable); 382 pIfTable = (MIB_IFTABLE*) HeapAlloc(GetProcessHeap(), 0, dwSize); 383 384 if ((dwRetVal = GetIfTable(pIfTable, &dwSize, 0)) == NO_ERROR) 385 { 386 ConResPuts(StdOut, IDS_ETHERNET_INTERFACE_STAT); 387 ConResPuts(StdOut, IDS_ETHERNET_THEADER); 388 ConResPrintf(StdOut, IDS_ETHERNET_BYTES, 389 pIfTable->table[0].dwInOctets, pIfTable->table[0].dwOutOctets); 390 ConResPrintf(StdOut, IDS_ETHERNET_UNICAST_PACKET, 391 pIfTable->table[0].dwInUcastPkts, pIfTable->table[0].dwOutUcastPkts); 392 ConResPrintf(StdOut, IDS_ETHERNET_NON_UNICAST_PACKET, 393 pIfTable->table[0].dwInNUcastPkts, pIfTable->table[0].dwOutNUcastPkts); 394 ConResPrintf(StdOut, IDS_ETHERNET_DISCARD, 395 pIfTable->table[0].dwInDiscards, pIfTable->table[0].dwOutDiscards); 396 ConResPrintf(StdOut, IDS_ETHERNET_ERROR, 397 pIfTable->table[0].dwInErrors, pIfTable->table[0].dwOutErrors); 398 ConResPrintf(StdOut, IDS_ETHERNET_UNKNOWN, 399 pIfTable->table[0].dwInUnknownProtos); 400 } 401 else 402 { 403 DoFormatMessage(dwRetVal); 404 } 405 } 406 HeapFree(GetProcessHeap(), 0, pIfTable); 407 } 408 409 BOOL ShowTcpTable(VOID) 410 { 411 PMIB_TCPTABLE_OWNER_PID tcpTable; 412 DWORD error, dwSize; 413 DWORD i; 414 CHAR HostIp[HOSTNAMELEN], HostPort[PORTNAMELEN]; 415 CHAR RemoteIp[HOSTNAMELEN], RemotePort[PORTNAMELEN]; 416 CHAR Host[ADDRESSLEN]; 417 CHAR Remote[ADDRESSLEN]; 418 CHAR PID[64]; 419 420 /* Get the table of TCP endpoints */ 421 dwSize = sizeof (MIB_TCPTABLE_OWNER_PID); 422 /* Should also work when we get new connections between 2 GetTcpTable() 423 * calls: */ 424 do 425 { 426 tcpTable = (PMIB_TCPTABLE_OWNER_PID) HeapAlloc(GetProcessHeap(), 0, dwSize); 427 error = GetExtendedTcpTable(tcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0); 428 if ( error != NO_ERROR ) 429 HeapFree(GetProcessHeap(), 0, tcpTable); 430 } 431 while ( error == ERROR_INSUFFICIENT_BUFFER ); 432 433 if (error != NO_ERROR) 434 { 435 ConResPrintf(StdErr, IDS_ERROR_TCP_SNAPSHOT); 436 DoFormatMessage(error); 437 HeapFree(GetProcessHeap(), 0, tcpTable); 438 return FALSE; 439 } 440 441 /* Dump the TCP table */ 442 for (i = 0; i < tcpTable->dwNumEntries; i++) 443 { 444 /* If we aren't showing all connections, only display established, close wait 445 * and time wait. This is the default output for netstat */ 446 if (bDoShowAllCons || (tcpTable->table[i].dwState == MIB_TCP_STATE_ESTAB) 447 || (tcpTable->table[i].dwState == MIB_TCP_STATE_CLOSE_WAIT) 448 || (tcpTable->table[i].dwState == MIB_TCP_STATE_TIME_WAIT)) 449 { 450 /* I've split this up so it's easier to follow */ 451 GetIpHostName(TRUE, tcpTable->table[i].dwLocalAddr, HostIp, sizeof(HostIp)); 452 GetPortName(tcpTable->table[i].dwLocalPort, "tcp", HostPort, sizeof(HostPort)); 453 sprintf(Host, "%s:%s", HostIp, HostPort); 454 455 if (tcpTable->table[i].dwState == MIB_TCP_STATE_LISTEN) 456 { 457 sprintf(Remote, "%s:0", HostIp); 458 } 459 else 460 { 461 GetIpHostName(FALSE, tcpTable->table[i].dwRemoteAddr, RemoteIp, sizeof(RemoteIp)); 462 GetPortName(tcpTable->table[i].dwRemotePort, "tcp", RemotePort, sizeof(RemotePort)); 463 sprintf(Remote, "%s:%s", RemoteIp, RemotePort); 464 } 465 466 if (bDoShowProcessId) 467 { 468 sprintf(PID, "%ld", tcpTable->table[i].dwOwningPid); 469 } 470 else 471 { 472 PID[0] = 0; 473 } 474 475 ConPrintf(StdOut, L" %-6s %-22S %-22S %-11s %S\n", L"TCP", 476 Host, Remote, TcpState[tcpTable->table[i].dwState], PID); 477 } 478 } 479 480 HeapFree(GetProcessHeap(), 0, tcpTable); 481 return TRUE; 482 } 483 484 BOOL ShowUdpTable(VOID) 485 { 486 PMIB_UDPTABLE_OWNER_PID udpTable; 487 DWORD error, dwSize; 488 DWORD i; 489 CHAR HostIp[HOSTNAMELEN], HostPort[PORTNAMELEN]; 490 CHAR Host[ADDRESSLEN]; 491 CHAR PID[64]; 492 493 /* Get the table of UDP endpoints */ 494 dwSize = 0; 495 error = GetExtendedUdpTable(NULL, &dwSize, TRUE, AF_INET, UDP_TABLE_OWNER_PID, 0); 496 if (error != ERROR_INSUFFICIENT_BUFFER) 497 { 498 ConResPuts(StdErr, IDS_ERROR_UDP_ENDPOINT); 499 DoFormatMessage(error); 500 return FALSE; 501 } 502 udpTable = (PMIB_UDPTABLE_OWNER_PID) HeapAlloc(GetProcessHeap(), 0, dwSize); 503 error = GetExtendedUdpTable(udpTable, &dwSize, TRUE, AF_INET, UDP_TABLE_OWNER_PID, 0); 504 if (error) 505 { 506 ConResPuts(StdErr, IDS_ERROR_UDP_ENDPOINT_TABLE); 507 DoFormatMessage(error); 508 HeapFree(GetProcessHeap(), 0, udpTable); 509 return FALSE; 510 } 511 512 /* Dump the UDP table */ 513 for (i = 0; i < udpTable->dwNumEntries; i++) 514 { 515 516 /* I've split this up so it's easier to follow */ 517 GetIpHostName(TRUE, udpTable->table[i].dwLocalAddr, HostIp, sizeof(HostIp)); 518 GetPortName(udpTable->table[i].dwLocalPort, "udp", HostPort, sizeof(HostPort)); 519 520 sprintf(Host, "%s:%s", HostIp, HostPort); 521 522 if (bDoShowProcessId) 523 { 524 sprintf(PID, "%ld", udpTable->table[i].dwOwningPid); 525 } 526 else 527 { 528 PID[0] = 0; 529 } 530 531 ConPrintf(StdOut, L" %-6s %-22S %-34s %S\n", L"UDP", Host, L"*:*", PID); 532 } 533 534 HeapFree(GetProcessHeap(), 0, udpTable); 535 return TRUE; 536 } 537 538 /* 539 * Translate port numbers into their text equivalent if there is one 540 */ 541 PCHAR 542 GetPortName(UINT Port, PCSTR Proto, CHAR Name[], INT NameLen) 543 { 544 struct servent *pServent; 545 546 if (bDoShowNumbers) 547 { 548 sprintf(Name, "%d", htons((WORD)Port)); 549 return Name; 550 } 551 /* Try to translate to a name */ 552 if ((pServent = getservbyport(Port, Proto))) 553 strcpy(Name, pServent->s_name ); 554 else 555 sprintf(Name, "%d", htons((WORD)Port)); 556 return Name; 557 } 558 559 /* 560 * convert addresses into dotted decimal or hostname 561 */ 562 PCHAR 563 GetIpHostName(BOOL Local, UINT IpAddr, CHAR Name[], INT NameLen) 564 { 565 // struct hostent *phostent; 566 UINT nIpAddr; 567 568 /* display dotted decimal */ 569 nIpAddr = htonl(IpAddr); 570 if (bDoShowNumbers) { 571 sprintf(Name, "%d.%d.%d.%d", 572 (nIpAddr >> 24) & 0xFF, 573 (nIpAddr >> 16) & 0xFF, 574 (nIpAddr >> 8) & 0xFF, 575 (nIpAddr) & 0xFF); 576 return Name; 577 } 578 579 Name[0] = '\0'; 580 581 /* try to resolve the name */ 582 if (!IpAddr) { 583 if (!Local) { 584 sprintf(Name, "%d.%d.%d.%d", 585 (nIpAddr >> 24) & 0xFF, 586 (nIpAddr >> 16) & 0xFF, 587 (nIpAddr >> 8) & 0xFF, 588 (nIpAddr) & 0xFF); 589 } else { 590 if (gethostname(Name, NameLen) != 0) 591 DoFormatMessage(WSAGetLastError()); 592 } 593 } else if (IpAddr == 0x0100007f) { 594 if (Local) { 595 if (gethostname(Name, NameLen) != 0) 596 DoFormatMessage(WSAGetLastError()); 597 } else { 598 strncpy(Name, "localhost", 10); 599 } 600 // } else if (phostent = gethostbyaddr((char*)&ipaddr, sizeof(nipaddr), PF_INET)) { 601 // strcpy(name, phostent->h_name); 602 } else { 603 sprintf(Name, "%d.%d.%d.%d", 604 ((nIpAddr >> 24) & 0x000000FF), 605 ((nIpAddr >> 16) & 0x000000FF), 606 ((nIpAddr >> 8) & 0x000000FF), 607 ((nIpAddr) & 0x000000FF)); 608 } 609 return Name; 610 } 611 612 /* 613 * 614 * Parse command line parameters and set any options 615 * Run display output, looping over set intervals if a number is given 616 * 617 */ 618 int wmain(int argc, wchar_t *argv[]) 619 { 620 BOOL Success; 621 WSADATA wsaData; 622 623 /* Initialize the Console Standard Streams */ 624 ConInitStdStreams(); 625 626 if (!ParseCmdline(argc, argv)) 627 return EXIT_FAILURE; 628 629 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) 630 { 631 ConResPrintf(StdErr, IDS_ERROR_WSA_START, WSAGetLastError()); 632 return EXIT_FAILURE; 633 } 634 635 Success = DisplayOutput(); 636 while (bLoopOutput && Success) 637 { 638 Sleep(Interval*1000); 639 Success = DisplayOutput(); 640 } 641 642 WSACleanup(); 643 return (Success ? EXIT_SUCCESS : EXIT_FAILURE); 644 } 645