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