Commit 98bd7ca0 authored by David Hankins's avatar David Hankins

DHCPv6 branch merged to HEAD.

parent 74dc3e0b
......@@ -131,6 +131,7 @@ MINORVERSION=MinorVersion
#COPTS = $(BINDDEF) -Wall -Wno-unused -Wno-implicit -Wno-comment \
# -Wno-uninitialized -Wno-char-subscripts -Wno-switch $(WARNERR) \
# -DSOLARIS_MAJOR=$(MAJORVERSION) -DSOLARIS_MINOR=$(MINORVERSION) \
# -D_XPG4_2 -D__EXTENSIONS__ \
# $(CC_OPTIONS)
#CF = cf/sunos5-5.h
#ADMMANDIR = /usr/share/man/man1m
......
Internet Systems Consortium DHCP Distribution
Version 3.1.0a1
August 1, 2006
Version 4.0.0-2007041300
April 13, 2007
README FILE
**********************************************************************
*** This is NOT a public release, and should not be redistributed. ***
**********************************************************************
You should read this file carefully before trying to install or use
the ISC DHCP Distribution.
......@@ -92,24 +96,18 @@ directory, it may not have up-to-date information).
RELEASE STATUS
This is the first ALPHA quality release of ISC DHCP 3.1.0, a feature
release based upon the work present in the 3.0.x development track.
It contains a large number of new features, and with that most likely
many new bugs.
This is a snapshot release of work leading up to the first alpha
of ISC DHCP 4.0.0, a feature release bent to the purpose of implemeting
DHCPv6.
In this release, the server and relay agent are currently fully
functional on NetBSD, Linux systems with kernel version 2.2 or later,
FreeBSD, OpenBSD, BSD/OS, Digital Tru64 Unix and Solaris. The software
will also run on AIX and HP-UX, but only supports a single network
interface. Ports also exist for QNX, SCO, NeXTStep, and MacOS X, but
are not in wide use, with all that implies. We are not aware of an
easy way to get this software running on HP-UX.
functional on Linux, and Solaris. The software may also runon other
systems.
The DHCP client currently only knows how to configure the network on
NetBSD, FreeBSD, OpenBSD, BSD/os, Linux, Solaris and NextStep. The
client depends on a system-dependent shell script to do network
configuration - support for other operating systems is simply a matter
of porting this shell script to the new platform.
Linux. The client depends on a system-dependent shell script to do
network configuration - support for other operating systems is simply
a matter of porting this shell script to the new platform.
If you are running the DHCP distribution on a machine which is a
firewall, or if there is a firewall between your DHCP server(s) and
......@@ -138,13 +136,13 @@ information. On Digital Unix, type ``man pfilt''.
To build the DHCP Distribution, unpack the compressed tar file using
the tar utility and the gzip command - type something like:
gunzip dhcp-3.1.0a1.tar.gz
tar xvf dhcp-3.1.0a1.tar
gunzip dhcp-4.0.0-2007041300.tar.gz
tar xvf dhcp-4.0.0-2007041300.tar
CONFIGURING IT
Now, cd to the dhcp-3.1.0a1 subdirectory that you've just created and
configure the source tree by typing:
Now, cd to the dhcp-dhcp-4.0.0-2007041300 subdirectory that you've
just created and configure the source tree by typing:
./configure
......
Internet Systems Consortium DHCP Distribution
Version 3.1.0a1
August 1, 2006
Version V4.0.0-2007041300
April 13, 2007
**********************************************************************
*** This is NOT a public release, and should not be redistributed. ***
**********************************************************************
Release Notes
NEW FEATURES
Version 3.1.x of the ISC DHCP Distribution includes the following major
new features compared to its 3.0.x derivative:
The DHCP server in version 4.0.x of the ISC DHCP Distribution supports
DHCPv6 in addition to DHCP for IPv4.
Several new options have been added to the dhcpd executable, which are
documented in the man page. Several changes have been made to the
configuration file as well, which are also documented in the man
pages.
There are a number of DHCPv6 limitiations and features missing in this
release, which will be addressed shortly:
- Only Solaris and Linux are supported.
- There is no DHCPv6 Relay support.
- Only a single fixed address is supported per IA.
- IA_TA addresses are not supported.
- Failover protocol 'MAC Address Affinity' to reduce pool churn.
- Support for the 'reserved' and 'bootp' failover flags, which
means in lay terms that static allocations can be made to
clients in which 'on events' can be supported.
- Several other failover optimizations and changes.
- Management of class and subclass statements via OMAPI.
- Many new configuration statement functions.
- Initial formal support for VIVCO/VIVSO options.
- IA_PD prefixes are not supported.
For a full list of new features added in this release, please observe
the changes list directly following this section.
- DHCPv6 includes human-readable text in status code messages. These
should be configurable, and probably localized via gettext() or the
like.
- The "host-identifier" option is limited to a simple token.
- Dynamically allocated leases do not respond to Confirm messages.
- Old (expired) leases are never cleaned.
- The client and server can only operate DHCPv4 or DHCPv6 at a time,
not both, so two instances of the daemons are required with the
"-6" command line option.
For information on how to install, configure and run this software,
as well as how to find documentation and report bugs, please consult
the README file.
Changes since 3.1.0b1
Changes since 4.0.0-20070413
- An obviated option code hash lookup to find D6O_CLIENTID was removed.
Changes since 3.1.0 (NEW FEATURES)
- DHCPv6 Client and Server protocol support. Use '-6' to run the daemons
as v6-only. Use '-4' to run the daemons as v4-only (default. There is
no support currently for both.
- Server support for multiple IA_NA options, containing at most one
IAADDR option.
- Client support for one IA_NA option, containing any number of IAADDR
options.
- Server support for the DHCPv6 Information-request message.
- Inappropriate unicast DHCPv6 messages sent to the server are now
discarded, and this has rearchitected the IO system slightly.
- The DHCPv6 server DUID defaults to type 1, is persistently stored in
the leases database, and can be over-ridden (either completely, or by
specifying type 1 or type 2).
- The server only uses Rapid-Commit if it has been configured with the
Rapid-Commit option and the client requests it.
- DDNS support. We now update AAAA records in the same place we would
update A records, if we have an IPv6 address. We also generate IP6.ARPA
style names for PTR records if we're dealing with an IPv6 address. Both
A and AAAA updates are done using the same 'fqdn.' virtual option space
(although the DHCPv4 FQDN and DHCPv6 FQDN options are formatted
differently, they both use the same code here).
- The Linux dhclient-script attempts to set and remove assigned addresses,
and to configure /etc/resolv.conf from nameserver and domain name
configurations. It can be extended to configure other parameters.
- Initial DHCPv6 lease support.
- The IO system now tracks all local IP addresses, so that the DHCP
applications (particularly the dhcrelay) can discern between what frames
were transmitted to it, and what frames are being carried through it which
it should not intercept.
Chagnes since 3.1.0b1
- Fixed a bug that caused OMAPI clients to freeze when opening lease
objects.
......@@ -104,7 +175,7 @@ the README file.
server responses, if they contain a valid DHCP_MESSAGE_TYPE (OFFER, ACK,
or NAK). The server will continue to not accept corrupt client packets.
- Support for 'reserved' (psuedo-static) and BOOTP leases via failover
- Support for 'reserved' (pseudo-static) and BOOTP leases via failover
was introduced.
- Support for adding, removing, and managing class and subclass statements
......@@ -409,7 +480,7 @@ the README file.
- Failover peers no longer bother to look for free leases to allocate when
they already found the client's ACTIVE lease. DISCOVERs are load balanced
wether freely-allocated or not, unless the server doubts the peer has
whether freely-allocated or not, unless the server doubts the peer has
leases to allocate.
- Fixed a bug in dhcrelay agent addition code that suppressed trailing
......@@ -498,7 +569,7 @@ the README file.
Thanks to a patch from Jason Vas Dias at RedHat.
- File handlers on configuration state (config files and lease dbs) should
be treated consistently, regardless of wether TRACING is defined or not.
be treated consistently, regardless of whether TRACING is defined or not.
- The linux build environment has had some minor improvements - better
sensing of 64-bit pointer sizes (only used for establishing an icmp_id),
......
......@@ -25,8 +25,8 @@ CATMANPAGES = dhclient.cat8 dhclient.conf.cat5 dhclient-script.cat8 \
dhclient.leases.cat5
SEDMANPAGES = dhclient.man8 dhclient.conf.man5 dhclient-script.man8 \
dhclient.leases.man5
SRCS = dhclient.c clparse.c
OBJS = dhclient.o clparse.o
SRCS = dhclient.c clparse.c dhc6.c
OBJS = dhclient.o clparse.o dhc6.o
PROG = dhclient
MAN = dhclient.8 dhclient.conf.5 dhclient-script.8 dhclient.leases.5
......
......@@ -34,7 +34,7 @@
#ifndef lint
static char copyright[] =
"$Id: clparse.c,v 1.68 2007/01/29 10:25:54 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
"$Id: clparse.c,v 1.69 2007/05/08 23:05:20 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
......@@ -54,6 +54,11 @@ u_int32_t default_requested_options [] = {
0
};
static void parse_client_default_duid(struct parse *cfile);
static void parse_client6_lease_statement(struct parse *cfile);
static struct dhc6_ia *parse_client6_ia_statement(struct parse *cfile);
static struct dhc6_addr *parse_client6_iaaddr_statement(struct parse *cfile);
/* client-conf-file :== client-declarations END_OF_FILE
client-declarations :== <nil>
| client-declaration
......@@ -66,9 +71,6 @@ isc_result_t read_client_conf ()
struct interface_info *ip;
isc_result_t status;
/* Set up the initial dhcp option universe. */
initialize_common_option_spaces ();
/* Initialize the top level client configuration. */
memset (&top_level_config, 0, sizeof top_level_config);
......@@ -84,6 +86,9 @@ isc_result_t read_client_conf ()
top_level_config.requested_options = default_requested_options;
top_level_config.omapi_port = -1;
top_level_config.do_forward_update = 1;
/* Requested lease time, used by DHCPv6 (DHCPv4 uses the option cache)
*/
top_level_config.requested_lease = 7200;
group_allocate (&top_level_config.on_receipt, MDL);
if (!top_level_config.on_receipt)
......@@ -200,13 +205,25 @@ void read_client_leases ()
token = next_token (&val, (unsigned *)0, cfile);
if (token == END_OF_FILE)
break;
if (token != LEASE) {
switch (token) {
case DEFAULT_DUID:
parse_client_default_duid(cfile);
break;
case LEASE:
parse_client_lease_statement(cfile, 0);
break;
case LEASE6:
parse_client6_lease_statement(cfile);
break;
default:
log_error ("Corrupt lease file - possible data loss!");
skip_to_semi (cfile);
break;
} else
parse_client_lease_statement (cfile, 0);
}
} while (1);
end_parse (&cfile);
......@@ -825,7 +842,7 @@ void make_client_config (client, config)
}
/* client-lease-statement :==
RBRACE client-lease-declarations LBRACE
LBRACE client-lease-declarations RBRACE
client-lease-declarations :==
<nil> |
......@@ -1071,6 +1088,505 @@ void parse_client_lease_declaration (cfile, lease, ipp, clientp)
}
}
/* Parse a default-duid ""; statement.
*/
static void
parse_client_default_duid(struct parse *cfile)
{
struct data_string new_duid;
const char *val = NULL;
unsigned len;
int token;
memset(&new_duid, 0, sizeof(new_duid));
token = next_token(&val, &len, cfile);
if (token != STRING) {
parse_warn(cfile, "Expected DUID string.");
skip_to_semi(cfile);
return;
}
if (len <= 2) {
parse_warn(cfile, "Invalid DUID contents.");
skip_to_semi(cfile);
return;
}
if (!buffer_allocate(&new_duid.buffer, len, MDL)) {
parse_warn(cfile, "Out of memory parsing default DUID.");
skip_to_semi(cfile);
return;
}
new_duid.data = new_duid.buffer->data;
new_duid.len = len;
memcpy(new_duid.buffer->data, val, len);
/* Rotate the last entry into place. */
if (default_duid.buffer != NULL)
data_string_forget(&default_duid, MDL);
data_string_copy(&default_duid, &new_duid, MDL);
data_string_forget(&new_duid, MDL);
parse_semi(cfile);
}
/* Parse a lease6 {} construct. The v6 client is a little different
* than the v4 client today, in that it only retains one lease, the
* active lease, and discards any less recent information. It may
* be useful in the future to cache additional information, but it
* is not worth the effort for the moment.
*/
static void
parse_client6_lease_statement(struct parse *cfile)
{
struct option_cache *oc = NULL;
struct dhc6_lease *lease;
struct dhc6_ia **ia;
struct client_state *client = NULL;
struct interface_info *iface = NULL;
struct data_string ds;
const char *val;
unsigned len;
int token, has_ia, no_semi, has_name;
token = next_token(NULL, NULL, cfile);
if (token != LBRACE) {
parse_warn(cfile, "Expecting open curly brace.");
skip_to_semi(cfile);
return;
}
lease = dmalloc(sizeof(*lease), MDL);
if (lease == NULL) {
parse_warn(cfile, "Unable to allocate lease state.");
skip_to_rbrace(cfile, 1);
return;
}
option_state_allocate(&lease->options, MDL);
if (lease->options == NULL) {
parse_warn(cfile, "Unable to allocate option cache.");
skip_to_rbrace(cfile, 1);
dfree(lease, MDL);
return;
}
has_ia = 0;
has_name = 0;
ia = &lease->bindings;
token = next_token(&val, NULL, cfile);
while (token != RBRACE) {
no_semi = 0;
switch(token) {
case IA_NA:
*ia = parse_client6_ia_statement(cfile);
if (*ia != NULL) {
ia = &(*ia)->next;
has_ia = 1;
}
no_semi = 1;
break;
case INTERFACE:
if (iface != NULL) {
parse_warn(cfile, "Multiple interface names?");
skip_to_semi(cfile);
no_semi = 1;
break;
}
token = next_token(&val, &len, cfile);
if (token != STRING) {
strerror:
parse_warn(cfile, "Expecting a string.");
skip_to_semi(cfile);
no_semi = 1;
break;
}
for (iface = interfaces ; iface != NULL ;
iface = iface->next) {
if (strcmp(iface->name, val) == 0)
break;
}
if (iface == NULL) {
parse_warn(cfile, "Unknown interface.");
break;
}
break;
case NAME:
has_name = 1;
if (client != NULL) {
parse_warn(cfile, "Multiple state names?");
skip_to_semi(cfile);
no_semi = 1;
break;
}
if (iface == NULL) {
parse_warn(cfile, "Client name without "
"interface.");
skip_to_semi(cfile);
no_semi = 1;
break;
}
token = next_token(&val, &len, cfile);
if (token != STRING)
goto strerror;
for (client = iface->client ; client != NULL ;
client = client->next) {
if ((client->name != NULL) &&
(strcmp(client->name, val) == 0))
break;
}
if (client == NULL) {
parse_warn(cfile, "Unknown client state %s.",
val);
break;
}
break;
case OPTION:
if (parse_option_decl(&oc, cfile)) {
save_option(oc->option->universe,
lease->options, oc);
option_cache_dereference(&oc, MDL);
}
no_semi = 1;
break;
default:
parse_warn(cfile, "Unexpected token, %s.", val);
no_semi = 1;
skip_to_semi(cfile);
break;
}
if (!no_semi)
parse_semi(cfile);
token = next_token(&val, NULL, cfile);
if (token == END_OF_FILE) {
parse_warn(cfile, "Unexpected end of file.");
break;
}
}
if (!has_ia) {
log_debug("Lease with no IA's discarded from lease db.");
dhc6_lease_destroy(lease, MDL);
return;
}
if (iface == NULL)
parse_warn(cfile, "Lease has no interface designation.");
if (!has_name && (client == NULL)) {
for (client = iface->client ; client != NULL ;
client = client->next) {
if (client->name == NULL)
break;
}
}
if (client == NULL) {
parse_warn(cfile, "No matching client state.");
dhc6_lease_destroy(lease, MDL);
return;
}
/* Fetch Preference option from option cache. */
memset(&ds, 0, sizeof(ds));
oc = lookup_option(&dhcpv6_universe, lease->options, D6O_PREFERENCE);
if ((oc != NULL) &&
evaluate_option_cache(&ds, NULL, NULL, NULL, lease->options,
NULL, &global_scope, oc, MDL)) {
if (ds.len != 1) {
log_error("Invalid length of DHCPv6 Preference option "
"(%d != 1)", ds.len);
data_string_forget(&ds, MDL);
dhc6_lease_destroy(lease, MDL);
return;
} else
lease->pref = ds.data[0];
data_string_forget(&ds, MDL);
}
/* Fetch server-id option from option cache. */
oc = lookup_option(&dhcpv6_universe, lease->options, D6O_SERVERID);
if ((oc == NULL) ||
!evaluate_option_cache(&lease->server_id, NULL, NULL, NULL,
lease->options, NULL, &global_scope, oc,
MDL) ||
(lease->server_id.len == 0)) {
/* This should be impossible... */
log_error("Invalid SERVERID option cache.");
dhc6_lease_destroy(lease, MDL);
return;
}
if (client->active_lease != NULL)
dhc6_lease_destroy(client->active_lease, MDL);
client->active_lease = lease;
}
/* Parse an ia_na object from the client lease.
*/
static struct dhc6_ia *
parse_client6_ia_statement(struct parse *cfile)
{
struct data_string id;
struct option_cache *oc = NULL;
struct dhc6_ia *ia;
struct dhc6_addr **addr;
const char *val;
unsigned len;
int token, no_semi;
ia = dmalloc(sizeof(*ia), MDL);
if (ia == NULL) {
parse_warn(cfile, "Out of memory allocating IA_NA state.");
skip_to_semi(cfile);
return NULL;
}