> VMware creates number of virtual network cards (or hubs) and even provides its own dhcp server and NAT. Each virtual hub gets two addresses, on host side and VM side.
Having to fake up a DHCP server isn’t necessarily a feature – it’s kind of a nuisance to implement it correctly (see what a mess that got mobile broadband NICs into). Thus Windows 7 permits a NIC to declare “I am special. Do not attempt to use DHCP on me.” by setting EnableDhcp=0 in the miniport driver’s INF file. However, this is probably not flexible enough for you since, if you ever want to change this setting, you’d have to go reinstall your miniport.
if you want this anyway, look for a thread that mentions calling WMI from a driver.
It’s unclear to me which WMI class would be used here. Win32_NetworkAdapterConfiguration (which is the canonical WMI class for meddling with DHCP through its EnableDHCP / EnableStatic methods) can’t be called from kernel mode since its provider isn’t implemented as a driver. (MSNdis_* classes are nicer that way…).
is it something I should do from userspace?
Ultimately the easiest way to do this in a manner that works on all popular OSes (i.e., at least WinXP, possibly even Win2k) and carries the least risk of user astonishment is to have some usermode agent do the work. (Start with the previously-mentioned WMI class).
But it’s no fun if there aren’t *some* kernel APIs to play with :). On Vista / Server 2008 or later, you can actually make a solid dent in your requirements by using the kernelmode Netio API. As a caveat, however, you aren’t actually *disabling* DHCP or *permanently* configuring the interface with a static IP address. So the management UIs will be sort of misleading, in that they might state that DHCP is still enabled. (Since the permanent setting *is* still DHCP enabled.) But if the caveats are ok, then you can go party on CreateUnicastIpAddressEntry / DeleteUnicastIpAddressEntry. These routines will let you associate a temporary IP address with a network interface, and delete any the other ones.
A full discussion of how to use these APIs is located here: http://msdn.microsoft.com/en-us/library/ff552604(VS.85).aspx (ignore the fact that it’s written for Mobile Broadband miniports; much of it applies to you, except, probably, the EnableDhcp=0 INF directive). The key concept is that the OS keeps associations of tuples, and you there’s an API to enum/create/delete/query/modify these associations.
> Preventing the user from changing the configuration might be a nice feature
If you really want to get into the business of enforcing policy from kernelmode, you can register for notifications (NotifyUnicastIpAddressChange) and reassert your own addresses. But this is, IMHO, a bad idea, since it doesn’t buy you much (obviously you can’t actually protect the VM host from within the guest), and I can see code like this needlessly annoying the admin. It would not really work well with the management UIs. (“I applied the new settings successfully - now why aren’t they showing up in ipconfig?”). I think users generally understand that if they set their IP address to “some random value”, then their network might break; they don’t need any more hand-holding on that.
Anyway, more concretely, here’s some sample code to do this. I just cobbled this together from bits and pieces of my test code, so I don’t guarantee that it works – do your own QA 
#include <wdm.h>
#include <netioapi.h>
NTSTATUS
DeleteAllAddressesOnInterfaceEx(
in NET_IFINDEX TargetInterface,
in ADDRESS_FAMILY AddressFamily
);
NTSTATUS
DeleteAllAddressesOnInterface(
__in NET_IFINDEX TargetInterface
)
{
NTSTATUS NtStatus;
NtStatus = DeleteAllAddressesOnInterfaceEx(TargetInterface, AF_INET); // IPV4
if (STATUS_SUCCESS != NtStatus)
{
return NtStatus;
}
NtStatus = DeleteAllAddressesOnInterfaceEx(TargetInterface, AF_INET6); // IPV6
if (STATUS_SUCCESS != NtStatus)
{
return NtStatus;
}
return STATUS_SUCCESS;
}
NTSTATUS
DeleteAllAddressesOnInterfaceEx(
__in NET_IFINDEX TargetInterface,
__in ADDRESS_FAMILY AddressFamily
)
{
NTSTATUS NtStatus;
PMIB_UNICASTIPADDRESS_TABLE Table = NULL;
ULONG i;
// Enumerate all interfaces for the given address family
NtStatus = GetUnicastIpAddressTable(AddressFamily, &Table);
if (STATUS_SUCCESS != NtStatus)
{
return NtStatus;
}
for (i = 0; i < Table->NumEntries; i++)
{
PMIB_UNICASTIPADDRESS_ROW Row = &Table->Table[i];
// Ignore network interface if it’s not my network interface
if (Row->InterfaceIndex != TargetInterface)
{
continue;
}
// Don’t delete IPv6 link-local addresses
if ((AddressFamily == AF_INET6)
&& (Row->PrefixOrigin == IpPrefixOriginWellKnown))
{
continue;
}
NtStatus = DeleteUnicastIpAddressEntry(Row);
if (STATUS_SUCCESS != NtStatus)
{
// Note that it may be undesirable to break while we’re
// only part-way through this operation.
break;
}
}
if (Table)
{
FreeMibTable(Table);
}
return NtStatus;
}
NTSTATUS
AddAddressToInterface(
__in SOCKADDR_INET *TargetAddress,
__in NET_IFINDEX TargetInterface
)
{
NTSTATUS NtStatus;
MIB_UNICASTIPADDRESS_ROW Row;
InitializeUnicastIpAddressEntry(&Row);
Row.Address = *TargetAddress;
Row.InterfaceIndex = TargetInterface;
NtStatus = CreateUnicastIpAddressEntry(&Row);
if (STATUS_SUCCESS != NtStatus)
{
return NtStatus;
}
return NtStatus;
}
This is a stupid example of how one might use the functions above.
NTSTATUS
Set192_168_1_99(
__in NET_IFINDEX TargetIndex
)
{
NTSTATUS NtStatus;
SOCKADDR_INET Address;
NtStatus = DeleteAllAddressesOnInterface(TargetIndex);
if (STATUS_SUCCESS != NtStatus)
{
return NtStatus;
}
// Build up the IPv4 address 192.168.1.99
RtlZeroMemory(&Address, sizeof(Address));
Address.si_family = AF_INET;
Address.Ipv4.sin_addr.S_un.S_un_b.s_b1 = 192;
Address.Ipv4.sin_addr.S_un.S_un_b.s_b2 = 168;
Address.Ipv4.sin_addr.S_un.S_un_b.s_b3 = 1;
Address.Ipv4.sin_addr.S_un.S_un_b.s_b4 = 99;
NtStatus = AddAddressToInterface(&Address, TargetIndex);
if (STATUS_SUCCESS != NtStatus)
{
return NtStatus;
}
return STATUS_SUCCESS;
}
-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Pavel A.
Sent: Monday, November 22, 2010 2:09 AM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] setting an IP address - kernel or userspace?
VMware creates number of virtual network cards (or hubs) and even provides its own dhcp server and NAT. Each virtual hub gets two addresses, on host side and VM side.
Forcing the host to use IP specified by a network interface is kind of antipodic… if you want this anyway, look for a thread that mentions calling WMI from a driver.
– pa
“James Harper” wrote in message news:xxxxx@ntdev…
> Under Xen it is possible to add an IP address to the VM configuration
> file, and Linux picks this up and configures the virtual network
> interface with that IP address.
>
> If I wanted to do this under Windows, I can get the configuration data
> easily enough but can I (should I?) actually set the IP address from
> my driver or is it something I should do from userspace? Kernel would
> be nicer but only if it’s a supported thing to do.
>
> I’m comfortable with the fact that it will be set at boot time and
> that the user can change it later if they want but it will be reset
> again next boot. Preventing the user from changing the configuration
> might be a nice feature but is not necessary - appropriate firewall
> rules will prevent the user breaking the network outside their own VM.
>
> James
—
NTDEV is sponsored by OSR
For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars
To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer</netioapi.h></wdm.h>