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__
|