From owner-freebsd-bugs@FreeBSD.ORG Tue Jun 27 10:00:45 2006 Return-Path: X-Original-To: freebsd-bugs@hub.freebsd.org Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 8F5C016A4DF for ; Tue, 27 Jun 2006 10:00:45 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id DCB8B43D72 for ; Tue, 27 Jun 2006 10:00:33 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.4/8.13.4) with ESMTP id k5RA0Xkd049299 for ; Tue, 27 Jun 2006 10:00:33 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.4/8.13.4/Submit) id k5RA0XvK049293; Tue, 27 Jun 2006 10:00:33 GMT (envelope-from gnats) Resent-Date: Tue, 27 Jun 2006 10:00:33 GMT Resent-Message-Id: <200606271000.k5RA0XvK049293@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, "Andrey V. Elsukov" Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id DC44116A406 for ; Tue, 27 Jun 2006 09:54:57 +0000 (UTC) (envelope-from butcher@heavennet.ru) Received: from mail.insysnet.ru (ns2.insysnet.ru [81.18.141.4]) by mx1.FreeBSD.org (Postfix) with SMTP id 6474B43D64 for ; Tue, 27 Jun 2006 09:54:53 +0000 (GMT) (envelope-from butcher@heavennet.ru) Received: (qmail 20775 invoked by uid 3005); 27 Jun 2006 04:27:29 -0000 Received: from butcher@heavennet.ru by mail.insysnet.ru by uid 3002 with qmail-scanner-1.15 (Virus scan Clear:. Processed in 0.268305 secs); 27 Jun 2006 04:27:29 -0000 Received: from unknown (HELO mail.heavennet.ru) (81.18.141.41) by mail.insysnet.ru with SMTP; 27 Jun 2006 04:27:29 -0000 Received: by mail.heavennet.ru (Postfix, from userid 1000) id E394E15C4A; Tue, 27 Jun 2006 08:27:28 +0400 (MSD) Message-Id: <20060627042728.E394E15C4A@mail.heavennet.ru> Date: Tue, 27 Jun 2006 08:27:28 +0400 (MSD) From: "Andrey V. Elsukov" To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Cc: Brooks Davis , Ed Maste Subject: bin/99534: [patch] dhclient Classless Static Routes support X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: "Andrey V. Elsukov" List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 27 Jun 2006 10:00:45 -0000 >Number: 99534 >Category: bin >Synopsis: [patch] dhclient Classless Static Routes support >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: update >Submitter-Id: current-users >Arrival-Date: Tue Jun 27 10:00:32 GMT 2006 >Closed-Date: >Last-Modified: >Originator: Andrey V. Elsukov >Release: FreeBSD >Organization: >Environment: Tested on 6.1-STABLE. >Description: I have implemented RFC3442 support for the FreeBSD dhclient. I have a small bit of testing with isc-dhcpd and dnsmasqd. It tested and works with: 1) classless routes: 10.0.0.0/21 router, 10.1.0.0/19 router; 2) default route; 3) link routes (different networks on the same interface): 192.168.0.0/24 0.0.0.0, 192.168.1.0/24 0.0.0.0 Brooks Davis has suggested filling a PR. RFC: http://www.ietf.org/rfc/rfc3442.txt patch: http://butcher.heavennet.ru/patches/other/dhclient/ FreeBSD Projects ideas: http://www.freebsd.org/projects/ideas/#p-rfc3442 isc-dhcpd configuration: http://www.opennet.ru/tips/info/666.shtml >How-To-Repeat: >Fix: --- dhclient.diff begins here --- Index: src/sbin/dhclient/clparse.c =================================================================== RCS file: /ncvs/src/sbin/dhclient/clparse.c,v retrieving revision 1.2 diff -u -r1.2 clparse.c --- src/sbin/dhclient/clparse.c 23 Aug 2005 23:59:55 -0000 1.2 +++ src/sbin/dhclient/clparse.c 17 Jun 2006 20:48:13 -0000 @@ -90,6 +90,8 @@ top_level_config.requested_options [top_level_config.requested_option_count++] = DHO_TIME_OFFSET; top_level_config.requested_options + [top_level_config.requested_option_count++] = DHO_CLASSLESS_ROUTES; + top_level_config.requested_options [top_level_config.requested_option_count++] = DHO_ROUTERS; top_level_config.requested_options [top_level_config.requested_option_count++] = DHO_DOMAIN_NAME; Index: src/sbin/dhclient/dhclient-script =================================================================== RCS file: /ncvs/src/sbin/dhclient/dhclient-script,v retrieving revision 1.14 diff -u -r1.14 dhclient-script --- src/sbin/dhclient/dhclient-script 26 Jan 2006 21:05:39 -0000 1.14 +++ src/sbin/dhclient/dhclient-script 17 Jun 2006 20:48:13 -0000 @@ -86,8 +86,43 @@ 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() { #route delete "$old_ip_address" $LOCALHOST >/dev/null 2>&1 + 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 + for router in $old_routers; do if [ $if_defaultroute = x -o $if_defaultroute = $interface ]; then route delete default $route >/dev/null 2>&1 @@ -107,6 +142,31 @@ add_new_routes() { #route add $new_ip_address $LOCALHOST >/dev/null 2>&1 + + # RFC 3442: If the DHCP server returns both a Classless Static + # Routes option and a Router option, the DHCP client MUST ignore + # the Router option. + # + # DHCP clients that support this option (Classless Static Routes) + # MUST NOT install the routes specified in the Static Routes + # option (option code 33) if both a Static Routes option and the + # Classless Static Routes option are provided. + + if [ -n "$new_classless_routes" ]; then + fill_classless_routes "$new_classless_routes" + $LOGGER "New Classless Static Routes ($interface): $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: src/sbin/dhclient/dhclient.c =================================================================== RCS file: /ncvs/src/sbin/dhclient/dhclient.c,v retrieving revision 1.15 diff -u -r1.15 dhclient.c --- src/sbin/dhclient/dhclient.c 23 May 2006 16:57:47 -0000 1.15 +++ src/sbin/dhclient/dhclient.c 17 Jun 2006 20:48:13 -0000 @@ -115,6 +115,7 @@ 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); int check_search(const char *srch); @@ -2379,12 +2380,77 @@ 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); } } +/* RFC 3442 The Classless Static Routes option checks */ +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); + + /* From RFC 3442: + * ... After deriving a subnet number and subnet mask + * from each destination descriptor, the DHCP client + * MUST zero any bits in the subnet number where the + * corresponding bit in the mask is zero... + */ + 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 res_hnok(const char *dn) { Index: src/sbin/dhclient/dhclient.conf =================================================================== RCS file: /ncvs/src/sbin/dhclient/dhclient.conf,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 dhclient.conf --- src/sbin/dhclient/dhclient.conf 7 Jun 2005 04:05:07 -0000 1.1.1.1 +++ src/sbin/dhclient/dhclient.conf 17 Jun 2006 20:48:13 -0000 @@ -3,8 +3,9 @@ send dhcp-lease-time 3600; supersede domain-name "fugue.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; timeout 60; retry 60; Index: src/sbin/dhclient/dhcp.h =================================================================== RCS file: /ncvs/src/sbin/dhclient/dhcp.h,v retrieving revision 1.2 diff -u -r1.2 dhcp.h --- src/sbin/dhclient/dhcp.h 30 Jun 2005 05:50:52 -0000 1.2 +++ src/sbin/dhclient/dhcp.h 17 Jun 2006 20:48:13 -0000 @@ -162,6 +162,7 @@ #define DHO_FINGER_SERVER 73 #define DHO_IRC_SERVER 74 #define DHO_DHCP_USER_CLASS_ID 77 +#define DHO_CLASSLESS_ROUTES 121 #define DHO_END 255 /* DHCP message types. */ Index: src/sbin/dhclient/tables.c =================================================================== RCS file: /ncvs/src/sbin/dhclient/tables.c,v retrieving revision 1.3 diff -u -r1.3 tables.c --- src/sbin/dhclient/tables.c 23 Aug 2005 23:59:55 -0000 1.3 +++ src/sbin/dhclient/tables.c 17 Jun 2006 20:48:13 -0000 @@ -186,7 +186,7 @@ { "option-118", "X", &dhcp_universe, 118 }, { "option-119", "X", &dhcp_universe, 119 }, { "option-120", "X", &dhcp_universe, 120 }, - { "option-121", "X", &dhcp_universe, 121 }, + { "classless-routes", "BA", &dhcp_universe, 121 }, { "option-122", "X", &dhcp_universe, 122 }, { "option-123", "X", &dhcp_universe, 123 }, { "option-124", "X", &dhcp_universe, 124 }, @@ -337,6 +337,7 @@ DHO_DHCP_CLIENT_IDENTIFIER, DHO_SUBNET_MASK, DHO_TIME_OFFSET, + DHO_CLASSLESS_ROUTES, DHO_ROUTERS, DHO_TIME_SERVERS, DHO_NAME_SERVERS, @@ -392,7 +393,7 @@ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, + 119, 120, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, --- dhclient.diff ends here --- >Release-Note: >Audit-Trail: >Unformatted: