RFC 3442 - Classless Static Route Option for DHCPv4 (#516325)
This commit is contained in:
parent
027db6fe99
commit
a21bc05f7d
2
.gitignore
vendored
2
.gitignore
vendored
@ -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
|
||||
|
142
dhclient-script
142
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
|
||||
|
405
dhcp-4.2.0-rfc3442-classless-static-routes.patch
Normal file
405
dhcp-4.2.0-rfc3442-classless-static-routes.patch
Normal file
@ -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 && \
|
10
dhcp.spec
10
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@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@redhat.com> - 12:4.2.0-4
|
||||
- RFC 3442 - Classless Static Route Option for DHCPv4 (#516325)
|
||||
|
||||
* Fri Aug 20 2010 Jiri Popelka <jpopelka@redhat.com> - 12:4.2.0-3
|
||||
- Add DHCRELAYARGS variable to /etc/sysconfig/dhcrelay
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user