Introduction
There are few articles which describe how to retrieve the statistics about network. We used to load the inetmib1.dll manually and map the function pointers in order to get all the required information.
Finally microsoft published some nice APIs to perform these operations. This article explains how to make use of those published APIs. The APIs are categorized as follows
Interface Class
This class allows applications to retrieve network adapter characteristic information. The IP Helper APIs available for Windows NT 4.0 Service Pack 4 are listed below:
GetIfTable
: Retrieves all network adapters physical characteristics.
GetIfEntry
: Retrieves specific adapter characteristics.
SetIfEntry
: Updates a specific adapter's operating status, such as describing whether an interface is up, down, or in a testing mode.
SetIpTTL
: Allows applications to modify the Time to Live (TTL) field for all IP packets sent from your system.
IP Address Class
This class allows applications to modify and retrieve IP configuration information. However, most of these APIs are not supported on Windows NT 4.0 Service Pack 4. The IP Helper APIs available for Windows NT 4.0 SP 4 are listed below:
GetIpAddrTable
: Allows an application to retrieve IP address information.
ARP Table Class
This class provides access to the address resolution protocol (ARP) entries by mapping from an IP address to a physical address. The IP Helper APIs available for Windows NT 4.0 Service Pack 4 are listed below:
GetIpNetTable
: Retrieves address resolution table information.
SetIpNetEntry
: Adds entry to the ARP table.
DeleteIpNetEntry
: Deletes entry from the ARP table.
Route Table Class
This class allows applications to retrieve IP routing information and permits applications to make modifications to route entries in the table. Routing is the selection of the next hop address from a routing table over which a packet is sent. The IP Helper APIs available for Windows NT 4.0 Service Pack 4 are listed below:
GetIpForwardTable
: Retrieves routing table information.
SetIpForwardEntry
: Adds a route table entry.
DeleteIpForwardEntry
: Deletes a route table entry.
GetRTTAndHopCount
: Provides approximated round trip time information to a specific IP destination and also provides the hop count to that destination.
Statistics Class
This class provides information on various kinds of packet/connection statistics information on a local computer. The IP Helper APIs available for Windows NT 4.0 Service Pack 4 are listed below:
GetIpStatistics
: Retrieves Internet Protocol (IP) packet statistics.
GetIcmpStatistics
: Retrieves Internet Control Message Protocol (ICMP) statistics.
GetTcpStatistics
: Retrieves Transmission Control Protocol (TCP) statistics.
GetUdpStatistics
: Retrieves User Datagram Protocol (UDP) statistics.
Source code and Demo application
I have put together this demo using Visual Studio .NET
#include "stdafx.h"
#include "WinNetStat.h"
#include "WinNetStatDoc.h"
#include "WinNetStatView.h"
#include "netstatmanager.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
IMPLEMENT_DYNCREATE(CWinNetStatView, CFormView)
BEGIN_MESSAGE_MAP(CWinNetStatView, CFormView)
ON_BN_CLICKED(IDC_TCPSTATS, OnClickedTcpstats)
ON_BN_CLICKED(IDC_UDPTATS, OnBnClickedUdptats)
ON_BN_CLICKED(IDC_IPSTATS, OnBnClickedIpstats)
ON_BN_CLICKED(IDC_NW_PARAMS, OnBnClickedNwParams)
ON_BN_CLICKED(IDC_ADAPTER_INFO, OnBnClickedAdapterInfo)
END_MESSAGE_MAP()
CWinNetStatView::CWinNetStatView() : CFormView(CWinNetStatView::IDD)
{
}
CWinNetStatView::~CWinNetStatView()
{
}
void CWinNetStatView::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
DDX_Control(pDX, IDC_TEXT_OUTPUT, m_TextOutput);
}
BOOL CWinNetStatView::PreCreateWindow(CREATESTRUCT& cs)
{
return CFormView::PreCreateWindow(cs);
}
void CWinNetStatView::OnInitialUpdate(){
CFormView::OnInitialUpdate();
GetParentFrame()->RecalcLayout();
ResizeParentToFit();
}
#ifdef _DEBUG
void CWinNetStatView::AssertValid() const
{
CFormView::AssertValid();
}
void CWinNetStatView::Dump(CDumpContext& dc) const{
CFormView::Dump(dc);
}
CWinNetStatDoc* CWinNetStatView::GetDocument() const
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CWinNetStatDoc)));
return (CWinNetStatDoc*)m_pDocument;
}
#endif
void CWinNetStatView::OnClickedTcpstats()
{
MIB_TCPSTATS TcpStatsMIB;
::GetTcpStatistics(&TcpStatsMIB);
CString strMsg;
CString strOutPut;
strOutPut.Format("\r\n************************************\r\n");
strMsg.Format("\tTCP/IP Statistics\t\r\n");
strOutPut+=strMsg;
strMsg.Format("\r\n************************************\r\n");
strOutPut+=strMsg;
strMsg.Format("time-out algorithm:\t%d\r\n",
TcpStatsMIB.dwRtoAlgorithm);
strOutPut+=strMsg;
strMsg.Format("minimum time-out:\t%d\r\n",
TcpStatsMIB.dwRtoMin);
strOutPut+=strMsg;
strMsg.Format("maximum time-out:\t%d\r\n",
TcpStatsMIB.dwRtoMax);
strOutPut+=strMsg;
strMsg.Format("maximum connections:\t%d\r\n",
TcpStatsMIB.dwMaxConn);
strOutPut+=strMsg;
strMsg.Format("active opens:\t%d\r\n",
TcpStatsMIB.dwActiveOpens);
strOutPut+=strMsg;
strMsg.Format("passive opens:\t%d\r\n",
TcpStatsMIB.dwPassiveOpens);
strOutPut+=strMsg;
strMsg.Format("failed attempts:\t%d\r\n",
TcpStatsMIB.dwAttemptFails);
strOutPut+=strMsg;
strMsg.Format("established connections reset:\t%d\r\n",
TcpStatsMIB.dwEstabResets);
strOutPut+=strMsg;
strMsg.Format("established connections:\t%d\r\n",
TcpStatsMIB.dwCurrEstab);
strOutPut+=strMsg;
strMsg.Format("segments received:\t%d\r\n",TcpStatsMIB.dwInSegs);
strOutPut+=strMsg;
strMsg.Format("segment sent:\t%d\r\n",TcpStatsMIB.dwOutSegs);
strOutPut+=strMsg;
strMsg.Format("segments retransmitted:\t%d\r\n",
TcpStatsMIB.dwRetransSegs);
strOutPut+=strMsg;
strMsg.Format("incoming errors:\t%d\r\n",TcpStatsMIB.dwInErrs);
strOutPut+=strMsg;
strMsg.Format("outgoing resets:\t%d\r\n",TcpStatsMIB.dwOutRsts);
strOutPut+=strMsg;
strMsg.Format("cumulative connections:\t%d\r\n",
TcpStatsMIB.dwNumConns);
strOutPut+=strMsg;
m_TextOutput.SetWindowText(strOutPut);
}
void CWinNetStatView::OnBnClickedUdptats(){
MIB_UDPSTATS UDPStatsMIB;
::GetUdpStatistics(&UDPStatsMIB);
CString strMsg;
CString strOutPut;
strOutPut.Format("\r\n************************************\r\n");
strMsg.Format("\tUDP Statistics\t\r\n");
strOutPut+=strMsg;
strMsg.Format("\r\n************************************\r\n");
strOutPut+=strMsg;
strMsg.Format("received datagrams:\t%d\r\n",UDPStatsMIB.dwInDatagrams);
strOutPut+=strMsg;
strMsg.Format("datagrams for which no port exists:\t%d\r\n"
,UDPStatsMIB.dwNoPorts);
strOutPut+=strMsg;
strMsg.Format("errors on received datagrams:\t%d\r\n",
UDPStatsMIB.dwInErrors);
strOutPut+=strMsg;
strMsg.Format("sent datagrams:\t%d\r\n",UDPStatsMIB.dwOutDatagrams);
strOutPut+=strMsg;
strMsg.Format("number of entries in UDP listener table:\t%d\r\n",
UDPStatsMIB.dwNumAddrs);
strOutPut+=strMsg;
m_TextOutput.SetWindowText(strOutPut);
}
void CWinNetStatView::OnBnClickedIpstats(){
MIB_IPSTATS IPStatsMIB;
::GetIpStatistics(&IPStatsMIB);
CString strMsg;
CString strOutPut;
strOutPut.Format("\r\n************************************\r\n");
strMsg.Format("\tIP Statistics\t\r\n");
strOutPut+=strMsg;
strMsg.Format("\r\n************************************\r\n");
strOutPut+=strMsg;
strMsg.Format("IP forwarding enabled or disabled:\t%d\r\n",
IPStatsMIB.dwForwarding);
strOutPut+=strMsg;
strMsg.Format("default time-to-live:\t%d\r\n",
IPStatsMIB.dwDefaultTTL);
strOutPut+=strMsg;
strMsg.Format("datagrams received:\t%d\r\n",
IPStatsMIB.dwInReceives);
strOutPut+=strMsg;
strMsg.Format("received header errors:\t%d\r\n",
IPStatsMIB.dwInHdrErrors);
strOutPut+=strMsg;
strMsg.Format("received address errors:\t%d\r\n",
IPStatsMIB.dwInAddrErrors);
strOutPut+=strMsg;
strMsg.Format("datagrams forwarded:\t%d\r\n",
IPStatsMIB.dwForwDatagrams);
strOutPut+=strMsg;
strMsg.Format("datagrams with unknown protocol:\t%d\r\n",
IPStatsMIB.dwInUnknownProtos);
strOutPut+=strMsg;
strMsg.Format("received datagrams discarded:\t%d\r\n",
IPStatsMIB.dwInDiscards);
strOutPut+=strMsg;
strMsg.Format("received datagrams delivered:\t%d\r\n",
IPStatsMIB.dwInDelivers);
strOutPut+=strMsg;
strMsg.Format("sent datagrams discarded:\t%d\r\n",
IPStatsMIB.dwOutDiscards);
strOutPut+=strMsg;
strMsg.Format("datagrams for which no route exists:\t%d\r\n",
IPStatsMIB.dwOutNoRoutes);
strOutPut+=strMsg;
strMsg.Format("datagrams for which all frags did not arrive:\t%d\r\n",
IPStatsMIB.dwReasmTimeout);
strOutPut+=strMsg;
strMsg.Format("datagrams requiring reassembly:\t%d\r\n",
IPStatsMIB.dwReasmReqds);
strOutPut+=strMsg;
strMsg.Format("successful reassemblies:\t%d\r\n",IPStatsMIB.dwReasmOks);
strOutPut+=strMsg;
strMsg.Format("failed reassemblies:\t%d\r\n",IPStatsMIB.dwReasmFails);
strOutPut+=strMsg;
strMsg.Format("successful fragmentations:\t%d\r\n",IPStatsMIB.dwFragOks);
strOutPut+=strMsg;
strMsg.Format("failed fragmentations:\t%d\r\n",IPStatsMIB.dwFragFails);
strOutPut+=strMsg;
strMsg.Format("datagrams fragmented:\t%d\r\n",IPStatsMIB.dwFragCreates);
strOutPut+=strMsg;
strMsg.Format("number of interfaces on computer:\t%d\r\n",
IPStatsMIB.dwNumIf);
strOutPut+=strMsg;
strMsg.Format("number of IP address on computer:\t%d\r\n",
IPStatsMIB.dwNumAddr);
strOutPut+=strMsg;
strMsg.Format("number of routes in routing table:\t%d\r\n",
IPStatsMIB.dwNumRoutes);
strOutPut+=strMsg;
m_TextOutput.SetWindowText(strOutPut);
}
void CWinNetStatView::OnBnClickedNwParams(){
FIXED_INFO * FixedInfo;
ULONG ulOutBufLen;
DWORD dwRetVal;
IP_ADDR_STRING * pIPAddr;
CString strMsg;
CString strOutPut;
strOutPut.Format("\r\n************************************\r\n");
strMsg.Format("\tNetwork Parameters\t\r\n");
strOutPut+=strMsg;
strMsg.Format("\r\n************************************\r\n");
strOutPut+=strMsg;
FixedInfo = (FIXED_INFO *) GlobalAlloc( GPTR, sizeof( FIXED_INFO ) );
ulOutBufLen = sizeof( FIXED_INFO );
if( ERROR_BUFFER_OVERFLOW == GetNetworkParams( FixedInfo, &ulOutBufLen ))
{
GlobalFree( FixedInfo );
FixedInfo =(FIXED_INFO *) GlobalAlloc( GPTR, ulOutBufLen );
}
if ( dwRetVal = GetNetworkParams( FixedInfo, &ulOutBufLen ) )
{
strMsg.Format(
"Call to GetNetworkParams failed. Return Value: %08x\r\n",
dwRetVal );
strOutPut+=strMsg;
}
else
{
strMsg.Format( "Host Name: %s\r\n", FixedInfo -> HostName );
strOutPut+=strMsg;
strMsg.Format( "Domain Name: %s\r\n", FixedInfo -> DomainName );
strOutPut+=strMsg;
strMsg.Format( "DNS Servers:\r\n" );
strOutPut+=strMsg;
strMsg.Format( "\t%s\r\n",
FixedInfo -> DnsServerList.IpAddress.String );
strOutPut+=strMsg;
pIPAddr = FixedInfo -> DnsServerList.Next;
while ( pIPAddr )
{
strMsg.Format( "\t%s\r\n", pIPAddr ->IpAddress.String );
strOutPut+=strMsg;
pIPAddr = pIPAddr ->Next;
}
}
m_TextOutput.SetWindowText(strOutPut);
}
void CWinNetStatView::OnBnClickedAdapterInfo(){
IP_ADAPTER_INFO * FixedInfo;
ULONG ulOutBufLen;
DWORD dwRetVal;
IP_ADDR_STRING * pIPAddr;
CString strMsg;
CString strOutPut;
strOutPut.Format("\r\n************************************\r\n");
strMsg.Format("\t Adaptor Information\t\r\n");
strOutPut+=strMsg;
strMsg.Format("\r\n************************************\r\n");
strOutPut+=strMsg;
FixedInfo = (IP_ADAPTER_INFO *) GlobalAlloc( GPTR,
sizeof( IP_ADAPTER_INFO ) );
ulOutBufLen = sizeof( IP_ADAPTER_INFO );
if( ERROR_BUFFER_OVERFLOW == GetAdaptersInfo(FixedInfo,&ulOutBufLen))
{
GlobalFree( FixedInfo );
FixedInfo =(IP_ADAPTER_INFO *) GlobalAlloc( GPTR, ulOutBufLen );
}
if ( dwRetVal = GetAdaptersInfo( FixedInfo, &ulOutBufLen ) )
{
strMsg.Format(
"Call to GetAdaptersInfo failed. Return Value: %08x\r\n",
dwRetVal );
strOutPut+=strMsg;
}
else
{
strMsg.Format( "AdapterName: %s\r\n",FixedInfo->AdapterName );
strOutPut+=strMsg;
strMsg.Format( "Description: %s\r\n",FixedInfo->Description );
strOutPut+=strMsg;
}
m_TextOutput.SetWindowText(strOutPut);
}