296e6dfe3f053253227c1e534709c9882010539e
[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 <tchar.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <iphlpapi.h>
26
27 #include "netstat.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 TCHAR TcpState[][32] = {
34 _T("???"),
35 _T("CLOSED"),
36 _T("LISTENING"),
37 _T("SYN_SENT"),
38 _T("SYN_RCVD"),
39 _T("ESTABLISHED"),
40 _T("FIN_WAIT1"),
41 _T("FIN_WAIT2"),
42 _T("CLOSE_WAIT"),
43 _T("CLOSING"),
44 _T("LAST_ACK"),
45 _T("TIME_WAIT"),
46 _T("DELETE_TCB")
47 };
48
49 /*
50 * format message string and display output
51 */
52 DWORD DoFormatMessage(DWORD ErrorCode)
53 {
54 LPVOID lpMsgBuf;
55 DWORD RetVal;
56
57 if ((RetVal = FormatMessage(
58 FORMAT_MESSAGE_ALLOCATE_BUFFER |
59 FORMAT_MESSAGE_FROM_SYSTEM |
60 FORMAT_MESSAGE_IGNORE_INSERTS,
61 NULL,
62 ErrorCode,
63 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
64 (LPTSTR) &lpMsgBuf,
65 0,
66 NULL )))
67 {
68 _tprintf(_T("%s"), (LPTSTR)lpMsgBuf);
69
70 LocalFree(lpMsgBuf);
71 /* return number of TCHAR's stored in output buffer
72 * excluding '\0' - as FormatMessage does*/
73 return RetVal;
74 }
75 else
76 return 0;
77 }
78
79 /*
80 *
81 * Parse command line parameters and set any options
82 *
83 */
84 BOOL ParseCmdline(int argc, char* argv[])
85 {
86 LPSTR Proto;
87 CHAR c;
88 INT i;
89
90 if ((argc == 1) || (_istdigit(*argv[1])))
91 bNoOptions = TRUE;
92
93 /* Parse command line for options we have been given. */
94 for (i = 1; i < argc; i++)
95 {
96 if ((argc > 1) && (argv[i][0] == '-' || argv[i][0] == '/'))
97 {
98 while ((c = *++argv[i]) != '\0')
99 {
100 switch (tolower(c))
101 {
102 case 'a' :
103 bDoShowAllCons = TRUE;
104 break;
105 case 'b' :
106 bDoShowProcName = TRUE;
107 break;
108 case 'e' :
109 bDoShowEthStats = TRUE;
110 break;
111 case 'n' :
112 bDoShowNumbers = TRUE;
113 break;
114 case 'p' :
115 bDoShowProtoCons = TRUE;
116 Proto = argv[i+1];
117 if (!_stricmp("IP", Proto))
118 Protocol = IP;
119 else if (!_stricmp("ICMP", Proto))
120 Protocol = ICMP;
121 else if (!_stricmp("TCP", Proto))
122 Protocol = TCP;
123 else if (!_stricmp("UDP", Proto))
124 Protocol = UDP;
125 else
126 {
127 Usage();
128 return EXIT_FAILURE;
129 }
130 break;
131 case 'r' :
132 bDoShowRouteTable = TRUE;
133 break;
134 case 's' :
135 bDoShowProtoStats = TRUE;
136 break;
137 case 'v' :
138 _tprintf(_T("got v\n"));
139 bDoDispSeqComp = TRUE;
140 break;
141 default :
142 Usage();
143 return EXIT_FAILURE;
144 }
145 }
146 }
147 else if (_istdigit(*argv[i]))
148 {
149 if (_stscanf(argv[i], "%lu", &Interval) != EOF)
150 bLoopOutput = TRUE;
151 else
152 return EXIT_FAILURE;
153 }
154 // else
155 // {
156 // Usage();
157 // EXIT_FAILURE;
158 // }
159 }
160
161 return EXIT_SUCCESS;
162 }
163
164 /*
165 * Simulate Microsofts netstat utility output
166 */
167 BOOL DisplayOutput()
168 {
169 if (bNoOptions)
170 {
171 _tprintf(_T("\n Proto Local Address Foreign Address State\n"));
172 ShowTcpTable();
173 return EXIT_SUCCESS;
174 }
175
176 if (bDoShowRouteTable)
177 {
178 /* mingw doesn't have lib for _tsystem */
179 if (system("route print") == -1)
180 {
181 _tprintf(_T("cannot find 'route.exe'\n"));
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 _tprintf(_T("\nActive Connections\n"));
215 _tprintf(_T("\n Proto Local Address Foreign Address State\n"));
216 ShowTcpTable();
217 break;
218 case UDP :
219 if (bDoShowProtoStats)
220 ShowUdpStatistics();
221 _tprintf(_T("\nActive Connections\n"));
222 _tprintf(_T("\n Proto Local Address Foreign Address State\n"));
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 _tprintf(_T("\nActive Connections\n"));
240 _tprintf(_T("\n Proto Local Address Foreign Address State\n"));
241 ShowTcpTable();
242 if (bDoShowAllCons)
243 ShowUdpTable();
244 }
245 return EXIT_SUCCESS;
246 }
247
248 VOID ShowIpStatistics()
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 _tprintf(_T("\nIPv4 Statistics\n\n"));
258 _tprintf(_T(" %-34s = %lu\n"), _T("Packets Received"), pIpStats->dwInReceives);
259 _tprintf(_T(" %-34s = %lu\n"), _T("Received Header Errors"), pIpStats->dwInHdrErrors);
260 _tprintf(_T(" %-34s = %lu\n"), _T("Received Address Errors"), pIpStats->dwInAddrErrors);
261 _tprintf(_T(" %-34s = %lu\n"), _T("Datagrams Forwarded"), pIpStats->dwForwDatagrams);
262 _tprintf(_T(" %-34s = %lu\n"), _T("Unknown Protocols Received"), pIpStats->dwInUnknownProtos);
263 _tprintf(_T(" %-34s = %lu\n"), _T("Received Packets Discarded"), pIpStats->dwInDiscards);
264 _tprintf(_T(" %-34s = %lu\n"), _T("Received Packets Delivered"), pIpStats->dwInDelivers);
265 _tprintf(_T(" %-34s = %lu\n"), _T("Output Requests"), pIpStats->dwOutRequests);
266 _tprintf(_T(" %-34s = %lu\n"), _T("Routing Discards"), pIpStats->dwRoutingDiscards);
267 _tprintf(_T(" %-34s = %lu\n"), _T("Discarded Output Packets"), pIpStats->dwOutDiscards);
268 _tprintf(_T(" %-34s = %lu\n"), _T("Output Packets No Route"), pIpStats->dwOutNoRoutes);
269 _tprintf(_T(" %-34s = %lu\n"), _T("Reassembly Required"), pIpStats->dwReasmReqds);
270 _tprintf(_T(" %-34s = %lu\n"), _T("Reassembly Succesful"), pIpStats->dwReasmOks);
271 _tprintf(_T(" %-34s = %lu\n"), _T("Reassembly Failures"), pIpStats->dwReasmFails);
272 // _tprintf(_T(" %-34s = %lu\n"), _T("Datagrams successfully fragmented"), NULL); /* FIXME: what is this one? */
273 _tprintf(_T(" %-34s = %lu\n"), _T("Datagrams Failing Fragmentation"), pIpStats->dwFragFails);
274 _tprintf(_T(" %-34s = %lu\n"), _T("Fragments Created"), pIpStats->dwFragCreates);
275 }
276 else
277 DoFormatMessage(dwRetVal);
278
279 HeapFree(GetProcessHeap(), 0, pIpStats);
280 }
281
282 VOID ShowIcmpStatistics()
283 {
284 PMIB_ICMP pIcmpStats;
285 DWORD dwRetVal;
286
287 pIcmpStats = (MIB_ICMP*) HeapAlloc(GetProcessHeap(), 0, sizeof(MIB_ICMP));
288
289 if ((dwRetVal = GetIcmpStatistics(pIcmpStats)) == NO_ERROR)
290 {
291 _tprintf(_T("\nICMPv4 Statistics\n\n"));
292 _tprintf(_T(" Received Sent\n"));
293 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Messages"),
294 pIcmpStats->stats.icmpInStats.dwMsgs, pIcmpStats->stats.icmpOutStats.dwMsgs);
295 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Errors"),
296 pIcmpStats->stats.icmpInStats.dwErrors, pIcmpStats->stats.icmpOutStats.dwErrors);
297 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Destination Unreachable"),
298 pIcmpStats->stats.icmpInStats.dwDestUnreachs, pIcmpStats->stats.icmpOutStats.dwDestUnreachs);
299 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Time Exceeded"),
300 pIcmpStats->stats.icmpInStats.dwTimeExcds, pIcmpStats->stats.icmpOutStats.dwTimeExcds);
301 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Parameter Problems"),
302 pIcmpStats->stats.icmpInStats.dwParmProbs, pIcmpStats->stats.icmpOutStats.dwParmProbs);
303 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Source Quenches"),
304 pIcmpStats->stats.icmpInStats.dwSrcQuenchs, pIcmpStats->stats.icmpOutStats.dwSrcQuenchs);
305 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Redirects"),
306 pIcmpStats->stats.icmpInStats.dwRedirects, pIcmpStats->stats.icmpOutStats.dwRedirects);
307 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Echos"),
308 pIcmpStats->stats.icmpInStats.dwEchos, pIcmpStats->stats.icmpOutStats.dwEchos);
309 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Echo Replies"),
310 pIcmpStats->stats.icmpInStats.dwEchoReps, pIcmpStats->stats.icmpOutStats.dwEchoReps);
311 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Timestamps"),
312 pIcmpStats->stats.icmpInStats.dwTimestamps, pIcmpStats->stats.icmpOutStats.dwTimestamps);
313 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Timestamp Replies"),
314 pIcmpStats->stats.icmpInStats.dwTimestampReps, pIcmpStats->stats.icmpOutStats.dwTimestampReps);
315 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Address Masks"),
316 pIcmpStats->stats.icmpInStats.dwAddrMasks, pIcmpStats->stats.icmpOutStats.dwAddrMasks);
317 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Address Mask Replies"),
318 pIcmpStats->stats.icmpInStats.dwAddrMaskReps, pIcmpStats->stats.icmpOutStats.dwAddrMaskReps);
319 }
320 else
321 DoFormatMessage(dwRetVal);
322
323 HeapFree(GetProcessHeap(), 0, pIcmpStats);
324
325 }
326
327 VOID ShowTcpStatistics()
328 {
329 PMIB_TCPSTATS pTcpStats;
330 DWORD dwRetVal;
331
332 pTcpStats = (MIB_TCPSTATS*) HeapAlloc(GetProcessHeap(), 0, sizeof(MIB_TCPSTATS));
333
334 if ((dwRetVal = GetTcpStatistics(pTcpStats)) == NO_ERROR)
335 {
336 _tprintf(_T("\nTCP Statistics for IPv4\n\n"));
337 _tprintf(_T(" %-35s = %lu\n"), _T("Active Opens"), pTcpStats->dwActiveOpens);
338 _tprintf(_T(" %-35s = %lu\n"), _T("Passive Opens"), pTcpStats->dwPassiveOpens);
339 _tprintf(_T(" %-35s = %lu\n"), _T("Failed Connection Attempts"), pTcpStats->dwAttemptFails);
340 _tprintf(_T(" %-35s = %lu\n"), _T("Reset Connections"), pTcpStats->dwEstabResets);
341 _tprintf(_T(" %-35s = %lu\n"), _T("Current Connections"), pTcpStats->dwCurrEstab);
342 _tprintf(_T(" %-35s = %lu\n"), _T("Segments Received"), pTcpStats->dwInSegs);
343 _tprintf(_T(" %-35s = %lu\n"), _T("Segments Sent"), pTcpStats->dwOutSegs);
344 _tprintf(_T(" %-35s = %lu\n"), _T("Segments Retransmitted"), pTcpStats->dwRetransSegs);
345 }
346 else
347 DoFormatMessage(dwRetVal);
348
349 HeapFree(GetProcessHeap(), 0, pTcpStats);
350 }
351
352 VOID ShowUdpStatistics()
353 {
354 PMIB_UDPSTATS pUdpStats;
355 DWORD dwRetVal;
356
357 pUdpStats = (MIB_UDPSTATS*) HeapAlloc(GetProcessHeap(), 0, sizeof(MIB_UDPSTATS));
358
359 if ((dwRetVal = GetUdpStatistics(pUdpStats)) == NO_ERROR)
360 {
361 _tprintf(_T("\nUDP Statistics for IPv4\n\n"));
362 _tprintf(_T(" %-21s = %lu\n"), _T("Datagrams Received"), pUdpStats->dwInDatagrams);
363 _tprintf(_T(" %-21s = %lu\n"), _T("No Ports"), pUdpStats->dwNoPorts);
364 _tprintf(_T(" %-21s = %lu\n"), _T("Receive Errors"), pUdpStats->dwInErrors);
365 _tprintf(_T(" %-21s = %lu\n"), _T("Datagrams Sent"), pUdpStats->dwOutDatagrams);
366 }
367 else
368 DoFormatMessage(dwRetVal);
369
370 HeapFree(GetProcessHeap(), 0, pUdpStats);
371 }
372
373 VOID ShowEthernetStatistics()
374 {
375 PMIB_IFTABLE pIfTable;
376 DWORD dwSize = 0;
377 DWORD dwRetVal = 0;
378
379 pIfTable = (MIB_IFTABLE*) HeapAlloc(GetProcessHeap(), 0, sizeof(MIB_IFTABLE));
380
381 if (GetIfTable(pIfTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER)
382 {
383 HeapFree(GetProcessHeap(), 0, pIfTable);
384 pIfTable = (MIB_IFTABLE*) HeapAlloc(GetProcessHeap(), 0, dwSize);
385
386 if ((dwRetVal = GetIfTable(pIfTable, &dwSize, 0)) == NO_ERROR)
387 {
388 _tprintf(_T("Interface Statistics\n\n"));
389 _tprintf(_T(" Received Sent\n\n"));
390 _tprintf(_T("%-20s %14lu %15lu\n"), _T("Bytes"),
391 pIfTable->table[0].dwInOctets, pIfTable->table[0].dwOutOctets);
392 _tprintf(_T("%-20s %14lu %15lu\n"), _T("Unicast packets"),
393 pIfTable->table[0].dwInUcastPkts, pIfTable->table[0].dwOutUcastPkts);
394 _tprintf(_T("%-20s %14lu %15lu\n"), _T("Non-unicast packets"),
395 pIfTable->table[0].dwInNUcastPkts, pIfTable->table[0].dwOutNUcastPkts);
396 _tprintf(_T("%-20s %14lu %15lu\n"), _T("Discards"),
397 pIfTable->table[0].dwInDiscards, pIfTable->table[0].dwOutDiscards);
398 _tprintf(_T("%-20s %14lu %15lu\n"), _T("Errors"),
399 pIfTable->table[0].dwInErrors, pIfTable->table[0].dwOutErrors);
400 _tprintf(_T("%-20s %14lu\n"), _T("Unknown Protocols"),
401 pIfTable->table[0].dwInUnknownProtos);
402 }
403 else
404 DoFormatMessage(dwRetVal);
405 }
406 HeapFree(GetProcessHeap(), 0, pIfTable);
407 }
408
409 VOID ShowTcpTable()
410 {
411 PMIB_TCPTABLE tcpTable;
412 DWORD error, dwSize;
413 DWORD i;
414 CHAR HostIp[HOSTNAMELEN], HostPort[PORTNAMELEN];
415 CHAR RemoteIp[HOSTNAMELEN], RemotePort[PORTNAMELEN];
416 CHAR Host[ADDRESSLEN];
417 CHAR Remote[ADDRESSLEN];
418
419 /* Get the table of TCP endpoints */
420 dwSize = sizeof (MIB_TCPTABLE);
421 /* Should also work when we get new connections between 2 GetTcpTable()
422 * calls: */
423 do
424 {
425 tcpTable = (PMIB_TCPTABLE) HeapAlloc(GetProcessHeap(), 0, dwSize);
426 error = GetTcpTable(tcpTable, &dwSize, TRUE);
427 if ( error != NO_ERROR )
428 HeapFree(GetProcessHeap(), 0, tcpTable);
429 }
430 while ( error == ERROR_INSUFFICIENT_BUFFER );
431
432 if (error != NO_ERROR)
433 {
434 printf("Failed to snapshot TCP endpoints.\n");
435 DoFormatMessage(error);
436 exit(EXIT_FAILURE);
437 }
438
439 /* Dump the TCP table */
440 for (i = 0; i < tcpTable->dwNumEntries; i++)
441 {
442 /* If we aren't showing all connections, only display established, close wait
443 * and time wait. This is the default output for netstat */
444 if (bDoShowAllCons || (tcpTable->table[i].dwState == MIB_TCP_STATE_ESTAB)
445 || (tcpTable->table[i].dwState == MIB_TCP_STATE_CLOSE_WAIT)
446 || (tcpTable->table[i].dwState == MIB_TCP_STATE_TIME_WAIT))
447 {
448 /* I've split this up so it's easier to follow */
449 GetIpHostName(TRUE, tcpTable->table[i].dwLocalAddr, HostIp, HOSTNAMELEN);
450 GetPortName(tcpTable->table[i].dwLocalPort, "tcp", HostPort, PORTNAMELEN);
451 sprintf(Host, "%s:%s", HostIp, HostPort);
452
453 if (tcpTable->table[i].dwState == MIB_TCP_STATE_LISTEN)
454 {
455 sprintf(Remote, "%s:0", HostIp);
456 }
457 else
458 {
459 GetIpHostName(FALSE, tcpTable->table[i].dwRemoteAddr, RemoteIp, HOSTNAMELEN);
460 GetPortName(tcpTable->table[i].dwRemotePort, "tcp", RemotePort, PORTNAMELEN);
461 sprintf(Remote, "%s:%s", RemoteIp, RemotePort);
462 }
463
464 _tprintf(_T(" %-6s %-22s %-22s %s\n"), _T("TCP"),
465 Host, Remote, TcpState[tcpTable->table[i].dwState]);
466 }
467 }
468 HeapFree(GetProcessHeap(), 0, tcpTable);
469 }
470
471 VOID ShowUdpTable()
472 {
473 PMIB_UDPTABLE udpTable;
474 DWORD error, dwSize;
475 DWORD i;
476 CHAR HostIp[HOSTNAMELEN], HostPort[PORTNAMELEN];
477 CHAR Host[ADDRESSLEN];
478
479 /* Get the table of UDP endpoints */
480 dwSize = 0;
481 error = GetUdpTable(NULL, &dwSize, TRUE);
482 if (error != ERROR_INSUFFICIENT_BUFFER)
483 {
484 printf("Failed to snapshot UDP endpoints.\n");
485 DoFormatMessage(error);
486 exit(EXIT_FAILURE);
487 }
488 udpTable = (PMIB_UDPTABLE) HeapAlloc(GetProcessHeap(), 0, dwSize);
489 error = GetUdpTable(udpTable, &dwSize, TRUE);
490 if (error)
491 {
492 printf("Failed to snapshot UDP endpoints table.\n");
493 DoFormatMessage(error);
494 HeapFree(GetProcessHeap(), 0, udpTable);
495 exit(EXIT_FAILURE);
496 }
497
498 /* Dump the UDP table */
499 for (i = 0; i < udpTable->dwNumEntries; i++)
500 {
501
502 /* I've split this up so it's easier to follow */
503 GetIpHostName(TRUE, udpTable->table[i].dwLocalAddr, HostIp, HOSTNAMELEN);
504 GetPortName(udpTable->table[i].dwLocalPort, "tcp", HostPort, PORTNAMELEN);
505
506 sprintf(Host, "%s:%s", HostIp, HostPort);
507
508 _tprintf(_T(" %-6s %-22s %-22s\n"), _T("UDP"), Host, _T("*:*"));
509 }
510
511 HeapFree(GetProcessHeap(), 0, udpTable);
512 }
513
514 /*
515 * Translate port numbers into their text equivalent if there is one
516 */
517 PCHAR
518 GetPortName(UINT Port, PCSTR Proto, CHAR Name[], INT NameLen)
519 {
520 struct servent *pServent;
521
522 if (bDoShowNumbers)
523 {
524 sprintf(Name, "%d", htons((WORD)Port));
525 return Name;
526 }
527 /* Try to translate to a name */
528 if ((pServent = getservbyport(Port, Proto)))
529 strcpy(Name, pServent->s_name );
530 else
531 sprintf(Name, "%d", htons((WORD)Port));
532 return Name;
533 }
534
535 /*
536 * convert addresses into dotted decimal or hostname
537 */
538 PCHAR
539 GetIpHostName(BOOL Local, UINT IpAddr, CHAR Name[], int NameLen)
540 {
541 // struct hostent *phostent;
542 UINT nIpAddr;
543
544 /* display dotted decimal */
545 nIpAddr = htonl(IpAddr);
546 if (bDoShowNumbers) {
547 sprintf(Name, "%d.%d.%d.%d",
548 (nIpAddr >> 24) & 0xFF,
549 (nIpAddr >> 16) & 0xFF,
550 (nIpAddr >> 8) & 0xFF,
551 (nIpAddr) & 0xFF);
552 return Name;
553 }
554
555 Name[0] = _T('\0');
556
557 /* try to resolve the name */
558 if (!IpAddr) {
559 if (!Local) {
560 sprintf(Name, "%d.%d.%d.%d",
561 (nIpAddr >> 24) & 0xFF,
562 (nIpAddr >> 16) & 0xFF,
563 (nIpAddr >> 8) & 0xFF,
564 (nIpAddr) & 0xFF);
565 } else {
566 if (gethostname(Name, NameLen) != 0)
567 DoFormatMessage(WSAGetLastError());
568 }
569 } else if (IpAddr == 0x0100007f) {
570 if (Local) {
571 if (gethostname(Name, NameLen) != 0)
572 DoFormatMessage(WSAGetLastError());
573 } else {
574 _tcsncpy(Name, _T("localhost"), 10);
575 }
576 // } else if (phostent = gethostbyaddr((char*)&ipaddr, sizeof(nipaddr), PF_INET)) {
577 // strcpy(name, phostent->h_name);
578 } else {
579 sprintf(Name, "%d.%d.%d.%d",
580 ((nIpAddr >> 24) & 0x000000FF),
581 ((nIpAddr >> 16) & 0x000000FF),
582 ((nIpAddr >> 8) & 0x000000FF),
583 ((nIpAddr) & 0x000000FF));
584 }
585 return Name;
586 }
587
588 VOID Usage()
589 {
590 _tprintf(_T("\nDisplays current TCP/IP protocol statistics and network connections.\n\n"
591 "NETSTAT [-a] [-e] [-n] [-p proto] [-r] [-s] [interval]\n\n"
592 " -a Displays all connections and listening ports.\n"
593 " -e Displays Ethernet statistics. May be combined with -s\n"
594 " option\n"
595 " -n Displays address and port numbers in numeric form.\n"
596 " -p proto Shows connections for protocol 'proto' TCP or UDP.\n"
597 " If used with the -s option to display\n"
598 " per-protocol statistics, 'proto' may be TCP, UDP, or IP.\n"
599 " -r Displays the current routing table.\n"
600 " -s Displays per-protocol statistics. By default, Statistics are\n"
601 " shown for IP, ICMP, TCP and UDP;\n"
602 " the -p option may be used to specify a subset of the default.\n"
603 " interval Redisplays selected statistics every 'interval' seconds.\n"
604 " Press CTRL+C to stop redisplaying. By default netstat will\n"
605 " print the current information only once.\n"));
606 }
607
608 /*
609 *
610 * Parse command line parameters and set any options
611 * Run display output, looping over set intervals if a number is given
612 *
613 */
614 int main(int argc, char *argv[])
615 {
616 WSADATA wsaData;
617
618 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
619 {
620 _tprintf(_T("WSAStartup() failed : %d\n"), WSAGetLastError());
621 return -1;
622 }
623
624 if (ParseCmdline(argc, argv))
625 return -1;
626
627 if (bLoopOutput)
628 {
629 while (1)
630 {
631 if (DisplayOutput())
632 return -1;
633 Sleep(Interval*1000);
634 }
635 }
636
637 if (DisplayOutput())
638 return -1;
639 else
640 return 0;
641 }