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