]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/dnspacket.cc
Merge pull request #2219 from mind04/mixed
[thirdparty/pdns.git] / pdns / dnspacket.cc
CommitLineData
12c86877
BH
1/*
2 PowerDNS Versatile Database Driven Nameserver
d06e6c8b 3 Copyright (C) 2001 - 2015 PowerDNS.COM BV
12c86877
BH
4
5 This program is free software; you can redistribute it and/or modify
feccc9fc 6 it under the terms of the GNU General Public License version 2 as
f28307ad 7 published by the Free Software Foundation
12c86877 8
f782fe38
MH
9 Additionally, the license of this program contains a special
10 exception which allows to distribute the program in binary form when
11 it is linked against OpenSSL.
12
12c86877
BH
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
06bd9ccf 20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12c86877 21*/
ff6a1e7b 22
12c86877
BH
23#include "utility.hh"
24#include <cstdio>
12c86877
BH
25#include <cstdlib>
26#include <sys/types.h>
12c86877 27#include <iostream>
12c86877
BH
28#include <string>
29#include <errno.h>
b8e0f341
BH
30#include <boost/tokenizer.hpp>
31#include <boost/algorithm/string.hpp>
12c86877 32#include <algorithm>
9c92ad4b
BH
33#include <boost/foreach.hpp>
34#include "dnsseckeeper.hh"
12c86877
BH
35#include "dns.hh"
36#include "dnsbackend.hh"
5c409fa2 37#include "pdnsexception.hh"
12c86877
BH
38#include "dnspacket.hh"
39#include "logger.hh"
40#include "arguments.hh"
b8e0f341
BH
41#include "dnswriter.hh"
42#include "dnsparser.hh"
7f7b8d55 43#include "dnsrecords.hh"
9c92ad4b 44#include "dnssecinfra.hh"
20665beb 45#include "base64.hh"
af7d3ea6
BH
46#include "ednssubnet.hh"
47
48bool DNSPacket::s_doEDNSSubnetProcessing;
15668f6a 49uint16_t DNSPacket::s_udpTruncationThreshold;
f15149ab 50
12c86877
BH
51DNSPacket::DNSPacket()
52{
53 d_wrapped=false;
54 d_compress=true;
e9dd48f9 55 d_tcp=false;
7f7b8d55 56 d_wantsnsid=false;
af7d3ea6 57 d_haveednssubnet = false;
9c92ad4b 58 d_dnssecOk=false;
12c86877
BH
59}
60
78bcb858 61const string& DNSPacket::getString()
b8e0f341
BH
62{
63 if(!d_wrapped)
e02d0a59 64 wrapup();
b8e0f341 65
78bcb858 66 return d_rawpacket;
b8e0f341
BH
67}
68
12c86877
BH
69string DNSPacket::getRemote() const
70{
d06799d4 71 return d_remote.toString();
12c86877
BH
72}
73
092f210a 74uint16_t DNSPacket::getRemotePort() const
288f4aa9 75{
d06799d4 76 return d_remote.sin4.sin_port;
288f4aa9 77}
12c86877 78
12c86877
BH
79DNSPacket::DNSPacket(const DNSPacket &orig)
80{
81 DLOG(L<<"DNSPacket copy constructor called!"<<endl);
82 d_socket=orig.d_socket;
d06799d4 83 d_remote=orig.d_remote;
12c86877
BH
84 d_qlen=orig.d_qlen;
85 d_dt=orig.d_dt;
12c86877 86 d_compress=orig.d_compress;
f28307ad 87 d_tcp=orig.d_tcp;
12c86877
BH
88 qtype=orig.qtype;
89 qclass=orig.qclass;
90 qdomain=orig.qdomain;
657e9124 91 d_maxreplylen = orig.d_maxreplylen;
7f7b8d55
BH
92 d_ednsping = orig.d_ednsping;
93 d_wantsnsid = orig.d_wantsnsid;
2b6f1436 94 d_anyLocal = orig.d_anyLocal;
af7d3ea6
BH
95 d_eso = orig.d_eso;
96 d_haveednssubnet = orig.d_haveednssubnet;
f20d5371 97 d_haveednssection = orig.d_haveednssection;
9c92ad4b
BH
98 d_dnssecOk = orig.d_dnssecOk;
99 d_rrs=orig.d_rrs;
78bcb858
BH
100
101 d_tsigkeyname = orig.d_tsigkeyname;
102 d_tsigprevious = orig.d_tsigprevious;
103 d_tsigtimersonly = orig.d_tsigtimersonly;
104 d_trc = orig.d_trc;
105 d_tsigsecret = orig.d_tsigsecret;
106
6dc26cf0 107 d_havetsig = orig.d_havetsig;
12c86877
BH
108 d_wrapped=orig.d_wrapped;
109
78bcb858 110 d_rawpacket=orig.d_rawpacket;
12c86877 111 d=orig.d;
12c86877
BH
112}
113
12c86877
BH
114void DNSPacket::setRcode(int v)
115{
116 d.rcode=v;
117}
118
119void DNSPacket::setAnswer(bool b)
120{
121 if(b) {
78bcb858 122 d_rawpacket.assign(12,(char)0);
12c86877
BH
123 memset((void *)&d,0,sizeof(d));
124
125 d.qr=b;
126 }
127}
128
129void DNSPacket::setA(bool b)
130{
131 d.aa=b;
132}
133
092f210a 134void DNSPacket::setID(uint16_t id)
12c86877
BH
135{
136 d.id=id;
137}
138
139void DNSPacket::setRA(bool b)
140{
141 d.ra=b;
142}
143
144void DNSPacket::setRD(bool b)
145{
146 d.rd=b;
147}
148
092f210a 149void DNSPacket::setOpcode(uint16_t opcode)
12c86877
BH
150{
151 d.opcode=opcode;
152}
153
12c86877 154
77235722
BH
155void DNSPacket::clearRecords()
156{
9c92ad4b 157 d_rrs.clear();
77235722
BH
158}
159
12c86877
BH
160void DNSPacket::addRecord(const DNSResourceRecord &rr)
161{
2e7834cb
BH
162 // this removes duplicates from the packet in case we are not compressing
163 // for AXFR, no such checking is performed!
12c86877 164 if(d_compress)
9c92ad4b 165 for(vector<DNSResourceRecord>::const_iterator i=d_rrs.begin();i!=d_rrs.end();++i)
ab2249ae 166 if(rr.qname==i->qname && rr.qtype==i->qtype && rr.content==i->content) {
4957a608 167 return;
ab2249ae 168 }
12c86877 169
9c92ad4b 170 d_rrs.push_back(rr);
12c86877
BH
171}
172
12c86877 173
12c86877
BH
174
175static int rrcomp(const DNSResourceRecord &A, const DNSResourceRecord &B)
176{
e02d0a59 177 if(A.d_place < B.d_place)
12c86877
BH
178 return 1;
179
180 return 0;
181}
182
f6ba332a 183vector<DNSResourceRecord*> DNSPacket::getAPRecords()
12c86877 184{
f6ba332a 185 vector<DNSResourceRecord*> arrs;
12c86877 186
9c92ad4b
BH
187 for(vector<DNSResourceRecord>::iterator i=d_rrs.begin();
188 i!=d_rrs.end();
12c86877
BH
189 ++i)
190 {
191 if(i->d_place!=DNSResourceRecord::ADDITIONAL &&
a16e8e3a
BH
192 (i->qtype.getCode()==QType::MX ||
193 i->qtype.getCode()==QType::NS ||
194 i->qtype.getCode()==QType::SRV))
4957a608
BH
195 {
196 arrs.push_back(&*i);
197 }
12c86877
BH
198 }
199
200 return arrs;
201
202}
203
9c92ad4b
BH
204vector<DNSResourceRecord*> DNSPacket::getAnswerRecords()
205{
206 vector<DNSResourceRecord*> arrs;
207
208 for(vector<DNSResourceRecord>::iterator i=d_rrs.begin();
209 i!=d_rrs.end();
210 ++i)
211 {
212 if(i->d_place!=DNSResourceRecord::ADDITIONAL)
232f0877 213 arrs.push_back(&*i);
9c92ad4b
BH
214 }
215 return arrs;
216}
217
218
12c86877
BH
219void DNSPacket::setCompress(bool compress)
220{
221 d_compress=compress;
78bcb858 222 d_rawpacket.reserve(65000);
9c92ad4b 223 d_rrs.reserve(200);
12c86877
BH
224}
225
7f7b8d55
BH
226bool DNSPacket::couldBeCached()
227{
adf13442 228 return d_ednsping.empty() && !d_wantsnsid && qclass==QClass::IN;
7f7b8d55 229}
20665beb 230
b35ea8ec
PD
231unsigned int DNSPacket::getMinTTL()
232{
233 unsigned int minttl = UINT_MAX;
234 BOOST_FOREACH(DNSResourceRecord rr, d_rrs) {
235 if (rr.ttl < minttl)
236 minttl = rr.ttl;
237 }
238
239 return minttl;
240}
241
9951e2d0
KM
242bool DNSPacket::isEmpty()
243{
244 return (d_rrs.empty());
245}
246
12c86877
BH
247/** Must be called before attempting to access getData(). This function stuffs all resource
248 * records found in rrs into the data buffer. It also frees resource records queued for us.
249 */
e02d0a59 250void DNSPacket::wrapup()
12c86877
BH
251{
252 if(d_wrapped) {
253 return;
254 }
51a3a4d4 255
12c86877
BH
256 DNSResourceRecord rr;
257 vector<DNSResourceRecord>::iterator pos;
258
12c86877
BH
259 // we now need to order rrs so that the different sections come at the right place
260 // we want a stable sort, based on the d_place field
261
e02d0a59 262 stable_sort(d_rrs.begin(),d_rrs.end(), rrcomp);
4c5d6da9 263 static bool mustNotShuffle = ::arg().mustDo("no-shuffle");
da73ef3c 264
4c5d6da9 265 if(!d_tcp && !mustNotShuffle) {
9c92ad4b 266 shuffle(d_rrs);
ff6a1e7b 267 }
12c86877
BH
268 d_wrapped=true;
269
b8e0f341 270 vector<uint8_t> packet;
adf13442 271 DNSPacketWriter pw(packet, qdomain, qtype.getCode(), qclass);
12c86877 272
6f966e0b 273 pw.getHeader()->rcode=d.rcode;
da22f3df 274 pw.getHeader()->opcode = d.opcode;
b8e0f341
BH
275 pw.getHeader()->aa=d.aa;
276 pw.getHeader()->ra=d.ra;
277 pw.getHeader()->qr=d.qr;
278 pw.getHeader()->id=d.id;
279 pw.getHeader()->rd=d.rd;
abc8f3f9 280 pw.getHeader()->tc=d.tc;
281
7f7b8d55
BH
282 DNSPacketWriter::optvect_t opts;
283 if(d_wantsnsid) {
8ca1a435 284 const static string mode_server_id=::arg()["server-id"];
49e8d5d5 285 if(mode_server_id != "disabled") {
8ca1a435
DB
286 opts.push_back(make_pair(3, mode_server_id));
287 }
7f7b8d55
BH
288 }
289
290 if(!d_ednsping.empty()) {
291 opts.push_back(make_pair(4, d_ednsping));
292 }
af7d3ea6
BH
293
294
f20d5371 295 if(!d_rrs.empty() || !opts.empty() || d_haveednssubnet || d_haveednssection) {
6f966e0b 296 try {
af7d3ea6 297 uint8_t maxScopeMask=0;
9c92ad4b 298 for(pos=d_rrs.begin(); pos < d_rrs.end(); ++pos) {
af7d3ea6 299 maxScopeMask = max(maxScopeMask, pos->scopeMask);
9c92ad4b 300
4957a608
BH
301 if(!pos->content.empty() && pos->qtype.getCode()==QType::TXT && pos->content[0]!='"') {
302 pos->content="\""+pos->content+"\"";
303 }
304 if(pos->content.empty()) // empty contents confuse the MOADNS setup
305 pos->content=".";
e02d0a59 306
95369951
BH
307 pw.startRecord(pos->qname, pos->qtype.getCode(), pos->ttl, pos->qclass, (DNSPacketWriter::Place)pos->d_place);
308 shared_ptr<DNSRecordContent> drc(DNSRecordContent::mastermake(pos->qtype.getCode(), 1, pos->content));
309 drc->toPacket(pw);
dffbaa08 310 if(pw.size() + 20U > (d_tcp ? 65535 : getMaxReplyLen())) { // 20 = room for EDNS0
95369951 311 pw.rollback();
c5c4fbdc 312 if(pos->d_place == DNSResourceRecord::ANSWER || pos->d_place == DNSResourceRecord::AUTHORITY) {
95369951
BH
313 pw.getHeader()->tc=1;
314 }
96b59a50 315 goto noCommit;
95369951
BH
316 }
317 }
732b7143
PD
318
319 // if(!pw.getHeader()->tc) // protect against double commit from addSignature
320
321 if(!d_rrs.empty()) pw.commit();
96b59a50 322
732b7143 323 noCommit:;
af7d3ea6
BH
324
325 if(d_haveednssubnet) {
326 string makeEDNSSubnetOptsString(const EDNSSubnetOpts& eso);
327 EDNSSubnetOpts eso = d_eso;
328 eso.scope = Netmask(eso.source.getNetwork(), maxScopeMask);
329
330 string opt = makeEDNSSubnetOptsString(eso);
48981c2e 331 opts.push_back(make_pair(8, opt)); // 'EDNS SUBNET'
af7d3ea6 332 }
9c92ad4b 333
f20d5371 334 if(!opts.empty() || d_haveednssection || d_dnssecOk)
75fc7cbc 335 {
1cd66b8e 336 pw.addOpt(s_udpTruncationThreshold, 0, d_dnssecOk ? EDNSOpts::DNSSECOK : 0, opts);
95369951 337 pw.commit();
75fc7cbc 338 }
6f966e0b 339 }
5172cb78 340 catch(std::exception& e) {
07676510 341 L<<Logger::Warning<<"Exception: "<<e.what()<<endl;
6f966e0b 342 throw;
12c86877 343 }
b8e0f341 344 }
78bcb858
BH
345
346 if(!d_trc.d_algoName.empty())
01cb2fe2 347 addTSIG(pw, &d_trc, d_tsigkeyname, d_tsigsecret, d_tsigprevious, d_tsigtimersonly);
78bcb858
BH
348
349 d_rawpacket.assign((char*)&packet[0], packet.size());
12c86877
BH
350}
351
288f4aa9 352void DNSPacket::setQuestion(int op, const string &qd, int newqtype)
12c86877
BH
353{
354 memset(&d,0,sizeof(d));
355 d.id=Utility::random();
356 d.rd=d.tc=d.aa=false;
357 d.qr=false;
358 d.qdcount=1; // is htons'ed later on
359 d.ancount=d.arcount=d.nscount=0;
360 d.opcode=op;
288f4aa9
BH
361 qdomain=qd;
362 qtype=newqtype;
12c86877
BH
363}
364
12c86877
BH
365/** convenience function for creating a reply packet from a question packet. Do not forget to delete it after use! */
366DNSPacket *DNSPacket::replyPacket() const
367{
368 DNSPacket *r=new DNSPacket;
369 r->setSocket(d_socket);
2b6f1436 370 r->d_anyLocal=d_anyLocal;
d06799d4 371 r->setRemote(&d_remote);
12c86877
BH
372 r->setAnswer(true); // this implies the allocation of the header
373 r->setA(true); // and we are authoritative
374 r->setRA(0); // no recursion available
78bcb858 375 r->setRD(d.rd); // if you wanted to recurse, answer will say you wanted it
12c86877
BH
376 r->setID(d.id);
377 r->setOpcode(d.opcode);
378
12c86877 379 r->d_dt=d_dt;
092c9cc4 380 r->d.qdcount=1;
f28307ad 381 r->d_tcp = d_tcp;
b8e0f341
BH
382 r->qdomain = qdomain;
383 r->qtype = qtype;
adf13442 384 r->qclass = qclass;
657e9124 385 r->d_maxreplylen = d_maxreplylen;
7f7b8d55
BH
386 r->d_ednsping = d_ednsping;
387 r->d_wantsnsid = d_wantsnsid;
9c92ad4b 388 r->d_dnssecOk = d_dnssecOk;
af7d3ea6
BH
389 r->d_eso = d_eso;
390 r->d_haveednssubnet = d_haveednssubnet;
f20d5371 391 r->d_haveednssection = d_haveednssection;
dac43fc2 392
78bcb858
BH
393 if(!d_tsigkeyname.empty()) {
394 r->d_tsigkeyname = d_tsigkeyname;
395 r->d_tsigprevious = d_tsigprevious;
396 r->d_trc = d_trc;
397 r->d_tsigsecret = d_tsigsecret;
398 r->d_tsigtimersonly = d_tsigtimersonly;
399 }
6dc26cf0 400 r->d_havetsig = d_havetsig;
12c86877
BH
401 return r;
402}
403
63e365db 404void DNSPacket::spoofQuestion(const DNSPacket *qd)
12c86877 405{
b8e0f341 406 d_wrapped=true; // if we do this, don't later on wrapup
7de6b0d5 407
63e365db
PD
408 int labellen;
409 string::size_type i=sizeof(d);
410
411 for(;;) {
412 labellen = qd->d_rawpacket[i];
413 if(!labellen) break;
414 i++;
415 d_rawpacket.replace(i, labellen, qd->d_rawpacket, i, labellen);
416 i = i + labellen;
7de6b0d5 417 }
b8e0f341 418}
12c86877 419
07676510
BH
420int DNSPacket::noparse(const char *mesg, int length)
421{
78bcb858 422 d_rawpacket.assign(mesg,length);
07676510 423 if(length < 12) {
d06e6c8b 424 L << Logger::Warning << "Ignoring packet: too short ("<<length<<" < 12) from "
425 << d_remote.toStringWithPort()<< endl;
07676510
BH
426 return -1;
427 }
428 d_wantsnsid=false;
429 d_ednsping.clear();
430 d_maxreplylen=512;
78bcb858 431 memcpy((void *)&d,(const void *)d_rawpacket.c_str(),12);
07676510
BH
432 return 0;
433}
434
78bcb858
BH
435void DNSPacket::setTSIGDetails(const TSIGRecordContent& tr, const string& keyname, const string& secret, const string& previous, bool timersonly)
436{
437 d_trc=tr;
438 d_tsigkeyname = keyname;
439 d_tsigsecret = secret;
440 d_tsigprevious = previous;
441 d_tsigtimersonly=timersonly;
442}
443
78bcb858
BH
444bool DNSPacket::getTSIGDetails(TSIGRecordContent* trc, string* keyname, string* message) const
445{
446 MOADNSParser mdp(d_rawpacket);
447
448 if(!mdp.getTSIGPos())
449 return false;
450
451 bool gotit=false;
452 for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {
453 if(i->first.d_type == QType::TSIG) {
454 *trc = *boost::dynamic_pointer_cast<TSIGRecordContent>(i->first.d_content);
455
456 gotit=true;
457 *keyname = i->first.d_label;
6507e8e8
BH
458 if(!keyname->empty())
459 keyname->resize(keyname->size()-1); // drop the trailing dot
78bcb858
BH
460 }
461 }
462 if(!gotit)
463 return false;
01cb2fe2
BH
464 if(message)
465 *message = makeTSIGMessageFromTSIGPacket(d_rawpacket, mdp.getTSIGPos(), *keyname, *trc, d_tsigprevious, false); // if you change rawpacket to getString it breaks!
78bcb858 466
78bcb858
BH
467 return true;
468}
469
b8e0f341
BH
470/** This function takes data from the network, possibly received with recvfrom, and parses
471 it into our class. Results of calling this function multiple times on one packet are
472 unknown. Returns -1 if the packet cannot be parsed.
473*/
474int DNSPacket::parse(const char *mesg, int length)
9f064e90 475try
b8e0f341 476{
78bcb858 477 d_rawpacket.assign(mesg,length);
0e7f49b5 478 d_wrapped=true;
b8e0f341
BH
479 if(length < 12) {
480 L << Logger::Warning << "Ignoring packet: too short from "
481 << getRemote() << endl;
482 return -1;
483 }
7f7b8d55 484
78bcb858 485 MOADNSParser mdp(d_rawpacket);
7f7b8d55
BH
486 EDNSOpts edo;
487
488 // ANY OPTION WHICH *MIGHT* BE SET DOWN BELOW SHOULD BE CLEARED FIRST!
489
490 d_wantsnsid=false;
9c92ad4b 491 d_dnssecOk=false;
7f7b8d55 492 d_ednsping.clear();
78bcb858 493 d_havetsig = mdp.getTSIGPos();
af7d3ea6 494 d_haveednssubnet = false;
f20d5371 495 d_haveednssection = false;
dac43fc2 496
9c92ad4b 497
7f7b8d55 498 if(getEDNSOpts(mdp, &edo)) {
f20d5371 499 d_haveednssection=true;
15668f6a 500 d_maxreplylen=std::min(edo.d_packetsize, s_udpTruncationThreshold);
d28f1bd6 501// cerr<<edo.d_Z<<endl;
9c92ad4b
BH
502 if(edo.d_Z & EDNSOpts::DNSSECOK)
503 d_dnssecOk=true;
7f7b8d55
BH
504
505 for(vector<pair<uint16_t, string> >::const_iterator iter = edo.d_options.begin();
4957a608
BH
506 iter != edo.d_options.end();
507 ++iter) {
7f7b8d55 508 if(iter->first == 3) {// 'EDNS NSID'
4957a608 509 d_wantsnsid=1;
7f7b8d55 510 }
deff621d 511 else if(iter->first == 5) {// 'EDNS PING'
4957a608 512 d_ednsping = iter->second;
7f7b8d55 513 }
48981c2e 514 else if(s_doEDNSSubnetProcessing && (iter->first == 8)) { // 'EDNS SUBNET'
17d6efc0 515 if(getEDNSSubnetOptsFromString(iter->second, &d_eso)) {
af7d3ea6
BH
516 //cerr<<"Parsed, source: "<<d_eso.source.toString()<<", scope: "<<d_eso.scope.toString()<<", family = "<<d_eso.scope.getNetwork().sin4.sin_family<<endl;
517 d_haveednssubnet=true;
518 }
519 }
520 else {
521 // cerr<<"Have an option #"<<iter->first<<": "<<makeHexDump(iter->second)<<endl;
522 }
7f7b8d55 523 }
657e9124 524 }
7f7b8d55 525 else {
657e9124 526 d_maxreplylen=512;
7f7b8d55 527 }
12c86877 528
78bcb858 529 memcpy((void *)&d,(const void *)d_rawpacket.c_str(),12);
b8e0f341
BH
530 qdomain=mdp.d_qname;
531 if(!qdomain.empty()) // strip dot
61b26744 532 boost::erase_tail(qdomain, 1);
12c86877 533
b8e0f341
BH
534 if(!ntohs(d.qdcount)) {
535 if(!d_tcp) {
bf491f9b 536 L << Logger::Warning << "No question section in packet from " << getRemote() <<", error="<<RCode::to_s(d.rcode)<<endl;
b8e0f341 537 return -1;
12c86877
BH
538 }
539 }
540
b8e0f341
BH
541 qtype=mdp.d_qtype;
542 qclass=mdp.d_qclass;
543 return 0;
12c86877 544}
5172cb78 545catch(std::exception& e) {
9f064e90
BH
546 return -1;
547}
12c86877 548
78bcb858 549unsigned int DNSPacket::getMaxReplyLen()
657e9124
BH
550{
551 return d_maxreplylen;
552}
553
80397312
BH
554void DNSPacket::setMaxReplyLen(int bytes)
555{
556 d_maxreplylen=bytes;
557}
558
b8e0f341
BH
559//! Use this to set where this packet was received from or should be sent to
560void DNSPacket::setRemote(const ComboAddress *s)
12c86877 561{
d06799d4 562 d_remote=*s;
b8e0f341 563}
12c86877 564
fe498ace
BH
565bool DNSPacket::hasEDNSSubnet()
566{
567 return d_haveednssubnet;
568}
569
17d0b1e6
PD
570bool DNSPacket::hasEDNS()
571{
572 return d_haveednssection;
573}
574
af7d3ea6
BH
575Netmask DNSPacket::getRealRemote() const
576{
577 if(d_haveednssubnet)
578 return d_eso.source;
579 return Netmask(d_remote);
580}
581
b8e0f341 582void DNSPacket::setSocket(Utility::sock_t sock)
12c86877 583{
b8e0f341 584 d_socket=sock;
12c86877
BH
585}
586
b8e0f341 587void DNSPacket::commitD()
12c86877 588{
78bcb858 589 d_rawpacket.replace(0,12,(char *)&d,12); // copy in d
12c86877
BH
590}
591
78bcb858
BH
592bool checkForCorrectTSIG(const DNSPacket* q, DNSBackend* B, string* keyname, string* secret, TSIGRecordContent* trc)
593{
594 string message;
785594c9 595
78bcb858 596 q->getTSIGDetails(trc, keyname, &message);
8261085f 597 int64_t now = time(0);
598 if(abs((int64_t)trc->d_time - now) > trc->d_fudge) {
6dc26cf0 599 L<<Logger::Error<<"Packet for '"<<q->qdomain<<"' denied: TSIG (key '"<<*keyname<<"') time delta "<< abs(trc->d_time - now)<<" > 'fudge' "<<trc->d_fudge<<endl;
78bcb858
BH
600 return false;
601 }
785594c9 602
87168c90
KM
603 string algoName = toLowerCanonic(trc->d_algoName);
604 if (algoName == "hmac-md5.sig-alg.reg.int")
9a459f10
KM
605 algoName = "hmac-md5";
606
78bcb858 607 string secret64;
9a459f10
KM
608 if(!B->getTSIGKey(*keyname, &algoName, &secret64)) {
609 L<<Logger::Error<<"Packet for domain '"<<q->qdomain<<"' denied: can't find TSIG key with name '"<<*keyname<<"' and algorithm '"<<algoName<<"'"<<endl;
78bcb858
BH
610 return false;
611 }
3213be1e
AT
612 if (trc->d_algoName == "hmac-md5")
613 trc->d_algoName += ".sig-alg.reg.int.";
614
a56bc64d 615 TSIGHashEnum algo;
785594c9 616 if(!getTSIGHashEnum(trc->d_algoName, algo)) {
a56bc64d
AT
617 L<<Logger::Error<<"Unsupported TSIG HMAC algorithm " << trc->d_algoName << endl;
618 return false;
9f782f99
AT
619 }
620
a56bc64d 621 B64Decode(secret64, *secret);
785594c9 622 bool result=calculateHMAC(*secret, message, algo) == trc->d_mac;
78bcb858
BH
623 if(!result) {
624 L<<Logger::Error<<"Packet for domain '"<<q->qdomain<<"' denied: TSIG signature mismatch using '"<<*keyname<<"' and algorithm '"<<trc->d_algoName<<"'"<<endl;
625 }
785594c9 626
78bcb858
BH
627 return result;
628}