Hi,

If the dhclient receives an OFFER or ACK, that does not contain all required 
parameters, a DECLINE is send. This DECLINE has the 'Requested IP Address' 
(DHO_DHCP_REQUESTET_ADDRESS) set to 0 instead of using the client IP address 
(yiaddr) from the packet. As far as I see it, the 'Requested IP Address' is the 
address the dhclient is declining, so the yiaddr would make more sense than 0.

This happens in dhclient.c::packet_to_lease() and only if not all required 
parameters are in the packet. For all other cases the 'Requested IP Address' of 
the DECLINE is set to the yiaddr from the OFFER / ACK packet. My fix would be 
to store (and check) the yiaddr from the packet before the first jump to the 
decline label occurs. I have included a diff below.

Best Regards,
Dominik

diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c
index 007358c5008..b287c19a3b2 100644
--- a/sbin/dhclient/dhclient.c
+++ b/sbin/dhclient/dhclient.c
@@ -1257,18 +1257,6 @@ packet_to_lease(struct interface_info *ifi, struct 
option_data *options)
                options[i].len = 0;
        }

-       /*
-        * If this lease doesn't supply a required parameter, decline it.
-        */
-       for (i = 0; i < config->required_option_count; i++) {
-               if (lease->options[config->required_options[i]].len == 0) {
-                       name = code_to_name(config->required_options[i]);
-                       log_warnx("%s: %s required but missing", log_procname,
-                           name);
-                       goto decline;
-               }
-       }
-
        /*
         * If this lease is trying to sell us an address we are already
         * using, decline it.
@@ -1282,6 +1270,18 @@ packet_to_lease(struct interface_info *ifi, struct 
option_data *options)
                goto decline;
        }

+       /*
+        * If this lease doesn't supply a required parameter, decline it.
+        */
+       for (i = 0; i < config->required_option_count; i++) {
+               if (lease->options[config->required_options[i]].len == 0) {
+                       name = code_to_name(config->required_options[i]);
+                       log_warnx("%s: %s required but missing", log_procname,
+                           name);
+                       goto decline;
+               }
+       }
+
        /* Save the siaddr (a.k.a. next-server) info. */
        lease->next_server.s_addr = packet->siaddr.s_addr;

Reply via email to