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