PATCH: udhcpc -- don't request set of options by default

L. Gabriel Somlo somlo at cmu.edu
Tue Apr 1 21:09:18 UTC 2008


Denys & All,

I noticed that udhcpc sends a default list of options in its request
(i.e., all options listed with flag OPTION_REQ in options.c)

That's bad, at least when used with some versions of isc dhcpd, which
will only include the requested options in a reply.

I know about the -O flag that can get udhcpc to request extra options,
but what if I want to see options I didn't think about asking for ?
Including a default option list in the request will always preclude me
from seeing options I didn't know to ask for.

I've added the '-o' command line flag to udhcpc, which inhibits
inclusion of default options in the request. Options can still be
explicitly requested with -O.

I have also added a mechanism to request '-o' (actually, its long form
--no-default-options) from ifupdown's /etc/network/interfaces:

	auto eth0
	iface eth0 inet dhcp
	  nodefaultopts --no-default-options

Last, but not least, a slightly more complex sample udhcpc.script,
which attempts to react to changes in parameters returned by the dhcp
server in a minimal-effort sort of way (i.e. don't reconfigure the
interface if the only change was in the list of ntp servers, etc.)

Please note that I did not change anything in the default behavior,
although I'd like to propose that udhcpc should not ask for a default
list of options unless we explicitly tell it to do so...

Please let me know what you think, and apply if you agree.

Regards,
--Gabriel
-------------- next part --------------
diff -NarU5 busybox-svn-21617.orig/examples/udhcp/udhcpc.script busybox-svn-21617/examples/udhcp/udhcpc.script
--- busybox-svn-21617.orig/examples/udhcp/udhcpc.script	1969-12-31 19:00:00.000000000 -0500
+++ busybox-svn-21617/examples/udhcp/udhcpc.script	2008-04-01 16:25:24.000000000 -0400
@@ -0,0 +1,88 @@
+#!/bin/busybox sh
+
+# a more "complex" udhcpc script that attempts to handle option changes with minimal work
+# Gabriel Somlo <somlo at cmu.edu>, 04/01/2008
+
+[ -z "$1" ] && echo 'Error: should be called from udhcpc' && exit 1
+
+CFG="/var/run/udhcpc.${interface}.cfg"
+RESOLV_CONF='/etc/resolv.conf'
+NTP_CONF='/etc/ntp.conf'
+# which interface configures DNS and NTP ? Comment out if none:
+PEERDNS_IF=eth0
+PEERNTP_IF=eth0
+
+case "$1" in
+  deconfig)
+    ip addr flush dev $interface
+    ip link set up dev $interface
+    rm -f $CFG
+    if [ "$PEERDNS_IF" == "$interface" ] ; then
+      [ -f ${RESOLV_CONF}.dhcsave ] && mv -f ${RESOLV_CONF}.dhcsave $RESOLV_CONF
+    fi
+    if [ "$PEERNTP_IF" == "$interface" ] ; then
+      [ -f ${NTP_CONF}.dhcsave ] && mv -f ${NTP_CONF}.dhcsave $NTP_CONF
+    fi
+    ;;
+  bound)
+    set > $CFG
+    ip addr flush dev $interface
+    [ -n "$mtu" ] && ip link set mtu $mtu dev $interface
+    ip addr add ${ip}/${mask} dev $interface
+    [ -n "$router" ] && ip route add default via ${router%% *} dev $interface
+    if [ "$PEERDNS_IF" == "$interface" ] ; then
+      [ -f $RESOLV_CONF ] && mv -f $RESOLV_CONF ${RESOLV_CONF}.dhcsave
+      [ -n "$domain" ] && echo search $domain > $RESOLV_CONF
+      for i in $dns ; do
+        echo nameserver $i >> $RESOLV_CONF
+      done
+    fi
+    if [ "$PEERNTP_IF" == "$interface" ] ; then
+      [ -f $NTP_CONF ] && mv -f $NTP_CONF ${NTP_CONF}.dhcsave
+      > $NTP_CONF
+      for i in $ntpsrv ; do
+        echo server $i >> $NTP_CONF
+      done
+    fi
+    ;;
+  renew)
+    set > ${CFG}.new
+    for i in $(diff -U1 $CFG ${CFG}.new | grep -E ^[+-] \
+                                        | tail +3 \
+                                        | awk -F[+-=] '{print $2}') ; do
+      case "$i" in
+        ip|mask|router|mtu)
+          REDO_NET='yes'
+          ;;
+        domain|dns)
+          REDO_DNS='yes'
+          ;;
+        ntpsrv)
+          REDO_NTP='yes'
+          ;;
+      esac
+    done
+    mv -f ${CFG}.new $CFG
+    if [ -n "$REDO_NET" ] ; then
+      ip addr flush dev $interface
+      [ -n "$mtu" ] && ip link set mtu $mtu dev $interface
+      ip addr add ${ip}/${mask} dev $interface
+      [ -n "$router" ] && ip route add default via ${router%% *} dev $interface
+    fi
+    if [ -n "$REDO_DNS" -a "$PEERDNS_IF" == "$interface" ] ; then
+      [ -n "$domain" ] && echo search $domain > $RESOLV_CONF
+      for i in $dns ; do
+        echo nameserver $i >> $RESOLV_CONF
+      done
+    fi
+    if [ -n "$REDO_NTP" -a "$PEERNTP_IF" == "$interface" ] ; then
+      > $NTP_CONF
+      for i in $ntpsrv ; do
+        echo server $i >> $NTP_CONF
+      done
+      # FIXME: RELOAD NTP DAEMON HERE
+    fi
+    ;;
+esac
+
+exit 0
diff -NarU5 busybox-svn-21617.orig/include/usage.h busybox-svn-21617/include/usage.h
--- busybox-svn-21617.orig/include/usage.h	2008-04-01 14:47:29.000000000 -0400
+++ busybox-svn-21617/include/usage.h	2008-04-01 15:20:40.000000000 -0400
@@ -4114,11 +4114,11 @@
        "[-T last-check-time] [-U UUID] device"
 #define tune2fs_full_usage \
        "Adjust filesystem options on ext[23] filesystems"
 
 #define udhcpc_trivial_usage \
-       "[-Cfbnqtv] [-c CID] [-V VCLS] [-H HOSTNAME] [-i INTERFACE]\n" \
+       "[-Cfbnqtvo] [-c CID] [-V VCLS] [-H HOSTNAME] [-i INTERFACE]\n" \
        "	[-p pidfile] [-r IP] [-s script] [-O dhcp-option]..." USE_FEATURE_UDHCP_PORT(" [-P N]")
 #define udhcpc_full_usage \
 	USE_GETOPT_LONG( \
        "	-V,--vendorclass=CLASSID	Vendor class identifier" \
      "\n	-i,--interface=INTERFACE	Interface to use (default eth0)" \
@@ -4142,10 +4142,11 @@
      "\n	-P,--client-port N  Use port N instead of default 68" \
 	) \
 	USE_FEATURE_UDHCPC_ARPING( \
      "\n	-a,--arping	Use arping to validate offered address" \
 	) \
+     "\n	-o,--no-default-options	Do not request options by default" \
 	) \
 	SKIP_GETOPT_LONG( \
        "	-V CLASSID	Vendor class identifier" \
      "\n	-i INTERFACE	Interface to use (default: eth0)" \
      "\n	-H,-h HOSTNAME	Client hostname" \
diff -NarU5 busybox-svn-21617.orig/networking/ifupdown.c busybox-svn-21617/networking/ifupdown.c
--- busybox-svn-21617.orig/networking/ifupdown.c	2008-04-01 14:47:25.000000000 -0400
+++ busybox-svn-21617/networking/ifupdown.c	2008-04-01 16:09:02.000000000 -0400
@@ -474,11 +474,11 @@
 	{ "pump",
 		"pump -i %iface%[[ -h %hostname%]][[ -l %leasehours%]]",
 		"pump -i %iface% -k",
 	},
 	{ "udhcpc",
-		"udhcpc -R -n -p /var/run/udhcpc.%iface%.pid -i %iface%[[ -H %hostname%]][[ -c %clientid%]][[ -s %script%]][[ -t %retries%]]",
+		"udhcpc -R -n -p /var/run/udhcpc.%iface%.pid -i %iface%[[ -H %hostname%]][[ -c %clientid%]][[ -s %script%]][[ -t %retries%]][[ %nodefaultopts%]]",
 		"kill `cat /var/run/udhcpc.%iface%.pid` 2>/dev/null",
 	},
 };
 #endif /* ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCPC */
 
@@ -505,11 +505,11 @@
 	/* ip doesn't up iface when it configures it (unlike ifconfig) */
 	if (!execute("ip link set %iface% up", ifd, exec))
 		return 0;
 #endif
 	return execute("udhcpc -R -n -p /var/run/udhcpc.%iface%.pid "
-			"-i %iface%[[ -H %hostname%]][[ -c %clientid%]][[ -s %script%]][[ -t %retries%]]",
+			"-i %iface%[[ -H %hostname%]][[ -c %clientid%]][[ -s %script%]][[ -t %retries%]][[ %nodefaultopts%]]",
 			ifd, exec);
 }
 #else
 static int dhcp_up(struct interface_defn_t *ifd ATTRIBUTE_UNUSED,
 		execfn *exec ATTRIBUTE_UNUSED)
diff -NarU5 busybox-svn-21617.orig/networking/udhcp/clientpacket.c busybox-svn-21617/networking/udhcp/clientpacket.c
--- busybox-svn-21617.orig/networking/udhcp/clientpacket.c	2008-04-01 14:47:25.000000000 -0400
+++ busybox-svn-21617/networking/udhcp/clientpacket.c	2008-04-01 15:04:18.000000000 -0400
@@ -62,11 +62,11 @@
 	int end = end_option(packet->options);
 	int i, len = 0;
 
 	packet->options[end + OPT_CODE] = DHCP_PARAM_REQ;
 	for (i = 0; (c = dhcp_options[i].code) != 0; i++) {
-		if ((dhcp_options[i].flags & OPTION_REQ)
+		if (((dhcp_options[i].flags & OPTION_REQ) && !client_config.no_default_options)
 		 || (client_config.opt_mask[c >> 3] & (1 << (c & 7)))
 		) {
 			packet->options[end + OPT_DATA + len] = c;
 			len++;
 		}
diff -NarU5 busybox-svn-21617.orig/networking/udhcp/dhcpc.c busybox-svn-21617/networking/udhcp/dhcpc.c
--- busybox-svn-21617.orig/networking/udhcp/dhcpc.c	2008-04-01 14:47:25.000000000 -0400
+++ busybox-svn-21617/networking/udhcp/dhcpc.c	2008-04-01 15:01:01.000000000 -0400
@@ -180,10 +180,11 @@
 #if ENABLE_FEATURE_UDHCPC_ARPING
 		OPT_a = 1 << 20,
 		OPT_W = 1 << 21,
 #endif
 		OPT_P = 1 << 22,
+		OPT_o = 1 << 23,
 	};
 #if ENABLE_GETOPT_LONG
 	static const char udhcpc_longopts[] ALIGN1 =
 		"clientid\0"       Required_argument "c"
 		"clientid-none\0"  No_argument       "C"
@@ -209,10 +210,11 @@
 #endif
 		"request-option\0" Required_argument "O"
 #if ENABLE_FEATURE_UDHCP_PORT
 		"client-port\0"	   Required_argument "P"
 #endif
+		"no-default-options\0"	No_argument "o"
 		;
 #endif
 	/* Default options. */
 #if ENABLE_FEATURE_UDHCP_PORT
 	SERVER_PORT = 67;
@@ -228,11 +230,11 @@
 	applet_long_options = udhcpc_longopts;
 #endif
 	opt = getopt32(argv, "c:CV:fbH:h:F:i:np:qRr:s:T:t:vSA:"
 		USE_FEATURE_UDHCPC_ARPING("aW:")
 		USE_FEATURE_UDHCP_PORT("P:")
-		"O:"
+		"O:o:"
 		, &str_c, &str_V, &str_h, &str_h, &str_F
 		, &client_config.interface, &client_config.pidfile, &str_r
 		, &client_config.script
 		, &discover_timeout, &discover_retries, &tryagain_timeout
 		USE_FEATURE_UDHCPC_ARPING(, &str_W)
@@ -289,10 +291,12 @@
 	if (opt & OPT_P) {
 		CLIENT_PORT = xatou16(str_P);
 		SERVER_PORT = CLIENT_PORT - 1;
 	}
 #endif
+	if (opt & OPT_o)
+		client_config.no_default_options = 1;
 	while (list_O) {
 		int n = index_in_strings(dhcp_option_strings, list_O->data);
 		if (n < 0)
 			bb_error_msg_and_die("unknown option '%s'", list_O->data);
 		n = dhcp_options[n].code;
diff -NarU5 busybox-svn-21617.orig/networking/udhcp/dhcpc.h busybox-svn-21617/networking/udhcp/dhcpc.h
--- busybox-svn-21617.orig/networking/udhcp/dhcpc.h	2008-04-01 14:47:25.000000000 -0400
+++ busybox-svn-21617/networking/udhcp/dhcpc.h	2008-04-01 14:56:12.000000000 -0400
@@ -19,10 +19,11 @@
 	char foreground;                /* Do not fork */
 	char quit_after_lease;          /* Quit after obtaining lease */
 	char release_on_quit;           /* Perform release on quit */
 	char abort_if_no_lease;         /* Abort if no lease */
 	char background_if_no_lease;    /* Fork to background if no lease */
+	char no_default_options;	    /* Do not include default optins in request */
 	const char *interface;          /* The name of the interface to use */
 	char *pidfile;                  /* Optionally store the process ID */
 	const char *script;             /* User script to run at dhcp events */
 	uint8_t *clientid;              /* Optional client id to use */
 	uint8_t *vendorclass;           /* Optional vendor class-id to use */


More information about the busybox mailing list