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

https://bitbucket.org/freebsd/freebsd-head/ · C · 466 lines · 343 code · 74 blank · 49 comment · 98 complexity · 330897ecea8db0d868c86e8ab5939499 MD5 · raw file

  1. /*
  2. * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (C) 1999-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: a6_38.c,v 1.56 2009/12/04 22:06:37 tbox Exp $ */
  18. /* RFC2874 */
  19. #ifndef RDATA_IN_1_A6_28_C
  20. #define RDATA_IN_1_A6_28_C
  21. #include <isc/net.h>
  22. #define RRTYPE_A6_ATTRIBUTES (0)
  23. static inline isc_result_t
  24. fromtext_in_a6(ARGS_FROMTEXT) {
  25. isc_token_t token;
  26. unsigned char addr[16];
  27. unsigned char prefixlen;
  28. unsigned char octets;
  29. unsigned char mask;
  30. dns_name_t name;
  31. isc_buffer_t buffer;
  32. isc_boolean_t ok;
  33. REQUIRE(type == 38);
  34. REQUIRE(rdclass == 1);
  35. UNUSED(type);
  36. UNUSED(rdclass);
  37. UNUSED(callbacks);
  38. /*
  39. * Prefix length.
  40. */
  41. RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
  42. ISC_FALSE));
  43. if (token.value.as_ulong > 128U)
  44. RETTOK(ISC_R_RANGE);
  45. prefixlen = (unsigned char)token.value.as_ulong;
  46. RETERR(mem_tobuffer(target, &prefixlen, 1));
  47. /*
  48. * Suffix.
  49. */
  50. if (prefixlen != 128) {
  51. /*
  52. * Prefix 0..127.
  53. */
  54. octets = prefixlen/8;
  55. /*
  56. * Octets 0..15.
  57. */
  58. RETERR(isc_lex_getmastertoken(lexer, &token,
  59. isc_tokentype_string,
  60. ISC_FALSE));
  61. if (inet_pton(AF_INET6, DNS_AS_STR(token), addr) != 1)
  62. RETTOK(DNS_R_BADAAAA);
  63. mask = 0xff >> (prefixlen % 8);
  64. addr[octets] &= mask;
  65. RETERR(mem_tobuffer(target, &addr[octets], 16 - octets));
  66. }
  67. if (prefixlen == 0)
  68. return (ISC_R_SUCCESS);
  69. RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
  70. ISC_FALSE));
  71. dns_name_init(&name, NULL);
  72. buffer_fromregion(&buffer, &token.value.as_region);
  73. origin = (origin != NULL) ? origin : dns_rootname;
  74. RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
  75. ok = ISC_TRUE;
  76. if ((options & DNS_RDATA_CHECKNAMES) != 0)
  77. ok = dns_name_ishostname(&name, ISC_FALSE);
  78. if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0)
  79. RETTOK(DNS_R_BADNAME);
  80. if (!ok && callbacks != NULL)
  81. warn_badname(&name, lexer, callbacks);
  82. return (ISC_R_SUCCESS);
  83. }
  84. static inline isc_result_t
  85. totext_in_a6(ARGS_TOTEXT) {
  86. isc_region_t sr, ar;
  87. unsigned char addr[16];
  88. unsigned char prefixlen;
  89. unsigned char octets;
  90. unsigned char mask;
  91. char buf[sizeof("128")];
  92. dns_name_t name;
  93. dns_name_t prefix;
  94. isc_boolean_t sub;
  95. REQUIRE(rdata->type == 38);
  96. REQUIRE(rdata->rdclass == 1);
  97. REQUIRE(rdata->length != 0);
  98. dns_rdata_toregion(rdata, &sr);
  99. prefixlen = sr.base[0];
  100. INSIST(prefixlen <= 128);
  101. isc_region_consume(&sr, 1);
  102. sprintf(buf, "%u", prefixlen);
  103. RETERR(str_totext(buf, target));
  104. RETERR(str_totext(" ", target));
  105. if (prefixlen != 128) {
  106. octets = prefixlen/8;
  107. memset(addr, 0, sizeof(addr));
  108. memcpy(&addr[octets], sr.base, 16 - octets);
  109. mask = 0xff >> (prefixlen % 8);
  110. addr[octets] &= mask;
  111. ar.base = addr;
  112. ar.length = sizeof(addr);
  113. RETERR(inet_totext(AF_INET6, &ar, target));
  114. isc_region_consume(&sr, 16 - octets);
  115. }
  116. if (prefixlen == 0)
  117. return (ISC_R_SUCCESS);
  118. RETERR(str_totext(" ", target));
  119. dns_name_init(&name, NULL);
  120. dns_name_init(&prefix, NULL);
  121. dns_name_fromregion(&name, &sr);
  122. sub = name_prefix(&name, tctx->origin, &prefix);
  123. return (dns_name_totext(&prefix, sub, target));
  124. }
  125. static inline isc_result_t
  126. fromwire_in_a6(ARGS_FROMWIRE) {
  127. isc_region_t sr;
  128. unsigned char prefixlen;
  129. unsigned char octets;
  130. unsigned char mask;
  131. dns_name_t name;
  132. REQUIRE(type == 38);
  133. REQUIRE(rdclass == 1);
  134. UNUSED(type);
  135. UNUSED(rdclass);
  136. dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
  137. isc_buffer_activeregion(source, &sr);
  138. /*
  139. * Prefix length.
  140. */
  141. if (sr.length < 1)
  142. return (ISC_R_UNEXPECTEDEND);
  143. prefixlen = sr.base[0];
  144. if (prefixlen > 128)
  145. return (ISC_R_RANGE);
  146. isc_region_consume(&sr, 1);
  147. RETERR(mem_tobuffer(target, &prefixlen, 1));
  148. isc_buffer_forward(source, 1);
  149. /*
  150. * Suffix.
  151. */
  152. if (prefixlen != 128) {
  153. octets = 16 - prefixlen / 8;
  154. if (sr.length < octets)
  155. return (ISC_R_UNEXPECTEDEND);
  156. mask = 0xff >> (prefixlen % 8);
  157. sr.base[0] &= mask; /* Ensure pad bits are zero. */
  158. RETERR(mem_tobuffer(target, sr.base, octets));
  159. isc_buffer_forward(source, octets);
  160. }
  161. if (prefixlen == 0)
  162. return (ISC_R_SUCCESS);
  163. dns_name_init(&name, NULL);
  164. return (dns_name_fromwire(&name, source, dctx, options, target));
  165. }
  166. static inline isc_result_t
  167. towire_in_a6(ARGS_TOWIRE) {
  168. isc_region_t sr;
  169. dns_name_t name;
  170. dns_offsets_t offsets;
  171. unsigned char prefixlen;
  172. unsigned char octets;
  173. REQUIRE(rdata->type == 38);
  174. REQUIRE(rdata->rdclass == 1);
  175. REQUIRE(rdata->length != 0);
  176. dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
  177. dns_rdata_toregion(rdata, &sr);
  178. prefixlen = sr.base[0];
  179. INSIST(prefixlen <= 128);
  180. octets = 1 + 16 - prefixlen / 8;
  181. RETERR(mem_tobuffer(target, sr.base, octets));
  182. isc_region_consume(&sr, octets);
  183. if (prefixlen == 0)
  184. return (ISC_R_SUCCESS);
  185. dns_name_init(&name, offsets);
  186. dns_name_fromregion(&name, &sr);
  187. return (dns_name_towire(&name, cctx, target));
  188. }
  189. static inline int
  190. compare_in_a6(ARGS_COMPARE) {
  191. int order;
  192. unsigned char prefixlen1, prefixlen2;
  193. unsigned char octets;
  194. dns_name_t name1;
  195. dns_name_t name2;
  196. isc_region_t region1;
  197. isc_region_t region2;
  198. REQUIRE(rdata1->type == rdata2->type);
  199. REQUIRE(rdata1->rdclass == rdata2->rdclass);
  200. REQUIRE(rdata1->type == 38);
  201. REQUIRE(rdata1->rdclass == 1);
  202. REQUIRE(rdata1->length != 0);
  203. REQUIRE(rdata2->length != 0);
  204. dns_rdata_toregion(rdata1, &region1);
  205. dns_rdata_toregion(rdata2, &region2);
  206. prefixlen1 = region1.base[0];
  207. prefixlen2 = region2.base[0];
  208. isc_region_consume(&region1, 1);
  209. isc_region_consume(&region2, 1);
  210. if (prefixlen1 < prefixlen2)
  211. return (-1);
  212. else if (prefixlen1 > prefixlen2)
  213. return (1);
  214. /*
  215. * Prefix lengths are equal.
  216. */
  217. octets = 16 - prefixlen1 / 8;
  218. if (octets > 0) {
  219. order = memcmp(region1.base, region2.base, octets);
  220. if (order < 0)
  221. return (-1);
  222. else if (order > 0)
  223. return (1);
  224. /*
  225. * Address suffixes are equal.
  226. */
  227. if (prefixlen1 == 0)
  228. return (order);
  229. isc_region_consume(&region1, octets);
  230. isc_region_consume(&region2, octets);
  231. }
  232. dns_name_init(&name1, NULL);
  233. dns_name_init(&name2, NULL);
  234. dns_name_fromregion(&name1, &region1);
  235. dns_name_fromregion(&name2, &region2);
  236. return (dns_name_rdatacompare(&name1, &name2));
  237. }
  238. static inline isc_result_t
  239. fromstruct_in_a6(ARGS_FROMSTRUCT) {
  240. dns_rdata_in_a6_t *a6 = source;
  241. isc_region_t region;
  242. int octets;
  243. isc_uint8_t bits;
  244. isc_uint8_t first;
  245. isc_uint8_t mask;
  246. REQUIRE(type == 38);
  247. REQUIRE(rdclass == 1);
  248. REQUIRE(source != NULL);
  249. REQUIRE(a6->common.rdtype == type);
  250. REQUIRE(a6->common.rdclass == rdclass);
  251. UNUSED(type);
  252. UNUSED(rdclass);
  253. if (a6->prefixlen > 128)
  254. return (ISC_R_RANGE);
  255. RETERR(uint8_tobuffer(a6->prefixlen, target));
  256. /* Suffix */
  257. if (a6->prefixlen != 128) {
  258. octets = 16 - a6->prefixlen / 8;
  259. bits = a6->prefixlen % 8;
  260. if (bits != 0) {
  261. mask = 0xffU >> bits;
  262. first = a6->in6_addr.s6_addr[16 - octets] & mask;
  263. RETERR(uint8_tobuffer(first, target));
  264. octets--;
  265. }
  266. if (octets > 0)
  267. RETERR(mem_tobuffer(target,
  268. a6->in6_addr.s6_addr + 16 - octets,
  269. octets));
  270. }
  271. if (a6->prefixlen == 0)
  272. return (ISC_R_SUCCESS);
  273. dns_name_toregion(&a6->prefix, &region);
  274. return (isc_buffer_copyregion(target, &region));
  275. }
  276. static inline isc_result_t
  277. tostruct_in_a6(ARGS_TOSTRUCT) {
  278. dns_rdata_in_a6_t *a6 = target;
  279. unsigned char octets;
  280. dns_name_t name;
  281. isc_region_t r;
  282. REQUIRE(rdata->type == 38);
  283. REQUIRE(rdata->rdclass == 1);
  284. REQUIRE(target != NULL);
  285. REQUIRE(rdata->length != 0);
  286. a6->common.rdclass = rdata->rdclass;
  287. a6->common.rdtype = rdata->type;
  288. ISC_LINK_INIT(&a6->common, link);
  289. dns_rdata_toregion(rdata, &r);
  290. a6->prefixlen = uint8_fromregion(&r);
  291. isc_region_consume(&r, 1);
  292. memset(a6->in6_addr.s6_addr, 0, sizeof(a6->in6_addr.s6_addr));
  293. /*
  294. * Suffix.
  295. */
  296. if (a6->prefixlen != 128) {
  297. octets = 16 - a6->prefixlen / 8;
  298. INSIST(r.length >= octets);
  299. memcpy(a6->in6_addr.s6_addr + 16 - octets, r.base, octets);
  300. isc_region_consume(&r, octets);
  301. }
  302. /*
  303. * Prefix.
  304. */
  305. dns_name_init(&a6->prefix, NULL);
  306. if (a6->prefixlen != 0) {
  307. dns_name_init(&name, NULL);
  308. dns_name_fromregion(&name, &r);
  309. RETERR(name_duporclone(&name, mctx, &a6->prefix));
  310. }
  311. a6->mctx = mctx;
  312. return (ISC_R_SUCCESS);
  313. }
  314. static inline void
  315. freestruct_in_a6(ARGS_FREESTRUCT) {
  316. dns_rdata_in_a6_t *a6 = source;
  317. REQUIRE(source != NULL);
  318. REQUIRE(a6->common.rdclass == 1);
  319. REQUIRE(a6->common.rdtype == 38);
  320. if (a6->mctx == NULL)
  321. return;
  322. if (dns_name_dynamic(&a6->prefix))
  323. dns_name_free(&a6->prefix, a6->mctx);
  324. a6->mctx = NULL;
  325. }
  326. static inline isc_result_t
  327. additionaldata_in_a6(ARGS_ADDLDATA) {
  328. REQUIRE(rdata->type == 38);
  329. REQUIRE(rdata->rdclass == 1);
  330. UNUSED(rdata);
  331. UNUSED(add);
  332. UNUSED(arg);
  333. return (ISC_R_SUCCESS);
  334. }
  335. static inline isc_result_t
  336. digest_in_a6(ARGS_DIGEST) {
  337. isc_region_t r1, r2;
  338. unsigned char prefixlen, octets;
  339. isc_result_t result;
  340. dns_name_t name;
  341. REQUIRE(rdata->type == 38);
  342. REQUIRE(rdata->rdclass == 1);
  343. dns_rdata_toregion(rdata, &r1);
  344. r2 = r1;
  345. prefixlen = r1.base[0];
  346. octets = 1 + 16 - prefixlen / 8;
  347. r1.length = octets;
  348. result = (digest)(arg, &r1);
  349. if (result != ISC_R_SUCCESS)
  350. return (result);
  351. if (prefixlen == 0)
  352. return (ISC_R_SUCCESS);
  353. isc_region_consume(&r2, octets);
  354. dns_name_init(&name, NULL);
  355. dns_name_fromregion(&name, &r2);
  356. return (dns_name_digest(&name, digest, arg));
  357. }
  358. static inline isc_boolean_t
  359. checkowner_in_a6(ARGS_CHECKOWNER) {
  360. REQUIRE(type == 38);
  361. REQUIRE(rdclass == 1);
  362. UNUSED(type);
  363. UNUSED(rdclass);
  364. return (dns_name_ishostname(name, wildcard));
  365. }
  366. static inline isc_boolean_t
  367. checknames_in_a6(ARGS_CHECKNAMES) {
  368. isc_region_t region;
  369. dns_name_t name;
  370. unsigned int prefixlen;
  371. REQUIRE(rdata->type == 38);
  372. REQUIRE(rdata->rdclass == 1);
  373. UNUSED(owner);
  374. dns_rdata_toregion(rdata, &region);
  375. prefixlen = uint8_fromregion(&region);
  376. if (prefixlen == 0)
  377. return (ISC_TRUE);
  378. isc_region_consume(&region, 1 + 16 - prefixlen / 8);
  379. dns_name_init(&name, NULL);
  380. dns_name_fromregion(&name, &region);
  381. if (!dns_name_ishostname(&name, ISC_FALSE)) {
  382. if (bad != NULL)
  383. dns_name_clone(&name, bad);
  384. return (ISC_FALSE);
  385. }
  386. return (ISC_TRUE);
  387. }
  388. static inline int
  389. casecompare_in_a6(ARGS_COMPARE) {
  390. return (compare_in_a6(rdata1, rdata2));
  391. }
  392. #endif /* RDATA_IN_1_A6_38_C */