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