1 // Copyright (C) 2013-2021 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #ifndef NCR_MSG_H
8 #define NCR_MSG_H
9 
10 /// @file ncr_msg.h
11 /// @brief This file provides the classes needed to embody, compose, and
12 /// decompose DNS update requests that are sent by DHCP-DDNS clients to
13 /// DHCP-DDNS. These requests are referred to as NameChangeRequests.
14 
15 #include <cc/data.h>
16 #include <dhcp/duid.h>
17 #include <dhcp/hwaddr.h>
18 #include <dns/name.h>
19 #include <exceptions/exceptions.h>
20 #include <util/buffer.h>
21 #include <util/time_utilities.h>
22 
23 #include <time.h>
24 #include <string>
25 
26 namespace isc {
27 namespace dhcp_ddns {
28 
29 /// @brief Exception thrown when NameChangeRequest marshalling error occurs.
30 class NcrMessageError : public isc::Exception {
31 public:
NcrMessageError(const char * file,size_t line,const char * what)32     NcrMessageError(const char* file, size_t line, const char* what) :
33         isc::Exception(file, line, what) { };
34 };
35 
36 /// @brief Exception thrown when there is an error occurred during computation
37 /// of the DHCID.
38 class DhcidRdataComputeError : public isc::Exception {
39 public:
DhcidRdataComputeError(const char * file,size_t line,const char * what)40     DhcidRdataComputeError(const char* file, size_t line, const char* what) :
41         isc::Exception(file, line, what) { };
42 };
43 
44 
45 /// @brief Defines the types of DNS updates that can be requested.
46 enum NameChangeType {
47   CHG_ADD,
48   CHG_REMOVE
49 };
50 
51 /// @brief Defines the runtime processing status values for requests.
52 enum NameChangeStatus  {
53   ST_NEW,
54   ST_PENDING,
55   ST_COMPLETED,
56   ST_FAILED
57 };
58 
59 /// @brief Defines the list of data wire formats supported.
60 enum NameChangeFormat {
61   FMT_JSON
62 };
63 
64 /// @brief Function which converts labels to  NameChangeFormat enum values.
65 ///
66 /// @param fmt_str text to convert to an enum.
67 /// Valid string values: "JSON"
68 ///
69 /// @return NameChangeFormat value which maps to the given string.
70 ///
71 /// @throw isc::BadValue if given a string value which does not map to an
72 /// enum value.
73 extern NameChangeFormat stringToNcrFormat(const std::string& fmt_str);
74 
75 /// @brief Function which converts NameChangeFormat enums to text labels.
76 ///
77 /// @param format enum value to convert to label
78 ///
79 /// @return std:string containing the text label if the value is valid, or
80 /// "UNKNOWN" if not.
81 extern std::string ncrFormatToString(NameChangeFormat format);
82 
83 /// @brief Container class for handling the DHCID value within a
84 /// NameChangeRequest. It provides conversion to and from string for JSON
85 /// formatting, but stores the data internally as unsigned bytes.
86 class D2Dhcid {
87 public:
88     /// @brief Default constructor
89     D2Dhcid();
90 
91     /// @brief Constructor - Creates a new instance, populated by converting
92     /// a given string of digits into an array of unsigned bytes.
93     ///
94     /// @param data is a string of hexadecimal digits. The format is simply
95     /// a contiguous stream of digits, with no delimiters. For example a string
96     /// containing "14A3" converts to a byte array containing:  0x14, 0xA3.
97     ///
98     /// @throw NcrMessageError if the input data contains non-digits
99     /// or there is an odd number of digits.
100     D2Dhcid(const std::string& data);
101 
102     /// @brief Constructor, creates an instance of the @c D2Dhcid from the
103     /// HW address.
104     ///
105     /// @param hwaddr A pointer to the object encapsulating HW address.
106     /// @param wire_fqdn A on-wire canonical representation of the FQDN.
107     D2Dhcid(const isc::dhcp::HWAddrPtr& hwaddr,
108             const std::vector<uint8_t>& wire_fqdn);
109 
110     /// @brief Constructor, creates an instance of the @c D2Dhcid from the
111     /// client identifier carried in the Client Identifier option.
112     ///
113     /// @param clientid_data Holds the raw bytes representing client identifier.
114     /// @param wire_fqdn A on-wire canonical representation of the FQDN.
115     D2Dhcid(const std::vector<uint8_t>& clientid_data,
116             const std::vector<uint8_t>& wire_fqdn);
117 
118     /// @brief Constructor, creates an instance of the @c D2Dhcid from the
119     /// @c isc::dhcp::DUID.
120     ///
121     /// @param duid An object representing DUID.
122     /// @param wire_fqdn A on-wire canonical representation of the FQDN.
123     D2Dhcid(const isc::dhcp::DUID& duid,
124             const std::vector<uint8_t>& wire_fqdn);
125 
126     /// @brief Returns the DHCID value as a string of hexadecimal digits.
127     ///
128     /// @return a string containing a contiguous stream of digits.
129     std::string toStr() const;
130 
131     /// @brief Sets the DHCID value based on the given string.
132     ///
133     /// @param data is a string of hexadecimal digits. The format is simply
134     /// a contiguous stream of digits, with no delimiters. For example a string
135     /// containing "14A3" converts to a byte array containing:  0x14, 0xA3.
136     ///
137     /// @throw NcrMessageError if the input data contains non-digits
138     /// or there is an odd number of digits.
139     void fromStr(const std::string& data);
140 
141     /// @brief Sets the DHCID value based on the Client Identifier.
142     ///
143     /// @param clientid_data Holds the raw bytes representing client identifier.
144     /// @param wire_fqdn A on-wire canonical representation of the FQDN.
145     void fromClientId(const std::vector<uint8_t>& clientid_data,
146                       const std::vector<uint8_t>& wire_fqdn);
147 
148     /// @brief Sets the DHCID value based on the DUID and FQDN.
149     ///
150     /// This function requires that the FQDN conforms to the section 3.5
151     /// of the RFC4701, which says that the FQDN must be in lowercase.
152     /// This function doesn't validate if it really converted.
153     ///
154     /// @param duid A @c isc::dhcp::DUID object encapsulating DUID.
155     /// @param wire_fqdn A on-wire canonical representation of the FQDN.
156     void fromDUID(const isc::dhcp::DUID& duid,
157                   const std::vector<uint8_t>& wire_fqdn);
158 
159     /// @brief Sets the DHCID value based on the HW address and FQDN.
160     ///
161     /// @param hwaddr A pointer to the object encapsulating HW address.
162     /// @param wire_fqdn A on-wire canonical representation of the FQDN.
163     void fromHWAddr(const isc::dhcp::HWAddrPtr& hwaddr,
164                     const std::vector<uint8_t>& wire_fqdn);
165 
166     /// @brief Returns a reference to the DHCID byte vector.
167     ///
168     /// @return a reference to the vector.
getBytes()169     const std::vector<uint8_t>& getBytes() const {
170         return (bytes_);
171     }
172 
173     /// @brief Compares two D2Dhcids for equality
174     bool operator==(const D2Dhcid& other) const {
175         return (this->bytes_ == other.bytes_);
176     }
177 
178     /// @brief Compares two D2Dhcids for inequality
179     bool operator!=(const D2Dhcid& other) const {
180         return (this->bytes_ != other.bytes_);
181     }
182 
183     /// @brief Compares two D2Dhcids lexically
184     bool operator<(const D2Dhcid& other) const {
185         return (this->bytes_ < other.bytes_);
186     }
187 
188 private:
189 
190     /// @brief Creates the DHCID using specified identifier.
191     ///
192     /// This function creates the DHCID RDATA as specified in RFC4701,
193     /// section 3.5.
194     ///
195     /// @param identifier_type is a less significant byte of the identifier-type
196     /// defined in RFC4701.
197     /// @param identifier_data A buffer holding client identifier raw data -
198     /// e.g. DUID, data carried in the Client Identifier option or client's
199     /// HW address.
200     /// @param A on-wire canonical representation of the FQDN.
201     void createDigest(const uint8_t identifier_type,
202                       const std::vector<uint8_t>& identifier_data,
203                       const std::vector<uint8_t>& wire_fqdn);
204 
205     /// @brief Storage for the DHCID value in unsigned bytes.
206     std::vector<uint8_t> bytes_;
207 };
208 
209 std::ostream&
210 operator<<(std::ostream& os, const D2Dhcid& dhcid);
211 
212 class NameChangeRequest;
213 /// @brief Defines a pointer to a NameChangeRequest.
214 typedef boost::shared_ptr<NameChangeRequest> NameChangeRequestPtr;
215 
216 /// @brief Defines a map of Elements, keyed by their string name.
217 typedef std::map<std::string, isc::data::ConstElementPtr> ElementMap;
218 
219 /// @brief  Represents a DHCP-DDNS client request.
220 /// This class is used by DHCP-DDNS clients (e.g. DHCP4, DHCP6) to
221 /// request DNS updates.  Each message contains a single DNS change (either an
222 /// add/update or a remove) for a single FQDN.  It provides marshalling services
223 /// for moving instances to and from the wire.  Currently, the only format
224 /// supported is JSON detailed here isc::dhcp_ddns::NameChangeRequest::fromJSON
225 /// The class provides an interface such that other formats can be readily
226 /// supported.
227 class NameChangeRequest {
228 public:
229     /// @brief Default Constructor.
230     ///
231     /// @todo Currently, fromWire makes use of the ability to create an empty
232     /// NameChangeRequest and then builds it bit by bit.  This means that it
233     /// is technically possible to create one and attempt to use in ways
234     /// other than intended and its invalid content may or may not be handled
235     /// gracefully by consuming code.  It might be wise to revisit this
236     /// structuring such that we do not use a default constructor and only
237     /// allow valid instantiations.
238     NameChangeRequest();
239 
240     /// @brief Constructor.  Full constructor, which provides parameters for
241     /// all of the class members, except status.
242     ///
243     /// @param change_type the type of change (Add or Update)
244     /// @param forward_change indicates if this change should be sent to forward
245     /// DNS servers.
246     /// @param reverse_change indicates if this change should be sent to reverse
247     /// DNS servers.
248     /// @param fqdn the domain name whose pointer record(s) should be
249     /// updated.
250     /// @param ip_address the ip address leased to the given FQDN.
251     /// @param dhcid the lease client's unique DHCID.
252     /// @param lease_expires_on a timestamp containing the date/time the lease
253     /// expires.
254     /// @param lease_length the amount of time in seconds for which the
255     /// lease is valid (TTL).
256     /// @param conflict_resolution indicates whether or not conflict resolution
257     /// (per RFC 4703) is enabled.
258     NameChangeRequest(const NameChangeType change_type,
259                       const bool forward_change, const bool reverse_change,
260                       const std::string& fqdn, const std::string& ip_address,
261                       const D2Dhcid& dhcid,
262                       const uint64_t lease_expires_on,
263                       const uint32_t lease_length,
264                       const bool conflict_resolution = true);
265 
266     /// @brief Static method for creating a NameChangeRequest from a
267     /// buffer containing a marshalled request in a given format.
268     ///
269     /// When the format is:
270     ///
271     /// JSON: The buffer is expected to contain a two byte unsigned integer
272     /// which specified the length of the JSON text; followed by the JSON
273     /// text itself.  This method attempts to extract "length" characters
274     /// from the buffer. This data is used to create a character string that
275     /// is than treated as JSON which is then parsed into the data needed
276     /// to create a request instance.
277     ///
278     /// (NOTE currently only JSON is supported.)
279     ///
280     /// @param format indicates the data format to use
281     /// @param buffer is the input buffer containing the marshalled request
282     ///
283     /// @return a pointer to the new NameChangeRequest
284     ///
285     /// @throw NcrMessageError if an error occurs creating new
286     /// request.
287     static NameChangeRequestPtr fromFormat(const NameChangeFormat format,
288                                            isc::util::InputBuffer& buffer);
289 
290     /// @brief Instance method for marshalling the contents of the request
291     /// into the given buffer in the given format.
292     ///
293     /// When the format is:
294     ///
295     /// JSON: Upon completion, the buffer will contain a two byte unsigned
296     /// integer which specifies the length of the JSON text; followed by the
297     /// JSON text itself. The JSON text contains the names and values for all
298     /// the request data needed to reassemble the request on the receiving
299     /// end. The JSON text in the buffer is NOT null-terminated.  The format
300     /// is identical that described under
301     /// isc::dhcp_ddns::NameChangeRequest::fromJSON
302     ///
303     /// (NOTE currently only JSON is supported.)
304     ///
305     /// @param format indicates the data format to use
306     /// @param buffer is the output buffer to which the request should be
307     /// marshalled.
308     void toFormat(const NameChangeFormat format,
309                   isc::util::OutputBuffer& buffer) const;
310 
311     /// @brief Static method for creating a NameChangeRequest from a
312     /// string containing a JSON rendition of a request.
313     ///
314     /// The JSON expected is described below.  Note that a request must be
315     /// enclosed within curly brackets "{..}" and that whitespace is optional
316     /// (it is used in the following examples for clarity).
317     ///
318     /// @code
319     ///     {
320     ///      "change-type" : <integer>,
321     ///      "forward-change" : <boolean>,
322     ///      "reverse-change" : <boolean>,
323     ///      "fqdn" : "<fqdn>",
324     ///      "ip-address" : "<address>",
325     ///      "dhcid" : "<hex_string>",
326     ///      "lease-expires-on" : "<yyyymmddHHMMSS>",
327     ///      "lease-length" : <secs>,
328     ///      "use-conflict-resolution": <boolean>
329     ///     }
330     /// @endcode
331     ///
332     /// - change-type - indicates whether this request is to add or update
333     ///   DNS entries or to remove them.  The value is an integer and is
334     ///   0 for add/update and 1 for remove.
335     /// - forward-change - indicates whether the forward (name to
336     ///   address) DNS zone should be updated.  The value is a string
337     ///   representing a boolean.  It is "true" if the zone should be updated
338     ///   and "false" if not. (Unlike the keyword, the boolean value is
339     ///   case-insensitive.)
340     /// - reverse-change - indicates whether the reverse (address to
341     ///   name) DNS zone should be updated.  The value is a string
342     ///   representing a boolean.  It is "true" if the zone should be updated
343     ///   and "false" if not. (Unlike the keyword, the boolean value is
344     ///   case-insensitive.)
345     /// - fqdn - fully qualified domain name such as "myhost.example.com.".
346     ///   (Note that a trailing dot will be appended if not supplied.)
347     /// - ip-address - the IPv4 or IPv6 address of the client.  The value
348     ///   is a string representing the IP address (e.g. "192.168.0.1" or
349     ///   "2001:db8:1::2").
350     /// - dhcid - identification of the DHCP client to whom the IP address has
351     ///   been leased.  The value is a string containing an even number of
352     ///   hexadecimal digits without delimiters such as "2C010203040A7F8E3D"
353     ///   (case insensitive).
354     /// - lease-expires-on - the date and time on which the lease expires.
355     ///   The value is a string of the form "yyyymmddHHMMSS" where:
356     ///     - yyyy - four digit year
357     ///     - mm - month of year (1-12),
358     ///     - dd - day of the month (1-31),
359     ///     - HH - hour of the day (0-23)
360     ///     - MM - minutes of the hour (0-59)
361     ///     - SS - seconds of the minute (0-59)
362     /// - lease-length - the length of the lease in seconds.  This is an
363     ///   integer and may range between 1 and 4294967295 (2^32 - 1) inclusive.
364     /// - use-conflict-resolution - when true, follow RFC 4703 which uses
365     ///   DHCID records to prohibit multiple clients from updating an FQDN
366     ///
367     /// Examples:
368     ///
369     /// Removal of an IPv4 address from the forward DNS zone only:
370     ///
371     /// @code
372     ///  {
373     ///     "change-type" : 1,
374     ///     "forward-change" : true,
375     ///     "reverse-change" : false,
376     ///     "fqdn" : "myhost.example.com.",
377     ///     "ip-address" : "192.168.2.1" ,
378     ///     "dhcid" : "010203040A7F8E3D" ,
379     ///     "lease-expires-on" : "20130121132405",
380     ///     "lease-length" : 1300,
381     ///     "use-conflict-resolution": true
382     ///  }
383     /// @endcode
384     ///
385     /// Addition of an IPv6 address to both forward and reverse DNS zones:
386     ///
387     /// @code
388     ///  {
389     ///     "change-type" : 0,
390     ///     "forward-change" : true,
391     ///     "reverse-change" : true,
392     ///     "fqdn" : "someother.example.com.",
393     ///     "ip-address" : "2001::db8:1::2",
394     ///     "dhcid" : "010203040A7F8E3D" , "
395     ///     "lease-expires-on" : "20130121132405",
396     ///     "lease-length" : 27400,
397     ///     "use-conflict-resolution": true
398     ///   }
399     /// @endcode
400     ///
401     /// @param json is a string containing the JSON text
402     ///
403     /// @return a pointer to the new NameChangeRequest
404     ///
405     /// @throw NcrMessageError if an error occurs creating new request.
406     static NameChangeRequestPtr fromJSON(const std::string& json);
407 
408     /// @brief Instance method for marshalling the contents of the request
409     /// into a string of JSON text.
410     ///
411     /// @return a string containing the JSON rendition of the request
412     std::string toJSON() const;
413 
414     /// @brief Validates the content of a populated request.  This method is
415     /// used by both the full constructor and from-wire marshalling to ensure
416     /// that the request is content valid.  Currently it enforces the
417     /// following rules:
418     ///
419     ///  - FQDN must not be blank.
420     ///  - The IP address must be a valid address.
421     ///  - The DHCID must not be blank.
422     ///  - The lease expiration date must be a valid date/time.
423     ///  - That at least one of the two direction flags, forward change and
424     ///    reverse change is true.
425     ///
426     /// @todo This is an initial implementation which provides a minimal amount
427     /// of validation.  FQDN, DHCID, and IP Address members are all currently
428     /// strings, these may be replaced with richer classes.
429     ///
430     /// @throw NcrMessageError if the request content violates any
431     /// of the validation rules.
432     void validateContent();
433 
434     /// @brief Fetches the request change type.
435     ///
436     /// @return the change type
getChangeType()437     NameChangeType getChangeType() const {
438         return (change_type_);
439     }
440 
441     /// @brief Sets the change type to the given value.
442     ///
443     /// @param value is the NameChangeType value to assign to the request.
444     void setChangeType(const NameChangeType value);
445 
446     /// @brief Sets the change type to the value of the given Element.
447     ///
448     /// @param element is an integer Element containing the change type value.
449     ///
450     /// @throw NcrMessageError if the element is not an integer
451     /// Element or contains an invalid value.
452     void setChangeType(isc::data::ConstElementPtr element);
453 
454     /// @brief Checks forward change flag.
455     ///
456     /// @return a true if the forward change flag is true.
isForwardChange()457     bool isForwardChange() const {
458         return (forward_change_);
459     }
460 
461     /// @brief Sets the forward change flag to the given value.
462     ///
463     /// @param value contains the new value to assign to the forward change
464     /// flag
465     void setForwardChange(const bool value);
466 
467     /// @brief Sets the forward change flag to the value of the given Element.
468     ///
469     /// @param element is a boolean Element containing the forward change flag
470     /// value.
471     ///
472     /// @throw NcrMessageError if the element is not a boolean
473     /// Element
474     void setForwardChange(isc::data::ConstElementPtr element);
475 
476     /// @brief Checks reverse change flag.
477     ///
478     /// @return a true if the reverse change flag is true.
isReverseChange()479     bool isReverseChange() const {
480         return (reverse_change_);
481     }
482 
483     /// @brief Sets the reverse change flag to the given value.
484     ///
485     /// @param value contains the new value to assign to the reverse change
486     /// flag
487     void setReverseChange(const bool value);
488 
489     /// @brief Sets the reverse change flag to the value of the given Element.
490     ///
491     /// @param element is a boolean Element containing the reverse change flag
492     /// value.
493     ///
494     /// @throw NcrMessageError if the element is not a boolean
495     /// Element
496     void setReverseChange(isc::data::ConstElementPtr element);
497 
498     /// @brief Fetches the request FQDN
499     ///
500     /// @return a string containing the FQDN
getFqdn()501     const std::string getFqdn() const {
502         return (fqdn_);
503     }
504 
505     /// @brief Sets the FQDN to the given value.
506     ///
507     /// @param value contains the new value to assign to the FQDN
508     void setFqdn(const std::string& value);
509 
510     /// @brief Sets the FQDN to the value of the given Element.
511     ///
512     /// @param element is a string Element containing the FQDN
513     ///
514     /// @throw NcrMessageError if the element is not a string
515     /// Element
516     void setFqdn(isc::data::ConstElementPtr element);
517 
518     /// @brief Fetches the request IP address string.
519     ///
520     /// @return a string containing the IP address
getIpAddress()521     std::string getIpAddress() const {
522         return (ip_io_address_.toText());
523     }
524 
525     /// @brief Fetches the request IP address as an IOAddress.
526     ///
527     /// @return a asiolink::IOAddress containing the IP address
getIpIoAddress()528     const asiolink::IOAddress& getIpIoAddress() const {
529         return (ip_io_address_);
530     }
531 
532     /// @brief Returns true if the lease address is a IPv4 lease.
533     ///
534     /// @return boolean true if the lease address family is AF_INET.
isV4()535     bool isV4 () const {
536         return (ip_io_address_.isV4());
537     }
538 
539     /// @brief Returns true if the lease address is a IPv6 lease.
540     ///
541     /// @return boolean true if the lease address family is AF_INET6.
isV6()542     bool isV6 () const {
543         return (ip_io_address_.isV6());
544     }
545 
546     /// @brief Sets the IP address to the given value.
547     ///
548     /// @param value contains the new value to assign to the IP address
549     void setIpAddress(const std::string& value);
550 
551     /// @brief Sets the IP address to the value of the given Element.
552     ///
553     /// @param element is a string Element containing the IP address
554     ///
555     /// @throw NcrMessageError if the element is not a string
556     /// Element
557     void setIpAddress(isc::data::ConstElementPtr element);
558 
559     /// @brief Fetches the request DHCID
560     ///
561     /// @return a reference to the request's D2Dhcid
getDhcid()562     const D2Dhcid& getDhcid() const {
563         return (dhcid_);
564     }
565 
566     /// @brief Sets the DHCID based on the given string value.
567     ///
568     /// @param value is a string of hexadecimal digits. The format is simply
569     /// a contiguous stream of digits, with no delimiters. For example a string
570     /// containing "14A3" converts to a byte array containing:  0x14, 0xA3.
571     ///
572     /// @throw NcrMessageError if the input data contains non-digits
573     /// or there is an odd number of digits.
574     void setDhcid(const std::string& value);
575 
576     /// @brief Sets the DHCID based on the value of the given Element.
577     ///
578     /// @param element is a string Element containing the string of hexadecimal
579     /// digits. (See setDhcid(std::string&) above.)
580     ///
581     /// @throw NcrMessageError if the input data contains non-digits
582     /// or there is an odd number of digits.
583     void setDhcid(isc::data::ConstElementPtr element);
584 
585     /// @brief Fetches the request ID.
586     ///
587     /// @todo Currently this is the DHCID, in the future we may add a unique ID per
588     /// request to allow for correlating messages and events between the DHCP servers
589     /// and the D2 server.  If we do that we shall also need to add or update other
590     /// functions to: set the request ID, add it to the JSON strings, etc.  The
591     /// primary purpose of this function is to provide a consistent way to identify
592     /// requests for logging purposes.
593     ///
594     /// @return a string with the request's request ID (currently DHCID)
getRequestId()595     std::string getRequestId() const {
596         return (dhcid_.toStr());
597     }
598 
599     /// @brief Fetches the request lease expiration
600     ///
601     /// @return the lease expiration as the number of seconds since
602     /// the (00:00:00 January 1, 1970)
getLeaseExpiresOn()603     uint64_t getLeaseExpiresOn() const {
604         return (lease_expires_on_);
605     }
606 
607     /// @brief Fetches the request lease expiration as string.
608     ///
609     /// The format of the string returned is:
610     ///
611     ///    YYYYMMDDHHmmSS
612     ///
613     /// Example: 18:54:54 June 26, 2013 would be: 20130626185455
614     /// NOTE This is always UTC time.
615     ///
616     /// @return a ISO date-time string of the lease expiration.
617     std::string getLeaseExpiresOnStr() const;
618 
619     /// @brief Sets the lease expiration based on the given string.
620     ///
621     /// @param value is an date-time string from which to set the
622     /// lease expiration. The format of the input is:
623     ///
624     ///    YYYYMMDDHHmmSS
625     ///
626     /// Example: 18:54:54 June 26, 2013 would be: 20130626185455
627     /// NOTE This is always UTC time.
628     ///
629     /// @throw NcrMessageError if the ISO string is invalid.
630     void setLeaseExpiresOn(const std::string& value);
631 
632     /// @brief Sets the lease expiration based on the given Element.
633     ///
634     /// @param element is string Element containing a date-time string.
635     ///
636     /// @throw NcrMessageError if the element is not a string
637     /// Element, or if the element value is an invalid date-time string.
638     void setLeaseExpiresOn(isc::data::ConstElementPtr element);
639 
640     /// @brief Fetches the request lease length.
641     ///
642     /// @return an integer containing the lease length
getLeaseLength()643     uint32_t getLeaseLength() const {
644         return (lease_length_);
645     }
646 
647     /// @brief Sets the lease length to the given value.
648     ///
649     /// @param value contains the new value to assign to the lease length
650     void setLeaseLength(const uint32_t value);
651 
652     /// @brief Sets the lease length to the value of the given Element.
653     ///
654     /// @param element is a integer Element containing the lease length
655     ///
656     /// @throw NcrMessageError if the element is not a string
657     /// Element
658     void setLeaseLength(isc::data::ConstElementPtr element);
659 
660     /// @brief Checks if conflict resolution is enabled
661     ///
662     /// @return a true if the conflict resolution is enabled.
useConflictResolution()663     bool useConflictResolution() const {
664         return (conflict_resolution_);
665     }
666 
667     /// @brief Sets the conflict resolution flag to the given value.
668     ///
669     /// @param value contains the new value to assign to the conflict
670     /// resolution flag
671     void setConflictResolution(const bool value);
672 
673     /// @brief Sets the conflict resolution flag to the value of the given Element.
674     ///
675     /// @param element is a boolean Element containing the conflict resolution flag
676     /// value.
677     ///
678     /// @throw NcrMessageError if the element is not a boolean
679     /// Element
680     void setConflictResolution(isc::data::ConstElementPtr element);
681 
682     /// @brief Fetches the request status.
683     ///
684     /// @return the request status as a NameChangeStatus
getStatus()685     NameChangeStatus getStatus() const {
686         return (status_);
687     }
688 
689     /// @brief Sets the request status to the given value.
690     ///
691     /// @param value contains the new value to assign to request status
692     void setStatus(const NameChangeStatus value);
693 
694     /// @brief Given a name, finds and returns an element from a map of
695     /// elements.
696     ///
697     /// @param name is the name of the desired element
698     /// @param element_map is the map of elements to search
699     ///
700     /// @return a pointer to the element if located
701     /// @throw NcrMessageError if the element cannot be found within
702     /// the map
703     isc::data::ConstElementPtr getElement(const std::string& name,
704                                           const ElementMap& element_map) const;
705 
706     /// @brief Returns a text rendition of the contents of the request.
707     /// This method is primarily for logging purposes.
708     ///
709     /// @return a string containing the text.
710     std::string toText() const;
711 
712     bool operator == (const NameChangeRequest& b);
713     bool operator != (const NameChangeRequest& b);
714 
715 private:
716     /// @brief Denotes the type of this change as either an Add or a Remove.
717     NameChangeType change_type_;
718 
719     /// @brief Indicates if this change should sent to forward DNS servers.
720     bool forward_change_;
721 
722     /// @brief Indicates if this change should sent to reverse DNS servers.
723     bool reverse_change_;
724 
725     /// @brief The domain name whose DNS entry(ies) are to be updated.
726     /// @todo Currently, this is a std::string but may be replaced with
727     /// dns::Name which provides additional validation and domain name
728     /// manipulation.
729     std::string fqdn_;
730 
731     /// @brief The ip address leased to the FQDN as an IOAddress.
732     ///
733     /// The lease address is used in many places, sometimes as a string
734     /// and sometimes as an IOAddress.  To avoid converting back and forth
735     /// continually over the life span of an NCR, we do it once when the
736     /// ip address is actually set.
737     asiolink::IOAddress ip_io_address_;
738 
739     /// @brief The lease client's unique DHCID.
740     /// @todo Currently, this is uses D2Dhcid it but may be replaced with
741     /// dns::DHCID which provides additional validation.
742     D2Dhcid dhcid_;
743 
744     /// @brief The date-time the lease expires.
745     uint64_t lease_expires_on_;
746 
747     /// @brief The amount of time in seconds for which the lease is valid (TTL).
748     uint32_t lease_length_;
749 
750     /// @brief Indicates if conflict resolution is enabled.
751     bool conflict_resolution_;
752 
753     /// @brief The processing status of the request.  Used internally.
754     NameChangeStatus status_;
755 };
756 
757 
758 }; // end of isc::dhcp_ddns namespace
759 }; // end of isc namespace
760 
761 #endif
762