From butcher@heavennet.ru  Tue Jun 27 09:54:57 2006
Return-Path: <butcher@heavennet.ru>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id DC44116A406
	for <FreeBSD-gnats-submit@freebsd.org>; 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 <FreeBSD-gnats-submit@freebsd.org>; 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 <bu7cher@yandex.ru>
Reply-To: Andrey V. Elsukov <bu7cher@yandex.ru>
To: FreeBSD-gnats-submit@freebsd.org
Cc: Ed Maste <emaste@FreeBSD.org>, Brooks Davis <brooks@FreeBSD.org>
Subject: [patch] dhclient Classless Static Routes support
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         99534
>Category:       bin
>Synopsis:       [patch] dhclient(8) Classless Static Routes support
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    emaste
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          update
>Submitter-Id:   current-users
>Arrival-Date:   Tue Jun 27 10:00:32 GMT 2006
>Closed-Date:    Sat Nov 03 01:42:13 UTC 2007
>Last-Modified:  Sat Nov 03 01:42:13 UTC 2007
>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:
Responsible-Changed-From-To: freebsd-bugs->emaste 
Responsible-Changed-By: emaste 
Responsible-Changed-When: Thu Jul 20 23:01:27 UTC 2006 
Responsible-Changed-Why:  
Grab 

http://www.freebsd.org/cgi/query-pr.cgi?pr=99534 

From: "Andrey V. Elsukov" <bu7cher@yandex.ru>
To: bug-followup@FreeBSD.org, bu7cher@yandex.ru
Cc: Ed Maste <emaste@FreeBSD.org>
Subject: Re: bin/99534: [patch] dhclient(8) Classless Static Routes support
Date: Tue, 26 Sep 2006 08:09:57 +0400

 It's any chance to have it commited?
 
 -- 
 WBR, Andrey V. Elsukov

From: Ed Maste <emaste@phaedrus.sandvine.ca>
To: "Andrey V. Elsukov" <bu7cher@yandex.ru>
Cc: bug-followup@FreeBSD.org, Ed Maste <emaste@FreeBSD.org>
Subject: Re: bin/99534: [patch] dhclient(8) Classless Static Routes support
Date: Thu, 19 Oct 2006 10:47:40 -0400

 Yes, I plan to commit this soon.  I wanted to give it sufficient testing
 before committing, and some unfortuante events prevented that until
 recently.
 
 I've massaged the patch a little to bring it closer to style(9) as well.
 
 Thanks again for the work on this.
 
 -ed
State-Changed-From-To: open->patched 
State-Changed-By: emaste 
State-Changed-When: Fri Feb 9 17:51:35 UTC 2007 
State-Changed-Why:  
Committed to -CURRENT 

http://www.freebsd.org/cgi/query-pr.cgi?pr=99534 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/99534: commit references a PR
Date: Fri,  9 Feb 2007 17:50:40 +0000 (UTC)

 emaste      2007-02-09 17:50:26 UTC
 
   FreeBSD src repository
 
   Modified files:
     sbin/dhclient        clparse.c dhclient-script dhclient.c 
                          dhclient.conf dhcp.h tables.c 
   Log:
   Implement RFC3442, the Classless Static Route option.
   
   The original DHCP specification includes a route option but it supports
   only class-based routes.  RFC3442 adds support for specifying the netmask
   width for each static route.  A variable length encoding is used to minimize
   the size of this option.
   
   PR:             bin/99534
   Submitted by:   Andrey V. Elsukov <bu7cher@yandex.ru>
   Reviewed by:    brooks
   
   Revision  Changes    Path
   1.3       +2 -0      src/sbin/dhclient/clparse.c
   1.15      +60 -0     src/sbin/dhclient/dhclient-script
   1.21      +68 -0     src/sbin/dhclient/dhclient.c
   1.3       +3 -2      src/sbin/dhclient/dhclient.conf
   1.3       +1 -0      src/sbin/dhclient/dhcp.h
   1.4       +3 -2      src/sbin/dhclient/tables.c
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/99534: commit references a PR
Date: Wed, 31 Oct 2007 14:30:26 +0000 (UTC)

 emaste      2007-10-31 14:30:20 UTC
 
   FreeBSD src repository
 
   Modified files:        (Branch: RELENG_6)
     sbin/dhclient        clparse.c dhclient-script dhclient.c 
                          dhclient.conf dhcp.h tables.c 
   Log:
   MFC to RELENG_6 dhclient RFC3442 support (the classless static route
   option)
   
   dhclient.conf 1.2
   
     Add a $FreeBSD$ tag missing after the original import.  Note that this
     file isn't actually installed; the one in src/etc is.
   
   clparse.c 1.3
   dhclient-script 1.15
   dhclient.c 1.21
   dhclient.conf 1.3
   dhcp.h 1.3
   tables.c 1.4
   
     Implement RFC3442, the Classless Static Route option.
   
     The original DHCP specification includes a route option but it
     supports only class-based routes.  RFC3442 adds support for
     specifying the netmask width for each static route.  A variable
     length encoding is used to minimize the size of this option.
   
     PR:             bin/99534
     Submitted by:   Andrey V. Elsukov <bu7cher@yandex.ru>
     Reviewed by:    brooks
   
   dhclient-script 1.16
   
     The minimum size of an RFC3442 destination descriptor is five bytes,
     so correct test to -ge 5.  Without this change an RFC3442 encoded
     default route would be ignored.
   
   Revision     Changes    Path
   1.1.1.1.2.2  +2 -0      src/sbin/dhclient/clparse.c
   1.4.2.6      +60 -0     src/sbin/dhclient/dhclient-script
   1.6.2.7      +68 -0     src/sbin/dhclient/dhclient.c
   1.1.1.1.2.1  +5 -2      src/sbin/dhclient/dhclient.conf
   1.2.2.1      +1 -0      src/sbin/dhclient/dhcp.h
   1.1.1.1.2.3  +3 -2      src/sbin/dhclient/tables.c
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: emaste 
State-Changed-When: Sat Nov 3 01:41:27 UTC 2007 
State-Changed-Why:  
Committed to RELENG_6 now in advance of 6.3. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=99534 
>Unformatted:
