]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
[master] Host declaration name can now be used in DNS forward name
authorThomas Markwalder <tmark@isc.org>
Wed, 19 Nov 2014 15:56:17 +0000 (10:56 -0500)
committerThomas Markwalder <tmark@isc.org>
Wed, 19 Nov 2014 15:56:17 +0000 (10:56 -0500)
        Merges in rt21323.

RELNOTES
common/alloc.c
common/tests/test_alloc.c
includes/dhcpd.h
server/ddns.c
server/dhcpd.c
server/dhcpd.conf.5

index 93acdfd69bcd9735d70ae816a68d99791677b9c7..ef89b5515ca74eb612c96b8a294e4814ead9db28 100644 (file)
--- a/RELNOTES
+++ b/RELNOTES
@@ -146,6 +146,19 @@ by Eric Young (eay@cryptsoft.com).
   [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
index 0280cbc469c7042064496abc0e127d3acd6d9dc2..a55f4712bfc76061b07e1ad211266d3a5d1e2ef9 100644 (file)
@@ -1253,6 +1253,70 @@ int binding_scope_reference (ptr, bp, file, line)
        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. */
 
index d941c8fb5cfaacecbd7ff3deecfa7e9ad0e53493..9e082135747baaf835a9df4d74879d2bc898b259 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -27,6 +27,8 @@
 #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) {
@@ -187,7 +189,7 @@ ATF_TC_BODY(buffer_dereference, 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");
     }
@@ -387,6 +389,103 @@ ATF_TC_BODY(data_string_copy_nobuf, tc) {
 
 }
 
+
+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);
@@ -396,6 +495,7 @@ ATF_TP_ADD_TCS(tp)
     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());
 }
index 9ad641be7506249d9d73d0968d5d1baff17d381e..edc9b89e48f38e65cad2594e94d213a3621703fb 100644 (file)
@@ -2384,6 +2384,8 @@ int option_state_reference (struct option_state **,
                            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);
index 6cbd3e3d23c38f9a684ee7ce5c1a80469f7181a0..b582787030ed2a9d90ea23583e78d63bded08027 100644 (file)
@@ -221,6 +221,22 @@ ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
        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,
index e0d45e175b73ba23872ec1b8bb4f0784d1ae224a..6747c209e0088b96594a5adb6db796f8008bd9e9 100644 (file)
@@ -63,10 +63,9 @@ int server_identifier_matched;
 
 /* 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.\";";
 
index 2f7eb7802bd5ee647c19395a004029f0fa5c9ea0..9d7178da5dd2f7c9b77a34951c5beb85b1318f62 100644 (file)
@@ -1153,17 +1153,23 @@ IP address, it can update its own A record, assuming that the
 .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
@@ -2931,6 +2937,11 @@ is equivalent to
       }
 .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