Commit d7d9c0c7 authored by Shawn Routhier's avatar Shawn Routhier

-n [master]

Add code to support the standards version of DDNS
parent 1d851cff
# Makefile.in generated by automake 1.13.1 from Makefile.am.
# Makefile.in generated by automake 1.14 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2012 Free Software Foundation, Inc.
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
......@@ -15,23 +15,51 @@
@SET_MAKE@
VPATH = @srcdir@
am__make_dryrun = \
{ \
am__dry=no; \
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
| grep '^AM OK$$' >/dev/null || am__dry=yes;; \
*) \
for am__flg in $$MAKEFLAGS; do \
case $$am__flg in \
*=*|--*) ;; \
*n*) am__dry=yes; break;; \
esac; \
done;; \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
test $$am__dry = yes; \
}
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
......@@ -54,7 +82,8 @@ subdir = .
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/configure $(am__configure_deps) \
$(top_srcdir)/doc/devel/doxyfile.in $(nobase_include_HEADERS) \
README config.guess config.sub depcomp install-sh missing
README compile config.guess config.sub depcomp install-sh \
missing
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
......@@ -380,13 +409,12 @@ uninstall-nobase_includeHEADERS:
# (which will cause the Makefiles to be regenerated when you run 'make');
# (2) otherwise, pass the desired values on the 'make' command line.
$(am__recursive_targets):
@fail= failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
*=* | --[!k]*);; \
*k*) failcom='fail=yes';; \
esac; \
done; \
@fail=; \
if $(am__make_keepgoing); then \
failcom='fail=yes'; \
else \
failcom='exit 1'; \
fi; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
case "$@" in \
......@@ -561,10 +589,16 @@ dist-xz: distdir
$(am__post_remove_distdir)
dist-tarZ: distdir
@echo WARNING: "Support for shar distribution archives is" \
"deprecated." >&2
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
$(am__post_remove_distdir)
dist-shar: distdir
@echo WARNING: "Support for distribution archives compressed with" \
"legacy program 'compress' is deprecated." >&2
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
$(am__post_remove_distdir)
......
......@@ -75,6 +75,15 @@ work on other platforms. Please report any problems and suggested fixes to
- Add support for using classes with v6.
[ISC-Bugs #26510]
- Update the DDNS code to current standards and allow for sharing
of DDNS entries between v4 and v6 clients. The new code is used
if the ddns-update-style is set to "standard", the older code is
still available if ddns-update-style is set to "interim". The
oldest DDNS code "ad-hoc" has been removed. Thanks to Thomas Pegeot
who submitted a patch for this issue. This patch is based on
that work with some modifications.
[ISC-Bugs 21139]
Changes since 4.2.5
- Address static analysis warnings.
......
This diff is collapsed.
# Makefile.in generated by automake 1.13.1 from Makefile.am.
# Makefile.in generated by automake 1.14 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2012 Free Software Foundation, Inc.
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
......@@ -16,23 +16,51 @@
VPATH = @srcdir@
am__make_dryrun = \
{ \
am__dry=no; \
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
| grep '^AM OK$$' >/dev/null || am__dry=yes;; \
*) \
for am__flg in $$MAKEFLAGS; do \
case $$am__flg in \
*=*|--*) ;; \
*n*) am__dry=yes; break;; \
esac; \
done;; \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
test $$am__dry = yes; \
}
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
......@@ -347,6 +375,7 @@ uninstall-sbinPROGRAMS:
clean-sbinPROGRAMS:
-test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS)
dhclient$(EXEEXT): $(dhclient_OBJECTS) $(dhclient_DEPENDENCIES) $(EXTRA_dhclient_DEPENDENCIES)
@rm -f dhclient$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(dhclient_OBJECTS) $(dhclient_LDADD) $(LIBS)
......@@ -366,14 +395,14 @@ distclean-compile:
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
install-man5: $(man_MANS)
@$(NORMAL_INSTALL)
@list1=''; \
......
......@@ -119,69 +119,6 @@ static int check_timing6(struct client_state *client, u_int8_t msg_type,
extern int onetry;
extern int stateless;
/*
* The "best" default DUID, since we cannot predict any information
* about the system (such as whether or not the hardware addresses are
* integrated into the motherboard or similar), is the "LLT", link local
* plus time, DUID. For real stateless "LL" is better.
*
* Once generated, this duid is stored into the state database, and
* retained across restarts.
*
* For the time being, there is probably a different state database for
* every daemon, so this winds up being a per-interface identifier...which
* is not how it is intended. Upcoming rearchitecting the client should
* address this "one daemon model."
*/
void
form_duid(struct data_string *duid, const char *file, int line)
{
struct interface_info *ip;
int len;
/* For now, just use the first interface on the list. */
ip = interfaces;
if (ip == NULL)
log_fatal("Impossible condition at %s:%d.", MDL);
if ((ip->hw_address.hlen == 0) ||
(ip->hw_address.hlen > sizeof(ip->hw_address.hbuf)))
log_fatal("Impossible hardware address length at %s:%d.", MDL);
if (duid_type == 0)
duid_type = stateless ? DUID_LL : DUID_LLT;
/*
* 2 bytes for the 'duid type' field.
* 2 bytes for the 'htype' field.
* (DUID_LLT) 4 bytes for the 'current time'.
* enough bytes for the hardware address (note that hw_address has
* the 'htype' on byte zero).
*/
len = 4 + (ip->hw_address.hlen - 1);
if (duid_type == DUID_LLT)
len += 4;
if (!buffer_allocate(&duid->buffer, len, MDL))
log_fatal("no memory for default DUID!");
duid->data = duid->buffer->data;
duid->len = len;
/* Basic Link Local Address type of DUID. */
if (duid_type == DUID_LLT) {
putUShort(duid->buffer->data, DUID_LLT);
putUShort(duid->buffer->data + 2, ip->hw_address.hbuf[0]);
putULong(duid->buffer->data + 4, cur_time - DUID_TIME_EPOCH);
memcpy(duid->buffer->data + 8, ip->hw_address.hbuf + 1,
ip->hw_address.hlen - 1);
} else {
putUShort(duid->buffer->data, DUID_LL);
putUShort(duid->buffer->data + 2, ip->hw_address.hbuf[0]);
memcpy(duid->buffer->data + 4, ip->hw_address.hbuf + 1,
ip->hw_address.hlen - 1);
}
}
/*
* Assign DHCPv6 port numbers as a client.
*/
......
.\" $Id: dhclient.8,v 1.36 2011/04/15 21:58:12 sar Exp $
.\"
.\" Copyright (c) 2004,2007-2012 by Internet Systems Consortium, Inc. ("ISC")
.\" Copyright (c) 2004,2007-2013 by Internet Systems Consortium, Inc. ("ISC")
.\" Copyright (c) 1996-2003 by Internet Software Consortium
.\"
.\" Permission to use, copy, modify, and distribute this software for any
......@@ -56,6 +56,12 @@ dhclient - Dynamic Host Configuration Protocol Client
]
]
[
.B -i
]
[
.B -I
]
[
.B -D
.I LL|LLT
]
......@@ -322,6 +328,17 @@ Set the giaddr field of all packets to the \fIrelay\fR IP address
simulating a relay agent. This is for testing pruposes only and
should not be expected to work in any consistent or useful way.
.TP
.BI \-i
Use a DUID with DHCPv4 clients. If no DUID is available in the
lease file one will be constructed and saved. The DUID will be
used to contstuct a RFC4361 style client id that will be included
in the client's messages. This client id can be overridden by
setting a client id in the configuration file. Overridding the
client id in this fashion is discouraged.
.TP
.BI \-I
Use the standard DDNS scheme from RFCs 4701 & 4702.
.TP
.BI \--version
Print version number and exit.
.PP
......@@ -351,8 +368,10 @@ DHCPv6 \fBdhclient\fR creates an identifier based on the link-layer address
(DUID-LL) if it is running in stateless mode (with \fB\-S\fR, not
requesting an address), or it creates an identifier based on the
link-layer address plus a timestamp (DUID-LLT) if it is running in
stateful mode (without \fB\-S\fR, requesting an address). \fB\-D\fR
overrides this default, with a value of either \fILL\fR or \fILLT\fR.
stateful mode (without \fB\-S\fR, requesting an address). When DHCPv4
is configued to use a DUID using \fB\-i\fR option the default is to use
a DUID-LLT. \fB\-D\fR
overrides these default, with a value of either \fILL\fR or \fILLT\fR.
.TP
.BI \-N
.\" TODO: is this for telling an already running dhclient?
......
......@@ -62,6 +62,8 @@ struct sockaddr_in sockaddr_broadcast;
struct in_addr giaddr;
struct data_string default_duid;
int duid_type = 0;
int duid_v4 = 0;
int std_dhcid = 0;
/* ASSERT_STATE() does nothing now; it used to be
assert (state_is == state_shouldbe). */
......@@ -287,12 +289,9 @@ main(int argc, char **argv) {
wanted_ia_na = 0;
}
wanted_ia_pd++;
#endif /* DHCPv6 */
} else if (!strcmp(argv[i], "-D")) {
if (local_family_set && (local_family == AF_INET)) {
usage();
}
local_family_set = 1;
local_family = AF_INET6;
duid_v4 = 1;
if (++i == argc)
usage();
if (!strcasecmp(argv[i], "LL")) {
......@@ -302,7 +301,12 @@ main(int argc, char **argv) {
} else {
usage();
}
#endif /* DHCPv6 */
} else if (!strcmp(argv[i], "-i")) {
/* enable DUID support for DHCPv4 clients */
duid_v4 = 1;
} else if (!strcmp(argv[i], "-I")) {
/* enable standard DHCID support for DDNS updates */
std_dhcid = 1;
} else if (!strcmp(argv[i], "-v")) {
quiet = 0;
} else if (!strcmp(argv[i], "--version")) {
......@@ -564,12 +568,13 @@ main(int argc, char **argv) {
}
srandom(seed + cur_time + (unsigned)getpid());
/* Start a configuration state machine for each interface. */
#ifdef DHCPv6
if (local_family == AF_INET6) {
/* Establish a default DUID. This may be moved to the
* DHCPv4 area later.
*/
/*
* Establish a default DUID. We always do so for v6 and
* do so if desired for v4 via the -D or -i options
*/
if ((local_family == AF_INET6) ||
((local_family == AF_INET) && (duid_v4 == 1))) {
if (default_duid.len == 0) {
if (default_duid.buffer != NULL)
data_string_forget(&default_duid, MDL);
......@@ -577,7 +582,11 @@ main(int argc, char **argv) {
form_duid(&default_duid, MDL);
write_duid(&default_duid);
}
}
/* Start a configuration state machine for each interface. */
#ifdef DHCPv6
if (local_family == AF_INET6) {
for (ip = interfaces ; ip != NULL ; ip = ip->next) {
for (client = ip->client ; client != NULL ;
client = client->next) {
......@@ -709,9 +718,9 @@ static void usage()
log_fatal("Usage: dhclient "
#ifdef DHCPv6
"[-4|-6] [-SNTP1dvrx] [-nw] [-p <port>] [-D LL|LLT]\n"
"[-4|-6] [-SNTPI1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n"
#else /* DHCPv6 */
"[-1dvrx] [-nw] [-p <port>]\n"
"[-I1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n"
#endif /* DHCPv6 */
" [-s server-addr] [-cf config-file] "
"[-lf lease-file]\n"
......@@ -2296,24 +2305,24 @@ make_client_options(struct client_state *client, struct client_lease *lease,
unsigned i;
struct option_cache *oc;
struct option *option = NULL;
struct buffer *bp = (struct buffer *)0;
struct buffer *bp = NULL;
/* If there are any leftover options, get rid of them. */
if (*op)
option_state_dereference (op, MDL);
option_state_dereference(op, MDL);
/* Allocate space for options. */
option_state_allocate (op, MDL);
option_state_allocate(op, MDL);
/* Send the server identifier if provided. */
if (sid)
save_option (&dhcp_universe, *op, sid);
save_option(&dhcp_universe, *op, sid);
oc = (struct option_cache *)0;
oc = NULL;
/* Send the requested address if provided. */
if (rip) {
client -> requested_address = *rip;
client->requested_address = *rip;
i = DHO_DHCP_REQUESTED_ADDRESS;
if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash,
&i, 0, MDL) &&
......@@ -2321,22 +2330,22 @@ make_client_options(struct client_state *client, struct client_lease *lease,
option, MDL)))
log_error ("can't make requested address cache.");
else {
save_option (&dhcp_universe, *op, oc);
option_cache_dereference (&oc, MDL);
save_option(&dhcp_universe, *op, oc);
option_cache_dereference(&oc, MDL);
}
option_dereference(&option, MDL);
} else {
client -> requested_address.len = 0;
client->requested_address.len = 0;
}
i = DHO_DHCP_MESSAGE_TYPE;
if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash, &i, 0,
MDL) &&
make_const_option_cache(&oc, NULL, type, 1, option, MDL)))
log_error ("can't make message type.");
log_error("can't make message type.");
else {
save_option (&dhcp_universe, *op, oc);
option_cache_dereference (&oc, MDL);
save_option(&dhcp_universe, *op, oc);
option_cache_dereference(&oc, MDL);
}
option_dereference(&option, MDL);
......@@ -2349,8 +2358,8 @@ make_client_options(struct client_state *client, struct client_lease *lease,
if (prl[i]->universe == &dhcp_universe)
len++;
if (!buffer_allocate (&bp, len, MDL))
log_error ("can't make parameter list buffer.");
if (!buffer_allocate(&bp, len, MDL))
log_error("can't make parameter list buffer.");
else {
unsigned code = DHO_DHCP_PARAMETER_REQUEST_LIST;
......@@ -2364,15 +2373,69 @@ make_client_options(struct client_state *client, struct client_lease *lease,
&code, 0, MDL) &&
make_const_option_cache(&oc, &bp, NULL, len,
option, MDL)))
log_error ("can't make option cache");
log_error("can't make option cache");
else {
save_option (&dhcp_universe, *op, oc);
option_cache_dereference (&oc, MDL);
save_option(&dhcp_universe, *op, oc);
option_cache_dereference(&oc, MDL);
}
option_dereference(&option, MDL);
}
}
/*
* If requested (duid_v4 == 1) add an RFC4361 compliant client-identifier
* This can be overridden by including a client id in the configuration
* file.
*/
if (duid_v4 == 1) {
struct data_string client_identifier;
int hw_idx, hw_len;
memset(&client_identifier, 0, sizeof(client_identifier));
client_identifier.len = 1 + 4 + default_duid.len;
if (!buffer_allocate(&client_identifier.buffer,
client_identifier.len, MDL))
log_fatal("no memory for default DUID!");
client_identifier.data = client_identifier.buffer->data;
i = DHO_DHCP_CLIENT_IDENTIFIER;
/* Client-identifier type : 1 byte */
*client_identifier.buffer->data = 255;
/* IAID : 4 bytes
* we use the low 4 bytes from the interface address
*/
if (client->interface->hw_address.hlen > 4) {
hw_idx = client->interface->hw_address.hlen - 4;
hw_len = 4;
} else {
hw_idx = 0;
hw_len = client->interface->hw_address.hlen;
}
memcpy(&client_identifier.buffer->data + 5 - hw_len,
client->interface->hw_address.hbuf + hw_idx,
hw_len);
/* Add the default duid */
memcpy(&client_identifier.buffer->data+(1+4),
default_duid.data, default_duid.len);
/* And save the option */
if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash,
&i, 0, MDL) &&
make_const_option_cache(&oc, NULL,
(u_int8_t *)client_identifier.data,
client_identifier.len,
option, MDL)))
log_error ("can't make requested client id cache..");
else {
save_option (&dhcp_universe, *op, oc);
option_cache_dereference (&oc, MDL);
}
option_dereference(&option, MDL);
}
/* Run statements that need to be run on transmission. */
if (client->config->on_transmission)
execute_statements_in_scope(NULL, NULL, NULL, client,
......@@ -2778,6 +2841,69 @@ write_options(struct client_state *client, struct option_state *options,
}
}
/*
* The "best" default DUID, since we cannot predict any information
* about the system (such as whether or not the hardware addresses are
* integrated into the motherboard or similar), is the "LLT", link local
* plus time, DUID. For real stateless "LL" is better.
*
* Once generated, this duid is stored into the state database, and
* retained across restarts.
*
* For the time being, there is probably a different state database for
* every daemon, so this winds up being a per-interface identifier...which
* is not how it is intended. Upcoming rearchitecting the client should
* address this "one daemon model."
*/
void
form_duid(struct data_string *duid, const char *file, int line)
{
struct interface_info *ip;
int len;
/* For now, just use the first interface on the list. */
ip = interfaces;
if (ip == NULL)
log_fatal("Impossible condition at %s:%d.", MDL);
if ((ip->hw_address.hlen == 0) ||
(ip->hw_address.hlen > sizeof(ip->hw_address.hbuf)))
log_fatal("Impossible hardware address length at %s:%d.", MDL);
if (duid_type == 0)
duid_type = stateless ? DUID_LL : DUID_LLT;
/*
* 2 bytes for the 'duid type' field.
* 2 bytes for the 'htype' field.
* (DUID_LLT) 4 bytes for the 'current time'.
* enough bytes for the hardware address (note that hw_address has
* the 'htype' on byte zero).
*/
len = 4 + (ip->hw_address.hlen - 1);
if (duid_type == DUID_LLT)
len += 4;
if (!buffer_allocate(&duid->buffer, len, MDL))
log_fatal("no memory for default DUID!");
duid->data = duid->buffer->data;
duid->len = len;
/* Basic Link Local Address type of DUID. */
if (duid_type == DUID_LLT) {
putUShort(duid->buffer->data, DUID_LLT);
putUShort(duid->buffer->data + 2, ip->hw_address.hbuf[0]);
putULong(duid->buffer->data + 4, cur_time - DUID_TIME_EPOCH);
memcpy(duid->buffer->data + 8, ip->hw_address.hbuf + 1,
ip->hw_address.hlen - 1);
} else {
putUShort(duid->buffer->data, DUID_LL);
putUShort(duid->buffer->data + 2, ip->hw_address.hbuf[0]);
memcpy(duid->buffer->data + 4, ip->hw_address.hbuf + 1,
ip->hw_address.hlen - 1);
}
}
/* Write the default DUID to the lease store. */
static isc_result_t
write_duid(struct data_string *duid)
......@@ -3991,6 +4117,7 @@ client_dns_update(struct client_state *client, dhcp_ddns_cb_t *ddns_cb)
struct option_cache *oc;
int ignorep;
int result;
int ddns_v4_type;
isc_result_t rcode;
/* If we didn't send an FQDN option, we certainly aren't going to
......@@ -4033,48 +4160,82 @@ client_dns_update(struct client_state *client, dhcp_ddns_cb_t *ddns_cb)
&global_scope, oc, MDL))
return ISC_R_SUCCESS;
/* If this is a DHCPv6 client update, make a dhcid string out of
* the DUID. If this is a DHCPv4 client update, choose either
* the client identifier, if there is one, or the interface's
* MAC address.
/*
* Construct the DHCID value for use in the DDNS update process
* We have the newer standard version and the older interim version
* chosen by the '-I' option. The interim version is left as is
* for backwards compatibility. The standard version is based on
* RFC 4701 section 3.3
*/
result = 0;
POST(result);
memset(&client_identifier, 0, sizeof(client_identifier));
if (std_dhcid == 1) {
/* standard style */
ddns_cb->dhcid_class = dns_rdatatype_dhcid;
ddns_v4_type = 1;
} else {
/* interim style */