Seems we were confused and DHCP doesn't actually interfere with adding
an address
via AddIPAddress however it does block netsh from adding a 2nd
address.
For anyone interested here is a C program built mostly from examples
in the MSDN
which uses AddIPAddress and DeleteIPAddress and will list the
interfaces and/or
the current set of ip addresses.
---------------------------------------------------------------------------------------------------------------------------------
/* Program: iphelper..c
* This is a collection of code pulled together from various
* examples in the MSDN to create a program that can add and
* delete IP alias addresses using AddIPAddress and DeleteIPAddress
*
* cc [-Zi] -c iphelper.c
* link [/debug] iphelper.obj
*/
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
/* Note: could also use malloc() and free() */
int listInterfaces();
int listAddresses();
int addAddress(UINT,UINT,UINT);
int delAddress(UINT);
int findAdapter(UINT);
int findIndex(UINT);
dohelp(char *prog) {
printf("usage: %s -a IPAddress NewIPAddress SubnetMask\n", prog);
printf("usage: %s -d IPAddress\n", prog);
printf("usage: %s -li list interfaces\n", prog);
printf("usage: %s -la list addresses\n", prog);
}
int __cdecl main(int argc, char **argv)
{
UINT iaNewIPAddress;
UINT iaIPAddress;
UINT iaIPMask;
char opt;
int rc;
ULONG context;
if (argc < 2 || *argv[1] != '-') {
dohelp(argv[0]);
exit(1);
}
opt = argv[1][1];
opt = tolower(opt);
if (opt != 'l' && opt != 'a' && opt != 'd') {
printf("invalid option -%c\n",opt);
dohelp(argv[0]);
exit(1);
}
if (opt == 'l') {
opt = argv[1][2];
opt = tolower(opt);
if (opt == 'i')
listInterfaces();
else if (opt == 'a')
listAddresses();
else {
printf("invalid list type -l%c\n",opt);
dohelp(argv[0]);
}
exit(0);
}
if ((opt == 'd' && argc != 3) ||
(opt == 'a' && argc != 5)) {
printf("Insufficient arguments for -%c\n",opt);
dohelp(argv[0]);
exit(1);
}
if (opt == 'a') {
iaIPAddress = inet_addr(argv[2]);
if (iaIPAddress == INADDR_NONE) {
printf("1st argument is not a valid ip address\n");
dohelp(argv[0]);
exit(1);
}
iaNewIPAddress = inet_addr(argv[3]);
if (iaNewIPAddress == INADDR_NONE) {
printf("New IP address is invalid\n");
dohelp(argv[0]);
exit(1);
}
iaIPMask = inet_addr(argv[4]);
if (iaIPMask == INADDR_NONE) {
printf("Invalid subnet mask\n");
dohelp(argv[0]);
exit(1);
}
rc = addAddress(iaIPAddress, iaNewIPAddress, iaIPMask);
}
if (opt == 'd') {
iaIPAddress = inet_addr(argv[2]);
if (iaIPAddress == INADDR_NONE) {
printf("1st argument is not a valid ip address\n");
dohelp(argv[0]);
exit(1);
}
rc = delAddress(iaIPAddress);
}
exit(rc);
}
/* Note: could also use malloc() and free() */
addAddress(UINT iaTargIPAddress, UINT iaIPAddress, UINT iaIPMask)
{
/* Variables used by GetIpAddrTable */
DWORD ifIndex;
/* Variables where handles to the added IP are returned */
ULONG NTEContext = 0;
ULONG NTEInstance = 0;
DWORD dwRetVal = 0;
/* Variables used to return error message */
LPVOID lpMsgBuf;
ifIndex = findAdapter(iaTargIPAddress);
if (ifIndex == -1) {
printf("Failed to find existing adaptor for target address\n");
return 1; /* failure */
}
if ((dwRetVal = AddIPAddress(iaIPAddress,
iaIPMask,
ifIndex,
&NTEContext, &NTEInstance)) == NO_ERROR) {
printf("\tIPv4 address was successfully added.\n");
} else {
printf("AddIPAddress failed with error: %d\n", dwRetVal);
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default
language
(LPTSTR) & lpMsgBuf, 0, NULL)) {
printf("\tError: %s", lpMsgBuf);
LocalFree(lpMsgBuf);
return 1;
}
}
return 0;
}
delAddress(UINT iAddr)
{
DWORD dwRetVal = 0;
int context;
context = findIndex(iAddr);
if (context == -1) {
printf("Failed to find address to delete\n");
return 1;
}
if ((dwRetVal = DeleteIPAddress(context)) != NO_ERROR) {
printf("DeleteIPAddress call failed with %d\n", dwRetVal);
}
return 0;
}
listInterfaces() {
/* Declare and initialize variables */
// It is possible for an adapter to have multiple
// IPv4 addresses, gateways, and secondary WINS servers
// assigned to the adapter.
//
// Note that this sample code only prints out the
// first entry for the IP address/mask, and gateway, and
// the primary and secondary WINS server for each adapter.
PIP_ADAPTER_INFO pAdapterInfo;
PIP_ADAPTER_INFO pAdapter = NULL;
DWORD dwRetVal = 0;
UINT i;
/* variables used to print DHCP time info */
struct tm newtime;
char buffer[32];
errno_t error;
ULONG ulOutBufLen = sizeof (IP_ADAPTER_INFO);
pAdapterInfo = (IP_ADAPTER_INFO *) MALLOC(sizeof
(IP_ADAPTER_INFO));
if (pAdapterInfo == NULL) {
printf("Error allocating memory needed to call GetAdaptersinfo
\n");
return 1;
}
// Make an initial call to GetAdaptersInfo to get
// the necessary size into the ulOutBufLen variable
if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) ==
ERROR_BUFFER_OVERFLOW) {
FREE(pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO *) MALLOC(ulOutBufLen);
if (pAdapterInfo == NULL) {
printf("Error allocating memory needed to call GetAdaptersinfo\n");
return 1;
}
}
if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) ==
NO_ERROR) {
pAdapter = pAdapterInfo;
while (pAdapter) {
printf("\tComboIndex: \t%d\n", pAdapter->ComboIndex);
printf("\tAdapter Name: \t%s\n", pAdapter->AdapterName);
printf("\tAdapter Desc: \t%s\n", pAdapter->Description);
printf("\tAdapter Addr: \t");
for (i = 0; i < pAdapter->AddressLength; i++) {
if (i == (pAdapter->AddressLength - 1))
printf("%.2X\n", (int) pAdapter->Address
);
else
printf("%.2X-", (int) pAdapter->Address);
}
printf("\tIndex: \t%d\n", pAdapter->Index);
printf("\tType: \t");
switch (pAdapter->Type) {
case MIB_IF_TYPE_OTHER:
printf("Other\n");
break;
case MIB_IF_TYPE_ETHERNET:
printf("Ethernet\n");
break;
case MIB_IF_TYPE_TOKENRING:
printf("Token Ring\n");
break;
case MIB_IF_TYPE_FDDI:
printf("FDDI\n");
break;
case MIB_IF_TYPE_PPP:
printf("PPP\n");
break;
case MIB_IF_TYPE_LOOPBACK:
printf("Lookback\n");
break;
case MIB_IF_TYPE_SLIP:
printf("Slip\n");
break;
default:
printf("Unknown type %ld\n", pAdapter->Type);
break;
}
printf("\tIP Address: \t%s\n",
pAdapter->IpAddressList.IpAddress.String);
printf("\tIP Mask: \t%s\n", pAdapter->IpAddressList.IpMask.String);
printf("\tGateway: \t%s\n", pAdapter->GatewayList.IpAddress.String);
printf("\t***\n");
if (pAdapter->DhcpEnabled) {
printf("\tDHCP Enabled: Yes\n");
printf("\t DHCP Server: \t%s\n",
pAdapter->DhcpServer.IpAddress.String);
printf("\t Lease Obtained: ");
/* Display local time */
error = _localtime32_s(&newtime, (__time32_t*) &pAdapter-
if (error)
printf("Invalid Argument to _localtime32_s\n");
else {
// Convert to an ASCII representation
error = asctime_s(buffer, 32, &newtime);
if (error)
printf("Invalid Argument to asctime_s\n");
else
/* asctime_s returns the string terminated by \n\0 */
printf("%s", buffer);
}
printf("\t Lease Expires: ");
error = _localtime32_s(&newtime, (__time32_t*) &pAdapter-
if (error)
printf("Invalid Argument to _localtime32_s\n");
else {
// Convert to an ASCII representation
error = asctime_s(buffer, 32, &newtime);
if (error)
printf("Invalid Argument to asctime_s\n");
else
/* asctime_s returns the string terminated by \n\0 */
printf("%s", buffer);
}
} else
printf("\tDHCP Enabled: No\n");
if (pAdapter->HaveWins) {
printf("\tHave Wins: Yes\n");
printf("\t Primary Wins Server: %s\n",
pAdapter->PrimaryWinsServer.IpAddress.String);
printf("\t Secondary Wins Server: %s\n",
pAdapter->SecondaryWinsServer.IpAddress.String);
} else
printf("\tHave Wins: No\n");
pAdapter = pAdapter->Next;
printf("\n");
}
} else {
printf("GetAdaptersInfo failed with error: %d\n", dwRetVal);
}
if (pAdapterInfo)
FREE(pAdapterInfo);
return 0;
}
int findAdapter(UINT iaAddress) {
int i;
int ifIndex;
/* Variables used by GetIpAddrTable */
PMIB_IPADDRTABLE pIPAddrTable;
DWORD dwSize = 0;
DWORD dwRetVal = 0;
IN_ADDR IPAddr;
/* Variables used to return error message */
LPVOID lpMsgBuf;
// Before calling AddIPAddress we use GetIpAddrTable to get
// an adapter to which we can add the IP.
pIPAddrTable = (MIB_IPADDRTABLE *) MALLOC(sizeof
(MIB_IPADDRTABLE));
if (pIPAddrTable) {
// Make an initial call to GetIpAddrTable to get the
// necessary size into the dwSize variable
if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) ==
ERROR_INSUFFICIENT_BUFFER) {
FREE(pIPAddrTable);
pIPAddrTable = (MIB_IPADDRTABLE *) MALLOC(dwSize);
}
if (pIPAddrTable == NULL) {
printf("Memory allocation failed for GetIpAddrTable\n");
return -1;
}
}
// Make a second call to GetIpAddrTable to get the
// actual data we want
if ( (dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 )) !=
NO_ERROR ) {
printf("GetIpAddrTable failed with error %d\n", dwRetVal);
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default
language
(LPTSTR) & lpMsgBuf, 0, NULL)) {
printf("\tError: %s", lpMsgBuf);
LocalFree(lpMsgBuf);
}
return -1;
}
ifIndex = -1; /* not found */
for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) {
if ((u_long) pIPAddrTable->table.dwAddr == iaAddress) {
ifIndex = pIPAddrTable->table.dwIndex;
goto done;
}
}
done:
if (pIPAddrTable) {
FREE(pIPAddrTable);
pIPAddrTable = NULL;
}
return ifIndex;
}
int listAddresses() {
int i;
/* Variables used by GetIpAddrTable */
PMIB_IPADDRTABLE pIPAddrTable;
DWORD dwSize = 0;
DWORD dwRetVal = 0;
IN_ADDR IPAddr;
/* Variables used to return error message */
LPVOID lpMsgBuf;
// Before calling AddIPAddress we use GetIpAddrTable to get
// an adapter to which we can add the IP.
pIPAddrTable = (MIB_IPADDRTABLE *) MALLOC(sizeof
(MIB_IPADDRTABLE));
if (pIPAddrTable) {
// Make an initial call to GetIpAddrTable to get the
// necessary size into the dwSize variable
if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) ==
ERROR_INSUFFICIENT_BUFFER) {
FREE(pIPAddrTable);
pIPAddrTable = (MIB_IPADDRTABLE *) MALLOC(dwSize);
}
if (pIPAddrTable == NULL) {
printf("Memory allocation failed for GetIpAddrTable\n");
return 0;
}
}
// Make a second call to GetIpAddrTable to get the
// actual data we want
if ( (dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 )) !=
NO_ERROR ) {
printf("GetIpAddrTable failed with error %d\n", dwRetVal);
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default
language
(LPTSTR) & lpMsgBuf, 0, NULL)) {
printf("\tError: %s", lpMsgBuf);
LocalFree(lpMsgBuf);
}
return 0;
}
printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries);
for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) {
printf("\n\tInterface Index[%d]:\t%ld\n", i, pIPAddrTable->table
.dwIndex);
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table.dwAddr;
printf("\tIP Address[%d]: \t%s\n", i, inet_ntoa(IPAddr) );
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table.dwMask;
printf("\tSubnet Mask[%d]: \t%s\n", i, inet_ntoa(IPAddr) );
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table
.dwBCastAddr;
printf("\tBroadCast[%d]: \t%s (%ld%)\n", i, inet_ntoa
(IPAddr), pIPAddrTable->table.dwBCastAddr);
printf("\tReassembly size[%d]:\t%ld\n", i, pIPAddrTable->table
.dwReasmSize);
printf("\tType and State[%d]:", i);
if (pIPAddrTable->table.wType & MIB_IPADDR_PRIMARY)
printf("\tPrimary IP Address");
if (pIPAddrTable->table.wType & MIB_IPADDR_DYNAMIC)
printf("\tDynamic IP Address");
if (pIPAddrTable->table.wType & MIB_IPADDR_DISCONNECTED)
printf("\tAddress is on disconnected interface");
if (pIPAddrTable->table.wType & MIB_IPADDR_DELETED)
printf("\tAddress is being deleted");
if (pIPAddrTable->table.wType & MIB_IPADDR_TRANSIENT)
printf("\tTransient address");
printf("\n");
}
if (pIPAddrTable) {
FREE(pIPAddrTable);
pIPAddrTable = NULL;
}
return 0;
}
int findIndex(UINT iFindAddr) {
/* Declare and initialize variables */
// It is possible for an adapter to have multiple
// IPv4 addresses, gateways, and secondary WINS servers
// assigned to the adapter.
//
// Note that this sample code only prints out the
// first entry for the IP address/mask, and gateway, and
// the primary and secondary WINS server for each adapter.
IP_ADDR_STRING * pIPAddr;
PIP_ADAPTER_INFO pAdapterInfo;
PIP_ADAPTER_INFO pAdapter = NULL;
DWORD dwRetVal = 0;
UINT i;
UINT iAddr;
int retContext;
/* variables used to print DHCP time info */
struct tm newtime;
char buffer[32];
errno_t error;
ULONG ulOutBufLen = sizeof (IP_ADAPTER_INFO);
pAdapterInfo = (IP_ADAPTER_INFO *) MALLOC(sizeof
(IP_ADAPTER_INFO));
if (pAdapterInfo == NULL) {
printf("Error allocating memory needed to call GetAdaptersinfo\n");
return -1;
}
// Make an initial call to GetAdaptersInfo to get
// the necessary size into the ulOutBufLen variable
if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) ==
ERROR_BUFFER_OVERFLOW) {
FREE(pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO *) MALLOC(ulOutBufLen);
if (pAdapterInfo == NULL) {
printf("Error allocating memory needed to call GetAdaptersinfo
\n");
return -1;
}
}
retContext = -1;
if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) ==
NO_ERROR) {
pAdapter = pAdapterInfo;
while (pAdapter) {
pIPAddr = &pAdapter->IpAddressList;
while (pIPAddr) {
iAddr = inet_addr(pIPAddr->IpAddress.String);
if (iAddr == iFindAddr) {
retContext = pIPAddr->Context;
goto done;
}
pIPAddr = pIPAddr->Next;
}
pAdapter = pAdapter->Next;
}
} else {
printf("GetAdaptersInfo failed with error: %d\n", dwRetVal);
}
done:
if (pAdapterInfo)
FREE(pAdapterInfo);
return retContext;
}