dhcp/dhcp-3.0.5-ldap-configuration.patch
2007-02-04 18:51:19 +00:00

3274 lines
103 KiB
Diff

--- dhcp-3.0.5/common/conflex.c.ldapconf 2007-01-31 20:39:38.000000000 -0500
+++ dhcp-3.0.5/common/conflex.c 2007-01-31 20:39:38.000000000 -0500
@@ -47,6 +47,7 @@
static enum dhcp_token read_number PROTO ((int, struct parse *));
static enum dhcp_token read_num_or_name PROTO ((int, struct parse *));
static enum dhcp_token intern PROTO ((char *, enum dhcp_token));
+static int read_function PROTO ((struct parse *));
isc_result_t new_parse (cfile, file, inbuf, buflen, name, eolp)
struct parse **cfile;
@@ -74,6 +75,10 @@
tmp -> file = file;
tmp -> eol_token = eolp;
+ if (file != -1) {
+ tmp -> read_function = read_function;;
+ }
+
tmp -> bufix = 0;
tmp -> buflen = buflen;
if (inbuf) {
@@ -113,22 +118,11 @@
int c;
if (cfile -> bufix == cfile -> buflen) {
- if (cfile -> file != -1) {
- cfile -> buflen =
- read (cfile -> file,
- cfile -> inbuf, cfile -> bufsiz);
- if (cfile -> buflen == 0) {
- c = EOF;
- cfile -> bufix = 0;
- } else if (cfile -> buflen < 0) {
- c = EOF;
- cfile -> bufix = cfile -> buflen = 0;
- } else {
- c = cfile -> inbuf [0];
- cfile -> bufix = 1;
- }
- } else
+ if (cfile -> read_function) {
+ c = cfile -> read_function (cfile);
+ } else {
c = EOF;
+ }
} else {
c = cfile -> inbuf [cfile -> bufix];
cfile -> bufix++;
@@ -1130,3 +1124,25 @@
}
return dfv;
}
+
+
+static int
+read_function (struct parse * cfile)
+{
+ int c;
+
+ cfile -> buflen = read (cfile -> file, cfile -> inbuf, cfile -> bufsiz);
+ if (cfile -> buflen == 0) {
+ c = EOF;
+ cfile -> bufix = 0;
+ } else if (cfile -> buflen < 0) {
+ c = EOF;
+ cfile -> bufix = cfile -> buflen = 0;
+ } else {
+ c = cfile -> inbuf [0];
+ cfile -> bufix = 1;
+ }
+
+ return c;
+}
+
--- dhcp-3.0.5/common/print.c.ldapconf 2007-01-31 20:39:38.000000000 -0500
+++ dhcp-3.0.5/common/print.c 2007-01-31 20:39:38.000000000 -0500
@@ -166,9 +166,9 @@
}
char *print_hw_addr (htype, hlen, data)
- int htype;
- int hlen;
- unsigned char *data;
+ const int htype;
+ const int hlen;
+ const unsigned char *data;
{
static char habuf [49];
char *s;
--- /dev/null 2007-01-31 10:24:38.956568237 -0500
+++ dhcp-3.0.5/contrib/dhcpd-conf-to-ldap.pl 2007-01-31 20:39:38.000000000 -0500
@@ -0,0 +1,517 @@
+#!/usr/bin/perl -w
+
+# Brian Masney <masneyb@ntelos.net>
+# 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
+
+use Sys::Hostname;
+
+my $basedn = "dc=ntelos, dc=net";
+
+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+(.*)/)
+ {
+ $line = $newline;
+ }
+ else
+ {
+ $token = $line;
+ $line = '';
+ }
+ $token_number++;
+
+ $token =~ y/[A-Z]/[a-z]/ if $lowercase;
+
+ return ($token);
+}
+
+
+sub remaining_line
+{
+ local ($tmp, $str);
+
+ $str = "";
+ while (($tmp = next_token (0)))
+ {
+ $str .= ' ' if !($str eq "");
+ $str .= $tmp;
+ last if $tmp =~ /;\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'}))
+ {
+ $host = hostname ();
+ $hostdn = "cn=$host, $basedn";
+ print "dn: $hostdn\n";
+ print "objectClass: top\n";
+ print "objectClass: dhcpServer\n";
+ print "cn: $host\n";
+ print "dhcpServiceDN: $current_dn\n\n";
+
+ print "dn: $current_dn\n";
+ print "cn: DHCP Config\n";
+ print "objectClass: top\n";
+ print "objectClass: dhcpService\n";
+ if (defined ($curentry{'options'}))
+ {
+ print "objectClass: dhcpOptions\n";
+ }
+ print "dhcpPrimaryDN: $hostdn\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{'range'}))
+ {
+ print "dhcpRange: " . $curentry{'range'} . "\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\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'}))
+ {
+ print "dhcpHWAddress: " . $curentry{'hwaddress'} . "\n";
+ }
+ }
+ elsif ($curentry{'type'} eq 'pool')
+ {
+ print "dn: $current_dn\n";
+ print "cn: pool\n";
+ print "objectClass: top\n";
+ print "objectClass: dhcpPool\n";
+ if (defined ($curentry{'options'}))
+ {
+ print "objectClass: dhcpOptions\n";
+ }
+
+ if (defined ($curentry{'range'}))
+ {
+ print "dhcpRange: " . $curentry{'range'} . "\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;
+}
+
+
+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 '{');
+
+ add_dn_to_stack ("cn=group");
+ $curentry{'type'} = 'group';
+}
+
+
+sub parse_pool
+{
+ local ($descr, $tmp);
+
+ print_entry () if %curentry;
+
+ $tmp = next_token (0);
+ parse_error () if !defined ($tmp);
+ parse_error () if !($tmp eq '{');
+
+ add_dn_to_stack ("cn=pool");
+ $curentry{'type'} = 'pool';
+}
+
+
+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 (0);
+ parse_error () if !defined ($type);
+
+ $hw = next_token (0);
+ 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/;$//;
+ $curentry{'range'} = $str;
+ }
+}
+
+
+sub parse_statement
+{
+ local ($token) = shift;
+ local ($str);
+
+ if ($token eq 'option')
+ {
+ $str = remaining_line ();
+ push (@{$curentry{'options'}}, $str);
+ }
+ else
+ {
+ $str = $token . " " . remaining_line ();
+ push (@{$curentry{'statements'}}, $str);
+ }
+}
+
+
+my $token;
+my $token_number = 0;
+my $line_number = 0;
+my %curentry;
+
+$current_dn = "cn=DHCP Config, $basedn";
+$curentry{'descr'} = 'DHCP Config';
+$line = '';
+
+while (($token = next_token (1)))
+ {
+ if ($token eq '}')
+ {
+ print_entry () if %curentry;
+ 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;
+ }
+ }
+
+
--- /dev/null 2007-01-31 10:24:38.956568237 -0500
+++ dhcp-3.0.5/doc/draft-ietf-dhc-ldap-schema-01.txt 2007-01-31 20:39:38.000000000 -0500
@@ -0,0 +1,1089 @@
+
+
+
+
+
+Network Working Group M. Meredith,
+Internet Draft V. Nanjundaswamy,
+Document: <draft-ietf-dhc-ldap-schema-00.txt> M. Hinckley
+Category: Proposed Standard Novell Inc.
+Expires: 15th December 2001 16th June 2001
+
+
+ LDAP Schema for DHCP
+
+Status of this Memo
+
+This document is an Internet-Draft and is in full conformance with all
+provisions of Section 10 of RFC2026 [ ].
+
+Internet-Drafts are working documents of the Internet Engineering Task
+Force (IETF), its areas, and its working groups. Note that other groups
+may also distribute working documents as Internet-Drafts. Internet-
+Drafts are draft documents valid for a maximum of six months and may be
+updated, replaced, or obsolete by other documents at any time. It is
+inappropriate to use Internet-Drafts as reference material or to cite
+them other than as "work in progress." The list of current Internet-
+Drafts can be accessed at http://www.ietf.org/ietf/1id-abstracts.txt The
+list of Internet-Draft Shadow Directories can be accessed at
+http://www.ietf.org/shadow.html.
+
+1. Abstract
+
+This document defines a schema for representing DHCP configuration in an
+LDAP directory. It can be used to represent the DHCP Service
+configuration(s) for an entire enterprise network, a subset of the
+network, or even a single server. Representing DHCP configuration in an
+LDAP directory enables centralized management of DHCP services offered
+by one or more DHCP Servers within the enterprise.
+
+2. Conventions used in this document
+
+The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+document are to be interpreted as described in RFC-2119 [ ].
+
+In places where different sets of terminology are commonly used to
+represent similar DHCP concepts, this schema uses the terminology of the
+Internet Software Consortium's DHCP server reference implementation.
+For more information see www.isc.org.
+
+3. Design Considerations
+
+The DHCP LDAP schema is designed to be a simple multi-server schema. The
+
+
+
+M. Meredith et al. Expires December 2001 [Page 1]
+
+
+
+
+
+INTERNET-DRAFT LDAP Schema for DHCP 16 June 2001
+
+
+intent of this schema is to provide a basic framework for representing
+the most common elements used in the configuration of DHCP Server. This
+should allow other network services to obtain and use basic DHCP
+configuration information in a server-independent but knowledgeable way.
+
+It is expected that some implementations may need to extend the schema
+objects, in order to implement all of their features or needs. It is
+recommended that you use the schema defined in this draft to represent
+DHCP configuration information in an LDAP directory. Conforming to a
+standard schema improves interoperability between DHCP implementations
+from different vendors.
+
+Some implementations may choose not to support all of the objects
+defined here.
+
+Two decisions are explicitly left up to each implementation:
+
+First, implementations may choose not to store the lease information in
+the directory, so those objects would not be used.
+
+Second, implementations may choose not to implement the auditing
+information.
+
+It is up to the implementation to determine if the data in the directory
+is considered "authoritative", or if it is simply a copy of data from an
+authoritative source. Validity of the information if used as a copy is
+to be ensured by the implementation.
+
+Primarily two types of applications will use the information in this
+schema: 1. DHCP servers (for loading their configuration) 2. Management
+Interfaces (for defining/editing configurations).
+
+The schema should be efficient for the needs of both types of
+applications. The schema is designed to allow objects managed by DHCP
+(such as computers, subnets, etc) to be present anywhere in a directory
+hierarchy (to allow those objects to be placed in the directory for
+managing administrative control and access to the objects).
+
+The schema uses a few naming conventions - all object classes and
+attributes are prefixed with "dhcp" to decrease the chance that object
+classes and attributes will have the same name. The schema also uses
+standard naming attributes ("cn", "ou", etc) for all objects.
+
+4. Common DHCP Configuration Attributes
+
+Although DHCP manages several different types of objects, the
+configuration of those objects is often similar. Consequently, most of
+these objects have a common set of attributes, which are defined below.
+
+
+
+M. Meredith et al. Expires December 2001 [Page 2]
+
+
+
+
+
+INTERNET-DRAFT LDAP Schema for DHCP 16 June 2001
+
+
+4.1. Attributes Definitions
+
+The schema definitions listed below are for readability. The LDIF
+layout for this schema will follow in section 8.
+
+Name: dhcpPrimaryDN Description: The Distinguished Name of the
+dhcpServer object, which is the primary server for the configuration.
+Syntax: DN Flags: SINGLE-VALUE
+
+Named: dhcpSecondaryDN Description: The Distinguished Name(s) of the
+dhcpServer object(s), which are secondary servers for the configuration.
+Syntax: DN
+
+Name: dhcpStatements Description: Flexible storage for representing any
+specific data depending on the object to which it is attached. Examples
+include conditional statements, Server parameters, etc. This also
+serves as a 'catch-all' attribute that allows the standard to evolve
+without needing to update the schema. Syntax: IA5String
+
+Name: dhcpRange Description: The starting and 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: IA5String
+
+Name: dhcpPermitList Description: This attribute contains the permit
+lists associated with a pool. Each permit list is defined as a separate
+value. Syntax: IA5String
+
+Name: dhcpNetMask Description: The subnet mask length for the subnet.
+The mask can be easily computed from this length. Syntax: Integer
+Flags: SINGLE-VALUE
+
+Name: dhcpOption Description: Encoded option values to be sent to
+clients. Each value represents a single option and contains (OptionTag,
+Length, OptionData) encoded in the format used by DHCP. For more
+information see [DHCPOPT]. Syntax: OctetString
+
+Name: dhcpClassData Description: 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 a 'match' or 'spawn
+with' statement in the class name declarations. Syntax: IA5String
+Flags: SINGLE-VALUE
+
+Name: dhcpSubclassesDN Description: List of subclasses, these are the
+actual DN of each subclass object. Syntax: DN
+
+Name: dhcpClassesDN Description: List of classes, these are the actual
+DN of each class object. Syntax: DN
+
+
+
+M. Meredith et al. Expires December 2001 [Page 3]
+
+
+
+
+
+INTERNET-DRAFT LDAP Schema for DHCP 16 June 2001
+
+
+Name: dhcpSubnetDN Description: List of subnets, these are the actual DN
+of each subnet object. Syntax: DN
+
+Name: dhcpPoolDN Description: List of pools, these are the actual DN of
+each Pool object. Syntax: DN
+
+Name: dhcpOptionsDN Description: List of options, these are the actual
+DN of each Options object. Syntax: DN
+
+Name: dhcpHostDN Description: List of hosts, these are the actual DN of
+each host object. Syntax: DN
+
+Name: dhcpSharedNetworkDN Description: List of shared networks, these
+are the actual DN of each shared network object. Syntax: DN
+
+Name: dhcpGroupDN Description: List of groups, these are the actual DN
+of each Group object. Syntax: DN
+
+Name: dhcpLeaseDN Description: Single Lease DN. A dhcpHost configuration
+uses this attribute to identify a static IP address assignment. Syntax:
+DN Flags: SINGLE-VALUE
+
+Name: dhcpLeasesDN Description: List of leases, these are the actual DN
+of each lease object. Syntax: DN
+
+Name: dhcpServiceDN Description: 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: DN
+
+Name: dhcpHWAddress Description: The hardware address of the client
+associated with a lease Syntax: OctetString Flags: SINGLE-VALUE
+
+Name: dhcpVersion Description: This is the version identified for the
+object that this attribute is part of. In case of the dhcpServer object,
+this represents the DHCP software version. Syntax: IA5String Flags:
+SINGLE-VALUE
+
+Name: dhcpImplementation Description: DHCP Server implementation
+description e.g. DHCP Vendor information. Syntax: IA5String Flags:
+SINGLE-VALUE
+
+Name: dhcpHashBucketAssignment Description: HashBucketAssignment bit map
+for the DHCP Server, as defined in DHC Load Balancing Algorithm [RFC
+3074]. Syntax: Octet String Flags: SINGLE-VALUE
+
+Name: dhcpDelayedServiceParameter Description: Delay in seconds
+corresponding to Delayed Service Parameter configuration, as defined in
+
+
+
+M. Meredith et al. Expires December 2001 [Page 4]
+
+
+
+
+
+INTERNET-DRAFT LDAP Schema for DHCP 16 June 2001
+
+
+DHC Load Balancing Algorithm [RFC 3074]. Syntax: Integer Flags: SINGLE-
+VALUE
+
+Name: dhcpMaxClientLeadTime Description: Maximum Client Lead Time
+configuration in seconds, as defined in DHCP Failover Protocol [FAILOVR]
+Syntax: Integer Flags: SINGLE-VALUE
+
+Name: dhcpFailOverEndpointState Description: Server (Failover Endpoint)
+state, as defined in DHCP Failover Protocol [FAILOVR] Syntax: IA5String
+Flags: SINGLE-VALUE
+
+5. Configurations and Services
+
+The schema definitions below are for readability the LDIF layout for
+this schema will follow in section 8.
+
+The DHC working group is currently considering several proposals for
+fail-over and redundancy of DHCP servers. These may require sharing of
+configuration information between servers. This schema provides a
+generalized mechanism for supporting any of these proposals, by
+separating the definition of a server from the definition of
+configuration service provided by the server.
+
+Separating the DHCP Server (dhcpServer) and the DHCP Configuration
+(dhcpService) representations allows a configuration service to be
+provided by one or more servers. Similarly, a server may provide one or
+more configurations. The schema allows a server to be configured as
+either a primary or secondary provider of a DHCP configuration.
+
+Configurations are also defined so that one configuration can include
+some of the objects that are defined in another configuration. This
+allows for sharing and/or a hierarchy of related configuration items.
+
+Name: dhcpService Description: Service object that represents the
+actual DHCP Service configuration. This will be a container with the
+following attributes. Must: cn, dhcpPrimaryDN May: dhcpSecondaryDN,
+dhcpSharedNetworkDN, dhcpSubnetDN, dhcpGroupDN, dhcpHostDN,
+dhcpClassesDN, dhcpOptionsDN, dhcpStatements
+
+The following objects could exist inside the dhcpService container:
+dhcpSharedNetwork, dhcpSubnet, dhcpGroup, dhcpHost, dhcpClass,
+dhcpOptions, dhcpLog
+
+Name: dhcpServer Description: Server object that the DHCP server will
+login as. The configuration information is in the dhcpService container
+that the dhcpServiceDN points to. Must: cn, dhcpServiceDN May:
+dhcpVersion, dhcpImplementation, dhcpHashBucketAssignment,
+dhcpDelayedServiceParameter, dhcpMaxClientLeadTime,
+
+
+
+M. Meredith et al. Expires December 2001 [Page 5]
+
+
+
+
+
+INTERNET-DRAFT LDAP Schema for DHCP 16 June 2001
+dhcpFailOverEndpointState, dhcpStatements
+
+5.1. DHCP Declaration related classes:
+
+Name: dhcpSharedNetwork Description: Shared Network class will list what
+pools and subnets are in this network.
+
+This will be a container with the following attributes. Must: cn May:
+dhcpSubnetDN, dhcpPoolDN, dhcpOptionsDN, dhcpStatements
+
+The following objects can exist within a dhcpSharedNetwork container:
+dhcpSubnet, dhcpPool, dhcpOptions, dhcpLog
+
+Name: dhcpSubnet Description: Subnet object will include configuration
+information associated with a subnet, including a range and a net mask.
+
+This will be a container with the following attributes. Must: cn
+(Subnet address), dhcpNetMask May: dhcpRange, dhcpPoolDN, dhcpGroupDN,
+dhcpHostDN, dhcpClassesDN, dhcpLeasesDN, dhcpOptionsDN, dhcpStatements
+
+The following objects can exist within a dhcpSubnet container: dhcpPool,
+dhcpGroup, dhcpHost, dhcpClass, dhcpOptions, dhcpLease, dhcpLog
+
+Name: dhcpGroup Description: Group object will have configuration
+information associated with a group.
+
+This will be a container with the following attributes. Must: cn May:
+dhcpHostDN, dhcpOptionsDN, dhcpStatements
+
+The following objects can exist within a dhcpGroup container: dhcpHost,
+dhcpOptions
+
+Name: dhcpHost Description: The host object includes DHCP host
+declarations to assign a static IP address or declare the client as
+known or specify statements for a specific client. Must: cn May:
+dhcpLeaseDN, dhcpHWAddress, dhcpOptionsDN, dhcpStatements
+
+The following objects can exist within a dhcpHost container: dhcpLease,
+dhcpOptions
+
+Name: dhcpOptions Description: The options class is for option space
+declarations, it contains a list of options. Must: cn, dhcpOption
+
+Name: dhcpClass Description: This is a class to group clients together
+based on matching rules.
+
+This will be a container with the following attributes. Must: cn May:
+dhcpSubClassesDN, dhcpOptionsDN, dhcpStatements
+
+The following object can exist within a dhcpClass container:
+dhcpSubclass, dhcpOptions
+
+
+
+M. Meredith et al. Expires December 2001 [Page 6]
+
+
+
+
+
+INTERNET-DRAFT LDAP Schema for DHCP 16 June 2001
+
+
+Name: dhcpSubClass Description: This includes configuration information
+for a subclass associated with a class. The dhcpSubClass object will
+always be contained within the corresponding class container object.
+Must: cn May: dhcpClassData, dhcpOptionsDN, dhcpStatements
+
+Name: dhcpPool Description: This contains configuration for a pool that
+will have the range of addresses, permit lists and point to classes and
+leases that are members of this pool.
+
+This will be a container that could be contained by dhcpSubnet or a
+dhcpSharedNetwork. Must: cn, dhcpRange May: dhcpClassesDN,
+dhcpPermitList, dhcpLeasesDN, dhcpOptionsDN, dhcpStatements
+
+The following objects can exist within a dhcpPool container: dhcpClass,
+dhcpOptions, dhcpLease, dhcpLog
+
+6. Tracking Address Assignments
+
+The behavior of a DHCP server is influenced by two factors - it's
+configuration and the current state of the addresses that have been
+assigned to clients. This schema defines a set of objects for
+representing the DHCP configuration associated with a server. The
+following object classes provide the ability to record how addresses are
+used including maintaining history (audit log) on individual leases.
+Recording lease information in a directory could result in a significant
+performance impact and is therefore optional. Implementations supporting
+logging of leases need to consider the performance impact.
+
+6.1. dhcpLeases Attribute Definitions
+
+The schema definitions below are for readability the LDIF layout for
+this schema will follow in section 8.
+
+Name: dhcpAddressState Description: This stores information about the
+current binding-status of an address. For dynamic addresses managed by
+DHCP, the values should be restricted to the states defined in the DHCP
+Failover Protocol draft [FAILOVR]: 'FREE', 'ACTIVE', 'EXPIRED',
+'RELEASED', 'RESET', 'ABANDONED', 'BACKUP'. For more information on
+these states see [FAILOVR]. 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: IA5String Flags: SINGLE-VALUE
+
+Name: dhcpExpirationTime Description: This is the time the current lease
+for an address expires. Syntax: DateTime Flags: SINGLE-VALUE
+
+
+
+
+M. Meredith et al. Expires December 2001 [Page 7]
+
+
+
+
+
+INTERNET-DRAFT LDAP Schema for DHCP 16 June 2001
+
+
+Name: dhcpStartTimeOfState Description: This is the time of the last
+state change for a leased address. Syntax: DateTime Flags: SINGLE-VALUE
+
+Name: dhcpLastTransactionTime Description: This is the last time a valid
+DHCP packet was received from the client. Syntax: DateTime Flags:
+SINGLE-VALUE
+
+Name: dhcpBootpFlag Description: This indicates whether the address was
+assigned via BOOTP Syntax: Boolean Flags: SINGLE-VALUE
+
+Name: dhcpDomainName Description: 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:
+IA5String Flags: SINGLE-VALUE
+
+Name: dhcpDnsStatus Description: 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 that has the same values as
+specified by the Failover-DDNS option (see [FAILOVR]). Syntax: Integer
+Flags: SINGLE-VALUE
+
+Name: dhcpRequestedHostName Description: This is the hostname that was
+requested by the client. Syntax: IA5String Flags: SINGLE-VALUE
+
+Name: dhcpAssignedHostName Description: 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: IA5String Flags: SINGLE-VALUE
+
+Name: dhcpReservedForClient Description: This is the distinguished name
+of the "dhcpHost" 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: DN Flags:
+SINGLE-VALUE
+
+Name: dhcpAssignedToClient Description: This is the distinguished name
+of a "dhcpHost" that an address is currently assigned to. This
+attribute is only present in the class when the address is leased.
+Syntax: DN Flags: SINGLE-VALUE
+
+Name: dhcpRelayAgentInfo Description: 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: OctetString Flags: SINGLE-VALUE
+
+Name: dhcpErrorLog Description: Generic error log attribute that allows
+logging error conditions within a dhcpService or a dhcpSubnet, like no IP
+addresses available for lease. Syntax: IA5String
+
+M. Meredith et al. Expires December 2001 [Page 8]
+
+
+
+
+
+INTERNET-DRAFT LDAP Schema for DHCP 16 June 2001
+
+
+6.2. dhcpLeases Object Class
+
+This class represents an IP address. It may or may not be leaseable,
+and the object may exist even though a lease is not currently active for
+the associated IP address.
+
+It is recommended that all Lease objects for a single DHCP Service be
+centrally located within a single container. This ensures that the lease
+objects and the corresponding logs do not have to be relocated, when
+address ranges allocated to individual DHCP subnets and/or pools change.
+
+The schema definitions below are for readability the LDIF layout for
+this schema will follow in section 8.
+
+Name: dhcpLeases Description: This is the object that holds state
+information about an IP address. The cn (which is the IP address), and
+the current address-state are mandatory attributes. If the address is
+assigned then, some of the optional attributes will have valid data.
+Must: cn, dhcpAddressState May: dhcpExpirationTime,
+dhcpStartTimeOfState, dhcpLastTransactionTime, dhcpBootpFlag,
+dhcpDomainName, dhcpDnsStatus, dhcpRequestedHostName,
+dhcpAssignedHostName, dhcpReservedForClient, dhcpAssignedToClient,
+dhcpRelayAgentInfo, dhcpHWAddress
+
+6.3 Audit Log Information
+
+A dhcpLog object is created whenever a lease is assigned or released.
+This object is intended to be created under the corresponding dhcpLeases
+container, or dhcpPool, dhcpSubnet, dhcpSharedNetwork or dhcpService
+containers.
+
+The log information under the dhcpLeases container would be for
+addresses matching that lease information. The log information in the
+other containers could be used for errors, i.e. when a pool or subnet is
+out our addresses or if a server is not able to assign any more
+addresses for a particular dhcpService.
+
+Name: dhcpLog Description: This is the object that holds past
+information about an 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. Must: cn May: dhcpAddressState,
+dhcpExpirationTime, dhcpStartTimeOfState, dhcpLastTransactionTime,
+dhcpBootpFlag, dhcpDomainName, dhcpDnsStatus, dhcpRequestedHostName,
+dhcpAssignedHostName, dhcpReservedForClient, dhcpAssignedToClient,
+dhcpRelayAgentInfo, dhcpHWAddress, dhcpErrorLog
+
+
+
+
+
+
+M. Meredith et al. Expires December 2001 [Page 9]
+
+
+
+
+
+INTERNET-DRAFT LDAP Schema for DHCP 16 June 2001
+
+
+7. Determining settings
+
+The dhcpStatements attribute is the key to DHC enhancements that may
+come along, and the different key words that a particular server
+implementation may use. This attribute can be used to hold conditional
+DHCP Statements and DHCP server parameters. Having a generic settings
+attribute that is just a string, allows this schema to be extensible and
+easy to configure.
+
+All of the attributes that end with DN are references to the class that
+precedes the DN e.g. the dhcpPrimaryDN and dhcpSecondaryDN attributes
+hold the Distinguished Names of the dhcpServer objects that are
+associated with the dhcpService object.
+
+8. LDIF format for attributes and classes.
+
+# Attributes
+
+( 2.16.840.1.113719.1.203.4.1 NAME 'dhcpPrimaryDN' 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 )
+
+( 2.16.840.1.113719.1.203.4.2 NAME 'dhcpSecondaryDN' 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 )
+
+( 2.16.840.1.113719.1.203.4.3 NAME 'dhcpStatements' 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 )
+
+( 2.16.840.1.113719.1.203.4.4 NAME 'dhcpRange' 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 )
+
+( 2.16.840.1.113719.1.203.4.5 NAME 'dhcpPermitList' 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 )
+
+( 2.16.840.1.113719.1.203.4.6 NAME 'dhcpNetMask' 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 )
+
+( 2.16.840.1.113719.1.203.4.7 NAME 'dhcpOption' 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.40 )
+
+M. Meredith et al. Expires December 2001 [Page 10]
+
+
+
+
+
+INTERNET-DRAFT LDAP Schema for DHCP 16 June 2001
+
+
+( 2.16.840.1.113719.1.203.4.8 NAME 'dhcpClassData' 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 )
+
+( 2.16.840.1.113719.1.203.4.9 NAME 'dhcpOptionsDN' 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 )
+
+( 2.16.840.1.113719.1.203.4.10 NAME 'dhcpHostDN' DESC 'the distinguished
+name(s) of the dhcpHost objects.' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+( 2.16.840.1.113719.1.203.4.11 NAME 'dhcpPoolDN' DESC 'The distinguished
+name(s) of pools.' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+( 2.16.840.1.113719.1.203.4.12 NAME 'dhcpGroupDN' DESC 'The
+distinguished name(s) of the groups.' SYNTAX
+1.3.6.1.4.1.1466.115.121.1.12 )
+
+( 2.16.840.1.113719.1.203.4.13 NAME 'dhcpSubnetDN' DESC 'The
+distinguished name(s) of the subnets.' SYNTAX
+1.3.6.1.4.1.1466.115.121.1.12 )
+
+( 2.16.840.1.113719.1.203.4.14 NAME 'dhcpLeaseDN' DESC 'The
+distinguished name of a client address.' SYNTAX
+1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE)
+
+( 2.16.840.1.113719.1.203.4.15 NAME 'dhcpLeasesDN' DESC 'The
+distinguished name(s) client addresses.' SYNTAX
+1.3.6.1.4.1.1466.115.121.1.12 )
+
+( 2.16.840.1.113719.1.203.4.16 NAME 'dhcpClassesDN' DESC 'The
+distinguished name(s) of a class(es) in a subclass.' SYNTAX
+1.3.6.1.4.1.1466.115.121.1.12 )
+
+( 2.16.840.1.113719.1.203.4.17 NAME 'dhcpSubclassesDN' DESC 'The
+distinguished name(s) of subclass(es).' SYNTAX
+1.3.6.1.4.1.1466.115.121.1.12 )
+
+( 2.16.840.1.113719.1.203.4.18 NAME 'dhcpSharedNetworkDN' DESC 'The
+distinguished name(s) of sharedNetworks.' SYNTAX
+1.3.6.1.4.1.1466.115.121.1.12 )
+
+( 2.16.840.1.113719.1.203.4.19 NAME 'dhcpServiceDN' DESC 'The DN of
+dhcpService object(s)which contain the configuration information. Each
+dhcpServer object has this attribute identifying the DHCP
+
+
+
+M. Meredith et al. Expires December 2001 [Page 11]
+
+
+
+
+
+INTERNET-DRAFT LDAP Schema for DHCP 16 June 2001
+
+
+configuration(s) that the server is associated with.' SYNTAX
+1.3.6.1.4.1.1466.115.121.1.12 )
+
+( 2.16.840.1.113719.1.203.4.20 NAME 'dhcpVersion' DESC 'The version
+attribute of this object.' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-
+VALUE )
+
+( 2.16.840.1.113719.1.203.4.21 NAME 'dhcpImplementation' DESC
+'Description of the DHCP Server implementation e.g. DHCP Server's
+vendor.' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+( 2.16.840.1.113719.1.203.4.22 NAME 'dhcpAddressState' 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 )
+
+( 2.16.840.1.113719.1.203.4.23 NAME 'dhcpExpirationTime' 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 )
+
+( 2.16.840.1.113719.1.203.4.24 NAME 'dhcpStartTimeOfState' 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 )
+
+( 2.16.840.1.113719.1.203.4.25 NAME 'dhcpLastTransactionTime' 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 )
+
+( 2.16.840.1.113719.1.203.4.26 NAME 'dhcpBootpFlag' DESC 'This indicates
+whether the address was assigned via BOOTP.' SYNTAX
+1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
+
+( 2.16.840.1.113719.1.203.4.27 NAME 'dhcpDomainName' 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 )
+
+( 2.16.840.1.113719.1.203.4.28 NAME 'dhcpDnsStatus' DESC 'This indicates
+the status of updating DNS resource records on behalf of the client by
+
+
+
+M. Meredith et al. Expires December 2001 [Page 12]
+
+
+
+
+
+INTERNET-DRAFT LDAP Schema for DHCP 16 June 2001
+
+
+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 )
+
+( 2.16.840.1.113719.1.203.4.29 NAME 'dhcpRequestedHostName' 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 )
+
+( 2.16.840.1.113719.1.203.4.30 NAME 'dhcpAssignedHostName' 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 )
+
+( 2.16.840.1.113719.1.203.4.31 NAME 'dhcpReservedForClient' 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 )
+
+( 2.16.840.1.113719.1.203.4.32 NAME 'dhcpAssignedToClient' 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 )
+
+( 2.16.840.1.113719.1.203.4.33 NAME 'dhcpRelayAgentInfo' 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 )
+
+( 2.16.840.1.113719.1.203.4.34 NAME 'dhcpHWAddress' DESC 'The clients
+hardware address that requested this IP address.' SYNTAX
+1.3.6.1.4.1.1466.115.121.1.40 SINGLE-VALUE )
+
+( 2.16.840.1.113719.1.203.4.35 NAME 'dhcpHashBucketAssignment' 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 )
+
+( 2.16.840.1.113719.1.203.4.36 NAME 'dhcpDelayedServiceParameter' 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 )
+
+( 2.16.840.1.113719.1.203.4.37 NAME 'dhcpMaxClientLeadTime' 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
+
+
+
+M. Meredith et al. Expires December 2001 [Page 13]
+
+
+
+
+
+INTERNET-DRAFT LDAP Schema for DHCP 16 June 2001
+
+
+SINGLE-VALUE )
+
+( 2.16.840.1.113719.1.203.4.38 NAME 'dhcpFailOverEndpointState' 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 )
+
+( 2.16.840.1.113719.1.203.4.39 NAME 'dhcpErrorLog' 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 )
+
+#Classes
+
+( 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 $ dhcpPrimaryDN) MAY
+(dhcpSecondaryDN $ dhcpSharedNetworkDN $ dhcpSubnetDN $ dhcpGroupDN $
+dhcpHostDN $ dhcpClassesDN $ dhcpOptionsDN $ dhcpStatements ) )
+
+( 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 $ dhcpStatements) X-
+NDS_CONTAINMENT ('dhcpService' ) )
+
+( 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 $ dhcpStatements) X-NDS_CONTAINMENT
+('dhcpService' 'dhcpSharedNetwork') )
+
+( 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 $
+dhcpStatements) X-NDS_CONTAINMENT ('dhcpSubnet' 'dhcpSharedNetwork') )
+
+( 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 ) X-NDS_CONTAINMENT
+('dhcpSubnet' 'dhcpService' ) )
+
+( 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) X-NDS_CONTAINMENT
+('dhcpService' 'dhcpSubnet' 'dhcpGroup') )
+
+( 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) X-NDS_CONTAINMENT
+('dhcpService' 'dhcpSubnet' ) )
+
+( 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) X-NDS_CONTAINMENT
+
+
+
+M. Meredith et al. Expires December 2001 [Page 14]
+
+
+
+
+
+INTERNET-DRAFT LDAP Schema for DHCP 16 June 2001
+
+
+'dhcpClass' )
+
+( 2.16.840.1.113719.1.203.6.9 NAME 'dhcpOptions' DESC 'Represents
+information about a collection of options defined.' SUP top MUST cn MAY
+( dhcpOption ) X-NDS_CONTAINMENT ('dhcpService' 'dhcpSharedNetwork'
+'dhcpSubnet' 'dhcpPool' 'dhcpGroup' 'dhcpHost' 'dhcpClass' )
+
+( 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') )
+
+( 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' ) )
+
+( 2.16.840.1.113719.1.203.6.12 NAME 'dhcpServer' DESC 'DHCP Server
+Object' SUP top MUST (cn, dhcpServiceDN) MAY (dhcpVersion $
+dhcpImplementation $ dhcpHashBucketAssignment $
+dhcpDelayedServiceParameter $ dhcpMaxClientLeadTime $
+dhcpFailOverEndpointState $ dhcpStatements) X-NDS_CONTAINMENT ('O' 'OU'
+'dc') )
+
+9. Security Considerations
+
+Since the DHCP Configuration information is stored in a directory, the
+security of the information is limited to the security offered by the
+directory including the security of the objects within that directory.
+
+10. Intellectual Property Rights Notices
+
+The IETF takes no position regarding the validity or scope of any
+intellectual property or other rights that might be claimed to pertain
+to the implementation or use of the technology described in this
+document or the extent to which any license under such rights might or
+might not be available; neither does it represent that it has made any
+effort to identify any such rights. Information on the IETF's
+procedures with respect to rights in standards-track and standards-
+
+
+
+M. Meredith et al. Expires December 2001 [Page 15]
+
+
+
+
+
+INTERNET-DRAFT LDAP Schema for DHCP 16 June 2001
+
+
+related documentation can be found in BCP-11. Copies of claims of
+rights made available for publication and any assurances of licenses to
+be made available, or the result of an attempt made to obtain a general
+license or permission for the use of such proprietary rights by
+implementors or users of this specification can be obtained from the
+IETF Secretariat.
+
+The IETF invites any interested party to bring to its attention any
+copyrights, patents or patent applications, or other proprietary rights
+which may cover technology that may be required to practice this
+standard. Please address the information to the IETF Executive
+Director.
+
+11. Full Copyright Statement
+
+Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+This document and translations of it may be copied and furnished to
+others, and derivative works that comment on or otherwise explain it or
+assist in its implementation may be prepared, copied, published and
+distributed, in whole or in part, without restriction of any kind,
+provided that the above copyright notice and this paragraph are included
+on all such copies and derivative works. However, this document itself
+may not be modified in any way, such as by removing the copyright notice
+or references to the Internet Society or other Internet organizations,
+except as needed for the purpose of developing Internet standards in
+which case the procedures for copyrights defined in the Internet
+Standards process must be followed, or as required to translate it into
+languages other than English.
+
+The limited permissions granted above are perpetual and will not be
+revoked by the Internet Society or its successors or assigns.
+
+This document and the information contained herein is provided on an "AS
+IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK
+FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT
+INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR
+FITNESS FOR A PARTICULAR PURPOSE.
+
+12. References
+
+[RFC2131] Droms, R., "Dynamic Host Configuration Protocol", RFC 2131,
+March 1997.
+
+[RFC2132] Alexander, S., Droms, R., "DHCP Options and BOOTP Vendor
+Extensions", RFC 2132, March 1997.
+
+
+
+
+M. Meredith et al. Expires December 2001 [Page 16]
+
+
+
+
+
+INTERNET-DRAFT LDAP Schema for DHCP 16 June 2001
+
+
+[MSDHCP] Gu, Y., Vyaghrapuri, R., "An LDAP Schema for Dynamic Host
+Configuration Protocol Service", Internet Draft <draft-gu-dhcp-ldap-
+schema-00.txt>, August 1998.
+
+[NOVDHCP] Miller, T., Patel, A., Rao, P., "Lightweight Directory Access
+Protocol (v3): Schema for Dynamic Host Configuration Protocol (DHCP)",
+Internet Draft <draft-miller-dhcp-ldap-schema-00.txt>, June 1998.
+
+[FAILOVR] Droms, R., Rabil, G., Dooley, M., Kapur, A., Gonczi, S., Volz,
+B., "DHCP Failover Protocol", Internet Draft <draft-ietf-dhc-
+failover-08.txt>, July 2000.
+
+[RFC 3074] Volz B., Gonczi S., Lemon T., Stevens R., "DHC Load Balancing
+Algorithm", February 2001
+
+[AGENT] Patrick, M., "DHCP Relay Agent Information Option", Internet
+Draft <draft-ietf-dhc-agent-options-09.txt>, March 2000.
+
+[DHCPOPT] Carney, M., "New Option Review Guidelines and Additional
+Option Namespace", Internet Draft <draft-ietf-dhc-
+option_review_and_namespace-01.txt>, October 1999.
+
+[POLICY] Strassner, J., Elleson, E., Moore, B., "Policy Framework LDAP
+Core Schema", Internet Draft <draft-ietf-policy-core-schema-06.txt>,
+November 1999.
+
+[RFC2251] Wahl, M., Howes, T., Kille, S., "Lightweight Directory Access
+Protocol (v3)", RFC 2251, December 1997.
+
+[RFC2252] Wahl, M., Coulbeck, A., Howes, T., Kille, S., "Lightweight
+Directory Access Protocol (v3) Attribute Syntax Definitions", RFC 2252,
+December 1997.
+
+[RFC2255] Howes, T., Smith, M., "The LDAP URL Format", RFC 2255,
+December 1997.
+
+[RFC951] Croft, B., Gilmore, J., "Bootstrap Protocol (BOOTP)", RFC 951,
+September 1985.
+
+[RFC2119] Bradner, S. "Key words for use in RFCs to Indicate Requirement
+Levels", RFC 2119, March 1997.
+
+13. Acknowledgments
+
+This work is partially based on a previous draft draft-ietf-dhc-
+schema-02.doc.
+
+
+
+
+
+M. Meredith et al. Expires December 2001 [Page 17]
+
+
+
+
+
+INTERNET-DRAFT LDAP Schema for DHCP 16 June 2001
+
+
+14. Author's Addresses
+
+Comments regarding this draft may be sent to the authors at the
+following address:
+
+Mark Meredith
+Mark Hinckley
+Novell Inc.
+1800 S. Novell Place
+Provo, Utah 84606
+
+Vijay K. Nanjundaswamy
+Novell Software Development (I) Ltd
+49/1 & 49/3, Garvebhavi Palya,
+7th Mile, Hosur Road
+Bangalore 560068
+
+email: mark_meredith@novell.com
+email: knvijay@novell.com
+email: mhinckley@novell.com
+
+This Internet Draft expires December 16, 2001.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+M. Meredith et al. Expires December 2001 [Page 18]
+
+
+
+
--- dhcp-3.0.5/includes/dhcpd.h.ldapconf 2007-01-31 20:39:38.000000000 -0500
+++ dhcp-3.0.5/includes/dhcpd.h 2007-01-31 20:39:38.000000000 -0500
@@ -79,6 +79,11 @@
#include <isc-dhcp/result.h>
#include <omapip/omapip_p.h>
+#if defined(LDAP_CONFIGURATION)
+# include <ldap.h>
+# include <sys/utsname.h> /* for uname() */
+#endif
+
#if !defined (OPTION_HASH_SIZE)
# define OPTION_HASH_SIZE 17
# define OPTION_HASH_PTWO 32 /* Next power of two above option hash. */
@@ -139,6 +144,8 @@
char *inbuf;
unsigned bufix, buflen;
unsigned bufsiz;
+
+ int (*read_function) (struct parse *);
};
/* Variable-length array of data. */
@@ -244,6 +251,27 @@
u_int8_t hbuf [17];
};
+#if defined(LDAP_CONFIGURATION)
+# define LDAP_BUFFER_SIZE 8192
+# define LDAP_METHOD_STATIC 0
+# define LDAP_METHOD_DYNAMIC 1
+
+/* This is a tree of the current configuration we are building from LDAP */
+
+struct ldap_config_stack {
+ LDAPMessage * res; /* Pointer returned from ldap_search */
+ LDAPMessage * ldent; /* Current item in LDAP that we're processing
+ in res */
+ int close_brace; /* Put a closing } after we're through with
+ this item */
+ int processed; /* We set this flag if this base item has been
+ processed. After this base item is processed,
+ we can start processing the children */
+ struct ldap_config_stack *children;
+ struct ldap_config_stack *next;
+};
+#endif
+
typedef enum {
server_startup = 0,
server_running = 1,
@@ -426,6 +454,15 @@
# define DEFAULT_PING_TIMEOUT 1
#endif
+#if defined(LDAP_CONFIGURATION)
+# define SV_LDAP_SERVER 46
+# define SV_LDAP_PORT 47
+# define SV_LDAP_USERNAME 48
+# define SV_LDAP_PASSWORD 49
+# define SV_LDAP_BASE_DN 50
+# define SV_LDAP_METHOD 51
+#endif
+
#if !defined (DEFAULT_DEFAULT_LEASE_TIME)
# define DEFAULT_DEFAULT_LEASE_TIME 43200
#endif
@@ -1526,7 +1563,7 @@
char *quotify_string (const char *, const char *, int);
char *quotify_buf (const unsigned char *, unsigned, const char *, int);
char *print_base64 (const unsigned char *, unsigned, const char *, int);
-char *print_hw_addr PROTO ((int, int, unsigned char *));
+char *print_hw_addr PROTO ((const int, const int, const unsigned char *));
void print_lease PROTO ((struct lease *));
void dump_raw PROTO ((const unsigned char *, unsigned));
void dump_packet_option (struct option_cache *, struct packet *,
@@ -2640,3 +2677,14 @@
#endif /* FAILOVER_PROTOCOL */
const char *binding_state_print (enum failover_state);
+
+/* ldap.c */
+#if defined(LDAP_CONFIGURATION)
+extern struct enumeration ldap_methods;
+isc_result_t ldap_read_config (void);
+int find_haddr_in_ldap (struct host_decl **, int, unsigned,
+ const unsigned char *, const char *, int);
+int find_subclass_in_ldap (struct class *, struct class **,
+ struct data_string *);
+#endif
+
--- dhcp-3.0.5/includes/site.h.ldapconf 2002-03-12 13:33:39.000000000 -0500
+++ dhcp-3.0.5/includes/site.h 2007-01-31 20:39:38.000000000 -0500
@@ -177,3 +177,13 @@
traces. */
#define TRACING
+
+/* Define this if you want to read your config from LDAP. Read README.ldap
+ about how to set this up */
+
+#define LDAP_CONFIGURATION
+
+#define _PATH_DHCPD_DB "/var/lib/dhcpd/dhcpd.leases"
+#define _PATH_DHCLIENT_DB "/var/lib/dhclient/dhclient.leases"
+#define _PATH_DHCPD_DB "/var/lib/dhcpd/dhcpd.leases"
+#define _PATH_DHCLIENT_DB "/var/lib/dhclient/dhclient.leases"
--- dhcp-3.0.5/server/Makefile.dist.ldapconf 2007-01-31 20:39:38.000000000 -0500
+++ dhcp-3.0.5/server/Makefile.dist 2007-01-31 21:00:06.000000000 -0500
@@ -25,9 +25,9 @@
CATMANPAGES = dhcpd.cat8 dhcpd.conf.cat5 dhcpd.leases.cat5
SEDMANPAGES = dhcpd.man8 dhcpd.conf.man5 dhcpd.leases.man5
SRCS = dhcpd.c dhcp.c bootp.c confpars.c db.c class.c failover.c \
- omapi.c mdb.c stables.c salloc.c ddns.c
+ omapi.c mdb.c stables.c salloc.c ddns.c ldap.c
OBJS = dhcpd.o dhcp.o bootp.o confpars.o db.o class.o failover.o \
- omapi.o mdb.o stables.o salloc.o ddns.o
+ omapi.o mdb.o stables.o salloc.o ddns.o ldap.o
PROG = dhcpd
MAN = dhcpd.8 dhcpd.conf.5 dhcpd.leases.5
@@ -103,6 +103,6 @@
-e "s#RUNDIR#$(VARRUN)#g" < dhcpd.leases.5 >dhcpd.leases.man5
dhcpd: $(OBJS) $(COBJ) $(DHCPLIB)
- $(CC) $(LFLAGS) -pie $(RPM_OPT_FLAGS) -Wl,-z,relro,-z,now,-z,noexecstack,-z,nodlopen -o dhcpd $(OBJS) $(DHCPLIB) $(LIBS)
+ $(CC) $(LFLAGS) -pie $(RPM_OPT_FLAGS) -Wl,-z,relro,-z,now,-z,noexecstack,-z,nodlopen -o dhcpd $(OBJS) $(DHCPLIB) $(LIBS) -lldap
# Dependencies (semi-automatically-generated)
--- dhcp-3.0.5/server/class.c.ldapconf 2004-06-10 13:59:51.000000000 -0400
+++ dhcp-3.0.5/server/class.c 2007-01-31 20:39:38.000000000 -0500
@@ -90,6 +90,7 @@
int matched = 0;
int status;
int ignorep;
+ int classfound;
for (class = collection -> classes; class; class = class -> nic) {
#if defined (DEBUG_CLASS_MATCHING)
@@ -135,9 +136,19 @@
class -> submatch, MDL));
if (status && data.len) {
nc = (struct class *)0;
- if (class_hash_lookup (&nc, class -> hash,
- (const char *)data.data,
- data.len, MDL)) {
+ classfound = class_hash_lookup (&nc,
+ class -> hash,
+ (const char *)data.data,
+ data.len, MDL);
+
+#ifdef LDAP_CONFIGURATION
+ if (!classfound &&
+ find_subclass_in_ldap (class,
+ &nc, &data))
+ classfound = 1;
+#endif
+
+ if (classfound) {
#if defined (DEBUG_CLASS_MATCHING)
log_info ("matches subclass %s.",
print_hex_1 (data.len,
--- dhcp-3.0.5/server/confpars.c.ldapconf 2007-01-31 20:39:38.000000000 -0500
+++ dhcp-3.0.5/server/confpars.c 2007-01-31 20:39:38.000000000 -0500
@@ -63,7 +63,17 @@
isc_result_t readconf ()
{
- return read_conf_file (path_dhcpd_conf, root_group, ROOT_GROUP, 0);
+ isc_result_t res;
+
+ res = read_conf_file (path_dhcpd_conf, root_group, ROOT_GROUP, 0);
+#if defined(LDAP_CONFIGURATION)
+ if (res != ISC_R_SUCCESS)
+ return (res);
+
+ return ldap_read_config ();
+#else
+ return (res);
+#endif
}
isc_result_t read_conf_file (const char *filename, struct group *group,
--- dhcp-3.0.5/server/dhcpd.c.ldapconf 2007-01-31 20:39:38.000000000 -0500
+++ dhcp-3.0.5/server/dhcpd.c 2007-01-31 20:39:38.000000000 -0500
@@ -433,6 +433,9 @@
/* Add the ddns update style enumeration prior to parsing. */
add_enumeration (&ddns_styles);
add_enumeration (&syslog_enum);
+#if defined (LDAP_CONFIGURATION)
+ add_enumeration (&ldap_methods);
+#endif
if (!group_allocate (&root_group, MDL))
log_fatal ("Can't allocate root group!");
--- /dev/null 2007-01-31 10:24:38.956568237 -0500
+++ dhcp-3.0.5/server/ldap.c 2007-01-31 20:39:38.000000000 -0500
@@ -0,0 +1,1142 @@
+/* ldap.c
+
+ Routines for reading the configuration from LDAP */
+
+/*
+ * Copyright (c) 1996-2001 Ntelos, 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:
+ *
+ * 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 The Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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.
+ *
+ * This LDAP module was written by Brian Masney <masneyb@ntelos.net>. It's
+ * development was sponsored by Ntelos, Inc. (www.ntelos.com).
+ */
+
+#include "dhcpd.h"
+
+#if defined(LDAP_CONFIGURATION)
+
+static LDAP * ld = NULL;
+static char *ldap_server = NULL,
+ *ldap_username = NULL,
+ *ldap_password = NULL,
+ *ldap_base_dn = NULL;
+static int ldap_method = LDAP_METHOD_DYNAMIC,
+ disable_ldap = 0;
+static struct ldap_config_stack *ldap_stack = NULL;
+
+
+static void
+ldap_parse_class (struct ldap_config_stack *item, struct parse *cfile)
+{
+ struct berval **temp;
+
+ if ((temp = ldap_get_values_len (ld, item->ldent, "cn")) == NULL ||
+ temp[0]->bv_val == NULL)
+ {
+ if (temp != NULL)
+ ldap_value_free_len (temp);
+
+ return;
+ }
+
+ strncat (cfile->inbuf, "class \"", LDAP_BUFFER_SIZE);
+ strncat (cfile->inbuf, temp[0]->bv_val, LDAP_BUFFER_SIZE);
+ strncat (cfile->inbuf, "\" {\n", LDAP_BUFFER_SIZE);
+
+ item->close_brace = 1;
+ ldap_value_free_len (temp);
+}
+
+
+static void
+ldap_parse_subclass (struct ldap_config_stack *item, struct parse *cfile)
+{
+ struct berval **temp, **classdata;
+
+ if ((temp = ldap_get_values_len (ld, item->ldent, "cn")) == NULL ||
+ temp[0]->bv_val == NULL)
+ {
+ if (temp != NULL)
+ ldap_value_free_len (temp);
+
+ return;
+ }
+
+
+ if ((classdata = ldap_get_values_len (ld, item->ldent,
+ "dhcpClassData")) == NULL ||
+ classdata[0]->bv_val == NULL)
+ {
+ if (classdata != NULL)
+ ldap_value_free_len (classdata);
+ ldap_value_free_len (temp);
+
+ return;
+ }
+
+ strncat (cfile->inbuf, "subclass ", LDAP_BUFFER_SIZE);
+ strncat (cfile->inbuf, (*classdata)->bv_val, LDAP_BUFFER_SIZE);
+ strncat (cfile->inbuf, " ", LDAP_BUFFER_SIZE);
+ strncat (cfile->inbuf, (*temp)->bv_val, LDAP_BUFFER_SIZE);
+ strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
+
+ item->close_brace = 1;
+ ldap_value_free_len (temp);
+ ldap_value_free_len (classdata);
+}
+
+
+static void
+ldap_parse_host (struct ldap_config_stack *item, struct parse *cfile)
+{
+ struct berval **temp, **hwaddr;
+
+
+ if ((temp = ldap_get_values_len (ld, item->ldent, "cn")) == NULL ||
+ temp[0]->bv_val == NULL)
+ {
+ if (temp != NULL)
+ ldap_value_free_len (temp);
+
+ return;
+ }
+
+ if ((hwaddr = ldap_get_values_len (ld, item->ldent,
+ "dhcpHWAddress")) == NULL ||
+ hwaddr[0]->bv_val == NULL)
+ {
+ if (hwaddr != NULL)
+ ldap_value_free_len (hwaddr);
+ ldap_value_free_len (temp);
+
+ return;
+ }
+
+ strncat (cfile->inbuf, "host ", LDAP_BUFFER_SIZE);
+ strncat (cfile->inbuf, (*temp)->bv_val, LDAP_BUFFER_SIZE);
+ strncat (cfile->inbuf, " {\nhardware ", LDAP_BUFFER_SIZE);
+ strncat (cfile->inbuf, (*hwaddr)->bv_val, LDAP_BUFFER_SIZE);
+ strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+
+ item->close_brace = 1;
+ ldap_value_free_len (temp);
+ ldap_value_free_len (hwaddr);
+}
+
+
+static void
+ldap_parse_shared_network (struct ldap_config_stack *item, struct parse *cfile)
+{
+ struct berval **temp;
+
+
+ if ((temp = ldap_get_values_len (ld, item->ldent, "cn")) == NULL ||
+ temp[0]->bv_val == NULL)
+ {
+ if (temp != NULL)
+ ldap_value_free_len (temp);
+
+ return;
+ }
+
+ strncat (cfile->inbuf, "shared-network ", LDAP_BUFFER_SIZE);
+ strncat (cfile->inbuf, (*temp)->bv_val, LDAP_BUFFER_SIZE);
+ strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
+
+ item->close_brace = 1;
+ ldap_value_free_len (temp);
+}
+
+
+static void
+parse_netmask (int netmask, char *netmaskbuf)
+{
+ unsigned long nm;
+ int i;
+
+ nm = 0;
+ for (i=1; i <= netmask; i++)
+ {
+ nm |= 1 << (32 - i);
+ }
+
+ sprintf (netmaskbuf, "%d.%d.%d.%d", (int) (nm >> 24) & 0xff,
+ (int) (nm >> 16) & 0xff,
+ (int) (nm >> 8) & 0xff,
+ (int) nm & 0xff);
+}
+
+static void
+ldap_parse_subnet (struct ldap_config_stack *item, struct parse *cfile)
+{
+ struct berval **temp, **netmask;
+ char netmaskbuf[16];
+ int i;
+
+ if ((temp = ldap_get_values_len (ld, item->ldent, "cn")) == NULL ||
+ temp[0]->bv_val == NULL)
+ {
+ if (temp != NULL)
+ ldap_value_free_len (temp);
+
+ return;
+ }
+
+ if ((netmask = ldap_get_values_len (ld, item->ldent,
+ "dhcpNetmask")) == NULL ||
+ netmask[0]->bv_val == NULL)
+ {
+ if (netmask != NULL)
+ ldap_value_free_len (netmask);
+ ldap_value_free_len (temp);
+
+ return;
+ }
+
+ strncat (cfile->inbuf, "subnet ", LDAP_BUFFER_SIZE);
+ strncat (cfile->inbuf, temp[0]->bv_val, LDAP_BUFFER_SIZE);
+
+ strncat (cfile->inbuf, " netmask ", LDAP_BUFFER_SIZE);
+ parse_netmask (strtol (netmask[0]->bv_val, NULL, 10), netmaskbuf);
+ strncat (cfile->inbuf, netmaskbuf, LDAP_BUFFER_SIZE);
+
+ strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
+
+ ldap_value_free_len (temp);
+ ldap_value_free_len (netmask);
+
+ if ((temp = ldap_get_values_len (ld, item->ldent, "dhcpRange")) != NULL)
+ {
+ strncat (cfile->inbuf, "range", LDAP_BUFFER_SIZE);
+ for (i=0; temp[i]->bv_val != NULL; i++)
+ {
+ strncat (cfile->inbuf, " ", LDAP_BUFFER_SIZE);
+ strncat (cfile->inbuf, temp[i]->bv_val, LDAP_BUFFER_SIZE);
+ }
+ strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+ ldap_value_free_len (temp);
+ }
+
+ item->close_brace = 1;
+}
+
+
+static void
+ldap_parse_pool (struct ldap_config_stack *item, struct parse *cfile)
+{
+ struct berval **temp;
+ int i;
+
+ strncat (cfile->inbuf, "pool {\n", LDAP_BUFFER_SIZE);
+
+ if ((temp = ldap_get_values_len (ld, item->ldent, "dhcpRange")) != NULL)
+ {
+ strncat (cfile->inbuf, "range", LDAP_BUFFER_SIZE);
+ for (i=0; temp[i]->bv_val != NULL; i++)
+ {
+ strncat (cfile->inbuf, " ", LDAP_BUFFER_SIZE);
+ strncat (cfile->inbuf, temp[i]->bv_val, LDAP_BUFFER_SIZE);
+ }
+ strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+ ldap_value_free_len (temp);
+ }
+
+ if ((temp = ldap_get_values_len (ld, item->ldent, "dhcpPermitList")) != NULL)
+ {
+ for (i=0; temp[i]->bv_val != NULL; i++)
+ {
+ strncat (cfile->inbuf, temp[i]->bv_val, LDAP_BUFFER_SIZE);
+ strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+ }
+ ldap_value_free_len (temp);
+ }
+
+ item->close_brace = 1;
+}
+
+
+static void
+ldap_parse_group (struct ldap_config_stack *item, struct parse *cfile)
+{
+ strncat (cfile->inbuf, "group {\n", LDAP_BUFFER_SIZE);
+ item->close_brace = 1;
+}
+
+
+static void
+parse_external_dns (LDAPMessage * ent)
+{
+ char *search[] = {"dhcpOptionsDN", "dhcpSharedNetworkDN", "dhcpSubnetDN",
+ "dhcpGroupDN", "dhcpHostDN", "dhcpClassesDN",
+ "dhcpPoolDN", NULL};
+ LDAPMessage * newres, * newent;
+ struct ldap_config_stack *ns;
+ struct berval **temp;
+ int i, ret;
+
+ for (i=0; search[i] != NULL; i++)
+ {
+ if ((ldap_method = LDAP_METHOD_DYNAMIC) &&
+ (strcmp (search[i], "dhcpHostDN") == 0))
+ continue;
+
+ if ((temp = ldap_get_values_len (ld, ent, search[i])) == NULL)
+ continue;
+
+ if ((ret = ldap_search_ext_s (ld, temp[0]->bv_val, LDAP_SCOPE_BASE,
+ "objectClass=*", NULL, 0,
+ NULL, NULL, NULL, 0,
+ &newres)) != LDAP_SUCCESS)
+ {
+ ldap_value_free_len (temp);
+ ldap_unbind_ext (ld, NULL, NULL);
+ ld = NULL;
+ return;
+ }
+
+ ldap_value_free_len (temp);
+
+ newent = ldap_first_entry (ld, newres);
+ if (newent == NULL)
+ {
+ ldap_msgfree (newres);
+ continue;
+ }
+
+#if defined(DEBUG_LDAP)
+ log_info ("Adding LDAP entry '%s' as child", ldap_get_dn (ld, newent));
+#endif
+
+ ns = dmalloc (sizeof (*ns), MDL);
+ ns->res = newres;
+ ns->ldent = newent;
+ ns->close_brace = 0;
+ ns->processed = 0;
+ ns->children = NULL;
+ ns->next = ldap_stack->children;
+ ldap_stack->children = ns;
+ }
+}
+
+
+static void
+ldap_generate_config_string (struct ldap_config_stack *item, struct parse *cfile)
+{
+ struct berval **objectClass, **temp;
+ int i, j, ignore, found;
+
+ if ((objectClass = ldap_get_values_len (ld, item->ldent,
+ "objectClass")) == NULL)
+ return;
+
+ ignore = 0;
+ found = 1;
+ for (i=0; objectClass[i]->bv_val != NULL; i++)
+ {
+ if (strcmp (objectClass[i]->bv_val, "dhcpSharedNetwork") == 0)
+ ldap_parse_shared_network (item, cfile);
+ else if (strcmp (objectClass[i]->bv_val, "dhcpClass") == 0)
+ ldap_parse_class (item, cfile);
+ else if (strcmp (objectClass[i]->bv_val, "dhcpSubnet") == 0)
+ ldap_parse_subnet (item, cfile);
+ else if (strcmp (objectClass[i]->bv_val, "dhcpPool") == 0)
+ ldap_parse_pool (item, cfile);
+ else if (strcmp (objectClass[i]->bv_val, "dhcpGroup") == 0)
+ ldap_parse_group (item, cfile);
+ else if (strcmp (objectClass[i]->bv_val, "dhcpHost") == 0)
+ {
+ if (ldap_method == LDAP_METHOD_STATIC)
+ ldap_parse_host (item, cfile);
+ else
+ {
+ ignore = 1;
+ break;
+ }
+ }
+ else if (strcmp (objectClass[i]->bv_val, "dhcpSubClass") == 0)
+ {
+ if (ldap_method == LDAP_METHOD_STATIC)
+ ldap_parse_subclass (item, cfile);
+ else
+ {
+ ignore = 1;
+ break;
+ }
+ }
+ else
+ found = 0;
+
+ if (found && cfile->inbuf[0] == '\0')
+ {
+ ignore = 1;
+ break;
+ }
+ }
+
+ ldap_value_free_len (objectClass);
+
+ if (ignore)
+ return;
+
+ if ((temp = ldap_get_values_len (ld, item->ldent, "dhcpOption")) != NULL)
+ {
+ for (j=0; temp[j]->bv_val != NULL; j++)
+ {
+ strncat (cfile->inbuf, "option ", LDAP_BUFFER_SIZE);
+ strncat (cfile->inbuf, temp[j]->bv_val, LDAP_BUFFER_SIZE);
+ strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+ }
+ ldap_value_free_len (temp);
+ }
+
+ if ((temp = ldap_get_values_len (ld, item->ldent, "dhcpStatements")) != NULL)
+ {
+ for (j=0; temp[j]->bv_val != NULL; j++)
+ {
+ strncat (cfile->inbuf, temp[j]->bv_val, LDAP_BUFFER_SIZE);
+ strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+ }
+ ldap_value_free_len (temp);
+ }
+
+ parse_external_dns (item->ldent);
+}
+
+
+static void
+free_stack_entry (struct ldap_config_stack *item)
+{
+ ldap_msgfree (item->res);
+ dfree (item, MDL);
+}
+
+
+static void
+next_ldap_entry (struct parse *cfile)
+{
+ struct ldap_config_stack *temp_stack;
+
+ if (ldap_stack->processed && ldap_stack->children != NULL)
+ {
+ temp_stack = ldap_stack->children;
+ if (temp_stack->close_brace)
+ strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE);
+
+ ldap_stack->children = ldap_stack->children->next;
+ free_stack_entry (temp_stack);
+
+ if (ldap_stack->processed && ldap_stack->children != NULL)
+ return;
+ }
+
+ if (ldap_stack->close_brace)
+ {
+ strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE);
+ ldap_stack->close_brace = 0;
+ }
+
+ while (ldap_stack != NULL && ldap_stack->children == NULL &&
+ (ldap_stack->ldent = ldap_next_entry (ld, ldap_stack->ldent)) == NULL)
+ {
+ if (ldap_stack->close_brace)
+ {
+ strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE);
+ ldap_stack->close_brace = 0;
+ }
+
+ temp_stack = ldap_stack;
+ ldap_stack = ldap_stack->next;
+ free_stack_entry (temp_stack);
+ }
+
+ if (ldap_stack != NULL && ldap_stack->children == NULL &&
+ ldap_stack->close_brace)
+ {
+ strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE);
+ ldap_stack->close_brace = 0;
+ }
+}
+
+
+static void
+add_to_config_stack (LDAPMessage * res, LDAPMessage * ent)
+{
+ struct ldap_config_stack *ns;
+
+ ns = dmalloc (sizeof (*ns), MDL);
+ ns->res = res;
+ ns->ldent = ent;
+ ns->close_brace = 0;
+ ns->processed = 0;
+ ns->children = NULL;
+ ns->next = ldap_stack;
+ ldap_stack = ns;
+}
+
+
+static void
+ldap_start (void)
+{
+ struct option_state *options;
+ struct option_cache *oc;
+ struct data_string db;
+ int ret;
+
+ if (ld != NULL)
+ return;
+
+ if (ldap_server == NULL)
+ {
+ options = NULL;
+ option_state_allocate (&options, MDL);
+
+ execute_statements_in_scope ((struct binding_value **) NULL,
+ (struct packet *) NULL, (struct lease *) NULL,
+ (struct client_state *) NULL, (struct option_state *) NULL,
+ options, &global_scope, root_group, (struct group *) NULL);
+
+ memset (&db, 0, sizeof (db));
+ oc = lookup_option (&server_universe, options, SV_LDAP_SERVER);
+ if (oc &&
+ evaluate_option_cache (&db, (struct packet*) NULL,
+ (struct lease *) NULL, (struct client_state *) NULL,
+ options, (struct option_state *) NULL, &global_scope, oc, MDL))
+ {
+ ldap_server = dmalloc (db.len + 1, MDL);
+ if (!ldap_server)
+ log_fatal ("no memory for ldap server");
+ memcpy (ldap_server, db.data, db.len);
+ ldap_server[db.len] = 0;
+ data_string_forget (&db, MDL);
+ }
+
+ oc = lookup_option (&server_universe, options, SV_LDAP_USERNAME);
+ if (oc &&
+ evaluate_option_cache (&db, (struct packet*) NULL,
+ (struct lease *) NULL, (struct client_state *) NULL,
+ options, (struct option_state *) NULL, &global_scope, oc, MDL))
+ {
+ ldap_username = dmalloc (db.len + 1, MDL);
+ if (!ldap_username)
+ log_fatal ("no memory for ldap username");
+ memcpy (ldap_username, db.data, db.len);
+ ldap_username[db.len] = 0;
+ data_string_forget (&db, MDL);
+ }
+
+ oc = lookup_option (&server_universe, options, SV_LDAP_PASSWORD);
+ if (oc &&
+ evaluate_option_cache (&db, (struct packet*) NULL,
+ (struct lease *) NULL, (struct client_state *) NULL,
+ options, (struct option_state *) NULL, &global_scope, oc, MDL))
+ {
+ ldap_password = dmalloc (db.len + 1, MDL);
+ if (!ldap_password)
+ log_fatal ("no memory for ldap password");
+ memcpy (ldap_password, db.data, db.len);
+ ldap_password[db.len] = 0;
+ data_string_forget (&db, MDL);
+ }
+
+ oc = lookup_option (&server_universe, options, SV_LDAP_BASE_DN);
+ if (oc &&
+ evaluate_option_cache (&db, (struct packet*) NULL,
+ (struct lease *) NULL, (struct client_state *) NULL,
+ options, (struct option_state *) NULL, &global_scope, oc, MDL))
+ {
+ ldap_base_dn = dmalloc (db.len + 1, MDL);
+ if (!ldap_base_dn)
+ log_fatal ("no memory for ldap password");
+ memcpy (ldap_base_dn, db.data, db.len);
+ ldap_base_dn[db.len] = 0;
+ data_string_forget (&db, MDL);
+ }
+
+ oc = lookup_option (&server_universe, options, SV_LDAP_METHOD);
+ if (oc &&
+ evaluate_option_cache (&db, (struct packet*) NULL,
+ (struct lease *) NULL, (struct client_state *) NULL,
+ options, (struct option_state *) NULL, &global_scope, oc, MDL))
+ {
+
+ if (db.len == 1)
+ ldap_method = db.data [0];
+ else
+ log_fatal ("invalid dns update type");
+ data_string_forget (&db, MDL);
+ }
+
+ option_state_dereference (&options, MDL);
+ }
+
+ if (ldap_server == NULL || ldap_username == NULL || ldap_password == NULL ||
+ ldap_base_dn == NULL)
+ {
+ log_info ("Not searching LDAP since ldap-server, ldap-port, ldap-username, ldap-password and ldap-baes-dn were not specified in the config file");
+ disable_ldap = 1;
+ return;
+ }
+
+#if defined (DEBUG_LDAP)
+ log_info ("Connecting to LDAP server ldap://%s", ldap_server);
+#endif
+
+ char *tmpserver = NULL;
+ if ((tmpserver = malloc(strlen(ldap_server) + 8)) == NULL)
+ {
+ log_error ("Cannot init tmpldapserver string to ldap://%s", ldap_server);
+ disable_ldap = 1;
+ return;
+ }
+
+ if (sprintf(tmpserver, "ldap://%s", ldap_server) == -1)
+ {
+ log_error ("Cannot init tmpldapserver via sprintf()");
+ disable_ldap = 1;
+ return;
+ }
+
+ ldap_initialize (&ld, tmpserver);
+ if (ld == NULL)
+ {
+ log_error ("Cannot init ldap session to %s", ldap_server);
+ disable_ldap = 1;
+ return;
+ }
+
+ free (tmpserver);
+
+ struct berval cred;
+ cred.bv_val = strdup(ldap_password);
+ cred.bv_len = strlen(ldap_password);
+ ret = ldap_sasl_bind_s (ld, ldap_username, LDAP_SASL_SIMPLE,
+ &cred, NULL,NULL, NULL);
+ if (ret != LDAP_SUCCESS)
+ {
+ log_error ("Error: Cannot log into ldap server %s: %s", ldap_server,
+ ldap_err2string (ret));
+ disable_ldap = 1;
+ ldap_unbind_ext (ld, NULL, NULL);
+ ld = NULL;
+ return;
+ }
+
+#if defined (DEBUG_LDAP)
+ log_info ("Successfully logged into LDAP server %s", ldap_server);
+#endif
+}
+
+
+static int
+ldap_read_function (struct parse *cfile)
+{
+ char *dn, eofstring[2] = {EOF, '\0'};
+ struct ldap_config_stack *curentry;
+ LDAPMessage * ent, * res;
+ int ret;
+
+ cfile->inbuf[0] = '\0';
+ cfile->buflen = 0;
+ while (1)
+ {
+ if (ldap_stack == NULL)
+ {
+ strncat (cfile->inbuf, eofstring, LDAP_BUFFER_SIZE);
+ cfile->buflen = strlen (cfile->inbuf);
+ cfile->bufix = 1;
+ return (cfile->inbuf[0]);
+ }
+
+ if (ldap_stack->processed && ldap_stack->children != NULL)
+ curentry = ldap_stack->children;
+ else
+ curentry = ldap_stack;
+
+ dn = ldap_get_dn (ld, curentry->ldent);
+#if defined(DEBUG_LDAP)
+ log_info ("Found LDAP entry '%s'", dn);
+#endif
+
+ ldap_generate_config_string (curentry, cfile);
+ if (strlen (cfile->inbuf) == 0)
+ {
+#if defined(DEBUG_LDAP)
+ log_info ("Skipping LDAP entry '%s'", dn);
+#endif
+ ldap_memfree (dn);
+ dn = NULL;
+ next_ldap_entry (cfile);
+ continue;
+ }
+
+ curentry->processed = 1;
+ break;
+ }
+
+ if (ld == NULL)
+ ldap_start ();
+
+ if (ld == NULL)
+ {
+ strncat (cfile->inbuf, eofstring, LDAP_BUFFER_SIZE);
+ cfile->buflen = strlen (cfile->inbuf);
+ cfile->bufix = 1;
+ return (cfile->inbuf[0]);
+ }
+
+ if ((ret = ldap_search_ext_s (ld, dn, LDAP_SCOPE_ONELEVEL, "objectClass=*",
+ NULL, 0, NULL, NULL, NULL, 0,
+ &res)) != LDAP_SUCCESS)
+ {
+ ldap_unbind_ext (ld, NULL, NULL);
+ ld = NULL;
+
+ strncat (cfile->inbuf, eofstring, LDAP_BUFFER_SIZE);
+ cfile->buflen = strlen (cfile->inbuf);
+ cfile->bufix = 1;
+ return (cfile->inbuf[0]);
+ }
+
+ ldap_memfree (dn);
+
+ ent = ldap_first_entry (ld, res);
+ if (ent != NULL)
+ add_to_config_stack (res, ent);
+ else
+ {
+ ldap_msgfree (res);
+ next_ldap_entry (cfile);
+ }
+
+#if defined (DEBUG_LDAP)
+ log_info ("Sending config line '%s'", cfile->inbuf);
+#endif
+
+ cfile->buflen = strlen (cfile->inbuf);
+ cfile->bufix = 1;
+ return (cfile->inbuf[0]);
+}
+
+
+static char *
+ldap_get_host_name (LDAPMessage * ent)
+{
+ struct berval **name;
+ char *ret;
+
+ ret = NULL;
+ if ((name = ldap_get_values_len (ld, ent, "cn")) == NULL || name[0] == NULL)
+ {
+ if (name != NULL)
+ ldap_value_free_len (name);
+
+#if defined (DEBUG_LDAP)
+ log_info ("Cannot get cn attribute for LDAP entry %s",
+ ldap_get_dn (ld, ent));
+#endif
+ return (NULL);
+ }
+
+ ret = dmalloc (strlen (name[0]->bv_val) + 1, MDL);
+ strcpy (ret, name[0]->bv_val);
+ ldap_value_free_len (name);
+
+ return (ret);
+}
+
+
+isc_result_t
+ldap_read_config (void)
+{
+ struct berval **temp;
+ char *buffer, dn[256];
+ LDAPMessage * ldres, * ent;
+ struct parse *cfile;
+ struct utsname unme;
+ isc_result_t res;
+ int ret;
+
+
+ buffer = dmalloc (LDAP_BUFFER_SIZE, MDL);
+ cfile = (struct parse *) NULL;
+ res = new_parse (&cfile, -1, buffer, LDAP_BUFFER_SIZE, "LDAP", 0);
+ if (res != ISC_R_SUCCESS)
+ return (res);
+
+ cfile->bufix = cfile->buflen = 0;
+ cfile->read_function = ldap_read_function;
+
+ if (ld == NULL)
+ ldap_start ();
+ if (ld == NULL)
+ return (ldap_server == NULL ? ISC_R_SUCCESS : ISC_R_FAILURE);
+
+ uname (&unme);
+ snprintf (dn, sizeof (dn), "(&(objectClass=dhcpServer)(cn=%s))",
+ unme.nodename);
+
+ if ((ret = ldap_search_ext_s (ld, ldap_base_dn, LDAP_SCOPE_SUBTREE, dn, NULL,
+ 0, NULL, NULL, NULL, 0, &ldres)) != LDAP_SUCCESS)
+ {
+ ldap_unbind_ext (ld, NULL, NULL);
+ ld = NULL;
+ log_error ("Cannot search LDAP for %s: %s", dn, ldap_err2string (ret));
+ return (ISC_R_FAILURE);
+ }
+
+ if ((ent = ldap_first_entry (ld, ldres)) == NULL)
+ {
+ ldap_unbind_ext (ld, NULL, NULL);
+ ld = NULL;
+ log_error ("Error: Cannot find LDAP entry matching %s", dn);
+ return (ISC_R_FAILURE);
+ }
+
+#if defined(DEBUG_LDAP)
+ buffer = ldap_get_dn (ld, ent);
+ log_info ("Found LDAP entry '%s'", buffer);
+ ldap_memfree (buffer);
+#endif
+
+ if ((temp = ldap_get_values_len (ld, ent, "dhcpServiceDN")) == NULL ||
+ temp[0]->bv_val == NULL)
+ {
+ if (temp != NULL)
+ ldap_value_free_len (temp);
+
+ ldap_unbind_ext (ld, NULL, NULL);
+ ld = NULL;
+ log_error ("Error: Cannot find LDAP entry matching %s", dn);
+ return (ISC_R_FAILURE);
+ }
+
+ ldap_msgfree (ldres);
+
+ if ((ret = ldap_search_ext_s (ld, temp[0]->bv_val, LDAP_SCOPE_BASE,
+ "objectClass=*", NULL, 0,
+ NULL, NULL, NULL, 0, &ldres)) != LDAP_SUCCESS)
+ {
+ ldap_value_free_len (temp);
+ ldap_unbind_ext (ld, NULL, NULL);
+ ld = NULL;
+ log_error ("Cannot search LDAP for %s: %s", temp[0]->bv_val,
+ ldap_err2string (ret));
+ return (ISC_R_FAILURE);
+ }
+
+ if ((ent = ldap_first_entry (ld, ldres)) == NULL)
+ {
+ ldap_value_free_len (temp);
+ ldap_unbind_ext (ld, NULL, NULL);
+ ld = NULL;
+ log_error ("Error: Cannot find LDAP entry matching %s", temp[0]->bv_val);
+ return (ISC_R_FAILURE);
+ }
+
+ ldap_value_free_len (temp);
+
+ add_to_config_stack (ldres, ent);
+
+ res = conf_file_subparse (cfile, root_group, ROOT_GROUP);
+ end_parse (&cfile);
+
+ return (res);
+}
+
+
+/* This function will parse the dhcpOption and dhcpStatements field in the LDAP
+ entry if it exists. Right now, type will be either HOST_DECL or CLASS_DECL.
+ If we are parsing a HOST_DECL, this always returns 0. If we are parsing a
+ CLASS_DECL, this will return what the current lease limit is in LDAP. If
+ there is no lease limit specified, we return 0 */
+
+static int
+ldap_parse_options (LDAPMessage * ent, struct group *group,
+ int type, struct host_decl *host,
+ struct class **class)
+{
+ struct berval **temp;
+ char option_buffer[8192];
+ int i, declaration, lease_limit;
+ enum dhcp_token token;
+ struct parse *cfile;
+ isc_result_t res;
+ const char *val;
+
+ lease_limit = 0;
+ *option_buffer = '\0';
+ if ((temp = ldap_get_values_len (ld, ent, "dhcpStatements")) != NULL)
+ {
+ for (i=0; temp[i]->bv_val != NULL; i++)
+ {
+ if (strncasecmp ("lease limit ", temp[i]->bv_val, 12) == 0)
+ {
+ lease_limit = strtol ((temp[i]->bv_val) + 12, NULL, 10);
+ continue;
+ }
+
+ strncat (option_buffer, temp[i]->bv_val, sizeof (option_buffer) - strlen (option_buffer) - 1);
+ strncat (option_buffer, ";\n", sizeof (option_buffer) - strlen (option_buffer) - 1);
+ }
+ ldap_value_free_len (temp);
+ }
+
+ if ((temp = ldap_get_values_len (ld, ent, "dhcpOption")) != NULL)
+ {
+ for (i=0; temp[i]->bv_val != NULL; i++)
+ {
+ strncat (option_buffer, "option ", sizeof (option_buffer) - strlen (option_buffer) - 1);
+ strncat (option_buffer, temp[i]->bv_val, sizeof (option_buffer) - strlen (option_buffer) - 1);
+ strncat (option_buffer, ";\n", sizeof (option_buffer) - strlen (option_buffer) - 1);
+ }
+ ldap_value_free_len (temp);
+ }
+
+ if (*option_buffer == '\0')
+ return (lease_limit);
+
+ cfile = (struct parse *) NULL;
+ res = new_parse (&cfile, -1, option_buffer, strlen (option_buffer),
+ type == HOST_DECL ? "LDAP-HOST" : "LDAP-SUBCLASS", 0);
+ if (res != ISC_R_SUCCESS)
+ return (lease_limit);
+
+#if defined (DEBUG_LDAP)
+ log_info ("Sending the following options: '%s'", option_buffer);
+#endif
+
+ declaration = 0;
+ do {
+ token = peek_token (&val, NULL, cfile);
+ if (token == END_OF_FILE)
+ break;
+ declaration = parse_statement (cfile, group, type, host, declaration);
+ } while (1);
+
+ end_parse (&cfile);
+
+ return (lease_limit);
+}
+
+
+
+int
+find_haddr_in_ldap (struct host_decl **hp, int htype, unsigned hlen,
+ const unsigned char *haddr, const char *file, int line)
+{
+ char buf[60], *type_str;
+ LDAPMessage * res, *ent;
+ struct host_decl * host;
+ isc_result_t status;
+ int ret;
+
+ if (disable_ldap || ldap_method == LDAP_METHOD_STATIC)
+ return (0);
+
+ if (ld == NULL)
+ ldap_start ();
+ if (ld == NULL)
+ return (0);
+
+ switch (htype)
+ {
+ case HTYPE_ETHER:
+ type_str = "ethernet";
+ break;
+ case HTYPE_IEEE802:
+ type_str = "token-ring";
+ break;
+ case HTYPE_FDDI:
+ type_str = "fddi";
+ break;
+ default:
+ log_info ("Ignoring unknown type %d", htype);
+ return (0);
+ }
+
+ snprintf (buf, sizeof (buf), "dhcpHWAddress=%s %s", type_str,
+ print_hw_addr (htype, hlen, haddr));
+#if defined (DEBUG_LDAP)
+ log_info ("Searching for %s in LDAP tree %s", buf, ldap_base_dn);
+#endif
+
+ if ((ret = ldap_search_ext_s (ld, ldap_base_dn, LDAP_SCOPE_SUBTREE,
+ buf, NULL, 0, NULL, NULL, NULL, 0,
+ &res)) != LDAP_SUCCESS)
+ {
+ if (ret != LDAP_NO_SUCH_OBJECT)
+ {
+ log_error ("Cannot search for %s in LDAP tree %s: %s", buf,
+ ldap_base_dn, ldap_err2string (ret));
+ ldap_unbind_ext (ld, NULL, NULL);
+ ld = NULL;
+ }
+#if defined (DEBUG_LDAP)
+ else
+ log_info ("ldap_search_ext_s returned %s when searching for %s in %s",
+ ldap_err2string (ret), buf, ldap_base_dn);
+#endif
+
+ return (0);
+ }
+
+ if ((ent = ldap_first_entry (ld, res)) != NULL)
+ {
+#if defined (DEBUG_LDAP)
+ log_info ("Found LDAP entry %s", ldap_get_dn (ld, ent));
+#endif
+
+ host = (struct host_decl *)0;
+ status = host_allocate (&host, MDL);
+ if (status != ISC_R_SUCCESS)
+ {
+ log_fatal ("can't allocate host decl struct: %s",
+ isc_result_totext (status));
+ return (0);
+ }
+
+ host->name = ldap_get_host_name (ent);
+ if (host->name == NULL)
+ {
+ host_dereference (&host, MDL);
+ ldap_msgfree (res);
+ return (0);
+ }
+
+ if (!clone_group (&host->group, root_group, MDL))
+ {
+ log_fatal ("can't clone group for host %s", host->name);
+ host_dereference (&host, MDL);
+ return (0);
+ }
+
+ ldap_parse_options (ent, host->group, HOST_DECL, host, NULL);
+
+ *hp = host;
+ ldap_msgfree (res);
+ return (1);
+ }
+
+
+ ldap_msgfree (res);
+ return (0);
+}
+
+
+int
+find_subclass_in_ldap (struct class *class, struct class **newclass,
+ struct data_string *data)
+{
+ LDAPMessage * res, * ent;
+ int ret, lease_limit;
+ isc_result_t status;
+ char buf[1024];
+
+ if (disable_ldap || ldap_method == LDAP_METHOD_STATIC)
+ return (0);
+
+ if (ld == NULL)
+ ldap_start ();
+ if (ld == NULL)
+ return (0);
+
+ snprintf (buf, sizeof (buf), "(&(objectClass=dhcpSubClass)(cn=%s)(dhcpClassData=%s))", print_hex_1 (data->len, data->data, 60), print_hex_2 (strlen (class->name), (const u_int8_t *) class->name, 60));
+#if defined (DEBUG_LDAP)
+ log_info ("Searching LDAP for %s", buf);
+#endif
+
+ if ((ret = ldap_search_ext_s (ld, ldap_base_dn, LDAP_SCOPE_SUBTREE,
+ buf, NULL, 0, NULL, NULL, NULL, 0,
+ &res)) != LDAP_SUCCESS)
+ {
+ if (ret != LDAP_NO_SUCH_OBJECT)
+ {
+ log_error ("Cannot search for %s in LDAP tree %s: %s", buf,
+ ldap_base_dn, ldap_err2string (ret));
+ ldap_unbind_ext (ld, NULL, NULL);
+ ld = NULL;
+ }
+#if defined (DEBUG_LDAP)
+ else
+ log_info ("ldap_search_ext_s returned %s when searching for %s in %s",
+ ldap_err2string (ret), buf, ldap_base_dn);
+#endif
+
+ return (0);
+ }
+
+ if ((ent = ldap_first_entry (ld, res)) != NULL)
+ {
+#if defined (DEBUG_LDAP)
+ log_info ("Found LDAP entry %s", ldap_get_dn (ld, ent));
+#endif
+
+ status = class_allocate (newclass, MDL);
+ if (status != ISC_R_SUCCESS)
+ {
+ log_error ("Cannot allocate memory for a new class");
+ return (0);
+ }
+
+ group_reference (&(*newclass)->group, class->group, MDL);
+ class_reference (&(*newclass)->superclass, class, MDL);
+ lease_limit = ldap_parse_options (ent, (*newclass)->group,
+ CLASS_DECL, NULL, newclass);
+ if (lease_limit == 0)
+ (*newclass)->lease_limit = class->lease_limit;
+ else
+ class->lease_limit = lease_limit;
+
+ if ((*newclass)->lease_limit)
+ {
+ (*newclass)->billed_leases =
+ dmalloc ((*newclass)->lease_limit * sizeof (struct lease *), MDL);
+ if (!(*newclass)->billed_leases)
+ {
+ log_error ("no memory for billing");
+ class_dereference (newclass, MDL);
+ return (0);
+ }
+ memset ((*newclass)->billed_leases, 0,
+ ((*newclass)->lease_limit * sizeof (*newclass)->billed_leases));
+ }
+
+ data_string_copy (&(*newclass)->hash_string, data, MDL);
+
+ ldap_msgfree (res);
+ return (1);
+ }
+
+
+ ldap_msgfree (res);
+ return (0);
+}
+
+#endif
+
--- dhcp-3.0.5/server/mdb.c.ldapconf 2007-01-31 20:39:38.000000000 -0500
+++ dhcp-3.0.5/server/mdb.c 2007-01-31 20:39:38.000000000 -0500
@@ -373,6 +373,12 @@
const char *file, int line)
{
struct hardware h;
+ int ret;
+
+#if defined(LDAP_CONFIGURATION)
+ if ((ret = find_haddr_in_ldap (hp, htype, hlen, haddr, file, line)))
+ return ret;
+#endif
h.hlen = hlen + 1;
h.hbuf [0] = htype;
--- dhcp-3.0.5/server/stables.c.ldapconf 2004-06-10 13:59:58.000000000 -0400
+++ dhcp-3.0.5/server/stables.c 2007-01-31 20:39:38.000000000 -0500
@@ -483,12 +483,21 @@
{ "log-facility", "Nsyslog-facilities.", &server_universe, 44 },
{ "do-forward-updates", "f", &server_universe, 45 },
{ "ping-timeout", "T", &server_universe, 46 },
+#if defined(LDAP_CONFIGURATION)
+ { "ldap-server", "t", &server_universe, 47 },
+ { "ldap-port", "d", &server_universe, 48 },
+ { "ldap-username", "t", &server_universe, 49 },
+ { "ldap-password", "t", &server_universe, 50 },
+ { "ldap-base-dn", "t", &server_universe, 51 },
+ { "ldap-method", "Nldap-methods.", &server_universe, 52 },
+#else
{ "unknown-47", "X", &server_universe, 47 },
{ "unknown-48", "X", &server_universe, 48 },
{ "unknown-49", "X", &server_universe, 49 },
{ "unknown-50", "X", &server_universe, 50 },
{ "unknown-51", "X", &server_universe, 51 },
{ "unknown-52", "X", &server_universe, 52 },
+#endif
{ "unknown-53", "X", &server_universe, 53 },
{ "unknown-54", "X", &server_universe, 54 },
{ "unknown-55", "X", &server_universe, 55 },
@@ -694,6 +703,20 @@
{ "option-end", "e", &server_universe, 255 },
};
+#if defined(LDAP_CONFIGURATION)
+struct enumeration_value ldap_values [] = {
+ { "static", LDAP_METHOD_STATIC },
+ { "dynamic", LDAP_METHOD_DYNAMIC },
+ { (char *) 0, 0 }
+};
+
+struct enumeration ldap_methods = {
+ (struct enumeration *)0,
+ "ldap-methods",
+ ldap_values
+};
+#endif
+
struct enumeration_value ddns_styles_values [] = {
{ "none", 0 },
{ "ad-hoc", 1 },
--- /dev/null 2007-01-31 10:24:38.956568237 -0500
+++ dhcp-3.0.5/README.ldap 2007-01-31 20:39:38.000000000 -0500
@@ -0,0 +1,157 @@
+LDAP Support in DHCP
+Brian Masney <masneyb@ntelos.net>
+Last updated 8/16/2002
+
+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://home.ntelos.net/~masneyb.
+
+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
+/usr/local/openldap/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 be ready to build DHCP. Edit the includes/site.h file and uncomment
+the #define LDAP_CONFIGURATION. Now run configure in the base source directory.
+Edit the work.os/server/Makefile and add -lldap to the LIBS= line. (replace os
+with your operating system, linux-2.2 on my machine). You should be able to
+type make to build your DHCP server.
+
+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;
+
+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.
+
+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
+contrib/dhcpd-conf-to-ldap.pl that will convert it for you.
+
+# 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 ad-hoc
+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 slapadd 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).
+
--- dhcp-3.0.5/site.conf.ldapconf 1999-07-07 11:20:10.000000000 -0400
+++ dhcp-3.0.5/site.conf 2007-01-31 20:39:38.000000000 -0500
@@ -1,2 +1,7 @@
-# Put local site configuration stuff here to override the default
-# settings in Makefile.conf
+VARDB=/var/lib/dhcpd
+ADMMANDIR=/usr/share/man/man8
+FFMANDIR=/usr/share/man/man5
+LIBMANDIR=/usr/share/man/man3
+USRMANDIR=/usr/share/man/man1
+LIBDIR=/usr/lib
+INCDIR=/usr/include