summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancis Dupont <fdupont@isc.org>2020-10-12 22:18:33 +0200
committerFrancis Dupont <fdupont@isc.org>2020-10-12 22:18:33 +0200
commit933b80fa645924c9bc6bb0c32209ca0865d6a4b8 (patch)
tree675e61775d1393df2e3c2b82ca836a3670c17bd5
parent9d8d2fb788ba28d514e8e0d157062a7788ec9609 (diff)
downloadisc-dhcp-933b80fa645924c9bc6bb0c32209ca0865d6a4b8.tar.gz
Checkpoint: added start/finish v6only
-rw-r--r--client/dhclient.c70
-rwxr-xr-xclient/scripts/linux8
-rw-r--r--includes/dhcpd.h10
3 files changed, 87 insertions, 1 deletions
diff --git a/client/dhclient.c b/client/dhclient.c
index 7a7837cb..b989d1b7 100644
--- a/client/dhclient.c
+++ b/client/dhclient.c
@@ -1242,6 +1242,73 @@ void state_init (cpp)
send_discover (client);
}
+/* v6only_timeout is called when the V6ONLY_WAIT timer expired. */
+
+void finish_v6only(cpp)
+ void *cpp;
+{
+ struct client_state *client = cpp;
+ client->state = S_INIT;
+ state_init(cpp);
+}
+
+/*
+ * state_v6only is called when a requested v6-only-preferred option was
+ * returned by the server. */
+
+void start_v6only(packet, client)
+ struct packet *packet;
+ struct client_state *client;
+{
+ struct option_cache *oc;
+ struct data_string data;
+ uint32_t v6only_wait = 0;
+ struct timeval tv;
+
+ /* Get the V6ONLY_WAIT timer. */
+ oc = lookup_option(&dhcp_universe, packet->options,
+ DHO_V6_ONLY_PREFERRED);
+ if (!oc) {
+ /* Should not happen... */
+ return;
+ }
+
+ memset(&data, 0, sizeof(data));
+
+ if (evaluate_option_cache(&data, packet, (struct lease *)0, client,
+ packet->options, (struct option_state *)0,
+ &global_scope, oc, MDL)) {
+ if (data.len > 3)
+ v6only_wait = getULong(data.data);
+ data_string_forget(&data, MDL);
+ }
+
+ if (v6only_wait < MIN_V6ONLY_WAIT)
+ v6only_wait = MIN_V6ONLY_WAIT;
+
+ /* Enter V6ONLY state. */
+
+ client->state = S_V6ONLY;
+
+ /* Run the client script. */
+ script_init(client, "V6ONLY", NULL);
+ if (client->active) {
+ script_write_params(client, "old_", client->active);
+ destroy_client_lease(client->active);
+ client->active = NULL;
+ }
+ script_write_requested(client);
+ client_envadd(client, "", "v6-only-preferred", "%lu",
+ (long unsigned)v6only_wait);
+ script_go(client);
+
+ /* Trigger finish_v6only after V6ONLY_WAIT seconds. */
+ tv.tv_sec = cur_tv.tv_sec + v6only_wait;
+ tv.tv_usec = cur_tv.tv_usec;
+
+ add_timeout(&tv, finish_v6only, client, 0, 0);
+}
+
/*
* state_selecting is called when one or more DHCPOFFER packets have been
* received and a configurable period of time has passed.
@@ -1650,6 +1717,7 @@ void state_stop (cpp)
cancel_timeout(send_discover, client);
cancel_timeout(send_request, client);
cancel_timeout(state_bound, client);
+ cancel_timeout(finish_v6only, client);
/* If we have an address, unconfigure it. */
if (client->active) {
@@ -4623,6 +4691,7 @@ void client_location_changed ()
case S_REBINDING:
case S_STOPPED:
case S_DECLINING:
+ case S_V6ONLY:
break;
}
client -> state = S_INIT;
@@ -4701,6 +4770,7 @@ void do_release(client)
cancel_timeout (state_init, client);
cancel_timeout (send_request, client);
cancel_timeout (state_reboot, client);
+ cancel_timeout (finish_v6only, client);
client -> state = S_STOPPED;
#if defined(DHCPv6) && defined(DHCP4o6)
diff --git a/client/scripts/linux b/client/scripts/linux
index 0c429697..63257bca 100755
--- a/client/scripts/linux
+++ b/client/scripts/linux
@@ -400,6 +400,14 @@ case "$reason" in
;;
+ V6ONLY)
+ if [ -n "$old_ip_address" ]; then
+ # flush leased IP
+ ${ip} -4 addr flush dev ${interface} label ${interface}
+ fi
+
+ ;;
+
### DHCPv6 Handlers
# TODO handle prefix change: ?based on ${old_ip6_prefix} and ${new_ip6_prefix}?
diff --git a/includes/dhcpd.h b/includes/dhcpd.h
index b20dd240..caeeaeda 100644
--- a/includes/dhcpd.h
+++ b/includes/dhcpd.h
@@ -877,6 +877,10 @@ struct lease_state {
# define DEFAULT_ABANDON_LEASE_TIME 86400
#endif
+#if !defined (MIN_V6ONLY_WAIT)
+# define MIN_V6ONLY_WAIT 300
+#endif
+
#define PLM_IGNORE 0
#define PLM_PREFER 1
#define PLM_EXACT 2
@@ -1204,7 +1208,8 @@ enum dhcp_state {
S_RENEWING = 6,
S_REBINDING = 7,
S_DECLINING = 8,
- S_STOPPED = 9
+ S_STOPPED = 9,
+ S_V6ONLY = 10
};
/* Possible pending client operations. */
@@ -3003,6 +3008,9 @@ void state_bound (void *);
void state_stop (void *);
void state_panic (void *);
+void start_v6only (struct packet *, struct client_state *);
+void finish_v6only (void *);
+
void bind_lease (struct client_state *);
void make_client_options (struct client_state *,