818f53414e9fc7aca8bcdacf64fceba51cb51095
[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 (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 }