File Coverage

blib/lib/Win32/IPConfig.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             package Win32::IPConfig;
2            
3 1     1   10815 use 5.006;
  1         4  
  1         36  
4 1     1   5 use strict;
  1         2  
  1         33  
5 1     1   5 use warnings;
  1         7  
  1         56  
6            
7             our $VERSION = '0.10';
8            
9 1     1   5 use Carp;
  1         2  
  1         84  
10 1     1   1773 use Win32::TieRegistry qw/:KEY_/;
  0            
  0            
11             use Win32::IPConfig::Adapter;
12            
13             sub new
14             {
15             my $class = shift;
16             my $host = shift || "";
17             my $access = shift || "ro";
18            
19             my $hklm = $Registry->Connect($host, "HKEY_LOCAL_MACHINE",
20             { Access => $access eq 'rw' ? KEY_READ|KEY_WRITE : KEY_READ })
21             or return undef;
22            
23             $hklm->SplitMultis(1); # return REG_MULTI_SZ as arrays
24            
25             my $osversion = $hklm->{"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\\\CurrentVersion"} or return undef;
26            
27             my $self = {};
28             $self->{"osversion"} = $osversion;
29             $self->{"access"} = $access;
30            
31             # Remember the necessary registry keys
32             my $services_key = $hklm->{"SYSTEM\\CurrentControlSet\\Services\\"}
33             or return undef;
34             $self->{"netbt_params_key"} = $services_key->{"Netbt\\Parameters\\"}
35             or return undef;
36             $self->{"tcpip_params_key"} = $services_key->{"Tcpip\\Parameters\\"}
37             or return undef;
38            
39             # Retrieve each network card's config
40             my $networkcards_key = $hklm->{"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards\\"} or return undef;
41             for my $nic ($networkcards_key->SubKeyNames) {
42             if (my $adapter = Win32::IPConfig::Adapter->new($hklm, $nic, $access)) {
43             push @{$self->{"adapters"}}, $adapter;
44             }
45             }
46            
47             bless $self, $class;
48             return $self;
49             }
50            
51             sub get_adapters
52             {
53             return wantarray ? @{$_[0]->{"adapters"}} : $_[0]->{"adapters"};
54             }
55            
56             sub get_configured_adapters
57             {
58             my @adapters = ();
59             for my $adapter (@{$_[0]->{"adapters"}}) {
60             if (my @ipaddresses = $adapter->get_ipaddresses) {
61             push @adapters, $adapter unless $ipaddresses[0] eq "0.0.0.0";
62             }
63             }
64             return wantarray ? @adapters : \@adapters;
65             }
66            
67             sub get_osversion { return $_[0]->{"osversion"}; }
68            
69             # Value: Hostname (REG_SZ)
70             # NT: Tcpip\Parameters
71             # 2000+: Tcpip\Parameters
72            
73             # Value: NV Hostname (REG_SZ)
74             # 2000+: Tcpip\Parameters
75            
76             sub get_hostname
77             {
78             my $self = shift;
79            
80             return $self->{"tcpip_params_key"}{"\\Hostname"};
81             }
82            
83             # Value: Domain (REG_SZ)
84             # NT: Tcpip\Parameters
85             # 2000+: Tcpip\Parameters (primary)
86             # 2000+: Tcpip\Parameters\Interfaces\ (connection-specific)
87            
88             # Value: NV Domain (REG_SZ)
89             # 2000+: Tcpip\Parameters
90            
91             # Value: DhcpDomain (REG_SZ)
92             # NT: Tcpip\Parameters
93             # 2000+: Tcpip\Parameters
94             # 2000+: Tcpip\Parameters\Interfaces\ (connection-specific)
95            
96             # How do you know when to read the Domain value and when to read the DhcpDomain
97             # value? The Domain and DhcpDomain values are attributes of a host, but
98             # the EnableDHCP value is an attribute of an adapter.
99            
100             # On Windows NT 4.0, when I set the adapter to static, the DhcpDomain
101             # setting disappears from the registry to leave only the empty Domain setting.
102             # This also appears to be the case on Windows XP.
103            
104             # What happens when Domain setting is set statically and an adapter card adds a
105             # DhcpDomain setting as well - i.e. when both Domain and DhcpDomain exist?
106            
107             # On Windows NT 4.0, when I set the adapter to dynamic and set a static domain
108             # setting, the static domain setting is returned by ipconfig /all while both
109             # settings exist in the registry.
110            
111             # This suggests: return the Domain setting if it is non-empty. Otherwise
112             # return the DhcpDomain if it is present. Otherwise, return an empty string.
113            
114             sub get_domain
115             {
116             my $self = shift;
117            
118             my $domain = $self->{"tcpip_params_key"}{"\\Domain"};
119             if (! $domain) {
120             $domain = $self->{"tcpip_params_key"}{"\\DhcpDomain"} || "";
121             }
122             return $domain;
123             }
124            
125             # Value: SearchList (REG_SZ) (space delimited on NT, comma delimited on 2000+)
126             # NT: Tcpip\Parameters
127             # 2000+: Tcpip\Parameters
128            
129             # The Windows 2000 Advanced TCP/IP Settings dialog gives you the choice of
130             # resolving unqualified names by:
131             # 1. appending primary and connection specific DNS suffixes
132             # 2. appending a user-specified list of DNS suffixes
133             # It appears to choose between each method simply by seeing if
134             # SearchList is set or not: if it is set, use it, otherwise append
135             # the primary and connection specific DNS suffixes.
136            
137             # The Windows NT Microsoft TCP/IP Properties dialog simply allows you
138             # the option of specifying a domain suffix search order.
139            
140             sub get_searchlist
141             {
142             my $self = shift;
143            
144             my @searchlist;
145             if ($self->{"osversion"} >= 5.0) {
146             @searchlist = split /,/, $self->{"tcpip_params_key"}{"\\SearchList"};
147             } else {
148             @searchlist = split / /, $self->{"tcpip_params_key"}{"\\SearchList"};
149             }
150             return wantarray ? @searchlist : \@searchlist;
151             }
152            
153             # Value: NodeType (REG_DWORD)
154             # NT: Netbt\Parameters
155             # 2000+: Netbt\Parameters
156            
157             # Value: DhcpNodeType (REG_DWORD) (overidden by NodeType)
158             # NT: Netbt\Parameters
159             # 2000+: Netbt\Parameters
160            
161             # On Windows NT 4.0, if the adapter receives a DhcpNodeType setting from the
162             # DHCP server, the DhcpNodeType setting is present. Otherwise neither the
163             # NodeType nor the DhcpNodeType setting is present. When neither setting is
164             # present, Windows NT 4.0 reports "Node Type = Broadcast".
165            
166             # According to the Q120642 and Q314053 the NodeType setting will override the
167             # DhcpNodeType setting.
168            
169             # This suggests: use the NodeType value if set. Otherwise check for a
170             # DhcpNodeType setting. If there is no DhcpNodeType make a stab at getting the
171             # default NodeType. Check all the adapters present for WINS settings. If there
172             # are any set, then return H-node, else return B-node.
173            
174             sub get_nodetype
175             {
176             my $self = shift;
177            
178             my %nodetypes = (1=>"B-node", 2=>"P-node", 4=>"M-node", 8=>"H-node");
179            
180             # Windows NT 4.0's ipconfig reports these node types as
181             # Broadcast, Peer-Peer, Mixed, Hybrid
182            
183             my $nodetype;
184             if (my $type = $self->{"netbt_params_key"}{"\\NodeType"}) {
185             $nodetype = hex($type);
186             } elsif ($type = $self->{"netbt_params_key"}{"\\DhcpNodeType"}) {
187             $nodetype = hex($type)
188             } else {
189             my $wins_count = 0;
190             for my $adapter ($self->get_adapters) {
191             my @wins = $adapter->get_wins;
192             $wins_count += @wins;
193             }
194             $nodetype = $wins_count ? 8 : 1;
195             }
196             return $nodetypes{$nodetype};
197             }
198            
199             # Value: IPEnableRouter (REG_DWORD)
200             # NT: Tcpip\Parameters
201             # 2000+: Tcpip\Parameters
202            
203             sub is_router
204             {
205             my $self = shift;
206            
207             if (my $router = $self->{"tcpip_params_key"}{"\\IPEnableRouter"}) {
208             return hex($router);
209             } else {
210             return 0; # defaults to 0
211             }
212             }
213            
214             # Value: EnableProxy (REG_DWORD)
215             # NT: Netbt\Parameters
216             # 2000+: Netbt\Parameters
217            
218             sub is_wins_proxy
219             {
220             my $self = shift;
221            
222             if (my $proxy = $self->{"netbt_params_key"}{"\\EnableProxy"}) {
223             return hex($proxy);
224             } else {
225             return 0; # defaults to 0
226             }
227             }
228            
229             # Value: EnableLMHOSTS (REG_DWORD)
230             # NT: Netbt\Parameters
231             # 2000+: Netbt\Parameters
232            
233             sub is_lmhosts_enabled
234             {
235             my $self = shift;
236            
237             if (my $lmhosts_enabled = $self->{"netbt_params_key"}{"\\EnableLMHOSTS"}) {
238             return hex($lmhosts_enabled);
239             } else {
240             return 1; # defaults to 1
241             }
242             }
243            
244             # Value: EnableDns (REG_DWORD)
245             # NT: Netbt\Parameters
246             # 2000+: Netbt\Parameters
247            
248             sub is_dns_enabled_for_netbt
249             {
250             my $self = shift;
251            
252             if (my $dns_enabled_for_netbt = $self->{"netbt_params_key"}{"\\EnableDns"}) {
253             return hex($dns_enabled_for_netbt);
254             } else {
255             return 0; # defaults to 0
256             }
257             }
258            
259             sub get_adapter
260             {
261             my $self = shift;
262             my $adapter_name_or_num = shift;
263            
264             if ($adapter_name_or_num =~ m/^\d+$/) {
265             my $adapter = $self->{"adapters"}[$adapter_name_or_num];
266             return $adapter;
267             } else {
268             for my $adapter ($self->get_adapters) {
269             if (uc $adapter->get_name eq uc $adapter_name_or_num) {
270             return $adapter;
271             }
272             }
273             return undef; # couldn't find a matching adapter.
274             }
275             }
276            
277             sub dump
278             {
279             my $self = shift;
280            
281             print "hostname=", $self->get_hostname, "\n";
282             print "domain=", $self->get_domain, "\n";
283             my @searchlist = $self->get_searchlist;
284             print "searchlist=@searchlist (", scalar @searchlist, ")\n";
285             print "nodetype=", $self->get_nodetype, "\n";
286             print "ip router enabled=", $self->is_router ? "Yes":"No", "\n";
287             print "wins proxy enabled=", $self->is_wins_proxy ? "Yes":"No", "\n";
288             print "LMHOSTS enabled=", $self->is_lmhosts_enabled ? "Yes":"No", "\n";
289             print "dns enabled for netbt=", $self->is_dns_enabled_for_netbt ? "Yes":"No", "\n";
290             my $i = 0;
291             for ($self->get_adapters) {
292             print "\nAdapter ", $i++, ":\n";
293             $_->dump;
294             }
295             }
296            
297             1;
298            
299             __END__