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