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

https://bitbucket.org/freebsd/freebsd-head/ · C · 458 lines · 338 code · 75 blank · 45 comment · 111 complexity · f7bf47eb191a20cecbac800be17769c8 MD5 · raw file

  1. /*
  2. * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (C) 2002 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: apl_42.c,v 1.16 2009/12/04 22:06:37 tbox Exp $ */
  18. /* RFC3123 */
  19. #ifndef RDATA_IN_1_APL_42_C
  20. #define RDATA_IN_1_APL_42_C
  21. #define RRTYPE_APL_ATTRIBUTES (0)
  22. static inline isc_result_t
  23. fromtext_in_apl(ARGS_FROMTEXT) {
  24. isc_token_t token;
  25. unsigned char addr[16];
  26. unsigned long afi;
  27. isc_uint8_t prefix;
  28. isc_uint8_t len;
  29. isc_boolean_t neg;
  30. char *cp, *ap, *slash;
  31. int n;
  32. REQUIRE(type == 42);
  33. REQUIRE(rdclass == 1);
  34. UNUSED(type);
  35. UNUSED(rdclass);
  36. UNUSED(origin);
  37. UNUSED(options);
  38. UNUSED(callbacks);
  39. do {
  40. RETERR(isc_lex_getmastertoken(lexer, &token,
  41. isc_tokentype_string, ISC_TRUE));
  42. if (token.type != isc_tokentype_string)
  43. break;
  44. cp = DNS_AS_STR(token);
  45. neg = ISC_TF(*cp == '!');
  46. if (neg)
  47. cp++;
  48. afi = strtoul(cp, &ap, 10);
  49. if (*ap++ != ':' || cp == ap)
  50. RETTOK(DNS_R_SYNTAX);
  51. if (afi > 0xffffU)
  52. RETTOK(ISC_R_RANGE);
  53. slash = strchr(ap, '/');
  54. if (slash == NULL || slash == ap)
  55. RETTOK(DNS_R_SYNTAX);
  56. RETTOK(isc_parse_uint8(&prefix, slash + 1, 10));
  57. switch (afi) {
  58. case 1:
  59. *slash = '\0';
  60. n = inet_pton(AF_INET, ap, addr);
  61. *slash = '/';
  62. if (n != 1)
  63. RETTOK(DNS_R_BADDOTTEDQUAD);
  64. if (prefix > 32)
  65. RETTOK(ISC_R_RANGE);
  66. for (len = 4; len > 0; len--)
  67. if (addr[len - 1] != 0)
  68. break;
  69. break;
  70. case 2:
  71. *slash = '\0';
  72. n = inet_pton(AF_INET6, ap, addr);
  73. *slash = '/';
  74. if (n != 1)
  75. RETTOK(DNS_R_BADAAAA);
  76. if (prefix > 128)
  77. RETTOK(ISC_R_RANGE);
  78. for (len = 16; len > 0; len--)
  79. if (addr[len - 1] != 0)
  80. break;
  81. break;
  82. default:
  83. RETTOK(ISC_R_NOTIMPLEMENTED);
  84. }
  85. RETERR(uint16_tobuffer(afi, target));
  86. RETERR(uint8_tobuffer(prefix, target));
  87. RETERR(uint8_tobuffer(len | ((neg) ? 0x80 : 0), target));
  88. RETERR(mem_tobuffer(target, addr, len));
  89. } while (1);
  90. /*
  91. * Let upper layer handle eol/eof.
  92. */
  93. isc_lex_ungettoken(lexer, &token);
  94. return (ISC_R_SUCCESS);
  95. }
  96. static inline isc_result_t
  97. totext_in_apl(ARGS_TOTEXT) {
  98. isc_region_t sr;
  99. isc_region_t ir;
  100. isc_uint16_t afi;
  101. isc_uint8_t prefix;
  102. isc_uint8_t len;
  103. isc_boolean_t neg;
  104. unsigned char buf[16];
  105. char txt[sizeof(" !64000")];
  106. const char *sep = "";
  107. int n;
  108. REQUIRE(rdata->type == 42);
  109. REQUIRE(rdata->rdclass == 1);
  110. UNUSED(tctx);
  111. dns_rdata_toregion(rdata, &sr);
  112. ir.base = buf;
  113. ir.length = sizeof(buf);
  114. while (sr.length > 0) {
  115. INSIST(sr.length >= 4);
  116. afi = uint16_fromregion(&sr);
  117. isc_region_consume(&sr, 2);
  118. prefix = *sr.base;
  119. isc_region_consume(&sr, 1);
  120. len = (*sr.base & 0x7f);
  121. neg = ISC_TF((*sr.base & 0x80) != 0);
  122. isc_region_consume(&sr, 1);
  123. INSIST(len <= sr.length);
  124. n = snprintf(txt, sizeof(txt), "%s%s%u:", sep,
  125. neg ? "!": "", afi);
  126. INSIST(n < (int)sizeof(txt));
  127. RETERR(str_totext(txt, target));
  128. switch (afi) {
  129. case 1:
  130. INSIST(len <= 4);
  131. INSIST(prefix <= 32);
  132. memset(buf, 0, sizeof(buf));
  133. memcpy(buf, sr.base, len);
  134. RETERR(inet_totext(AF_INET, &ir, target));
  135. break;
  136. case 2:
  137. INSIST(len <= 16);
  138. INSIST(prefix <= 128);
  139. memset(buf, 0, sizeof(buf));
  140. memcpy(buf, sr.base, len);
  141. RETERR(inet_totext(AF_INET6, &ir, target));
  142. break;
  143. default:
  144. return (ISC_R_NOTIMPLEMENTED);
  145. }
  146. n = snprintf(txt, sizeof(txt), "/%u", prefix);
  147. INSIST(n < (int)sizeof(txt));
  148. RETERR(str_totext(txt, target));
  149. isc_region_consume(&sr, len);
  150. sep = " ";
  151. }
  152. return (ISC_R_SUCCESS);
  153. }
  154. static inline isc_result_t
  155. fromwire_in_apl(ARGS_FROMWIRE) {
  156. isc_region_t sr, sr2;
  157. isc_region_t tr;
  158. isc_uint16_t afi;
  159. isc_uint8_t prefix;
  160. isc_uint8_t len;
  161. REQUIRE(type == 42);
  162. REQUIRE(rdclass == 1);
  163. UNUSED(type);
  164. UNUSED(dctx);
  165. UNUSED(rdclass);
  166. UNUSED(options);
  167. isc_buffer_activeregion(source, &sr);
  168. isc_buffer_availableregion(target, &tr);
  169. if (sr.length > tr.length)
  170. return (ISC_R_NOSPACE);
  171. sr2 = sr;
  172. /* Zero or more items */
  173. while (sr.length > 0) {
  174. if (sr.length < 4)
  175. return (ISC_R_UNEXPECTEDEND);
  176. afi = uint16_fromregion(&sr);
  177. isc_region_consume(&sr, 2);
  178. prefix = *sr.base;
  179. isc_region_consume(&sr, 1);
  180. len = (*sr.base & 0x7f);
  181. isc_region_consume(&sr, 1);
  182. if (len > sr.length)
  183. return (ISC_R_UNEXPECTEDEND);
  184. switch (afi) {
  185. case 1:
  186. if (prefix > 32 || len > 4)
  187. return (ISC_R_RANGE);
  188. break;
  189. case 2:
  190. if (prefix > 128 || len > 16)
  191. return (ISC_R_RANGE);
  192. }
  193. if (len > 0 && sr.base[len - 1] == 0)
  194. return (DNS_R_FORMERR);
  195. isc_region_consume(&sr, len);
  196. }
  197. isc_buffer_forward(source, sr2.length);
  198. return (mem_tobuffer(target, sr2.base, sr2.length));
  199. }
  200. static inline isc_result_t
  201. towire_in_apl(ARGS_TOWIRE) {
  202. UNUSED(cctx);
  203. REQUIRE(rdata->type == 42);
  204. REQUIRE(rdata->rdclass == 1);
  205. return (mem_tobuffer(target, rdata->data, rdata->length));
  206. }
  207. static inline int
  208. compare_in_apl(ARGS_COMPARE) {
  209. isc_region_t r1;
  210. isc_region_t r2;
  211. REQUIRE(rdata1->type == rdata2->type);
  212. REQUIRE(rdata1->rdclass == rdata2->rdclass);
  213. REQUIRE(rdata1->type == 42);
  214. REQUIRE(rdata1->rdclass == 1);
  215. dns_rdata_toregion(rdata1, &r1);
  216. dns_rdata_toregion(rdata2, &r2);
  217. return (isc_region_compare(&r1, &r2));
  218. }
  219. static inline isc_result_t
  220. fromstruct_in_apl(ARGS_FROMSTRUCT) {
  221. dns_rdata_in_apl_t *apl = source;
  222. isc_buffer_t b;
  223. REQUIRE(type == 42);
  224. REQUIRE(rdclass == 1);
  225. REQUIRE(source != NULL);
  226. REQUIRE(apl->common.rdtype == type);
  227. REQUIRE(apl->common.rdclass == rdclass);
  228. REQUIRE(apl->apl != NULL || apl->apl_len == 0);
  229. isc_buffer_init(&b, apl->apl, apl->apl_len);
  230. isc_buffer_add(&b, apl->apl_len);
  231. isc_buffer_setactive(&b, apl->apl_len);
  232. return(fromwire_in_apl(rdclass, type, &b, NULL, ISC_FALSE, target));
  233. }
  234. static inline isc_result_t
  235. tostruct_in_apl(ARGS_TOSTRUCT) {
  236. dns_rdata_in_apl_t *apl = target;
  237. isc_region_t r;
  238. REQUIRE(rdata->type == 42);
  239. REQUIRE(rdata->rdclass == 1);
  240. apl->common.rdclass = rdata->rdclass;
  241. apl->common.rdtype = rdata->type;
  242. ISC_LINK_INIT(&apl->common, link);
  243. dns_rdata_toregion(rdata, &r);
  244. apl->apl_len = r.length;
  245. apl->apl = mem_maybedup(mctx, r.base, r.length);
  246. if (apl->apl == NULL)
  247. return (ISC_R_NOMEMORY);
  248. apl->offset = 0;
  249. apl->mctx = mctx;
  250. return (ISC_R_SUCCESS);
  251. }
  252. static inline void
  253. freestruct_in_apl(ARGS_FREESTRUCT) {
  254. dns_rdata_in_apl_t *apl = source;
  255. REQUIRE(source != NULL);
  256. REQUIRE(apl->common.rdtype == 42);
  257. REQUIRE(apl->common.rdclass == 1);
  258. if (apl->mctx == NULL)
  259. return;
  260. if (apl->apl != NULL)
  261. isc_mem_free(apl->mctx, apl->apl);
  262. apl->mctx = NULL;
  263. }
  264. isc_result_t
  265. dns_rdata_apl_first(dns_rdata_in_apl_t *apl) {
  266. isc_uint32_t length;
  267. REQUIRE(apl != NULL);
  268. REQUIRE(apl->common.rdtype == 42);
  269. REQUIRE(apl->common.rdclass == 1);
  270. REQUIRE(apl->apl != NULL || apl->apl_len == 0);
  271. /*
  272. * If no APL return ISC_R_NOMORE.
  273. */
  274. if (apl->apl == NULL)
  275. return (ISC_R_NOMORE);
  276. /*
  277. * Sanity check data.
  278. */
  279. INSIST(apl->apl_len > 3U);
  280. length = apl->apl[apl->offset + 3] & 0x7f;
  281. INSIST(length <= apl->apl_len);
  282. apl->offset = 0;
  283. return (ISC_R_SUCCESS);
  284. }
  285. isc_result_t
  286. dns_rdata_apl_next(dns_rdata_in_apl_t *apl) {
  287. isc_uint32_t length;
  288. REQUIRE(apl != NULL);
  289. REQUIRE(apl->common.rdtype == 42);
  290. REQUIRE(apl->common.rdclass == 1);
  291. REQUIRE(apl->apl != NULL || apl->apl_len == 0);
  292. /*
  293. * No APL or have already reached the end return ISC_R_NOMORE.
  294. */
  295. if (apl->apl == NULL || apl->offset == apl->apl_len)
  296. return (ISC_R_NOMORE);
  297. /*
  298. * Sanity check data.
  299. */
  300. INSIST(apl->offset < apl->apl_len);
  301. INSIST(apl->apl_len > 3U);
  302. INSIST(apl->offset <= apl->apl_len - 4U);
  303. length = apl->apl[apl->offset + 3] & 0x7f;
  304. /*
  305. * 16 to 32 bits promotion as 'length' is 32 bits so there is
  306. * no overflow problems.
  307. */
  308. INSIST(length + apl->offset <= apl->apl_len);
  309. apl->offset += apl->apl[apl->offset + 3] & 0x7f;
  310. return ((apl->offset >= apl->apl_len) ? ISC_R_SUCCESS : ISC_R_NOMORE);
  311. }
  312. isc_result_t
  313. dns_rdata_apl_current(dns_rdata_in_apl_t *apl, dns_rdata_apl_ent_t *ent) {
  314. isc_uint32_t length;
  315. REQUIRE(apl != NULL);
  316. REQUIRE(apl->common.rdtype == 42);
  317. REQUIRE(apl->common.rdclass == 1);
  318. REQUIRE(ent != NULL);
  319. REQUIRE(apl->apl != NULL || apl->apl_len == 0);
  320. REQUIRE(apl->offset <= apl->apl_len);
  321. if (apl->offset == apl->apl_len)
  322. return (ISC_R_NOMORE);
  323. /*
  324. * Sanity check data.
  325. */
  326. INSIST(apl->apl_len > 3U);
  327. INSIST(apl->offset <= apl->apl_len - 4U);
  328. length = apl->apl[apl->offset + 3] & 0x7f;
  329. /*
  330. * 16 to 32 bits promotion as 'length' is 32 bits so there is
  331. * no overflow problems.
  332. */
  333. INSIST(length + apl->offset <= apl->apl_len);
  334. ent->family = (apl->apl[apl->offset] << 8) + apl->apl[apl->offset + 1];
  335. ent->prefix = apl->apl[apl->offset + 2];
  336. ent->length = apl->apl[apl->offset + 3] & 0x7f;
  337. ent->negative = ISC_TF((apl->apl[apl->offset + 3] & 0x80) != 0);
  338. if (ent->length != 0)
  339. ent->data = &apl->apl[apl->offset + 4];
  340. else
  341. ent->data = NULL;
  342. return (ISC_R_SUCCESS);
  343. }
  344. static inline isc_result_t
  345. additionaldata_in_apl(ARGS_ADDLDATA) {
  346. REQUIRE(rdata->type == 42);
  347. REQUIRE(rdata->rdclass == 1);
  348. (void)add;
  349. (void)arg;
  350. return (ISC_R_SUCCESS);
  351. }
  352. static inline isc_result_t
  353. digest_in_apl(ARGS_DIGEST) {
  354. isc_region_t r;
  355. REQUIRE(rdata->type == 42);
  356. REQUIRE(rdata->rdclass == 1);
  357. dns_rdata_toregion(rdata, &r);
  358. return ((digest)(arg, &r));
  359. }
  360. static inline isc_boolean_t
  361. checkowner_in_apl(ARGS_CHECKOWNER) {
  362. REQUIRE(type == 42);
  363. REQUIRE(rdclass == 1);
  364. UNUSED(name);
  365. UNUSED(type);
  366. UNUSED(rdclass);
  367. UNUSED(wildcard);
  368. return (ISC_TRUE);
  369. }
  370. static inline isc_boolean_t
  371. checknames_in_apl(ARGS_CHECKNAMES) {
  372. REQUIRE(rdata->type == 42);
  373. REQUIRE(rdata->rdclass == 1);
  374. UNUSED(rdata);
  375. UNUSED(owner);
  376. UNUSED(bad);
  377. return (ISC_TRUE);
  378. }
  379. static inline int
  380. casecompare_in_apl(ARGS_COMPARE) {
  381. return (compare_in_apl(rdata1, rdata2));
  382. }
  383. #endif /* RDATA_IN_1_APL_42_C */