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