In order for an application to communicate with another host over TCP/IP, the device must have a valid IP address. Network interfaces and adapters on Pocket PC devices always have a unique IP address associated with them. You can use the IP Helper APIs to add and remove them, as well as to release or renew DHCP-assigned addresses.
You can retrieve the IP addresses that are currently assigned on your device by using the GetIpAddrTable() function:
DWORD GetIpAddrTable(MIB_IPADDRTABLE *pIpAddrTable, ULONG *pdwSize, BOOL bOrder);
The first parameter, pIpAddrTable, is a pointer to a buffer that will receive a MIB_IPADDRTABLE structure, which outlines the entire interface to IP address mappings on the device. The pdwSize parameter should point to an unsigned long that specifies the size of the pIpAddrTable buffer. If you want to have the IP address table sorted, you should set the last parameter, bOrder, to TRUE.
The MIB_IPADDRTABLE structure is defined as follows:
typedef struct _MIB_IPADDRTABLE { DWORD dwNumEntries; MIB_IPADDRROW table[ANY_SIZE]; } MIB_IPADDRTABLE, *PMIB_IPADDRTABLE;
The structure contains two fields. The first, dwNumEntries, is the number of MIB_IPADDRROW structures in the table field. The table field contains the actual array of MIB_IPADDRROW structures that contain the IP address information. Each MIB_IPADDRROW structure is defined as follows:
typedef struct _MIB_IPADDRROW { DWORD dwAddr; DWORD dwIndex; DWORD dwMask; DWORD dwBCastAddr; DWORD dwReasmSize; unsigned short unused1; unsigned short unused2; } MIB_IPADDRROW, *PMIB_IPADDRROW;
The dwAddr field specifies the IP address.
The dwIndex field specifies the index of the interface associated with the dwAddr field.
The dwMask field specifies the subnet mask.
The dwBCastAddr field specifies the broadcast address for this IP address.
The dwReasmSize field specifies the datagram reassembly size.
The final two parameters, unused1 and unused2, are not currently used.
The following example shows how you can enumerate the IP address table:
// IP address table list MIB_IPADDRTABLE *pIpAddressTable = NULL; DWORD dwIPTableSize = 0; // Find out the size of the IP table if(GetIpAddrTable(NULL, &dwIPTableSize, FALSE) != ERROR_INSUFFICIENT_BUFFER) return FALSE; pIpAddressTable = (MIB_IPADDRTABLE *)LocalAlloc(LPTR, dwIPTableSize); if(!pIpAddressTable) return FALSE; // Get the IP table if(GetIpAddrTable(pIpAddressTable, &dwIPTableSize, TRUE) != NO_ERROR) { LocalFree(pIpAddressTable); return FALSE; } // Enumerate the IP addresses. Convert the IP address // from a DWORD to a string using inet_ntoa TCHAR tchIPTableEntry[256] = TEXT("\0"); for(DWORD dwIP = 0; dwIP < pIpAddressTable->dwNumEntries; dwIP++) { MIB_IPADDRROW *pIpAddrRow = NULL; struct in_addr sAddr; pIpAddrRow = (MIB_IPADDRROW *)&pIpAddressTable->table[dwIP]; sAddr.S_un.S_addr = (IPAddr)pIpAddrRow->dwAddr; wsprintf(tchIPTableEntry, TEXT("IP Address: %hs"), inet_ntoa(sAddr)); } LocalFree(pIpAddressTable);
TIP:
You cannot modify the value of an existing IP address?you have to delete it and then add a new entry with the corrected value.
To add an IP address to an adapter, call the AddIPAddress() function:
DWORD AddIPAddress(IPAddr Address, IPMask IpMask, DWORD IfIndex, ULONG *NTEContext, ULONG *NTEInstance);
The first two parameters, Address and IPMask, specify the adapter's new IP address and subnet mask values, respectively. The lfIndex parameter is the adapter index to which you want to add the address, followed by a pointer to a ULONG variable that will receive the context value associated with the new address. The final parameter, NTEInstance, is returned an instance value for the IP address.
To delete an individual IP address, you can use the DeleteIPAddress() function:
DWORD DeleteIPAddress(ULONG NTEContext);
The only parameter that DeleteIPAddress() needs is a network table entry (NTE) context value that describes the address you want to delete. You can get the context value from a previous call to the GetAdaptersInfo() function and by looking at the IP_ADDR_STRING structure.
Finally, we will look at two functions that specifically deal with IP addresses that are created when your device uses a DHCP server. When you use a DHCP server to request an IP address for a network adapter, you are given what is known as a lease on that particular address. The address assigned to your device from a DHCP server is typically taken from a pool of addresses that are defined and distributed by the server. A DHCP lease specifies the fixed amount of time for which you have rights to use that assigned IP address. You can find out more information about when the lease was obtained and when it expires by using the GetAdaptersInfo() function.
Devices that obtain their IP address through a DHCP server usually need to either renew or release their addresses. Renewing an IP address lets the server know that you still need to use the IP address, and that you are requesting that its expiration time be extended. Conversely, releasing the address lets the server know that you no longer need it so that it can be returned to the pool of available addresses that the DHCP server can assign.
Both tasks can be accomplished by using either the IpReleaseAddress() or IpRenewAddress() function:
DWORD IpReleaseAddress(IP_ADAPTER_INDEX_MAP *AdapterInfo); DWORD IpRenewAddress(IP_ADAPTER_INDEX_MAP *AdapterInfo);
The AdapterInfo parameter is a pointer to an IP_ADAPTER_INDEX_MAP structure that you can get from calling the GetInterfaceInfo() function.
For example, the following releases the primary IP address from its DHCP lease:
if(GetInterfaceInfo(pIpInterface, &dwInterfaceSize) != NO_ERROR) { LocalFree(pIpInterface); return FALSE; } IP_ADAPTER_INDEX_MAP *pIpAdapterMapEntry = (IP_ADAPTER_INDEX_MAP *) &pIpInterface->Adapter[0]; IpReleaseAddress(pIpAdapterMapEntry);