16 #include <boost/dynamic_bitset.hpp>
30 const uint8_t delegated_prefix_length,
32 const uint8_t excluded_prefix_length)
34 excluded_prefix_length_(excluded_prefix_length),
38 if (!delegated_prefix.
isV6() || !excluded_prefix.
isV6() ||
39 (delegated_prefix_length > 128) || (excluded_prefix_length_ > 128)) {
41 << delegated_prefix <<
"/"
42 << static_cast<int>(delegated_prefix_length) <<
", "
43 << excluded_prefix <<
"/"
44 << static_cast<int>(excluded_prefix_length_));
48 if (excluded_prefix_length_ <= delegated_prefix_length) {
50 << excluded_prefix <<
"/"
51 << static_cast<int>(excluded_prefix_length_)
52 <<
" must be greater than the length of the"
53 " delegated prefix " << delegated_prefix <<
"/"
54 << static_cast<int>(delegated_prefix_length));
59 std::vector<uint8_t> delegated_prefix_bytes = delegated_prefix.
toBytes();
60 boost::dynamic_bitset<uint8_t> delegated_prefix_bits(delegated_prefix_bytes.rbegin(),
61 delegated_prefix_bytes.rend());
63 std::vector<uint8_t> excluded_prefix_bytes = excluded_prefix.
toBytes();
64 boost::dynamic_bitset<uint8_t> excluded_prefix_bits(excluded_prefix_bytes.rbegin(),
65 excluded_prefix_bytes.rend());
69 const uint8_t delta = 128 - delegated_prefix_length;
71 if ((delegated_prefix_bits >> delta) != (excluded_prefix_bits >> delta)) {
73 << excluded_prefix <<
"/"
74 << static_cast<int>(excluded_prefix_length_)
75 <<
" must have the same common prefix part of "
76 << static_cast<int>(delegated_prefix_length)
77 <<
" as the delegated prefix "
78 << delegated_prefix <<
"/"
79 << static_cast<int>(delegated_prefix_length));
85 excluded_prefix_bits <<= delegated_prefix_length;
88 const uint8_t subnet_id_length = getSubnetIDLength(delegated_prefix_length,
89 excluded_prefix_length);
90 for (uint8_t i = 0; i < subnet_id_length; ++i) {
92 const boost::dynamic_bitset<uint8_t> first_byte = excluded_prefix_bits >> 120;
95 uint8_t val =
static_cast<uint8_t
>(first_byte.to_ulong());
99 if (i == subnet_id_length - 1) {
100 uint8_t length_delta = excluded_prefix_length_ - delegated_prefix_length;
101 if (length_delta % 8 != 0) {
103 mask <<= (8 - (length_delta % 8));
108 subnet_id_.push_back(val);
111 excluded_prefix_bits <<= 8;
118 excluded_prefix_length_(0),
125 return (cloneInternal<Option6PDExclude>());
132 if ((excluded_prefix_length_ == 0) || subnet_id_.empty()) {
134 " must not be empty");
144 buf.
writeData(static_cast<const void*>(&subnet_id_[0]), subnet_id_.size());
154 if (std::distance(begin, end) < 2) {
159 uint8_t excluded_prefix_length = *begin++;
160 if (excluded_prefix_length == 0) {
164 std::vector<uint8_t> subnet_id_bytes(begin, end);
169 uint8_t last_bits_num = excluded_prefix_length % 8;
170 if (last_bits_num > 0) {
171 *subnet_id_bytes.rbegin() = (*subnet_id_bytes.rbegin() >> (8 - last_bits_num)
172 << (8 - (last_bits_num)));
175 excluded_prefix_length_ = excluded_prefix_length;
176 subnet_id_.swap(subnet_id_bytes);
181 return (
getHeaderLen() +
sizeof(excluded_prefix_length_) + subnet_id_.size());
186 std::ostringstream s;
188 s <<
"excluded-prefix-len=" <<
static_cast<unsigned>(excluded_prefix_length_)
195 const uint8_t delegated_prefix_length)
const {
197 std::vector<uint8_t> delegated_prefix_bytes = delegated_prefix.
toBytes();
200 const uint8_t bytes_length = (delegated_prefix_length / 8) +
201 static_cast<uint8_t>(delegated_prefix_length % 8 != 0);
202 std::fill(delegated_prefix_bytes.begin() + bytes_length,
203 delegated_prefix_bytes.end(), 0);
206 boost::dynamic_bitset<uint8_t> bits(delegated_prefix_bytes.rbegin(),
207 delegated_prefix_bytes.rend());
209 boost::dynamic_bitset<uint8_t> subnet_id_bits(subnet_id_.rbegin(),
214 for (
int i = subnet_id_bits.size() - 1; i >= 0; --i) {
215 bits.set(128 - delegated_prefix_length - subnet_id_bits.size() + i,
216 subnet_id_bits.test(i));
220 std::vector<uint8_t> bytes(V6ADDRESS_LEN);
221 boost::to_block_range(bits, bytes.rbegin());
228 Option6PDExclude::getSubnetIDLength(
const uint8_t delegated_prefix_length,
229 const uint8_t excluded_prefix_length)
const {
230 uint8_t subnet_id_length_bits = excluded_prefix_length -
231 delegated_prefix_length - 1;
232 uint8_t subnet_id_length = (subnet_id_length_bits / 8) + 1;
233 return (subnet_id_length);
asiolink::IOAddress getExcludedPrefix(const asiolink::IOAddress &delegated_prefix, const uint8_t delegated_prefix_length) const
Returns excluded prefix.
void packHeader(isc::util::OutputBuffer &buf) const
Store option's header in a buffer.
virtual void pack(isc::util::OutputBuffer &buf) const
Writes option in wire-format to a buffer.
boost::shared_ptr< Option > OptionPtr
virtual uint16_t len() const
Returns length of the complete option (data length + DHCPv6 option header)
virtual uint16_t getHeaderLen() const
Returns length of header (2 for v4, 4 for v6)
std::vector< uint8_t > toBytes() const
Return address as set of bytes.
Option6PDExclude(const isc::asiolink::IOAddress &delegated_prefix, const uint8_t delegated_prefix_length, const isc::asiolink::IOAddress &excluded_prefix, const uint8_t excluded_prefix_length)
Constructor.
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
static IOAddress fromBytes(short family, const uint8_t *data)
Creates an address from over wire data.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
OptionBuffer::const_iterator OptionBufferConstIter
const_iterator for walking over OptionBuffer
Defines the logger used by the top-level component of kea-dhcp-ddns.
string encodeHex(const vector< uint8_t > &binary)
Encode binary data in the base16 ('hex') format.
virtual std::string toText(int indent=0) const
Returns Prefix Exclude option in textual format.
virtual OptionPtr clone() const
Copies this option and returns a pointer to the copy.
std::string headerToText(const int indent=0, const std::string &type_name="") const
Returns option header in the textual format.
void writeUint8(uint8_t data)
Write an unsigned 8-bit integer into the buffer.
bool isV6() const
Convenience function to check for an IPv6 address.
The IOAddress class represents an IP addresses (version agnostic)
virtual void unpack(OptionBufferConstIter begin, OptionBufferConstIter end)
Parses received buffer.