Annotation of embedaddon/dhcp/contrib/ms2isc/ms2isc.pl, revision 1.1
1.1 ! misho 1: #set ts=3
! 2: #
! 3: # ms2isc.pl
! 4: # MS NT4 DHCP to ISC DHCP Configuration Migration Tool
! 5: #
! 6: # Author: Shu-Min Chang
! 7: #
! 8: # Copyright(c) 2003 Intel Corporation. All rights reserved
! 9: #
! 10: # Redistribution and use in source and binary forms, with or without
! 11: # modification, are permitted provided that the following conditions are met:
! 12: #
! 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.
! 21: #
! 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
! 32: # DAMAGE.
! 33:
! 34: use strict;
! 35: use Socket;
! 36: use Getopt::Std;
! 37: use Filehandle;
! 38: use Registry; # Custom Perl Module to make Registry access easier.
! 39:
! 40: my $usage = << 'ENDOFHELP';
! 41:
! 42: Purpose: A Perl Script converting MS NT4 DHCP configuration to ISC DHCP3
! 43: configuration file by reading NT4's registry.
! 44:
! 45: Requires: Registry.pm and ActiveState 5.6.0
! 46:
! 47: Usage: $ARGV -s <Srv> -o <Out> [-p <Pri> [-k <key>]] [-f <Fo>]
! 48:
! 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.
! 54:
! 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.
! 58:
! 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.
! 64:
! 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.
! 67:
! 68: NOTE: the program only knows of the following global and subnet options:
! 69: 3, 6, 15, 28, 44, and 46
! 70:
! 71: If it runs into options other than the known ones, it will quit. You
! 72: may fix this by modifying the following procedures:
! 73: GetGlobalOptions
! 74: GetScopes
! 75: PrintSubnetConfig
! 76:
! 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
! 79: want :).
! 80:
! 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.
! 86:
! 87: Author: Shu-Min Chang <smchang@yahoo.com>
! 88:
! 89: Copyright: Please read the top of the source code
! 90:
! 91: Acknowledgement:
! 92: Brian L. King for coding help, Douglas A. Darrah for testing, and James E.
! 93: Pressley for being the DHCP reference book :).
! 94:
! 95: Usage: $ARGV -s <Srv> -o <Out> [-p <Pri> [-k <key>]] [-f <Fo>]
! 96:
! 97: Version: 1.0.1
! 98:
! 99: ENDOFHELP
! 100:
! 101: ###################### Begin Main Program ####################################
! 102:
! 103: my (%opts, %GlobalOptions, %SuperScopes, %Scopes);
! 104:
! 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; }
! 109:
! 110: ### Read all the registry stuff into the memory
! 111: %GlobalOptions = GetGlobalOptions($opts{s});
! 112: %SuperScopes = GetSuperScope($opts{s});
! 113: %Scopes = GetScopes ($opts{s});
! 114:
! 115: ### Process and print out to the output file
! 116: my ($outfile, $i, $j, @Domains);
! 117:
! 118: $outfile = new FileHandle "> $opts{o}";
! 119: if (!defined $outfile) {
! 120: die "Can't open file: $opts{o}: $!";
! 121: }
! 122:
! 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};
! 131: delete $Scopes{$j};
! 132: }
! 133: print $outfile "}\n";
! 134: if ($opts{p} or $opts{k}) {
! 135: foreach $j (@{$SuperScopes{$i}}) {
! 136: PrintSubnetUpdate($outfile, $j, $opts{p}, $opts{k});
! 137: }
! 138: }
! 139: }
! 140:
! 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};
! 146: }
! 147:
! 148: if ($opts{p} or $opts{k}) {
! 149: InsertIfUnique (\@Domains, $GlobalOptions{domain}) if exists $GlobalOptions{domain};
! 150: for $i (@Domains) {
! 151: PrintDomainUpdate($outfile, $i, $opts{p}, $opts{k});
! 152: }
! 153: }
! 154:
! 155: undef ($outfile);
! 156: print "Done.\n";
! 157: exit();
! 158:
! 159: ################################## End Main Program ###########################
! 160:
! 161:
! 162:
! 163:
! 164:
! 165: ######################################################################
! 166: sub InsertIfUnique ($$) {
! 167: my ($Array, $data) = @_;
! 168: # purpose: insert $data into array @{$Array} iff the data is not in there yet
! 169: # input:
! 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
! 172: # output:
! 173: # $Array: reference of the array with the resulting array.
! 174: # return: none
! 175:
! 176: my ($i);
! 177:
! 178: for ($i=0; $i<=$#{$Array} && ${$Array}[$i] ne $data; $i++) { }
! 179:
! 180: if ($i > $#{$Array}) {
! 181: ${$Array}[$i] = $data;
! 182: }
! 183: }
! 184: ######################################################################
! 185: sub PrintDomainUpdate ($$$$) {
! 186: my ($outfile, $Domain, $DDNSServer, $key) = @_;
! 187: # purpose: print out the foward domain zone update declaration
! 188: # input:
! 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
! 193: # output: none
! 194: # return: none
! 195: #
! 196:
! 197: print $outfile "zone $Domain {\n";
! 198: print $outfile "\tprimary $DDNSServer;\n";
! 199: !$key or print $outfile "\tkey $key;\n";
! 200: print $outfile "}\n";
! 201:
! 202: }
! 203: ######################################################################
! 204: sub PrintSubnetUpdate ($$$$) {
! 205: my ($outfile, $Subnet, $DDNSServer, $key) = @_;
! 206: # purpose: print out the reverse domain zone update declaration
! 207: # input:
! 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
! 212: # output: none
! 213: # return: none
! 214: #
! 215:
! 216: my ($Reverse);
! 217:
! 218: $_ = join (".", reverse(split(/\./, $Subnet)));
! 219: m/\d*\.(.*)/;
! 220: $Reverse = $1;
! 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";
! 225:
! 226: }
! 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.
! 232: # input:
! 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
! 239: # output: none
! 240: # return: none
! 241: #
! 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";
! 250: } else {
! 251: print $outfile "### WARNING: No router was found for this subnet!!! ##########\n";
! 252: }
! 253:
! 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";
! 258: }
! 259:
! 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";
! 264: }
! 265:
! 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";
! 270: }
! 271:
! 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";
! 276: }
! 277:
! 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"
! 282: }
! 283:
! 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";
! 288: }
! 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";
! 293: }
! 294:
! 295: ######################################################################
! 296: sub GetScopes ($) {
! 297: my ($Server) = @_;
! 298: my (%Scopes);
! 299: # purpose: to return NT4 server's scope configuration
! 300: # input:
! 301: # $Server: string of the valid IP or name of the NT4 server
! 302: # output: none
! 303: # return:
! 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
! 313: # 1-10 and 100-200)
! 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
! 321:
! 322: my ($RegVal, @Subnets, @Router, $SubnetName, $SubnetComment, @SubnetOptions, @SRouter, @SDNSServers, @SDomainname, @SWINSservers, @SNetBIOS, @SLeaseDuration, @SSubnetState, @SExclusionRanges, @SSubnetAddress, @SSubnetMask, @SFirstAddress, $SStartAddress, $SEndAddress, @InclusionRanges, @SBroadcastAddress);
! 323:
! 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";
! 327: }
! 328:
! 329: for (my $i=0; $i<=$#Subnets; $i++) {
! 330: print "\t Fetching Subnet $Subnets[$i] (",$i+1, "/", $#Subnets+1, "): ";
! 331:
! 332: print ".";
! 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
! 337:
! 338: print ".";
! 339: if (!Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\IpRanges\\$SFirstAddress[0]\\StartAddress", \$RegVal)) {
! 340: $SStartAddress = $RegVal;
! 341: }
! 342: print ".";
! 343: if (!Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\IpRanges\\$SFirstAddress[0]\\EndAddress", \$RegVal)) {
! 344: $SEndAddress = $RegVal;
! 345: }
! 346: # print "\n\tInclusion Range: ", Registry::ExtractIp($SStartAddress), " - ", Registry::ExtractIp($SEndAddress),"\n";
! 347:
! 348: } else {
! 349: die "\n\n# Error Getting Inclusion Range FirstAddress!!!\n\n";
! 350: }
! 351:
! 352: if (!Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\ExcludedIpRanges", \$RegVal)) {
! 353: @SExclusionRanges = Registry::ExtractExclusionRanges($RegVal);
! 354:
! 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");
! 358: # }
! 359: # }
! 360:
! 361: @SExclusionRanges = sort(@SExclusionRanges);
! 362:
! 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]);
! 366: # }
! 367:
! 368: }
! 369: @InclusionRanges = FindInclusionRanges ($SStartAddress, $SEndAddress, @SExclusionRanges);
! 370:
! 371: print ".";
! 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";
! 375: }
! 376:
! 377: print ".";
! 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";
! 381: }
! 382: print ".";
! 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]";
! 386: }
! 387: print ".";
! 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]";
! 391: }
! 392:
! 393: print ".";
! 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]";
! 397: }
! 398:
! 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]);
! 405: }
! 406:
! 407: ################## Get scope options
! 408:
! 409: my (@SubnetOptionsList);
! 410:
! 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";
! 414: }
! 415:
! 416: for (my $j=0; $j<=$#SubnetOptionsList; $j++) {
! 417: print ".";
! 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]) {
! 420: /003/ and do {
! 421: # @SRouter = Registry::ExtractOptionIps($RegVal);
! 422: $Scopes{$Subnets[$i]}{routers} = [Registry::ExtractOptionIps($RegVal)];
! 423: last;
! 424: };
! 425: /006/ and do {
! 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];
! 430: }
! 431: last;
! 432: };
! 433: /015/ and do {
! 434: @SDomainname = Registry::ExtractOptionStrings($RegVal);
! 435: $Scopes{$Subnets[$i]}{domain} = $SDomainname[0];
! 436: last;
! 437: };
! 438: /028/ and do {
! 439: @SBroadcastAddress = Registry::ExtractOptionIps($RegVal);
! 440: $Scopes{$Subnets[$i]}{broadcast} = $SBroadcastAddress[0];
! 441: last;
! 442: };
! 443: /044/ and do {
! 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];
! 448: }
! 449: last;
! 450: };
! 451: /046/ and do {
! 452: @SNetBIOS = Registry::ExtractOptionHex($RegVal);
! 453: $Scopes{$Subnets[$i]}{winstype} = hex($SNetBIOS[0]);
! 454: last;
! 455: };
! 456: /051/ and do {
! 457: @SLeaseDuration = Registry::ExtractOptionHex($RegVal);
! 458: $Scopes{$Subnets[$i]}{leaseduration} = hex($SLeaseDuration[0]);
! 459: last;
! 460: };
! 461: die "This program does not recognize subnet option \#$SubnetOptionsList[$j] yet!\n"
! 462: }
! 463: } else {
! 464: die "Unable to obtain option SubnetOptionsList[$j] from $Subnets[$i], most likely a registry problem!\n"
! 465: }
! 466: }
! 467: print "\n";
! 468: }
! 469:
! 470: return %Scopes;
! 471: }
! 472:
! 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:
! 479: # $EndAddress:
! 480: # @ExclusionRanges
! 481: # output: none
! 482: # return: An arry of IP address pair representing the inclusion ranges
! 483: # in the native registry format.
! 484: #
! 485:
! 486: my ($SA, $EA, @ER);
! 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]);
! 492: }
! 493:
! 494: my @InclusionRanges;
! 495:
! 496:
! 497: $InclusionRanges[0] = $SA;
! 498: $InclusionRanges[1] = $EA;
! 499:
! 500: for (my $i=0; $i<=$#ER; $i+=2) {
! 501: if ($ER[$i] == $InclusionRanges[$#InclusionRanges-1]) {
! 502: $InclusionRanges[$#InclusionRanges-1] = $ER[$i+1] + 1;
! 503: }
! 504: if ($ER[$i] > $InclusionRanges[$#InclusionRanges-1]) {
! 505: $InclusionRanges[$#InclusionRanges] = $ER[$i]-1;
! 506: }
! 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;
! 511: }
! 512: if ($InclusionRanges[$#InclusionRanges] < $InclusionRanges[$#InclusionRanges-1]) {
! 513: $#InclusionRanges -= 2;
! 514: }
! 515: }
! 516:
! 517: for (my $i=0; $i<=$#InclusionRanges; $i++) {
! 518: $InclusionRanges[$i] = pack("L", $InclusionRanges[$i]);
! 519: # print "Inclusion: ", Registry::ExtractIp($InclusionRanges[$i]), "\n";
! 520: }
! 521: return @InclusionRanges;
! 522: }
! 523:
! 524: ####################################################################
! 525: sub GetSuperScope ($) {
! 526: my ($Server) = @_;
! 527: my (%SuperScopes);
! 528: #
! 529: # purpose: gets the Superscope list from the given server
! 530: # input:
! 531: # $Server: string of the valid IP address or name of the NT4 server
! 532: # ouput: none
! 533: # return:
! 534: # %SuperScopes: hash of array subnets with the following data structure
! 535: # $SuperScopes{<SuperscopeName>} => array of sunbets
! 536: #
! 537: my (@SuperScopeNames, @SCSubnetList);
! 538:
! 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++) {
! 542: print ".";
! 543: if (!Registry::GetRegSubkeyList ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\SuperScope\\$SuperScopeNames[$i]", \@SCSubnetList)) {
! 544: $SuperScopes{$SuperScopeNames[$i]} = [@SCSubnetList];
! 545: }
! 546: }
! 547: print "\n";
! 548: }
! 549:
! 550: return %SuperScopes;
! 551: }
! 552:
! 553: ####################################################################
! 554: sub GetGlobalOptions($) {
! 555: my ($Server) = @_;
! 556: my (%GlobalOptions);
! 557: # purpose: to return NT4 server's global scope configuration
! 558: # input:
! 559: # $Server: string of the valid IP or name of the NT4 server
! 560: # output: none
! 561: # return:
! 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
! 570:
! 571: my ($RegVal, @temp, @GlobalOptionValues);
! 572:
! 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";
! 576: }
! 577:
! 578: for (my $i=0; $i<=$#GlobalOptionValues; $i++) {
! 579: print ".";
! 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";
! 582: }
! 583:
! 584:
! 585: for ($GlobalOptionValues[$i]) {
! 586: /003/ and do {
! 587: @temp=Registry::ExtractOptionIps($RegVal);
! 588: $GlobalOptions{routers} = [@temp];
! 589: last;
! 590: };
! 591: /006/ and do {
! 592: # DNS Servers
! 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];
! 597: }
! 598: last;
! 599: };
! 600: /015/ and do {
! 601: # Domain Name
! 602: @temp = Registry::ExtractOptionStrings($RegVal);
! 603: $GlobalOptions{domain} = $temp[0];
! 604: last;
! 605: };
! 606: /028/ and do {
! 607: # broadcast address
! 608: @temp = Registry::ExtractOptionIps($RegVal);
! 609: $GlobalOptions{broadcast} = $temp[0];
! 610: last;
! 611: };
! 612: /044/ and do {
! 613: # WINS Servers
! 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];
! 619: }
! 620: last;
! 621: };
! 622: /046/ and do {
! 623: # NETBIOS node type
! 624: @temp = Registry::ExtractOptionHex($RegVal);
! 625: $GlobalOptions{winstype} = hex($temp[0]);
! 626: last;
! 627: };
! 628: die "This program does not recgonize global option \#$GlobalOptionValues[$i] yet!\n"
! 629: }
! 630: }
! 631: print "\n";
! 632:
! 633: return %GlobalOptions;
! 634: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>