root/trunk/pdns/pdns/dnsrecords.cc @ 2338

Revision 2338, 10.8 KB (checked in by peter, 2 years ago)

Update DANE/TLSA support to comply with newer drafts. Spotted by James Cloos

Line 
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
23boilerplate_conv(A, ns_t_a, conv.xfrIP(d_ip));
24
25ARecordContent::ARecordContent(uint32_t ip) : DNSRecordContent(ns_t_a)
26{
27  d_ip = ip;
28}
29
30uint32_t ARecordContent::getIP() const
31{
32  return d_ip;
33}
34
35void 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
41class AAAARecordContent : public DNSRecordContent
42{
43public:
44  AAAARecordContent() : DNSRecordContent(ns_t_aaaa)
45  {}
46
47  static void report(void)
48  {
49    regist(1, ns_t_aaaa, &make, &make, "AAAA");
50  }
51
52  static DNSRecordContent* make(const DNSRecord &dr, PacketReader& pr) 
53  {
54    if(dr.d_clen!=16)
55      throw MOADNSException("Wrong size for AAAA record");
56
57    AAAARecordContent* ret=new AAAARecordContent();
58    pr.copyRecord((unsigned char*) &ret->d_ip6, 16);
59    return ret;
60  }
61
62  static DNSRecordContent* make(const string& zone) 
63  {
64    AAAARecordContent *ar=new AAAARecordContent();
65    if(Utility::inet_pton( AF_INET6, zone.c_str(), static_cast< void * >( ar->d_ip6 )) <= 0)
66      throw MOADNSException("Asked to encode '"+zone+"' as an IPv6 address, but does not parse");
67    return ar;
68  }
69
70  void toPacket(DNSPacketWriter& pw)
71  {
72    string blob(d_ip6, d_ip6+16);
73    pw.xfrBlob(blob);
74  }
75 
76  string getZoneRepresentation() const
77  {
78    struct sockaddr_in6 addr;
79    memset(&addr, 0, sizeof(addr));
80    addr.sin6_family=AF_INET6;
81    memcpy(&addr.sin6_addr, d_ip6, 16);
82
83    char tmp[128];
84    tmp[0]=0;
85    Utility::inet_ntop(AF_INET6, (const char*)& addr.sin6_addr, tmp, sizeof(tmp));
86    return tmp;
87  }
88
89private:
90  unsigned char d_ip6[16];
91};
92
93
94
95boilerplate_conv(NS, ns_t_ns, conv.xfrLabel(d_content, true));
96boilerplate_conv(PTR, ns_t_ptr, conv.xfrLabel(d_content, true));
97boilerplate_conv(CNAME, ns_t_cname, conv.xfrLabel(d_content, true));
98boilerplate_conv(MR, ns_t_mr, conv.xfrLabel(d_alias, false));
99boilerplate_conv(TXT, ns_t_txt, conv.xfrText(d_text, true));
100boilerplate_conv(SPF, 99, conv.xfrText(d_text, true));
101boilerplate_conv(HINFO, ns_t_hinfo,  conv.xfrText(d_cpu);   conv.xfrText(d_host));
102
103boilerplate_conv(RP, ns_t_rp,
104                 conv.xfrLabel(d_mbox);   
105                 conv.xfrLabel(d_info)
106                 );
107
108
109boilerplate_conv(OPT, ns_t_opt, 
110                   conv.xfrBlob(d_data)
111                 );
112
113void OPTRecordContent::getData(vector<pair<uint16_t, string> >& options)
114{
115  string::size_type pos=0;
116  uint16_t code, len;
117  while(d_data.size() >= 4 + pos) {
118    code = 256 * (unsigned char)d_data[pos] + (unsigned char)d_data[pos+1];
119    len = 256 * (unsigned char)d_data[pos+2] + (unsigned char)d_data[pos+3];
120    pos+=4;
121
122    if(pos + len > d_data.size())
123      break;
124
125    string field(d_data.c_str() + pos, len);
126    pos+=len;
127    options.push_back(make_pair(code, field));
128  }
129}
130
131boilerplate_conv(TSIG, ns_t_tsig, 
132                 conv.xfrLabel(d_algoName);
133                 conv.xfr48BitInt(d_time);
134                 conv.xfr16BitInt(d_fudge);
135                 uint16_t size=d_mac.size();
136                 conv.xfr16BitInt(size);
137                 conv.xfrBlob(d_mac, size);
138                 conv.xfr16BitInt(d_origID);
139                 conv.xfr16BitInt(d_eRcode);
140                 size=d_otherData.size();
141                 conv.xfr16BitInt(size);
142                 conv.xfrBlob(d_otherData, size);
143                 );
144
145MXRecordContent::MXRecordContent(uint16_t preference, const string& mxname) : DNSRecordContent(ns_t_mx), d_preference(preference), d_mxname(mxname)
146{
147}
148
149boilerplate_conv(MX, ns_t_mx, 
150                 conv.xfr16BitInt(d_preference);
151                 conv.xfrLabel(d_mxname, true);
152                 )
153
154boilerplate_conv(KX, ns_t_kx, 
155                 conv.xfr16BitInt(d_preference);
156                 conv.xfrLabel(d_exchanger, false);
157                 )
158
159boilerplate_conv(IPSECKEY, 45,  /* ns_t_ipsec */
160                 conv.xfr8BitInt(d_preference);
161                 conv.xfr8BitInt(d_gatewaytype);
162                 conv.xfr8BitInt(d_algorithm);
163                 conv.xfrLabel(d_gateway, false);
164                 conv.xfrBlob(d_publickey);
165                 )
166
167boilerplate_conv(DHCID, 49, 
168                 conv.xfrBlob(d_content);
169                 )
170
171
172boilerplate_conv(AFSDB, ns_t_afsdb, 
173                 conv.xfr16BitInt(d_subtype);
174                 conv.xfrLabel(d_hostname);
175                 )
176
177
178boilerplate_conv(NAPTR, ns_t_naptr,
179                 conv.xfr16BitInt(d_order);    conv.xfr16BitInt(d_preference);
180                 conv.xfrText(d_flags);        conv.xfrText(d_services);         conv.xfrText(d_regexp);
181                 conv.xfrLabel(d_replacement);
182                 )
183
184
185SRVRecordContent::SRVRecordContent(uint16_t preference, uint16_t weight, uint16_t port, const string& target) 
186  : DNSRecordContent(ns_t_srv), d_preference(preference), d_weight(weight), d_port(port), d_target(target)
187{}
188
189boilerplate_conv(SRV, ns_t_srv, 
190                 conv.xfr16BitInt(d_preference);   conv.xfr16BitInt(d_weight);   conv.xfr16BitInt(d_port);
191                 conv.xfrLabel(d_target);
192                 )
193
194
195
196SOARecordContent::SOARecordContent(const string& mname, const string& rname, const struct soatimes& st) 
197  : DNSRecordContent(ns_t_soa), d_mname(mname), d_rname(rname)
198{
199  d_st=st;
200}
201
202boilerplate_conv(SOA, ns_t_soa, 
203                 conv.xfrLabel(d_mname, true);
204                 conv.xfrLabel(d_rname, true);
205                 conv.xfr32BitInt(d_st.serial);
206                 conv.xfr32BitInt(d_st.refresh);
207                 conv.xfr32BitInt(d_st.retry);
208                 conv.xfr32BitInt(d_st.expire);
209                 conv.xfr32BitInt(d_st.minimum);
210                 );
211#undef KEY
212boilerplate_conv(KEY, ns_t_key, 
213                 conv.xfr16BitInt(d_flags); 
214                 conv.xfr8BitInt(d_protocol); 
215                 conv.xfr8BitInt(d_algorithm); 
216                 conv.xfrBlob(d_certificate);
217                 );
218
219boilerplate_conv(CERT, 37, 
220                 conv.xfr16BitInt(d_type); 
221                 conv.xfr16BitInt(d_tag); 
222                 conv.xfr8BitInt(d_algorithm); 
223                 conv.xfrBlob(d_certificate);
224                 )
225                 
226boilerplate_conv(TLSA, 65468, 
227                 conv.xfr8BitInt(d_certusage); 
228                 conv.xfr8BitInt(d_selector); 
229                 conv.xfr8BitInt(d_matchtype); 
230                 conv.xfrBlob(d_cert);
231                 )               
232                 
233#undef DS
234DSRecordContent::DSRecordContent() : DNSRecordContent(43) {}
235boilerplate_conv(DS, 43, 
236                 conv.xfr16BitInt(d_tag); 
237                 conv.xfr8BitInt(d_algorithm); 
238                 conv.xfr8BitInt(d_digesttype); 
239                 conv.xfrHexBlob(d_digest, true); // keep reading across spaces
240                 )
241
242DLVRecordContent::DLVRecordContent() : DNSRecordContent(32769) {}
243boilerplate_conv(DLV,32769 , 
244                 conv.xfr16BitInt(d_tag); 
245                 conv.xfr8BitInt(d_algorithm); 
246                 conv.xfr8BitInt(d_digesttype); 
247                 conv.xfrHexBlob(d_digest, true); // keep reading across spaces
248                 )
249
250
251boilerplate_conv(SSHFP, 44, 
252                 conv.xfr8BitInt(d_algorithm); 
253                 conv.xfr8BitInt(d_fptype); 
254                 conv.xfrHexBlob(d_fingerprint);
255                 )
256
257boilerplate_conv(RRSIG, 46, 
258                 conv.xfrType(d_type); 
259                 conv.xfr8BitInt(d_algorithm); 
260                 conv.xfr8BitInt(d_labels); 
261                 conv.xfr32BitInt(d_originalttl); 
262                 conv.xfrTime(d_sigexpire); 
263                 conv.xfrTime(d_siginception); 
264                 conv.xfr16BitInt(d_tag); 
265                 conv.xfrLabel(d_signer);
266                 conv.xfrBlob(d_signature);
267                 )
268                 
269RRSIGRecordContent::RRSIGRecordContent() : DNSRecordContent(46) {}
270
271boilerplate_conv(DNSKEY, 48, 
272                 conv.xfr16BitInt(d_flags); 
273                 conv.xfr8BitInt(d_protocol); 
274                 conv.xfr8BitInt(d_algorithm); 
275                 conv.xfrBlob(d_key);
276                 )
277DNSKEYRecordContent::DNSKEYRecordContent() : DNSRecordContent(48) {}
278
279uint16_t DNSKEYRecordContent::getTag()
280{
281  string data=this->serialize("");
282  const unsigned char* key=(const unsigned char*)data.c_str();
283  unsigned int keysize=data.length();
284
285  unsigned long ac;     /* assumed to be 32 bits or larger */
286  unsigned int i;                /* loop index */
287 
288  for ( ac = 0, i = 0; i < keysize; ++i )
289    ac += (i & 1) ? key[i] : key[i] << 8;
290  ac += (ac >> 16) & 0xFFFF;
291  return ac & 0xFFFF;
292}
293
294// "fancy records"
295boilerplate_conv(URL, QType::URL, 
296                 conv.xfrLabel(d_url);
297                 )
298
299boilerplate_conv(MBOXFW, QType::MBOXFW, 
300                 conv.xfrLabel(d_mboxfw);
301                 )
302
303
304
305bool getEDNSOpts(const MOADNSParser& mdp, EDNSOpts* eo)
306{
307  if(mdp.d_header.arcount && !mdp.d_answers.empty()) {
308    BOOST_FOREACH(const MOADNSParser::answers_t::value_type& val, mdp.d_answers) {
309      if(val.first.d_place == DNSRecord::Additional && val.first.d_type == QType::OPT) {
310        eo->d_packetsize=val.first.d_class;
311       
312        EDNS0Record stuff;
313        uint32_t ttl=ntohl(val.first.d_ttl);
314        memcpy(&stuff, &ttl, sizeof(stuff));
315       
316        eo->d_extRCode=stuff.extRCode;
317        eo->d_version=stuff.version;
318        eo->d_Z = ntohs(stuff.Z);
319        OPTRecordContent* orc = 
320          dynamic_cast<OPTRecordContent*>(val.first.d_content.get());
321        if(!orc)
322          return false;
323        orc->getData(eo->d_options);
324        return true;
325      }
326    }
327  }
328  return false;
329}
330
331
332void reportBasicTypes()
333{
334  ARecordContent::report();
335  AAAARecordContent::report();
336  NSRecordContent::report();
337  CNAMERecordContent::report();
338  MXRecordContent::report();
339  SOARecordContent::report();
340  SRVRecordContent::report();
341  PTRRecordContent::report();
342  DNSRecordContent::regist(3, ns_t_txt, &TXTRecordContent::make, &TXTRecordContent::make, "TXT");
343  TXTRecordContent::report();
344  DNSRecordContent::regist(1, QType::ANY, 0, 0, "ANY");
345}
346
347void reportOtherTypes()
348{
349   AFSDBRecordContent::report();
350   SPFRecordContent::report();
351   NAPTRRecordContent::report();
352   LOCRecordContent::report();
353   HINFORecordContent::report();
354   RPRecordContent::report();
355   KEYRecordContent::report();
356   DNSKEYRecordContent::report();
357   RRSIGRecordContent::report();
358   DSRecordContent::report();
359   SSHFPRecordContent::report();
360   CERTRecordContent::report();
361   NSECRecordContent::report();
362   NSEC3RecordContent::report();
363   NSEC3PARAMRecordContent::report();
364   TLSARecordContent::report();
365   DLVRecordContent::report();
366   DNSRecordContent::regist(0xff, QType::TSIG, &TSIGRecordContent::make, &TSIGRecordContent::make, "TSIG");
367   OPTRecordContent::report();
368}
369
370void reportFancyTypes()
371{
372  URLRecordContent::report();
373  MBOXFWRecordContent::report();
374}
375
376void reportAllTypes()
377{
378  reportBasicTypes();
379  reportOtherTypes();
380}
381
382#if 0
383static struct Reporter
384{
385  Reporter()
386  {
387    reportAllTypes();
388  }
389} reporter __attribute__((init_priority(65535)));
390#endif
Note: See TracBrowser for help on using the browser.