summaryrefslogtreecommitdiff
path: root/client/dhclient.c
diff options
context:
space:
mode:
authorThomas Markwalder <tmark@isc.org>2019-11-22 13:39:45 -0500
committerThomas Markwalder <tmark@isc.org>2019-11-22 13:39:45 -0500
commit0cd94b5ef4a078097fc2bd1dc72f5e80c2cf1844 (patch)
treee4dfe9a92d676a49b18ab547d781fb3fb10c8e6a /client/dhclient.c
parent97c155273c0df0c8518f226e2b5e338e3ad63e87 (diff)
downloadisc-dhcp-0cd94b5ef4a078097fc2bd1dc72f5e80c2cf1844.tar.gz
[#64,!35] Restored work
Restored cummulative work.
Diffstat (limited to 'client/dhclient.c')
-rw-r--r--client/dhclient.c124
1 files changed, 113 insertions, 11 deletions
diff --git a/client/dhclient.c b/client/dhclient.c
index 6828c676..4a22803a 100644
--- a/client/dhclient.c
+++ b/client/dhclient.c
@@ -51,6 +51,8 @@ static char path_dhclient_script_array[] = _PATH_DHCLIENT_SCRIPT;
char *path_dhclient_script = path_dhclient_script_array;
const char *path_dhclient_duid = NULL;
+static void add_to_tail(struct client_lease** lease_list, struct client_lease* lease);
+
/* False (default) => we write and use a pid file */
isc_boolean_t no_pid_file = ISC_FALSE;
@@ -1556,8 +1558,16 @@ void bind_lease (client)
write_client_lease(client, client->new, 0, 1);
/* Replace the old active lease with the new one. */
- if (client->active)
- destroy_client_lease(client->active);
+ if (client->active) {
+ if (client->active->is_static) {
+ // We need to preserve the fallback lease in case
+ // we lose DHCP service again.
+ add_to_tail(&client->leases, client->active);
+ } else {
+ destroy_client_lease(client->active);
+ }
+ }
+
client->active = client->new;
client->new = NULL;
@@ -2458,6 +2468,99 @@ void send_discover (cpp)
add_timeout(&tv, send_discover, client, 0, 0);
}
+
+/*
+ * \brief Remove leases from a list of leases which duplicate a given lease
+ *
+ * Searches through a linked-list of leases, remove the first one matches the
+ * given lease's address and value of is_static. The latter test is done
+ * so we only remove leases that are from the same source (i.e server/lease file
+ * vs config file). This ensures we do not discard "fallback" config file leases
+ * that happen to match non-config file leases.
+ *
+ * \param lease_list list of leases to clean
+ * \param lease lease for which duplicates should be removed
+ */
+void discard_duplicate (struct client_lease** lease_list, struct client_lease* lease) {
+ struct client_lease *cur, *prev, *next;
+
+ if (!lease_list || !lease) {
+ return;
+ }
+
+ prev = (struct client_lease *)0;
+ for (cur = *lease_list; cur; cur = next) {
+ next = cur->next;
+ if ((cur->is_static == lease->is_static) &&
+ (cur->address.len == lease->address.len &&
+ !memcmp (cur->address.iabuf, lease->address.iabuf,
+ lease->address.len))) {
+ if (prev)
+ prev->next = next;
+ else
+ *lease_list = next;
+
+ destroy_client_lease (cur);
+ break;
+ } else {
+ prev = cur;
+ }
+ }
+}
+
+/*
+ * \brief Add a given lease to the end of list of leases
+ *
+ * Searches through a linked-list of leases, removing any that match the
+ * given lease's address and value of is_static. The latter test is done
+ * so we only remove leases that are from the same source (i.e server/lease file
+ * vs config file). This ensures we do not discard "fallback" config file leases
+ * that happen to match non-config file leases.
+ *
+ * \param lease_list list of leases to clean
+ * \param lease lease for which duplicates should be removed
+ */
+void add_to_tail(struct client_lease** lease_list,
+ struct client_lease* lease)
+{
+ if (!lease_list || !lease) {
+ return;
+ }
+
+ /* If there is already a lease for this address and
+ * is_static value, toss discard it. This ensures
+ * we only keep one dynamic and/or one static lease
+ * for a given address. */
+ discard_duplicate(lease_list, lease);
+
+ /* Find the tail */
+ struct client_lease* tail;
+ for (tail = *lease_list; tail && tail->next; tail = tail->next){};
+
+ /* Ensure the tail points nowhere. */
+ lease->next = NULL;
+
+ /* Add to the tail. */
+ if (!tail) {
+ *lease_list = lease;
+ } else {
+ tail->next = lease;
+ }
+}
+
+#if 0
+void dbg_print_lease(char *text, struct client_lease* lease) {
+ if (!lease) {
+ log_debug("%s, lease is null", text);
+ } else {
+ log_debug ("%s: %p addr:%s expires:%ld :is_static? %d",
+ text, lease, piaddr (lease->address),
+ (lease->expiry - cur_time),
+ lease->is_static);
+ }
+}
+#endif
+
/* state_panic gets called if we haven't received any offers in a preset
amount of time. When this happens, we try to use existing leases that
haven't yet expired, and failing that, we call the client script and
@@ -2483,8 +2586,10 @@ void state_panic (cpp)
/* Run through the list of leases and see if one can be used. */
while (client -> active) {
if (client -> active -> expiry > cur_time) {
- log_info ("Trying recorded lease %s",
- piaddr (client -> active -> address));
+ log_info ("Trying %s lease %s",
+ (client -> active -> is_static
+ ? "fallback" : "recorded"),
+ piaddr (client -> active -> address));
/* Run the client script with the existing
parameters. */
script_init(client, "TIMEOUT",
@@ -2531,12 +2636,8 @@ void state_panic (cpp)
activate_next:
/* Otherwise, put the active lease at the end of the
lease list, and try another lease.. */
- for (lp = client -> leases; lp -> next; lp = lp -> next)
- ;
- lp -> next = client -> active;
- if (lp -> next) {
- lp -> next -> next = (struct client_lease *)0;
- }
+ add_to_tail(&client->leases, client->active);
+
client -> active = client -> leases;
client -> leases = client -> leases -> next;
@@ -4078,9 +4179,10 @@ void client_option_envadd (struct option_cache *oc,
"option - discarded",
name);
}
- data_string_forget (&data, MDL);
}
}
+
+ data_string_forget (&data, MDL);
}
}