]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
[master] Added lease-id-format to server and client
authorThomas Markwalder <tmark@isc.org>
Fri, 4 Mar 2016 19:16:29 +0000 (14:16 -0500)
committerThomas Markwalder <tmark@isc.org>
Fri, 4 Mar 2016 19:16:29 +0000 (14:16 -0500)
    Merges in rt26378

13 files changed:
RELNOTES
client/clparse.c
client/dhclient.c
client/dhclient.conf.5
common/conflex.c
common/print.c
includes/dhcpd.h
includes/dhctoken.h
server/confpars.c
server/db.c
server/dhcpd.c
server/dhcpd.conf.5
server/dhcpd.leases.5

index 445deba9ed24013dca72aedf19b354b12c980288..84fcc49d8898360491cc4d33e7ac446402df64ae 100644 (file)
--- a/RELNOTES
+++ b/RELNOTES
@@ -236,7 +236,7 @@ by Eric Young (eay@cryptsoft.com).
   Please look at doc/DHCPv4-over-DHCPv6 for more details.
   [ISC-Bugs #35711]
 
-- Corrected interface name formation when using DLPI under Solaris 11. As of
+- Correct interface name formation when using DLPI under Solaris 11. As of
   Solaris 11, ethernet device files are located in "/dev/net".  The configure
   script has been modified to detect this situation and adjust the directory
   used accordingly. Thanks to Jarkko Torppa for reporting this issue and
@@ -248,6 +248,12 @@ by Eric Young (eay@cryptsoft.com).
   decoding a packet.
   [ISC-Bugs #41774]
 
+- Add a new parameter, lease-id-format, to both dhcpd and dhclient. The
+  parameter controls the format in which certain values are written to lease
+  files.  Formats supported are octal - quoted string containing octal
+  escapes, and hex - unquoted, colon separated hex digits.
+  [ISC-Busg #26378]
+
                        Changes since 4.3.3b1
 
 - None
index 643b3faed32a0b9bbdee0f427ded99b08b383400..03190c33a9c2df911a9e3a3b779c55583527a582 100644 (file)
@@ -3,7 +3,7 @@
    Parser for dhclient config and lease files... */
 
 /*
- * Copyright (c) 2004-2014,2016 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2016 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
@@ -45,6 +45,8 @@ static struct dhc6_addr *parse_client6_iaaddr_statement(struct parse *cfile);
 static struct dhc6_addr *parse_client6_iaprefix_statement(struct parse *cfile);
 #endif /* DHCPv6 */
 
+static void parse_lease_id_format (struct parse *cfile);
+
 /* client-conf-file :== client-declarations END_OF_FILE
    client-declarations :== <nil>
                         | client-declaration
@@ -168,6 +170,7 @@ isc_result_t read_client_conf ()
        top_level_config.retry_interval = 300;
        top_level_config.backoff_cutoff = 15;
        top_level_config.initial_interval = 3;
+       top_level_config.lease_id_format = TOKEN_OCTAL;
 
        /*
         * RFC 2131, section 4.4.1 specifies that the client SHOULD wait a
@@ -809,6 +812,12 @@ void parse_client_statement (cfile, ip, config)
                parse_reject_statement (cfile, config);
                return;
 
+             case LEASE_ID_FORMAT:
+               skip_token(&val, (unsigned *)0, cfile);
+               parse_lease_id_format(cfile);
+               break;
+
+
              default:
                lose = 0;
                stmt = (struct executable_statement *)0;
@@ -1324,25 +1333,17 @@ static void
 parse_client_default_duid(struct parse *cfile)
 {
        struct data_string new_duid;
-       const char *val = NULL;
+       u_int8_t buf[128];
        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;
-       }
 
+       len = parse_X(cfile, buf, sizeof(buf));
        if (len <= 2) {
                parse_warn(cfile, "Invalid DUID contents.");
                skip_to_semi(cfile);
                return;
        }
 
+       memset(&new_duid, 0, sizeof(new_duid));
        if (!buffer_allocate(&new_duid.buffer, len, MDL)) {
                parse_warn(cfile, "Out of memory parsing default DUID.");
                skip_to_semi(cfile);
@@ -1351,7 +1352,7 @@ parse_client_default_duid(struct parse *cfile)
        new_duid.data = new_duid.buffer->data;
        new_duid.len = len;
 
-       memcpy(new_duid.buffer->data, val, len);
+       memcpy(new_duid.buffer->data, buf, len);
 
        /* Rotate the last entry into place. */
        if (default_duid.buffer != NULL)
@@ -2310,3 +2311,45 @@ int parse_allow_deny (oc, cfile, flag)
        skip_to_semi (cfile);
        return 0;
 }
+
+
+
+/*!
+ * \brief Parses an lease-id-format statement
+ *
+ * A valid statement looks like this:
+ *
+ *     lease-id-format :==
+ *             LEASE_ID_FORMAT TOKEN_OCTAL | TOKEN_HEX ;
+ *
+ * This function is used to parse the lease-id-format statement. It sets
+ * top_level_config.lease_id_format.
+ *
+ * \param cfile the current parse file
+ *
+*/
+void parse_lease_id_format (struct parse *cfile)
+{
+       enum dhcp_token token;
+       const char *val;
+
+       token = next_token(&val, NULL, cfile);
+       switch(token) {
+       case TOKEN_OCTAL:
+               top_level_config.lease_id_format = TOKEN_OCTAL;
+               break;
+       case TOKEN_HEX:
+               top_level_config.lease_id_format = TOKEN_HEX;
+               break;
+       default:
+               parse_warn(cfile, "lease-id-format is invalid: "
+                                   " it must be octal or hex.");
+               skip_to_semi(cfile);
+               return;
+       }
+
+       log_debug("lease_id_format is: %s",
+                 (top_level_config.lease_id_format == TOKEN_OCTAL
+                  ? "octal" : "hex"));
+
+}
index d1d83a0134b45629813ee4849cf59e1fa56e718c..98e691b51077c1a5ea74701b3ebc96571cc201af 100644 (file)
@@ -3489,10 +3489,12 @@ form_duid(struct data_string *duid, const char *file, int line)
                       ip->hw_address.hlen - 1);
        }
 
-       str = quotify_buf(duid->data, duid->len, MDL);
-       if (str == NULL)
-               log_info("Created duid.");
-       else {
+       /* Now format the output based on lease-id-format */
+       str = format_lease_id(duid->data, duid->len,
+                             top_level_config.lease_id_format, MDL);
+       if (str == NULL) {
+               log_info("form_duid: Couldn't allocate memory to log duid!");
+       } else {
                log_info("Created duid %s.", str);
                dfree(str, MDL);
        }
@@ -3516,16 +3518,13 @@ write_duid(struct data_string *duid)
                }
        }
 
-       /* It would make more sense to write this as a hex string,
-        * but our function to do that (print_hex_n) uses a fixed
-        * length buffer...and we can't guarantee a duid would be
-        * less than the fixed length.
-        */
-       str = quotify_buf(duid->data, duid->len, MDL);
+       /* Generate a formatted duid string per lease-id-format */
+       str = format_lease_id(duid->data, duid->len,
+                             top_level_config.lease_id_format, MDL);
        if (str == NULL)
                return ISC_R_NOMEMORY;
 
-       stat = fprintf(leaseFile, "default-duid \"%s\";\n", str);
+       stat = fprintf(leaseFile, "default-duid %s;\n", str);
        dfree(str, MDL);
        if (stat <= 0)
                return ISC_R_IOERROR;
@@ -3586,8 +3585,35 @@ write_client6_lease(struct client_state *client, struct dhc6_lease *lease,
                                ianame = "ia-pd";
                                break;
                }
-               stat = fprintf(leaseFile, "  %s %s {\n",
-                              ianame, print_hex_1(4, ia->iaid, 12));
+
+               /* For some reason IAID was never octal or hex, but string or
+                * hex. Go figure.  So for compatibilty's sake we will either
+                * do hex or "legacy" i.e string rather than octal. What a
+                * cluster. */
+               switch(top_level_config.lease_id_format) {
+                       case TOKEN_HEX: {
+                               char* iaid_str = format_lease_id(
+                                       (const unsigned char *) &ia->iaid, 4,
+                                       top_level_config.lease_id_format, MDL);
+
+                               if (!iaid_str) {
+                                       log_error("Can't format iaid");
+                                       return ISC_R_IOERROR;
+                               }
+
+                               stat = fprintf(leaseFile, "  %s %s {\n",
+                                              ianame, iaid_str);
+                               dfree(iaid_str, MDL);
+                               break;
+                       }
+
+                       case TOKEN_OCTAL:
+                       default:
+                               stat = fprintf(leaseFile, "  %s %s {\n", ianame,
+                                              print_hex_1(4, ia->iaid, 12));
+                               break;
+               }
+
                if (stat <= 0)
                        return ISC_R_IOERROR;
 
index 11706d9ef6e2684e4bbe575376f146e11f200a08..382837c0b3745acf08e110ed4662d0848af72532 100644 (file)
@@ -1,8 +1,6 @@
 .\"    $Id: dhclient.conf.5,v 1.34 2012/01/24 22:23:39 sar Exp $
 .\"
-.\" Copyright (c) 2014,2016 by Internet Systems Consortium, Inc. ("ISC")
-.\" Copyright (c) 2009-2012 by Internet Systems Consortium, Inc. ("ISC")
-.\" Copyright (c) 2004,2007 by Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (c) 2004-2016 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
@@ -599,6 +597,28 @@ day-and-time in UTC, whereas \fIlocal\fR uses a seconds-since-epoch to store
 the time value, and helpfully places a local timezone time in a comment on
 the same line.  The formats are described in detail in this manpage, within
 the LEASE DECLARATIONS section.
+.PP
+The
+.I lease-id-format
+parameter
+.RS 0.25i
+.PP
+.B lease-id-format \fIformat\fB;\fR
+.PP
+The \fIformat\fR parameter must be either \fBoctal\fR or \fBhex\fR.
+This parameter governs the format used to write certain values to lease
+files. With the default format, octal, values are written as quoted strings in
+which non-printable characters are represented as octal escapes -
+a backslash character followed by three octal digits.  When the hex format
+is specified, values are written as an unquoted series of hexadecimal digit
+pairs, separated by colons.
+
+Currently, the values written out based on lease-id-format are the default-duid
+and the IAID value (DHCPv6 only).  The client automatically reads the values
+in either format.  Note that when the format is octal, rather than as an octal
+string, IAID is output as hex if it contains no printable characters or as a
+string if contains only printable characters. This is done to maintain backward
+compatibility.
 .PP
  \fBreject \fIcidr-ip-address\fR [\fB,\fR \fI...\fB \fIcidr-ip-address\fR ] \fB;\fR
 .PP
index a1ba95fda90ce0602fd88522bb87fdda3dbbae6d..fe994acf86cb21c42d98eaeab645be2b9a4ae9e0 100644 (file)
@@ -3,7 +3,7 @@
    Lexical scanner for dhcpd config file... */
 
 /*
- * Copyright (c) 2004-2015 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2016 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -1050,6 +1050,9 @@ intern(char *atom, enum dhcp_token dfv) {
                        return HOSTNAME;
                if (!strcasecmp (atom + 1, "elp"))
                        return TOKEN_HELP;
+               if (!strcasecmp (atom + 1, "ex")) {
+                       return TOKEN_HEX;
+               }
                break;
              case 'i':
                if (!strcasecmp(atom+1, "a-na")) 
@@ -1136,6 +1139,9 @@ intern(char *atom, enum dhcp_token dfv) {
                if (!strcasecmp(atom+1, "ittle-endian")) {
                        return TOKEN_LITTLE_ENDIAN;
                }
+               if (!strcasecmp (atom + 1, "ease-id-format")) {
+                       return LEASE_ID_FORMAT;
+               }
                break;
              case 'm':
                if (!strncasecmp (atom + 1, "ax", 2)) {
@@ -1236,6 +1242,9 @@ intern(char *atom, enum dhcp_token dfv) {
                        return OF;
                if (!strcasecmp (atom + 1, "wner"))
                        return OWNER;
+               if (!strcasecmp (atom + 1, "ctal")) {
+                       return TOKEN_OCTAL;
+               }
                break;
              case 'p':
                if (!strcasecmp (atom + 1, "arse-vendor-option"))
index dfe0593bcff8fde86bcb38a3fade2269298e1e06..40b64fb69daa65ebc616a569005ff43c5b4d616e 100644 (file)
@@ -3,7 +3,7 @@
    Turn data structures into printable text. */
 
 /*
- * Copyright (c) 2009-2014 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2009-2014,2016 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995-2003 by Internet Software Consortium
  *
@@ -69,7 +69,7 @@ char *quotify_string (const char *s, const char *file, int line)
        return buf;
 }
 
-char *quotify_buf (const unsigned char *s, unsigned len,
+char *quotify_buf (const unsigned char *s, unsigned len, char enclose_char,
                   const char *file, int line)
 {
        unsigned nulen = 0;
@@ -87,9 +87,17 @@ char *quotify_buf (const unsigned char *s, unsigned len,
                        nulen++;
        }
 
+       if (enclose_char) {
+               nulen +=2 ;
+       }
+
        buf = dmalloc (nulen + 1, MDL);
        if (buf) {
                nsp = buf;
+               if (enclose_char) {
+                       *nsp++ = enclose_char;
+               }
+
                for (i = 0; i < len; i++) {
                        if (s [i] == ' ')
                                *nsp++ = ' ';
@@ -102,6 +110,10 @@ char *quotify_buf (const unsigned char *s, unsigned len,
                        } else
                                *nsp++ = s [i];
                }
+
+               if (enclose_char) {
+                       *nsp++ = enclose_char;
+               }
                *nsp++ = 0;
        }
        return buf;
@@ -1517,3 +1529,87 @@ print_time(TIME t)
 
        return buf;
 }
+
+/* !brief Return the given data as a string of hex digits "xx:xx:xx ..."
+ *
+ * Converts the given data into a null-terminated, string of hex digits,
+ * stored in an allocated buffer.  It is the caller's responsiblity to free
+ * the buffer.
+ *
+ * \param s - pointer to the data to convert
+ * \param len - length of the data to convert
+ * \param file - source file of invocation
+ * \param line - line number of invocation
+ *
+ * \return Returns an allocated buffer containing the hex string
+*/
+char *buf_to_hex (const unsigned char *s, unsigned len,
+                  const char *file, int line)
+{
+       unsigned nulen = 0;
+       char *buf;
+
+       /* If somebody hands us length of zero, we'll give them
+        * back an empty string */
+       if (!len) {
+               buf = dmalloc (1, MDL);
+               if (buf) {
+                       *buf = 0x0;
+               }
+
+               return (buf);
+       }
+
+
+       /* Figure out how big it needs to be. print_to_hex uses
+        * "%02x:" per character.  Note since there's no trailing colon
+        * we'll have room for the null */
+       nulen = (len * 3);
+
+       /* Allocate our buffer */
+       buf = dmalloc (nulen, MDL);
+
+       /* Hex-ify it */
+       if (buf) {
+               print_hex_only (len, s, nulen, buf);
+       }
+
+       return buf;
+}
+
+/* !brief Formats data into a string based on a lease id format
+ *
+ * Takes the given data and returns an allocated string whose contents are
+ * the string version of that data, formatted according to the output lease
+ * id format.  Note it is the caller's responsiblity to delete the string.
+ *
+ * Currently two formats are supported:
+ *
+ *  OCTAL - Default or "legacy" CSL format enclosed in quotes '"'.
+ *
+ *  HEX - Bytes represented as string colon seperated of hex digit pairs
+ *  (xx:xx:xx...)
+ *
+ * \param s - data to convert
+ * \param len - length of the data to convert
+ * \param format - desired format of the result
+ * \param file -  source file of invocation
+ * \param line - line number of invocation
+ *
+ * \return A pointer to the allocated, null-terminated string
+*/
+char *format_lease_id(const unsigned char *s, unsigned len,
+                      int format, const char *file, int line) {
+       char *idstr = NULL;
+
+       switch (format) {
+               case TOKEN_HEX:
+                       idstr = buf_to_hex(s, len, MDL);
+                       break;
+               case TOKEN_OCTAL:
+               default:
+                       idstr = quotify_buf(s, len, '"', MDL);
+                       break;
+       }
+       return (idstr);
+}
index 4b3001a847c4fbd685c131d34b3b4e80ec155cfe..d149792842c48f7676e612060c22330a43c59003 100644 (file)
@@ -1243,6 +1243,9 @@ struct client_config {
        int do_forward_update;          /* If nonzero, and if we have the
                                           information we need, update the
                                           A record for the address we get. */
+
+       int lease_id_format;            /* format for IDs in lease file,
+                                          TOKEN_OCTAL or TOKEN_HEX */
 };
 
 /* Per-interface state used in the dhcp client... */
@@ -2065,6 +2068,7 @@ extern int server_id_check;
 
 extern int prefix_length_mode;
 extern int authoring_byte_order;
+extern int lease_id_format;
 
 extern const char *path_dhcpd_conf;
 extern const char *path_dhcpd_db;
@@ -2089,6 +2093,7 @@ extern enum dhcp_shutdown_state shutdown_state;
 isc_result_t dhcp_io_shutdown (omapi_object_t *, void *);
 isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
                                     control_object_state_t newstate);
+
 #if defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
 void relinquish_ackqueue(void);
 #endif
@@ -2532,13 +2537,13 @@ int binding_scope_reference (struct binding_scope **,
 int dns_zone_allocate (struct dns_zone **, const char *, int);
 int dns_zone_reference (struct dns_zone **,
                        struct dns_zone *, const char *, int);
-
 /* print.c */
 #define DEFAULT_TIME_FORMAT 0
 #define LOCAL_TIME_FORMAT   1
 extern int db_time_format;
 char *quotify_string (const char *, const char *, int);
-char *quotify_buf (const unsigned char *, unsigned, const char *, int);
+char *quotify_buf (const unsigned char *, unsigned, const char,
+                  const char *, int);
 char *print_base64 (const unsigned char *, unsigned, const char *, int);
 char *print_hw_addr (const int, const int, const unsigned char *);
 void print_lease (struct lease *);
@@ -2572,7 +2577,10 @@ void print_dns_status (int, struct dhcp_ddns_cb *, isc_result_t);
 const char *print_time(TIME);
 
 void get_hw_addr(const char *name, struct hardware *hw);
-
+char *buf_to_hex (const unsigned char *s, unsigned len,
+                   const char *file, int line);
+char *format_lease_id(const unsigned char *s, unsigned len, int format,
+                      const char *file, int line);
 /* socket.c */
 #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_RECEIVE) \
        || defined (USE_SOCKET_FALLBACK)
index c1db9da39f5df8c8abf4bfd2a87df85cd9cb8be9..fa3c0bc21316939d321681aaa9827f54b7c6b287 100644 (file)
@@ -3,7 +3,7 @@
    Tokens for config file lexer and parser. */
 
 /*
- * Copyright (c) 2011-2015 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2011-2016 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 2004,2007-2009 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1996-2003 by Internet Software Consortium
  *
@@ -371,7 +371,10 @@ enum dhcp_token {
        PARSE_VENDOR_OPT = 672,
        AUTHORING_BYTE_ORDER = 673,
        TOKEN_LITTLE_ENDIAN = 674,
-       TOKEN_BIG_ENDIAN = 675
+       TOKEN_BIG_ENDIAN = 675,
+       LEASE_ID_FORMAT = 676,
+       TOKEN_HEX = 677,
+       TOKEN_OCTAL = 678
 };
 
 #define is_identifier(x)       ((x) >= FIRST_TOKEN &&  \
index 1b37a22eb5a3200957284329f788bbffc9622d5d..e4c690b6c48f5d318b476b58603ef75f7289af59 100644 (file)
@@ -36,6 +36,9 @@ static int parse_binding_value(struct parse *cfile,
                                struct binding_value *value);
 
 static void parse_authoring_byte_order (struct parse *cfile);
+static void parse_lease_id_format (struct parse *cfile);
+static int parse_iaid_duid(struct parse *cfile, struct ia_xx** ia,
+                          u_int32_t *iaid, const char* file, int line);
 
 #if defined (TRACING)
 trace_type_t *trace_readconf_type;
@@ -802,6 +805,11 @@ int parse_statement (cfile, group, type, host_decl, declaration)
                break;
 #endif /* DHCPv6 */
 
+             case LEASE_ID_FORMAT:
+               token = next_token (&val, (unsigned *)0, cfile);
+               parse_lease_id_format(cfile);
+               break;
+
              default:
                et = (struct executable_statement *)0;
                lose = 0;
@@ -1451,6 +1459,52 @@ void parse_authoring_byte_order (struct parse *cfile)
         }
 }
 
+/*!
+ * \brief Parses a lease-id-format statement
+ *
+ * A valid statement looks like this:
+ *
+ *     lease-id-format :==
+ *             LEASE_ID_FORMAT TOKEN_OCTAL | TOKEN_HEX ;
+ *
+ * This function is used to parse the lease-id-format statement. It sets the
+ * global variable, lease_id_format.
+ *
+ * \param cfile the current parse file
+ *
+*/
+void parse_lease_id_format (struct parse *cfile)
+{
+       enum dhcp_token token;
+       const char *val;
+       unsigned int len;
+
+       token = next_token(&val, NULL, cfile);
+       switch(token) {
+       case TOKEN_OCTAL:
+               lease_id_format = TOKEN_OCTAL;
+               break;
+       case TOKEN_HEX:
+               lease_id_format = TOKEN_HEX;
+               break;
+       default:
+               parse_warn(cfile, "lease-id-format is invalid: "
+                                   " it must be octal or hex.");
+               skip_to_semi(cfile);
+               return;
+       }
+
+       log_debug("lease_id_format is: %s",
+                 lease_id_format == TOKEN_OCTAL ? "octal" : "hex");
+
+        token = next_token(&val, &len, cfile);
+        if (token != SEMI) {
+                parse_warn(cfile, "corrupt lease file; expecting a semicolon");
+                skip_to_semi(cfile);
+                return;
+        }
+}
+
 /*!
  * 
  * \brief Parse allow and deny statements
@@ -4664,10 +4718,9 @@ parse_ia_na_declaration(struct parse *cfile) {
        skip_to_semi(cfile);
 #else /* defined(DHCPv6) */
        enum dhcp_token token;
-       struct ia_xx *ia;
+       struct ia_xx *ia = NULL;
        const char *val;
        struct ia_xx *old_ia;
-       unsigned int len;
        u_int32_t iaid;
        struct iaddr iaddr;
        binding_state_t state;
@@ -4690,26 +4743,10 @@ parse_ia_na_declaration(struct parse *cfile) {
                 return;
         }
 
-       token = next_token(&val, &len, cfile);
-       if (token != STRING) {
-               parse_warn(cfile, "corrupt lease file; "
-                                 "expecting an iaid+ia_na string");
-               skip_to_semi(cfile);
-               return;
-       }
-       if (len < 5) {
-               parse_warn(cfile, "corrupt lease file; "
-                                 "iaid+ia_na string too short");
-               skip_to_semi(cfile);
+       if (!parse_iaid_duid(cfile, &ia, &iaid, MDL)) {
                return;
        }
 
-       iaid = parse_byte_order_uint32(val);
-
-       ia = NULL;
-       if (ia_allocate(&ia, iaid, val+4, len-4, MDL) != ISC_R_SUCCESS) {
-               log_fatal("Out of memory.");
-       }
        ia->ia_type = D6O_IA_NA;
 
        token = next_token(&val, NULL, cfile);
@@ -5117,10 +5154,9 @@ parse_ia_ta_declaration(struct parse *cfile) {
        skip_to_semi(cfile);
 #else /* defined(DHCPv6) */
        enum dhcp_token token;
-       struct ia_xx *ia;
+       struct ia_xx *ia = NULL;
        const char *val;
        struct ia_xx *old_ia;
-       unsigned int len;
        u_int32_t iaid;
        struct iaddr iaddr;
        binding_state_t state;
@@ -5143,26 +5179,10 @@ parse_ia_ta_declaration(struct parse *cfile) {
                 return;
         }
 
-       token = next_token(&val, &len, cfile);
-       if (token != STRING) {
-               parse_warn(cfile, "corrupt lease file; "
-                                 "expecting an iaid+ia_ta string");
-               skip_to_semi(cfile);
-               return;
-       }
-       if (len < 5) {
-               parse_warn(cfile, "corrupt lease file; "
-                                 "iaid+ia_ta string too short");
-               skip_to_semi(cfile);
+       if (!parse_iaid_duid(cfile, &ia, &iaid, MDL)) {
                return;
        }
 
-       iaid = parse_byte_order_uint32(val);
-
-       ia = NULL;
-       if (ia_allocate(&ia, iaid, val+4, len-4, MDL) != ISC_R_SUCCESS) {
-               log_fatal("Out of memory.");
-       }
        ia->ia_type = D6O_IA_TA;
 
        token = next_token(&val, NULL, cfile);
@@ -5570,10 +5590,9 @@ parse_ia_pd_declaration(struct parse *cfile) {
        skip_to_semi(cfile);
 #else /* defined(DHCPv6) */
        enum dhcp_token token;
-       struct ia_xx *ia;
+       struct ia_xx *ia = NULL;
        const char *val;
        struct ia_xx *old_ia;
-       unsigned int len;
        u_int32_t iaid;
        struct iaddr iaddr;
        u_int8_t plen;
@@ -5597,26 +5616,10 @@ parse_ia_pd_declaration(struct parse *cfile) {
                 return;
         }
 
-       token = next_token(&val, &len, cfile);
-       if (token != STRING) {
-               parse_warn(cfile, "corrupt lease file; "
-                                 "expecting an iaid+ia_pd string");
-               skip_to_semi(cfile);
+       if (!parse_iaid_duid(cfile, &ia, &iaid, MDL)) {
                return;
        }
-       if (len < 5) {
-               parse_warn(cfile, "corrupt lease file; "
-                                 "iaid+ia_pd string too short");
-               skip_to_semi(cfile);
-               return;
-       }
-
-       iaid = parse_byte_order_uint32(val);
 
-       ia = NULL;
-       if (ia_allocate(&ia, iaid, val+4, len-4, MDL) != ISC_R_SUCCESS) {
-               log_fatal("Out of memory.");
-       }
        ia->ia_type = D6O_IA_PD;
 
        token = next_token(&val, NULL, cfile);
@@ -6024,39 +6027,37 @@ parse_ia_pd_declaration(struct parse *cfile) {
  * DUID stored in a string:
  *
  * server-duid "\000\001\000\001\015\221\034JRT\000\0224Y";
+ *
+ * OR as a hex string of digits:
+ *
+ * server-duid 00:01:00:01:1e:68:b3:db:0a:00:27:00:00:02;
  */
 void 
 parse_server_duid(struct parse *cfile) {
-       enum dhcp_token token;
-       const char *val;
-       unsigned int len;
        struct data_string duid;
+       unsigned char bytes[128];  /* Maximum valid DUID is 128 */
+       unsigned int len;
 
-       token = next_token(&val, &len, cfile);
-       if (token != STRING) {
-               parse_warn(cfile, "corrupt lease file; expecting a DUID");
+       len = parse_X(cfile, bytes, sizeof(bytes));
+       if (len <= 2) {
+               parse_warn(cfile, "Invalid duid contents");
                skip_to_semi(cfile);
                return;
        }
 
-       memset(&duid, 0, sizeof(duid));
-       duid.len = len;
-       if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
-               log_fatal("Out of memory storing DUID");
+       memset(&duid, 0x0, sizeof(duid));
+       if (!buffer_allocate(&duid.buffer, len, MDL)) {
+               log_fatal("parse_server_duid: out of memory");
        }
-       duid.data = (unsigned char *)duid.buffer->data;
-       memcpy(duid.buffer->data, val, len);
 
-       set_server_duid(&duid);
+       memcpy(duid.buffer->data, bytes, len);
+       duid.len = len;
+       duid.data = duid.buffer->data;
 
+       set_server_duid(&duid);
        data_string_forget(&duid, MDL);
 
-       token = next_token(&val, &len, cfile);
-       if (token != SEMI) {
-               parse_warn(cfile, "corrupt lease file; expecting a semicolon");
-               skip_to_semi(cfile);
-               return;
-       }
+       parse_semi(cfile);
 }
 
 /*
@@ -6343,5 +6344,51 @@ uint32_t parse_byte_order_uint32(const void *source) {
        return (value);
 }
 
+/* !brief Parses an iaid/duid string into an iaid and struct ia
+ *
+ * Given a string containing the iaid-duid value read from the file,
+ * and using the format specified by input lease-id-format, convert
+ * it into an IAID value and an ia_xx struct.
+ *
+ * \param cfile - file being parsed
+ * \param ia - pointer in which to store the allocated ia_xx struct
+ * \param iaid - pointer in which to return the IAID value
+ * \param file - source file name of invocation
+ * \param line - line numbe of invocation
+ *
+ * \return 0 if parsing fails, non-zero otherwise
+*/
+int
+parse_iaid_duid(struct parse* cfile, struct ia_xx** ia, u_int32_t *iaid,
+       const char* file, int line) {
+        unsigned char bytes[132];  /* Maximum valid IAID-DUID is 132 */
+        unsigned int len;
+
+       if (!ia) {
+               log_error("parse_iaid_duid: ia ptr cannot be null");
+               return (0);
+       }
+
+       *ia = NULL;
+        len = parse_X(cfile, bytes, sizeof(bytes));
+        if (len <= 5) {
+               parse_warn(cfile, "corrupt lease file; "
+                          "iaid+ia_xx string too short");
+                skip_to_semi(cfile);
+                return (0);
+        }
+
+       /* Extract the IAID from the front */
+       *iaid = parse_byte_order_uint32(bytes);
+
+       /* Instantiate the ia_xx */
+       if (ia_allocate(ia, *iaid, (const char*)bytes + 4, len - 4, file, line)
+           != ISC_R_SUCCESS) {
+               log_fatal("parse_iaid_duid:Out of memory.");
+       }
+
+       return (1);
+}
+
 #endif /* DHCPv6 */
 
index 645ea0dc898d92de663467214089880fff3f73a3..0eaa8d12fa24a5140d42c025a249016bf25b7862 100644 (file)
@@ -3,7 +3,7 @@
    Persistent database management routines for DHCPD... */
 
 /*
- * Copyright (c) 2012-2015 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2012-2016 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995-2003 by Internet Software Consortium
  *
@@ -56,10 +56,10 @@ write_binding_scope(FILE *db_file, struct binding *bnd, char *prepend) {
        if (bnd->value->type == binding_data) {
                if (bnd->value->value.data.data != NULL) {
                        s = quotify_buf(bnd->value->value.data.data,
-                                       bnd->value->value.data.len, MDL);
+                                       bnd->value->value.data.len, '"', MDL);
                        if (s != NULL) {
                                errno = 0;
-                               fprintf(db_file, "%sset %s = \"%s\";",
+                               fprintf(db_file, "%sset %s = %s;",
                                        prepend, bnd->name, s);
                                dfree(s, MDL);
                                if (errno)
@@ -207,10 +207,11 @@ int write_lease (lease)
                        ++errors;
        }
        if (lease -> uid_len) {
-               s = quotify_buf (lease -> uid, lease -> uid_len, MDL);
+               s = format_lease_id(lease->uid, lease->uid_len, lease_id_format,
+                                   MDL);
                if (s) {
                        errno = 0;
-                       fprintf (db_file, "\n  uid \"%s\";", s);
+                       fprintf (db_file, "\n  uid %s;", s);
                        if (errno)
                                ++errors;
                        dfree (s, MDL);
@@ -539,23 +540,23 @@ write_ia(const struct ia_xx *ia) {
                ++count;
        }
 
-       
-       s = quotify_buf(ia->iaid_duid.data, ia->iaid_duid.len, MDL);
+       s = format_lease_id(ia->iaid_duid.data, ia->iaid_duid.len,
+                           lease_id_format, MDL);
        if (s == NULL) {
                goto error_exit;
        }
        switch (ia->ia_type) {
        case D6O_IA_NA:
-               fprintf_ret = fprintf(db_file, "ia-na \"%s\" {\n", s);
+               fprintf_ret = fprintf(db_file, "ia-na %s {\n", s);
                break;
        case D6O_IA_TA:
-               fprintf_ret = fprintf(db_file, "ia-ta \"%s\" {\n", s);
+               fprintf_ret = fprintf(db_file, "ia-ta %s {\n", s);
                break;
        case D6O_IA_PD:
-               fprintf_ret = fprintf(db_file, "ia-pd \"%s\" {\n", s);
+               fprintf_ret = fprintf(db_file, "ia-pd %s {\n", s);
                break;
        default:
-               log_error("Unknown ia type %u for \"%s\" at %s:%d",
+               log_error("Unknown ia type %u for %s at %s:%d",
                          (unsigned)ia->ia_type, s, MDL);
                fprintf_ret = -1;
        }
@@ -712,7 +713,8 @@ write_server_duid(void) {
         */
        memset(&server_duid, 0, sizeof(server_duid));
        copy_server_duid(&server_duid, MDL);
-       s = quotify_buf(server_duid.data, server_duid.len, MDL);
+       s = format_lease_id(server_duid.data, server_duid.len, lease_id_format,
+                           MDL);
        data_string_forget(&server_duid, MDL);
        if (s == NULL) {
                goto error_exit;
@@ -721,7 +723,7 @@ write_server_duid(void) {
        /*
         * Write to the leases file.
         */
-       fprintf_ret = fprintf(db_file, "server-duid \"%s\";\n\n", s);
+       fprintf_ret = fprintf(db_file, "server-duid %s;\n\n", s);
        dfree(s, MDL);
        if (fprintf_ret < 0) {
                goto error_exit;
@@ -1183,7 +1185,6 @@ int new_lease_file ()
        if (errno)
                goto fail;
 
-
        /* At this point we have a new lease file that, so far, could not
         * be described as either corrupt nor valid.
         */
index 145561c06040c6f568e3b32f41ea0cfd05a6b53d..abf333d18369d8ebdccb8565d629cd367cf7fefb 100644 (file)
@@ -77,6 +77,7 @@ int server_id_check = 0; /* 0 = default, don't check server id, 1 = do check */
 int prefix_length_mode = PLM_EXACT;
 
 int authoring_byte_order = 0; /* 0 = not set */
+int lease_id_format = TOKEN_OCTAL; /* octal by default */
 
 const char *path_dhcpd_conf = _PATH_DHCPD_CONF;
 const char *path_dhcpd_db = _PATH_DHCPD_DB;
index ebc99120cbe729d2b6b0038113133a4b2867112c..a6b19776717328e956d78f94f37af10d06ad67cb 100644 (file)
@@ -2509,6 +2509,26 @@ is, the latter value will be used.
 .RE
 .PP
 The
+.I lease-id-format
+parameter
+.RS 0.25i
+.PP
+.B lease-id-format \fIformat\fB;\fR
+.PP
+The \fIformat\fR parameter must be either \fBoctal\fR or \fBhex\fR.
+This parameter governs the format used to write certain values to lease
+files. With the default format, octal, values are written as quoted strings in
+which non-printable characters are represented as octal escapes -
+a backslash character followed by three octal digits.  When the hex format
+is specified, values are written as an unquoted series of pairs of
+hexadecimal digits, separated by colons.
+
+Currently, the values written out based on lease-id-format are the server-duid,
+the uid (DHCPv4 leases), and the IAID_DUID (DHCPv6 leases).  Note the server
+automatically reads the values in either format.
+.RE
+.PP
+The
 .I local-port
 statement
 .RS 0.25i
index 025b9bf8da1e526ad3a2df447469294ac8b8a8d5..df59d82527bc50d3a426b980d6a92def4174096a 100644 (file)
@@ -1,6 +1,6 @@
 .\"    dhcpd.leases.5
 .\"
-.\" Copyright (c) 2014-2015 by Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (c) 2014-2016 by Internet Systems Consortium, Inc. ("ISC")
 .\" Copyright (c) 2004,2009 by Internet Systems Consortium, Inc. ("ISC")
 .\" Copyright (c) 1996-2003 by Internet Software Consortium
 .\"
@@ -246,7 +246,8 @@ The client identifier is recorded as a colon-separated hexadecimal
 list or as a quoted string.   If it is recorded as a quoted string and
 it contains one or more non-printable characters, those characters are
 represented as octal escapes - a backslash character followed by three
-octal digits.
+octal digits.  The format used is determined by the lease-id-format
+parameter, which defaults to octal.
 .PP
 .B client-hostname "\fIhostname\fB";\fR
 .PP
@@ -327,7 +328,8 @@ The IAID_DUID value is recorded as a colon-separated hexadecimal
 list or as a quoted string.   If it is recorded as a quoted string and
 it contains one or more non-printable characters, those characters are
 represented as octal escapes - a backslash character followed by three
-octal digits.
+octal digits.  The format used is governed by the lease-id-format parameter,
+which defaults to octal.
 .PP
 .B cltt \fIdate\fB;\fR
 .PP