rdata.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 1998-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$ */
00019 
00020 /*! \file */
00021 
00022 #include <config.h>
00023 #include <ctype.h>
00024 
00025 #include <isc/base64.h>
00026 #include <isc/hex.h>
00027 #include <isc/lex.h>
00028 #include <isc/mem.h>
00029 #include <isc/parseint.h>
00030 #include <isc/print.h>
00031 #include <isc/string.h>
00032 #include <isc/stdlib.h>
00033 #include <isc/util.h>
00034 
00035 #include <dns/callbacks.h>
00036 #include <dns/cert.h>
00037 #include <dns/compress.h>
00038 #include <dns/dsdigest.h>
00039 #include <dns/enumtype.h>
00040 #include <dns/keyflags.h>
00041 #include <dns/keyvalues.h>
00042 #include <dns/message.h>
00043 #include <dns/rcode.h>
00044 #include <dns/rdata.h>
00045 #include <dns/rdataclass.h>
00046 #include <dns/rdatastruct.h>
00047 #include <dns/rdatatype.h>
00048 #include <dns/result.h>
00049 #include <dns/secalg.h>
00050 #include <dns/secproto.h>
00051 #include <dns/time.h>
00052 #include <dns/ttl.h>
00053 
00054 #define RETERR(x) \
00055         do { \
00056                 isc_result_t _r = (x); \
00057                 if (_r != ISC_R_SUCCESS) \
00058                         return (_r); \
00059         } while (0)
00060 
00061 #define RETTOK(x) \
00062         do { \
00063                 isc_result_t _r = (x); \
00064                 if (_r != ISC_R_SUCCESS) { \
00065                         isc_lex_ungettoken(lexer, &token); \
00066                         return (_r); \
00067                 } \
00068         } while (0)
00069 
00070 #define DNS_AS_STR(t) ((t).value.as_textregion.base)
00071 
00072 #define ARGS_FROMTEXT   int rdclass, dns_rdatatype_t type, \
00073                         isc_lex_t *lexer, dns_name_t *origin, \
00074                         unsigned int options, isc_buffer_t *target, \
00075                         dns_rdatacallbacks_t *callbacks
00076 
00077 #define ARGS_TOTEXT     dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, \
00078                         isc_buffer_t *target
00079 
00080 #define ARGS_FROMWIRE   int rdclass, dns_rdatatype_t type, \
00081                         isc_buffer_t *source, dns_decompress_t *dctx, \
00082                         unsigned int options, isc_buffer_t *target
00083 
00084 #define ARGS_TOWIRE     dns_rdata_t *rdata, dns_compress_t *cctx, \
00085                         isc_buffer_t *target
00086 
00087 #define ARGS_COMPARE    const dns_rdata_t *rdata1, const dns_rdata_t *rdata2
00088 
00089 #define ARGS_FROMSTRUCT int rdclass, dns_rdatatype_t type, \
00090                         void *source, isc_buffer_t *target
00091 
00092 #define ARGS_TOSTRUCT   dns_rdata_t *rdata, void *target, isc_mem_t *mctx
00093 
00094 #define ARGS_FREESTRUCT void *source
00095 
00096 #define ARGS_ADDLDATA   dns_rdata_t *rdata, dns_additionaldatafunc_t add, \
00097                         void *arg
00098 
00099 #define ARGS_DIGEST     dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg
00100 
00101 #define ARGS_CHECKOWNER dns_name_t *name, dns_rdataclass_t rdclass, \
00102                         dns_rdatatype_t type, isc_boolean_t wildcard
00103 
00104 #define ARGS_CHECKNAMES dns_rdata_t *rdata, dns_name_t *owner, dns_name_t *bad
00105 
00106 
00107 /*%
00108  * Context structure for the totext_ functions.
00109  * Contains formatting options for rdata-to-text
00110  * conversion.
00111  */
00112 typedef struct dns_rdata_textctx {
00113         dns_name_t *origin;     /*%< Current origin, or NULL. */
00114         unsigned int flags;     /*%< DNS_STYLEFLAG_*  */
00115         unsigned int width;     /*%< Width of rdata column. */
00116         const char *linebreak;  /*%< Line break string. */
00117 } dns_rdata_textctx_t;
00118 
00119 static isc_result_t
00120 txt_totext(isc_region_t *source, isc_boolean_t quote, isc_buffer_t *target);
00121 
00122 static isc_result_t
00123 txt_fromtext(isc_textregion_t *source, isc_buffer_t *target);
00124 
00125 static isc_result_t
00126 txt_fromwire(isc_buffer_t *source, isc_buffer_t *target);
00127 
00128 static isc_result_t
00129 multitxt_totext(isc_region_t *source, isc_buffer_t *target);
00130 
00131 static isc_result_t
00132 multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target);
00133 
00134 static isc_boolean_t
00135 name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target);
00136 
00137 static unsigned int
00138 name_length(dns_name_t *name);
00139 
00140 static isc_result_t
00141 str_totext(const char *source, isc_buffer_t *target);
00142 
00143 static isc_result_t
00144 inet_totext(int af, isc_region_t *src, isc_buffer_t *target);
00145 
00146 static isc_boolean_t
00147 buffer_empty(isc_buffer_t *source);
00148 
00149 static void
00150 buffer_fromregion(isc_buffer_t *buffer, isc_region_t *region);
00151 
00152 static isc_result_t
00153 uint32_tobuffer(isc_uint32_t, isc_buffer_t *target);
00154 
00155 static isc_result_t
00156 uint16_tobuffer(isc_uint32_t, isc_buffer_t *target);
00157 
00158 static isc_result_t
00159 uint8_tobuffer(isc_uint32_t, isc_buffer_t *target);
00160 
00161 static isc_result_t
00162 name_tobuffer(dns_name_t *name, isc_buffer_t *target);
00163 
00164 static isc_uint32_t
00165 uint32_fromregion(isc_region_t *region);
00166 
00167 static isc_uint16_t
00168 uint16_fromregion(isc_region_t *region);
00169 
00170 static isc_uint8_t
00171 uint8_fromregion(isc_region_t *region);
00172 
00173 static isc_uint8_t
00174 uint8_consume_fromregion(isc_region_t *region);
00175 
00176 static isc_result_t
00177 mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
00178 
00179 static int
00180 hexvalue(char value);
00181 
00182 static int
00183 decvalue(char value);
00184 
00185 static isc_result_t
00186 btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target);
00187 
00188 static isc_result_t
00189 atob_tobuffer(isc_lex_t *lexer, isc_buffer_t *target);
00190 
00191 static void
00192 default_fromtext_callback(dns_rdatacallbacks_t *callbacks, const char *, ...)
00193      ISC_FORMAT_PRINTF(2, 3);
00194 
00195 static void
00196 fromtext_error(void (*callback)(dns_rdatacallbacks_t *, const char *, ...),
00197                dns_rdatacallbacks_t *callbacks, const char *name,
00198                unsigned long line, isc_token_t *token, isc_result_t result);
00199 
00200 static void
00201 fromtext_warneof(isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks);
00202 
00203 static isc_result_t
00204 rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
00205              isc_buffer_t *target);
00206 
00207 static void
00208 warn_badname(dns_name_t *name, isc_lex_t *lexer,
00209              dns_rdatacallbacks_t *callbacks);
00210 
00211 static void
00212 warn_badmx(isc_token_t *token, isc_lex_t *lexer,
00213            dns_rdatacallbacks_t *callbacks);
00214 
00215 static isc_uint16_t
00216 uint16_consume_fromregion(isc_region_t *region);
00217 
00218 static isc_result_t
00219 unknown_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
00220                isc_buffer_t *target);
00221 
00222 /*% INT16 Size */
00223 #define NS_INT16SZ      2
00224 /*% IPv6 Address Size */
00225 #define NS_LOCATORSZ    8
00226 
00227 /*%
00228  *      convert presentation level address to network order binary form.
00229  * \return
00230  *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
00231  * \note
00232  *      (1) does not touch `dst' unless it's returning 1.
00233  */
00234 static inline int
00235 locator_pton(const char *src, unsigned char *dst) {
00236         static const char xdigits_l[] = "0123456789abcdef",
00237                           xdigits_u[] = "0123456789ABCDEF";
00238         unsigned char tmp[NS_LOCATORSZ];
00239         unsigned char *tp = tmp, *endp;
00240         const char *xdigits;
00241         int ch, seen_xdigits;
00242         unsigned int val;
00243 
00244         memset(tp, '\0', NS_LOCATORSZ);
00245         endp = tp + NS_LOCATORSZ;
00246         seen_xdigits = 0;
00247         val = 0;
00248         while ((ch = *src++) != '\0') {
00249                 const char *pch;
00250 
00251                 pch = strchr((xdigits = xdigits_l), ch);
00252                 if (pch == NULL)
00253                         pch = strchr((xdigits = xdigits_u), ch);
00254                 if (pch != NULL) {
00255                         val <<= 4;
00256                         val |= (pch - xdigits);
00257                         if (++seen_xdigits > 4)
00258                                 return (0);
00259                         continue;
00260                 }
00261                 if (ch == ':') {
00262                         if (!seen_xdigits)
00263                                 return (0);
00264                         if (tp + NS_INT16SZ > endp)
00265                                 return (0);
00266                         *tp++ = (unsigned char) (val >> 8) & 0xff;
00267                         *tp++ = (unsigned char) val & 0xff;
00268                         seen_xdigits = 0;
00269                         val = 0;
00270                         continue;
00271                 }
00272                 return (0);
00273         }
00274         if (seen_xdigits) {
00275                 if (tp + NS_INT16SZ > endp)
00276                         return (0);
00277                 *tp++ = (unsigned char) (val >> 8) & 0xff;
00278                 *tp++ = (unsigned char) val & 0xff;
00279         }
00280         if (tp != endp)
00281                 return (0);
00282         memmove(dst, tmp, NS_LOCATORSZ);
00283         return (1);
00284 }
00285 
00286 static inline int
00287 getquad(const void *src, struct in_addr *dst,
00288         isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks)
00289 {
00290         int result;
00291         struct in_addr *tmp;
00292 
00293         result = inet_aton(src, dst);
00294         if (result == 1 && callbacks != NULL &&
00295             inet_pton(AF_INET, src, &tmp) != 1) {
00296                 const char *name = isc_lex_getsourcename(lexer);
00297                 if (name == NULL)
00298                         name = "UNKNOWN";
00299                 (*callbacks->warn)(callbacks, "%s:%lu: \"%s\" "
00300                                    "is not a decimal dotted quad", name,
00301                                    isc_lex_getsourceline(lexer), src);
00302         }
00303         return (result);
00304 }
00305 
00306 static inline isc_result_t
00307 name_duporclone(dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) {
00308 
00309         if (mctx != NULL)
00310                 return (dns_name_dup(source, mctx, target));
00311         dns_name_clone(source, target);
00312         return (ISC_R_SUCCESS);
00313 }
00314 
00315 static inline void *
00316 mem_maybedup(isc_mem_t *mctx, void *source, size_t length) {
00317         void *new;
00318 
00319         if (mctx == NULL)
00320                 return (source);
00321         new = isc_mem_allocate(mctx, length);
00322         if (new != NULL)
00323                 memmove(new, source, length);
00324 
00325         return (new);
00326 }
00327 
00328 static const char hexdigits[] = "0123456789abcdef";
00329 static const char decdigits[] = "0123456789";
00330 
00331 #include "code.h"
00332 
00333 #define META 0x0001
00334 #define RESERVED 0x0002
00335 
00336 /***
00337  *** Initialization
00338  ***/
00339 
00340 void
00341 dns_rdata_init(dns_rdata_t *rdata) {
00342 
00343         REQUIRE(rdata != NULL);
00344 
00345         rdata->data = NULL;
00346         rdata->length = 0;
00347         rdata->rdclass = 0;
00348         rdata->type = 0;
00349         rdata->flags = 0;
00350         ISC_LINK_INIT(rdata, link);
00351         /* ISC_LIST_INIT(rdata->list); */
00352 }
00353 
00354 void
00355 dns_rdata_reset(dns_rdata_t *rdata) {
00356 
00357         REQUIRE(rdata != NULL);
00358 
00359         REQUIRE(!ISC_LINK_LINKED(rdata, link));
00360         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
00361 
00362         rdata->data = NULL;
00363         rdata->length = 0;
00364         rdata->rdclass = 0;
00365         rdata->type = 0;
00366         rdata->flags = 0;
00367 }
00368 
00369 /***
00370  ***
00371  ***/
00372 
00373 void
00374 dns_rdata_clone(const dns_rdata_t *src, dns_rdata_t *target) {
00375 
00376         REQUIRE(src != NULL);
00377         REQUIRE(target != NULL);
00378 
00379         REQUIRE(DNS_RDATA_INITIALIZED(target));
00380 
00381         REQUIRE(DNS_RDATA_VALIDFLAGS(src));
00382         REQUIRE(DNS_RDATA_VALIDFLAGS(target));
00383 
00384         target->data = src->data;
00385         target->length = src->length;
00386         target->rdclass = src->rdclass;
00387         target->type = src->type;
00388         target->flags = src->flags;
00389 }
00390 
00391 
00392 /***
00393  *** Comparisons
00394  ***/
00395 
00396 int
00397 dns_rdata_compare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2) {
00398         int result = 0;
00399         isc_boolean_t use_default = ISC_FALSE;
00400 
00401         REQUIRE(rdata1 != NULL);
00402         REQUIRE(rdata2 != NULL);
00403         REQUIRE(rdata1->length == 0 || rdata1->data != NULL);
00404         REQUIRE(rdata2->length == 0 || rdata2->data != NULL);
00405         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata1));
00406         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata2));
00407 
00408         if (rdata1->rdclass != rdata2->rdclass)
00409                 return (rdata1->rdclass < rdata2->rdclass ? -1 : 1);
00410 
00411         if (rdata1->type != rdata2->type)
00412                 return (rdata1->type < rdata2->type ? -1 : 1);
00413 
00414         COMPARESWITCH
00415 
00416         if (use_default) {
00417                 isc_region_t r1;
00418                 isc_region_t r2;
00419 
00420                 dns_rdata_toregion(rdata1, &r1);
00421                 dns_rdata_toregion(rdata2, &r2);
00422                 result = isc_region_compare(&r1, &r2);
00423         }
00424         return (result);
00425 }
00426 
00427 int
00428 dns_rdata_casecompare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2) {
00429         int result = 0;
00430         isc_boolean_t use_default = ISC_FALSE;
00431 
00432         REQUIRE(rdata1 != NULL);
00433         REQUIRE(rdata2 != NULL);
00434         REQUIRE(rdata1->length == 0 || rdata1->data != NULL);
00435         REQUIRE(rdata2->length == 0 || rdata2->data != NULL);
00436         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata1));
00437         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata2));
00438 
00439         if (rdata1->rdclass != rdata2->rdclass)
00440                 return (rdata1->rdclass < rdata2->rdclass ? -1 : 1);
00441 
00442         if (rdata1->type != rdata2->type)
00443                 return (rdata1->type < rdata2->type ? -1 : 1);
00444 
00445         CASECOMPARESWITCH
00446 
00447         if (use_default) {
00448                 isc_region_t r1;
00449                 isc_region_t r2;
00450 
00451                 dns_rdata_toregion(rdata1, &r1);
00452                 dns_rdata_toregion(rdata2, &r2);
00453                 result = isc_region_compare(&r1, &r2);
00454         }
00455         return (result);
00456 }
00457 
00458 /***
00459  *** Conversions
00460  ***/
00461 
00462 void
00463 dns_rdata_fromregion(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
00464                      dns_rdatatype_t type, isc_region_t *r)
00465 {
00466 
00467         REQUIRE(rdata != NULL);
00468         REQUIRE(DNS_RDATA_INITIALIZED(rdata));
00469         REQUIRE(r != NULL);
00470 
00471         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
00472 
00473         rdata->data = r->base;
00474         rdata->length = r->length;
00475         rdata->rdclass = rdclass;
00476         rdata->type = type;
00477         rdata->flags = 0;
00478 }
00479 
00480 void
00481 dns_rdata_toregion(const dns_rdata_t *rdata, isc_region_t *r) {
00482 
00483         REQUIRE(rdata != NULL);
00484         REQUIRE(r != NULL);
00485         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
00486 
00487         r->base = rdata->data;
00488         r->length = rdata->length;
00489 }
00490 
00491 isc_result_t
00492 dns_rdata_fromwire(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
00493                    dns_rdatatype_t type, isc_buffer_t *source,
00494                    dns_decompress_t *dctx, unsigned int options,
00495                    isc_buffer_t *target)
00496 {
00497         isc_result_t result = ISC_R_NOTIMPLEMENTED;
00498         isc_region_t region;
00499         isc_buffer_t ss;
00500         isc_buffer_t st;
00501         isc_boolean_t use_default = ISC_FALSE;
00502         isc_uint32_t activelength;
00503         unsigned int length;
00504 
00505         REQUIRE(dctx != NULL);
00506         if (rdata != NULL) {
00507                 REQUIRE(DNS_RDATA_INITIALIZED(rdata));
00508                 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
00509         }
00510         REQUIRE(source != NULL);
00511         REQUIRE(target != NULL);
00512 
00513         if (type == 0)
00514                 return (DNS_R_FORMERR);
00515 
00516         ss = *source;
00517         st = *target;
00518 
00519         activelength = isc_buffer_activelength(source);
00520         INSIST(activelength < 65536);
00521 
00522         FROMWIRESWITCH
00523 
00524         if (use_default) {
00525                 if (activelength > isc_buffer_availablelength(target))
00526                         result = ISC_R_NOSPACE;
00527                 else {
00528                         isc_buffer_putmem(target, isc_buffer_current(source),
00529                                           activelength);
00530                         isc_buffer_forward(source, activelength);
00531                         result = ISC_R_SUCCESS;
00532                 }
00533         }
00534 
00535         /*
00536          * Reject any rdata that expands out to more than DNS_RDATA_MAXLENGTH
00537          * as we cannot transmit it.
00538          */
00539         length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st);
00540         if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH)
00541                 result = DNS_R_FORMERR;
00542 
00543         /*
00544          * We should have consumed all of our buffer.
00545          */
00546         if (result == ISC_R_SUCCESS && !buffer_empty(source))
00547                 result = DNS_R_EXTRADATA;
00548 
00549         if (rdata != NULL && result == ISC_R_SUCCESS) {
00550                 region.base = isc_buffer_used(&st);
00551                 region.length = length;
00552                 dns_rdata_fromregion(rdata, rdclass, type, &region);
00553         }
00554 
00555         if (result != ISC_R_SUCCESS) {
00556                 *source = ss;
00557                 *target = st;
00558         }
00559         return (result);
00560 }
00561 
00562 isc_result_t
00563 dns_rdata_towire(dns_rdata_t *rdata, dns_compress_t *cctx,
00564                  isc_buffer_t *target)
00565 {
00566         isc_result_t result = ISC_R_NOTIMPLEMENTED;
00567         isc_boolean_t use_default = ISC_FALSE;
00568         isc_region_t tr;
00569         isc_buffer_t st;
00570 
00571         REQUIRE(rdata != NULL);
00572         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
00573 
00574         /*
00575          * Some DynDNS meta-RRs have empty rdata.
00576          */
00577         if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
00578                 INSIST(rdata->length == 0);
00579                 return (ISC_R_SUCCESS);
00580         }
00581 
00582         st = *target;
00583 
00584         TOWIRESWITCH
00585 
00586         if (use_default) {
00587                 isc_buffer_availableregion(target, &tr);
00588                 if (tr.length < rdata->length)
00589                         return (ISC_R_NOSPACE);
00590                 memmove(tr.base, rdata->data, rdata->length);
00591                 isc_buffer_add(target, rdata->length);
00592                 return (ISC_R_SUCCESS);
00593         }
00594         if (result != ISC_R_SUCCESS) {
00595                 *target = st;
00596                 INSIST(target->used < 65536);
00597                 dns_compress_rollback(cctx, (isc_uint16_t)target->used);
00598         }
00599         return (result);
00600 }
00601 
00602 /*
00603  * If the binary data in 'src' is valid uncompressed wire format
00604  * rdata of class 'rdclass' and type 'type', return ISC_R_SUCCESS
00605  * and copy the validated rdata to 'dest'.  Otherwise return an error.
00606  */
00607 static isc_result_t
00608 rdata_validate(isc_buffer_t *src, isc_buffer_t *dest, dns_rdataclass_t rdclass,
00609             dns_rdatatype_t type)
00610 {
00611         dns_decompress_t dctx;
00612         isc_result_t result;
00613 
00614         dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
00615         isc_buffer_setactive(src, isc_buffer_usedlength(src));
00616         result = dns_rdata_fromwire(NULL, rdclass, type, src, &dctx, 0, dest);
00617         dns_decompress_invalidate(&dctx);
00618 
00619         return (result);
00620 }
00621 
00622 static isc_result_t
00623 unknown_fromtext(dns_rdataclass_t rdclass, dns_rdatatype_t type,
00624                  isc_lex_t *lexer, isc_mem_t *mctx, isc_buffer_t *target)
00625 {
00626         isc_result_t result;
00627         isc_buffer_t *buf = NULL;
00628         isc_token_t token;
00629 
00630         if (type == 0 || dns_rdatatype_ismeta(type))
00631                 return (DNS_R_METATYPE);
00632 
00633         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
00634                                         ISC_FALSE));
00635         if (token.value.as_ulong > 65535U)
00636                 return (ISC_R_RANGE);
00637         result = isc_buffer_allocate(mctx, &buf, token.value.as_ulong);
00638         if (result != ISC_R_SUCCESS)
00639                 return (result);
00640 
00641         result = isc_hex_tobuffer(lexer, buf,
00642                                   (unsigned int)token.value.as_ulong);
00643         if (result != ISC_R_SUCCESS)
00644                goto failure;
00645         if (isc_buffer_usedlength(buf) != token.value.as_ulong) {
00646                 result = ISC_R_UNEXPECTEDEND;
00647                 goto failure;
00648         }
00649 
00650         if (dns_rdatatype_isknown(type)) {
00651                 result = rdata_validate(buf, target, rdclass, type);
00652         } else {
00653                 isc_region_t r;
00654                 isc_buffer_usedregion(buf, &r);
00655                 result = isc_buffer_copyregion(target, &r);
00656         }
00657         if (result != ISC_R_SUCCESS)
00658                 goto failure;
00659 
00660         isc_buffer_free(&buf);
00661         return (ISC_R_SUCCESS);
00662 
00663  failure:
00664         isc_buffer_free(&buf);
00665         return (result);
00666 }
00667 
00668 isc_result_t
00669 dns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
00670                    dns_rdatatype_t type, isc_lex_t *lexer,
00671                    dns_name_t *origin, unsigned int options, isc_mem_t *mctx,
00672                    isc_buffer_t *target, dns_rdatacallbacks_t *callbacks)
00673 {
00674         isc_result_t result = ISC_R_NOTIMPLEMENTED;
00675         isc_region_t region;
00676         isc_buffer_t st;
00677         isc_token_t token;
00678         unsigned int lexoptions = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF |
00679                                   ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE;
00680         char *name;
00681         unsigned long line;
00682         void (*callback)(dns_rdatacallbacks_t *, const char *, ...);
00683         isc_result_t tresult;
00684         unsigned int length;
00685         isc_boolean_t unknown;
00686 
00687         REQUIRE(origin == NULL || dns_name_isabsolute(origin) == ISC_TRUE);
00688         if (rdata != NULL) {
00689                 REQUIRE(DNS_RDATA_INITIALIZED(rdata));
00690                 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
00691         }
00692         if (callbacks != NULL) {
00693                 REQUIRE(callbacks->warn != NULL);
00694                 REQUIRE(callbacks->error != NULL);
00695         }
00696 
00697         st = *target;
00698 
00699         if (callbacks != NULL)
00700                 callback = callbacks->error;
00701         else
00702                 callback = default_fromtext_callback;
00703 
00704         result = isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
00705                                         ISC_FALSE);
00706         if (result != ISC_R_SUCCESS) {
00707                 name = isc_lex_getsourcename(lexer);
00708                 line = isc_lex_getsourceline(lexer);
00709                 fromtext_error(callback, callbacks, name, line, NULL, result);
00710                 return (result);
00711         }
00712 
00713         unknown = ISC_FALSE;
00714         if (token.type == isc_tokentype_string &&
00715             strcmp(DNS_AS_STR(token), "\\#") == 0) {
00716                 /*
00717                  * If this is a TXT record '\#' could be a escaped '#'.
00718                  * Look to see if the next token is a number and if so
00719                  * treat it as a unknown record format.
00720                  */
00721                 if (type == dns_rdatatype_txt) {
00722                         result = isc_lex_getmastertoken(lexer, &token,
00723                                                         isc_tokentype_number,
00724                                                         ISC_FALSE);
00725                         if (result == ISC_R_SUCCESS)
00726                                 isc_lex_ungettoken(lexer, &token);
00727                 }
00728 
00729                 if (result == ISC_R_SUCCESS) {
00730                         unknown = ISC_TRUE;
00731                         result = unknown_fromtext(rdclass, type, lexer,
00732                                                   mctx, target);
00733                 } else
00734                         options |= DNS_RDATA_UNKNOWNESCAPE;
00735         } else
00736                 isc_lex_ungettoken(lexer, &token);
00737 
00738         if (!unknown)
00739                 FROMTEXTSWITCH
00740 
00741         /*
00742          * Consume to end of line / file.
00743          * If not at end of line initially set error code.
00744          * Call callback via fromtext_error once if there was an error.
00745          */
00746         do {
00747                 name = isc_lex_getsourcename(lexer);
00748                 line = isc_lex_getsourceline(lexer);
00749                 tresult = isc_lex_gettoken(lexer, lexoptions, &token);
00750                 if (tresult != ISC_R_SUCCESS) {
00751                         if (result == ISC_R_SUCCESS)
00752                                 result = tresult;
00753                         if (callback != NULL)
00754                                 fromtext_error(callback, callbacks, name,
00755                                                line, NULL, result);
00756                         break;
00757                 } else if (token.type != isc_tokentype_eol &&
00758                            token.type != isc_tokentype_eof) {
00759                         if (result == ISC_R_SUCCESS)
00760                                 result = DNS_R_EXTRATOKEN;
00761                         if (callback != NULL) {
00762                                 fromtext_error(callback, callbacks, name,
00763                                                line, &token, result);
00764                                 callback = NULL;
00765                         }
00766                 } else if (result != ISC_R_SUCCESS && callback != NULL) {
00767                         fromtext_error(callback, callbacks, name, line,
00768                                        &token, result);
00769                         break;
00770                 } else {
00771                         if (token.type == isc_tokentype_eof)
00772                                 fromtext_warneof(lexer, callbacks);
00773                         break;
00774                 }
00775         } while (1);
00776 
00777         length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st);
00778         if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH)
00779                 result = ISC_R_NOSPACE;
00780 
00781         if (rdata != NULL && result == ISC_R_SUCCESS) {
00782                 region.base = isc_buffer_used(&st);
00783                 region.length = length;
00784                 dns_rdata_fromregion(rdata, rdclass, type, &region);
00785         }
00786         if (result != ISC_R_SUCCESS) {
00787                 *target = st;
00788         }
00789         return (result);
00790 }
00791 
00792 static isc_result_t
00793 unknown_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
00794                isc_buffer_t *target)
00795 {
00796         isc_result_t result;
00797         char buf[sizeof("65535")];
00798         isc_region_t sr;
00799 
00800         strlcpy(buf, "\\# ", sizeof(buf));
00801         result = str_totext(buf, target);
00802         if (result != ISC_R_SUCCESS)
00803                 return (result);
00804 
00805         dns_rdata_toregion(rdata, &sr);
00806         INSIST(sr.length < 65536);
00807         snprintf(buf, sizeof(buf), "%u", sr.length);
00808         result = str_totext(buf, target);
00809         if (result != ISC_R_SUCCESS)
00810                 return (result);
00811 
00812         if (sr.length != 0U) {
00813                 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
00814                         result = str_totext(" ( ", target);
00815                 else
00816                         result = str_totext(" ", target);
00817 
00818                 if (result != ISC_R_SUCCESS)
00819                         return (result);
00820 
00821                 if (tctx->width == 0) /* No splitting */
00822                         result = isc_hex_totext(&sr, 0, "", target);
00823                 else
00824                         result = isc_hex_totext(&sr, tctx->width - 2,
00825                                                 tctx->linebreak,
00826                                                 target);
00827                 if (result == ISC_R_SUCCESS &&
00828                     (tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
00829                         result = str_totext(" )", target);
00830         }
00831         return (result);
00832 }
00833 
00834 static isc_result_t
00835 rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
00836              isc_buffer_t *target)
00837 {
00838         isc_result_t result = ISC_R_NOTIMPLEMENTED;
00839         isc_boolean_t use_default = ISC_FALSE;
00840 
00841         REQUIRE(rdata != NULL);
00842         REQUIRE(tctx->origin == NULL ||
00843                 dns_name_isabsolute(tctx->origin) == ISC_TRUE);
00844 
00845         /*
00846          * Some DynDNS meta-RRs have empty rdata.
00847          */
00848         if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
00849                 INSIST(rdata->length == 0);
00850                 return (ISC_R_SUCCESS);
00851         }
00852 
00853         TOTEXTSWITCH
00854 
00855         if (use_default)
00856                 result = unknown_totext(rdata, tctx, target);
00857 
00858         return (result);
00859 }
00860 
00861 isc_result_t
00862 dns_rdata_totext(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target)
00863 {
00864         dns_rdata_textctx_t tctx;
00865 
00866         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
00867 
00868         /*
00869          * Set up formatting options for single-line output.
00870          */
00871         tctx.origin = origin;
00872         tctx.flags = 0;
00873         tctx.width = 60;
00874         tctx.linebreak = " ";
00875         return (rdata_totext(rdata, &tctx, target));
00876 }
00877 
00878 isc_result_t
00879 dns_rdata_tofmttext(dns_rdata_t *rdata, dns_name_t *origin,
00880                     unsigned int flags, unsigned int width,
00881                     unsigned int split_width, const char *linebreak,
00882                     isc_buffer_t *target)
00883 {
00884         dns_rdata_textctx_t tctx;
00885 
00886         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
00887 
00888         /*
00889          * Set up formatting options for formatted output.
00890          */
00891         tctx.origin = origin;
00892         tctx.flags = flags;
00893         if (split_width == 0xffffffff)
00894                 tctx.width = width;
00895         else
00896                 tctx.width = split_width;
00897 
00898         if ((flags & DNS_STYLEFLAG_MULTILINE) != 0)
00899                 tctx.linebreak = linebreak;
00900         else {
00901                 if (split_width == 0xffffffff)
00902                         tctx.width = 60; /* Used for hex word length only. */
00903                 tctx.linebreak = " ";
00904         }
00905         return (rdata_totext(rdata, &tctx, target));
00906 }
00907 
00908 isc_result_t
00909 dns_rdata_fromstruct(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
00910                      dns_rdatatype_t type, void *source,
00911                      isc_buffer_t *target)
00912 {
00913         isc_result_t result = ISC_R_NOTIMPLEMENTED;
00914         isc_buffer_t st;
00915         isc_region_t region;
00916         isc_boolean_t use_default = ISC_FALSE;
00917         unsigned int length;
00918 
00919         REQUIRE(source != NULL);
00920         if (rdata != NULL) {
00921                 REQUIRE(DNS_RDATA_INITIALIZED(rdata));
00922                 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
00923         }
00924 
00925         st = *target;
00926 
00927         FROMSTRUCTSWITCH
00928 
00929         if (use_default)
00930                 (void)NULL;
00931 
00932         length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st);
00933         if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH)
00934                 result = ISC_R_NOSPACE;
00935 
00936         if (rdata != NULL && result == ISC_R_SUCCESS) {
00937                 region.base = isc_buffer_used(&st);
00938                 region.length = length;
00939                 dns_rdata_fromregion(rdata, rdclass, type, &region);
00940         }
00941         if (result != ISC_R_SUCCESS)
00942                 *target = st;
00943         return (result);
00944 }
00945 
00946 isc_result_t
00947 dns_rdata_tostruct(dns_rdata_t *rdata, void *target, isc_mem_t *mctx) {
00948         isc_result_t result = ISC_R_NOTIMPLEMENTED;
00949         isc_boolean_t use_default = ISC_FALSE;
00950 
00951         REQUIRE(rdata != NULL);
00952         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
00953 
00954         TOSTRUCTSWITCH
00955 
00956         if (use_default)
00957                 (void)NULL;
00958 
00959         return (result);
00960 }
00961 
00962 void
00963 dns_rdata_freestruct(void *source) {
00964         dns_rdatacommon_t *common = source;
00965         REQUIRE(source != NULL);
00966 
00967         FREESTRUCTSWITCH
00968 }
00969 
00970 isc_result_t
00971 dns_rdata_additionaldata(dns_rdata_t *rdata, dns_additionaldatafunc_t add,
00972                          void *arg)
00973 {
00974         isc_result_t result = ISC_R_NOTIMPLEMENTED;
00975         isc_boolean_t use_default = ISC_FALSE;
00976 
00977         /*
00978          * Call 'add' for each name and type from 'rdata' which is subject to
00979          * additional section processing.
00980          */
00981 
00982         REQUIRE(rdata != NULL);
00983         REQUIRE(add != NULL);
00984         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
00985 
00986         ADDITIONALDATASWITCH
00987 
00988         /* No additional processing for unknown types */
00989         if (use_default)
00990                 result = ISC_R_SUCCESS;
00991 
00992         return (result);
00993 }
00994 
00995 isc_result_t
00996 dns_rdata_digest(dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg) {
00997         isc_result_t result = ISC_R_NOTIMPLEMENTED;
00998         isc_boolean_t use_default = ISC_FALSE;
00999         isc_region_t r;
01000 
01001         /*
01002          * Send 'rdata' in DNSSEC canonical form to 'digest'.
01003          */
01004 
01005         REQUIRE(rdata != NULL);
01006         REQUIRE(digest != NULL);
01007         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
01008 
01009         DIGESTSWITCH
01010 
01011         if (use_default) {
01012                 dns_rdata_toregion(rdata, &r);
01013                 result = (digest)(arg, &r);
01014         }
01015 
01016         return (result);
01017 }
01018 
01019 isc_boolean_t
01020 dns_rdata_checkowner(dns_name_t *name, dns_rdataclass_t rdclass,
01021                      dns_rdatatype_t type, isc_boolean_t wildcard)
01022 {
01023         isc_boolean_t result;
01024 
01025         CHECKOWNERSWITCH
01026         return (result);
01027 }
01028 
01029 isc_boolean_t
01030 dns_rdata_checknames(dns_rdata_t *rdata, dns_name_t *owner, dns_name_t *bad)
01031 {
01032         isc_boolean_t result;
01033 
01034         CHECKNAMESSWITCH
01035         return (result);
01036 }
01037 
01038 unsigned int
01039 dns_rdatatype_attributes(dns_rdatatype_t type)
01040 {
01041         RDATATYPE_ATTRIBUTE_SW
01042         return (DNS_RDATATYPEATTR_UNKNOWN);
01043 }
01044 
01045 isc_result_t
01046 dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source) {
01047         unsigned int hash;
01048         unsigned int n;
01049         unsigned char a, b;
01050 
01051         n = source->length;
01052 
01053         if (n == 0)
01054                 return (DNS_R_UNKNOWN);
01055 
01056         a = tolower((unsigned char)source->base[0]);
01057         b = tolower((unsigned char)source->base[n - 1]);
01058 
01059         hash = ((a + n) * b) % 256;
01060 
01061         /*
01062          * This switch block is inlined via \#define, and will use "return"
01063          * to return a result to the caller if it is a valid (known)
01064          * rdatatype name.
01065          */
01066         RDATATYPE_FROMTEXT_SW(hash, source->base, n, typep);
01067 
01068         if (source->length > 4 && source->length < (4 + sizeof("65000")) &&
01069             strncasecmp("type", source->base, 4) == 0) {
01070                 char buf[sizeof("65000")];
01071                 char *endp;
01072                 unsigned int val;
01073 
01074                 strncpy(buf, source->base + 4, source->length - 4);
01075                 buf[source->length - 4] = '\0';
01076                 val = strtoul(buf, &endp, 10);
01077                 if (*endp == '\0' && val <= 0xffff) {
01078                         *typep = (dns_rdatatype_t)val;
01079                         return (ISC_R_SUCCESS);
01080                 }
01081         }
01082 
01083         return (DNS_R_UNKNOWN);
01084 }
01085 
01086 isc_result_t
01087 dns_rdatatype_totext(dns_rdatatype_t type, isc_buffer_t *target) {
01088         char buf[sizeof("TYPE65535")];
01089 
01090         RDATATYPE_TOTEXT_SW
01091         snprintf(buf, sizeof(buf), "TYPE%u", type);
01092         return (str_totext(buf, target));
01093 }
01094 
01095 void
01096 dns_rdatatype_format(dns_rdatatype_t rdtype,
01097                      char *array, unsigned int size)
01098 {
01099         isc_result_t result;
01100         isc_buffer_t buf;
01101 
01102         if (size == 0U)
01103                 return;
01104 
01105         isc_buffer_init(&buf, array, size);
01106         result = dns_rdatatype_totext(rdtype, &buf);
01107         /*
01108          * Null terminate.
01109          */
01110         if (result == ISC_R_SUCCESS) {
01111                 if (isc_buffer_availablelength(&buf) >= 1)
01112                         isc_buffer_putuint8(&buf, 0);
01113                 else
01114                         result = ISC_R_NOSPACE;
01115         }
01116         if (result != ISC_R_SUCCESS)
01117                 strlcpy(array, "<unknown>", size);
01118 }
01119 
01120 /*
01121  * Private function.
01122  */
01123 
01124 static unsigned int
01125 name_length(dns_name_t *name) {
01126         return (name->length);
01127 }
01128 
01129 static isc_result_t
01130 txt_totext(isc_region_t *source, isc_boolean_t quote, isc_buffer_t *target) {
01131         unsigned int tl;
01132         unsigned int n;
01133         unsigned char *sp;
01134         char *tp;
01135         isc_region_t region;
01136 
01137         isc_buffer_availableregion(target, &region);
01138         sp = source->base;
01139         tp = (char *)region.base;
01140         tl = region.length;
01141 
01142         n = *sp++;
01143 
01144         REQUIRE(n + 1 <= source->length);
01145         if (n == 0U)
01146                 REQUIRE(quote == ISC_TRUE);
01147 
01148         if (quote) {
01149                 if (tl < 1)
01150                         return (ISC_R_NOSPACE);
01151                 *tp++ = '"';
01152                 tl--;
01153         }
01154         while (n--) {
01155                 /*
01156                  * \DDD space (0x20) if not quoting.
01157                  */
01158                 if (*sp < (quote ? 0x20 : 0x21) || *sp >= 0x7f) {
01159                         if (tl < 4)
01160                                 return (ISC_R_NOSPACE);
01161                         *tp++ = 0x5c;
01162                         *tp++ = 0x30 + ((*sp / 100) % 10);
01163                         *tp++ = 0x30 + ((*sp / 10) % 10);
01164                         *tp++ = 0x30 + (*sp % 10);
01165                         sp++;
01166                         tl -= 4;
01167                         continue;
01168                 }
01169                 /*
01170                  * Escape double quote and backslash.  If we are not
01171                  * enclosing the string in double quotes also escape
01172                  * at sign and semicolon.
01173                  */
01174                 if (*sp == 0x22 || *sp == 0x5c ||
01175                     (!quote && (*sp == 0x40 || *sp == 0x3b))) {
01176                         if (tl < 2)
01177                                 return (ISC_R_NOSPACE);
01178                         *tp++ = '\\';
01179                         tl--;
01180                 }
01181                 if (tl < 1)
01182                         return (ISC_R_NOSPACE);
01183                 *tp++ = *sp++;
01184                 tl--;
01185         }
01186         if (quote) {
01187                 if (tl < 1)
01188                         return (ISC_R_NOSPACE);
01189                 *tp++ = '"';
01190                 tl--;
01191         }
01192         isc_buffer_add(target, (unsigned int)(tp - (char *)region.base));
01193         isc_region_consume(source, *source->base + 1);
01194         return (ISC_R_SUCCESS);
01195 }
01196 
01197 static isc_result_t
01198 txt_fromtext(isc_textregion_t *source, isc_buffer_t *target) {
01199         isc_region_t tregion;
01200         isc_boolean_t escape;
01201         unsigned int n, nrem;
01202         char *s;
01203         unsigned char *t;
01204         int d;
01205         int c;
01206 
01207         isc_buffer_availableregion(target, &tregion);
01208         s = source->base;
01209         n = source->length;
01210         t = tregion.base;
01211         nrem = tregion.length;
01212         escape = ISC_FALSE;
01213         if (nrem < 1)
01214                 return (ISC_R_NOSPACE);
01215         /*
01216          * Length byte.
01217          */
01218         nrem--;
01219         t++;
01220         /*
01221          * Maximum text string length.
01222          */
01223         if (nrem > 255)
01224                 nrem = 255;
01225         while (n-- != 0) {
01226                 c = (*s++) & 0xff;
01227                 if (escape && (d = decvalue((char)c)) != -1) {
01228                         c = d;
01229                         if (n == 0)
01230                                 return (DNS_R_SYNTAX);
01231                         n--;
01232                         if ((d = decvalue(*s++)) != -1)
01233                                 c = c * 10 + d;
01234                         else
01235                                 return (DNS_R_SYNTAX);
01236                         if (n == 0)
01237                                 return (DNS_R_SYNTAX);
01238                         n--;
01239                         if ((d = decvalue(*s++)) != -1)
01240                                 c = c * 10 + d;
01241                         else
01242                                 return (DNS_R_SYNTAX);
01243                         if (c > 255)
01244                                 return (DNS_R_SYNTAX);
01245                 } else if (!escape && c == '\\') {
01246                         escape = ISC_TRUE;
01247                         continue;
01248                 }
01249                 escape = ISC_FALSE;
01250                 if (nrem == 0)
01251                         return ((tregion.length <= 256U) ?
01252                                 ISC_R_NOSPACE : DNS_R_SYNTAX);
01253                 *t++ = c;
01254                 nrem--;
01255         }
01256         if (escape)
01257                 return (DNS_R_SYNTAX);
01258         *tregion.base = (unsigned char)(t - tregion.base - 1);
01259         isc_buffer_add(target, *tregion.base + 1);
01260         return (ISC_R_SUCCESS);
01261 }
01262 
01263 static isc_result_t
01264 txt_fromwire(isc_buffer_t *source, isc_buffer_t *target) {
01265         unsigned int n;
01266         isc_region_t sregion;
01267         isc_region_t tregion;
01268 
01269         isc_buffer_activeregion(source, &sregion);
01270         if (sregion.length == 0)
01271                 return(ISC_R_UNEXPECTEDEND);
01272         n = *sregion.base + 1;
01273         if (n > sregion.length)
01274                 return (ISC_R_UNEXPECTEDEND);
01275 
01276         isc_buffer_availableregion(target, &tregion);
01277         if (n > tregion.length)
01278                 return (ISC_R_NOSPACE);
01279 
01280         if (tregion.base != sregion.base)
01281                 memmove(tregion.base, sregion.base, n);
01282         isc_buffer_forward(source, n);
01283         isc_buffer_add(target, n);
01284         return (ISC_R_SUCCESS);
01285 }
01286 
01287 /*
01288  * Conversion of TXT-like rdata fields without length limits.
01289  */
01290 static isc_result_t
01291 multitxt_totext(isc_region_t *source, isc_buffer_t *target) {
01292         unsigned int tl;
01293         unsigned int n0, n;
01294         unsigned char *sp;
01295         char *tp;
01296         isc_region_t region;
01297 
01298         isc_buffer_availableregion(target, &region);
01299         sp = source->base;
01300         tp = (char *)region.base;
01301         tl = region.length;
01302 
01303         if (tl < 1)
01304                 return (ISC_R_NOSPACE);
01305         *tp++ = '"';
01306         tl--;
01307         do {
01308                 n = source->length;
01309                 n0 = source->length - 1;
01310 
01311                 while (n--) {
01312                         if (*sp < 0x20 || *sp >= 0x7f) {
01313                                 if (tl < 4)
01314                                         return (ISC_R_NOSPACE);
01315                                 *tp++ = 0x5c;
01316                                 *tp++ = 0x30 + ((*sp / 100) % 10);
01317                                 *tp++ = 0x30 + ((*sp / 10) % 10);
01318                                 *tp++ = 0x30 + (*sp % 10);
01319                                 sp++;
01320                                 tl -= 4;
01321                                 continue;
01322                         }
01323                         /* double quote, semi-colon, backslash */
01324                         if (*sp == 0x22 || *sp == 0x3b || *sp == 0x5c) {
01325                                 if (tl < 2)
01326                                         return (ISC_R_NOSPACE);
01327                                 *tp++ = '\\';
01328                                 tl--;
01329                         }
01330                         if (tl < 1)
01331                                 return (ISC_R_NOSPACE);
01332                         *tp++ = *sp++;
01333                         tl--;
01334                 }
01335                 isc_region_consume(source, n0 + 1);
01336         } while (source->length != 0);
01337         if (tl < 1)
01338                 return (ISC_R_NOSPACE);
01339         *tp++ = '"';
01340         tl--;
01341         isc_buffer_add(target, (unsigned int)(tp - (char *)region.base));
01342         return (ISC_R_SUCCESS);
01343 }
01344 
01345 static isc_result_t
01346 multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target) {
01347         isc_region_t tregion;
01348         isc_boolean_t escape;
01349         unsigned int n, nrem;
01350         char *s;
01351         unsigned char *t0, *t;
01352         int d;
01353         int c;
01354 
01355         s = source->base;
01356         n = source->length;
01357         escape = ISC_FALSE;
01358 
01359         do {
01360                 isc_buffer_availableregion(target, &tregion);
01361                 t0 = t = tregion.base;
01362                 nrem = tregion.length;
01363                 if (nrem < 1)
01364                         return (ISC_R_NOSPACE);
01365 
01366                 while (n != 0) {
01367                         --n;
01368                         c = (*s++) & 0xff;
01369                         if (escape && (d = decvalue((char)c)) != -1) {
01370                                 c = d;
01371                                 if (n == 0)
01372                                         return (DNS_R_SYNTAX);
01373                                 n--;
01374                                 if ((d = decvalue(*s++)) != -1)
01375                                         c = c * 10 + d;
01376                                 else
01377                                         return (DNS_R_SYNTAX);
01378                                 if (n == 0)
01379                                         return (DNS_R_SYNTAX);
01380                                 n--;
01381                                 if ((d = decvalue(*s++)) != -1)
01382                                         c = c * 10 + d;
01383                                 else
01384                                         return (DNS_R_SYNTAX);
01385                                 if (c > 255)
01386                                         return (DNS_R_SYNTAX);
01387                         } else if (!escape && c == '\\') {
01388                                 escape = ISC_TRUE;
01389                                 continue;
01390                         }
01391                         escape = ISC_FALSE;
01392                         *t++ = c;
01393                         nrem--;
01394                         if (nrem == 0)
01395                                 break;
01396                 }
01397                 if (escape)
01398                         return (DNS_R_SYNTAX);
01399 
01400                 isc_buffer_add(target, (unsigned int)(t - t0));
01401         } while (n != 0);
01402         return (ISC_R_SUCCESS);
01403 }
01404 
01405 static isc_boolean_t
01406 name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target) {
01407         int l1, l2;
01408 
01409         if (origin == NULL)
01410                 goto return_false;
01411 
01412         if (dns_name_compare(origin, dns_rootname) == 0)
01413                 goto return_false;
01414 
01415         if (!dns_name_issubdomain(name, origin))
01416                 goto return_false;
01417 
01418         l1 = dns_name_countlabels(name);
01419         l2 = dns_name_countlabels(origin);
01420 
01421         if (l1 == l2)
01422                 goto return_false;
01423 
01424         /* Master files should be case preserving. */
01425         dns_name_getlabelsequence(name, l1 - l2, l2, target);
01426         if (!dns_name_caseequal(origin, target))
01427                 goto return_false;
01428 
01429         dns_name_getlabelsequence(name, 0, l1 - l2, target);
01430         return (ISC_TRUE);
01431 
01432 return_false:
01433         *target = *name;
01434         return (ISC_FALSE);
01435 }
01436 
01437 static isc_result_t
01438 str_totext(const char *source, isc_buffer_t *target) {
01439         unsigned int l;
01440         isc_region_t region;
01441 
01442         isc_buffer_availableregion(target, &region);
01443         l = strlen(source);
01444 
01445         if (l > region.length)
01446                 return (ISC_R_NOSPACE);
01447 
01448         memmove(region.base, source, l);
01449         isc_buffer_add(target, l);
01450         return (ISC_R_SUCCESS);
01451 }
01452 
01453 static isc_result_t
01454 inet_totext(int af, isc_region_t *src, isc_buffer_t *target) {
01455         char tmpbuf[64];
01456 
01457         /* Note - inet_ntop doesn't do size checking on its input. */
01458         if (inet_ntop(af, src->base, tmpbuf, sizeof(tmpbuf)) == NULL)
01459                 return (ISC_R_NOSPACE);
01460         if (strlen(tmpbuf) > isc_buffer_availablelength(target))
01461                 return (ISC_R_NOSPACE);
01462         isc_buffer_putstr(target, tmpbuf);
01463         return (ISC_R_SUCCESS);
01464 }
01465 
01466 static isc_boolean_t
01467 buffer_empty(isc_buffer_t *source) {
01468         return((source->current == source->active) ? ISC_TRUE : ISC_FALSE);
01469 }
01470 
01471 static void
01472 buffer_fromregion(isc_buffer_t *buffer, isc_region_t *region) {
01473         isc_buffer_init(buffer, region->base, region->length);
01474         isc_buffer_add(buffer, region->length);
01475         isc_buffer_setactive(buffer, region->length);
01476 }
01477 
01478 static isc_result_t
01479 uint32_tobuffer(isc_uint32_t value, isc_buffer_t *target) {
01480         isc_region_t region;
01481 
01482         isc_buffer_availableregion(target, &region);
01483         if (region.length < 4)
01484                 return (ISC_R_NOSPACE);
01485         isc_buffer_putuint32(target, value);
01486         return (ISC_R_SUCCESS);
01487 }
01488 
01489 static isc_result_t
01490 uint16_tobuffer(isc_uint32_t value, isc_buffer_t *target) {
01491         isc_region_t region;
01492 
01493         if (value > 0xffff)
01494                 return (ISC_R_RANGE);
01495         isc_buffer_availableregion(target, &region);
01496         if (region.length < 2)
01497                 return (ISC_R_NOSPACE);
01498         isc_buffer_putuint16(target, (isc_uint16_t)value);
01499         return (ISC_R_SUCCESS);
01500 }
01501 
01502 static isc_result_t
01503 uint8_tobuffer(isc_uint32_t value, isc_buffer_t *target) {
01504         isc_region_t region;
01505 
01506         if (value > 0xff)
01507                 return (ISC_R_RANGE);
01508         isc_buffer_availableregion(target, &region);
01509         if (region.length < 1)
01510                 return (ISC_R_NOSPACE);
01511         isc_buffer_putuint8(target, (isc_uint8_t)value);
01512         return (ISC_R_SUCCESS);
01513 }
01514 
01515 static isc_result_t
01516 name_tobuffer(dns_name_t *name, isc_buffer_t *target) {
01517         isc_region_t r;
01518         dns_name_toregion(name, &r);
01519         return (isc_buffer_copyregion(target, &r));
01520 }
01521 
01522 static isc_uint32_t
01523 uint32_fromregion(isc_region_t *region) {
01524         isc_uint32_t value;
01525 
01526         REQUIRE(region->length >= 4);
01527         value = region->base[0] << 24;
01528         value |= region->base[1] << 16;
01529         value |= region->base[2] << 8;
01530         value |= region->base[3];
01531         return(value);
01532 }
01533 
01534 static isc_uint16_t
01535 uint16_consume_fromregion(isc_region_t *region) {
01536         isc_uint16_t r = uint16_fromregion(region);
01537 
01538         isc_region_consume(region, 2);
01539         return r;
01540 }
01541 
01542 static isc_uint16_t
01543 uint16_fromregion(isc_region_t *region) {
01544 
01545         REQUIRE(region->length >= 2);
01546 
01547         return ((region->base[0] << 8) | region->base[1]);
01548 }
01549 
01550 static isc_uint8_t
01551 uint8_fromregion(isc_region_t *region) {
01552 
01553         REQUIRE(region->length >= 1);
01554 
01555         return (region->base[0]);
01556 }
01557 
01558 static isc_uint8_t
01559 uint8_consume_fromregion(isc_region_t *region) {
01560         isc_uint8_t r = uint8_fromregion(region);
01561 
01562         isc_region_consume(region, 1);
01563         return r;
01564 }
01565 
01566 static isc_result_t
01567 mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
01568         isc_region_t tr;
01569 
01570         isc_buffer_availableregion(target, &tr);
01571         if (length > tr.length)
01572                 return (ISC_R_NOSPACE);
01573         if (tr.base != base)
01574                 memmove(tr.base, base, length);
01575         isc_buffer_add(target, length);
01576         return (ISC_R_SUCCESS);
01577 }
01578 
01579 static int
01580 hexvalue(char value) {
01581         char *s;
01582         unsigned char c;
01583 
01584         c = (unsigned char)value;
01585 
01586         if (!isascii(c))
01587                 return (-1);
01588         if (isupper(c))
01589                 c = tolower(c);
01590         if ((s = strchr(hexdigits, c)) == NULL)
01591                 return (-1);
01592         return (int)(s - hexdigits);
01593 }
01594 
01595 static int
01596 decvalue(char value) {
01597         char *s;
01598 
01599         /*
01600          * isascii() is valid for full range of int values, no need to
01601          * mask or cast.
01602          */
01603         if (!isascii(value))
01604                 return (-1);
01605         if ((s = strchr(decdigits, value)) == NULL)
01606                 return (-1);
01607         return (int)(s - decdigits);
01608 }
01609 
01610 static const char atob_digits[86] =
01611         "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" \
01612         "abcdefghijklmnopqrstu";
01613 /*
01614  * Subroutines to convert between 8 bit binary bytes and printable ASCII.
01615  * Computes the number of bytes, and three kinds of simple checksums.
01616  * Incoming bytes are collected into 32-bit words, then printed in base 85:
01617  *      exp(85,5) > exp(2,32)
01618  * The ASCII characters used are between '!' and 'u';
01619  * 'z' encodes 32-bit zero; 'x' is used to mark the end of encoded data.
01620  *
01621  * Originally by Paul Rutter (philabs!per) and Joe Orost (petsd!joe) for
01622  * the atob/btoa programs, released with the compress program, in mod.sources.
01623  * Modified by Mike Schwartz 8/19/86 for use in BIND.
01624  * Modified to be re-entrant 3/2/99.
01625  */
01626 
01627 
01628 struct state {
01629         isc_int32_t Ceor;
01630         isc_int32_t Csum;
01631         isc_int32_t Crot;
01632         isc_int32_t word;
01633         isc_int32_t bcount;
01634 };
01635 
01636 #define Ceor state->Ceor
01637 #define Csum state->Csum
01638 #define Crot state->Crot
01639 #define word state->word
01640 #define bcount state->bcount
01641 
01642 #define times85(x)      ((((((x<<2)+x)<<2)+x)<<2)+x)
01643 
01644 static isc_result_t     byte_atob(int c, isc_buffer_t *target,
01645                                   struct state *state);
01646 static isc_result_t     putbyte(int c, isc_buffer_t *, struct state *state);
01647 static isc_result_t     byte_btoa(int c, isc_buffer_t *, struct state *state);
01648 
01649 /*
01650  * Decode ASCII-encoded byte c into binary representation and
01651  * place into *bufp, advancing bufp.
01652  */
01653 static isc_result_t
01654 byte_atob(int c, isc_buffer_t *target, struct state *state) {
01655         char *s;
01656         if (c == 'z') {
01657                 if (bcount != 0)
01658                         return(DNS_R_SYNTAX);
01659                 else {
01660                         RETERR(putbyte(0, target, state));
01661                         RETERR(putbyte(0, target, state));
01662                         RETERR(putbyte(0, target, state));
01663                         RETERR(putbyte(0, target, state));
01664                 }
01665         } else if ((s = strchr(atob_digits, c)) != NULL) {
01666                 if (bcount == 0) {
01667                         word = (isc_int32_t)(s - atob_digits);
01668                         ++bcount;
01669                 } else if (bcount < 4) {
01670                         word = times85(word);
01671                         word += (isc_int32_t)(s - atob_digits);
01672                         ++bcount;
01673                 } else {
01674                         word = times85(word);
01675                         word += (isc_int32_t)(s - atob_digits);
01676                         RETERR(putbyte((word >> 24) & 0xff, target, state));
01677                         RETERR(putbyte((word >> 16) & 0xff, target, state));
01678                         RETERR(putbyte((word >> 8) & 0xff, target, state));
01679                         RETERR(putbyte(word & 0xff, target, state));
01680                         word = 0;
01681                         bcount = 0;
01682                 }
01683         } else
01684                 return(DNS_R_SYNTAX);
01685         return(ISC_R_SUCCESS);
01686 }
01687 
01688 /*
01689  * Compute checksum info and place c into target.
01690  */
01691 static isc_result_t
01692 putbyte(int c, isc_buffer_t *target, struct state *state) {
01693         isc_region_t tr;
01694 
01695         Ceor ^= c;
01696         Csum += c;
01697         Csum += 1;
01698         if ((Crot & 0x80000000)) {
01699                 Crot <<= 1;
01700                 Crot += 1;
01701         } else {
01702                 Crot <<= 1;
01703         }
01704         Crot += c;
01705         isc_buffer_availableregion(target, &tr);
01706         if (tr.length < 1)
01707                 return (ISC_R_NOSPACE);
01708         tr.base[0] = c;
01709         isc_buffer_add(target, 1);
01710         return (ISC_R_SUCCESS);
01711 }
01712 
01713 /*
01714  * Read the ASCII-encoded data from inbuf, of length inbuflen, and convert
01715  * it into T_UNSPEC (binary data) in outbuf, not to exceed outbuflen bytes;
01716  * outbuflen must be divisible by 4.  (Note: this is because outbuf is filled
01717  * in 4 bytes at a time.  If the actual data doesn't end on an even 4-byte
01718  * boundary, there will be no problem...it will be padded with 0 bytes, and
01719  * numbytes will indicate the correct number of bytes.  The main point is
01720  * that since the buffer is filled in 4 bytes at a time, even if there is
01721  * not a full 4 bytes of data at the end, there has to be room to 0-pad the
01722  * data, so the buffer must be of size divisible by 4).  Place the number of
01723  * output bytes in numbytes, and return a failure/success status.
01724  */
01725 
01726 static isc_result_t
01727 atob_tobuffer(isc_lex_t *lexer, isc_buffer_t *target) {
01728         long oeor, osum, orot;
01729         struct state statebuf, *state= &statebuf;
01730         isc_token_t token;
01731         char c;
01732         char *e;
01733 
01734         Ceor = Csum = Crot = word = bcount = 0;
01735 
01736         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
01737                                       ISC_FALSE));
01738         while (token.value.as_textregion.length != 0) {
01739                 if ((c = token.value.as_textregion.base[0]) == 'x') {
01740                         break;
01741                 } else
01742                         RETERR(byte_atob(c, target, state));
01743                 isc_textregion_consume(&token.value.as_textregion, 1);
01744         }
01745 
01746         /*
01747          * Number of bytes.
01748          */
01749         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
01750                                       ISC_FALSE));
01751         if ((token.value.as_ulong % 4) != 0U)
01752                 isc_buffer_subtract(target,  4 - (token.value.as_ulong % 4));
01753 
01754         /*
01755          * Checksum.
01756          */
01757         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
01758                                       ISC_FALSE));
01759         oeor = strtol(DNS_AS_STR(token), &e, 16);
01760         if (*e != 0)
01761                 return (DNS_R_SYNTAX);
01762 
01763         /*
01764          * Checksum.
01765          */
01766         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
01767                                       ISC_FALSE));
01768         osum = strtol(DNS_AS_STR(token), &e, 16);
01769         if (*e != 0)
01770                 return (DNS_R_SYNTAX);
01771 
01772         /*
01773          * Checksum.
01774          */
01775         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
01776                                       ISC_FALSE));
01777         orot = strtol(DNS_AS_STR(token), &e, 16);
01778         if (*e != 0)
01779                 return (DNS_R_SYNTAX);
01780 
01781         if ((oeor != Ceor) || (osum != Csum) || (orot != Crot))
01782                 return(DNS_R_BADCKSUM);
01783         return (ISC_R_SUCCESS);
01784 }
01785 
01786 /*
01787  * Encode binary byte c into ASCII representation and place into *bufp,
01788  * advancing bufp.
01789  */
01790 static isc_result_t
01791 byte_btoa(int c, isc_buffer_t *target, struct state *state) {
01792         isc_region_t tr;
01793 
01794         isc_buffer_availableregion(target, &tr);
01795         Ceor ^= c;
01796         Csum += c;
01797         Csum += 1;
01798         if ((Crot & 0x80000000)) {
01799                 Crot <<= 1;
01800                 Crot += 1;
01801         } else {
01802                 Crot <<= 1;
01803         }
01804         Crot += c;
01805 
01806         word <<= 8;
01807         word |= c;
01808         if (bcount == 3) {
01809                 if (word == 0) {
01810                         if (tr.length < 1)
01811                                 return (ISC_R_NOSPACE);
01812                         tr.base[0] = 'z';
01813                         isc_buffer_add(target, 1);
01814                 } else {
01815                     register int tmp = 0;
01816                     register isc_int32_t tmpword = word;
01817 
01818                     if (tmpword < 0) {
01819                            /*
01820                             * Because some don't support u_long.
01821                             */
01822                         tmp = 32;
01823                         tmpword -= (isc_int32_t)(85 * 85 * 85 * 85 * 32);
01824                     }
01825                     if (tmpword < 0) {
01826                         tmp = 64;
01827                         tmpword -= (isc_int32_t)(85 * 85 * 85 * 85 * 32);
01828                     }
01829                         if (tr.length < 5)
01830                                 return (ISC_R_NOSPACE);
01831                         tr.base[0] = atob_digits[(tmpword /
01832                                               (isc_int32_t)(85 * 85 * 85 * 85))
01833                                                 + tmp];
01834                         tmpword %= (isc_int32_t)(85 * 85 * 85 * 85);
01835                         tr.base[1] = atob_digits[tmpword / (85 * 85 * 85)];
01836                         tmpword %= (85 * 85 * 85);
01837                         tr.base[2] = atob_digits[tmpword / (85 * 85)];
01838                         tmpword %= (85 * 85);
01839                         tr.base[3] = atob_digits[tmpword / 85];
01840                         tmpword %= 85;
01841                         tr.base[4] = atob_digits[tmpword];
01842                         isc_buffer_add(target, 5);
01843                 }
01844                 bcount = 0;
01845         } else {
01846                 bcount += 1;
01847         }
01848         return (ISC_R_SUCCESS);
01849 }
01850 
01851 
01852 /*
01853  * Encode the binary data from inbuf, of length inbuflen, into a
01854  * target.  Return success/failure status
01855  */
01856 static isc_result_t
01857 btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target) {
01858         int inc;
01859         struct state statebuf, *state = &statebuf;
01860         char buf[sizeof("x 2000000000 ffffffff ffffffff ffffffff")];
01861 
01862         Ceor = Csum = Crot = word = bcount = 0;
01863         for (inc = 0; inc < inbuflen; inbuf++, inc++)
01864                 RETERR(byte_btoa(*inbuf, target, state));
01865 
01866         while (bcount != 0)
01867                 RETERR(byte_btoa(0, target, state));
01868 
01869         /*
01870          * Put byte count and checksum information at end of buffer,
01871          * delimited by 'x'
01872          */
01873         snprintf(buf, sizeof(buf), "x %d %x %x %x", inbuflen, Ceor, Csum, Crot);
01874         return (str_totext(buf, target));
01875 }
01876 
01877 
01878 static void
01879 default_fromtext_callback(dns_rdatacallbacks_t *callbacks, const char *fmt,
01880                           ...)
01881 {
01882         va_list ap;
01883 
01884         UNUSED(callbacks);
01885 
01886         va_start(ap, fmt);
01887         vfprintf(stderr, fmt, ap);
01888         va_end(ap);
01889         fprintf(stderr, "\n");
01890 }
01891 
01892 static void
01893 fromtext_warneof(isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks) {
01894         if (isc_lex_isfile(lexer) && callbacks != NULL) {
01895                 const char *name = isc_lex_getsourcename(lexer);
01896                 if (name == NULL)
01897                         name = "UNKNOWN";
01898                 (*callbacks->warn)(callbacks,
01899                                    "%s:%lu: file does not end with newline",
01900                                    name, isc_lex_getsourceline(lexer));
01901         }
01902 }
01903 
01904 static void
01905 warn_badmx(isc_token_t *token, isc_lex_t *lexer,
01906            dns_rdatacallbacks_t *callbacks)
01907 {
01908         const char *file;
01909         unsigned long line;
01910 
01911         if (lexer != NULL) {
01912                 file = isc_lex_getsourcename(lexer);
01913                 line = isc_lex_getsourceline(lexer);
01914                 (*callbacks->warn)(callbacks, "%s:%u: warning: '%s': %s",
01915                                    file, line, DNS_AS_STR(*token),
01916                                    dns_result_totext(DNS_R_MXISADDRESS));
01917         }
01918 }
01919 
01920 static void
01921 warn_badname(dns_name_t *name, isc_lex_t *lexer,
01922              dns_rdatacallbacks_t *callbacks)
01923 {
01924         const char *file;
01925         unsigned long line;
01926         char namebuf[DNS_NAME_FORMATSIZE];
01927 
01928         if (lexer != NULL) {
01929                 file = isc_lex_getsourcename(lexer);
01930                 line = isc_lex_getsourceline(lexer);
01931                 dns_name_format(name, namebuf, sizeof(namebuf));
01932                 (*callbacks->warn)(callbacks, "%s:%u: warning: %s: %s",
01933                                    file, line, namebuf,
01934                                    dns_result_totext(DNS_R_BADNAME));
01935         }
01936 }
01937 
01938 static void
01939 fromtext_error(void (*callback)(dns_rdatacallbacks_t *, const char *, ...),
01940                dns_rdatacallbacks_t *callbacks, const char *name,
01941                unsigned long line, isc_token_t *token, isc_result_t result)
01942 {
01943         if (name == NULL)
01944                 name = "UNKNOWN";
01945 
01946         if (token != NULL) {
01947                 switch (token->type) {
01948                 case isc_tokentype_eol:
01949                         (*callback)(callbacks, "%s: %s:%lu: near eol: %s",
01950                                     "dns_rdata_fromtext", name, line,
01951                                     dns_result_totext(result));
01952                         break;
01953                 case isc_tokentype_eof:
01954                         (*callback)(callbacks, "%s: %s:%lu: near eof: %s",
01955                                     "dns_rdata_fromtext", name, line,
01956                                     dns_result_totext(result));
01957                         break;
01958                 case isc_tokentype_number:
01959                         (*callback)(callbacks, "%s: %s:%lu: near %lu: %s",
01960                                     "dns_rdata_fromtext", name, line,
01961                                     token->value.as_ulong,
01962                                     dns_result_totext(result));
01963                         break;
01964                 case isc_tokentype_string:
01965                 case isc_tokentype_qstring:
01966                         (*callback)(callbacks, "%s: %s:%lu: near '%s': %s",
01967                                     "dns_rdata_fromtext", name, line,
01968                                     DNS_AS_STR(*token),
01969                                     dns_result_totext(result));
01970                         break;
01971                 default:
01972                         (*callback)(callbacks, "%s: %s:%lu: %s",
01973                                     "dns_rdata_fromtext", name, line,
01974                                     dns_result_totext(result));
01975                         break;
01976                 }
01977         } else {
01978                 (*callback)(callbacks, "dns_rdata_fromtext: %s:%lu: %s",
01979                             name, line, dns_result_totext(result));
01980         }
01981 }
01982 
01983 dns_rdatatype_t
01984 dns_rdata_covers(dns_rdata_t *rdata) {
01985         if (rdata->type == 46)
01986                 return (covers_rrsig(rdata));
01987         return (covers_sig(rdata));
01988 }
01989 
01990 isc_boolean_t
01991 dns_rdatatype_ismeta(dns_rdatatype_t type) {
01992         if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_META) != 0)
01993                 return (ISC_TRUE);
01994         return (ISC_FALSE);
01995 }
01996 
01997 isc_boolean_t
01998 dns_rdatatype_issingleton(dns_rdatatype_t type) {
01999         if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_SINGLETON)
02000             != 0)
02001                 return (ISC_TRUE);
02002         return (ISC_FALSE);
02003 }
02004 
02005 isc_boolean_t
02006 dns_rdatatype_notquestion(dns_rdatatype_t type) {
02007         if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_NOTQUESTION)
02008             != 0)
02009                 return (ISC_TRUE);
02010         return (ISC_FALSE);
02011 }
02012 
02013 isc_boolean_t
02014 dns_rdatatype_questiononly(dns_rdatatype_t type) {
02015         if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_QUESTIONONLY)
02016             != 0)
02017                 return (ISC_TRUE);
02018         return (ISC_FALSE);
02019 }
02020 
02021 isc_boolean_t
02022 dns_rdatatype_atparent(dns_rdatatype_t type) {
02023         if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_ATPARENT) != 0)
02024                 return (ISC_TRUE);
02025         return (ISC_FALSE);
02026 }
02027 
02028 isc_boolean_t
02029 dns_rdataclass_ismeta(dns_rdataclass_t rdclass) {
02030 
02031         if (rdclass == dns_rdataclass_reserved0
02032             || rdclass == dns_rdataclass_none
02033             || rdclass == dns_rdataclass_any)
02034                 return (ISC_TRUE);
02035 
02036         return (ISC_FALSE);  /* Assume it is not a meta class. */
02037 }
02038 
02039 isc_boolean_t
02040 dns_rdatatype_isdnssec(dns_rdatatype_t type) {
02041         if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_DNSSEC) != 0)
02042                 return (ISC_TRUE);
02043         return (ISC_FALSE);
02044 }
02045 
02046 isc_boolean_t
02047 dns_rdatatype_iszonecutauth(dns_rdatatype_t type) {
02048         if ((dns_rdatatype_attributes(type)
02049              & (DNS_RDATATYPEATTR_DNSSEC | DNS_RDATATYPEATTR_ZONECUTAUTH))
02050             != 0)
02051                 return (ISC_TRUE);
02052         return (ISC_FALSE);
02053 }
02054 
02055 isc_boolean_t
02056 dns_rdatatype_isknown(dns_rdatatype_t type) {
02057         if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_UNKNOWN)
02058             == 0)
02059                 return (ISC_TRUE);
02060         return (ISC_FALSE);
02061 }
02062 
02063 void
02064 dns_rdata_exists(dns_rdata_t *rdata, dns_rdatatype_t type) {
02065 
02066         REQUIRE(rdata != NULL);
02067         REQUIRE(DNS_RDATA_INITIALIZED(rdata));
02068 
02069         rdata->data = NULL;
02070         rdata->length = 0;
02071         rdata->flags = DNS_RDATA_UPDATE;
02072         rdata->type = type;
02073         rdata->rdclass = dns_rdataclass_any;
02074 }
02075 
02076 void
02077 dns_rdata_notexist(dns_rdata_t *rdata, dns_rdatatype_t type) {
02078 
02079         REQUIRE(rdata != NULL);
02080         REQUIRE(DNS_RDATA_INITIALIZED(rdata));
02081 
02082         rdata->data = NULL;
02083         rdata->length = 0;
02084         rdata->flags = DNS_RDATA_UPDATE;
02085         rdata->type = type;
02086         rdata->rdclass = dns_rdataclass_none;
02087 }
02088 
02089 void
02090 dns_rdata_deleterrset(dns_rdata_t *rdata, dns_rdatatype_t type) {
02091 
02092         REQUIRE(rdata != NULL);
02093         REQUIRE(DNS_RDATA_INITIALIZED(rdata));
02094 
02095         rdata->data = NULL;
02096         rdata->length = 0;
02097         rdata->flags = DNS_RDATA_UPDATE;
02098         rdata->type = type;
02099         rdata->rdclass = dns_rdataclass_any;
02100 }
02101 
02102 void
02103 dns_rdata_makedelete(dns_rdata_t *rdata) {
02104         REQUIRE(rdata != NULL);
02105 
02106         rdata->rdclass = dns_rdataclass_none;
02107 }
02108 
02109 const char *
02110 dns_rdata_updateop(dns_rdata_t *rdata, dns_section_t section) {
02111 
02112         REQUIRE(rdata != NULL);
02113         REQUIRE(DNS_RDATA_INITIALIZED(rdata));
02114 
02115         switch (section) {
02116         case DNS_SECTION_PREREQUISITE:
02117                 switch (rdata->rdclass) {
02118                 case dns_rdataclass_none:
02119                         switch (rdata->type) {
02120                         case dns_rdatatype_any:
02121                                 return ("domain doesn't exist");
02122                         default:
02123                                 return ("rrset doesn't exist");
02124                         }
02125                 case dns_rdataclass_any:
02126                         switch (rdata->type) {
02127                         case dns_rdatatype_any:
02128                                 return ("domain exists");
02129                         default:
02130                                 return ("rrset exists (value independent)");
02131                         }
02132                 default:
02133                         return ("rrset exists (value dependent)");
02134                 }
02135         case DNS_SECTION_UPDATE:
02136                 switch (rdata->rdclass) {
02137                 case dns_rdataclass_none:
02138                         return ("delete");
02139                 case dns_rdataclass_any:
02140                         switch (rdata->type) {
02141                         case dns_rdatatype_any:
02142                                 return ("delete all rrsets");
02143                         default:
02144                                 return ("delete rrset");
02145                         }
02146                 default:
02147                         return ("add");
02148                 }
02149         }
02150         return ("invalid");
02151 }

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