Kea 2.7.1
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...
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
The RRTTL class encapsulates TTLs used in DNS resource records.
Definition rrttl.h:51
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.