Index: clparse.c =================================================================== RCS file: /cvs/src/sbin/dhclient/clparse.c,v retrieving revision 1.29 diff -u -p -r1.29 clparse.c --- clparse.c 8 May 2006 17:25:59 -0000 1.29 +++ clparse.c 23 Oct 2006 16:02:39 -0000 @@ -80,6 +80,8 @@ read_client_conf(void) 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; Index: dhclient-script =================================================================== RCS file: /cvs/src/sbin/dhclient/dhclient-script,v retrieving revision 1.10 diff -u -p -r1.10 dhclient-script --- dhclient-script 3 Jun 2006 19:30:06 -0000 1.10 +++ dhclient-script 23 Oct 2006 16:02:39 -0000 @@ -55,9 +55,44 @@ add_new_alias() { 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 delete default >/dev/null 2>&1 if [ -n "$old_static_routes" ]; then @@ -73,6 +108,21 @@ delete_old_routes() { add_new_routes() { route delete default >/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 Index: dhclient.c =================================================================== RCS file: /cvs/src/sbin/dhclient/dhclient.c,v retrieving revision 1.89 diff -u -p -r1.89 dhclient.c --- dhclient.c 24 Sep 2006 14:54:54 -0000 1.89 +++ dhclient.c 23 Oct 2006 16:02:40 -0000 @@ -92,6 +92,7 @@ struct sockaddr *get_ifa(char *, int); void routehandler(struct protocol *); 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); @@ -2172,10 +2173,69 @@ check_option(struct client_lease *l, int 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 Index: dhclient.conf.5 =================================================================== RCS file: /cvs/src/sbin/dhclient/dhclient.conf.5,v retrieving revision 1.11 diff -u -p -r1.11 dhclient.conf.5 --- dhclient.conf.5 2 Jun 2006 15:19:24 -0000 1.11 +++ dhclient.conf.5 23 Oct 2006 16:02:40 -0000 @@ -510,8 +510,9 @@ interface "ep0" { 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"; Index: dhcp.h =================================================================== RCS file: /cvs/src/sbin/dhclient/dhcp.h,v retrieving revision 1.5 diff -u -p -r1.5 dhcp.h --- dhcp.h 4 May 2004 15:49:49 -0000 1.5 +++ dhcp.h 23 Oct 2006 16:02:41 -0000 @@ -155,6 +155,7 @@ struct dhcp_packet { #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. */ Index: tables.c =================================================================== RCS file: /cvs/src/sbin/dhclient/tables.c,v retrieving revision 1.11 diff -u -p -r1.11 tables.c --- tables.c 16 Jul 2005 16:31:46 -0000 1.11 +++ tables.c 23 Oct 2006 16:02:41 -0000 @@ -182,7 +182,7 @@ const struct option dhcp_options[256] = /* 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" },