2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-08-22 18:07:25 +00:00

[master] Added lease-id-format to server and client

Merges in rt26378
This commit is contained in:
Thomas Markwalder 2016-03-04 14:16:29 -05:00
parent 7f4e6f9778
commit cc1bd34e09
13 changed files with 413 additions and 131 deletions

View File

@ -236,7 +236,7 @@ by Eric Young (eay@cryptsoft.com).
Please look at doc/DHCPv4-over-DHCPv6 for more details. Please look at doc/DHCPv4-over-DHCPv6 for more details.
[ISC-Bugs #35711] [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 Solaris 11, ethernet device files are located in "/dev/net". The configure
script has been modified to detect this situation and adjust the directory script has been modified to detect this situation and adjust the directory
used accordingly. Thanks to Jarkko Torppa for reporting this issue and used accordingly. Thanks to Jarkko Torppa for reporting this issue and
@ -248,6 +248,12 @@ by Eric Young (eay@cryptsoft.com).
decoding a packet. decoding a packet.
[ISC-Bugs #41774] [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 Changes since 4.3.3b1
- None - None

View File

@ -3,7 +3,7 @@
Parser for dhclient config and lease files... */ 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 * Copyright (c) 1996-2003 by Internet Software Consortium
* *
* Permission to use, copy, modify, and distribute this software for any * 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); static struct dhc6_addr *parse_client6_iaprefix_statement(struct parse *cfile);
#endif /* DHCPv6 */ #endif /* DHCPv6 */
static void parse_lease_id_format (struct parse *cfile);
/* client-conf-file :== client-declarations END_OF_FILE /* client-conf-file :== client-declarations END_OF_FILE
client-declarations :== <nil> client-declarations :== <nil>
| client-declaration | client-declaration
@ -168,6 +170,7 @@ isc_result_t read_client_conf ()
top_level_config.retry_interval = 300; top_level_config.retry_interval = 300;
top_level_config.backoff_cutoff = 15; top_level_config.backoff_cutoff = 15;
top_level_config.initial_interval = 3; 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 * 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); parse_reject_statement (cfile, config);
return; return;
case LEASE_ID_FORMAT:
skip_token(&val, (unsigned *)0, cfile);
parse_lease_id_format(cfile);
break;
default: default:
lose = 0; lose = 0;
stmt = (struct executable_statement *)0; stmt = (struct executable_statement *)0;
@ -1324,25 +1333,17 @@ static void
parse_client_default_duid(struct parse *cfile) parse_client_default_duid(struct parse *cfile)
{ {
struct data_string new_duid; struct data_string new_duid;
const char *val = NULL; u_int8_t buf[128];
unsigned len; 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) { if (len <= 2) {
parse_warn(cfile, "Invalid DUID contents."); parse_warn(cfile, "Invalid DUID contents.");
skip_to_semi(cfile); skip_to_semi(cfile);
return; return;
} }
memset(&new_duid, 0, sizeof(new_duid));
if (!buffer_allocate(&new_duid.buffer, len, MDL)) { if (!buffer_allocate(&new_duid.buffer, len, MDL)) {
parse_warn(cfile, "Out of memory parsing default DUID."); parse_warn(cfile, "Out of memory parsing default DUID.");
skip_to_semi(cfile); skip_to_semi(cfile);
@ -1351,7 +1352,7 @@ parse_client_default_duid(struct parse *cfile)
new_duid.data = new_duid.buffer->data; new_duid.data = new_duid.buffer->data;
new_duid.len = len; new_duid.len = len;
memcpy(new_duid.buffer->data, val, len); memcpy(new_duid.buffer->data, buf, len);
/* Rotate the last entry into place. */ /* Rotate the last entry into place. */
if (default_duid.buffer != NULL) if (default_duid.buffer != NULL)
@ -2310,3 +2311,45 @@ int parse_allow_deny (oc, cfile, flag)
skip_to_semi (cfile); skip_to_semi (cfile);
return 0; 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"));
}

View File

@ -3489,10 +3489,12 @@ form_duid(struct data_string *duid, const char *file, int line)
ip->hw_address.hlen - 1); ip->hw_address.hlen - 1);
} }
str = quotify_buf(duid->data, duid->len, MDL); /* Now format the output based on lease-id-format */
if (str == NULL) str = format_lease_id(duid->data, duid->len,
log_info("Created duid."); top_level_config.lease_id_format, MDL);
else { if (str == NULL) {
log_info("form_duid: Couldn't allocate memory to log duid!");
} else {
log_info("Created duid %s.", str); log_info("Created duid %s.", str);
dfree(str, MDL); 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, /* Generate a formatted duid string per lease-id-format */
* but our function to do that (print_hex_n) uses a fixed str = format_lease_id(duid->data, duid->len,
* length buffer...and we can't guarantee a duid would be top_level_config.lease_id_format, MDL);
* less than the fixed length.
*/
str = quotify_buf(duid->data, duid->len, MDL);
if (str == NULL) if (str == NULL)
return ISC_R_NOMEMORY; return ISC_R_NOMEMORY;
stat = fprintf(leaseFile, "default-duid \"%s\";\n", str); stat = fprintf(leaseFile, "default-duid %s;\n", str);
dfree(str, MDL); dfree(str, MDL);
if (stat <= 0) if (stat <= 0)
return ISC_R_IOERROR; return ISC_R_IOERROR;
@ -3586,8 +3585,35 @@ write_client6_lease(struct client_state *client, struct dhc6_lease *lease,
ianame = "ia-pd"; ianame = "ia-pd";
break; 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) if (stat <= 0)
return ISC_R_IOERROR; return ISC_R_IOERROR;

View File

@ -1,8 +1,6 @@
.\" $Id: dhclient.conf.5,v 1.34 2012/01/24 22:23:39 sar Exp $ .\" $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) 2004-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) 1996-2003 by Internet Software Consortium .\" Copyright (c) 1996-2003 by Internet Software Consortium
.\" .\"
.\" Permission to use, copy, modify, and distribute this software for any .\" 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 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 same line. The formats are described in detail in this manpage, within
the LEASE DECLARATIONS section. 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 .PP
\fBreject \fIcidr-ip-address\fR [\fB,\fR \fI...\fB \fIcidr-ip-address\fR ] \fB;\fR \fBreject \fIcidr-ip-address\fR [\fB,\fR \fI...\fB \fIcidr-ip-address\fR ] \fB;\fR
.PP .PP

View File

@ -3,7 +3,7 @@
Lexical scanner for dhcpd config file... */ 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 * Copyright (c) 1995-2003 by Internet Software Consortium
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
@ -1050,6 +1050,9 @@ intern(char *atom, enum dhcp_token dfv) {
return HOSTNAME; return HOSTNAME;
if (!strcasecmp (atom + 1, "elp")) if (!strcasecmp (atom + 1, "elp"))
return TOKEN_HELP; return TOKEN_HELP;
if (!strcasecmp (atom + 1, "ex")) {
return TOKEN_HEX;
}
break; break;
case 'i': case 'i':
if (!strcasecmp(atom+1, "a-na")) if (!strcasecmp(atom+1, "a-na"))
@ -1136,6 +1139,9 @@ intern(char *atom, enum dhcp_token dfv) {
if (!strcasecmp(atom+1, "ittle-endian")) { if (!strcasecmp(atom+1, "ittle-endian")) {
return TOKEN_LITTLE_ENDIAN; return TOKEN_LITTLE_ENDIAN;
} }
if (!strcasecmp (atom + 1, "ease-id-format")) {
return LEASE_ID_FORMAT;
}
break; break;
case 'm': case 'm':
if (!strncasecmp (atom + 1, "ax", 2)) { if (!strncasecmp (atom + 1, "ax", 2)) {
@ -1236,6 +1242,9 @@ intern(char *atom, enum dhcp_token dfv) {
return OF; return OF;
if (!strcasecmp (atom + 1, "wner")) if (!strcasecmp (atom + 1, "wner"))
return OWNER; return OWNER;
if (!strcasecmp (atom + 1, "ctal")) {
return TOKEN_OCTAL;
}
break; break;
case 'p': case 'p':
if (!strcasecmp (atom + 1, "arse-vendor-option")) if (!strcasecmp (atom + 1, "arse-vendor-option"))

View File

@ -3,7 +3,7 @@
Turn data structures into printable text. */ 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) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1995-2003 by Internet Software Consortium * 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; 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) const char *file, int line)
{ {
unsigned nulen = 0; unsigned nulen = 0;
@ -87,9 +87,17 @@ char *quotify_buf (const unsigned char *s, unsigned len,
nulen++; nulen++;
} }
if (enclose_char) {
nulen +=2 ;
}
buf = dmalloc (nulen + 1, MDL); buf = dmalloc (nulen + 1, MDL);
if (buf) { if (buf) {
nsp = buf; nsp = buf;
if (enclose_char) {
*nsp++ = enclose_char;
}
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
if (s [i] == ' ') if (s [i] == ' ')
*nsp++ = ' '; *nsp++ = ' ';
@ -102,6 +110,10 @@ char *quotify_buf (const unsigned char *s, unsigned len,
} else } else
*nsp++ = s [i]; *nsp++ = s [i];
} }
if (enclose_char) {
*nsp++ = enclose_char;
}
*nsp++ = 0; *nsp++ = 0;
} }
return buf; return buf;
@ -1517,3 +1529,87 @@ print_time(TIME t)
return buf; 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);
}

View File

@ -1243,6 +1243,9 @@ struct client_config {
int do_forward_update; /* If nonzero, and if we have the int do_forward_update; /* If nonzero, and if we have the
information we need, update the information we need, update the
A record for the address we get. */ 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... */ /* Per-interface state used in the dhcp client... */
@ -2065,6 +2068,7 @@ extern int server_id_check;
extern int prefix_length_mode; extern int prefix_length_mode;
extern int authoring_byte_order; extern int authoring_byte_order;
extern int lease_id_format;
extern const char *path_dhcpd_conf; extern const char *path_dhcpd_conf;
extern const char *path_dhcpd_db; 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_io_shutdown (omapi_object_t *, void *);
isc_result_t dhcp_set_control_state (control_object_state_t oldstate, isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
control_object_state_t newstate); control_object_state_t newstate);
#if defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) #if defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
void relinquish_ackqueue(void); void relinquish_ackqueue(void);
#endif #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_allocate (struct dns_zone **, const char *, int);
int dns_zone_reference (struct dns_zone **, int dns_zone_reference (struct dns_zone **,
struct dns_zone *, const char *, int); struct dns_zone *, const char *, int);
/* print.c */ /* print.c */
#define DEFAULT_TIME_FORMAT 0 #define DEFAULT_TIME_FORMAT 0
#define LOCAL_TIME_FORMAT 1 #define LOCAL_TIME_FORMAT 1
extern int db_time_format; extern int db_time_format;
char *quotify_string (const char *, const char *, int); 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_base64 (const unsigned char *, unsigned, const char *, int);
char *print_hw_addr (const int, const int, const unsigned char *); char *print_hw_addr (const int, const int, const unsigned char *);
void print_lease (struct lease *); 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); const char *print_time(TIME);
void get_hw_addr(const char *name, struct hardware *hw); 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 */ /* socket.c */
#if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_RECEIVE) \ #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_RECEIVE) \
|| defined (USE_SOCKET_FALLBACK) || defined (USE_SOCKET_FALLBACK)

View File

@ -3,7 +3,7 @@
Tokens for config file lexer and parser. */ 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) 2004,2007-2009 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1996-2003 by Internet Software Consortium * Copyright (c) 1996-2003 by Internet Software Consortium
* *
@ -371,7 +371,10 @@ enum dhcp_token {
PARSE_VENDOR_OPT = 672, PARSE_VENDOR_OPT = 672,
AUTHORING_BYTE_ORDER = 673, AUTHORING_BYTE_ORDER = 673,
TOKEN_LITTLE_ENDIAN = 674, 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 && \ #define is_identifier(x) ((x) >= FIRST_TOKEN && \

View File

@ -36,6 +36,9 @@ static int parse_binding_value(struct parse *cfile,
struct binding_value *value); struct binding_value *value);
static void parse_authoring_byte_order (struct parse *cfile); 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) #if defined (TRACING)
trace_type_t *trace_readconf_type; trace_type_t *trace_readconf_type;
@ -802,6 +805,11 @@ int parse_statement (cfile, group, type, host_decl, declaration)
break; break;
#endif /* DHCPv6 */ #endif /* DHCPv6 */
case LEASE_ID_FORMAT:
token = next_token (&val, (unsigned *)0, cfile);
parse_lease_id_format(cfile);
break;
default: default:
et = (struct executable_statement *)0; et = (struct executable_statement *)0;
lose = 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 * \brief Parse allow and deny statements
@ -4664,10 +4718,9 @@ parse_ia_na_declaration(struct parse *cfile) {
skip_to_semi(cfile); skip_to_semi(cfile);
#else /* defined(DHCPv6) */ #else /* defined(DHCPv6) */
enum dhcp_token token; enum dhcp_token token;
struct ia_xx *ia; struct ia_xx *ia = NULL;
const char *val; const char *val;
struct ia_xx *old_ia; struct ia_xx *old_ia;
unsigned int len;
u_int32_t iaid; u_int32_t iaid;
struct iaddr iaddr; struct iaddr iaddr;
binding_state_t state; binding_state_t state;
@ -4690,26 +4743,10 @@ parse_ia_na_declaration(struct parse *cfile) {
return; return;
} }
token = next_token(&val, &len, cfile); if (!parse_iaid_duid(cfile, &ia, &iaid, MDL)) {
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);
return; 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; ia->ia_type = D6O_IA_NA;
token = next_token(&val, NULL, cfile); token = next_token(&val, NULL, cfile);
@ -5117,10 +5154,9 @@ parse_ia_ta_declaration(struct parse *cfile) {
skip_to_semi(cfile); skip_to_semi(cfile);
#else /* defined(DHCPv6) */ #else /* defined(DHCPv6) */
enum dhcp_token token; enum dhcp_token token;
struct ia_xx *ia; struct ia_xx *ia = NULL;
const char *val; const char *val;
struct ia_xx *old_ia; struct ia_xx *old_ia;
unsigned int len;
u_int32_t iaid; u_int32_t iaid;
struct iaddr iaddr; struct iaddr iaddr;
binding_state_t state; binding_state_t state;
@ -5143,26 +5179,10 @@ parse_ia_ta_declaration(struct parse *cfile) {
return; return;
} }
token = next_token(&val, &len, cfile); if (!parse_iaid_duid(cfile, &ia, &iaid, MDL)) {
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);
return; 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; ia->ia_type = D6O_IA_TA;
token = next_token(&val, NULL, cfile); token = next_token(&val, NULL, cfile);
@ -5570,10 +5590,9 @@ parse_ia_pd_declaration(struct parse *cfile) {
skip_to_semi(cfile); skip_to_semi(cfile);
#else /* defined(DHCPv6) */ #else /* defined(DHCPv6) */
enum dhcp_token token; enum dhcp_token token;
struct ia_xx *ia; struct ia_xx *ia = NULL;
const char *val; const char *val;
struct ia_xx *old_ia; struct ia_xx *old_ia;
unsigned int len;
u_int32_t iaid; u_int32_t iaid;
struct iaddr iaddr; struct iaddr iaddr;
u_int8_t plen; u_int8_t plen;
@ -5597,26 +5616,10 @@ parse_ia_pd_declaration(struct parse *cfile) {
return; return;
} }
token = next_token(&val, &len, cfile); if (!parse_iaid_duid(cfile, &ia, &iaid, MDL)) {
if (token != STRING) {
parse_warn(cfile, "corrupt lease file; "
"expecting an iaid+ia_pd string");
skip_to_semi(cfile);
return;
}
if (len < 5) {
parse_warn(cfile, "corrupt lease file; "
"iaid+ia_pd string too short");
skip_to_semi(cfile);
return; 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; ia->ia_type = D6O_IA_PD;
token = next_token(&val, NULL, cfile); token = next_token(&val, NULL, cfile);
@ -6024,39 +6027,37 @@ parse_ia_pd_declaration(struct parse *cfile) {
* DUID stored in a string: * DUID stored in a string:
* *
* server-duid "\000\001\000\001\015\221\034JRT\000\0224Y"; * 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 void
parse_server_duid(struct parse *cfile) { parse_server_duid(struct parse *cfile) {
enum dhcp_token token;
const char *val;
unsigned int len;
struct data_string duid; struct data_string duid;
unsigned char bytes[128]; /* Maximum valid DUID is 128 */
unsigned int len;
token = next_token(&val, &len, cfile); len = parse_X(cfile, bytes, sizeof(bytes));
if (token != STRING) { if (len <= 2) {
parse_warn(cfile, "corrupt lease file; expecting a DUID"); parse_warn(cfile, "Invalid duid contents");
skip_to_semi(cfile); skip_to_semi(cfile);
return; return;
} }
memset(&duid, 0, sizeof(duid)); memset(&duid, 0x0, sizeof(duid));
duid.len = len; if (!buffer_allocate(&duid.buffer, len, MDL)) {
if (!buffer_allocate(&duid.buffer, duid.len, MDL)) { log_fatal("parse_server_duid: out of memory");
log_fatal("Out of memory storing DUID");
} }
duid.data = (unsigned char *)duid.buffer->data;
memcpy(duid.buffer->data, val, len); memcpy(duid.buffer->data, bytes, len);
duid.len = len;
duid.data = duid.buffer->data;
set_server_duid(&duid); set_server_duid(&duid);
data_string_forget(&duid, MDL); data_string_forget(&duid, MDL);
token = next_token(&val, &len, cfile); parse_semi(cfile);
if (token != SEMI) {
parse_warn(cfile, "corrupt lease file; expecting a semicolon");
skip_to_semi(cfile);
return;
}
} }
/* /*
@ -6343,5 +6344,51 @@ uint32_t parse_byte_order_uint32(const void *source) {
return (value); 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 */ #endif /* DHCPv6 */

View File

@ -3,7 +3,7 @@
Persistent database management routines for DHCPD... */ 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) 2004-2010 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1995-2003 by Internet Software Consortium * 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->type == binding_data) {
if (bnd->value->value.data.data != NULL) { if (bnd->value->value.data.data != NULL) {
s = quotify_buf(bnd->value->value.data.data, s = quotify_buf(bnd->value->value.data.data,
bnd->value->value.data.len, MDL); bnd->value->value.data.len, '"', MDL);
if (s != NULL) { if (s != NULL) {
errno = 0; errno = 0;
fprintf(db_file, "%sset %s = \"%s\";", fprintf(db_file, "%sset %s = %s;",
prepend, bnd->name, s); prepend, bnd->name, s);
dfree(s, MDL); dfree(s, MDL);
if (errno) if (errno)
@ -207,10 +207,11 @@ int write_lease (lease)
++errors; ++errors;
} }
if (lease -> uid_len) { 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) { if (s) {
errno = 0; errno = 0;
fprintf (db_file, "\n uid \"%s\";", s); fprintf (db_file, "\n uid %s;", s);
if (errno) if (errno)
++errors; ++errors;
dfree (s, MDL); dfree (s, MDL);
@ -539,23 +540,23 @@ write_ia(const struct ia_xx *ia) {
++count; ++count;
} }
s = format_lease_id(ia->iaid_duid.data, ia->iaid_duid.len,
s = quotify_buf(ia->iaid_duid.data, ia->iaid_duid.len, MDL); lease_id_format, MDL);
if (s == NULL) { if (s == NULL) {
goto error_exit; goto error_exit;
} }
switch (ia->ia_type) { switch (ia->ia_type) {
case D6O_IA_NA: 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; break;
case D6O_IA_TA: 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; break;
case D6O_IA_PD: 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; break;
default: 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); (unsigned)ia->ia_type, s, MDL);
fprintf_ret = -1; fprintf_ret = -1;
} }
@ -712,7 +713,8 @@ write_server_duid(void) {
*/ */
memset(&server_duid, 0, sizeof(server_duid)); memset(&server_duid, 0, sizeof(server_duid));
copy_server_duid(&server_duid, MDL); 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); data_string_forget(&server_duid, MDL);
if (s == NULL) { if (s == NULL) {
goto error_exit; goto error_exit;
@ -721,7 +723,7 @@ write_server_duid(void) {
/* /*
* Write to the leases file. * 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); dfree(s, MDL);
if (fprintf_ret < 0) { if (fprintf_ret < 0) {
goto error_exit; goto error_exit;
@ -1183,7 +1185,6 @@ int new_lease_file ()
if (errno) if (errno)
goto fail; goto fail;
/* At this point we have a new lease file that, so far, could not /* At this point we have a new lease file that, so far, could not
* be described as either corrupt nor valid. * be described as either corrupt nor valid.
*/ */

View 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 prefix_length_mode = PLM_EXACT;
int authoring_byte_order = 0; /* 0 = not set */ 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_conf = _PATH_DHCPD_CONF;
const char *path_dhcpd_db = _PATH_DHCPD_DB; const char *path_dhcpd_db = _PATH_DHCPD_DB;

View File

@ -2509,6 +2509,26 @@ is, the latter value will be used.
.RE .RE
.PP .PP
The 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 .I local-port
statement statement
.RS 0.25i .RS 0.25i

View File

@ -1,6 +1,6 @@
.\" dhcpd.leases.5 .\" 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) 2004,2009 by Internet Systems Consortium, Inc. ("ISC")
.\" Copyright (c) 1996-2003 by Internet Software Consortium .\" 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 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 it contains one or more non-printable characters, those characters are
represented as octal escapes - a backslash character followed by three 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 .PP
.B client-hostname "\fIhostname\fB";\fR .B client-hostname "\fIhostname\fB";\fR
.PP .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 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 it contains one or more non-printable characters, those characters are
represented as octal escapes - a backslash character followed by three 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 .PP
.B cltt \fIdate\fB;\fR .B cltt \fIdate\fB;\fR
.PP .PP