Blob Blame History Raw
--- dhcp-3.0.5/client/scripts/linux.dbus-example.enoi	2006-11-13 12:59:34.000000000 -0500
+++ dhcp-3.0.5/client/scripts/linux.dbus-example	2006-11-13 12:59:26.000000000 -0500
@@ -0,0 +1,223 @@
+#!/bin/bash
+# dhclient-script for Linux. Dan Halbert, March, 1997.
+# Updated for Linux 2.[12] by Brian J. Murrell, January 1999.
+# No guarantees about this. I'm a novice at the details of Linux
+# networking.
+
+# Notes:
+
+# 0. This script is based on the netbsd script supplied with dhcp-970306.
+
+# 1. ifconfig down apparently deletes all relevant routes and flushes
+# the arp cache, so this doesn't need to be done explicitly.
+
+# 2. The alias address handling here has not been tested AT ALL.
+# I'm just going by the doc of modern Linux ip aliasing, which uses
+# notations like eth0:0, eth0:1, for each alias.
+
+# 3. I have to calculate the network address, and calculate the broadcast
+# address if it is not supplied. This might be much more easily done
+# by the dhclient C code, and passed on.
+
+# 4. TIMEOUT not tested. ping has a flag I don't know, and I'm suspicious
+# of the $1 in its args.
+
+if [ -n "${dhc_dbus}" ]; then
+  /bin/dbus-send \
+    --system --dest=com.redhat.dhcp --type=method_call \
+    /com/redhat/dhcp/$interface com.redhat.dhcp.set \
+    'string:'"`env | /bin/egrep -v '^(PATH|SHLVL|_|PWD|dhc_dbus)\='`";
+    if (( ( dhc_dbus & 31 ) == 31 )); then
+    exit 0;
+    fi;
+fi;
+
+make_resolv_conf() {
+  if [ "x$new_domain_name" != x ] && [ x"$new_domain_name_servers" != x ]; then
+    echo search $new_domain_name >/etc/resolv.conf
+    chmod 644 /etc/resolv.conf
+    for nameserver in $new_domain_name_servers; do
+      echo nameserver $nameserver >>/etc/resolv.conf
+    done
+  fi
+}
+
+# Must be used on exit.   Invokes the local dhcp client exit hooks, if any.
+exit_with_hooks() {
+  exit_status=$1
+  if [ -f /etc/dhclient-exit-hooks ]; then
+    . /etc/dhclient-exit-hooks
+  fi
+# probably should do something with exit status of the local script
+  exit $exit_status
+}
+
+# Invoke the local dhcp client enter hooks, if they exist.
+if [ -f /etc/dhclient-enter-hooks ]; then
+  exit_status=0
+  . /etc/dhclient-enter-hooks
+  # allow the local script to abort processing of this state
+  # local script must set exit_status variable to nonzero.
+  if [ $exit_status -ne 0 ]; then
+    exit $exit_status
+  fi
+fi
+
+release=`uname -r`
+release=`expr $release : '\(.*\)\..*'`
+relminor=`echo $release |sed -e 's/[0-9]*\.\([0-9][0-9]*\)\(\..*\)*$/\1/'`
+relmajor=`echo $release |sed -e 's/\([0-9][0-9]*\)\..*$/\1/'`
+
+if [ x$new_broadcast_address != x ]; then
+  new_broadcast_arg="broadcast $new_broadcast_address"
+fi
+if [ x$old_broadcast_address != x ]; then
+  old_broadcast_arg="broadcast $old_broadcast_address"
+fi
+if [ x$new_subnet_mask != x ]; then
+  new_subnet_arg="netmask $new_subnet_mask"
+fi
+if [ x$old_subnet_mask != x ]; then
+  old_subnet_arg="netmask $old_subnet_mask"
+fi
+if [ x$alias_subnet_mask != x ]; then
+  alias_subnet_arg="netmask $alias_subnet_mask"
+fi
+
+if [ x$reason = xMEDIUM ]; then
+  # Linux doesn't do mediums (ok, ok, media).
+  exit_with_hooks 0
+fi
+
+if [ x$reason = xPREINIT ]; then
+  if [ x$alias_ip_address != x ]; then
+    # Bring down alias interface. Its routes will disappear too.
+    ifconfig $interface:0- inet 0
+  fi
+  if [ $relmajor -lt 2 ] || ( [ $relmajor -eq 2 ] && [ $relminor -eq 0 ] )
+   then
+    ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 \
+		broadcast 255.255.255.255 up
+    # Add route to make broadcast work. Do not omit netmask.
+    route add default dev $interface netmask 0.0.0.0
+  else
+    ifconfig $interface 0 up
+  fi
+
+  # We need to give the kernel some time to get the interface up.
+  sleep 1
+
+  exit_with_hooks 0
+fi
+
+if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then
+  exit_with_hooks 0
+fi
+  
+if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \
+   [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then
+  current_hostname=`hostname`
+  if [ x$current_hostname = x ] || \
+     [ x$current_hostname = x$old_host_name ]; then
+    if [ x$current_hostname = x ] || \
+       [ x$new_host_name != x$old_host_name ]; then
+      hostname $new_host_name
+    fi
+  fi
+
+  if [ -z "${dhc_dbus}" ] || (( ( dhc_dbus & 2 ) != 2 )); then
+  if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \
+		[ x$alias_ip_address != x$old_ip_address ]; then
+    # Possible new alias. Remove old alias.
+    ifconfig $interface:0- inet 0
+  fi
+  if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]; then
+    # IP address changed. Bringing down the interface will delete all routes,
+    # and clear the ARP cache.
+    ifconfig $interface inet 0 down
+
+  fi
+  fi
+  if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \
+     [ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then
+  if [ -z "${dhc_dbus}" ] || (( ( dhc_dbus & 2 ) != 2 )); then
+    ifconfig $interface inet $new_ip_address $new_subnet_arg \
+							$new_broadcast_arg
+  fi
+  if [ -z "${dhc_dbus}" ] || (( ( dhc_dbus & 4 ) != 4 )); then
+    # Add a network route to the computed network address.
+    if [ $relmajor -lt 2 ] || \
+		( [ $relmajor -eq 2 ] && [ $relminor -eq 0 ] ); then
+      route add -net $new_network_number $new_subnet_arg dev $interface
+    fi
+    for router in $new_routers; do
+      route add default gw $router
+    done
+  fi
+  fi
+  if [ -z "${dhc_dbus}" ] || (( ( dhc_dbus & 2 ) != 2 )); then
+  if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ];
+   then
+    ifconfig $interface:0- inet 0
+    ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg
+    route add -host $alias_ip_address $interface:0
+  fi
+  fi
+  if [ -z "${dhc_dbus}" ] || (( ( dhc_dbus & 1 ) != 1 )); then
+  make_resolv_conf
+  fi
+  exit_with_hooks 0
+fi
+
+if [ -z "${dhc_dbus}" ] || (( ( dhc_dbus & 2 ) != 2 )); then
+if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ] || [ x$reason = xRELEASE ] \
+   || [ x$reason = xSTOP ]; then
+  if [ x$alias_ip_address != x ]; then
+    # Turn off alias interface.
+    ifconfig $interface:0- inet 0
+  fi
+  if [ x$old_ip_address != x ]; then
+    # Shut down interface, which will delete routes and clear arp cache.
+    ifconfig $interface inet 0 down
+  fi
+  if [ x$alias_ip_address != x ]; then
+    ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg
+    route add -host $alias_ip_address $interface:0
+  fi
+  exit_with_hooks 0
+fi
+fi
+
+if [ x$reason = xTIMEOUT ]; then
+  if [ -z "${dhc_dbus}" ] || (( ( dhc_dbus & 2 ) != 2 )); then
+  if [ x$alias_ip_address != x ]; then
+    ifconfig $interface:0- inet 0
+  fi
+  ifconfig $interface inet $new_ip_address $new_subnet_arg \
+					$new_broadcast_arg
+  fi
+  set $new_routers
+  ############## what is -w in ping?
+  if ping -q -c 1 $1; then
+    if [ x$new_ip_address != x$alias_ip_address ] && \
+			[ x$alias_ip_address != x ]; then
+      ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg
+      route add -host $alias_ip_address dev $interface:0
+    fi
+    if [ $relmajor -lt 2 ] || \
+		( [ $relmajor -eq 2 ] && [ $relminor -eq 0 ] ); then
+      route add -net $new_network_number
+    fi
+    for router in $new_routers; do
+      route add default gw $router
+    done
+    make_resolv_conf
+    exit_with_hooks 0
+  fi
+  if [ -z "${dhc_dbus}" ] || (( ( dhc_dbus & 2 ) != 2 )); then
+  ifconfig $interface inet 0 down
+  fi
+  exit_with_hooks 1
+fi
+
+exit_with_hooks 0
--- dhcp-3.0.5/client/dhclient.c.enoi	2006-08-22 11:13:57.000000000 -0400
+++ dhcp-3.0.5/client/dhclient.c	2006-11-13 12:44:11.000000000 -0500
@@ -74,6 +74,9 @@
 int onetry=0;
 int quiet=0;
 int nowait=0;
+#ifdef EXTENDED_NEW_OPTION_INFO
+int extended_option_environment = 0;
+#endif
 
 static void usage PROTO ((void));
 
@@ -204,6 +207,11 @@
 		} else if (!strcmp (argv [i], "--version")) {
 			log_info ("isc-dhclient-%s", DHCP_VERSION);
 			exit (0);
+#ifdef EXTENDED_NEW_OPTION_INFO
+		} else if (!strcmp (argv [i], "-x")) {
+			extended_option_environment = 1;
+			new_option_info_tree = GENERATE_NEW_OPTION_INFO;
+#endif
  		} else if (argv [i][0] == '-') {
  		    usage ();
 		} else {
@@ -476,7 +484,11 @@
 	log_info (arr);
 	log_info (url);
 
+#ifdef EXTENDED_NEW_OPTION_INFO
+	log_error ("Usage: dhclient [-1dqr] [-nwx] [-p <port>] %s",
+#else
 	log_error ("Usage: dhclient [-1dqr] [-nw] [-p <port>] %s",
+#endif
 		   "[-s server]");
 	log_error ("                [-cf config-file] [-lf lease-file]%s",
 		   "[-pf pid-file] [-e VAR=val]");
@@ -2447,8 +2459,30 @@
 struct envadd_state {
 	struct client_state *client;
 	const char *prefix;
+#ifdef EXTENDED_NEW_OPTION_INFO
+	struct universe *universe;
+#endif
 };
 
+#ifdef EXTENDED_NEW_OPTION_INFO
+static
+void build_universe_info_envvar
+(	struct option_cache *oc,
+	struct packet *p, struct lease *l,
+	struct client_state *client,
+	struct option_state *in_o,
+	struct option_state *cf_o,
+	struct binding_scope **scope,
+	struct universe *u, void *es
+)
+{
+	char info_name[512], info_data[512];
+	snprintf(info_name, 512, "%s._universe_.", oc->option->universe->name);
+	snprintf(info_data, 512, "%u:%s", oc->option->code,oc->option->format);
+	client_envadd( client, info_name, oc->option->name, info_data );
+}
+#endif
+
 void client_option_envadd (struct option_cache *oc,
 			   struct packet *packet, struct lease *lease,
 			   struct client_state *client_state,
@@ -2465,6 +2499,28 @@
 				   in_options, cfg_options, scope, oc, MDL)) {
 		if (data.len) {
 			char name [256];
+#ifdef EXTENDED_NEW_OPTION_INFO
+			if (extended_option_environment) {
+				if ((oc->option->universe != &dhcp_universe)
+					&& (oc->option->universe->index > fqdn_universe.index)
+					&& (es->universe !=  oc->option->universe)) {
+					es->universe = oc->option->universe;
+					(*(es->universe->foreach)) ((struct packet *)0,
+											    (struct lease *)0, 
+					                            client_state, 
+					                            in_options, cfg_options,
+					                            scope, es->universe, es,  
+					                            build_universe_info_envvar);
+				} else {
+					if (lookup_new_option_info(oc->option) != NULL) {
+						build_universe_info_envvar(oc, packet, lease,
+						                           client_state, in_options,
+						                           cfg_options, scope,
+						                           oc->option->universe, es);
+					}
+				}
+			}
+#endif
 			if (dhcp_option_ev_name (name, sizeof name,
 						 oc -> option)) {
 				client_envadd (es -> client, es -> prefix,
@@ -2704,7 +2760,14 @@
 			s = option -> name;
 			if (j + 1 == buflen)
 				return 0;
+#ifdef EXTENDED_NEW_OPTION_INFO
+			if (!extended_option_environment)
+				buf[j++] = '_';
+			else
+				buf[j++] = '.';
+#else
 			buf [j++] = '_';
+#endif
 		}
 		++i;
 	} while (i != 2);
--- dhcp-3.0.5/client/dhclient.8.enoi	2005-09-14 12:03:33.000000000 -0400
+++ dhcp-3.0.5/client/dhclient.8	2006-11-13 12:42:28.000000000 -0500
@@ -82,6 +82,9 @@
 .B -w
 ]
 [
+.B -x
+]
+[
 .I if0
 [
 .I ...ifN
@@ -265,6 +268,11 @@
 supplying the
 .B -nw
 flag.
+.PP
+The -x argument enables extended option information to be created in the
+-s dhclient-script environment, which would allow applications running
+in that environment to handle options they do not know about in advance -
+this is a Red Hat extension to support dhcdbd and NetworkManager.
 .SH CONFIGURATION
 The syntax of the dhclient.conf(5) file is discussed separately.
 .SH OMAPI
--- dhcp-3.0.5/common/parse.c.enoi	2006-02-22 17:43:27.000000000 -0500
+++ dhcp-3.0.5/common/parse.c	2006-11-13 12:42:28.000000000 -0500
@@ -1271,6 +1271,10 @@
 	option_hash_add (option -> universe -> hash,
 			 (const char *)option -> name,
 			 0, option, MDL);
+#ifdef EXTENDED_NEW_OPTION_INFO
+	if (new_option_info_tree != NULL)
+		add_new_option_info(option);
+#endif
 	return 1;
 }
 
--- dhcp-3.0.5/common/tables.c.enoi	2006-02-22 17:43:27.000000000 -0500
+++ dhcp-3.0.5/common/tables.c	2006-11-13 12:42:28.000000000 -0500
@@ -1250,3 +1250,35 @@
 			   fqdn_universe.name, 0,
 			   &fqdn_universe, MDL);
 }
+
+#ifdef EXTENDED_NEW_OPTION_INFO
+#include <search.h>
+
+void *new_option_info_tree = NULL;
+
+static int new_option_info_comparator(const void * p1, const void * p2) {
+	uint32_t ocode1 = (((const struct option*)p1)->universe->index << 8)
+	                   | (((const struct option*)p1)->code),
+	         ocode2 = (((const struct option*)p2)->universe->index << 8)
+	                   | (((const struct option*)p2)->code);
+
+	return((ocode1 == ocode2) ? 0 : ((ocode1 > ocode2) ? 1 : -1));
+}
+
+void *add_new_option_info(struct option * option) {
+	if (option->universe->index >= fqdn_universe.index)
+		return NULL;
+
+	if (new_option_info_tree == GENERATE_NEW_OPTION_INFO)
+		new_option_info_tree = NULL;
+
+    return tsearch(option, &(new_option_info_tree), new_option_info_comparator);
+}
+
+void *lookup_new_option_info(struct option * option) {
+	if (new_option_info_tree == GENERATE_NEW_OPTION_INFO)
+		return NULL;
+
+	return tfind(option, &(new_option_info_tree), new_option_info_comparator);
+}
+#endif
--- dhcp-3.0.5/includes/dhcpd.h.enoi	2006-05-17 16:16:59.000000000 -0400
+++ dhcp-3.0.5/includes/dhcpd.h	2006-11-13 12:42:28.000000000 -0500
@@ -1811,6 +1811,13 @@
 void initialize_common_option_spaces PROTO ((void));
 struct universe *config_universe;
 
+#ifdef EXTENDED_NEW_OPTION_INFO
+#define GENERATE_NEW_OPTION_INFO ((void*)1)
+extern void *new_option_info_tree;
+extern void *add_new_option_info(struct option *);
+extern void *lookup_new_option_info(struct option *);
+#endif
+
 /* stables.c */
 #if defined (FAILOVER_PROTOCOL)
 extern failover_option_t null_failover_option;