< Chap 13: Index | Winsock 2 Main | Netstat: Retrieve TCP, UDP Tables & Protocol Statistics >
What do we have in this chapter 13 part 1?
|
This chapter will introduce you to API functions that allow you to query and manage IP characteristics on your computer. The functions are designed to help you programmatically achieve the functionality that is available in the following standard IP utilities:
The functions described in this chapter are available mainly in Windows 98, Windows Me, Windows 2000, Windows XP and so on. Several are also available in Windows NT 4.0 Service Pack 4 or later; however, none are available in Windows 95. We will point out platform specifics as we discuss each function. The prototypes for all of the functions described in this chapter are defined in IPHLPAPI.H. In addition, many of the data structures are defined in IPTYPES.H. When you are building your application, you must link it to the library file IPHLPAPI.LIB. Note that the IP Helper APIs were developed before the availability of IPv6 on the Windows platforms. Therefore, all of the APIs return information about IPv4 only except for a single new IP Helper API GetAdaptersAddresses(), which is discussed in the next section.
Ipconfig
The IPCONFIG.EXE utility presents two pieces of information: IPv4 configuration information and IPv4 configuration parameters specific to each network adapter installed on your machine.
|
To retrieve IP configuration information, use the GetNetworkParams() function, which is defined as:
DWORD GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen);
The pFixedInfo parameter receives a pointer to a buffer that receives a FIXED_INFO data structure your application must provide to retrieve the IPv4 configuration information. The pOutBufLen parameter is a pointer to a variable that specifies the size of the buffer you passed in the pFixedInfo parameter. If your buffer is not large enough, GetNetworkParams() returns ERROR_BUFFER_ OVERFLOW and sets the pOutBufLen parameter to the required buffer size. The FIXED_INFO structure used in GetNetworkParams() is defined as:
typedef struct
{
char HostName[MAX_HOSTNAME_LEN + 4] ;
char DomainName[MAX_DOMAIN_NAME_LEN + 4];
PIP_ADDR_STRING CurrentDnsServer;
IP_ADDR_STRING DnsServerList;
UINT NodeType;
char ScopeId[MAX_SCOPE_ID_LEN + 4];
UINT EnableRouting;
UINT EnableProxy;
UINT EnableDns;
} FIXED_INFO, *PFIXED_INFO;
The fields are defined as follows:
Table 16-1 Possible Node Type Values
|
|
Value |
Description |
BROADCAST_NODETYPE |
Known as b-node NetBIOS name resolution, in which the system uses IP broadcasting to perform NetBIOS name registration and name resolution. |
PEER_TO_PEER_NODETYPE |
Known as p-node NetBIOS name resolution, in which the system uses point-to-point communication with a NetBIOS name server (such as WINS) to register and resolve computer names to IP addresses. |
MIXED_NODETYPE |
Known as m-node (mixed node) NetBIOS name resolution, in which the system uses both the b-node and p-node techniques. The b-node method is used first; if it fails, the p-node method is used. |
HYBRID_NODETYPE |
Known as h-node (hybrid node) NetBIOS name resolution, in which the system uses both the b-node and p-node techniques. The p-node method is used first; if it fails, the b-node method is used next. |
The DnsServerList field of a FIXED_INFO structure is an IP_ADDR_STRING structure that represents the beginning of a linked list of IPv4 addresses. This field is defined as:
typedef struct _IP_ADDR_STRING
{
struct _IP_ADDR_STRING* Next;
IP_ADDRESS_STRING IpAddress;
IP_MASK_STRING IpMask;
DWORD Context;
} IP_ADDR_STRING, *PIP_ADDR_STRING;
The Next field identifies the next DNS server IPv4 address in the list. If Next is set to NULL, it indicates the end of the list. The IpAddress field is a string of characters that represents an IPv4 address as a dotted decimal string. The IpMask field is a string of characters that represents the subnet mask associated with the IPv4 address listed in IpAddress. The final field, Context, identifies the IPv4 address with a unique value on the system.
The IPCONFIG.EXE utility is also capable of retrieving IP configuration information specific to a network interface. A network interface can be a hardware Ethernet adapter or even a RAS dial-up adapter. You can retrieve adapter information by calling GetAdaptersInfo(), which is defined as:
DWORD GetAdaptersInfo (PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen);
Use the pAdapterInfo parameter to pass a pointer to an application-provided buffer that receives an ADAPTER_INFO data structure with the adapter configuration information. The pOutBufLen parameter is a pointer to a variable that specifies the size of the buffer you passed in the pAdapterInfo parameter. If your buffer is not large enough, GetAdaptersInfo() returns ERROR_BUFFER_ OVERFLOW and sets the pOutBufLen parameter to the required buffer size.
The IP_ADAPTER_INFO structure is actually a list of structures containing IPv4 configuration information specific to every network adapter available on your machine. IP_ADAPTER_INFO is defined as:
typedef struct _IP_ADAPTER_INFO
{
struct _IP_ADAPTER_INFO* Next;
DWORD ComboIndex;
char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4];
char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];
UINT AddressLength;
BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH];
DWORD Index;
UINT Type;
UINT DhcpEnabled;
PIP_ADDR_STRING CurrentIpAddress;
IP_ADDR_STRING IpAddressList;
IP_ADDR_STRING GatewayList;
IP_ADDR_STRING DhcpServer;
BOOL HaveWins;
IP_ADDR_STRING PrimaryWinsServer;
IP_ADDR_STRING SecondaryWinsServer;
time_t LeaseObtained;
time_t LeaseExpires;
} IP_ADAPTER_INFO, *PIP_ADAPTER_INFO;
The fields of the structure are defined as follows:
Table 16-2 Adapter Types
|
|
Adapter Type Value |
Description |
MIB_IF_TYPE_ETHERNET |
Ethernet adapter |
MIB_IF_TYPE_FDDI |
Fiber Distributed Data Interface (FDDI) adapter |
MIB_IF_TYPE_LOOPBACK |
Loopback adapter |
MIB_IF_TYPE_OTHER |
Other type of adapter |
MIB_IF_TYPE_PPP |
PPP adapter |
MIB_IF_TYPE_SLIP |
Slip adapter |
MIB_IF_TYPE_TOKENRING |
Token Ring adapter |
The GetAdaptersInfo() returns a great deal of information about the physical adapter and the IPv4 addresses assigned to it, but it does not return any IPv6 information. Instead, a new API GetAdaptersAddresses() has been introduced to fill this gap as it returns address information for both IPv4 and IPv6. The API is declared as:
DWORD WINAPI GetAdaptersAddresses(
ULONG Family,
DWORD Flags,
PVOID Reserved,
PIP_ADAPTER_ADDRESSES pAdapterAddresses,
PULONG pOutBufLen
);
The Family parameter indicates which address family should be enumerated. The valid values are: AF_INET, AF_INET6, or AF_UNSPEC, depending on whether you want IPv4, IPv6, or all IP information. The Flags parameter controls the type of addresses returned. Table 16-3 lists the possible values and their meaning. Note that more than one flag can be specified by ORing multiple flags together. By default, all addresses are returned. The last two parameters are the buffer that the IP information is returned in and the length of the buffer.
-----------------------------------------------------------
Table 16-3 GetAdaptersAddresses() Flag
|
|
Flag |
Description |
GAA_FLAG_SKIP_UNICAST |
Exclude unicast addresses. |
GAA_FLAG_SKIP_ANYCAST |
Exclude anycast addresses. |
GAA_FLAG_SKIP_MULTICAST |
Exclude multicast addresses. |
GAA_FLAG_SKIP_DNS_SERVER |
Exclude DNS server addresses. |
The IP information is returned in the form of an IP_ADAPTER_ADDRESSES structure. This structure is defined as:
typedef struct _IP_ADAPTER_ADDRESSES {
union {
ULONGLONG Alignment;
struct {
ULONG Length;
DWORD IfIndex;
}
}
struct _IP_ADAPTER_ADDRESSES *Next;
PCHAR AdapterName;
PIP_ADAPTER_UNICAST_ADDRESS FirstUnicastAddress;
PIP_ADAPTER_ANYCAST_ADDRESS FirstAnycastAddress;
PIP_ADAPTER_MULTICAST_ADDRESS FirstMulticastAddress;
PIP_ADAPTER_DNS_SERVER_ADDRESS FirstDnsServerAddress;
PWCHAR DnsSuffix;
PWCHAR Description;
PWCHAR FriendlyName;
BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH];
DWORD PhysicalAddressLength;
DWORD Flags;
DWORD Mtu;
DWORD IfType;
IF_OPER_STATUS OperStatus;
DWORD Ipv6IfIndex;
DWORD ZoneIndices[16];
PIP_ADAPTER_PREFIX FirstPrefix;
} IP_ADAPTER_ADDRESSES, *PIP_ADAPTER_ADDRESSES;
Table 16-4 IP_ADAPTERS_ADDRESSES Flags
|
|
Flag |
Description |
IP_ADAPTER_DDNS_ENABLED |
Dynamic DNS is enabled on this adapter. |
IP_ADAPTER_REGISTER_ADAPTER_SUFFIX |
The DNS suffix for this adapter is registered. |
IP_ADAPTER_DHCP_ENABLED |
DHCP is enabled on this adapter. |
IP_ADAPTER_RECEIVE_ONLY |
The interface is capable of receiving data only. |
IP_ADAPTER_NO_MULTICAST |
The interface is not capable of receiving multicast data. |
IP_ADAPTER_IPV6_OTHER_STATEFUL_CONFIG |
Indicates the “O” bit in the most recently received IPv6 router advertisement was set. This indicates the presence of stateful configuration information such as DHCPv6. |
The last piece of the IP_ADAPTERS_ADDRESSES structure is the adapter structures. These four structures are very similar and for the most part contain the same kind of information. We'll discuss only the unicast version of the structure because the remaining address structures can be inferred from this one. The unicast structure is defined as:
typedef struct _IP_ADAPTER_UNICAST_ADDRESS {
union {
ULONGLONG Alignment;
struct {
ULONG Length;
DWORD Flags;
};
};
struct _IP_ADAPTER_UNICAST_ADDRESS *Next;
SOCKET_ADDRESS Address;
IP_PREFIX_ORIGIN PrefixOrigin;
IP_SUFFIX_ORIGIN SuffixOrigin;
IP_DAD_STATE DadState;
ULONG ValidLifetime;
ULONG PreferredLifeTime;
ULONG LeaseLifeTime;
} IP_ADAPTER_UNICAST_ADDRESS, *PIP_ADAPTER_UNICAST_ADDRESS;
Table 16-5 Per Address Flags
|
|
Per Address Flags |
Description |
IP_ADAPTER_ADDRESS_DNS_ELIGIBLE |
Address can be registered with DNS (such as DHCP or RA assigned). |
IP_ADAPTER_ADDRESS_TRANSIENT |
Address is not a permanent address (such as IPv6 privacy address). |
Table 16-6 Prefix Origin Values
|
|
Prefix Origin Value |
Description |
IpPrefixOriginOther |
Prefix obtained from source other than those listed in this table. |
IpPrefixOriginManual |
Prefix was manually configured - for example, assigning a static IPv4 address. |
IpPrefixOriginWellKnown |
Prefix is a well-known address - for example, the loopback address. |
IpPrefixOriginDhcp |
Prefix is assigned by DHCP. |
IpPrefixOriginRouterAdvertisement |
Prefix is assigned by a router advertisement - for example, an IPv6 site local or global address. |
Table 16-7 Suffix Origin Values
|
|
Suffix Origin Value |
Description |
IpSuffixOriginOther |
Suffix obtained from a source other than those listed in this table. |
IpSuffixOriginManual |
Suffix was configured manually - for example, a statically assigned IP address. |
IpSuffixOriginWellKnown |
Suffix is a well-known address - for example, the loopback adapter. |
IpSuffixOriginDhcp |
Suffix is assigned by DHCP. |
IpSuffixOriginLinkLayerAddress |
Suffix is obtained from the lower network layer. For example, IPv6 link local addresses. |
IpSuffixOriginRandom |
Suffix is a randomly assigned value. For example, IPv6 privacy addresses. |
Table 16-8 Address States
|
|
Address State |
Description |
IpDadStateInvalid |
Address is in the process of being deleted. |
IpDadStateTentative |
Duplicate address detection is in progress. |
IpDadStateDuplicate |
A duplicate address has been detected. |
IpDadStateDeprecated |
Address is no longer preferred for new connections. |
IpDatStatePreferred |
Address is the preferred address. |
The IPCONFIG.EXE utility also features the ability to release and renew IPv4 addresses obtained from the DHCP server by specifying the /release and /renew command line parameters. If you want to programmatically release an IPv4 address, you can call the IPReleaseAddress() function, which is defined as:
DWORD IpReleaseAddress (PIP_ADAPTER_INDEX_MAP AdapterInfo);
If you want to renew an IP address, you can call the IPRenewAddress() function, which is defined as:
DWORD IpRenewAddress (PIP_ADAPTER_INDEX_MAP AdapterInfo);
Each of these two functions features an AdapterInfo parameter that is an IP_ADAPTER_INDEX_MAP structure, which identifies the adapter to release or renew the address for. The IP_ADAPTER_INDEX_MAP structure is defined as:
typedef struct _IP_ADAPTER_INDEX_MAP
{
ULONG Index;
WCHAR Name[MAX_ADAPTER_NAME];
}IP_ADAPTER_INDEX_MAP, *PIP_ADAPTER_INDEX_MAP;
The fields of this structure are defined as follows:
You can retrieve the IP_ADAPTER_INDEX_MAP structure for a particular adapter by calling the GetInterfaceInfo() function, which is defined as:
DWORD GetInterfaceInfo (IN PIP_INTERFACE_INFO pIfTable, OUT PULONG dwOutBufLen);
The pIfTable parameter is a pointer to an IP_INTERFACE_INFO application buffer that will receive interface information. The dwOutBufLen parameter is a pointer to a variable that specifies the size of the buffer you passed in the pIfTable parameter. If the buffer is not large enough to hold the interface information, GetInterfaceInfo() returns the error ERROR_INSUFFICIENT_BUFFER and sets the dwOutBufLen parameter to the required buffer size. The IP_INTERFACE_INFO structure is defined as:
typedef struct _IP_INTERFACE_INFO
{
LONG NumAdapters;
IP_ADAPTER_INDEX_MAP Adapter[1];
} IP_INTERFACE_INFO,*PIP_INTERFACE_INFO;
Its fields are defined as follows:
Once you have obtained the IP_ADAPTER_INDEX_MAP structure for a particular adapter, you can release or renew the DHCP-assigned IPv4 address using the IPReleaseAddress() and IPRenewAddress() functions we just described.
The IPCONFIG.EXE utility does not allow you to change an IP address for a network adapter (except in the case of DHCP). However, two functions will allow you to add or delete an IP address for a particular adapter: the AddIpAddress() and DeleteIpAddress() IP Helper functions. These require you to understand adapter index numbers and IP context numbers. In Windows, every network adapter has a unique index ID (which we described earlier), and every IP address has a unique context ID. Adapter index IDs and IP context numbers can be retrieved using GetAdaptersInfo(). The AddIpAddress() function is defined as:
DWORD AddIPAddress (
IPAddr Address,
IPMask IpMask,
DWORD IfIndex,
PULONG NTEContext,
PULONG NTEInstance
);
The Address parameter specifies the IPv4 address to add as an unsigned long value. The IpMask parameter specifies the subnet mask for the IPv4 address as an unsigned long value. The IfIndex parameter specifies the adapter index to add the address to. The NTEContext parameter receives the context value associated with the IPv4 address added. The NTEInstance parameter receives an instance value associated with an IPv4 address.
If you want to programmatically delete an IPv4 address for an adapter, you can call DeleteIpAddress(), which is defined as:
DWORD DeleteIPAddress (ULONG NTEContext);
The NTEContext parameter identifies a context value associated with an IPv4 address. This value can be obtained from GetAdaptersInfo(), which we described earlier in the chapter.
Note that IPv4 addresses added via the AddIpAddress function are persistent only until reboot.
< Chap 13: Index | Winsock 2 Main | Netstat: Retrieve TCP, UDP Tables & Protocol Statistics >