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