summaryrefslogtreecommitdiff
path: root/server/omapi.c
diff options
context:
space:
mode:
authorThomas Markwalder <tmark@isc.org>2016-02-05 09:03:51 -0500
committerThomas Markwalder <tmark@isc.org>2016-02-05 09:03:51 -0500
commit606f272018a8bf2ff2a0699bc3ee1e96d8c3911e (patch)
tree21399bc4b77a9c9d53b65811ed777223b84961c8 /server/omapi.c
parent1d3fc4d0d8f8781c1c718d31ea33096a3f48e8ab (diff)
downloadisc-dhcp-606f272018a8bf2ff2a0699bc3ee1e96d8c3911e.tar.gz
[master] Fixed infinite-is-reserved and lease:flags setting via omapi
Merges in rt31179.
Diffstat (limited to 'server/omapi.c')
-rw-r--r--server/omapi.c101
1 files changed, 84 insertions, 17 deletions
diff --git a/server/omapi.c b/server/omapi.c
index 5756d294..60e35f3f 100644
--- a/server/omapi.c
+++ b/server/omapi.c
@@ -3,7 +3,7 @@
OMAPI object interfaces for the DHCP server. */
/*
- * Copyright (c) 2012-2015 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2012-2016 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 2004-2009 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1999-2003 by Internet Software Consortium
*
@@ -41,6 +41,9 @@ static isc_result_t class_lookup (omapi_object_t **,
omapi_object_t *, omapi_object_t *,
omapi_object_type_t *);
+static isc_result_t update_lease_flags(struct lease* lease,
+ omapi_typed_data_t *value);
+
omapi_object_type_t *dhcp_type_lease;
omapi_object_type_t *dhcp_type_pool;
omapi_object_type_t *dhcp_type_class;
@@ -269,22 +272,7 @@ isc_result_t dhcp_lease_set_value (omapi_object_t *h,
piaddr(lease->ip_addr), old_lease_end, lease_end);
return ISC_R_IOERROR;
} else if (!omapi_ds_strcmp(name, "flags")) {
- u_int8_t oldflags;
-
- if (value->type != omapi_datatype_data)
- return DHCP_R_INVALIDARG;
-
- oldflags = lease->flags;
- lease->flags = (value->u.buffer.value[0] & EPHEMERAL_FLAGS) |
- (lease->flags & ~EPHEMERAL_FLAGS);
- if(oldflags == lease->flags)
- return ISC_R_SUCCESS;
- if (!supersede_lease(lease, NULL, 1, 1, 1, 0)) {
- log_error("Failed to update flags for lease %s.",
- piaddr(lease->ip_addr));
- return ISC_R_IOERROR;
- }
- return ISC_R_SUCCESS;
+ return (update_lease_flags(lease, value));
} else if (!omapi_ds_strcmp (name, "billing-class")) {
return DHCP_R_UNCHANGED; /* XXX carefully allow change. */
} else if (!omapi_ds_strcmp (name, "hardware-address")) {
@@ -321,6 +309,85 @@ isc_result_t dhcp_lease_set_value (omapi_object_t *h,
return ISC_R_IOERROR;
}
+/*
+ * \brief Updates the lease's flags to a given value
+ *
+ * In order to update the lease's flags, we make a copy of the
+ * lease, and update the copy's flags with the new value.
+ * We then use the updated copy as the second parameter to a
+ * call to supersede_lease(). This ensures that the lease
+ * moves between queues correctly. This is critical when
+ * the RESERVED_LEASE flag is being changed.
+ *
+ * Note that only the EPHEMERAL flags are permitted to be changed.
+ *
+ * \param lease - pointer to the lease to update
+ * \param value - omapi data value containing the new flags value
+ *
+ * \return ISC_R_SUCCESS if the lease was successfully updated,
+ * DHCP_R_UNCHANGED if new value would result in no change to the
+ * lease's flags, or an appropriate status on other errors
+ */
+static isc_result_t update_lease_flags(struct lease* lease,
+ omapi_typed_data_t *value)
+{
+ u_int8_t oldflags;
+ u_int8_t newflags;
+ struct lease* lupdate = NULL;
+ isc_result_t status;
+
+ /* Grab the requested flags value. We (the server) send flags
+ * out as 1-byte, so we expect clients to do the same. However
+ * omshell, will send a network-ordered 4 byte integer if the
+ * input is "set flags = <n>", so we'll accomdate that too. */
+ if (value->u.buffer.len == 1) {
+ newflags = value->u.buffer.value[0];
+ } else {
+ unsigned long tmp;
+
+ status = omapi_get_int_value (&tmp, value);
+ if (status != ISC_R_SUCCESS) {
+ return (status);
+ }
+
+ newflags = (u_int8_t)tmp;
+ }
+
+ /* Save off the current flags value. */
+ oldflags = lease->flags;
+
+ /* The new value must preserve all PERSISTANT_FLAGS */
+ newflags = ((lease->flags & ~EPHEMERAL_FLAGS) |
+ (newflags & EPHEMERAL_FLAGS));
+
+ /* If there's no net change, we're done */
+ if (oldflags == newflags) {
+ return (DHCP_R_UNCHANGED);
+ }
+
+ /* Make a copy of the lease. */
+ if (!lease_copy(&lupdate, lease, MDL)) {
+ return (ISC_R_FAILURE);
+ }
+
+ /* Set the copy's flags to the new value */
+ lupdate->flags = newflags;
+
+ /* Attempt to update the lease */
+ if (!supersede_lease(lease, lupdate, 1, 1, 1, 0)) {
+ log_error("Failed to update flags for lease %s.",
+ piaddr(lease->ip_addr));
+ status = ISC_R_FAILURE;
+ } else {
+ log_debug ("lease flags changed from %x to %x for lease %s.",
+ oldflags, newflags, piaddr(lease->ip_addr));
+ status = ISC_R_SUCCESS;
+ }
+
+ lease_dereference(&lupdate, MDL);
+ return (status);
+}
+
isc_result_t dhcp_lease_get_value (omapi_object_t *h, omapi_object_t *id,
omapi_data_string_t *name,