[dhcp] RFC 3442 - Classless Static Route Option for DHCPv4 (#516325)

Jiří Popelka jpopelka at fedoraproject.org
Tue Aug 31 11:26:02 UTC 2010


commit a21bc05f7d31dc7ddc84e4d1cd810daf6bdf279d
Author: Jiri Popelka <jpopelka at redhat.com>
Date:   Tue Aug 31 13:01:51 2010 +0200

    RFC 3442 - Classless Static Route Option for DHCPv4 (#516325)

 .gitignore                                       |    2 -
 dhclient-script                                  |  142 +++++---
 dhcp-4.2.0-rfc3442-classless-static-routes.patch |  405 ++++++++++++++++++++++
 dhcp.spec                                        |   10 +-
 sources                                          |    2 -
 5 files changed, 501 insertions(+), 60 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 5e21cc6..d904b0b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1 @@
-ldap-for-dhcp-4.1.1-2.tar.gz
-dhcp-4.1.1-P1.tar.gz
 dhcp-4.2.0.tar.gz
diff --git a/dhclient-script b/dhclient-script
index eb0e840..9290d91 100755
--- a/dhclient-script
+++ b/dhclient-script
@@ -171,13 +171,28 @@ num2ip() {
     echo "${o1}.${o2}.${o3}.${o4}"
 }
 
-mask() {
+get_network_address() {
+# get network address for the given IP address and (netmask or prefix)
     ip="${1}"
-    m="${2}"
-    let ip="$(IFS="." ip2num ${ip})"
-    let m="$(IFS="." ip2num ${m})"
-    let n="ip & m"
-    num2ip ${n}
+    nm="${2}"
+
+    if [ -n "${ip}" -a -n "${nm}" ]; then
+        if [[ "${nm}" = *.* ]]; then
+            ipcalc -s -n ${ip} ${nm} | cut -d '=' -f 2
+        else
+            ipcalc -s -n ${ip}/${nm} | cut -d '=' -f 2
+        fi
+    fi
+}
+
+get_prefix() {
+# get prefix for the given IP address and mask
+    ip="${1}"
+    nm="${2}"
+
+    if [ -n "${ip}" -a -n "${nm}" ]; then
+        ipcalc -s -p ${ip} ${nm} | cut -d '=' -f 2
+    fi
 }
 
 class_bits() {
@@ -198,8 +213,8 @@ class_bits() {
 is_router_reachable() {
     # handle DHCP servers that give us a router not on our subnet
     router="${1}"
-    routersubnet="$(mask ${router} ${new_subnet_mask})"
-    mysubnet="$(mask ${new_ip_address} ${new_subnet_mask})"
+    routersubnet="$(get_network_address ${router} ${new_subnet_mask})"
+    mysubnet="$(get_network_address ${new_ip_address} ${new_subnet_mask})"
     unreachable=0
 
     if [ ! "${routersubnet}" = "${mysubnet}" ]; then
@@ -280,6 +295,69 @@ dhconfig() {
             . ${ETCDIR}/dhclient-up-hooks
         fi
 
+        # static routes
+        if [ -n "${new_classless_static_routes}" ] ||
+           [ -n "${new_static_routes}" ]; then
+            if [ -n "${new_classless_static_routes}" ]; then
+                IFS=', |' static_routes=(${new_classless_static_routes})
+
+                # If the DHCP server returns both a Classless Static Routes option and
+                # a Router option, the DHCP client MUST ignore the Router option. (RFC3442)
+                new_routers=""
+            else
+                IFS=', |' static_routes=(${new_static_routes})
+            fi
+            route_targets=()
+
+            for((i=0; i<${#static_routes[@]}; i+=2)); do
+                target=${static_routes[$i]}
+                if [ -n "${new_classless_static_routes}" ]; then
+                    prefix=$(echo ${target} | cut -d "." -f 1)
+                    target=$(echo ${target} | cut -d "." -f 2-)
+                    IFS="." target_arr=(${target})
+                    unset IFS
+                    ((pads=4-${#target_arr[@]}))
+                    for j in $(seq $pads); do
+                        target=${target}".0"
+                    done
+
+                    # Client MUST zero any bits in the subnet number where the corresponding bit in the mask is zero.
+                    # In other words, the subnet number installed in the routing table is the logical AND of
+                    # the subnet number and subnet mask given in the Classless Static Routes option. (RFC3442)
+                    target="$(get_network_address ${target} ${prefix})"
+                else
+                    prefix=$(class_bits ${target})
+                fi
+                gateway=${static_routes[$i+1]}
+
+                metric=''
+                for t in ${route_targets[@]}; do
+                    if [ ${t} = ${target} ]; then
+                        if [ -z "${metric}" ]; then
+                            metric=1
+                        else
+                            ((metric=metric+1))
+                        fi
+                    fi
+                done
+
+                if [ -n "${metric}" ]; then
+                    metric="metric ${metric}"
+                fi
+
+                if is_router_reachable ${gateway}; then
+                    ip -4 route replace ${target}/${prefix} via ${gateway} dev ${interface} ${metric}
+
+                    if [ $? -ne 0 ]; then
+                        logmessage "failed to create static route: ${target}/${prefix} via ${gateway} dev ${interface} ${metric}"
+                    else
+                        route_targets=(${route_targets[@]} ${target})
+                    fi
+                fi
+            done
+        fi
+
+        # gateways
         if [[ ( "${DEFROUTE}" != "no") &&
               (( -z "${GATEWAYDEV}" ) ||
                ( "${GATEWAYDEV}" = "${interface}" )) ]]; then
@@ -313,8 +391,8 @@ dhconfig() {
                     metric=${i}
                 done
             elif [ -n "${GATEWAY}" ]; then
-                routersubnet=$(mask ${GATEWAY} ${new_subnet_mask})
-                mysubnet=$(mask ${new_ip_address} ${new_subnet_mask})
+                routersubnet=$(get_network_address ${GATEWAY} ${new_subnet_mask})
+                mysubnet=$(get_network_address ${new_ip_address} ${new_subnet_mask})
 
                 if [ "${routersubnet}" = "${mysubnet}" ]; then
                     ip -4 route replace default via ${GATEWAY} dev ${interface}
@@ -322,41 +400,6 @@ dhconfig() {
             fi
         fi
 
-        # static routes
-        if [ -n "${new_static_routes}" ]; then
-            IFS=', |' static_routes=(${new_static_routes})
-            route_targets=()
-
-            for((i=0; i<${#static_routes[@]}; i+=2)); do
-                target=${static_routes[$i]}
-                gateway=${static_routes[$i+1]}
-                metric=''
-
-                for t in ${route_targets[@]}; do
-                    if [ ${t} = ${target} ]; then
-                        if [ -z "${metric}" ]; then
-                            metric=1
-                        else
-                            ((metric=metric+1))
-                        fi
-                    fi
-                done
-
-                if [ -n "${metric}" ]; then
-                    metric="metric ${metric}"
-                fi
-
-                if is_router_reachable ${gateway}; then
-                    ip -4 route replace ${target}/$(class_bits ${target}) via ${gateway} dev ${interface} ${metric}
-
-                    if [ $? -ne 0 ]; then
-                        logmessage "failed to create static route: ${target}/$(class_bits ${target}) via ${gateway} dev ${interface} ${metric}"
-                    else
-                        route_targets=(${route_targets[@]} ${target})
-                    fi
-                fi
-            done
-        fi
     fi
 
     if [ ! "${new_ip_address}" = "${alias_ip_address}" ] &&
@@ -490,15 +533,6 @@ dh6config() {
     fi
 }
 
-get_prefix() {
-    ip="${1}"
-    nm="${2}"
-
-    if [ -n "${ip}" -a -n "${nm}" ]; then
-        ipcalc -s -p ${ip} ${nm} | cut -d '=' -f 2
-    fi
-}
-
 
 #
 # ### MAIN
diff --git a/dhcp-4.2.0-rfc3442-classless-static-routes.patch b/dhcp-4.2.0-rfc3442-classless-static-routes.patch
new file mode 100644
index 0000000..c98ddc2
--- /dev/null
+++ b/dhcp-4.2.0-rfc3442-classless-static-routes.patch
@@ -0,0 +1,405 @@
+diff -up dhcp-4.2.0/client/clparse.c.rfc3442 dhcp-4.2.0/client/clparse.c
+--- dhcp-4.2.0/client/clparse.c.rfc3442	2010-08-31 10:12:51.000000000 +0200
++++ dhcp-4.2.0/client/clparse.c	2010-08-31 10:13:49.000000000 +0200
+@@ -37,7 +37,7 @@
+ 
+ struct client_config top_level_config;
+ 
+-#define NUM_DEFAULT_REQUESTED_OPTS	14
++#define NUM_DEFAULT_REQUESTED_OPTS	15
+ struct option *default_requested_options[NUM_DEFAULT_REQUESTED_OPTS + 1];
+ 
+ static void parse_client_default_duid(struct parse *cfile);
+@@ -82,7 +82,11 @@ isc_result_t read_client_conf ()
+ 				dhcp_universe.code_hash, &code, 0, MDL);
+ 
+ 	/* 4 */
+-	code = DHO_ROUTERS;
++	/* The Classless Static Routes option code MUST appear in the parameter
++     * request list prior to both the Router option code and the Static
++     * Routes option code, if present. (RFC3442)
++	 */
++	code = DHO_CLASSLESS_STATIC_ROUTES;
+ 	option_code_hash_lookup(&default_requested_options[3],
+ 				dhcp_universe.code_hash, &code, 0, MDL);
+ 
+@@ -136,6 +140,11 @@ isc_result_t read_client_conf ()
+ 	option_code_hash_lookup(&default_requested_options[13],
+ 				dhcp_universe.code_hash, &code, 0, MDL);
+ 
++	/* 15 */
++	code = DHO_ROUTERS;
++	option_code_hash_lookup(&default_requested_options[14],
++				dhcp_universe.code_hash, &code, 0, MDL);
++
+ 	for (code = 0 ; code < NUM_DEFAULT_REQUESTED_OPTS ; code++) {
+ 		if (default_requested_options[code] == NULL)
+ 			log_fatal("Unable to find option definition for "
+diff -up dhcp-4.2.0/common/dhcp-options.5.rfc3442 dhcp-4.2.0/common/dhcp-options.5
+--- dhcp-4.2.0/common/dhcp-options.5.rfc3442	2010-08-31 10:12:51.000000000 +0200
++++ dhcp-4.2.0/common/dhcp-options.5	2010-08-31 10:13:49.000000000 +0200
+@@ -115,6 +115,26 @@ hexadecimal, separated by colons.   For 
+ or
+   option dhcp-client-identifier 43:4c:49:45:54:2d:46:4f:4f;
+ .fi
++.PP
++The
++.B destination-descriptor
++describe the IP subnet number and subnet mask
++of a particular destination using a compact encoding. This encoding
++consists of one octet describing the width of the subnet mask,
++followed by all the significant octets of the subnet number.
++The following table contains some examples of how various subnet
++number/mask combinations can be encoded:
++.nf
++.sp 1
++Subnet number   Subnet mask      Destination descriptor
++0               0                0
++10.0.0.0        255.0.0.0        8.10
++10.0.0.0        255.255.255.0    24.10.0.0
++10.17.0.0       255.255.0.0      16.10.17
++10.27.129.0     255.255.255.0    24.10.27.129
++10.229.0.128    255.255.255.128  25.10.229.0.128
++10.198.122.47   255.255.255.255  32.10.198.122.47
++.fi
+ .SH SETTING OPTION VALUES USING EXPRESSIONS
+ Sometimes it's helpful to be able to set the value of a DHCP option
+ based on some value that the client has sent.   To do this, you can
+@@ -931,6 +951,29 @@ dhclient-script will create routes:
+ .RE
+ .PP
+ .nf
++.B option \fBclassless-static-routes\fR \fIdestination-descriptor ip-address\fR
++                  [\fB,\fR \fIdestination-descriptor ip-address\fR...]\fB;\fR
++.fi
++.RS 0.25i
++.PP
++This option (see RFC3442) specifies a list of classless static routes
++that the client should install in its routing cache.
++.PP
++This option can contain one or more static routes, each of which
++consists of a destination descriptor and the IP address of the router
++that should be used to reach that destination.
++.PP
++Many clients may not implement the Classless Static Routes option.
++DHCP server administrators should therefore configure their DHCP
++servers to send both a Router option and a Classless Static Routes
++option, and should specify the default router(s) both in the Router
++option and in the Classless Static Routes option.
++.PP
++If the DHCP server returns both a Classless Static Routes option and
++a Router option, the DHCP client ignores the Router option.
++.RE
++.PP
++.nf
+ .B option \fBstreettalk-directory-assistance-server\fR \fIip-address\fR
+                                            [\fB,\fR \fIip-address\fR...]\fB;\fR
+ .fi
+diff -up dhcp-4.2.0/common/inet.c.rfc3442 dhcp-4.2.0/common/inet.c
+--- dhcp-4.2.0/common/inet.c.rfc3442	2009-11-20 02:49:00.000000000 +0100
++++ dhcp-4.2.0/common/inet.c	2010-08-31 10:13:49.000000000 +0200
+@@ -526,6 +526,60 @@ free_iaddrcidrnetlist(struct iaddrcidrne
+ 	return ISC_R_SUCCESS;
+ }
+ 
++static const char *
++inet_ntopdd(const unsigned char *src, unsigned srclen, char *dst, size_t size)
++{
++	char tmp[sizeof("32.255.255.255.255")];
++	int len;
++
++	switch (srclen) {
++		case 2:
++			len = sprintf (tmp, "%u.%u", src[0], src[1]);
++			break;
++		case 3:
++			len = sprintf (tmp, "%u.%u.%u", src[0], src[1], src[2]);
++			break;
++		case 4:
++			len = sprintf (tmp, "%u.%u.%u.%u", src[0], src[1], src[2], src[3]);
++			break;
++		case 5:
++			len = sprintf (tmp, "%u.%u.%u.%u.%u", src[0], src[1], src[2], src[3], src[4]);
++			break;
++		default:
++			return NULL;
++	}
++	if (len < 0)
++		return NULL;
++
++	if (len > size) {
++		errno = ENOSPC;
++		return NULL;
++	}
++
++	return strcpy (dst, tmp);
++}
++
++/* pdestdesc() turns an iaddr structure into a printable dest. descriptor */
++const char *
++pdestdesc(const struct iaddr addr) {
++	static char pbuf[sizeof("255.255.255.255.255")];
++
++	if (addr.len == 0) {
++		return "<null destination descriptor>";
++	}
++	if (addr.len == 1) {
++		return "0";
++	}
++	if ((addr.len >= 2) && (addr.len <= 5)) {
++		return inet_ntopdd(addr.iabuf, addr.len, pbuf, sizeof(pbuf));
++	}
++
++	log_fatal("pdestdesc():%s:%d: Invalid destination descriptor length %d.",
++		  MDL, addr.len);
++	/* quell compiler warnings */
++	return NULL;
++}
++
+ /* piaddr() turns an iaddr structure into a printable address. */
+ /* XXX: should use a const pointer rather than passing the structure */
+ const char *
+diff -up dhcp-4.2.0/common/options.c.rfc3442 dhcp-4.2.0/common/options.c
+--- dhcp-4.2.0/common/options.c.rfc3442	2010-06-01 19:29:59.000000000 +0200
++++ dhcp-4.2.0/common/options.c	2010-08-31 10:13:49.000000000 +0200
+@@ -706,7 +706,11 @@ cons_options(struct packet *inpacket, st
+ 		 * packet.
+ 		 */
+ 		priority_list[priority_len++] = DHO_SUBNET_MASK;
+-		priority_list[priority_len++] = DHO_ROUTERS;
++		if (op = lookup_option(&dhcp_universe, cfg_options,
++								DHO_CLASSLESS_STATIC_ROUTES))
++			priority_list[priority_len++] = DHO_CLASSLESS_STATIC_ROUTES;
++		else
++			priority_list[priority_len++] = DHO_ROUTERS;
+ 		priority_list[priority_len++] = DHO_DOMAIN_NAME_SERVERS;
+ 		priority_list[priority_len++] = DHO_HOST_NAME;
+ 		priority_list[priority_len++] = DHO_FQDN;
+@@ -1683,6 +1687,7 @@ const char *pretty_print_option (option,
+ 	const unsigned char *dp = data;
+ 	char comma;
+ 	unsigned long tval;
++        unsigned int octets = 0;
+ 
+ 	if (emit_commas)
+ 		comma = ',';
+@@ -1691,6 +1696,7 @@ const char *pretty_print_option (option,
+ 
+ 	memset (enumbuf, 0, sizeof enumbuf);
+ 
++	if (option->format[0] != 'R') { /* see explanation lower */
+ 	/* Figure out the size of the data. */
+ 	for (l = i = 0; option -> format [i]; i++, l++) {
+ 		if (l >= sizeof(fmtbuf) - 1)
+@@ -1840,6 +1846,33 @@ const char *pretty_print_option (option,
+ 	if (numhunk < 0)
+ 		numhunk = 1;
+ 
++	} else { /* option->format[i] == 'R') */
++		/* R (destination descriptor) has variable length.
++		 * We can find it only in classless static route option,
++		 * so we are for sure parsing classless static route option now.
++		 * We go through whole the option to check whether there are no
++		 * missing/extra bytes.
++		 * I didn't find out how to improve the existing code and that's the
++		 * reason for this separate 'else' where I do my own checkings.
++		 * I know it's little bit unsystematic, but it works.
++		 */
++		numhunk = 0;
++		numelem = 2; /* RI */
++		fmtbuf[0]='R'; fmtbuf[1]='I'; fmtbuf[2]=0;
++		for (i =0; i < len; i = i + octets + 5) {
++			if (data[i] > 32) { /* subnet mask width */
++				log_error ("wrong subnet mask width in destination descriptor");
++				break;
++			}
++			numhunk++;
++			octets = ((data[i]+7) / 8);
++		}
++		if (i != len) {
++			log_error ("classless static routes option has wrong size or "
++					   "there's some garbage in format");
++		}
++	}
++
+ 	/* Cycle through the array (or hunk) printing the data. */
+ 	for (i = 0; i < numhunk; i++) {
+ 		for (j = 0; j < numelem; j++) {
+@@ -1978,6 +2011,20 @@ const char *pretty_print_option (option,
+ 				strcpy(op, piaddr(iaddr));
+ 				dp += 4;
+ 				break;
++
++			      case 'R':
++				if (dp[0] <= 32)
++					iaddr.len = (((dp[0]+7)/8)+1);
++				else {
++					log_error ("wrong subnet mask width in destination descriptor");
++					return "<error>";
++				}
++
++				memcpy(iaddr.iabuf, dp, iaddr.len);
++				strcpy(op, pdestdesc(iaddr));
++				dp += iaddr.len;
++				break;
++
+ 			      case '6':
+ 				iaddr.len = 16;
+ 				memcpy(iaddr.iabuf, dp, 16);
+diff -up dhcp-4.2.0/common/parse.c.rfc3442 dhcp-4.2.0/common/parse.c
+--- dhcp-4.2.0/common/parse.c.rfc3442	2010-08-31 10:12:51.000000000 +0200
++++ dhcp-4.2.0/common/parse.c	2010-08-31 10:13:49.000000000 +0200
+@@ -341,6 +341,39 @@ int parse_ip_addr (cfile, addr)
+ }	
+ 
+ /*
++ * destination-descriptor :== NUMBER DOT NUMBER |
++ *                            NUMBER DOT NUMBER DOT NUMBER |
++ *                            NUMBER DOT NUMBER DOT NUMBER DOT NUMBER |
++ *                            NUMBER DOT NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
++ */
++
++int parse_destination_descriptor (cfile, addr)
++	struct parse *cfile;
++	struct iaddr *addr;
++{
++		unsigned int mask_width, dest_dest_len;
++		addr -> len = 0;
++		if (parse_numeric_aggregate (cfile, addr -> iabuf,
++									 &addr -> len, DOT, 10, 8)) {
++			mask_width = (unsigned int)addr->iabuf[0];
++			dest_dest_len = (((mask_width+7)/8)+1);
++			if (mask_width > 32) {
++				parse_warn (cfile,
++				"subnet mask width (%u) greater than 32.", mask_width);
++			}
++			else if (dest_dest_len != addr->len) {
++				parse_warn (cfile,
++				"destination descriptor with subnet mask width %u "
++				"should have %u octets, but has %u octets.",
++				mask_width, dest_dest_len, addr->len);
++			}
++
++			return 1;
++		}
++		return 0;
++}
++
++/*
+  * Return true if every character in the string is hexadecimal.
+  */
+ static int
+@@ -707,8 +740,10 @@ unsigned char *parse_numeric_aggregate (
+ 		if (count) {
+ 			token = peek_token (&val, (unsigned *)0, cfile);
+ 			if (token != separator) {
+-				if (!*max)
++				if (!*max) {
++					*max = count;
+ 					break;
++				}
+ 				if (token != RBRACE && token != LBRACE)
+ 					token = next_token (&val,
+ 							    (unsigned *)0,
+@@ -1619,6 +1654,9 @@ int parse_option_code_definition (cfile,
+ 	      case IP_ADDRESS:
+ 		type = 'I';
+ 		break;
++	      case DESTINATION_DESCRIPTOR:
++		type = 'R';
++		break;
+ 	      case IP6_ADDRESS:
+ 		type = '6';
+ 		break;
+@@ -5232,6 +5270,15 @@ int parse_option_token (rv, cfile, fmt, 
+ 		}
+ 		break;
+ 
++	      case 'R': /* destination descriptor */
++		if (!parse_destination_descriptor (cfile, &addr)) {
++			return 0;
++		}
++		if (!make_const_data (&t, addr.iabuf, addr.len, 0, 1, MDL)) {
++			return 0;
++		}
++		break;
++
+ 	      case '6': /* IPv6 address. */
+ 		if (!parse_ip6_addr(cfile, &addr)) {
+ 			return 0;
+@@ -5492,6 +5539,13 @@ int parse_option_decl (oc, cfile)
+ 					goto exit;
+ 				len = ip_addr.len;
+ 				dp = ip_addr.iabuf;
++				goto alloc;
++
++			      case 'R': /* destination descriptor */
++				if (!parse_destination_descriptor (cfile, &ip_addr))
++					goto exit;
++				len = ip_addr.len;
++				dp = ip_addr.iabuf;
+ 
+ 			      alloc:
+ 				if (hunkix + len > sizeof hunkbuf) {
+diff -up dhcp-4.2.0/common/tables.c.rfc3442 dhcp-4.2.0/common/tables.c
+--- dhcp-4.2.0/common/tables.c.rfc3442	2010-08-31 10:12:51.000000000 +0200
++++ dhcp-4.2.0/common/tables.c	2010-08-31 10:13:49.000000000 +0200
+@@ -51,6 +51,7 @@ HASH_FUNCTIONS (option_code, const unsig
+    Format codes:
+ 
+    I - IPv4 address
++   R - destination descriptor (RFC3442)
+    6 - IPv6 address
+    l - 32-bit signed integer
+    L - 32-bit unsigned integer
+@@ -208,6 +209,7 @@ static struct option dhcp_options[] = {
+ 	{ "default-url", "t",			&dhcp_universe, 114, 1 },
+ 	{ "subnet-selection", "I",		&dhcp_universe, 118, 1 },
+ 	{ "domain-search", "D",		&dhcp_universe, 119, 1 },
++	{ "classless-static-routes", "RIA",	&dhcp_universe, 121, 1 },
+ 	{ "vivco", "Evendor-class.",		&dhcp_universe, 124, 1 },
+ 	{ "vivso", "Evendor.",			&dhcp_universe, 125, 1 },
+ #if 0
+diff -up dhcp-4.2.0/includes/dhcpd.h.rfc3442 dhcp-4.2.0/includes/dhcpd.h
+--- dhcp-4.2.0/includes/dhcpd.h.rfc3442	2010-08-31 10:12:51.000000000 +0200
++++ dhcp-4.2.0/includes/dhcpd.h	2010-08-31 10:13:49.000000000 +0200
+@@ -2638,6 +2638,7 @@ isc_result_t range2cidr(struct iaddrcidr
+ 			const struct iaddr *lo, const struct iaddr *hi);
+ isc_result_t free_iaddrcidrnetlist(struct iaddrcidrnetlist **result);
+ const char *piaddr PROTO ((struct iaddr));
++const char *pdestdesc PROTO ((struct iaddr));
+ char *piaddrmask(struct iaddr *, struct iaddr *);
+ char *piaddrcidr(const struct iaddr *, unsigned int);
+ u_int16_t validate_port(char *);
+@@ -2849,6 +2850,7 @@ void parse_client_lease_declaration PROT
+ int parse_option_decl PROTO ((struct option_cache **, struct parse *));
+ void parse_string_list PROTO ((struct parse *, struct string_list **, int));
+ int parse_ip_addr PROTO ((struct parse *, struct iaddr *));
++int parse_destination_descriptor PROTO ((struct parse *, struct iaddr *));
+ int parse_ip_addr_with_subnet(struct parse *, struct iaddrmatch *);
+ void parse_reject_statement PROTO ((struct parse *, struct client_config *));
+ 
+diff -up dhcp-4.2.0/includes/dhcp.h.rfc3442 dhcp-4.2.0/includes/dhcp.h
+--- dhcp-4.2.0/includes/dhcp.h.rfc3442	2009-11-20 02:49:01.000000000 +0100
++++ dhcp-4.2.0/includes/dhcp.h	2010-08-31 10:13:49.000000000 +0200
+@@ -158,6 +158,7 @@ struct dhcp_packet {
+ #define DHO_ASSOCIATED_IP			92
+ #define DHO_SUBNET_SELECTION			118 /* RFC3011! */
+ #define DHO_DOMAIN_SEARCH			119 /* RFC3397 */
++#define DHO_CLASSLESS_STATIC_ROUTES		121 /* RFC3442 */
+ #define DHO_VIVCO_SUBOPTIONS			124
+ #define DHO_VIVSO_SUBOPTIONS			125
+ 
+diff -up dhcp-4.2.0/includes/dhctoken.h.rfc3442 dhcp-4.2.0/includes/dhctoken.h
+--- dhcp-4.2.0/includes/dhctoken.h.rfc3442	2010-08-31 10:12:51.000000000 +0200
++++ dhcp-4.2.0/includes/dhctoken.h	2010-08-31 10:15:39.000000000 +0200
+@@ -358,7 +358,8 @@ enum dhcp_token {
+ 	AUTO_PARTNER_DOWN = 661,
+ 	GETHOSTNAME = 662,
+ 	REWIND = 663,
+-	BOOTP_BROADCAST_ALWAYS = 664
++	BOOTP_BROADCAST_ALWAYS = 664,
++	DESTINATION_DESCRIPTOR = 666
+ };
+ 
+ #define is_identifier(x)	((x) >= FIRST_TOKEN &&	\
diff --git a/dhcp.spec b/dhcp.spec
index ed222ec..44f5331 100644
--- a/dhcp.spec
+++ b/dhcp.spec
@@ -7,7 +7,7 @@
 Summary:  Dynamic host configuration protocol software
 Name:     dhcp
 Version:  4.2.0
-Release:  3%{?dist}
+Release:  4%{?dist}
 # NEVER CHANGE THE EPOCH on this package.  The previous maintainer (prior to
 # dcantrell maintaining the package) made incorrect use of the epoch and
 # that's why it is at 12 now.  It should have never been used, but it was.
@@ -26,7 +26,6 @@ Source6:  11-dhclient
 Source7:  12-dhcpd
 Source8:  56dhclient
 
-
 Patch0:   dhcp-4.2.0-errwarn-message.patch
 Patch1:   dhcp-4.2.0-options.patch
 Patch2:   dhcp-4.2.0-release-by-ifup.patch
@@ -54,6 +53,7 @@ Patch24:  dhcp-4.2.0-retransmission.patch
 Patch25:  dhcp-4.2.0-release6-elapsed.patch
 Patch26:  dhcp-4.2.0-initialization-delay.patch
 Patch27:  dhcp-4.2.0-parse_date.patch
+Patch28:  dhcp-4.2.0-rfc3442-classless-static-routes.patch
 
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 BuildRequires: autoconf
@@ -226,6 +226,9 @@ libdhcpctl and libomapi static libraries are also included in this package.
 # (Submitted to dhcp-bugs at isc.org - [ISC-Bugs #21501])
 %patch27 -p1 -b .parse_date
 
+# RFC 3442 - Classless Static Route Option for DHCPv4 (#516325)
+%patch28 -p1 -b .rfc3442
+
 # Copy in the Fedora/RHEL dhclient script
 %{__install} -p -m 0755 %{SOURCE4} client/scripts/linux
 %{__install} -p -m 0644 %{SOURCE5} .
@@ -507,6 +510,9 @@ fi
 %attr(0644,root,root) %{_mandir}/man3/omapi.3.gz
 
 %changelog
+* Tue Aug 31 2010 Jiri Popelka <jpopelka at redhat.com> - 12:4.2.0-4
+- RFC 3442 - Classless Static Route Option for DHCPv4 (#516325)
+
 * Fri Aug 20 2010 Jiri Popelka <jpopelka at redhat.com> - 12:4.2.0-3
 - Add DHCRELAYARGS variable to /etc/sysconfig/dhcrelay
 
diff --git a/sources b/sources
index 90101ef..98008bc 100644
--- a/sources
+++ b/sources
@@ -1,3 +1 @@
-9fa2f64826c969a55fd28263e4b6cad6  ldap-for-dhcp-4.1.1-2.tar.gz
-ee390a35687dd75dbfc32c856c0938d1  dhcp-4.1.1-P1.tar.gz
 83abd7c4f9c24d8dd024ca5a71380c0a  dhcp-4.2.0.tar.gz


More information about the scm-commits mailing list