|
@@ -21,22 +21,87 @@
|
|
#include <dns/messagerenderer.h>
|
|
#include <dns/messagerenderer.h>
|
|
#include <dns/rrttl.h>
|
|
#include <dns/rrttl.h>
|
|
|
|
|
|
|
|
+#include <boost/lexical_cast.hpp>
|
|
|
|
+#include <algorithm>
|
|
|
|
+#include <cctype>
|
|
|
|
+
|
|
using namespace std;
|
|
using namespace std;
|
|
using namespace isc::dns;
|
|
using namespace isc::dns;
|
|
using namespace isc::util;
|
|
using namespace isc::util;
|
|
|
|
|
|
|
|
+namespace {
|
|
|
|
+
|
|
|
|
+// We wrap the C isalpha, because it seems to be overloaded with something.
|
|
|
|
+// Then the find_if doesn't work.
|
|
|
|
+bool
|
|
|
|
+myIsalpha(char c) {
|
|
|
|
+ return (isalpha(c));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// The conversion of units to their size
|
|
|
|
+struct Unit {
|
|
|
|
+ char unit;
|
|
|
|
+ uint32_t multiply;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+Unit units[] = {
|
|
|
|
+ { 'S', 1 },
|
|
|
|
+ { 'M', 60 },
|
|
|
|
+ { 'H', 60 * 60 },
|
|
|
|
+ { 'D', 24 * 60 * 60 },
|
|
|
|
+ { 'W', 7 * 24 * 60 * 60 }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
namespace isc {
|
|
namespace isc {
|
|
namespace dns {
|
|
namespace dns {
|
|
|
|
|
|
RRTTL::RRTTL(const std::string& ttlstr) {
|
|
RRTTL::RRTTL(const std::string& ttlstr) {
|
|
- // Some systems (at least gcc-4.4) flow negative values over into
|
|
|
|
- // unsigned integer, where older systems failed to parse. We want
|
|
|
|
- // that failure here, so we extract into int64 and check the value
|
|
|
|
- int64_t val;
|
|
|
|
-
|
|
|
|
- istringstream iss(ttlstr);
|
|
|
|
- iss >> dec >> val;
|
|
|
|
- if (iss.rdstate() == ios::eofbit && val >= 0 && val <= 0xffffffff) {
|
|
|
|
|
|
+ int64_t val = 0;
|
|
|
|
+
|
|
|
|
+ const string::const_iterator end = ttlstr.end();
|
|
|
|
+ string::const_iterator pos = ttlstr.begin();
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ while (pos != end) {
|
|
|
|
+ // Find the first unit, if there's any.
|
|
|
|
+ const string::const_iterator unit = find_if(pos, end,
|
|
|
|
+ myIsalpha);
|
|
|
|
+ // Default multiplication if no unit.
|
|
|
|
+ uint32_t multiply = 1;
|
|
|
|
+ if (unit != end) {
|
|
|
|
+ // Find the unit and get the size.
|
|
|
|
+ bool found = false;
|
|
|
|
+ for (size_t i = 0; i < sizeof units / sizeof *units; ++i) {
|
|
|
|
+ if (toupper(*unit) == units[i].unit) {
|
|
|
|
+ found = true;
|
|
|
|
+ multiply = units[i].multiply;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (!found) {
|
|
|
|
+ isc_throw(InvalidRRTTL, "Unknown unit used: " << *unit);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // Now extract the number, defaut to 1 if there's no digit
|
|
|
|
+ const int64_t value = (unit == pos) ? 1 :
|
|
|
|
+ boost::lexical_cast<int64_t>(string(pos,
|
|
|
|
+ unit));
|
|
|
|
+ // Add what we found
|
|
|
|
+ val += multiply * value;
|
|
|
|
+ // Move to after the unit (if any). But make sure not to increment
|
|
|
|
+ // past end, which is, strictly speaking, illegal.
|
|
|
|
+ pos = unit;
|
|
|
|
+ if (pos != end) {
|
|
|
|
+ ++pos;
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ } catch (const boost::bad_lexical_cast&) {
|
|
|
|
+ isc_throw(InvalidRRTTL, "invalid TTL");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (val >= 0 && val <= 0xffffffff) {
|
|
ttlval_ = static_cast<uint32_t>(val);
|
|
ttlval_ = static_cast<uint32_t>(val);
|
|
} else {
|
|
} else {
|
|
isc_throw(InvalidRRTTL, "invalid TTL");
|
|
isc_throw(InvalidRRTTL, "invalid TTL");
|