October 24, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

IP Helper API: ARP, Routing, and Network Statistics

  • September 30, 2004
  • By Alex Gusev
  • Send Email »
  • More Articles »

Well, this article is the last in the series ("IP Helper API: Retrieving Basic Information" and "IP Helper API: Managing IP Addresses") dedicated to the IP Helper API. We have covered most of the API calls. Now, we will talk mainly about ARP, forwarding of IP requests, and network statistics.

Retrieving ARP Information

In the previous articles, we touched a bit about how to get basic Address Resolution Protocol (ARP) information. In addition, you had the following functions defined:

  • CreateIpNetEntry
  • SetIpNetEntry
  • DeleteIpNetEntry
  • FlushIpNetTable
  • CreateProxyArpEntry
  • DeleteProxyArpEntry
  • SendARP

They are used to create, delete, or modify ARP table entries. In each case, you should provide a valid MIB_IPNETROW struct. You also can manage proxy ARP records. All these functions may be quite useful; for example, when you're developing applications for devices that do not support IP, but are using Windows CE as a front end to access the network.

Besides, the SendARP function deserves our attention. It allows you to retrieve the MAC address of the destination IP. When might you need it? The first thing rising in my head is raw sockets. You also can use this request for authentication purposes. Below, you'll find a simple example of SendARP usage:

void CNWParamsDlg::OnSendARP()
{
   IPAddr dstAddr = inet_addr("10.168.242.170");
   ULONG MacAddr[2];
   ULONG PhyAddrLen = 6;
   memset(MacAddr,0,sizeof(MacAddr));
   DWORD dwRes = SendARP(dstAddr,0,MacAddr,&PhyAddrLen);

   if ( dwRes == NO_ERROR )
   {
      m_ListBox.ResetContent();

      BYTE *pAddr = (BYTE*)MacAddr;
      CString sTmp, sMAC;
      for (int i = 0; i < PhyAddrLen - 1; i++,pAddr++)
      {
         sTmp.Format(L"%02X:",*pAddr);
         sMAC += sTmp;
      }
      if ( PhyAddrLen )
      {
         sTmp.Format(L"%02X",*pAddr);
         sMAC += sTmp;
      }
      if ( !sMAC.IsEmpty() )
      {
         m_ListBox.AddString(sMAC);
      }
   }
}

Note, that SendARP send requests to local network, so all calls with outer IP will fail.

Utilizing Routing Mechanism

Let's move now to other networking issue. Most of IP requests are forwarded to their destinations. With IP Helper API, you have rich capabilities to manage the way how datagrams are routed over the network. You have the following functions to manage the IP routing table, and to obtain other routing information:

  • GetIpForwardTable—to get the contents of IP forwarding table
  • CreateIpForwardEntry—to create entry
  • DeleteIpForwardEntry—to delete entry
  • SetIpForwardEntry—to modify entry
  • GetBestRoute—to get the best route to a specified destination address

Let's start from GetIpForwardTable. This function returns the contents of IP routing table. Similar to other IP Helper tables, that's an array of MIB_IPFORWARDROW structs. This struct contains different forwarding information, which describes an IP network route. We will use it in our test only few fields. For more details, see RFC 1354. So, here is code snippet:

void CNWParamsDlg::ShowForwardRows(PMIB_IPFORWARDTABLE
                                   pIpForwardTable)
{
   m_ListBox.ResetContent();

   CString sTmp;
   sTmp.Format(L"NumEntries: %d",pIpForwardTable->dwNumEntries);
   m_ListBox.AddString(sTmp);

   in_addr addr;
   TCHAR szBuffer[128];
   for (int i = 0; i < pIpForwardTable->dwNumEntries; i++)
   {
      MIB_IFROW mibRow;
      memset(&mibRow,0,sizeof(mibRow));
      mibRow.dwIndex = pIpForwardTable->table[i].dwForwardIfIndex;
      GetIfEntry(&mibRow);
      sTmp.Format(L"Idx: %lu Name: %s",
                  pIpForwardTable->table[i].dwForwardIfIndex,
                  mibRow.wszName);
      m_ListBox.AddString(sTmp);

      addr.S_un.S_addr = pIpForwardTable->table[i].dwForwardDest;
      char *szAddr = inet_ntoa(addr);
      memset(szBuffer,0,sizeof(szBuffer));
      MultiByteToWideChar(CP_ACP,0,szAddr,strlen(szAddr),szBuffer,
                          sizeof(szBuffer));
      sTmp.Format(L"   Dest IP: %s", szBuffer);
      m_ListBox.AddString(sTmp);

      addr.S_un.S_addr = pIpForwardTable->table[i].dwForwardMask;
      szAddr = inet_ntoa(addr);
      memset(szBuffer,0,sizeof(szBuffer));
      MultiByteToWideChar(CP_ACP,0,szAddr,strlen(szAddr),szBuffer,
                          sizeof(szBuffer));
      sTmp.Format(L"   Subnet Mask: %s", szBuffer);
      m_ListBox.AddString(sTmp);

      sTmp = L"   Type:";
      switch (pIpForwardTable->table[i].dwForwardType)
      {
      case MIB_IPROUTE_TYPE_OTHER:
         sTmp += L" OTHER";
         break;
      case MIB_IPROUTE_TYPE_INVALID:
         sTmp += L" INVALID";
         break;
      case MIB_IPROUTE_TYPE_DIRECT:      // Local
         sTmp += L" DIRECT";
         break;
      case MIB_IPROUTE_TYPE_INDIRECT:    // Remote
         sTmp += L" INDIRECT";
         break;
      }
      m_ListBox.AddString(sTmp);
   }
}

void CNWParamsDlg::OnGetIpForwardTable()
{
   PMIB_IPFORWARDTABLE pIpForwardTable = 0;
   ULONG dwSize = 0;
   DWORD dwRes = GetIpForwardTable(pIpForwardTable, &dwSize, FALSE);

   if ( dwRes == ERROR_INSUFFICIENT_BUFFER )
   {
      pIpForwardTable = (PMIB_IPFORWARDTABLE) new BYTE[dwSize];
      dwRes = GetIpForwardTable(pIpForwardTable, &dwSize, FALSE);
      if ( dwRes == NO_ERROR )
         ShowForwardRows(pIpForwardTable);
      delete pIpForwardTable;
   }
}

As you can see, the test code displays correspondend the interface index and name, destination host IP, and subnet mask and route type. Once again, all details are documented in RFC 1354, so we will not touch them here. But, anyway, the information returned gives your application enough feeding to process.





Page 1 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel