summary refs log tree commit diff
path: root/src/n-dhcp4
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2022-08-16 18:24:19 +0200
committerMichael Biebl <biebl@debian.org>2022-08-16 18:24:19 +0200
commit0018d1f3cf71d680d7b6bceda55a5717244d8b26 (patch)
treea058f1d106d172d3354179437ef034c9355cdf9c /src/n-dhcp4
parent6accbd3ec0e42d8633bbde4d47ed7bfe854e7e0b (diff)
New upstream version 1.39.90 upstream/1.39.90
Diffstat (limited to 'src/n-dhcp4')
-rw-r--r--src/n-dhcp4/src/n-dhcp4-c-lease.c64
-rw-r--r--src/n-dhcp4/src/n-dhcp4-c-probe.c52
-rw-r--r--src/n-dhcp4/src/n-dhcp4-client.c4
-rw-r--r--src/n-dhcp4/src/n-dhcp4-private.h1
4 files changed, 50 insertions, 71 deletions
diff --git a/src/n-dhcp4/src/n-dhcp4-c-lease.c b/src/n-dhcp4/src/n-dhcp4-c-lease.c
index bae2f674..be0d7886 100644
--- a/src/n-dhcp4/src/n-dhcp4-c-lease.c
+++ b/src/n-dhcp4/src/n-dhcp4-c-lease.c
@@ -251,7 +251,7 @@ _c_public_ void n_dhcp4_client_lease_get_lifetime(NDhcp4ClientLease *lease, uint
  *
  * Return: 0 on success,
  *         N_DHCP4_E_UNSET if the lease doesn't contain a server-identifier, or
- *         N_DCHP4_E_INTERNAL if the server-identifier is not valid.
+ *         N_DHCP4_E_INTERNAL if the server-identifier is not valid.
  */
 _c_public_ int n_dhcp4_client_lease_get_server_identifier(NDhcp4ClientLease *lease, struct in_addr *addr) {
         uint8_t *data;
@@ -279,25 +279,25 @@ _c_public_ int n_dhcp4_client_lease_get_server_identifier(NDhcp4ClientLease *lea
  *
  * Return: 0 on success,
  *         N_DHCP4_E_UNSET if the lease does not contain a file name, or
- *         N_DCHP4_E_INTERNAL if the file name is invalid.
+ *         N_DHCP4_E_INTERNAL if the file name is invalid.
  */
 _c_public_ int n_dhcp4_client_lease_get_file(NDhcp4ClientLease *lease, const char **file) {
         NDhcp4Message *message;
 
         if (lease->message->options[N_DHCP4_OPTION_OVERLOAD].size > 0
             && ((*lease->message->options[N_DHCP4_OPTION_OVERLOAD].value) & N_DHCP4_OVERLOAD_FILE)) {
-            /* The field is overloaded to contain other options */
-            return N_DHCP4_E_UNSET;
+                /* The field is overloaded to contain other options */
+                return N_DHCP4_E_UNSET;
         }
 
         message = &lease->message->message;
 
         if (message->file[0] == '\0')
-            return N_DHCP4_E_UNSET;
+                return N_DHCP4_E_UNSET;
 
         if (!memchr(message->file, '\0', sizeof(message->file))) {
-            /* The field is NULL-terminated (RFC 2131 section 2) */
-            return N_DHCP4_E_INTERNAL;
+                /* The field is NULL-terminated (RFC 2131 section 2) */
+                return N_DHCP4_E_INTERNAL;
         }
 
         *file = (const char *) message->file;
@@ -316,7 +316,7 @@ _c_public_ int n_dhcp4_client_lease_get_file(NDhcp4ClientLease *lease, const cha
  * be queried, and only options that were explicitly requested can be queried.
  *
  * Return: 0 on success,
- *         N_DCHP4_E_INTERNAL if an invalid option is queried,
+ *         N_DHCP4_E_INTERNAL if an invalid option is queried,
  *         N_DHCP4_E_UNSET if the lease did not contain the option, or
  *         a negative error code on failure.
  */
@@ -351,32 +351,15 @@ _c_public_ int n_dhcp4_client_lease_query(NDhcp4ClientLease *lease, uint8_t opti
  * selected none of the others can be.
  *
  * Return: 0 on success, or a negative error code on failure.
+ *   Returns -ENOTRECOVERABLE when called in an unexpected state.
  */
 _c_public_ int n_dhcp4_client_lease_select(NDhcp4ClientLease *lease) {
-        NDhcp4ClientLease *l, *t_l;
-        NDhcp4ClientProbe *probe;
-        int r;
-
-        /* XXX error handling, this must be an OFFER */
-
         if (!lease->probe)
                 return -ENOTRECOVERABLE;
         if (lease->probe->current_lease)
                 return -ENOTRECOVERABLE;
 
-        r = n_dhcp4_client_probe_transition_select(lease->probe, lease->message, n_dhcp4_gettime(CLOCK_BOOTTIME));
-        if (r)
-                return r;
-
-        /*
-         * Only one of the offered leases can be selected, so flush the list.
-         * All offered lease, including this one are now dead.
-         */
-        probe = lease->probe;
-        c_list_for_each_entry_safe(l, t_l, &probe->lease_list, probe_link)
-                n_dhcp4_client_lease_unlink(l);
-
-        return 0;
+        return n_dhcp4_client_probe_transition_select(lease->probe, lease->message, n_dhcp4_gettime(CLOCK_BOOTTIME));
 }
 
 /**
@@ -390,24 +373,15 @@ _c_public_ int n_dhcp4_client_lease_select(NDhcp4ClientLease *lease) {
  * can be accepted.
  *
  * Return: 0 on success, or a negative error code on failure.
+ *   Returns -ENOTRECOVERABLE when called in an unexpected state.
  */
 _c_public_ int n_dhcp4_client_lease_accept(NDhcp4ClientLease *lease) {
-        int r;
-
-        /* XXX error handling, this must be an ACK */
-
         if (!lease->probe)
                 return -ENOTRECOVERABLE;
         if (lease->probe->current_lease != lease)
                 return -ENOTRECOVERABLE;
 
-        r = n_dhcp4_client_probe_transition_accept(lease->probe, lease->message);
-        if (r)
-                return r;
-
-        n_dhcp4_client_lease_unlink(lease);
-
-        return 0;
+        return n_dhcp4_client_probe_transition_accept(lease->probe, lease->message);
 }
 
 /**
@@ -421,23 +395,13 @@ _c_public_ int n_dhcp4_client_lease_accept(NDhcp4ClientLease *lease) {
  * decline.
  *
  * Return: 0 on success, or a negative error code on failure.
+ *   Returns -ENOTRECOVERABLE when called in an unexpected state.
  */
 _c_public_ int n_dhcp4_client_lease_decline(NDhcp4ClientLease *lease, const char *error) {
-        int r;
-
-        /* XXX: error handling, this must be an ACK */
-
         if (!lease->probe)
                 return -ENOTRECOVERABLE;
         if (lease->probe->current_lease != lease)
                 return -ENOTRECOVERABLE;
 
-        r = n_dhcp4_client_probe_transition_decline(lease->probe, lease->message, error, n_dhcp4_gettime(CLOCK_BOOTTIME));
-        if (r)
-                return r;
-
-        lease->probe->current_lease = n_dhcp4_client_lease_unref(lease->probe->current_lease);
-        n_dhcp4_client_lease_unlink(lease);
-
-        return 0;
+        return n_dhcp4_client_probe_transition_decline(lease->probe, lease->message, error, n_dhcp4_gettime(CLOCK_BOOTTIME));
 }
diff --git a/src/n-dhcp4/src/n-dhcp4-c-probe.c b/src/n-dhcp4/src/n-dhcp4-c-probe.c
index 283c1693..284aa428 100644
--- a/src/n-dhcp4/src/n-dhcp4-c-probe.c
+++ b/src/n-dhcp4/src/n-dhcp4-c-probe.c
@@ -1024,6 +1024,7 @@ static int n_dhcp4_client_probe_transition_nak(NDhcp4ClientProbe *probe) {
 
 int n_dhcp4_client_probe_transition_select(NDhcp4ClientProbe *probe, NDhcp4Incoming *offer, uint64_t ns_now) {
         _c_cleanup_(n_dhcp4_outgoing_freep) NDhcp4Outgoing *request = NULL;
+        NDhcp4ClientLease *l, *t_l;
         int r;
 
         switch (probe->state) {
@@ -1042,11 +1043,16 @@ int n_dhcp4_client_probe_transition_select(NDhcp4ClientProbe *probe, NDhcp4Incom
                 else
                         request = NULL; /* consumed */
 
-                /* XXX: ignore other offers */
-
                 probe->state = N_DHCP4_CLIENT_PROBE_STATE_REQUESTING;
 
-                break;
+                /*
+                 * Only one of the offered leases can be selected, so flush the list.
+                 * All offered lease, including this one are now dead.
+                 */
+                c_list_for_each_entry_safe(l, t_l, &probe->lease_list, probe_link)
+                        n_dhcp4_client_lease_unlink(l);
+
+                return 0;
         case N_DHCP4_CLIENT_PROBE_STATE_INIT:
         case N_DHCP4_CLIENT_PROBE_STATE_INIT_REBOOT:
         case N_DHCP4_CLIENT_PROBE_STATE_REBOOTING:
@@ -1057,11 +1063,9 @@ int n_dhcp4_client_probe_transition_select(NDhcp4ClientProbe *probe, NDhcp4Incom
         case N_DHCP4_CLIENT_PROBE_STATE_REBINDING:
         case N_DHCP4_CLIENT_PROBE_STATE_EXPIRED:
         default:
-                /* ignore */
-                break;
+                /* user called in invalid state. Return error. */
+                return -ENOTRECOVERABLE;
         }
-
-        return 0;
 }
 
 /**
@@ -1085,10 +1089,11 @@ int n_dhcp4_client_probe_transition_accept(NDhcp4ClientProbe *probe, NDhcp4Incom
                         return r;
 
                 probe->state = N_DHCP4_CLIENT_PROBE_STATE_BOUND;
-
+                probe->ns_decline_restart_delay = 0;
+                n_dhcp4_client_lease_unlink(probe->current_lease);
                 n_dhcp4_client_arm_timer(probe->client);
 
-                break;
+                return 0;
 
         case N_DHCP4_CLIENT_PROBE_STATE_INIT:
         case N_DHCP4_CLIENT_PROBE_STATE_INIT_REBOOT:
@@ -1100,11 +1105,9 @@ int n_dhcp4_client_probe_transition_accept(NDhcp4ClientProbe *probe, NDhcp4Incom
         case N_DHCP4_CLIENT_PROBE_STATE_REBINDING:
         case N_DHCP4_CLIENT_PROBE_STATE_EXPIRED:
         default:
-                /* ignore */
-                break;
+                /* user called in invalid state. Return error. */
+                return -ENOTRECOVERABLE;
         }
-
-        return 0;
 }
 
 /**
@@ -1126,9 +1129,22 @@ int n_dhcp4_client_probe_transition_decline(NDhcp4ClientProbe *probe, NDhcp4Inco
                 else
                         request = NULL; /* consumed */
 
-                /* XXX: what state to transition to? */
+                n_dhcp4_client_lease_unlink(probe->current_lease);
+                probe->current_lease = n_dhcp4_client_lease_unref(probe->current_lease);
+
+                probe->state = N_DHCP4_CLIENT_PROBE_STATE_INIT;
 
-                break;
+                /* RFC2131, 3.1, 5.) The client SHOULD wait a minimum of ten seconds before restarting
+                 * the configuration process to avoid excessive network traffic in case of looping.
+                 *
+                 * Let's go beyond that, and use an exponential backoff. */
+                probe->ns_decline_restart_delay = C_CLAMP(probe->ns_decline_restart_delay * 2u,
+                                                          UINT64_C(10)  * UINT64_C(1000000000),
+                                                          UINT64_C(300) * UINT64_C(1000000000));
+                probe->ns_deferred =  n_dhcp4_gettime(CLOCK_BOOTTIME) + probe->ns_decline_restart_delay;
+
+                n_dhcp4_client_arm_timer(probe->client);
+                return 0;
 
         case N_DHCP4_CLIENT_PROBE_STATE_INIT:
         case N_DHCP4_CLIENT_PROBE_STATE_INIT_REBOOT:
@@ -1140,11 +1156,9 @@ int n_dhcp4_client_probe_transition_decline(NDhcp4ClientProbe *probe, NDhcp4Inco
         case N_DHCP4_CLIENT_PROBE_STATE_REBINDING:
         case N_DHCP4_CLIENT_PROBE_STATE_EXPIRED:
         default:
-                /* ignore */
-                break;
+                /* user called in invalid state. Return error. */
+                return -ENOTRECOVERABLE;
         }
-
-        return 0;
 }
 
 /**
diff --git a/src/n-dhcp4/src/n-dhcp4-client.c b/src/n-dhcp4/src/n-dhcp4-client.c
index 1dedbf30..3b4a70c8 100644
--- a/src/n-dhcp4/src/n-dhcp4-client.c
+++ b/src/n-dhcp4/src/n-dhcp4-client.c
@@ -214,8 +214,8 @@ _c_public_ void n_dhcp4_client_config_set_mac(NDhcp4ClientConfig *config, const
 _c_public_ void n_dhcp4_client_config_set_broadcast_mac(NDhcp4ClientConfig *config, const uint8_t *mac, size_t n_mac) {
         config->n_broadcast_mac = n_mac;
 
-        if (n_mac > sizeof(config->mac))
-                n_mac = sizeof(config->mac);
+        if (n_mac > sizeof(config->broadcast_mac))
+                n_mac = sizeof(config->broadcast_mac);
 
         memcpy(config->broadcast_mac, mac, n_mac);
 }
diff --git a/src/n-dhcp4/src/n-dhcp4-private.h b/src/n-dhcp4/src/n-dhcp4-private.h
index 858c3d3a..6b366884 100644
--- a/src/n-dhcp4/src/n-dhcp4-private.h
+++ b/src/n-dhcp4/src/n-dhcp4-private.h
@@ -378,6 +378,7 @@ struct NDhcp4ClientProbe {
         uint64_t ns_deferred;                   /* timeout for deferred action */
         uint64_t ns_reinit;
         uint64_t ns_nak_restart_delay;          /* restart delay after a nak */
+        uint64_t ns_decline_restart_delay;      /* restart delay after a decline */
         NDhcp4ClientLease *current_lease;       /* current lease */
 
         NDhcp4CConnection connection;           /* client connection wrapper */