xref: /minix3/external/bsd/dhcp/dist/contrib/ms2isc/ms2isc.pl (revision 83ee113ee0d94f3844d44065af2311604e9a30ad)
1*83ee113eSDavid van Moolenbroek#set ts=3
2*83ee113eSDavid van Moolenbroek#
3*83ee113eSDavid van Moolenbroek# ms2isc.pl
4*83ee113eSDavid van Moolenbroek# MS NT4 DHCP to ISC DHCP Configuration Migration Tool
5*83ee113eSDavid van Moolenbroek#
6*83ee113eSDavid van Moolenbroek# Author: Shu-Min Chang
7*83ee113eSDavid van Moolenbroek#
8*83ee113eSDavid van Moolenbroek# Copyright(c) 2003 Intel Corporation.  All rights reserved
9*83ee113eSDavid van Moolenbroek#
10*83ee113eSDavid van Moolenbroek# Redistribution and use in source and binary forms, with or without
11*83ee113eSDavid van Moolenbroek# modification, are permitted provided that the following conditions are met:
12*83ee113eSDavid van Moolenbroek#
13*83ee113eSDavid van Moolenbroek# 1. Redistributions of source code must retain the above copyright notice,
14*83ee113eSDavid van Moolenbroek#    this list of conditions and the following disclaimer.
15*83ee113eSDavid van Moolenbroek# 2. Redistributions in binary form must reproduce the above copyright notice
16*83ee113eSDavid van Moolenbroek#    this list of conditions and the following disclaimer in the documentation
17*83ee113eSDavid van Moolenbroek#    and/or other materials provided with the distribution
18*83ee113eSDavid van Moolenbroek# 3. Neither the name of Intel Corporation nor the names of its contributors
19*83ee113eSDavid van Moolenbroek#    may be used to endorse or promote products derived from this software
20*83ee113eSDavid van Moolenbroek#    without specific prior written permission.
21*83ee113eSDavid van Moolenbroek#
22*83ee113eSDavid van Moolenbroek# THIS SOFTWARE IS PROVIDED BY THE INTEL CORPORATION AND CONTRIBUTORS "AS IS"
23*83ee113eSDavid van Moolenbroek# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24*83ee113eSDavid van Moolenbroek# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25*83ee113eSDavid van Moolenbroek# ARE DISCLAIMED.  IN NO EVENT SHALL THE INTEL CORPORATION OR CONTRIBUTORS BE
26*83ee113eSDavid van Moolenbroek# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL EXEMPLARY, OR
27*83ee113eSDavid van Moolenbroek# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO PROCUREMENT OF SUBSTITUE
28*83ee113eSDavid van Moolenbroek# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29*83ee113eSDavid van Moolenbroek# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30*83ee113eSDavid van Moolenbroek# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31*83ee113eSDavid van Moolenbroek# OF THE USE OF THIS SOFTWARE, EVEN IF ADVICED OF THE POSSIBILITY OF SUCH
32*83ee113eSDavid van Moolenbroek# DAMAGE.
33*83ee113eSDavid van Moolenbroek
34*83ee113eSDavid van Moolenbroekuse strict;
35*83ee113eSDavid van Moolenbroekuse Socket;
36*83ee113eSDavid van Moolenbroekuse Getopt::Std;
37*83ee113eSDavid van Moolenbroekuse Filehandle;
38*83ee113eSDavid van Moolenbroekuse Registry; # Custom Perl Module to make Registry access easier.
39*83ee113eSDavid van Moolenbroek
40*83ee113eSDavid van Moolenbroekmy $usage = << 'ENDOFHELP';
41*83ee113eSDavid van Moolenbroek
42*83ee113eSDavid van MoolenbroekPurpose: A Perl Script converting MS NT4 DHCP configuration to ISC DHCP3
43*83ee113eSDavid van Moolenbroekconfiguration file by reading NT4's registry.
44*83ee113eSDavid van Moolenbroek
45*83ee113eSDavid van MoolenbroekRequires: Registry.pm and ActiveState 5.6.0
46*83ee113eSDavid van Moolenbroek
47*83ee113eSDavid van MoolenbroekUsage: $ARGV -s <Srv> -o <Out> [-p <Pri> [-k <key>]] [-f <Fo>]
48*83ee113eSDavid van Moolenbroek
49*83ee113eSDavid van Moolenbroek  <Srv>  Server IP or name for NT4 DHCP server to fetch the configuration from.
50*83ee113eSDavid van Moolenbroek  <Out>  Output filename for the configuration file.
51*83ee113eSDavid van Moolenbroek  <Pri>  Primary DNS server name for sending the dynamic DNS update to.
52*83ee113eSDavid van Moolenbroek  <Key>  Key name for use in updating the dynamic DNS zone.
53*83ee113eSDavid van Moolenbroek  <Fo>   Failover peer name shared with the DHCP partner.
54*83ee113eSDavid van Moolenbroek
55*83ee113eSDavid van MoolenbroekEssentially the <Srv> needs to be an NT4 (3.x should work but not tested) which
56*83ee113eSDavid van Moolenbroekyou should have registry read access to.  You must run this script from a
57*83ee113eSDavid van MoolenbroekWindows machine because of the requirement to access the registry.
58*83ee113eSDavid van Moolenbroek
59*83ee113eSDavid van MoolenbroekThe <Pri> is optional parameter for desginating the dynamic DNS update if
60*83ee113eSDavid van Moolenbroekmissing then the "zone" section of the declaration will be skipped.  The <Key>
61*83ee113eSDavid van Moolenbroekis needed if you've configured your DNS zone with a key, in addition, you'll
62*83ee113eSDavid van Moolenbroekneed to define that key in this DHCP configuration file elsewhere manually,
63*83ee113eSDavid van Moolenbroekread the DHCP Handbook to figure out what you need to define.
64*83ee113eSDavid van Moolenbroek
65*83ee113eSDavid van MoolenbroekThe <Fo> specifies the fail-over peer name in the pool section, you'll need to
66*83ee113eSDavid van Moolenbroekdefine additional detail elsewhere manually, again read the DHCP handbook.
67*83ee113eSDavid van Moolenbroek
68*83ee113eSDavid van MoolenbroekNOTE: the program only knows of the following global and subnet options:
69*83ee113eSDavid van Moolenbroek        3, 6, 15, 28, 44, and 46
70*83ee113eSDavid van Moolenbroek
71*83ee113eSDavid van Moolenbroek      If it runs into options other than the known ones, it will quit.  You
72*83ee113eSDavid van Moolenbroek      may fix this by modifying the following procedures:
73*83ee113eSDavid van Moolenbroek        GetGlobalOptions
74*83ee113eSDavid van Moolenbroek        GetScopes
75*83ee113eSDavid van Moolenbroek        PrintSubnetConfig
76*83ee113eSDavid van Moolenbroek
77*83ee113eSDavid van Moolenbroek      In addition, the resulting subnets configuration will have the "deny
78*83ee113eSDavid van Moolenbroek      dynamic bootp clients" you should take them out if that's not what you
79*83ee113eSDavid van Moolenbroek      want :).
80*83ee113eSDavid van Moolenbroek
81*83ee113eSDavid van Moolenbroek      Finally, as the parameter structures implied, it is assumed that you
82*83ee113eSDavid van Moolenbroek      want the same zone primary and update key for all zones and that the
83*83ee113eSDavid van Moolenbroek      same failover is to be applied to all the pools.  Furthermore the
84*83ee113eSDavid van Moolenbroek      subnet zones are all assumed to be class C delineated, but if you
85*83ee113eSDavid van Moolenbroek      happend to be delegated at the class B level, this will work fine too.
86*83ee113eSDavid van Moolenbroek
87*83ee113eSDavid van MoolenbroekAuthor: Shu-Min Chang <smchang@yahoo.com>
88*83ee113eSDavid van Moolenbroek
89*83ee113eSDavid van MoolenbroekCopyright: Please read the top of the source code
90*83ee113eSDavid van Moolenbroek
91*83ee113eSDavid van MoolenbroekAcknowledgement:
92*83ee113eSDavid van Moolenbroek  Brian L. King for coding help, Douglas A. Darrah for testing, and James E.
93*83ee113eSDavid van MoolenbroekPressley for being the DHCP reference book :).
94*83ee113eSDavid van Moolenbroek
95*83ee113eSDavid van MoolenbroekUsage: $ARGV -s <Srv> -o <Out> [-p <Pri> [-k <key>]] [-f <Fo>]
96*83ee113eSDavid van Moolenbroek
97*83ee113eSDavid van MoolenbroekVersion: 1.0.1
98*83ee113eSDavid van Moolenbroek
99*83ee113eSDavid van MoolenbroekENDOFHELP
100*83ee113eSDavid van Moolenbroek
101*83ee113eSDavid van Moolenbroek###################### Begin Main Program ####################################
102*83ee113eSDavid van Moolenbroek
103*83ee113eSDavid van Moolenbroek	my (%opts, %GlobalOptions, %SuperScopes, %Scopes);
104*83ee113eSDavid van Moolenbroek
105*83ee113eSDavid van Moolenbroek	### Get parameters and make sure that they meet the require/optoinal criteria
106*83ee113eSDavid van Moolenbroek	getopts('s:o:p:k:f:', \%opts) or die $usage;
107*83ee113eSDavid van Moolenbroek	($opts{s} and $opts{o}) or die $usage;
108*83ee113eSDavid van Moolenbroek	if ($opts{k}) { $opts{p} or die $usage; }
109*83ee113eSDavid van Moolenbroek
110*83ee113eSDavid van Moolenbroek	### Read all the registry stuff into the memory
111*83ee113eSDavid van Moolenbroek	%GlobalOptions = GetGlobalOptions($opts{s});
112*83ee113eSDavid van Moolenbroek	%SuperScopes = GetSuperScope($opts{s});
113*83ee113eSDavid van Moolenbroek	%Scopes = GetScopes ($opts{s});
114*83ee113eSDavid van Moolenbroek
115*83ee113eSDavid van Moolenbroek	### Process and print out to the output file
116*83ee113eSDavid van Moolenbroek	my ($outfile, $i, $j, @Domains);
117*83ee113eSDavid van Moolenbroek
118*83ee113eSDavid van Moolenbroek	$outfile = new FileHandle "> $opts{o}";
119*83ee113eSDavid van Moolenbroek	if (!defined $outfile) {
120*83ee113eSDavid van Moolenbroek		die "Can't open file: $opts{o}: $!";
121*83ee113eSDavid van Moolenbroek	}
122*83ee113eSDavid van Moolenbroek
123*83ee113eSDavid van Moolenbroek	for $i (keys %SuperScopes) {
124*83ee113eSDavid van Moolenbroek		print $outfile "\n##############################################################\n";
125*83ee113eSDavid van Moolenbroek		my ($Scopename) = $i;
126*83ee113eSDavid van Moolenbroek		$Scopename =~ s/ //g;
127*83ee113eSDavid van Moolenbroek		print $outfile "shared-network $Scopename {\n";
128*83ee113eSDavid van Moolenbroek		foreach $j (@{$SuperScopes{$i}}) {
129*83ee113eSDavid van Moolenbroek			PrintSubnetConfig($outfile, \%GlobalOptions, \%{$Scopes{$j}}, $j, "\t", $opts{f});
130*83ee113eSDavid van Moolenbroek			InsertIfUnique (\@Domains, $Scopes{$j}{domain}) if exists $Scopes{$j}{domain};
131*83ee113eSDavid van Moolenbroek			delete $Scopes{$j};
132*83ee113eSDavid van Moolenbroek		}
133*83ee113eSDavid van Moolenbroek		print $outfile "}\n";
134*83ee113eSDavid van Moolenbroek		if ($opts{p} or $opts{k}) {
135*83ee113eSDavid van Moolenbroek			foreach $j (@{$SuperScopes{$i}}) {
136*83ee113eSDavid van Moolenbroek				PrintSubnetUpdate($outfile, $j, $opts{p}, $opts{k});
137*83ee113eSDavid van Moolenbroek			}
138*83ee113eSDavid van Moolenbroek		}
139*83ee113eSDavid van Moolenbroek	}
140*83ee113eSDavid van Moolenbroek
141*83ee113eSDavid van Moolenbroek	for $i (keys %Scopes) {
142*83ee113eSDavid van Moolenbroek		print $outfile "\n##############################################################\n";
143*83ee113eSDavid van Moolenbroek		PrintSubnetConfig($outfile, \%GlobalOptions, \%{$Scopes{$i}}, $i, "", $opts{f});
144*83ee113eSDavid van Moolenbroek		if ($opts{p} or $opts{k}) { PrintSubnetUpdate($outfile, $i, $opts{p}, $opts{k}); }
145*83ee113eSDavid van Moolenbroek		InsertIfUnique (\@Domains, $Scopes{$i}{domain}) if exists $Scopes{$i}{domain};
146*83ee113eSDavid van Moolenbroek	}
147*83ee113eSDavid van Moolenbroek
148*83ee113eSDavid van Moolenbroek	if ($opts{p} or $opts{k}) {
149*83ee113eSDavid van Moolenbroek		InsertIfUnique (\@Domains, $GlobalOptions{domain}) if exists $GlobalOptions{domain};
150*83ee113eSDavid van Moolenbroek		for $i (@Domains) {
151*83ee113eSDavid van Moolenbroek			PrintDomainUpdate($outfile, $i, $opts{p}, $opts{k});
152*83ee113eSDavid van Moolenbroek		}
153*83ee113eSDavid van Moolenbroek	}
154*83ee113eSDavid van Moolenbroek
155*83ee113eSDavid van Moolenbroek	undef ($outfile);
156*83ee113eSDavid van Moolenbroek	print "Done.\n";
157*83ee113eSDavid van Moolenbroek	exit();
158*83ee113eSDavid van Moolenbroek
159*83ee113eSDavid van Moolenbroek################################## End Main Program ###########################
160*83ee113eSDavid van Moolenbroek
161*83ee113eSDavid van Moolenbroek
162*83ee113eSDavid van Moolenbroek
163*83ee113eSDavid van Moolenbroek
164*83ee113eSDavid van Moolenbroek
165*83ee113eSDavid van Moolenbroek######################################################################
166*83ee113eSDavid van Moolenbroeksub InsertIfUnique ($$) {
167*83ee113eSDavid van Moolenbroek	my ($Array, $data) = @_;
168*83ee113eSDavid van Moolenbroek# purpose: insert $data into array @{$Array} iff the data is not in there yet
169*83ee113eSDavid van Moolenbroek# input:
170*83ee113eSDavid van Moolenbroek#   $data: scalar data to be added to the @{$Array} if unique
171*83ee113eSDavid van Moolenbroek#   $Array: reference of the Array to compare the uniqueness of the $data
172*83ee113eSDavid van Moolenbroek# output:
173*83ee113eSDavid van Moolenbroek#   $Array: reference of the array with the resulting array.
174*83ee113eSDavid van Moolenbroek# return: none
175*83ee113eSDavid van Moolenbroek
176*83ee113eSDavid van Moolenbroek	my ($i);
177*83ee113eSDavid van Moolenbroek
178*83ee113eSDavid van Moolenbroek	for ($i=0; $i<=$#{$Array} && ${$Array}[$i] ne $data; $i++) { }
179*83ee113eSDavid van Moolenbroek
180*83ee113eSDavid van Moolenbroek	if ($i > $#{$Array}) {
181*83ee113eSDavid van Moolenbroek		${$Array}[$i] = $data;
182*83ee113eSDavid van Moolenbroek	}
183*83ee113eSDavid van Moolenbroek}
184*83ee113eSDavid van Moolenbroek######################################################################
185*83ee113eSDavid van Moolenbroeksub PrintDomainUpdate ($$$$) {
186*83ee113eSDavid van Moolenbroek	my ($outfile, $Domain, $DDNSServer, $key) = @_;
187*83ee113eSDavid van Moolenbroek# purpose: print out the foward domain zone update declaration
188*83ee113eSDavid van Moolenbroek# input:
189*83ee113eSDavid van Moolenbroek#   $outfile: filehandle of the file to write the output to
190*83ee113eSDavid van Moolenbroek#   $Domain: a string representing the forward domain
191*83ee113eSDavid van Moolenbroek#   $DDNSServer: a string of the DNS server accepting the DDNS update
192*83ee113eSDavid van Moolenbroek#   $key: a string representing the key used to update the zone
193*83ee113eSDavid van Moolenbroek# output: none
194*83ee113eSDavid van Moolenbroek# return: none
195*83ee113eSDavid van Moolenbroek#
196*83ee113eSDavid van Moolenbroek
197*83ee113eSDavid van Moolenbroek	print $outfile "zone $Domain {\n";
198*83ee113eSDavid van Moolenbroek	print $outfile "\tprimary $DDNSServer;\n";
199*83ee113eSDavid van Moolenbroek	!$key or print $outfile "\tkey $key;\n";
200*83ee113eSDavid van Moolenbroek	print $outfile "}\n";
201*83ee113eSDavid van Moolenbroek
202*83ee113eSDavid van Moolenbroek}
203*83ee113eSDavid van Moolenbroek######################################################################
204*83ee113eSDavid van Moolenbroeksub PrintSubnetUpdate ($$$$) {
205*83ee113eSDavid van Moolenbroek	my ($outfile, $Subnet, $DDNSServer, $key) = @_;
206*83ee113eSDavid van Moolenbroek# purpose: print out the reverse domain zone update declaration
207*83ee113eSDavid van Moolenbroek# input:
208*83ee113eSDavid van Moolenbroek#   $outfile: filehandle of the file to write the output to
209*83ee113eSDavid van Moolenbroek#   $Subnet: a string representing the subnet in the form 1.2.3.4
210*83ee113eSDavid van Moolenbroek#   $DDNSServer: a string of the DNS server accepting the DDNS update
211*83ee113eSDavid van Moolenbroek#   $key: a string representing the key used to update the zone
212*83ee113eSDavid van Moolenbroek# output: none
213*83ee113eSDavid van Moolenbroek# return: none
214*83ee113eSDavid van Moolenbroek#
215*83ee113eSDavid van Moolenbroek
216*83ee113eSDavid van Moolenbroek	my ($Reverse);
217*83ee113eSDavid van Moolenbroek
218*83ee113eSDavid van Moolenbroek	$_ = join (".", reverse(split(/\./, $Subnet)));
219*83ee113eSDavid van Moolenbroek	m/\d*\.(.*)/;
220*83ee113eSDavid van Moolenbroek	$Reverse = $1;
221*83ee113eSDavid van Moolenbroek	print $outfile "zone $Reverse.in-addr.arpa. {\n";
222*83ee113eSDavid van Moolenbroek	print $outfile "\tprimary $DDNSServer;\n";
223*83ee113eSDavid van Moolenbroek	!$key or print $outfile "\tkey $key;\n";
224*83ee113eSDavid van Moolenbroek	print $outfile "}\n";
225*83ee113eSDavid van Moolenbroek
226*83ee113eSDavid van Moolenbroek}
227*83ee113eSDavid van Moolenbroek######################################################################
228*83ee113eSDavid van Moolenbroeksub PrintSubnetConfig ($$$$$$) {
229*83ee113eSDavid van Moolenbroek	my ($outfile, $GlobalOptions, $Scope, $Subnet, $prefix, $failover) = @_;
230*83ee113eSDavid van Moolenbroek# purpose: print out the effective scope configuration for one subnet as
231*83ee113eSDavid van Moolenbroek#          derived from the global and scope options.
232*83ee113eSDavid van Moolenbroek# input:
233*83ee113eSDavid van Moolenbroek#   $outfile: filehandle of the file to write the output to
234*83ee113eSDavid van Moolenbroek#   $GlobalOptions: refernce to the hashed variable from GetGlobalOptions
235*83ee113eSDavid van Moolenbroek#   $Scopes: reference to the hashed variable of the subnet in interest
236*83ee113eSDavid van Moolenbroek#   $Subnet: string variable of the subnet being processed
237*83ee113eSDavid van Moolenbroek#   $prefix: string to be printed before each line (designed for tab)
238*83ee113eSDavid van Moolenbroek#   $failover: string to be used for the "failover peer" line
239*83ee113eSDavid van Moolenbroek# output: none
240*83ee113eSDavid van Moolenbroek# return: none
241*83ee113eSDavid van Moolenbroek#
242*83ee113eSDavid van Moolenbroek	my ($pound) = ( ${$Scope}{disable}? "#".$prefix : $prefix);
243*83ee113eSDavid van Moolenbroek	print $outfile $pound, "subnet $Subnet netmask ${$Scope}{mask} {\n";
244*83ee113eSDavid van Moolenbroek	print $outfile "$prefix# Name: ${$Scope}{name}\n";
245*83ee113eSDavid van Moolenbroek	print $outfile "$prefix# Comment: ${$Scope}{comment}\n";
246*83ee113eSDavid van Moolenbroek	if (exists ${$Scope}{routers}) {
247*83ee113eSDavid van Moolenbroek		print $outfile $pound, "\toption routers @{${$Scope}{routers}};\n";
248*83ee113eSDavid van Moolenbroek	} elsif (exists ${$GlobalOptions}{routers}) {
249*83ee113eSDavid van Moolenbroek		print $outfile $pound, "\toption routers @{${$GlobalOptions}{routers}};\t# NOTE: obtained from global option, bad practice detected\n";
250*83ee113eSDavid van Moolenbroek	} else {
251*83ee113eSDavid van Moolenbroek		print $outfile "### WARNING: No router was found for this subnet!!! ##########\n";
252*83ee113eSDavid van Moolenbroek	}
253*83ee113eSDavid van Moolenbroek
254*83ee113eSDavid van Moolenbroek	if (exists ${$Scope}{dnses}) {
255*83ee113eSDavid van Moolenbroek		print $outfile $pound, "\toption domain-name-servers ", join(",", @{${$Scope}{dnses}}), ";\n";
256*83ee113eSDavid van Moolenbroek	} elsif (exists ${$GlobalOptions}{dnses}) {
257*83ee113eSDavid van Moolenbroek		print $outfile $pound, "\toption domain-name-servers ", join(",", @{${$GlobalOptions}{dnses}}), ";\n";
258*83ee113eSDavid van Moolenbroek	}
259*83ee113eSDavid van Moolenbroek
260*83ee113eSDavid van Moolenbroek	if (exists ${$Scope}{domain}) {
261*83ee113eSDavid van Moolenbroek		print $outfile $pound, "\toption domain-name \"${$Scope}{domain}\";\n";
262*83ee113eSDavid van Moolenbroek	} elsif (exists ${$GlobalOptions}{domain}) {
263*83ee113eSDavid van Moolenbroek		print $outfile $pound, "\toption domain-name \"${$GlobalOptions}{domain}\";\n";
264*83ee113eSDavid van Moolenbroek	}
265*83ee113eSDavid van Moolenbroek
266*83ee113eSDavid van Moolenbroek	if (exists ${$Scope}{broadcast}) {
267*83ee113eSDavid van Moolenbroek		print $outfile $pound, "\toption broadcast-address ${$Scope}{broadcast};\n";
268*83ee113eSDavid van Moolenbroek	} elsif (exists ${$GlobalOptions}{broadcast}) {
269*83ee113eSDavid van Moolenbroek		print $outfile $pound, "\toption broadcast-address ${$GlobalOptions}{broadcast};\n";
270*83ee113eSDavid van Moolenbroek	}
271*83ee113eSDavid van Moolenbroek
272*83ee113eSDavid van Moolenbroek	if (exists ${$Scope}{winses}) {
273*83ee113eSDavid van Moolenbroek		print $outfile $pound, "\toption netbios-name-servers ", join(",", @{${$Scope}{winses}}), ";\n";
274*83ee113eSDavid van Moolenbroek	} elsif (exists ${$GlobalOptions}{winses}) {
275*83ee113eSDavid van Moolenbroek		print $outfile $pound, "\toption netbios-name-servers ", join(",", @{${$GlobalOptions}{winses}}), ";\n";
276*83ee113eSDavid van Moolenbroek	}
277*83ee113eSDavid van Moolenbroek
278*83ee113eSDavid van Moolenbroek	if (exists ${$Scope}{winstype}) {
279*83ee113eSDavid van Moolenbroek		print $outfile $pound, "\toption netbios-node-type ${$Scope}{winstype};\n";
280*83ee113eSDavid van Moolenbroek	} elsif (exists ${$GlobalOptions}{winstype}) {
281*83ee113eSDavid van Moolenbroek		print $outfile $pound, "\toption netbios-node-type ${$GlobalOptions}{winstype};\n"
282*83ee113eSDavid van Moolenbroek	}
283*83ee113eSDavid van Moolenbroek
284*83ee113eSDavid van Moolenbroek	print $outfile $pound, "\tdefault-lease-time ${$Scope}{leaseduration};\n";
285*83ee113eSDavid van Moolenbroek	print $outfile $pound, "\tpool {\n";
286*83ee113eSDavid van Moolenbroek	for (my $r=0; $r<=$#{${$Scope}{ranges}}; $r+=2) {
287*83ee113eSDavid van Moolenbroek		print $outfile $pound, "\t\trange ${$Scope}{ranges}[$r] ${$Scope}{ranges}[$r+1];\n";
288*83ee113eSDavid van Moolenbroek	}
289*83ee113eSDavid van Moolenbroek	!$failover or print $outfile $pound, "\t\tfailover peer \"$failover\";\n";
290*83ee113eSDavid van Moolenbroek	print $outfile $pound, "\t\tdeny dynamic bootp clients;\n";
291*83ee113eSDavid van Moolenbroek	print $outfile $pound, "\t}\n";
292*83ee113eSDavid van Moolenbroek	print $outfile $pound, "}\n";
293*83ee113eSDavid van Moolenbroek}
294*83ee113eSDavid van Moolenbroek
295*83ee113eSDavid van Moolenbroek######################################################################
296*83ee113eSDavid van Moolenbroeksub GetScopes ($) {
297*83ee113eSDavid van Moolenbroek	my ($Server) = @_;
298*83ee113eSDavid van Moolenbroek	my (%Scopes);
299*83ee113eSDavid van Moolenbroek# purpose: to return NT4 server's scope configuration
300*83ee113eSDavid van Moolenbroek# input:
301*83ee113eSDavid van Moolenbroek#   $Server: string of the valid IP or name of the NT4 server
302*83ee113eSDavid van Moolenbroek# output: none
303*83ee113eSDavid van Moolenbroek# return:
304*83ee113eSDavid van Moolenbroek#   %Scope: hash of hash of hash of various data types to be returned of the
305*83ee113eSDavid van Moolenbroek#           following data structure
306*83ee113eSDavid van Moolenbroek#     $Scope{<subnet>}{disable} => boolean
307*83ee113eSDavid van Moolenbroek#     $Scope{<subnet>}{mask} => string (e.g. "1.2.3.255")
308*83ee113eSDavid van Moolenbroek#     $Scope{<subnet>}{name} => string (e.g "Office Subnet #1")
309*83ee113eSDavid van Moolenbroek#     $Scope{<subnet>}{comment} => string (e.g. "This is a funny subnet")
310*83ee113eSDavid van Moolenbroek#     $Scope{<subnet>}{ranges} => array of paired inclusion IP addresses
311*83ee113eSDavid van Moolenbroek#                                 (e.g. "1.2.3.1 1.2.3.10 1.2.3.100 10.2.3.200
312*83ee113eSDavid van Moolenbroek#                                  says that we have 2 inclusion ranges of
313*83ee113eSDavid van Moolenbroek#                                  1-10 and 100-200)
314*83ee113eSDavid van Moolenbroek#     $Scopes{<subnet>}{routers} => array of IP address strings
315*83ee113eSDavid van Moolenbroek#     $Scopes{<subnet>}{dnses} => array of IP address/name string
316*83ee113eSDavid van Moolenbroek#     $Scopes{<subnet>}{domain} > string
317*83ee113eSDavid van Moolenbroek#     $Scopes{<subnet>}{broadcast} => string
318*83ee113eSDavid van Moolenbroek#     $Scopes{<subnet>}{winses} => array of IP addresses/name string
319*83ee113eSDavid van Moolenbroek#     $Scopes{<subnet>}{winstype} => integer
320*83ee113eSDavid van Moolenbroek#     $Scopes{<subnet>}{leaseduration} => integer
321*83ee113eSDavid van Moolenbroek
322*83ee113eSDavid van Moolenbroek	my ($RegVal, @Subnets, @Router, $SubnetName, $SubnetComment, @SubnetOptions, @SRouter, @SDNSServers, @SDomainname, @SWINSservers, @SNetBIOS, @SLeaseDuration, @SSubnetState, @SExclusionRanges, @SSubnetAddress, @SSubnetMask, @SFirstAddress, $SStartAddress, $SEndAddress, @InclusionRanges, @SBroadcastAddress);
323*83ee113eSDavid van Moolenbroek
324*83ee113eSDavid van Moolenbroek	print "Getting list of subnets\n";
325*83ee113eSDavid van Moolenbroek	if (Registry::GetRegSubkeyList ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets", \@Subnets)) {
326*83ee113eSDavid van Moolenbroek		die "Unable to obtain a list of subnets from the server!\n";
327*83ee113eSDavid van Moolenbroek	}
328*83ee113eSDavid van Moolenbroek
329*83ee113eSDavid van Moolenbroek	for (my $i=0; $i<=$#Subnets; $i++) {
330*83ee113eSDavid van Moolenbroek		print "\t Fetching Subnet $Subnets[$i] (",$i+1, "/", $#Subnets+1, "): ";
331*83ee113eSDavid van Moolenbroek
332*83ee113eSDavid van Moolenbroek		print ".";
333*83ee113eSDavid van Moolenbroek		if (!Registry::GetRegSubkeyList ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\IpRanges", \@SFirstAddress)) {
334*83ee113eSDavid van Moolenbroek			# Don't know why MS has a tree for this, but as far
335*83ee113eSDavid van Moolenbroek			# as I can tell, only one subtree will ever come out of
336*83ee113eSDavid van Moolenbroek			# this, so I'm skipping the 'for' loop
337*83ee113eSDavid van Moolenbroek
338*83ee113eSDavid van Moolenbroek			print ".";
339*83ee113eSDavid van Moolenbroek			if (!Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\IpRanges\\$SFirstAddress[0]\\StartAddress", \$RegVal)) {
340*83ee113eSDavid van Moolenbroek				$SStartAddress = $RegVal;
341*83ee113eSDavid van Moolenbroek			}
342*83ee113eSDavid van Moolenbroek			print ".";
343*83ee113eSDavid van Moolenbroek			if (!Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\IpRanges\\$SFirstAddress[0]\\EndAddress", \$RegVal)) {
344*83ee113eSDavid van Moolenbroek				$SEndAddress = $RegVal;
345*83ee113eSDavid van Moolenbroek			}
346*83ee113eSDavid van Moolenbroek# print "\n\tInclusion Range: ", Registry::ExtractIp($SStartAddress), " - ", Registry::ExtractIp($SEndAddress),"\n";
347*83ee113eSDavid van Moolenbroek
348*83ee113eSDavid van Moolenbroek		} else {
349*83ee113eSDavid van Moolenbroek			die "\n\n# Error Getting Inclusion Range FirstAddress!!!\n\n";
350*83ee113eSDavid van Moolenbroek		}
351*83ee113eSDavid van Moolenbroek
352*83ee113eSDavid van Moolenbroek		if (!Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\ExcludedIpRanges", \$RegVal)) {
353*83ee113eSDavid van Moolenbroek			@SExclusionRanges = Registry::ExtractExclusionRanges($RegVal);
354*83ee113eSDavid van Moolenbroek
355*83ee113eSDavid van Moolenbroek#			for (my $j=2; $j<=$#SExclusionRanges; $j+=2) {
356*83ee113eSDavid van Moolenbroek#				if (unpack("L",$SExclusionRanges[$j]) < unpack("L",$SExclusionRanges[$j-2])) {
357*83ee113eSDavid van Moolenbroek#					print ("\n******** Subnet exclusion ranges out of order ********\n");
358*83ee113eSDavid van Moolenbroek#				}
359*83ee113eSDavid van Moolenbroek#			}
360*83ee113eSDavid van Moolenbroek
361*83ee113eSDavid van Moolenbroek			@SExclusionRanges = sort(@SExclusionRanges);
362*83ee113eSDavid van Moolenbroek
363*83ee113eSDavid van Moolenbroek#		print "\n\tExclusion Ranges: ";
364*83ee113eSDavid van Moolenbroek#		for (my $j=0; $j<=$#SExclusionRanges; $j+=2) {
365*83ee113eSDavid van Moolenbroek#			print "\n\t\t",Registry::ExtractIp($SExclusionRanges[$j])," - ",Registry::ExtractIp($SExclusionRanges[$j+1]);
366*83ee113eSDavid van Moolenbroek#		}
367*83ee113eSDavid van Moolenbroek
368*83ee113eSDavid van Moolenbroek		}
369*83ee113eSDavid van Moolenbroek		@InclusionRanges = FindInclusionRanges ($SStartAddress, $SEndAddress, @SExclusionRanges);
370*83ee113eSDavid van Moolenbroek
371*83ee113eSDavid van Moolenbroek		print ".";
372*83ee113eSDavid van Moolenbroek		if (!Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\SubnetName", \$RegVal)) {
373*83ee113eSDavid van Moolenbroek			$SubnetName = $RegVal;
374*83ee113eSDavid van Moolenbroek#		print "\n\tSubnetName: $SubnetName";
375*83ee113eSDavid van Moolenbroek		}
376*83ee113eSDavid van Moolenbroek
377*83ee113eSDavid van Moolenbroek		print ".";
378*83ee113eSDavid van Moolenbroek		if (!Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\SubnetComment", \$RegVal)) {
379*83ee113eSDavid van Moolenbroek			$SubnetComment = $RegVal;
380*83ee113eSDavid van Moolenbroek#		print "\n\tSubnetComment: $SubnetComment";
381*83ee113eSDavid van Moolenbroek		}
382*83ee113eSDavid van Moolenbroek		print ".";
383*83ee113eSDavid van Moolenbroek		if (!Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\SubnetAddress", \$RegVal)) {
384*83ee113eSDavid van Moolenbroek			@SSubnetAddress = Registry::ExtractIp($RegVal);
385*83ee113eSDavid van Moolenbroek#		print "\n\tSubnetAddress: $SSubnetAddress[0]";
386*83ee113eSDavid van Moolenbroek		}
387*83ee113eSDavid van Moolenbroek		print ".";
388*83ee113eSDavid van Moolenbroek		if (!Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\SubnetMask", \$RegVal)) {
389*83ee113eSDavid van Moolenbroek			@SSubnetMask = Registry::ExtractIp($RegVal);
390*83ee113eSDavid van Moolenbroek#		print "\n\tSubnetMask: $SSubnetMask[0]";
391*83ee113eSDavid van Moolenbroek		}
392*83ee113eSDavid van Moolenbroek
393*83ee113eSDavid van Moolenbroek		print ".";
394*83ee113eSDavid van Moolenbroek		if (!Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\SubnetState", \$RegVal)) {
395*83ee113eSDavid van Moolenbroek			@SSubnetState = Registry::ExtractHex ($RegVal);
396*83ee113eSDavid van Moolenbroek#		print "\n\tSubnetState = $SSubnetState[0]";
397*83ee113eSDavid van Moolenbroek		}
398*83ee113eSDavid van Moolenbroek
399*83ee113eSDavid van Moolenbroek		$Scopes{$Subnets[$i]}{disable} = hex($SSubnetState[0]) ? 1 : 0;
400*83ee113eSDavid van Moolenbroek		$Scopes{$Subnets[$i]}{mask} = $SSubnetMask[0];
401*83ee113eSDavid van Moolenbroek		$Scopes{$Subnets[$i]}{name} = $SubnetName;
402*83ee113eSDavid van Moolenbroek		$Scopes{$Subnets[$i]}{comment} = $SubnetComment;
403*83ee113eSDavid van Moolenbroek		for (my $r=0; $r<=$#InclusionRanges; $r++) {
404*83ee113eSDavid van Moolenbroek			$Scopes{$Subnets[$i]}{ranges}[$r] = Registry::ExtractIp($InclusionRanges[$r]);
405*83ee113eSDavid van Moolenbroek		}
406*83ee113eSDavid van Moolenbroek
407*83ee113eSDavid van Moolenbroek################## Get scope options
408*83ee113eSDavid van Moolenbroek
409*83ee113eSDavid van Moolenbroek		my (@SubnetOptionsList);
410*83ee113eSDavid van Moolenbroek
411*83ee113eSDavid van Moolenbroek		print "\n\t\tOptions:";
412*83ee113eSDavid van Moolenbroek		if (Registry::GetRegSubkeyList ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\SubnetOptions", \@SubnetOptionsList)) {
413*83ee113eSDavid van Moolenbroek			die "Unable to get subnet options list for $Subnets[$i]!\n";
414*83ee113eSDavid van Moolenbroek		}
415*83ee113eSDavid van Moolenbroek
416*83ee113eSDavid van Moolenbroek		for (my $j=0; $j<=$#SubnetOptionsList; $j++) {
417*83ee113eSDavid van Moolenbroek			print ".";
418*83ee113eSDavid van Moolenbroek			if (!Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\SubnetOptions\\$SubnetOptionsList[$j]\\OptionValue", \$RegVal)) {
419*83ee113eSDavid van Moolenbroek				for ($SubnetOptionsList[$j]) {
420*83ee113eSDavid van Moolenbroek					/003/ and do {
421*83ee113eSDavid van Moolenbroek#						@SRouter = Registry::ExtractOptionIps($RegVal);
422*83ee113eSDavid van Moolenbroek						$Scopes{$Subnets[$i]}{routers} = [Registry::ExtractOptionIps($RegVal)];
423*83ee113eSDavid van Moolenbroek						last;
424*83ee113eSDavid van Moolenbroek					};
425*83ee113eSDavid van Moolenbroek					/006/ and do {
426*83ee113eSDavid van Moolenbroek						@SDNSServers = Registry::ExtractOptionIps($RegVal);
427*83ee113eSDavid van Moolenbroek						for (my $d=0; $d<=$#SDNSServers; $d++) {
428*83ee113eSDavid van Moolenbroek							my ($ipname, $rest) = gethostbyaddr(pack("C4", split(/\./, $SDNSServers[$d])), &AF_INET);
429*83ee113eSDavid van Moolenbroek							$Scopes{$Subnets[$i]}{dnses}[$d] = $ipname ? $ipname : $SDNSServers[$d];
430*83ee113eSDavid van Moolenbroek		}
431*83ee113eSDavid van Moolenbroek						last;
432*83ee113eSDavid van Moolenbroek					};
433*83ee113eSDavid van Moolenbroek					/015/ and do {
434*83ee113eSDavid van Moolenbroek						@SDomainname = Registry::ExtractOptionStrings($RegVal);
435*83ee113eSDavid van Moolenbroek						$Scopes{$Subnets[$i]}{domain} = $SDomainname[0];
436*83ee113eSDavid van Moolenbroek						last;
437*83ee113eSDavid van Moolenbroek					};
438*83ee113eSDavid van Moolenbroek					/028/ and do {
439*83ee113eSDavid van Moolenbroek						@SBroadcastAddress = Registry::ExtractOptionIps($RegVal);
440*83ee113eSDavid van Moolenbroek						$Scopes{$Subnets[$i]}{broadcast} = $SBroadcastAddress[0];
441*83ee113eSDavid van Moolenbroek						last;
442*83ee113eSDavid van Moolenbroek					};
443*83ee113eSDavid van Moolenbroek					/044/ and do {
444*83ee113eSDavid van Moolenbroek						@SWINSservers = Registry::ExtractOptionIps($RegVal);
445*83ee113eSDavid van Moolenbroek						for (my $w=0; $w<=$#SWINSservers; $w++) {
446*83ee113eSDavid van Moolenbroek							my ($ipname, $rest) = gethostbyaddr(pack("C4", split(/\./, $SWINSservers[$w])), &AF_INET);
447*83ee113eSDavid van Moolenbroek							$Scopes{$Subnets[$i]}{winses}[$w] = $ipname ? $ipname : $SWINSservers[$w];
448*83ee113eSDavid van Moolenbroek						}
449*83ee113eSDavid van Moolenbroek						last;
450*83ee113eSDavid van Moolenbroek					};
451*83ee113eSDavid van Moolenbroek					/046/ and do {
452*83ee113eSDavid van Moolenbroek						@SNetBIOS = Registry::ExtractOptionHex($RegVal);
453*83ee113eSDavid van Moolenbroek						$Scopes{$Subnets[$i]}{winstype} = hex($SNetBIOS[0]);
454*83ee113eSDavid van Moolenbroek						last;
455*83ee113eSDavid van Moolenbroek					};
456*83ee113eSDavid van Moolenbroek					/051/ and do {
457*83ee113eSDavid van Moolenbroek						@SLeaseDuration = Registry::ExtractOptionHex($RegVal);
458*83ee113eSDavid van Moolenbroek						$Scopes{$Subnets[$i]}{leaseduration} = hex($SLeaseDuration[0]);
459*83ee113eSDavid van Moolenbroek						last;
460*83ee113eSDavid van Moolenbroek					};
461*83ee113eSDavid van Moolenbroek					die "This program does not recognize subnet option \#$SubnetOptionsList[$j] yet!\n"
462*83ee113eSDavid van Moolenbroek				}
463*83ee113eSDavid van Moolenbroek			} else {
464*83ee113eSDavid van Moolenbroek					die "Unable to obtain option SubnetOptionsList[$j] from $Subnets[$i], most likely a registry problem!\n"
465*83ee113eSDavid van Moolenbroek			}
466*83ee113eSDavid van Moolenbroek		}
467*83ee113eSDavid van Moolenbroek		print "\n";
468*83ee113eSDavid van Moolenbroek	}
469*83ee113eSDavid van Moolenbroek
470*83ee113eSDavid van Moolenbroek	return %Scopes;
471*83ee113eSDavid van Moolenbroek}
472*83ee113eSDavid van Moolenbroek
473*83ee113eSDavid van Moolenbroek######################################################################
474*83ee113eSDavid van Moolenbroeksub FindInclusionRanges ($$@) {
475*83ee113eSDavid van Moolenbroek	my ($StartAddress, $EndAddress, @ExclusionRanges) = @_;
476*83ee113eSDavid van Moolenbroek# Purpose: to calculate and return the DHCP inclusion ranges out of
477*83ee113eSDavid van Moolenbroek#          data provided by the NT4 DHCP server
478*83ee113eSDavid van Moolenbroek# input:	$StartAddress:
479*83ee113eSDavid van Moolenbroek#        $EndAddress:
480*83ee113eSDavid van Moolenbroek#        @ExclusionRanges
481*83ee113eSDavid van Moolenbroek# output: none
482*83ee113eSDavid van Moolenbroek# return: An arry of IP address pair representing the inclusion ranges
483*83ee113eSDavid van Moolenbroek#         in the native registry format.
484*83ee113eSDavid van Moolenbroek#
485*83ee113eSDavid van Moolenbroek
486*83ee113eSDavid van Moolenbroek	my ($SA, $EA, @ER);
487*83ee113eSDavid van Moolenbroek	$SA = unpack("L", $StartAddress);
488*83ee113eSDavid van Moolenbroek	$EA = unpack("L", $EndAddress);
489*83ee113eSDavid van Moolenbroek	@ER = @ExclusionRanges;
490*83ee113eSDavid van Moolenbroek	for (my $i=0; $i<=$#ER; $i++) {
491*83ee113eSDavid van Moolenbroek		$ER[$i] = unpack ("L", $ER[$i]);
492*83ee113eSDavid van Moolenbroek	}
493*83ee113eSDavid van Moolenbroek
494*83ee113eSDavid van Moolenbroek	my @InclusionRanges;
495*83ee113eSDavid van Moolenbroek
496*83ee113eSDavid van Moolenbroek
497*83ee113eSDavid van Moolenbroek	$InclusionRanges[0] = $SA;
498*83ee113eSDavid van Moolenbroek	$InclusionRanges[1] = $EA;
499*83ee113eSDavid van Moolenbroek
500*83ee113eSDavid van Moolenbroek	for (my $i=0; $i<=$#ER; $i+=2) {
501*83ee113eSDavid van Moolenbroek		if ($ER[$i] == $InclusionRanges[$#InclusionRanges-1]) {
502*83ee113eSDavid van Moolenbroek			$InclusionRanges[$#InclusionRanges-1] = $ER[$i+1] + 1;
503*83ee113eSDavid van Moolenbroek		}
504*83ee113eSDavid van Moolenbroek		if ($ER[$i] > $InclusionRanges[$#InclusionRanges-1]) {
505*83ee113eSDavid van Moolenbroek			$InclusionRanges[$#InclusionRanges] = $ER[$i]-1;
506*83ee113eSDavid van Moolenbroek		}
507*83ee113eSDavid van Moolenbroek		if (($ER[$i+1] > $InclusionRanges[$#InclusionRanges]) &&
508*83ee113eSDavid van Moolenbroek		    ($ER[$i+1] != $EA)) {
509*83ee113eSDavid van Moolenbroek			$InclusionRanges[$#InclusionRanges+1] = $ER[$i+1] + 1;
510*83ee113eSDavid van Moolenbroek			$InclusionRanges[$#InclusionRanges+1] = $EA;
511*83ee113eSDavid van Moolenbroek		}
512*83ee113eSDavid van Moolenbroek		if ($InclusionRanges[$#InclusionRanges] < $InclusionRanges[$#InclusionRanges-1]) {
513*83ee113eSDavid van Moolenbroek			$#InclusionRanges -= 2;
514*83ee113eSDavid van Moolenbroek		}
515*83ee113eSDavid van Moolenbroek	}
516*83ee113eSDavid van Moolenbroek
517*83ee113eSDavid van Moolenbroek	for (my $i=0; $i<=$#InclusionRanges; $i++) {
518*83ee113eSDavid van Moolenbroek		$InclusionRanges[$i] = pack("L", $InclusionRanges[$i]);
519*83ee113eSDavid van Moolenbroek	#	print "Inclusion: ", Registry::ExtractIp($InclusionRanges[$i]), "\n";
520*83ee113eSDavid van Moolenbroek	}
521*83ee113eSDavid van Moolenbroek	return @InclusionRanges;
522*83ee113eSDavid van Moolenbroek}
523*83ee113eSDavid van Moolenbroek
524*83ee113eSDavid van Moolenbroek####################################################################
525*83ee113eSDavid van Moolenbroeksub GetSuperScope ($) {
526*83ee113eSDavid van Moolenbroek	my ($Server) = @_;
527*83ee113eSDavid van Moolenbroek	my (%SuperScopes);
528*83ee113eSDavid van Moolenbroek#
529*83ee113eSDavid van Moolenbroek# purpose: gets the Superscope list from the given server
530*83ee113eSDavid van Moolenbroek# input:
531*83ee113eSDavid van Moolenbroek#   $Server:  string of the valid IP address or name of the NT4 server
532*83ee113eSDavid van Moolenbroek# ouput: none
533*83ee113eSDavid van Moolenbroek# return:
534*83ee113eSDavid van Moolenbroek#   %SuperScopes: hash of array subnets with the following data structure
535*83ee113eSDavid van Moolenbroek#          $SuperScopes{<SuperscopeName>} => array of sunbets
536*83ee113eSDavid van Moolenbroek#
537*83ee113eSDavid van Moolenbroek	my (@SuperScopeNames, @SCSubnetList);
538*83ee113eSDavid van Moolenbroek
539*83ee113eSDavid van Moolenbroek	print "Getting Superscope list: ";
540*83ee113eSDavid van Moolenbroek	if (!Registry::GetRegSubkeyList ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\SuperScope", \@SuperScopeNames)) {
541*83ee113eSDavid van Moolenbroek		for (my $i=0; $i<=$#SuperScopeNames; $i++) {
542*83ee113eSDavid van Moolenbroek			print ".";
543*83ee113eSDavid van Moolenbroek			if (!Registry::GetRegSubkeyList ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\SuperScope\\$SuperScopeNames[$i]", \@SCSubnetList)) {
544*83ee113eSDavid van Moolenbroek				$SuperScopes{$SuperScopeNames[$i]} = [@SCSubnetList];
545*83ee113eSDavid van Moolenbroek			}
546*83ee113eSDavid van Moolenbroek		}
547*83ee113eSDavid van Moolenbroek		print "\n";
548*83ee113eSDavid van Moolenbroek	}
549*83ee113eSDavid van Moolenbroek
550*83ee113eSDavid van Moolenbroek	return %SuperScopes;
551*83ee113eSDavid van Moolenbroek}
552*83ee113eSDavid van Moolenbroek
553*83ee113eSDavid van Moolenbroek####################################################################
554*83ee113eSDavid van Moolenbroeksub GetGlobalOptions($) {
555*83ee113eSDavid van Moolenbroek	my ($Server) = @_;
556*83ee113eSDavid van Moolenbroek	my (%GlobalOptions);
557*83ee113eSDavid van Moolenbroek# purpose: to return NT4 server's global scope configuration
558*83ee113eSDavid van Moolenbroek# input:
559*83ee113eSDavid van Moolenbroek#   $Server: string of the valid IP or name of the NT4 server
560*83ee113eSDavid van Moolenbroek# output: none
561*83ee113eSDavid van Moolenbroek# return:
562*83ee113eSDavid van Moolenbroek#   %GlobalOptions: hash of hash of various data types to be returned of the
563*83ee113eSDavid van Moolenbroek#           following data structure
564*83ee113eSDavid van Moolenbroek#     $GlobalOptions{routers} => array of IP address strings
565*83ee113eSDavid van Moolenbroek#     $GlobalOptions{dnses} => array of IP address/name string
566*83ee113eSDavid van Moolenbroek#     $GlobalOptions{domain} > string
567*83ee113eSDavid van Moolenbroek#     $GlobalOptions{broadcast} => string
568*83ee113eSDavid van Moolenbroek#     $GlobalOptions{winses} => array of IP addresses/name string
569*83ee113eSDavid van Moolenbroek#     $GlobalOptions{winstype} => integer
570*83ee113eSDavid van Moolenbroek
571*83ee113eSDavid van Moolenbroek	my ($RegVal, @temp, @GlobalOptionValues);
572*83ee113eSDavid van Moolenbroek
573*83ee113eSDavid van Moolenbroek	print "Getting Global Options: ";
574*83ee113eSDavid van Moolenbroek	if (Registry::GetRegSubkeyList ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\GlobalOptionValues", \@GlobalOptionValues)) {
575*83ee113eSDavid van Moolenbroek		die "Unable to obtain GlobalOptionValues";
576*83ee113eSDavid van Moolenbroek	}
577*83ee113eSDavid van Moolenbroek
578*83ee113eSDavid van Moolenbroek	for (my $i=0; $i<=$#GlobalOptionValues; $i++) {
579*83ee113eSDavid van Moolenbroek		print ".";
580*83ee113eSDavid van Moolenbroek		if (Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\configuration\\globaloptionvalues\\$GlobalOptionValues[$i]\\optionvalue", \$RegVal)) {
581*83ee113eSDavid van Moolenbroek			die "Unable to retrive global option $GlobalOptionValues[$i]\n";
582*83ee113eSDavid van Moolenbroek		}
583*83ee113eSDavid van Moolenbroek
584*83ee113eSDavid van Moolenbroek
585*83ee113eSDavid van Moolenbroek		for ($GlobalOptionValues[$i]) {
586*83ee113eSDavid van Moolenbroek			/003/ and do {
587*83ee113eSDavid van Moolenbroek				@temp=Registry::ExtractOptionIps($RegVal);
588*83ee113eSDavid van Moolenbroek				$GlobalOptions{routers} = [@temp];
589*83ee113eSDavid van Moolenbroek				last;
590*83ee113eSDavid van Moolenbroek			};
591*83ee113eSDavid van Moolenbroek			/006/ and do {
592*83ee113eSDavid van Moolenbroek				# DNS Servers
593*83ee113eSDavid van Moolenbroek				@temp = Registry::ExtractOptionIps($RegVal);
594*83ee113eSDavid van Moolenbroek				for (my $d=0; $d<=$#temp; $d++) {
595*83ee113eSDavid van Moolenbroek					my ($ipname, $rest) = gethostbyaddr(pack("C4", split(/\./, $temp[$d])), &AF_INET);
596*83ee113eSDavid van Moolenbroek					$GlobalOptions{dnses}[$d] = $ipname ? $ipname : $temp[$d];
597*83ee113eSDavid van Moolenbroek				}
598*83ee113eSDavid van Moolenbroek				last;
599*83ee113eSDavid van Moolenbroek			};
600*83ee113eSDavid van Moolenbroek			/015/ and do {
601*83ee113eSDavid van Moolenbroek				# Domain Name
602*83ee113eSDavid van Moolenbroek				@temp = Registry::ExtractOptionStrings($RegVal);
603*83ee113eSDavid van Moolenbroek				$GlobalOptions{domain} = $temp[0];
604*83ee113eSDavid van Moolenbroek				last;
605*83ee113eSDavid van Moolenbroek			};
606*83ee113eSDavid van Moolenbroek			/028/ and do {
607*83ee113eSDavid van Moolenbroek				# broadcast address
608*83ee113eSDavid van Moolenbroek				@temp = Registry::ExtractOptionIps($RegVal);
609*83ee113eSDavid van Moolenbroek				$GlobalOptions{broadcast} = $temp[0];
610*83ee113eSDavid van Moolenbroek				last;
611*83ee113eSDavid van Moolenbroek			};
612*83ee113eSDavid van Moolenbroek			/044/ and do {
613*83ee113eSDavid van Moolenbroek				# WINS Servers
614*83ee113eSDavid van Moolenbroek				@temp = Registry::ExtractOptionIps ($RegVal);
615*83ee113eSDavid van Moolenbroek				$GlobalOptions{winses} = [@temp];
616*83ee113eSDavid van Moolenbroek				for (my $w=0; $w<=$#temp; $w++) {
617*83ee113eSDavid van Moolenbroek					my ($ipname, $rest) = gethostbyaddr(pack("C4", split(/\./, $temp[$w])), &AF_INET);
618*83ee113eSDavid van Moolenbroek					$GlobalOptions{winses}[$w] = $ipname ? $ipname : $temp[$w];
619*83ee113eSDavid van Moolenbroek				}
620*83ee113eSDavid van Moolenbroek				last;
621*83ee113eSDavid van Moolenbroek			};
622*83ee113eSDavid van Moolenbroek			/046/ and do {
623*83ee113eSDavid van Moolenbroek				# NETBIOS node type
624*83ee113eSDavid van Moolenbroek				@temp = Registry::ExtractOptionHex($RegVal);
625*83ee113eSDavid van Moolenbroek				$GlobalOptions{winstype} = hex($temp[0]);
626*83ee113eSDavid van Moolenbroek				last;
627*83ee113eSDavid van Moolenbroek			};
628*83ee113eSDavid van Moolenbroek			die "This program does not recgonize global option \#$GlobalOptionValues[$i] yet!\n"
629*83ee113eSDavid van Moolenbroek		}
630*83ee113eSDavid van Moolenbroek	}
631*83ee113eSDavid van Moolenbroek	print "\n";
632*83ee113eSDavid van Moolenbroek
633*83ee113eSDavid van Moolenbroek	return %GlobalOptions;
634*83ee113eSDavid van Moolenbroek}
635