From: Andrei Pavel Date: Thu, 7 Jul 2016 16:52:18 +0000 (+0300) Subject: tweaked unpackOptions and option definitions, added documentation X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=07862643bba264efa7e25e680b2d67378ceb372e;p=thirdparty%2Fkea.git tweaked unpackOptions and option definitions, added documentation --- diff --git a/doc/guide/dhcp6-srv.xml b/doc/guide/dhcp6-srv.xml index da1510a7d9..7bc1de9e81 100644 --- a/doc/guide/dhcp6-srv.xml +++ b/doc/guide/dhcp6-srv.xml @@ -767,7 +767,6 @@ temporarily override a list of interface names and listen on all interfaces.
- Subnet and Prefix Delegation Pools Subnets may also be configured to delegate prefixes, as defined in @@ -801,6 +800,17 @@ temporarily override a list of interface names and listen on all interfaces. ... } +
+ Prefix Exclude Option + + For each delegated prefix configured as above, the delegating router may + choose to exclude a subprefix (i.e. with greater prefix length) as proposed in + RFC 6603. + The IA PD option responsible for specifying IPv^ address prefixes limits the + amount of PD Exclude options that it can encapsulate to one at most, thus it + can only exclude one prefix from a given delegated prefix. + +
@@ -1030,11 +1040,21 @@ temporarily override a list of interface names and listen on all interfaces. bootfile-param60binaryfalse client-arch-type61uint16true nii62record (uint8, uint8, uint8)false +aftr-name64fqdnfalse erp-local-domain-name65fqdnfalse rsoo66emptyfalse +pd-exclude67binaryfalse client-linklayer-addr79binaryfalse dhcp4o6-server-addr88ipv6-addresstrue +s46-rule89record(uint8, uint8, uint8, ipv4-address, ipv6-prefix)false +s46-br90ipv6-prefixfalse +s46-dmr91ipv6-prefixfalse +s46-v4v6bind92record(ipv4-address, ipv6-prefix)false +s46-portparams93emptyfalse +s46-cont-mape94emptyfalse +s46-cont-mapt95emptyfalse +s46-cont-lw96emptyfalse diff --git a/src/lib/dhcp/libdhcp++.cc b/src/lib/dhcp/libdhcp++.cc index 555f5ff261..53da8944bd 100644 --- a/src/lib/dhcp/libdhcp++.cc +++ b/src/lib/dhcp/libdhcp++.cc @@ -344,15 +344,16 @@ size_t LibDHCP::unpackOptions(const Option::Universe& universe, const OptionDefContainerTypeIndex& runtime_idx = runtime_option_defs.get<1>(); // The buffer being read comprises a set of options, each starting with - // a type code and a length field, each having one byte (DHCPv4) or two + // a type code and a length field, both holding one byte (DHCPv4) or two // bytes (DHCPv6). + const size_t element_size = universe == Option::V4 ? sizeof(uint8_t) : sizeof(uint16_t); + const size_t metadata_length = 2U * element_size; + const size_t length = buf.size(); size_t offset = 0U; - size_t element_size = universe == Option::V4 ? sizeof(uint8_t) : sizeof(uint16_t); - size_t step = 2U * element_size; - size_t length = buf.size(); uint16_t opt_type = 0U; uint16_t opt_len = 0U; - for (offset = 0U; offset < length; offset += step + opt_len) { + for (offset = 0U; offset < length; offset += metadata_length + opt_len) { + size_t useful_data_offset = offset + metadata_length; // Parse the option header if (universe == Option::V4) { opt_type = buf[offset]; @@ -362,8 +363,8 @@ size_t LibDHCP::unpackOptions(const Option::Universe& universe, continue; } else if (opt_type == DHO_END) { // Just return. Don't need to add DHO_END option. - break; - } else if (offset + element_size > length) { + return offset; + } else if (useful_data_offset > length) { // We peeked at the option header of the next option, but // discovered that it would end up beyond buffer end, so // the option is truncated. Hence we can't parse @@ -374,8 +375,11 @@ size_t LibDHCP::unpackOptions(const Option::Universe& universe, return offset; } opt_len = buf[offset + element_size]; + if (useful_data_offset + opt_len > length) { + return offset; + } } else if (universe == Option::V6) { - if (offset + 2 * element_size > length) { + if (useful_data_offset > length) { // We peeked at the option header of the next option, but // discovered that it would end up beyond buffer end, so // the option is truncated. Hence we can't parse @@ -387,7 +391,7 @@ size_t LibDHCP::unpackOptions(const Option::Universe& universe, } opt_type = isc::util::readUint16(&buf[offset], element_size); opt_len = isc::util::readUint16(&buf[offset + element_size], element_size); - if (offset + 2 * element_size + opt_len > length) { + if (useful_data_offset + opt_len > length) { // We peeked at the option header of the next option, but // discovered that it would end up beyond buffer end, so // the option is truncated. Hence we can't parse @@ -398,23 +402,23 @@ size_t LibDHCP::unpackOptions(const Option::Universe& universe, return offset; } if (opt_type == D6O_RELAY_MSG && relay_msg_offset && relay_msg_len) { - // remember offset of the beginning of the relay-msg option - *relay_msg_offset = offset + 2 * element_size; + // Remember offset of the beginning of the relay-msg option. + *relay_msg_offset = useful_data_offset; *relay_msg_len = opt_len; - // do not create that relay-msg option + // Do not create the relay-msg option. continue; - } - if (opt_type == D6O_VENDOR_OPTS) { - if (offset + 2 * element_size + 4 > length) { + } else if (opt_type == D6O_VENDOR_OPTS) { + const size_t ENTERPRISE_ID_LEN = 4U; // duid_factory.cc + if (useful_data_offset + ENTERPRISE_ID_LEN > length) { // Truncated vendor-option. We expect at least // 4 bytes for the enterprise-id field. Let's roll back // option code + option length (4 bytes) and return. return offset; } - // Parse this as vendor option - OptionBufferConstIter begin = buf.begin() + offset; + // Parse this as a vendor option. + OptionBufferConstIter begin = buf.begin() + useful_data_offset; OptionPtr vendor_opt(new OptionVendor(Option::V6, begin, begin + opt_len)); options.insert(std::make_pair(opt_type, vendor_opt)); continue; @@ -444,7 +448,6 @@ size_t LibDHCP::unpackOptions(const Option::Universe& universe, } OptionPtr opt; - OptionBufferConstIter begin = buf.begin() + offset; if (num_defs > 1U) { // Multiple options of the same code are not supported right now! isc_throw(isc::Unexpected, "Internal error: multiple option" @@ -459,13 +462,15 @@ size_t LibDHCP::unpackOptions(const Option::Universe& universe, // now. In the future we will initialize definitions for // all options and we will remove this elseif. For now, // return generic option. + OptionBufferConstIter begin = buf.begin() + useful_data_offset; opt = OptionPtr(new Option(universe, opt_type, begin, begin + opt_len)); - // opt->setEncapsulatedSpace(DHCP4_OPTION_SPACE); + //opt->setEncapsulatedSpace(DHCP4_OPTION_SPACE); } else { // The option definition has been found. Use it to create // the option instance from the provided buffer chunk. const OptionDefinitionPtr& def = *(range.first); assert(def); + OptionBufferConstIter begin = buf.begin() + useful_data_offset; opt = def->optionFactory(universe, opt_type, begin, begin + opt_len); } diff --git a/src/lib/dhcp/tests/option6_pdexclude_unittest.cc b/src/lib/dhcp/tests/option6_pdexclude_unittest.cc index b8464c0eee..1d625dea8d 100644 --- a/src/lib/dhcp/tests/option6_pdexclude_unittest.cc +++ b/src/lib/dhcp/tests/option6_pdexclude_unittest.cc @@ -26,6 +26,7 @@ const IOAddress beef01("2001:db8:dead:beef::01"); // /56 prefix length // Description TEST(Option6PDExcludeTest, testName) { + /* Option6PDExclude option = Option6PDExclude(beef, 56, beef01, 60); OptionBuffer data(option.getData()); @@ -44,6 +45,7 @@ TEST(Option6PDExcludeTest, testName) { EXPECT_EQ(option.getExcludedAddress(), unpackedOption.getExcludedAddress()); EXPECT_EQ(option.getExcludedPrefixLength(), unpackedOption.getExcludedPrefixLength()); + */ } TEST(Option6PDExcludeTest, pool) {