Network Detection for Mobility

Submit New Article

March 9, 2009 2:00 AM PDT



Challenge

Implement robust support for network detection in mobilized software applications. A true mobility-enabled application must adapt to the changing network connectivity of the mobile PC. Today, most mobile PCs have both wired and wireless network capabilities. Multiple network adapters may be connected to the network at the same time. The same mobile PC could have a high-speed wired network connection at one moment and a lower-speed wireless LAN (802.11), wireless WAN (GPRS), or modem connection a moment later. The mobility aware application must know the status, type, and speed of the network connection.


Solution

Implement network detection code using the Windows* Platform SDK and Microsoft’s IP Helper API. Note that to simplify the code in this document, buffer allocations and a lot of basic good programming practices are not shown (e.g., return value error checking, NULL pointer checking, ASSERTs, etc.)

Finding the right adapter: The first step in network detection is to identify the correct adapter and connection. This process begins by getting a list of all adapters and interfaces on the system:

// Get Adapter Table
GetAdaptersInfo(pAdapterTable, &ulAdapterTableSize);

// Get the network Interface Table
GetIfTable(pIfTable, &dwIfTableSize, TRUE);

 

We now have a lot of information about all the network adapters and their associated interfaces on the system. Next, we ask the routing table manager to determine the best interface for the specified IP address by making a call to IP Helper function GetBestInterface:

unsigned long dwBestIfIndex = 0;

IPAddr dwDestAddr = (IPAddr) inet_addr(strDestIPAddress);

// Get the route table information
if (GetBestInterface(dwDestAddr,&dwBestIfIndex) != NO_ERROR)
return false;

 

On a Windows* XP system, GetBestInterface will by default prefer wired connections over wireless ones. Therefore, we have the preferred interface index now (dwBestIfIndex), but we still need to find that interface associated with that index in the interface table:

MIB_IFROW * pCurInterface = NULL;
for (DWORD dwArrayIndex = 0; dwArrayIndex < dwIfTableSize; dwArrayIndex++)
{
if (pIfTable->table[dwArrayIndex].dwIndex == dwBestIfIndex)
{
pCurInterface = &amp;pIfTable->table[dwArrayIndex];
break;
}
}

if (!pCurInterface)
return false;

 

Now that we have the best interface, we need to locate the adapter that belongs to that interface. Note that there is a one-to-one relationship between adapters and interfaces, so the next step just requires a bit of searching:

IP_ADAPTER_INFO * pCurAdapter = &amp;pAdapterTable[0];
while (pCurAdapter &amp;&amp; (pCurAdapter->Index != dwBestIfIndex))
{
pCurAdapter = pCurAdapter->Next;
}

if (!pCurAdapter)
return false;

 

Getting the Connection Status and Speed: Once we have located the adapter and interface, we must extract the information. Connection speed is either the maximum speed of the network card or the actual speed of the serial (modem) connection:

dwSpeed= pCurInterface->dwSpeed;

 

Connection status:

dwStatus= pCurInterface->dwOperStatus;

 

The interesting status values are as follows:

MIB_IF_OPER_STATUS_OPERATIONAL This is what most LAN adapters return when they are connected and functioning properly.
MIB_IF_OPER_STATUS_DISCONNECTED This is what you will see if the network cable is disconnected for LAN adapters, or for a modem when it receives a NO CARRIER.
MIB_IF_OPER_STATUS_CONNECTED This is the state a functioning modem connection will be in. All other states are not connected.

 

All other states are not connected.

Getting the Connection Type: The connection type requires a bit more work, because the information reported in the interface and adapter tables may not be sufficient to distinguish between a wired and wireless LAN connection. To get the most accurate data, we have to ask the device driver for the adapter itself. This can be done using the function DeviceIoControl to send the OID_GEN_PHYSICAL_MEDIUM request to the driver. Most wireless network cards, including the Intel® PRO/Wireless cards, will return the NdisPhysicalMediumWirelessLan value from this call. Here is an example of obtaining the adapter type:

HANDLE hDevice = INVALID_HANDLE_VALUE;

// Build the path to the device
char szDevPath[MAX_ADAPTER_NAME_LENGTH + 8];
wsprintf( szDevPath, ".\%s", &amp;pCurAdapter->AdapterName[0] );

// Open the device for reading
hDevice = CreateFile( szDevPath, 0, FILE_SHARE_READ,
(LPSECURITY_ATTRIBUTES) NULL,

_EXISTING, 0, (HANDLE) INVALID_HANDLE_VALUE);

if (hDevice == INVALID_HANDLE_VALUE)
return false;

// Query the device for its type
NDIS_OID OidCode = OID_GEN_PHYSICAL_MEDIUM;
ULONG ulOidPhysicalMedium=0;
ULONG ulBytesReturned=0;
bool bResult = (bool) DeviceIoControl( hDevice,
IOCTL_NDIS_QUERY_GLOBAL_STATS,
&amp;OidCode,
sizeof(NDIS_OID),
&amp;ulOidPhysicalMedium,
sizeof(ULONG),
&amp;ulBytesReturned, NULL );

// Close the device
CloseHandle(hDevice);

 

In this sample code, if the command succeeded, ulOidPhysicalMedium will be set to one of the following values:

NdisPhysicalMediumWirelessLan
NdisPhysicalMediumCableModem
NdisPhysicalMediumPhoneLine
NdisPhysicalMediumPowerLine
NdisPhysicalMediumDSL
NdisPhysicalMediumFibreChannel
NdisPhysicalMedium1394
NdisPhysicalMediumWirelessWan

 


Source

Implementing Network Detection for Mobility