Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / MFC

IPConfigEx

4.50/5 (11 votes)
5 Jul 2007CPOL2 min read 1   1.9K  
A simple hybrid between the ipconfig and the arp commands.

Screenshot - cmd_demo.png

1. Introduction

This article is intended to be an introduction to the IP helper API and to the Winsock API. The demo project is named IPConfigEx because it implements the basic functionalities of the "ipconfig" [^] command and some of the "arp" [^]) commands with the ability to send the information displayed as an email.

2. Motivation for the article and for the project

I needed a tool that is able to send an email with the network settings of a Windows box (Win2K, WinXP), and that application had to work without any complicated install procedures or dependencies. I took a look at the WinPCap [^], but that was an overkill for my needs and it requires WinPCap to be installed. The IP Helper API [^] was the solution.

3. How to use the IPConfigEx utility

Since this is a command line tool, the user controls its behavior through command line switches. Without any arguments, the tool will display the list of network adapters followed by the list of the ARP entries.

The commonly used command line switches:

[-i:ip] - shows information about the network adapters
[-i:arp] - show the ARP table

I implemented the email sending function to be driven by default parameters, only the destination email must be specified.

4. Discussion of the IP Helper API methods

The backbone of the project is constructed around the GetAdaptersInfo and GetIpNetTable methods. As the MSDN states:

The GetAdaptersInfo function retrieves adapter information for the local computer. The GetIpNetTable function retrieves the IP-to-physical address mapping table.

I won't detail here the workings of these methods; anyone interested should look in the source code provided. It's pretty simple.

5. Enumerating the network adapters

To GetAdaptersInfo call returns a linked list of the adapter info structures. Straightforward.

C++
// Loops through the network adapters list and fills the adapters vector

// with an AdapterEntry structure for each NIC.

void AdapterInfo::EnumAdapters()
{
    IP_ADAPTER_INFO* pAdapterList = NULL;
    IP_ADAPTER_INFO* pAdapter = NULL;
    ULONG ulBufLen = 0;
    DWORD err = ERROR_SUCCESS;

    // clear the network adapters vector

    adapters.clear();

    // the first call to GetAdaptersInfo will fail and 

    // fills the ulBufLen with the required size

    err = ::GetAdaptersInfo(pAdapterList, &ulBufLen);
    if (err == ERROR_BUFFER_OVERFLOW) 
    {
        // allocate memory for the linked adapters of IP_ADAPTER_INFO structures

        pAdapterList = (IP_ADAPTER_INFO*) ::HeapAlloc(::GetProcessHeap(), 
                        HEAP_ZERO_MEMORY, ulBufLen);
        err = ::GetAdaptersInfo(pAdapterList, &ulBufLen);
    }
    else if (err != ERROR_SUCCESS)
    {
        fprintf(stderr, "EnumAdapters error. Code: %d\n", err);
        return;
    }

    if (pAdapterList == NULL) 
    {
        // error HeapAlloc returned NULL

        fprintf(stderr, "Can't allocate memory on heap " 
                        "(%d bytes): EnumAdapters\n", ulBufLen);
        return;
    }

    // enumerate the network adapters 

    pAdapter = pAdapterList;
    while (pAdapter != NULL) 
    {
        AdapterEntry adapterEntry;

        adapterEntry.index = pAdapter->Index;

        adapterEntry.name = pAdapter->AdapterName;
        adapterEntry.description = pAdapter->Description;
        adapterEntry.mac = IpHelper::HrMacAddress(pAdapter->Address, 
                           pAdapter->AddressLength);

        adapterEntry.ip = pAdapter->IpAddressList.IpAddress;
        adapterEntry.subnet = pAdapter->IpAddressList.IpMask;

        // check if gateway is present

        if (strlen(pAdapter->GatewayList.IpAddress.String) > 0)
            adapterEntry.gateway = pAdapter->GatewayList.IpAddress;
        else
            ZeroMemory(&adapterEntry.gateway, 16);
        
        // dhcp

        adapterEntry.dhcpEnabled = pAdapter->DhcpEnabled ? true : false;
        if (adapterEntry.dhcpEnabled) 
            adapterEntry.dhcpServer = pAdapter->DhcpServer.IpAddress;

        // try to get the dns server list

        this->EnumDnsServers(adapterEntry);        

        // if the adapter isn't in the adapters dictionary insert it

        if (adapters.find(adapterEntry.index) == adapters.end())
            adapters[adapterEntry.index] = adapterEntry;

        // go on to the next adapter item

        pAdapter = pAdapter->Next;
    }

    ::HeapFree(::GetProcessHeap(), 0, pAdapterList);
}

Again from MSDN:

"The order in which adapters appear in the list returned by this function can be controlled from the Network Connections folder: select the Advanced Settings menu item from the Advanced menu."

I tried and changed the order of the network adapters, but the index of the adapters didn't change.

6. Things to keep in mind

The first version was built using Visual Studio 2005. However, the built executable requires the Visual C++ 2005 redistributable package to be installed. The same project built with Visual Studio 2003 runs just fine on all Win2K and WinXP systems. I wasn't aware of this until this point.

The SMTP message class uses Winsock methods to send the email. So, for that, you need to add ws2_32.lib to your project (Linker -> Input -> Additional dependencies). For the IP Helper API, you need to add iphlpapi.lib as a dependency.

7. To do

  • Add the possibility to display the host name of the machine.
  • Check for a way to know if there is no link on an interface (media disconnected).
  • More detailed command line switches.

8. References

  • The "New ipconfig" and the IP Helper API [^]
  • About IP Helper [^]
  • Windows Networking Overview [^]

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)