2025-11-28 00:35:46 +09:00

558 lines
16 KiB
C++

/*---------------------------------------------------------------------------
Copyright (c) 1998 - 2000 Microsoft Corporation
Module Name: IpStat.exe
File : IpStat.cpp
Description: This file demonstrates the use of IP Helper APIs to
get IP statistics.
Author:
Frank Li April 21, 1998
Revision History:
Who When What
-------- -------- ----------------------------------
Frank Li 04-21-98 created
---------------------------------------------------------------------------*/
#include "IpStat.h"
void Usage(char * pszProgramName)
{
printf("Manipulates IP Statistics.\n\n");
printf("%s -p proto Shows connections for the protocol specified\n", pszProgramName);
printf(" by proto, proto may be tcp or udp.\n");
printf("%s -s [-p proto] Displays per-protocol statistics.\n", pszProgramName);
printf(" By default, statistics are shown for\n");
printf(" IP, ICMP, TCP and UDP; the -p option\n");
printf(" may be used to specify a subset of the default.\n");
printf("Examples:\n\n");
printf("> IpStat -p tcp\n");
printf("> IpStat -s\n");
WSACleanup();
exit(1);
}
void _cdecl main(int argc, char **argv)
{
WORD wVersionRequested = MAKEWORD(1,1);
WSADATA wsaData;
int nRet;
nRet = WSAStartup(wVersionRequested, &wsaData);
if (wsaData.wVersion != wVersionRequested)
{
fprintf(stderr,"\n Wrong version\n");
return;
}
if ((argc < 2) || (argv[1][0] != '-'))
Usage("IpStat");
if (strlen(argv[1]) > 2)
Usage("IpStat");
switch(argv[1][1])
{
case 'p':
// Print connection table
if (argc == 3)
DoGetConnTable(argv[2]);
else
Usage("IpStat");
break;
case 's':
// show statistics
if (argc == 4 && argv[2][1] == 'p')
DoGetStat(argv[3]); // Get stat for a specific protocol
else if (argc == 2)
DoGetStat(); // Get stat for all protocols
else
Usage("IpStat");
break;
default:
// help
Usage("IpStat");
break;
}
WSACleanup();
}
void DoGetConnTable(char* pszProto)
{
DWORD dwStatus;
if (_strnicmp(pszProto, "tcp", 3) == 0)
{
//Print Tcp Connnection Table
PMIB_TCPTABLE pTcpTable = NULL;
dwStatus = MyGetTcpTable(pTcpTable, TRUE);
if (dwStatus != NO_ERROR)
{
printf("Ipstat: Couldn't get tcp connection table.\n");
if (pTcpTable)
free(pTcpTable);
return;
}
else
{
DumpTcpTable(pTcpTable);
free(pTcpTable);
}
}
else if (_strnicmp(pszProto, "udp", 3) == 0)
{
//Print Udp Table
PMIB_UDPTABLE pUdpTable = NULL;
dwStatus = MyGetUdpTable(pUdpTable, TRUE);
if (dwStatus != NO_ERROR)
{
printf("Ipstat: Couldn't get udp table.\n");
if (pUdpTable)
free(pUdpTable);
return;
}
else
{
DumpUdpTable(pUdpTable);
free(pUdpTable);
}
}
else
Usage("IpStat");
}
void DoGetStat(char* pszProto /*NULL*/)
{
if (pszProto == NULL)
{
// by default, display all statistics
{
PMIB_IPSTATS pIpStats = NULL;
if (MyGetIpStatistics(pIpStats) != NO_ERROR)
printf("IpStat: error in getting ip statistics.\n");
else
PrintIpStats(pIpStats);
if (pIpStats)
free(pIpStats);
}
{
PMIB_ICMP pIcmpStats = NULL;
if (MyGetIcmpStatistics(pIcmpStats) != NO_ERROR)
printf("IpStat: error in getting icmp statistics.\n");
else
PrintIcmpStats(&(pIcmpStats->stats));
if (pIcmpStats)
free(pIcmpStats);
}
{
PMIB_TCPSTATS pTcpStats = NULL;
if (MyGetTcpStatistics(pTcpStats) != NO_ERROR)
printf("IpStat: error in getting tcp statistics.\n");
else
PrintTcpStats(pTcpStats);
if (pTcpStats)
free(pTcpStats);
}
{
PMIB_UDPSTATS pUdpStats = NULL;
if (MyGetUdpStatistics(pUdpStats) != NO_ERROR)
printf("IpStat: error in getting udp statistics.\n");
else
PrintUdpStats(pUdpStats);
if (pUdpStats)
free(pUdpStats);
}
}
// make sure the protocol specified was ip not ipx or some other string
else if (strlen(pszProto) == 2 && _strnicmp(pszProto, "ip", 2) == 0)
{
PMIB_IPSTATS pIpStats = NULL;
if (MyGetIpStatistics(pIpStats) != NO_ERROR)
printf("IpStat: error in getting ip statistics.\n");
else
PrintIpStats(pIpStats);
if (pIpStats)
free(pIpStats);
}
else if (_strnicmp(pszProto, "icmp", 4) == 0)
{
PMIB_ICMP pIcmpStats = NULL;
if (MyGetIcmpStatistics(pIcmpStats) != NO_ERROR)
printf("IpStat: error in getting icmp statistics.\n");
else
PrintIcmpStats(&(pIcmpStats->stats));
if (pIcmpStats)
free(pIcmpStats);
}
else if (_strnicmp(pszProto, "tcp", 3) == 0)
{
PMIB_TCPSTATS pTcpStats = NULL;
if (MyGetTcpStatistics(pTcpStats) != NO_ERROR)
printf("IpStat: error in getting tcp statistics.\n");
else
PrintTcpStats(pTcpStats);
if (pTcpStats)
free(pTcpStats);
}
else if (_strnicmp(pszProto, "udp", 3) == 0)
{
PMIB_UDPSTATS pUdpStats = NULL;
if (MyGetUdpStatistics(pUdpStats) != NO_ERROR)
printf("IpStat: error in getting udp statistics.\n");
else
PrintUdpStats(pUdpStats);
if (pUdpStats)
free(pUdpStats);
}
else
printf("IpStat: no available statistics for %s.\n", pszProto);
}
void DumpTcpTable(PMIB_TCPTABLE pTcpTable)
{
char strState[MAX_STRLEN];
struct in_addr inadLocal, inadRemote;
DWORD dwRemotePort = 0;
char szLocalIp[MAX_STRLEN];
char szRemIp[MAX_STRLEN];
if (pTcpTable != NULL)
{
printf("TCP TABLE\n");
printf("%20s %10s %20s %10s %s\n", "Loc Addr", "Loc Port", "Rem Addr",
"Rem Port", "State");
for (UINT i = 0; i < pTcpTable->dwNumEntries; ++i)
{
switch (pTcpTable->table[i].dwState)
{
case MIB_TCP_STATE_CLOSED:
strcpy_s(strState, MAX_STRLEN, "CLOSED");
break;
case MIB_TCP_STATE_TIME_WAIT:
strcpy_s(strState, MAX_STRLEN, "TIME_WAIT");
break;
case MIB_TCP_STATE_LAST_ACK:
strcpy_s(strState, MAX_STRLEN, "LAST_ACK");
break;
case MIB_TCP_STATE_CLOSING:
strcpy_s(strState, MAX_STRLEN, "CLOSING");
break;
case MIB_TCP_STATE_CLOSE_WAIT:
strcpy_s(strState, MAX_STRLEN, "CLOSE_WAIT");
break;
case MIB_TCP_STATE_FIN_WAIT1:
strcpy_s(strState, MAX_STRLEN, "FIN_WAIT1");
break;
case MIB_TCP_STATE_ESTAB:
strcpy_s(strState, MAX_STRLEN, "ESTAB");
break;
case MIB_TCP_STATE_SYN_RCVD:
strcpy_s(strState, MAX_STRLEN, "SYN_RCVD");
break;
case MIB_TCP_STATE_SYN_SENT:
strcpy_s(strState, MAX_STRLEN, "SYN_SENT");
break;
case MIB_TCP_STATE_LISTEN:
strcpy_s(strState, MAX_STRLEN, "LISTEN");
break;
case MIB_TCP_STATE_DELETE_TCB:
strcpy_s(strState, MAX_STRLEN, "DELETE");
break;
default:
printf("Error: unknown state!\n");
break;
}
inadLocal.s_addr = pTcpTable->table[i].dwLocalAddr;
if (strcmp(strState, "LISTEN") != 0)
{
dwRemotePort = pTcpTable->table[i].dwRemotePort;
}
else
dwRemotePort = 0;
inadRemote.s_addr = pTcpTable->table[i].dwRemoteAddr;
strcpy_s(szLocalIp, MAX_STRLEN, inet_ntoa(inadLocal));
strcpy_s(szRemIp, MAX_STRLEN, inet_ntoa(inadRemote));
printf("%20s %10u %20s %10u %s\n",
szLocalIp, ntohs((unsigned short)(0x0000FFFF & pTcpTable->table[i].dwLocalPort)),
szRemIp, ntohs((unsigned short)(0x0000FFFF & dwRemotePort)),
strState);
}
}
}
void DumpUdpTable(PMIB_UDPTABLE pUdpTable)
{
struct in_addr inadLocal;
if (pUdpTable != NULL)
{
printf("UDP TABLE\n");
printf("%20s %10s\n", "Loc Addr", "Loc Port");
for (UINT i = 0; i < pUdpTable->dwNumEntries; ++i)
{
inadLocal.s_addr = pUdpTable->table[i].dwLocalAddr;
printf("%20s %10u \n",
inet_ntoa(inadLocal), ntohs((unsigned short)(0x0000FFFF & pUdpTable->table[i].dwLocalPort)));
}
}
}
//----------------------------------------------------------------------------
// Wrapper to GetTcpTable()
//----------------------------------------------------------------------------
DWORD MyGetTcpTable(PMIB_TCPTABLE& pTcpTable, BOOL fOrder)
{
DWORD status = NO_ERROR;
DWORD statusRetry = NO_ERROR;
DWORD dwActualSize = 0;
// query for buffer size needed
status = GetTcpTable(pTcpTable, &dwActualSize, fOrder);
if (status == NO_ERROR)
{
printf("No error\n");
return status;
}
else if (status == ERROR_INSUFFICIENT_BUFFER)
{
// need more space
pTcpTable = (PMIB_TCPTABLE) malloc(dwActualSize);
assert(pTcpTable);
statusRetry = GetTcpTable(pTcpTable, &dwActualSize, fOrder);
return statusRetry;
}
else
{
return status;
}
}
//----------------------------------------------------------------------------
// Wrapper to GetUdpTable()
//----------------------------------------------------------------------------
DWORD MyGetUdpTable(PMIB_UDPTABLE& pUdpTable, BOOL fOrder)
{
DWORD status = NO_ERROR;
DWORD statusRetry = NO_ERROR;
DWORD dwActualSize = 0;
// query for buffer size needed
status = GetUdpTable(pUdpTable, &dwActualSize, fOrder);
if (status == NO_ERROR)
{
printf("No error\n");
return status;
}
else if (status == ERROR_INSUFFICIENT_BUFFER)
{
// need more space
pUdpTable = (PMIB_UDPTABLE) malloc(dwActualSize);
assert(pUdpTable);
statusRetry = GetUdpTable(pUdpTable, &dwActualSize, fOrder);
return statusRetry;
}
else
{
return status;
}
}
DWORD MyGetIpStatistics(PMIB_IPSTATS& pIpStats)
{
pIpStats = (PMIB_IPSTATS)malloc(sizeof(MIB_IPSTATS));
assert(pIpStats != NULL);
return GetIpStatistics(pIpStats);
}
DWORD MyGetIcmpStatistics(PMIB_ICMP& pIcmpStats)
{
pIcmpStats = (PMIB_ICMP)malloc(sizeof(MIB_ICMP));
assert(pIcmpStats != NULL);
return GetIcmpStatistics(pIcmpStats);
}
DWORD MyGetTcpStatistics(PMIB_TCPSTATS& pTcpStats)
{
pTcpStats = (PMIB_TCPSTATS)malloc(sizeof(MIB_TCPSTATS));
assert(pTcpStats != NULL);
return GetTcpStatistics(pTcpStats);
}
DWORD MyGetUdpStatistics(PMIB_UDPSTATS& pUdpStats)
{
pUdpStats = (PMIB_UDPSTATS)malloc(sizeof(MIB_UDPSTATS));
assert(pUdpStats != NULL);
return GetUdpStatistics(pUdpStats);
}
void PrintIpStats(PMIB_IPSTATS pStats)
{
if (pStats != NULL)
{
printf("\nIP Statistics:\n");
printf("\
dwForwarding = %lu\n\
dwDefaultTTL = %lu\n\
dwInReceives = %lu\n\
dwInHdrErrors = %lu\n\
dwInAddrErrors = %lu\n\
dwForwDatagrams = %lu\n\
dwInUnknownProtos = %lu\n\
dwInDiscards = %lu\n\
dwInDelivers = %lu\n\
dwOutRequests = %lu\n\
dwRoutingDiscards = %lu\n\
dwOutDiscards = %lu\n\
dwOutNoRoutes = %lu\n\
dwReasmTimeout = %lu\n\
dwReasmReqds = %lu\n\
dwReasmOks = %lu\n\
dwReasmFails = %lu\n\
dwFragOks = %lu\n\
dwFragFails = %lu\n\
dwFragCreates = %lu\n\
dwNumIf = %lu\n\
dwNumAddr = %lu\n\
dwNumRoutes = %lu\n",
pStats->dwForwarding,
pStats->dwDefaultTTL,
pStats->dwInReceives,
pStats->dwInHdrErrors,
pStats->dwInAddrErrors,
pStats->dwForwDatagrams,
pStats->dwInUnknownProtos,
pStats->dwInDiscards,
pStats->dwInDelivers,
pStats->dwOutRequests,
pStats->dwRoutingDiscards,
pStats->dwOutDiscards,
pStats->dwOutNoRoutes,
pStats->dwReasmTimeout,
pStats->dwReasmReqds,
pStats->dwReasmOks,
pStats->dwReasmFails,
pStats->dwFragOks,
pStats->dwFragFails,
pStats->dwFragCreates,
pStats->dwNumIf,
pStats->dwNumAddr,
pStats->dwNumRoutes);
}
}
void PrintIcmpStats(MIBICMPINFO *pStats)
{
if (pStats != NULL)
{
printf("\n%20s %10s %10s\n","ICMP Statistics", "IN", "OUT");
printf("%20s %10s %10s\n","---------------", "------", "------");
printf("%20s %10lu %10lu\n", "dwMsgs", pStats->icmpInStats.dwMsgs, pStats->icmpOutStats.dwMsgs);
printf("%20s %10lu %10lu\n", "dwErrors", pStats->icmpInStats.dwErrors, pStats->icmpOutStats.dwErrors);
printf("%20s %10lu %10lu\n", "dwDestUnreachs", pStats->icmpInStats.dwDestUnreachs, pStats->icmpOutStats.dwDestUnreachs);
printf("%20s %10lu %10lu\n", "dwTimeExcds", pStats->icmpInStats.dwTimeExcds, pStats->icmpOutStats.dwTimeExcds);
printf("%20s %10lu %10lu\n", "dwParmProbs", pStats->icmpInStats.dwParmProbs, pStats->icmpOutStats.dwParmProbs);
printf("%20s %10lu %10lu\n", "dwSrcQuenchs", pStats->icmpInStats.dwSrcQuenchs, pStats->icmpOutStats.dwSrcQuenchs);
printf("%20s %10lu %10lu\n", "dwRedirects", pStats->icmpInStats.dwRedirects, pStats->icmpOutStats.dwRedirects);
printf("%20s %10lu %10lu\n", "dwEchos", pStats->icmpInStats.dwEchos, pStats->icmpOutStats.dwEchos);
printf("%20s %10lu %10lu\n", "dwEchoReps", pStats->icmpInStats.dwEchoReps, pStats->icmpOutStats.dwEchoReps);
printf("%20s %10lu %10lu\n", "dwTimestamps", pStats->icmpInStats.dwTimestamps, pStats->icmpOutStats.dwTimestamps);
printf("%20s %10lu %10lu\n", "dwTimestampReps", pStats->icmpInStats.dwTimestampReps, pStats->icmpOutStats.dwTimestampReps);
printf("%20s %10lu %10lu\n", "dwAddrMasks", pStats->icmpInStats.dwAddrMasks, pStats->icmpOutStats.dwAddrMasks);
printf("%20s %10lu %10lu\n", "dwAddrMaskReps", pStats->icmpInStats.dwAddrMaskReps, pStats->icmpOutStats.dwAddrMaskReps);
}
}
void PrintTcpStats(PMIB_TCPSTATS pStats)
{
if (pStats != NULL)
{
printf("\nTCP Statistics\n");
printf("\
dwRtoAlgorithm = %lu\n\
dwRtoMin = %lu\n\
dwRtoMax = %lu\n\
dwMaxConn = %lu\n\
dwActiveOpens = %lu\n\
dwPassiveOpens = %lu\n\
dwAttemptFails = %lu\n\
dwEstabResets = %lu\n\
dwCurrEstab = %lu\n\
dwInSegs = %lu\n\
dwOutSegs = %lu\n\
dwRetransSegs = %lu\n\
dwInErrs = %lu\n\
dwOutRsts = %lu\n\
dwNumConns = %lu\n",
pStats->dwRtoAlgorithm,
pStats->dwRtoMin,
pStats->dwRtoMax,
pStats->dwMaxConn,
pStats->dwActiveOpens,
pStats->dwPassiveOpens,
pStats->dwAttemptFails,
pStats->dwEstabResets,
pStats->dwCurrEstab,
pStats->dwInSegs,
pStats->dwOutSegs,
pStats->dwRetransSegs,
pStats->dwInErrs,
pStats->dwOutRsts,
pStats->dwNumConns);
}
}
void PrintUdpStats(PMIB_UDPSTATS pStats)
{
if (pStats != NULL)
{
printf("\nUDP Statistics\n");
printf("\
dwInDatagrams = %lu\n\
dwNoPorts = %lu\n\
dwInErrors = %lu\n\
dwOutDatagrams = %lu\n\
dwNumAddrs = %lu\n",
pStats->dwInDatagrams,
pStats->dwNoPorts,
pStats->dwInErrors,
pStats->dwOutDatagrams,
pStats->dwNumAddrs);
}
}