PageRenderTime 26ms CodeModel.GetById 1ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 0ms

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