From: Francis Dupont Date: Fri, 22 Aug 2025 18:37:21 +0000 (+0200) Subject: [#3860] Added vendor VALUE in dicts X-Git-Tag: Kea-3.1.2~39 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=761aaac1d5d5b70142fbf60647cea14833a4920e;p=thirdparty%2Fkea.git [#3860] Added vendor VALUE in dicts --- diff --git a/src/hooks/dhcp/radius/client_dictionary.cc b/src/hooks/dhcp/radius/client_dictionary.cc index 2706111460..ab288ad0fb 100644 --- a/src/hooks/dhcp/radius/client_dictionary.cc +++ b/src/hooks/dhcp/radius/client_dictionary.cc @@ -154,9 +154,10 @@ AttrDefs::getName(const uint8_t type, const uint32_t vendor) const { } IntCstDefPtr -AttrDefs::getByName(const uint8_t type, const string& name) const { +AttrDefs::getByName(const uint8_t type, const string& name, + const uint32_t vendor) const { auto const& idx = ic_container_.get<0>(); - auto it = idx.find(boost::make_tuple(type, name)); + auto it = idx.find(boost::make_tuple(vendor, type, name)); if (it != idx.end()) { return (*it); } @@ -164,9 +165,10 @@ AttrDefs::getByName(const uint8_t type, const string& name) const { } IntCstDefPtr -AttrDefs::getByValue(const uint8_t type, const uint32_t value) const { +AttrDefs::getByValue(const uint8_t type, const uint32_t value, + const uint32_t vendor) const { auto const& idx = ic_container_.get<1>(); - auto it = idx.find(boost::make_tuple(type, value)); + auto it = idx.find(boost::make_tuple(vendor, type, value)); if (it != idx.end()) { return (*it); } @@ -179,7 +181,7 @@ AttrDefs::add(IntCstDefPtr def) { return; } auto& idx = ic_container_.get<0>(); - auto it = idx.find(boost::make_tuple(def->type_, def->name_)); + auto it = idx.find(boost::make_tuple(def->vendor_, def->type_, def->name_)); if (it != idx.end()) { if (def->value_ == (*it)->value_) { // Duplicate: ignore. @@ -191,9 +193,15 @@ AttrDefs::add(IntCstDefPtr def) { << def->name_ << "' value " << (*it)->value_ << " by " << def->value_); } - isc_throw(BadValue, "Illegal integer constant redefinition of '" - << def->name_ << "' for attribute '" << getName(def->type_) - << "' value " << (*it)->value_ << " by " << def->value_); + ostringstream msg; + msg << "Illegal integer constant redefinition of '" + << def->name_ << "' for attribute '" + << getName(def->type_, def->vendor_) << "'"; + if (def->vendor_ != 0) { + msg << " in vendor " << def->vendor_; + } + msg << " value " << (*it)->value_ << " by " << def->value_; + isc_throw(BadValue, msg.str()); } static_cast(ic_container_.insert(def)); } @@ -254,21 +262,27 @@ AttrDefs::parseLine(const string& line, uint32_t& vendor, unsigned int depth) { } // Integer constant definition. if (tokens[0] == "VALUE") { - if (vendor != 0) { - // Ignore vendor constant definitions. - return; - } if (tokens.size() != 4) { isc_throw(Unexpected, "expected 4 tokens, got " << tokens.size()); } const string& attr_str = tokens[1]; - AttrDefPtr attr = getByName(attr_str/*, vendor*/); + AttrDefPtr attr = getByName(attr_str, vendor); if (!attr) { - isc_throw(Unexpected, "unknown attribute '" << attr_str << "'"); + ostringstream msg; + msg << "unknown attribute '" << attr_str << "'"; + if (vendor != 0) { + msg << " in vendor " << vendor; + } + isc_throw(Unexpected, msg.str()); } if (attr->value_type_ != PW_TYPE_INTEGER) { - isc_throw(Unexpected, "attribute '" << attr_str - << "' is not an integer attribute"); + ostringstream msg; + msg << "attribute '" << attr_str << "'"; + if (vendor != 0) { + msg << " in vendor " << vendor; + } + msg << " is not an integer attribute"; + isc_throw(Unexpected, msg.str()); } const string& name = tokens[2]; const string& value_str = tokens[3]; @@ -283,7 +297,7 @@ AttrDefs::parseLine(const string& line, uint32_t& vendor, unsigned int depth) { } catch (...) { isc_throw(Unexpected, "can't parse integer value " << value_str); } - IntCstDefPtr def(new IntCstDef(attr->type_, name, value)); + IntCstDefPtr def(new IntCstDef(attr->type_, name, value, vendor)); add(def); return; } diff --git a/src/hooks/dhcp/radius/client_dictionary.h b/src/hooks/dhcp/radius/client_dictionary.h index 854fef8990..cec8986a26 100644 --- a/src/hooks/dhcp/radius/client_dictionary.h +++ b/src/hooks/dhcp/radius/client_dictionary.h @@ -118,9 +118,10 @@ public: /// @param type attribute type. /// @param name integer constant name. /// @param value integer constant value. + /// @param vendor vendor id (default 0). IntCstDef(const uint8_t type, const std::string& name, - const uint32_t value) - : type_(type), name_(name), value_(value) { + const uint32_t value, const uint32_t vendor = 0) + : type_(type), name_(name), value_(value), vendor_(vendor) { } /// @brief attribute type. @@ -131,6 +132,9 @@ public: /// @brief value. const uint32_t value_; + + /// @brief vendor id (default 0). + const uint32_t vendor_; }; /// @brief Shared pointers to Integer constant definition. @@ -200,10 +204,13 @@ public: IntCstDefPtr, // Start specification of indexes here. boost::multi_index::indexed_by< - // Hash index for by type and name. + // Hash index for by vendor, type and name. boost::multi_index::hashed_unique< boost::multi_index::composite_key< IntCstDef, + boost::multi_index::member< + IntCstDef, const uint32_t, &IntCstDef::vendor_ + >, boost::multi_index::member< IntCstDef, const uint8_t, &IntCstDef::type_ >, @@ -212,10 +219,13 @@ public: > > >, - // Hash index for by type and value. + // Hash index for by vendor, type and value. boost::multi_index::hashed_unique< boost::multi_index::composite_key< IntCstDef, + boost::multi_index::member< + IntCstDef, const uint32_t, &IntCstDef::vendor_ + >, boost::multi_index::member< IntCstDef, const uint8_t, &IntCstDef::type_ >, @@ -271,15 +281,19 @@ public: /// /// @param type attribute type. /// @param name name to look for. + /// @param vendor vendor id to look for (default 0). /// @return pointer to the integer constant definition or null. - IntCstDefPtr getByName(const uint8_t type, const std::string& name) const; + IntCstDefPtr getByName(const uint8_t type, const std::string& name, + const uint32_t vendor = 0) const; /// @brief Get integer constant definition by attribute type and value. /// /// @param type attribute type. /// @param value value to look for. + /// @param vendor vendor id to look for (default 0). /// @return pointer to the integer constant definition or null. - IntCstDefPtr getByValue(const uint8_t type, const uint32_t value) const; + IntCstDefPtr getByValue(const uint8_t type, const uint32_t value, + const uint32_t vendor = 0) const; /// @brief Add (or replace) an integer constant definition. /// diff --git a/src/hooks/dhcp/radius/tests/dictionary_unittests.cc b/src/hooks/dhcp/radius/tests/dictionary_unittests.cc index 436a02722c..b2cc58ec7a 100644 --- a/src/hooks/dhcp/radius/tests/dictionary_unittests.cc +++ b/src/hooks/dhcp/radius/tests/dictionary_unittests.cc @@ -144,6 +144,9 @@ TEST_F(DictionaryTest, parseLine) { "expected 4 tokens, got 3 at line 1"); EXPECT_THROW_MSG(parseLine("VALUE My-Attribute My-Value 1"), BadValue, "unknown attribute 'My-Attribute' at line 1"); + EXPECT_THROW_MSG(parseLine("VALUE My-Attribute My-Value 1", 99), + BadValue, + "unknown attribute 'My-Attribute' in vendor 99 at line 1"); EXPECT_THROW_MSG(parseLine("$INCLUDE"), BadValue, "expected 2 tokens, got 1 at line 1"); @@ -229,6 +232,18 @@ TEST_F(DictionaryTest, integerConstant) { expected += " at line 2"; EXPECT_THROW_MSG(parseLines(not_integer_attr), BadValue, expected); + // Same with a vendor attribute. + list not_integer_attrv = { + "VENDOR DSL-Forum 3561", + "BEGIN-VENDOR DSL-Forum", + "ATTRIBUTE Agent-Circuit-Id 1 string", + "VALUE Agent-Circuit-Id My-Value 1", + "END-VENDOR DSL-Forum" + }; + expected = "attribute 'Agent-Circuit-Id' in vendor 3561"; + expected += " is not an integer attribute at line 4"; + EXPECT_THROW_MSG(parseLines(not_integer_attrv), BadValue, expected); + // Value must be an integer. list not_integer_val = { "ATTRIBUTE Acct-Status-Type 40 integer", @@ -262,6 +277,10 @@ TEST_F(DictionaryTest, integerConstant) { expected += "'Start' for attribute 'Acct-Status-Type' value 1 by 2"; expected += " at line 3"; EXPECT_THROW_MSG(parseLines(new_value), BadValue, expected); + expected = "Illegal integer constant redefinition of "; + expected += "'Start' for attribute 'Acct-Status-Type' in vendor 1234 "; + expected += "value 1 by 2 at line 3"; + EXPECT_THROW_MSG(parseLines(new_value, 1234, 1234), BadValue, expected); } // Verifies vendor id definitions.