123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- // Copyright (C) 2010 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.
- // $Id$
- #include <config.h>
- #include <stdint.h>
- #include <cassert>
- #include <boost/lexical_cast.hpp>
- #include <exceptions/exceptions.h>
- #include <dns/edns.h>
- #include <dns/exceptions.h>
- #include <dns/message.h>
- #include <dns/messagerenderer.h>
- #include <dns/name.h>
- #include <dns/rdata.h>
- #include <dns/rdataclass.h>
- #include <dns/rrclass.h>
- #include <dns/rrttl.h>
- #include <dns/rrtype.h>
- using namespace std;
- using namespace boost;
- using namespace isc::dns::rdata;
- namespace isc {
- namespace dns {
- namespace {
- // This diagram shows the wire-format representation of the TTL field of
- // OPT RR and its relationship with implementation specific parameters.
- //
- // 0 7 15 31
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | EXTENDED-RCODE| VERSION |D| Z |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // <= VERSION_SHIFT (16 bits)
- // <= EXTRCODE_SHIFT (24 bits)
- //EXTFLAG_DO:0 0 0 ....................... 0 1 0 0 0 0.....................0
- //VER_MASK: 0 0 0 ........0 1 1 1 1 1 1 1 1 0 0 ..........................0
- const unsigned int VERSION_SHIFT = 16;
- const unsigned int EXTRCODE_SHIFT = 24;
- const uint32_t VERSION_MASK = 0x00ff0000;
- const uint32_t EXTFLAG_DO = 0x00008000;
- }
- EDNS::EDNS(const uint8_t version) :
- version_(version),
- udp_size_(Message::DEFAULT_MAX_UDPSIZE),
- dnssec_aware_(false)
- {
- if (version_ > SUPPORTED_VERSION) {
- isc_throw(isc::InvalidParameter,
- "failed to construct EDNS: unsupported version: " <<
- static_cast<unsigned int>(version_));
- }
- }
- EDNS::EDNS(const Name& name, const RRClass& rrclass, const RRType& rrtype,
- const RRTTL& ttl, const Rdata& rdata UNUSED_PARAM) :
- version_((ttl.getValue() & VERSION_MASK) >> VERSION_SHIFT)
- {
- if (rrtype != RRType::OPT()) {
- isc_throw(isc::InvalidParameter,
- "EDNS is being created with incompatible RR type: "
- << rrtype);
- }
-
- if (version_ > EDNS::SUPPORTED_VERSION) {
- isc_throw(DNSMessageBADVERS, "unsupported EDNS version: " <<
- static_cast<unsigned int>(version_));
- }
- if (name != Name::ROOT_NAME()) {
- isc_throw(DNSMessageFORMERR, "invalid owner name for EDNS OPT RR: " <<
- name);
- }
- dnssec_aware_ = ((ttl.getValue() & EXTFLAG_DO) != 0);
- udp_size_ = rrclass.getCode();
- }
- string
- EDNS::toText() const {
- string ret = "; EDNS: version: ";
- ret += lexical_cast<string>(static_cast<int>(getVersion()));
- ret += ", flags:";
- if (getDNSSECAwareness()) {
- ret += " do";
- }
- ret += "; udp: " + lexical_cast<string>(getUDPSize()) + "\n";
- return (ret);
- }
- template <typename Output>
- int
- EDNS::toWire(Output& output, const uint8_t extended_rcode) const {
- // Render EDNS OPT RR
- uint32_t extrcode_flags = extended_rcode << EXTRCODE_SHIFT;
- extrcode_flags |= (version_ << VERSION_SHIFT) & VERSION_MASK;
- if (dnssec_aware_) {
- extrcode_flags |= EXTFLAG_DO;
- }
- // Construct an RRset corresponding to the EDNS.
- // We don't support any options for now, so the OPT RR can be empty.
- RRsetPtr edns_rrset(new RRset(Name::ROOT_NAME(), RRClass(udp_size_),
- RRType::OPT(), RRTTL(extrcode_flags)));
- edns_rrset->addRdata(ConstRdataPtr(new generic::OPT()));
- edns_rrset->toWire(output);
- return (1);
- }
- unsigned int
- EDNS::toWire(MessageRenderer& renderer, const uint8_t extended_rcode) const {
- // If adding the OPT RR would exceed the size limit, don't do it.
- // 11 = len(".") + type(2byte) + class(2byte) + TTL(4byte) + RDLEN(2byte)
- // (RDATA is empty in this simple implementation)
- if (renderer.getLength() + 11 > renderer.getLengthLimit()) {
- return (0);
- }
- return (toWire<MessageRenderer>(renderer, extended_rcode));
- }
- unsigned int
- EDNS::toWire(OutputBuffer& buffer, const uint8_t extended_rcode) const {
- return (toWire<OutputBuffer>(buffer, extended_rcode));
- }
- EDNS*
- createEDNSFromRR(const Name& name, const RRClass& rrclass,
- const RRType& rrtype, const RRTTL& ttl,
- const Rdata& rdata UNUSED_PARAM,
- uint8_t& extended_rcode)
- {
- // Create a new EDNS object first for exception guarantee.
- EDNS* edns = new EDNS(name, rrclass, rrtype, ttl, rdata);
- // At this point we can update extended_rcode safely.
- extended_rcode = ttl.getValue() >> EXTRCODE_SHIFT;
- return (edns);
- }
- ostream&
- operator<<(std::ostream& os, const EDNS& edns) {
- os << edns.toText();
- return (os);
- }
- } // end of namespace dns
- } // end of namespace isc
|