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

Reply via email to