2 * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2002 Internet Software Consortium.
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.
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.
18 /* $Id: apl_42.c,v 1.12.128.2 2008/01/22 23:27:35 tbox Exp $ */
22 #ifndef RDATA_IN_1_APL_42_C
23 #define RDATA_IN_1_APL_42_C
25 #define RRTYPE_APL_ATTRIBUTES (0)
27 static inline isc_result_t
28 fromtext_in_apl(ARGS_FROMTEXT
) {
30 unsigned char addr
[16];
35 char *cp
, *ap
, *slash
;
39 REQUIRE(rdclass
== 1);
48 RETERR(isc_lex_getmastertoken(lexer
, &token
,
49 isc_tokentype_string
, ISC_TRUE
));
50 if (token
.type
!= isc_tokentype_string
)
53 cp
= DNS_AS_STR(token
);
54 neg
= ISC_TF(*cp
== '!');
57 afi
= strtoul(cp
, &ap
, 10);
58 if (*ap
++ != ':' || cp
== ap
)
62 slash
= strchr(ap
, '/');
63 if (slash
== NULL
|| slash
== ap
)
65 RETTOK(isc_parse_uint8(&prefix
, slash
+ 1, 10));
69 n
= inet_pton(AF_INET
, ap
, addr
);
72 RETTOK(DNS_R_BADDOTTEDQUAD
);
75 for (len
= 4; len
> 0; len
--)
76 if (addr
[len
- 1] != 0)
82 n
= inet_pton(AF_INET6
, ap
, addr
);
85 RETTOK(DNS_R_BADAAAA
);
88 for (len
= 16; len
> 0; len
--)
89 if (addr
[len
- 1] != 0)
94 RETTOK(ISC_R_NOTIMPLEMENTED
);
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
));
103 * Let upper layer handle eol/eof.
105 isc_lex_ungettoken(lexer
, &token
);
107 return (ISC_R_SUCCESS
);
110 static inline isc_result_t
111 totext_in_apl(ARGS_TOTEXT
) {
118 unsigned char buf
[16];
119 char txt
[sizeof(" !64000")];
120 const char *sep
= "";
123 REQUIRE(rdata
->type
== 42);
124 REQUIRE(rdata
->rdclass
== 1);
128 dns_rdata_toregion(rdata
, &sr
);
130 ir
.length
= sizeof(buf
);
132 while (sr
.length
> 0) {
133 INSIST(sr
.length
>= 4);
134 afi
= uint16_fromregion(&sr
);
135 isc_region_consume(&sr
, 2);
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
,
144 INSIST(n
< (int)sizeof(txt
));
145 RETERR(str_totext(txt
, target
));
149 INSIST(prefix
<= 32);
150 memset(buf
, 0, sizeof(buf
));
151 memcpy(buf
, sr
.base
, len
);
152 RETERR(inet_totext(AF_INET
, &ir
, target
));
157 INSIST(prefix
<= 128);
158 memset(buf
, 0, sizeof(buf
));
159 memcpy(buf
, sr
.base
, len
);
160 RETERR(inet_totext(AF_INET6
, &ir
, target
));
164 return (ISC_R_NOTIMPLEMENTED
);
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
);
172 return (ISC_R_SUCCESS
);
175 static inline isc_result_t
176 fromwire_in_apl(ARGS_FROMWIRE
) {
177 isc_region_t sr
, sr2
;
184 REQUIRE(rdclass
== 1);
191 isc_buffer_activeregion(source
, &sr
);
192 isc_buffer_availableregion(target
, &tr
);
193 if (sr
.length
> tr
.length
)
194 return (ISC_R_NOSPACE
);
197 /* Zero or more items */
198 while (sr
.length
> 0) {
200 return (ISC_R_UNEXPECTEDEND
);
201 afi
= uint16_fromregion(&sr
);
202 isc_region_consume(&sr
, 2);
204 isc_region_consume(&sr
, 1);
205 len
= (*sr
.base
& 0x7f);
206 isc_region_consume(&sr
, 1);
208 return (ISC_R_UNEXPECTEDEND
);
211 if (prefix
> 32 || len
> 4)
212 return (ISC_R_RANGE
);
215 if (prefix
> 128 || len
> 16)
216 return (ISC_R_RANGE
);
218 if (len
> 0 && sr
.base
[len
- 1] == 0)
219 return (DNS_R_FORMERR
);
220 isc_region_consume(&sr
, len
);
222 isc_buffer_forward(source
, sr2
.length
);
223 return (mem_tobuffer(target
, sr2
.base
, sr2
.length
));
226 static inline isc_result_t
227 towire_in_apl(ARGS_TOWIRE
) {
230 REQUIRE(rdata
->type
== 42);
231 REQUIRE(rdata
->rdclass
== 1);
233 return (mem_tobuffer(target
, rdata
->data
, rdata
->length
));
237 compare_in_apl(ARGS_COMPARE
) {
241 REQUIRE(rdata1
->type
== rdata2
->type
);
242 REQUIRE(rdata1
->rdclass
== rdata2
->rdclass
);
243 REQUIRE(rdata1
->type
== 42);
244 REQUIRE(rdata1
->rdclass
== 1);
246 dns_rdata_toregion(rdata1
, &r1
);
247 dns_rdata_toregion(rdata2
, &r2
);
248 return (isc_region_compare(&r1
, &r2
));
251 static inline isc_result_t
252 fromstruct_in_apl(ARGS_FROMSTRUCT
) {
253 dns_rdata_in_apl_t
*apl
= source
;
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);
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
));
269 static inline isc_result_t
270 tostruct_in_apl(ARGS_TOSTRUCT
) {
271 dns_rdata_in_apl_t
*apl
= target
;
274 REQUIRE(rdata
->type
== 42);
275 REQUIRE(rdata
->rdclass
== 1);
277 apl
->common
.rdclass
= rdata
->rdclass
;
278 apl
->common
.rdtype
= rdata
->type
;
279 ISC_LINK_INIT(&apl
->common
, link
);
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
);
289 return (ISC_R_SUCCESS
);
293 freestruct_in_apl(ARGS_FREESTRUCT
) {
294 dns_rdata_in_apl_t
*apl
= source
;
296 REQUIRE(source
!= NULL
);
297 REQUIRE(apl
->common
.rdtype
== 42);
298 REQUIRE(apl
->common
.rdclass
== 1);
300 if (apl
->mctx
== NULL
)
302 if (apl
->apl
!= NULL
)
303 isc_mem_free(apl
->mctx
, apl
->apl
);
308 dns_rdata_apl_first(dns_rdata_in_apl_t
*apl
) {
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);
317 * If no APL return ISC_R_NOMORE.
319 if (apl
->apl
== NULL
)
320 return (ISC_R_NOMORE
);
325 INSIST(apl
->apl_len
> 3U);
326 length
= apl
->apl
[apl
->offset
+ 3] & 0x7f;
327 INSIST(length
<= apl
->apl_len
);
330 return (ISC_R_SUCCESS
);
334 dns_rdata_apl_next(dns_rdata_in_apl_t
*apl
) {
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);
343 * No APL or have already reached the end return ISC_R_NOMORE.
345 if (apl
->apl
== NULL
|| apl
->offset
== apl
->apl_len
)
346 return (ISC_R_NOMORE
);
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;
356 * 16 to 32 bits promotion as 'length' is 32 bits so there is
357 * no overflow problems.
359 INSIST(length
+ apl
->offset
<= apl
->apl_len
);
361 apl
->offset
+= apl
->apl
[apl
->offset
+ 3] & 0x7f;
362 return ((apl
->offset
>= apl
->apl_len
) ? ISC_R_SUCCESS
: ISC_R_NOMORE
);
366 dns_rdata_apl_current(dns_rdata_in_apl_t
*apl
, dns_rdata_apl_ent_t
*ent
) {
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
);
376 if (apl
->offset
== apl
->apl_len
)
377 return (ISC_R_NOMORE
);
382 INSIST(apl
->apl_len
> 3U);
383 INSIST(apl
->offset
<= apl
->apl_len
- 4U);
384 length
= apl
->apl
[apl
->offset
+ 3] & 0x7f;
386 * 16 to 32 bits promotion as 'length' is 32 bits so there is
387 * no overflow problems.
389 INSIST(length
+ apl
->offset
<= apl
->apl_len
);
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];
399 return (ISC_R_SUCCESS
);
402 static inline isc_result_t
403 additionaldata_in_apl(ARGS_ADDLDATA
) {
404 REQUIRE(rdata
->type
== 42);
405 REQUIRE(rdata
->rdclass
== 1);
410 return (ISC_R_SUCCESS
);
413 static inline isc_result_t
414 digest_in_apl(ARGS_DIGEST
) {
417 REQUIRE(rdata
->type
== 42);
418 REQUIRE(rdata
->rdclass
== 1);
420 dns_rdata_toregion(rdata
, &r
);
422 return ((digest
)(arg
, &r
));
425 static inline isc_boolean_t
426 checkowner_in_apl(ARGS_CHECKOWNER
) {
429 REQUIRE(rdclass
== 1);
440 static inline isc_boolean_t
441 checknames_in_apl(ARGS_CHECKNAMES
) {
443 REQUIRE(rdata
->type
== 42);
444 REQUIRE(rdata
->rdclass
== 1);
453 #endif /* RDATA_IN_1_APL_42_C */