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