time_utilities.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. // Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #ifndef __TIME_UTILITIES_H
  15. #define __TIME_UTILITIES_H 1
  16. #include <string>
  17. #include <sys/types.h>
  18. #include <stdint.h>
  19. #include <exceptions/exceptions.h>
  20. //
  21. // Note: this helper module isn't specific to the DNS protocol per se.
  22. // We should probably move this to somewhere else, possibly in some common
  23. // utility area.
  24. //
  25. namespace isc {
  26. namespace util {
  27. ///
  28. /// \brief A standard DNS (or ISC) module exception that is thrown if
  29. /// a time conversion function encounters bad input
  30. ///
  31. class InvalidTime : public Exception {
  32. public:
  33. InvalidTime(const char* file, size_t line, const char* what) :
  34. isc::Exception(file, line, what) {}
  35. };
  36. namespace detail {
  37. /// Return the current time in seconds
  38. ///
  39. /// This function returns the "current" time in seconds from epoch
  40. /// (00:00:00 January 1, 1970) as a 64-bit signed integer. The return
  41. /// value can represent a point of time before epoch as a negative number.
  42. ///
  43. /// This function is provided to help test time conscious implementations
  44. /// such as DNSSEC and TSIG signatures. It is difficult to test them with
  45. /// an unusual or a specifically chosen "current" via system-provided
  46. /// library functions to get time. This function acts as a straightforward
  47. /// wrapper of such a library function, but provides test code with a hook
  48. /// to return an arbitrary time value: if \c isc::util::detail::gettimeFunction
  49. /// is set to a pointer of function that returns 64-bit signed integer,
  50. /// \c gettimeWrapper() calls that function instead of the system library.
  51. ///
  52. /// This hook variable is specifically intended for testing purposes, so,
  53. /// even if it's visible outside of this library, it's not even declared in a
  54. /// header file.
  55. ///
  56. /// If the implementation doesn't need to be tested with faked current time,
  57. /// it should simply use the system supplied library function instead of
  58. /// this one.
  59. int64_t gettimeWrapper();
  60. }
  61. ///
  62. /// \name DNSSEC time conversion functions.
  63. ///
  64. /// These functions convert between times represented in seconds (in integer)
  65. /// since epoch and those in the textual form used in the RRSIG records.
  66. /// For integers we provide both 32-bit and 64-bit versions.
  67. /// The RRSIG expiration and inception fields are both 32-bit unsigned
  68. /// integers, so 32-bit versions would be more useful for protocol operations.
  69. /// However, with 32-bit integers we need to take into account wrap-around
  70. /// points and compare values using the serial number arithmetic as specified
  71. /// in RFC4034, which would be more error prone. We therefore provide 64-bit
  72. /// versions, too.
  73. ///
  74. /// The timezone is always UTC for these functions.
  75. //@{
  76. /// Convert textual DNSSEC time to integer, 64-bit version.
  77. ///
  78. /// The textual form must only consist of digits and be in the form of
  79. /// YYYYMMDDHHmmSS, where:
  80. /// - YYYY must be between 1970 and 9999
  81. /// - MM must be between 01 and 12
  82. /// - DD must be between 01 and 31 and must be a valid day for the month
  83. /// represented in 'MM'. For example, if MM is 04, DD cannot be 31.
  84. /// DD can be 29 when MM is 02 only when YYYY is a leap year.
  85. /// - HH must be between 00 and 23
  86. /// - mm must be between 00 and 59
  87. /// - SS must be between 00 and 60
  88. ///
  89. /// For all fields the range includes the begin and end values. Note that
  90. /// 60 is allowed for 'SS', intending a leap second, although in real operation
  91. /// it's unlikely to be specified.
  92. ///
  93. /// If the given text is valid, this function converts it to an unsigned
  94. /// 64-bit number of seconds since epoch (1 January 1970 00:00:00) and returns
  95. /// the converted value. 64 bits are sufficient to represent all possible
  96. /// values for the valid format uniquely, so there is no overflow.
  97. ///
  98. /// \note RFC4034 also defines the textual form of an unsigned decimal integer
  99. /// for the corresponding time in seconds. This function doesn't support
  100. /// this form, and if given it throws an exception of class \c InvalidTime.
  101. ///
  102. /// \exception InvalidTime The given textual representation is invalid.
  103. ///
  104. /// \param time_txt Textual time in the form of YYYYMMDDHHmmSS
  105. /// \return Seconds since epoch corresponding to \c time_txt
  106. uint64_t
  107. timeFromText64(const std::string& time_txt);
  108. /// Convert textual DNSSEC time to integer, 32-bit version.
  109. ///
  110. /// This version is the same as \c timeFromText64() except that the return
  111. /// value is wrapped around to an unsigned 32-bit integer, simply dropping
  112. /// the upper 32 bits.
  113. uint32_t
  114. timeFromText32(const std::string& time_txt);
  115. /// Convert integral DNSSEC time to textual form, 64-bit version.
  116. ///
  117. /// This function takes an integer that would be seconds since epoch and
  118. /// converts it in the form of YYYYMMDDHHmmSS. For example, if \c value is
  119. /// 0, it returns "19700101000000". If the value corresponds to a point
  120. /// of time on and after year 10,000, which cannot be represented in the
  121. /// YYYY... form, an exception of class \c InvalidTime will be thrown.
  122. ///
  123. /// \exception InvalidTime The given time specifies on or after year 10,000.
  124. /// \exception Other A standard exception, if resource allocation for the
  125. /// returned text fails.
  126. ///
  127. /// \param value Seconds since epoch to be converted.
  128. /// \return Textual representation of \c value in the form of YYYYMMDDHHmmSS.
  129. std::string
  130. timeToText64(uint64_t value);
  131. /// Convert integral DNSSEC time to textual form, 32-bit version.
  132. ///
  133. /// This version is the same as \c timeToText64(), but the time value
  134. /// is expected to be the lower 32 bits of the full 64-bit value.
  135. /// These two will be different on and after a certain point of time
  136. /// in year 2106, so this function internally resolves the ambiguity
  137. /// using the current system time at the time of function call;
  138. /// it first identifies the range of [N*2^32 - 2^31, N*2^32 + 2^31)
  139. /// that contains the current time, and interprets \c value in the context
  140. /// of that range. It then applies the same process as \c timeToText64().
  141. ///
  142. /// There is one important exception in this processing, however.
  143. /// Until 19 Jan 2038 03:14:08 (2^31 seconds since epoch), this range
  144. /// would contain time before epoch. In order to ensure the returned
  145. /// value is also a valid input to \c timeFromText, this function uses
  146. /// a special range [0, 2^32) until that time. As a result, all upper
  147. /// half of the 32-bit values are treated as a future time. For example,
  148. /// 2^32-1 (the highest value in 32-bit unsigned integers) will be converted
  149. /// to "21060207062815", instead of "19691231235959".
  150. std::string
  151. timeToText32(const uint32_t value);
  152. //@}
  153. }
  154. }
  155. #endif // __DNSSECTIME_H
  156. // Local Variables:
  157. // mode: c++
  158. // End: