PageRenderTime 64ms CodeModel.GetById 42ms app.highlight 19ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/bind9/lib/dns/rdata/generic/nsec_47.c

https://bitbucket.org/freebsd/freebsd-head/
C | 396 lines | 283 code | 66 blank | 47 comment | 77 complexity | e8a389093c249d2f9fcc9d0ca70e2d1c MD5 | raw file
  1/*
  2 * Copyright (C) 2004, 2007-2009, 2011  Internet Systems Consortium, Inc. ("ISC")
  3 * Copyright (C) 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
 18/* $Id: nsec_47.c,v 1.15 2011/01/13 04:59:26 tbox Exp $ */
 19
 20/* reviewed: Wed Mar 15 18:21:15 PST 2000 by brister */
 21
 22/* RFC 3845 */
 23
 24#ifndef RDATA_GENERIC_NSEC_47_C
 25#define RDATA_GENERIC_NSEC_47_C
 26
 27/*
 28 * The attributes do not include DNS_RDATATYPEATTR_SINGLETON
 29 * because we must be able to handle a parent/child NSEC pair.
 30 */
 31#define RRTYPE_NSEC_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC)
 32
 33static inline isc_result_t
 34fromtext_nsec(ARGS_FROMTEXT) {
 35	isc_token_t token;
 36	dns_name_t name;
 37	isc_buffer_t buffer;
 38	unsigned char bm[8*1024]; /* 64k bits */
 39	dns_rdatatype_t covered;
 40	int octet;
 41	int window;
 42
 43	REQUIRE(type == 47);
 44
 45	UNUSED(type);
 46	UNUSED(rdclass);
 47	UNUSED(callbacks);
 48
 49	/*
 50	 * Next domain.
 51	 */
 52	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
 53				      ISC_FALSE));
 54	dns_name_init(&name, NULL);
 55	buffer_fromregion(&buffer, &token.value.as_region);
 56	origin = (origin != NULL) ? origin : dns_rootname;
 57	RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
 58
 59	memset(bm, 0, sizeof(bm));
 60	do {
 61		RETERR(isc_lex_getmastertoken(lexer, &token,
 62					      isc_tokentype_string, ISC_TRUE));
 63		if (token.type != isc_tokentype_string)
 64			break;
 65		RETTOK(dns_rdatatype_fromtext(&covered,
 66					      &token.value.as_textregion));
 67		bm[covered/8] |= (0x80>>(covered%8));
 68	} while (1);
 69	isc_lex_ungettoken(lexer, &token);
 70	for (window = 0; window < 256 ; window++) {
 71		/*
 72		 * Find if we have a type in this window.
 73		 */
 74		for (octet = 31; octet >= 0; octet--)
 75			if (bm[window * 32 + octet] != 0)
 76				break;
 77		if (octet < 0)
 78			continue;
 79		RETERR(uint8_tobuffer(window, target));
 80		RETERR(uint8_tobuffer(octet + 1, target));
 81		RETERR(mem_tobuffer(target, &bm[window * 32], octet + 1));
 82	}
 83	return (ISC_R_SUCCESS);
 84}
 85
 86static inline isc_result_t
 87totext_nsec(ARGS_TOTEXT) {
 88	isc_region_t sr;
 89	unsigned int i, j, k;
 90	dns_name_t name;
 91	unsigned int window, len;
 92
 93	REQUIRE(rdata->type == 47);
 94	REQUIRE(rdata->length != 0);
 95
 96	UNUSED(tctx);
 97
 98	dns_name_init(&name, NULL);
 99	dns_rdata_toregion(rdata, &sr);
100	dns_name_fromregion(&name, &sr);
101	isc_region_consume(&sr, name_length(&name));
102	RETERR(dns_name_totext(&name, ISC_FALSE, target));
103
104
105	for (i = 0; i < sr.length; i += len) {
106		INSIST(i + 2 <= sr.length);
107		window = sr.base[i];
108		len = sr.base[i + 1];
109		INSIST(len > 0 && len <= 32);
110		i += 2;
111		INSIST(i + len <= sr.length);
112		for (j = 0; j < len; j++) {
113			dns_rdatatype_t t;
114			if (sr.base[i + j] == 0)
115				continue;
116			for (k = 0; k < 8; k++) {
117				if ((sr.base[i + j] & (0x80 >> k)) == 0)
118					continue;
119				t = window * 256 + j * 8 + k;
120				RETERR(str_totext(" ", target));
121				if (dns_rdatatype_isknown(t)) {
122					RETERR(dns_rdatatype_totext(t, target));
123				} else {
124					char buf[sizeof("TYPE65535")];
125					sprintf(buf, "TYPE%u", t);
126					RETERR(str_totext(buf, target));
127				}
128			}
129		}
130	}
131	return (ISC_R_SUCCESS);
132}
133
134static /* inline */ isc_result_t
135fromwire_nsec(ARGS_FROMWIRE) {
136	isc_region_t sr;
137	dns_name_t name;
138	unsigned int window, lastwindow = 0;
139	unsigned int len;
140	isc_boolean_t first = ISC_TRUE;
141	unsigned int i;
142
143	REQUIRE(type == 47);
144
145	UNUSED(type);
146	UNUSED(rdclass);
147
148	dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
149
150	dns_name_init(&name, NULL);
151	RETERR(dns_name_fromwire(&name, source, dctx, options, target));
152
153	isc_buffer_activeregion(source, &sr);
154	for (i = 0; i < sr.length; i += len) {
155		/*
156		 * Check for overflow.
157		 */
158		if (i + 2 > sr.length)
159			RETERR(DNS_R_FORMERR);
160		window = sr.base[i];
161		len = sr.base[i + 1];
162		i += 2;
163		/*
164		 * Check that bitmap windows are in the correct order.
165		 */
166		if (!first && window <= lastwindow)
167			RETERR(DNS_R_FORMERR);
168		/*
169		 * Check for legal lengths.
170		 */
171		if (len < 1 || len > 32)
172			RETERR(DNS_R_FORMERR);
173		/*
174		 * Check for overflow.
175		 */
176		if (i + len > sr.length)
177			RETERR(DNS_R_FORMERR);
178		/*
179		 * The last octet of the bitmap must be non zero.
180		 */
181		if (sr.base[i + len - 1] == 0)
182			RETERR(DNS_R_FORMERR);
183		lastwindow = window;
184		first = ISC_FALSE;
185	}
186	if (i != sr.length)
187		return (DNS_R_EXTRADATA);
188	if (first)
189		RETERR(DNS_R_FORMERR);
190	RETERR(mem_tobuffer(target, sr.base, sr.length));
191	isc_buffer_forward(source, sr.length);
192	return (ISC_R_SUCCESS);
193}
194
195static inline isc_result_t
196towire_nsec(ARGS_TOWIRE) {
197	isc_region_t sr;
198	dns_name_t name;
199	dns_offsets_t offsets;
200
201	REQUIRE(rdata->type == 47);
202	REQUIRE(rdata->length != 0);
203
204	dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
205	dns_name_init(&name, offsets);
206	dns_rdata_toregion(rdata, &sr);
207	dns_name_fromregion(&name, &sr);
208	isc_region_consume(&sr, name_length(&name));
209	RETERR(dns_name_towire(&name, cctx, target));
210
211	return (mem_tobuffer(target, sr.base, sr.length));
212}
213
214static inline int
215compare_nsec(ARGS_COMPARE) {
216	isc_region_t r1;
217	isc_region_t r2;
218
219	REQUIRE(rdata1->type == rdata2->type);
220	REQUIRE(rdata1->rdclass == rdata2->rdclass);
221	REQUIRE(rdata1->type == 47);
222	REQUIRE(rdata1->length != 0);
223	REQUIRE(rdata2->length != 0);
224
225	dns_rdata_toregion(rdata1, &r1);
226	dns_rdata_toregion(rdata2, &r2);
227	return (isc_region_compare(&r1, &r2));
228}
229
230static inline isc_result_t
231fromstruct_nsec(ARGS_FROMSTRUCT) {
232	dns_rdata_nsec_t *nsec = source;
233	isc_region_t region;
234	unsigned int i, len, window, lastwindow = 0;
235	isc_boolean_t first = ISC_TRUE;
236
237	REQUIRE(type == 47);
238	REQUIRE(source != NULL);
239	REQUIRE(nsec->common.rdtype == type);
240	REQUIRE(nsec->common.rdclass == rdclass);
241	REQUIRE(nsec->typebits != NULL || nsec->len == 0);
242
243	UNUSED(type);
244	UNUSED(rdclass);
245
246	dns_name_toregion(&nsec->next, &region);
247	RETERR(isc_buffer_copyregion(target, &region));
248	/*
249	 * Perform sanity check.
250	 */
251	for (i = 0; i < nsec->len ; i += len) {
252		INSIST(i + 2 <= nsec->len);
253		window = nsec->typebits[i];
254		len = nsec->typebits[i+1];
255		i += 2;
256		INSIST(first || window > lastwindow);
257		INSIST(len > 0 && len <= 32);
258		INSIST(i + len <= nsec->len);
259		INSIST(nsec->typebits[i + len - 1] != 0);
260		lastwindow = window;
261		first = ISC_FALSE;
262	}
263	INSIST(!first);
264	return (mem_tobuffer(target, nsec->typebits, nsec->len));
265}
266
267static inline isc_result_t
268tostruct_nsec(ARGS_TOSTRUCT) {
269	isc_region_t region;
270	dns_rdata_nsec_t *nsec = target;
271	dns_name_t name;
272
273	REQUIRE(rdata->type == 47);
274	REQUIRE(target != NULL);
275	REQUIRE(rdata->length != 0);
276
277	nsec->common.rdclass = rdata->rdclass;
278	nsec->common.rdtype = rdata->type;
279	ISC_LINK_INIT(&nsec->common, link);
280
281	dns_name_init(&name, NULL);
282	dns_rdata_toregion(rdata, &region);
283	dns_name_fromregion(&name, &region);
284	isc_region_consume(&region, name_length(&name));
285	dns_name_init(&nsec->next, NULL);
286	RETERR(name_duporclone(&name, mctx, &nsec->next));
287
288	nsec->len = region.length;
289	nsec->typebits = mem_maybedup(mctx, region.base, region.length);
290	if (nsec->typebits == NULL)
291		goto cleanup;
292
293	nsec->mctx = mctx;
294	return (ISC_R_SUCCESS);
295
296 cleanup:
297	if (mctx != NULL)
298		dns_name_free(&nsec->next, mctx);
299	return (ISC_R_NOMEMORY);
300}
301
302static inline void
303freestruct_nsec(ARGS_FREESTRUCT) {
304	dns_rdata_nsec_t *nsec = source;
305
306	REQUIRE(source != NULL);
307	REQUIRE(nsec->common.rdtype == 47);
308
309	if (nsec->mctx == NULL)
310		return;
311
312	dns_name_free(&nsec->next, nsec->mctx);
313	if (nsec->typebits != NULL)
314		isc_mem_free(nsec->mctx, nsec->typebits);
315	nsec->mctx = NULL;
316}
317
318static inline isc_result_t
319additionaldata_nsec(ARGS_ADDLDATA) {
320	REQUIRE(rdata->type == 47);
321
322	UNUSED(rdata);
323	UNUSED(add);
324	UNUSED(arg);
325
326	return (ISC_R_SUCCESS);
327}
328
329static inline isc_result_t
330digest_nsec(ARGS_DIGEST) {
331	isc_region_t r;
332
333	REQUIRE(rdata->type == 47);
334
335	dns_rdata_toregion(rdata, &r);
336	return ((digest)(arg, &r));
337}
338
339static inline isc_boolean_t
340checkowner_nsec(ARGS_CHECKOWNER) {
341
342       REQUIRE(type == 47);
343
344       UNUSED(name);
345       UNUSED(type);
346       UNUSED(rdclass);
347       UNUSED(wildcard);
348
349       return (ISC_TRUE);
350}
351
352static inline isc_boolean_t
353checknames_nsec(ARGS_CHECKNAMES) {
354
355	REQUIRE(rdata->type == 47);
356
357	UNUSED(rdata);
358	UNUSED(owner);
359	UNUSED(bad);
360
361	return (ISC_TRUE);
362}
363
364static inline int
365casecompare_nsec(ARGS_COMPARE) {
366	isc_region_t region1;
367	isc_region_t region2;
368	dns_name_t name1;
369	dns_name_t name2;
370	int order;
371
372	REQUIRE(rdata1->type == rdata2->type);
373	REQUIRE(rdata1->rdclass == rdata2->rdclass);
374	REQUIRE(rdata1->type == 47);
375	REQUIRE(rdata1->length != 0);
376	REQUIRE(rdata2->length != 0);
377
378	dns_name_init(&name1, NULL);
379	dns_name_init(&name2, NULL);
380
381	dns_rdata_toregion(rdata1, &region1);
382	dns_rdata_toregion(rdata2, &region2);
383
384	dns_name_fromregion(&name1, &region1);
385	dns_name_fromregion(&name2, &region2);
386
387	order = dns_name_rdatacompare(&name1, &name2);
388	if (order != 0)
389		return (order);
390
391	isc_region_consume(&region1, name_length(&name1));
392	isc_region_consume(&region2, name_length(&name2));
393
394	return (isc_region_compare(&region1, &region2));
395}
396#endif	/* RDATA_GENERIC_NSEC_47_C */