📄 name.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: name.c,v 1.127.2.7.2.11 2004/09/01 05:19:59 marka Exp $ */#include <config.h>#include <ctype.h>#include <isc/buffer.h>#include <isc/hash.h>#include <isc/mem.h>#include <isc/print.h>#include <isc/string.h>#include <isc/util.h>#include <dns/compress.h>#include <dns/name.h>#include <dns/result.h>#define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)typedef enum { ft_init = 0, ft_start, ft_ordinary, ft_initialescape, ft_escape, ft_escdecimal, ft_at} ft_state;typedef enum { fw_start = 0, fw_ordinary, fw_copy, fw_newcurrent} fw_state;static char digitvalue[256] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/};static unsigned char maptolower[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff};#define CONVERTTOASCII(c)#define CONVERTFROMASCII(c)#define INIT_OFFSETS(name, var, default) \ if (name->offsets != NULL) \ var = name->offsets; \ else \ var = default;#define SETUP_OFFSETS(name, var, default) \ if (name->offsets != NULL) \ var = name->offsets; \ else { \ var = default; \ set_offsets(name, var, NULL); \ }/* * Note: If additional attributes are added that should not be set for * empty names, MAKE_EMPTY() must be changed so it clears them. */#define MAKE_EMPTY(name) \do { \ name->ndata = NULL; \ name->length = 0; \ name->labels = 0; \ name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \} while (0);/* * A name is "bindable" if it can be set to point to a new value, i.e. * name->ndata and name->length may be changed. */#define BINDABLE(name) \ ((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \ == 0)/* * Note that the name data must be a char array, not a string * literal, to avoid compiler warnings about discarding * the const attribute of a string. */static unsigned char root_ndata[] = { '\0' };static unsigned char root_offsets[] = { 0 };static dns_name_t root = { DNS_NAME_MAGIC, root_ndata, 1, 1, DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, root_offsets, NULL, {(void *)-1, (void *)-1}, {NULL, NULL}};/* XXXDCL make const? */LIBDNS_EXTERNAL_DATA dns_name_t *dns_rootname = &root;static unsigned char wild_ndata[] = { '\001', '*' };static unsigned char wild_offsets[] = { 0 };static dns_name_t wild ={ DNS_NAME_MAGIC, wild_ndata, 2, 1, DNS_NAMEATTR_READONLY, wild_offsets, NULL, {(void *)-1, (void *)-1}, {NULL, NULL}};/* XXXDCL make const? */LIBDNS_EXTERNAL_DATA dns_name_t *dns_wildcardname = &wild;unsigned intdns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive);static voidset_offsets(const dns_name_t *name, unsigned char *offsets, dns_name_t *set_name);voiddns_name_init(dns_name_t *name, unsigned char *offsets) { /* * Initialize 'name'. */ DNS_NAME_INIT(name, offsets);}voiddns_name_reset(dns_name_t *name) { REQUIRE(VALID_NAME(name)); REQUIRE(BINDABLE(name)); DNS_NAME_RESET(name);}voiddns_name_invalidate(dns_name_t *name) { /* * Make 'name' invalid. */ REQUIRE(VALID_NAME(name)); name->magic = 0; name->ndata = NULL; name->length = 0; name->labels = 0; name->attributes = 0; name->offsets = NULL; name->buffer = NULL; ISC_LINK_INIT(name, link);}voiddns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) { /* * Dedicate a buffer for use with 'name'. */ REQUIRE(VALID_NAME(name)); REQUIRE((buffer != NULL && name->buffer == NULL) || (buffer == NULL)); name->buffer = buffer;}isc_boolean_tdns_name_hasbuffer(const dns_name_t *name) { /* * Does 'name' have a dedicated buffer? */ REQUIRE(VALID_NAME(name)); if (name->buffer != NULL) return (ISC_TRUE); return (ISC_FALSE);}isc_boolean_tdns_name_isabsolute(const dns_name_t *name) { /* * Does 'name' end in the root label? */ REQUIRE(VALID_NAME(name)); if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) return (ISC_TRUE); return (ISC_FALSE);}#define hyphenchar(c) ((c) == 0x2d)#define asterchar(c) ((c) == 0x2a)#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \ || ((c) >= 0x61 && (c) <= 0x7a))#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)#define borderchar(c) (alphachar(c) || digitchar(c))#define middlechar(c) (borderchar(c) || hyphenchar(c))#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)isc_boolean_tdns_name_ismailbox(const dns_name_t *name) { unsigned char *ndata, ch; unsigned int n; isc_boolean_t first; REQUIRE(VALID_NAME(name)); REQUIRE(name->labels > 0); REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE); /* * Root label. */ if (name->length == 1) return (ISC_TRUE); ndata = name->ndata; n = *ndata++; INSIST(n <= 63); while (n--) { ch = *ndata++; if (!domainchar(ch)) return (ISC_FALSE); } if (ndata == name->ndata + name->length) return (ISC_FALSE); /* * RFC292/RFC1123 hostname. */ while (ndata < (name->ndata + name->length)) { n = *ndata++; INSIST(n <= 63); first = ISC_TRUE; while (n--) { ch = *ndata++; if (first || n == 0) { if (!borderchar(ch)) return (ISC_FALSE); } else { if (!middlechar(ch)) return (ISC_FALSE); } first = ISC_FALSE; } } return (ISC_TRUE);}isc_boolean_tdns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard) { unsigned char *ndata, ch; unsigned int n; isc_boolean_t first; REQUIRE(VALID_NAME(name)); REQUIRE(name->labels > 0); REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE); /* * Root label. */ if (name->length == 1) return (ISC_TRUE); /* * Skip wildcard if this is a ownername. */ ndata = name->ndata; if (wildcard && ndata[0] == 1 && ndata[1] == '*') ndata += 2; /* * RFC292/RFC1123 hostname. */ while (ndata < (name->ndata + name->length)) { n = *ndata++; INSIST(n <= 63); first = ISC_TRUE; while (n--) { ch = *ndata++; if (first || n == 0) { if (!borderchar(ch)) return (ISC_FALSE); } else { if (!middlechar(ch)) return (ISC_FALSE); } first = ISC_FALSE; } } return (ISC_TRUE);}isc_boolean_tdns_name_iswildcard(const dns_name_t *name) { unsigned char *ndata; /* * Is 'name' a wildcard name? */ REQUIRE(VALID_NAME(name)); REQUIRE(name->labels > 0); if (name->length >= 2) { ndata = name->ndata; if (ndata[0] == 1 && ndata[1] == '*') return (ISC_TRUE); } return (ISC_FALSE);}static inline unsigned intname_hash(dns_name_t *name, isc_boolean_t case_sensitive) { unsigned int length; const unsigned char *s; unsigned int h = 0; unsigned char c; length = name->length; if (length > 16) length = 16; /* * This hash function is similar to the one Ousterhout * uses in Tcl. */ s = name->ndata; if (case_sensitive) { while (length > 0) { h += ( h << 3 ) + *s; s++; length--; } } else { while (length > 0) { c = maptolower[*s]; h += ( h << 3 ) + c; s++; length--; } } return (h);}unsigned intdns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive) { /* * Provide a hash value for 'name'. */ REQUIRE(VALID_NAME(name)); if (name->labels == 0) return (0); return (name_hash(name, case_sensitive));}unsigned intdns_name_fullhash(dns_name_t *name, isc_boolean_t case_sensitive) { /* * Provide a hash value for 'name'. */ REQUIRE(VALID_NAME(name)); if (name->labels == 0) return (0); return (isc_hash_calc((const unsigned char *)name->ndata, name->length, case_sensitive));}unsigned intdns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive) { /* * This function was deprecated due to the breakage of the name space * convention. We only keep this internally to provide binary backward * compatibility. */ REQUIRE(VALID_NAME(name)); return (dns_name_fullhash(name, case_sensitive));}unsigned intdns_name_hashbylabel(dns_name_t *name, isc_boolean_t case_sensitive) { unsigned char *offsets; dns_offsets_t odata; dns_name_t tname; unsigned int h = 0; unsigned int i; /* * Provide a hash value for 'name'. */ REQUIRE(VALID_NAME(name)); if (name->labels == 0) return (0); else if (name->labels == 1) return (name_hash(name, case_sensitive)); SETUP_OFFSETS(name, offsets, odata); DNS_NAME_INIT(&tname, NULL); tname.labels = 1; h = 0; for (i = 0; i < name->labels; i++) { tname.ndata = name->ndata + offsets[i]; if (i == name->labels - 1) tname.length = name->length - offsets[i]; else tname.length = offsets[i + 1] - offsets[i]; h += name_hash(&tname, case_sensitive); } return (h);}dns_namereln_tdns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2, int *orderp, unsigned int *nlabelsp){ unsigned int l1, l2, l, count1, count2, count, nlabels; int cdiff, ldiff, chdiff; unsigned char *label1, *label2; unsigned char *offsets1, *offsets2; dns_offsets_t odata1, odata2; dns_namereln_t namereln = dns_namereln_none; /* * Determine the relative ordering under the DNSSEC order relation of * 'name1' and 'name2', and also determine the hierarchical * relationship of the names. * * Note: It makes no sense for one of the names to be relative and the * other absolute. If both names are relative, then to be meaningfully * compared the caller must ensure that they are both relative to the * same domain. */ REQUIRE(VALID_NAME(name1)); REQUIRE(VALID_NAME(name2)); REQUIRE(orderp != NULL); REQUIRE(nlabelsp != NULL); /* * Either name1 is absolute and name2 is absolute, or neither is. */ REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) == (name2->attributes & DNS_NAMEATTR_ABSOLUTE)); SETUP_OFFSETS(name1, offsets1, odata1); SETUP_OFFSETS(name2, offsets2, odata2); nlabels = 0; l1 = name1->labels; l2 = name2->labels; ldiff = (int)l1 - (int)l2; if (ldiff < 0) l = l1; else l = l2; while (l > 0) { l--; l1--; l2--; label1 = &name1->ndata[offsets1[l1]]; label2 = &name2->ndata[offsets2[l2]]; count1 = *label1++; count2 = *label2++; /* * We dropped bitstring labels, and we don't support any * other extended label types. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -