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
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
|
// Copyright (C) 2014-2015 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 <boost/shared_ptr.hpp>
#include <list>
#include <map>
#include <string>
#include <utility>
namespace isc {
namespace dhcp {
/// @brief IPv6 reservation for a host.
///
/// This class represents a reservation for a host of a single IPv6
/// address or prefix (in @c Host object).
///
/// The class holds the address and prefix length, a value of 128
/// for the latter implying that the reservation is for a single
/// IPv6 address.
class IPv6Resrv {
public:
/// @brief Type of the reservation.
///
/// Currently supported types are NA and PD.
enum Type {
TYPE_NA,
TYPE_PD
};
/// @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 type Reservation type: NA or PD.
/// @param prefix Address or prefix to be reserved.
/// @param prefix_len Prefix length.
///
/// @throw isc::BadValue if prefix is not IPv6 prefix, is a
/// multicast address or the prefix length is greater than 128.
IPv6Resrv(const Type& type,
const asiolink::IOAddress& prefix,
const uint8_t prefix_len = 128);
/// @brief Returns prefix for the reservation.
const asiolink::IOAddress& getPrefix() const {
return (prefix_);
}
/// @brief Returns prefix length.
uint8_t getPrefixLen() const {
return (prefix_len_);
}
/// @brief Returns reservation type.
///
/// The type of reservation is determined using a prefix length.
///
/// @return NA for prefix length equal to 128, PD otherwise.
Type getType() const {
return (type_);
}
/// @brief Sets a new prefix and prefix length.
///
/// @param type Reservation type: NA or PD.
/// @param prefix New prefix.
/// @param prefix_len New prefix length.
///
/// @throw isc::BadValue if prefix is not IPv6 prefix, is a
/// multicast address or the prefix length is greater than 128.
void set(const Type& type, const asiolink::IOAddress& prefix,
const uint8_t prefix_len);
/// @brief Returns information about the reservation in the textual format.
std::string toText() const;
/// @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;
private:
Type type_; ///< Reservation type.
asiolink::IOAddress prefix_; ///< Prefix
uint8_t prefix_len_; ///< Prefix length.
};
/// @brief Collection of IPv6 reservations for the host.
typedef std::multimap<IPv6Resrv::Type, IPv6Resrv> IPv6ResrvCollection;
typedef IPv6ResrvCollection::const_iterator IPv6ResrvIterator;
typedef std::pair<IPv6Resrv::Type, IPv6Resrv> IPv6ResrvTuple;
typedef std::pair<IPv6ResrvIterator, IPv6ResrvIterator> IPv6ResrvRange;
/// @brief Represents a device with IPv4 and/or IPv6 reservations.
///
/// This class represents a network device which can be identified
/// by a 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 "host" in this context has a different meaning from
/// 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 if the
/// device has multiple interfaces. Under normal circumstances, a non-mobile
/// dual stack device using one interface should be represented by a single
/// @c Host object.
///
/// 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 the DHCPv4 and
/// DHCPv6 servers may use the same database for storing host reservations, so
/// the information about the DHCPv4 reservations are 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.
///
/// @todo This class offers basic functionality for storing host information.
/// It will need to be extended to allow for the following operations:
/// - store DHCPv4 and DHCPv6 options for the host,
/// - remove and replace IPv6 reservations
/// - remove and replace client classes
/// - disable IPv4 reservation without a need to set it to the 0.0.0.0 address
/// Note that the last three operations are mainly required for managing
/// host reservations which will be implemented later.
class Host {
public:
/// @brief Type of the host identifier.
///
/// Currently hardware address assigned to an interface and the
/// DHCPv6 client's DUID are supported.
enum IdentifierType {
IDENT_HWADDR,
IDENT_DUID
};
/// @brief Constructor.
///
/// Creates a @c Host object using an identifier in a binary format. This
/// is most useful in cases where 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.
/// @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.
///
/// @throw BadValue if the provided values are invalid. In particular,
/// if the identifier is invalid.
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,
const std::string& hostname = "",
const std::string& dhcp4_client_classes = "",
const std::string& dhcp6_client_classes = "");
/// @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 formats
/// for the hardware address and DUID have 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.
/// @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.
///
/// @throw BadValue if the provided values are invalid. In particular,
/// if the identifier is invalid.
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,
const std::string& hostname = "",
const std::string& dhcp4_client_classes = "",
const std::string& dhcp6_client_classes = "");
/// @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 the @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 the @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.
void setIdentifier(const std::string& identifier, const std::string& name);
/// @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.
HWAddrPtr getHWAddress() const {
return (hw_address_);
}
/// @brief Returns 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.
DuidPtr getDuid() const {
return (duid_);
}
/// @brief Returns the identifier (MAC or DUID) in binary form.
/// @return const reference to MAC or DUID in vector<uint8_t> form
const std::vector<uint8_t>& getIdentifier() const;
/// @brief Returns the identifier type.
/// @return the identifier type
IdentifierType getIdentifierType() const;
/// @brief Returns host identifier (mac or DUID) in printer friendly form.
/// @return text form of the identifier, including (duid= or mac=).
std::string getIdentifierAsText() const;
/// @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;
}
/// @brief Returns subnet identifier for IPv4 reservation.
SubnetID getIPv4SubnetID() const {
return (ipv4_subnet_id_);
}
/// @brief Returns subnet identifier for IPv6 reservations.
SubnetID getIPv6SubnetID() const {
return (ipv6_subnet_id_);
}
/// @brief Sets new IPv4 reservation.
///
/// The new reservation removes a previous reservation.
///
/// @param address Address to be reserved for the client.
///
/// @throw isc::BadValue if the provided address is not an IPv4 address.
void setIPv4Reservation(const asiolink::IOAddress& address);
/// @brief Returns reserved IPv4 address.
///
/// @return IPv4 address or 0.0.0.0 if no IPv4 reservation specified.
const asiolink::IOAddress& getIPv4Reservation() const {
return (ipv4_reservation_);
}
/// @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;
/// @brief Returns all IPv6 reservations.
///
/// @return A range of iterators pointing to the reservations of
/// the specified type.
IPv6ResrvRange getIPv6Reservations() const;
/// @brief Checks if there is at least one IPv6 reservation for this host.
///
/// @return true if there is a reservation for the host, false otherwise.
bool hasIPv6Reservation() const;
/// @brief Checks if specified IPv6 reservation exists for the host.
///
/// @param reservation A reservation to be checked for the host.
///
/// @return true if the reservation already exists for the host, false
/// otherwise.
bool hasReservation(const IPv6Resrv& reservation) const;
/// @brief Sets new hostname.
///
/// @param hostname New hostname.
void setHostname(const std::string& hostname) {
hostname_ = hostname;
}
/// @brief Returns reserved hostname.
const std::string& getHostname() const {
return (hostname_);
}
/// @brief Adds new client class for DHCPv4.
///
/// @param class_name Class name.
void addClientClass4(const std::string& class_name);
/// @brief Returns classes which DHCPv4 client is associated with.
const ClientClasses& getClientClasses4() const {
return (dhcp4_client_classes_);
}
/// @brief Adds new client class for DHCPv6.
///
/// @param class_name Class name.
void addClientClass6(const std::string& class_name);
/// @brief Returns classes which DHCPv6 client is associated with.
const ClientClasses& getClientClasses6() const {
return (dhcp6_client_classes_);
}
private:
/// @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);
/// @brief Pointer to the hardware address associated with the reservations
/// for the host.
HWAddrPtr hw_address_;
/// @brief Pointer to the DUID associated with the reservations for the
/// host.
DuidPtr duid_;
/// @brief Subnet identifier for the DHCPv4 client.
SubnetID ipv4_subnet_id_;
/// @brief Subnet identifier for the DHCPv6 client.
SubnetID ipv6_subnet_id_;
/// @brief Reserved IPv4 address.
asiolink::IOAddress ipv4_reservation_;
/// @brief Collection of IPv6 reservations for the host.
IPv6ResrvCollection ipv6_reservations_;
/// @brief Name reserved for the host.
std::string hostname_;
/// @brief Collection of classes associated with a DHCPv4 client.
ClientClasses dhcp4_client_classes_;
/// @brief Collection of classes associated with a DHCPv6 client.
ClientClasses dhcp6_client_classes_;
};
/// @brief Pointer to the @c Host object.
typedef boost::shared_ptr<Host> HostPtr;
/// @brief Const pointer to the @c Host object.
typedef boost::shared_ptr<const Host> ConstHostPtr;
/// @brief Collection of the const Host objects.
typedef std::vector<ConstHostPtr> ConstHostCollection;
/// @brief Collection of the @c Host objects.
typedef std::vector<HostPtr> HostCollection;
}
}
#endif // HOST_H
|