labelsequence.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  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 <dns/labelsequence.h>
  15. #include <dns/name_internal.h>
  16. #include <exceptions/exceptions.h>
  17. #include <boost/functional/hash.hpp>
  18. #include <cstring>
  19. namespace isc {
  20. namespace dns {
  21. LabelSequence::LabelSequence(const void* buf) {
  22. if (buf == NULL) {
  23. isc_throw(BadValue,
  24. "Null pointer passed to LabelSequence constructor");
  25. }
  26. const uint8_t* bp = reinterpret_cast<const uint8_t*>(buf);
  27. first_label_ = 0;
  28. const uint8_t offsets_len = *bp++;
  29. if (offsets_len == 0 || offsets_len > Name::MAX_LABELS) {
  30. isc_throw(BadValue,
  31. "Bad offsets len in serialized LabelSequence data: "
  32. << static_cast<unsigned int>(offsets_len));
  33. }
  34. last_label_ = offsets_len - 1;
  35. offsets_ = bp;
  36. data_ = bp + offsets_len;
  37. // Check the integrity on the offsets and the name data
  38. const uint8_t* dp = data_;
  39. for (size_t cur_offset = 0; cur_offset < offsets_len; ++cur_offset) {
  40. if (offsets_[cur_offset] > Name::MAX_LABELLEN ||
  41. dp - data_ != offsets_[cur_offset]) {
  42. isc_throw(BadValue,
  43. "Broken offset or name data in serialized "
  44. "LabelSequence data");
  45. }
  46. dp += (1 + *dp);
  47. }
  48. }
  49. LabelSequence::LabelSequence(const LabelSequence& src,
  50. uint8_t buf[MAX_SERIALIZED_LENGTH])
  51. {
  52. size_t data_len;
  53. const uint8_t *data = src.getData(&data_len);
  54. memcpy(buf, data, data_len);
  55. for (size_t i = 0; i < src.getLabelCount(); ++i) {
  56. buf[Name::MAX_WIRE + i] = src.offsets_[i + src.first_label_] -
  57. src.offsets_[src.first_label_];
  58. }
  59. first_label_ = 0;
  60. last_label_ = src.last_label_ - src.first_label_;
  61. data_ = buf;
  62. offsets_ = &buf[Name::MAX_WIRE];
  63. }
  64. const uint8_t*
  65. LabelSequence::getData(size_t *len) const {
  66. *len = getDataLength();
  67. return (&data_[offsets_[first_label_]]);
  68. }
  69. size_t
  70. LabelSequence::getDataLength() const {
  71. const size_t last_label_len = data_[offsets_[last_label_]] + 1;
  72. return (offsets_[last_label_] - offsets_[first_label_] + last_label_len);
  73. }
  74. size_t
  75. LabelSequence::getSerializedLength() const {
  76. return (1 + getLabelCount() + getDataLength());
  77. }
  78. void
  79. LabelSequence::serialize(void* buf, size_t buf_len) const {
  80. const size_t expected_size = getSerializedLength();
  81. if (expected_size > buf_len) {
  82. isc_throw(BadValue, "buffer too short for LabelSequence::serialize");
  83. }
  84. const size_t offsets_len = getLabelCount();
  85. assert(offsets_len < 256); // should be in the 8-bit range
  86. uint8_t* bp = reinterpret_cast<uint8_t*>(buf);
  87. *bp++ = offsets_len;
  88. for (size_t i = 0; i < offsets_len; ++i) {
  89. *bp++ = offsets_[first_label_ + i] - offsets_[first_label_];
  90. }
  91. const size_t ndata_len = getDataLength();
  92. memcpy(bp, &data_[offsets_[first_label_]], ndata_len);
  93. bp += ndata_len;
  94. assert(bp - reinterpret_cast<const uint8_t*>(buf) == expected_size);
  95. }
  96. bool
  97. LabelSequence::equals(const LabelSequence& other, bool case_sensitive) const {
  98. size_t len, other_len;
  99. const uint8_t* data = getData(&len);
  100. const uint8_t* other_data = other.getData(&other_len);
  101. if (len != other_len) {
  102. return (false);
  103. }
  104. if (case_sensitive) {
  105. return (std::memcmp(data, other_data, len) == 0);
  106. }
  107. // As long as the data was originally validated as (part of) a name,
  108. // label length must never be a capital ascii character, so we can
  109. // simply compare them after converting to lower characters.
  110. for (size_t i = 0; i < len; ++i) {
  111. const uint8_t ch = data[i];
  112. const uint8_t other_ch = other_data[i];
  113. if (isc::dns::name::internal::maptolower[ch] !=
  114. isc::dns::name::internal::maptolower[other_ch]) {
  115. return (false);
  116. }
  117. }
  118. return (true);
  119. }
  120. NameComparisonResult
  121. LabelSequence::compare(const LabelSequence& other,
  122. bool case_sensitive) const
  123. {
  124. // Determine the relative ordering under the DNSSEC order relation of
  125. // 'this' and 'other', and also determine the hierarchical relationship
  126. // of the labels.
  127. unsigned int nlabels = 0;
  128. int l1 = getLabelCount();
  129. int l2 = other.getLabelCount();
  130. const int ldiff = static_cast<int>(l1) - static_cast<int>(l2);
  131. unsigned int l = (ldiff < 0) ? l1 : l2;
  132. while (l > 0) {
  133. --l;
  134. --l1;
  135. --l2;
  136. size_t pos1 = offsets_[l1 + first_label_];
  137. size_t pos2 = other.offsets_[l2 + other.first_label_];
  138. unsigned int count1 = data_[pos1++];
  139. unsigned int count2 = other.data_[pos2++];
  140. // We don't support any extended label types including now-obsolete
  141. // bitstring labels.
  142. assert(count1 <= Name::MAX_LABELLEN && count2 <= Name::MAX_LABELLEN);
  143. const int cdiff = static_cast<int>(count1) - static_cast<int>(count2);
  144. unsigned int count = (cdiff < 0) ? count1 : count2;
  145. while (count > 0) {
  146. const uint8_t label1 = data_[pos1];
  147. const uint8_t label2 = other.data_[pos2];
  148. int chdiff;
  149. if (case_sensitive) {
  150. chdiff = static_cast<int>(label1) - static_cast<int>(label2);
  151. } else {
  152. chdiff = static_cast<int>(
  153. isc::dns::name::internal::maptolower[label1]) -
  154. static_cast<int>(
  155. isc::dns::name::internal::maptolower[label2]);
  156. }
  157. if (chdiff != 0) {
  158. return (NameComparisonResult(
  159. chdiff, nlabels,
  160. nlabels == 0 ? NameComparisonResult::NONE :
  161. NameComparisonResult::COMMONANCESTOR));
  162. }
  163. --count;
  164. ++pos1;
  165. ++pos2;
  166. }
  167. if (cdiff != 0) {
  168. return (NameComparisonResult(
  169. cdiff, nlabels,
  170. nlabels == 0 ? NameComparisonResult::NONE :
  171. NameComparisonResult::COMMONANCESTOR));
  172. }
  173. ++nlabels;
  174. }
  175. if (ldiff < 0) {
  176. return (NameComparisonResult(ldiff, nlabels,
  177. NameComparisonResult::SUPERDOMAIN));
  178. } else if (ldiff > 0) {
  179. return (NameComparisonResult(ldiff, nlabels,
  180. NameComparisonResult::SUBDOMAIN));
  181. }
  182. return (NameComparisonResult(ldiff, nlabels, NameComparisonResult::EQUAL));
  183. }
  184. void
  185. LabelSequence::stripLeft(size_t i) {
  186. if (i >= getLabelCount()) {
  187. isc_throw(OutOfRange, "Cannot strip to zero or less labels; " << i <<
  188. " (labelcount: " << getLabelCount() << ")");
  189. }
  190. first_label_ += i;
  191. }
  192. void
  193. LabelSequence::stripRight(size_t i) {
  194. if (i >= getLabelCount()) {
  195. isc_throw(OutOfRange, "Cannot strip to zero or less labels; " << i <<
  196. " (labelcount: " << getLabelCount() << ")");
  197. }
  198. last_label_ -= i;
  199. }
  200. bool
  201. LabelSequence::isAbsolute() const {
  202. return (data_[offsets_[last_label_]] == 0);
  203. }
  204. size_t
  205. LabelSequence::getHash(bool case_sensitive) const {
  206. size_t length;
  207. const uint8_t* s = getData(&length);
  208. if (length > 16) {
  209. length = 16;
  210. }
  211. size_t hash_val = 0;
  212. while (length > 0) {
  213. const uint8_t c = *s++;
  214. boost::hash_combine(hash_val, case_sensitive ? c :
  215. isc::dns::name::internal::maptolower[c]);
  216. --length;
  217. }
  218. return (hash_val);
  219. }
  220. std::string
  221. LabelSequence::toText(bool omit_final_dot) const {
  222. const uint8_t* np = &data_[offsets_[first_label_]];
  223. const uint8_t* np_end = np + getDataLength();
  224. // use for integrity check
  225. unsigned int labels = getLabelCount();
  226. // init with an impossible value to catch error cases in the end:
  227. unsigned int count = Name::MAX_LABELLEN + 1;
  228. // result string: it will roughly have the same length as the wire format
  229. // label sequence data. reserve that length to minimize reallocation.
  230. std::string result;
  231. result.reserve(getDataLength());
  232. while (np != np_end) {
  233. labels--;
  234. count = *np++;
  235. if (count == 0) {
  236. // We've reached the "final dot". If we've not dumped any
  237. // character, the entire label sequence is the root name.
  238. // In that case we don't omit the final dot.
  239. if (!omit_final_dot || result.empty()) {
  240. result.push_back('.');
  241. }
  242. break;
  243. }
  244. if (count <= Name::MAX_LABELLEN) {
  245. assert(np_end - np >= count);
  246. if (!result.empty()) {
  247. // just after a non-empty label. add a separating dot.
  248. result.push_back('.');
  249. }
  250. while (count-- > 0) {
  251. const uint8_t c = *np++;
  252. switch (c) {
  253. case 0x22: // '"'
  254. case 0x28: // '('
  255. case 0x29: // ')'
  256. case 0x2E: // '.'
  257. case 0x3B: // ';'
  258. case 0x5C: // '\\'
  259. // Special modifiers in zone files.
  260. case 0x40: // '@'
  261. case 0x24: // '$'
  262. result.push_back('\\');
  263. result.push_back(c);
  264. break;
  265. default:
  266. if (c > 0x20 && c < 0x7f) {
  267. // append printable characters intact
  268. result.push_back(c);
  269. } else {
  270. // encode non-printable characters in the form of \DDD
  271. result.push_back(0x5c);
  272. result.push_back(0x30 + ((c / 100) % 10));
  273. result.push_back(0x30 + ((c / 10) % 10));
  274. result.push_back(0x30 + (c % 10));
  275. }
  276. }
  277. }
  278. } else {
  279. isc_throw(BadLabelType, "unknown label type in name data");
  280. }
  281. }
  282. // We should be at the end of the data and have consumed all labels.
  283. assert(np == np_end);
  284. assert(labels == 0);
  285. return (result);
  286. }
  287. std::string
  288. LabelSequence::toText() const {
  289. return (toText(!isAbsolute()));
  290. }
  291. void
  292. LabelSequence::extend(const LabelSequence& labels,
  293. uint8_t buf[MAX_SERIALIZED_LENGTH])
  294. {
  295. // collect data to perform steps before anything is changed
  296. bool absolute = isAbsolute();
  297. size_t label_count = last_label_ + 1;
  298. // Since we may have been stripped, do not use getDataLength(), but
  299. // calculate actual data size we use
  300. size_t data_pos = offsets_[last_label_] + data_[offsets_[last_label_]] + 1;
  301. // If this labelsequence is absolute, virtually strip the root label.
  302. if (absolute) {
  303. data_pos--;
  304. label_count--;
  305. }
  306. size_t append_label_count = labels.getLabelCount();
  307. size_t data_len;
  308. const uint8_t *data = labels.getData(&data_len);
  309. // Sanity checks
  310. if (data_ != buf || offsets_ != &buf[Name::MAX_WIRE]) {
  311. isc_throw(BadValue,
  312. "extend() called with unrelated buffer");
  313. }
  314. if (data_pos + data_len > Name::MAX_WIRE) {
  315. isc_throw(BadValue,
  316. "extend() would exceed maximum wire length");
  317. }
  318. if (label_count + append_label_count > Name::MAX_LABELS) {
  319. isc_throw(BadValue,
  320. "extend() would exceed maximum number of labels");
  321. }
  322. // All seems to be reasonably ok, let's proceed.
  323. // Note: In theory this could be done with a straightforward memcpy.
  324. // However, one can extend a labelsequence with itself, in which
  325. // case we'd be copying overlapping data (overwriting the current last
  326. // label if this LabelSequence is absolute). Therefore we do this
  327. // manually, and more importantly, backwards.
  328. // (note2 obviously this destroys data_len, don't use below,
  329. // or reset it)
  330. while (--data_len) {
  331. buf[data_pos + data_len] = data[data_len];
  332. }
  333. buf[data_pos + data_len] = data[data_len];
  334. for (size_t i = 0; i < append_label_count; ++i) {
  335. buf[Name::MAX_WIRE + label_count + i] =
  336. offsets_[label_count] +
  337. labels.offsets_[i + labels.first_label_] -
  338. labels.offsets_[labels.first_label_];
  339. }
  340. last_label_ = label_count + append_label_count - 1;
  341. }
  342. std::ostream&
  343. operator<<(std::ostream& os, const LabelSequence& label_sequence) {
  344. os << label_sequence.toText();
  345. return (os);
  346. }
  347. void
  348. LabelSequence::dump() const {
  349. std::cout << "[XX] serialized data: ";
  350. for (size_t i = 0; i < getDataLength(); ++i) {
  351. std::cout << (int)data_[i] << " ";
  352. }
  353. std::cout << std::endl;
  354. std::cout << "[XX] offsets: ";
  355. size_t cur_offset = 0;
  356. uint8_t cur_ll = data_[offsets_[cur_offset]];
  357. while(cur_ll != 0) {
  358. std::cout << (int)offsets_[cur_offset] << " ";
  359. cur_offset++;
  360. cur_ll = data_[offsets_[cur_offset]];
  361. }
  362. std::cout << std::endl;
  363. std::cout << "[XX] first label: " << first_label_ << std::endl;
  364. std::cout << "[XX] last label: " << last_label_ << std::endl;
  365. if (isAbsolute()) {
  366. std::cout << "[XX] absolute" << std::endl;
  367. } else {
  368. std::cout << "[XX] not absolute" << std::endl;
  369. }
  370. }
  371. } // end namespace dns
  372. } // end namespace isc