root cause of continuous DHCPDECLINE

Yeung, Pauline yeungp at cisco.com
Thu Jul 3 00:23:34 UTC 2008


We have a case of continuous DHCPDECLINE which depletes the complete IP
address pool in the DHCP server.  Since this takes at least 3 days to
reproduce even with a 15 minutes lease time, it has taken us a while to
get to the root cause of this issue.

We run dhclient in an embedded device using Linux 2.6.14, busybox 1.01,
glibc 2.4, and limited RAM.   The embedded device is slowly leaking
memory.  When it leaks below certain level, and if dhclient performs
renew, it can still fork the script.  But due to low memory, busybox
command inside the script may fail with "cannot fork" and return code 2,
or busybox may fail with "cannot load shared libraries" from the GNU
glibc loader ld-2.4.so and return code 127.

The return code 2 or 127 is returned in bit 8 to 15 of wstatus in line
2957 to script_go().  script_go() extracts the return code 2 or 127 in
line 2985.   bind_lease() decides to send DHCPDECLINE if return code is
non zero in line 958.

Since this low free memory condition persists, when dhclient performs
the next renew after a timeout, it repeats the above sequence.  The
continuous DHCPDECLINE becomes a DoS attack, and prevent other devices
to acquire an IP address from the DHCP server.

I resolved this by using return code 131 in the script
dhcp-4.1.0a1/client/scripts/linux.  Besides 2 and 127, return code -2 to
+6, 20, and 126 are also used by busybox 1.01 and ld-2.4.so and should
also be avoided.

<====== extracted from dhcp-4.1.0a1/client/dhclient.c =====>

 933 void bind_lease (client)
 934     struct client_state *client;
 935 {
:
 955     /* If the BOUND/RENEW code detects another machine using the
 956        offered address, it exits nonzero.  We need to send a
 957        DHCPDECLINE and toss the lease. */
 958     if (script_go (client)) {
 959         make_decline (client, client -> new);
 960         send_decline (client);
 961         destroy_client_lease (client -> new);
 962         client -> new = (struct client_lease *)0;
 963         state_init (client);
 964         return;
 965     }
:
:
2907 int script_go (client)
2908     struct client_state *client;
2909 {
:
2951     pid = fork ();
2952     if (pid < 0) {
2953         log_error ("fork: %m");
2954         wstatus = 0;
2955     } else if (pid) {
2956         do {
2957             wpid = wait (&wstatus);
2958         } while (wpid != pid && wpid > 0);
2959         if (wpid < 0) {
2960             log_error ("wait: %m");
2961             wstatus = 0;
2962         }
2963     } else {
2964         /* We don't want to pass an open file descriptor for
2965          * dhclient.leases when executing dhclient-script.
2966          */
2967         if (leaseFile != NULL)
2968             fclose(leaseFile);
2969         execve (scriptName, argv, envp);
2970         log_error ("execve (%s, ...): %m", scriptName);
2971         exit (0);
2972     }
:
2982     dfree (envp, MDL);
2983     gettimeofday(&cur_tv, NULL);
2984     return (WIFEXITED (wstatus) ?
2985         WEXITSTATUS (wstatus) : -WTERMSIG (wstatus));
2986 }



Pauline




     - - - - -                              Cisco                            - - - - -         
This e-mail and any attachments may contain information which is confidential, 
proprietary, privileged or otherwise protected by law. The information is solely 
intended for the named addressee (or a person responsible for delivering it to 
the addressee). If you are not the intended recipient of this message, you are 
not authorized to read, print, retain, copy or disseminate this message or any 
part of it. If you have received this e-mail in error, please notify the sender 
immediately by return e-mail and delete it from your computer.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.isc.org/pipermail/dhcp-users/attachments/20080702/4c9c7e4f/attachment.html>


More information about the dhcp-users mailing list