Merges in rt21323.
[ISC-Bugs #36810]
[ISC-Bugs #20352]
+- By default, the server will now choose the value to use in the forward DNS
+ name from the following in order of preference:
+
+ 1. FQDN option if provided by the client
+ 2. Host name option if provided by the client
+ 3. Configured option host-name if defined
+
+ As before, this may be overridden by defining ddns-hostname to the desired
+ value (or expression). In addition, the server logic has been extended to
+ use the value of the host name declaration if use-host-decl-names is enabled
+ and no other value is available.
+ [ISC-Bugs #21323]
+
Changes since 4.3.1b1
- Modify the linux and openwrt dhclient scripts to process information
return 1;
}
+/*!
+ * \brief Constructs a null-terminated data_string from a char* and length.
+ *
+ * Allocates a data_string and copies into it the given length of bytes
+ * from the given source, adding a terminating null if not present in the source
+ * at length-1.
+ *
+ * \param new_string pointer to the data_string to construct. Cannot be
+ * NULL. Note that its contents will be overwritten. Passing in the address
+ * of an allocated data_string will result in memory leaks.
+ * \param src data to be copied. Cannot be NULL.
+ * \param len length of the data to copied
+ *
+ * \return 1 - if the data_string is constructed successfully, 0 if
+ * target data_struct is NULL or the buffer allocation fails.
+ */
+int
+data_string_new(struct data_string *new_string,
+ const char *src, unsigned int len,
+ const char *file, int line)
+{
+ unsigned int copy_len = 0;
+
+ if (new_string == NULL) {
+ log_error("data_string_new: new_string cannot be NULL %s(%d)",
+ file, line);
+ return (0);
+ }
+
+ if (src == NULL) {
+ log_error("data_string_new: src cannot be NULL %s(%d)",
+ file, line);
+ return (0);
+ }
+
+ memset(new_string, 0, sizeof (struct data_string));
+
+ /* If we already have a NULL back off length by one. This lets
+ * us always just add a NULL at the end. */
+ copy_len = (len > 0 && src[len - 1 ] == 0) ? len - 1 : len;
+
+ /* Allocate the buffer, accounting for terminating null */
+ if (!buffer_allocate(&(new_string->buffer), copy_len + 1, MDL)) {
+ log_error("data_string_new: No memory %s(%d)", file, line);
+ return (0);
+ }
+
+ /* Only copy if there's something to copy */
+ if (copy_len > 0) {
+ memcpy(new_string->buffer->data, src, copy_len);
+ }
+
+ /* Always tack on the null */
+ new_string->buffer->data[copy_len + 1] = 0;
+
+ /* Update data_string accessor values. Note len does NOT include
+ * the NULL. */
+ new_string->data = new_string->buffer->data;
+ new_string->len = copy_len;
+ new_string->terminated = 1;
+
+ return (1);
+}
+
/* Make a copy of the data in data_string, upping the buffer reference
count if there's a buffer. */
/*
- * Copyright (c) 2007,2009,2012 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2007,2009-2014 by Internet Systems Consortium, Inc. ("ISC")
*
* We test the functions provided in alloc.c here. These are very
* basic functions, and it is very important that they work correctly.
#include <atf-c.h>
#include "dhcpd.h"
+static const char* checkString (struct data_string* ds, const char *src);
+
ATF_TC(buffer_allocate);
ATF_TC_HEAD(buffer_allocate, tc) {
if (!buffer_reference(&b, a, MDL)) {
atf_tc_fail("buffer_reference() failed");
}
- a->refcnt = 0; /* purposely set to invalid value */
+ a->refcnt = 0; /* purposely set to invalid value */
if (buffer_dereference(&a, MDL)) {
atf_tc_fail("buffer_dereference() succeeded on error input");
}
}
+
+ATF_TC(data_string_new);
+
+ATF_TC_HEAD(data_string_new, tc) {
+ atf_tc_set_md_var(tc, "descr", "data_string_new test, "
+ "exercises data_string_new function");
+}
+
+ATF_TC_BODY(data_string_new, tc) {
+ struct data_string new_string;
+ const char *src = "Really? Latin? ... geeks";
+ int len_arg = 0;
+ const char *error;
+
+ /* Case 1: Call with an invalid data_string pointer, should fail */
+ if (data_string_new(NULL, src, len_arg, MDL)) {
+ atf_tc_fail("case 1: call should have failed");
+ }
+
+ /* Case 2: Passing in NULL src should fail */
+ if (data_string_new(&new_string, NULL, 10, MDL)) {
+ atf_tc_fail("case 2: did not return success");
+ }
+
+ /* Case 3: Call with valid params, length includes NULL */
+ len_arg = strlen(src) + 1;
+ if (data_string_new(&new_string, src, len_arg, MDL) == 0) {
+ atf_tc_fail("case 3: did not return success");
+ }
+
+ error = checkString(&new_string, src);
+ ATF_REQUIRE_MSG((error == NULL), "case 3: %s", error);
+ data_string_forget(&new_string, MDL);
+
+
+ /* Case 4: Call with valid params, length does not include NULL */
+ len_arg = 7;
+ if (data_string_new(&new_string, src, len_arg, MDL) == 0) {
+ atf_tc_fail("case 4: did not return success");
+ }
+
+ error = checkString(&new_string, "Really?");
+ ATF_REQUIRE_MSG((error == NULL), "case 4: %s", error);
+ data_string_forget(&new_string, MDL);
+
+
+ /* Case 5: Call with valid params, source string is "" */
+ len_arg = 0;
+ if (data_string_new(&new_string, "", len_arg, MDL) == 0) {
+ atf_tc_fail("case 5: did not return success");
+ }
+
+ error = checkString(&new_string, "");
+ ATF_REQUIRE_MSG((error == NULL), "case 4: %s", error);
+ data_string_forget(&new_string, MDL);
+
+
+}
+
+/* Helper function which tests validity of a data_string
+*
+* Verifies that the given data_string contains a null-terminated string
+* equal to a given string.
+*
+* \param string data_string to test
+* \param src text content string should contain
+* \return returns NULL if data_string is validate or an error message
+* describing why it is invalid
+*/
+const char* checkString (struct data_string* string,
+ const char* src) {
+ int src_len = strlen(src);
+
+ if (string->buffer == NULL) {
+ return ("buffer is NULL");
+ }
+
+ if (string->data != string->buffer->data) {
+ return ("data not set to buffer->data");
+ }
+
+ if (string->len != src_len) {
+ return ("len is wrong ");
+ }
+
+ if (string->terminated != 1) {
+ return ("terminated flag not set");
+ }
+
+ if (memcmp(string->data, src, src_len + 1)) {
+ return ("data content wrong");
+ }
+
+ return (NULL);
+}
+
+
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, buffer_allocate);
ATF_TP_ADD_TC(tp, data_string_forget_nobuf);
ATF_TP_ADD_TC(tp, data_string_copy);
ATF_TP_ADD_TC(tp, data_string_copy_nobuf);
+ ATF_TP_ADD_TC(tp, data_string_new);
return (atf_no_error());
}
struct option_state *, const char *, int);
int option_state_dereference (struct option_state **,
const char *, int);
+int data_string_new(struct data_string *, const char *, unsigned int,
+ const char *, int);
void data_string_copy(struct data_string *, const struct data_string *,
const char *, int);
void data_string_forget (struct data_string *, const char *, int);
else
s1 = 0;
+ /* If we don't have a host name based on ddns-hostname then use
+ * the host declaration name if there is one and use-host-decl-names
+ * is turned on. */
+ if ((s1 == 0) && (lease && lease->host && lease->host->name)) {
+ oc = lookup_option(&server_universe, options,
+ SV_USE_HOST_DECL_NAMES);
+ if (evaluate_boolean_option_cache(NULL, packet, lease,
+ NULL, packet->options,
+ options, scope, oc, MDL)) {
+ s1 = ((data_string_new(&ddns_hostname,
+ lease->host->name,
+ strlen(lease->host->name),
+ MDL) && ddns_hostname.len > 0));
+ }
+ }
+
oc = lookup_option(&server_universe, options, SV_DDNS_DOMAIN_NAME);
if (oc)
s2 = evaluate_option_cache(&ddns_domainname, packet, lease,
/* This stuff is always executed to figure the default values for certain
ddns variables. */
-
char std_nsupdate [] = " \n\
option server.ddns-hostname = \n\
- pick (option fqdn.hostname, option host-name); \n\
+ pick (option fqdn.hostname, option host-name, config-option host-name); \n\
option server.ddns-domainname = config-option domain-name; \n\
option server.ddns-rev-domainname = \"in-addr.arpa.\";";
.PP
If the server is configured not to allow client updates, or if the
client doesn\'t want to do its own update, the server will simply
-choose a name for the client from either the \fBfqdn\fR option (if present)
-or the hostname option (if present). It will use its own
-domain name for the client. It will then update both the A and PTR
-record, using the name that it chose for the client. If the client
-sends a fully-qualified domain name in the \fBfqdn\fR option, the
-server uses only the leftmost part of the domain name - in the
-example above, "jschmoe" instead of "jschmoe.radish.org".
-.PP
-If the defaults for choosing the host name are not appropriate
+choose a name for the client. By default, the server will choose
+from the following three values:
+.PP
+ 1. \fBfqdn\fR option (if present)
+ 2. hostname option (if present)
+ 3. Configured hostname option (if defined).
+.PP
+If these defaults for choosing the host name are not appropriate
you can write your own statement to set the ddns-hostname variable
-as you wish.
+as you wish. If none of the above are found the server will use
+the host declaration name (if one) and use-host-decl-names is on.
+.PP
+It will use its own domain name for the client. It will then update
+both the A and PTR record, using the name that it chose for the client.
+If the client sends a fully-qualified domain name in the \fBfqdn\fR option,
+the server uses only the leftmost part of the domain name - in the example
+above, "jschmoe" instead of "jschmoe.radish.org".
.PP
Further, if the \fIignore client-updates;\fR directive is used, then
the server will in addition send a response in the DHCP packet, using
}
.fi
.PP
+Additionally, enabling use-host-decl-names instructs the server to use
+the host declaration name in the the forward DNS name, if no other values
+are available. This value selection process is discussed in more detail
+under DNS updates.
+.PP
An \fIoption host-name\fR statement within a host declaration will
override the use of the name in the host declaration.
.PP