summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancis Dupont <fdupont@isc.org>2020-10-13 10:15:00 +0200
committerFrancis Dupont <fdupont@isc.org>2020-10-13 10:15:00 +0200
commit3354013a47fe53f073c520c3c486ab9b7ff53601 (patch)
treed2a8749be54960d35cdec42d356813823227f5cf
parent933b80fa645924c9bc6bb0c32209ca0865d6a4b8 (diff)
downloadisc-dhcp-3354013a47fe53f073c520c3c486ab9b7ff53601.tar.gz
Checkpoint: code done, need tests
-rw-r--r--client/dhclient.c94
-rw-r--r--includes/dhcpd.h3
2 files changed, 74 insertions, 23 deletions
diff --git a/client/dhclient.c b/client/dhclient.c
index b989d1b7..1a7ac85e 100644
--- a/client/dhclient.c
+++ b/client/dhclient.c
@@ -1242,49 +1242,79 @@ void state_init (cpp)
send_discover (client);
}
-/* v6only_timeout is called when the V6ONLY_WAIT timer expired. */
+/* check_v6only is called by dhcpoffer and dhcpack. It checks if a
+ * requested v6-only-preferred option is present and returned the
+ * V6ONLY_WAIT delay to suspend DHCPv4. */
-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)
+uint32_t check_v6only(packet, client)
struct packet *packet;
struct client_state *client;
{
+ int i;
+ struct option **req;
+ isc_boolean_t found = ISC_FALSE;
struct option_cache *oc;
struct data_string data;
uint32_t v6only_wait = 0;
- struct timeval tv;
+ /* Check if the v6-only-preferred was requested. */
+ req = client->config->requested_options;
+
+ if (req == NULL)
+ return 0;
+
+ for (i = 0 ; req[i] != NULL ; i++) {
+ if ((req[i]->universe == &dhcp_universe) &&
+ (req[i]->code == DHO_V6_ONLY_PREFERRED)) {
+ found = ISC_TRUE;
+ break;
+ }
+ }
+
+ if (found == ISC_FALSE)
+ return 0;
+
/* Get the V6ONLY_WAIT timer. */
oc = lookup_option(&dhcp_universe, packet->options,
DHO_V6_ONLY_PREFERRED);
- if (!oc) {
- /* Should not happen... */
- return;
- }
+ if (!oc)
+ return 0;
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)
+ if (data.len > 3) {
v6only_wait = getULong(data.data);
+ if (v6only_wait < MIN_V6ONLY_WAIT)
+ v6only_wait = MIN_V6ONLY_WAIT;
+ }
data_string_forget(&data, MDL);
}
- if (v6only_wait < MIN_V6ONLY_WAIT)
- v6only_wait = MIN_V6ONLY_WAIT;
+ return (v6only_wait);
+}
+
+/* finish_v6only 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);
+}
+
+/*
+ * start_v6only is called when a requested v6-only-preferred option was
+ * returned by the server. */
+
+void start_v6only(client, v6only_wait)
+ struct client_state *client;
+ uint32_t v6only_wait;
+{
+ struct timeval tv;
/* Enter V6ONLY state. */
@@ -1404,6 +1434,7 @@ void dhcpack (packet)
{
struct interface_info *ip = packet -> interface;
struct client_state *client;
+ uint32_t v6only_wait;
struct client_lease *lease;
struct option_cache *oc;
struct data_string ds;
@@ -1439,6 +1470,15 @@ void dhcpack (packet)
inet_ntoa(packet->raw->yiaddr),
piaddr (packet->client_addr));
+ /* Check v6only first. */
+ v6only_wait = check_v6only(packet, client);
+ if (v6only_wait > 0) {
+ log_info("v6 only preferred for %lu.",
+ (long unsigned)v6only_wait);
+ start_v6only(client, v6only_wait);
+ return;
+ }
+
lease = packet_to_lease (packet, client);
if (!lease) {
log_info ("packet_to_lease failed.");
@@ -2077,6 +2117,7 @@ void dhcpoffer (packet)
{
struct interface_info *ip = packet -> interface;
struct client_state *client;
+ uint32_t v6only_wait;
struct client_lease *lease, *lp;
struct option **req;
int i;
@@ -2112,6 +2153,15 @@ void dhcpoffer (packet)
inet_ntoa(packet->raw->yiaddr),
piaddr(packet->client_addr));
+ /* Check v6only first. */
+ v6only_wait = check_v6only(packet, client);
+ if (v6only_wait > 0) {
+ log_info("%s: v6 only preferred for %lu.", obuf,
+ (long unsigned)v6only_wait);
+ start_v6only(client, v6only_wait);
+ return;
+ }
+
/* If this lease doesn't supply the minimum required DHCPv4 parameters,
* ignore it.
*/
diff --git a/includes/dhcpd.h b/includes/dhcpd.h
index caeeaeda..f9217ea8 100644
--- a/includes/dhcpd.h
+++ b/includes/dhcpd.h
@@ -3008,7 +3008,8 @@ void state_bound (void *);
void state_stop (void *);
void state_panic (void *);
-void start_v6only (struct packet *, struct client_state *);
+uint32_t check_v6only (struct packet *, struct client_state *);
+void start_v6only (struct client_state *, uint32_t);
void finish_v6only (void *);
void bind_lease (struct client_state *);