mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-22 18:07:25 +00:00
Might even work.
This commit is contained in:
parent
75135a3f7f
commit
e4a6be15e8
7
RELNOTES
7
RELNOTES
@ -52,6 +52,13 @@ The system has only been tested on Linux, FreeBSD, and Solaris, and
|
|||||||
may not work on other platforms. Please report any problems and
|
may not work on other platforms. Please report any problems and
|
||||||
suggested fixes to <dhcp-users@isc.org>.
|
suggested fixes to <dhcp-users@isc.org>.
|
||||||
|
|
||||||
|
|
||||||
|
Changes since 4.0.0b2
|
||||||
|
|
||||||
|
- The server will now include multiple IA_NA's and multiple IAADDRs within
|
||||||
|
them, if advertised by the client. It still only seeks to allocate one
|
||||||
|
new address.
|
||||||
|
|
||||||
Changes since 4.0.0b1
|
Changes since 4.0.0b1
|
||||||
|
|
||||||
- Use different paths for PID and lease files when running in DHCPv4
|
- Use different paths for PID and lease files when running in DHCPv4
|
||||||
|
@ -1177,8 +1177,7 @@ void parse_client_lease_declaration (cfile, lease, ipp, clientp)
|
|||||||
case OPTION:
|
case OPTION:
|
||||||
oc = (struct option_cache *)0;
|
oc = (struct option_cache *)0;
|
||||||
if (parse_option_decl (&oc, cfile)) {
|
if (parse_option_decl (&oc, cfile)) {
|
||||||
save_option (oc -> option -> universe,
|
save_option(oc->option->universe, lease->options, oc);
|
||||||
lease -> options, oc);
|
|
||||||
option_cache_dereference (&oc, MDL);
|
option_cache_dereference (&oc, MDL);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
182
common/options.c
182
common/options.c
@ -43,6 +43,10 @@ static int pretty_text(char **, char *, const unsigned char **,
|
|||||||
const unsigned char *, int);
|
const unsigned char *, int);
|
||||||
static int pretty_domain(char **, char *, const unsigned char **,
|
static int pretty_domain(char **, char *, const unsigned char **,
|
||||||
const unsigned char *);
|
const unsigned char *);
|
||||||
|
static int prepare_option_buffer(struct universe *universe, struct buffer *bp,
|
||||||
|
unsigned char *buffer, unsigned length,
|
||||||
|
unsigned code, int terminatep,
|
||||||
|
struct option_cache **opp);
|
||||||
|
|
||||||
/* Parse all available options out of the specified packet. */
|
/* Parse all available options out of the specified packet. */
|
||||||
|
|
||||||
@ -2143,15 +2147,64 @@ struct option_cache *lookup_hashed_option (universe, options, code)
|
|||||||
return (struct option_cache *)0;
|
return (struct option_cache *)0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int save_option_buffer (struct universe *universe,
|
/* Save a specified buffer into an option cache. */
|
||||||
struct option_state *options,
|
int
|
||||||
struct buffer *bp,
|
save_option_buffer(struct universe *universe, struct option_state *options,
|
||||||
unsigned char *buffer, unsigned length,
|
struct buffer *bp, unsigned char *buffer, unsigned length,
|
||||||
unsigned code, int tp)
|
unsigned code, int terminatep)
|
||||||
{
|
{
|
||||||
struct buffer *lbp = (struct buffer *)0;
|
struct option_cache *op = NULL;
|
||||||
struct option_cache *op = (struct option_cache *)0;
|
int status = 1;
|
||||||
|
|
||||||
|
status = prepare_option_buffer(universe, bp, buffer, length, code,
|
||||||
|
terminatep, &op);
|
||||||
|
|
||||||
|
if (status == 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
save_option(universe, options, op);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (op != NULL)
|
||||||
|
option_cache_dereference(&op, MDL);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append a specified buffer onto the tail of an option cache. */
|
||||||
|
int
|
||||||
|
append_option_buffer(struct universe *universe, struct option_state *options,
|
||||||
|
struct buffer *bp, unsigned char *buffer, unsigned length,
|
||||||
|
unsigned code, int terminatep)
|
||||||
|
{
|
||||||
|
struct option_cache *op = NULL;
|
||||||
|
int status = 1;
|
||||||
|
|
||||||
|
status = prepare_option_buffer(universe, bp, buffer, length, code,
|
||||||
|
terminatep, &op);
|
||||||
|
|
||||||
|
if (status == 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
also_save_option(universe, options, op);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (op != NULL)
|
||||||
|
option_cache_dereference(&op, MDL);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create/copy a buffer into a new option cache. */
|
||||||
|
static int
|
||||||
|
prepare_option_buffer(struct universe *universe, struct buffer *bp,
|
||||||
|
unsigned char *buffer, unsigned length, unsigned code,
|
||||||
|
int terminatep, struct option_cache **opp)
|
||||||
|
{
|
||||||
|
struct buffer *lbp = NULL;
|
||||||
struct option *option = NULL;
|
struct option *option = NULL;
|
||||||
|
struct option_cache *op;
|
||||||
|
int status = 1;
|
||||||
|
|
||||||
/* Code sizes of 8, 16, and 32 bits are allowed. */
|
/* Code sizes of 8, 16, and 32 bits are allowed. */
|
||||||
switch(universe->tag_size) {
|
switch(universe->tag_size) {
|
||||||
@ -2199,26 +2252,28 @@ int save_option_buffer (struct universe *universe,
|
|||||||
option->refcnt = 1;
|
option->refcnt = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!option_cache_allocate (&op, MDL)) {
|
if (!option_cache_allocate (opp, MDL)) {
|
||||||
log_error("No memory for option code %s.%s.",
|
log_error("No memory for option code %s.%s.",
|
||||||
universe->name, option->name);
|
universe->name, option->name);
|
||||||
option_dereference(&option, MDL);
|
status = 0;
|
||||||
return 0;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Pointer rather than double pointer makes for less parens. */
|
||||||
|
op = *opp;
|
||||||
|
|
||||||
option_reference(&op->option, option, MDL);
|
option_reference(&op->option, option, MDL);
|
||||||
|
|
||||||
/* If we weren't passed a buffer in which the data are saved and
|
/* If we weren't passed a buffer in which the data are saved and
|
||||||
refcounted, allocate one now. */
|
refcounted, allocate one now. */
|
||||||
if (!bp) {
|
if (!bp) {
|
||||||
if (!buffer_allocate (&lbp, length + tp, MDL)) {
|
if (!buffer_allocate (&lbp, length + terminatep, MDL)) {
|
||||||
log_error ("no memory for option buffer.");
|
log_error ("no memory for option buffer.");
|
||||||
|
|
||||||
option_cache_dereference (&op, MDL);
|
status = 0;
|
||||||
option_dereference(&option, MDL);
|
goto cleanup;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
memcpy (lbp -> data, buffer, length + tp);
|
memcpy (lbp -> data, buffer, length + terminatep);
|
||||||
bp = lbp;
|
bp = lbp;
|
||||||
buffer = &bp -> data [0]; /* Refer to saved buffer. */
|
buffer = &bp -> data [0]; /* Refer to saved buffer. */
|
||||||
}
|
}
|
||||||
@ -2231,7 +2286,7 @@ int save_option_buffer (struct universe *universe,
|
|||||||
op -> data.data = buffer;
|
op -> data.data = buffer;
|
||||||
op -> data.len = length;
|
op -> data.len = length;
|
||||||
|
|
||||||
if (tp) {
|
if (terminatep) {
|
||||||
/* NUL terminate (we can get away with this because we (or
|
/* NUL terminate (we can get away with this because we (or
|
||||||
the caller!) allocated one more than the buffer size, and
|
the caller!) allocated one more than the buffer size, and
|
||||||
because the byte following the end of an option is always
|
because the byte following the end of an option is always
|
||||||
@ -2257,11 +2312,8 @@ int save_option_buffer (struct universe *universe,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now store the option. */
|
|
||||||
save_option (universe, options, op);
|
|
||||||
|
|
||||||
/* And let go of our references. */
|
/* And let go of our references. */
|
||||||
option_cache_dereference (&op, MDL);
|
cleanup:
|
||||||
option_dereference(&option, MDL);
|
option_dereference(&option, MDL);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -2298,6 +2350,10 @@ collect_oro(struct option_cache *oc,
|
|||||||
oro->len += 2;
|
oro->len += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* build_server_oro() is presently unusued, but may be used at a future date
|
||||||
|
* with support for Reconfigure messages (as a hint to the client about new
|
||||||
|
* option value contents).
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
build_server_oro(struct data_string *server_oro,
|
build_server_oro(struct data_string *server_oro,
|
||||||
struct option_state *options,
|
struct option_state *options,
|
||||||
@ -2362,20 +2418,31 @@ build_server_oro(struct data_string *server_oro,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_option (struct universe *universe,
|
/* Wrapper function to put an option cache into an option state. */
|
||||||
struct option_state *options, struct option_cache *oc)
|
void
|
||||||
|
save_option(struct universe *universe, struct option_state *options,
|
||||||
|
struct option_cache *oc)
|
||||||
{
|
{
|
||||||
if (universe -> save_func)
|
if (universe->save_func)
|
||||||
(*universe -> save_func) (universe, options, oc);
|
(*universe->save_func)(universe, options, oc, ISC_FALSE);
|
||||||
else
|
else
|
||||||
log_error ("can't store options in %s space.",
|
log_error("can't store options in %s space.", universe->name);
|
||||||
universe -> name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_hashed_option (universe, options, oc)
|
/* Wrapper function to append an option cache into an option state's list. */
|
||||||
struct universe *universe;
|
void
|
||||||
struct option_state *options;
|
also_save_option(struct universe *universe, struct option_state *options,
|
||||||
struct option_cache *oc;
|
struct option_cache *oc)
|
||||||
|
{
|
||||||
|
if (universe->save_func)
|
||||||
|
(*universe->save_func)(universe, options, oc, ISC_TRUE);
|
||||||
|
else
|
||||||
|
log_error("can't store options in %s space.", universe->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
save_hashed_option(struct universe *universe, struct option_state *options,
|
||||||
|
struct option_cache *oc, isc_boolean_t appendp)
|
||||||
{
|
{
|
||||||
int hashix;
|
int hashix;
|
||||||
pair bptr;
|
pair bptr;
|
||||||
@ -2407,12 +2474,22 @@ void save_hashed_option (universe, options, oc)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we find one, dereference it and put the new one
|
/* Deal with collisions on the hash list. */
|
||||||
in its place. */
|
|
||||||
if (bptr) {
|
if (bptr) {
|
||||||
ocloc = (struct option_cache **)&bptr->car;
|
ocloc = (struct option_cache **)&bptr->car;
|
||||||
|
|
||||||
option_cache_dereference(ocloc, MDL);
|
/*
|
||||||
|
* If appendp is set, append it onto the tail of the
|
||||||
|
* ->next list. If it is not set, rotate it into
|
||||||
|
* position at the head of the list.
|
||||||
|
*/
|
||||||
|
if (appendp) {
|
||||||
|
while ((*ocloc)->next != NULL)
|
||||||
|
ocloc = &(*ocloc)->next;
|
||||||
|
} else {
|
||||||
|
option_cache_dereference(ocloc, MDL);
|
||||||
|
}
|
||||||
|
|
||||||
option_cache_reference(ocloc, oc, MDL);
|
option_cache_reference(ocloc, oc, MDL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3053,44 +3130,35 @@ int fqdn_option_space_encapsulate (result, packet, lease, client_state,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shill to the DHCPv4 fqdn option cache any lookups in the fqdn6 universe.
|
/*
|
||||||
*
|
* Trap invalid attempts to inspect FQND6 contents.
|
||||||
* XXX: Is this necessary? There shouldn't be any lookups directly...
|
|
||||||
*/
|
*/
|
||||||
struct option_cache *
|
struct option_cache *
|
||||||
lookup_fqdn6_option(struct universe *universe, struct option_state *options,
|
lookup_fqdn6_option(struct universe *universe, struct option_state *options,
|
||||||
unsigned code)
|
unsigned code)
|
||||||
{
|
{
|
||||||
log_fatal("Impossible condition at %s:%d.", MDL);
|
log_fatal("Impossible condition at %s:%d.", MDL);
|
||||||
|
return NULL;
|
||||||
return fqdn_universe.lookup_func(&fqdn_universe, options, code);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shill to the DHCPv4 fqdn option cache any direct saves to the fqdn6
|
/*
|
||||||
* universe.
|
* Trap invalid attempts to save options directly to FQDN6 rather than FQDN.
|
||||||
*
|
|
||||||
* XXX: Should this even be possible? Never excercised code?
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
save_fqdn6_option(struct universe *universe, struct option_state *options,
|
save_fqdn6_option(struct universe *universe, struct option_state *options,
|
||||||
struct option_cache *oc)
|
struct option_cache *oc, isc_boolean_t appendp)
|
||||||
{
|
{
|
||||||
log_fatal("Impossible condition at %s:%d.", MDL);
|
log_fatal("Impossible condition at %s:%d.", MDL);
|
||||||
|
|
||||||
fqdn_universe.save_func(&fqdn_universe, options, oc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shill to the DHCPv4 fqdn option cache any attempts to remove entries.
|
/*
|
||||||
*
|
* Trap invalid attempts to delete an option out of the FQDN6 universe.
|
||||||
* XXX: Again...should this even be possible?
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
delete_fqdn6_option(struct universe *universe, struct option_state *options,
|
delete_fqdn6_option(struct universe *universe, struct option_state *options,
|
||||||
int code)
|
int code)
|
||||||
{
|
{
|
||||||
log_fatal("Impossible condition at %s:%d.", MDL);
|
log_fatal("Impossible condition at %s:%d.", MDL);
|
||||||
|
|
||||||
fqdn_universe.delete_func(&fqdn_universe, options, code);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shill to the DHCPv4 fqdn option cache any attempts to traverse the
|
/* Shill to the DHCPv4 fqdn option cache any attempts to traverse the
|
||||||
@ -3395,10 +3463,9 @@ void hashed_option_space_foreach (struct packet *packet, struct lease *lease,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_linked_option (universe, options, oc)
|
void
|
||||||
struct universe *universe;
|
save_linked_option(struct universe *universe, struct option_state *options,
|
||||||
struct option_state *options;
|
struct option_cache *oc, isc_boolean_t appendp)
|
||||||
struct option_cache *oc;
|
|
||||||
{
|
{
|
||||||
pair *tail;
|
pair *tail;
|
||||||
struct option_chain_head *head;
|
struct option_chain_head *head;
|
||||||
@ -3422,7 +3489,12 @@ void save_linked_option (universe, options, oc)
|
|||||||
ocloc = (struct option_cache **)&(*tail)->car;
|
ocloc = (struct option_cache **)&(*tail)->car;
|
||||||
|
|
||||||
if (oc->option->code == (*ocloc)->option->code) {
|
if (oc->option->code == (*ocloc)->option->code) {
|
||||||
option_cache_dereference(ocloc, MDL);
|
if (appendp) {
|
||||||
|
while ((*ocloc)->next != NULL)
|
||||||
|
ocloc = &(*ocloc)->next;
|
||||||
|
} else {
|
||||||
|
option_cache_dereference(ocloc, MDL);
|
||||||
|
}
|
||||||
option_cache_reference(ocloc, oc, MDL);
|
option_cache_reference(ocloc, oc, MDL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1382,7 +1382,7 @@ lookup_fqdn6_option(struct universe *universe, struct option_state *options,
|
|||||||
unsigned code);
|
unsigned code);
|
||||||
void
|
void
|
||||||
save_fqdn6_option(struct universe *universe, struct option_state *options,
|
save_fqdn6_option(struct universe *universe, struct option_state *options,
|
||||||
struct option_cache *oc);
|
struct option_cache *oc, isc_boolean_t appendp);
|
||||||
void
|
void
|
||||||
delete_fqdn6_option(struct universe *universe, struct option_state *options,
|
delete_fqdn6_option(struct universe *universe, struct option_state *options,
|
||||||
int code);
|
int code);
|
||||||
@ -1452,12 +1452,17 @@ struct option_cache *next_hashed_option(struct universe *,
|
|||||||
int save_option_buffer (struct universe *, struct option_state *,
|
int save_option_buffer (struct universe *, struct option_state *,
|
||||||
struct buffer *, unsigned char *, unsigned,
|
struct buffer *, unsigned char *, unsigned,
|
||||||
unsigned, int);
|
unsigned, int);
|
||||||
|
int append_option_buffer(struct universe *, struct option_state *,
|
||||||
|
struct buffer *, unsigned char *, unsigned,
|
||||||
|
unsigned, int);
|
||||||
void build_server_oro(struct data_string *, struct option_state *,
|
void build_server_oro(struct data_string *, struct option_state *,
|
||||||
const char *, int);
|
const char *, int);
|
||||||
void save_option PROTO ((struct universe *,
|
void save_option(struct universe *, struct option_state *,
|
||||||
struct option_state *, struct option_cache *));
|
struct option_cache *);
|
||||||
void save_hashed_option PROTO ((struct universe *,
|
void also_save_option(struct universe *, struct option_state *,
|
||||||
struct option_state *, struct option_cache *));
|
struct option_cache *);
|
||||||
|
void save_hashed_option(struct universe *, struct option_state *,
|
||||||
|
struct option_cache *, isc_boolean_t appendp);
|
||||||
void delete_option PROTO ((struct universe *, struct option_state *, int));
|
void delete_option PROTO ((struct universe *, struct option_state *, int));
|
||||||
void delete_hashed_option PROTO ((struct universe *,
|
void delete_hashed_option PROTO ((struct universe *,
|
||||||
struct option_state *, int));
|
struct option_state *, int));
|
||||||
@ -1544,8 +1549,8 @@ int linked_option_get PROTO ((struct data_string *, struct universe *,
|
|||||||
int linked_option_state_dereference PROTO ((struct universe *,
|
int linked_option_state_dereference PROTO ((struct universe *,
|
||||||
struct option_state *,
|
struct option_state *,
|
||||||
const char *, int));
|
const char *, int));
|
||||||
void save_linked_option (struct universe *, struct option_state *,
|
void save_linked_option(struct universe *, struct option_state *,
|
||||||
struct option_cache *);
|
struct option_cache *, isc_boolean_t appendp);
|
||||||
void linked_option_space_foreach (struct packet *, struct lease *,
|
void linked_option_space_foreach (struct packet *, struct lease *,
|
||||||
struct client_state *,
|
struct client_state *,
|
||||||
struct option_state *,
|
struct option_state *,
|
||||||
|
@ -304,7 +304,7 @@ struct universe {
|
|||||||
struct option_state *,
|
struct option_state *,
|
||||||
unsigned);
|
unsigned);
|
||||||
void (*save_func) (struct universe *, struct option_state *,
|
void (*save_func) (struct universe *, struct option_state *,
|
||||||
struct option_cache *);
|
struct option_cache *, isc_boolean_t);
|
||||||
void (*foreach) (struct packet *,
|
void (*foreach) (struct packet *,
|
||||||
struct lease *, struct client_state *,
|
struct lease *, struct client_state *,
|
||||||
struct option_state *, struct option_state *,
|
struct option_state *, struct option_state *,
|
||||||
|
@ -756,7 +756,6 @@ start_reply(struct packet *packet,
|
|||||||
struct dhcpv6_packet *reply)
|
struct dhcpv6_packet *reply)
|
||||||
{
|
{
|
||||||
struct option_cache *oc;
|
struct option_cache *oc;
|
||||||
struct data_string server_oro;
|
|
||||||
const unsigned char *server_id_data;
|
const unsigned char *server_id_data;
|
||||||
int server_id_len;
|
int server_id_len;
|
||||||
|
|
||||||
@ -877,21 +876,6 @@ start_reply(struct packet *packet,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the ORO for the main packet.
|
|
||||||
*/
|
|
||||||
build_server_oro(&server_oro, *opt_state, MDL);
|
|
||||||
if (!save_option_buffer(&dhcpv6_universe, *opt_state,
|
|
||||||
server_oro.buffer,
|
|
||||||
(unsigned char *)server_oro.data,
|
|
||||||
server_oro.len, D6O_ORO, 0)) {
|
|
||||||
log_error("start_reply: error saving server ORO.");
|
|
||||||
data_string_forget(&server_oro, MDL);
|
|
||||||
option_state_dereference(opt_state, MDL);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
data_string_forget(&server_oro, MDL);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1951,11 +1935,14 @@ reply_process_is_addressed(struct reply_state *reply,
|
|||||||
reply->valid = reply->send_valid;
|
reply->valid = reply->send_valid;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* XXX: Old 4.0.0 alpha code would change the host {} record
|
/*
|
||||||
* XXX: uid upon lease assignment. I think this was an error;
|
* XXX: Old 4.0.0 alpha code would change the host {} record
|
||||||
* XXX: it doesn't make sense to me now in retrospect to change
|
* XXX: uid upon lease assignment. This was intended to cover the
|
||||||
* XXX: what is essentially configuration state with network
|
* XXX: case where a client first identifies itself using vendor
|
||||||
* XXX: supplied values.
|
* XXX: options in a solicit, or request, but later neglects to include
|
||||||
|
* XXX: these options in a Renew or Rebind. It is not clear that this
|
||||||
|
* XXX: is required, and has some startling ramnifications (such as
|
||||||
|
* XXX: how to recover this dynamic host {} state across restarts).
|
||||||
*/
|
*/
|
||||||
if (reply->host != NULL)
|
if (reply->host != NULL)
|
||||||
change_host_uid(host, reply->client_id->data,
|
change_host_uid(host, reply->client_id->data,
|
||||||
@ -2021,9 +2008,9 @@ reply_process_send_addr(struct reply_state *reply, struct iaddr *addr) {
|
|||||||
putULong(data.buffer->data + 16, reply->send_prefer);
|
putULong(data.buffer->data + 16, reply->send_prefer);
|
||||||
putULong(data.buffer->data + 20, reply->send_valid);
|
putULong(data.buffer->data + 20, reply->send_valid);
|
||||||
|
|
||||||
if (!save_option_buffer(&dhcpv6_universe, reply->reply_ia,
|
if (!append_option_buffer(&dhcpv6_universe, reply->reply_ia,
|
||||||
data.buffer, data.buffer->data,
|
data.buffer, data.buffer->data,
|
||||||
data.len, D6O_IAADDR, 0)) {
|
data.len, D6O_IAADDR, 0)) {
|
||||||
log_error("reply_process_ia: unable to save IAADDR "
|
log_error("reply_process_ia: unable to save IAADDR "
|
||||||
"option");
|
"option");
|
||||||
status = ISC_R_FAILURE;
|
status = ISC_R_FAILURE;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user