]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
added PDEXCLUDE option and PSID data type
authorAndrei Pavel <andrei.pavel@qualitance.com>
Thu, 16 Jun 2016 09:16:05 +0000 (12:16 +0300)
committerAndrei Pavel <andrei.pavel@qualitance.com>
Thu, 16 Jun 2016 09:16:05 +0000 (12:16 +0300)
13 files changed:
src/bin/dhcp6/dhcp6_srv.cc
src/bin/dhcp6/json_config_parser.cc
src/lib/dhcp/Makefile.am
src/lib/dhcp/dhcp6.h
src/lib/dhcp/option6_pdexclude.cc [new file with mode: 0644]
src/lib/dhcp/option6_pdexclude.h [new file with mode: 0644]
src/lib/dhcp/option_custom.cc
src/lib/dhcp/option_data_types.cc
src/lib/dhcp/option_data_types.h
src/lib/dhcp/option_definition.cc
src/lib/dhcp/std_option_defs.h
src/lib/dhcpsrv/pool.cc
src/lib/dhcpsrv/pool.h

index b64739051e15134e47717404d13ffc1fd72d896f..34aa64863f2f398e8c20a81bb2a43d3bf5385032 100644 (file)
@@ -20,6 +20,7 @@
 #include <dhcp/option6_iaaddr.h>
 #include <dhcp/option6_iaprefix.h>
 #include <dhcp/option6_status_code.h>
+#include <dhcp/option6_pdexclude.h>
 #include <dhcp/option_custom.h>
 #include <dhcp/option_vendor.h>
 #include <dhcp/option_vendor_class.h>
@@ -1504,6 +1505,36 @@ Dhcpv6Srv::assignIA_PD(const Pkt6Ptr& query, const Pkt6Ptr& answer,
                                          (*l)->prefixlen_, (*l)->preferred_lft_,
                                          (*l)->valid_lft_));
             ia_rsp->addOption(addr);
+
+            // Client requests some options using ORO option. Try to
+            // get this option from client's message.
+            boost::shared_ptr<OptionIntArray<uint16_t> > option_oro =
+                boost::dynamic_pointer_cast<OptionIntArray<uint16_t> >
+                (query->getOption(D6O_ORO));
+
+            if (option_oro) {
+
+                // Get the list of options that client requested.
+                const std::vector<uint16_t>& requested_opts = option_oro->getValues();
+
+                bool pdExcludeFound = false;
+
+                BOOST_FOREACH(uint16_t opt, requested_opts) {
+                    if (opt == D6O_PD_EXCLUDE) {
+                        pdExcludeFound = true;
+                        break;
+                    }
+                }
+
+                Pool6Ptr pool = boost::dynamic_pointer_cast<Pool6>
+                        (ctx.subnet_->getPool(ctx.type_, (*l)->addr_, false));
+
+                if (pdExcludeFound && pool && pool->getPrefixExcludedLength() > 0) {
+                    OptionPtr opt(new Option6PDExclude((*l)->addr_, (*l)->prefixlen_,
+                                    pool->getPrefixExcluded(), pool->getPrefixExcludedLength()));
+                    addr->addOption(opt);
+                }
+            }
         }
 
         // It would be possible to insert status code=0(success) as well,
@@ -1778,6 +1809,37 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query,
                                (*l)->addr_, (*l)->prefixlen_,
                                (*l)->preferred_lft_, (*l)->valid_lft_));
         ia_rsp->addOption(prf);
+
+        // Client requests some options using ORO option. Try to
+        // get this option from client's message.
+        boost::shared_ptr<OptionIntArray<uint16_t> > option_oro =
+            boost::dynamic_pointer_cast<OptionIntArray<uint16_t> >
+            (query->getOption(D6O_ORO));
+
+        if (option_oro) {
+
+            // Get the list of options that client requested.
+            const std::vector<uint16_t>& requested_opts = option_oro->getValues();
+
+            bool pdExcludeFound = false;
+
+            BOOST_FOREACH(uint16_t opt, requested_opts) {
+                if (opt == D6O_PD_EXCLUDE) {
+                    pdExcludeFound = true;
+                    break;
+                }
+            }
+
+            Pool6Ptr pool = boost::dynamic_pointer_cast<Pool6>
+                    (ctx.subnet_->getPool(ctx.type_, (*l)->addr_, false));
+
+            if (pdExcludeFound && pool && pool->getPrefixExcludedLength() > 0) {
+                OptionPtr opt(new Option6PDExclude((*l)->addr_, (*l)->prefixlen_,
+                                pool->getPrefixExcluded(), pool->getPrefixExcludedLength()));
+                prf->addOption(opt);
+            }
+        }
+
         LOG_INFO(lease6_logger, DHCP6_PD_LEASE_RENEW)
             .arg(query->getLabel())
             .arg((*l)->addr_.toText())
index b2a2790ac2d186cdbed243e9c050551d6003db35..7a6e6ba1cde65fdcb40aa60be23269759cc1fa52 100644 (file)
@@ -172,11 +172,12 @@ public:
         BOOST_FOREACH(ConfigPair param, pd_pool_->mapValue()) {
             std::string entry(param.first);
             ParserPtr parser;
-            if (entry == "prefix") {
+            if (entry == "prefix" || entry =="excluded-prefix") {
                 StringParserPtr str_parser(new StringParser(entry,
                                                             string_values_));
                 parser = str_parser;
-            } else if (entry == "prefix-len" || entry == "delegated-len") {
+            } else if (entry == "prefix-len" || entry == "delegated-len" ||
+                       entry == "excluded-prefix-len") {
                 Uint32ParserPtr code_parser(new Uint32Parser(entry,
                                                              uint32_values_));
                 parser = code_parser;
@@ -195,10 +196,17 @@ public:
             std::string addr_str = string_values_->getParam("prefix");
             uint32_t prefix_len = uint32_values_->getParam("prefix-len");
             uint32_t delegated_len = uint32_values_->getParam("delegated-len");
-
+            std::string excluded_prefix_str = "::";
+            uint32_t excluded_prefix_len = 0;
+            try {
+                    excluded_prefix_str = string_values_->getParam("excluded-prefix");
+                    excluded_prefix_len = uint32_values_->getParam("excluded-prefix-len");
+            } catch (DhcpConfigError& ex) {
+            }
             // Attempt to construct the local pool.
-            pool_.reset(new Pool6(Lease::TYPE_PD, IOAddress(addr_str),
-                                  prefix_len, delegated_len));
+            pool_.reset(new Pool6(Lease::TYPE_PD, IOAddress(addr_str), prefix_len,
+                                  delegated_len, IOAddress(excluded_prefix_str),
+                                  excluded_prefix_len));
         } catch (const std::exception& ex) {
             // Some parameters don't exist or are invalid. Since we are not
             // aware whether they don't exist or are invalid, let's append
index 72c40835454c5c061713344ee738c52323f803d6..12787157dec72ea481c64cd9858d61b86d6d11c4 100644 (file)
@@ -31,6 +31,7 @@ libkea_dhcp___la_SOURCES += option4_client_fqdn.cc option4_client_fqdn.h
 libkea_dhcp___la_SOURCES += option6_ia.cc option6_ia.h
 libkea_dhcp___la_SOURCES += option6_iaaddr.cc option6_iaaddr.h
 libkea_dhcp___la_SOURCES += option6_iaprefix.cc option6_iaprefix.h
+libkea_dhcp___la_SOURCES += option6_pdexclude.cc option6_pdexclude.h
 libkea_dhcp___la_SOURCES += option6_addrlst.cc option6_addrlst.h
 libkea_dhcp___la_SOURCES += option6_client_fqdn.cc option6_client_fqdn.h
 libkea_dhcp___la_SOURCES += option6_status_code.cc option6_status_code.h
index bcc5cabc1fd0664581eaf9c2f929f25c734be190..21f43a7e1605b6a2a0e46819abfc30763976f9b3 100644 (file)
@@ -82,7 +82,7 @@
 #define D6O_AFTR_NAME                           64 /* RFC6334 */
 #define D6O_ERP_LOCAL_DOMAIN_NAME               65 /* RFC6440 */
 #define D6O_RSOO                                66 /* RFC6422 */
-//#define D6O_PD_EXCLUDE                          67 /* RFC6603 */
+#define D6O_PD_EXCLUDE                          67 /* RFC6603 */
 //#define D6O_VSS                                 68 /* RFC6607 */
 //#define D6O_MIP6_IDINF                          69 /* RFC6610 */
 //#define D6O_MIP6_UDINF                          70 /* RFC6610 */
diff --git a/src/lib/dhcp/option6_pdexclude.cc b/src/lib/dhcp/option6_pdexclude.cc
new file mode 100644 (file)
index 0000000..34fbbd1
--- /dev/null
@@ -0,0 +1,102 @@
+// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <asiolink/io_address.h>
+#include <dhcp/dhcp6.h>
+#include <dhcp/libdhcp++.h>
+#include <dhcp/option6_pdexclude.h>
+#include <exceptions/exceptions.h>
+#include <util/io_utilities.h>
+
+#include <boost/dynamic_bitset.hpp>
+
+#include <sstream>
+
+#include <arpa/inet.h>
+#include <stdint.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dhcp;
+using namespace isc::asiolink;
+using namespace isc::util;
+
+namespace isc {
+namespace dhcp {
+
+Option6PDExclude::Option6PDExclude(const isc::asiolink::IOAddress& addr,
+                                   uint8_t prefix_len,
+                                   const isc::asiolink::IOAddress& prefix_excluded,
+                                   uint8_t prefix_excluded_len
+                                   )
+    :Option(V6, D6O_PD_EXCLUDE)
+    ,addr_(addr), prefix_len_(prefix_len)
+    ,prefix_excluded_(prefix_excluded)
+    ,prefix_excluded_len_(prefix_excluded_len) {
+
+}
+
+void
+Option6PDExclude::pack(isc::util::OutputBuffer& buf) {
+    // Header = option code and length.
+    packHeader(buf);
+
+    uint8_t excludedPrefLenBytes = excludedPrefixLenBytes();
+
+    buf.writeData(&prefix_excluded_len_, sizeof(prefix_excluded_len_));
+
+    std::vector<uint8_t> addrV6 = prefix_excluded_.toBytes();
+    boost::dynamic_bitset<uint8_t> bits(addrV6.rbegin(), addrV6.rend());
+    bits = bits << prefix_len_;
+
+    for (int i = 0; i < excludedPrefLenBytes; i++) {
+        boost::dynamic_bitset<uint8_t> tmp = bits >> 120;
+
+        uint8_t val = static_cast<uint8_t>(tmp.to_ulong());
+
+        //Zero padded bits follow when prefix_excluded_len_ is not divided exactly by 8
+        if (i == excludedPrefLenBytes - 1) {
+            uint8_t excluded_prefix_bits_no = prefix_excluded_len_ - prefix_len_;
+
+            uint8_t unusedBits = 0xFF;
+            unusedBits <<= (8 - (excluded_prefix_bits_no % 8)) % 8;
+
+            val = val & unusedBits;
+        }
+        bits = bits << 8;
+        buf.writeData(&val, sizeof(val));
+    }
+}
+
+void Option6PDExclude::unpack(OptionBufferConstIter begin,
+                              OptionBufferConstIter end) {
+    prefix_len_ = 0;
+    prefix_excluded_len_ = *begin;
+    begin += sizeof(uint8_t);
+    addr_ = IOAddress::IPV6_ZERO_ADDRESS();
+    prefix_excluded_ = IOAddress::IPV6_ZERO_ADDRESS();
+    begin = end;
+}
+
+uint16_t
+Option6PDExclude::len()
+{
+    return getHeaderLen() + sizeof (prefix_excluded_len_) +
+            excludedPrefixLenBytes();
+}
+
+uint8_t
+Option6PDExclude::excludedPrefixLenBytes()
+{
+    uint8_t excludedPrefLenBits = prefix_excluded_len_ - prefix_len_ - 1;
+    uint8_t excludedPrefLenBytes = (excludedPrefLenBits / 8) + 1;
+    return excludedPrefLenBytes;
+}
+
+} // end of namespace isc::dhcp
+} // end of namespace isc
diff --git a/src/lib/dhcp/option6_pdexclude.h b/src/lib/dhcp/option6_pdexclude.h
new file mode 100644 (file)
index 0000000..677d41f
--- /dev/null
@@ -0,0 +1,70 @@
+// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef OPTION6_PDEXCLUDE_H
+#define OPTION6_PDEXCLUDE_H
+
+#include <asiolink/io_address.h>
+#include <boost/shared_ptr.hpp>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief DHCPv6 Option class for handling list of IPv6 addresses.
+///
+/// This class handles a list of IPv6 addresses. An example of such option
+/// is dns-servers option. It can also be used to handle single address.
+class Option6PDExclude: public Option {
+
+public:
+
+    Option6PDExclude(const isc::asiolink::IOAddress& addr,
+                     uint8_t prefix_len,
+                     const isc::asiolink::IOAddress& prefix_excluded,
+                     uint8_t prefix_excluded_len);
+
+    /// @brief Writes option in wire-format to a buffer.
+    ///
+    /// Writes option in wire-format to buffer, returns pointer to first unused
+    /// byte after stored option (that is useful for writing options one after
+    /// another).
+    ///
+    /// @param buf pointer to a buffer
+    ///
+    /// @throw BadValue Universe of the option is neither V4 nor V6.
+    virtual void pack(isc::util::OutputBuffer& buf);
+
+    /// @brief Parses received buffer.
+    ///
+    /// @param begin iterator to first byte of option data
+    /// @param end iterator to end of option data (first byte after option end)
+    virtual void unpack(OptionBufferConstIter begin,
+                        OptionBufferConstIter end);
+
+    /// Returns length of the complete option (data length + DHCPv6
+    /// option header)
+    ///
+    /// @return length of the option
+    virtual uint16_t len();
+
+protected:
+    uint8_t excludedPrefixLenBytes();
+
+protected:
+    isc::asiolink::IOAddress addr_;
+    uint8_t prefix_len_;
+
+    isc::asiolink::IOAddress prefix_excluded_;
+    uint8_t prefix_excluded_len_;
+};
+
+/// @brief Pointer to the @c Option6PDExclude object.
+typedef boost::shared_ptr<Option6PDExclude> Option6PDExcludePtr;
+
+} // isc::dhcp namespace
+} // isc namespace
+
+#endif // OPTION6_PDEXCLUDE_H
index 79d0aca57ee52606182993d64aed33a3db13c25f..d78654280a864cfe690cb97195af42a6fd6b33ae 100644 (file)
@@ -194,6 +194,15 @@ OptionCustom::createBuffers(const OptionBuffer& data_buf) {
                     // that the validate() function in OptionDefinition object
                     // should have checked wheter it is a case for this option.
                     data_size = std::distance(data, data_buf.end());
+                } else if ( *field == OPT_IPV6_PREFIX_TYPE ) {
+                    // The size of the IPV6 prefix type is determined as
+                    // one byte (which is the size of the prefix in bits)
+                    // followed by the prefix bits (right-padded with
+                    // zeros to the nearest octet boundary)
+
+                    uint8_t lenBits = *data;
+                    uint8_t lenBytes = (lenBits + 7) / 8;
+                    data_size = lenBytes + sizeof(lenBits);
                 } else {
                     // If we reached the end of buffer we assume that this option is
                     // truncated because there is no remaining data to initialize
index 8a8fdf622d5b22e44522231ea2c39cbe17dd0df1..47f080d987c904e01076a08d9d64a94270f2c3f8 100644 (file)
@@ -24,6 +24,8 @@ OptionDataTypeUtil::OptionDataTypeUtil() {
     data_types_["uint32"] = OPT_UINT32_TYPE;
     data_types_["ipv4-address"] = OPT_IPV4_ADDRESS_TYPE;
     data_types_["ipv6-address"] = OPT_IPV6_ADDRESS_TYPE;
+    data_types_["ipv6-prefix"] = OPT_IPV6_PREFIX_TYPE;
+    data_types_["psid"] = OPT_PSID_TYPE;
     data_types_["string"] = OPT_STRING_TYPE;
     data_types_["fqdn"] = OPT_FQDN_TYPE;
     data_types_["record"] = OPT_RECORD_TYPE;
@@ -39,6 +41,8 @@ OptionDataTypeUtil::OptionDataTypeUtil() {
     data_type_names_[OPT_UINT32_TYPE] = "uint32";
     data_type_names_[OPT_IPV4_ADDRESS_TYPE] = "ipv4-address";
     data_type_names_[OPT_IPV6_ADDRESS_TYPE] = "ipv6-address";
+    data_type_names_[OPT_IPV6_PREFIX_TYPE] = "ipv6-prefix";
+    data_type_names_[OPT_PSID_TYPE] = "psid";
     data_type_names_[OPT_STRING_TYPE] = "string";
     data_type_names_[OPT_FQDN_TYPE] = "fqdn";
     data_type_names_[OPT_RECORD_TYPE] = "record";
@@ -86,6 +90,9 @@ OptionDataTypeUtil::getDataTypeLen(const OptionDataType data_type) {
     case OPT_IPV6_ADDRESS_TYPE:
         return (asiolink::V6ADDRESS_LEN);
 
+    case OPT_PSID_TYPE:
+        return (3);
+
     default:
         ;
     }
index 4bb688f12c4e961c6ff396b34d2e3a18b1909031..767036231290713b10527fe2c4d3ef78bf724965 100644 (file)
@@ -54,6 +54,7 @@ enum OptionDataType {
     OPT_IPV4_ADDRESS_TYPE,
     OPT_IPV6_ADDRESS_TYPE,
     OPT_IPV6_PREFIX_TYPE,
+    OPT_PSID_TYPE,
     OPT_STRING_TYPE,
     OPT_FQDN_TYPE,
     OPT_RECORD_TYPE,
index b40f8e0fe9750773116803de9a1e59994f7fe5a6..af8198291c427409b5ba889f0cbf2ff9d38944c0 100644 (file)
@@ -625,6 +625,67 @@ OptionDefinition::writeToBuffer(const std::string& value,
 
             return;
     }
+    case OPT_PSID_TYPE:
+    {
+        std::string txt = value;
+
+        // first let's remove any whitespaces
+        boost::erase_all(txt, " "); // space
+        boost::erase_all(txt, "\t"); // tabulation
+
+        // Is this prefix/len notation?
+        size_t pos = txt.find("/");
+
+        if (pos == string::npos) {
+            isc_throw(BadDataTypeCast, "provided psid-len/psid "
+                      << value
+                      << " is not valid.");
+        }
+
+        std::string txt_psid = txt.substr(0, pos);
+        std::string txt_psid_len = txt.substr(pos + 1);
+
+        uint16_t psid = 0;
+        uint8_t psid_len = 0;
+
+        try {
+            psid = lexicalCastWithRangeCheck<uint16_t>(txt_psid);
+        } catch (...)  {
+            isc_throw(BadDataTypeCast, "provided psid "
+                      << txt_psid
+                      << " is not valid.");
+        }
+
+        try {
+            psid_len = lexicalCastWithRangeCheck<uint8_t>(txt_psid_len);
+        } catch (...)  {
+            isc_throw(BadDataTypeCast, "provided psid-len "
+                      << txt_psid_len
+                      << " is not valid.");
+        }
+
+        if (psid >= (1 << psid_len)) {
+            isc_throw(BadDataTypeCast, "provided psid "
+                      << txt_psid
+                      << " is not valid.");
+        }
+
+        if (psid_len > sizeof(uint16_t) * 8) {
+            isc_throw(BadDataTypeCast, "provided psid-len "
+                      << txt_psid_len
+                      << " is not valid.");
+        }
+
+        psid = psid << (sizeof(uint16_t) * 8 - psid_len);
+
+        // Write the psid length
+        OptionDataTypeUtil::writeInt<uint8_t>(psid_len, buf);
+
+        // Write the psid
+        OptionDataTypeUtil::writeInt<uint16_t>(psid, buf);
+
+        return;
+    }
     case OPT_STRING_TYPE:
         OptionDataTypeUtil::writeString(value, buf);
         return;
index 1d6a68d03b4efa073595f5ccdc92291ba2f1c3aa..366f48bc9a60c1a4334f04cd1794dd4939636279 100644 (file)
@@ -251,7 +251,7 @@ RECORD_DECL(S46_RULE, OPT_UINT8_TYPE, OPT_UINT8_TYPE, OPT_UINT8_TYPE,
 // s46-v4v6bind
 RECORD_DECL(S46_V4V6BIND, OPT_IPV4_ADDRESS_TYPE, OPT_IPV6_PREFIX_TYPE);
 // s46-portparams
-RECORD_DECL(S46_PORTPARAMS, OPT_UINT8_TYPE, OPT_UINT8_TYPE, OPT_UINT16_TYPE);
+RECORD_DECL(S46_PORTPARAMS, OPT_UINT8_TYPE, OPT_PSID_TYPE);
 // status-code
 RECORD_DECL(STATUS_CODE_RECORDS, OPT_UINT16_TYPE, OPT_STRING_TYPE);
 // vendor-class
@@ -361,6 +361,7 @@ const OptionDefParams STANDARD_V6_OPTION_DEFINITIONS[] = {
     { "erp-local-domain-name", D6O_ERP_LOCAL_DOMAIN_NAME, OPT_FQDN_TYPE, false,
       NO_RECORD_DEF, "" },
     { "rsoo", D6O_RSOO, OPT_EMPTY_TYPE, false, NO_RECORD_DEF, "rsoo-opts" },
+    { "pd-exclude", D6O_PD_EXCLUDE, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" },
     { "client-linklayer-addr", D6O_CLIENT_LINKLAYER_ADDR, OPT_BINARY_TYPE, false,
       NO_RECORD_DEF, "" },
     { "dhcpv4-message", D6O_DHCPV4_MSG, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" },
index fa89aac580d6ae4e1e1283b37446878bc4e0b1b1..136cea6d9e6b27f904d0f220fea00c6808392b72 100644 (file)
@@ -76,7 +76,9 @@ Pool4::Pool4( const isc::asiolink::IOAddress& prefix, uint8_t prefix_len)
 
 Pool6::Pool6(Lease::Type type, const isc::asiolink::IOAddress& first,
              const isc::asiolink::IOAddress& last)
-    :Pool(type, first, last), prefix_len_(128) {
+    :Pool(type, first, last), prefix_len_(128)
+    ,prefix_excluded_(isc::asiolink::IOAddress::IPV6_ZERO_ADDRESS())
+    ,prefix_excluded_len_(0) {
 
     // check if specified address boundaries are sane
     if (!first.isV6() || !last.isV6()) {
@@ -117,8 +119,11 @@ Pool6::Pool6(Lease::Type type, const isc::asiolink::IOAddress& first,
 }
 
 Pool6::Pool6(Lease::Type type, const isc::asiolink::IOAddress& prefix,
-             uint8_t prefix_len, uint8_t delegated_len /* = 128 */)
-    :Pool(type, prefix, IOAddress("::")), prefix_len_(delegated_len) {
+             uint8_t prefix_len, uint8_t delegated_len /* = 128 */,
+             const isc::asiolink::IOAddress& prefix_excluded /*= IOAddress::IPV6_ZERO_ADDRESS()*/,
+             uint8_t prefix_excluded_len /* = 0 */)
+    :Pool(type, prefix, IOAddress("::")), prefix_len_(delegated_len)
+    , prefix_excluded_(prefix_excluded), prefix_excluded_len_(prefix_excluded_len){
 
     // check if the prefix is sane
     if (!prefix.isV6()) {
index d5b26aa28fbfc5bc1e370fef0680fda093ae1dc7..d0bdb2e76e91ad98d49ea46cdbefa1a697e54a43 100644 (file)
@@ -199,7 +199,9 @@ public:
     /// @param prefix_len specifies prefix length of the pool
     /// @param delegated_len specifies lenght of the delegated prefixes
     Pool6(Lease::Type type, const isc::asiolink::IOAddress& prefix,
-          uint8_t prefix_len, uint8_t delegated_len = 128);
+          uint8_t prefix_len, uint8_t delegated_len = 128,
+          const isc::asiolink::IOAddress& prefix_excluded = isc::asiolink::IOAddress::IPV6_ZERO_ADDRESS(),
+          uint8_t prefix_excluded_len = 0);
 
     /// @brief returns pool type
     ///
@@ -217,6 +219,22 @@ public:
         return (prefix_len_);
     }
 
+    /// @brief returns excluded prefix
+    ///
+    /// This is useful for prefix definitions exclude pools.
+    /// @return excluded prefix
+    const isc::asiolink::IOAddress& getPrefixExcluded() const{
+        return (prefix_excluded_);
+    }
+
+    /// @brief returns excluded prefix length
+    ///
+    /// This is useful for prefix definitions exclude pools.
+    /// @return excluded prefix length (2-128)
+    uint8_t getPrefixExcludedLength() const{
+        return (prefix_excluded_len_);
+    }
+
     /// @brief returns textual representation of the pool
     ///
     /// @return textual representation
@@ -225,6 +243,12 @@ public:
 private:
     /// @brief Defines prefix length (for TYPE_PD only)
     uint8_t prefix_len_;
+
+    /// @brief The excluded prefix (for TYPE_PD only)
+    isc::asiolink::IOAddress prefix_excluded_;
+
+    /// @brief The excluded prefix length (for TYPE_PD only)
+    uint8_t prefix_excluded_len_;
 };
 
 /// @brief a pointer an IPv6 Pool