Kea  2.1.7-git
edns.cc
Go to the documentation of this file.
1 // Copyright (C) 2010-2015 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 #include <config.h>
8 
9 #include <stdint.h>
10 
11 #include <cassert>
12 
13 #include <boost/lexical_cast.hpp>
14 
15 #include <exceptions/exceptions.h>
16 
17 #include <dns/edns.h>
18 #include <dns/exceptions.h>
19 #include <dns/message.h>
20 #include <dns/messagerenderer.h>
21 #include <dns/name.h>
22 #include <dns/rdata.h>
23 #include <dns/rdataclass.h>
24 #include <dns/rrclass.h>
25 #include <dns/rrttl.h>
26 #include <dns/rrtype.h>
27 
28 using namespace std;
29 using boost::lexical_cast;
30 using namespace isc::dns::rdata;
31 using namespace isc::util;
32 
33 namespace isc {
34 namespace dns {
35 
36 namespace {
37 // This diagram shows the wire-format representation of the TTL field of
38 // OPT RR and its relationship with implementation specific parameters.
39 //
40 // 0 7 15 31
41 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42 // | EXTENDED-RCODE| VERSION |D| Z |
43 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44 // <= VERSION_SHIFT (16 bits)
45 // <= EXTRCODE_SHIFT (24 bits)
46 //EXTFLAG_DO:0 0 0 ....................... 0 1 0 0 0 0.....................0
47 //VER_MASK: 0 0 0 ........0 1 1 1 1 1 1 1 1 0 0 ..........................0
48 
49 const unsigned int VERSION_SHIFT = 16;
50 const unsigned int EXTRCODE_SHIFT = 24;
51 const uint32_t VERSION_MASK = 0x00ff0000;
52 const uint32_t EXTFLAG_DO = 0x00008000;
53 }
54 
55 EDNS::EDNS(const uint8_t version) :
56  version_(version),
57  udp_size_(Message::DEFAULT_MAX_UDPSIZE),
58  dnssec_aware_(false)
59 {
60  if (version_ > SUPPORTED_VERSION) {
62  "failed to construct EDNS: unsupported version: " <<
63  static_cast<unsigned int>(version_));
64  }
65 }
66 
67 EDNS::EDNS(const Name& name, const RRClass& rrclass, const RRType& rrtype,
68  const RRTTL& ttl, const Rdata&) :
69  version_((ttl.getValue() & VERSION_MASK) >> VERSION_SHIFT)
70 {
71  if (rrtype != RRType::OPT()) {
73  "EDNS is being created with incompatible RR type: "
74  << rrtype);
75  }
76 
77  if (version_ > EDNS::SUPPORTED_VERSION) {
78  isc_throw(DNSMessageBADVERS, "unsupported EDNS version: " <<
79  static_cast<unsigned int>(version_));
80  }
81 
82  if (name != Name::ROOT_NAME()) {
83  isc_throw(DNSMessageFORMERR, "invalid owner name for EDNS OPT RR: " <<
84  name);
85  }
86 
87  dnssec_aware_ = ((ttl.getValue() & EXTFLAG_DO) != 0);
88  udp_size_ = rrclass.getCode();
89 }
90 
91 string
92 EDNS::toText() const {
93  string ret = "; EDNS: version: ";
94 
95  ret += lexical_cast<string>(static_cast<int>(getVersion()));
96  ret += ", flags:";
97  if (getDNSSECAwareness()) {
98  ret += " do";
99  }
100  ret += "; udp: " + lexical_cast<string>(getUDPSize()) + "\n";
101 
102  return (ret);
103 }
104 
105 namespace {
108 template <typename Output>
109 int
110 toWireCommon(Output& output, const uint8_t version,
111  const uint16_t udp_size, const bool dnssec_aware,
112  const uint8_t extended_rcode)
113 {
114  // Render EDNS OPT RR
115  uint32_t extrcode_flags = extended_rcode << EXTRCODE_SHIFT;
116  extrcode_flags |= (version << VERSION_SHIFT) & VERSION_MASK;
117  if (dnssec_aware) {
118  extrcode_flags |= EXTFLAG_DO;
119  }
120 
121  // Construct an RRset corresponding to the EDNS.
122  // We don't support any options for now, so the OPT RR can be empty.
123  RRsetPtr edns_rrset(new RRset(Name::ROOT_NAME(), RRClass(udp_size),
124  RRType::OPT(), RRTTL(extrcode_flags)));
125  edns_rrset->addRdata(ConstRdataPtr(new generic::OPT()));
126 
127  edns_rrset->toWire(output);
128 
129  return (1);
130 }
131 }
132 
133 unsigned int
135  const uint8_t extended_rcode) const
136 {
137  // If adding the OPT RR would exceed the size limit, don't do it.
138  // 11 = len(".") + type(2byte) + class(2byte) + TTL(4byte) + RDLEN(2byte)
139  // (RDATA is empty in this simple implementation)
140  if (renderer.getLength() + 11 > renderer.getLengthLimit()) {
141  return (0);
142  }
143 
144  return (toWireCommon(renderer, version_, udp_size_, dnssec_aware_,
145  extended_rcode));
146 }
147 
148 unsigned int
150  const uint8_t extended_rcode) const
151 {
152  return (toWireCommon(buffer, version_, udp_size_, dnssec_aware_,
153  extended_rcode));
154 }
155 
156 EDNS*
157 createEDNSFromRR(const Name& name, const RRClass& rrclass,
158  const RRType& rrtype, const RRTTL& ttl,
159  const Rdata& rdata,
160  uint8_t& extended_rcode)
161 {
162  // Create a new EDNS object first for exception guarantee.
163  EDNS* edns = new EDNS(name, rrclass, rrtype, ttl, rdata);
164 
165  // At this point we can update extended_rcode safely.
166  extended_rcode = ttl.getValue() >> EXTRCODE_SHIFT;
167 
168  return (edns);
169 }
170 
171 ostream&
172 operator<<(std::ostream& os, const EDNS& edns) {
173  os << edns.toText();
174  return (os);
175 }
176 
177 } // end of namespace dns
178 } // end of namespace isc
The Name class encapsulates DNS names.
Definition: name.h:223
ostream & operator<<(std::ostream &os, const EDNS &edns)
Insert the EDNS as a string into stream.
Definition: edns.cc:172
std::string toText() const
Convert the EDNS to a string.
Definition: edns.cc:92
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
boost::shared_ptr< const Rdata > ConstRdataPtr
Definition: rdata.h:72
unsigned int toWire(AbstractMessageRenderer &renderer, const uint8_t extended_rcode) const
Render the EDNS in the wire format.
Definition: edns.cc:134
The Rdata class is an abstract base class that provides a set of common interfaces to manipulate conc...
Definition: rdata.h:123
STL namespace.
uint32_t getValue() const
Returns the TTL value as a 32-bit unsigned integer.
Definition: rrttl.h:176
uint16_t getCode() const
Returns the RR class code as a 16-bit unsigned integer.
Definition: rrclass.h:238
static const RRType & OPT()
Definition: rrtype.h:437
The Message class encapsulates a standard DNS message.
Definition: message.h:143
The RRClass class encapsulates DNS resource record classes.
Definition: rrclass.h:98
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition: edns.h:19
The AbstractMessageRenderer class is an abstract base class that provides common interfaces for rende...
uint8_t getVersion() const
Returns the version of EDNS.
Definition: edns.h:225
EDNS(const uint8_t version=SUPPORTED_VERSION)
Constructor with the EDNS version.
Definition: edns.cc:55
bool getDNSSECAwareness() const
Returns whether the message sender is DNSSEC aware.
Definition: edns.h:253
static const Name & ROOT_NAME()
Root name (i.e. ".").
Definition: name.h:738
The RRTTL class encapsulates TTLs used in DNS resource records.
Definition: rrttl.h:55
The EDNS class represents the EDNS OPT RR defined in RFC2671.
Definition: edns.h:123
int version()
returns Kea hooks version.
EDNS * createEDNSFromRR(const Name &name, const RRClass &rrclass, const RRType &rrtype, const RRTTL &ttl, const Rdata &rdata, uint8_t &extended_rcode)
Create a new EDNS object from a set of RR parameters, also providing the extended RCODE value...
Definition: edns.cc:157
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Definition: buffer.h:294
Defines the logger used by the top-level component of kea-lfc.
static const uint8_t SUPPORTED_VERSION
The highest EDNS version this implementation supports.
Definition: edns.h:351
The RRset class is a concrete derived class of BasicRRset which contains a pointer to an additional R...
Definition: rrset.h:847
The RRType class encapsulates DNS resource record types.
Definition: rrtype.h:106
size_t getLength() const
Return the length of data written in the internal buffer.
boost::shared_ptr< AbstractRRset > RRsetPtr
A pointer-like type pointing to an RRset object.
Definition: rrset.h:47
virtual size_t getLengthLimit() const =0
Return the maximum length of rendered data that can fit in the corresponding DNS message without trun...
uint16_t getUDPSize() const
Returns the maximum payload size of UDP messages for the sender of the message containing this EDNS...
Definition: edns.h:231