| 1 | /* |
|---|
| 2 | PowerDNS Versatile Database Driven Nameserver |
|---|
| 3 | Copyright (C) 2001 - 2008 PowerDNS.COM BV |
|---|
| 4 | |
|---|
| 5 | This program is free software; you can redistribute it and/or modify |
|---|
| 6 | it under the terms of the GNU General Public License version 2 as |
|---|
| 7 | published by the Free Software Foundation |
|---|
| 8 | |
|---|
| 9 | This program is distributed in the hope that it will be useful, |
|---|
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 12 | GNU General Public License for more details. |
|---|
| 13 | |
|---|
| 14 | You should have received a copy of the GNU General Public License |
|---|
| 15 | along with this program; if not, write to the Free Software |
|---|
| 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|---|
| 17 | */ |
|---|
| 18 | |
|---|
| 19 | #include "utility.hh" |
|---|
| 20 | #include <cstdio> |
|---|
| 21 | |
|---|
| 22 | #include <cstdlib> |
|---|
| 23 | #include <sys/types.h> |
|---|
| 24 | |
|---|
| 25 | #include <iostream> |
|---|
| 26 | |
|---|
| 27 | #include <string> |
|---|
| 28 | #include <errno.h> |
|---|
| 29 | #include <boost/tokenizer.hpp> |
|---|
| 30 | #include <boost/algorithm/string.hpp> |
|---|
| 31 | #include <algorithm> |
|---|
| 32 | |
|---|
| 33 | #include "dns.hh" |
|---|
| 34 | #include "dnsbackend.hh" |
|---|
| 35 | #include "ahuexception.hh" |
|---|
| 36 | #include "dnspacket.hh" |
|---|
| 37 | #include "logger.hh" |
|---|
| 38 | #include "arguments.hh" |
|---|
| 39 | #include "dnswriter.hh" |
|---|
| 40 | #include "dnsparser.hh" |
|---|
| 41 | #include "dnsrecords.hh" |
|---|
| 42 | |
|---|
| 43 | DNSPacket::DNSPacket() |
|---|
| 44 | { |
|---|
| 45 | d_wrapped=false; |
|---|
| 46 | d_compress=true; |
|---|
| 47 | d_tcp=false; |
|---|
| 48 | d_wantsnsid=false; |
|---|
| 49 | } |
|---|
| 50 | |
|---|
| 51 | string DNSPacket::getString() |
|---|
| 52 | { |
|---|
| 53 | return stringbuffer; |
|---|
| 54 | } |
|---|
| 55 | |
|---|
| 56 | const char *DNSPacket::getData(void) |
|---|
| 57 | { |
|---|
| 58 | if(!d_wrapped) |
|---|
| 59 | wrapup(); |
|---|
| 60 | |
|---|
| 61 | return stringbuffer.data(); |
|---|
| 62 | } |
|---|
| 63 | |
|---|
| 64 | const char *DNSPacket::getRaw(void) |
|---|
| 65 | { |
|---|
| 66 | return stringbuffer.data(); |
|---|
| 67 | } |
|---|
| 68 | |
|---|
| 69 | string DNSPacket::getRemote() const |
|---|
| 70 | { |
|---|
| 71 | return remote.toString(); |
|---|
| 72 | } |
|---|
| 73 | |
|---|
| 74 | uint16_t DNSPacket::getRemotePort() const |
|---|
| 75 | { |
|---|
| 76 | return remote.sin4.sin_port; |
|---|
| 77 | } |
|---|
| 78 | |
|---|
| 79 | DNSPacket::DNSPacket(const DNSPacket &orig) |
|---|
| 80 | { |
|---|
| 81 | DLOG(L<<"DNSPacket copy constructor called!"<<endl); |
|---|
| 82 | d_socket=orig.d_socket; |
|---|
| 83 | remote=orig.remote; |
|---|
| 84 | len=orig.len; |
|---|
| 85 | d_qlen=orig.d_qlen; |
|---|
| 86 | d_dt=orig.d_dt; |
|---|
| 87 | d_compress=orig.d_compress; |
|---|
| 88 | d_tcp=orig.d_tcp; |
|---|
| 89 | qtype=orig.qtype; |
|---|
| 90 | qclass=orig.qclass; |
|---|
| 91 | qdomain=orig.qdomain; |
|---|
| 92 | d_maxreplylen = orig.d_maxreplylen; |
|---|
| 93 | d_ednsping = orig.d_ednsping; |
|---|
| 94 | d_wantsnsid = orig.d_wantsnsid; |
|---|
| 95 | rrs=orig.rrs; |
|---|
| 96 | |
|---|
| 97 | d_wrapped=orig.d_wrapped; |
|---|
| 98 | |
|---|
| 99 | stringbuffer=orig.stringbuffer; |
|---|
| 100 | d=orig.d; |
|---|
| 101 | } |
|---|
| 102 | |
|---|
| 103 | void DNSPacket::setRcode(int v) |
|---|
| 104 | { |
|---|
| 105 | d.rcode=v; |
|---|
| 106 | } |
|---|
| 107 | |
|---|
| 108 | void DNSPacket::setAnswer(bool b) |
|---|
| 109 | { |
|---|
| 110 | if(b) { |
|---|
| 111 | stringbuffer.assign(12,(char)0); |
|---|
| 112 | memset((void *)&d,0,sizeof(d)); |
|---|
| 113 | |
|---|
| 114 | d.qr=b; |
|---|
| 115 | } |
|---|
| 116 | } |
|---|
| 117 | |
|---|
| 118 | void DNSPacket::setA(bool b) |
|---|
| 119 | { |
|---|
| 120 | d.aa=b; |
|---|
| 121 | } |
|---|
| 122 | |
|---|
| 123 | void DNSPacket::setID(uint16_t id) |
|---|
| 124 | { |
|---|
| 125 | d.id=id; |
|---|
| 126 | } |
|---|
| 127 | |
|---|
| 128 | void DNSPacket::setRA(bool b) |
|---|
| 129 | { |
|---|
| 130 | d.ra=b; |
|---|
| 131 | } |
|---|
| 132 | |
|---|
| 133 | void DNSPacket::setRD(bool b) |
|---|
| 134 | { |
|---|
| 135 | d.rd=b; |
|---|
| 136 | } |
|---|
| 137 | |
|---|
| 138 | void DNSPacket::setOpcode(uint16_t opcode) |
|---|
| 139 | { |
|---|
| 140 | d.opcode=opcode; |
|---|
| 141 | } |
|---|
| 142 | |
|---|
| 143 | |
|---|
| 144 | void DNSPacket::clearRecords() |
|---|
| 145 | { |
|---|
| 146 | rrs.clear(); |
|---|
| 147 | } |
|---|
| 148 | |
|---|
| 149 | void DNSPacket::addRecord(const DNSResourceRecord &rr) |
|---|
| 150 | { |
|---|
| 151 | if(d_compress) |
|---|
| 152 | for(vector<DNSResourceRecord>::const_iterator i=rrs.begin();i!=rrs.end();++i) |
|---|
| 153 | if(rr.qname==i->qname && rr.qtype==i->qtype && rr.content==i->content) { |
|---|
| 154 | if(rr.qtype.getCode()!=QType::MX && rr.qtype.getCode()!=QType::SRV) |
|---|
| 155 | return; |
|---|
| 156 | if(rr.priority==i->priority) |
|---|
| 157 | return; |
|---|
| 158 | } |
|---|
| 159 | |
|---|
| 160 | rrs.push_back(rr); |
|---|
| 161 | } |
|---|
| 162 | |
|---|
| 163 | // the functions below update the 'arcount' and 'ancount', plus they serialize themselves to the stringbuffer |
|---|
| 164 | |
|---|
| 165 | string& attodot(string &str) |
|---|
| 166 | { |
|---|
| 167 | if(str.find_first_of("@")==string::npos) |
|---|
| 168 | return str; |
|---|
| 169 | |
|---|
| 170 | for (unsigned int i = 0; i < str.length(); i++) |
|---|
| 171 | { |
|---|
| 172 | if (str[i] == '@') { |
|---|
| 173 | str[i] = '.'; |
|---|
| 174 | break; |
|---|
| 175 | } else if (str[i] == '.') { |
|---|
| 176 | str.insert(i++, "\\"); |
|---|
| 177 | } |
|---|
| 178 | } |
|---|
| 179 | |
|---|
| 180 | return str; |
|---|
| 181 | } |
|---|
| 182 | |
|---|
| 183 | void fillSOAData(const string &content, SOAData &data) |
|---|
| 184 | { |
|---|
| 185 | // content consists of fields separated by spaces: |
|---|
| 186 | // nameservername hostmaster serial-number [refresh [retry [expire [ minimum] ] ] ] |
|---|
| 187 | |
|---|
| 188 | // fill out data with some plausible defaults: |
|---|
| 189 | // 10800 3600 604800 3600 |
|---|
| 190 | data.serial=0; |
|---|
| 191 | data.refresh=::arg().asNum("soa-refresh-default"); |
|---|
| 192 | data.retry=::arg().asNum("soa-retry-default"); |
|---|
| 193 | data.expire=::arg().asNum("soa-expire-default"); |
|---|
| 194 | data.default_ttl=::arg().asNum("soa-minimum-ttl"); |
|---|
| 195 | |
|---|
| 196 | vector<string>parts; |
|---|
| 197 | stringtok(parts,content); |
|---|
| 198 | int pleft=parts.size(); |
|---|
| 199 | |
|---|
| 200 | // cout<<"'"<<content<<"'"<<endl; |
|---|
| 201 | |
|---|
| 202 | if(pleft) |
|---|
| 203 | data.nameserver=parts[0]; |
|---|
| 204 | |
|---|
| 205 | if(pleft>1) |
|---|
| 206 | data.hostmaster=attodot(parts[1]); // ahu@ds9a.nl -> ahu.ds9a.nl, piet.puk@ds9a.nl -> piet\.puk.ds9a.nl |
|---|
| 207 | |
|---|
| 208 | if(pleft>2) |
|---|
| 209 | data.serial=strtoul(parts[2].c_str(), NULL, 10); |
|---|
| 210 | |
|---|
| 211 | if(pleft>3) |
|---|
| 212 | data.refresh=atoi(parts[3].c_str()); |
|---|
| 213 | |
|---|
| 214 | if(pleft>4) |
|---|
| 215 | data.retry=atoi(parts[4].c_str()); |
|---|
| 216 | |
|---|
| 217 | if(pleft>5) |
|---|
| 218 | data.expire=atoi(parts[5].c_str()); |
|---|
| 219 | |
|---|
| 220 | if(pleft>6) |
|---|
| 221 | data.default_ttl=atoi(parts[6].c_str()); |
|---|
| 222 | |
|---|
| 223 | } |
|---|
| 224 | |
|---|
| 225 | string serializeSOAData(const SOAData &d) |
|---|
| 226 | { |
|---|
| 227 | ostringstream o; |
|---|
| 228 | // nameservername hostmaster serial-number [refresh [retry [expire [ minimum] ] ] ] |
|---|
| 229 | o<<d.nameserver<<" "<< d.hostmaster <<" "<< d.serial <<" "<< d.refresh << " "<< d.retry << " "<< d.expire << " "<< d.default_ttl; |
|---|
| 230 | |
|---|
| 231 | return o.str(); |
|---|
| 232 | } |
|---|
| 233 | |
|---|
| 234 | |
|---|
| 235 | static int rrcomp(const DNSResourceRecord &A, const DNSResourceRecord &B) |
|---|
| 236 | { |
|---|
| 237 | if(A.d_place<B.d_place) |
|---|
| 238 | return 1; |
|---|
| 239 | |
|---|
| 240 | return 0; |
|---|
| 241 | } |
|---|
| 242 | |
|---|
| 243 | vector<DNSResourceRecord*> DNSPacket::getAPRecords() |
|---|
| 244 | { |
|---|
| 245 | vector<DNSResourceRecord*> arrs; |
|---|
| 246 | |
|---|
| 247 | for(vector<DNSResourceRecord>::iterator i=rrs.begin(); |
|---|
| 248 | i!=rrs.end(); |
|---|
| 249 | ++i) |
|---|
| 250 | { |
|---|
| 251 | if(i->d_place!=DNSResourceRecord::ADDITIONAL && |
|---|
| 252 | (i->qtype.getCode()==15 || |
|---|
| 253 | i->qtype.getCode()==2 )) // CNAME or MX or NS |
|---|
| 254 | { |
|---|
| 255 | arrs.push_back(&*i); |
|---|
| 256 | } |
|---|
| 257 | } |
|---|
| 258 | |
|---|
| 259 | return arrs; |
|---|
| 260 | |
|---|
| 261 | } |
|---|
| 262 | |
|---|
| 263 | void DNSPacket::setCompress(bool compress) |
|---|
| 264 | { |
|---|
| 265 | d_compress=compress; |
|---|
| 266 | stringbuffer.reserve(65000); |
|---|
| 267 | rrs.reserve(200); |
|---|
| 268 | } |
|---|
| 269 | |
|---|
| 270 | bool DNSPacket::couldBeCached() |
|---|
| 271 | { |
|---|
| 272 | return d_ednsping.empty() && !d_wantsnsid; |
|---|
| 273 | } |
|---|
| 274 | |
|---|
| 275 | /** Must be called before attempting to access getData(). This function stuffs all resource |
|---|
| 276 | * records found in rrs into the data buffer. It also frees resource records queued for us. |
|---|
| 277 | */ |
|---|
| 278 | void DNSPacket::wrapup(void) |
|---|
| 279 | { |
|---|
| 280 | if(d_wrapped) { |
|---|
| 281 | return; |
|---|
| 282 | } |
|---|
| 283 | |
|---|
| 284 | // do embedded-additional processing decapsulation |
|---|
| 285 | DNSResourceRecord rr; |
|---|
| 286 | vector<DNSResourceRecord>::iterator pos; |
|---|
| 287 | |
|---|
| 288 | vector<DNSResourceRecord> additional; |
|---|
| 289 | |
|---|
| 290 | int ipos=rrs.size(); |
|---|
| 291 | rrs.resize(rrs.size()+additional.size()); |
|---|
| 292 | copy(additional.begin(), additional.end(), rrs.begin()+ipos); |
|---|
| 293 | |
|---|
| 294 | // we now need to order rrs so that the different sections come at the right place |
|---|
| 295 | // we want a stable sort, based on the d_place field |
|---|
| 296 | |
|---|
| 297 | stable_sort(rrs.begin(),rrs.end(),rrcomp); |
|---|
| 298 | |
|---|
| 299 | static bool mustShuffle =::arg().mustDo("no-shuffle"); |
|---|
| 300 | |
|---|
| 301 | if(!d_tcp && !mustShuffle) { |
|---|
| 302 | shuffle(rrs); |
|---|
| 303 | } |
|---|
| 304 | d_wrapped=true; |
|---|
| 305 | |
|---|
| 306 | vector<uint8_t> packet; |
|---|
| 307 | DNSPacketWriter pw(packet, qdomain, qtype.getCode(), 1); |
|---|
| 308 | |
|---|
| 309 | pw.getHeader()->rcode=d.rcode; |
|---|
| 310 | pw.getHeader()->aa=d.aa; |
|---|
| 311 | pw.getHeader()->ra=d.ra; |
|---|
| 312 | pw.getHeader()->qr=d.qr; |
|---|
| 313 | pw.getHeader()->id=d.id; |
|---|
| 314 | pw.getHeader()->rd=d.rd; |
|---|
| 315 | |
|---|
| 316 | DNSPacketWriter::optvect_t opts; |
|---|
| 317 | if(d_wantsnsid) { |
|---|
| 318 | opts.push_back(make_pair(3, ::arg()["server-id"])); |
|---|
| 319 | } |
|---|
| 320 | |
|---|
| 321 | if(!d_ednsping.empty()) { |
|---|
| 322 | opts.push_back(make_pair(4, d_ednsping)); |
|---|
| 323 | } |
|---|
| 324 | |
|---|
| 325 | if(!rrs.empty() || !opts.empty()) { |
|---|
| 326 | try { |
|---|
| 327 | for(pos=rrs.begin(); pos < rrs.end(); ++pos) { |
|---|
| 328 | // this needs to deal with the 'prio' mismatch! |
|---|
| 329 | if(pos->qtype.getCode()==QType::MX || pos->qtype.getCode() == QType::SRV) { |
|---|
| 330 | pos->content = lexical_cast<string>(pos->priority) + " " + pos->content; |
|---|
| 331 | } |
|---|
| 332 | pw.startRecord(pos->qname, pos->qtype.getCode(), pos->ttl, 1, (DNSPacketWriter::Place)pos->d_place); |
|---|
| 333 | if(!pos->content.empty() && pos->qtype.getCode()==QType::TXT && pos->content[0]!='"') { |
|---|
| 334 | pos->content="\""+pos->content+"\""; |
|---|
| 335 | } |
|---|
| 336 | if(pos->content.empty()) // empty contents confuse the MOADNS setup |
|---|
| 337 | pos->content="."; |
|---|
| 338 | shared_ptr<DNSRecordContent> drc(DNSRecordContent::mastermake(pos->qtype.getCode(), 1, pos->content)); |
|---|
| 339 | drc->toPacket(pw); |
|---|
| 340 | } |
|---|
| 341 | if(!opts.empty()) |
|---|
| 342 | pw.addOpt(2800, 0, 0, opts); |
|---|
| 343 | |
|---|
| 344 | pw.commit(); |
|---|
| 345 | } |
|---|
| 346 | catch(exception& e) { |
|---|
| 347 | L<<Logger::Error<<"Exception: "<<e.what()<<endl; |
|---|
| 348 | throw; |
|---|
| 349 | } |
|---|
| 350 | } |
|---|
| 351 | stringbuffer.assign((char*)&packet[0], packet.size()); |
|---|
| 352 | len=packet.size(); |
|---|
| 353 | } |
|---|
| 354 | |
|---|
| 355 | |
|---|
| 356 | /** Truncates a packet that has already been wrapup()-ed, possibly via a call to getData(). Do not call this function |
|---|
| 357 | before having done this - it will possibly break your packet, or crash your program. |
|---|
| 358 | |
|---|
| 359 | This method sets the 'TC' bit in the stringbuffer, and caps the len attributed to new_length. |
|---|
| 360 | */ |
|---|
| 361 | |
|---|
| 362 | void DNSPacket::truncate(int new_length) |
|---|
| 363 | { |
|---|
| 364 | if(new_length>len || !d_wrapped) |
|---|
| 365 | return; |
|---|
| 366 | |
|---|
| 367 | DLOG(L<<Logger::Warning<<"Truncating a packet to "<< remote.toString() <<endl); |
|---|
| 368 | |
|---|
| 369 | len=new_length; |
|---|
| 370 | stringbuffer[2]|=2; // set TC |
|---|
| 371 | } |
|---|
| 372 | |
|---|
| 373 | |
|---|
| 374 | void DNSPacket::setQuestion(int op, const string &qd, int newqtype) |
|---|
| 375 | { |
|---|
| 376 | memset(&d,0,sizeof(d)); |
|---|
| 377 | d.id=Utility::random(); |
|---|
| 378 | d.rd=d.tc=d.aa=false; |
|---|
| 379 | d.qr=false; |
|---|
| 380 | d.qdcount=1; // is htons'ed later on |
|---|
| 381 | d.ancount=d.arcount=d.nscount=0; |
|---|
| 382 | d.opcode=op; |
|---|
| 383 | qdomain=qd; |
|---|
| 384 | qtype=newqtype; |
|---|
| 385 | } |
|---|
| 386 | |
|---|
| 387 | /** convenience function for creating a reply packet from a question packet. Do not forget to delete it after use! */ |
|---|
| 388 | DNSPacket *DNSPacket::replyPacket() const |
|---|
| 389 | { |
|---|
| 390 | DNSPacket *r=new DNSPacket; |
|---|
| 391 | r->setSocket(d_socket); |
|---|
| 392 | |
|---|
| 393 | r->setRemote(&remote); |
|---|
| 394 | r->setAnswer(true); // this implies the allocation of the header |
|---|
| 395 | r->setA(true); // and we are authoritative |
|---|
| 396 | r->setRA(0); // no recursion available |
|---|
| 397 | r->setRD(d.rd); // if you wanted to recurse, answer will say you wanted it (we don't do it) |
|---|
| 398 | r->setID(d.id); |
|---|
| 399 | r->setOpcode(d.opcode); |
|---|
| 400 | |
|---|
| 401 | r->d_dt=d_dt; |
|---|
| 402 | r->d.qdcount=1; |
|---|
| 403 | r->d_tcp = d_tcp; |
|---|
| 404 | r->qdomain = qdomain; |
|---|
| 405 | r->qtype = qtype; |
|---|
| 406 | r->d_maxreplylen = d_maxreplylen; |
|---|
| 407 | r->d_ednsping = d_ednsping; |
|---|
| 408 | r->d_wantsnsid = d_wantsnsid; |
|---|
| 409 | return r; |
|---|
| 410 | } |
|---|
| 411 | |
|---|
| 412 | void DNSPacket::spoofQuestion(const string &qd) |
|---|
| 413 | { |
|---|
| 414 | string label=simpleCompress(qd); |
|---|
| 415 | for(string::size_type i=0;i<label.size();++i) |
|---|
| 416 | stringbuffer[i+sizeof(d)]=label[i]; |
|---|
| 417 | d_wrapped=true; // if we do this, don't later on wrapup |
|---|
| 418 | } |
|---|
| 419 | |
|---|
| 420 | /** This function takes data from the network, possibly received with recvfrom, and parses |
|---|
| 421 | it into our class. Results of calling this function multiple times on one packet are |
|---|
| 422 | unknown. Returns -1 if the packet cannot be parsed. |
|---|
| 423 | */ |
|---|
| 424 | int DNSPacket::parse(const char *mesg, int length) |
|---|
| 425 | try |
|---|
| 426 | { |
|---|
| 427 | stringbuffer.assign(mesg,length); |
|---|
| 428 | |
|---|
| 429 | len=length; |
|---|
| 430 | if(length < 12) { |
|---|
| 431 | L << Logger::Warning << "Ignoring packet: too short from " |
|---|
| 432 | << getRemote() << endl; |
|---|
| 433 | return -1; |
|---|
| 434 | } |
|---|
| 435 | |
|---|
| 436 | MOADNSParser mdp(stringbuffer); |
|---|
| 437 | EDNSOpts edo; |
|---|
| 438 | |
|---|
| 439 | // ANY OPTION WHICH *MIGHT* BE SET DOWN BELOW SHOULD BE CLEARED FIRST! |
|---|
| 440 | |
|---|
| 441 | d_wantsnsid=false; |
|---|
| 442 | d_ednsping.clear(); |
|---|
| 443 | |
|---|
| 444 | if(getEDNSOpts(mdp, &edo)) { |
|---|
| 445 | d_maxreplylen=max(edo.d_packetsize, (uint16_t)1280); |
|---|
| 446 | |
|---|
| 447 | for(vector<pair<uint16_t, string> >::const_iterator iter = edo.d_options.begin(); |
|---|
| 448 | iter != edo.d_options.end(); |
|---|
| 449 | ++iter) { |
|---|
| 450 | if(iter->first == 3) {// 'EDNS NSID' |
|---|
| 451 | d_wantsnsid=1; |
|---|
| 452 | } |
|---|
| 453 | else if(iter->first == 5) {// 'EDNS PING' |
|---|
| 454 | d_ednsping = iter->second; |
|---|
| 455 | } |
|---|
| 456 | else |
|---|
| 457 | ; // cerr<<"Have an option #"<<iter->first<<endl; |
|---|
| 458 | } |
|---|
| 459 | } |
|---|
| 460 | else { |
|---|
| 461 | d_maxreplylen=512; |
|---|
| 462 | } |
|---|
| 463 | |
|---|
| 464 | memcpy((void *)&d,(const void *)stringbuffer.c_str(),12); |
|---|
| 465 | qdomain=mdp.d_qname; |
|---|
| 466 | if(!qdomain.empty()) // strip dot |
|---|
| 467 | erase_tail(qdomain, 1); |
|---|
| 468 | |
|---|
| 469 | if(!ntohs(d.qdcount)) { |
|---|
| 470 | if(!d_tcp) { |
|---|
| 471 | L << Logger::Warning << "No question section in packet from " << getRemote() <<", rcode="<<(int)d.rcode<<endl; |
|---|
| 472 | return -1; |
|---|
| 473 | } |
|---|
| 474 | } |
|---|
| 475 | |
|---|
| 476 | qtype=mdp.d_qtype; |
|---|
| 477 | qclass=mdp.d_qclass; |
|---|
| 478 | return 0; |
|---|
| 479 | } |
|---|
| 480 | catch(exception& e) { |
|---|
| 481 | return -1; |
|---|
| 482 | } |
|---|
| 483 | |
|---|
| 484 | int DNSPacket::getMaxReplyLen() |
|---|
| 485 | { |
|---|
| 486 | return d_maxreplylen; |
|---|
| 487 | } |
|---|
| 488 | |
|---|
| 489 | //! Use this to set where this packet was received from or should be sent to |
|---|
| 490 | void DNSPacket::setRemote(const ComboAddress *s) |
|---|
| 491 | { |
|---|
| 492 | remote=*s; |
|---|
| 493 | } |
|---|
| 494 | |
|---|
| 495 | void DNSPacket::spoofID(uint16_t id) |
|---|
| 496 | { |
|---|
| 497 | stringbuffer[1]=(id>>8)&0xff; |
|---|
| 498 | stringbuffer[0]=id&0xff; |
|---|
| 499 | d.id=id; |
|---|
| 500 | } |
|---|
| 501 | |
|---|
| 502 | void DNSPacket::setSocket(Utility::sock_t sock) |
|---|
| 503 | { |
|---|
| 504 | d_socket=sock; |
|---|
| 505 | } |
|---|
| 506 | |
|---|
| 507 | void DNSPacket::commitD() |
|---|
| 508 | { |
|---|
| 509 | stringbuffer.replace(0,12,(char *)&d,12); // copy in d |
|---|
| 510 | } |
|---|
| 511 | |
|---|