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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
// Copyright (C) 2013-2022 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_CLIENT_FQDN_H
#define OPTION6_CLIENT_FQDN_H

#include <dhcp/option.h>
#include <dns/name.h>

#include <string><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.

namespace isc {
namespace dhcp {

/// @brief Exception thrown when invalid flags have been specified for
/// DHCPv6 Client Fqdn %Option.
class InvalidOption6FqdnFlags : public Exception {
public:
    InvalidOption6FqdnFlags(const char* file, size_t line, const char* what) :
        isc::Exception(file, line, what) {}
};

/// @brief Exception thrown when invalid domain name is specified.
class InvalidOption6FqdnDomainName : public Exception {
public:
    InvalidOption6FqdnDomainName(const char* file, size_t line,
                                const char* what) :
        isc::Exception(file, line, what) {}
};

/// Forward declaration to implementation of @c Option6ClientFqdn class.
class Option6ClientFqdnImpl;

/// @brief Represents DHCPv6 Client FQDN %Option (code 39).
///
/// This option has been defined in the RFC 4704 and it has a following
/// structure:
/// - option-code = 39 (2 octets)
/// - option-len (2 octets)
/// - flags (1 octet)
/// - domain-name - variable length field comprising partial or fully qualified
/// domain name.
///
/// The flags field has the following structure:
/// @code
///        0 1 2 3 4 5 6 7
///       +-+-+-+-+-+-+-+-+
///       |  MBZ    |N|O|S|
///       +-+-+-+-+-+-+-+-+
/// @endcode
/// where:
/// - N flag specifies whether server should (0) or should not (1) perform DNS
///  Update,
/// - O flag is set by the server to indicate that it has overridden client's
/// preference set with the S bit.
/// - S flag specifies whether server should (1) or should not (0) perform
/// forward (FQDN-to-address) updates.
///
/// This class exposes a set of functions to modify flags and check their
/// correctness.
///
/// Domain names being carried by DHCPv6 Client Fqdn %Option can be fully
/// qualified or partial. Partial domain names are encoded similar to the
/// fully qualified domain names, except that they lack terminating zero
/// at the end of their wire representation. It is also accepted to create an
/// instance of this option which has empty domain-name. Clients use empty
/// domain-names to indicate that server should generate complete fully
/// qualified domain-name.
///
/// Since domain names are case insensitive (see RFC 4343), this class
/// converts them to lower case format regardless if they are received over
/// the wire or created from strings.
///
/// <b>Design choice:</b> This class uses pimpl idiom to separate the interface
/// from implementation specifics. Implementations may use different approaches
/// to handle domain names (mostly validation of the domain-names). The existing
/// @c isc::dns::Name class is a natural (and the simplest) choice to handle
/// domain-names. Use of this class however, implies that libdhcp must be linked
/// with libdns. At some point these libraries may need to be separated, i.e. to
/// support compilation and use of standalone DHCP server. This will require
/// that the part of implementation which deals with domain-names is modified to
/// not use classes from libdns. These changes will be transparent for this
/// interface.
class Option6ClientFqdn : public Option {
public:

    ///
    ///@name A set of constants setting respective bits in 'flags' field
    //@{
    static const uint8_t FLAG_S = 0x01; ///< S bit.
    static const uint8_t FLAG_O = 0x02; ///< O bit.
    static const uint8_t FLAG_N = 0x04; ///< N bit.
    //@}

    /// @brief Mask which zeroes MBZ flag bits.
    static const uint8_t FLAG_MASK = 0x7;

    /// @brief The length of the flag field within DHCPv6 Client Fqdn %Option.
    static const uint16_t FLAG_FIELD_LEN = 1;

    /// @brief Type of the domain-name: partial or full.
    enum DomainNameType {
        PARTIAL,
        FULL
    };

    /// @brief Constructor, creates option instance using flags and domain name.
    ///
    /// This constructor is used to create instance of the option which will be
    /// included in outgoing messages.
    ///
    /// @param flags a combination of flag bits to be stored in flags field.
    /// @param domain_name a name to be stored in the domain-name field.
    /// @param domain_name_type indicates if the domain name is partial
    /// or full.
    explicit Option6ClientFqdn(const uint8_t flags,
                               const std::string& domain_name,
                               const DomainNameType domain_name_type = FULL);

    /// @brief Constructor, creates option instance using flags.
    ///
    /// This constructor creates an instance of the option with empty
    /// domain-name. This domain-name is marked partial.
    ///
    /// @param flags A combination of flag bits to be stored in flags field.
    Option6ClientFqdn(const uint8_t flags);

    /// @brief Constructor, creates an option instance from part of the buffer.
    ///
    /// This constructor is mainly used to parse options in the received
    /// messages. Function parameters specify buffer bounds from which the
    /// option should be created. The size of the buffer chunk, specified by
    /// the constructor's parameters should be equal or larger than the size
    /// of the option. Otherwise, constructor will throw an exception.
    ///
    /// @param first the lower bound of the buffer to create option from.
    /// @param last the upper bound of the buffer to create option from.
    explicit Option6ClientFqdn(OptionBufferConstIter first,
                               OptionBufferConstIter last);

    /// @brief Copy constructor
    Option6ClientFqdn(const Option6ClientFqdn& source);

    /// @brief Copies this option and returns a pointer to the copy.
    virtual OptionPtr clone() const;

    /// @brief Destructor
    virtual ~Option6ClientFqdn();

    /// @brief Assignment operator
    Option6ClientFqdn& operator=(const Option6ClientFqdn& source);

    /// @brief Checks if the specified flag of the DHCPv6 Client FQDN %Option
    /// is set.
    ///
    /// This method checks the single bit of flags field. Therefore, a caller
    /// should use one of the: @c FLAG_S, @c FLAG_N, @c FLAG_O constants as
    /// an argument of the function. Attempt to use any other value (including
    /// combinations of these constants) will result in exception.
    ///
    /// @param flag A value specifying the flags bit to be checked. It can be
    /// one of the following: @c FLAG_S, @c FLAG_N, @c FLAG_O.
    ///
    /// @return true if the bit of the specified flag is set, false otherwise.
    bool getFlag(const uint8_t flag) const;

    /// @brief Modifies the value of the specified DHCPv6 Client Fqdn %Option
    /// flag.
    ///
    /// This method sets the single bit of flags field. Therefore, a caller
    /// should use one of the: @c FLAG_S, @c FLAG_N, @c FLAG_O constants as
    /// an argument of the function. Attempt to use any other value (including
    /// combinations of these constants) will result in exception.
    ///
    /// @param flag A value specifying the flags bit to be modified. It can
    /// be one of the following: @c FLAG_S, @c FLAG_N, @c FLAG_O.
    /// @param set a boolean value which indicates whether flag should be
    /// set (true), or cleared (false).
    void setFlag(const uint8_t flag, const bool set);

    /// @brief Sets the flag field value to 0.
    void resetFlags();

    /// @brief Returns the domain-name in the text format.
    ///
    /// If domain-name is partial, it lacks the dot at the end (e.g. myhost).
    /// If domain-name is fully qualified, it has the dot at the end (e.g.
    /// myhost.example.com.).
    ///
    /// @return domain-name in the text format.
    std::string getDomainName() const;

    /// @brief Writes domain-name in the wire format into a buffer.
    ///
    /// The data being written are appended at the end of the buffer.
    ///
    /// @param [out] buf buffer where domain-name will be written.
    void packDomainName(isc::util::OutputBuffer& buf) const;

    /// @brief Set new domain-name.
    ///
    /// @param domain_name domain name field value in the text format.
    /// @param domain_name_type type of the domain name: partial or fully
    /// qualified.
    void setDomainName(const std::string& domain_name,
                       const DomainNameType domain_name_type);

    /// @brief Set empty domain-name.
    ///
    /// This function is equivalent to @c Option6ClientFqdn::setDomainName
    /// with empty partial domain-name. It is exception safe.
    void resetDomainName();

    /// @brief Returns enumerator value which indicates whether domain-name is
    /// partial or full.
    ///
    /// @return An enumerator value indicating whether domain-name is partial
    /// or full.
    DomainNameType getDomainNameType() const;

    /// @brief Writes option in the wire format into a buffer.
    ///
    /// @param [out] buf output buffer where option data will be stored.
    /// @param check if set to false, allows options larger than 255 for v4
    virtual void pack(isc::util::OutputBuffer& buf, bool check = true) const;<--- Function in derived class

    /// @brief Parses option from the received buffer.
    ///
    /// Method creates an instance of the DHCPv6 Client FQDN %Option from the
    /// wire format. Parameters specify the bounds of the buffer to read option
    /// data from. The size of the buffer limited by the specified parameters
    /// should be equal or larger than size of the option (including its
    /// header). Otherwise exception will be thrown.
    ///
    /// @param first lower bound of the buffer to parse option from.
    /// @param last upper bound of the buffer to parse option from.
    virtual void unpack(OptionBufferConstIter first,
                        OptionBufferConstIter last);

    /// @brief Returns string representation of the option.
    ///
    /// The string returned by the method comprises the bit value of each
    /// option flag and the domain-name.
    ///
    /// @param indent number of spaces before printed text.
    ///
    /// @return string with text representation.
    virtual std::string toText(int indent = 0) const;<--- Function in derived class

    /// @brief Returns length of the complete option (data length +
    /// DHCPv6 option header).
    ///
    /// @return length of the option.
    virtual uint16_t len() const;<--- Function in derived class

private:

    /// @brief A pointer to the implementation.
    Option6ClientFqdnImpl* impl_;
};

/// A pointer to the @c Option6ClientFqdn object.
typedef boost::shared_ptr<Option6ClientFqdn> Option6ClientFqdnPtr;

} // namespace isc::dhcp
} // namespace isc

#endif // OPTION6_CLIENT_FQDN_H