]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/dnspacket.cc
Better (actual) fix for leak reported by Coverity.
[thirdparty/pdns.git] / pdns / dnspacket.cc
CommitLineData
12c86877 1/*
12471842
PL
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
870a0fe4
AT
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
12c86877
BH
25#include "utility.hh"
26#include <cstdio>
12c86877
BH
27#include <cstdlib>
28#include <sys/types.h>
12c86877 29#include <iostream>
12c86877 30#include <string>
b8e0f341 31#include <boost/tokenizer.hpp>
14155043 32#include <boost/functional/hash.hpp>
b8e0f341 33#include <boost/algorithm/string.hpp>
e0db069a 34#include <openssl/hmac.h>
12c86877 35#include <algorithm>
fa8fd4d2 36
9c92ad4b 37#include "dnsseckeeper.hh"
12c86877
BH
38#include "dns.hh"
39#include "dnsbackend.hh"
ea892f70 40#include "ednsoptions.hh"
5c409fa2 41#include "pdnsexception.hh"
12c86877
BH
42#include "dnspacket.hh"
43#include "logger.hh"
44#include "arguments.hh"
b8e0f341
BH
45#include "dnswriter.hh"
46#include "dnsparser.hh"
7f7b8d55 47#include "dnsrecords.hh"
af184eb0 48#include "dnssecinfra.hh"
20665beb 49#include "base64.hh"
af7d3ea6 50#include "ednssubnet.hh"
7f9ac49b 51#include "gss_context.hh"
d2116c15 52#include "dns_random.hh"
bbec1961 53#include "shuffle.hh"
af7d3ea6
BH
54
55bool DNSPacket::s_doEDNSSubnetProcessing;
15668f6a 56uint16_t DNSPacket::s_udpTruncationThreshold;
f15149ab 57
eace2c24 58DNSPacket::DNSPacket(bool isQuery): d_isQuery(isQuery)
12c86877 59{
b8874063 60 memset(&d, 0, sizeof(d));
12c86877
BH
61}
62
78bcb858 63const string& DNSPacket::getString()
b8e0f341
BH
64{
65 if(!d_wrapped)
e02d0a59 66 wrapup();
b8e0f341 67
78bcb858 68 return d_rawpacket;
b8e0f341
BH
69}
70
b9b4da23 71ComboAddress DNSPacket::getRemote() const
12c86877 72{
b9b4da23 73 return d_remote;
12c86877
BH
74}
75
092f210a 76uint16_t DNSPacket::getRemotePort() const
288f4aa9 77{
d06799d4 78 return d_remote.sin4.sin_port;
288f4aa9 79}
12c86877 80
12c86877
BH
81void DNSPacket::setRcode(int v)
82{
83 d.rcode=v;
84}
85
86void DNSPacket::setAnswer(bool b)
87{
88 if(b) {
78bcb858 89 d_rawpacket.assign(12,(char)0);
12c86877
BH
90 memset((void *)&d,0,sizeof(d));
91
92 d.qr=b;
93 }
94}
95
96void DNSPacket::setA(bool b)
97{
98 d.aa=b;
99}
100
092f210a 101void DNSPacket::setID(uint16_t id)
12c86877
BH
102{
103 d.id=id;
104}
105
106void DNSPacket::setRA(bool b)
107{
108 d.ra=b;
109}
110
111void DNSPacket::setRD(bool b)
112{
113 d.rd=b;
114}
115
092f210a 116void DNSPacket::setOpcode(uint16_t opcode)
12c86877
BH
117{
118 d.opcode=opcode;
119}
120
77235722
BH
121void DNSPacket::clearRecords()
122{
9c92ad4b 123 d_rrs.clear();
55b524a0 124 d_dedup.clear();
77235722
BH
125}
126
9bbcf03a 127void DNSPacket::addRecord(DNSZoneRecord&& rr)
12c86877 128{
a4a67412 129 // this removes duplicates from the packet.
130 // in case we are not compressing for AXFR, no such checking is performed!
55b524a0 131
3d00ef90 132 if(d_compress) {
a4a67412 133 std::string ser = const_cast<DNSZoneRecord&>(rr).dr.d_content->serialize(rr.dr.d_name);
9d40dd1f 134 auto hash = boost::hash< std::pair<DNSName, std::string> >()({rr.dr.d_name, ser});
135 if(d_dedup.count(hash)) { // might be a dup
55b524a0 136 for(auto i=d_rrs.begin();i!=d_rrs.end();++i) {
137 if(rr.dr == i->dr) // XXX SUPER SLOW
4957a608 138 return;
55b524a0 139 }
90ba52e0 140 }
9d40dd1f 141 d_dedup.insert(hash);
a4a67412 142 }
90ba52e0 143
9bbcf03a 144 d_rrs.push_back(std::move(rr));
12c86877
BH
145}
146
90ba52e0 147vector<DNSZoneRecord*> DNSPacket::getAPRecords()
12c86877 148{
90ba52e0 149 vector<DNSZoneRecord*> arrs;
12c86877 150
90ba52e0 151 for(vector<DNSZoneRecord>::iterator i=d_rrs.begin();
9c92ad4b 152 i!=d_rrs.end();
12c86877
BH
153 ++i)
154 {
90ba52e0 155 if(i->dr.d_place!=DNSResourceRecord::ADDITIONAL &&
156 (i->dr.d_type==QType::MX ||
157 i->dr.d_type==QType::NS ||
158 i->dr.d_type==QType::SRV))
4957a608
BH
159 {
160 arrs.push_back(&*i);
161 }
12c86877 162 }
12c86877 163 return arrs;
12c86877
BH
164}
165
90ba52e0 166vector<DNSZoneRecord*> DNSPacket::getAnswerRecords()
9c92ad4b 167{
90ba52e0 168 vector<DNSZoneRecord*> arrs;
9c92ad4b 169
90ba52e0 170 for(vector<DNSZoneRecord>::iterator i=d_rrs.begin();
9c92ad4b
BH
171 i!=d_rrs.end();
172 ++i)
173 {
90ba52e0 174 if(i->dr.d_place!=DNSResourceRecord::ADDITIONAL)
232f0877 175 arrs.push_back(&*i);
9c92ad4b
BH
176 }
177 return arrs;
178}
179
180
12c86877
BH
181void DNSPacket::setCompress(bool compress)
182{
183 d_compress=compress;
78bcb858 184 d_rawpacket.reserve(65000);
9c92ad4b 185 d_rrs.reserve(200);
12c86877
BH
186}
187
c2826d2e 188bool DNSPacket::couldBeCached() const
7f7b8d55 189{
ea892f70 190 return !d_wantsnsid && qclass==QClass::IN && !d_havetsig;
7f7b8d55 191}
20665beb 192
b35ea8ec
PD
193unsigned int DNSPacket::getMinTTL()
194{
195 unsigned int minttl = UINT_MAX;
90ba52e0 196 for(const DNSZoneRecord& rr : d_rrs) {
197 if (rr.dr.d_ttl < minttl)
198 minttl = rr.dr.d_ttl;
b35ea8ec
PD
199 }
200
201 return minttl;
202}
203
9951e2d0
KM
204bool DNSPacket::isEmpty()
205{
206 return (d_rrs.empty());
207}
208
12c86877
BH
209/** Must be called before attempting to access getData(). This function stuffs all resource
210 * records found in rrs into the data buffer. It also frees resource records queued for us.
211 */
e02d0a59 212void DNSPacket::wrapup()
12c86877
BH
213{
214 if(d_wrapped) {
215 return;
216 }
51a3a4d4 217
90ba52e0 218 DNSZoneRecord rr;
219 vector<DNSZoneRecord>::iterator pos;
12c86877 220
12c86877
BH
221 // we now need to order rrs so that the different sections come at the right place
222 // we want a stable sort, based on the d_place field
223
90ba52e0 224 stable_sort(d_rrs.begin(),d_rrs.end(), [](const DNSZoneRecord& a, const DNSZoneRecord& b) {
225 return a.dr.d_place < b.dr.d_place;
226 });
4c5d6da9 227 static bool mustNotShuffle = ::arg().mustDo("no-shuffle");
da73ef3c 228
4c5d6da9 229 if(!d_tcp && !mustNotShuffle) {
bbec1961 230 pdns::shuffle(d_rrs);
ff6a1e7b 231 }
12c86877
BH
232 d_wrapped=true;
233
b8e0f341 234 vector<uint8_t> packet;
adf13442 235 DNSPacketWriter pw(packet, qdomain, qtype.getCode(), qclass);
12c86877 236
6f966e0b 237 pw.getHeader()->rcode=d.rcode;
da22f3df 238 pw.getHeader()->opcode = d.opcode;
b8e0f341
BH
239 pw.getHeader()->aa=d.aa;
240 pw.getHeader()->ra=d.ra;
241 pw.getHeader()->qr=d.qr;
242 pw.getHeader()->id=d.id;
243 pw.getHeader()->rd=d.rd;
abc8f3f9 244 pw.getHeader()->tc=d.tc;
245
7f7b8d55 246 DNSPacketWriter::optvect_t opts;
e0db069a
PD
247
248 /* optsize is expected to hold an upper bound of data that will be
249 added after actual record data - i.e. OPT, TSIG, perhaps one day
250 XPF. Because of the way `pw` incrementally writes the packet, we
251 cannot easily 'go back' and remove a few records. So, to prevent
252 going over our maximum size, we keep our (potential) extra data
253 in mind.
254
255 This means that sometimes we'll send TC even if we'd end up with
256 a few bytes to spare, but so be it.
257 */
258 size_t optsize = 0;
259
e65929c6
PL
260 if (d_haveednssection || d_dnssecOk) {
261 /* root label (1), type (2), class (2), ttl (4) + rdlen (2) */
e0db069a 262 optsize = 11;
e65929c6 263 }
e0db069a 264
7f7b8d55 265 if(d_wantsnsid) {
8ca1a435 266 const static string mode_server_id=::arg()["server-id"];
49e8d5d5 267 if(mode_server_id != "disabled") {
e65929c6
PL
268 opts.push_back(make_pair(EDNSOptionCode::NSID, mode_server_id));
269 optsize += EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE + mode_server_id.size();
8ca1a435 270 }
7f7b8d55
BH
271 }
272
e0db069a
PD
273 if (d_haveednssubnet)
274 {
275 // this is an upper bound
e65929c6 276 optsize += EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE + 2 + 1 + 1; // code+len+family+src len+scope len
d14121a8 277 optsize += d_eso.source.isIPv4() ? 4 : 16;
e0db069a
PD
278 }
279
280 if (d_trc.d_algoName.countLabels())
281 {
282 // TSIG is not OPT, but we count it in optsize anyway
283 optsize += d_trc.d_algoName.wirelength() + 3 + 1 + 2; // algo + time + fudge + maclen
284 optsize += EVP_MAX_MD_SIZE + 2 + 2 + 2 + 0; // mac + origid + ercode + otherdatalen + no other data
285
286 static_assert(EVP_MAX_MD_SIZE <= 64, "EVP_MAX_MD_SIZE is overly huge on this system, please check");
287 }
288
f20d5371 289 if(!d_rrs.empty() || !opts.empty() || d_haveednssubnet || d_haveednssection) {
6f966e0b 290 try {
af7d3ea6 291 uint8_t maxScopeMask=0;
9c92ad4b 292 for(pos=d_rrs.begin(); pos < d_rrs.end(); ++pos) {
66ddf73d 293 // cerr<<"during wrapup, content=["<<pos->content<<"]"<<endl;
af7d3ea6 294 maxScopeMask = max(maxScopeMask, pos->scopeMask);
e02d0a59 295
90ba52e0 296 pw.startRecord(pos->dr.d_name, pos->dr.d_type, pos->dr.d_ttl, pos->dr.d_class, pos->dr.d_place);
297 pos->dr.d_content->toPacket(pw);
e0db069a 298 if(pw.size() + optsize > (d_tcp ? 65535 : getMaxReplyLen())) {
95369951 299 pw.rollback();
06ba4702
KM
300 pw.truncate();
301 pw.getHeader()->tc=1;
96b59a50 302 goto noCommit;
95369951
BH
303 }
304 }
732b7143
PD
305
306 // if(!pw.getHeader()->tc) // protect against double commit from addSignature
307
308 if(!d_rrs.empty()) pw.commit();
96b59a50 309
732b7143 310 noCommit:;
af7d3ea6
BH
311
312 if(d_haveednssubnet) {
af7d3ea6
BH
313 EDNSSubnetOpts eso = d_eso;
314 eso.scope = Netmask(eso.source.getNetwork(), maxScopeMask);
315
316 string opt = makeEDNSSubnetOptsString(eso);
48981c2e 317 opts.push_back(make_pair(8, opt)); // 'EDNS SUBNET'
af7d3ea6 318 }
9c92ad4b 319
f20d5371 320 if(!opts.empty() || d_haveednssection || d_dnssecOk)
75fc7cbc 321 {
298fabc3 322 pw.addOpt(s_udpTruncationThreshold, d_ednsrcode, d_dnssecOk ? EDNSOpts::DNSSECOK : 0, opts);
95369951 323 pw.commit();
75fc7cbc 324 }
6f966e0b 325 }
5172cb78 326 catch(std::exception& e) {
e6a9dde5 327 g_log<<Logger::Warning<<"Exception: "<<e.what()<<endl;
6f966e0b 328 throw;
12c86877 329 }
b8e0f341 330 }
78bcb858 331
4a51ff72 332 if(d_trc.d_algoName.countLabels())
ea3816cf 333 addTSIG(pw, d_trc, d_tsigkeyname, d_tsigsecret, d_tsigprevious, d_tsigtimersonly);
78bcb858 334
90ba52e0 335 d_rawpacket.assign((char*)&packet[0], packet.size()); // XXX we could do this natively on a vector..
3e8216c8 336
da286f66 337 // copy RR counts so they can be read later
3e8216c8
PD
338 d.qdcount = pw.getHeader()->qdcount;
339 d.ancount = pw.getHeader()->ancount;
340 d.nscount = pw.getHeader()->nscount;
341 d.arcount = pw.getHeader()->arcount;
12c86877
BH
342}
343
c2f3be9d 344void DNSPacket::setQuestion(int op, const DNSName &qd, int newqtype)
12c86877
BH
345{
346 memset(&d,0,sizeof(d));
a410b176 347 d.id=dns_random_uint16();
12c86877
BH
348 d.rd=d.tc=d.aa=false;
349 d.qr=false;
350 d.qdcount=1; // is htons'ed later on
351 d.ancount=d.arcount=d.nscount=0;
352 d.opcode=op;
288f4aa9
BH
353 qdomain=qd;
354 qtype=newqtype;
12c86877
BH
355}
356
c2826d2e
RG
357/** convenience function for creating a reply packet from a question packet. */
358std::unique_ptr<DNSPacket> DNSPacket::replyPacket() const
12c86877 359{
c2826d2e 360 auto r=make_unique<DNSPacket>(false);
12c86877 361 r->setSocket(d_socket);
2b6f1436 362 r->d_anyLocal=d_anyLocal;
d06799d4 363 r->setRemote(&d_remote);
12c86877
BH
364 r->setAnswer(true); // this implies the allocation of the header
365 r->setA(true); // and we are authoritative
366 r->setRA(0); // no recursion available
78bcb858 367 r->setRD(d.rd); // if you wanted to recurse, answer will say you wanted it
12c86877
BH
368 r->setID(d.id);
369 r->setOpcode(d.opcode);
370
12c86877 371 r->d_dt=d_dt;
092c9cc4 372 r->d.qdcount=1;
f28307ad 373 r->d_tcp = d_tcp;
b8e0f341
BH
374 r->qdomain = qdomain;
375 r->qtype = qtype;
adf13442 376 r->qclass = qclass;
657e9124 377 r->d_maxreplylen = d_maxreplylen;
7f7b8d55 378 r->d_wantsnsid = d_wantsnsid;
9c92ad4b 379 r->d_dnssecOk = d_dnssecOk;
af7d3ea6
BH
380 r->d_eso = d_eso;
381 r->d_haveednssubnet = d_haveednssubnet;
f20d5371 382 r->d_haveednssection = d_haveednssection;
298fabc3
AT
383 r->d_ednsversion = 0;
384 r->d_ednsrcode = 0;
385
675fa24c 386 if(d_tsigkeyname.countLabels()) {
78bcb858
BH
387 r->d_tsigkeyname = d_tsigkeyname;
388 r->d_tsigprevious = d_tsigprevious;
389 r->d_trc = d_trc;
390 r->d_tsigsecret = d_tsigsecret;
391 r->d_tsigtimersonly = d_tsigtimersonly;
392 }
6dc26cf0 393 r->d_havetsig = d_havetsig;
12c86877
BH
394 return r;
395}
396
c2826d2e 397void DNSPacket::spoofQuestion(const DNSPacket& qd)
12c86877 398{
b8e0f341 399 d_wrapped=true; // if we do this, don't later on wrapup
7de6b0d5 400
63e365db
PD
401 int labellen;
402 string::size_type i=sizeof(d);
403
404 for(;;) {
c2826d2e 405 labellen = qd.d_rawpacket[i];
63e365db
PD
406 if(!labellen) break;
407 i++;
c2826d2e 408 d_rawpacket.replace(i, labellen, qd.d_rawpacket, i, labellen);
63e365db 409 i = i + labellen;
7de6b0d5 410 }
b8e0f341 411}
12c86877 412
a683e8bd 413int DNSPacket::noparse(const char *mesg, size_t length)
07676510 414{
78bcb858 415 d_rawpacket.assign(mesg,length);
07676510 416 if(length < 12) {
e6a9dde5 417 g_log << Logger::Debug << "Ignoring packet: too short ("<<length<<" < 12) from "
d06e6c8b 418 << d_remote.toStringWithPort()<< endl;
07676510
BH
419 return -1;
420 }
421 d_wantsnsid=false;
07676510 422 d_maxreplylen=512;
78bcb858 423 memcpy((void *)&d,(const void *)d_rawpacket.c_str(),12);
07676510
BH
424 return 0;
425}
426
675fa24c 427void DNSPacket::setTSIGDetails(const TSIGRecordContent& tr, const DNSName& keyname, const string& secret, const string& previous, bool timersonly)
78bcb858
BH
428{
429 d_trc=tr;
e49d0a2f 430 d_trc.d_origID = (((d.id & 0xFF)<<8) | ((d.id & 0xFF00)>>8));
78bcb858
BH
431 d_tsigkeyname = keyname;
432 d_tsigsecret = secret;
433 d_tsigprevious = previous;
434 d_tsigtimersonly=timersonly;
435}
436
ea3816cf 437bool DNSPacket::getTSIGDetails(TSIGRecordContent* trc, DNSName* keyname, uint16_t* tsigPosOut) const
78bcb858 438{
27c0050c 439 MOADNSParser mdp(d_isQuery, d_rawpacket);
ea3816cf
RG
440 uint16_t tsigPos = mdp.getTSIGPos();
441 if(!tsigPos)
78bcb858
BH
442 return false;
443
444 bool gotit=false;
445 for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {
60a1c204 446 if(i->first.d_type == QType::TSIG && i->first.d_class == QType::ANY) {
6b3e413d
CH
447 // cast can fail, f.e. if d_content is an UnknownRecordContent.
448 shared_ptr<TSIGRecordContent> content = std::dynamic_pointer_cast<TSIGRecordContent>(i->first.d_content);
449 if (!content) {
e6a9dde5 450 g_log<<Logger::Error<<"TSIG record has no or invalid content (invalid packet)"<<endl;
6b3e413d
CH
451 return false;
452 }
453 *trc = *content;
f809c028 454 *keyname = i->first.d_name;
6b3e413d 455 gotit=true;
78bcb858
BH
456 }
457 }
458 if(!gotit)
459 return false;
ea3816cf
RG
460
461 if (tsigPosOut) {
462 *tsigPosOut = tsigPos;
463 }
78bcb858 464
78bcb858
BH
465 return true;
466}
467
675fa24c 468bool DNSPacket::getTKEYRecord(TKEYRecordContent *tr, DNSName *keyname) const
4429ed62 469{
27c0050c 470 MOADNSParser mdp(d_isQuery, d_rawpacket);
4429ed62
AT
471 bool gotit=false;
472
473 for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {
474 if (gotit) {
e6a9dde5 475 g_log<<Logger::Error<<"More than one TKEY record found in query"<<endl;
4429ed62
AT
476 return false;
477 }
478
479 if(i->first.d_type == QType::TKEY) {
6b3e413d
CH
480 // cast can fail, f.e. if d_content is an UnknownRecordContent.
481 shared_ptr<TKEYRecordContent> content = std::dynamic_pointer_cast<TKEYRecordContent>(i->first.d_content);
482 if (!content) {
e6a9dde5 483 g_log<<Logger::Error<<"TKEY record has no or invalid content (invalid packet)"<<endl;
6b3e413d
CH
484 return false;
485 }
486 *tr = *content;
f809c028 487 *keyname = i->first.d_name;
4429ed62
AT
488 gotit=true;
489 }
490 }
491
492 return gotit;
493}
494
b8e0f341
BH
495/** This function takes data from the network, possibly received with recvfrom, and parses
496 it into our class. Results of calling this function multiple times on one packet are
497 unknown. Returns -1 if the packet cannot be parsed.
498*/
a683e8bd 499int DNSPacket::parse(const char *mesg, size_t length)
9f064e90 500try
b8e0f341 501{
78bcb858 502 d_rawpacket.assign(mesg,length);
0e7f49b5 503 d_wrapped=true;
b8e0f341 504 if(length < 12) {
77562377 505 g_log << Logger::Debug << "Ignoring packet: too short from "
b8e0f341
BH
506 << getRemote() << endl;
507 return -1;
508 }
7f7b8d55 509
27c0050c 510 MOADNSParser mdp(d_isQuery, d_rawpacket);
7f7b8d55
BH
511 EDNSOpts edo;
512
513 // ANY OPTION WHICH *MIGHT* BE SET DOWN BELOW SHOULD BE CLEARED FIRST!
514
515 d_wantsnsid=false;
9c92ad4b 516 d_dnssecOk=false;
78bcb858 517 d_havetsig = mdp.getTSIGPos();
af7d3ea6 518 d_haveednssubnet = false;
f20d5371 519 d_haveednssection = false;
9c92ad4b 520
7f7b8d55 521 if(getEDNSOpts(mdp, &edo)) {
f20d5371 522 d_haveednssection=true;
7a9b7c95
RG
523 /* rfc6891 6.2.3:
524 "Values lower than 512 MUST be treated as equal to 512."
525 */
779b8a25 526 d_ednsRawPacketSizeLimit=edo.d_packetsize;
7a9b7c95 527 d_maxreplylen=std::min(std::max(static_cast<uint16_t>(512), edo.d_packetsize), s_udpTruncationThreshold);
d6c335ab
PL
528// cerr<<edo.d_extFlags<<endl;
529 if(edo.d_extFlags & EDNSOpts::DNSSECOK)
9c92ad4b 530 d_dnssecOk=true;
7f7b8d55
BH
531
532 for(vector<pair<uint16_t, string> >::const_iterator iter = edo.d_options.begin();
4957a608
BH
533 iter != edo.d_options.end();
534 ++iter) {
ea892f70
CH
535 if(iter->first == EDNSOptionCode::NSID) {
536 d_wantsnsid=true;
7f7b8d55 537 }
ea892f70 538 else if(s_doEDNSSubnetProcessing && (iter->first == EDNSOptionCode::ECS)) { // 'EDNS SUBNET'
17d6efc0 539 if(getEDNSSubnetOptsFromString(iter->second, &d_eso)) {
af7d3ea6
BH
540 //cerr<<"Parsed, source: "<<d_eso.source.toString()<<", scope: "<<d_eso.scope.toString()<<", family = "<<d_eso.scope.getNetwork().sin4.sin_family<<endl;
541 d_haveednssubnet=true;
542 }
543 }
544 else {
545 // cerr<<"Have an option #"<<iter->first<<": "<<makeHexDump(iter->second)<<endl;
546 }
7f7b8d55 547 }
298fabc3
AT
548 d_ednsversion = edo.d_version;
549 d_ednsrcode = edo.d_extRCode;
779b8a25 550 }
7f7b8d55 551 else {
657e9124 552 d_maxreplylen=512;
779b8a25 553 d_ednsRawPacketSizeLimit=-1;
7f7b8d55 554 }
12c86877 555
78bcb858 556 memcpy((void *)&d,(const void *)d_rawpacket.c_str(),12);
b8e0f341 557 qdomain=mdp.d_qname;
c2f3be9d
PD
558 // if(!qdomain.empty()) // strip dot
559 // boost::erase_tail(qdomain, 1);
12c86877 560
b8e0f341
BH
561 if(!ntohs(d.qdcount)) {
562 if(!d_tcp) {
d8fc9f7e 563 g_log << Logger::Debug << "No question section in packet from " << getRemote() <<", RCode="<<RCode::to_s(d.rcode)<<endl;
b8e0f341 564 return -1;
12c86877
BH
565 }
566 }
567
b8e0f341
BH
568 qtype=mdp.d_qtype;
569 qclass=mdp.d_qclass;
b7992721
RG
570
571 d_trc = TSIGRecordContent();
572
b8e0f341 573 return 0;
12c86877 574}
5172cb78 575catch(std::exception& e) {
9f064e90
BH
576 return -1;
577}
12c86877 578
78bcb858 579unsigned int DNSPacket::getMaxReplyLen()
657e9124
BH
580{
581 return d_maxreplylen;
582}
583
80397312
BH
584void DNSPacket::setMaxReplyLen(int bytes)
585{
586 d_maxreplylen=bytes;
587}
588
b8e0f341
BH
589//! Use this to set where this packet was received from or should be sent to
590void DNSPacket::setRemote(const ComboAddress *s)
12c86877 591{
d06799d4 592 d_remote=*s;
b8e0f341 593}
12c86877 594
02980dc2 595bool DNSPacket::hasEDNSSubnet() const
fe498ace
BH
596{
597 return d_haveednssubnet;
598}
599
c2826d2e 600bool DNSPacket::hasEDNS() const
17d0b1e6
PD
601{
602 return d_haveednssection;
603}
604
af7d3ea6
BH
605Netmask DNSPacket::getRealRemote() const
606{
607 if(d_haveednssubnet)
608 return d_eso.source;
609 return Netmask(d_remote);
610}
611
b8e0f341 612void DNSPacket::setSocket(Utility::sock_t sock)
12c86877 613{
b8e0f341 614 d_socket=sock;
12c86877
BH
615}
616
b8e0f341 617void DNSPacket::commitD()
12c86877 618{
78bcb858 619 d_rawpacket.replace(0,12,(char *)&d,12); // copy in d
12c86877
BH
620}
621
ea3816cf 622bool DNSPacket::checkForCorrectTSIG(UeberBackend* B, DNSName* keyname, string* secret, TSIGRecordContent* trc) const
78bcb858 623{
ea3816cf 624 uint16_t tsigPos;
60a1c204 625
ea3816cf 626 if (!this->getTSIGDetails(trc, keyname, &tsigPos)) {
78bcb858
BH
627 return false;
628 }
785594c9 629
ea3816cf
RG
630 TSIGTriplet tt;
631 tt.name = *keyname;
632 tt.algo = trc->d_algoName;
633 if (tt.algo == DNSName("hmac-md5.sig-alg.reg.int"))
634 tt.algo = DNSName("hmac-md5");
9a459f10 635
ea3816cf
RG
636 string secret64;
637 if (tt.algo != DNSName("gss-tsig")) {
638 if(!B->getTSIGKey(*keyname, &tt.algo, &secret64)) {
e6a9dde5 639 g_log<<Logger::Error<<"Packet for domain '"<<this->qdomain<<"' denied: can't find TSIG key with name '"<<*keyname<<"' and algorithm '"<<tt.algo<<"'"<<endl;
7f9ac49b
AT
640 return false;
641 }
ea3816cf
RG
642 B64Decode(secret64, *secret);
643 tt.secret = *secret;
7f9ac49b
AT
644 }
645
ea3816cf 646 bool result;
3213be1e 647
ea3816cf
RG
648 try {
649 result = validateTSIG(d_rawpacket, tsigPos, tt, *trc, "", trc->d_mac, false);
9f782f99 650 }
ea3816cf 651 catch(const std::runtime_error& err) {
e6a9dde5 652 g_log<<Logger::Error<<"Packet for '"<<this->qdomain<<"' denied: "<<err.what()<<endl;
ea3816cf 653 return false;
78bcb858 654 }
785594c9 655
78bcb858
BH
656 return result;
657}
1a5ac5d7 658
6fe866b4 659const DNSName& DNSPacket::getTSIGKeyname() const {
1a5ac5d7
AT
660 return d_tsigkeyname;
661}