]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3860] Added VENDOR
authorFrancis Dupont <fdupont@isc.org>
Wed, 20 Aug 2025 20:15:20 +0000 (22:15 +0200)
committerFrancis Dupont <fdupont@isc.org>
Fri, 12 Sep 2025 21:44:54 +0000 (23:44 +0200)
doc/sphinx/arm/ext-radius.rst
src/hooks/dhcp/radius/client_dictionary.cc
src/hooks/dhcp/radius/client_dictionary.h
src/hooks/dhcp/radius/data/dictionary
src/hooks/dhcp/radius/tests/dictionary_unittests.cc

index 7e4d038a74b8bbeed3efd65df526b140cb64c4ae..ca1c2b4c655a1601f1a0c6c129937a0dcc48eb77 100644 (file)
@@ -550,7 +550,7 @@ RADIUS dictionary. There are differences:
 
       - Yes
 
-      - No
+      - since Kea 3.1.1
 
     * - Support for Vendor Attributes
 
index c247437ef03d2a1619b816b10bdf5e5d1b3c1a2f..01f7b9b6419431cb8ae3cf664ad2f74dd3068af5 100644 (file)
@@ -172,6 +172,12 @@ AttrDefs::add(IntCstDefPtr def) {
             // Duplicate: ignore.
             return;
         }
+        if (def->type_ == PW_VENDOR_SPECIFIC) {
+            // Vendor id special case.
+            isc_throw(BadValue, "Illegal vendor id redefinition of '"
+                      << 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_);
@@ -259,6 +265,28 @@ AttrDefs::parseLine(const string& line, unsigned int depth) {
         add(def);
         return;
     }
+    // Vendor id definition.
+    if (tokens[0] == "VENDOR") {
+        if (tokens.size() != 3) {
+            isc_throw(Unexpected, "expected 3 tokens, got " << tokens.size());
+        }
+        const string& name = tokens[1];
+        const string& value_str = tokens[2];
+        uint32_t value = 0;
+        try {
+            int64_t val = boost::lexical_cast<int64_t>(value_str);
+            if ((val < numeric_limits<int32_t>::min()) ||
+                (val > numeric_limits<uint32_t>::max())) {
+                isc_throw(Unexpected, "not 32 bit " << value_str);
+            }
+            value = static_cast<uint32_t>(val);
+        } catch (...) {
+            isc_throw(Unexpected, "can't parse integer value " << value_str);
+        }
+        IntCstDefPtr def(new IntCstDef(PW_VENDOR_SPECIFIC, name, value));
+        add(def);
+        return;
+    }
     isc_throw(Unexpected, "unknown dictionary entry '" << tokens[0] << "'");
 }
 
index c3b16e8edcb4efee9b190faf3a42619d8df1c82c..21ee11b9b1557a7958d7bb4b117b8ce349c5ffe9 100644 (file)
@@ -79,6 +79,8 @@ typedef boost::shared_ptr<AttrDef> AttrDefPtr;
 typedef std::list<AttrDef> AttrDefList;
 
 /// @brief RADIUS integer constant definitions.
+///
+/// Include vendor ids with Vendor-Specific attribute.
 class IntCstDef {
 public:
 
index 6e252bc2df1ac390b57537f980ace54430427585..f06dde01b3d3159fd65738375d86f40b44ca7d3e 100644 (file)
@@ -252,3 +252,8 @@ VALUE           Acct-Terminate-Cause    Service-Unavailable     15
 VALUE           Acct-Terminate-Cause    Callback                16
 VALUE           Acct-Terminate-Cause    User-Error              17
 VALUE           Acct-Terminate-Cause    Host-Request            18
+
+#      Examples
+
+#$INCLUDE      foobar
+#VENDOR                DSL-Forum               3561
index dc39ea9cb2901095f0bd74a34be2111243688d21..2fbd014bc907faf1434a748c0d96a12681efc144 100644 (file)
@@ -131,8 +131,20 @@ 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("VENDOR my-vendor 4417"), BadValue,
-                     "unknown dictionary entry 'VENDOR' at line 1");
+
+    EXPECT_THROW_MSG(parseLine("$INCLUDE"), BadValue,
+                     "expected 2 tokens, got 1 at line 1");
+    EXPECT_THROW_MSG(parseLine("$INCLUDE foo bar"), BadValue,
+                     "expected 2 tokens, got 3 at line 1");
+    EXPECT_THROW_MSG(parseLine("VENDOR my-vendor"), BadValue,
+                     "expected 3 tokens, got 2 at line 1");
+    EXPECT_THROW_MSG(parseLine("VENDOR my-vendor 44 17"), BadValue,
+                     "expected 3 tokens, got 4 at line 1");
+
+    EXPECT_THROW_MSG(parseLine("BEGIN-VENDOR my-vendor"), BadValue,
+                     "unknown dictionary entry 'BEGIN-VENDOR' at line 1");
+    EXPECT_THROW_MSG(parseLine("END-VENDOR my-vendor"), BadValue,
+                     "unknown dictionary entry 'END-VENDOR' at line 1");
 }
 
 // Verifies sequences attribute of (re)definitions.
@@ -216,12 +228,49 @@ TEST_F(DictionaryTest, integerConstant) {
     EXPECT_THROW_MSG(parseLines(new_value), BadValue, expected);
 }
 
+// Verifies vendor id definitions.
+TEST_F(DictionaryTest, vendorId) {
+    // Value must be an integer.
+    list<string> not_integer_val = {
+        "VENDOR My-Value Non-Integer"
+    };
+    EXPECT_THROW_MSG(parseLines(not_integer_val), BadValue,
+                     "can't parse integer value Non-Integer at line 1");
+
+    // Positive case.
+    list<string> positive = {
+        "VENDOR ISC 2495"
+    };
+    EXPECT_NO_THROW_LOG(parseLines(positive));
+
+    // Redefine the same vendor id.
+    list<string> same = {
+        "VENDOR ISC 2495",
+        "VENDOR ISC 2495"
+    };
+    EXPECT_NO_THROW_LOG(parseLines(same));
+
+    // Redefine with a different value is not allowed.
+    list<string> new_value = {
+        "VENDOR ISC 2495",
+        "VENDOR ISC 24950",
+    };
+    string expected = "Illegal vendor id redefinition of ";
+    expected += "'ISC' value 2495 by 24950 at line 2";
+    EXPECT_THROW_MSG(parseLines(new_value), BadValue, expected);
+}
+
 // Verifies errors from bad dictionary files.
 TEST_F(DictionaryTest, badFile) {
     string expected = "can't open dictionary '/does-not-exist': ";
     expected += "No such file or directory";
     EXPECT_THROW_MSG(AttrDefs::instance().readDictionary("/does-not-exist"),
                      BadValue, expected);
+    list<string> bad_include = {
+        "$INCLUDE /does-not-exist"
+    };
+    expected += " at line 1";
+    EXPECT_THROW_MSG(parseLines(bad_include), BadValue, expected);
 }
 
 // Definitions of Standard attributes used by the hook.
@@ -239,13 +288,11 @@ TEST_F(DictionaryTest, include) {
     include.push_back("# Including the dictonary");
     include.push_back(string("$INCLUDE ") + string(TEST_DICTIONARY));
     include.push_back("# Dictionary included");
-    //    include.push_back("VALUE Vendor-Specific ISC 2495");
-    include.push_back("VALUE ARAP-Security ISC 2495");
+    include.push_back("VENDOR ISC 2495");
     EXPECT_NO_THROW_LOG(parseLines(include));
     EXPECT_NO_THROW_LOG(AttrDefs::instance().
         checkStandardDefs(RadiusConfigParser::USED_STANDARD_ATTR_DEFS));
-    //    auto isc = AttrDefs::instance().getByName(PW_VENDOR_SPECIFIC, "ISC");
-    auto isc = AttrDefs::instance().getByName(PW_ARAP_SECURITY, "ISC");
+    auto isc = AttrDefs::instance().getByName(PW_VENDOR_SPECIFIC, "ISC");
     ASSERT_TRUE(isc);
     EXPECT_EQ(2495, isc->value_);