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