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);