rdata_field.cc 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. // Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include "rdata_field.h"
  15. #include <dns/rrclass.h>
  16. #include <dns/rrtype.h>
  17. #include <boost/static_assert.hpp>
  18. using namespace isc::dns;
  19. namespace isc {
  20. namespace datasrc {
  21. namespace memory {
  22. namespace {
  23. // Many types of RDATA can be treated as a single-field, variable length
  24. // field (in terms of our encoding). The following define such most general
  25. // form of field spec.
  26. const RdataFieldSpec generic_data_fields[] = {
  27. {RdataFieldSpec::VARLEN_DATA, 0, NAMEATTR_NONE}
  28. };
  29. const uint16_t n_generic_data_fields =
  30. sizeof(generic_data_fields) / sizeof(RdataFieldSpec);
  31. const RdataEncodeSpec generic_data_spec = {
  32. n_generic_data_fields, 0, 1, generic_data_fields
  33. };
  34. // RDATA consist of a single IPv4 address field.
  35. const RdataFieldSpec single_ipv4_fields[] = {
  36. {RdataFieldSpec::FIXEDLEN_DATA, sizeof(uint32_t), NAMEATTR_NONE}
  37. };
  38. const uint16_t n_ipv4_fields =
  39. sizeof(single_ipv4_fields) / sizeof(RdataFieldSpec);
  40. // RDATA consist of a single IPv6 address field.
  41. const RdataFieldSpec single_ipv6_fields[] = {
  42. {RdataFieldSpec::FIXEDLEN_DATA, 16, NAMEATTR_NONE} // 128bits = 16 bytes
  43. };
  44. const uint16_t n_ipv6_fields =
  45. sizeof(single_ipv6_fields) / sizeof(RdataFieldSpec);
  46. // There are several RR types that consist of a single domain name.
  47. const RdataFieldSpec single_noattr_name_fields[] = {
  48. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE}
  49. };
  50. const RdataFieldSpec single_compressible_name_fields[] = {
  51. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_COMPRESSIBLE}
  52. };
  53. const RdataFieldSpec single_compadditional_name_fields[] = {
  54. {RdataFieldSpec::DOMAIN_NAME, 0,
  55. static_cast<RdataNameAttributes>(
  56. static_cast<unsigned int>(NAMEATTR_COMPRESSIBLE) |
  57. static_cast<unsigned int>(NAMEATTR_ADDITIONAL))}
  58. };
  59. const uint16_t n_single_name_fields =
  60. sizeof(single_noattr_name_fields) / sizeof(RdataFieldSpec);
  61. // RDATA consisting of two names. There are some of this type.
  62. const RdataFieldSpec double_compressible_name_fields[] = {
  63. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_COMPRESSIBLE},
  64. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_COMPRESSIBLE}
  65. };
  66. const RdataFieldSpec double_noattr_name_fields[] = {
  67. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE},
  68. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE}
  69. };
  70. const uint16_t n_double_name_fields =
  71. sizeof(double_compressible_name_fields) / sizeof(RdataFieldSpec);
  72. // SOA specific: two compressible names + 5*32-bit data
  73. const RdataFieldSpec soa_fields[] = {
  74. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_COMPRESSIBLE},
  75. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_COMPRESSIBLE},
  76. {RdataFieldSpec::FIXEDLEN_DATA, sizeof(uint32_t) * 5, NAMEATTR_NONE}
  77. };
  78. const uint16_t n_soa_fields = sizeof(soa_fields) / sizeof(RdataFieldSpec);
  79. // MX specific: 16-bit data + compressible/additional name
  80. const RdataFieldSpec mx_fields[] = {
  81. {RdataFieldSpec::FIXEDLEN_DATA, sizeof(uint16_t), NAMEATTR_NONE},
  82. {RdataFieldSpec::DOMAIN_NAME, 0,
  83. static_cast<RdataNameAttributes>(
  84. static_cast<unsigned int>(NAMEATTR_COMPRESSIBLE) |
  85. static_cast<unsigned int>(NAMEATTR_ADDITIONAL))}
  86. };
  87. const uint16_t n_mx_fields = sizeof(mx_fields) / sizeof(RdataFieldSpec);
  88. // AFSDB specific: 16-bit data + no-attribute name
  89. const RdataFieldSpec afsdb_fields[] = {
  90. {RdataFieldSpec::FIXEDLEN_DATA, sizeof(uint16_t), NAMEATTR_NONE},
  91. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE}
  92. };
  93. const uint16_t n_afsdb_fields = sizeof(afsdb_fields) / sizeof(RdataFieldSpec);
  94. // SRV specific: 3*16-bit data + additional name
  95. const RdataFieldSpec srv_fields[] = {
  96. {RdataFieldSpec::FIXEDLEN_DATA, sizeof(uint16_t) * 3, NAMEATTR_NONE},
  97. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_ADDITIONAL}
  98. };
  99. const uint16_t n_srv_fields = sizeof(srv_fields) / sizeof(RdataFieldSpec);
  100. // NAPTR specific: (multi-field) variable data + (additional) name
  101. // NAPTR requires complicated additional section handling; for now, we skip
  102. // the additional handling completely.
  103. const RdataFieldSpec naptr_fields[] = {
  104. {RdataFieldSpec::VARLEN_DATA, 0, NAMEATTR_NONE},
  105. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE}
  106. };
  107. const uint16_t n_naptr_fields = sizeof(naptr_fields) / sizeof(RdataFieldSpec);
  108. // NSEC specific: no-attribute name + varlen data
  109. const RdataFieldSpec nsec_fields[] = {
  110. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE},
  111. {RdataFieldSpec::VARLEN_DATA, 0, NAMEATTR_NONE}
  112. };
  113. const uint16_t n_nsec_fields = sizeof(nsec_fields) / sizeof(RdataFieldSpec);
  114. // Class IN encode specs. This gives a shortcut to the encode spec for
  115. // some well-known types of RDATA specific to class IN (most of which are
  116. // generic and can be used for other classes). The array index is the
  117. // RR type code.
  118. const RdataEncodeSpec encode_spec_list_in[] = {
  119. generic_data_spec, // #0: (NONE)
  120. {n_ipv4_fields, 0, 0, single_ipv4_fields}, // #1: A
  121. {n_single_name_fields, 1, 0, single_compadditional_name_fields}, // #2: NS
  122. generic_data_spec, // #3
  123. generic_data_spec, // #4
  124. {n_single_name_fields, 1, 0, single_compressible_name_fields}, // #5: CNAME
  125. {n_soa_fields, 2, 0, soa_fields}, // #6: SOA
  126. generic_data_spec, // #7
  127. generic_data_spec, // #8
  128. generic_data_spec, // #9
  129. generic_data_spec, // #10
  130. generic_data_spec, // #11
  131. {n_single_name_fields, 1, 0, single_compressible_name_fields}, // #12: PTR
  132. generic_data_spec, // #13: HINFO
  133. {n_double_name_fields, 2, 0, double_compressible_name_fields}, // #14:HINFO
  134. {n_mx_fields, 1, 0, mx_fields}, // #15: MX
  135. generic_data_spec, // #16: TXT
  136. {n_double_name_fields, 2, 0, double_noattr_name_fields}, // 17: RP
  137. {n_afsdb_fields, 1, 0, afsdb_fields}, // #18: AFSDB
  138. // #19-#26
  139. generic_data_spec, generic_data_spec, generic_data_spec, generic_data_spec,
  140. generic_data_spec, generic_data_spec, generic_data_spec, generic_data_spec,
  141. generic_data_spec, // #27
  142. {n_ipv6_fields, 0, 0, single_ipv6_fields}, // #28: AAAA
  143. // #29-#32
  144. generic_data_spec, generic_data_spec, generic_data_spec, generic_data_spec,
  145. {n_srv_fields, 1, 0, srv_fields}, // #33: SRV
  146. generic_data_spec, // #34
  147. {n_naptr_fields, 1, 1, naptr_fields}, // #35: NAPTR
  148. generic_data_spec, // #36
  149. generic_data_spec, // #37
  150. generic_data_spec, // #38
  151. {n_single_name_fields, 1, 0, single_noattr_name_fields}, // #39 DNAME
  152. generic_data_spec, // #40
  153. generic_data_spec, // #41 (OPT)
  154. generic_data_spec, // #42
  155. generic_data_spec, // #43: DS (this is opaque for encoding purposes)
  156. generic_data_spec, // #44: SSHFP (this is opaque for encoding purposes)
  157. generic_data_spec, // #45
  158. generic_data_spec, // #46: RRSIG (this is opaque for encoding purposes)
  159. {n_nsec_fields, 1, 1, nsec_fields} // #47: NSEC
  160. // All others can be treated as single-field variable length data, at
  161. // least for currently supported RR types.
  162. };
  163. // # of entries in encode_spec_list_in
  164. const size_t encode_spec_list_in_size =
  165. sizeof(encode_spec_list_in) / sizeof(encode_spec_list_in[0]);
  166. BOOST_STATIC_ASSERT(encode_spec_list_in_size == 48);
  167. }
  168. const RdataEncodeSpec&
  169. getRdataEncodeSpec(const RRClass& rrclass, const RRType& rrtype) {
  170. // Special case: for classes other than IN, we treat RDATA of RR types
  171. // that are class-IN specific as generic opaque data.
  172. if (rrclass != RRClass::IN() &&
  173. (rrtype == RRType::A() || rrtype == RRType::AAAA() ||
  174. rrtype == RRType::SRV())) {
  175. return (generic_data_spec);
  176. }
  177. // Otherwise, if the type is in the pre-defined range, we use the defined
  178. // spec; otherwise we treat it as opaque data.
  179. const uint16_t typecode = rrtype.getCode();
  180. if (typecode < encode_spec_list_in_size) {
  181. return (encode_spec_list_in[rrtype.getCode()]);
  182. }
  183. return (generic_data_spec);
  184. }
  185. }
  186. }
  187. }