a6_38.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004, 2007, 2009, 2014  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 1999-2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /* $Id: a6_38.c,v 1.56 2009/12/04 22:06:37 tbox Exp $ */
00019 
00020 /* RFC2874 */
00021 
00022 #ifndef RDATA_IN_1_A6_28_C
00023 #define RDATA_IN_1_A6_28_C
00024 
00025 #include <isc/net.h>
00026 
00027 #define RRTYPE_A6_ATTRIBUTES (0)
00028 
00029 static inline isc_result_t
00030 fromtext_in_a6(ARGS_FROMTEXT) {
00031         isc_token_t token;
00032         unsigned char addr[16];
00033         unsigned char prefixlen;
00034         unsigned char octets;
00035         unsigned char mask;
00036         dns_name_t name;
00037         isc_buffer_t buffer;
00038         isc_boolean_t ok;
00039 
00040         REQUIRE(type == 38);
00041         REQUIRE(rdclass == 1);
00042 
00043         UNUSED(type);
00044         UNUSED(rdclass);
00045         UNUSED(callbacks);
00046 
00047         /*
00048          * Prefix length.
00049          */
00050         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
00051                                       ISC_FALSE));
00052         if (token.value.as_ulong > 128U)
00053                 RETTOK(ISC_R_RANGE);
00054 
00055         prefixlen = (unsigned char)token.value.as_ulong;
00056         RETERR(mem_tobuffer(target, &prefixlen, 1));
00057 
00058         /*
00059          * Suffix.
00060          */
00061         if (prefixlen != 128) {
00062                 /*
00063                  * Prefix 0..127.
00064                  */
00065                 octets = prefixlen/8;
00066                 /*
00067                  * Octets 0..15.
00068                  */
00069                 RETERR(isc_lex_getmastertoken(lexer, &token,
00070                                               isc_tokentype_string,
00071                                               ISC_FALSE));
00072                 if (inet_pton(AF_INET6, DNS_AS_STR(token), addr) != 1)
00073                         RETTOK(DNS_R_BADAAAA);
00074                 mask = 0xff >> (prefixlen % 8);
00075                 addr[octets] &= mask;
00076                 RETERR(mem_tobuffer(target, &addr[octets], 16 - octets));
00077         }
00078 
00079         if (prefixlen == 0)
00080                 return (ISC_R_SUCCESS);
00081 
00082         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
00083                                       ISC_FALSE));
00084         dns_name_init(&name, NULL);
00085         buffer_fromregion(&buffer, &token.value.as_region);
00086         origin = (origin != NULL) ? origin : dns_rootname;
00087         RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
00088         ok = ISC_TRUE;
00089         if ((options & DNS_RDATA_CHECKNAMES) != 0)
00090                 ok = dns_name_ishostname(&name, ISC_FALSE);
00091         if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0)
00092                 RETTOK(DNS_R_BADNAME);
00093         if (!ok && callbacks != NULL)
00094                 warn_badname(&name, lexer, callbacks);
00095         return (ISC_R_SUCCESS);
00096 }
00097 
00098 static inline isc_result_t
00099 totext_in_a6(ARGS_TOTEXT) {
00100         isc_region_t sr, ar;
00101         unsigned char addr[16];
00102         unsigned char prefixlen;
00103         unsigned char octets;
00104         unsigned char mask;
00105         char buf[sizeof("128")];
00106         dns_name_t name;
00107         dns_name_t prefix;
00108         isc_boolean_t sub;
00109 
00110         REQUIRE(rdata->type == 38);
00111         REQUIRE(rdata->rdclass == 1);
00112         REQUIRE(rdata->length != 0);
00113 
00114         dns_rdata_toregion(rdata, &sr);
00115         prefixlen = sr.base[0];
00116         INSIST(prefixlen <= 128);
00117         isc_region_consume(&sr, 1);
00118         sprintf(buf, "%u", prefixlen);
00119         RETERR(str_totext(buf, target));
00120         RETERR(str_totext(" ", target));
00121 
00122         if (prefixlen != 128) {
00123                 octets = prefixlen/8;
00124                 memset(addr, 0, sizeof(addr));
00125                 memmove(&addr[octets], sr.base, 16 - octets);
00126                 mask = 0xff >> (prefixlen % 8);
00127                 addr[octets] &= mask;
00128                 ar.base = addr;
00129                 ar.length = sizeof(addr);
00130                 RETERR(inet_totext(AF_INET6, &ar, target));
00131                 isc_region_consume(&sr, 16 - octets);
00132         }
00133 
00134         if (prefixlen == 0)
00135                 return (ISC_R_SUCCESS);
00136 
00137         RETERR(str_totext(" ", target));
00138         dns_name_init(&name, NULL);
00139         dns_name_init(&prefix, NULL);
00140         dns_name_fromregion(&name, &sr);
00141         sub = name_prefix(&name, tctx->origin, &prefix);
00142         return (dns_name_totext(&prefix, sub, target));
00143 }
00144 
00145 static inline isc_result_t
00146 fromwire_in_a6(ARGS_FROMWIRE) {
00147         isc_region_t sr;
00148         unsigned char prefixlen;
00149         unsigned char octets;
00150         unsigned char mask;
00151         dns_name_t name;
00152 
00153         REQUIRE(type == 38);
00154         REQUIRE(rdclass == 1);
00155 
00156         UNUSED(type);
00157         UNUSED(rdclass);
00158 
00159         dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
00160 
00161         isc_buffer_activeregion(source, &sr);
00162         /*
00163          * Prefix length.
00164          */
00165         if (sr.length < 1)
00166                 return (ISC_R_UNEXPECTEDEND);
00167         prefixlen = sr.base[0];
00168         if (prefixlen > 128)
00169                 return (ISC_R_RANGE);
00170         isc_region_consume(&sr, 1);
00171         RETERR(mem_tobuffer(target, &prefixlen, 1));
00172         isc_buffer_forward(source, 1);
00173 
00174         /*
00175          * Suffix.
00176          */
00177         if (prefixlen != 128) {
00178                 octets = 16 - prefixlen / 8;
00179                 if (sr.length < octets)
00180                         return (ISC_R_UNEXPECTEDEND);
00181                 mask = 0xff >> (prefixlen % 8);
00182                 sr.base[0] &= mask;     /* Ensure pad bits are zero. */
00183                 RETERR(mem_tobuffer(target, sr.base, octets));
00184                 isc_buffer_forward(source, octets);
00185         }
00186 
00187         if (prefixlen == 0)
00188                 return (ISC_R_SUCCESS);
00189 
00190         dns_name_init(&name, NULL);
00191         return (dns_name_fromwire(&name, source, dctx, options, target));
00192 }
00193 
00194 static inline isc_result_t
00195 towire_in_a6(ARGS_TOWIRE) {
00196         isc_region_t sr;
00197         dns_name_t name;
00198         dns_offsets_t offsets;
00199         unsigned char prefixlen;
00200         unsigned char octets;
00201 
00202         REQUIRE(rdata->type == 38);
00203         REQUIRE(rdata->rdclass == 1);
00204         REQUIRE(rdata->length != 0);
00205 
00206         dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
00207         dns_rdata_toregion(rdata, &sr);
00208         prefixlen = sr.base[0];
00209         INSIST(prefixlen <= 128);
00210 
00211         octets = 1 + 16 - prefixlen / 8;
00212         RETERR(mem_tobuffer(target, sr.base, octets));
00213         isc_region_consume(&sr, octets);
00214 
00215         if (prefixlen == 0)
00216                 return (ISC_R_SUCCESS);
00217 
00218         dns_name_init(&name, offsets);
00219         dns_name_fromregion(&name, &sr);
00220         return (dns_name_towire(&name, cctx, target));
00221 }
00222 
00223 static inline int
00224 compare_in_a6(ARGS_COMPARE) {
00225         int order;
00226         unsigned char prefixlen1, prefixlen2;
00227         unsigned char octets;
00228         dns_name_t name1;
00229         dns_name_t name2;
00230         isc_region_t region1;
00231         isc_region_t region2;
00232 
00233         REQUIRE(rdata1->type == rdata2->type);
00234         REQUIRE(rdata1->rdclass == rdata2->rdclass);
00235         REQUIRE(rdata1->type == 38);
00236         REQUIRE(rdata1->rdclass == 1);
00237         REQUIRE(rdata1->length != 0);
00238         REQUIRE(rdata2->length != 0);
00239 
00240         dns_rdata_toregion(rdata1, &region1);
00241         dns_rdata_toregion(rdata2, &region2);
00242         prefixlen1 = region1.base[0];
00243         prefixlen2 = region2.base[0];
00244         isc_region_consume(&region1, 1);
00245         isc_region_consume(&region2, 1);
00246         if (prefixlen1 < prefixlen2)
00247                 return (-1);
00248         else if (prefixlen1 > prefixlen2)
00249                 return (1);
00250         /*
00251          * Prefix lengths are equal.
00252          */
00253         octets = 16 - prefixlen1 / 8;
00254 
00255         if (octets > 0) {
00256                 order = memcmp(region1.base, region2.base, octets);
00257                 if (order < 0)
00258                         return (-1);
00259                 else if (order > 0)
00260                         return (1);
00261                 /*
00262                  * Address suffixes are equal.
00263                  */
00264                 if (prefixlen1 == 0)
00265                         return (order);
00266                 isc_region_consume(&region1, octets);
00267                 isc_region_consume(&region2, octets);
00268         }
00269 
00270         dns_name_init(&name1, NULL);
00271         dns_name_init(&name2, NULL);
00272         dns_name_fromregion(&name1, &region1);
00273         dns_name_fromregion(&name2, &region2);
00274         return (dns_name_rdatacompare(&name1, &name2));
00275 }
00276 
00277 static inline isc_result_t
00278 fromstruct_in_a6(ARGS_FROMSTRUCT) {
00279         dns_rdata_in_a6_t *a6 = source;
00280         isc_region_t region;
00281         int octets;
00282         isc_uint8_t bits;
00283         isc_uint8_t first;
00284         isc_uint8_t mask;
00285 
00286         REQUIRE(type == 38);
00287         REQUIRE(rdclass == 1);
00288         REQUIRE(source != NULL);
00289         REQUIRE(a6->common.rdtype == type);
00290         REQUIRE(a6->common.rdclass == rdclass);
00291 
00292         UNUSED(type);
00293         UNUSED(rdclass);
00294 
00295         if (a6->prefixlen > 128)
00296                 return (ISC_R_RANGE);
00297 
00298         RETERR(uint8_tobuffer(a6->prefixlen, target));
00299 
00300         /* Suffix */
00301         if (a6->prefixlen != 128) {
00302                 octets = 16 - a6->prefixlen / 8;
00303                 bits = a6->prefixlen % 8;
00304                 if (bits != 0) {
00305                         mask = 0xffU >> bits;
00306                         first = a6->in6_addr.s6_addr[16 - octets] & mask;
00307                         RETERR(uint8_tobuffer(first, target));
00308                         octets--;
00309                 }
00310                 if (octets > 0)
00311                         RETERR(mem_tobuffer(target,
00312                                             a6->in6_addr.s6_addr + 16 - octets,
00313                                             octets));
00314         }
00315 
00316         if (a6->prefixlen == 0)
00317                 return (ISC_R_SUCCESS);
00318         dns_name_toregion(&a6->prefix, &region);
00319         return (isc_buffer_copyregion(target, &region));
00320 }
00321 
00322 static inline isc_result_t
00323 tostruct_in_a6(ARGS_TOSTRUCT) {
00324         dns_rdata_in_a6_t *a6 = target;
00325         unsigned char octets;
00326         dns_name_t name;
00327         isc_region_t r;
00328 
00329         REQUIRE(rdata->type == 38);
00330         REQUIRE(rdata->rdclass == 1);
00331         REQUIRE(target != NULL);
00332         REQUIRE(rdata->length != 0);
00333 
00334         a6->common.rdclass = rdata->rdclass;
00335         a6->common.rdtype = rdata->type;
00336         ISC_LINK_INIT(&a6->common, link);
00337 
00338         dns_rdata_toregion(rdata, &r);
00339 
00340         a6->prefixlen = uint8_fromregion(&r);
00341         isc_region_consume(&r, 1);
00342         memset(a6->in6_addr.s6_addr, 0, sizeof(a6->in6_addr.s6_addr));
00343 
00344         /*
00345          * Suffix.
00346          */
00347         if (a6->prefixlen != 128) {
00348                 octets = 16 - a6->prefixlen / 8;
00349                 INSIST(r.length >= octets);
00350                 memmove(a6->in6_addr.s6_addr + 16 - octets, r.base, octets);
00351                 isc_region_consume(&r, octets);
00352         }
00353 
00354         /*
00355          * Prefix.
00356          */
00357         dns_name_init(&a6->prefix, NULL);
00358         if (a6->prefixlen != 0) {
00359                 dns_name_init(&name, NULL);
00360                 dns_name_fromregion(&name, &r);
00361                 RETERR(name_duporclone(&name, mctx, &a6->prefix));
00362         }
00363         a6->mctx = mctx;
00364         return (ISC_R_SUCCESS);
00365 }
00366 
00367 static inline void
00368 freestruct_in_a6(ARGS_FREESTRUCT) {
00369         dns_rdata_in_a6_t *a6 = source;
00370 
00371         REQUIRE(source != NULL);
00372         REQUIRE(a6->common.rdclass == 1);
00373         REQUIRE(a6->common.rdtype == 38);
00374 
00375         if (a6->mctx == NULL)
00376                 return;
00377 
00378         if (dns_name_dynamic(&a6->prefix))
00379                 dns_name_free(&a6->prefix, a6->mctx);
00380         a6->mctx = NULL;
00381 }
00382 
00383 static inline isc_result_t
00384 additionaldata_in_a6(ARGS_ADDLDATA) {
00385         REQUIRE(rdata->type == 38);
00386         REQUIRE(rdata->rdclass == 1);
00387 
00388         UNUSED(rdata);
00389         UNUSED(add);
00390         UNUSED(arg);
00391 
00392         return (ISC_R_SUCCESS);
00393 }
00394 
00395 static inline isc_result_t
00396 digest_in_a6(ARGS_DIGEST) {
00397         isc_region_t r1, r2;
00398         unsigned char prefixlen, octets;
00399         isc_result_t result;
00400         dns_name_t name;
00401 
00402         REQUIRE(rdata->type == 38);
00403         REQUIRE(rdata->rdclass == 1);
00404 
00405         dns_rdata_toregion(rdata, &r1);
00406         r2 = r1;
00407         prefixlen = r1.base[0];
00408         octets = 1 + 16 - prefixlen / 8;
00409 
00410         r1.length = octets;
00411         result = (digest)(arg, &r1);
00412         if (result != ISC_R_SUCCESS)
00413                 return (result);
00414         if (prefixlen == 0)
00415                 return (ISC_R_SUCCESS);
00416 
00417         isc_region_consume(&r2, octets);
00418         dns_name_init(&name, NULL);
00419         dns_name_fromregion(&name, &r2);
00420         return (dns_name_digest(&name, digest, arg));
00421 }
00422 
00423 static inline isc_boolean_t
00424 checkowner_in_a6(ARGS_CHECKOWNER) {
00425 
00426         REQUIRE(type == 38);
00427         REQUIRE(rdclass == 1);
00428 
00429         UNUSED(type);
00430         UNUSED(rdclass);
00431 
00432         return (dns_name_ishostname(name, wildcard));
00433 }
00434 
00435 static inline isc_boolean_t
00436 checknames_in_a6(ARGS_CHECKNAMES) {
00437         isc_region_t region;
00438         dns_name_t name;
00439         unsigned int prefixlen;
00440 
00441         REQUIRE(rdata->type == 38);
00442         REQUIRE(rdata->rdclass == 1);
00443 
00444         UNUSED(owner);
00445 
00446         dns_rdata_toregion(rdata, &region);
00447         prefixlen = uint8_fromregion(&region);
00448         if (prefixlen == 0)
00449                 return (ISC_TRUE);
00450         isc_region_consume(&region, 1 + 16 - prefixlen / 8);
00451         dns_name_init(&name, NULL);
00452         dns_name_fromregion(&name, &region);
00453         if (!dns_name_ishostname(&name, ISC_FALSE)) {
00454                 if (bad != NULL)
00455                         dns_name_clone(&name, bad);
00456                 return (ISC_FALSE);
00457         }
00458         return (ISC_TRUE);
00459 }
00460 
00461 static inline int
00462 casecompare_in_a6(ARGS_COMPARE) {
00463         return (compare_in_a6(rdata1, rdata2));
00464 }
00465 
00466 #endif  /* RDATA_IN_1_A6_38_C */

Generated on Tue Apr 28 17:41:00 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha