/contrib/bind9/lib/dns/rdata/in_1/naptr_35.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 710 lines · 456 code · 107 blank · 147 comment · 138 complexity · fa9703acc10abada13acce9b1dde9836 MD5 · raw file

  1. /*
  2. * Copyright (C) 2004, 2005, 2007-2009, 2012 Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (C) 1999-2001, 2003 Internet Software Consortium.
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  10. * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  11. * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  12. * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  13. * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  14. * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  15. * PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. /* $Id$ */
  18. /* Reviewed: Thu Mar 16 16:52:50 PST 2000 by bwelling */
  19. /* RFC2915 */
  20. #ifndef RDATA_IN_1_NAPTR_35_C
  21. #define RDATA_IN_1_NAPTR_35_C
  22. #define RRTYPE_NAPTR_ATTRIBUTES (0)
  23. #ifdef HAVE_REGEX_H
  24. #include <regex.h>
  25. #endif
  26. /*
  27. * Check the wire format of the Regexp field.
  28. * Don't allow embeded NUL's.
  29. */
  30. static inline isc_result_t
  31. txt_valid_regex(const unsigned char *txt) {
  32. #ifdef HAVE_REGEX_H
  33. regex_t preg;
  34. unsigned int regflags = REG_EXTENDED;
  35. unsigned int nsub = 0;
  36. char regex[256];
  37. char *cp;
  38. #endif
  39. isc_boolean_t flags = ISC_FALSE;
  40. isc_boolean_t replace = ISC_FALSE;
  41. unsigned char c;
  42. unsigned char delim;
  43. unsigned int len;
  44. len = *txt++;
  45. if (len == 0U)
  46. return (ISC_R_SUCCESS);
  47. delim = *txt++;
  48. len--;
  49. /*
  50. * Digits, backslash and flags can't be delimiters.
  51. */
  52. switch (delim) {
  53. case '0': case '1': case '2': case '3': case '4':
  54. case '5': case '6': case '7': case '8': case '9':
  55. case '\\': case 'i': case 0:
  56. return (DNS_R_SYNTAX);
  57. }
  58. #ifdef HAVE_REGEX_H
  59. memset(&preg, 0, sizeof(preg));
  60. cp = regex;
  61. #endif
  62. while (len-- > 0) {
  63. c = *txt++;
  64. if (c == 0)
  65. return (DNS_R_SYNTAX);
  66. if (c == delim && !replace) {
  67. replace = ISC_TRUE;
  68. continue;
  69. } else if (c == delim && !flags) {
  70. flags = ISC_TRUE;
  71. continue;
  72. } else if (c == delim)
  73. return (DNS_R_SYNTAX);
  74. /*
  75. * Flags are not escaped.
  76. */
  77. if (flags) {
  78. switch (c) {
  79. case 'i':
  80. #ifdef HAVE_REGEX_H
  81. regflags |= REG_ICASE;
  82. #endif
  83. continue;
  84. default:
  85. return (DNS_R_SYNTAX);
  86. }
  87. }
  88. #ifdef HAVE_REGEX_H
  89. if (!replace)
  90. *cp++ = c;
  91. #endif
  92. if (c == '\\') {
  93. if (len == 0)
  94. return (DNS_R_SYNTAX);
  95. c = *txt++;
  96. if (c == 0)
  97. return (DNS_R_SYNTAX);
  98. len--;
  99. if (replace)
  100. switch (c) {
  101. case '0': return (DNS_R_SYNTAX);
  102. #ifdef HAVE_REGEX_H
  103. case '1': if (nsub < 1) nsub = 1; break;
  104. case '2': if (nsub < 2) nsub = 2; break;
  105. case '3': if (nsub < 3) nsub = 3; break;
  106. case '4': if (nsub < 4) nsub = 4; break;
  107. case '5': if (nsub < 5) nsub = 5; break;
  108. case '6': if (nsub < 6) nsub = 6; break;
  109. case '7': if (nsub < 7) nsub = 7; break;
  110. case '8': if (nsub < 8) nsub = 8; break;
  111. case '9': if (nsub < 9) nsub = 9; break;
  112. #endif
  113. }
  114. #ifdef HAVE_REGEX_H
  115. if (!replace)
  116. *cp++ = c;
  117. #endif
  118. }
  119. }
  120. if (!flags)
  121. return (DNS_R_SYNTAX);
  122. #ifdef HAVE_REGEX_H
  123. *cp = '\0';
  124. if (regcomp(&preg, regex, regflags))
  125. return (DNS_R_SYNTAX);
  126. /*
  127. * Check that substitutions in the replacement string are consistant
  128. * with the regular expression.
  129. */
  130. if (preg.re_nsub < nsub) {
  131. regfree(&preg);
  132. return (DNS_R_SYNTAX);
  133. }
  134. regfree(&preg);
  135. #endif
  136. return (ISC_R_SUCCESS);
  137. }
  138. static inline isc_result_t
  139. fromtext_in_naptr(ARGS_FROMTEXT) {
  140. isc_token_t token;
  141. dns_name_t name;
  142. isc_buffer_t buffer;
  143. unsigned char *regex;
  144. REQUIRE(type == 35);
  145. REQUIRE(rdclass == 1);
  146. UNUSED(type);
  147. UNUSED(rdclass);
  148. UNUSED(callbacks);
  149. /*
  150. * Order.
  151. */
  152. RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
  153. ISC_FALSE));
  154. if (token.value.as_ulong > 0xffffU)
  155. RETTOK(ISC_R_RANGE);
  156. RETERR(uint16_tobuffer(token.value.as_ulong, target));
  157. /*
  158. * Preference.
  159. */
  160. RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
  161. ISC_FALSE));
  162. if (token.value.as_ulong > 0xffffU)
  163. RETTOK(ISC_R_RANGE);
  164. RETERR(uint16_tobuffer(token.value.as_ulong, target));
  165. /*
  166. * Flags.
  167. */
  168. RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
  169. ISC_FALSE));
  170. RETTOK(txt_fromtext(&token.value.as_textregion, target));
  171. /*
  172. * Service.
  173. */
  174. RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
  175. ISC_FALSE));
  176. RETTOK(txt_fromtext(&token.value.as_textregion, target));
  177. /*
  178. * Regexp.
  179. */
  180. regex = isc_buffer_used(target);
  181. RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
  182. ISC_FALSE));
  183. RETTOK(txt_fromtext(&token.value.as_textregion, target));
  184. RETTOK(txt_valid_regex(regex));
  185. /*
  186. * Replacement.
  187. */
  188. RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
  189. ISC_FALSE));
  190. dns_name_init(&name, NULL);
  191. buffer_fromregion(&buffer, &token.value.as_region);
  192. origin = (origin != NULL) ? origin : dns_rootname;
  193. RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
  194. return (ISC_R_SUCCESS);
  195. }
  196. static inline isc_result_t
  197. totext_in_naptr(ARGS_TOTEXT) {
  198. isc_region_t region;
  199. dns_name_t name;
  200. dns_name_t prefix;
  201. isc_boolean_t sub;
  202. char buf[sizeof("64000")];
  203. unsigned short num;
  204. REQUIRE(rdata->type == 35);
  205. REQUIRE(rdata->rdclass == 1);
  206. REQUIRE(rdata->length != 0);
  207. dns_name_init(&name, NULL);
  208. dns_name_init(&prefix, NULL);
  209. dns_rdata_toregion(rdata, &region);
  210. /*
  211. * Order.
  212. */
  213. num = uint16_fromregion(&region);
  214. isc_region_consume(&region, 2);
  215. sprintf(buf, "%u", num);
  216. RETERR(str_totext(buf, target));
  217. RETERR(str_totext(" ", target));
  218. /*
  219. * Preference.
  220. */
  221. num = uint16_fromregion(&region);
  222. isc_region_consume(&region, 2);
  223. sprintf(buf, "%u", num);
  224. RETERR(str_totext(buf, target));
  225. RETERR(str_totext(" ", target));
  226. /*
  227. * Flags.
  228. */
  229. RETERR(txt_totext(&region, target));
  230. RETERR(str_totext(" ", target));
  231. /*
  232. * Service.
  233. */
  234. RETERR(txt_totext(&region, target));
  235. RETERR(str_totext(" ", target));
  236. /*
  237. * Regexp.
  238. */
  239. RETERR(txt_totext(&region, target));
  240. RETERR(str_totext(" ", target));
  241. /*
  242. * Replacement.
  243. */
  244. dns_name_fromregion(&name, &region);
  245. sub = name_prefix(&name, tctx->origin, &prefix);
  246. return (dns_name_totext(&prefix, sub, target));
  247. }
  248. static inline isc_result_t
  249. fromwire_in_naptr(ARGS_FROMWIRE) {
  250. dns_name_t name;
  251. isc_region_t sr;
  252. unsigned char *regex;
  253. REQUIRE(type == 35);
  254. REQUIRE(rdclass == 1);
  255. UNUSED(type);
  256. UNUSED(rdclass);
  257. dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
  258. dns_name_init(&name, NULL);
  259. /*
  260. * Order, preference.
  261. */
  262. isc_buffer_activeregion(source, &sr);
  263. if (sr.length < 4)
  264. return (ISC_R_UNEXPECTEDEND);
  265. RETERR(mem_tobuffer(target, sr.base, 4));
  266. isc_buffer_forward(source, 4);
  267. /*
  268. * Flags.
  269. */
  270. RETERR(txt_fromwire(source, target));
  271. /*
  272. * Service.
  273. */
  274. RETERR(txt_fromwire(source, target));
  275. /*
  276. * Regexp.
  277. */
  278. regex = isc_buffer_used(target);
  279. RETERR(txt_fromwire(source, target));
  280. RETERR(txt_valid_regex(regex));
  281. /*
  282. * Replacement.
  283. */
  284. return (dns_name_fromwire(&name, source, dctx, options, target));
  285. }
  286. static inline isc_result_t
  287. towire_in_naptr(ARGS_TOWIRE) {
  288. dns_name_t name;
  289. dns_offsets_t offsets;
  290. isc_region_t sr;
  291. REQUIRE(rdata->type == 35);
  292. REQUIRE(rdata->rdclass == 1);
  293. REQUIRE(rdata->length != 0);
  294. dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
  295. /*
  296. * Order, preference.
  297. */
  298. dns_rdata_toregion(rdata, &sr);
  299. RETERR(mem_tobuffer(target, sr.base, 4));
  300. isc_region_consume(&sr, 4);
  301. /*
  302. * Flags.
  303. */
  304. RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1));
  305. isc_region_consume(&sr, sr.base[0] + 1);
  306. /*
  307. * Service.
  308. */
  309. RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1));
  310. isc_region_consume(&sr, sr.base[0] + 1);
  311. /*
  312. * Regexp.
  313. */
  314. RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1));
  315. isc_region_consume(&sr, sr.base[0] + 1);
  316. /*
  317. * Replacement.
  318. */
  319. dns_name_init(&name, offsets);
  320. dns_name_fromregion(&name, &sr);
  321. return (dns_name_towire(&name, cctx, target));
  322. }
  323. static inline int
  324. compare_in_naptr(ARGS_COMPARE) {
  325. dns_name_t name1;
  326. dns_name_t name2;
  327. isc_region_t region1;
  328. isc_region_t region2;
  329. int order, len;
  330. REQUIRE(rdata1->type == rdata2->type);
  331. REQUIRE(rdata1->rdclass == rdata2->rdclass);
  332. REQUIRE(rdata1->type == 35);
  333. REQUIRE(rdata1->rdclass == 1);
  334. REQUIRE(rdata1->length != 0);
  335. REQUIRE(rdata2->length != 0);
  336. dns_rdata_toregion(rdata1, &region1);
  337. dns_rdata_toregion(rdata2, &region2);
  338. /*
  339. * Order, preference.
  340. */
  341. order = memcmp(region1.base, region2.base, 4);
  342. if (order != 0)
  343. return (order < 0 ? -1 : 1);
  344. isc_region_consume(&region1, 4);
  345. isc_region_consume(&region2, 4);
  346. /*
  347. * Flags.
  348. */
  349. len = ISC_MIN(region1.base[0], region2.base[0]);
  350. order = memcmp(region1.base, region2.base, len + 1);
  351. if (order != 0)
  352. return (order < 0 ? -1 : 1);
  353. isc_region_consume(&region1, region1.base[0] + 1);
  354. isc_region_consume(&region2, region2.base[0] + 1);
  355. /*
  356. * Service.
  357. */
  358. len = ISC_MIN(region1.base[0], region2.base[0]);
  359. order = memcmp(region1.base, region2.base, len + 1);
  360. if (order != 0)
  361. return (order < 0 ? -1 : 1);
  362. isc_region_consume(&region1, region1.base[0] + 1);
  363. isc_region_consume(&region2, region2.base[0] + 1);
  364. /*
  365. * Regexp.
  366. */
  367. len = ISC_MIN(region1.base[0], region2.base[0]);
  368. order = memcmp(region1.base, region2.base, len + 1);
  369. if (order != 0)
  370. return (order < 0 ? -1 : 1);
  371. isc_region_consume(&region1, region1.base[0] + 1);
  372. isc_region_consume(&region2, region2.base[0] + 1);
  373. /*
  374. * Replacement.
  375. */
  376. dns_name_init(&name1, NULL);
  377. dns_name_init(&name2, NULL);
  378. dns_name_fromregion(&name1, &region1);
  379. dns_name_fromregion(&name2, &region2);
  380. return (dns_name_rdatacompare(&name1, &name2));
  381. }
  382. static inline isc_result_t
  383. fromstruct_in_naptr(ARGS_FROMSTRUCT) {
  384. dns_rdata_in_naptr_t *naptr = source;
  385. isc_region_t region;
  386. REQUIRE(type == 35);
  387. REQUIRE(rdclass == 1);
  388. REQUIRE(source != NULL);
  389. REQUIRE(naptr->common.rdtype == type);
  390. REQUIRE(naptr->common.rdclass == rdclass);
  391. REQUIRE(naptr->flags != NULL || naptr->flags_len == 0);
  392. REQUIRE(naptr->service != NULL || naptr->service_len == 0);
  393. REQUIRE(naptr->regexp != NULL || naptr->regexp_len == 0);
  394. UNUSED(type);
  395. UNUSED(rdclass);
  396. RETERR(uint16_tobuffer(naptr->order, target));
  397. RETERR(uint16_tobuffer(naptr->preference, target));
  398. RETERR(uint8_tobuffer(naptr->flags_len, target));
  399. RETERR(mem_tobuffer(target, naptr->flags, naptr->flags_len));
  400. RETERR(uint8_tobuffer(naptr->service_len, target));
  401. RETERR(mem_tobuffer(target, naptr->service, naptr->service_len));
  402. RETERR(uint8_tobuffer(naptr->regexp_len, target));
  403. RETERR(mem_tobuffer(target, naptr->regexp, naptr->regexp_len));
  404. dns_name_toregion(&naptr->replacement, &region);
  405. return (isc_buffer_copyregion(target, &region));
  406. }
  407. static inline isc_result_t
  408. tostruct_in_naptr(ARGS_TOSTRUCT) {
  409. dns_rdata_in_naptr_t *naptr = target;
  410. isc_region_t r;
  411. isc_result_t result;
  412. dns_name_t name;
  413. REQUIRE(rdata->type == 35);
  414. REQUIRE(rdata->rdclass == 1);
  415. REQUIRE(target != NULL);
  416. REQUIRE(rdata->length != 0);
  417. naptr->common.rdclass = rdata->rdclass;
  418. naptr->common.rdtype = rdata->type;
  419. ISC_LINK_INIT(&naptr->common, link);
  420. naptr->flags = NULL;
  421. naptr->service = NULL;
  422. naptr->regexp = NULL;
  423. dns_rdata_toregion(rdata, &r);
  424. naptr->order = uint16_fromregion(&r);
  425. isc_region_consume(&r, 2);
  426. naptr->preference = uint16_fromregion(&r);
  427. isc_region_consume(&r, 2);
  428. naptr->flags_len = uint8_fromregion(&r);
  429. isc_region_consume(&r, 1);
  430. INSIST(naptr->flags_len <= r.length);
  431. naptr->flags = mem_maybedup(mctx, r.base, naptr->flags_len);
  432. if (naptr->flags == NULL)
  433. goto cleanup;
  434. isc_region_consume(&r, naptr->flags_len);
  435. naptr->service_len = uint8_fromregion(&r);
  436. isc_region_consume(&r, 1);
  437. INSIST(naptr->service_len <= r.length);
  438. naptr->service = mem_maybedup(mctx, r.base, naptr->service_len);
  439. if (naptr->service == NULL)
  440. goto cleanup;
  441. isc_region_consume(&r, naptr->service_len);
  442. naptr->regexp_len = uint8_fromregion(&r);
  443. isc_region_consume(&r, 1);
  444. INSIST(naptr->regexp_len <= r.length);
  445. naptr->regexp = mem_maybedup(mctx, r.base, naptr->regexp_len);
  446. if (naptr->regexp == NULL)
  447. goto cleanup;
  448. isc_region_consume(&r, naptr->regexp_len);
  449. dns_name_init(&name, NULL);
  450. dns_name_fromregion(&name, &r);
  451. dns_name_init(&naptr->replacement, NULL);
  452. result = name_duporclone(&name, mctx, &naptr->replacement);
  453. if (result != ISC_R_SUCCESS)
  454. goto cleanup;
  455. naptr->mctx = mctx;
  456. return (ISC_R_SUCCESS);
  457. cleanup:
  458. if (mctx != NULL && naptr->flags != NULL)
  459. isc_mem_free(mctx, naptr->flags);
  460. if (mctx != NULL && naptr->service != NULL)
  461. isc_mem_free(mctx, naptr->service);
  462. if (mctx != NULL && naptr->regexp != NULL)
  463. isc_mem_free(mctx, naptr->regexp);
  464. return (ISC_R_NOMEMORY);
  465. }
  466. static inline void
  467. freestruct_in_naptr(ARGS_FREESTRUCT) {
  468. dns_rdata_in_naptr_t *naptr = source;
  469. REQUIRE(source != NULL);
  470. REQUIRE(naptr->common.rdclass == 1);
  471. REQUIRE(naptr->common.rdtype == 35);
  472. if (naptr->mctx == NULL)
  473. return;
  474. if (naptr->flags != NULL)
  475. isc_mem_free(naptr->mctx, naptr->flags);
  476. if (naptr->service != NULL)
  477. isc_mem_free(naptr->mctx, naptr->service);
  478. if (naptr->regexp != NULL)
  479. isc_mem_free(naptr->mctx, naptr->regexp);
  480. dns_name_free(&naptr->replacement, naptr->mctx);
  481. naptr->mctx = NULL;
  482. }
  483. static inline isc_result_t
  484. additionaldata_in_naptr(ARGS_ADDLDATA) {
  485. dns_name_t name;
  486. dns_offsets_t offsets;
  487. isc_region_t sr;
  488. dns_rdatatype_t atype;
  489. unsigned int i, flagslen;
  490. char *cp;
  491. REQUIRE(rdata->type == 35);
  492. REQUIRE(rdata->rdclass == 1);
  493. /*
  494. * Order, preference.
  495. */
  496. dns_rdata_toregion(rdata, &sr);
  497. isc_region_consume(&sr, 4);
  498. /*
  499. * Flags.
  500. */
  501. atype = 0;
  502. flagslen = sr.base[0];
  503. cp = (char *)&sr.base[1];
  504. for (i = 0; i < flagslen; i++, cp++) {
  505. if (*cp == 'S' || *cp == 's') {
  506. atype = dns_rdatatype_srv;
  507. break;
  508. }
  509. if (*cp == 'A' || *cp == 'a') {
  510. atype = dns_rdatatype_a;
  511. break;
  512. }
  513. }
  514. isc_region_consume(&sr, flagslen + 1);
  515. /*
  516. * Service.
  517. */
  518. isc_region_consume(&sr, sr.base[0] + 1);
  519. /*
  520. * Regexp.
  521. */
  522. isc_region_consume(&sr, sr.base[0] + 1);
  523. /*
  524. * Replacement.
  525. */
  526. dns_name_init(&name, offsets);
  527. dns_name_fromregion(&name, &sr);
  528. if (atype != 0)
  529. return ((add)(arg, &name, atype));
  530. return (ISC_R_SUCCESS);
  531. }
  532. static inline isc_result_t
  533. digest_in_naptr(ARGS_DIGEST) {
  534. isc_region_t r1, r2;
  535. unsigned int length, n;
  536. isc_result_t result;
  537. dns_name_t name;
  538. REQUIRE(rdata->type == 35);
  539. REQUIRE(rdata->rdclass == 1);
  540. dns_rdata_toregion(rdata, &r1);
  541. r2 = r1;
  542. length = 0;
  543. /*
  544. * Order, preference.
  545. */
  546. length += 4;
  547. isc_region_consume(&r2, 4);
  548. /*
  549. * Flags.
  550. */
  551. n = r2.base[0] + 1;
  552. length += n;
  553. isc_region_consume(&r2, n);
  554. /*
  555. * Service.
  556. */
  557. n = r2.base[0] + 1;
  558. length += n;
  559. isc_region_consume(&r2, n);
  560. /*
  561. * Regexp.
  562. */
  563. n = r2.base[0] + 1;
  564. length += n;
  565. isc_region_consume(&r2, n);
  566. /*
  567. * Digest the RR up to the replacement name.
  568. */
  569. r1.length = length;
  570. result = (digest)(arg, &r1);
  571. if (result != ISC_R_SUCCESS)
  572. return (result);
  573. /*
  574. * Replacement.
  575. */
  576. dns_name_init(&name, NULL);
  577. dns_name_fromregion(&name, &r2);
  578. return (dns_name_digest(&name, digest, arg));
  579. }
  580. static inline isc_boolean_t
  581. checkowner_in_naptr(ARGS_CHECKOWNER) {
  582. REQUIRE(type == 35);
  583. REQUIRE(rdclass == 1);
  584. UNUSED(name);
  585. UNUSED(type);
  586. UNUSED(rdclass);
  587. UNUSED(wildcard);
  588. return (ISC_TRUE);
  589. }
  590. static inline isc_boolean_t
  591. checknames_in_naptr(ARGS_CHECKNAMES) {
  592. REQUIRE(rdata->type == 35);
  593. REQUIRE(rdata->rdclass == 1);
  594. UNUSED(rdata);
  595. UNUSED(owner);
  596. UNUSED(bad);
  597. return (ISC_TRUE);
  598. }
  599. static inline int
  600. casecompare_in_naptr(ARGS_COMPARE) {
  601. return (compare_in_naptr(rdata1, rdata2));
  602. }
  603. #endif /* RDATA_IN_1_NAPTR_35_C */