]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#2536] Working on packing DNRv6 Option
authorPiotrek Zadroga <piotrek@isc.org>
Tue, 11 Apr 2023 18:46:46 +0000 (20:46 +0200)
committerPiotrek Zadroga <piotrek@isc.org>
Thu, 4 May 2023 21:17:18 +0000 (23:17 +0200)
src/lib/dhcp/option_dnr.cc
src/lib/dhcp/option_dnr.h
src/lib/dhcp/tests/option_dnr_unittest.cc

index ef6d762e4f696ecfb272e13dcb25b6e2fee497a7..545026641f247274db6803c756b20181658b84d0 100644 (file)
@@ -11,6 +11,7 @@
 #include <dhcp/dhcp6.h>
 #include <dhcp/opaque_data_tuple.h>
 #include <dhcp/option_dnr.h>
+#include <dns/labelsequence.h>
 
 using namespace isc::asiolink;
 
@@ -24,7 +25,7 @@ OptionDnr6::OptionDnr6(OptionBufferConstIter begin, OptionBufferConstIter end)
 
 OptionPtr
 OptionDnr6::clone() const {
-    return Option::clone();
+    return (cloneInternal<OptionDnr6>());
 }
 
 void
@@ -32,7 +33,46 @@ OptionDnr6::pack(util::OutputBuffer& buf, bool check) const {
     packHeader(buf, check);
 
     buf.writeUint16(service_priority_);
-    // TBD
+    buf.writeUint16(adn_length_);
+    packAdn(buf);
+    if (adn_only_mode_) {
+        return;
+    }
+    buf.writeUint16(addr_length_);
+    packAddresses(buf);
+    packSvcParams(buf);
+}
+
+void
+OptionDnr6::packAdn(util::OutputBuffer& buf) const {
+    if (!adn_) {
+        // This should not happen since Encrypted DNS options are designed
+        // to always include an authentication domain name.
+        return;
+    }
+    isc::dns::LabelSequence label_sequence(*adn_);
+    if (label_sequence.getDataLength() > 0) {
+        size_t data_length = 0;
+        const uint8_t* data = label_sequence.getData(&data_length);
+        buf.writeData(data, data_length);
+    }
+}
+
+void
+OptionDnr6::packAddresses(util::OutputBuffer& buf) const {
+    for (auto address = ipv6_addresses_.begin(); address != ipv6_addresses_.end(); ++address) {
+        if (!address->isV6()) {
+            isc_throw(isc::BadValue, address->toText() << " is not an IPv6 address");
+        }
+        buf.writeData(&address->toBytes()[0], V6ADDRESS_LEN);
+    }
+}
+
+void
+OptionDnr6::packSvcParams(util::OutputBuffer& buf) const {
+    if (svc_params_length_ > 0) {
+        buf.writeData(&*svc_params_.begin(), svc_params_length_);
+    }
 }
 
 void
@@ -100,7 +140,10 @@ OptionDnr6::unpack(OptionBufferConstIter begin, OptionBufferConstIter end) {
 
     // SvcParams (variable length) field is last
     svc_params_length_ = std::distance(begin, end);
-    // TBD svcParams unpack
+    if (svc_params_length_ > 0) {
+        // for now let's keep SvcParams as binary data in buffer
+        svc_params_.assign(begin, end);
+    }
 }
 
 std::string
index d95fa4a10c5cd4838b06141b98c89d37fc1c5c76..ea4f70e27dd0332ea82d02dc7af71ea9fa2ca4ac 100644 (file)
@@ -116,8 +116,18 @@ private:
     /// @brief Length of Service Parameters field in octets.
     uint16_t svc_params_length_ = 0;
 
+    /// @brief Flag stating whether ADN only mode is used or not.
+    ///
+    /// "Addr Length", "ipv6-address(es)", and "Service Parameters (SvcParams)"
+    /// fields are not present if the ADN-only mode is used.
     bool adn_only_mode_ = true;
 
+    /// @brief Service Parameters (SvcParams) (variable length).
+    ///
+    /// Specifies a set of service parameters that are encoded
+    /// following the rules in Section 2.1 of [I-D.ietf-dnsop-svcb-https].
+    std::vector<uint8_t> svc_params_;
+
     /// @brief Returns minimal length of the option data (without headers) in octets.
     ///
     /// If the ADN-only mode is used, then "Addr Length", "ipv6-address(es)",
@@ -129,6 +139,12 @@ private:
     static uint8_t getMinimalLength() {
         return SERVICE_PRIORITY_SIZE + ADN_LENGTH_SIZE;
     };
+
+    void packAdn(isc::util::OutputBuffer& buf) const;
+
+    void packAddresses(isc::util::OutputBuffer& buf) const;
+
+    void packSvcParams(isc::util::OutputBuffer& buf) const;
 };
 
 class OptionDnr4 : public Option {
index d7d2a8603b72615966e44926af207facf54706d8..b405d011a5f730746993fd919ea630e3be30605d 100644 (file)
@@ -190,8 +190,7 @@ TEST(OptionDnr6Test, validIpV6Addresses) {
         0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef,
         0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // ff02::face:b00c
         0x00, 0x00, 0x00, 0x00, 0xfa, 0xce, 0xb0, 0x0c,
-        // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
     };