1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
// Copyright (C) 2018-2024 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 <dhcp/dhcp6.h>
#include <dhcp/libdhcp++.h>
#include <dhcp/option6_auth.h>
#include <dhcp/option_space.h>
#include <exceptions/exceptions.h>
#include <util/io_utilities.h>
#include <util/encode/hex.h>
#include <sstream>
#include <stdint.h>
using namespace std;
using namespace isc::util;
namespace isc {
namespace dhcp {
Option6Auth::Option6Auth(const uint8_t proto, const uint8_t algo,
const uint8_t method, const uint64_t rdm,
const std::vector<uint8_t>& info)
: Option(Option::V6, D6O_AUTH),
protocol_(proto), algorithm_(algo),
rdm_method_(method), rdm_value_(rdm),
auth_info_(info) {
}
OptionPtr
Option6Auth::clone() const {
return (cloneInternal<Option6Auth>());
}
void
Option6Auth::pack(isc::util::OutputBuffer& buf, bool) const {
if (buf.getCapacity() < (OPTION6_AUTH_MIN_LEN + OPTION6_HASH_MSG_LEN + OPTION6_HDR)) {
isc_throw(OutOfRange, "Option " << type_ << "Buffer too small for"
"packing data");
}
//header = option code + length
buf.writeUint16(type_);
// length = 11 bytes fixed field length+ length of auth information
buf.writeUint16(11 + uint16_t(auth_info_.size()));
// protocol 1 byte
buf.writeUint8(protocol_);
// algorithm 1 byte
buf.writeUint8(algorithm_);
// replay detection method
buf.writeUint8(rdm_method_);
// replay detection value
buf.writeUint64( rdm_value_);
// authentication information for reconfig msg
// should have zero
for (auto const& i : auth_info_) {
buf.writeUint8(i);
}
}
void
Option6Auth::packHashInput(isc::util::OutputBuffer& buf) const {
if (buf.getCapacity() < (OPTION6_AUTH_MIN_LEN + OPTION6_HASH_MSG_LEN + OPTION6_HDR)) {
isc_throw(OutOfRange, "Option " << type_ << "Buffer too small for"
"computing hash input");
}
//header = option code + length
buf.writeUint16(type_);
// length = 11 bytes fixed field length+ length of auth information
buf.writeUint16(OPTION6_AUTH_MIN_LEN + OPTION6_HASH_MSG_LEN);
// protocol 1 byte
buf.writeUint8(protocol_);
// algorithm 1 byte
buf.writeUint8(algorithm_);
// replay detection method
buf.writeUint8(rdm_method_);
// replay detection value
buf.writeUint64(rdm_value_);
// authentication information for reconfig msg
// should have zero
for (uint8_t i = 0; i < OPTION6_HASH_MSG_LEN; i++) {
buf.writeUint8(0);
}
}
void
Option6Auth::unpack(OptionBufferConstIter begin,
OptionBufferConstIter end) {
// throw if it contains length less than minimum size of the auth option
if (distance(begin, end) < Option6Auth::OPTION6_AUTH_MIN_LEN) {
isc_throw(OutOfRange, "Option " << type_ << " truncated");
}
protocol_ = *begin;
begin += sizeof(uint8_t);
algorithm_ = *begin;
begin += sizeof(uint8_t);
rdm_method_ = *begin;
begin += sizeof(uint8_t);
rdm_value_ = isc::util::readUint64(&(*begin), sizeof(uint64_t));
begin += sizeof(uint64_t);
auth_info_.erase(auth_info_.begin(), auth_info_.end());
std::for_each(begin, end, [this](uint8_t msgdata)
{ auth_info_.push_back(msgdata); });
}
std::string
Option6Auth::toText(int indent) const {
stringstream output;
std::string in(indent, ' '); //base indent
output << in << "protocol=" << static_cast<int>(protocol_)
<< ", algorithm=" << static_cast<int>(algorithm_)
<< ", rdm method=" << static_cast<int>(rdm_method_)
<< ", rdm value=" << rdm_value_
<< ", value=" << isc::util::encode::encodeHex(auth_info_);
return output.str();
}
} // end namespace dhcp
} // end namespace isc
|