apl_42.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004, 2005, 2007-2009, 2014  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 2002  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: apl_42.c,v 1.16 2009/12/04 22:06:37 tbox Exp $ */
00019 
00020 /* RFC3123 */
00021 
00022 #ifndef RDATA_IN_1_APL_42_C
00023 #define RDATA_IN_1_APL_42_C
00024 
00025 #define RRTYPE_APL_ATTRIBUTES (0)
00026 
00027 static inline isc_result_t
00028 fromtext_in_apl(ARGS_FROMTEXT) {
00029         isc_token_t token;
00030         unsigned char addr[16];
00031         unsigned long afi;
00032         isc_uint8_t prefix;
00033         isc_uint8_t len;
00034         isc_boolean_t neg;
00035         char *cp, *ap, *slash;
00036         int n;
00037 
00038         REQUIRE(type == 42);
00039         REQUIRE(rdclass == 1);
00040 
00041         UNUSED(type);
00042         UNUSED(rdclass);
00043         UNUSED(origin);
00044         UNUSED(options);
00045         UNUSED(callbacks);
00046 
00047         do {
00048                 RETERR(isc_lex_getmastertoken(lexer, &token,
00049                                               isc_tokentype_string, ISC_TRUE));
00050                 if (token.type != isc_tokentype_string)
00051                         break;
00052 
00053                 cp = DNS_AS_STR(token);
00054                 neg = ISC_TF(*cp == '!');
00055                 if (neg)
00056                         cp++;
00057                 afi = strtoul(cp, &ap, 10);
00058                 if (*ap++ != ':' || cp == ap)
00059                         RETTOK(DNS_R_SYNTAX);
00060                 if (afi > 0xffffU)
00061                         RETTOK(ISC_R_RANGE);
00062                 slash = strchr(ap, '/');
00063                 if (slash == NULL || slash == ap)
00064                         RETTOK(DNS_R_SYNTAX);
00065                 RETTOK(isc_parse_uint8(&prefix, slash + 1, 10));
00066                 switch (afi) {
00067                 case 1:
00068                         *slash = '\0';
00069                         n = inet_pton(AF_INET, ap, addr);
00070                         *slash = '/';
00071                         if (n != 1)
00072                                 RETTOK(DNS_R_BADDOTTEDQUAD);
00073                         if (prefix > 32)
00074                                 RETTOK(ISC_R_RANGE);
00075                         for (len = 4; len > 0; len--)
00076                                 if (addr[len - 1] != 0)
00077                                         break;
00078                         break;
00079 
00080                 case 2:
00081                         *slash = '\0';
00082                         n = inet_pton(AF_INET6, ap, addr);
00083                         *slash = '/';
00084                         if (n != 1)
00085                                 RETTOK(DNS_R_BADAAAA);
00086                         if (prefix > 128)
00087                                 RETTOK(ISC_R_RANGE);
00088                         for (len = 16; len > 0; len--)
00089                                 if (addr[len - 1] != 0)
00090                                         break;
00091                         break;
00092 
00093                 default:
00094                         RETTOK(ISC_R_NOTIMPLEMENTED);
00095                 }
00096                 RETERR(uint16_tobuffer(afi, target));
00097                 RETERR(uint8_tobuffer(prefix, target));
00098                 RETERR(uint8_tobuffer(len | ((neg) ? 0x80 : 0), target));
00099                 RETERR(mem_tobuffer(target, addr, len));
00100         } while (1);
00101 
00102         /*
00103          * Let upper layer handle eol/eof.
00104          */
00105         isc_lex_ungettoken(lexer, &token);
00106 
00107         return (ISC_R_SUCCESS);
00108 }
00109 
00110 static inline isc_result_t
00111 totext_in_apl(ARGS_TOTEXT) {
00112         isc_region_t sr;
00113         isc_region_t ir;
00114         isc_uint16_t afi;
00115         isc_uint8_t prefix;
00116         isc_uint8_t len;
00117         isc_boolean_t neg;
00118         unsigned char buf[16];
00119         char txt[sizeof(" !64000")];
00120         const char *sep = "";
00121         int n;
00122 
00123         REQUIRE(rdata->type == 42);
00124         REQUIRE(rdata->rdclass == 1);
00125 
00126         UNUSED(tctx);
00127 
00128         dns_rdata_toregion(rdata, &sr);
00129         ir.base = buf;
00130         ir.length = sizeof(buf);
00131 
00132         while (sr.length > 0) {
00133                 INSIST(sr.length >= 4);
00134                 afi = uint16_fromregion(&sr);
00135                 isc_region_consume(&sr, 2);
00136                 prefix = *sr.base;
00137                 isc_region_consume(&sr, 1);
00138                 len = (*sr.base & 0x7f);
00139                 neg = ISC_TF((*sr.base & 0x80) != 0);
00140                 isc_region_consume(&sr, 1);
00141                 INSIST(len <= sr.length);
00142                 n = snprintf(txt, sizeof(txt), "%s%s%u:", sep,
00143                              neg ? "!": "", afi);
00144                 INSIST(n < (int)sizeof(txt));
00145                 RETERR(str_totext(txt, target));
00146                 switch (afi) {
00147                 case 1:
00148                         INSIST(len <= 4);
00149                         INSIST(prefix <= 32);
00150                         memset(buf, 0, sizeof(buf));
00151                         memmove(buf, sr.base, len);
00152                         RETERR(inet_totext(AF_INET, &ir, target));
00153                         break;
00154 
00155                 case 2:
00156                         INSIST(len <= 16);
00157                         INSIST(prefix <= 128);
00158                         memset(buf, 0, sizeof(buf));
00159                         memmove(buf, sr.base, len);
00160                         RETERR(inet_totext(AF_INET6, &ir, target));
00161                         break;
00162 
00163                 default:
00164                         return (ISC_R_NOTIMPLEMENTED);
00165                 }
00166                 n = snprintf(txt, sizeof(txt), "/%u", prefix);
00167                 INSIST(n < (int)sizeof(txt));
00168                 RETERR(str_totext(txt, target));
00169                 isc_region_consume(&sr, len);
00170                 sep = " ";
00171         }
00172         return (ISC_R_SUCCESS);
00173 }
00174 
00175 static inline isc_result_t
00176 fromwire_in_apl(ARGS_FROMWIRE) {
00177         isc_region_t sr, sr2;
00178         isc_region_t tr;
00179         isc_uint16_t afi;
00180         isc_uint8_t prefix;
00181         isc_uint8_t len;
00182 
00183         REQUIRE(type == 42);
00184         REQUIRE(rdclass == 1);
00185 
00186         UNUSED(type);
00187         UNUSED(dctx);
00188         UNUSED(rdclass);
00189         UNUSED(options);
00190 
00191         isc_buffer_activeregion(source, &sr);
00192         isc_buffer_availableregion(target, &tr);
00193         if (sr.length > tr.length)
00194                 return (ISC_R_NOSPACE);
00195         sr2 = sr;
00196 
00197         /* Zero or more items */
00198         while (sr.length > 0) {
00199                 if (sr.length < 4)
00200                         return (ISC_R_UNEXPECTEDEND);
00201                 afi = uint16_fromregion(&sr);
00202                 isc_region_consume(&sr, 2);
00203                 prefix = *sr.base;
00204                 isc_region_consume(&sr, 1);
00205                 len = (*sr.base & 0x7f);
00206                 isc_region_consume(&sr, 1);
00207                 if (len > sr.length)
00208                         return (ISC_R_UNEXPECTEDEND);
00209                 switch (afi) {
00210                 case 1:
00211                         if (prefix > 32 || len > 4)
00212                                 return (ISC_R_RANGE);
00213                         break;
00214                 case 2:
00215                         if (prefix > 128 || len > 16)
00216                                 return (ISC_R_RANGE);
00217                 }
00218                 if (len > 0 && sr.base[len - 1] == 0)
00219                         return (DNS_R_FORMERR);
00220                 isc_region_consume(&sr, len);
00221         }
00222         isc_buffer_forward(source, sr2.length);
00223         return (mem_tobuffer(target, sr2.base, sr2.length));
00224 }
00225 
00226 static inline isc_result_t
00227 towire_in_apl(ARGS_TOWIRE) {
00228         UNUSED(cctx);
00229 
00230         REQUIRE(rdata->type == 42);
00231         REQUIRE(rdata->rdclass == 1);
00232 
00233         return (mem_tobuffer(target, rdata->data, rdata->length));
00234 }
00235 
00236 static inline int
00237 compare_in_apl(ARGS_COMPARE) {
00238         isc_region_t r1;
00239         isc_region_t r2;
00240 
00241         REQUIRE(rdata1->type == rdata2->type);
00242         REQUIRE(rdata1->rdclass == rdata2->rdclass);
00243         REQUIRE(rdata1->type == 42);
00244         REQUIRE(rdata1->rdclass == 1);
00245 
00246         dns_rdata_toregion(rdata1, &r1);
00247         dns_rdata_toregion(rdata2, &r2);
00248         return (isc_region_compare(&r1, &r2));
00249 }
00250 
00251 static inline isc_result_t
00252 fromstruct_in_apl(ARGS_FROMSTRUCT) {
00253         dns_rdata_in_apl_t *apl = source;
00254         isc_buffer_t b;
00255 
00256         REQUIRE(type == 42);
00257         REQUIRE(rdclass == 1);
00258         REQUIRE(source != NULL);
00259         REQUIRE(apl->common.rdtype == type);
00260         REQUIRE(apl->common.rdclass == rdclass);
00261         REQUIRE(apl->apl != NULL || apl->apl_len == 0);
00262 
00263         isc_buffer_init(&b, apl->apl, apl->apl_len);
00264         isc_buffer_add(&b, apl->apl_len);
00265         isc_buffer_setactive(&b, apl->apl_len);
00266         return(fromwire_in_apl(rdclass, type, &b, NULL, ISC_FALSE, target));
00267 }
00268 
00269 static inline isc_result_t
00270 tostruct_in_apl(ARGS_TOSTRUCT) {
00271         dns_rdata_in_apl_t *apl = target;
00272         isc_region_t r;
00273 
00274         REQUIRE(rdata->type == 42);
00275         REQUIRE(rdata->rdclass == 1);
00276 
00277         apl->common.rdclass = rdata->rdclass;
00278         apl->common.rdtype = rdata->type;
00279         ISC_LINK_INIT(&apl->common, link);
00280 
00281         dns_rdata_toregion(rdata, &r);
00282         apl->apl_len = r.length;
00283         apl->apl = mem_maybedup(mctx, r.base, r.length);
00284         if (apl->apl == NULL)
00285                 return (ISC_R_NOMEMORY);
00286 
00287         apl->offset = 0;
00288         apl->mctx = mctx;
00289         return (ISC_R_SUCCESS);
00290 }
00291 
00292 static inline void
00293 freestruct_in_apl(ARGS_FREESTRUCT) {
00294         dns_rdata_in_apl_t *apl = source;
00295 
00296         REQUIRE(source != NULL);
00297         REQUIRE(apl->common.rdtype == 42);
00298         REQUIRE(apl->common.rdclass == 1);
00299 
00300         if (apl->mctx == NULL)
00301                 return;
00302         if (apl->apl != NULL)
00303                 isc_mem_free(apl->mctx, apl->apl);
00304         apl->mctx = NULL;
00305 }
00306 
00307 isc_result_t
00308 dns_rdata_apl_first(dns_rdata_in_apl_t *apl) {
00309         isc_uint32_t length;
00310 
00311         REQUIRE(apl != NULL);
00312         REQUIRE(apl->common.rdtype == 42);
00313         REQUIRE(apl->common.rdclass == 1);
00314         REQUIRE(apl->apl != NULL || apl->apl_len == 0);
00315 
00316         /*
00317          * If no APL return ISC_R_NOMORE.
00318          */
00319         if (apl->apl == NULL)
00320                 return (ISC_R_NOMORE);
00321 
00322         /*
00323          * Sanity check data.
00324          */
00325         INSIST(apl->apl_len > 3U);
00326         length = apl->apl[apl->offset + 3] & 0x7f;
00327         INSIST(length <= apl->apl_len);
00328 
00329         apl->offset = 0;
00330         return (ISC_R_SUCCESS);
00331 }
00332 
00333 isc_result_t
00334 dns_rdata_apl_next(dns_rdata_in_apl_t *apl) {
00335         isc_uint32_t length;
00336 
00337         REQUIRE(apl != NULL);
00338         REQUIRE(apl->common.rdtype == 42);
00339         REQUIRE(apl->common.rdclass == 1);
00340         REQUIRE(apl->apl != NULL || apl->apl_len == 0);
00341 
00342         /*
00343          * No APL or have already reached the end return ISC_R_NOMORE.
00344          */
00345         if (apl->apl == NULL || apl->offset == apl->apl_len)
00346                 return (ISC_R_NOMORE);
00347 
00348         /*
00349          * Sanity check data.
00350          */
00351         INSIST(apl->offset < apl->apl_len);
00352         INSIST(apl->apl_len > 3U);
00353         INSIST(apl->offset <= apl->apl_len - 4U);
00354         length = apl->apl[apl->offset + 3] & 0x7f;
00355         /*
00356          * 16 to 32 bits promotion as 'length' is 32 bits so there is
00357          * no overflow problems.
00358          */
00359         INSIST(length + apl->offset <= apl->apl_len);
00360 
00361         apl->offset += apl->apl[apl->offset + 3] & 0x7f;
00362         return ((apl->offset >= apl->apl_len) ? ISC_R_SUCCESS : ISC_R_NOMORE);
00363 }
00364 
00365 isc_result_t
00366 dns_rdata_apl_current(dns_rdata_in_apl_t *apl, dns_rdata_apl_ent_t *ent) {
00367         isc_uint32_t length;
00368 
00369         REQUIRE(apl != NULL);
00370         REQUIRE(apl->common.rdtype == 42);
00371         REQUIRE(apl->common.rdclass == 1);
00372         REQUIRE(ent != NULL);
00373         REQUIRE(apl->apl != NULL || apl->apl_len == 0);
00374         REQUIRE(apl->offset <= apl->apl_len);
00375 
00376         if (apl->offset == apl->apl_len)
00377                 return (ISC_R_NOMORE);
00378 
00379         /*
00380          * Sanity check data.
00381          */
00382         INSIST(apl->apl_len > 3U);
00383         INSIST(apl->offset <= apl->apl_len - 4U);
00384         length = apl->apl[apl->offset + 3] & 0x7f;
00385         /*
00386          * 16 to 32 bits promotion as 'length' is 32 bits so there is
00387          * no overflow problems.
00388          */
00389         INSIST(length + apl->offset <= apl->apl_len);
00390 
00391         ent->family = (apl->apl[apl->offset] << 8) + apl->apl[apl->offset + 1];
00392         ent->prefix = apl->apl[apl->offset + 2];
00393         ent->length = apl->apl[apl->offset + 3] & 0x7f;
00394         ent->negative = ISC_TF((apl->apl[apl->offset + 3] & 0x80) != 0);
00395         if (ent->length != 0)
00396                 ent->data = &apl->apl[apl->offset + 4];
00397         else
00398                 ent->data = NULL;
00399         return (ISC_R_SUCCESS);
00400 }
00401 
00402 static inline isc_result_t
00403 additionaldata_in_apl(ARGS_ADDLDATA) {
00404         REQUIRE(rdata->type == 42);
00405         REQUIRE(rdata->rdclass == 1);
00406 
00407         (void)add;
00408         (void)arg;
00409 
00410         return (ISC_R_SUCCESS);
00411 }
00412 
00413 static inline isc_result_t
00414 digest_in_apl(ARGS_DIGEST) {
00415         isc_region_t r;
00416 
00417         REQUIRE(rdata->type == 42);
00418         REQUIRE(rdata->rdclass == 1);
00419 
00420         dns_rdata_toregion(rdata, &r);
00421 
00422         return ((digest)(arg, &r));
00423 }
00424 
00425 static inline isc_boolean_t
00426 checkowner_in_apl(ARGS_CHECKOWNER) {
00427 
00428         REQUIRE(type == 42);
00429         REQUIRE(rdclass == 1);
00430 
00431         UNUSED(name);
00432         UNUSED(type);
00433         UNUSED(rdclass);
00434         UNUSED(wildcard);
00435 
00436         return (ISC_TRUE);
00437 }
00438 
00439 
00440 static inline isc_boolean_t
00441 checknames_in_apl(ARGS_CHECKNAMES) {
00442 
00443         REQUIRE(rdata->type == 42);
00444         REQUIRE(rdata->rdclass == 1);
00445 
00446         UNUSED(rdata);
00447         UNUSED(owner);
00448         UNUSED(bad);
00449 
00450         return (ISC_TRUE);
00451 }
00452 
00453 static inline int
00454 casecompare_in_apl(ARGS_COMPARE) {
00455         return (compare_in_apl(rdata1, rdata2));
00456 }
00457 
00458 #endif  /* RDATA_IN_1_APL_42_C */

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