</section>
<section>
-<!-- @todo: add real meat to the prefix delegation config this is just place holder stuff -->
<title>Subnet and Prefix Delegation Pools</title>
<para>
Subnets may also be configured to delegate prefixes, as defined in
...
}</screen>
</para>
+ <section>
+ <title>Prefix Exclude Option</title>
+ <para>
+ 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
+ <ulink url="http://tools.ietf.org/html/rfc6603"> RFC 6603</ulink>.
+ 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.
+ </para>
+ </section>
</section>
<section id="dhcp6-std-options">
<row><entry>bootfile-param</entry><entry>60</entry><entry>binary</entry><entry>false</entry></row>
<row><entry>client-arch-type</entry><entry>61</entry><entry>uint16</entry><entry>true</entry></row>
<row><entry>nii</entry><entry>62</entry><entry>record (uint8, uint8, uint8)</entry><entry>false</entry></row>
+<row><entry>aftr-name</entry><entry>64</entry><entry>fqdn</entry><entry>false</entry></row>
<row><entry>erp-local-domain-name</entry><entry>65</entry><entry>fqdn</entry><entry>false</entry></row>
<row><entry>rsoo</entry><entry>66</entry><entry>empty</entry><entry>false</entry></row>
+<row><entry>pd-exclude</entry><entry>67</entry><entry>binary</entry><entry>false</entry></row>
<row><entry>client-linklayer-addr</entry><entry>79</entry><entry>binary</entry><entry>false</entry></row>
<!-- <row><entry>dhcpv4-message</entry><entry>87</entry><entry>binary</entry><entry>false</entry></row> -->
<row><entry>dhcp4o6-server-addr</entry><entry>88</entry><entry>ipv6-address</entry><entry>true</entry></row>
+<row><entry>s46-rule</entry><entry>89</entry><entry>record(uint8, uint8, uint8, ipv4-address, ipv6-prefix)</entry><entry>false</entry></row>
+<row><entry>s46-br</entry><entry>90</entry><entry>ipv6-prefix</entry><entry>false</entry></row>
+<row><entry>s46-dmr</entry><entry>91</entry><entry>ipv6-prefix</entry><entry>false</entry></row>
+<row><entry>s46-v4v6bind</entry><entry>92</entry><entry>record(ipv4-address, ipv6-prefix)</entry><entry>false</entry></row>
+<row><entry>s46-portparams</entry><entry>93</entry><entry>empty</entry><entry>false</entry></row>
+<row><entry>s46-cont-mape</entry><entry>94</entry><entry>empty</entry><entry>false</entry></row>
+<row><entry>s46-cont-mapt</entry><entry>95</entry><entry>empty</entry><entry>false</entry></row>
+<row><entry>s46-cont-lw</entry><entry>96</entry><entry>empty</entry><entry>false</entry></row>
</tbody>
</tgroup>
</table>
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];
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
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
}
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
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;
}
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"
// 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);
}