|
@@ -24,6 +24,8 @@
|
|
#include <stdint.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <string.h>
|
|
|
|
|
|
|
|
+#include <cerrno>
|
|
|
|
+#include <cstring>
|
|
#include <string>
|
|
#include <string>
|
|
|
|
|
|
#include <arpa/inet.h> // XXX: for inet_pton/ntop(), not exist in C++ standards
|
|
#include <arpa/inet.h> // XXX: for inet_pton/ntop(), not exist in C++ standards
|
|
@@ -35,24 +37,70 @@ using namespace isc::util;
|
|
// BEGIN_ISC_NAMESPACE
|
|
// BEGIN_ISC_NAMESPACE
|
|
// BEGIN_RDATA_NAMESPACE
|
|
// BEGIN_RDATA_NAMESPACE
|
|
|
|
|
|
-AAAA::AAAA(const std::string& addrstr) {
|
|
|
|
- if (inet_pton(AF_INET6, addrstr.c_str(), &addr_) != 1) {
|
|
|
|
- isc_throw(InvalidRdataText,
|
|
|
|
- "IN/AAAA RDATA construction from text failed: "
|
|
|
|
- "Address cannot be converted: " << addrstr);
|
|
|
|
|
|
+namespace {
|
|
|
|
+void
|
|
|
|
+convertToIPv6Addr(const char* src, size_t src_len, void* dst) {
|
|
|
|
+ if (src_len != strlen(src)) {
|
|
|
|
+ isc_throw(InvalidRdataText, "Bad IN/AAAA RDATA text: "
|
|
|
|
+ "extra character: '" << src << "'");
|
|
}
|
|
}
|
|
|
|
+ const int result = inet_pton(AF_INET6, src, dst);
|
|
|
|
+ if (result == 0) {
|
|
|
|
+ isc_throw(InvalidRdataText, "Bad IN/AAAA RDATA text: '" << src << "'");
|
|
|
|
+ } else if (result < 0) {
|
|
|
|
+ isc_throw(isc::Unexpected,
|
|
|
|
+ "Unexpected failure in parsing IN/AAAA RDATA text: '"
|
|
|
|
+ << src << "': " << std::strerror(errno));
|
|
|
|
+ }
|
|
|
|
+}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// \brief Constructor from string.
|
|
|
|
+///
|
|
|
|
+/// The given string must be a valid textual representation of an IPv6
|
|
|
|
+/// address as specified in RFC1886.
|
|
|
|
+///
|
|
|
|
+/// No extra character should be contained in \c addrstr other than the
|
|
|
|
+/// textual address. These include spaces and the nul character.
|
|
|
|
+///
|
|
|
|
+/// \throw InvalidRdata The text extracted by the lexer isn't recognized as
|
|
|
|
+/// a valid IPv6 address.
|
|
|
|
+/// \throw Unexpected Unexpected system error in conversion (this should be
|
|
|
|
+/// very rare).
|
|
|
|
+///
|
|
|
|
+/// \param addrstr Textual representation of IPv6 address to be used as the
|
|
|
|
+/// RDATA.
|
|
|
|
+AAAA::AAAA(const std::string& addrstr) {
|
|
|
|
+ convertToIPv6Addr(addrstr.c_str(), addrstr.size(), addr_);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// \brief Constructor with a context of MasterLexer.
|
|
|
|
+///
|
|
|
|
+/// The \c lexer should point to the beginning of valid textual representation
|
|
|
|
+/// of a class IN AAAA RDATA.
|
|
|
|
+///
|
|
|
|
+/// The acceptable form of the textual address is generally the same as the
|
|
|
|
+/// string version of the constructor, but this version is slightly more
|
|
|
|
+/// flexible. See the similar constructor of \c in::A class; the same
|
|
|
|
+/// notes apply here.
|
|
|
|
+///
|
|
|
|
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
|
|
|
|
+/// \throw InvalidRdata The text extracted by the lexer isn't recognized as
|
|
|
|
+/// a valid IPv6 address.
|
|
|
|
+/// \throw Unexpected Unexpected system error in conversion (this should be
|
|
|
|
+/// very rare).
|
|
|
|
+///
|
|
|
|
+/// \param lexer A \c MasterLexer object parsing a master file for the
|
|
|
|
+/// RDATA to be created
|
|
AAAA::AAAA(MasterLexer& lexer, const Name*,
|
|
AAAA::AAAA(MasterLexer& lexer, const Name*,
|
|
MasterLoader::Options, MasterLoaderCallbacks&)
|
|
MasterLoader::Options, MasterLoaderCallbacks&)
|
|
{
|
|
{
|
|
const MasterToken& token = lexer.getNextToken(MasterToken::STRING);
|
|
const MasterToken& token = lexer.getNextToken(MasterToken::STRING);
|
|
- if (inet_pton(AF_INET6, token.getStringRegion().beg, &addr_) != 1) {
|
|
|
|
- isc_throw(InvalidRdataText, "Failed to convert '"
|
|
|
|
- << token.getString() << "' to IN/AAAA RDATA");
|
|
|
|
- }
|
|
|
|
|
|
+ convertToIPv6Addr(token.getStringRegion().beg, token.getStringRegion().len,
|
|
|
|
+ addr_);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// \brief Copy constructor.
|
|
AAAA::AAAA(InputBuffer& buffer, size_t rdata_len) {
|
|
AAAA::AAAA(InputBuffer& buffer, size_t rdata_len) {
|
|
if (rdata_len != sizeof(addr_)) {
|
|
if (rdata_len != sizeof(addr_)) {
|
|
isc_throw(DNSMessageFORMERR,
|
|
isc_throw(DNSMessageFORMERR,
|
|
@@ -72,6 +120,7 @@ AAAA::AAAA(const AAAA& other) : Rdata() {
|
|
memcpy(addr_, other.addr_, sizeof(addr_));
|
|
memcpy(addr_, other.addr_, sizeof(addr_));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// \brief Return a textual form of the underlying IPv6 address of the RDATA.
|
|
void
|
|
void
|
|
AAAA::toWire(OutputBuffer& buffer) const {
|
|
AAAA::toWire(OutputBuffer& buffer) const {
|
|
buffer.writeData(&addr_, sizeof(addr_));
|
|
buffer.writeData(&addr_, sizeof(addr_));
|
|
@@ -86,7 +135,8 @@ string
|
|
AAAA::toText() const {
|
|
AAAA::toText() const {
|
|
char addr_string[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
|
|
char addr_string[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
|
|
|
|
|
|
- if (inet_ntop(AF_INET6, &addr_, addr_string, sizeof(addr_string)) == NULL) {
|
|
|
|
|
|
+ if (inet_ntop(AF_INET6, &addr_, addr_string, sizeof(addr_string))
|
|
|
|
+ == NULL) {
|
|
isc_throw(Unexpected,
|
|
isc_throw(Unexpected,
|
|
"Failed to convert IN/AAAA RDATA to textual IPv6 address");
|
|
"Failed to convert IN/AAAA RDATA to textual IPv6 address");
|
|
}
|
|
}
|
|
@@ -94,6 +144,9 @@ AAAA::toText() const {
|
|
return (string(addr_string));
|
|
return (string(addr_string));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// \brief Compare two in::AAAA RDATAs.
|
|
|
|
+///
|
|
|
|
+/// In effect, it compares the two RDATA as an unsigned 128-bit integer.
|
|
int
|
|
int
|
|
AAAA::compare(const Rdata& other) const {
|
|
AAAA::compare(const Rdata& other) const {
|
|
const AAAA& other_a = dynamic_cast<const AAAA&>(other);
|
|
const AAAA& other_a = dynamic_cast<const AAAA&>(other);
|