From 21da96d4bcb34a2289e5b16eead8ce181d8eb61c Mon Sep 17 00:00:00 2001 From: Marcin Siodelski Date: Tue, 11 Dec 2012 17:31:34 +0100 Subject: [PATCH] [2526] Use V4 option definitions when unpacking an option. Some of the unit tests had to be modified after this change. This is because they used to create options which data length did not match the actual std options' formats. --- src/lib/dhcp/libdhcp++.cc | 47 ++++++++++++++++++++---- src/lib/dhcp/pkt4.cc | 6 ++- src/lib/dhcp/tests/libdhcp++_unittest.cc | 24 +++++++----- src/lib/dhcp/tests/pkt4_unittest.cc | 41 +++++++++++++-------- 4 files changed, 83 insertions(+), 35 deletions(-) diff --git a/src/lib/dhcp/libdhcp++.cc b/src/lib/dhcp/libdhcp++.cc index 1faa5e9906..e6f552eacf 100644 --- a/src/lib/dhcp/libdhcp++.cc +++ b/src/lib/dhcp/libdhcp++.cc @@ -65,10 +65,12 @@ const OptionDefContainer& LibDHCP::getOptionDefs(const Option::Universe u) { switch (u) { case Option::V4: - initStdOptionDefs4(); + if (v4option_defs_.empty()) { + initStdOptionDefs4(); + } return (v4option_defs_); case Option::V6: - if (v6option_defs_.size() == 0) { + if (v6option_defs_.empty()) { initStdOptionDefs6(); } return (v6option_defs_); @@ -192,8 +194,10 @@ size_t LibDHCP::unpackOptions4(const OptionBuffer& buf, continue; if (offset + 1 >= buf.size()) { + // opt_type must be cast to integer so as it is not treated as + // unsigned char value (a number is presented in error message). isc_throw(OutOfRange, "Attempt to parse truncated option " - << opt_type); + << static_cast(opt_type)); } uint8_t opt_len = buf[offset++]; @@ -203,12 +207,41 @@ size_t LibDHCP::unpackOptions4(const OptionBuffer& buf, << "-byte long buffer."); } + // Get the list of stdandard option definitions. + OptionDefContainer option_defs = LibDHCP::getOptionDefs(Option::V4); + // Get the search index #1. It allows to search for option definitions + // using option code. + const OptionDefContainerTypeIndex& idx = option_defs.get<1>(); + // Get all options with the particular option code. Note that option code + // is non-unique within this container however at this point we expect + // to get one option definition with the particular code. If more are + // returned we report an error. + const OptionDefContainerTypeRange& range = idx.equal_range(opt_type); + // Get the number of returned option definitions for the option code. + size_t num_defs = distance(range.first, range.second); + + OptionPtr opt; - switch(opt_type) { - default: + if (num_defs > 1) { + // Multiple options of the same code are not supported right now! + isc_throw(isc::Unexpected, "Internal error: multiple option definitions" + " for option type " << static_cast(opt_type) + << " returned. Currently it is not supported to initialize" + << " multiple option definitions for the same option code." + << " This will be supported once support for option spaces" + << " is implemented"); + } else if (num_defs == 0) { opt = OptionPtr(new Option(Option::V4, opt_type, - buf.begin()+offset, - buf.begin()+offset+opt_len)); + buf.begin() + offset, + buf.begin() + offset + opt_len)); + } 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); + opt = def->optionFactory(Option::V4, opt_type, + buf.begin() + offset, + buf.begin() + offset + opt_len); } options.insert(std::make_pair(opt_type, opt)); diff --git a/src/lib/dhcp/pkt4.cc b/src/lib/dhcp/pkt4.cc index 5be82113a9..35342951fe 100644 --- a/src/lib/dhcp/pkt4.cc +++ b/src/lib/dhcp/pkt4.cc @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -184,9 +185,10 @@ Pkt4::unpack() { } void Pkt4::check() { - boost::shared_ptr