summaryrefslogtreecommitdiffstats
path: root/src/lib/dhcp/option_space.h
blob: 4826b0f00af60a6e42f40b3d220d177ad1d13c60 (plain)
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
// Copyright (C) 2012-2020 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 OPTION_SPACE_H
#define OPTION_SPACE_H

#include <dhcp/std_option_defs.h>
#include <exceptions/exceptions.h>

#include <boost/shared_ptr.hpp>
#include <map>
#include <stdint.h>
#include <string>

namespace isc {
namespace dhcp {

/// @brief Exception to be thrown when invalid option space
/// is specified.
class InvalidOptionSpace : public Exception {
public:
    InvalidOptionSpace(const char* file, size_t line, const char* what) :
        isc::Exception(file, line, what) { };
};

/// OptionSpace forward declaration.
class OptionSpace;
/// A pointer to OptionSpace object.
typedef boost::shared_ptr<OptionSpace> OptionSpacePtr;
/// A collection of option spaces.
typedef std::map<std::string, OptionSpacePtr> OptionSpaceCollection;

/// @brief DHCP option space.
///
/// This class represents single option space. The option spaces are used
/// to group DHCP options having unique option codes. The special type
/// of the option space is so called "vendor specific option space".
/// It groups sub-options being sent within Vendor Encapsulated Options.
/// For DHCPv4 it is the option with code 43. The option spaces are
/// assigned to option instances represented by isc::dhcp::Option and
/// other classes derived from it. Each particular option may belong to
/// multiple option spaces.
/// This class may be used to represent any DHCPv4 option space. If the
/// option space is to group DHCPv4 Vendor Encapsulated Options then
/// "vendor space" flag must be set using \ref OptionSpace::setVendorSpace
/// or the argument passed to the constructor. In theory, this class can
/// be also used to represent non-vendor specific DHCPv6 option space
/// but this is discouraged. For DHCPv6 option spaces the OptionSpace6
/// class should be used instead.
///
/// @note this class is intended to be used to represent DHCPv4 option
/// spaces only. However, it hasn't been called OptionSpace4 (that would
/// suggest that it is specific to DHCPv4) because it can be also
/// used to represent some DHCPv6 option spaces and is a base class
/// for \ref OptionSpace6. Thus, if one declared the container as follows:
/// @code
/// std::vector<OptionSpace4> container;
/// @endcode
/// it would suggest that the container holds DHCPv4 option spaces while
/// it could hold both DHCPv4 and DHCPv6 option spaces as the OptionSpace6
/// object could be upcast to OptionSpace4. This confusion does not appear
/// when OptionSpace is used as a name for the base class.
class OptionSpace {
public:

    /// @brief Constructor.
    ///
    /// @param name option space name.
    /// @param vendor_space boolean value that indicates that the object
    /// describes the vendor specific option space.
    ///
    /// @throw isc::dhcp::InvalidOptionSpace if given option space name
    /// contains invalid characters or is empty. This constructor uses
    /// \ref validateName function to check that the specified name is
    /// correct.
    OptionSpace(const std::string& name, const bool vendor_space = false);

    /// @brief Return option space name.
    ///
    /// @return option space name.
    const std::string& getName() const { return (name_); }

    /// @brief Mark option space as non-vendor space.
    void clearVendorSpace() {
        vendor_space_ = false;
    }

    /// @brief Check if option space is vendor specific.
    ///
    /// @return boolean value that indicates if the object describes
    /// the vendor specific option space.
    bool isVendorSpace() const { return (vendor_space_); }

    /// @brief Mark option space as vendor specific.
    void setVendorSpace() {
        vendor_space_ = true;
    }

    /// @brief Checks that the provided option space name is valid.
    ///
    /// It is expected that option space name consists of upper or
    /// lower case letters or digits. Also, it may contain underscores
    /// or dashes. Other characters are prohibited. The empty option
    /// space names are invalid.
    ///
    /// @param name option space name to be validated.
    ///
    /// @return true if the option space is valid, else it returns false.
    static bool validateName(const std::string& name);

private:
    std::string name_;  ///< Holds option space name.

    bool vendor_space_; ///< Is this the vendor space?

};

/// @brief DHCPv6 option space with enterprise number assigned.
///
/// This class extends the base class with the support for enterprise numbers.
/// The enterprise numbers are assigned by IANA to various organizations
/// and they are carried as uint32_t integers in DHCPv6 Vendor Specific
/// Information Options (VSIO). For more information refer to RFC 8415.
/// All option spaces that group VSIO options must have enterprise number
/// set. It can be set using a constructor or \ref setVendorSpace function.
/// The extra functionality of this class (enterprise numbers) allows to
/// represent DHCPv6 vendor-specific option spaces but this class is also
/// intended to be used for all other DHCPv6 option spaces. That way all
/// DHCPv6 option spaces can be stored in the container holding OptionSpace6
/// objects. Also, it is easy to mark vendor-specific option space as non-vendor
/// specific option space (and the other way around) without a need to cast
/// between OptionSpace and OptionSpace6 types.
class OptionSpace6 : public OptionSpace {
public:

    /// @brief Constructor for non-vendor-specific options.
    ///
    /// This constructor marks option space as non-vendor specific.
    ///
    /// @param name option space name.
    ///
    /// @throw isc::dhcp::InvalidOptionSpace if given option space name
    /// contains invalid characters or is empty. This constructor uses
    /// \ref OptionSpace::validateName function to check that the specified
    /// name is correct.
    OptionSpace6(const std::string& name);

    /// @brief Constructor for vendor-specific options.
    ///
    /// This constructor marks option space as vendor specific and sets
    /// enterprise number to a given value.
    ///
    /// @param name option space name.
    /// @param enterprise_number enterprise number.
    ///
    /// @throw isc::dhcp::InvalidOptionSpace if given option space name
    /// contains invalid characters or is empty. This constructor uses
    /// \ref OptionSpace::validateName function to check that the specified
    /// name is correct.
    OptionSpace6(const std::string& name, const uint32_t enterprise_number);

    /// @brief Return enterprise number for the option space.
    ///
    /// @return enterprise number.
    uint32_t getEnterpriseNumber() const { return (enterprise_number_); }

    /// @brief Mark option space as vendor specific.
    ///
    /// @param enterprise_number enterprise number.
    void setVendorSpace(const uint32_t enterprise_number);

private:

    uint32_t enterprise_number_; ///< IANA assigned enterprise number.
};

}  // namespace dhcp
}  // namespace isc

#endif // OPTION_SPACE_H