]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/dnspacket.cc
Sphinx 1.8.0 seems broken, use any other version available instead
[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"
5c409fa2 39#include "pdnsexception.hh"
12c86877
BH
40#include "dnspacket.hh"
41#include "logger.hh"
42#include "arguments.hh"
b8e0f341
BH
43#include "dnswriter.hh"
44#include "dnsparser.hh"
7f7b8d55 45#include "dnsrecords.hh"
9c92ad4b 46#include "dnssecinfra.hh"
20665beb 47#include "base64.hh"
af7d3ea6 48#include "ednssubnet.hh"
7f9ac49b 49#include "gss_context.hh"
d2116c15 50#include "dns_random.hh"
af7d3ea6
BH
51
52bool DNSPacket::s_doEDNSSubnetProcessing;
15668f6a 53uint16_t DNSPacket::s_udpTruncationThreshold;
f15149ab 54
27c0050c 55DNSPacket::DNSPacket(bool isQuery)
12c86877
BH
56{
57 d_wrapped=false;
58 d_compress=true;
e9dd48f9 59 d_tcp=false;
7f7b8d55 60 d_wantsnsid=false;
af7d3ea6 61 d_haveednssubnet = false;
9c92ad4b 62 d_dnssecOk=false;
298fabc3
AT
63 d_ednsversion=0;
64 d_ednsrcode=0;
b8874063
AT
65 memset(&d, 0, sizeof(d));
66 qclass = QClass::IN;
67 d_tsig_algo = TSIG_MD5;
68 d_havetsig = false;
69 d_socket = -1;
70 d_maxreplylen = 0;
b8874063
AT
71 d_tsigtimersonly = false;
72 d_haveednssection = false;
27c0050c 73 d_isQuery = isQuery;
12c86877
BH
74}
75
78bcb858 76const string& DNSPacket::getString()
b8e0f341
BH
77{
78 if(!d_wrapped)
e02d0a59 79 wrapup();
b8e0f341 80
78bcb858 81 return d_rawpacket;
b8e0f341
BH
82}
83
b9b4da23 84ComboAddress DNSPacket::getRemote() const
12c86877 85{
b9b4da23 86 return d_remote;
12c86877
BH
87}
88
092f210a 89uint16_t DNSPacket::getRemotePort() const
288f4aa9 90{
d06799d4 91 return d_remote.sin4.sin_port;
288f4aa9 92}
12c86877 93
12c86877
BH
94DNSPacket::DNSPacket(const DNSPacket &orig)
95{
96 DLOG(L<<"DNSPacket copy constructor called!"<<endl);
97 d_socket=orig.d_socket;
d06799d4 98 d_remote=orig.d_remote;
12c86877 99 d_dt=orig.d_dt;
12c86877 100 d_compress=orig.d_compress;
f28307ad 101 d_tcp=orig.d_tcp;
12c86877
BH
102 qtype=orig.qtype;
103 qclass=orig.qclass;
104 qdomain=orig.qdomain;
3e8216c8
PD
105 qdomainwild=orig.qdomainwild;
106 qdomainzone=orig.qdomainzone;
657e9124 107 d_maxreplylen = orig.d_maxreplylen;
7f7b8d55
BH
108 d_ednsping = orig.d_ednsping;
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;
124
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{
9e79c2d4 245 return d_ednsping.empty() && !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
309 if(!d_ednsping.empty()) {
310 opts.push_back(make_pair(4, d_ednsping));
311 }
af7d3ea6
BH
312
313
f20d5371 314 if(!d_rrs.empty() || !opts.empty() || d_haveednssubnet || d_haveednssection) {
6f966e0b 315 try {
af7d3ea6 316 uint8_t maxScopeMask=0;
9c92ad4b 317 for(pos=d_rrs.begin(); pos < d_rrs.end(); ++pos) {
66ddf73d 318 // cerr<<"during wrapup, content=["<<pos->content<<"]"<<endl;
af7d3ea6 319 maxScopeMask = max(maxScopeMask, pos->scopeMask);
e02d0a59 320
90ba52e0 321 pw.startRecord(pos->dr.d_name, pos->dr.d_type, pos->dr.d_ttl, pos->dr.d_class, pos->dr.d_place);
322 pos->dr.d_content->toPacket(pw);
dffbaa08 323 if(pw.size() + 20U > (d_tcp ? 65535 : getMaxReplyLen())) { // 20 = room for EDNS0
95369951 324 pw.rollback();
90ba52e0 325 if(pos->dr.d_place == DNSResourceRecord::ANSWER || pos->dr.d_place == DNSResourceRecord::AUTHORITY) {
95369951
BH
326 pw.getHeader()->tc=1;
327 }
96b59a50 328 goto noCommit;
95369951
BH
329 }
330 }
732b7143
PD
331
332 // if(!pw.getHeader()->tc) // protect against double commit from addSignature
333
334 if(!d_rrs.empty()) pw.commit();
96b59a50 335
732b7143 336 noCommit:;
af7d3ea6
BH
337
338 if(d_haveednssubnet) {
339 string makeEDNSSubnetOptsString(const EDNSSubnetOpts& eso);
340 EDNSSubnetOpts eso = d_eso;
341 eso.scope = Netmask(eso.source.getNetwork(), maxScopeMask);
342
343 string opt = makeEDNSSubnetOptsString(eso);
48981c2e 344 opts.push_back(make_pair(8, opt)); // 'EDNS SUBNET'
af7d3ea6 345 }
9c92ad4b 346
f20d5371 347 if(!opts.empty() || d_haveednssection || d_dnssecOk)
75fc7cbc 348 {
298fabc3 349 pw.addOpt(s_udpTruncationThreshold, d_ednsrcode, d_dnssecOk ? EDNSOpts::DNSSECOK : 0, opts);
95369951 350 pw.commit();
75fc7cbc 351 }
6f966e0b 352 }
5172cb78 353 catch(std::exception& e) {
07676510 354 L<<Logger::Warning<<"Exception: "<<e.what()<<endl;
6f966e0b 355 throw;
12c86877 356 }
b8e0f341 357 }
78bcb858 358
4a51ff72 359 if(d_trc.d_algoName.countLabels())
ea3816cf 360 addTSIG(pw, d_trc, d_tsigkeyname, d_tsigsecret, d_tsigprevious, d_tsigtimersonly);
78bcb858 361
90ba52e0 362 d_rawpacket.assign((char*)&packet[0], packet.size()); // XXX we could do this natively on a vector..
3e8216c8 363
da286f66 364 // copy RR counts so they can be read later
3e8216c8
PD
365 d.qdcount = pw.getHeader()->qdcount;
366 d.ancount = pw.getHeader()->ancount;
367 d.nscount = pw.getHeader()->nscount;
368 d.arcount = pw.getHeader()->arcount;
12c86877
BH
369}
370
c2f3be9d 371void DNSPacket::setQuestion(int op, const DNSName &qd, int newqtype)
12c86877
BH
372{
373 memset(&d,0,sizeof(d));
d2116c15 374 d.id=dns_random(0xffff);
12c86877
BH
375 d.rd=d.tc=d.aa=false;
376 d.qr=false;
377 d.qdcount=1; // is htons'ed later on
378 d.ancount=d.arcount=d.nscount=0;
379 d.opcode=op;
288f4aa9
BH
380 qdomain=qd;
381 qtype=newqtype;
12c86877
BH
382}
383
12c86877
BH
384/** convenience function for creating a reply packet from a question packet. Do not forget to delete it after use! */
385DNSPacket *DNSPacket::replyPacket() const
386{
27c0050c 387 DNSPacket *r=new DNSPacket(false);
12c86877 388 r->setSocket(d_socket);
2b6f1436 389 r->d_anyLocal=d_anyLocal;
d06799d4 390 r->setRemote(&d_remote);
12c86877
BH
391 r->setAnswer(true); // this implies the allocation of the header
392 r->setA(true); // and we are authoritative
393 r->setRA(0); // no recursion available
78bcb858 394 r->setRD(d.rd); // if you wanted to recurse, answer will say you wanted it
12c86877
BH
395 r->setID(d.id);
396 r->setOpcode(d.opcode);
397
12c86877 398 r->d_dt=d_dt;
092c9cc4 399 r->d.qdcount=1;
f28307ad 400 r->d_tcp = d_tcp;
b8e0f341
BH
401 r->qdomain = qdomain;
402 r->qtype = qtype;
adf13442 403 r->qclass = qclass;
657e9124 404 r->d_maxreplylen = d_maxreplylen;
7f7b8d55
BH
405 r->d_ednsping = d_ednsping;
406 r->d_wantsnsid = d_wantsnsid;
9c92ad4b 407 r->d_dnssecOk = d_dnssecOk;
af7d3ea6
BH
408 r->d_eso = d_eso;
409 r->d_haveednssubnet = d_haveednssubnet;
f20d5371 410 r->d_haveednssection = d_haveednssection;
298fabc3
AT
411 r->d_ednsversion = 0;
412 r->d_ednsrcode = 0;
413
675fa24c 414 if(d_tsigkeyname.countLabels()) {
78bcb858
BH
415 r->d_tsigkeyname = d_tsigkeyname;
416 r->d_tsigprevious = d_tsigprevious;
417 r->d_trc = d_trc;
418 r->d_tsigsecret = d_tsigsecret;
419 r->d_tsigtimersonly = d_tsigtimersonly;
420 }
6dc26cf0 421 r->d_havetsig = d_havetsig;
12c86877
BH
422 return r;
423}
424
63e365db 425void DNSPacket::spoofQuestion(const DNSPacket *qd)
12c86877 426{
b8e0f341 427 d_wrapped=true; // if we do this, don't later on wrapup
7de6b0d5 428
63e365db
PD
429 int labellen;
430 string::size_type i=sizeof(d);
431
432 for(;;) {
433 labellen = qd->d_rawpacket[i];
434 if(!labellen) break;
435 i++;
436 d_rawpacket.replace(i, labellen, qd->d_rawpacket, i, labellen);
437 i = i + labellen;
7de6b0d5 438 }
b8e0f341 439}
12c86877 440
a683e8bd 441int DNSPacket::noparse(const char *mesg, size_t length)
07676510 442{
78bcb858 443 d_rawpacket.assign(mesg,length);
07676510 444 if(length < 12) {
d06e6c8b 445 L << Logger::Warning << "Ignoring packet: too short ("<<length<<" < 12) from "
446 << d_remote.toStringWithPort()<< endl;
07676510
BH
447 return -1;
448 }
449 d_wantsnsid=false;
450 d_ednsping.clear();
451 d_maxreplylen=512;
78bcb858 452 memcpy((void *)&d,(const void *)d_rawpacket.c_str(),12);
07676510
BH
453 return 0;
454}
455
675fa24c 456void DNSPacket::setTSIGDetails(const TSIGRecordContent& tr, const DNSName& keyname, const string& secret, const string& previous, bool timersonly)
78bcb858
BH
457{
458 d_trc=tr;
e49d0a2f 459 d_trc.d_origID = (((d.id & 0xFF)<<8) | ((d.id & 0xFF00)>>8));
78bcb858
BH
460 d_tsigkeyname = keyname;
461 d_tsigsecret = secret;
462 d_tsigprevious = previous;
463 d_tsigtimersonly=timersonly;
464}
465
ea3816cf 466bool DNSPacket::getTSIGDetails(TSIGRecordContent* trc, DNSName* keyname, uint16_t* tsigPosOut) const
78bcb858 467{
27c0050c 468 MOADNSParser mdp(d_isQuery, d_rawpacket);
ea3816cf
RG
469 uint16_t tsigPos = mdp.getTSIGPos();
470 if(!tsigPos)
78bcb858
BH
471 return false;
472
473 bool gotit=false;
474 for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {
60a1c204 475 if(i->first.d_type == QType::TSIG && i->first.d_class == QType::ANY) {
6b3e413d
CH
476 // cast can fail, f.e. if d_content is an UnknownRecordContent.
477 shared_ptr<TSIGRecordContent> content = std::dynamic_pointer_cast<TSIGRecordContent>(i->first.d_content);
478 if (!content) {
479 L<<Logger::Error<<"TSIG record has no or invalid content (invalid packet)"<<endl;
480 return false;
481 }
482 *trc = *content;
f809c028 483 *keyname = i->first.d_name;
6b3e413d 484 gotit=true;
78bcb858
BH
485 }
486 }
487 if(!gotit)
488 return false;
ea3816cf
RG
489
490 if (tsigPosOut) {
491 *tsigPosOut = tsigPos;
492 }
78bcb858 493
78bcb858
BH
494 return true;
495}
496
675fa24c 497bool DNSPacket::getTKEYRecord(TKEYRecordContent *tr, DNSName *keyname) const
4429ed62 498{
27c0050c 499 MOADNSParser mdp(d_isQuery, d_rawpacket);
4429ed62
AT
500 bool gotit=false;
501
502 for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {
503 if (gotit) {
504 L<<Logger::Error<<"More than one TKEY record found in query"<<endl;
505 return false;
506 }
507
508 if(i->first.d_type == QType::TKEY) {
6b3e413d
CH
509 // cast can fail, f.e. if d_content is an UnknownRecordContent.
510 shared_ptr<TKEYRecordContent> content = std::dynamic_pointer_cast<TKEYRecordContent>(i->first.d_content);
511 if (!content) {
512 L<<Logger::Error<<"TKEY record has no or invalid content (invalid packet)"<<endl;
513 return false;
514 }
515 *tr = *content;
f809c028 516 *keyname = i->first.d_name;
4429ed62
AT
517 gotit=true;
518 }
519 }
520
521 return gotit;
522}
523
b8e0f341
BH
524/** This function takes data from the network, possibly received with recvfrom, and parses
525 it into our class. Results of calling this function multiple times on one packet are
526 unknown. Returns -1 if the packet cannot be parsed.
527*/
a683e8bd 528int DNSPacket::parse(const char *mesg, size_t length)
9f064e90 529try
b8e0f341 530{
78bcb858 531 d_rawpacket.assign(mesg,length);
0e7f49b5 532 d_wrapped=true;
b8e0f341
BH
533 if(length < 12) {
534 L << Logger::Warning << "Ignoring packet: too short from "
535 << getRemote() << endl;
536 return -1;
537 }
7f7b8d55 538
27c0050c 539 MOADNSParser mdp(d_isQuery, d_rawpacket);
7f7b8d55
BH
540 EDNSOpts edo;
541
542 // ANY OPTION WHICH *MIGHT* BE SET DOWN BELOW SHOULD BE CLEARED FIRST!
543
544 d_wantsnsid=false;
9c92ad4b 545 d_dnssecOk=false;
7f7b8d55 546 d_ednsping.clear();
78bcb858 547 d_havetsig = mdp.getTSIGPos();
af7d3ea6 548 d_haveednssubnet = false;
f20d5371 549 d_haveednssection = false;
dac43fc2 550
9c92ad4b 551
7f7b8d55 552 if(getEDNSOpts(mdp, &edo)) {
f20d5371 553 d_haveednssection=true;
7a9b7c95
RG
554 /* rfc6891 6.2.3:
555 "Values lower than 512 MUST be treated as equal to 512."
556 */
557 d_maxreplylen=std::min(std::max(static_cast<uint16_t>(512), edo.d_packetsize), s_udpTruncationThreshold);
d28f1bd6 558// cerr<<edo.d_Z<<endl;
9c92ad4b
BH
559 if(edo.d_Z & EDNSOpts::DNSSECOK)
560 d_dnssecOk=true;
7f7b8d55
BH
561
562 for(vector<pair<uint16_t, string> >::const_iterator iter = edo.d_options.begin();
4957a608
BH
563 iter != edo.d_options.end();
564 ++iter) {
7f7b8d55 565 if(iter->first == 3) {// 'EDNS NSID'
4957a608 566 d_wantsnsid=1;
7f7b8d55 567 }
deff621d 568 else if(iter->first == 5) {// 'EDNS PING'
4957a608 569 d_ednsping = iter->second;
7f7b8d55 570 }
48981c2e 571 else if(s_doEDNSSubnetProcessing && (iter->first == 8)) { // 'EDNS SUBNET'
17d6efc0 572 if(getEDNSSubnetOptsFromString(iter->second, &d_eso)) {
af7d3ea6
BH
573 //cerr<<"Parsed, source: "<<d_eso.source.toString()<<", scope: "<<d_eso.scope.toString()<<", family = "<<d_eso.scope.getNetwork().sin4.sin_family<<endl;
574 d_haveednssubnet=true;
575 }
576 }
577 else {
578 // cerr<<"Have an option #"<<iter->first<<": "<<makeHexDump(iter->second)<<endl;
579 }
7f7b8d55 580 }
298fabc3
AT
581 d_ednsversion = edo.d_version;
582 d_ednsrcode = edo.d_extRCode;
657e9124 583 }
7f7b8d55 584 else {
657e9124 585 d_maxreplylen=512;
7f7b8d55 586 }
12c86877 587
78bcb858 588 memcpy((void *)&d,(const void *)d_rawpacket.c_str(),12);
b8e0f341 589 qdomain=mdp.d_qname;
c2f3be9d
PD
590 // if(!qdomain.empty()) // strip dot
591 // boost::erase_tail(qdomain, 1);
12c86877 592
b8e0f341
BH
593 if(!ntohs(d.qdcount)) {
594 if(!d_tcp) {
bf491f9b 595 L << Logger::Warning << "No question section in packet from " << getRemote() <<", error="<<RCode::to_s(d.rcode)<<endl;
b8e0f341 596 return -1;
12c86877
BH
597 }
598 }
599
b8e0f341
BH
600 qtype=mdp.d_qtype;
601 qclass=mdp.d_qclass;
602 return 0;
12c86877 603}
5172cb78 604catch(std::exception& e) {
9f064e90
BH
605 return -1;
606}
12c86877 607
78bcb858 608unsigned int DNSPacket::getMaxReplyLen()
657e9124
BH
609{
610 return d_maxreplylen;
611}
612
80397312
BH
613void DNSPacket::setMaxReplyLen(int bytes)
614{
615 d_maxreplylen=bytes;
616}
617
b8e0f341
BH
618//! Use this to set where this packet was received from or should be sent to
619void DNSPacket::setRemote(const ComboAddress *s)
12c86877 620{
d06799d4 621 d_remote=*s;
b8e0f341 622}
12c86877 623
fe498ace
BH
624bool DNSPacket::hasEDNSSubnet()
625{
626 return d_haveednssubnet;
627}
628
17d0b1e6
PD
629bool DNSPacket::hasEDNS()
630{
631 return d_haveednssection;
632}
633
af7d3ea6
BH
634Netmask DNSPacket::getRealRemote() const
635{
636 if(d_haveednssubnet)
637 return d_eso.source;
638 return Netmask(d_remote);
639}
640
b8e0f341 641void DNSPacket::setSocket(Utility::sock_t sock)
12c86877 642{
b8e0f341 643 d_socket=sock;
12c86877
BH
644}
645
b8e0f341 646void DNSPacket::commitD()
12c86877 647{
78bcb858 648 d_rawpacket.replace(0,12,(char *)&d,12); // copy in d
12c86877
BH
649}
650
ea3816cf 651bool DNSPacket::checkForCorrectTSIG(UeberBackend* B, DNSName* keyname, string* secret, TSIGRecordContent* trc) const
78bcb858 652{
ea3816cf 653 uint16_t tsigPos;
60a1c204 654
ea3816cf 655 if (!this->getTSIGDetails(trc, keyname, &tsigPos)) {
78bcb858
BH
656 return false;
657 }
785594c9 658
ea3816cf
RG
659 TSIGTriplet tt;
660 tt.name = *keyname;
661 tt.algo = trc->d_algoName;
662 if (tt.algo == DNSName("hmac-md5.sig-alg.reg.int"))
663 tt.algo = DNSName("hmac-md5");
9a459f10 664
ea3816cf
RG
665 string secret64;
666 if (tt.algo != DNSName("gss-tsig")) {
667 if(!B->getTSIGKey(*keyname, &tt.algo, &secret64)) {
668 L<<Logger::Error<<"Packet for domain '"<<this->qdomain<<"' denied: can't find TSIG key with name '"<<*keyname<<"' and algorithm '"<<tt.algo<<"'"<<endl;
7f9ac49b
AT
669 return false;
670 }
ea3816cf
RG
671 B64Decode(secret64, *secret);
672 tt.secret = *secret;
7f9ac49b
AT
673 }
674
ea3816cf 675 bool result;
3213be1e 676
ea3816cf
RG
677 try {
678 result = validateTSIG(d_rawpacket, tsigPos, tt, *trc, "", trc->d_mac, false);
9f782f99 679 }
ea3816cf
RG
680 catch(const std::runtime_error& err) {
681 L<<Logger::Error<<"Packet for '"<<this->qdomain<<"' denied: "<<err.what()<<endl;
682 return false;
78bcb858 683 }
785594c9 684
78bcb858
BH
685 return result;
686}
1a5ac5d7 687
6fe866b4 688const DNSName& DNSPacket::getTSIGKeyname() const {
1a5ac5d7
AT
689 return d_tsigkeyname;
690}