host.h 15.6 KB
Newer Older
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
// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

#ifndef HOST_H
#define HOST_H

#include <asiolink/io_address.h>
#include <dhcp/classify.h>
#include <dhcp/duid.h>
#include <dhcp/hwaddr.h>
#include <dhcpsrv/subnet_id.h>
#include <list>
#include <map>
#include <string>
#include <utility>

namespace isc {
namespace dhcp {

31
32
33
34
35
36
37
38
/// @brief IPv6 reservation for a host.
///
/// This class represents a reservation of a single IPv6 address or
/// prefix for the host (in @c Host object). The type of reservation
/// indicates whether an address on prefix is reserved. The class
/// holds the information about the prefix length for the prefix
/// reservations. The prefix length for the address reservation is
/// set to 128.
39
40
41
class IPv6Resrv {
public:

42
43
44
    /// @brief Type of the reservation.
    ///
    /// Currently supported types are NA and PD.
45
46
47
48
49
    enum Type {
        TYPE_NA,
        TYPE_PD
    };

50
51
52
53
54
55
56
57
58
    /// @brief Constructor.
    ///
    /// Creates a reservation from the IPv6 address and prefix length
    /// value. If the prefix length is not specified, the default value
    /// of 128 is used. This value indicates that the reservation is made
    /// for an IPv6 address.
    ///
    /// @param prefix Address or prefix to be reserved.
    /// @param prefix_len Prefix length.
59
60
61
    ///
    /// @throw isc::BadValue if address is not IPv6 address or is a
    /// multicast address.
62
    IPv6Resrv(const asiolink::IOAddress& prefix,
63
              const uint8_t prefix_len = 128);
64

65
66
67
    /// @brief Returns prefix for the reservation.
    const asiolink::IOAddress& getPrefix() const {
        return (prefix_);
68
69
    }

70
    /// @brief Returns prefix length.
71
72
73
74
    uint8_t getPrefixLen() const {
        return (prefix_len_);
    }

75
76
77
78
79
    /// @brief Returns reservation type.
    ///
    /// The type of reservation is determined using a prefix length.
    ///
    /// @return NA for prefix length equal to 128, PD otherwise.
80
81
82
83
    Type getType() const {
        return (prefix_len_ == 128 ? TYPE_NA : TYPE_PD);
    }

84
85
86
87
88
89
    /// @brief Sets a new prefix and prefix length.
    ///
    /// @param prefix New prefix.
    /// @param prefix_len New prefix length.
    void set(const asiolink::IOAddress& prefix, const uint8_t prefix_len) {
        prefix_ = prefix;
90
91
92
        prefix_len_ = prefix_len;
    }

93
94
95
96
97
98
99
100
101
102
    /// @brief Equality operator.
    ///
    /// @param other Reservation to compare to.
    bool operator==(const IPv6Resrv& other) const;

    /// @brief Inequality operator.
    ///
    /// @param other Reservation to compare to.
    bool operator!=(const IPv6Resrv& other) const;

103
private:
104
105
    asiolink::IOAddress prefix_; ///< Prefix
    uint8_t prefix_len_;         ///< Prefix length.
106
107
108
109
110

};

/// @brief Collection of IPv6 reservations for the host.
typedef std::multimap<IPv6Resrv::Type, IPv6Resrv> IPv6ResrvCollection;
111
112
typedef IPv6ResrvCollection::const_iterator IPv6ResrvIterator;
typedef std::pair<IPv6Resrv::Type, IPv6Resrv> IPv6ResrvTuple;
113
114
typedef std::pair<IPv6ResrvIterator, IPv6ResrvIterator> IPv6ResrvRange;

115
116
/// @brief Represents a device with IPv4 and/or IPv6 reservations.
///
117
/// This class represents a network device which can be identified
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
/// by the unique property, such as MAC address on the interface or
/// client identifier (DUID), and for which some resources are statically
/// assigned:
/// - IPv4 address which the device obtains when it contacts a DHCPv4 server
/// - IPv6 address(es) which the device obtains when it contacts a DHCPv6
/// server
/// - IPv6 prefix(es) obtained when the device contacts the DHCPv6 server
/// and requests allocation of prefixes using prefix delegation mechanism
/// - hostname which is used for dynamic DNS updates for both DHCPv4 and
/// DHCPv6 exchanges.
/// - client classes which the client is associated with
/// - DHCP options specifically configured for the device
///
/// Note, that the "host" in this context has a different meaning than the
/// host construed as device attached to a network with (possibly) multiple
/// interfaces. For the MAC address based reservations, each interface on a
/// network device maps to a single @c Host object as each @c Host object
/// contains at most one MAC address. So, it is possible that a single
/// device is associated with multiple distinct @c Host objects.
///
/// A DHCPv6 DUID is common for all interfaces on a device. Therefore, for
/// DUID based reservations a @c Host object may represent a network device with
/// multiple interfaces. However, since @c Host objects are grouped by
/// subnets to which device's interfaces are connected a single instance of
/// @c Host object usually defines reservations for a single interface.
///
/// The @c Host object combines reservations for both IPv4 and IPv6 resources
/// to allow for correlation of the information about the dual stack devices
/// using DHCPv4 and DHCPv6 respectively. For example: both DHCPv4 and DHCPv6
/// server may use the same database for storing host reservations, so the
/// information about the DHCPv4 reservations are also available for the
/// DHCPv6 server and vice versa. Also, this approach allows for reserving
/// common resources such as host name for DHCPv4 and DHCPv6 clients.
151
152
153
class Host {
public:

154
155
156
157
    /// @brief Type of the host identifier.
    ///
    /// Currently hardware address assigned to an interface and the
    /// DHCPv6 client's DUID are supported.
158
159
160
161
162
    enum IdentifierType {
        IDENT_HWADDR,
        IDENT_DUID
    };

163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
    /// @brief Constructor.
    ///
    /// Creates @c Host object using an identifier in a binary format. This
    /// is most useful in cases when the identifier is obtained from the
    /// database. The constructor will create an instance of the @c HWAddr
    /// or @c DUID object depending on the identifier type.
    ///
    /// @param identifier Pointer to the binary value holding an identifier.
    /// @param identifier_len Length of the identifier.
    /// @param identifier_type Type of the identifier (hardware address or
    /// DUID).
    /// @param ipv4_subnet_id Identifier of the IPv4 subnet to which the host
    /// is connected.
    /// @param ipv6_subnet_id Identifier of the IPv6 subnet to which the host
    /// is connected.
    /// @param ipv4_reservation An IPv4 address reserved for the client. If
    /// this address is set to 0, there is no reservation.
    /// @param hostname Hostname to be allocated to both DHCPv4 and DHCPv6
    /// clients. This is empty string if hostname is not allocated.
182
183
184
185
    /// @param dhcp4_client_classes A string holding DHCPv4 client class names
    /// separated by commas. The names get trimmed by this constructor.
    /// @param dhcp6_client_classes A string holding DHCPv6 client class names
    /// separated by commas. The names get trimmed by this constructor.
186
187
188
    ///
    /// @throw BadValue if the provided values are invalid. In particular,
    /// if the identifier is invalid.
189
190
191
192
    Host(const uint8_t* identifier, const size_t identifier_len,
         const IdentifierType& identifier_type,
         const SubnetID ipv4_subnet_id, const SubnetID ipv6_subnet_id,
         const asiolink::IOAddress& ipv4_reservation,
193
194
195
         const std::string& hostname = "",
         const std::string& dhcp4_client_classes = "",
         const std::string& dhcp6_client_classes = "");
196

197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
    /// @brief Constructor.
    ///
    /// Creates @c Host object using an identifier in a textual format. This
    /// is useful in cases when the reservation is specified in the server
    /// configuration file, where:
    /// - MAC address is specified as: "01:02:03:04:05:06"
    /// - DUID is specified as: "010203040506abcd"
    ///
    /// @param identifier Identifier in the textual format. The expected format
    /// for hardware address and DUID has been shown above.
    /// @param identifier_name One of "hw-address" or "duid"
    /// @param ipv4_subnet_id Identifier of the IPv4 subnet to which the host
    /// is connected.
    /// @param ipv6_subnet_id Identifier of the IPv6 subnet to which the host
    /// is connected.
    /// @param ipv4_reservation An IPv4 address reserved for the client. If
    /// this address is set to 0, there is no reservation.
    /// @param hostname Hostname to be allocated to both DHCPv4 and DHCPv6
    /// clients. This is empty string if hostname is not allocated.
216
217
218
219
    /// @param dhcp4_client_classes A string holding DHCPv4 client class names
    /// separated by commas. The names get trimmed by this constructor.
    /// @param dhcp6_client_classes A string holding DHCPv6 client class names
    /// separated by commas. The names get trimmed by this constructor.
220
221
222
    ///
    /// @throw BadValue if the provided values are invalid. In particular,
    /// if the identifier is invalid.
223
224
225
    Host(const std::string& identifier, const std::string& identifier_name,
         const SubnetID ipv4_subnet_id, const SubnetID ipv6_subnet_id,
         const asiolink::IOAddress& ipv4_reservation,
226
227
228
         const std::string& hostname = "",
         const std::string& dhcp4_client_classes = "",
         const std::string& dhcp6_client_classes = "");
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
    /// @brief Replaces currently used identifier with a new identifier.
    ///
    /// This method initializes hardware address or DUID (@c hw_address_ or
    /// @c duid_ respectively). The other (not initialized member) is
    /// deallocated.
    ///
    /// This method is called by @c Host constructor.
    ///
    /// @param identifier Pointer to the new identifier in the textual format.
    /// @param len Length of the identifier that the @c identifier points to.
    /// @param type Identifier type.
    ///
    /// @throw BadValue if the identifier is invalid.
    void setIdentifier(const uint8_t* identifier, const size_t len,
                       const IdentifierType& type);

    /// @brief Replaces currently used identifier with a new identifier.
    ///
    /// This method initializes hardware address or DUID (@c hw_address_ or
    /// @c duid_ respectively). The other (not initialized member) is
    /// deallocated.
    ///
    /// This method is called by @c Host constructor.
    ///
    /// @param identifier Pointer to the new identifier in the textual format.
    /// @param name One of "hw-address" or "duid".
    ///
    /// @throw BadValue if the identifier is invalid.
258
259
    void setIdentifier(const std::string& identifier, const std::string& name);

260
261
262
263
    /// @brief Returns hardware address for which the reservations are made.
    ///
    /// @return Pointer to the @c HWAddr structure or null if the reservation
    /// is not associated with a hardware address.
264
265
266
267
    HWAddrPtr getHWAddress() const {
        return (hw_address_);
    }

268
269
270
271
    /// @brief Retruns DUID for which the reservations are made.
    ///
    /// @return Pointer to the @c DUID structure or null if the reservation
    /// is not associated with a DUID.
272
273
274
275
    DuidPtr getDuid() const {
        return (duid_);
    }

276
277
278
279
280
281
282
283
284
285
286
287
288
289
    /// @brief Sets new IPv4 subnet identifier.
    ///
    /// @param ipv4_subnet_id New subnet identifier.
    void setIPv4SubnetID(const SubnetID ipv4_subnet_id) {
        ipv4_subnet_id_ = ipv4_subnet_id;
    }

    /// @brief Sets new IPv6 subnet identifier.
    ///
    /// @param ipv6_subnet_id New subnet identifier.
    void setIPv6SubnetID(const SubnetID ipv6_subnet_id) {
        ipv6_subnet_id_ = ipv6_subnet_id;
    }

290
    /// @brief Returns subnet identifier for IPv4 reservation.
291
292
293
294
    SubnetID getIPv4SubnetID() const {
        return (ipv4_subnet_id_);
    }

295
    /// @brief Returns subnet identifier for IPv6 reservations.
296
297
298
299
    SubnetID getIPv6SubnetID() const {
        return (ipv6_subnet_id_);
    }

300
301
302
303
304
305
306
307
308
    /// @brief Sets new IPv4 reservation.
    ///
    /// The new reservation removes a previous reservation.
    ///
    /// @param address Address to be reserved for the client.
    void setIPv4Reservation(const asiolink::IOAddress& address) {
        ipv4_reservation_ = address;
    }

309
310
311
    /// @brief Returns reserved IPv4 address.
    ///
    /// @return IPv4 address or 0.0.0.0 if no IPv4 reservation specified.
312
313
314
315
    const asiolink::IOAddress& getIPv4Reservation() const {
        return (ipv4_reservation_);
    }

316
317
318
319
320
321
322
323
324
325
326
327
    /// @brief Adds new IPv6 reservation.
    ///
    /// @param reservation New IPv6 reservation to be appended.
    void addReservation(const IPv6Resrv& reservation);

    /// @brief Returns IPv6 reservations of a specified type.
    ///
    /// @param type Type of the reservations to be returned (NA or PD).
    ///
    /// @return A range of iterators pointing to the reservations of
    /// the specified type.
    IPv6ResrvRange getIPv6Reservations(const IPv6Resrv::Type& type) const;
328

329
330
331
332
333
334
335
    /// @brief Sets new hostname.
    ///
    /// @param hostname New hostname.
    void setHostname(const std::string& hostname) {
        hostname_ = hostname;
    }

336
    /// @brief Returns reserved hostname.
337
338
339
340
    const std::string& getHostname() const {
        return (hostname_);
    }

341
342
343
344
345
346
347
    /// @brief Adds new client class for DHCPv4.
    ///
    /// @param class_name Class name.
    void addClientClass4(const std::string& class_name) {
        addClientClassInternal(dhcp4_client_classes_, class_name);
    }

348
    /// @brief Returns classes which DHCPv4 client is associated with.
349
350
351
352
    const ClientClasses& getClientClasses4() const {
        return (dhcp4_client_classes_);
    }

353
354
355
356
357
358
359
    /// @brief Adds new client class for DHCPv6.
    ///
    /// @param class_name Class name.
    void addClientClass6(const std::string& class_name) {
        addClientClassInternal(dhcp6_client_classes_, class_name);
    }

360
    /// @brief Returns classes which DHCPv6 client is associated with.
361
362
363
364
365
366
    const ClientClasses& getClientClasses6() const {
        return (dhcp6_client_classes_);
    }

private:

367
368
369
370
371
372
373
374
375
376
377
378
379
    /// @brief Adds new client class for DHCPv4 or DHCPv6.
    ///
    /// This method is called internally by the @c addClientClass4 and
    /// @c addClientClass6 functions. It adds the class of the specified name
    /// to the supplied class set. The class names are trimmed before they are
    /// added. Empty class names are ignored.
    ///
    /// @param [out] classes Set of classes to which the new class should be
    /// inserted.
    /// @param class_name Class name.
    void addClientClassInternal(ClientClasses& classes,
                                const std::string& class_name);

380
381
    /// @brief Pointer to the hardware address associated with the reservations
    /// for the host.
382
    HWAddrPtr hw_address_;
383
384
    /// @brief Pointer to the DUID associated with the reservations for the
    /// host.
385
    DuidPtr duid_;
386
    /// @brief Subnet identifier for the DHCPv4 client.
387
    SubnetID ipv4_subnet_id_;
388
    /// @brief Subnet identifier for the DHCPv6 client.
389
    SubnetID ipv6_subnet_id_;
390
    /// @brief Reserved IPv4 address.
391
    asiolink::IOAddress ipv4_reservation_;
392
    /// @brief Collection of IPv6 reservations for the host.
393
    IPv6ResrvCollection ipv6_reservations_;
394
    /// @brief Name reserved for the host.
395
    std::string hostname_;
396
    /// @brief Collection of classes associated with a DHCPv4 client.
397
    ClientClasses dhcp4_client_classes_;
398
    /// @brief Collection of classes associated with a DHCPv6 client.
399
400
401
402
403
404
405
    ClientClasses dhcp6_client_classes_;
};

}
}

#endif // HOST_H