]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/dnsrecords.cc
report TXT only once, thanks @zeha
[thirdparty/pdns.git] / pdns / dnsrecords.cc
CommitLineData
4192ca66
BH
1/*
2 PowerDNS Versatile Database Driven Nameserver
0407751c 3 Copyright (C) 2005 - 2009 PowerDNS.COM BV
4192ca66
BH
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
ff6a1e7b 8
4192ca66
BH
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.
2770fad0 13
4192ca66
BH
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
06bd9ccf 16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
4192ca66
BH
17*/
18
705f31ae 19#include "utility.hh"
4192ca66 20#include "dnsrecords.hh"
0e4ab7bc 21#include <boost/foreach.hpp>
2770fad0 22
8c1c9170
BH
23boilerplate_conv(A, ns_t_a, conv.xfrIP(d_ip));
24
efb265e3
BH
25ARecordContent::ARecordContent(uint32_t ip) : DNSRecordContent(ns_t_a)
26{
27 d_ip = ip;
28}
29
748eff9f
BH
30uint32_t ARecordContent::getIP() const
31{
32 return d_ip;
33}
34
2770fad0
BH
35void ARecordContent::doRecordCheck(const DNSRecord& dr)
36{
37 if(dr.d_clen!=4)
7738a23f 38 throw MOADNSException("Wrong size for A record ("+lexical_cast<string>(dr.d_clen)+")");
a0a276c2 39}
ff6a1e7b 40
fc465b41 41boilerplate_conv(AAAA, ns_t_aaaa, conv.xfrIP6(d_ip6); );
9d9c52ef 42
bca6643b
BH
43boilerplate_conv(NS, ns_t_ns, conv.xfrLabel(d_content, true));
44boilerplate_conv(PTR, ns_t_ptr, conv.xfrLabel(d_content, true));
45boilerplate_conv(CNAME, ns_t_cname, conv.xfrLabel(d_content, true));
2dd20a07 46boilerplate_conv(MR, ns_t_mr, conv.xfrLabel(d_alias, true));
7c0b8593 47boilerplate_conv(MINFO, ns_t_minfo, conv.xfrLabel(d_rmailbx, true); conv.xfrLabel(d_emailbx, true));
ef6a78d5
BH
48boilerplate_conv(TXT, ns_t_txt, conv.xfrText(d_text, true));
49boilerplate_conv(SPF, 99, conv.xfrText(d_text, true));
8c1c9170 50boilerplate_conv(HINFO, ns_t_hinfo, conv.xfrText(d_cpu); conv.xfrText(d_host));
ff6a1e7b 51
8c1c9170 52boilerplate_conv(RP, ns_t_rp,
4957a608
BH
53 conv.xfrLabel(d_mbox);
54 conv.xfrLabel(d_info)
55 );
ff6a1e7b 56
ff6a1e7b 57
7f7b8d55 58boilerplate_conv(OPT, ns_t_opt,
4957a608
BH
59 conv.xfrBlob(d_data)
60 );
878435ce 61
7f7b8d55
BH
62void OPTRecordContent::getData(vector<pair<uint16_t, string> >& options)
63{
64 string::size_type pos=0;
65 uint16_t code, len;
66 while(d_data.size() >= 4 + pos) {
17d6efc0
BH
67 code = 256 * (unsigned char)d_data[pos] + (unsigned char)d_data[pos+1];
68 len = 256 * (unsigned char)d_data[pos+2] + (unsigned char)d_data[pos+3];
7f7b8d55
BH
69 pos+=4;
70
71 if(pos + len > d_data.size())
72 break;
73
74 string field(d_data.c_str() + pos, len);
75 pos+=len;
7f7b8d55
BH
76 options.push_back(make_pair(code, field));
77 }
78}
06ffdc52 79
a6a83beb 80boilerplate_conv(TSIG, ns_t_tsig,
4957a608
BH
81 conv.xfrLabel(d_algoName);
82 conv.xfr48BitInt(d_time);
83 conv.xfr16BitInt(d_fudge);
84 uint16_t size=d_mac.size();
85 conv.xfr16BitInt(size);
86 conv.xfrBlob(d_mac, size);
87 conv.xfr16BitInt(d_origID);
88 conv.xfr16BitInt(d_eRcode);
a6a83beb
AT
89 size=d_otherData.size();
90 conv.xfr16BitInt(size);
91 if (size>0) conv.xfrBlob(d_otherData, size);
4957a608 92 );
06ffdc52 93
ea634573 94MXRecordContent::MXRecordContent(uint16_t preference, const string& mxname) : DNSRecordContent(ns_t_mx), d_preference(preference), d_mxname(mxname)
2770fad0
BH
95{
96}
ff6a1e7b 97
8c1c9170 98boilerplate_conv(MX, ns_t_mx,
4957a608
BH
99 conv.xfr16BitInt(d_preference);
100 conv.xfrLabel(d_mxname, true);
101 )
ff6a1e7b 102
39d464c4 103boilerplate_conv(KX, ns_t_kx,
4957a608
BH
104 conv.xfr16BitInt(d_preference);
105 conv.xfrLabel(d_exchanger, false);
106 )
9fd71f2e 107
74b3a069 108boilerplate_conv(IPSECKEY, ns_t_ipseckey,
1cafb958
AT
109 conv.xfr8BitInt(d_preference);
110 conv.xfr8BitInt(d_gatewaytype);
111 conv.xfr8BitInt(d_algorithm);
112
113 // now we need to determine values
114 switch(d_gatewaytype) {
115 case 0: // NO KEY
116 break;
117 case 1: // IPv4 GW
118 conv.xfrIP(d_ip4);
119 break;
120 case 2: // IPv6 GW
121 conv.xfrIP6(d_ip6);
122 break;
123 case 3: // DNS label
124 conv.xfrLabel(d_gateway, false);
125 break;
126 default:
127 throw MOADNSException("Parsing record content: invalid gateway type");
128 };
129
130 switch(d_algorithm) {
131 case 0:
132 break;
133 case 1:
134 case 2:
135 conv.xfrBlob(d_publickey);
136 break;
137 default:
138 throw MOADNSException("Parsing record content: invalid algorithm type");
74b3a069
AT
139 }
140)
9fd71f2e
BH
141
142boilerplate_conv(DHCID, 49,
4957a608
BH
143 conv.xfrBlob(d_content);
144 )
9fd71f2e
BH
145
146
37f47031 147boilerplate_conv(AFSDB, ns_t_afsdb,
4957a608
BH
148 conv.xfr16BitInt(d_subtype);
149 conv.xfrLabel(d_hostname);
150 )
37f47031 151
ff6a1e7b 152
8c1c9170 153boilerplate_conv(NAPTR, ns_t_naptr,
4957a608
BH
154 conv.xfr16BitInt(d_order); conv.xfr16BitInt(d_preference);
155 conv.xfrText(d_flags); conv.xfrText(d_services); conv.xfrText(d_regexp);
156 conv.xfrLabel(d_replacement);
157 )
8c1c9170 158
ff6a1e7b 159
2770fad0 160SRVRecordContent::SRVRecordContent(uint16_t preference, uint16_t weight, uint16_t port, const string& target)
ea634573 161 : DNSRecordContent(ns_t_srv), d_preference(preference), d_weight(weight), d_port(port), d_target(target)
2770fad0 162{}
ff6a1e7b 163
8c1c9170 164boilerplate_conv(SRV, ns_t_srv,
4957a608 165 conv.xfr16BitInt(d_preference); conv.xfr16BitInt(d_weight); conv.xfr16BitInt(d_port);
8655a427 166 conv.xfrLabel(d_target);
4957a608 167 )
9d9c52ef 168
2770fad0 169SOARecordContent::SOARecordContent(const string& mname, const string& rname, const struct soatimes& st)
ea634573 170 : DNSRecordContent(ns_t_soa), d_mname(mname), d_rname(rname)
a0a276c2 171{
2770fad0 172 d_st=st;
a0a276c2 173}
9d9c52ef 174
8c1c9170 175boilerplate_conv(SOA, ns_t_soa,
4957a608
BH
176 conv.xfrLabel(d_mname, true);
177 conv.xfrLabel(d_rname, true);
178 conv.xfr32BitInt(d_st.serial);
179 conv.xfr32BitInt(d_st.refresh);
180 conv.xfr32BitInt(d_st.retry);
181 conv.xfr32BitInt(d_st.expire);
182 conv.xfr32BitInt(d_st.minimum);
183 );
4b5762f1
BH
184#undef KEY
185boilerplate_conv(KEY, ns_t_key,
4957a608
BH
186 conv.xfr16BitInt(d_flags);
187 conv.xfr8BitInt(d_protocol);
188 conv.xfr8BitInt(d_algorithm);
189 conv.xfrBlob(d_certificate);
190 );
8c1c9170 191
2475a4fc 192boilerplate_conv(CERT, 37,
4957a608 193 conv.xfr16BitInt(d_type);
689516b3
AT
194 if (d_type == 0) throw MOADNSException("CERT type 0 is reserved");
195
4957a608
BH
196 conv.xfr16BitInt(d_tag);
197 conv.xfr8BitInt(d_algorithm);
689516b3
AT
198 conv.xfrBlob(d_certificate);
199 )
200
2a4e06e9 201boilerplate_conv(TLSA, 52,
f5a09796
PD
202 conv.xfr8BitInt(d_certusage);
203 conv.xfr8BitInt(d_selector);
204 conv.xfr8BitInt(d_matchtype);
b9ec21ad 205 conv.xfrHexBlob(d_cert, true);
07dbe87e
BH
206 )
207
6a5b669b 208#undef DS
1c4d88c5 209DSRecordContent::DSRecordContent() : DNSRecordContent(43) {}
8c1c9170 210boilerplate_conv(DS, 43,
4957a608
BH
211 conv.xfr16BitInt(d_tag);
212 conv.xfr8BitInt(d_algorithm);
213 conv.xfr8BitInt(d_digesttype);
e4090157 214 conv.xfrHexBlob(d_digest, true); // keep reading across spaces
4957a608 215 )
8c1c9170 216
0b55f2f5
BH
217DLVRecordContent::DLVRecordContent() : DNSRecordContent(32769) {}
218boilerplate_conv(DLV,32769 ,
219 conv.xfr16BitInt(d_tag);
220 conv.xfr8BitInt(d_algorithm);
221 conv.xfr8BitInt(d_digesttype);
222 conv.xfrHexBlob(d_digest, true); // keep reading across spaces
223 )
224
225
a40a693b 226boilerplate_conv(SSHFP, 44,
4957a608
BH
227 conv.xfr8BitInt(d_algorithm);
228 conv.xfr8BitInt(d_fptype);
229 conv.xfrHexBlob(d_fingerprint);
230 )
a40a693b 231
8c1c9170 232boilerplate_conv(RRSIG, 46,
4957a608
BH
233 conv.xfrType(d_type);
234 conv.xfr8BitInt(d_algorithm);
235 conv.xfr8BitInt(d_labels);
4957a608
BH
236 conv.xfr32BitInt(d_originalttl);
237 conv.xfrTime(d_sigexpire);
238 conv.xfrTime(d_siginception);
239 conv.xfr16BitInt(d_tag);
240 conv.xfrLabel(d_signer);
241 conv.xfrBlob(d_signature);
242 )
243
1c4d88c5
BH
244RRSIGRecordContent::RRSIGRecordContent() : DNSRecordContent(46) {}
245
8c1c9170 246boilerplate_conv(DNSKEY, 48,
4957a608
BH
247 conv.xfr16BitInt(d_flags);
248 conv.xfr8BitInt(d_protocol);
249 conv.xfr8BitInt(d_algorithm);
250 conv.xfrBlob(d_key);
251 )
1c4d88c5
BH
252DNSKEYRecordContent::DNSKEYRecordContent() : DNSRecordContent(48) {}
253
66a07c55
AT
254/* EUI48 start */
255
256void EUI48RecordContent::report(void)
257{
258 regist(1, ns_t_eui48, &make, &make, "EUI48");
259}
260DNSRecordContent* EUI48RecordContent::make(const DNSRecord &dr, PacketReader& pr)
261{
262 if(dr.d_clen!=6)
263 throw MOADNSException("Wrong size for EUI48 record");
264
265 EUI48RecordContent* ret=new EUI48RecordContent();
266 pr.copyRecord((uint8_t*) &ret->d_eui48, 6);
267 return ret;
268}
269DNSRecordContent* EUI48RecordContent::make(const string& zone)
270{
271 // try to parse
272 EUI48RecordContent *ret=new EUI48RecordContent();
273 // format is 6 hex bytes and dashes
274 if (sscanf(zone.c_str(), "%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx",
275 ret->d_eui48, ret->d_eui48+1, ret->d_eui48+2,
276 ret->d_eui48+3, ret->d_eui48+4, ret->d_eui48+5) != 6) {
0fc965fd 277 throw MOADNSException("Asked to encode '"+zone+"' as an EUI48 address, but does not parse");
66a07c55
AT
278 }
279 return ret;
280}
281void EUI48RecordContent::toPacket(DNSPacketWriter& pw)
282{
283 string blob(d_eui48, d_eui48+6);
284 pw.xfrBlob(blob);
285}
286string EUI48RecordContent::getZoneRepresentation() const
287{
288 char tmp[18];
289 snprintf(tmp,18,"%02x-%02x-%02x-%02x-%02x-%02x",
290 d_eui48[0], d_eui48[1], d_eui48[2],
291 d_eui48[3], d_eui48[4], d_eui48[5]);
292 return tmp;
293}
294
295/* EUI48 end */
296
297/* EUI64 start */
298
299void EUI64RecordContent::report(void)
300{
301 regist(1, ns_t_eui64, &make, &make, "EUI64");
302}
303DNSRecordContent* EUI64RecordContent::make(const DNSRecord &dr, PacketReader& pr)
304{
305 if(dr.d_clen!=8)
306 throw MOADNSException("Wrong size for EUI64 record");
307
308 EUI64RecordContent* ret=new EUI64RecordContent();
309 pr.copyRecord((uint8_t*) &ret->d_eui64, 8);
310 return ret;
311}
312DNSRecordContent* EUI64RecordContent::make(const string& zone)
313{
314 // try to parse
315 EUI64RecordContent *ret=new EUI64RecordContent();
316 // format is 8 hex bytes and dashes
317 if (sscanf(zone.c_str(), "%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx",
318 ret->d_eui64, ret->d_eui64+1, ret->d_eui64+2,
319 ret->d_eui64+3, ret->d_eui64+4, ret->d_eui64+5,
320 ret->d_eui64+6, ret->d_eui64+7) != 8) {
321 throw MOADNSException("Asked to encode '"+zone+"' as an EUI64 address, but does not parse");
322 }
323 return ret;
324}
325void EUI64RecordContent::toPacket(DNSPacketWriter& pw)
326{
327 string blob(d_eui64, d_eui64+8);
328 pw.xfrBlob(blob);
329}
330string EUI64RecordContent::getZoneRepresentation() const
331{
332 char tmp[24];
333 snprintf(tmp,24,"%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x",
334 d_eui64[0], d_eui64[1], d_eui64[2],
335 d_eui64[3], d_eui64[4], d_eui64[5],
336 d_eui64[6], d_eui64[7]);
337 return tmp;
338}
339
340/* EUI64 end */
341
342
1c4d88c5
BH
343uint16_t DNSKEYRecordContent::getTag()
344{
345 string data=this->serialize("");
346 const unsigned char* key=(const unsigned char*)data.c_str();
347 unsigned int keysize=data.length();
348
349 unsigned long ac; /* assumed to be 32 bits or larger */
350 unsigned int i; /* loop index */
351
352 for ( ac = 0, i = 0; i < keysize; ++i )
353 ac += (i & 1) ? key[i] : key[i] << 8;
354 ac += (ac >> 16) & 0xFFFF;
355 return ac & 0xFFFF;
356}
357
d34d3e01
BH
358// "fancy records"
359boilerplate_conv(URL, QType::URL,
4957a608
BH
360 conv.xfrLabel(d_url);
361 )
7f7b8d55 362
d34d3e01 363boilerplate_conv(MBOXFW, QType::MBOXFW,
4957a608
BH
364 conv.xfrLabel(d_mboxfw);
365 )
d34d3e01 366
0e4ab7bc
BH
367
368
7f7b8d55
BH
369bool getEDNSOpts(const MOADNSParser& mdp, EDNSOpts* eo)
370{
0e4ab7bc
BH
371 if(mdp.d_header.arcount && !mdp.d_answers.empty()) {
372 BOOST_FOREACH(const MOADNSParser::answers_t::value_type& val, mdp.d_answers) {
373 if(val.first.d_place == DNSRecord::Additional && val.first.d_type == QType::OPT) {
374 eo->d_packetsize=val.first.d_class;
375
376 EDNS0Record stuff;
377 uint32_t ttl=ntohl(val.first.d_ttl);
378 memcpy(&stuff, &ttl, sizeof(stuff));
379
380 eo->d_extRCode=stuff.extRCode;
381 eo->d_version=stuff.version;
382 eo->d_Z = ntohs(stuff.Z);
383 OPTRecordContent* orc =
384 dynamic_cast<OPTRecordContent*>(val.first.d_content.get());
385 if(!orc)
386 return false;
387 orc->getData(eo->d_options);
388 return true;
389 }
390 }
7f7b8d55 391 }
0e4ab7bc 392 return false;
7f7b8d55
BH
393}
394
395
ea634573 396void reportBasicTypes()
ff6a1e7b 397{
a9af3782
BH
398 ARecordContent::report();
399 AAAARecordContent::report();
400 NSRecordContent::report();
401 CNAMERecordContent::report();
402 MXRecordContent::report();
403 SOARecordContent::report();
404 SRVRecordContent::report();
405 PTRRecordContent::report();
a6a83beb
AT
406 //DNSRecordContent::regist(3, ns_t_txt, &TXTRecordContent::make, &TXTRecordContent::make, "TXT");
407 TXTRecordContent::report();
0407751c 408 DNSRecordContent::regist(1, QType::ANY, 0, 0, "ANY");
ea634573
BH
409}
410
411void reportOtherTypes()
412{
37f47031 413 AFSDBRecordContent::report();
ea634573
BH
414 SPFRecordContent::report();
415 NAPTRRecordContent::report();
c6a60874 416 LOCRecordContent::report();
9770663f 417 HINFORecordContent::report();
ea634573 418 RPRecordContent::report();
4b5762f1 419 KEYRecordContent::report();
ea634573
BH
420 DNSKEYRecordContent::report();
421 RRSIGRecordContent::report();
422 DSRecordContent::report();
59a0f653 423 SSHFPRecordContent::report();
2475a4fc 424 CERTRecordContent::report();
ea634573 425 NSECRecordContent::report();
1c4d88c5
BH
426 NSEC3RecordContent::report();
427 NSEC3PARAMRecordContent::report();
07dbe87e 428 TLSARecordContent::report();
4fb75774 429 DLVRecordContent::report();
a6a83beb
AT
430 //DNSRecordContent::regist(0xff, QType::TSIG, &TSIGRecordContent::make, &TSIGRecordContent::make, "TSIG");
431 TSIGRecordContent::report();
ea634573 432 OPTRecordContent::report();
66a07c55
AT
433 EUI48RecordContent::report();
434 EUI64RecordContent::report();
5eea7309 435 MINFORecordContent::report();
ea634573
BH
436}
437
afbb76cd
BH
438void reportFancyTypes()
439{
440 URLRecordContent::report();
d34d3e01 441 MBOXFWRecordContent::report();
afbb76cd
BH
442}
443
ea634573
BH
444void reportAllTypes()
445{
446 reportBasicTypes();
447 reportOtherTypes();
448}
449
450#if 0
451static struct Reporter
452{
453 Reporter()
454 {
455 reportAllTypes();
ff6a1e7b
BH
456 }
457} reporter __attribute__((init_priority(65535)));
250d1fd8 458#endif