Copy w32api from trunk
[reactos.git] / reactos / apps / utils / net / netstat / netstat.c
1 /*
2 * netstat - display IP stack statistics.
3 *
4 * This source code is in the PUBLIC DOMAIN and has NO WARRANTY.
5 *
6 * Robert Dickenson <robd@reactos.org>, August 15, 2002.
7 */
8
9 // Extensive reference made and use of source to netstatp by:
10 // Copyright (C) 1998-2002 Mark Russinovich
11 // www.sysinternals.com
12
13 #define ANY_SIZE 1
14
15 #include <windows.h>
16 #include <winsock.h>
17 #include <tchar.h>
18 #include <stdio.h>
19 #include <time.h>
20
21 #include <iptypes.h>
22 #include <ipexport.h>
23 #include <tlhelp32.h>
24 #include <iphlpapi.h>
25 #include <snmp.h>
26
27 #include "trace.h"
28 #include "resource.h"
29
30
31 #define MAX_RESLEN 4000
32
33 //
34 // Possible TCP endpoint states
35 //
36 static char TcpState[][32] = {
37 "???",
38 "CLOSED",
39 "LISTENING",
40 "SYN_SENT",
41 "SYN_RCVD",
42 "ESTABLISHED",
43 "FIN_WAIT1",
44 "FIN_WAIT2",
45 "CLOSE_WAIT",
46 "CLOSING",
47 "LAST_ACK",
48 "TIME_WAIT",
49 "DELETE_TCB"
50 };
51
52 VOID PrintError(DWORD ErrorCode)
53 {
54 LPVOID lpMsgBuf;
55
56 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
57 NULL, ErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
58 (LPTSTR)&lpMsgBuf, 0, NULL);
59 printf("%s\n", lpMsgBuf);
60 LocalFree(lpMsgBuf);
61 }
62
63 static void ShowTcpStatistics()
64 {
65 MIB_TCPSTATS TcpStatsMIB;
66 GetTcpStatistics(&TcpStatsMIB);
67
68 _tprintf(_T("TCP/IP Statistics\t\n"));
69 _tprintf(_T(" time-out algorithm:\t\t%d\n"), TcpStatsMIB.dwRtoAlgorithm);
70 _tprintf(_T(" minimum time-out:\t\t%d\n"), TcpStatsMIB.dwRtoMin);
71 _tprintf(_T(" maximum time-out:\t\t%d\n"), TcpStatsMIB.dwRtoMax);
72 _tprintf(_T(" maximum connections:\t\t%d\n"), TcpStatsMIB.dwMaxConn);
73 _tprintf(_T(" active opens:\t\t\t%d\n"), TcpStatsMIB.dwActiveOpens);
74 _tprintf(_T(" passive opens:\t\t\t%d\n"), TcpStatsMIB.dwPassiveOpens);
75 _tprintf(_T(" failed attempts:\t\t%d\n"), TcpStatsMIB.dwAttemptFails);
76 _tprintf(_T(" established connections reset:\t%d\n"), TcpStatsMIB.dwEstabResets);
77 _tprintf(_T(" established connections:\t%d\n"), TcpStatsMIB.dwCurrEstab);
78 _tprintf(_T(" segments received:\t\t%d\n"), TcpStatsMIB.dwInSegs);
79 _tprintf(_T(" segment sent:\t\t\t%d\n"), TcpStatsMIB.dwOutSegs);
80 _tprintf(_T(" segments retransmitted:\t\t%d\n"), TcpStatsMIB.dwRetransSegs);
81 _tprintf(_T(" incoming errors:\t\t%d\n"), TcpStatsMIB.dwInErrs);
82 _tprintf(_T(" outgoing resets:\t\t%d\n"), TcpStatsMIB.dwOutRsts);
83 _tprintf(_T(" cumulative connections:\t\t%d\n"), TcpStatsMIB.dwNumConns);
84 }
85
86 static void ShowUdpStatistics()
87 {
88 MIB_UDPSTATS UDPStatsMIB;
89 GetUdpStatistics(&UDPStatsMIB);
90
91 _tprintf(_T("UDP Statistics\t\n"));
92 _tprintf(_T(" received datagrams:\t\t\t%d\n"), UDPStatsMIB.dwInDatagrams);
93 _tprintf(_T(" datagrams for which no port exists:\t%d\n"), UDPStatsMIB.dwNoPorts);
94 _tprintf(_T(" errors on received datagrams:\t\t%d\n"), UDPStatsMIB.dwInErrors);
95 _tprintf(_T(" sent datagrams:\t\t\t\t%d\n"), UDPStatsMIB.dwOutDatagrams);
96 _tprintf(_T(" number of entries in listener table:\t%d\n"), UDPStatsMIB.dwNumAddrs);
97 }
98
99 static void ShowIpStatistics()
100 {
101 MIB_IPSTATS IPStatsMIB;
102 GetIpStatistics(&IPStatsMIB);
103
104 _tprintf(_T("IP Statistics\t\n"));
105 _tprintf(_T(" IP forwarding enabled or disabled:\t%d\n"), IPStatsMIB.dwForwarding);
106 _tprintf(_T(" default time-to-live:\t\t\t%d\n"), IPStatsMIB.dwDefaultTTL);
107 _tprintf(_T(" datagrams received:\t\t\t%d\n"), IPStatsMIB.dwInReceives);
108 _tprintf(_T(" received header errors:\t\t\t%d\n"), IPStatsMIB.dwInHdrErrors);
109 _tprintf(_T(" received address errors:\t\t%d\n"), IPStatsMIB.dwInAddrErrors);
110 _tprintf(_T(" datagrams forwarded:\t\t\t%d\n"), IPStatsMIB.dwForwDatagrams);
111 _tprintf(_T(" datagrams with unknown protocol:\t%d\n"), IPStatsMIB.dwInUnknownProtos);
112 _tprintf(_T(" received datagrams discarded:\t\t%d\n"), IPStatsMIB.dwInDiscards);
113 _tprintf(_T(" received datagrams delivered:\t\t%d\n"), IPStatsMIB.dwInDelivers);
114 _tprintf(_T(" sent datagrams discarded:\t\t%d\n"), IPStatsMIB.dwOutDiscards);
115 _tprintf(_T(" datagrams for which no route exists:\t%d\n"), IPStatsMIB.dwOutNoRoutes);
116 _tprintf(_T(" datagrams for which frags didn't arrive:%d\n"), IPStatsMIB.dwReasmTimeout);
117 _tprintf(_T(" datagrams requiring reassembly:\t\t%d\n"), IPStatsMIB.dwReasmReqds);
118 _tprintf(_T(" successful reassemblies:\t\t%d\n"), IPStatsMIB.dwReasmOks);
119 _tprintf(_T(" failed reassemblies:\t\t\t%d\n"), IPStatsMIB.dwReasmFails);
120 _tprintf(_T(" successful fragmentations:\t\t%d\n"), IPStatsMIB.dwFragOks);
121 _tprintf(_T(" failed fragmentations:\t\t\t%d\n"), IPStatsMIB.dwFragFails);
122 _tprintf(_T(" datagrams fragmented:\t\t\t%d\n"), IPStatsMIB.dwFragCreates);
123 _tprintf(_T(" number of interfaces on computer:\t%d\n"), IPStatsMIB.dwNumIf);
124 _tprintf(_T(" number of IP address on computer:\t%d\n"), IPStatsMIB.dwNumAddr);
125 _tprintf(_T(" number of routes in routing table:\t%d\n"), IPStatsMIB.dwNumRoutes);
126 }
127
128 static void ShowNetworkParams()
129 {
130 FIXED_INFO* FixedInfo;
131 IP_ADDR_STRING* pIPAddr;
132 ULONG ulOutBufLen;
133 DWORD dwRetVal;
134
135 _tprintf(_T("Network Parameters\t\n"));
136
137 FixedInfo = (FIXED_INFO*)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
138 ulOutBufLen = sizeof(FIXED_INFO);
139 if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &ulOutBufLen)) {
140 GlobalFree(FixedInfo);
141 FixedInfo =(FIXED_INFO*)GlobalAlloc(GPTR, ulOutBufLen);
142 }
143 if (dwRetVal = GetNetworkParams(FixedInfo, &ulOutBufLen)) {
144 _tprintf(_T("Call to GetNetworkParams failed. Return Value: %08x\n"), dwRetVal);
145 } else {
146 printf(" Host Name: %s", FixedInfo->HostName);
147 printf("\n Domain Name: %s", FixedInfo->DomainName);
148 printf("\n DNS Servers:\t%s\n", FixedInfo->DnsServerList.IpAddress.String);
149 pIPAddr = FixedInfo->DnsServerList.Next;
150 while (pIPAddr) {
151 printf("\t\t\t%s\n", pIPAddr->IpAddress.String);
152 pIPAddr = pIPAddr->Next;
153 }
154 }
155 }
156
157 static void ShowAdapterInfo()
158 {
159 IP_ADAPTER_INFO* pAdaptorInfo;
160 ULONG ulOutBufLen;
161 DWORD dwRetVal;
162
163 _tprintf(_T("\nAdaptor Information\t\n"));
164 pAdaptorInfo = (IP_ADAPTER_INFO*)GlobalAlloc(GPTR, sizeof(IP_ADAPTER_INFO));
165 ulOutBufLen = sizeof(IP_ADAPTER_INFO);
166
167 if (ERROR_BUFFER_OVERFLOW == GetAdaptersInfo(pAdaptorInfo, &ulOutBufLen)) {
168 GlobalFree(pAdaptorInfo);
169 pAdaptorInfo = (IP_ADAPTER_INFO*)GlobalAlloc(GPTR, ulOutBufLen);
170 }
171 if (dwRetVal = GetAdaptersInfo(pAdaptorInfo, &ulOutBufLen)) {
172 _tprintf(_T("Call to GetAdaptersInfo failed. Return Value: %08x\n"), dwRetVal);
173 } else {
174 while (pAdaptorInfo) {
175 printf(" AdapterName: %s\n", pAdaptorInfo->AdapterName);
176 printf(" Description: %s\n", pAdaptorInfo->Description);
177 pAdaptorInfo = pAdaptorInfo->Next;
178 }
179 }
180 }
181
182 /*
183 typedef struct {
184 UINT idLength;
185 UINT* ids;
186 } AsnObjectIdentifier;
187
188 VOID SnmpUtilPrintAsnAny(AsnAny* pAny); // pointer to value to print
189 VOID SnmpUtilPrintOid(AsnObjectIdentifier* Oid); // object identifier to print
190
191 */
192 void test_snmp(void)
193 {
194 int nBytes = 500;
195 BYTE* pCache;
196
197 pCache = (BYTE*)SnmpUtilMemAlloc(nBytes);
198 if (pCache != NULL) {
199 AsnObjectIdentifier* pOidSrc = NULL;
200 AsnObjectIdentifier AsnObId;
201 if (SnmpUtilOidCpy(&AsnObId, pOidSrc)) {
202 //
203 //
204 //
205 SnmpUtilOidFree(&AsnObId);
206 }
207 SnmpUtilMemFree(pCache);
208 } else {
209 _tprintf(_T("ERROR: call to SnmpUtilMemAlloc() failed\n"));
210 }
211 }
212
213 // Maximum string lengths for ASCII ip address and port names
214 //
215 #define HOSTNAMELEN 256
216 #define PORTNAMELEN 256
217 #define ADDRESSLEN HOSTNAMELEN+PORTNAMELEN
218
219 //
220 // Our option flags
221 //
222 #define FLAG_SHOW_ALL_ENDPOINTS 1
223 #define FLAG_SHOW_ETH_STATS 2
224 #define FLAG_SHOW_NUMBERS 3
225 #define FLAG_SHOW_PROT_CONNECTIONS 4
226 #define FLAG_SHOW_ROUTE_TABLE 5
227 #define FLAG_SHOW_PROT_STATS 6
228 #define FLAG_SHOW_INTERVAL 7
229
230
231 // Undocumented extended information structures available only on XP and higher
232
233 typedef struct {
234 DWORD dwState; // state of the connection
235 DWORD dwLocalAddr; // address on local computer
236 DWORD dwLocalPort; // port number on local computer
237 DWORD dwRemoteAddr; // address on remote computer
238 DWORD dwRemotePort; // port number on remote computer
239 DWORD dwProcessId;
240 } MIB_TCPEXROW, *PMIB_TCPEXROW;
241
242 typedef struct {
243 DWORD dwNumEntries;
244 MIB_TCPEXROW table[ANY_SIZE];
245 } MIB_TCPEXTABLE, *PMIB_TCPEXTABLE;
246
247 typedef struct {
248 DWORD dwLocalAddr; // address on local computer
249 DWORD dwLocalPort; // port number on local computer
250 DWORD dwProcessId;
251 } MIB_UDPEXROW, *PMIB_UDPEXROW;
252
253 typedef struct {
254 DWORD dwNumEntries;
255 MIB_UDPEXROW table[ANY_SIZE];
256 } MIB_UDPEXTABLE, *PMIB_UDPEXTABLE;
257
258
259 //
260 // GetPortName
261 //
262 // Translate port numbers into their text equivalent if there is one
263 //
264 PCHAR
265 GetPortName(DWORD Flags, UINT port, PCHAR proto, PCHAR name, int namelen)
266 {
267 struct servent *psrvent;
268
269 if (Flags & FLAG_SHOW_NUMBERS) {
270 sprintf(name, "%d", htons((WORD)port));
271 return name;
272 }
273 // Try to translate to a name
274 if (psrvent = getservbyport(port, proto)) {
275 strcpy(name, psrvent->s_name );
276 } else {
277 sprintf(name, "%d", htons((WORD)port));
278 }
279 return name;
280 }
281
282
283 //
284 // GetIpHostName
285 //
286 // Translate IP addresses into their name-resolved form if possible.
287 //
288 PCHAR
289 GetIpHostName(DWORD Flags, BOOL local, UINT ipaddr, PCHAR name, int namelen)
290 {
291 // struct hostent *phostent;
292 UINT nipaddr;
293
294 // Does the user want raw numbers?
295 nipaddr = htonl(ipaddr);
296 if (Flags & FLAG_SHOW_NUMBERS ) {
297 sprintf(name, "%d.%d.%d.%d",
298 (nipaddr >> 24) & 0xFF,
299 (nipaddr >> 16) & 0xFF,
300 (nipaddr >> 8) & 0xFF,
301 (nipaddr) & 0xFF);
302 return name;
303 }
304
305 name[0] = _T('\0');
306
307 // Try to translate to a name
308 if (!ipaddr) {
309 if (!local) {
310 sprintf(name, "%d.%d.%d.%d",
311 (nipaddr >> 24) & 0xFF,
312 (nipaddr >> 16) & 0xFF,
313 (nipaddr >> 8) & 0xFF,
314 (nipaddr) & 0xFF);
315 } else {
316 //gethostname(name, namelen);
317 }
318 } else if (ipaddr == 0x0100007f) {
319 if (local) {
320 //gethostname(name, namelen);
321 } else {
322 strcpy(name, "localhost");
323 }
324 // } else if (phostent = gethostbyaddr((char*)&ipaddr, sizeof(nipaddr), PF_INET)) {
325 // strcpy(name, phostent->h_name);
326 } else {
327 #if 0
328 int i1, i2, i3, i4;
329
330 i1 = (nipaddr >> 24) & 0x000000FF;
331 i2 = (nipaddr >> 16) & 0x000000FF;
332 i3 = (nipaddr >> 8) & 0x000000FF;
333 i4 = (nipaddr) & 0x000000FF;
334
335 i1 = 10;
336 i2 = 20;
337 i3 = 30;
338 i4 = 40;
339
340 sprintf(name, "%d.%d.%d.%d", i1,i2,i3,i4);
341 #else
342 sprintf(name, "%d.%d.%d.%d",
343 ((nipaddr >> 24) & 0x000000FF),
344 ((nipaddr >> 16) & 0x000000FF),
345 ((nipaddr >> 8) & 0x000000FF),
346 ((nipaddr) & 0x000000FF));
347 #endif
348 }
349 return name;
350 }
351
352 BOOLEAN usage(void)
353 {
354 TCHAR buffer[MAX_RESLEN];
355
356 int length = LoadString(GetModuleHandle(NULL), IDS_APP_USAGE, buffer, sizeof(buffer)/sizeof(buffer[0]));
357 _fputts(buffer, stderr);
358 return FALSE;
359 }
360
361 //
362 // GetOptions
363 //
364 // Parses the command line arguments.
365 //
366 BOOLEAN
367 GetOptions(int argc, char *argv[], PDWORD pFlags)
368 {
369 int i, j;
370 BOOLEAN skipArgument;
371
372 *pFlags = 0;
373 for (i = 1; i < argc; i++) {
374 skipArgument = FALSE;
375 switch (argv[i][0]) {
376 case '-':
377 case '/':
378 j = 1;
379 while (argv[i][j]) {
380 switch (toupper(argv[i][j])) {
381 case 'A':
382 *pFlags |= FLAG_SHOW_ALL_ENDPOINTS;
383 break;
384 case 'E':
385 *pFlags |= FLAG_SHOW_ETH_STATS;
386 break;
387 case 'N':
388 *pFlags |= FLAG_SHOW_NUMBERS;
389 break;
390 case 'P':
391 *pFlags |= FLAG_SHOW_PROT_CONNECTIONS;
392 break;
393 case 'R':
394 *pFlags |= FLAG_SHOW_ROUTE_TABLE;
395 break;
396 case 'S':
397 *pFlags |= FLAG_SHOW_PROT_STATS;
398 break;
399 default:
400 return usage();
401 }
402 if (skipArgument) break;
403 j++;
404 }
405 break;
406 case 'i':
407 *pFlags |= FLAG_SHOW_INTERVAL;
408 break;
409 default:
410 return usage();
411 }
412 }
413 return TRUE;
414 }
415
416 #if 1
417
418 CHAR localname[HOSTNAMELEN], remotename[HOSTNAMELEN];
419 CHAR remoteport[PORTNAMELEN], localport[PORTNAMELEN];
420 CHAR localaddr[ADDRESSLEN], remoteaddr[ADDRESSLEN];
421
422 int main(int argc, char *argv[])
423 {
424 PMIB_TCPTABLE tcpTable;
425 PMIB_UDPTABLE udpTable;
426 DWORD error, dwSize;
427 DWORD i, flags;
428
429 // Get options
430 if (!GetOptions(argc, argv, &flags)) {
431 return -1;
432 } else {
433 // Get the table of TCP endpoints
434 dwSize = 0;
435 error = GetTcpTable(NULL, &dwSize, TRUE);
436 if (error != ERROR_INSUFFICIENT_BUFFER) {
437 printf("Failed to snapshot TCP endpoints.\n");
438 PrintError(error);
439 return -1;
440 }
441 tcpTable = (PMIB_TCPTABLE)malloc(dwSize);
442 error = GetTcpTable(tcpTable, &dwSize, TRUE );
443 if (error) {
444 printf("Failed to snapshot TCP endpoints table.\n");
445 PrintError(error);
446 return -1;
447 }
448
449 // Get the table of UDP endpoints
450 dwSize = 0;
451 error = GetUdpTable(NULL, &dwSize, TRUE);
452 if (error != ERROR_INSUFFICIENT_BUFFER) {
453 printf("Failed to snapshot UDP endpoints.\n");
454 PrintError(error);
455 return -1;
456 }
457 udpTable = (PMIB_UDPTABLE)malloc(dwSize);
458 error = GetUdpTable(udpTable, &dwSize, TRUE);
459 if (error) {
460 printf("Failed to snapshot UDP endpoints table.\n");
461 PrintError(error);
462 return -1;
463 }
464
465 // Dump the TCP table
466 for (i = 0; i < tcpTable->dwNumEntries; i++) {
467 if (flags & FLAG_SHOW_ALL_ENDPOINTS ||
468 tcpTable->table[i].dwState == MIB_TCP_STATE_ESTAB) {
469 sprintf(localaddr, "%s:%s",
470 GetIpHostName(flags, TRUE, tcpTable->table[i].dwLocalAddr, localname, HOSTNAMELEN),
471 GetPortName(flags, tcpTable->table[i].dwLocalPort, "tcp", localport, PORTNAMELEN));
472 sprintf(remoteaddr, "%s:%s",
473 GetIpHostName(flags, FALSE, tcpTable->table[i].dwRemoteAddr, remotename, HOSTNAMELEN),
474 tcpTable->table[i].dwRemoteAddr ?
475 GetPortName(flags, tcpTable->table[i].dwRemotePort, "tcp", remoteport, PORTNAMELEN):
476 "0");
477 printf("%4s\tState: %s\n", "[TCP]", TcpState[tcpTable->table[i].dwState]);
478 printf(" Local: %s\n Remote: %s\n", localaddr, remoteaddr);
479 }
480 }
481 // Dump the UDP table
482 if (flags & FLAG_SHOW_ALL_ENDPOINTS) {
483 for (i = 0; i < udpTable->dwNumEntries; i++) {
484 sprintf(localaddr, "%s:%s",
485 GetIpHostName(flags, TRUE, udpTable->table[i].dwLocalAddr, localname, HOSTNAMELEN),
486 GetPortName(flags, udpTable->table[i].dwLocalPort, "tcp", localport, PORTNAMELEN));
487 printf("%4s", "[UDP]");
488 printf(" Local: %s\n Remote: %s\n", localaddr, "*.*.*.*:*");
489 }
490 }
491 }
492 printf("\n");
493 return 0;
494 }
495
496 #else
497
498 int main(int argc, char *argv[])
499 {
500 if (argc > 1) {
501 usage();
502 return 1;
503 }
504
505 _tprintf(_T("\nActive Connections\n\n")\
506 _T(" Proto Local Address Foreign Address State\n\n"));
507 test_snmp();
508
509 ShowTcpStatistics();
510 ShowUdpStatistics();
511 ShowIpStatistics();
512 ShowNetworkParams();
513 ShowAdapterInfo();
514
515 return 0;
516 }
517
518 #endif