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