Hi All,
could you please include to new release this patch to dhclient, based on
FreeBSD dhclient's patch.
The patch adds support of RFC 3442 (The Classless Static Route Option for
Dynamic Host) by dhclient.
diff -u /tmp/src/sbin/dhclient/clparse.c /usr/src/sbin/dhclient/clparse.c
--- /tmp/src/sbin/dhclient/clparse.c Sun Jul 19 04:18:02 2009
+++ /usr/src/sbin/dhclient/clparse.c Wed Feb 3 11:14:34 2010
@@ -75,6 +75,8 @@
config->requested_options
[config->requested_option_count++] = DHO_TIME_OFFSET;
config->requested_options
+ [config->requested_option_count++] = DHO_CLASSLESS_ROUTES;
+ config->requested_options
[config->requested_option_count++] = DHO_ROUTERS;
config->requested_options
[config->requested_option_count++] = DHO_DOMAIN_NAME;
diff -u /tmp/src/sbin/dhclient/dhclient-script
/usr/src/sbin/dhclient/dhclient-script
--- /tmp/src/sbin/dhclient/dhclient-script Wed Jun 3 09:12:51 2009
+++ /usr/src/sbin/dhclient/dhclient-script Wed Feb 10 16:06:55 2010
@@ -55,9 +55,44 @@
fi
}
+fill_classless_routes() {
+ set $1
+ while [ $# -gt 5 ]; do
+ if [ $1 -eq 0 ]; then
+ route="default"
+ elif [ $1 -lt 9 ]; then
+ route="$2.0.0.0/$1"
+ shift
+ elif [ $1 -lt 17 ]; then
+ route="$2.$3.0.0/$1"
+ shift; shift
+ elif [ $1 -lt 25 ]; then
+ route="$2.$3.$4.0/$1"
+ shift; shift; shift
+ else
+ route="$2.$3.$4.$5/$1"
+ shift; shift; shift; shift
+ fi
+ shift
+ router="$1.$2.$3.$4"
+ classless_routes="$classless_routes $route $router"
+ shift; shift; shift; shift
+ done
+}
+
delete_old_routes() {
# Delete existing default route. We only allow one, so no need to
# process $old_routers list.
+ if [ -n "$old_classless_routes" ]; then
+ fill_classless_routes "$old_classless_routes"
+ set $classless_routes
+ while [ $# -gt 1 ]; do
+ route delete "$1" "$2"
+ shift; shift
+ done
+ return 0;
+ fi
+
route -n flush -inet -iface $interface >/dev/null 2>&1
if [ -n "$old_static_routes" ]; then
@@ -73,6 +108,21 @@
add_new_routes() {
route -n flush -inet -iface $interface >/dev/null 2>&1
+
+ if [ -n "$new_classless_routes" ]; then
+ fill_classless_routes "$new_classless_routes"
+ set $classless_routes
+ while [ $# -gt 1 ]; do
+ if [ "0.0.0.0" = "$2" ]; then
+ route add "$1" -iface "$interface"
+ else
+ route add "$1" "$2"
+ fi
+ shift; shift
+ done
+ return
+ fi
+
for router in $new_routers; do
if [ "$new_ip_address" = "$router" ]; then
route add default -iface $router >/dev/null 2>&1
diff -u /tmp/src/sbin/dhclient/dhclient.c /usr/src/sbin/dhclient/dhclient.c
--- /tmp/src/sbin/dhclient/dhclient.c Thu Nov 12 17:18:45 2009
+++ /usr/src/sbin/dhclient/dhclient.c Wed Feb 3 11:14:34 2010
@@ -88,6 +88,7 @@
struct sockaddr *get_ifa(char *, int);
void usage(void);
int check_option(struct client_lease *l, int option);
+int check_classless_option(unsigned char *data, int len);
int ipv4addrs(char * buf);
int res_hnok(const char *dn);
char *option_as_string(unsigned int code, unsigned char *data,
int len);
@@ -2034,10 +2035,69 @@
case DHO_DHCP_USER_CLASS_ID:
case DHO_END:
return (1);
+ case DHO_CLASSLESS_ROUTES:
+ return (check_classless_option(l->options[option].data,
+ l->options[option].len));
default:
warning("unknown dhcp option value 0x%x", option);
return (unknown_ok);
}
+}
+
+int
+check_classless_option(unsigned char *data, int len)
+{
+ int i = 0;
+ unsigned char width;
+ in_addr_t addr, mask;
+
+ if (len < 5) {
+ warning("Too small length: %d", len);
+ return (0);
+ }
+
+ while(i < len) {
+ width = data[i++];
+ if (width == 0) {
+ i += 4; continue;
+ } else if (width < 9) {
+ addr = (in_addr_t)(data[i] << 24);
+ i += 1;
+ } else if (width < 17) {
+ addr = (in_addr_t)(data[i] << 24) +
+ (in_addr_t)(data[i + 1] << 16);
+ i += 2;
+ } else if (width < 25) {
+ addr = (in_addr_t)(data[i] << 24) +
+ (in_addr_t)(data[i + 1] << 16) +
+ (in_addr_t)(data[i + 2] << 8);
+ i += 3;
+ } else if (width < 33) {
+ addr = (in_addr_t)(data[i] << 24) +
+ (in_addr_t)(data[i + 1] << 16) +
+ (in_addr_t)(data[i + 2] << 8) +
+ data[i + 3];
+ i += 4;
+ } else {
+ warning("Incorrect subnet width: %d", width);
+ return(0);
+ }
+ mask = (in_addr_t)(~0) << (32 - width);
+ addr = ntohl(addr);
+ mask = ntohl(mask);
+
+ if ((addr & mask) != addr) {
+ addr &= mask;
+ data[i - 1] = (unsigned char)
+ ((addr >> (((32 - width)/8)*8)) & 0xFF);
+ }
+ i += 4;
+ }
+ if (i > len) {
+ warning("Incorrect data length: %d (must be %d)", len, i);
+ return (0);
+ }
+ return (1);
}
int
diff -u /tmp/src/sbin/dhclient/dhclient.conf.5
/usr/src/sbin/dhclient/dhclient.conf.5
--- /tmp/src/sbin/dhclient/dhclient.conf.5 Mon Oct 6 00:36:00 2008
+++ /usr/src/sbin/dhclient/dhclient.conf.5 Wed Feb 3 11:14:34 2010
@@ -514,8 +514,9 @@
send dhcp-lease-time 3600;
supersede domain-name "fugue.com rc.vix.com home.vix.com";
prepend domain-name-servers 127.0.0.1;
- request subnet-mask, broadcast-address, time-offset, routers,
- domain-name, domain-name-servers, host-name;
+ request subnet-mask, broadcast-address, time-offset,
+ classless-routes, routers, domain-name,
+ domain-name-servers, host-name;
require subnet-mask, domain-name-servers;
script "/etc/dhclient-script";
media "media 10baseT/UTP", "media 10base2/BNC";
diff -u /tmp/src/sbin/dhclient/dhcp.h /usr/src/sbin/dhclient/dhcp.h
--- /tmp/src/sbin/dhclient/dhcp.h Fri Feb 2 01:39:43 2007
+++ /usr/src/sbin/dhclient/dhcp.h Wed Feb 3 11:14:34 2010
@@ -153,6 +153,7 @@
#define DHO_DHCP_CLASS_IDENTIFIER 60
#define DHO_DHCP_CLIENT_IDENTIFIER 61
#define DHO_DHCP_USER_CLASS_ID 77
+#define DHO_CLASSLESS_ROUTES 121
#define DHO_END 255
/* DHCP message types. */
diff -u /tmp/src/sbin/dhclient/tables.c /usr/src/sbin/dhclient/tables.c
--- /tmp/src/sbin/dhclient/tables.c Sat Jul 16 20:31:46 2005
+++ /usr/src/sbin/dhclient/tables.c Wed Feb 3 11:14:34 2010
@@ -182,7 +182,7 @@
/* 118 */ { "option-118", "X" },
/* 119 */ { "option-119", "X" },
/* 120 */ { "option-120", "X" },
- /* 121 */ { "option-121", "X" },
+ /* 121 */ { "classless-routes", "BA" },
/* 122 */ { "option-122", "X" },
/* 123 */ { "option-123", "X" },
/* 124 */ { "option-124", "X" },
--
Anton Kasimov