package Win32::IPConfig::Adapter; use 5.006; use strict; use warnings; use Carp; use Win32::TieRegistry qw/:KEY_/; sub new { my $class = shift; my $hklm = shift; # connection to registry my $nic = shift; # We only need to test that $id is defined because $osversion and # $networkcards_key have already been tested by Win32::IPConfig, and # $description is not necessary for any of the object methods. my $osversion = $hklm->{"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\\\CurrentVersion"}; my $networkcards_key = $hklm->{"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards\\"}; my $description = $networkcards_key->{"$nic\\\\Description"}; my $id = $networkcards_key->{"$nic\\\\ServiceName"} or return undef; my $self = {}; $self->{"osversion"} = $osversion; $self->{"id"} = $id; $self->{"description"} = $description; # connect to the appropriate registry keys # HKLM\SYSTEM\CurrentControlSet\Services # HKLM\SYSTEM\CurrentControlSet\Tcpip\Parameters # HKLM\SYSTEM\CurrentControlSet\Netbt\Parameters # Win32::IPConfig has already tested that the following keys are defined # (or we wouldn't be here). my $services_key = $hklm->{"SYSTEM\\CurrentControlSet\\Services\\"}; my $tcpip_params_key = $services_key->{"Tcpip\\Parameters\\"}; my $netbt_params_key = $services_key->{"Netbt\\Parameters\\"}; # 2000+ specific registry keys # HKLM\...\Services\Tcpip\Parameters\Interfaces\ # HKLM\...\Services\Netbt\Parameters\Interfaces\Tcpip_ # HKLM\...\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318} my $tcpip_params_interface_key = $tcpip_params_key->{"Interfaces\\$id\\"}; my $netbt_params_interface_key = $netbt_params_key->{"Interfaces\\Tcpip_$id\\"}; my $network_connection_key = $hklm->{"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\"}; # NT4 specific registry keys # HKLM\...\Services\\Parameters # HKLM\...\Services\\Parameters\Tcpip # HKLM\...\Services\Netbt\Adapters\ my $adapter_params_key = $services_key->{"$id\\Parameters\\"}; my $adapter_params_tcpip_key = $adapter_params_key->{"Tcpip\\"}; my $netbt_adapter_key = $services_key->{"Netbt\\Adapters\\$id\\"}; # Abandon this adapter if any of the required registry keys are missing. if ($self->{"osversion"} >= 5.0) { defined $tcpip_params_interface_key or return undef; defined $netbt_params_interface_key or return undef; defined $network_connection_key or return undef; } else { defined $adapter_params_key or return undef; defined $adapter_params_tcpip_key or return undef; defined $netbt_adapter_key or return undef; } $self->{"tcpip_params_key"} = $tcpip_params_key; $self->{"netbt_params_key"} = $netbt_params_key; $self->{"tcpip_params_interface_key"} = $tcpip_params_interface_key; $self->{"netbt_params_interface_key"} = $netbt_params_interface_key; $self->{"network_connection_key"} = $network_connection_key; $self->{"adapter_params_key"} = $adapter_params_key; $self->{"adapter_params_tcpip_key"} = $adapter_params_tcpip_key; $self->{"netbt_adapter_key"} = $netbt_adapter_key; # Is DHCP enabled? As most of the methods need to know if DHCP is # enabled in order to determine which registry value to query, this # would entail an additional check of the EnableDHCP value for every value # queried. To avoid this, the EnableDHCP value is cached in the # Win32::IPConfig::Adapter object. my $key = $self->{"osversion"} >= 5.0 ? $self->{"tcpip_params_interface_key"} : $self->{"adapter_params_tcpip_key"}; if (my $enable_dhcp = $key->{"\\EnableDHCP"}) { # REG_DWORD $self->{"dhcp_enabled"} = hex($enable_dhcp); } else { die "Unable to determine if adapter is enabled for DHCP\n"; } bless $self, $class; return $self; } sub get_id { return $_[0]->{"id"}; } sub get_description { return $_[0]->{"description"}; } sub get_name { my $self = shift; my $id = $self->get_id; my $name; if ($self->{"osversion"} >= 5.0) { $name = $self->{"network_connection_key"}{"$id\\Connection\\\\Name"}; } return $name || $id; } # Value: EnableDHCP (REG_DWORD) # NT: \Parameters\Tcpip # 2000+: Tcpip\Parameters\Interfaces\ sub is_dhcp_enabled { return $_[0]->{"dhcp_enabled"}; } # Value: IPAddress (REG_MULTI_SZ) # NT: \Parameters\Tcpip # 2000+: Tcpip\Parameters\Interfaces\ sub _get_static_ipaddresses { my $self = shift; my @ipaddresses = (); my $key = $self->{"osversion"} >= 5.0 ? $self->{"tcpip_params_interface_key"} : $self->{"adapter_params_tcpip_key"}; if (my $ipaddresses = $key->{"\\IPAddress"}) { # REG_MULTI_SZ @ipaddresses = @{$ipaddresses}; } return @ipaddresses; } # Value: DhcpIPAddress (REG_SZ) # NT: \Parameters\Tcpip # 2000+: Tcpip\Parameters\Interfaces\ sub _get_dhcp_ipaddresses { my $self = shift; my @ipaddresses = (); my $key = $self->{"osversion"} >= 5.0 ? $self->{"tcpip_params_interface_key"} : $self->{"adapter_params_tcpip_key"}; if (my $dhcpipaddress = $key->{"\\DhcpIPAddress"}) { # REG_SZ @ipaddresses = ($dhcpipaddress); } return @ipaddresses; } sub get_ipaddresses { my $self = shift; # According to Q120642, if IPAddress has a first value set to something # other than 0.0.0.0, it will override DhcpIPAddress. However, in testing, # ipconfig did NOT show the statically assigned IP addresses overriding the # DHCP IP address. Additionally, pings showed that the original DHCP IP # address was still being used. # Anyway, I still can't get my head around statically configured # IP addresses on an adapter that is enabled for DHCP. # Hence the ip address returned is determined solely by whether or not the # adapter is configured for DHCP. my @ipaddresses = $self->_get_static_ipaddresses; if ($self->is_dhcp_enabled) { @ipaddresses = $self->_get_dhcp_ipaddresses; } return wantarray ? @ipaddresses : \@ipaddresses; } # Value: SubnetMask (REG_MULTI_SZ) # NT: \Parameters\Tcpip # 2000+: Tcpip\Parameters\Interfaces\ sub _get_static_subnet_masks { my $self = shift; my @subnet_masks = (); my $key = $self->{"osversion"} >= 5.0 ? $self->{"tcpip_params_interface_key"} : $self->{"adapter_params_tcpip_key"}; if (my $subnet_masks = $key->{"\\SubnetMask"}) { # REG_MULTI_SZ @subnet_masks = @{$subnet_masks}; } return @subnet_masks; } # Value: DhcpSubnetMask (REG_SZ) # NT: \Parameters\Tcpip # 2000+: Tcpip\Parameters\Interfaces\ sub _get_dhcp_subnet_masks { my $self = shift; my @subnet_masks = (); my $key = $self->{"osversion"} >= 5.0 ? $self->{"tcpip_params_interface_key"} : $self->{"adapter_params_tcpip_key"}; if (my $subnet_masks = $key->{"\\DhcpSubnetMask"}) { # REG_SZ @subnet_masks = ($subnet_masks); } return @subnet_masks; } sub get_subnet_masks { my $self = shift; # On a Windows NT 4.0 machine configured for DHCP, IPAddress was set to # ["0.0.0.0"] and SubnetMask set to ["255.0.0.0"]. On a Windows XP machine # configured for DHCP, IPAddress was set to ["0.0.0.0"] and SubnetMask set # to ["0.0.0.0"]. # The subnet mask returned is determined solely by whether or not the # adapter is configured for DHCP (just like the ip address, and unlike all # the other settings in which static settings DO override dynamic settings). my @subnet_masks = $self->_get_static_subnet_masks; if ($self->is_dhcp_enabled) { @subnet_masks = $self->_get_dhcp_subnet_masks; } return wantarray ? @subnet_masks : \@subnet_masks; } # Value: DefaultGateway (REG_MULTI_SZ) # NT: \Parameters\Tcpip # 2000+: Tcpip\Parameters\Interfaces\ sub _get_static_gateways { my $self = shift; my @gateways = (); my $key = $self->{"osversion"} >= 5.0 ? $self->{"tcpip_params_interface_key"} : $self->{"adapter_params_tcpip_key"}; if (my $gateways = $key->{"\\DefaultGateway"}) { # REG_MULTI_SZ @gateways = @{$gateways}; } @gateways = grep { $_ } @gateways; # remove any empty entries return @gateways; } # Value: DhcpDefaultGateway (REG_MULTI_SZ) # NT: \Parameters\Tcpip # 2000+: Tcpip\Parameters\Interfaces\ sub _get_dhcp_gateways { my $self = shift; my @gateways = (); my $key = $self->{"osversion"} >= 5.0 ? $self->{"tcpip_params_interface_key"} : $self->{"adapter_params_tcpip_key"}; if (my $gateways = $key->{"\\DhcpDefaultGateway"}) { # REG_MULTI_SZ @gateways = @{$gateways}; } return @gateways; } sub get_gateways { my $self = shift; # statically configured gateways override dhcp assigned gateways my @gateways = $self->_get_static_gateways; if (@gateways == 0 && $self->is_dhcp_enabled) { @gateways = $self->_get_dhcp_gateways; } return wantarray ? @gateways : \@gateways; } # Value: Domain (REG_SZ) # NT: Tcpip\Parameters # 2000+: Tcpip\Parameters (primary) # 2000+: Tcpip\Parameters\Interfaces\ (connection-specific) # Value: NV Domain (REG_SZ) # 2000+: Tcpip\Parameters # Note: NT stores the Domain setting for the machine, not for the card sub _get_static_domain { my $self = shift; my $key = $self->{"osversion"} >= 5.0 ? $self->{"tcpip_params_interface_key"} : $self->{"tcpip_params_key"}; # Returns the connection-specific DNS suffix on Windows 2000 and later. # As a convenience, returns the host DNS suffix on Windows NT. my $domain = $key->{"\\Domain"} || ""; # REG_SZ return $domain; } # Value: DhcpDomain (REG_SZ) # NT: Tcpip\Parameters # 2000+: Tcpip\Parameters # 2000+: Tcpip\Parameters\Interfaces\ (connection-specific) # Note: NT stores the DhcpDomain setting for the machine, not for the card sub _get_dhcp_domain { my $self = shift; my $key = $self->{"osversion"} >= 5.0 ? $self->{"tcpip_params_interface_key"} : $self->{"tcpip_params_key"}; # Returns the connection-specific DNS suffix on Windows 2000 and later. # As a convenience, returns the host DNS suffix on Windows NT. my $domain = $key->{"\\DhcpDomain"} || ""; # REG_SZ return $domain; } sub get_domain { my $self = shift; # statically configured domain overrides dhcp configured domain my $domain = $self->_get_static_domain; if ($self->is_dhcp_enabled && $domain eq "") { $domain = $self->_get_dhcp_domain; } return $domain; } # Value: NameServer (REG_SZ) (space delimited on NT, comma delimited on 2000+) # NT: Tcpip\Parameters # 2000+: Tcpip\Parameters\Interfaces\ # The Microsoft Support Articles Q120642 and Q314053 indicate that NameServer is # in the Tcpip\Parameters key on Windows NT, 2000, and XP. But this is wrong. # NameServer also appears to be comma delimited on Windows 2000 and later, # and not space delimited as the support articles state. sub _get_static_dns { my $self = shift; my @dns = (); # actually a NT4 host setting rather than an adapter one my $key = $self->{"osversion"} >= 5.0 ? $self->{"tcpip_params_interface_key"} : $self->{"tcpip_params_key"}; if (my $dns = $key->{"\\NameServer"}) { # REG_SZ @dns = split /[ ,]/, $dns; } return @dns; } # Value: DhcpNameServer (REG_SZ) (a space delimited list) # NT: Tcpip\Parameters # 2000+: Tcpip\Parameters\Interfaces\ # The comment that applies to NameServer above also applies to DhcpNameServer. # However, unlike NameServer, DhcpNameServer is actually space delimited # on all platforms (that I've seen so far). sub _get_dhcp_dns { my $self = shift; my @dns = (); # actually a NT4 host setting rather than an adapter one my $key = $self->{"osversion"} >= 5.0 ? $self->{"tcpip_params_interface_key"} : $self->{"tcpip_params_key"}; if (my $dns = $key->{"\\DhcpNameServer"}) { # REG_SZ @dns = split / /, $dns; } return @dns; } sub get_dns { my $self = shift; # statically configured dns servers override dhcp assigned dns servers my @dns = $self->_get_static_dns; if (@dns == 0 && $self->is_dhcp_enabled) { @dns = $self->_get_dhcp_dns; } return wantarray ? @dns : \@dns; } # Value: NameServer (REG_SZ) # NT: Netbt\Adapters\ # Value: NameServerBackup (REG_SZ) # NT: Netbt\Adapters\ # Value: NameServerList (REG_MULTI_SZ) # 2000+: Netbt\Parameters\Interfaces\Tcpip_ # Q120642 and Q314053 talk about NameServer and NameServerBackup # existing on Windows 2000 in the Netbt\Parameters\Interfaces\Tcpip_ # registry key, but this appears to be wrong. The values actually # appear to be stored in the NameServerList setting. sub _get_static_wins { my $self = shift; my @wins = (); if ($self->{"osversion"} >= 5.0) { my $key = $self->{"netbt_params_interface_key"}; if (my $wins = $key->{"\\NameServerList"}) { # REG_MULTI_SZ @wins = @{$wins}; @wins = grep { $_ } @wins; # remove empty entries } } else { my $key = $self->{"netbt_adapter_key"}; my $nameserver = $key->{"\\NameServer"}; # REG_SZ my $nameserverbackup = $key->{"\\NameServerBackup"}; # REG_SZ push @wins, $nameserver if $nameserver; push @wins, $nameserverbackup if $nameserverbackup; } return @wins; } # Value: DhcpNameServer (REG_SZ) # NT: Netbt\Adapters\ # Value: DhcpNameServerBackup (REG_SZ) # NT: Netbt\Adapters\ # Value: DhcpNameServerList (REG_MULTI_SZ) # 2000+: Netbt\Parameters\Interfaces\Tcpip_ # Q120642 and Q314053 talk about DhcpNameServer and DhcpNameServerBackup # existing on Windows 2000, but the values appear to be stored in the # DhcpNameServerList setting. sub _get_dhcp_wins { my $self = shift; my @wins = (); if ($self->{"osversion"} >= 5.0) { my $key = $self->{"netbt_params_interface_key"}; if (my $wins = $key->{"\\DhcpNameServerList"}) { # REG_MULTI_SZ @wins = @{$wins}; } } else { my $key = $self->{"netbt_adapter_key"}; my $nameserver = $key->{"\\DhcpNameServer"}; # REG_SZ my $nameserverbackup = $key->{"\\DhcpNameServerBackup"}; # REG_SZ push @wins, $nameserver if $nameserver; push @wins, $nameserverbackup if $nameserverbackup; } return @wins; } sub get_wins { my $self = shift; # statically configured wins servers override dhcp assigned wins servers my @wins = $self->_get_static_wins; if (@wins == 0 && $self->is_dhcp_enabled) { @wins = $self->_get_dhcp_wins; } return wantarray ? @wins : \@wins; } # Value: DhcpServer (REG_SZ) # NT: \Parameters\Tcpip # 2000+: Tcpip\Parameters\Interfaces\ sub get_dhcp_server { my $self = shift; croak "Adapter is not configured through DHCP" unless $self->is_dhcp_enabled; my $key = $self->{"osversion"} >= 5.0 ? $self->{"tcpip_params_interface_key"} : $self->{"adapter_params_tcpip_key"}; my $dhcpserver = $key->{"\\DhcpServer"} || ""; return $dhcpserver; } sub _format_time { my @time = localtime shift; return sprintf "%04d-%02d-%02d %02d:%02d", $time[5]+1900, $time[4]+1, $time[3], $time[2], $time[1]; } # Value: LeaseObtainedTime (REG_DWORD) # NT: \Parameters\Tcpip # 2000+: Tcpip\Parameters\Interfaces\ sub get_dhcp_lease_obtained_time { my $self = shift; croak "Adapter is not configured through DHCP" unless $self->is_dhcp_enabled; my $lease_obtained; my $key = $self->{"osversion"} >= 5.0 ? $self->{"tcpip_params_interface_key"} : $self->{"adapter_params_tcpip_key"}; if (my $time = $key->{"\\LeaseObtainedTime"}) { $lease_obtained = _format_time(hex($time)); } else { $lease_obtained = ""; } return $lease_obtained; } # Value: LeaseTerminatesTime (REG_DWORD) # NT: \Parameters\Tcpip # 2000+: Tcpip\Parameters\Interfaces\ sub get_dhcp_lease_terminates_time { my $self = shift; croak "Adapter is not configured through DHCP" unless $self->is_dhcp_enabled; my $lease_terminates; my $key = $self->{"osversion"} >= 5.0 ? $self->{"tcpip_params_interface_key"} : $self->{"adapter_params_tcpip_key"}; if (my $time = $key->{"\\LeaseTerminatesTime"}) { $lease_terminates = _format_time(hex($time)); } else { $lease_terminates = ""; } return $lease_terminates; } sub dump { my $self = shift; print "name=", $self->get_name, "\n"; print "id=", $self->get_id, "\n"; print "description=", $self->get_description, "\n"; print "domain=", $self->get_domain, " "; if ($self->_get_static_domain && $self->is_dhcp_enabled) { print "(statically overridden)"; } print "\n"; print "dhcp enabled=", $self->is_dhcp_enabled ? "Yes" : "No", "\n"; my @ipaddresses = $self->get_ipaddresses; print "ip addresses=@ipaddresses (", scalar @ipaddresses, ")\n"; my @subnet_masks = $self->get_subnet_masks; print "subnet masks=@subnet_masks (", scalar @subnet_masks, ")\n"; my @gateways = $self->get_gateways; print "gateways=@gateways (", scalar @gateways, ") "; if ($self->_get_static_gateways != 0 && $self->is_dhcp_enabled) { print "(statically overridden)"; } print "\n"; my @dns = $self->get_dns; print "dns=@dns (", scalar @dns, ") "; if ($self->_get_static_dns != 0 && $self->is_dhcp_enabled) { print "(statically overridden)"; } print "\n"; my @wins = $self->get_wins; print "wins=@wins (", scalar @wins, ") "; if ($self->_get_static_wins != 0 && $self->is_dhcp_enabled) { print "(statically overridden)"; } print "\n"; if ($self->is_dhcp_enabled) { print "dhcp server=", $self->get_dhcp_server, "\n"; print "dhcp lease obtained=", $self->get_dhcp_lease_obtained_time, "\n"; print "dhcp lease terminates=", $self->get_dhcp_lease_terminates_time, "\n"; } } sub set_domain { my $self = shift; # bail if dhcp enabled croak "Adapter is configured through DHCP" if $self->is_dhcp_enabled; my $domain = shift; croak "Invalid Domain Name Suffix" unless $domain =~ /^[\w\.\-]+$/; if ($self->{"osversion"} >= 5.0) { # Set connection-specific domain $self->{"tcpip_params_interface_key"}{"\\Domain"} = $domain; } else { # As a convenience, set the host-specific domain $self->{"tcpip_params_key"}{"\\Domain"} = $domain; } } sub set_dns { my $self = shift; # bail if dhcp enabled croak "Adapter is configured through DHCP" if $self->is_dhcp_enabled; my @dns = @_; for (@dns) { croak "Invalid IP address" if $_ !~ /^\d+\.\d+\.\d+\.\d+$/; } @dns = grep { $_ } @dns; # remove empty entries # could also check number of dns servers? if ($self->{"osversion"} >= 5.0) { $self->{"tcpip_params_interface_key"}{"\\NameServer"} = join(",", @dns); } else { $self->{"tcpip_params_key"}{"\\NameServer"} = join(" ", @dns); } } sub set_wins { my $self = shift; # bail if dhcp enabled croak "Adapter is configured through DHCP" if $self->is_dhcp_enabled; my @wins = @_; for (@wins) { croak "Invalid IP address" if $_ !~ /^\d+\.\d+\.\d+\.\d+$/; } @wins = grep { $_ } @wins; # remove empty entries # could also check number of wins servers? if ($self->{"osversion"} >= 5.0) { $self->{"netbt_params_interface_key"}{"\\NameServerList"} = [[@wins], "REG_MULTI_SZ"]; } else { $self->{"netbt_adapter_key"}{"\\NameServer"} = $wins[0]; $self->{"netbt_adapter_key"}{"\\NameServerBackup"} = $wins[1]; } } 1; __END__ =head1 NAME Win32::IPConfig::Adapter - Network Adapter IP Configuration Settings for Windows NT/2000/XP/2003 =head1 SYNOPSIS use Win32::IPConfig; $host = shift || ""; if ($ipconfig = Win32::IPConfig->new($host)) { print "hostname=", $ipconfig->get_hostname, "\n"; print "domain=", $ipconfig->get_domain, "\n"; my @searchlist = $ipconfig->get_searchlist; print "searchlist=@searchlist (", scalar @searchlist, ")\n"; print "nodetype=", $ipconfig->get_nodetype, "\n"; print "IP routing enabled=", $ipconfig->is_router ? "Yes" : "No", "\n"; print "WINS proxy enabled=", $ipconfig->is_wins_proxy ? "Yes" : "No", "\n"; print "LMHOSTS enabled=", $ipconfig->is_lmhosts_enabled ? "Yes" : "No", "\n"; print "DNS enabled for netbt=", $ipconfig->is_dns_enabled_for_netbt ? "Yes" : "No", "\n"; foreach $adapter ($ipconfig->get_adapters) { print "\nAdapter '", $adapter->get_name, "':\n"; print "Description=", $adapter->get_description, "\n"; print "DHCP enabled=", $adapter->is_dhcp_enabled ? "Yes" : "No", "\n"; @ipaddresses = $adapter->get_ipaddresses; print "IP addresses=@ipaddresses (", scalar @ipaddresses, ")\n"; @subnet_masks = $adapter->get_subnet_masks; print "subnet masks=@subnet_masks (", scalar @subnet_masks, ")\n"; @gateways = $adapter->get_gateways; print "gateways=@gateways (", scalar @gateways, ")\n"; print "domain=", $adapter->get_domain, "\n"; @dns = $adapter->get_dns; print "dns=@dns (", scalar @dns, ")\n"; @wins = $adapter->get_wins; print "wins=@wins (", scalar @wins, ")\n"; } } =head1 DESCRIPTION Win32::IPConfig::Adapter encapsulates the TCP/IP configuration settings for a Windows NT/2000/XP/2003 network adapter. =head1 METHODS =over 4 =item $adapter->get_name On Windows 2000 and later, returns the name of the connection as it appears in Network Connections, e.g. "Local Area Connection". On Windows NT returns the service name of the adapter (the same value as get_id). =item $adapter->get_id Returns the adapter id. This is used to determine where the adapter settings are stored. See REGISTRY KEYS USED in the Win32::IPConfig documentation. =item $adapter->get_description Returns the Network Adapter Description. =item $adapter->is_dhcp_enabled Returns 1 if DHCP is enabled, 0 otherwise. If DHCP is enabled, the values returned from the get_ipaddresses, get_gateways, get_domain, get_dns, and get_wins methods will be retrieved from the DHCP-specific registry keys. =item $adapter->get_ipaddresses Returns a list of IP addresses for this adapter. (Returns a reference to a list in a scalar context.) =item $adapter->get_subnet_masks Returns a list of subnet masks for this adapter. (Returns a reference to a list in a scalar context.) The order of subnet masks follows the order of IP addresses, so, for example, the 2nd subnet mask will match the 2nd IP address. =item $adapter->get_gateways Returns a list containing the default gateway IP addresses. (Returns a reference to a list in a scalar context.) If no default gateways are configured, an empty list will be returned. Statically configured default gateways will override any assigned by DHCP. (Bet you didn't realise Windows allowed you to have multiple default gateways.) =item $adapter->get_domain Returns the connection-specific domain name suffix. A statically configured domain name suffix will override any assigned by DHCP. Connection-specific domain name suffixes were introduced on Windows 2000. Windows NT machines do not support connection-specific domain names, so when run on Windows NT this method will return the domain name suffix for the host: all adapters on a Windows NT machine will therefore return the same domain name. =item $adapter->get_dns Returns a list containing DNS server IP addresses. (Returns a reference to a list in a scalar context.) If no DNS servers are configured, an empty list will be returned. Statically configured DNS Servers will override any assigned by DHCP. Only Windows 2000 and later have DNS servers configured per adapter. Windows NT machines store the DNS servers as a property of the host, not of the adapter, so when run on Windows NT this method will return the DNS servers set for the host: all adapters on a Windows NT machine will therefore return the same DNS servers. =item $adapter->get_wins Returns a list containing WINS server IP addresses. (Returns a reference to a list in a scalar context.) If no WINS servers are configured, an empty list will be returned. Statically configured WINS Servers will override any assigned by DHCP. =item $adapter->get_dhcp_server Returns the IP address of the DHCP server that supplied the adapter's IP address. You will only be able to read this value if the host adapter is configured through DHCP. =item $adapter->get_dhcp_lease_obtained_time Returns the time the DHCP lease began in the format YYYY-MM-DD HH-MM. You will only be able to read this value if the host adapter is configured through DHCP. =item $adapter->get_dhcp_lease_terminates_time Returns the time the DHCP lease runs out in the format YYYY-MM-DD HH-MM. You will only be able to read this value if the host adapter is configured through DHCP. =item $adapter->set_domain($domain_suffix) On Windows 2000 and later, sets the connection-specific domain name suffix. On Windows NT, sets the host-specific domain name suffix. You will not be allowed to set this value if the host adapter is configured through DHCP. When tested on a Windows NT system, the setting appeared to take effect immediately. When tested on a Windows 2000 system, the setting did not appear to take effect until the DNS Client service was restarted or the machine was rebooted. =item $adapter->set_dns(@dns_servers) Sets the DNS servers to @dns_servers. You can use an empty list to remove all configured DNS servers. On Windows 2000 and later, sets the DNS servers for the adapter; on Windows NT, sets the DNS servers for the host. You will not be allowed to set this value if the host adapter is configured through DHCP. When tested on a Windows NT system, the machine needed to be rebooted for it to take effect. When tested on a Windows 2000 system, the DNS Client service needed to be restarted or the machine rebooted. =item $adapter->set_wins(@wins_servers) Set the host's WINS servers to @wins_servers, which should be a list of contactable WINS servers on the network. You can use an empty list to remove all configured WINS servers. On Windows NT only the first two WINS servers will actually be set; on Windows 2000 and later, all the WINS servers you specify will be be inserted into the registry. You will not be allowed to set this value if the host adapter is configured through DHCP. When tested on a Windows NT system, the machine needed to be rebooted for the change to take effect. When tested on a Windows 2000 system, the machine also needed to be rebooted. =back =head1 AUTHOR James Macfarlane, Ejmacfarla@cpan.orgE =head1 SEE ALSO Win32::IPConfig =cut