]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[564-customer-request-relax-constraints-on-allowable-option-types-to-permit-option...
authorFrancis Dupont <fdupont@isc.org>
Thu, 11 Apr 2019 10:04:16 +0000 (12:04 +0200)
committerFrancis Dupont <fdupont@isc.org>
Thu, 18 Apr 2019 14:48:12 +0000 (16:48 +0200)
src/bin/dhcp4/tests/vendor_opts_unittest.cc
src/lib/dhcp/tests/libdhcp++_unittest.cc
src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc

index fed81ec34f511ad8a4a112943821fba2dfd4cf4e..2f94205a71e28a57a23ca1d1587f2c5a9cc7503a 100644 (file)
@@ -1499,3 +1499,129 @@ TEST_F(Dhcpv4SrvTest, truncatedVIVSOOption) {
     Pkt4Ptr offer = srv.fake_sent_.front();
     ASSERT_TRUE(offer);
 }
+
+/// Checks that it's possible to define and use a suboption 0.
+TEST_F(VendorOptsTest, vendorOpsSubOption0) {
+    IfaceMgrTestConfig test_config(true);
+    IfaceMgr::instance().openSockets4();
+
+    NakedDhcpv4Srv srv(0);
+
+    // Zero Touch provisioning
+    string config =
+        "{"
+        "    \"interfaces-config\": {"
+        "        \"interfaces\": [ \"*\" ]"
+        "    },"
+        "    \"option-def\": ["
+        "        {"
+        "            \"name\": \"vendor-encapsulated-options\","
+        "            \"code\": 43,"
+        "            \"type\": \"empty\","
+        "            \"encapsulate\": \"ZTP\""
+        "        },"
+        "        {"
+        "            \"name\": \"config-file-name\","
+        "            \"code\": 1,"
+        "            \"space\": \"ZTP\","
+        "            \"type\": \"string\""
+        "        },"
+        "        {"
+        "            \"name\": \"image-file-name\","
+        "            \"code\": 0,"
+        "            \"space\": \"ZTP\","
+        "            \"type\": \"string\""
+        "        },"
+        "        {"
+        "            \"name\": \"image-file-type\","
+        "            \"code\": 2,"
+        "            \"space\": \"ZTP\","
+        "            \"type\": \"string\""
+        "        },"
+        "        {"
+        "            \"name\": \"transfer-mode\","
+        "            \"code\": 3,"
+        "            \"space\": \"ZTP\","
+        "            \"type\": \"string\""
+        "        },"
+        "        {"
+        "            \"name\": \"all-image-file-name\","
+        "            \"code\": 4,"
+        "            \"space\": \"ZTP\","
+        "            \"type\": \"string\""
+        "        },"
+        "        {"
+        "            \"name\": \"http-port\","
+        "            \"code\": 5,"
+        "            \"space\": \"ZTP\","
+        "            \"type\": \"string\""
+        "        }"
+        "    ],"
+        "    \"option-data\": ["
+        "        {"
+        "            \"name\": \"vendor-encapsulated-options\""
+        "        },"
+        "        {"
+        "            \"name\": \"image-file-name\","
+        "            \"data\": \"/dist/images/jinstall-ex.tgz\","
+        "            \"space\": \"ZTP\""
+        "        }"
+        "    ],"
+        "\"subnet4\": [ { "
+        "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
+        "    \"subnet\": \"192.0.2.0/24\""
+        " } ]"
+        "}";
+
+    ConstElementPtr json;
+    ASSERT_NO_THROW(json = parseDHCP4(config, true));
+    ConstElementPtr status;
+
+    // Configure the server and make sure the config is accepted
+    EXPECT_NO_THROW(status = configureDhcp4Server(srv, json));
+    ASSERT_TRUE(status);
+    comment_ = parseAnswer(rcode_, status);
+    ASSERT_EQ(0, rcode_);
+
+    CfgMgr::instance().commit();
+
+        // Create a packet with enough to select the subnet and go through
+    // the DISCOVER processing
+    Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 1234));
+    query->setRemoteAddr(IOAddress("192.0.2.1"));
+    OptionPtr clientid = generateClientId();
+    query->addOption(clientid);
+    query->setIface("eth1");
+
+    // Create and add a PRL option to the query
+    OptionUint8ArrayPtr prl(new OptionUint8Array(Option::V4,
+                                                 DHO_DHCP_PARAMETER_REQUEST_LIST));
+    ASSERT_TRUE(prl);
+    prl->addValue(DHO_VENDOR_ENCAPSULATED_OPTIONS);
+    prl->addValue(DHO_VENDOR_CLASS_IDENTIFIER);
+    query->addOption(prl);
+
+    srv.classifyPacket(query);
+    ASSERT_NO_THROW(srv.deferredUnpack(query));
+
+    // Pass it to the server and get an offer
+    Pkt4Ptr offer = srv.processDiscover(query);
+
+    // Check if we get response at all
+    checkResponse(offer, DHCPOFFER, 1234);
+
+    // Processing should add a vendor-encapsulated-options (code 43)
+    OptionPtr opt = offer->getOption(DHO_VENDOR_ENCAPSULATED_OPTIONS);
+    ASSERT_TRUE(opt);
+    const OptionCollection& opts = opt->getOptions();
+    ASSERT_EQ(1, opts.size());
+    OptionPtr sopt = opts.begin()->second;
+    ASSERT_TRUE(sopt);
+    EXPECT_EQ(0, sopt->getType());
+
+    // Check suboption 0 content.
+    OptionStringPtr sopt0 =
+        boost::dynamic_pointer_cast<OptionString>(sopt);
+    ASSERT_TRUE(sopt0);
+    EXPECT_EQ("/dist/images/jinstall-ex.tgz", sopt0->getValue());
+}
index 90471943e2d24b22c9680227ff7baa63342651bf..64ce61def9370e1ae3329cabb67b0812a036310a 100644 (file)
@@ -1055,7 +1055,9 @@ TEST_F(LibDhcpTest, unpackPadEnd) {
         // Suboption 1.
         0x01, 0x03, 0x66, 0x6f, 0x6f, // code = 1, length = 2, content = "foo"
         // END
-        0xff
+        0xff,
+        // Extra bytes at tail.
+        0x01, 0x02, 0x03, 0x04
     };
     size_t raw_data_len = sizeof(raw_data) / sizeof(uint8_t);
     OptionBuffer buf(raw_data, raw_data + raw_data_len);
@@ -1063,8 +1065,12 @@ TEST_F(LibDhcpTest, unpackPadEnd) {
     // Parse options.
     OptionCollection options;
     list<uint16_t> deferred;
-    ASSERT_NO_THROW(LibDHCP::unpackOptions4(buf, DHCP4_OPTION_SPACE,
-                                            options, deferred));
+    size_t offset = 0;
+    ASSERT_NO_THROW(offset = LibDHCP::unpackOptions4(buf, DHCP4_OPTION_SPACE,
+                                                     options, deferred));
+
+    // Returned offset should point to the END.
+    EXPECT_EQ(0xff, raw_data[offset]);
 
     // There should be one top level option.
     ASSERT_EQ(1, options.size());
index 94ba6c0da32f2ae6f31b297d5c906bca6485647d..57f217111357f1d7e09b7395106706bf3fdcb545 100644 (file)
@@ -723,7 +723,6 @@ TEST_F(ParseConfigTest, defaultSpaceOptionDefTest) {
 TEST_F(ParseConfigTest, badCodeOptionDefTest) {
 
     {
-
         SCOPED_TRACE("negative code");
         std::string config =
             "{ \"option-def\": [ {"
@@ -769,6 +768,56 @@ TEST_F(ParseConfigTest, badCodeOptionDefTest) {
         int rcode = parseConfiguration(config, false);
         ASSERT_NE(0, rcode);
     }
+
+    {
+        SCOPED_TRACE("conflict with PAD");
+        family_ = AF_INET;     // Switch to DHCPv4.
+
+        std::string config =
+            "{ \"option-def\": [ {"
+            "      \"name\": \"zero\","
+            "      \"code\": 0,"
+            "      \"type\": \"ip-address\","
+            "      \"space\": \"dhcp4\""
+            "  } ]"
+            "}";
+
+        int rcode = parseConfiguration(config, false);
+        ASSERT_NE(0, rcode);
+    }
+
+    {
+        SCOPED_TRACE("conflict with END");
+        family_ = AF_INET;     // Switch to DHCPv4.
+
+        std::string config =
+            "{ \"option-def\": [ {"
+            "      \"name\": \"max\","
+            "      \"code\": 255,"
+            "      \"type\": \"ip-address\","
+            "      \"space\": \"dhcp4\""
+            "  } ]"
+            "}";
+
+        int rcode = parseConfiguration(config, false);
+        ASSERT_NE(0, rcode);
+    }
+
+    {
+        SCOPED_TRACE("conflict with reserved");
+
+        std::string config =
+            "{ \"option-def\": [ {"
+            "      \"name\": \"zero\","
+            "      \"code\": 0,"
+            "      \"type\": \"ipv6-address\","
+            "      \"space\": \"dhcp6\""
+            "  } ]"
+            "}";
+
+        int rcode = parseConfiguration(config, false);
+        ASSERT_NE(0, rcode);
+    }
 }
 
 /// @brief Check parsing of option definitions using invalid space fails.
@@ -968,6 +1017,105 @@ TEST_F(ParseConfigTest, unknownOptionDataTest) {
     ASSERT_NE(0, rcode);
 }
 
+/// @brief Check parsing of option data using invalid code fails.
+TEST_F(ParseConfigTest, badCodeOptionDataTest) {
+
+    {
+        SCOPED_TRACE("negative code");
+        std::string config =
+            "{ \"option-data\": [ {"
+            "      \"code\": -1,"
+            "      \"data\": \"01\","
+            "      \"space\": \"isc\""
+            "  } ]"
+            "}";
+
+        int rcode = parseConfiguration(config, true);
+        ASSERT_NE(0, rcode);
+    }
+
+    {
+        SCOPED_TRACE("out of range code (v6)");
+        std::string config =
+            "{ \"option-data\": [ {"
+            "      \"code\": 100000,"
+            "      \"data\": \"01\","
+            "      \"space\": \"isc\""
+            "  } ]"
+            "}";
+
+        int rcode = parseConfiguration(config, true);
+        ASSERT_NE(0, rcode);
+    }
+
+    {
+        SCOPED_TRACE("out of range code (v4)");
+        family_ = AF_INET;     // Switch to DHCPv4.
+
+        std::string config =
+            "{ \"option-data\": [ {"
+            "      \"code\": 1000,"
+            "      \"data\": \"01\","
+            "      \"space\": \"isc\""
+            "  } ]"
+            "}";
+
+        int rcode = parseConfiguration(config, false);
+        ASSERT_NE(0, rcode);
+    }
+
+    {
+        SCOPED_TRACE("conflict with PAD");
+        family_ = AF_INET;     // Switch to DHCPv4.
+
+        std::string config =
+            "{ \"option-data\": [ {"
+            "      \"code\": 0,"
+            "      \"data\": \"01\","
+            "      \"csv-format\": false,"
+            "      \"space\": \"dhcp4\""
+            "  } ]"
+            "}";
+
+        int rcode = parseConfiguration(config, false);
+        ASSERT_NE(0, rcode);
+    }
+
+    {
+        SCOPED_TRACE("conflict with END");
+        family_ = AF_INET;     // Switch to DHCPv4.
+
+        std::string config =
+            "{ \"option-data\": [ {"
+            "      \"code\": 255,"
+            "      \"data\": \"01\","
+            "      \"csv-format\": false,"
+            "      \"space\": \"dhcp4\""
+            "  } ]"
+            "}";
+
+        int rcode = parseConfiguration(config, false);
+        ASSERT_NE(0, rcode);
+    }
+
+    {
+        SCOPED_TRACE("conflict with reserved");
+        family_ = AF_INET6;    // Switch to DHCPv6.
+
+        std::string config =
+            "{ \"option-data\": [ {"
+            "      \"code\": 0,"
+            "      \"data\": \"01\","
+            "      \"csv-format\": false,"
+            "      \"space\": \"dhcp6\""
+            "  } ]"
+            "}";
+
+        int rcode = parseConfiguration(config, false);
+        ASSERT_NE(0, rcode);
+    }
+}
+
 /// @brief Check parsing of options with invalid space fails.
 TEST_F(ParseConfigTest, badSpaceOptionDataTest) {