diff options
Diffstat (limited to 'contrib')
-rwxr-xr-x | contrib/3.0b1-lease-convert | 126 | ||||
-rw-r--r-- | contrib/dhclient-tz-exithook.sh | 179 | ||||
-rw-r--r-- | contrib/dhcp.spec | 157 | ||||
-rw-r--r-- | contrib/ldap/README.ldap | 191 | ||||
-rw-r--r-- | contrib/ldap/dhcp.schema | 462 | ||||
-rw-r--r-- | contrib/ldap/dhcpd-conf-to-ldap | 760 | ||||
-rw-r--r-- | contrib/ms2isc/Registry.pm | 361 | ||||
-rw-r--r-- | contrib/ms2isc/ms2isc.pl | 634 | ||||
-rw-r--r-- | contrib/ms2isc/readme.txt | 15 | ||||
-rw-r--r-- | contrib/sethostname.sh | 29 | ||||
-rw-r--r-- | contrib/solaris.init | 28 |
11 files changed, 2942 insertions, 0 deletions
diff --git a/contrib/3.0b1-lease-convert b/contrib/3.0b1-lease-convert new file mode 100755 index 0000000..049a3a7 --- /dev/null +++ b/contrib/3.0b1-lease-convert @@ -0,0 +1,126 @@ +#!/usr/bin/perl +# +# Start Date: Mon, 26 Mar 2001 14:24:09 +0200 +# Time-stamp: <Monday, 26 March 2001 16:09:44 by brister> +# File: leaseconvertor.pl +# RCSId: $Id: 3.0b1-lease-convert,v 1.1 2001/04/18 19:17:34 mellon Exp $ +# +# Description: Convert 3.0b1 to 3.0b2/final lease file format +# + +require 5.004; + +my $rcsID =<<'EOM'; +$Id: 3.0b1-lease-convert,v 1.1 2001/04/18 19:17:34 mellon Exp $ +EOM + +use strict; + +my $revstatement =<<'EOS'; + switch (ns-update (delete (1, 12, ddns-rev-name, null))) { + case 0: + unset ddns-rev-name; + break; + } +EOS + +my $fwdstatement =<<'EOS'; + switch (ns-update (delete (1, 1, ddns-fwd-name, leased-address))) { + case 0: + unset ddns-fwd-name; + break; + } +EOS + + +if (@ARGV && $ARGV[0] =~ m!^-!) { + usage(); +} + + + +# read stdin and write stdout. +while (<>) { + if (! /^lease\s/) { + print; + } else { + my $lease = $_; + while (<>) { + $lease .= $_; + # in a b1 file we should only see a left curly brace on a lease + # lines. Seening it anywhere else means the user is probably + # running a b2 or later file through this. + # Ditto for a 'set' statement. + if (m!\{! || m!^\s*set\s!) { + warn "this doesn't look like a 3.0b1 file. Ignoring rest.\n"; + print $lease; + dumpRestAndExit(); + } + + last if m!^\}\s*$!; + } + + # $lease contains all the lines for the lease entry. + $lease = makeNewLease($lease); + print $lease; + } +} + + + +sub usage { + my $prog = $0; + $prog =~ s!.*/!!; + + print STDERR <<EOM; +usage: $prog [ file ] + +Reads from the lease file listed on the command line (or stdin if not filename +given) and writes to stdout. Converts a 3.0b1-style leases file to a 3.0b2 +style (for ad-hoc ddns updates). +EOM + + exit (0); +} + + + +# takes a string that's the lines of a lease entry and converts it, if +# necessary to a b2 style lease entry. Returns the new lease in printable form. +sub makeNewLease { + my ($lease) = @_; + + my $convertedfwd; + my $convertedrev; + my $newlease = ""; + foreach (split "\n", $lease) { + if (m!^(\s+)(ddns-fwd-name|ddns-rev-name)\s+(\"[^\"]+\"\s*;)!) { + $newlease .= $1 . "set " . $2 . " = " . $3 . "\n"; + + # If there's one of them, then it will always be the -fwd-. There + # may not always be a -rev-. + $convertedfwd++; + $convertedrev++ if ($2 eq "ddns-rev-name"); + } elsif (m!^\s*\}!) { + if ($convertedfwd) { + $newlease .= "\ton expiry or release {\n"; + $newlease .= $revstatement if $convertedrev; + $newlease .= $fwdstatement; + $newlease .= "\t on expiry or release;\n\t}\n"; + } + $newlease .= "}\n"; + } else { + $newlease .= $_ . "\n"; + } + } + + return $newlease; +} + + +sub dumpRestAndExit { + while (<>) { + print; + } + exit (0); +} diff --git a/contrib/dhclient-tz-exithook.sh b/contrib/dhclient-tz-exithook.sh new file mode 100644 index 0000000..9aa63c0 --- /dev/null +++ b/contrib/dhclient-tz-exithook.sh @@ -0,0 +1,179 @@ +#!/bin/bash +# +# dhclient-tz-exithook.sh +# Version 1.01 elear +# +# Copyright (c) 2007, Cisco Systems, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# - Neither the name of Cisco Systems, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# the following script is used to set the timezone based on the new +# dhcp timezone option defined currently in the IETF document +# draft-ietf-dhc-timezone-option-04.txt. + +# this code is intended for use with ISC's dhclient. it is to be called +# either as, or by, dhclient-exit-hooks +# +# As this is test code, in order for it to be called two changes +# must be made to /etc/dhclient.conf. First, dhclient.conf must be +# aware of the tzName option. The IANA has assigned tzName option +# code 101. You may need to add this to your configuration file. +# +# option tzName code 101 = text; +# +# Next, add tzName to the list of options in the "request" statement. +# For example: +# +# request subnet-mask, broadcast-address, time-offset, routers, +# domain-name, domain-name-servers, host-name, tzName; +# +# +# And of course make sure that your dhcp server is transmitting timezone +# information for option 101. For IOS this can be done as follows: +# +# option 101 ascii "Europe/Berlin" +# + +timefile=/etc/localtime +oldfile=$timefile.old +tmpfile=$timefile.$$ + +# function to clean up just in case we are interrupted or something +# bad happens. +restore_file () { + + if [ ! -f $timefile ]; then + $DEBUG mv $tmpfile $timefile + fi + $DEBUG rm $tmpfile + exit +} + + +#set DEBUG to "echo" to see what would happen. +if [ x$DEBUG = x ]; then + DEBUG= +fi + +# if something has already gone wrong we're not doing a thing. +if [ x$exit_status != x0 ]; then + exit $exit_status +fi + + +# if we don't have a new timezone, then we have nothing to change, so +# goodbye. +if [ x$new_tzName = x ]; then + exit 0 +fi + +# if the timezone doesn't exist, goodbye. +if [ ! -e $timefile ]; then + exit 0 +fi + +# find zoneinfo. use the first one. +ftz=0 +for a in /usr/share/zoneinfo /usr/lib/zoneinfo /var/share/zoneinfo /var/zoneinfo; do + if [ -d $a -a $ftz = 0 ]; then + zoneinfo=$a + ftz=1 + fi +done + +# no zoneinfo found. goodbye. +if [ x$zoneinfo = x ]; then + exit 0 +fi + +# timezone not found. goodbye. +if [ ! -f $zoneinfo/$new_tzName ]; then + exit 0 +fi + +# if we're here we can actually do something useful. +# first, link a copy of the existing timefile. + +$DEBUG ln $timefile $tmpfile + +if [ $? != 0 ]; then + echo "unable to create temporary file" + exit -1 +fi + +# in case of interrupt, cleanup. +trap restore_file SIGINT SIGSEGV SIGQUIT SIGTERM + +# we destroy old backup files in this process. if we cannot and the +# file exists then something went wrong. +if [ -e $oldfile ]; then + $DEBUG rm $oldfile + if [ $? != 0 ]; then + echo "$0: failed to remove $oldfile" + rm -f $tmpfile + exit -1 + fi +fi + +# sensitive part happens here: +# +$DEBUG mv $timefile $oldfile + + if [ $? != 0 ]; then + echo "$0: failed to move old $timefile file out of the way" + rm $tmpfile + exit -1 + fi + +$DEBUG ln $zoneinfo/$new_tzName $timefile + +# we don't complain just yet- a hard link could fail because +# we're on two different file systems. Go for a soft link. +# + +if [ $? != 0 ]; then + $DEBUG ln -s $zoneinfo/$new_tzName $timefile +fi + +if [ $? != 0 ]; then # failed to softlink. now we're getting nervous. + echo "$0: unable to establish new timezone. Attempting to revert." + $DEBUG ln $tmpfile $timefile +fi + + +if [ $? != 0 ]; then # we're absolutely hosed + echo "$0: unable to link or softlink timezone file, and unable to restore old file - giving up!" + exit -1 +fi + +$DEBUG rm $tmpfile + +exit $? diff --git a/contrib/dhcp.spec b/contrib/dhcp.spec new file mode 100644 index 0000000..0eb7201 --- /dev/null +++ b/contrib/dhcp.spec @@ -0,0 +1,157 @@ +Summary: The Internet Systems Consortium (ISC) DHCP server +Name: dhcp +%define version 3.0.2 +Version: %{version} +Release: 2tac +Group: System Environment/Daemons +Source: /usr/local/src/RPM/SOURCES/dhcp-%{version}.tar.gz +Copyright: ISC +BuildRoot: /var/tmp/dhcp-%{version}-root + +%description +Dhcp includes the DHCP server which is used for dynamically configuring +hosts on a network. Host configuration items such as IP address, name +servers, domain name, etc. can all be retrieved from the DHCP server by +a DHCP client. This eases the burden of network wide configuration by +putting all of the configuration into one place. + +%package client +Summary: A DHCP client +Group: System Environment/Configuration + +%description client +Dhcp client is a DHCP client for various UNIX operating systems. It allows +a UNIX machine to obtain it's networking parameters from a DHCP server. + +%package relay +Summary: A DHCP relay +Group: System Environment/Daemons + +%description relay +Dhcp relay is a relay agent for DHCP packets. It is used on a subnet with +DHCP clients to "relay" their requests to a subnet that has a DHCP server +on it. Because DHCP packets can be broadcast, they will not be routed off +of the local subnet. The DHCP relay takes care of this for the client. + +%package devel +Summary: Development headers and libraries for the dhcpctl API +Group: Development/Libraries + +%description devel +Dhcp devel contains all of the libraries and headers for developing with +the dhcpctl API. + +%prep +%setup -q -n dhcp-%{version} +# do some file editing +egrep "VARRUN +ETC +VARDB" site.conf | sed -e 's/ *=/=/g' -e 's/= */=/g' > vars +. ./vars +cat << EOF >> includes/site.h +#define _PATH_DHCPD_PID "$VARRUN/dhcpd.pid" +#define _PATH_DHCPD_DB "$ETC/dhcpd.leases" +#define _PATH_DHCPD_CONF "$ETC/dhcpd.conf" +EOF +./configure --with-nsupdate + +%build +make + +%install +rm -rf $RPM_BUILD_ROOT +mkdir -p $RPM_BUILD_ROOT/usr/local/sbin + +make DESTDIR="$RPM_BUILD_ROOT" install + +%ifos linux +mkdir -p ${RPM_BUILD_ROOT}/etc/rc.d/{init,rc0,rc1,rc2,rc3,rc4,rc5,rc6}.d +install -m 755 linux.init ${RPM_BUILD_ROOT}/etc/rc.d/init.d/dhcpd +%else +%ifos solaris +mkdir -p ${RPM_BUILD_ROOT}/etc/init.d +sed -e s'|@PREFIX@|%{_prefix}|g' < contrib/solaris.init > ${RPM_BUILD_ROOT}/etc/init.d/dhcpd +chmod 755 ${RPM_BUILD_ROOT}/etc/init.d/dhcpd +%endif +%endif + +# strip binaries and libraries +strip $RPM_BUILD_ROOT%{_prefix}/sbin/* || : +for i in `find $RPM_BUILD_ROOT/ -type 'f' -perm '+a=x' ! -name 'lib*so*'`; do + file $i |grep -q "not stripped" && strip $i +done + +%post +%ifos linux + /sbin/chkconfig --add dhcpd + /etc/rc.d/init.d/dhcpd start +%else + %ifos solaris + ln /etc/init.d/dhcpd /etc/rc2.d/S90dhcpd + ln /etc/init.d/dhcpd /etc/rc0.d/K30dhcpd + /etc/init.d/dhcpd start + %else + echo "Unknown O/S. You will need to manually configure your\nsystem" + echo "to start the DHCP server on system startup." + %endif +%endif + +%preun +if [ $1 = 0 ]; then + %ifos linux + /etc/rc.d/init.d/dhcpd stop + /sbin/chkconfig --del dhcpd + %else + %ifos solaris + /etc/init.d/dhcpd stop + rm /etc/rc2.d/S90dhcpd + rm /etc/rc0.d/K30dhcpd + %else + echo "Unknown O/S. You will need to manually clean up the DHCP" + echo "server startup\n in your system startup environment." + %endif + %endif +fi + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +%doc COPYRIGHT DOCUMENTATION ISC-LICENSE CHANGES README RELNOTES doc/* + +%{_prefix}/sbin/dhcpd +%{_prefix}/man/cat1m/dhcpd.1m +%{_prefix}/man/cat4/dhcpd.conf.4 +%{_prefix}/man/cat4/dhcpd.leases.4 +%{_prefix}/man/cat4/dhcp-options.4 +%{_prefix}/man/cat4/dhcp-eval.4 +%{_prefix}/man/cat4/dhcp-contrib.4 +%ifos linux +%config /etc/rc.d/init.d/dhcpd +%else +%ifos solaris +%config /etc/init.d/dhcpd +%endif +%endif + +%files devel +%{_prefix}/man/cat3 +%{_prefix}/lib +%{_prefix}/include + +%files client +%{_prefix}/etc/dhclient-script +%{_prefix}/sbin/dhclient +%{_prefix}/man/cat1m/dhclient.1m +%{_prefix}/man/cat1m/dhclient-script.1m +%{_prefix}/man/cat4/dhclient.conf.4 +%{_prefix}/man/cat4/dhclient.leases.4 + +%files relay +%{_prefix}/sbin/dhcrelay +%{_prefix}/man/cat1m/dhcrelay.1m + +%changelog +* Fri Oct 1 1999 Brian J. Murrell <brian@interlinx.bc.ca> +- write a spec file for dhcpd diff --git a/contrib/ldap/README.ldap b/contrib/ldap/README.ldap new file mode 100644 index 0000000..c413790 --- /dev/null +++ b/contrib/ldap/README.ldap @@ -0,0 +1,191 @@ +LDAP Support in DHCP +Original Author: Brian Masney <masneyb@gftp.org> +Current Maintainer: David Cantrell <dcantrell@redhat.com> +Last updated 07-Jul-2009 + +This document describes setting up the DHCP server to read it's configuration +from LDAP. This work is based on the IETF document +draft-ietf-dhc-ldap-schema-01.txt included in the doc directory. For the +latest version of this document, please see +http://dcantrel.fedorapeople.org/dhcp/ldap-patch/ + +First question on most people's mind is "Why do I want to store my +configuration in LDAP?" If you run a small DHCP server, and the configuration +on it rarely changes, then you won't need to store your configuration in LDAP. +But, if you have several DHCP servers, and you want an easy way to manage your +configuration, this can be a solution. + +The first step will be to setup your LDAP server. I am using OpenLDAP from +www.openldap.org. Building and installing OpenLDAP is beyond the scope of +this document. There is plenty of documentation out there about this. Once +you have OpenLDAP installed, you will have to edit your slapd.conf file. I +added the following 2 lines to my configuration file: + +include /etc/ldap/schema/dhcp.schema +index dhcpHWAddress eq +index dhcpClassData eq + +The first line tells it to include the dhcp schema file. You will find this +file under the contrib directory in this distribution. You will need to copy +this file to where your other schema files are (maybe /etc/openldap/schema/). +The second line sets up an index for the dhcpHWAddress parameter. The third +parameter is for reading subclasses from LDAP every time a DHCP request comes +in. Make sure you run the slapindex command and restart slapd to have these +changes to into effect. + +Now that you have LDAP setup, you should be able to use gq +(http://biot.com/gq/) to verify that the dhcp schema file is loaded into LDAP. +Pull up gq, and click on the Schema tab. Go under objectClasses, and you +should see at least the following object classes listed: dhcpClass, dhcpGroup, +dhcpHost, dhcpOptions, dhcpPool, dhcpServer, dhcpService, dhcpSharedNetwork, +dhcpSubClass, and dhcpSubnet. If you do not see these, you need to check over +your LDAP configuration before you go any further. + +You should now be ready to build DHCP. If you would like to enable LDAP in +dhcpd, you will need to perform the following steps: + + * Apply the patch here to the unpacked ISC dhcp source tree. + * Regenerate the configure script (requires GNU autoconf and automake): + aclocal + libtoolize --copy --force + autoconf + autoheader + automake --foreign --add-missing --copy + * Run ./configure with the '--with-ldap' argument to enable OpenLDAP. + If you want LDAP over SSL, also use the '--with-ldapcrypto' argument. + * Run 'make' to build ISC dhcp. + +Once you have DHCP installed, you will need to setup your initial plaintext +config file. In my /etc/dhcpd.conf file, I have: + +ldap-server "localhost"; +ldap-port 389; +ldap-username "cn=DHCP User, dc=ntelos, dc=net"; +ldap-password "blah"; +ldap-base-dn "dc=ntelos, dc=net"; +ldap-method dynamic; +ldap-debug-file "/var/log/dhcp-ldap-startup.log"; + +If SSL has been enabled at compile time, the dhcp server trys to use TLS if +possible, but continues without TLS if not. + +You can modify this behaviour using following option in /etc/dhcp/dhcpd.conf: + +ldap-ssl <off | ldaps | start_tls | on> + off: disables TLS/LDAPS. + ldaps: enables LDAPS -- don't forget to set ldap-port to 636. + start_tls: enables TLS using START_TLS command + on: enables LDAPS if ldap-port is set to 636 or TLS in + other cases. + +See also "man 5 ldap.conf" for description the following TLS related +options: + ldap-tls-reqcert, ldap-tls-ca-file, ldap-tls-ca-dir, ldap-tls-cert + ldap-tls-key, ldap-tls-crlcheck, ldap-tls-ciphers, ldap-tls-randfile + +All of these parameters should be self explanatory except for the ldap-method. +You can set this to static or dynamic. If you set it to static, the +configuration is read once on startup, and LDAP isn't used anymore. But, if +you set this to dynamic, the configuration is read once on startup, and the +hosts that are stored in LDAP are looked up every time a DHCP request comes +in. + +When the optional statement ldap-debug-file is specified, on startup the DHCP +server will write out the configuration that it generated from LDAP. If you +are getting errors about your LDAP configuration, this is a good place to +start looking. + +The next step is to set up your LDAP tree. Here is an example config that will +give a 10.100.0.x address to machines that have a host entry in LDAP. +Otherwise, it will give a 10.200.0.x address to them. (NOTE: replace +dc=ntelos, dc=net with your base dn). If you would like to convert your +existing dhcpd.conf file to LDIF format, there is a script +dhcpd-conf-to-ldap that will convert it for you. Type +dhcpd-conf-to-ldap --help to see the usage information for this script. + +# You must specify the server's host name in LDAP that you are going to run +# DHCP on and point it to which config tree you want to use. Whenever DHCP +# first starts up, it will do a search for this entry to find out which +# config to use +dn: cn=brian.ntelos.net, dc=ntelos, dc=net +objectClass: top +objectClass: dhcpServer +cn: brian.ntelos.net +dhcpServiceDN: cn=DHCP Service Config, dc=ntelos, dc=net + +# Here is the config tree that brian.ntelos.net points to. +dn: cn=DHCP Service Config, dc=ntelos, dc=net +cn: DHCP Service Config +objectClass: top +objectClass: dhcpService +dhcpPrimaryDN: dc=ntelos, dc=net +dhcpStatements: ddns-update-style none +dhcpStatements: default-lease-time 600 +dhcpStatements: max-lease-time 7200 + +# Set up a shared network segment +dn: cn=WV Test, cn=DHCP Service Config, dc=ntelos, dc=net +cn: WV +objectClass: top +objectClass: dhcpSharedNetwork + +# Set up a subnet declaration with a pool statement. Also note that we have +# a dhcpOptions object with this entry +dn: cn=10.100.0.0, cn=WV Test, cn=DHCP Service Config, dc=ntelos, dc=net +cn: 10.100.0.0 +objectClass: top +objectClass: dhcpSubnet +objectClass: dhcpOptions +dhcpOption: domain-name-servers 10.100.0.2 +dhcpOption: routers 10.100.0.1 +dhcpOption: subnet-mask 255.255.255.0 +dhcpOption: broadcast-address 10.100.0.255 +dhcpNetMask: 24 + +# Set up a pool for this subnet. Only known hosts will get these IPs +dn: cn=Known Pool, cn=10.100.0.0, cn=WV Test, cn=DHCP Service Config, dc=ntelos, dc=net +cn: Known Pool +objectClass: top +objectClass: dhcpPool +dhcpRange: 10.100.0.3 10.100.0.254 +dhcpPermitList: deny unknown-clients + +# Set up another subnet declaration with a pool statement +dn: cn=10.200.0.0, cn=WV Test, cn=DHCP Service Config, dc=ntelos, dc=net +cn: 10.200.0.0 +objectClass: top +objectClass: dhcpSubnet +objectClass: dhcpOptions +dhcpOption: domain-name-servers 10.200.0.2 +dhcpOption: routers 10.200.0.1 +dhcpOption: subnet-mask 255.255.255.0 +dhcpOption: broadcast-address 10.200.0.255 +dhcpNetMask: 24 + +# Set up a pool for this subnet. Only unknown hosts will get these IPs +dn: cn=Known Pool, cn=10.200.0.0, cn=WV Test, cn=DHCP Service Config, dc=ntelos, dc=net +cn: Known Pool +objectClass: top +objectClass: dhcpPool +dhcpRange: 10.200.0.3 10.200.0.254 +dhcpPermitList: deny known clients + +# Set aside a group for all of our known MAC addresses +dn: cn=Customers, cn=DHCP Service Config, dc=ntelos, dc=net +objectClass: top +objectClass: dhcpGroup +cn: Customers + +# Host entry for my laptop +dn: cn=brianlaptop, cn=Customers, cn=DHCP Service Config, dc=ntelos, dc=net +objectClass: top +objectClass: dhcpHost +cn: brianlaptop +dhcpHWAddress: ethernet 00:00:00:00:00:00 + +You can use the command ldapadd to load all of these entries into your LDAP +server. After you load this, you should be able to start up DHCP. If you run +into problems reading the configuration, try running dhcpd with the -d flag. +If you still have problems, edit the site.conf file in the DHCP source and +add the line: COPTS= -DDEBUG_LDAP and recompile DHCP. (make sure you run make +clean and rerun configure before you rebuild). diff --git a/contrib/ldap/dhcp.schema b/contrib/ldap/dhcp.schema new file mode 100644 index 0000000..c5ed6c7 --- /dev/null +++ b/contrib/ldap/dhcp.schema @@ -0,0 +1,462 @@ +attributetype ( 2.16.840.1.113719.1.203.4.1 + NAME 'dhcpPrimaryDN' + EQUALITY distinguishedNameMatch + DESC 'The DN of the dhcpServer which is the primary server for the configuration.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.2 + NAME 'dhcpSecondaryDN' + EQUALITY distinguishedNameMatch + DESC 'The DN of dhcpServer(s) which provide backup service for the configuration.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + +attributetype ( 2.16.840.1.113719.1.203.4.3 + NAME 'dhcpStatements' + EQUALITY caseIgnoreIA5Match + DESC 'Flexible storage for specific data depending on what object this exists in. Like conditional statements, server parameters, etc. This allows the standard to evolve without needing to adjust the schema.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 2.16.840.1.113719.1.203.4.4 + NAME 'dhcpRange' + EQUALITY caseIgnoreIA5Match + DESC 'The starting & ending IP Addresses in the range (inclusive), separated by a hyphen; if the range only contains one address, then just the address can be specified with no hyphen. Each range is defined as a separate value.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 2.16.840.1.113719.1.203.4.5 + NAME 'dhcpPermitList' + EQUALITY caseIgnoreIA5Match + DESC 'This attribute contains the permit lists associated with a pool. Each permit list is defined as a separate value.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 2.16.840.1.113719.1.203.4.6 + NAME 'dhcpNetMask' + EQUALITY integerMatch + DESC 'The subnet mask length for the subnet. The mask can be easily computed from this length.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.7 + NAME 'dhcpOption' + EQUALITY caseIgnoreIA5Match + DESC 'Encoded option values to be sent to clients. Each value represents a single option and contains (OptionTag, Length, OptionValue) encoded in the format used by DHCP.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 2.16.840.1.113719.1.203.4.8 + NAME 'dhcpClassData' + EQUALITY caseIgnoreIA5Match + DESC 'Encoded text string or list of bytes expressed in hexadecimal, separated by colons. Clients match subclasses based on matching the class data with the results of match or spawn with statements in the class name declarations.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.9 + NAME 'dhcpOptionsDN' + EQUALITY distinguishedNameMatch + DESC 'The distinguished name(s) of the dhcpOption objects containing the configuration options provided by the server.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + +attributetype ( 2.16.840.1.113719.1.203.4.10 + NAME 'dhcpHostDN' + EQUALITY distinguishedNameMatch + DESC 'the distinguished name(s) of the dhcpHost objects.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + +attributetype ( 2.16.840.1.113719.1.203.4.11 + NAME 'dhcpPoolDN' + EQUALITY distinguishedNameMatch + DESC 'The distinguished name(s) of pools.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + +attributetype ( 2.16.840.1.113719.1.203.4.12 + NAME 'dhcpGroupDN' + EQUALITY distinguishedNameMatch + DESC 'The distinguished name(s) of the groups.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + +attributetype ( 2.16.840.1.113719.1.203.4.13 + NAME 'dhcpSubnetDN' + EQUALITY distinguishedNameMatch + DESC 'The distinguished name(s) of the subnets.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + +attributetype ( 2.16.840.1.113719.1.203.4.14 + NAME 'dhcpLeaseDN' + EQUALITY distinguishedNameMatch + DESC 'The distinguished name of a client address.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE) + +attributetype ( 2.16.840.1.113719.1.203.4.15 + NAME 'dhcpLeasesDN' + DESC 'The distinguished name(s) client addresses.' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + +attributetype ( 2.16.840.1.113719.1.203.4.16 + NAME 'dhcpClassesDN' + EQUALITY distinguishedNameMatch + DESC 'The distinguished name(s) of a class(es) in a subclass.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + +attributetype ( 2.16.840.1.113719.1.203.4.17 + NAME 'dhcpSubclassesDN' + EQUALITY distinguishedNameMatch + DESC 'The distinguished name(s) of subclass(es).' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + +attributetype ( 2.16.840.1.113719.1.203.4.18 + NAME 'dhcpSharedNetworkDN' + EQUALITY distinguishedNameMatch + DESC 'The distinguished name(s) of sharedNetworks.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + +attributetype ( 2.16.840.1.113719.1.203.4.19 + NAME 'dhcpServiceDN' + EQUALITY distinguishedNameMatch + DESC 'The DN of dhcpService object(s)which contain the configuration information. Each dhcpServer object has this attribute identifying the DHCP configuration(s) that the server is associated with.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + +attributetype ( 2.16.840.1.113719.1.203.4.20 + NAME 'dhcpVersion' + DESC 'The version attribute of this object.' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.21 + NAME 'dhcpImplementation' + EQUALITY caseIgnoreIA5Match + DESC 'Description of the DHCP Server implementation e.g. DHCP Servers vendor.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.22 + NAME 'dhcpAddressState' + EQUALITY caseIgnoreIA5Match + DESC 'This stores information about the current binding-status of an address. For dynamic addresses managed by DHCP, the values should be restricted to the following: "FREE", "ACTIVE", "EXPIRED", "RELEASED", "RESET", "ABANDONED", "BACKUP". For other addresses, it SHOULD be one of the following: "UNKNOWN", "RESERVED" (an address that is managed by DHCP that is reserved for a specific client), "RESERVED-ACTIVE" (same as reserved, but address is currently in use), "ASSIGNED" (assigned manually or by some other mechanism), "UNASSIGNED", "NOTASSIGNABLE".' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.23 + NAME 'dhcpExpirationTime' + EQUALITY generalizedTimeMatch + DESC 'This is the time the current lease for an address expires.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.24 + NAME 'dhcpStartTimeOfState' + EQUALITY generalizedTimeMatch + DESC 'This is the time of the last state change for a leased address.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.25 + NAME 'dhcpLastTransactionTime' + EQUALITY generalizedTimeMatch + DESC 'This is the last time a valid DHCP packet was received from the client.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.26 + NAME 'dhcpBootpFlag' + EQUALITY booleanMatch + DESC 'This indicates whether the address was assigned via BOOTP.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.27 + NAME 'dhcpDomainName' + EQUALITY caseIgnoreIA5Match + DESC 'This is the name of the domain sent to the client by the server. It is essentially the same as the value for DHCP option 15 sent to the client, and represents only the domain - not the full FQDN. To obtain the full FQDN assigned to the client you must prepend the "dhcpAssignedHostName" to this value with a ".".' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.28 + NAME 'dhcpDnsStatus' + EQUALITY integerMatch + DESC 'This indicates the status of updating DNS resource records on behalf of the client by the DHCP server for this address. The value is a 16-bit bitmask.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.29 + NAME 'dhcpRequestedHostName' + EQUALITY caseIgnoreIA5Match + DESC 'This is the hostname that was requested by the client.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.30 + NAME 'dhcpAssignedHostName' + EQUALITY caseIgnoreIA5Match + DESC 'This is the actual hostname that was assigned to a client. It may not be the name that was requested by the client. The fully qualified domain name can be determined by appending the value of "dhcpDomainName" (with a dot separator) to this name.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.31 + NAME 'dhcpReservedForClient' + EQUALITY distinguishedNameMatch + DESC 'The distinguished name of a "dhcpClient" that an address is reserved for. This may not be the same as the "dhcpAssignedToClient" attribute if the address is being reassigned but the current lease has not yet expired.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.32 + NAME 'dhcpAssignedToClient' + EQUALITY distinguishedNameMatch + DESC 'This is the distinguished name of a "dhcpClient" that an address is currently assigned to. This attribute is only present in the class when the address is leased.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.33 + NAME 'dhcpRelayAgentInfo' + EQUALITY octetStringMatch + DESC 'If the client request was received via a relay agent, this contains information about the relay agent that was available from the DHCP request. This is a hex-encoded option value.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.34 + NAME 'dhcpHWAddress' + EQUALITY caseIgnoreIA5Match + DESC 'The clients hardware address that requested this IP address.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.35 + NAME 'dhcpHashBucketAssignment' + EQUALITY octetStringMatch + DESC 'HashBucketAssignment bit map for the DHCP Server, as defined in DHC Load Balancing Algorithm [RFC 3074].' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.36 + NAME 'dhcpDelayedServiceParameter' + EQUALITY integerMatch + DESC 'Delay in seconds corresponding to Delayed Service Parameter configuration, as defined in DHC Load Balancing Algorithm [RFC 3074]. ' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.37 + NAME 'dhcpMaxClientLeadTime' + EQUALITY integerMatch + DESC 'Maximum Client Lead Time configuration in seconds, as defined in DHCP Failover Protocol [FAILOVR]' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.38 + NAME 'dhcpFailOverEndpointState' + EQUALITY caseIgnoreIA5Match + DESC 'Server (Failover Endpoint) state, as defined in DHCP Failover Protocol [FAILOVR]' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.39 + NAME 'dhcpErrorLog' + EQUALITY caseIgnoreIA5Match + DESC 'Generic error log attribute that allows logging error conditions within a dhcpService or a dhcpSubnet, like no IP addresses available for lease.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.40 + NAME 'dhcpLocatorDN' + EQUALITY distinguishedNameMatch + DESC 'The DN of dhcpLocator object which contain the DNs of all DHCP configuration objects. There will be a single dhcpLocator object in the tree with links to all the DHCP objects in the tree' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + +attributetype ( 2.16.840.1.113719.1.203.4.41 + NAME 'dhcpKeyAlgorithm' + EQUALITY caseIgnoreIA5Match + DESC 'Algorithm to generate TSIG Key' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.42 + NAME 'dhcpKeySecret' + EQUALITY octetStringMatch + DESC 'Secret to generate TSIG Key' SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.43 + NAME 'dhcpDnsZoneServer' + EQUALITY caseIgnoreIA5Match + DESC 'Master server of the DNS Zone' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) + +attributetype ( 2.16.840.1.113719.1.203.4.44 + NAME 'dhcpKeyDN' + EQUALITY distinguishedNameMatch + DESC 'The DNs of TSIG Key to use in secure dynamic updates. In case of locator object, this will be list of TSIG keys. In case of DHCP Service, Shared Network, Subnet and DNS Zone, it will be a single key.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12) + +attributetype ( 2.16.840.1.113719.1.203.4.45 + NAME 'dhcpZoneDN' + EQUALITY distinguishedNameMatch + DESC 'The DNs of DNS Zone. In case of locator object, this will be list of DNS Zones in the tree. In case of DHCP Service, Shared Network and Subnet, it will be a single DNS Zone.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12) + +attributetype ( 2.16.840.1.113719.1.203.4.46 + NAME 'dhcpFailOverPrimaryServer' + EQUALITY caseIgnoreIA5Match + DESC 'IP address or DNS name of the server playing primary role in DHC Load Balancing and Fail over.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 2.16.840.1.113719.1.203.4.47 + NAME 'dhcpFailOverSecondaryServer' + EQUALITY caseIgnoreIA5Match + DESC 'IP address or DNS name of the server playing secondary role in DHC Load Balancing and Fail over.' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 2.16.840.1.113719.1.203.4.48 + NAME 'dhcpFailOverPrimaryPort' + EQUALITY integerMatch + DESC 'Port on which primary server listens for connections from its fail over peer (secondary server)' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) + +attributetype ( 2.16.840.1.113719.1.203.4.49 + NAME 'dhcpFailOverSecondaryPort' + EQUALITY integerMatch + DESC 'Port on which secondary server listens for connections from its fail over peer (primary server)' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) + +attributetype ( 2.16.840.1.113719.1.203.4.50 + NAME 'dhcpFailOverResponseDelay' + EQUALITY integerMatch + DESC 'Maximum response time in seconds, before Server assumes that connection to fail over peer has failed' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) + +attributetype ( 2.16.840.1.113719.1.203.4.51 + NAME 'dhcpFailOverUnackedUpdates' + EQUALITY integerMatch + DESC 'Number of BNDUPD messages that server can send before it receives BNDACK from its fail over peer' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) + +attributetype ( 2.16.840.1.113719.1.203.4.52 + NAME 'dhcpFailOverSplit' + EQUALITY integerMatch + DESC 'Split between the primary and secondary servers for fail over purpose' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) + +attributetype ( 2.16.840.1.113719.1.203.4.53 + NAME 'dhcpFailOverLoadBalanceTime' + EQUALITY integerMatch + DESC 'Cutoff time in seconds, after which load balance is disabled' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) + +attributetype ( 2.16.840.1.113719.1.203.4.54 + NAME 'dhcpFailOverPeerDN' + EQUALITY distinguishedNameMatch + DESC 'The DNs of Fail over peers. In case of locator object, this will be list of fail over peers in the tree. In case of Subnet and pool, it will be a single Fail Over Peer' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + +#List of all servers in the tree +attributetype ( 2.16.840.1.113719.1.203.4.55 + NAME 'dhcpServerDN' + EQUALITY distinguishedNameMatch + DESC 'List of all DHCP Servers in the tree. Used by dhcpLocatorObject' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + +attributetype ( 2.16.840.1.113719.1.203.4.56 + NAME 'dhcpComments' + EQUALITY caseIgnoreIA5Match + DESC 'Generic attribute that allows coments within any DHCP object' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) + +# Classes + +objectclass ( 2.16.840.1.113719.1.203.6.1 + NAME 'dhcpService' + DESC 'Service object that represents the actual DHCP Service configuration. This is a container object.' + SUP top + MUST (cn) + MAY ( dhcpPrimaryDN $ dhcpSecondaryDN $ dhcpServerDN $ dhcpSharedNetworkDN $ dhcpSubnetDN $ dhcpGroupDN $ dhcpHostDN $ dhcpClassesDN $ dhcpOptionsDN $ dhcpZoneDN $ dhcpKeyDN $ dhcpFailOverPeerDN $ dhcpStatements $dhcpComments $ dhcpOption) ) + +objectclass ( 2.16.840.1.113719.1.203.6.2 + NAME 'dhcpSharedNetwork' + DESC 'This stores configuration information for a shared network.' + SUP top + MUST cn + MAY ( dhcpSubnetDN $ dhcpPoolDN $ dhcpOptionsDN $ dhcpZoneDN $ dhcpStatements $dhcpComments $ dhcpOption) X-NDS_CONTAINMENT ('dhcpService' ) ) + +objectclass ( 2.16.840.1.113719.1.203.6.3 + NAME 'dhcpSubnet' + DESC 'This class defines a subnet. This is a container object.' + SUP top + MUST ( cn $ dhcpNetMask ) + MAY ( dhcpRange $ dhcpPoolDN $ dhcpGroupDN $ dhcpHostDN $ dhcpClassesDN $ dhcpLeasesDN $ dhcpOptionsDN $ dhcpZoneDN $ dhcpKeyDN $ dhcpFailOverPeerDN $ dhcpStatements $ dhcpComments $ dhcpOption ) X-NDS_CONTAINMENT ('dhcpService' 'dhcpSharedNetwork') ) + +objectclass ( 2.16.840.1.113719.1.203.6.4 + NAME 'dhcpPool' + DESC 'This stores configuration information about a pool.' + SUP top + MUST ( cn $ dhcpRange ) + MAY ( dhcpClassesDN $ dhcpPermitList $ dhcpLeasesDN $ dhcpOptionsDN $ dhcpZoneDN $dhcpKeyDN $ dhcpStatements $ dhcpComments $ dhcpOption ) + X-NDS_CONTAINMENT ('dhcpSubnet' 'dhcpSharedNetwork') ) + +objectclass ( 2.16.840.1.113719.1.203.6.5 + NAME 'dhcpGroup' + DESC 'Group object that lists host DNs and parameters. This is a container object.' + SUP top + MUST cn + MAY ( dhcpHostDN $ dhcpOptionsDN $ dhcpStatements $ dhcpComments $ dhcpOption ) + X-NDS_CONTAINMENT ('dhcpSubnet' 'dhcpService' ) ) + +objectclass ( 2.16.840.1.113719.1.203.6.6 + NAME 'dhcpHost' + DESC 'This represents information about a particular client' + SUP top + MUST cn + MAY (dhcpLeaseDN $ dhcpHWAddress $ dhcpOptionsDN $ dhcpStatements $ dhcpComments $ dhcpOption) + X-NDS_CONTAINMENT ('dhcpService' 'dhcpSubnet' 'dhcpGroup') ) + +objectclass ( 2.16.840.1.113719.1.203.6.7 + NAME 'dhcpClass' + DESC 'Represents information about a collection of related clients.' + SUP top + MUST cn + MAY (dhcpSubClassesDN $ dhcpOptionsDN $ dhcpStatements $ dhcpComments $ dhcpOption) + X-NDS_CONTAINMENT ('dhcpService' 'dhcpSubnet' ) ) + +objectclass ( 2.16.840.1.113719.1.203.6.8 + NAME 'dhcpSubClass' + DESC 'Represents information about a collection of related classes.' + SUP top + MUST cn + MAY (dhcpClassData $ dhcpOptionsDN $ dhcpStatements $ dhcpComments $ dhcpOption) X-NDS_CONTAINMENT 'dhcpClass' ) + +objectclass ( 2.16.840.1.113719.1.203.6.9 + NAME 'dhcpOptions' + DESC 'Represents information about a collection of options defined.' + SUP top AUXILIARY + MUST cn + MAY ( dhcpOption $ dhcpComments ) + X-NDS_CONTAINMENT ('dhcpService' 'dhcpSharedNetwork' 'dhcpSubnet' 'dhcpPool' 'dhcpGroup' 'dhcpHost' 'dhcpClass' ) ) + +objectclass ( 2.16.840.1.113719.1.203.6.10 + NAME 'dhcpLeases' + DESC 'This class represents an IP Address, which may or may not have been leased.' + SUP top + MUST ( cn $ dhcpAddressState ) + MAY ( dhcpExpirationTime $ dhcpStartTimeOfState $ dhcpLastTransactionTime $ dhcpBootpFlag $ dhcpDomainName $ dhcpDnsStatus $ dhcpRequestedHostName $ dhcpAssignedHostName $ dhcpReservedForClient $ dhcpAssignedToClient $ dhcpRelayAgentInfo $ dhcpHWAddress ) + X-NDS_CONTAINMENT ( 'dhcpService' 'dhcpSubnet' 'dhcpPool') ) + +objectclass ( 2.16.840.1.113719.1.203.6.11 + NAME 'dhcpLog' + DESC 'This is the object that holds past information about the IP address. The cn is the time/date stamp when the address was assigned or released, the address state at the time, if the address was assigned or released.' + SUP top + MUST ( cn ) + MAY ( dhcpAddressState $ dhcpExpirationTime $ dhcpStartTimeOfState $ dhcpLastTransactionTime $ dhcpBootpFlag $ dhcpDomainName $ dhcpDnsStatus $ dhcpRequestedHostName $ dhcpAssignedHostName $ dhcpReservedForClient $ dhcpAssignedToClient $ dhcpRelayAgentInfo $ dhcpHWAddress $ dhcpErrorLog) + X-NDS_CONTAINMENT ('dhcpLeases' 'dhcpPool' 'dhcpSubnet' 'dhcpSharedNetwork' 'dhcpService' ) ) + +objectclass ( 2.16.840.1.113719.1.203.6.12 + NAME 'dhcpServer' + DESC 'DHCP Server Object' + SUP top + MUST ( cn ) + MAY (dhcpServiceDN $ dhcpLocatorDN $ dhcpVersion $ dhcpImplementation $ dhcpHashBucketAssignment $ dhcpDelayedServiceParameter $ dhcpMaxClientLeadTime $ dhcpFailOverEndpointState $ dhcpStatements $ dhcpComments $ dhcpOption) + X-NDS_CONTAINMENT ('organization' 'organizationalunit' 'domain') ) + +objectclass ( 2.16.840.1.113719.1.203.6.13 + NAME 'dhcpTSigKey' + DESC 'TSIG key for secure dynamic updates' + SUP top + MUST (cn $ dhcpKeyAlgorithm $ dhcpKeySecret ) + MAY ( dhcpComments ) + X-NDS_CONTAINMENT ('dhcpService' 'dhcpSharedNetwork' 'dhcpSubnet') ) + +objectclass ( 2.16.840.1.113719.1.203.6.14 + NAME 'dhcpDnsZone' + DESC 'DNS Zone for updating leases' + SUP top + MUST (cn $ dhcpDnsZoneServer ) + MAY (dhcpKeyDN $ dhcpComments) + X-NDS_CONTAINMENT ('dhcpService' 'dhcpSharedNetwork' 'dhcpSubnet') ) + +objectclass ( 2.16.840.1.113719.1.203.6.15 + NAME 'dhcpFailOverPeer' + DESC 'This class defines the Fail over peer' + SUP top + MUST ( cn $ dhcpFailOverPrimaryServer $ dhcpFailOverSecondaryServer $ dhcpFailoverPrimaryPort $ dhcpFailOverSecondaryPort) MAY (dhcpFailOverResponseDelay $ dhcpFailOverUnackedUpdates $ dhcpMaxClientLeadTime $ dhcpFailOverSplit $ dhcpHashBucketAssignment $ dhcpFailOverLoadBalanceTime $ dhcpComments ) + X-NDS_CONTAINMENT ('dhcpService' 'dhcpSharedNetwork' 'dhcpSubnet') ) + +objectclass ( 2.16.840.1.113719.1.203.6.16 + NAME 'dhcpLocator' + DESC 'Locator object for DHCP configuration in the tree. There will be a single dhcpLocator object in the tree with links to all the DHCP objects in the tree' + SUP top + MUST ( cn ) + MAY ( dhcpServiceDN $dhcpServerDN $ dhcpSharedNetworkDN $ dhcpSubnetDN $ dhcpPoolDN $ dhcpGroupDN $ dhcpHostDN $ dhcpClassesDN $ dhcpKeyDN $ dhcpZoneDN $ dhcpFailOverPeerDN $ dhcpOption $ dhcpComments) + X-NDS_CONTAINMENT ('organization' 'organizationalunit' 'domain') ) + + diff --git a/contrib/ldap/dhcpd-conf-to-ldap b/contrib/ldap/dhcpd-conf-to-ldap new file mode 100644 index 0000000..aee6c97 --- /dev/null +++ b/contrib/ldap/dhcpd-conf-to-ldap @@ -0,0 +1,760 @@ +#!/usr/bin/perl -w + +# Brian Masney <masneyb@gftp.org> +# To use this script, set your base DN below. Then run +# ./dhcpd-conf-to-ldap.pl < /path-to-dhcpd-conf/dhcpd.conf > output-file +# The output of this script will generate entries in LDIF format. You can use +# the slapadd command to add these entries into your LDAP server. You will +# definately want to double check that your LDAP entries are correct before +# you load them into LDAP. + +# This script does not do much error checking. Make sure before you run this +# that the DHCP server doesn't give any errors about your config file + +# FailOver notes: +# Failover is disabled by default, since it may need manually intervention. +# You can try the '--use=failover' option to see what happens :-) +# +# If enabled, the failover pool references will be written to LDIF output. +# The failover configs itself will be added to the dhcpServer statements +# and not to the dhcpService object (since this script uses only one and +# it may be usefull to have multiple service containers in failover mode). +# Further, this script does not check if primary or secondary makes sense, +# it simply converts what it gets... + +use Net::Domain qw(hostname hostfqdn hostdomain); +use Getopt::Long; + +my $domain = hostdomain(); # your.domain +my $basedn = "dc=".$domain; + $basedn =~ s/\./,dc=/g; # dc=your,dc=domain +my $server = hostname(); # hostname (nodename) +my $dhcpcn = 'DHCP Config'; # CN of DHCP config tree +my $dhcpdn = "cn=$dhcpcn, $basedn"; # DHCP config tree DN +my $second = ''; # secondary server DN / hostname +my $i_conf = ''; # dhcp.conf file to read or stdin +my $o_ldif = ''; # output ldif file name or stdout +my @use = (); # extended flags (failover) + +sub usage($;$) +{ + my $rc = shift; + my $err= shift; + + print STDERR "Error: $err\n\n" if(defined $err); + print STDERR <<__EOF_USAGE__; +usage: + $0 [options] < dhcpd.conf > dhcpd.ldif + +options: + + --basedn "dc=your,dc=domain" ("$basedn") + + --dhcpdn "dhcp config DN" ("$dhcpdn") + + --server "dhcp server name" ("$server") + + --second "secondary server or DN" ("$second") + + --conf "/path/to/dhcpd.conf" (default is stdin) + --ldif "/path/to/output.ldif" (default is stdout) + + --use "extended features" (see source comments) +__EOF_USAGE__ + exit($rc); +} + + +sub next_token +{ + local ($lowercase) = @_; + local ($token, $newline); + + do + { + if (!defined ($line) || length ($line) == 0) + { + $line = <>; + return undef if !defined ($line); + chop $line; + $line_number++; + $token_number = 0; + } + + $line =~ s/#.*//; + $line =~ s/^\s+//; + $line =~ s/\s+$//; + } + while (length ($line) == 0); + + if (($token, $newline) = $line =~ /^(.*?)\s+(.*)/) + { + if ($token =~ /^"/) { + #handle quoted token + if ($token !~ /"\s*$/) + { + ($tok, $newline) = $newline =~ /([^"]+")(.*)/; + $token .= " $tok"; + } + } + $line = $newline; + } + else + { + $token = $line; + $line = ''; + } + $token_number++; + + $token =~ y/[A-Z]/[a-z]/ if $lowercase; + + return ($token); +} + + +sub remaining_line +{ + local ($block) = shift || 0; + local ($tmp, $str); + + $str = ""; + while (defined($tmp = next_token (0))) + { + $str .= ' ' if !($str eq ""); + $str .= $tmp; + last if $tmp =~ /;\s*$/; + last if($block and $tmp =~ /\s*[}{]\s*$/); + } + + $str =~ s/;$//; + return ($str); +} + + +sub +add_dn_to_stack +{ + local ($dn) = @_; + + $current_dn = "$dn, $current_dn"; +} + + +sub +remove_dn_from_stack +{ + $current_dn =~ s/^.*?,\s*//; +} + + +sub +parse_error +{ + print "Parse error on line number $line_number at token number $token_number\n"; + exit (1); +} + + +sub +print_entry +{ + return if (scalar keys %curentry == 0); + + if (!defined ($curentry{'type'})) + { + $hostdn = "cn=$server, $basedn"; + print "dn: $hostdn\n"; + print "cn: $server\n"; + print "objectClass: top\n"; + print "objectClass: dhcpServer\n"; + print "dhcpServiceDN: $current_dn\n"; + if(grep(/FaIlOvEr/i, @use)) + { + foreach my $fo_peer (keys %failover) + { + next if(scalar(@{$failover{$fo_peer}}) <= 1); + print "dhcpStatements: failover peer $fo_peer { ", + join('; ', @{$failover{$fo_peer}}), "; }\n"; + } + } + print "\n"; + + print "dn: $current_dn\n"; + print "cn: $dhcpcn\n"; + print "objectClass: top\n"; + print "objectClass: dhcpService\n"; + if (defined ($curentry{'options'})) + { + print "objectClass: dhcpOptions\n"; + } + print "dhcpPrimaryDN: $hostdn\n"; + if(grep(/FaIlOvEr/i, @use) and ($second ne '')) + { + print "dhcpSecondaryDN: $second\n"; + } + } + elsif ($curentry{'type'} eq 'subnet') + { + print "dn: $current_dn\n"; + print "cn: " . $curentry{'ip'} . "\n"; + print "objectClass: top\n"; + print "objectClass: dhcpSubnet\n"; + if (defined ($curentry{'options'})) + { + print "objectClass: dhcpOptions\n"; + } + + print "dhcpNetMask: " . $curentry{'netmask'} . "\n"; + if (defined ($curentry{'ranges'})) + { + foreach $statement (@{$curentry{'ranges'}}) + { + print "dhcpRange: $statement\n"; + } + } + } + elsif ($curentry{'type'} eq 'shared-network') + { + print "dn: $current_dn\n"; + print "cn: " . $curentry{'descr'} . "\n"; + print "objectClass: top\n"; + print "objectClass: dhcpSharedNetwork\n"; + if (defined ($curentry{'options'})) + { + print "objectClass: dhcpOptions\n"; + } + } + elsif ($curentry{'type'} eq 'group') + { + print "dn: $current_dn\n"; + print "cn: group", $curentry{'idx'}, "\n"; + print "objectClass: top\n"; + print "objectClass: dhcpGroup\n"; + if (defined ($curentry{'options'})) + { + print "objectClass: dhcpOptions\n"; + } + } + elsif ($curentry{'type'} eq 'host') + { + print "dn: $current_dn\n"; + print "cn: " . $curentry{'host'} . "\n"; + print "objectClass: top\n"; + print "objectClass: dhcpHost\n"; + if (defined ($curentry{'options'})) + { + print "objectClass: dhcpOptions\n"; + } + + if (defined ($curentry{'hwaddress'})) + { + $curentry{'hwaddress'} =~ y/[A-Z]/[a-z]/; + print "dhcpHWAddress: " . $curentry{'hwaddress'} . "\n"; + } + } + elsif ($curentry{'type'} eq 'pool') + { + print "dn: $current_dn\n"; + print "cn: pool", $curentry{'idx'}, "\n"; + print "objectClass: top\n"; + print "objectClass: dhcpPool\n"; + if (defined ($curentry{'options'})) + { + print "objectClass: dhcpOptions\n"; + } + + if (defined ($curentry{'ranges'})) + { + foreach $statement (@{$curentry{'ranges'}}) + { + print "dhcpRange: $statement\n"; + } + } + } + elsif ($curentry{'type'} eq 'class') + { + print "dn: $current_dn\n"; + print "cn: " . $curentry{'class'} . "\n"; + print "objectClass: top\n"; + print "objectClass: dhcpClass\n"; + if (defined ($curentry{'options'})) + { + print "objectClass: dhcpOptions\n"; + } + } + elsif ($curentry{'type'} eq 'subclass') + { + print "dn: $current_dn\n"; + print "cn: " . $curentry{'subclass'} . "\n"; + print "objectClass: top\n"; + print "objectClass: dhcpSubClass\n"; + if (defined ($curentry{'options'})) + { + print "objectClass: dhcpOptions\n"; + } + print "dhcpClassData: " . $curentry{'class'} . "\n"; + } + + if (defined ($curentry{'statements'})) + { + foreach $statement (@{$curentry{'statements'}}) + { + print "dhcpStatements: $statement\n"; + } + } + + if (defined ($curentry{'options'})) + { + foreach $statement (@{$curentry{'options'}}) + { + print "dhcpOption: $statement\n"; + } + } + + print "\n"; + undef (%curentry); +} + + +sub parse_netmask +{ + local ($netmask) = @_; + local ($i); + + if ((($a, $b, $c, $d) = $netmask =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) != 4) + { + parse_error (); + } + + $num = (($a & 0xff) << 24) | + (($b & 0xff) << 16) | + (($c & 0xff) << 8) | + ($d & 0xff); + + for ($i=1; $i<=32 && $num & (1 << (32 - $i)); $i++) + { + } + $i--; + + return ($i); +} + + +sub parse_subnet +{ + local ($ip, $tmp, $netmask); + + print_entry () if %curentry; + + $ip = next_token (0); + parse_error () if !defined ($ip); + + $tmp = next_token (1); + parse_error () if !defined ($tmp); + parse_error () if !($tmp eq 'netmask'); + + $tmp = next_token (0); + parse_error () if !defined ($tmp); + $netmask = parse_netmask ($tmp); + + $tmp = next_token (0); + parse_error () if !defined ($tmp); + parse_error () if !($tmp eq '{'); + + add_dn_to_stack ("cn=$ip"); + $curentry{'type'} = 'subnet'; + $curentry{'ip'} = $ip; + $curentry{'netmask'} = $netmask; + $cursubnet = $ip; + $curcounter{$ip} = { pool => 0, group => 0 }; +} + + +sub parse_shared_network +{ + local ($descr, $tmp); + + print_entry () if %curentry; + + $descr = next_token (0); + parse_error () if !defined ($descr); + + $tmp = next_token (0); + parse_error () if !defined ($tmp); + parse_error () if !($tmp eq '{'); + + add_dn_to_stack ("cn=$descr"); + $curentry{'type'} = 'shared-network'; + $curentry{'descr'} = $descr; +} + + +sub parse_host +{ + local ($descr, $tmp); + + print_entry () if %curentry; + + $host = next_token (0); + parse_error () if !defined ($host); + + $tmp = next_token (0); + parse_error () if !defined ($tmp); + parse_error () if !($tmp eq '{'); + + add_dn_to_stack ("cn=$host"); + $curentry{'type'} = 'host'; + $curentry{'host'} = $host; +} + + +sub parse_group +{ + local ($descr, $tmp); + + print_entry () if %curentry; + + $tmp = next_token (0); + parse_error () if !defined ($tmp); + parse_error () if !($tmp eq '{'); + + my $idx; + if(exists($curcounter{$cursubnet})) { + $idx = ++$curcounter{$cursubnet}->{'group'}; + } else { + $idx = ++$curcounter{''}->{'group'}; + } + + add_dn_to_stack ("cn=group".$idx); + $curentry{'type'} = 'group'; + $curentry{'idx'} = $idx; +} + + +sub parse_pool +{ + local ($descr, $tmp); + + print_entry () if %curentry; + + $tmp = next_token (0); + parse_error () if !defined ($tmp); + parse_error () if !($tmp eq '{'); + + my $idx; + if(exists($curcounter{$cursubnet})) { + $idx = ++$curcounter{$cursubnet}->{'pool'}; + } else { + $idx = ++$curcounter{''}->{'pool'}; + } + + add_dn_to_stack ("cn=pool".$idx); + $curentry{'type'} = 'pool'; + $curentry{'idx'} = $idx; +} + + +sub parse_class +{ + local ($descr, $tmp); + + print_entry () if %curentry; + + $class = next_token (0); + parse_error () if !defined ($class); + + $tmp = next_token (0); + parse_error () if !defined ($tmp); + parse_error () if !($tmp eq '{'); + + $class =~ s/\"//g; + add_dn_to_stack ("cn=$class"); + $curentry{'type'} = 'class'; + $curentry{'class'} = $class; +} + + +sub parse_subclass +{ + local ($descr, $tmp); + + print_entry () if %curentry; + + $class = next_token (0); + parse_error () if !defined ($class); + + $subclass = next_token (0); + parse_error () if !defined ($subclass); + + $tmp = next_token (0); + parse_error () if !defined ($tmp); + parse_error () if !($tmp eq '{'); + + add_dn_to_stack ("cn=$subclass"); + $curentry{'type'} = 'subclass'; + $curentry{'class'} = $class; + $curentry{'subclass'} = $subclass; +} + + +sub parse_hwaddress +{ + local ($type, $hw, $tmp); + + $type = next_token (1); + parse_error () if !defined ($type); + + $hw = next_token (1); + parse_error () if !defined ($hw); + $hw =~ s/;$//; + + $curentry{'hwaddress'} = "$type $hw"; +} + + +sub parse_range +{ + local ($tmp, $str); + + $str = remaining_line (); + + if (!($str eq '')) + { + $str =~ s/;$//; + push (@{$curentry{'ranges'}}, $str); + } +} + + +sub parse_statement +{ + local ($token) = shift; + local ($str); + + if ($token eq 'option') + { + $str = remaining_line (); + push (@{$curentry{'options'}}, $str); + } + elsif($token eq 'failover') + { + $str = remaining_line (1); # take care on block + if($str =~ /[{]/) + { + my ($peername, @statements); + + parse_error() if($str !~ /^\s*peer\s+(.+?)\s+[{]\s*$/); + parse_error() if(($peername = $1) !~ /^\"?[^\"]+\"?$/); + + # + # failover config block found: + # e.g. 'failover peer "some-name" {' + # + if(not grep(/FaIlOvEr/i, @use)) + { + print STDERR "Warning: Failover config 'peer $peername' found!\n"; + print STDERR " Skipping it, since failover disabled!\n"; + print STDERR " You may try out --use=failover option.\n"; + } + + until($str =~ /[}]/ or $str eq "") + { + $str = remaining_line (1); + # collect all statements, except ending '}' + push(@statements, $str) if($str !~ /[}]/); + } + $failover{$peername} = [@statements]; + } + else + { + # + # pool reference to failover config is fine + # e.g. 'failover peer "some-name";' + # + if(not grep(/FaIlOvEr/i, @use)) + { + print STDERR "Warning: Failover reference '$str' found!\n"; + print STDERR " Skipping it, since failover disabled!\n"; + print STDERR " You may try out --use=failover option.\n"; + } + else + { + push (@{$curentry{'statements'}}, $token. " " . $str); + } + } + } + elsif($token eq 'zone') + { + $str = $token; + while($str !~ /}$/) { + $str .= ' ' . next_token (0); + } + push (@{$curentry{'statements'}}, $str); + } + elsif($token =~ /^(authoritative)[;]*$/) + { + push (@{$curentry{'statements'}}, $1); + } + else + { + $str = $token . " " . remaining_line (); + push (@{$curentry{'statements'}}, $str); + } +} + + +my $ok = GetOptions( + 'basedn=s' => \$basedn, + 'dhcpdn=s' => \$dhcpdn, + 'server=s' => \$server, + 'second=s' => \$second, + 'conf=s' => \$i_conf, + 'ldif=s' => \$o_ldif, + 'use=s' => \@use, + 'h|help|usage' => sub { usage(0); }, +); + +unless($server =~ /^\w+/) + { + usage(1, "invalid server name '$server'"); + } +unless($basedn =~ /^\w+=[^,]+/) + { + usage(1, "invalid base dn '$basedn'"); + } + +if($dhcpdn =~ /^cn=([^,]+)/i) + { + $dhcpcn = "$1"; + } +$second = '' if not defined $second; +unless($second eq '' or $second =~ /^cn=[^,]+\s*,\s*\w+=[^,]+/i) + { + if($second =~ /^cn=[^,]+$/i) + { + # relative DN 'cn=name' + $second = "$second, $basedn"; + } + elsif($second =~ /^\w+/) + { + # assume hostname only + $second = "cn=$second, $basedn"; + } + else + { + usage(1, "invalid secondary '$second'") + } + } + +usage(1) unless($ok); + +if($i_conf ne "" and -f $i_conf) + { + if(not open(STDIN, '<', $i_conf)) + { + print STDERR "Error: can't open conf file '$i_conf': $!\n"; + exit(1); + } + } +if($o_ldif ne "") + { + if(-e $o_ldif) + { + print STDERR "Error: output ldif name '$o_ldif' already exists!\n"; + exit(1); + } + if(not open(STDOUT, '>', $o_ldif)) + { + print STDERR "Error: can't open ldif file '$o_ldif': $!\n"; + exit(1); + } + } + + +print STDERR "Creating LDAP Configuration with the following options:\n"; +print STDERR "\tBase DN: $basedn\n"; +print STDERR "\tDHCP DN: $dhcpdn\n"; +print STDERR "\tServer DN: cn=$server, $basedn\n"; +print STDERR "\tSecondary DN: $second\n" + if(grep(/FaIlOvEr/i, @use) and $second ne ''); +print STDERR "\n"; + +my $token; +my $token_number = 0; +my $line_number = 0; +my %curentry; +my $cursubnet = ''; +my %curcounter = ( '' => { pool => 0, group => 0 } ); + +$current_dn = "$dhcpdn"; +$curentry{'descr'} = $dhcpcn; +$line = ''; +%failover = (); + +while (($token = next_token (1))) + { + if ($token eq '}') + { + print_entry () if %curentry; + if($current_dn =~ /.+?,\s*${dhcpdn}$/) { + # don't go below dhcpdn ... + remove_dn_from_stack (); + } + } + elsif ($token eq 'subnet') + { + parse_subnet (); + next; + } + elsif ($token eq 'shared-network') + { + parse_shared_network (); + next; + } + elsif ($token eq 'class') + { + parse_class (); + next; + } + elsif ($token eq 'subclass') + { + parse_subclass (); + next; + } + elsif ($token eq 'pool') + { + parse_pool (); + next; + } + elsif ($token eq 'group') + { + parse_group (); + next; + } + elsif ($token eq 'host') + { + parse_host (); + next; + } + elsif ($token eq 'hardware') + { + parse_hwaddress (); + next; + } + elsif ($token eq 'range') + { + parse_range (); + next; + } + else + { + parse_statement ($token); + next; + } + } + +close(STDIN) if($i_conf); +close(STDOUT) if($o_ldif); + +print STDERR "Done.\n"; + diff --git a/contrib/ms2isc/Registry.pm b/contrib/ms2isc/Registry.pm new file mode 100644 index 0000000..69e2413 --- /dev/null +++ b/contrib/ms2isc/Registry.pm @@ -0,0 +1,361 @@ +# Registry.pm
+# A perl module provided easy Windows Registry access
+#
+# Author: Shu-Min Chang
+#
+# Copyright(c) 2002 Intel Corporation. All rights reserved
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright notice
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution
+# 3. Neither the name of Intel Corporation nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INTEL CORPORATION AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL CORPORATION OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO PROCUREMENT OF SUBSTITUE
+# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+# OF THE USE OF THIS SOFTWARE, EVEN IF ADVICED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+package Registry;
+use strict;
+use Win32API::Registry 0.21 qw( :ALL );
+
+
+###############################################################################
+
+#-----------------------------------------
+sub GetRegKeyVal($*) {
+ my ($FullRegPath, $value) = @_;
+#-----------------------------------------
+# Purpose: uses Win32API to get registry information from a given server
+#
+# WARNING: this procedure is VERY Win32 specific, you'll need a Win32 manual
+# to figure out why something is done.
+# input: $FullRegPath: a MS specific way of fully qualifying a registry path
+# \\Server\RootKey\Path\ValueName
+# output: *value: the value of the registry key of $FullRegPath
+#
+
+ my ($RemoteMachine, $RootKey, $RegPath, $KeyName, $i);
+
+#print "in sub:GetRegKeyVal:Parameters:", @_, "\n";
+
+ # Check the for valid fully qualified registry path
+ return -1 if (! ($FullRegPath =~ /\\.+\\.+/)) && (!($FullRegPath =~ /\\\\.+\\.+\\.+/));
+
+
+ $RemoteMachine = (index($FullRegPath, "\\\\") == $[ ? substr($FullRegPath, $[+2, index($FullRegPath, "\\", $[+2)-2):0);
+
+#print "RemoteMachine = $RemoteMachine\n";
+
+ $i = $RemoteMachine ? $[+3+length($RemoteMachine) : $[+1;
+ $RootKey = substr ($FullRegPath, $i, index($FullRegPath, "\\", $i)-$i);
+
+ $KeyName = $FullRegPath;
+ $KeyName =~ s/.*\\(.+)/$1/;
+#print "KeyName = $KeyName\n";
+
+ $i = index($FullRegPath, $RootKey, $[+length($RemoteMachine)) + $[ + length($RootKey)+1;
+ $RegPath = substr ($FullRegPath, $i, length($FullRegPath) - length($KeyName) -$i - 1);
+#print "RegPath = $RegPath\n";
+
+ my ($RootKeyHandle, $handle, $key, $type);
+
+ if ($RemoteMachine) {
+ $RootKeyHandle = regConstant($RootKey);
+
+ if (!RegConnectRegistry ($RemoteMachine, $RootKeyHandle, $handle)) {
+ $$value = regLastError();
+ return -2;
+ }
+ } else { # not valid actually because I can't find the mapping table of default
+ # local handle mapping. Should always pass in the Machine name to use for now
+ $handle = $RootKey;
+ }
+
+ if (!RegOpenKeyEx ($handle, $RegPath, 0, KEY_READ, $key)) {
+ $$value = regLastError();
+#print "regLastError = $$value\n";
+ return -3;
+ }
+ if (!RegQueryValueEx( $key, $KeyName, [], $type, $$value, [] )) {
+ $$value = regLastError();
+#print "regLastError = $$value\n";
+ return -4;
+ }
+
+#print "RegType=$type\n"; # Perl doesn't fetch type, at this in this
+ # ActiveState 5.6.0 that I'm using
+#print "RegValue=$$value\n";
+ RegCloseKey ($key);
+ RegCloseKey ($handle);
+
+ return 0;
+}
+
+###############################################################################
+
+#-----------------------------------------
+sub GetRegSubkeyList($*) {
+ my ($FullKeyRegPath, $Subkeys) = @_;
+#-----------------------------------------
+# Purpose: uses Win32API to get registry subkey list from a given server
+#
+# WARNING: this procedure is VERY Win32 specific, you'll need a Win32 manual
+# to figure out why something is done.
+# input: $FullKeyRegPath: a MS specific way of fully qualifying a registry path
+# \\Server\RootKey\Path\KeyName
+# output: *Subkeys: the list of subkeys in array of the registry key of
+# $FullKeyRegPath
+#
+
+ my ($RemoteMachine, $RootKey, $RegPath, $KeyName, $i);
+
+#print "in sub:GetRegSubkeyList:Parameters:", @_, "\n";
+
+ # Check the for valid registry key path
+ return -1 if (! ($FullKeyRegPath =~ /\\.+\\.+/)) && (!($FullKeyRegPath =~ /\\\\.+\\.+\\.+/));
+
+
+ $RemoteMachine = (index($FullKeyRegPath, "\\\\") == $[ ? substr($FullKeyRegPath, $[+2, index($FullKeyRegPath, "\\", $[+2)-2):0);
+
+#print "RemoteMachine = $RemoteMachine\n";
+
+ $i = $RemoteMachine ? $[+3+length($RemoteMachine) : $[+1;
+ $RootKey = substr ($FullKeyRegPath, $i, index($FullKeyRegPath, "\\", $i)-$i);
+
+ $i = index($FullKeyRegPath, $RootKey, $[+length($RemoteMachine)) + $[ + length($RootKey)+1;
+ $RegPath = substr ($FullKeyRegPath, $i);
+
+#print "RegPath = $RegPath\n";
+
+ my ($RootKeyHandle, $handle, $key, $type);
+
+ if ($RemoteMachine) {
+ $RootKeyHandle = regConstant($RootKey);
+
+ if (!RegConnectRegistry ($RemoteMachine, $RootKeyHandle, $handle)) {
+ @$Subkeys[0]= regLastError();
+ return -2;
+ }
+ } else { # not valid actually because I can't find the mapping table of default
+ # local handle mapping. Should always pass in the Machine name to use for now
+ $handle = $RootKey;
+ }
+
+ if (!RegOpenKeyEx ($handle, $RegPath, 0, KEY_READ, $key)) {
+ @$Subkeys[0] = regLastError();
+#print "regLastError = @$Subkeys[0]\n";
+ return -3;
+ }
+
+ my $tmp;
+ # For some reason, the regLastError() stays at ERROR_NO_MORE_ITEMS
+ # in occasional call sequence, so I'm resetting the error code
+ # before entering the loop
+ regLastError(0);
+ for ($i=0; regLastError()==regConstant("ERROR_NO_MORE_ITEMS"); $i++) {
+#print "\nERROR: error enumumerating reg\n";
+ if (RegEnumKeyEx ($key, $i, $tmp, [], [], [], [], [])) {
+ @$Subkeys[$i] = $tmp;
+ }
+ }
+
+#print "RegType=$type\n";
+#print "RegValue=@$Subkeys\n";
+ RegCloseKey ($key);
+ RegCloseKey ($handle);
+
+ return 0;
+}
+
+#####################################################
+
+sub ExtractOptionIps ($) {
+ my ($MSDHCPOption6Value) = @_;
+ my @ip;
+# purpose: DHCP registry specific; to return the extracted IP addresses from
+# the input variable
+# input:
+# $MSDHCPOption6Value: Option 6 was used to develop, but it works for any
+# other options of the same datatype.
+# output: none
+# return:
+# @ip: an arry of IP addresses in human readable format.
+
+
+ # First extract the size of the option
+ my ($byte, $size, $ind1, $ind2, @octet) = unpack("VVVV", $MSDHCPOption6Value);
+# print "byte = $byte\nsize=$size\nind1=$ind1\nind2=$ind2\n";
+
+ # Calculate total number of bytes that IP addresses occupy
+ my $number = $size * $ind1;
+ ($byte, $size, $ind1, $ind2, @octet) = unpack("VVVVC$number", $MSDHCPOption6Value);
+
+ for (my $i=0; $i<$#octet; $i=$i+4) {
+ $ip[$i/4] = "$octet[$i+3]\.$octet[$i+2]\.$octet[$i+1]\.$octet[$i]";
+ }
+
+ return @ip;
+}
+
+#####################################################
+
+sub ExtractOptionStrings ($) {
+ my ($MSDHCPOption15Value) = @_;
+ my @string;
+# purpose: DHCP registry specific; to return the extracted string from
+# the input variable
+# input:
+# $MSDHCPOption15Value: Option 15 was used to develop, but it works for any
+# other options of the same datatype.
+# output: none
+# return:
+# @string: an arry of strings in human readable format.
+
+
+ # First extract the size of the option
+ my ($byte, $start, $ind1, $ind2, $size, @data) = unpack("VVVVV", $MSDHCPOption15Value);
+# print "byte = $byte\nstart=$start\nind1=$ind1\nind2=$ind2\nsize=$size\n";
+
+ # Calculate total number of bytes that IP addresses occupy
+ my $number = $size * $ind1;
+ ($byte, $start, $ind1, $ind2, $size, @data) = unpack("VVVVVC$number", $MSDHCPOption15Value);
+
+ for (my $i=0; $i<$ind1; $i++) {
+ # actually this is only programmed to do one string, until I see
+ # example of how the multiple strings are represented, I don't have a
+ # guess to how to program them properly.
+ for (my $j=0; $j<$#data & $data[$j]!=0; $j+=2) {
+ $string[$i] = $string[$i].chr($data[$j]);
+ }
+ }
+
+ return @string;
+}
+
+#####################################################
+
+sub ExtractOptionHex ($) {
+ my ($MSDHCPOption46Value) = @_;
+ my @Hex;
+# purpose: DHCP registry specific; to return the extracted hex from the input
+# variable
+# input:
+# $MSDHCPOption46Value: Option 46 was used to develop, but it works for any
+# other options of the same datatype.
+# output: none
+# return:
+# @Hex: an arry of hex strings in human readable format.
+ my $Temp;
+
+
+ # First extract the size of the option
+ my ($byte, $unknown, $ind1, $ind2, @data) = unpack("VVVV", $MSDHCPOption46Value);
+# print "byte=$byte\nunknown=$unknown\nind1=$ind1\nind2=$ind2\n";
+
+ # Calculate total number of bytes that IP addresses occupy
+ my $number = $byte - 15;
+ ($byte, $unknown, $ind1, $ind2, @data) = unpack("VVVVC$number", $MSDHCPOption46Value);
+
+# printf "data=%4x\n", $data[0];
+
+ for (my $i=0; $i<$ind1; $i++) {
+ # actually this is only programmed to do one Hex, until I see
+ # example of how the multiple Hexes are represented, I don't have a
+ # guess to how to program them properly.
+ for (my $j=3; $j>=0; $j--) {
+ $Hex[$i] = $Hex[$i].sprintf ("%x", $data[$j+$i*4]);
+ }
+ }
+
+ return @Hex;
+}
+
+#####################################################
+
+sub ExtractExclusionRanges ($) {
+ my ($MSDHCPExclusionRanges) = @_;
+ my @RangeList;
+# purpose: DHCP registry specific; to return the extracted exclusion ranges
+# from the input variable
+# input:
+# $MSDHCPExclusionRanges: Exclusion range as DHCP server returns them
+# output: none
+# return:
+# @RangeList: an arry of paird IP addresses strings in human readable format.
+
+
+ # First extract the size of the option
+ my ($paircount, @data) = unpack("V", $MSDHCPExclusionRanges);
+# print "paircount = $paircount\n";
+
+ # Calculate total number of bytes that IP addresses occupy
+# my $number = $paircount * 4*2;
+# ($paircount, @data) = unpack("VC$number", $MSDHCPExclusionRanges);
+#
+# for (my $i=0; $i<$#data; $i=$i+4) {
+# $ip[$i/4] = "$data[$i+3]\.$data[$i+2]\.$data[$i+1]\.$data[$i]";
+# }
+#
+ my $number = $paircount * 2;
+ ($paircount, @data) = unpack("VL$number", $MSDHCPExclusionRanges);
+
+ for (my $i=0; $i<=$#data; $i++) {
+ $RangeList[$i] = pack ("L", $data[$i]);
+# print "extracted", ExtractIp ($RangeList[$i]), "\n";
+ }
+
+ return @RangeList;
+}
+#####################################################
+
+sub ExtractIp ($) {
+ my ($octet) = @_;
+# purpose: to return the registry saved IP address in a readable form
+# input:
+# $octet: a 4 byte data storing the IP address as the registry save it as
+# output: none
+# return: anonymous variable of a string of IP address
+
+ my (@data) = unpack ("C4", $octet);
+
+ return "$data[3]\.$data[2]\.$data[1]\.$data[0]";
+
+}
+#####################################################
+
+sub ExtractHex ($) {
+ my ($HexVal) = @_;
+ my @Hex;
+# purpose: to return the registry saved hex number in a readable form
+# input:
+# $octet: a 4 byte data storing the hex number as the registry save it as
+# output: none
+# return:
+# $Hex: string of hex digit
+
+
+ # First extract the size of the option
+ my (@data) = unpack("C4", $HexVal);
+
+ for (my $i=3; $i>=0; $i--) {
+ $Hex[0] = $Hex[0] . sprintf ("%x", $data[$i]);
+ }
+
+ return @Hex;
+}
+1;
diff --git a/contrib/ms2isc/ms2isc.pl b/contrib/ms2isc/ms2isc.pl new file mode 100644 index 0000000..da3e10f --- /dev/null +++ b/contrib/ms2isc/ms2isc.pl @@ -0,0 +1,634 @@ +#set ts=3
+#
+# ms2isc.pl
+# MS NT4 DHCP to ISC DHCP Configuration Migration Tool
+#
+# Author: Shu-Min Chang
+#
+# Copyright(c) 2003 Intel Corporation. All rights reserved
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright notice
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution
+# 3. Neither the name of Intel Corporation nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INTEL CORPORATION AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL CORPORATION OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO PROCUREMENT OF SUBSTITUE
+# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+# OF THE USE OF THIS SOFTWARE, EVEN IF ADVICED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+use strict;
+use Socket;
+use Getopt::Std;
+use Filehandle;
+use Registry; # Custom Perl Module to make Registry access easier.
+
+my $usage = << 'ENDOFHELP';
+
+Purpose: A Perl Script converting MS NT4 DHCP configuration to ISC DHCP3
+configuration file by reading NT4's registry.
+
+Requires: Registry.pm and ActiveState 5.6.0
+
+Usage: $ARGV -s <Srv> -o <Out> [-p <Pri> [-k <key>]] [-f <Fo>]
+
+ <Srv> Server IP or name for NT4 DHCP server to fetch the configuration from.
+ <Out> Output filename for the configuration file.
+ <Pri> Primary DNS server name for sending the dynamic DNS update to.
+ <Key> Key name for use in updating the dynamic DNS zone.
+ <Fo> Failover peer name shared with the DHCP partner.
+
+Essentially the <Srv> needs to be an NT4 (3.x should work but not tested) which
+you should have registry read access to. You must run this script from a
+Windows machine because of the requirement to access the registry.
+
+The <Pri> is optional parameter for desginating the dynamic DNS update if
+missing then the "zone" section of the declaration will be skipped. The <Key>
+is needed if you've configured your DNS zone with a key, in addition, you'll
+need to define that key in this DHCP configuration file elsewhere manually,
+read the DHCP Handbook to figure out what you need to define.
+
+The <Fo> specifies the fail-over peer name in the pool section, you'll need to
+define additional detail elsewhere manually, again read the DHCP handbook.
+
+NOTE: the program only knows of the following global and subnet options:
+ 3, 6, 15, 28, 44, and 46
+
+ If it runs into options other than the known ones, it will quit. You
+ may fix this by modifying the following procedures:
+ GetGlobalOptions
+ GetScopes
+ PrintSubnetConfig
+
+ In addition, the resulting subnets configuration will have the "deny
+ dynamic bootp clients" you should take them out if that's not what you
+ want :).
+
+ Finally, as the parameter structures implied, it is assumed that you
+ want the same zone primary and update key for all zones and that the
+ same failover is to be applied to all the pools. Furthermore the
+ subnet zones are all assumed to be class C delineated, but if you
+ happend to be delegated at the class B level, this will work fine too.
+
+Author: Shu-Min Chang <smchang@yahoo.com>
+
+Copyright: Please read the top of the source code
+
+Acknowledgement:
+ Brian L. King for coding help, Douglas A. Darrah for testing, and James E.
+Pressley for being the DHCP reference book :).
+
+Usage: $ARGV -s <Srv> -o <Out> [-p <Pri> [-k <key>]] [-f <Fo>]
+
+Version: 1.0.1
+
+ENDOFHELP
+
+###################### Begin Main Program ####################################
+
+ my (%opts, %GlobalOptions, %SuperScopes, %Scopes);
+
+ ### Get parameters and make sure that they meet the require/optoinal criteria
+ getopts('s:o:p:k:f:', \%opts) or die $usage;
+ ($opts{s} and $opts{o}) or die $usage;
+ if ($opts{k}) { $opts{p} or die $usage; }
+
+ ### Read all the registry stuff into the memory
+ %GlobalOptions = GetGlobalOptions($opts{s});
+ %SuperScopes = GetSuperScope($opts{s});
+ %Scopes = GetScopes ($opts{s});
+
+ ### Process and print out to the output file
+ my ($outfile, $i, $j, @Domains);
+
+ $outfile = new FileHandle "> $opts{o}";
+ if (!defined $outfile) {
+ die "Can't open file: $opts{o}: $!";
+ }
+
+ for $i (keys %SuperScopes) {
+ print $outfile "\n##############################################################\n";
+ my ($Scopename) = $i;
+ $Scopename =~ s/ //g;
+ print $outfile "shared-network $Scopename {\n";
+ foreach $j (@{$SuperScopes{$i}}) {
+ PrintSubnetConfig($outfile, \%GlobalOptions, \%{$Scopes{$j}}, $j, "\t", $opts{f});
+ InsertIfUnique (\@Domains, $Scopes{$j}{domain}) if exists $Scopes{$j}{domain};
+ delete $Scopes{$j};
+ }
+ print $outfile "}\n";
+ if ($opts{p} or $opts{k}) {
+ foreach $j (@{$SuperScopes{$i}}) {
+ PrintSubnetUpdate($outfile, $j, $opts{p}, $opts{k});
+ }
+ }
+ }
+
+ for $i (keys %Scopes) {
+ print $outfile "\n##############################################################\n";
+ PrintSubnetConfig($outfile, \%GlobalOptions, \%{$Scopes{$i}}, $i, "", $opts{f});
+ if ($opts{p} or $opts{k}) { PrintSubnetUpdate($outfile, $i, $opts{p}, $opts{k}); }
+ InsertIfUnique (\@Domains, $Scopes{$i}{domain}) if exists $Scopes{$i}{domain};
+ }
+
+ if ($opts{p} or $opts{k}) {
+ InsertIfUnique (\@Domains, $GlobalOptions{domain}) if exists $GlobalOptions{domain};
+ for $i (@Domains) {
+ PrintDomainUpdate($outfile, $i, $opts{p}, $opts{k});
+ }
+ }
+
+ undef ($outfile);
+ print "Done.\n";
+ exit();
+
+################################## End Main Program ###########################
+
+
+
+
+
+######################################################################
+sub InsertIfUnique ($$) {
+ my ($Array, $data) = @_;
+# purpose: insert $data into array @{$Array} iff the data is not in there yet
+# input:
+# $data: scalar data to be added to the @{$Array} if unique
+# $Array: reference of the Array to compare the uniqueness of the $data
+# output:
+# $Array: reference of the array with the resulting array.
+# return: none
+
+ my ($i);
+
+ for ($i=0; $i<=$#{$Array} && ${$Array}[$i] ne $data; $i++) { }
+
+ if ($i > $#{$Array}) {
+ ${$Array}[$i] = $data;
+ }
+}
+######################################################################
+sub PrintDomainUpdate ($$$$) {
+ my ($outfile, $Domain, $DDNSServer, $key) = @_;
+# purpose: print out the foward domain zone update declaration
+# input:
+# $outfile: filehandle of the file to write the output to
+# $Domain: a string representing the forward domain
+# $DDNSServer: a string of the DNS server accepting the DDNS update
+# $key: a string representing the key used to update the zone
+# output: none
+# return: none
+#
+
+ print $outfile "zone $Domain {\n";
+ print $outfile "\tprimary $DDNSServer;\n";
+ !$key or print $outfile "\tkey $key;\n";
+ print $outfile "}\n";
+
+}
+######################################################################
+sub PrintSubnetUpdate ($$$$) {
+ my ($outfile, $Subnet, $DDNSServer, $key) = @_;
+# purpose: print out the reverse domain zone update declaration
+# input:
+# $outfile: filehandle of the file to write the output to
+# $Subnet: a string representing the subnet in the form 1.2.3.4
+# $DDNSServer: a string of the DNS server accepting the DDNS update
+# $key: a string representing the key used to update the zone
+# output: none
+# return: none
+#
+
+ my ($Reverse);
+
+ $_ = join (".", reverse(split(/\./, $Subnet)));
+ m/\d*\.(.*)/;
+ $Reverse = $1;
+ print $outfile "zone $Reverse.in-addr.arpa. {\n";
+ print $outfile "\tprimary $DDNSServer;\n";
+ !$key or print $outfile "\tkey $key;\n";
+ print $outfile "}\n";
+
+}
+######################################################################
+sub PrintSubnetConfig ($$$$$$) {
+ my ($outfile, $GlobalOptions, $Scope, $Subnet, $prefix, $failover) = @_;
+# purpose: print out the effective scope configuration for one subnet as
+# derived from the global and scope options.
+# input:
+# $outfile: filehandle of the file to write the output to
+# $GlobalOptions: refernce to the hashed variable from GetGlobalOptions
+# $Scopes: reference to the hashed variable of the subnet in interest
+# $Subnet: string variable of the subnet being processed
+# $prefix: string to be printed before each line (designed for tab)
+# $failover: string to be used for the "failover peer" line
+# output: none
+# return: none
+#
+ my ($pound) = ( ${$Scope}{disable}? "#".$prefix : $prefix);
+ print $outfile $pound, "subnet $Subnet netmask ${$Scope}{mask} {\n";
+ print $outfile "$prefix# Name: ${$Scope}{name}\n";
+ print $outfile "$prefix# Comment: ${$Scope}{comment}\n";
+ if (exists ${$Scope}{routers}) {
+ print $outfile $pound, "\toption routers @{${$Scope}{routers}};\n";
+ } elsif (exists ${$GlobalOptions}{routers}) {
+ print $outfile $pound, "\toption routers @{${$GlobalOptions}{routers}};\t# NOTE: obtained from global option, bad practice detected\n";
+ } else {
+ print $outfile "### WARNING: No router was found for this subnet!!! ##########\n";
+ }
+
+ if (exists ${$Scope}{dnses}) {
+ print $outfile $pound, "\toption domain-name-servers ", join(",", @{${$Scope}{dnses}}), ";\n";
+ } elsif (exists ${$GlobalOptions}{dnses}) {
+ print $outfile $pound, "\toption domain-name-servers ", join(",", @{${$GlobalOptions}{dnses}}), ";\n";
+ }
+
+ if (exists ${$Scope}{domain}) {
+ print $outfile $pound, "\toption domain-name \"${$Scope}{domain}\";\n";
+ } elsif (exists ${$GlobalOptions}{domain}) {
+ print $outfile $pound, "\toption domain-name \"${$GlobalOptions}{domain}\";\n";
+ }
+
+ if (exists ${$Scope}{broadcast}) {
+ print $outfile $pound, "\toption broadcast-address ${$Scope}{broadcast};\n";
+ } elsif (exists ${$GlobalOptions}{broadcast}) {
+ print $outfile $pound, "\toption broadcast-address ${$GlobalOptions}{broadcast};\n";
+ }
+
+ if (exists ${$Scope}{winses}) {
+ print $outfile $pound, "\toption netbios-name-servers ", join(",", @{${$Scope}{winses}}), ";\n";
+ } elsif (exists ${$GlobalOptions}{winses}) {
+ print $outfile $pound, "\toption netbios-name-servers ", join(",", @{${$GlobalOptions}{winses}}), ";\n";
+ }
+
+ if (exists ${$Scope}{winstype}) {
+ print $outfile $pound, "\toption netbios-node-type ${$Scope}{winstype};\n";
+ } elsif (exists ${$GlobalOptions}{winstype}) {
+ print $outfile $pound, "\toption netbios-node-type ${$GlobalOptions}{winstype};\n"
+ }
+
+ print $outfile $pound, "\tdefault-lease-time ${$Scope}{leaseduration};\n";
+ print $outfile $pound, "\tpool {\n";
+ for (my $r=0; $r<=$#{${$Scope}{ranges}}; $r+=2) {
+ print $outfile $pound, "\t\trange ${$Scope}{ranges}[$r] ${$Scope}{ranges}[$r+1];\n";
+ }
+ !$failover or print $outfile $pound, "\t\tfailover peer \"$failover\";\n";
+ print $outfile $pound, "\t\tdeny dynamic bootp clients;\n";
+ print $outfile $pound, "\t}\n";
+ print $outfile $pound, "}\n";
+}
+
+######################################################################
+sub GetScopes ($) {
+ my ($Server) = @_;
+ my (%Scopes);
+# purpose: to return NT4 server's scope configuration
+# input:
+# $Server: string of the valid IP or name of the NT4 server
+# output: none
+# return:
+# %Scope: hash of hash of hash of various data types to be returned of the
+# following data structure
+# $Scope{<subnet>}{disable} => boolean
+# $Scope{<subnet>}{mask} => string (e.g. "1.2.3.255")
+# $Scope{<subnet>}{name} => string (e.g "Office Subnet #1")
+# $Scope{<subnet>}{comment} => string (e.g. "This is a funny subnet")
+# $Scope{<subnet>}{ranges} => array of paired inclusion IP addresses
+# (e.g. "1.2.3.1 1.2.3.10 1.2.3.100 10.2.3.200
+# says that we have 2 inclusion ranges of
+# 1-10 and 100-200)
+# $Scopes{<subnet>}{routers} => array of IP address strings
+# $Scopes{<subnet>}{dnses} => array of IP address/name string
+# $Scopes{<subnet>}{domain} > string
+# $Scopes{<subnet>}{broadcast} => string
+# $Scopes{<subnet>}{winses} => array of IP addresses/name string
+# $Scopes{<subnet>}{winstype} => integer
+# $Scopes{<subnet>}{leaseduration} => integer
+
+ my ($RegVal, @Subnets, @Router, $SubnetName, $SubnetComment, @SubnetOptions, @SRouter, @SDNSServers, @SDomainname, @SWINSservers, @SNetBIOS, @SLeaseDuration, @SSubnetState, @SExclusionRanges, @SSubnetAddress, @SSubnetMask, @SFirstAddress, $SStartAddress, $SEndAddress, @InclusionRanges, @SBroadcastAddress);
+
+ print "Getting list of subnets\n";
+ if (Registry::GetRegSubkeyList ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets", \@Subnets)) {
+ die "Unable to obtain a list of subnets from the server!\n";
+ }
+
+ for (my $i=0; $i<=$#Subnets; $i++) {
+ print "\t Fetching Subnet $Subnets[$i] (",$i+1, "/", $#Subnets+1, "): ";
+
+ print ".";
+ if (!Registry::GetRegSubkeyList ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\IpRanges", \@SFirstAddress)) {
+ # Don't know why MS has a tree for this, but as far
+ # as I can tell, only one subtree will ever come out of
+ # this, so I'm skipping the 'for' loop
+
+ print ".";
+ if (!Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\IpRanges\\$SFirstAddress[0]\\StartAddress", \$RegVal)) {
+ $SStartAddress = $RegVal;
+ }
+ print ".";
+ if (!Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\IpRanges\\$SFirstAddress[0]\\EndAddress", \$RegVal)) {
+ $SEndAddress = $RegVal;
+ }
+# print "\n\tInclusion Range: ", Registry::ExtractIp($SStartAddress), " - ", Registry::ExtractIp($SEndAddress),"\n";
+
+ } else {
+ die "\n\n# Error Getting Inclusion Range FirstAddress!!!\n\n";
+ }
+
+ if (!Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\ExcludedIpRanges", \$RegVal)) {
+ @SExclusionRanges = Registry::ExtractExclusionRanges($RegVal);
+
+# for (my $j=2; $j<=$#SExclusionRanges; $j+=2) {
+# if (unpack("L",$SExclusionRanges[$j]) < unpack("L",$SExclusionRanges[$j-2])) {
+# print ("\n******** Subnet exclusion ranges out of order ********\n");
+# }
+# }
+
+ @SExclusionRanges = sort(@SExclusionRanges);
+
+# print "\n\tExclusion Ranges: ";
+# for (my $j=0; $j<=$#SExclusionRanges; $j+=2) {
+# print "\n\t\t",Registry::ExtractIp($SExclusionRanges[$j])," - ",Registry::ExtractIp($SExclusionRanges[$j+1]);
+# }
+
+ }
+ @InclusionRanges = FindInclusionRanges ($SStartAddress, $SEndAddress, @SExclusionRanges);
+
+ print ".";
+ if (!Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\SubnetName", \$RegVal)) {
+ $SubnetName = $RegVal;
+# print "\n\tSubnetName: $SubnetName";
+ }
+
+ print ".";
+ if (!Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\SubnetComment", \$RegVal)) {
+ $SubnetComment = $RegVal;
+# print "\n\tSubnetComment: $SubnetComment";
+ }
+ print ".";
+ if (!Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\SubnetAddress", \$RegVal)) {
+ @SSubnetAddress = Registry::ExtractIp($RegVal);
+# print "\n\tSubnetAddress: $SSubnetAddress[0]";
+ }
+ print ".";
+ if (!Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\SubnetMask", \$RegVal)) {
+ @SSubnetMask = Registry::ExtractIp($RegVal);
+# print "\n\tSubnetMask: $SSubnetMask[0]";
+ }
+
+ print ".";
+ if (!Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\SubnetState", \$RegVal)) {
+ @SSubnetState = Registry::ExtractHex ($RegVal);
+# print "\n\tSubnetState = $SSubnetState[0]";
+ }
+
+ $Scopes{$Subnets[$i]}{disable} = hex($SSubnetState[0]) ? 1 : 0;
+ $Scopes{$Subnets[$i]}{mask} = $SSubnetMask[0];
+ $Scopes{$Subnets[$i]}{name} = $SubnetName;
+ $Scopes{$Subnets[$i]}{comment} = $SubnetComment;
+ for (my $r=0; $r<=$#InclusionRanges; $r++) {
+ $Scopes{$Subnets[$i]}{ranges}[$r] = Registry::ExtractIp($InclusionRanges[$r]);
+ }
+
+################## Get scope options
+
+ my (@SubnetOptionsList);
+
+ print "\n\t\tOptions:";
+ if (Registry::GetRegSubkeyList ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\SubnetOptions", \@SubnetOptionsList)) {
+ die "Unable to get subnet options list for $Subnets[$i]!\n";
+ }
+
+ for (my $j=0; $j<=$#SubnetOptionsList; $j++) {
+ print ".";
+ if (!Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\Subnets\\$Subnets[$i]\\SubnetOptions\\$SubnetOptionsList[$j]\\OptionValue", \$RegVal)) {
+ for ($SubnetOptionsList[$j]) {
+ /003/ and do {
+# @SRouter = Registry::ExtractOptionIps($RegVal);
+ $Scopes{$Subnets[$i]}{routers} = [Registry::ExtractOptionIps($RegVal)];
+ last;
+ };
+ /006/ and do {
+ @SDNSServers = Registry::ExtractOptionIps($RegVal);
+ for (my $d=0; $d<=$#SDNSServers; $d++) {
+ my ($ipname, $rest) = gethostbyaddr(pack("C4", split(/\./, $SDNSServers[$d])), &AF_INET);
+ $Scopes{$Subnets[$i]}{dnses}[$d] = $ipname ? $ipname : $SDNSServers[$d];
+ }
+ last;
+ };
+ /015/ and do {
+ @SDomainname = Registry::ExtractOptionStrings($RegVal);
+ $Scopes{$Subnets[$i]}{domain} = $SDomainname[0];
+ last;
+ };
+ /028/ and do {
+ @SBroadcastAddress = Registry::ExtractOptionIps($RegVal);
+ $Scopes{$Subnets[$i]}{broadcast} = $SBroadcastAddress[0];
+ last;
+ };
+ /044/ and do {
+ @SWINSservers = Registry::ExtractOptionIps($RegVal);
+ for (my $w=0; $w<=$#SWINSservers; $w++) {
+ my ($ipname, $rest) = gethostbyaddr(pack("C4", split(/\./, $SWINSservers[$w])), &AF_INET);
+ $Scopes{$Subnets[$i]}{winses}[$w] = $ipname ? $ipname : $SWINSservers[$w];
+ }
+ last;
+ };
+ /046/ and do {
+ @SNetBIOS = Registry::ExtractOptionHex($RegVal);
+ $Scopes{$Subnets[$i]}{winstype} = hex($SNetBIOS[0]);
+ last;
+ };
+ /051/ and do {
+ @SLeaseDuration = Registry::ExtractOptionHex($RegVal);
+ $Scopes{$Subnets[$i]}{leaseduration} = hex($SLeaseDuration[0]);
+ last;
+ };
+ die "This program does not recognize subnet option \#$SubnetOptionsList[$j] yet!\n"
+ }
+ } else {
+ die "Unable to obtain option SubnetOptionsList[$j] from $Subnets[$i], most likely a registry problem!\n"
+ }
+ }
+ print "\n";
+ }
+
+ return %Scopes;
+}
+
+######################################################################
+sub FindInclusionRanges ($$@) {
+ my ($StartAddress, $EndAddress, @ExclusionRanges) = @_;
+# Purpose: to calculate and return the DHCP inclusion ranges out of
+# data provided by the NT4 DHCP server
+# input: $StartAddress:
+# $EndAddress:
+# @ExclusionRanges
+# output: none
+# return: An arry of IP address pair representing the inclusion ranges
+# in the native registry format.
+#
+
+ my ($SA, $EA, @ER);
+ $SA = unpack("L", $StartAddress);
+ $EA = unpack("L", $EndAddress);
+ @ER = @ExclusionRanges;
+ for (my $i=0; $i<=$#ER; $i++) {
+ $ER[$i] = unpack ("L", $ER[$i]);
+ }
+
+ my @InclusionRanges;
+
+
+ $InclusionRanges[0] = $SA;
+ $InclusionRanges[1] = $EA;
+
+ for (my $i=0; $i<=$#ER; $i+=2) {
+ if ($ER[$i] == $InclusionRanges[$#InclusionRanges-1]) {
+ $InclusionRanges[$#InclusionRanges-1] = $ER[$i+1] + 1;
+ }
+ if ($ER[$i] > $InclusionRanges[$#InclusionRanges-1]) {
+ $InclusionRanges[$#InclusionRanges] = $ER[$i]-1;
+ }
+ if (($ER[$i+1] > $InclusionRanges[$#InclusionRanges]) &&
+ ($ER[$i+1] != $EA)) {
+ $InclusionRanges[$#InclusionRanges+1] = $ER[$i+1] + 1;
+ $InclusionRanges[$#InclusionRanges+1] = $EA;
+ }
+ if ($InclusionRanges[$#InclusionRanges] < $InclusionRanges[$#InclusionRanges-1]) {
+ $#InclusionRanges -= 2;
+ }
+ }
+
+ for (my $i=0; $i<=$#InclusionRanges; $i++) {
+ $InclusionRanges[$i] = pack("L", $InclusionRanges[$i]);
+ # print "Inclusion: ", Registry::ExtractIp($InclusionRanges[$i]), "\n";
+ }
+ return @InclusionRanges;
+}
+
+####################################################################
+sub GetSuperScope ($) {
+ my ($Server) = @_;
+ my (%SuperScopes);
+#
+# purpose: gets the Superscope list from the given server
+# input:
+# $Server: string of the valid IP address or name of the NT4 server
+# ouput: none
+# return:
+# %SuperScopes: hash of array subnets with the following data structure
+# $SuperScopes{<SuperscopeName>} => array of sunbets
+#
+ my (@SuperScopeNames, @SCSubnetList);
+
+ print "Getting Superscope list: ";
+ if (!Registry::GetRegSubkeyList ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\SuperScope", \@SuperScopeNames)) {
+ for (my $i=0; $i<=$#SuperScopeNames; $i++) {
+ print ".";
+ if (!Registry::GetRegSubkeyList ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\SuperScope\\$SuperScopeNames[$i]", \@SCSubnetList)) {
+ $SuperScopes{$SuperScopeNames[$i]} = [@SCSubnetList];
+ }
+ }
+ print "\n";
+ }
+
+ return %SuperScopes;
+}
+
+####################################################################
+sub GetGlobalOptions($) {
+ my ($Server) = @_;
+ my (%GlobalOptions);
+# purpose: to return NT4 server's global scope configuration
+# input:
+# $Server: string of the valid IP or name of the NT4 server
+# output: none
+# return:
+# %GlobalOptions: hash of hash of various data types to be returned of the
+# following data structure
+# $GlobalOptions{routers} => array of IP address strings
+# $GlobalOptions{dnses} => array of IP address/name string
+# $GlobalOptions{domain} > string
+# $GlobalOptions{broadcast} => string
+# $GlobalOptions{winses} => array of IP addresses/name string
+# $GlobalOptions{winstype} => integer
+
+ my ($RegVal, @temp, @GlobalOptionValues);
+
+ print "Getting Global Options: ";
+ if (Registry::GetRegSubkeyList ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Configuration\\GlobalOptionValues", \@GlobalOptionValues)) {
+ die "Unable to obtain GlobalOptionValues";
+ }
+
+ for (my $i=0; $i<=$#GlobalOptionValues; $i++) {
+ print ".";
+ if (Registry::GetRegKeyVal ("\\\\$Server\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\configuration\\globaloptionvalues\\$GlobalOptionValues[$i]\\optionvalue", \$RegVal)) {
+ die "Unable to retrive global option $GlobalOptionValues[$i]\n";
+ }
+
+
+ for ($GlobalOptionValues[$i]) {
+ /003/ and do {
+ @temp=Registry::ExtractOptionIps($RegVal);
+ $GlobalOptions{routers} = [@temp];
+ last;
+ };
+ /006/ and do {
+ # DNS Servers
+ @temp = Registry::ExtractOptionIps($RegVal);
+ for (my $d=0; $d<=$#temp; $d++) {
+ my ($ipname, $rest) = gethostbyaddr(pack("C4", split(/\./, $temp[$d])), &AF_INET);
+ $GlobalOptions{dnses}[$d] = $ipname ? $ipname : $temp[$d];
+ }
+ last;
+ };
+ /015/ and do {
+ # Domain Name
+ @temp = Registry::ExtractOptionStrings($RegVal);
+ $GlobalOptions{domain} = $temp[0];
+ last;
+ };
+ /028/ and do {
+ # broadcast address
+ @temp = Registry::ExtractOptionIps($RegVal);
+ $GlobalOptions{broadcast} = $temp[0];
+ last;
+ };
+ /044/ and do {
+ # WINS Servers
+ @temp = Registry::ExtractOptionIps ($RegVal);
+ $GlobalOptions{winses} = [@temp];
+ for (my $w=0; $w<=$#temp; $w++) {
+ my ($ipname, $rest) = gethostbyaddr(pack("C4", split(/\./, $temp[$w])), &AF_INET);
+ $GlobalOptions{winses}[$w] = $ipname ? $ipname : $temp[$w];
+ }
+ last;
+ };
+ /046/ and do {
+ # NETBIOS node type
+ @temp = Registry::ExtractOptionHex($RegVal);
+ $GlobalOptions{winstype} = hex($temp[0]);
+ last;
+ };
+ die "This program does not recgonize global option \#$GlobalOptionValues[$i] yet!\n"
+ }
+ }
+ print "\n";
+
+ return %GlobalOptions;
+}
diff --git a/contrib/ms2isc/readme.txt b/contrib/ms2isc/readme.txt new file mode 100644 index 0000000..862d010 --- /dev/null +++ b/contrib/ms2isc/readme.txt @@ -0,0 +1,15 @@ +Copyright: please read the top of the source code.
+
+Usage:
+Objective: please read the help screen by executing the program without any
+ parameter.
+
+Revision:
+SMC: Shu-Min Chang
+
+Who When What
+--- ------ --------------------------------------------------------------------
+SMC 021107 Initial release Version 1.0 to ISC DHCP repository
+SMC 030129 Fixed inclusion range calculation by sorting exclusion before
+ passing to FindInclusionRanges
+SMC 030228 release 1.0.1 to ISC DHCP repository
diff --git a/contrib/sethostname.sh b/contrib/sethostname.sh new file mode 100644 index 0000000..7088c00 --- /dev/null +++ b/contrib/sethostname.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +# This script can be installed in /etc/dhclient-enter-hooks to set the client's +# hostname based either on the hostname that the DHCP server supplied or the +# hostname in whatever ptr record exists for the assigned IP address. + +if [ x$new_host_name = x ]; then + ptrname=`echo $new_ip_address \ + |sed -e \ + 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\4.\3.\2.\1.in-addr.arpa/'` + (echo "set type=ptr"; echo "$ptrname") |nslookup >/tmp/nslookup.$$ + set `sed -n -e "s/$ptrname[ ]*\(canonical \)*name *= *\(.*\)/\2 \1/p" \ + < /tmp/nslookup.$$` _ + if [ x$1 = x_ ]; then + new_host_name="" + else + if [ $# -gt 1 ] && [ x$2 = xcanonical ]; then + new_host_name=`sed -n -e "s/$1[ ]*name *= *\(.*\)/\1/p" \ + </tmp/nslookup.$$` + else + new_host_name=$1 + fi + fi + rm /tmp/nslookup.$$ +fi +if [ x$new_host_name != x ]; then + hostname $new_host_name +fi + diff --git a/contrib/solaris.init b/contrib/solaris.init new file mode 100644 index 0000000..2c79898 --- /dev/null +++ b/contrib/solaris.init @@ -0,0 +1,28 @@ +#!/bin/sh +# Contributed by Brian Murrell + +state=$1 + +set `who -r` +case $state in + +'start') + if [ $9 = "2" -o $9 = "3" ] + then + exit + fi + if [ -f @PREFIX@/sbin/dhcpd ]; then + echo "Starting the ISC DHCP server" + @PREFIX@/sbin/dhcpd + fi + ;; +'stop') + if [ -f @PREFIX@/etc/dhcpd.pid ]; then + PID=`cat @PREFIX@/etc/dhcpd.pid` + if [ -d /proc/$PID ]; then + echo "Stopping the ISC DHCP server" + kill $PID + fi + fi + ;; +esac |