00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00109
00110
00111
00112 typedef struct dns_rdata_textctx {
00113 dns_name_t *origin;
00114 unsigned int flags;
00115 unsigned int width;
00116 const char *linebreak;
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
00223 #define NS_INT16SZ 2
00224
00225 #define NS_LOCATORSZ 8
00226
00227
00228
00229
00230
00231
00232
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
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
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
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
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
00537
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
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, ®ion);
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
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
00604
00605
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
00718
00719
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
00743
00744
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, ®ion);
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)
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
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
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
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;
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, ®ion);
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
00979
00980
00981
00982 REQUIRE(rdata != NULL);
00983 REQUIRE(add != NULL);
00984 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
00985
00986 ADDITIONALDATASWITCH
00987
00988
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
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
01063
01064
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
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
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, ®ion);
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
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
01171
01172
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
01217
01218 nrem--;
01219 t++;
01220
01221
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
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, ®ion);
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
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
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, ®ion);
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
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, ®ion);
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, ®ion);
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, ®ion);
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
01601
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
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
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
01651
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
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
01715
01716
01717
01718
01719
01720
01721
01722
01723
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
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
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
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
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
01788
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
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
01854
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
01871
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);
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 }