1 /* $NetBSD: apl_42.c,v 1.5 2014/12/10 04:37:59 christos Exp $ */
4 * Copyright (C) 2004, 2005, 2007-2009, 2014 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2002 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: apl_42.c,v 1.16 2009/12/04 22:06:37 tbox Exp */
24 #ifndef RDATA_IN_1_APL_42_C
25 #define RDATA_IN_1_APL_42_C
27 #define RRTYPE_APL_ATTRIBUTES (0)
29 static inline isc_result_t
30 fromtext_in_apl(ARGS_FROMTEXT
) {
32 unsigned char addr
[16];
37 char *cp
, *ap
, *slash
;
41 REQUIRE(rdclass
== 1);
50 RETERR(isc_lex_getmastertoken(lexer
, &token
,
51 isc_tokentype_string
, ISC_TRUE
));
52 if (token
.type
!= isc_tokentype_string
)
55 cp
= DNS_AS_STR(token
);
56 neg
= ISC_TF(*cp
== '!');
59 afi
= strtoul(cp
, &ap
, 10);
60 if (*ap
++ != ':' || cp
== ap
)
64 slash
= strchr(ap
, '/');
65 if (slash
== NULL
|| slash
== ap
)
67 RETTOK(isc_parse_uint8(&prefix
, slash
+ 1, 10));
71 n
= inet_pton(AF_INET
, ap
, addr
);
74 RETTOK(DNS_R_BADDOTTEDQUAD
);
77 for (len
= 4; len
> 0; len
--)
78 if (addr
[len
- 1] != 0)
84 n
= inet_pton(AF_INET6
, ap
, addr
);
87 RETTOK(DNS_R_BADAAAA
);
90 for (len
= 16; len
> 0; len
--)
91 if (addr
[len
- 1] != 0)
96 RETTOK(ISC_R_NOTIMPLEMENTED
);
98 RETERR(uint16_tobuffer(afi
, target
));
99 RETERR(uint8_tobuffer(prefix
, target
));
100 RETERR(uint8_tobuffer(len
| ((neg
) ? 0x80 : 0), target
));
101 RETERR(mem_tobuffer(target
, addr
, len
));
105 * Let upper layer handle eol/eof.
107 isc_lex_ungettoken(lexer
, &token
);
109 return (ISC_R_SUCCESS
);
112 static inline isc_result_t
113 totext_in_apl(ARGS_TOTEXT
) {
120 unsigned char buf
[16];
121 char txt
[sizeof(" !64000")];
122 const char *sep
= "";
125 REQUIRE(rdata
->type
== 42);
126 REQUIRE(rdata
->rdclass
== 1);
130 dns_rdata_toregion(rdata
, &sr
);
132 ir
.length
= sizeof(buf
);
134 while (sr
.length
> 0) {
135 INSIST(sr
.length
>= 4);
136 afi
= uint16_fromregion(&sr
);
137 isc_region_consume(&sr
, 2);
139 isc_region_consume(&sr
, 1);
140 len
= (*sr
.base
& 0x7f);
141 neg
= ISC_TF((*sr
.base
& 0x80) != 0);
142 isc_region_consume(&sr
, 1);
143 INSIST(len
<= sr
.length
);
144 n
= snprintf(txt
, sizeof(txt
), "%s%s%u:", sep
,
146 INSIST(n
< (int)sizeof(txt
));
147 RETERR(str_totext(txt
, target
));
151 INSIST(prefix
<= 32);
152 memset(buf
, 0, sizeof(buf
));
153 memmove(buf
, sr
.base
, len
);
154 RETERR(inet_totext(AF_INET
, &ir
, target
));
159 INSIST(prefix
<= 128);
160 memset(buf
, 0, sizeof(buf
));
161 memmove(buf
, sr
.base
, len
);
162 RETERR(inet_totext(AF_INET6
, &ir
, target
));
166 return (ISC_R_NOTIMPLEMENTED
);
168 n
= snprintf(txt
, sizeof(txt
), "/%u", prefix
);
169 INSIST(n
< (int)sizeof(txt
));
170 RETERR(str_totext(txt
, target
));
171 isc_region_consume(&sr
, len
);
174 return (ISC_R_SUCCESS
);
177 static inline isc_result_t
178 fromwire_in_apl(ARGS_FROMWIRE
) {
179 isc_region_t sr
, sr2
;
186 REQUIRE(rdclass
== 1);
193 isc_buffer_activeregion(source
, &sr
);
194 isc_buffer_availableregion(target
, &tr
);
195 if (sr
.length
> tr
.length
)
196 return (ISC_R_NOSPACE
);
199 /* Zero or more items */
200 while (sr
.length
> 0) {
202 return (ISC_R_UNEXPECTEDEND
);
203 afi
= uint16_fromregion(&sr
);
204 isc_region_consume(&sr
, 2);
206 isc_region_consume(&sr
, 1);
207 len
= (*sr
.base
& 0x7f);
208 isc_region_consume(&sr
, 1);
210 return (ISC_R_UNEXPECTEDEND
);
213 if (prefix
> 32 || len
> 4)
214 return (ISC_R_RANGE
);
217 if (prefix
> 128 || len
> 16)
218 return (ISC_R_RANGE
);
220 if (len
> 0 && sr
.base
[len
- 1] == 0)
221 return (DNS_R_FORMERR
);
222 isc_region_consume(&sr
, len
);
224 isc_buffer_forward(source
, sr2
.length
);
225 return (mem_tobuffer(target
, sr2
.base
, sr2
.length
));
228 static inline isc_result_t
229 towire_in_apl(ARGS_TOWIRE
) {
232 REQUIRE(rdata
->type
== 42);
233 REQUIRE(rdata
->rdclass
== 1);
235 return (mem_tobuffer(target
, rdata
->data
, rdata
->length
));
239 compare_in_apl(ARGS_COMPARE
) {
243 REQUIRE(rdata1
->type
== rdata2
->type
);
244 REQUIRE(rdata1
->rdclass
== rdata2
->rdclass
);
245 REQUIRE(rdata1
->type
== 42);
246 REQUIRE(rdata1
->rdclass
== 1);
248 dns_rdata_toregion(rdata1
, &r1
);
249 dns_rdata_toregion(rdata2
, &r2
);
250 return (isc_region_compare(&r1
, &r2
));
253 static inline isc_result_t
254 fromstruct_in_apl(ARGS_FROMSTRUCT
) {
255 dns_rdata_in_apl_t
*apl
= source
;
259 REQUIRE(rdclass
== 1);
260 REQUIRE(source
!= NULL
);
261 REQUIRE(apl
->common
.rdtype
== type
);
262 REQUIRE(apl
->common
.rdclass
== rdclass
);
263 REQUIRE(apl
->apl
!= NULL
|| apl
->apl_len
== 0);
265 isc_buffer_init(&b
, apl
->apl
, apl
->apl_len
);
266 isc_buffer_add(&b
, apl
->apl_len
);
267 isc_buffer_setactive(&b
, apl
->apl_len
);
268 return(fromwire_in_apl(rdclass
, type
, &b
, NULL
, ISC_FALSE
, target
));
271 static inline isc_result_t
272 tostruct_in_apl(ARGS_TOSTRUCT
) {
273 dns_rdata_in_apl_t
*apl
= target
;
276 REQUIRE(rdata
->type
== 42);
277 REQUIRE(rdata
->rdclass
== 1);
279 apl
->common
.rdclass
= rdata
->rdclass
;
280 apl
->common
.rdtype
= rdata
->type
;
281 ISC_LINK_INIT(&apl
->common
, link
);
283 dns_rdata_toregion(rdata
, &r
);
284 apl
->apl_len
= r
.length
;
285 apl
->apl
= mem_maybedup(mctx
, r
.base
, r
.length
);
286 if (apl
->apl
== NULL
)
287 return (ISC_R_NOMEMORY
);
291 return (ISC_R_SUCCESS
);
295 freestruct_in_apl(ARGS_FREESTRUCT
) {
296 dns_rdata_in_apl_t
*apl
= source
;
298 REQUIRE(source
!= NULL
);
299 REQUIRE(apl
->common
.rdtype
== 42);
300 REQUIRE(apl
->common
.rdclass
== 1);
302 if (apl
->mctx
== NULL
)
304 if (apl
->apl
!= NULL
)
305 isc_mem_free(apl
->mctx
, apl
->apl
);
310 dns_rdata_apl_first(dns_rdata_in_apl_t
*apl
) {
313 REQUIRE(apl
!= NULL
);
314 REQUIRE(apl
->common
.rdtype
== 42);
315 REQUIRE(apl
->common
.rdclass
== 1);
316 REQUIRE(apl
->apl
!= NULL
|| apl
->apl_len
== 0);
319 * If no APL return ISC_R_NOMORE.
321 if (apl
->apl
== NULL
)
322 return (ISC_R_NOMORE
);
327 INSIST(apl
->apl_len
> 3U);
328 length
= apl
->apl
[apl
->offset
+ 3] & 0x7f;
329 INSIST(length
<= apl
->apl_len
);
332 return (ISC_R_SUCCESS
);
336 dns_rdata_apl_next(dns_rdata_in_apl_t
*apl
) {
339 REQUIRE(apl
!= NULL
);
340 REQUIRE(apl
->common
.rdtype
== 42);
341 REQUIRE(apl
->common
.rdclass
== 1);
342 REQUIRE(apl
->apl
!= NULL
|| apl
->apl_len
== 0);
345 * No APL or have already reached the end return ISC_R_NOMORE.
347 if (apl
->apl
== NULL
|| apl
->offset
== apl
->apl_len
)
348 return (ISC_R_NOMORE
);
353 INSIST(apl
->offset
< apl
->apl_len
);
354 INSIST(apl
->apl_len
> 3U);
355 INSIST(apl
->offset
<= apl
->apl_len
- 4U);
356 length
= apl
->apl
[apl
->offset
+ 3] & 0x7f;
358 * 16 to 32 bits promotion as 'length' is 32 bits so there is
359 * no overflow problems.
361 INSIST(length
+ apl
->offset
<= apl
->apl_len
);
363 apl
->offset
+= apl
->apl
[apl
->offset
+ 3] & 0x7f;
364 return ((apl
->offset
>= apl
->apl_len
) ? ISC_R_SUCCESS
: ISC_R_NOMORE
);
368 dns_rdata_apl_current(dns_rdata_in_apl_t
*apl
, dns_rdata_apl_ent_t
*ent
) {
371 REQUIRE(apl
!= NULL
);
372 REQUIRE(apl
->common
.rdtype
== 42);
373 REQUIRE(apl
->common
.rdclass
== 1);
374 REQUIRE(ent
!= NULL
);
375 REQUIRE(apl
->apl
!= NULL
|| apl
->apl_len
== 0);
376 REQUIRE(apl
->offset
<= apl
->apl_len
);
378 if (apl
->offset
== apl
->apl_len
)
379 return (ISC_R_NOMORE
);
384 INSIST(apl
->apl_len
> 3U);
385 INSIST(apl
->offset
<= apl
->apl_len
- 4U);
386 length
= apl
->apl
[apl
->offset
+ 3] & 0x7f;
388 * 16 to 32 bits promotion as 'length' is 32 bits so there is
389 * no overflow problems.
391 INSIST(length
+ apl
->offset
<= apl
->apl_len
);
393 ent
->family
= (apl
->apl
[apl
->offset
] << 8) + apl
->apl
[apl
->offset
+ 1];
394 ent
->prefix
= apl
->apl
[apl
->offset
+ 2];
395 ent
->length
= apl
->apl
[apl
->offset
+ 3] & 0x7f;
396 ent
->negative
= ISC_TF((apl
->apl
[apl
->offset
+ 3] & 0x80) != 0);
397 if (ent
->length
!= 0)
398 ent
->data
= &apl
->apl
[apl
->offset
+ 4];
401 return (ISC_R_SUCCESS
);
404 static inline isc_result_t
405 additionaldata_in_apl(ARGS_ADDLDATA
) {
406 REQUIRE(rdata
->type
== 42);
407 REQUIRE(rdata
->rdclass
== 1);
412 return (ISC_R_SUCCESS
);
415 static inline isc_result_t
416 digest_in_apl(ARGS_DIGEST
) {
419 REQUIRE(rdata
->type
== 42);
420 REQUIRE(rdata
->rdclass
== 1);
422 dns_rdata_toregion(rdata
, &r
);
424 return ((digest
)(arg
, &r
));
427 static inline isc_boolean_t
428 checkowner_in_apl(ARGS_CHECKOWNER
) {
431 REQUIRE(rdclass
== 1);
442 static inline isc_boolean_t
443 checknames_in_apl(ARGS_CHECKNAMES
) {
445 REQUIRE(rdata
->type
== 42);
446 REQUIRE(rdata
->rdclass
== 1);
456 casecompare_in_apl(ARGS_COMPARE
) {
457 return (compare_in_apl(rdata1
, rdata2
));
460 #endif /* RDATA_IN_1_APL_42_C */