Start of a rewrite for netstat.exe
[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 * rewrite DisplayOutput
35 * sort function return values. BOOL is crap
36 * implement -b, -o and -v
37 * clean up GetPortName and GetIpHostName
38 * command line parser needs more work
39 */
40
41 #include <windows.h>
42 #include <winsock.h>
43 #include <tchar.h>
44 #include <stdio.h>
45 #include <iphlpapi.h>
46 #include "netstat.h"
47
48 CHAR localname[HOSTNAMELEN], remotename[HOSTNAMELEN];
49 CHAR remoteport[PORTNAMELEN], localport[PORTNAMELEN];
50 CHAR localaddr[ADDRESSLEN], remoteaddr[ADDRESSLEN];
51
52 enum ProtoType {IP, TCP, UDP, ICMP} Protocol;
53 DWORD Interval; /* time to pause between printing output */
54
55 /* TCP endpoint states */
56 TCHAR TcpState[][32] = {
57 _T("???"),
58 _T("CLOSED"),
59 _T("LISTENING"),
60 _T("SYN_SENT"),
61 _T("SYN_RCVD"),
62 _T("ESTABLISHED"),
63 _T("FIN_WAIT1"),
64 _T("FIN_WAIT2"),
65 _T("CLOSE_WAIT"),
66 _T("CLOSING"),
67 _T("LAST_ACK"),
68 _T("TIME_WAIT"),
69 _T("DELETE_TCB")
70 };
71
72
73 /*
74 *
75 * Parse command line parameters and set any options
76 *
77 */
78 BOOL ParseCmdline(int argc, char* argv[])
79 {
80 INT i;
81
82 TCHAR Proto[5];
83
84 if ((argc == 1) || (isdigit(*argv[1])))
85 bNoOptions = TRUE;
86
87 /* Parse command line for options we have been given. */
88 for (i = 1; i < argc; i++)
89 {
90 if ( (argc > 1)&&(argv[i][0] == '-') )
91 {
92 TCHAR c;
93
94 while ((c = *++argv[i]) != '\0')
95 {
96 switch (tolower(c))
97 {
98 case 'a' :
99 //_tprintf(_T("got a\n"));
100 bDoShowAllCons = TRUE;
101 break;
102 case 'e' :
103 //_tprintf(_T("got e\n"));
104 bDoShowEthStats = TRUE;
105 break;
106 case 'n' :
107 //_tprintf(_T("got n\n"));
108 bDoShowNumbers = TRUE;
109 break;
110 case 's' :
111 //_tprintf(_T("got s\n"));
112 bDoShowProtoStats = TRUE;
113 break;
114 case 'p' :
115 //_tprintf(_T("got p\n"));
116 bDoShowProtoCons = TRUE;
117
118 strncpy(Proto, (++argv)[i], sizeof(Proto));
119 if (!_tcsicmp( "IP", Proto ))
120 Protocol = IP;
121 else if (!_tcsicmp( "ICMP", Proto ))
122 Protocol = ICMP;
123 else if (!_tcsicmp( "TCP", Proto ))
124 Protocol = TCP;
125 else if (!_tcsicmp( "UDP", Proto ))
126 Protocol = UDP;
127 else
128 {
129 Usage();
130 return EXIT_FAILURE;
131 }
132 (--argv)[i]; /* move pointer back down to previous argv */
133 break;
134 case 'r' :
135 bDoShowRouteTable = FALSE;
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 (isdigit(*argv[i]))
148 {
149 _stscanf(argv[i], "%lu", &Interval);
150 bLoopOutput = TRUE;
151 }
152 // else
153 // {
154 // Usage();
155 // EXIT_FAILURE;
156 // }
157 }
158
159 return EXIT_SUCCESS;
160 }
161
162 /* Simulate Microsofts netstat utility output. It's a bit
163 * ugly and over nested, but it is a fairly acurate simulation
164 * It was easier for testing, I'll rewrite it later with flags
165 * For now, it works*/
166 BOOL DisplayOutput()
167 // FIXME: This whole function needs rewriting
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 (bDoShowEthStats)
177 {
178 ShowEthernetStatistics();
179 return EXIT_SUCCESS;
180 }
181
182 if (bDoShowRouteTable)
183 {
184 if (system("route print") == -1)
185 {
186 //mingw doesn't have lib for _tsystem
187 _tprintf(_T("cannot find 'route.exe'\n"));
188 return EXIT_FAILURE;
189 }
190 }
191
192 /* output connections: -a */
193 if (bDoShowAllCons)
194 {
195 /* filter out certain protocols: -p */
196 if (bDoShowProtoCons)
197 {
198 /* do we want to list the stats: -s */
199 if (bDoShowProtoStats)
200 {
201 switch (Protocol)
202 {
203 case IP :
204 ShowIpStatistics();
205 break;
206 case ICMP :
207 ShowIcmpStatistics();
208 break;
209 case TCP :
210 ShowTcpStatistics();
211 _tprintf(_T("\nActive Connections\n"));
212 _tprintf(_T("\n Proto Local Address Foreign Address State\n"));
213 ShowTcpTable();
214 break;
215 case UDP :
216 ShowUdpStatistics();
217 _tprintf(_T("\nActive Connections\n"));
218 _tprintf(_T("\n Proto Local Address Foreign Address State\n"));
219 ShowUdpTable();
220 break;
221 default :
222 break;
223 }
224 return EXIT_SUCCESS;
225 }
226 else
227 {
228 switch (Protocol)
229 {
230 case IP :
231 break;
232 case ICMP :
233 ShowIcmpStatistics();
234 break;
235 case TCP :
236 _tprintf(_T("\nActive Connections\n"));
237 _tprintf(_T("\n Proto Local Address Foreign Address State\n"));
238 ShowTcpTable();
239 break;
240 case UDP :
241 _tprintf(_T("\nActive Connections\n"));
242 _tprintf(_T("\n Proto Local Address Foreign Address State\n"));
243 ShowUdpTable();
244 break;
245 default :
246 break;
247 }
248 return EXIT_SUCCESS;
249 }
250
251 }
252 else
253 {
254 _tprintf(_T("\nActive Connections\n"));
255 _tprintf(_T("\n Proto Local Address Foreign Address State\n"));
256 ShowTcpTable();
257 ShowUdpTable();
258 return EXIT_SUCCESS;
259 }
260 }
261
262 /* do we want to list the stats: -s */
263 if (bDoShowProtoStats)
264 {
265 if (bDoShowProtoCons) // -p
266 {
267 /* show individual protocols only */
268 switch (Protocol)
269 {
270 case IP :
271 ShowIpStatistics();
272 break;
273 case ICMP :
274 ShowIcmpStatistics();
275 break;
276 case TCP :
277 ShowTcpStatistics();
278 _tprintf(_T("\nActive Connections\n"));
279 _tprintf(_T("\n Proto Local Address Foreign Address State\n"));
280 ShowTcpTable();
281 break;
282 case UDP :
283 ShowUdpStatistics();
284 _tprintf(_T("\nActive Connections\n"));
285 _tprintf(_T("\n Proto Local Address Foreign Address State\n"));
286 ShowUdpTable();
287 break;
288 default :
289 break;
290 }
291 return EXIT_SUCCESS;
292 }
293 else
294 {
295 /* list the lot */
296 ShowIpStatistics();
297 ShowIcmpStatistics();
298 ShowTcpStatistics();
299 ShowUdpStatistics();
300 return EXIT_SUCCESS;
301 }
302 }
303 return EXIT_SUCCESS;
304 }
305
306
307 /* format message string and display output */
308 DWORD DoFormatMessage(DWORD ErrorCode)
309 {
310 LPVOID lpMsgBuf;
311 DWORD RetVal;
312
313 if ((RetVal = FormatMessage(
314 FORMAT_MESSAGE_ALLOCATE_BUFFER |
315 FORMAT_MESSAGE_FROM_SYSTEM |
316 FORMAT_MESSAGE_IGNORE_INSERTS,
317 NULL,
318 ErrorCode,
319 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
320 (LPTSTR) &lpMsgBuf,
321 0,
322 NULL )))
323 {
324 _tprintf(_T("%s"), (LPTSTR)lpMsgBuf);
325
326 LocalFree(lpMsgBuf);
327 /* return number of TCHAR's stored in output buffer
328 * excluding '\0' - as FormatMessage does*/
329 return RetVal;
330 }
331 else
332 return 0;
333 }
334
335
336 VOID ShowIpStatistics()
337 {
338 PMIB_IPSTATS pIpStats;
339 DWORD dwRetVal;
340
341 pIpStats = (MIB_IPSTATS*) malloc(sizeof(MIB_IPSTATS));
342
343 if ((dwRetVal = GetIpStatistics(pIpStats)) == NO_ERROR)
344 {
345 _tprintf(_T("\nIPv4 Statistics\n\n"));
346 _tprintf(_T(" %-34s = %lu\n"), _T("Packets Recieved"), pIpStats->dwInReceives);
347 _tprintf(_T(" %-34s = %lu\n"), _T("Received Header Errors"), pIpStats->dwInHdrErrors);
348 _tprintf(_T(" %-34s = %lu\n"), _T("Received Address Errors"), pIpStats->dwInAddrErrors);
349 _tprintf(_T(" %-34s = %lu\n"), _T("Datagrams Forwarded"), pIpStats->dwForwDatagrams);
350 _tprintf(_T(" %-34s = %lu\n"), _T("Unknown Protocols Recieved"), pIpStats->dwInUnknownProtos);
351 _tprintf(_T(" %-34s = %lu\n"), _T("Received Packets Discarded"), pIpStats->dwInDiscards);
352 _tprintf(_T(" %-34s = %lu\n"), _T("Recieved Packets Delivered"), pIpStats->dwInDelivers);
353 _tprintf(_T(" %-34s = %lu\n"), _T("Output Requests"), pIpStats->dwOutRequests);
354 _tprintf(_T(" %-34s = %lu\n"), _T("Routing Discards"), pIpStats->dwRoutingDiscards);
355 _tprintf(_T(" %-34s = %lu\n"), _T("Discarded Output Packets"), pIpStats->dwOutDiscards);
356 _tprintf(_T(" %-34s = %lu\n"), _T("Output Packets No Route"), pIpStats->dwOutNoRoutes);
357 _tprintf(_T(" %-34s = %lu\n"), _T("Reassembly Required"), pIpStats->dwReasmReqds);
358 _tprintf(_T(" %-34s = %lu\n"), _T("Reassembly Succesful"), pIpStats->dwReasmOks);
359 _tprintf(_T(" %-34s = %lu\n"), _T("Reassembly Failures"), pIpStats->dwReasmFails);
360 // _tprintf(_T(" %-34s = %lu\n"), _T("Datagrams succesfully fragmented"), NULL); /* FIXME: what is this one? */
361 _tprintf(_T(" %-34s = %lu\n"), _T("Datagrams Failing Fragmentation"), pIpStats->dwFragFails);
362 _tprintf(_T(" %-34s = %lu\n"), _T("Fragments Created"), pIpStats->dwFragCreates);
363 }
364 else
365 DoFormatMessage(dwRetVal);
366 }
367
368 VOID ShowIcmpStatistics()
369 {
370 PMIB_ICMP pIcmpStats;
371 DWORD dwRetVal;
372
373 pIcmpStats = (MIB_ICMP*) malloc(sizeof(MIB_ICMP));
374
375 if ((dwRetVal = GetIcmpStatistics(pIcmpStats)) == NO_ERROR)
376 {
377 _tprintf(_T("\nICMPv4 Statistics\n\n"));
378 _tprintf(_T(" Received Sent\n"));
379 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Messages"),
380 pIcmpStats->stats.icmpInStats.dwMsgs, pIcmpStats->stats.icmpOutStats.dwMsgs);
381 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Errors"),
382 pIcmpStats->stats.icmpInStats.dwErrors, pIcmpStats->stats.icmpOutStats.dwErrors);
383 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Destination Unreachable"),
384 pIcmpStats->stats.icmpInStats.dwDestUnreachs, pIcmpStats->stats.icmpOutStats.dwDestUnreachs);
385 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Time Exceeded"),
386 pIcmpStats->stats.icmpInStats.dwTimeExcds, pIcmpStats->stats.icmpOutStats.dwTimeExcds);
387 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Parameter Problems"),
388 pIcmpStats->stats.icmpInStats.dwParmProbs, pIcmpStats->stats.icmpOutStats.dwParmProbs);
389 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Source Quenches"),
390 pIcmpStats->stats.icmpInStats.dwSrcQuenchs, pIcmpStats->stats.icmpOutStats.dwSrcQuenchs);
391 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Redirects"),
392 pIcmpStats->stats.icmpInStats.dwRedirects, pIcmpStats->stats.icmpOutStats.dwRedirects);
393 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Echos"),
394 pIcmpStats->stats.icmpInStats.dwEchos, pIcmpStats->stats.icmpOutStats.dwEchos);
395 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Echo Replies"),
396 pIcmpStats->stats.icmpInStats.dwEchoReps, pIcmpStats->stats.icmpOutStats.dwEchoReps);
397 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Timestamps"),
398 pIcmpStats->stats.icmpInStats.dwTimestamps, pIcmpStats->stats.icmpOutStats.dwTimestamps);
399 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Timestamp Replies"),
400 pIcmpStats->stats.icmpInStats.dwTimestampReps, pIcmpStats->stats.icmpOutStats.dwTimestampReps);
401 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Address Masks"),
402 pIcmpStats->stats.icmpInStats.dwAddrMasks, pIcmpStats->stats.icmpOutStats.dwAddrMasks);
403 _tprintf(_T(" %-25s %-11lu %lu\n"), _T("Address Mask Replies"),
404 pIcmpStats->stats.icmpInStats.dwAddrMaskReps, pIcmpStats->stats.icmpOutStats.dwAddrMaskReps);
405 }
406 else
407 DoFormatMessage(dwRetVal);
408
409 }
410
411 VOID ShowTcpStatistics()
412 {
413 PMIB_TCPSTATS pTcpStats;
414 DWORD dwRetVal;
415
416 pTcpStats = (MIB_TCPSTATS*) malloc(sizeof(MIB_TCPSTATS));
417
418 if ((dwRetVal = GetTcpStatistics(pTcpStats)) == NO_ERROR)
419 {
420 _tprintf(_T("\nTCP Statistics for IPv4\n\n"));
421 _tprintf(_T(" %-35s = %lu\n"), _T("Active Opens"), pTcpStats->dwActiveOpens);
422 _tprintf(_T(" %-35s = %lu\n"), _T("Passive Opens"), pTcpStats->dwPassiveOpens);
423 _tprintf(_T(" %-35s = %lu\n"), _T("Failed Connection Attempts"), pTcpStats->dwAttemptFails);
424 _tprintf(_T(" %-35s = %lu\n"), _T("Reset Connections"), pTcpStats->dwEstabResets);
425 _tprintf(_T(" %-35s = %lu\n"), _T("Current Connections"), pTcpStats->dwCurrEstab);
426 _tprintf(_T(" %-35s = %lu\n"), _T("Segments Recieved"), pTcpStats->dwInSegs);
427 _tprintf(_T(" %-35s = %lu\n"), _T("Segments Sent"), pTcpStats->dwOutSegs);
428 _tprintf(_T(" %-35s = %lu\n"), _T("Segments Retransmitted"), pTcpStats->dwRetransSegs);
429 }
430 else
431 DoFormatMessage(dwRetVal);
432 }
433
434 VOID ShowUdpStatistics()
435 {
436 PMIB_UDPSTATS pUdpStats;
437 DWORD dwRetVal;
438
439 pUdpStats = (MIB_UDPSTATS*) malloc(sizeof(MIB_UDPSTATS));
440
441 if ((dwRetVal = GetUdpStatistics(pUdpStats)) == NO_ERROR)
442 {
443 _tprintf(_T("\nUDP Statistics for IPv4\n\n"));
444 _tprintf(_T(" %-21s = %lu\n"), _T("Datagrams Recieved"), pUdpStats->dwInDatagrams);
445 _tprintf(_T(" %-21s = %lu\n"), _T("No Ports"), pUdpStats->dwNoPorts);
446 _tprintf(_T(" %-21s = %lu\n"), _T("Recieve Errors"), pUdpStats->dwInErrors);
447 _tprintf(_T(" %-21s = %lu\n"), _T("Datagrams Sent"), pUdpStats->dwOutDatagrams);
448 }
449 else
450 DoFormatMessage(dwRetVal);
451 }
452
453 VOID ShowEthernetStatistics()
454 {
455 PMIB_IFTABLE pIfTable;
456 DWORD dwSize = 0;
457 DWORD dwRetVal = 0;
458
459 pIfTable = (MIB_IFTABLE*) malloc(sizeof(MIB_IFTABLE));
460
461 if (GetIfTable(pIfTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER)
462 {
463 GlobalFree(pIfTable);
464 pIfTable = (MIB_IFTABLE*) malloc(dwSize);
465
466 if ((dwRetVal = GetIfTable(pIfTable, &dwSize, 0)) == NO_ERROR)
467 {
468 _tprintf(_T("Interface Statistics\n\n"));
469 _tprintf(_T(" Received Sent\n\n"));
470 _tprintf(_T("%-20s %14lu %15lu\n"), _T("Bytes"),
471 pIfTable->table[0].dwInOctets, pIfTable->table[0].dwOutOctets);
472 _tprintf(_T("%-20s %14lu %15lu\n"), _T("Unicast packets"),
473 pIfTable->table[0].dwInUcastPkts, pIfTable->table[0].dwOutUcastPkts);
474 _tprintf(_T("%-20s %14lu %15lu\n"), _T("Non-unicast packets"),
475 pIfTable->table[0].dwInNUcastPkts, pIfTable->table[0].dwOutNUcastPkts);
476 _tprintf(_T("%-20s %14lu %15lu\n"), _T("Discards"),
477 pIfTable->table[0].dwInDiscards, pIfTable->table[0].dwOutDiscards);
478 _tprintf(_T("%-20s %14lu %15lu\n"), _T("Errors"),
479 pIfTable->table[0].dwInErrors, pIfTable->table[0].dwOutErrors);
480 _tprintf(_T("%-20s %14lu\n"), _T("Unknown Protocols"),
481 pIfTable->table[0].dwInUnknownProtos);
482 }
483 else
484 DoFormatMessage(dwRetVal);
485 }
486 }
487
488 VOID ShowTcpTable()
489 {
490 PMIB_TCPTABLE tcpTable;
491 DWORD error, dwSize;
492 DWORD i;
493
494 // Get the table of TCP endpoints
495 dwSize = 0;
496 error = GetTcpTable(NULL, &dwSize, TRUE);
497 if (error != ERROR_INSUFFICIENT_BUFFER)
498 {
499 printf("Failed to snapshot TCP endpoints.\n");
500 DoFormatMessage(error);
501 exit(EXIT_FAILURE);
502 }
503 tcpTable = (PMIB_TCPTABLE)malloc(dwSize);
504 error = GetTcpTable(tcpTable, &dwSize, TRUE );
505 if (error)
506 {
507 printf("Failed to snapshot TCP endpoints table.\n");
508 DoFormatMessage(error);
509 exit(EXIT_FAILURE);
510 }
511
512 // Dump the TCP table
513 for (i = 0; i < tcpTable->dwNumEntries; i++)
514 {
515 if (bDoShowAllCons || (tcpTable->table[i].dwState ==
516 MIB_TCP_STATE_ESTAB))
517 {
518 sprintf(localaddr, "%s:%s",
519 GetIpHostName(TRUE, tcpTable->table[i].dwLocalAddr, localname, HOSTNAMELEN),
520 GetPortName(tcpTable->table[i].dwLocalPort, "tcp", localport, PORTNAMELEN));
521 sprintf(remoteaddr, "%s:%s",
522 GetIpHostName(FALSE, tcpTable->table[i].dwRemoteAddr, remotename, HOSTNAMELEN),
523 tcpTable->table[i].dwRemoteAddr ?
524 GetPortName(tcpTable->table[i].dwRemotePort, "tcp", remoteport, PORTNAMELEN):
525 "0");
526 _tprintf(_T(" %-6s %-22s %-22s %s\n"), _T("TCP"), localaddr, remoteaddr, TcpState[tcpTable->table[i].dwState]);
527 }
528 }
529 }
530
531
532 VOID ShowUdpTable()
533 {
534 PMIB_UDPTABLE udpTable;
535 DWORD error, dwSize;
536 DWORD i;
537
538 // Get the table of UDP endpoints
539 dwSize = 0;
540 error = GetUdpTable(NULL, &dwSize, TRUE);
541 if (error != ERROR_INSUFFICIENT_BUFFER)
542 {
543 printf("Failed to snapshot UDP endpoints.\n");
544 DoFormatMessage(error);
545 exit(EXIT_FAILURE);
546 }
547 udpTable = (PMIB_UDPTABLE)malloc(dwSize);
548 error = GetUdpTable(udpTable, &dwSize, TRUE);
549 if (error)
550 {
551 printf("Failed to snapshot UDP endpoints table.\n");
552 DoFormatMessage(error);
553 exit(EXIT_FAILURE);
554 }
555
556 // Dump the UDP table
557 for (i = 0; i < udpTable->dwNumEntries; i++)
558 {
559 sprintf(localaddr, "%s:%s",
560 GetIpHostName(TRUE, udpTable->table[i].dwLocalAddr, localname, HOSTNAMELEN),
561 GetPortName(udpTable->table[i].dwLocalPort, "tcp", localport, PORTNAMELEN));
562 _tprintf(_T(" %-6s %-22s %-22s\n"), _T("UDP"), localaddr, _T(":*:"));
563 }
564 }
565
566
567 //
568 // GetPortName
569 //
570 // Translate port numbers into their text equivalent if there is one
571 //
572 PCHAR
573 GetPortName(UINT port, PCHAR proto, PCHAR name, int namelen)
574 {
575 struct servent *psrvent;
576
577 if (bDoShowNumbers) {
578 sprintf(name, "%d", htons((WORD)port));
579 return name;
580 }
581 // Try to translate to a name
582 if ((psrvent = getservbyport(port, proto))) {
583 strcpy(name, psrvent->s_name );
584 } else {
585 sprintf(name, "%d", htons((WORD)port));
586 }
587 return name;
588 }
589
590
591 //
592 // GetIpHostName
593 //
594 // Translate IP addresses into their name-resolved form if possible.
595 //
596 PCHAR
597 GetIpHostName(BOOL local, UINT ipaddr, PCHAR name, int namelen)
598 {
599 // struct hostent *phostent;
600 UINT nipaddr;
601
602 // Does the user want raw numbers?
603 nipaddr = htonl(ipaddr);
604 if (bDoShowNumbers) {
605 sprintf(name, "%d.%d.%d.%d",
606 (nipaddr >> 24) & 0xFF,
607 (nipaddr >> 16) & 0xFF,
608 (nipaddr >> 8) & 0xFF,
609 (nipaddr) & 0xFF);
610 return name;
611 }
612
613 name[0] = _T('\0');
614
615 // Try to translate to a name
616 if (!ipaddr) {
617 if (!local) {
618 sprintf(name, "%d.%d.%d.%d",
619 (nipaddr >> 24) & 0xFF,
620 (nipaddr >> 16) & 0xFF,
621 (nipaddr >> 8) & 0xFF,
622 (nipaddr) & 0xFF);
623 } else {
624 //gethostname(name, namelen);
625 }
626 } else if (ipaddr == 0x0100007f) {
627 if (local) {
628 //gethostname(name, namelen);
629 } else {
630 strcpy(name, "localhost");
631 }
632 // } else if (phostent = gethostbyaddr((char*)&ipaddr, sizeof(nipaddr), PF_INET)) {
633 // strcpy(name, phostent->h_name);
634 } else {
635 sprintf(name, "%d.%d.%d.%d",
636 ((nipaddr >> 24) & 0x000000FF),
637 ((nipaddr >> 16) & 0x000000FF),
638 ((nipaddr >> 8) & 0x000000FF),
639 ((nipaddr) & 0x000000FF));
640 }
641 return name;
642 }
643
644 VOID Usage()
645 {
646 _tprintf(_T("Displays current TCP/IP protocol statistics and network connections.\n\n"
647 "NETSTAT [-a] [-e] [-n] [-s] [-p proto] [-r] [interval]\n\n"
648 " -a Displays all connections and listening ports.\n"
649 " -e Displays Ethernet statistics. May be combined with -s\n"
650 " option\n"
651 " -n Displays address and port numbers in numeric form.\n"
652 " -p proto Shows connections for protocol 'proto' TCP or UDP.\n"
653 " If used with the -s option to display\n"
654 " per-protocol statistics, 'proto' may be TCP, UDP, or IP.\n"
655 " -r Displays the current routing table.\n"
656 " -s Displays per-protocol statistics. By default, Statistics are\n"
657 " shown for IP, ICMP, TCP and UDP;\n"
658 " the -p option may be used to specify a subset of the default.\n"
659 " interval Redisplays selected statistics every 'interval' seconds.\n"
660 " Press CTRL+C to stop redisplaying. By default netstat will\n"
661 " print the current information only once.\n"));
662 }
663
664
665
666
667 /*
668 *
669 * Parse command line parameters and set any options
670 * Run display output, looping over set intervals if a number is given
671 *
672 */
673 int main(int argc, char *argv[])
674 {
675 if (ParseCmdline(argc, argv))
676 return -1;
677
678 if (bLoopOutput)
679 {
680 while (1)
681 {
682 if (DisplayOutput())
683 return -1;
684 Sleep(Interval*1000);
685 }
686 }
687
688 if (DisplayOutput())
689 return -1;
690 else
691 return 0;
692 }