fixed warnings when compiled with -Wwrite-strings
[reactos.git] / reactos / apps / utils / net / netstat / netstat.c
1 /*
2 * ReactOS Win32 Applications
3 * Copyright (C) 2005 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 /*
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS netstat utility
23 * FILE: apps/utils/net/netstat/netstat.c
24 * PURPOSE: display IP stack statistics
25 * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
26 * REVISIONS:
27 * Ged Murphy 19/09/05 Created
28 * Some ideas/code taken from Rob Dickinson's original app
29 *
30 */
31
32 /*
33 * TODO:
34 * sort function return values.
35 * implement -b, -o and -v
36 * clean up GetIpHostName
37 * command line parser needs more work
38 */
39
40 #include <windows.h>
41 #include <winsock.h>
42 #include <tchar.h>
43 #include <stdio.h>
44 #include <iphlpapi.h>
45 #include "netstat.h"
46
47
48 enum ProtoType {IP, TCP, UDP, ICMP} Protocol;
49 DWORD Interval; /* time to pause between printing output */
50
51 /* TCP endpoint states */
52 TCHAR TcpState[][32] = {
53 _T("???"),
54 _T("CLOSED"),
55 _T("LISTENING"),
56 _T("SYN_SENT"),
57 _T("SYN_RCVD"),
58 _T("ESTABLISHED"),
59 _T("FIN_WAIT1"),
60 _T("FIN_WAIT2"),
61 _T("CLOSE_WAIT"),
62 _T("CLOSING"),
63 _T("LAST_ACK"),
64 _T("TIME_WAIT"),
65 _T("DELETE_TCB")
66 };
67
68
69 /*
70 * format message string and display output
71 */
72 DWORD DoFormatMessage(DWORD ErrorCode)
73 {
74 LPVOID lpMsgBuf;
75 DWORD RetVal;
76
77 if ((RetVal = FormatMessage(
78 FORMAT_MESSAGE_ALLOCATE_BUFFER |
79 FORMAT_MESSAGE_FROM_SYSTEM |
80 FORMAT_MESSAGE_IGNORE_INSERTS,
81 NULL,
82 ErrorCode,
83 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
84 (LPTSTR) &lpMsgBuf,
85 0,
86 NULL )))
87 {
88 _tprintf(_T("%s"), (LPTSTR)lpMsgBuf);
89
90 LocalFree(lpMsgBuf);
91 /* return number of TCHAR's stored in output buffer
92 * excluding '\0' - as FormatMessage does*/
93 return RetVal;
94 }
95 else
96 return 0;
97 }
98
99
100 /*
101 *
102 * Parse command line parameters and set any options
103 *
104 */
105 BOOL ParseCmdline(int argc, char* argv[])
106 {
107 INT i;
108
109 TCHAR Proto[5];
110
111 if ((argc == 1) || (isdigit(*argv[1])))
112 bNoOptions = TRUE;
113
114 /* Parse command line for options we have been given. */
115 for (i = 1; i < argc; i++)
116 {
117 if ( (argc > 1)&&(argv[i][0] == '-') )
118 {
119 TCHAR c;
120
121 while ((c = *++argv[i]) != '\0')
122 {
123 switch (tolower(c))
124 {
125 case 'a' :
126 //_tprintf(_T("got a\n"));
127 bDoShowAllCons = TRUE;
128 break;
129 case 'e' :
130 //_tprintf(_T("got e\n"));
131 bDoShowEthStats = TRUE;
132 break;
133 case 'n' :
134 //_tprintf(_T("got n\n"));
135 bDoShowNumbers = TRUE;
136 break;
137 case 's' :
138 //_tprintf(_T("got s\n"));
139 bDoShowProtoStats = TRUE;
140 break;
141 case 'p' :
142 //_tprintf(_T("got p\n"));
143 bDoShowProtoCons = TRUE;
144
145 strncpy(Proto, (++argv)[i], sizeof(Proto));
146 if (!_tcsicmp( "IP", Proto ))
147 Protocol = IP;
148 else if (!_tcsicmp( "ICMP", Proto ))
149 Protocol = ICMP;
150 else if (!_tcsicmp( "TCP", Proto ))
151 Protocol = TCP;
152 else if (!_tcsicmp( "UDP", Proto ))
153 Protocol = UDP;
154 else
155 {
156 Usage();
157 return EXIT_FAILURE;
158 }
159 (--argv)[i]; /* move pointer back down to previous argv */
160 break;
161 case 'r' :
162 bDoShowRouteTable = TRUE;
163 break;
164 case 'v' :
165 _tprintf(_T("got v\n"));
166 bDoDispSeqComp = TRUE;
167 break;
168 default :
169 Usage();
170 return EXIT_FAILURE;
171 }
172 }
173 }
174 else if (isdigit(*argv[i]))
175 {
176 _stscanf(argv[i], "%lu", &Interval);
177 bLoopOutput = TRUE;
178 }
179 // else
180 // {
181 // Usage();
182 // EXIT_FAILURE;
183 // }
184 }
185
186 return EXIT_SUCCESS;
187 }
188
189
190 /*
191 * Simulate Microsofts netstat utility output
192 */
193 BOOL DisplayOutput()
194 {
195 if (bNoOptions)
196 {
197 _tprintf(_T("\n Proto Local Address Foreign Address State\n"));
198 ShowTcpTable();
199 return EXIT_SUCCESS;
200 }
201
202 if (bDoShowRouteTable)
203 {
204 if (system("route print") == -1)
205 {
206 //mingw doesn't have lib for _tsystem
207 _tprintf(_T("cannot find 'route.exe'\n"));
208 return EXIT_FAILURE;
209 }
210 return EXIT_SUCCESS;
211 }
212
213 if (bDoShowEthStats)
214 {
215 ShowEthernetStatistics();
216 return EXIT_SUCCESS;
217 }
218
219 if (bDoShowProtoCons)
220 {
221 switch (Protocol)
222 {
223 case IP :
224 if (bDoShowProtoStats)
225 {
226 ShowIpStatistics();
227 return EXIT_SUCCESS;
228 }
229 break;
230 case ICMP :
231 if (bDoShowProtoStats)
232 {
233 ShowIcmpStatistics();
234 return EXIT_SUCCESS;
235 }
236 break;
237 case TCP :
238 if (bDoShowProtoStats)
239 ShowTcpStatistics();
240 _tprintf(_T("\nActive Connections\n"));
241 _tprintf(_T("\n Proto Local Address Foreign Address State\n"));
242 ShowTcpTable();
243 break;
244 case UDP :
245 if (bDoShowProtoStats)
246 ShowUdpStatistics();
247 _tprintf(_T("\nActive Connections\n"));
248 _tprintf(_T("\n Proto Local Address Foreign Address State\n"));
249 ShowUdpTable();
250 break;
251 default :
252 break;
253 }
254 }
255 else if (bDoShowProtoStats)
256 {
257 ShowIpStatistics();
258 ShowIcmpStatistics();
259 ShowTcpStatistics();
260 ShowUdpStatistics();
261 return EXIT_SUCCESS;
262 }
263 else //if (bDoShowAllCons)
264 {
265 _tprintf(_T("\nActive Connections\n"));
266 _tprintf(_T("\n Proto Local Address Foreign Address State\n"));
267 ShowTcpTable();
268 ShowUdpTable();
269 }
270 return EXIT_SUCCESS;
271 }
272
273
274
275
276 VOID ShowIpStatistics()
277 {
278 PMIB_IPSTATS pIpStats;
279 DWORD dwRetVal;
280
281 pIpStats = (MIB_IPSTATS*) malloc(sizeof(MIB_IPSTATS));
282
283 if ((dwRetVal = GetIpStatistics(pIpStats)) == NO_ERROR)
284 {
285 _tprintf(_T("\nIPv4 Statistics\n\n"));
286 _tprintf(_T(" %-34s = %lu\n"), _T("Packets Recieved"), pIpStats->dwInReceives);
287 _tprintf(_T(" %-34s = %lu\n"), _T("Received Header Errors"), pIpStats->dwInHdrErrors);
288 _tprintf(_T(" %-34s = %lu\n"), _T("Received Address Errors"), pIpStats->dwInAddrErrors);
289 _tprintf(_T(" %-34s = %lu\n"), _T("Datagrams Forwarded"), pIpStats->dwForwDatagrams);
290 _tprintf(_T(" %-34s = %lu\n"), _T("Unknown Protocols Recieved"), pIpStats->dwInUnknownProtos);
291 _tprintf(_T(" %-34s = %lu\n"), _T("Received Packets Discarded"), pIpStats->dwInDiscards);
292 _tprintf(_T(" %-34s = %lu\n"), _T("Recieved Packets Delivered"), pIpStats->dwInDelivers);
293 _tprintf(_T(" %-34s = %lu\n"), _T("Output Requests"), pIpStats->dwOutRequests);
294 _tprintf(_T(" %-34s = %lu\n"), _T("Routing Discards"), pIpStats->dwRoutingDiscards);
295 _tprintf(_T(" %-34s = %lu\n"), _T("Discarded Output Packets"), pIpStats->dwOutDiscards);
296 _tprintf(_T(" %-34s = %lu\n"), _T("Output Packets No Route"), pIpStats->dwOutNoRoutes);
297 _tprintf(_T(" %-34s = %lu\n"), _T("Reassembly Required"), pIpStats->dwReasmReqds);
298 _tprintf(_T(" %-34s = %lu\n"), _T("Reassembly Succesful"), pIpStats->dwReasmOks);
299 _tprintf(_T(" %-34s = %lu\n"), _T("Reassembly Failures"), pIpStats->dwReasmFails);
300 // _tprintf(_T(" %-34s = %lu\n"), _T("Datagrams succesfully fragmented"), NULL); /* FIXME: what is this one? */
301 _tprintf(_T(" %-34s = %lu\n"), _T("Datagrams Failing Fragmentation"), pIpStats->dwFragFails);
302 _tprintf(_T(" %-34s = %lu\n"), _T("Fragments Created"), pIpStats->dwFragCreates);
303 }
304 else
305 DoFormatMessage(dwRetVal);
306 }
307
308 VOID ShowIcmpStatistics()
309 {
310 PMIB_ICMP pIcmpStats;
311 DWORD dwRetVal;
312
313 pIcmpStats = (MIB_ICMP*) malloc(sizeof(MIB_ICMP));
314
315 if ((dwRetVal = GetIcmpStatistics(pIcmpStats)) == NO_ERROR)
316 {
317 _tprintf(_T("\nICMPv4 Statistics\n\n"));
318 _tprintf(_T(" Received Sent\n"));
319 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Messages"),
320 pIcmpStats->stats.icmpInStats.dwMsgs, pIcmpStats->stats.icmpOutStats.dwMsgs);
321 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Errors"),
322 pIcmpStats->stats.icmpInStats.dwErrors, pIcmpStats->stats.icmpOutStats.dwErrors);
323 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Destination Unreachable"),
324 pIcmpStats->stats.icmpInStats.dwDestUnreachs, pIcmpStats->stats.icmpOutStats.dwDestUnreachs);
325 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Time Exceeded"),
326 pIcmpStats->stats.icmpInStats.dwTimeExcds, pIcmpStats->stats.icmpOutStats.dwTimeExcds);
327 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Parameter Problems"),
328 pIcmpStats->stats.icmpInStats.dwParmProbs, pIcmpStats->stats.icmpOutStats.dwParmProbs);
329 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Source Quenches"),
330 pIcmpStats->stats.icmpInStats.dwSrcQuenchs, pIcmpStats->stats.icmpOutStats.dwSrcQuenchs);
331 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Redirects"),
332 pIcmpStats->stats.icmpInStats.dwRedirects, pIcmpStats->stats.icmpOutStats.dwRedirects);
333 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Echos"),
334 pIcmpStats->stats.icmpInStats.dwEchos, pIcmpStats->stats.icmpOutStats.dwEchos);
335 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Echo Replies"),
336 pIcmpStats->stats.icmpInStats.dwEchoReps, pIcmpStats->stats.icmpOutStats.dwEchoReps);
337 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Timestamps"),
338 pIcmpStats->stats.icmpInStats.dwTimestamps, pIcmpStats->stats.icmpOutStats.dwTimestamps);
339 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Timestamp Replies"),
340 pIcmpStats->stats.icmpInStats.dwTimestampReps, pIcmpStats->stats.icmpOutStats.dwTimestampReps);
341 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Address Masks"),
342 pIcmpStats->stats.icmpInStats.dwAddrMasks, pIcmpStats->stats.icmpOutStats.dwAddrMasks);
343 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Address Mask Replies"),
344 pIcmpStats->stats.icmpInStats.dwAddrMaskReps, pIcmpStats->stats.icmpOutStats.dwAddrMaskReps);
345 }
346 else
347 DoFormatMessage(dwRetVal);
348
349 }
350
351 VOID ShowTcpStatistics()
352 {
353 PMIB_TCPSTATS pTcpStats;
354 DWORD dwRetVal;
355
356 pTcpStats = (MIB_TCPSTATS*) malloc(sizeof(MIB_TCPSTATS));
357
358 if ((dwRetVal = GetTcpStatistics(pTcpStats)) == NO_ERROR)
359 {
360 _tprintf(_T("\nTCP Statistics for IPv4\n\n"));
361 _tprintf(_T(" %-35s = %lu\n"), _T("Active Opens"), pTcpStats->dwActiveOpens);
362 _tprintf(_T(" %-35s = %lu\n"), _T("Passive Opens"), pTcpStats->dwPassiveOpens);
363 _tprintf(_T(" %-35s = %lu\n"), _T("Failed Connection Attempts"), pTcpStats->dwAttemptFails);
364 _tprintf(_T(" %-35s = %lu\n"), _T("Reset Connections"), pTcpStats->dwEstabResets);
365 _tprintf(_T(" %-35s = %lu\n"), _T("Current Connections"), pTcpStats->dwCurrEstab);
366 _tprintf(_T(" %-35s = %lu\n"), _T("Segments Recieved"), pTcpStats->dwInSegs);
367 _tprintf(_T(" %-35s = %lu\n"), _T("Segments Sent"), pTcpStats->dwOutSegs);
368 _tprintf(_T(" %-35s = %lu\n"), _T("Segments Retransmitted"), pTcpStats->dwRetransSegs);
369 }
370 else
371 DoFormatMessage(dwRetVal);
372 }
373
374 VOID ShowUdpStatistics()
375 {
376 PMIB_UDPSTATS pUdpStats;
377 DWORD dwRetVal;
378
379 pUdpStats = (MIB_UDPSTATS*) malloc(sizeof(MIB_UDPSTATS));
380
381 if ((dwRetVal = GetUdpStatistics(pUdpStats)) == NO_ERROR)
382 {
383 _tprintf(_T("\nUDP Statistics for IPv4\n\n"));
384 _tprintf(_T(" %-21s = %lu\n"), _T("Datagrams Recieved"), pUdpStats->dwInDatagrams);
385 _tprintf(_T(" %-21s = %lu\n"), _T("No Ports"), pUdpStats->dwNoPorts);
386 _tprintf(_T(" %-21s = %lu\n"), _T("Recieve Errors"), pUdpStats->dwInErrors);
387 _tprintf(_T(" %-21s = %lu\n"), _T("Datagrams Sent"), pUdpStats->dwOutDatagrams);
388 }
389 else
390 DoFormatMessage(dwRetVal);
391 }
392
393 VOID ShowEthernetStatistics()
394 {
395 PMIB_IFTABLE pIfTable;
396 DWORD dwSize = 0;
397 DWORD dwRetVal = 0;
398
399 pIfTable = (MIB_IFTABLE*) malloc(sizeof(MIB_IFTABLE));
400
401 if (GetIfTable(pIfTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER)
402 {
403 GlobalFree(pIfTable);
404 pIfTable = (MIB_IFTABLE*) malloc(dwSize);
405
406 if ((dwRetVal = GetIfTable(pIfTable, &dwSize, 0)) == NO_ERROR)
407 {
408 _tprintf(_T("Interface Statistics\n\n"));
409 _tprintf(_T(" Received Sent\n\n"));
410 _tprintf(_T("%-20s %14lu %15lu\n"), _T("Bytes"),
411 pIfTable->table[0].dwInOctets, pIfTable->table[0].dwOutOctets);
412 _tprintf(_T("%-20s %14lu %15lu\n"), _T("Unicast packets"),
413 pIfTable->table[0].dwInUcastPkts, pIfTable->table[0].dwOutUcastPkts);
414 _tprintf(_T("%-20s %14lu %15lu\n"), _T("Non-unicast packets"),
415 pIfTable->table[0].dwInNUcastPkts, pIfTable->table[0].dwOutNUcastPkts);
416 _tprintf(_T("%-20s %14lu %15lu\n"), _T("Discards"),
417 pIfTable->table[0].dwInDiscards, pIfTable->table[0].dwOutDiscards);
418 _tprintf(_T("%-20s %14lu %15lu\n"), _T("Errors"),
419 pIfTable->table[0].dwInErrors, pIfTable->table[0].dwOutErrors);
420 _tprintf(_T("%-20s %14lu\n"), _T("Unknown Protocols"),
421 pIfTable->table[0].dwInUnknownProtos);
422 }
423 else
424 DoFormatMessage(dwRetVal);
425 }
426 }
427
428 VOID ShowTcpTable()
429 {
430 PMIB_TCPTABLE tcpTable;
431 DWORD error, dwSize;
432 DWORD i;
433 CHAR HostIp[HOSTNAMELEN], HostPort[PORTNAMELEN];
434 CHAR RemoteIp[HOSTNAMELEN], RemotePort[PORTNAMELEN];
435 CHAR Host[ADDRESSLEN];
436 CHAR Remote[ADDRESSLEN];
437
438 /* Get the table of TCP endpoints */
439 dwSize = 0;
440 error = GetTcpTable(NULL, &dwSize, TRUE);
441 if (error != ERROR_INSUFFICIENT_BUFFER)
442 {
443 printf("Failed to snapshot TCP endpoints.\n");
444 DoFormatMessage(error);
445 exit(EXIT_FAILURE);
446 }
447 tcpTable = (PMIB_TCPTABLE)malloc(dwSize);
448 error = GetTcpTable(tcpTable, &dwSize, TRUE );
449 if (error)
450 {
451 printf("Failed to snapshot TCP endpoints table.\n");
452 DoFormatMessage(error);
453 exit(EXIT_FAILURE);
454 }
455
456 /* Dump the TCP table */
457 for (i = 0; i < tcpTable->dwNumEntries; i++)
458 {
459 /* If we aren't showing all connections, only display established, close wait
460 * and time wait. This is the default output for netstat */
461 if (bDoShowAllCons || (tcpTable->table[i].dwState == MIB_TCP_STATE_ESTAB)
462 || (tcpTable->table[i].dwState == MIB_TCP_STATE_CLOSE_WAIT)
463 || (tcpTable->table[i].dwState == MIB_TCP_STATE_TIME_WAIT))
464 {
465 /* I've split this up so it's easier to follow */
466 GetIpHostName(TRUE, tcpTable->table[i].dwLocalAddr, HostIp, HOSTNAMELEN);
467 GetPortName(tcpTable->table[i].dwLocalPort, "tcp", HostPort, PORTNAMELEN);
468 GetIpHostName(FALSE, tcpTable->table[i].dwRemoteAddr, RemoteIp, HOSTNAMELEN);
469 GetPortName(tcpTable->table[i].dwRemotePort, "tcp", RemotePort, PORTNAMELEN);
470
471 sprintf(Host, "%s:%s", HostIp, HostPort);
472 sprintf(Remote, "%s:%s", RemoteIp, RemotePort);
473
474 _tprintf(_T(" %-6s %-22s %-22s %s\n"), _T("TCP"),
475 Host, Remote, TcpState[tcpTable->table[i].dwState]);
476 }
477 }
478 }
479
480
481 VOID ShowUdpTable()
482 {
483 PMIB_UDPTABLE udpTable;
484 DWORD error, dwSize;
485 DWORD i;
486 CHAR HostIp[HOSTNAMELEN], HostPort[PORTNAMELEN];
487 CHAR Host[ADDRESSLEN];
488
489 /* Get the table of UDP endpoints */
490 dwSize = 0;
491 error = GetUdpTable(NULL, &dwSize, TRUE);
492 if (error != ERROR_INSUFFICIENT_BUFFER)
493 {
494 printf("Failed to snapshot UDP endpoints.\n");
495 DoFormatMessage(error);
496 exit(EXIT_FAILURE);
497 }
498 udpTable = (PMIB_UDPTABLE)malloc(dwSize);
499 error = GetUdpTable(udpTable, &dwSize, TRUE);
500 if (error)
501 {
502 printf("Failed to snapshot UDP endpoints table.\n");
503 DoFormatMessage(error);
504 exit(EXIT_FAILURE);
505 }
506
507 /* Dump the UDP table */
508 for (i = 0; i < udpTable->dwNumEntries; i++)
509 {
510
511 /* I've split this up so it's easier to follow */
512 GetIpHostName(TRUE, udpTable->table[i].dwLocalAddr, HostIp, HOSTNAMELEN);
513 GetPortName(udpTable->table[i].dwLocalPort, "tcp", HostPort, PORTNAMELEN);
514
515 sprintf(Host, "%s:%s", HostIp, HostPort);
516
517 _tprintf(_T(" %-6s %-22s %-22s\n"), _T("UDP"), Host, _T(":*:"));
518 }
519 }
520
521
522 /*
523 * Translate port numbers into their text equivalent if there is one
524 */
525 PCHAR
526 GetPortName(UINT Port, PCSTR Proto, CHAR Name[], INT NameLen)
527 {
528 struct servent *pSrvent;
529
530 if (bDoShowNumbers)
531 {
532 sprintf(Name, "%d", htons((WORD)Port));
533 return Name;
534 }
535 /* Try to translate to a name */
536 if ((pSrvent = getservbyport(Port, Proto)))
537 strcpy(Name, pSrvent->s_name );
538 else
539 sprintf(Name, "%d", htons((WORD)Port));
540 return Name;
541 }
542
543
544 //
545 // GetIpHostName
546 //
547 // Translate IP addresses into their name-resolved form if possible.
548 //
549 PCHAR
550 GetIpHostName(BOOL Local, UINT IpAddr, CHAR Name[], int NameLen)
551 {
552 // struct hostent *phostent;
553 UINT nIpAddr;
554
555 // Does the user want raw numbers?
556 nIpAddr = htonl(IpAddr);
557 if (bDoShowNumbers) {
558 sprintf(Name, "%d.%d.%d.%d",
559 (nIpAddr >> 24) & 0xFF,
560 (nIpAddr >> 16) & 0xFF,
561 (nIpAddr >> 8) & 0xFF,
562 (nIpAddr) & 0xFF);
563 return Name;
564 }
565
566 Name[0] = L'\0';
567
568 // Try to translate to a name
569 if (!IpAddr) {
570 if (!Local) {
571 sprintf(Name, "%d.%d.%d.%d",
572 (nIpAddr >> 24) & 0xFF,
573 (nIpAddr >> 16) & 0xFF,
574 (nIpAddr >> 8) & 0xFF,
575 (nIpAddr) & 0xFF);
576 } else {
577 //gethostname(name, namelen);
578 }
579 } else if (IpAddr == 0x0100007f) {
580 if (Local) {
581 //gethostname(name, namelen);
582 } else {
583 strcpy(Name, "localhost");
584 }
585 // } else if (phostent = gethostbyaddr((char*)&ipaddr, sizeof(nipaddr), PF_INET)) {
586 // strcpy(name, phostent->h_name);
587 } else {
588 sprintf(Name, "%d.%d.%d.%d",
589 ((nIpAddr >> 24) & 0x000000FF),
590 ((nIpAddr >> 16) & 0x000000FF),
591 ((nIpAddr >> 8) & 0x000000FF),
592 ((nIpAddr) & 0x000000FF));
593 }
594 return Name;
595 }
596
597 VOID Usage()
598 {
599 _tprintf(_T("Displays current TCP/IP protocol statistics and network connections.\n\n"
600 "NETSTAT [-a] [-e] [-n] [-s] [-p proto] [-r] [interval]\n\n"
601 " -a Displays all connections and listening ports.\n"
602 " -e Displays Ethernet statistics. May be combined with -s\n"
603 " option\n"
604 " -n Displays address and port numbers in numeric form.\n"
605 " -p proto Shows connections for protocol 'proto' TCP or UDP.\n"
606 " If used with the -s option to display\n"
607 " per-protocol statistics, 'proto' may be TCP, UDP, or IP.\n"
608 " -r Displays the current routing table.\n"
609 " -s Displays per-protocol statistics. By default, Statistics are\n"
610 " shown for IP, ICMP, TCP and UDP;\n"
611 " the -p option may be used to specify a subset of the default.\n"
612 " interval Redisplays selected statistics every 'interval' seconds.\n"
613 " Press CTRL+C to stop redisplaying. By default netstat will\n"
614 " print the current information only once.\n"));
615 }
616
617
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 main(int argc, char *argv[])
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 }