Sync usage with man page.
[netbsd-mini2440.git] / external / bsd / bind / dist / lib / dns / rdata / generic / nsec3_50.c
blob12e929c1af40a7e41efa9864952b278b17bae7df
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2008, 2009 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
19 /* Id: nsec3_50.c,v 1.7 2009/12/04 21:09:34 marka Exp */
22 * Copyright (C) 2004 Nominet, Ltd.
24 * Permission to use, copy, modify, and distribute this software for any
25 * purpose with or without fee is hereby granted, provided that the above
26 * copyright notice and this permission notice appear in all copies.
28 * THE SOFTWARE IS PROVIDED "AS IS" AND NOMINET DISCLAIMS ALL WARRANTIES WITH
29 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
30 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
31 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
32 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
33 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
34 * PERFORMANCE OF THIS SOFTWARE.
37 /* RFC 5155 */
39 #ifndef RDATA_GENERIC_NSEC3_50_C
40 #define RDATA_GENERIC_NSEC3_50_C
42 #include <isc/iterated_hash.h>
43 #include <isc/base32.h>
45 #define RRTYPE_NSEC3_ATTRIBUTES DNS_RDATATYPEATTR_DNSSEC
47 static inline isc_result_t
48 fromtext_nsec3(ARGS_FROMTEXT) {
49 isc_token_t token;
50 unsigned char bm[8*1024]; /* 64k bits */
51 dns_rdatatype_t covered;
52 int octet;
53 int window;
54 unsigned int flags;
55 unsigned char hashalg;
56 isc_buffer_t b;
58 REQUIRE(type == 50);
60 UNUSED(type);
61 UNUSED(rdclass);
62 UNUSED(callbacks);
63 UNUSED(origin);
64 UNUSED(options);
66 /* Hash. */
67 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
68 ISC_FALSE));
69 RETTOK(dns_hashalg_fromtext(&hashalg, &token.value.as_textregion));
70 RETERR(uint8_tobuffer(hashalg, target));
72 /* Flags. */
73 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
74 ISC_FALSE));
75 flags = token.value.as_ulong;
76 if (flags > 255U)
77 RETTOK(ISC_R_RANGE);
78 RETERR(uint8_tobuffer(flags, target));
80 /* Iterations. */
81 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
82 ISC_FALSE));
83 if (token.value.as_ulong > 0xffffU)
84 RETTOK(ISC_R_RANGE);
85 RETERR(uint16_tobuffer(token.value.as_ulong, target));
87 /* salt */
88 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
89 ISC_FALSE));
90 if (token.value.as_textregion.length > (255*2))
91 RETTOK(DNS_R_TEXTTOOLONG);
92 if (strcmp(DNS_AS_STR(token), "-") == 0) {
93 RETERR(uint8_tobuffer(0, target));
94 } else {
95 RETERR(uint8_tobuffer(strlen(DNS_AS_STR(token)) / 2, target));
96 RETERR(isc_hex_decodestring(DNS_AS_STR(token), target));
100 * Next hash a single base32hex word.
102 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
103 ISC_FALSE));
104 isc_buffer_init(&b, bm, sizeof(bm));
105 RETTOK(isc_base32hex_decodestring(DNS_AS_STR(token), &b));
106 if (isc_buffer_usedlength(&b) > 0xffU)
107 RETTOK(ISC_R_RANGE);
108 RETERR(uint8_tobuffer(isc_buffer_usedlength(&b), target));
109 RETERR(mem_tobuffer(target, &bm, isc_buffer_usedlength(&b)));
111 memset(bm, 0, sizeof(bm));
112 do {
113 RETERR(isc_lex_getmastertoken(lexer, &token,
114 isc_tokentype_string, ISC_TRUE));
115 if (token.type != isc_tokentype_string)
116 break;
117 RETTOK(dns_rdatatype_fromtext(&covered,
118 &token.value.as_textregion));
119 bm[covered/8] |= (0x80>>(covered%8));
120 } while (1);
121 isc_lex_ungettoken(lexer, &token);
122 for (window = 0; window < 256 ; window++) {
124 * Find if we have a type in this window.
126 for (octet = 31; octet >= 0; octet--)
127 if (bm[window * 32 + octet] != 0)
128 break;
129 if (octet < 0)
130 continue;
131 RETERR(uint8_tobuffer(window, target));
132 RETERR(uint8_tobuffer(octet + 1, target));
133 RETERR(mem_tobuffer(target, &bm[window * 32], octet + 1));
135 return (ISC_R_SUCCESS);
138 static inline isc_result_t
139 totext_nsec3(ARGS_TOTEXT) {
140 isc_region_t sr;
141 unsigned int i, j, k;
142 unsigned int window, len;
143 unsigned char hash;
144 unsigned char flags;
145 char buf[sizeof("65535 ")];
146 isc_uint32_t iterations;
148 REQUIRE(rdata->type == 50);
149 REQUIRE(rdata->length != 0);
151 UNUSED(tctx);
153 dns_rdata_toregion(rdata, &sr);
155 hash = uint8_fromregion(&sr);
156 isc_region_consume(&sr, 1);
158 flags = uint8_fromregion(&sr);
159 isc_region_consume(&sr, 1);
161 iterations = uint16_fromregion(&sr);
162 isc_region_consume(&sr, 2);
164 sprintf(buf, "%u ", hash);
165 RETERR(str_totext(buf, target));
167 sprintf(buf, "%u ", flags);
168 RETERR(str_totext(buf, target));
170 sprintf(buf, "%u ", iterations);
171 RETERR(str_totext(buf, target));
173 j = uint8_fromregion(&sr);
174 isc_region_consume(&sr, 1);
175 INSIST(j <= sr.length);
177 if (j != 0) {
178 i = sr.length;
179 sr.length = j;
180 RETERR(isc_hex_totext(&sr, 1, "", target));
181 sr.length = i - j;
182 RETERR(str_totext(" ", target));
183 } else
184 RETERR(str_totext("- ", target));
186 j = uint8_fromregion(&sr);
187 isc_region_consume(&sr, 1);
188 INSIST(j <= sr.length);
190 i = sr.length;
191 sr.length = j;
192 RETERR(isc_base32hex_totext(&sr, 1, "", target));
193 sr.length = i - j;
195 for (i = 0; i < sr.length; i += len) {
196 INSIST(i + 2 <= sr.length);
197 window = sr.base[i];
198 len = sr.base[i + 1];
199 INSIST(len > 0 && len <= 32);
200 i += 2;
201 INSIST(i + len <= sr.length);
202 for (j = 0; j < len; j++) {
203 dns_rdatatype_t t;
204 if (sr.base[i + j] == 0)
205 continue;
206 for (k = 0; k < 8; k++) {
207 if ((sr.base[i + j] & (0x80 >> k)) == 0)
208 continue;
209 t = window * 256 + j * 8 + k;
210 RETERR(str_totext(" ", target));
211 if (dns_rdatatype_isknown(t)) {
212 RETERR(dns_rdatatype_totext(t, target));
213 } else {
214 char buf[sizeof("TYPE65535")];
215 sprintf(buf, "TYPE%u", t);
216 RETERR(str_totext(buf, target));
221 return (ISC_R_SUCCESS);
224 static inline isc_result_t
225 fromwire_nsec3(ARGS_FROMWIRE) {
226 isc_region_t sr, rr;
227 unsigned int window, lastwindow = 0;
228 unsigned int len;
229 unsigned int saltlen, hashlen;
230 isc_boolean_t first = ISC_TRUE;
231 unsigned int i;
233 REQUIRE(type == 50);
235 UNUSED(type);
236 UNUSED(rdclass);
237 UNUSED(options);
238 UNUSED(dctx);
240 isc_buffer_activeregion(source, &sr);
241 rr = sr;
243 /* hash(1), flags(1), iteration(2), saltlen(1) */
244 if (sr.length < 5U)
245 RETERR(DNS_R_FORMERR);
246 saltlen = sr.base[4];
247 isc_region_consume(&sr, 5);
249 if (sr.length < saltlen)
250 RETERR(DNS_R_FORMERR);
251 isc_region_consume(&sr, saltlen);
253 if (sr.length < 1U)
254 RETERR(DNS_R_FORMERR);
255 hashlen = sr.base[0];
256 isc_region_consume(&sr, 1);
258 if (sr.length < hashlen)
259 RETERR(DNS_R_FORMERR);
260 isc_region_consume(&sr, hashlen);
262 for (i = 0; i < sr.length; i += len) {
264 * Check for overflow.
266 if (i + 2 > sr.length)
267 RETERR(DNS_R_FORMERR);
268 window = sr.base[i];
269 len = sr.base[i + 1];
270 i += 2;
272 * Check that bitmap windows are in the correct order.
274 if (!first && window <= lastwindow)
275 RETERR(DNS_R_FORMERR);
277 * Check for legal lengths.
279 if (len < 1 || len > 32)
280 RETERR(DNS_R_FORMERR);
282 * Check for overflow.
284 if (i + len > sr.length)
285 RETERR(DNS_R_FORMERR);
287 * The last octet of the bitmap must be non zero.
289 if (sr.base[i + len - 1] == 0)
290 RETERR(DNS_R_FORMERR);
291 lastwindow = window;
292 first = ISC_FALSE;
294 if (i != sr.length)
295 return (DNS_R_EXTRADATA);
296 RETERR(mem_tobuffer(target, rr.base, rr.length));
297 isc_buffer_forward(source, rr.length);
298 return (ISC_R_SUCCESS);
301 static inline isc_result_t
302 towire_nsec3(ARGS_TOWIRE) {
303 isc_region_t sr;
305 REQUIRE(rdata->type == 50);
306 REQUIRE(rdata->length != 0);
308 UNUSED(cctx);
310 dns_rdata_toregion(rdata, &sr);
311 return (mem_tobuffer(target, sr.base, sr.length));
314 static inline int
315 compare_nsec3(ARGS_COMPARE) {
316 isc_region_t r1;
317 isc_region_t r2;
319 REQUIRE(rdata1->type == rdata2->type);
320 REQUIRE(rdata1->rdclass == rdata2->rdclass);
321 REQUIRE(rdata1->type == 50);
322 REQUIRE(rdata1->length != 0);
323 REQUIRE(rdata2->length != 0);
325 dns_rdata_toregion(rdata1, &r1);
326 dns_rdata_toregion(rdata2, &r2);
327 return (isc_region_compare(&r1, &r2));
330 static inline isc_result_t
331 fromstruct_nsec3(ARGS_FROMSTRUCT) {
332 dns_rdata_nsec3_t *nsec3 = source;
333 unsigned int i, len, window, lastwindow = 0;
334 isc_boolean_t first = ISC_TRUE;
336 REQUIRE(type == 50);
337 REQUIRE(source != NULL);
338 REQUIRE(nsec3->common.rdtype == type);
339 REQUIRE(nsec3->common.rdclass == rdclass);
340 REQUIRE(nsec3->typebits != NULL || nsec3->len == 0);
341 REQUIRE(nsec3->hash == dns_hash_sha1);
343 UNUSED(type);
344 UNUSED(rdclass);
346 RETERR(uint8_tobuffer(nsec3->hash, target));
347 RETERR(uint8_tobuffer(nsec3->flags, target));
348 RETERR(uint16_tobuffer(nsec3->iterations, target));
349 RETERR(uint8_tobuffer(nsec3->salt_length, target));
350 RETERR(mem_tobuffer(target, nsec3->salt, nsec3->salt_length));
351 RETERR(uint8_tobuffer(nsec3->next_length, target));
352 RETERR(mem_tobuffer(target, nsec3->next, nsec3->next_length));
355 * Perform sanity check.
357 for (i = 0; i < nsec3->len ; i += len) {
358 INSIST(i + 2 <= nsec3->len);
359 window = nsec3->typebits[i];
360 len = nsec3->typebits[i+1];
361 i += 2;
362 INSIST(first || window > lastwindow);
363 INSIST(len > 0 && len <= 32);
364 INSIST(i + len <= nsec3->len);
365 INSIST(nsec3->typebits[i + len - 1] != 0);
366 lastwindow = window;
367 first = ISC_FALSE;
369 return (mem_tobuffer(target, nsec3->typebits, nsec3->len));
372 static inline isc_result_t
373 tostruct_nsec3(ARGS_TOSTRUCT) {
374 isc_region_t region;
375 dns_rdata_nsec3_t *nsec3 = target;
377 REQUIRE(rdata->type == 50);
378 REQUIRE(target != NULL);
379 REQUIRE(rdata->length != 0);
381 nsec3->common.rdclass = rdata->rdclass;
382 nsec3->common.rdtype = rdata->type;
383 ISC_LINK_INIT(&nsec3->common, link);
385 region.base = rdata->data;
386 region.length = rdata->length;
387 nsec3->hash = uint8_consume_fromregion(&region);
388 nsec3->flags = uint8_consume_fromregion(&region);
389 nsec3->iterations = uint16_consume_fromregion(&region);
391 nsec3->salt_length = uint8_consume_fromregion(&region);
392 nsec3->salt = mem_maybedup(mctx, region.base, nsec3->salt_length);
393 if (nsec3->salt == NULL)
394 return (ISC_R_NOMEMORY);
395 isc_region_consume(&region, nsec3->salt_length);
397 nsec3->next_length = uint8_consume_fromregion(&region);
398 nsec3->next = mem_maybedup(mctx, region.base, nsec3->next_length);
399 if (nsec3->next == NULL)
400 goto cleanup;
401 isc_region_consume(&region, nsec3->next_length);
403 nsec3->len = region.length;
404 nsec3->typebits = mem_maybedup(mctx, region.base, region.length);
405 if (nsec3->typebits == NULL)
406 goto cleanup;
408 nsec3->mctx = mctx;
409 return (ISC_R_SUCCESS);
411 cleanup:
412 if (nsec3->next != NULL)
413 isc_mem_free(mctx, nsec3->next);
414 isc_mem_free(mctx, nsec3->salt);
415 return (ISC_R_NOMEMORY);
418 static inline void
419 freestruct_nsec3(ARGS_FREESTRUCT) {
420 dns_rdata_nsec3_t *nsec3 = source;
422 REQUIRE(source != NULL);
423 REQUIRE(nsec3->common.rdtype == 50);
425 if (nsec3->mctx == NULL)
426 return;
428 if (nsec3->salt != NULL)
429 isc_mem_free(nsec3->mctx, nsec3->salt);
430 if (nsec3->next != NULL)
431 isc_mem_free(nsec3->mctx, nsec3->next);
432 if (nsec3->typebits != NULL)
433 isc_mem_free(nsec3->mctx, nsec3->typebits);
434 nsec3->mctx = NULL;
437 static inline isc_result_t
438 additionaldata_nsec3(ARGS_ADDLDATA) {
439 REQUIRE(rdata->type == 50);
441 UNUSED(rdata);
442 UNUSED(add);
443 UNUSED(arg);
445 return (ISC_R_SUCCESS);
448 static inline isc_result_t
449 digest_nsec3(ARGS_DIGEST) {
450 isc_region_t r;
452 REQUIRE(rdata->type == 50);
454 dns_rdata_toregion(rdata, &r);
455 return ((digest)(arg, &r));
458 static inline isc_boolean_t
459 checkowner_nsec3(ARGS_CHECKOWNER) {
461 REQUIRE(type == 50);
463 UNUSED(name);
464 UNUSED(type);
465 UNUSED(rdclass);
466 UNUSED(wildcard);
468 return (ISC_TRUE);
471 static inline isc_boolean_t
472 checknames_nsec3(ARGS_CHECKNAMES) {
474 REQUIRE(rdata->type == 50);
476 UNUSED(rdata);
477 UNUSED(owner);
478 UNUSED(bad);
480 return (ISC_TRUE);
483 static inline int
484 casecompare_nsec3(ARGS_COMPARE) {
485 return (compare_nsec3(rdata1, rdata2));
488 #endif /* RDATA_GENERIC_NSEC3_50_C */