4 # MS NT4 DHCP to ISC DHCP Configuration Migration Tool
6 # Author: Shu-Min Chang
8 # Copyright(c) 2003 Intel Corporation. All rights reserved
10 # Redistribution and use in source and binary forms, with or without
11 # modification, are permitted provided that the following conditions are met:
13 # 1. Redistributions of source code must retain the above copyright notice,
14 # this list of conditions and the following disclaimer.
15 # 2. Redistributions in binary form must reproduce the above copyright notice
16 # this list of conditions and the following disclaimer in the documentation
17 # and/or other materials provided with the distribution
18 # 3. Neither the name of Intel Corporation nor the names of its contributors
19 # may be used to endorse or promote products derived from this software
20 # without specific prior written permission.
22 # THIS SOFTWARE IS PROVIDED BY THE INTEL CORPORATION AND CONTRIBUTORS "AS IS"
23 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 # ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL CORPORATION OR CONTRIBUTORS BE
26 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL EXEMPLARY, OR
27 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO PROCUREMENT OF SUBSTITUE
28 # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 # OF THE USE OF THIS SOFTWARE, EVEN IF ADVICED OF THE POSSIBILITY OF SUCH
38 use Registry
; # Custom Perl Module to make Registry access easier.
40 my $usage = << 'ENDOFHELP';
42 Purpose
: A Perl Script converting MS NT4 DHCP configuration to ISC DHCP3
43 configuration file by reading NT4
's registry.
45 Requires: Registry.pm and ActiveState 5.6.0
47 Usage: $ARGV -s <Srv> -o <Out> [-p <Pri> [-k <key>]] [-f <Fo>]
49 <Srv> Server IP or name for NT4 DHCP server to fetch the configuration from.
50 <Out> Output filename for the configuration file.
51 <Pri> Primary DNS server name for sending the dynamic DNS update to.
52 <Key> Key name for use in updating the dynamic DNS zone.
53 <Fo> Failover peer name shared with the DHCP partner.
55 Essentially the <Srv> needs to be an NT4 (3.x should work but not tested) which
56 you should have registry read access to. You must run this script from a
57 Windows machine because of the requirement to access the registry.
59 The <Pri> is optional parameter for desginating the dynamic DNS update if
60 missing then the "zone" section of the declaration will be skipped. The <Key>
61 is needed if you've configured your DNS zone with a key
, in addition
, you
'll
62 need to define that key in this DHCP configuration file elsewhere manually,
63 read the DHCP Handbook to figure out what you need to define.
65 The <Fo> specifies the fail-over peer name in the pool section, you'll need to
66 define additional detail elsewhere manually
, again
read the DHCP handbook
.
68 NOTE
: the program only knows of the following global
and subnet options
:
69 3, 6, 15, 28, 44, and 46
71 If it runs into options other than the known ones
, it will quit
. You
72 may fix this by modifying the following procedures
:
77 In addition
, the resulting subnets configuration will have the
"deny
78 dynamic bootp clients" you should take them out
if that
's not what you
81 Finally, as the parameter structures implied, it is assumed that you
82 want the same zone primary and update key for all zones and that the
83 same failover is to be applied to all the pools. Furthermore the
84 subnet zones are all assumed to be class C delineated, but if you
85 happend to be delegated at the class B level, this will work fine too.
87 Author: Shu-Min Chang <smchang@yahoo.com>
89 Copyright: Please read the top of the source code
92 Brian L. King for coding help, Douglas A. Darrah for testing, and James E.
93 Pressley for being the DHCP reference book :).
95 Usage: $ARGV -s <Srv> -o <Out> [-p <Pri> [-k <key>]] [-f <Fo>]
101 ###################### Begin Main Program ####################################
103 my (%opts, %GlobalOptions, %SuperScopes, %Scopes);
105 ### Get parameters and make sure that they meet the require/optoinal criteria
106 getopts('s
:o
:p
:k
:f
:', \%opts) or die $usage;
107 ($opts{s} and $opts{o}) or die $usage;
108 if ($opts{k}) { $opts{p} or die $usage; }
110 ### Read all the registry stuff into the memory
111 %GlobalOptions = GetGlobalOptions($opts{s});
112 %SuperScopes = GetSuperScope($opts{s});
113 %Scopes = GetScopes ($opts{s});
115 ### Process and print out to the output file
116 my ($outfile, $i, $j, @Domains);
118 $outfile = new FileHandle "> $opts{o}";
119 if (!defined $outfile) {
120 die "Can't
open file
: $opts{o
}: $!";
123 for $i (keys %SuperScopes) {
124 print $outfile "\n##############################################################\n";
125 my ($Scopename) = $i;
126 $Scopename =~ s/ //g;
127 print $outfile "shared-network $Scopename {\n";
128 foreach $j (@
{$SuperScopes{$i}}) {
129 PrintSubnetConfig
($outfile, \
%GlobalOptions, \
%{$Scopes{$j}}, $j, "\t", $opts{f
});
130 InsertIfUnique
(\
@Domains, $Scopes{$j}{domain
}) if exists $Scopes{$j}{domain
};
133 print $outfile "}\n";
134 if ($opts{p
} or $opts{k
}) {
135 foreach $j (@
{$SuperScopes{$i}}) {
136 PrintSubnetUpdate
($outfile, $j, $opts{p
}, $opts{k
});
141 for $i (keys %Scopes) {
142 print $outfile "\n##############################################################\n";
143 PrintSubnetConfig
($outfile, \
%GlobalOptions, \
%{$Scopes{$i}}, $i, "", $opts{f
});
144 if ($opts{p
} or $opts{k
}) { PrintSubnetUpdate
($outfile, $i, $opts{p
}, $opts{k
}); }
145 InsertIfUnique
(\
@Domains, $Scopes{$i}{domain
}) if exists $Scopes{$i}{domain
};
148 if ($opts{p
} or $opts{k
}) {
149 InsertIfUnique
(\
@Domains, $GlobalOptions{domain
}) if exists $GlobalOptions{domain
};
151 PrintDomainUpdate
($outfile, $i, $opts{p
}, $opts{k
});
159 ################################## End Main Program ###########################
165 ######################################################################
166 sub InsertIfUnique
($$) {
167 my ($Array, $data) = @_;
168 # purpose: insert $data into array @{$Array} iff the data is not in there yet
170 # $data: scalar data to be added to the @{$Array} if unique
171 # $Array: reference of the Array to compare the uniqueness of the $data
173 # $Array: reference of the array with the resulting array.
178 for ($i=0; $i<=$#{$Array} && ${$Array}[$i] ne $data; $i++) { }
180 if ($i > $#{$Array}) {
181 ${$Array}[$i] = $data;
184 ######################################################################
185 sub PrintDomainUpdate
($$$$) {
186 my ($outfile, $Domain, $DDNSServer, $key) = @_;
187 # purpose: print out the foward domain zone update declaration
189 # $outfile: filehandle of the file to write the output to
190 # $Domain: a string representing the forward domain
191 # $DDNSServer: a string of the DNS server accepting the DDNS update
192 # $key: a string representing the key used to update the zone
197 print $outfile "zone $Domain {\n";
198 print $outfile "\tprimary $DDNSServer;\n";
199 !$key or print $outfile "\tkey $key;\n";
200 print $outfile "}\n";
203 ######################################################################
204 sub PrintSubnetUpdate
($$$$) {
205 my ($outfile, $Subnet, $DDNSServer, $key) = @_;
206 # purpose: print out the reverse domain zone update declaration
208 # $outfile: filehandle of the file to write the output to
209 # $Subnet: a string representing the subnet in the form 1.2.3.4
210 # $DDNSServer: a string of the DNS server accepting the DDNS update
211 # $key: a string representing the key used to update the zone
218 $_ = join (".", reverse(split(/\./, $Subnet)));
221 print $outfile "zone $Reverse.in-addr.arpa. {\n";
222 print $outfile "\tprimary $DDNSServer;\n";
223 !$key or print $outfile "\tkey $key;\n";
224 print $outfile "}\n";
227 ######################################################################
228 sub PrintSubnetConfig
($$$$$$) {
229 my ($outfile, $GlobalOptions, $Scope, $Subnet, $prefix, $failover) = @_;
230 # purpose: print out the effective scope configuration for one subnet as
231 # derived from the global and scope options.
233 # $outfile: filehandle of the file to write the output to
234 # $GlobalOptions: refernce to the hashed variable from GetGlobalOptions
235 # $Scopes: reference to the hashed variable of the subnet in interest
236 # $Subnet: string variable of the subnet being processed
237 # $prefix: string to be printed before each line (designed for tab)
238 # $failover: string to be used for the "failover peer" line
242 my ($pound) = ( ${$Scope}{disable
}?
"#".$prefix : $prefix);
243 print $outfile $pound, "subnet $Subnet netmask ${$Scope}{mask} {\n";
244 print $outfile "$prefix# Name: ${$Scope}{name}\n";
245 print $outfile "$prefix# Comment: ${$Scope}{comment}\n";
246 if (exists ${$Scope}{routers
}) {
247 print $outfile $pound, "\toption routers @{${$Scope}{routers}};\n";
248 } elsif (exists ${$GlobalOptions}{routers
}) {
249 print $outfile $pound, "\toption routers @{${$GlobalOptions}{routers}};\t# NOTE: obtained from global option, bad practice detected\n";
251 print $outfile "### WARNING: No router was found for this subnet!!! ##########\n";
254 if (exists ${$Scope}{dnses
}) {
255 print $outfile $pound, "\toption domain-name-servers ", join(",", @
{${$Scope}{dnses
}}), ";\n";
256 } elsif (exists ${$GlobalOptions}{dnses
}) {
257 print $outfile $pound, "\toption domain-name-servers ", join(",", @
{${$GlobalOptions}{dnses
}}), ";\n";
260 if (exists ${$Scope}{domain
}) {
261 print $outfile $pound, "\toption domain-name \"${$Scope}{domain}\";\n";
262 } elsif (exists ${$GlobalOptions}{domain
}) {
263 print $outfile $pound, "\toption domain-name \"${$GlobalOptions}{domain}\";\n";
266 if (exists ${$Scope}{broadcast
}) {
267 print $outfile $pound, "\toption broadcast-address ${$Scope}{broadcast};\n";
268 } elsif (exists ${$GlobalOptions}{broadcast
}) {
269 print $outfile $pound, "\toption broadcast-address ${$GlobalOptions}{broadcast};\n";
272 if (exists ${$Scope}{winses
}) {
273 print $outfile $pound, "\toption netbios-name-servers ", join(",", @
{${$Scope}{winses
}}), ";\n";
274 } elsif (exists ${$GlobalOptions}{winses
}) {
275 print $outfile $pound, "\toption netbios-name-servers ", join(",", @
{${$GlobalOptions}{winses
}}), ";\n";
278 if (exists ${$Scope}{winstype
}) {
279 print $outfile $pound, "\toption netbios-node-type ${$Scope}{winstype};\n";
280 } elsif (exists ${$GlobalOptions}{winstype
}) {
281 print $outfile $pound, "\toption netbios-node-type ${$GlobalOptions}{winstype};\n"
284 print $outfile $pound, "\tdefault-lease-time ${$Scope}{leaseduration};\n";
285 print $outfile $pound, "\tpool {\n";
286 for (my $r=0; $r<=$#{${$Scope}{ranges}}; $r+=2) {
287 print $outfile $pound, "\t\trange ${$Scope}{ranges}[$r] ${$Scope}{ranges}[$r+1];\n";
289 !$failover or print $outfile $pound, "\t\tfailover peer \"$failover\";\n";
290 print $outfile $pound, "\t\tdeny dynamic bootp clients;\n";
291 print $outfile $pound, "\t}\n";
292 print $outfile $pound, "}\n";
295 ######################################################################
299 # purpose: to return NT4 server's scope configuration
301 # $Server: string of the valid IP or name of the NT4 server
304 # %Scope: hash of hash of hash of various data types to be returned of the
305 # following data structure
306 # $Scope{<subnet>}{disable} => boolean
307 # $Scope{<subnet>}{mask} => string (e.g. "1.2.3.255")
308 # $Scope{<subnet>}{name} => string (e.g "Office Subnet #1")
309 # $Scope{<subnet>}{comment} => string (e.g. "This is a funny subnet")
310 # $Scope{<subnet>}{ranges} => array of paired inclusion IP addresses
311 # (e.g. "1.2.3.1 1.2.3.10 1.2.3.100 10.2.3.200
312 # says that we have 2 inclusion ranges of
314 # $Scopes{<subnet>}{routers} => array of IP address strings
315 # $Scopes{<subnet>}{dnses} => array of IP address/name string
316 # $Scopes{<subnet>}{domain} > string
317 # $Scopes{<subnet>}{broadcast} => string
318 # $Scopes{<subnet>}{winses} => array of IP addresses/name string
319 # $Scopes{<subnet>}{winstype} => integer
320 # $Scopes{<subnet>}{leaseduration} => integer
322 my ($RegVal, @Subnets, @Router, $SubnetName, $SubnetComment, @SubnetOptions, @SRouter, @SDNSServers, @SDomainname, @SWINSservers, @SNetBIOS, @SLeaseDuration, @SSubnetState, @SExclusionRanges, @SSubnetAddress, @SSubnetMask, @SFirstAddress, $SStartAddress, $SEndAddress, @InclusionRanges, @SBroadcastAddress);
324 print "Getting list of subnets\n";
325 if (Registry
::GetRegSubkeyList
("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets", \
@Subnets)) {
326 die "Unable to obtain a list of subnets from the server!\n";
329 for (my $i=0; $i<=$#Subnets; $i++) {
330 print "\t Fetching Subnet $Subnets[$i] (",$i+1, "/", $#Subnets+1, "): ";
333 if (!Registry
::GetRegSubkeyList
("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\IpRanges", \
@SFirstAddress)) {
334 # Don't know why MS has a tree for this, but as far
335 # as I can tell, only one subtree will ever come out of
336 # this, so I'm skipping the 'for' loop
339 if (!Registry
::GetRegKeyVal
("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\IpRanges\\$SFirstAddress[0]\\StartAddress", \
$RegVal)) {
340 $SStartAddress = $RegVal;
343 if (!Registry
::GetRegKeyVal
("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\IpRanges\\$SFirstAddress[0]\\EndAddress", \
$RegVal)) {
344 $SEndAddress = $RegVal;
346 # print "\n\tInclusion Range: ", Registry::ExtractIp($SStartAddress), " - ", Registry::ExtractIp($SEndAddress),"\n";
349 die "\n\n# Error Getting Inclusion Range FirstAddress!!!\n\n";
352 if (!Registry
::GetRegKeyVal
("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\ExcludedIpRanges", \
$RegVal)) {
353 @SExclusionRanges = Registry
::ExtractExclusionRanges
($RegVal);
355 # for (my $j=2; $j<=$#SExclusionRanges; $j+=2) {
356 # if (unpack("L",$SExclusionRanges[$j]) < unpack("L",$SExclusionRanges[$j-2])) {
357 # print ("\n******** Subnet exclusion ranges out of order ********\n");
361 @SExclusionRanges = sort(@SExclusionRanges);
363 # print "\n\tExclusion Ranges: ";
364 # for (my $j=0; $j<=$#SExclusionRanges; $j+=2) {
365 # print "\n\t\t",Registry::ExtractIp($SExclusionRanges[$j])," - ",Registry::ExtractIp($SExclusionRanges[$j+1]);
369 @InclusionRanges = FindInclusionRanges
($SStartAddress, $SEndAddress, @SExclusionRanges);
372 if (!Registry
::GetRegKeyVal
("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\SubnetName", \
$RegVal)) {
373 $SubnetName = $RegVal;
374 # print "\n\tSubnetName: $SubnetName";
378 if (!Registry
::GetRegKeyVal
("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\SubnetComment", \
$RegVal)) {
379 $SubnetComment = $RegVal;
380 # print "\n\tSubnetComment: $SubnetComment";
383 if (!Registry
::GetRegKeyVal
("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\SubnetAddress", \
$RegVal)) {
384 @SSubnetAddress = Registry
::ExtractIp
($RegVal);
385 # print "\n\tSubnetAddress: $SSubnetAddress[0]";
388 if (!Registry
::GetRegKeyVal
("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\SubnetMask", \
$RegVal)) {
389 @SSubnetMask = Registry
::ExtractIp
($RegVal);
390 # print "\n\tSubnetMask: $SSubnetMask[0]";
394 if (!Registry
::GetRegKeyVal
("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\SubnetState", \
$RegVal)) {
395 @SSubnetState = Registry
::ExtractHex
($RegVal);
396 # print "\n\tSubnetState = $SSubnetState[0]";
399 $Scopes{$Subnets[$i]}{disable
} = hex($SSubnetState[0]) ?
1 : 0;
400 $Scopes{$Subnets[$i]}{mask
} = $SSubnetMask[0];
401 $Scopes{$Subnets[$i]}{name
} = $SubnetName;
402 $Scopes{$Subnets[$i]}{comment
} = $SubnetComment;
403 for (my $r=0; $r<=$#InclusionRanges; $r++) {
404 $Scopes{$Subnets[$i]}{ranges
}[$r] = Registry
::ExtractIp
($InclusionRanges[$r]);
407 ################## Get scope options
409 my (@SubnetOptionsList);
411 print "\n\t\tOptions:";
412 if (Registry
::GetRegSubkeyList
("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\SubnetOptions", \
@SubnetOptionsList)) {
413 die "Unable to get subnet options list for $Subnets[$i]!\n";
416 for (my $j=0; $j<=$#SubnetOptionsList; $j++) {
418 if (!Registry
::GetRegKeyVal
("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\SubnetOptions\\$SubnetOptionsList[$j]\\OptionValue", \
$RegVal)) {
419 for ($SubnetOptionsList[$j]) {
421 # @SRouter = Registry::ExtractOptionIps($RegVal);
422 $Scopes{$Subnets[$i]}{routers
} = [Registry
::ExtractOptionIps
($RegVal)];
426 @SDNSServers = Registry
::ExtractOptionIps
($RegVal);
427 for (my $d=0; $d<=$#SDNSServers; $d++) {
428 my ($ipname, $rest) = gethostbyaddr(pack("C4", split(/\./, $SDNSServers[$d])), &AF_INET
);
429 $Scopes{$Subnets[$i]}{dnses
}[$d] = $ipname ?
$ipname : $SDNSServers[$d];
434 @SDomainname = Registry
::ExtractOptionStrings
($RegVal);
435 $Scopes{$Subnets[$i]}{domain
} = $SDomainname[0];
439 @SBroadcastAddress = Registry
::ExtractOptionIps
($RegVal);
440 $Scopes{$Subnets[$i]}{broadcast
} = $SBroadcastAddress[0];
444 @SWINSservers = Registry
::ExtractOptionIps
($RegVal);
445 for (my $w=0; $w<=$#SWINSservers; $w++) {
446 my ($ipname, $rest) = gethostbyaddr(pack("C4", split(/\./, $SWINSservers[$w])), &AF_INET
);
447 $Scopes{$Subnets[$i]}{winses
}[$w] = $ipname ?
$ipname : $SWINSservers[$w];
452 @SNetBIOS = Registry
::ExtractOptionHex
($RegVal);
453 $Scopes{$Subnets[$i]}{winstype
} = hex($SNetBIOS[0]);
457 @SLeaseDuration = Registry
::ExtractOptionHex
($RegVal);
458 $Scopes{$Subnets[$i]}{leaseduration
} = hex($SLeaseDuration[0]);
461 die "This program does not recognize subnet option \#$SubnetOptionsList[$j] yet!\n"
464 die "Unable to obtain option SubnetOptionsList[$j] from $Subnets[$i], most likely a registry problem!\n"
473 ######################################################################
474 sub FindInclusionRanges
($$@
) {
475 my ($StartAddress, $EndAddress, @ExclusionRanges) = @_;
476 # Purpose: to calculate and return the DHCP inclusion ranges out of
477 # data provided by the NT4 DHCP server
478 # input: $StartAddress:
482 # return: An arry of IP address pair representing the inclusion ranges
483 # in the native registry format.
487 $SA = unpack("L", $StartAddress);
488 $EA = unpack("L", $EndAddress);
489 @ER = @ExclusionRanges;
490 for (my $i=0; $i<=$#ER; $i++) {
491 $ER[$i] = unpack ("L", $ER[$i]);
497 $InclusionRanges[0] = $SA;
498 $InclusionRanges[1] = $EA;
500 for (my $i=0; $i<=$#ER; $i+=2) {
501 if ($ER[$i] == $InclusionRanges[$#InclusionRanges-1]) {
502 $InclusionRanges[$#InclusionRanges-1] = $ER[$i+1] + 1;
504 if ($ER[$i] > $InclusionRanges[$#InclusionRanges-1]) {
505 $InclusionRanges[$#InclusionRanges] = $ER[$i]-1;
507 if (($ER[$i+1] > $InclusionRanges[$#InclusionRanges]) &&
508 ($ER[$i+1] != $EA)) {
509 $InclusionRanges[$#InclusionRanges+1] = $ER[$i+1] + 1;
510 $InclusionRanges[$#InclusionRanges+1] = $EA;
512 if ($InclusionRanges[$#InclusionRanges] < $InclusionRanges[$#InclusionRanges-1]) {
513 $#InclusionRanges -= 2;
517 for (my $i=0; $i<=$#InclusionRanges; $i++) {
518 $InclusionRanges[$i] = pack("L", $InclusionRanges[$i]);
519 # print "Inclusion: ", Registry::ExtractIp($InclusionRanges[$i]), "\n";
521 return @InclusionRanges;
524 ####################################################################
525 sub GetSuperScope
($) {
529 # purpose: gets the Superscope list from the given server
531 # $Server: string of the valid IP address or name of the NT4 server
534 # %SuperScopes: hash of array subnets with the following data structure
535 # $SuperScopes{<SuperscopeName>} => array of sunbets
537 my (@SuperScopeNames, @SCSubnetList);
539 print "Getting Superscope list: ";
540 if (!Registry
::GetRegSubkeyList
("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\SuperScope", \
@SuperScopeNames)) {
541 for (my $i=0; $i<=$#SuperScopeNames; $i++) {
543 if (!Registry
::GetRegSubkeyList
("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\SuperScope\\$SuperScopeNames[$i]", \
@SCSubnetList)) {
544 $SuperScopes{$SuperScopeNames[$i]} = [@SCSubnetList];
553 ####################################################################
554 sub GetGlobalOptions
($) {
557 # purpose: to return NT4 server's global scope configuration
559 # $Server: string of the valid IP or name of the NT4 server
562 # %GlobalOptions: hash of hash of various data types to be returned of the
563 # following data structure
564 # $GlobalOptions{routers} => array of IP address strings
565 # $GlobalOptions{dnses} => array of IP address/name string
566 # $GlobalOptions{domain} > string
567 # $GlobalOptions{broadcast} => string
568 # $GlobalOptions{winses} => array of IP addresses/name string
569 # $GlobalOptions{winstype} => integer
571 my ($RegVal, @temp, @GlobalOptionValues);
573 print "Getting Global Options: ";
574 if (Registry
::GetRegSubkeyList
("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\GlobalOptionValues", \
@GlobalOptionValues)) {
575 die "Unable to obtain GlobalOptionValues";
578 for (my $i=0; $i<=$#GlobalOptionValues; $i++) {
580 if (Registry
::GetRegKeyVal
("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\configuration\\globaloptionvalues\\$GlobalOptionValues[$i]\\optionvalue", \
$RegVal)) {
581 die "Unable to retrive global option $GlobalOptionValues[$i]\n";
585 for ($GlobalOptionValues[$i]) {
587 @temp=Registry
::ExtractOptionIps
($RegVal);
588 $GlobalOptions{routers
} = [@temp];
593 @temp = Registry
::ExtractOptionIps
($RegVal);
594 for (my $d=0; $d<=$#temp; $d++) {
595 my ($ipname, $rest) = gethostbyaddr(pack("C4", split(/\./, $temp[$d])), &AF_INET
);
596 $GlobalOptions{dnses
}[$d] = $ipname ?
$ipname : $temp[$d];
602 @temp = Registry
::ExtractOptionStrings
($RegVal);
603 $GlobalOptions{domain
} = $temp[0];
608 @temp = Registry
::ExtractOptionIps
($RegVal);
609 $GlobalOptions{broadcast
} = $temp[0];
614 @temp = Registry
::ExtractOptionIps
($RegVal);
615 $GlobalOptions{winses
} = [@temp];
616 for (my $w=0; $w<=$#temp; $w++) {
617 my ($ipname, $rest) = gethostbyaddr(pack("C4", split(/\./, $temp[$w])), &AF_INET
);
618 $GlobalOptions{winses
}[$w] = $ipname ?
$ipname : $temp[$w];
624 @temp = Registry
::ExtractOptionHex
($RegVal);
625 $GlobalOptions{winstype
} = hex($temp[0]);
628 die "This program does not recgonize global option \#$GlobalOptionValues[$i] yet!\n"
633 return %GlobalOptions;