Overview
"Monitor IP Scanner" is a tool used to monitor the system resources and perform some of its basic
functionalities. It is intended for both system administrators and general users to monitor and
manage their networks.
Monitor IP Scanner can be used to monitor: memory usage, IP configurations,
network configuration details with IP statistics, routing tables and ARP table information. You can also check if a network computer is alive or not using the IP address or domain name. You can even
send messages between the computers on a network by establishing client / server connectivity. Therefore, the server
would support a greater number of client connections. This will also be used to get the information from other
PCs which are on the same network. Things like - getting the routing table, IP statistics, ARP table information from
another computer and displaying it in another computer by establishing a TCP connection using the IP address which displays in a TCP routing table or user-defined IP address - are all possibilities.
Components
Monitor IP Scanner supports some of the following major features:
- Host Config
- IP Config
- MonAdmin config
- Network Config
- Ping Config
- Send Message
A walkthrough in Monitor IP and its components.
HOST config
This will display your system's information such as memory usage and host name. Memory usage details
like: Page file usage, virtual size usage and Page fault count and etc., this information is retrieved
using "ZwQuerySystemInformation" API which imported from the NTDLL.Lib file. This API is used to get all the
currently running process information of the PC. The retrieving global structure contains the memory usage
information.
typedef struct _VM_COUNTERS {
SIZE_T PeakVirtualSize;
SIZE_T VirtualSize;
ULONG PageFaultCount;
SIZE_T PeakWorkingSetSize;
SIZE_T WorkingSetSize;
SIZE_T QuotaPeakPagedPoolUsage;
SIZE_T QuotaPagedPoolUsage;
SIZE_T QuotaPeakNonPagedPoolUsage;
SIZE_T QuotaNonPagedPoolUsage;
SIZE_T PagefileUsage;
SIZE_T PeakPagefileUsage;
} VM_COUNTERS;
typedef struct _SYSTEM_THREAD_INFORMATION {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
KPRIORITY Priority;
KPRIORITY BasePriority;
ULONG ContextSwitchCount;
LONG State;
LONG WaitReason;
} SYSTEM_THREAD_INFORMATION, * PSYSTEM_THREAD_INFORMATION;
typedef struct _SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryDelta;
ULONG ThreadCount;
ULONG Reserved1[6];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ProcessName;
KPRIORITY BasePriority;
ULONG ProcessId;
ULONG InheritedFromProcessId;
ULONG HandleCount;
ULONG Reserved2[2];
VM_COUNTERS VmCounters;
IO_COUNTERS IoCounters;
SYSTEM_THREAD_INFORMATION Threads[1];
} SYSTEM_PROCESS_INFORMATION, * PSYSTEM_PROCESS_INFORMATION;
extern "C"
NTSYSAPI
NTSTATUS
NTAPI
ZwQuerySystemInformation(
IN UINT SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
At the bottom of this panel, there is a button called, "System Info . . .", that gives you
information on: what drives are available on your system, processors, processor speed, etc.
...
if(GetSystemInfo(m_SysInfo))
{
UINT Res = (UINT) ::ShellExecute(GetSafeHwnd(), _T("open"),
m_SysInfo, NULL, NULL, SW_SHOWNORMAL);
if( Res <= HINSTANCE_ERROR )
{
AfxMessageBox( _T( "Error Executing \"MsInfo32.exe\" !" ),
MB_OK | MB_ICONEXCLAMATION );
}
}
...
IP config
This displays your all the NIC/adapter card's information which are available in your PC, with the
local IP address, MAC address, Subnet mask, Default gateway and other information which is configured to the
particular NIC/adapter card. This will also display DNS and DHCP information.
To Get the Adapter Information with IP addresses, MAC address, Subnet Mask and default Gateway:
...
PIP_ADAPTER_INFO pAdapter = NULL;
dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen);
DNS information is retrieved using...
PFIXED_INFO pFixedInfo;
m_dwResult = GetNetworkParams((PFIXED_INFO)m_pBuffer,&m_ulSize);
MonAdmin config
Here you can get information like the Protocol statistics, Routing tables and ARP table information
from any other computer that is running Monitor IP at the same time as you. You can do this by: Selecting
the IP address in the TCP connection table that you would want information from and select the type of
information to retrieve, and then click on the "Retrieve Info" button. If the IP you're looking for is
not in the TCP connection table, then click on the "Other IP's" button and manually type it. After
the progress bar is finished, the Information will appear in the "Retrieved Info" box.
Structure and API used to get TCP Connection Table
PMIB_TCPTABLE pTcpTable;
GetTcpTable(pTcpTable, &dwSize, TRUE)
...
NETWORK config
This displays your NIC/adapter's networking activities and shows how many bytes have been sent, the number of bytes that have been discarded, how many bytes are errors, and how many are included with unicast packet details
since the NIC/adapter has been activated. It also displays routing table, protocol statistics, and ARP
table information.
Code to retrieve network activities...
MIB_IFTABLE *m_pTable;
pGetIfTable=(TGetIfTable)GetProcAddress(LoadLibrary
("Iphlpapi.dll"), "GetIfTable");
pGetNumberOfInterfaces=(TGetNumberOfInterfaces)GetProcAddress
(LoadLibrary("Iphlpapi.dll"),"GetNumberOfInterfaces");
m_pTable=NULL;
if (!pGetIfTable || !pGetNumberOfInterfaces)
{
AfxMessageBox("Error loading Iphlpapi.dll");
return;
}
ULONG uRetCode = pGetIfTable(m_pTable,&m_dwAdapters,TRUE);
m_pTable=new MIB_IFTABLE[m_dwAdapters];
pGetIfTable(m_pTable,&m_dwAdapters,TRUE);
...
MIB_IPSTATS IPStats;
m_dwResult = GetIpStatistics(&IPStats);
MIB_IPFORWARDROW IPForwardRow;
m_dwResult = GetBestRoute(inet_addr(_T("207.219.70.31")), 0,
&IPForwardRow);
...
PMIB_IPNETTABLE pMib = (PMIB_IPNETTABLE)
malloc(sizeof(MIB_IPNETTABLE)+sizeof(MIB_IPNETROW)*nSize);
DWORD dwRet = GetIpNetTable(pMib,&nSize,TRUE);
...
PING config
This gives the ability to check if a connection between you and another computer is up or down.
The usage is basically self-explanatory, but if it is not ... you have the option of pinging by
domain names or IP address and you can set timeout, TTL, and the number of packets to send.
Ping Configuration code...
...
HANDLE hIP = IcmpCreateFile();
IP_OPTION_INFORMATION OptionInfo;
OptionInfo.Ttl = PingOption.m_nTTL;
OptionInfo.Tos = PingOption.m_nTOS;
if (PingOption.m_bDontFragment)
OptionInfo.Flags = IP_FLAG_DF;
Set up the data which will be sent
unsigned char* pBuf = new unsigned
char[PingOption.m_wDataRequestSize];
memset(pBuf, 'S', PingOption.m_wDataRequestSize);
Do the actual Ping
DWORD dwReplySize = sizeof(ICMP_ECHO_REPLY) +
max(PingOption.m_wDataRequestSize, 8);
unsigned char* pReply = new unsigned char[dwReplySize];
ICMP_ECHO_REPLY* pEchoReply =
reinterpret_cast<icmp_echo_reply*>(pReply);
DWORD nRecvPackets = IcmpSendEcho(hIP, addr, pBuf,
PingOption.m_wDataRequestSize, &OptionInfo,
pReply, dwReplySize, PingOption.m_dwTimeout);
...</icmp_echo_reply*>
SEND MESSAGE
To Send Messages, a server must be created for clients to connect to. If a server is already
created, then you must create a client and connect to a server. Either way, when connected you will
be able to talk to a maximum of three other clients connected to that server. Using a user name is optional.
Here are instructions to use the send message option:
- Create a server by entering the port number (remember this port number).
- Press "Start Server" button.
- Create a Client by entering the address and port number of the server you have created.
- Press the "Start Client" button. (NOTE: If all of this is being done off of the same computer, then the only address you will be using is the loopback address (127.0.0.1)).
- Once the connection is established. A user name is generated automatically with the prefix "Client #" followed with connection number.
- A successful greeting on the client window as well in server window will be getting displayed.
- Now the data can be exchanged between the client and server by click the "send message button".
- Before sending message from server every time, the client name should be selected from user list to which the data has to be send.
Send Message Code Implementation...
{
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
...
Server_Addr.sin_port = htons(m_PortNo);
Server_Addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
Server_Addr.sin_family = AF_INET;
addlen = sizeof(Server_Addr);
Sock = socket(AF_INET, SOCK_STREAM, NULL);
...
if(bind(Sock, (const sockaddr *) &Server_Addr, addlen))
...
if(listen(Sock, 5))
...
AfxBeginThread(&ServerThread, NULL, 0, 0, 0, NULL);
}
UINT ServerThread(LPVOID lpVoid)
{
m_Socket = accept(SendMsgDlg->Sock,(SOCKADDR *)
&SendMsgDlg->Server_Addr, &SendMsgDlg->addlen);
...
AfxBeginThread(&ServerThread, NULL, 0, 0, 0, NULL);
...
while((Res = recv(m_Socket, RecvBuffer, sizeof(RecvBuffer),
0)) != SOCKET_ERROR)
{
...
}
send(m_Socket, "Disconnected", 100, 0);
...
::closesocket(m_Socket);
::AfxEndThread(0);
return TRUE;
}