- Implement -r Calling route.exe for output

- Rewrote DisplayOutput so simulates the MS netstat tool better and is now readable
- Fix ShowTcpTable to show correct endpoints on default, and expand it a little so it's easier to follow
- expand ShowUdpTable in the same manner
- Cleaner formatting in GetPortName

svn path=/trunk/; revision=18459
This commit is contained in:
Ged Murphy 2005-10-14 21:35:03 +00:00
parent 30a546e327
commit 901449fbf7
2 changed files with 151 additions and 199 deletions

View file

@ -31,10 +31,9 @@
/* /*
* TODO: * TODO:
* rewrite DisplayOutput * sort function return values.
* sort function return values. BOOL is crap
* implement -b, -o and -v * implement -b, -o and -v
* clean up GetPortName and GetIpHostName * clean up GetIpHostName
* command line parser needs more work * command line parser needs more work
*/ */
@ -45,9 +44,6 @@
#include <iphlpapi.h> #include <iphlpapi.h>
#include "netstat.h" #include "netstat.h"
CHAR localname[HOSTNAMELEN], remotename[HOSTNAMELEN];
CHAR remoteport[PORTNAMELEN], localport[PORTNAMELEN];
CHAR localaddr[ADDRESSLEN], remoteaddr[ADDRESSLEN];
enum ProtoType {IP, TCP, UDP, ICMP} Protocol; enum ProtoType {IP, TCP, UDP, ICMP} Protocol;
DWORD Interval; /* time to pause between printing output */ DWORD Interval; /* time to pause between printing output */
@ -70,6 +66,37 @@ TCHAR TcpState[][32] = {
}; };
/*
* format message string and display output
*/
DWORD DoFormatMessage(DWORD ErrorCode)
{
LPVOID lpMsgBuf;
DWORD RetVal;
if ((RetVal = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
ErrorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
(LPTSTR) &lpMsgBuf,
0,
NULL )))
{
_tprintf(_T("%s"), (LPTSTR)lpMsgBuf);
LocalFree(lpMsgBuf);
/* return number of TCHAR's stored in output buffer
* excluding '\0' - as FormatMessage does*/
return RetVal;
}
else
return 0;
}
/* /*
* *
* Parse command line parameters and set any options * Parse command line parameters and set any options
@ -132,7 +159,7 @@ BOOL ParseCmdline(int argc, char* argv[])
(--argv)[i]; /* move pointer back down to previous argv */ (--argv)[i]; /* move pointer back down to previous argv */
break; break;
case 'r' : case 'r' :
bDoShowRouteTable = FALSE; bDoShowRouteTable = TRUE;
break; break;
case 'v' : case 'v' :
_tprintf(_T("got v\n")); _tprintf(_T("got v\n"));
@ -159,12 +186,11 @@ BOOL ParseCmdline(int argc, char* argv[])
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
/* Simulate Microsofts netstat utility output. It's a bit
* ugly and over nested, but it is a fairly acurate simulation /*
* It was easier for testing, I'll rewrite it later with flags * Simulate Microsofts netstat utility output
* For now, it works*/ */
BOOL DisplayOutput() BOOL DisplayOutput()
// FIXME: This whole function needs rewriting
{ {
if (bNoOptions) if (bNoOptions)
{ {
@ -173,12 +199,6 @@ BOOL DisplayOutput()
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
if (bDoShowEthStats)
{
ShowEthernetStatistics();
return EXIT_SUCCESS;
}
if (bDoShowRouteTable) if (bDoShowRouteTable)
{ {
if (system("route print") == -1) if (system("route print") == -1)
@ -187,150 +207,70 @@ BOOL DisplayOutput()
_tprintf(_T("cannot find 'route.exe'\n")); _tprintf(_T("cannot find 'route.exe'\n"));
return EXIT_FAILURE; return EXIT_FAILURE;
} }
return EXIT_SUCCESS;
} }
/* output connections: -a */ if (bDoShowEthStats)
if (bDoShowAllCons)
{ {
/* filter out certain protocols: -p */ ShowEthernetStatistics();
if (bDoShowProtoCons) return EXIT_SUCCESS;
{
/* do we want to list the stats: -s */
if (bDoShowProtoStats)
{
switch (Protocol)
{
case IP :
ShowIpStatistics();
break;
case ICMP :
ShowIcmpStatistics();
break;
case TCP :
ShowTcpStatistics();
_tprintf(_T("\nActive Connections\n"));
_tprintf(_T("\n Proto Local Address Foreign Address State\n"));
ShowTcpTable();
break;
case UDP :
ShowUdpStatistics();
_tprintf(_T("\nActive Connections\n"));
_tprintf(_T("\n Proto Local Address Foreign Address State\n"));
ShowUdpTable();
break;
default :
break;
}
return EXIT_SUCCESS;
}
else
{
switch (Protocol)
{
case IP :
break;
case ICMP :
ShowIcmpStatistics();
break;
case TCP :
_tprintf(_T("\nActive Connections\n"));
_tprintf(_T("\n Proto Local Address Foreign Address State\n"));
ShowTcpTable();
break;
case UDP :
_tprintf(_T("\nActive Connections\n"));
_tprintf(_T("\n Proto Local Address Foreign Address State\n"));
ShowUdpTable();
break;
default :
break;
}
return EXIT_SUCCESS;
}
}
else
{
_tprintf(_T("\nActive Connections\n"));
_tprintf(_T("\n Proto Local Address Foreign Address State\n"));
ShowTcpTable();
ShowUdpTable();
return EXIT_SUCCESS;
}
} }
/* do we want to list the stats: -s */ if (bDoShowProtoCons)
if (bDoShowProtoStats)
{ {
if (bDoShowProtoCons) // -p switch (Protocol)
{ {
/* show individual protocols only */
switch (Protocol)
{
case IP : case IP :
ShowIpStatistics(); if (bDoShowProtoStats)
{
ShowIpStatistics();
return EXIT_SUCCESS;
}
break; break;
case ICMP : case ICMP :
ShowIcmpStatistics(); if (bDoShowProtoStats)
{
ShowIcmpStatistics();
return EXIT_SUCCESS;
}
break; break;
case TCP : case TCP :
ShowTcpStatistics(); if (bDoShowProtoStats)
ShowTcpStatistics();
_tprintf(_T("\nActive Connections\n")); _tprintf(_T("\nActive Connections\n"));
_tprintf(_T("\n Proto Local Address Foreign Address State\n")); _tprintf(_T("\n Proto Local Address Foreign Address State\n"));
ShowTcpTable(); ShowTcpTable();
break; break;
case UDP : case UDP :
ShowUdpStatistics(); if (bDoShowProtoStats)
ShowUdpStatistics();
_tprintf(_T("\nActive Connections\n")); _tprintf(_T("\nActive Connections\n"));
_tprintf(_T("\n Proto Local Address Foreign Address State\n")); _tprintf(_T("\n Proto Local Address Foreign Address State\n"));
ShowUdpTable(); ShowUdpTable();
break; break;
default : default :
break; break;
}
return EXIT_SUCCESS;
}
else
{
/* list the lot */
ShowIpStatistics();
ShowIcmpStatistics();
ShowTcpStatistics();
ShowUdpStatistics();
return EXIT_SUCCESS;
} }
} }
else if (bDoShowProtoStats)
{
ShowIpStatistics();
ShowIcmpStatistics();
ShowTcpStatistics();
ShowUdpStatistics();
return EXIT_SUCCESS;
}
else //if (bDoShowAllCons)
{
_tprintf(_T("\nActive Connections\n"));
_tprintf(_T("\n Proto Local Address Foreign Address State\n"));
ShowTcpTable();
ShowUdpTable();
}
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
/* format message string and display output */
DWORD DoFormatMessage(DWORD ErrorCode)
{
LPVOID lpMsgBuf;
DWORD RetVal;
if ((RetVal = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
ErrorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
(LPTSTR) &lpMsgBuf,
0,
NULL )))
{
_tprintf(_T("%s"), (LPTSTR)lpMsgBuf);
LocalFree(lpMsgBuf);
/* return number of TCHAR's stored in output buffer
* excluding '\0' - as FormatMessage does*/
return RetVal;
}
else
return 0;
}
VOID ShowIpStatistics() VOID ShowIpStatistics()
@ -490,8 +430,12 @@ VOID ShowTcpTable()
PMIB_TCPTABLE tcpTable; PMIB_TCPTABLE tcpTable;
DWORD error, dwSize; DWORD error, dwSize;
DWORD i; DWORD i;
CHAR HostIp[HOSTNAMELEN], HostPort[PORTNAMELEN];
CHAR RemoteIp[HOSTNAMELEN], RemotePort[PORTNAMELEN];
CHAR Host[ADDRESSLEN];
CHAR Remote[ADDRESSLEN];
// Get the table of TCP endpoints /* Get the table of TCP endpoints */
dwSize = 0; dwSize = 0;
error = GetTcpTable(NULL, &dwSize, TRUE); error = GetTcpTable(NULL, &dwSize, TRUE);
if (error != ERROR_INSUFFICIENT_BUFFER) if (error != ERROR_INSUFFICIENT_BUFFER)
@ -509,21 +453,26 @@ VOID ShowTcpTable()
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// Dump the TCP table /* Dump the TCP table */
for (i = 0; i < tcpTable->dwNumEntries; i++) for (i = 0; i < tcpTable->dwNumEntries; i++)
{ {
if (bDoShowAllCons || (tcpTable->table[i].dwState == /* If we aren't showing all connections, only display established, close wait
MIB_TCP_STATE_ESTAB)) * and time wait. This is the default output for netstat */
if (bDoShowAllCons || (tcpTable->table[i].dwState == MIB_TCP_STATE_ESTAB)
|| (tcpTable->table[i].dwState == MIB_TCP_STATE_CLOSE_WAIT)
|| (tcpTable->table[i].dwState == MIB_TCP_STATE_TIME_WAIT))
{ {
sprintf(localaddr, "%s:%s", /* I've split this up so it's easier to follow */
GetIpHostName(TRUE, tcpTable->table[i].dwLocalAddr, localname, HOSTNAMELEN), GetIpHostName(TRUE, tcpTable->table[i].dwLocalAddr, HostIp, HOSTNAMELEN);
GetPortName(tcpTable->table[i].dwLocalPort, "tcp", localport, PORTNAMELEN)); GetPortName(tcpTable->table[i].dwLocalPort, "tcp", HostPort, PORTNAMELEN);
sprintf(remoteaddr, "%s:%s", GetIpHostName(FALSE, tcpTable->table[i].dwRemoteAddr, RemoteIp, HOSTNAMELEN);
GetIpHostName(FALSE, tcpTable->table[i].dwRemoteAddr, remotename, HOSTNAMELEN), GetPortName(tcpTable->table[i].dwRemotePort, "tcp", RemotePort, PORTNAMELEN);
tcpTable->table[i].dwRemoteAddr ?
GetPortName(tcpTable->table[i].dwRemotePort, "tcp", remoteport, PORTNAMELEN): sprintf(Host, "%s:%s", HostIp, HostPort);
"0"); sprintf(Remote, "%s:%s", RemoteIp, RemotePort);
_tprintf(_T(" %-6s %-22s %-22s %s\n"), _T("TCP"), localaddr, remoteaddr, TcpState[tcpTable->table[i].dwState]);
_tprintf(_T(" %-6s %-22s %-22s %s\n"), _T("TCP"),
Host, Remote, TcpState[tcpTable->table[i].dwState]);
} }
} }
} }
@ -534,8 +483,10 @@ VOID ShowUdpTable()
PMIB_UDPTABLE udpTable; PMIB_UDPTABLE udpTable;
DWORD error, dwSize; DWORD error, dwSize;
DWORD i; DWORD i;
CHAR HostIp[HOSTNAMELEN], HostPort[PORTNAMELEN];
CHAR Host[ADDRESSLEN];
// Get the table of UDP endpoints /* Get the table of UDP endpoints */
dwSize = 0; dwSize = 0;
error = GetUdpTable(NULL, &dwSize, TRUE); error = GetUdpTable(NULL, &dwSize, TRUE);
if (error != ERROR_INSUFFICIENT_BUFFER) if (error != ERROR_INSUFFICIENT_BUFFER)
@ -553,38 +504,40 @@ VOID ShowUdpTable()
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// Dump the UDP table /* Dump the UDP table */
for (i = 0; i < udpTable->dwNumEntries; i++) for (i = 0; i < udpTable->dwNumEntries; i++)
{ {
sprintf(localaddr, "%s:%s",
GetIpHostName(TRUE, udpTable->table[i].dwLocalAddr, localname, HOSTNAMELEN), /* I've split this up so it's easier to follow */
GetPortName(udpTable->table[i].dwLocalPort, "tcp", localport, PORTNAMELEN)); GetIpHostName(TRUE, udpTable->table[i].dwLocalAddr, HostIp, HOSTNAMELEN);
_tprintf(_T(" %-6s %-22s %-22s\n"), _T("UDP"), localaddr, _T(":*:")); GetPortName(udpTable->table[i].dwLocalPort, "tcp", HostPort, PORTNAMELEN);
sprintf(Host, "%s:%s", HostIp, HostPort);
_tprintf(_T(" %-6s %-22s %-22s\n"), _T("UDP"), Host, _T(":*:"));
} }
} }
// /*
// GetPortName * Translate port numbers into their text equivalent if there is one
// */
// Translate port numbers into their text equivalent if there is one
//
PCHAR PCHAR
GetPortName(UINT port, PCHAR proto, PCHAR name, int namelen) GetPortName(UINT Port, PCHAR Proto, CHAR Name[], INT NameLen)
{ {
struct servent *psrvent; struct servent *pSrvent;
if (bDoShowNumbers) { if (bDoShowNumbers)
sprintf(name, "%d", htons((WORD)port)); {
return name; sprintf(Name, "%d", htons((WORD)Port));
return Name;
} }
// Try to translate to a name /* Try to translate to a name */
if ((psrvent = getservbyport(port, proto))) { if ((pSrvent = getservbyport(Port, Proto)))
strcpy(name, psrvent->s_name ); strcpy(Name, pSrvent->s_name );
} else { else
sprintf(name, "%d", htons((WORD)port)); sprintf(Name, "%d", htons((WORD)Port));
} return Name;
return name;
} }
@ -594,51 +547,51 @@ GetPortName(UINT port, PCHAR proto, PCHAR name, int namelen)
// Translate IP addresses into their name-resolved form if possible. // Translate IP addresses into their name-resolved form if possible.
// //
PCHAR PCHAR
GetIpHostName(BOOL local, UINT ipaddr, PCHAR name, int namelen) GetIpHostName(BOOL Local, UINT IpAddr, CHAR Name[], int NameLen)
{ {
// struct hostent *phostent; // struct hostent *phostent;
UINT nipaddr; UINT nIpAddr;
// Does the user want raw numbers? // Does the user want raw numbers?
nipaddr = htonl(ipaddr); nIpAddr = htonl(IpAddr);
if (bDoShowNumbers) { if (bDoShowNumbers) {
sprintf(name, "%d.%d.%d.%d", sprintf(Name, "%d.%d.%d.%d",
(nipaddr >> 24) & 0xFF, (nIpAddr >> 24) & 0xFF,
(nipaddr >> 16) & 0xFF, (nIpAddr >> 16) & 0xFF,
(nipaddr >> 8) & 0xFF, (nIpAddr >> 8) & 0xFF,
(nipaddr) & 0xFF); (nIpAddr) & 0xFF);
return name; return Name;
} }
name[0] = _T('\0'); Name[0] = L'\0';
// Try to translate to a name // Try to translate to a name
if (!ipaddr) { if (!IpAddr) {
if (!local) { if (!Local) {
sprintf(name, "%d.%d.%d.%d", sprintf(Name, "%d.%d.%d.%d",
(nipaddr >> 24) & 0xFF, (nIpAddr >> 24) & 0xFF,
(nipaddr >> 16) & 0xFF, (nIpAddr >> 16) & 0xFF,
(nipaddr >> 8) & 0xFF, (nIpAddr >> 8) & 0xFF,
(nipaddr) & 0xFF); (nIpAddr) & 0xFF);
} else { } else {
//gethostname(name, namelen); //gethostname(name, namelen);
} }
} else if (ipaddr == 0x0100007f) { } else if (IpAddr == 0x0100007f) {
if (local) { if (Local) {
//gethostname(name, namelen); //gethostname(name, namelen);
} else { } else {
strcpy(name, "localhost"); strcpy(Name, "localhost");
} }
// } else if (phostent = gethostbyaddr((char*)&ipaddr, sizeof(nipaddr), PF_INET)) { // } else if (phostent = gethostbyaddr((char*)&ipaddr, sizeof(nipaddr), PF_INET)) {
// strcpy(name, phostent->h_name); // strcpy(name, phostent->h_name);
} else { } else {
sprintf(name, "%d.%d.%d.%d", sprintf(Name, "%d.%d.%d.%d",
((nipaddr >> 24) & 0x000000FF), ((nIpAddr >> 24) & 0x000000FF),
((nipaddr >> 16) & 0x000000FF), ((nIpAddr >> 16) & 0x000000FF),
((nipaddr >> 8) & 0x000000FF), ((nIpAddr >> 8) & 0x000000FF),
((nipaddr) & 0x000000FF)); ((nIpAddr) & 0x000000FF));
} }
return name; return Name;
} }
VOID Usage() VOID Usage()

View file

@ -1,6 +1,5 @@
// Maximum string lengths for ASCII ip address and port names /* Maximum string lengths for ASCII ip address and port names */
//
#define HOSTNAMELEN 256 #define HOSTNAMELEN 256
#define PORTNAMELEN 256 #define PORTNAMELEN 256
#define ADDRESSLEN HOSTNAMELEN+PORTNAMELEN #define ADDRESSLEN HOSTNAMELEN+PORTNAMELEN
@ -55,7 +54,7 @@ VOID ShowUdpStatistics(VOID);
VOID ShowEthernetStatistics(VOID); VOID ShowEthernetStatistics(VOID);
VOID ShowTcpTable(VOID); VOID ShowTcpTable(VOID);
VOID ShowUdpTable(VOID); VOID ShowUdpTable(VOID);
PCHAR GetPortName(UINT port, PCHAR proto, PCHAR name, int namelen); PCHAR GetPortName(UINT Port, PCHAR Proto, CHAR Name[PORTNAMELEN], INT NameLen);
PCHAR GetIpHostName(BOOL local, UINT ipaddr, PCHAR name, int namelen); PCHAR GetIpHostName(BOOL local, UINT ipaddr, CHAR name[HOSTNAMELEN], int namelen);
VOID Usage(VOID); VOID Usage(VOID);