PageRenderTime 72ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 1ms

/contrib/unbound/util/data/dname.c

https://bitbucket.org/freebsd/freebsd-base
C | 811 lines | 651 code | 46 blank | 114 comment | 150 complexity | aad2c491ea80ac13f1320e06a0dcd5c6 MD5 | raw file
  1. /*
  2. * util/data/dname.h - domain name handling
  3. *
  4. * Copyright (c) 2007, NLnet Labs. All rights reserved.
  5. *
  6. * This software is open source.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * Redistributions of source code must retain the above copyright notice,
  13. * this list of conditions and the following disclaimer.
  14. *
  15. * Redistributions in binary form must reproduce the above copyright notice,
  16. * this list of conditions and the following disclaimer in the documentation
  17. * and/or other materials provided with the distribution.
  18. *
  19. * Neither the name of the NLNET LABS nor the names of its contributors may
  20. * be used to endorse or promote products derived from this software without
  21. * specific prior written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  24. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  25. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  26. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  27. * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  28. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
  29. * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  30. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  31. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  32. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  33. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  34. */
  35. /**
  36. * \file
  37. *
  38. * This file contains domain name handling functions.
  39. */
  40. #include "config.h"
  41. #include <ctype.h>
  42. #include "util/data/dname.h"
  43. #include "util/data/msgparse.h"
  44. #include "util/log.h"
  45. #include "util/storage/lookup3.h"
  46. #include "sldns/sbuffer.h"
  47. /* determine length of a dname in buffer, no compression pointers allowed */
  48. size_t
  49. query_dname_len(sldns_buffer* query)
  50. {
  51. size_t len = 0;
  52. size_t labellen;
  53. while(1) {
  54. if(sldns_buffer_remaining(query) < 1)
  55. return 0; /* parse error, need label len */
  56. labellen = sldns_buffer_read_u8(query);
  57. if(labellen&0xc0)
  58. return 0; /* no compression allowed in queries */
  59. len += labellen + 1;
  60. if(len > LDNS_MAX_DOMAINLEN)
  61. return 0; /* too long */
  62. if(labellen == 0)
  63. return len;
  64. if(sldns_buffer_remaining(query) < labellen)
  65. return 0; /* parse error, need content */
  66. sldns_buffer_skip(query, (ssize_t)labellen);
  67. }
  68. }
  69. size_t
  70. dname_valid(uint8_t* dname, size_t maxlen)
  71. {
  72. size_t len = 0;
  73. size_t labellen;
  74. labellen = *dname++;
  75. while(labellen) {
  76. if(labellen&0xc0)
  77. return 0; /* no compression ptrs allowed */
  78. len += labellen + 1;
  79. if(len >= LDNS_MAX_DOMAINLEN)
  80. return 0; /* too long */
  81. if(len > maxlen)
  82. return 0; /* does not fit in memory allocation */
  83. dname += labellen;
  84. labellen = *dname++;
  85. }
  86. len += 1;
  87. if(len > maxlen)
  88. return 0; /* does not fit in memory allocation */
  89. return len;
  90. }
  91. /** compare uncompressed, noncanonical, registers are hints for speed */
  92. int
  93. query_dname_compare(register uint8_t* d1, register uint8_t* d2)
  94. {
  95. register uint8_t lab1, lab2;
  96. log_assert(d1 && d2);
  97. lab1 = *d1++;
  98. lab2 = *d2++;
  99. while( lab1 != 0 || lab2 != 0 ) {
  100. /* compare label length */
  101. /* if one dname ends, it has labellength 0 */
  102. if(lab1 != lab2) {
  103. if(lab1 < lab2)
  104. return -1;
  105. return 1;
  106. }
  107. log_assert(lab1 == lab2 && lab1 != 0);
  108. /* compare lowercased labels. */
  109. while(lab1--) {
  110. /* compare bytes first for speed */
  111. if(*d1 != *d2 &&
  112. tolower((unsigned char)*d1) != tolower((unsigned char)*d2)) {
  113. if(tolower((unsigned char)*d1) < tolower((unsigned char)*d2))
  114. return -1;
  115. return 1;
  116. }
  117. d1++;
  118. d2++;
  119. }
  120. /* next pair of labels. */
  121. lab1 = *d1++;
  122. lab2 = *d2++;
  123. }
  124. return 0;
  125. }
  126. void
  127. query_dname_tolower(uint8_t* dname)
  128. {
  129. /* the dname is stored uncompressed */
  130. uint8_t labellen;
  131. labellen = *dname;
  132. while(labellen) {
  133. dname++;
  134. while(labellen--) {
  135. *dname = (uint8_t)tolower((unsigned char)*dname);
  136. dname++;
  137. }
  138. labellen = *dname;
  139. }
  140. }
  141. void
  142. pkt_dname_tolower(sldns_buffer* pkt, uint8_t* dname)
  143. {
  144. uint8_t lablen;
  145. int count = 0;
  146. if(dname >= sldns_buffer_end(pkt))
  147. return;
  148. lablen = *dname++;
  149. while(lablen) {
  150. if(LABEL_IS_PTR(lablen)) {
  151. if((size_t)PTR_OFFSET(lablen, *dname)
  152. >= sldns_buffer_limit(pkt))
  153. return;
  154. dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));
  155. lablen = *dname++;
  156. if(count++ > MAX_COMPRESS_PTRS)
  157. return;
  158. continue;
  159. }
  160. if(dname+lablen >= sldns_buffer_end(pkt))
  161. return;
  162. while(lablen--) {
  163. *dname = (uint8_t)tolower((unsigned char)*dname);
  164. dname++;
  165. }
  166. if(dname >= sldns_buffer_end(pkt))
  167. return;
  168. lablen = *dname++;
  169. }
  170. }
  171. size_t
  172. pkt_dname_len(sldns_buffer* pkt)
  173. {
  174. size_t len = 0;
  175. int ptrcount = 0;
  176. uint8_t labellen;
  177. size_t endpos = 0;
  178. /* read dname and determine length */
  179. /* check compression pointers, loops, out of bounds */
  180. while(1) {
  181. /* read next label */
  182. if(sldns_buffer_remaining(pkt) < 1)
  183. return 0;
  184. labellen = sldns_buffer_read_u8(pkt);
  185. if(LABEL_IS_PTR(labellen)) {
  186. /* compression ptr */
  187. uint16_t ptr;
  188. if(sldns_buffer_remaining(pkt) < 1)
  189. return 0;
  190. ptr = PTR_OFFSET(labellen, sldns_buffer_read_u8(pkt));
  191. if(ptrcount++ > MAX_COMPRESS_PTRS)
  192. return 0; /* loop! */
  193. if(sldns_buffer_limit(pkt) <= ptr)
  194. return 0; /* out of bounds! */
  195. if(!endpos)
  196. endpos = sldns_buffer_position(pkt);
  197. sldns_buffer_set_position(pkt, ptr);
  198. } else {
  199. /* label contents */
  200. if(labellen > 0x3f)
  201. return 0; /* label too long */
  202. len += 1 + labellen;
  203. if(len > LDNS_MAX_DOMAINLEN)
  204. return 0;
  205. if(labellen == 0) {
  206. /* end of dname */
  207. break;
  208. }
  209. if(sldns_buffer_remaining(pkt) < labellen)
  210. return 0;
  211. sldns_buffer_skip(pkt, (ssize_t)labellen);
  212. }
  213. }
  214. if(endpos)
  215. sldns_buffer_set_position(pkt, endpos);
  216. return len;
  217. }
  218. int
  219. dname_pkt_compare(sldns_buffer* pkt, uint8_t* d1, uint8_t* d2)
  220. {
  221. uint8_t len1, len2;
  222. log_assert(pkt && d1 && d2);
  223. len1 = *d1++;
  224. len2 = *d2++;
  225. while( len1 != 0 || len2 != 0 ) {
  226. /* resolve ptrs */
  227. if(LABEL_IS_PTR(len1)) {
  228. d1 = sldns_buffer_at(pkt, PTR_OFFSET(len1, *d1));
  229. len1 = *d1++;
  230. continue;
  231. }
  232. if(LABEL_IS_PTR(len2)) {
  233. d2 = sldns_buffer_at(pkt, PTR_OFFSET(len2, *d2));
  234. len2 = *d2++;
  235. continue;
  236. }
  237. /* check label length */
  238. log_assert(len1 <= LDNS_MAX_LABELLEN);
  239. log_assert(len2 <= LDNS_MAX_LABELLEN);
  240. if(len1 != len2) {
  241. if(len1 < len2) return -1;
  242. return 1;
  243. }
  244. log_assert(len1 == len2 && len1 != 0);
  245. /* compare labels */
  246. while(len1--) {
  247. if(tolower((unsigned char)*d1) != tolower((unsigned char)*d2)) {
  248. if(tolower((unsigned char)*d1) < tolower((unsigned char)*d2))
  249. return -1;
  250. return 1;
  251. }
  252. d1++;
  253. d2++;
  254. }
  255. len1 = *d1++;
  256. len2 = *d2++;
  257. }
  258. return 0;
  259. }
  260. hashvalue_type
  261. dname_query_hash(uint8_t* dname, hashvalue_type h)
  262. {
  263. uint8_t labuf[LDNS_MAX_LABELLEN+1];
  264. uint8_t lablen;
  265. int i;
  266. /* preserve case of query, make hash label by label */
  267. lablen = *dname++;
  268. while(lablen) {
  269. log_assert(lablen <= LDNS_MAX_LABELLEN);
  270. labuf[0] = lablen;
  271. i=0;
  272. while(lablen--) {
  273. labuf[++i] = (uint8_t)tolower((unsigned char)*dname);
  274. dname++;
  275. }
  276. h = hashlittle(labuf, labuf[0] + 1, h);
  277. lablen = *dname++;
  278. }
  279. return h;
  280. }
  281. hashvalue_type
  282. dname_pkt_hash(sldns_buffer* pkt, uint8_t* dname, hashvalue_type h)
  283. {
  284. uint8_t labuf[LDNS_MAX_LABELLEN+1];
  285. uint8_t lablen;
  286. int i;
  287. /* preserve case of query, make hash label by label */
  288. lablen = *dname++;
  289. while(lablen) {
  290. if(LABEL_IS_PTR(lablen)) {
  291. /* follow pointer */
  292. dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));
  293. lablen = *dname++;
  294. continue;
  295. }
  296. log_assert(lablen <= LDNS_MAX_LABELLEN);
  297. labuf[0] = lablen;
  298. i=0;
  299. while(lablen--) {
  300. labuf[++i] = (uint8_t)tolower((unsigned char)*dname);
  301. dname++;
  302. }
  303. h = hashlittle(labuf, labuf[0] + 1, h);
  304. lablen = *dname++;
  305. }
  306. return h;
  307. }
  308. void dname_pkt_copy(sldns_buffer* pkt, uint8_t* to, uint8_t* dname)
  309. {
  310. /* copy over the dname and decompress it at the same time */
  311. size_t len = 0;
  312. uint8_t lablen;
  313. lablen = *dname++;
  314. while(lablen) {
  315. if(LABEL_IS_PTR(lablen)) {
  316. /* follow pointer */
  317. dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));
  318. lablen = *dname++;
  319. continue;
  320. }
  321. log_assert(lablen <= LDNS_MAX_LABELLEN);
  322. len += (size_t)lablen+1;
  323. if(len >= LDNS_MAX_DOMAINLEN) {
  324. *to = 0; /* end the result prematurely */
  325. log_err("bad dname in dname_pkt_copy");
  326. return;
  327. }
  328. *to++ = lablen;
  329. memmove(to, dname, lablen);
  330. dname += lablen;
  331. to += lablen;
  332. lablen = *dname++;
  333. }
  334. /* copy last \0 */
  335. *to = 0;
  336. }
  337. void dname_print(FILE* out, struct sldns_buffer* pkt, uint8_t* dname)
  338. {
  339. uint8_t lablen;
  340. if(!out) out = stdout;
  341. if(!dname) return;
  342. lablen = *dname++;
  343. if(!lablen)
  344. fputc('.', out);
  345. while(lablen) {
  346. if(LABEL_IS_PTR(lablen)) {
  347. /* follow pointer */
  348. if(!pkt) {
  349. fputs("??compressionptr??", out);
  350. return;
  351. }
  352. dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));
  353. lablen = *dname++;
  354. continue;
  355. }
  356. if(lablen > LDNS_MAX_LABELLEN) {
  357. fputs("??extendedlabel??", out);
  358. return;
  359. }
  360. while(lablen--)
  361. fputc((int)*dname++, out);
  362. fputc('.', out);
  363. lablen = *dname++;
  364. }
  365. }
  366. int
  367. dname_count_labels(uint8_t* dname)
  368. {
  369. uint8_t lablen;
  370. int labs = 1;
  371. lablen = *dname++;
  372. while(lablen) {
  373. labs++;
  374. dname += lablen;
  375. lablen = *dname++;
  376. }
  377. return labs;
  378. }
  379. int
  380. dname_count_size_labels(uint8_t* dname, size_t* size)
  381. {
  382. uint8_t lablen;
  383. int labs = 1;
  384. size_t sz = 1;
  385. lablen = *dname++;
  386. while(lablen) {
  387. labs++;
  388. sz += lablen+1;
  389. dname += lablen;
  390. lablen = *dname++;
  391. }
  392. *size = sz;
  393. return labs;
  394. }
  395. /**
  396. * Compare labels in memory, lowercase while comparing.
  397. * @param p1: label 1
  398. * @param p2: label 2
  399. * @param len: number of bytes to compare.
  400. * @return: 0, -1, +1 comparison result.
  401. */
  402. static int
  403. memlowercmp(uint8_t* p1, uint8_t* p2, uint8_t len)
  404. {
  405. while(len--) {
  406. if(*p1 != *p2 && tolower((unsigned char)*p1) != tolower((unsigned char)*p2)) {
  407. if(tolower((unsigned char)*p1) < tolower((unsigned char)*p2))
  408. return -1;
  409. return 1;
  410. }
  411. p1++;
  412. p2++;
  413. }
  414. return 0;
  415. }
  416. int
  417. dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs)
  418. {
  419. uint8_t len1, len2;
  420. int atlabel = labs1;
  421. int lastmlabs;
  422. int lastdiff = 0;
  423. /* first skip so that we compare same label. */
  424. if(labs1 > labs2) {
  425. while(atlabel > labs2) {
  426. len1 = *d1++;
  427. d1 += len1;
  428. atlabel--;
  429. }
  430. log_assert(atlabel == labs2);
  431. } else if(labs1 < labs2) {
  432. atlabel = labs2;
  433. while(atlabel > labs1) {
  434. len2 = *d2++;
  435. d2 += len2;
  436. atlabel--;
  437. }
  438. log_assert(atlabel == labs1);
  439. }
  440. lastmlabs = atlabel+1;
  441. /* now at same label in d1 and d2, atlabel */
  442. /* www.example.com. */
  443. /* 4 3 2 1 atlabel number */
  444. /* repeat until at root label (which is always the same) */
  445. while(atlabel > 1) {
  446. len1 = *d1++;
  447. len2 = *d2++;
  448. if(len1 != len2) {
  449. log_assert(len1 != 0 && len2 != 0);
  450. if(len1<len2)
  451. lastdiff = -1;
  452. else lastdiff = 1;
  453. lastmlabs = atlabel;
  454. d1 += len1;
  455. d2 += len2;
  456. } else {
  457. /* memlowercmp is inlined here; or just like
  458. * if((c=memlowercmp(d1, d2, len1)) != 0) {
  459. * lastdiff = c;
  460. * lastmlabs = atlabel; } apart from d1++,d2++ */
  461. while(len1) {
  462. if(*d1 != *d2 && tolower((unsigned char)*d1)
  463. != tolower((unsigned char)*d2)) {
  464. if(tolower((unsigned char)*d1) <
  465. tolower((unsigned char)*d2)) {
  466. lastdiff = -1;
  467. lastmlabs = atlabel;
  468. d1 += len1;
  469. d2 += len1;
  470. break;
  471. }
  472. lastdiff = 1;
  473. lastmlabs = atlabel;
  474. d1 += len1;
  475. d2 += len1;
  476. break; /* out of memlowercmp */
  477. }
  478. d1++;
  479. d2++;
  480. len1--;
  481. }
  482. }
  483. atlabel--;
  484. }
  485. /* last difference atlabel number, so number of labels matching,
  486. * at the right side, is one less. */
  487. *mlabs = lastmlabs-1;
  488. if(lastdiff == 0) {
  489. /* all labels compared were equal, check if one has more
  490. * labels, so that example.com. > com. */
  491. if(labs1 > labs2)
  492. return 1;
  493. else if(labs1 < labs2)
  494. return -1;
  495. }
  496. return lastdiff;
  497. }
  498. int
  499. dname_lab_startswith(uint8_t* label, char* prefix, char** endptr)
  500. {
  501. size_t plen = strlen(prefix);
  502. size_t orig_plen = plen;
  503. size_t lablen = (size_t)*label;
  504. if(plen > lablen)
  505. return 0;
  506. label++;
  507. while(plen--) {
  508. if(*prefix != tolower((unsigned char)*label)) {
  509. return 0;
  510. }
  511. prefix++; label++;
  512. }
  513. if(orig_plen < lablen)
  514. *endptr = (char *)label;
  515. else
  516. /* prefix length == label length */
  517. *endptr = NULL;
  518. return 1;
  519. }
  520. int
  521. dname_buffer_write(sldns_buffer* pkt, uint8_t* dname)
  522. {
  523. uint8_t lablen;
  524. if(sldns_buffer_remaining(pkt) < 1)
  525. return 0;
  526. lablen = *dname++;
  527. sldns_buffer_write_u8(pkt, lablen);
  528. while(lablen) {
  529. if(sldns_buffer_remaining(pkt) < (size_t)lablen+1)
  530. return 0;
  531. sldns_buffer_write(pkt, dname, lablen);
  532. dname += lablen;
  533. lablen = *dname++;
  534. sldns_buffer_write_u8(pkt, lablen);
  535. }
  536. return 1;
  537. }
  538. void dname_str(uint8_t* dname, char* str)
  539. {
  540. size_t len = 0;
  541. uint8_t lablen = 0;
  542. char* s = str;
  543. if(!dname || !*dname) {
  544. *s++ = '.';
  545. *s = 0;
  546. return;
  547. }
  548. lablen = *dname++;
  549. while(lablen) {
  550. if(lablen > LDNS_MAX_LABELLEN) {
  551. *s++ = '#';
  552. *s = 0;
  553. return;
  554. }
  555. len += lablen+1;
  556. if(len >= LDNS_MAX_DOMAINLEN-1) {
  557. *s++ = '&';
  558. *s = 0;
  559. return;
  560. }
  561. while(lablen--) {
  562. if(isalnum((unsigned char)*dname)
  563. || *dname == '-' || *dname == '_'
  564. || *dname == '*')
  565. *s++ = *(char*)dname++;
  566. else {
  567. *s++ = '?';
  568. dname++;
  569. }
  570. }
  571. *s++ = '.';
  572. lablen = *dname++;
  573. }
  574. *s = 0;
  575. }
  576. int
  577. dname_strict_subdomain(uint8_t* d1, int labs1, uint8_t* d2, int labs2)
  578. {
  579. int m;
  580. /* check subdomain: d1: www.example.com. and d2: example.com. */
  581. if(labs2 >= labs1)
  582. return 0;
  583. if(dname_lab_cmp(d1, labs1, d2, labs2, &m) > 0) {
  584. /* subdomain if all labels match */
  585. return (m == labs2);
  586. }
  587. return 0;
  588. }
  589. int
  590. dname_strict_subdomain_c(uint8_t* d1, uint8_t* d2)
  591. {
  592. return dname_strict_subdomain(d1, dname_count_labels(d1), d2,
  593. dname_count_labels(d2));
  594. }
  595. int
  596. dname_subdomain_c(uint8_t* d1, uint8_t* d2)
  597. {
  598. int m;
  599. /* check subdomain: d1: www.example.com. and d2: example.com. */
  600. /* or d1: example.com. and d2: example.com. */
  601. int labs1 = dname_count_labels(d1);
  602. int labs2 = dname_count_labels(d2);
  603. if(labs2 > labs1)
  604. return 0;
  605. if(dname_lab_cmp(d1, labs1, d2, labs2, &m) < 0) {
  606. /* must have been example.com , www.example.com - wrong */
  607. /* or otherwise different dnames */
  608. return 0;
  609. }
  610. return (m == labs2);
  611. }
  612. int
  613. dname_is_root(uint8_t* dname)
  614. {
  615. uint8_t len;
  616. log_assert(dname);
  617. len = dname[0];
  618. log_assert(!LABEL_IS_PTR(len));
  619. return (len == 0);
  620. }
  621. void
  622. dname_remove_label(uint8_t** dname, size_t* len)
  623. {
  624. size_t lablen;
  625. log_assert(dname && *dname && len);
  626. lablen = (*dname)[0];
  627. log_assert(!LABEL_IS_PTR(lablen));
  628. log_assert(*len > lablen);
  629. if(lablen == 0)
  630. return; /* do not modify root label */
  631. *len -= lablen+1;
  632. *dname += lablen+1;
  633. }
  634. void
  635. dname_remove_labels(uint8_t** dname, size_t* len, int n)
  636. {
  637. int i;
  638. for(i=0; i<n; i++)
  639. dname_remove_label(dname, len);
  640. }
  641. int
  642. dname_signame_label_count(uint8_t* dname)
  643. {
  644. uint8_t lablen;
  645. int count = 0;
  646. if(!*dname)
  647. return 0;
  648. if(dname[0] == 1 && dname[1] == '*')
  649. dname += 2;
  650. lablen = dname[0];
  651. while(lablen) {
  652. count++;
  653. dname += lablen;
  654. dname += 1;
  655. lablen = dname[0];
  656. }
  657. return count;
  658. }
  659. int
  660. dname_is_wild(uint8_t* dname)
  661. {
  662. return (dname[0] == 1 && dname[1] == '*');
  663. }
  664. /**
  665. * Compare labels in memory, lowercase while comparing.
  666. * Returns canonical order for labels. If all is equal, the
  667. * shortest is first.
  668. *
  669. * @param p1: label 1
  670. * @param len1: length of label 1.
  671. * @param p2: label 2
  672. * @param len2: length of label 2.
  673. * @return: 0, -1, +1 comparison result.
  674. */
  675. static int
  676. memcanoncmp(uint8_t* p1, uint8_t len1, uint8_t* p2, uint8_t len2)
  677. {
  678. uint8_t min = (len1<len2)?len1:len2;
  679. int c = memlowercmp(p1, p2, min);
  680. if(c != 0)
  681. return c;
  682. /* equal, see who is shortest */
  683. if(len1 < len2)
  684. return -1;
  685. if(len1 > len2)
  686. return 1;
  687. return 0;
  688. }
  689. int
  690. dname_canon_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs)
  691. {
  692. /* like dname_lab_cmp, but with different label comparison,
  693. * empty character sorts before \000.
  694. * So ylyly is before z. */
  695. uint8_t len1, len2;
  696. int atlabel = labs1;
  697. int lastmlabs;
  698. int lastdiff = 0;
  699. int c;
  700. /* first skip so that we compare same label. */
  701. if(labs1 > labs2) {
  702. while(atlabel > labs2) {
  703. len1 = *d1++;
  704. d1 += len1;
  705. atlabel--;
  706. }
  707. log_assert(atlabel == labs2);
  708. } else if(labs1 < labs2) {
  709. atlabel = labs2;
  710. while(atlabel > labs1) {
  711. len2 = *d2++;
  712. d2 += len2;
  713. atlabel--;
  714. }
  715. log_assert(atlabel == labs1);
  716. }
  717. lastmlabs = atlabel+1;
  718. /* now at same label in d1 and d2, atlabel */
  719. /* www.example.com. */
  720. /* 4 3 2 1 atlabel number */
  721. /* repeat until at root label (which is always the same) */
  722. while(atlabel > 1) {
  723. len1 = *d1++;
  724. len2 = *d2++;
  725. if((c=memcanoncmp(d1, len1, d2, len2)) != 0) {
  726. if(c<0)
  727. lastdiff = -1;
  728. else lastdiff = 1;
  729. lastmlabs = atlabel;
  730. }
  731. d1 += len1;
  732. d2 += len2;
  733. atlabel--;
  734. }
  735. /* last difference atlabel number, so number of labels matching,
  736. * at the right side, is one less. */
  737. *mlabs = lastmlabs-1;
  738. if(lastdiff == 0) {
  739. /* all labels compared were equal, check if one has more
  740. * labels, so that example.com. > com. */
  741. if(labs1 > labs2)
  742. return 1;
  743. else if(labs1 < labs2)
  744. return -1;
  745. }
  746. return lastdiff;
  747. }
  748. int
  749. dname_canonical_compare(uint8_t* d1, uint8_t* d2)
  750. {
  751. int labs1, labs2, m;
  752. labs1 = dname_count_labels(d1);
  753. labs2 = dname_count_labels(d2);
  754. return dname_canon_lab_cmp(d1, labs1, d2, labs2, &m);
  755. }
  756. uint8_t* dname_get_shared_topdomain(uint8_t* d1, uint8_t* d2)
  757. {
  758. int labs1, labs2, m;
  759. size_t len = LDNS_MAX_DOMAINLEN;
  760. labs1 = dname_count_labels(d1);
  761. labs2 = dname_count_labels(d2);
  762. (void)dname_lab_cmp(d1, labs1, d2, labs2, &m);
  763. dname_remove_labels(&d1, &len, labs1-m);
  764. return d1;
  765. }