📄 rdata.c
字号:
/* * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. *//* $Id: rdata.c,v 1.147.2.11.2.15 2004/03/12 10:31:25 marka Exp $ */#include <config.h>#include <ctype.h>#include <isc/base64.h>#include <isc/hex.h>#include <isc/lex.h>#include <isc/mem.h>#include <isc/parseint.h>#include <isc/print.h>#include <isc/string.h>#include <isc/stdlib.h>#include <isc/util.h>#include <dns/callbacks.h>#include <dns/cert.h>#include <dns/compress.h>#include <dns/enumtype.h>#include <dns/keyflags.h>#include <dns/keyvalues.h>#include <dns/rcode.h>#include <dns/rdata.h>#include <dns/rdataclass.h>#include <dns/rdatastruct.h>#include <dns/rdatatype.h>#include <dns/result.h>#include <dns/secalg.h>#include <dns/secproto.h>#include <dns/time.h>#include <dns/ttl.h>#define RETERR(x) \ do { \ isc_result_t _r = (x); \ if (_r != ISC_R_SUCCESS) \ return (_r); \ } while (0)#define RETTOK(x) \ do { \ isc_result_t _r = (x); \ if (_r != ISC_R_SUCCESS) { \ isc_lex_ungettoken(lexer, &token); \ return (_r); \ } \ } while (0)#define DNS_AS_STR(t) ((t).value.as_textregion.base)#define ARGS_FROMTEXT int rdclass, dns_rdatatype_t type, \ isc_lex_t *lexer, dns_name_t *origin, \ unsigned int options, isc_buffer_t *target, \ dns_rdatacallbacks_t *callbacks#define ARGS_TOTEXT dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, \ isc_buffer_t *target#define ARGS_FROMWIRE int rdclass, dns_rdatatype_t type, \ isc_buffer_t *source, dns_decompress_t *dctx, \ unsigned int options, isc_buffer_t *target#define ARGS_TOWIRE dns_rdata_t *rdata, dns_compress_t *cctx, \ isc_buffer_t *target#define ARGS_COMPARE const dns_rdata_t *rdata1, const dns_rdata_t *rdata2#define ARGS_FROMSTRUCT int rdclass, dns_rdatatype_t type, \ void *source, isc_buffer_t *target#define ARGS_TOSTRUCT dns_rdata_t *rdata, void *target, isc_mem_t *mctx#define ARGS_FREESTRUCT void *source#define ARGS_ADDLDATA dns_rdata_t *rdata, dns_additionaldatafunc_t add, \ void *arg#define ARGS_DIGEST dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg#define ARGS_CHECKOWNER dns_name_t *name, dns_rdataclass_t rdclass, \ dns_rdatatype_t type, isc_boolean_t wildcard#define ARGS_CHECKNAMES dns_rdata_t *rdata, dns_name_t *owner, dns_name_t *bad/* * Context structure for the totext_ functions. * Contains formatting options for rdata-to-text * conversion. */typedef struct dns_rdata_textctx { dns_name_t *origin; /* Current origin, or NULL. */ unsigned int flags; /* DNS_STYLEFLAG_* */ unsigned int width; /* Width of rdata column. */ const char *linebreak; /* Line break string. */} dns_rdata_textctx_t;static isc_result_ttxt_totext(isc_region_t *source, isc_buffer_t *target);static isc_result_ttxt_fromtext(isc_textregion_t *source, isc_buffer_t *target);static isc_result_ttxt_fromwire(isc_buffer_t *source, isc_buffer_t *target);static isc_boolean_tname_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target);static unsigned intname_length(dns_name_t *name);static isc_result_tstr_totext(const char *source, isc_buffer_t *target);static isc_result_tinet_totext(int af, isc_region_t *src, isc_buffer_t *target);static isc_boolean_tbuffer_empty(isc_buffer_t *source);static voidbuffer_fromregion(isc_buffer_t *buffer, isc_region_t *region);static isc_result_tuint32_tobuffer(isc_uint32_t, isc_buffer_t *target);static isc_result_tuint16_tobuffer(isc_uint32_t, isc_buffer_t *target);static isc_result_tuint8_tobuffer(isc_uint32_t, isc_buffer_t *target);static isc_result_tname_tobuffer(dns_name_t *name, isc_buffer_t *target);static isc_uint32_tuint32_fromregion(isc_region_t *region);static isc_uint16_tuint16_fromregion(isc_region_t *region);static isc_uint8_tuint8_fromregion(isc_region_t *region);static isc_result_tmem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);static inthexvalue(char value);static intdecvalue(char value);static isc_result_tbtoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target);static isc_result_tatob_tobuffer(isc_lex_t *lexer, isc_buffer_t *target);static voiddefault_fromtext_callback(dns_rdatacallbacks_t *callbacks, const char *, ...) ISC_FORMAT_PRINTF(2, 3);static voidfromtext_error(void (*callback)(dns_rdatacallbacks_t *, const char *, ...), dns_rdatacallbacks_t *callbacks, const char *name, unsigned long line, isc_token_t *token, isc_result_t result);static voidfromtext_warneof(isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks);static isc_result_trdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, isc_buffer_t *target);static voidwarn_badname(dns_name_t *name, isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks);static inline intgetquad(const void *src, struct in_addr *dst, isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks){ int result; struct in_addr *tmp; result = inet_aton(src, dst); if (result == 1 && callbacks != NULL && inet_pton(AF_INET, src, &tmp) != 1) { const char *name = isc_lex_getsourcename(lexer); if (name == NULL) name = "UNKNOWN"; (*callbacks->warn)(callbacks, "%s:%lu: \"%s\" " "is not a decimal dotted quad", name, isc_lex_getsourceline(lexer), src); } return (result);}static inline isc_result_tname_duporclone(dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) { if (mctx != NULL) return (dns_name_dup(source, mctx, target)); dns_name_clone(source, target); return (ISC_R_SUCCESS);}static inline void *mem_maybedup(isc_mem_t *mctx, void *source, size_t length) { void *new; if (mctx == NULL) return (source); new = isc_mem_allocate(mctx, length); if (new != NULL) memcpy(new, source, length); return (new);}static const char hexdigits[] = "0123456789abcdef";static const char decdigits[] = "0123456789";#include "code.h"#define META 0x0001#define RESERVED 0x0002/*** *** Initialization ***/voiddns_rdata_init(dns_rdata_t *rdata) { REQUIRE(rdata != NULL); rdata->data = NULL; rdata->length = 0; rdata->rdclass = 0; rdata->type = 0; rdata->flags = 0; ISC_LINK_INIT(rdata, link); /* ISC_LIST_INIT(rdata->list); */}#if 0#define DNS_RDATA_INITIALIZED(rdata) \ ((rdata)->data == NULL && (rdata)->length == 0 && \ (rdata)->rdclass == 0 && (rdata)->type == 0 && (rdata)->flags == 0 && \ !ISC_LINK_LINKED((rdata), link))#else#ifdef ISC_LIST_CHECKINIT#define DNS_RDATA_INITIALIZED(rdata) \ (!ISC_LINK_LINKED((rdata), link))#else#define DNS_RDATA_INITIALIZED(rdata) ISC_TRUE#endif#endif#define DNS_RDATA_VALIDFLAGS(rdata) \ (((rdata)->flags & ~DNS_RDATA_UPDATE) == 0)voiddns_rdata_reset(dns_rdata_t *rdata) { REQUIRE(rdata != NULL); REQUIRE(!ISC_LINK_LINKED(rdata, link)); REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); rdata->data = NULL; rdata->length = 0; rdata->rdclass = 0; rdata->type = 0; rdata->flags = 0;}/*** *** ***/voiddns_rdata_clone(const dns_rdata_t *src, dns_rdata_t *target) { REQUIRE(src != NULL); REQUIRE(target != NULL); REQUIRE(DNS_RDATA_INITIALIZED(target)); REQUIRE(DNS_RDATA_VALIDFLAGS(src)); REQUIRE(DNS_RDATA_VALIDFLAGS(target)); target->data = src->data; target->length = src->length; target->rdclass = src->rdclass; target->type = src->type; target->flags = src->flags;}/*** *** Comparisons ***/intdns_rdata_compare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2) { int result = 0; isc_boolean_t use_default = ISC_FALSE; REQUIRE(rdata1 != NULL); REQUIRE(rdata2 != NULL); REQUIRE(rdata1->data != NULL); REQUIRE(rdata2->data != NULL); REQUIRE(DNS_RDATA_VALIDFLAGS(rdata1)); REQUIRE(DNS_RDATA_VALIDFLAGS(rdata2)); if (rdata1->rdclass != rdata2->rdclass) return (rdata1->rdclass < rdata2->rdclass ? -1 : 1); if (rdata1->type != rdata2->type) return (rdata1->type < rdata2->type ? -1 : 1); COMPARESWITCH if (use_default) { isc_region_t r1; isc_region_t r2; dns_rdata_toregion(rdata1, &r1); dns_rdata_toregion(rdata2, &r2); result = isc_region_compare(&r1, &r2); } return (result);}/*** *** Conversions ***/voiddns_rdata_fromregion(dns_rdata_t *rdata, dns_rdataclass_t rdclass, dns_rdatatype_t type, isc_region_t *r){ REQUIRE(rdata != NULL); REQUIRE(DNS_RDATA_INITIALIZED(rdata)); REQUIRE(r != NULL); REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); rdata->data = r->base; rdata->length = r->length; rdata->rdclass = rdclass; rdata->type = type; rdata->flags = 0;}voiddns_rdata_toregion(const dns_rdata_t *rdata, isc_region_t *r) { REQUIRE(rdata != NULL); REQUIRE(r != NULL); REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); r->base = rdata->data; r->length = rdata->length;}isc_result_tdns_rdata_fromwire(dns_rdata_t *rdata, dns_rdataclass_t rdclass, dns_rdatatype_t type, isc_buffer_t *source, dns_decompress_t *dctx, unsigned int options, isc_buffer_t *target){ isc_result_t result = ISC_R_NOTIMPLEMENTED; isc_region_t region; isc_buffer_t ss; isc_buffer_t st; isc_boolean_t use_default = ISC_FALSE; isc_uint32_t activelength; REQUIRE(dctx != NULL); if (rdata != NULL) { REQUIRE(DNS_RDATA_INITIALIZED(rdata)); REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); } if (type == 0) return (DNS_R_FORMERR); ss = *source; st = *target; activelength = isc_buffer_activelength(source); INSIST(activelength < 65536); FROMWIRESWITCH if (use_default) { if (activelength > isc_buffer_availablelength(target)) result = ISC_R_NOSPACE; else { isc_buffer_putmem(target, isc_buffer_current(source), activelength); isc_buffer_forward(source, activelength); result = ISC_R_SUCCESS; } } /* * We should have consumed all of our buffer. */ if (result == ISC_R_SUCCESS && !buffer_empty(source)) result = DNS_R_EXTRADATA; if (rdata != NULL && result == ISC_R_SUCCESS) { region.base = isc_buffer_used(&st); region.length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st); dns_rdata_fromregion(rdata, rdclass, type, ®ion); } if (result != ISC_R_SUCCESS) { *source = ss; *target = st; } return (result);}isc_result_tdns_rdata_towire(dns_rdata_t *rdata, dns_compress_t *cctx, isc_buffer_t *target){ isc_result_t result = ISC_R_NOTIMPLEMENTED; isc_boolean_t use_default = ISC_FALSE; isc_region_t tr; isc_buffer_t st; REQUIRE(rdata != NULL); REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); /* * Some DynDNS meta-RRs have empty rdata. */ if ((rdata->flags & DNS_RDATA_UPDATE) != 0) { INSIST(rdata->length == 0); return (ISC_R_SUCCESS); } st = *target; TOWIRESWITCH if (use_default) { isc_buffer_availableregion(target, &tr); if (tr.length < rdata->length) return (ISC_R_NOSPACE); memcpy(tr.base, rdata->data, rdata->length); isc_buffer_add(target, rdata->length); return (ISC_R_SUCCESS); } if (result != ISC_R_SUCCESS) { *target = st; INSIST(target->used < 65536); dns_compress_rollback(cctx, (isc_uint16_t)target->used); } return (result);}/* * If the binary data in 'src' is valid uncompressed wire format * rdata of class 'rdclass' and type 'type', return ISC_R_SUCCESS * and copy the validated rdata to 'dest'. Otherwise return an error. */static isc_result_trdata_validate(isc_buffer_t *src, isc_buffer_t *dest, dns_rdataclass_t rdclass, dns_rdatatype_t type){ dns_decompress_t dctx; dns_rdata_t rdata = DNS_RDATA_INIT; isc_result_t result; dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE); isc_buffer_setactive(src, isc_buffer_usedlength(src)); result = dns_rdata_fromwire(&rdata, rdclass, type, src, &dctx, 0, dest); dns_decompress_invalidate(&dctx); return (result);}static isc_result_tunknown_fromtext(dns_rdataclass_t rdclass, dns_rdatatype_t type, isc_lex_t *lexer, isc_mem_t *mctx, isc_buffer_t *target){ isc_result_t result; isc_buffer_t *buf = NULL; isc_token_t token; if (type == 0 || dns_rdatatype_ismeta(type)) return (DNS_R_METATYPE); result = isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, ISC_FALSE); if (result == ISC_R_SUCCESS && token.value.as_ulong > 65535U) return (ISC_R_RANGE); result = isc_buffer_allocate(mctx, &buf, token.value.as_ulong); if (result != ISC_R_SUCCESS) return (result); result = isc_hex_tobuffer(lexer, buf, (unsigned int)token.value.as_ulong); if (result != ISC_R_SUCCESS) goto failure; if (isc_buffer_usedlength(buf) != token.value.as_ulong) { result = ISC_R_UNEXPECTEDEND; goto failure; } if (dns_rdatatype_isknown(type)) { result = rdata_validate(buf, target, rdclass, type); } else { isc_region_t r; isc_buffer_usedregion(buf, &r); result = isc_buffer_copyregion(target, &r); } if (result != ISC_R_SUCCESS) goto failure; isc_buffer_free(&buf); return (ISC_R_SUCCESS); failure: isc_buffer_free(&buf); return (result);}isc_result_tdns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t rdclass, dns_rdatatype_t type, isc_lex_t *lexer, dns_name_t *origin, unsigned int options, isc_mem_t *mctx, isc_buffer_t *target, dns_rdatacallbacks_t *callbacks){ isc_result_t result = ISC_R_NOTIMPLEMENTED; isc_region_t region; isc_buffer_t st; isc_token_t token; unsigned int lexoptions = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE; char *name; unsigned long line; void (*callback)(dns_rdatacallbacks_t *, const char *, ...); isc_result_t tresult; REQUIRE(origin == NULL || dns_name_isabsolute(origin) == ISC_TRUE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -