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