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