Return to ms2isc.pl CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / dhcp / contrib / ms2isc |
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: }