name.c revision 9c3531d72aeaad6c5f01efe6a1c82023e1379e4d
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews/*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Copyright (C) 1998-2000 Internet Software Consortium.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Permission to use, copy, modify, and distribute this software for any
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * purpose with or without fee is hereby granted, provided that the above
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * copyright notice and this permission notice appear in all copies.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * SOFTWARE.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt/* $Id: name.c,v 1.93 2000/06/22 21:54:32 tale Exp $ */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <config.h>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <ctype.h>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews#include <isc/buffer.h>
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews#include <isc/mem.h>
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews#include <isc/print.h>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <isc/string.h>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <isc/util.h>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt#include <dns/result.h>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <dns/name.h>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <dns/compress.h>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunttypedef enum {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ft_init = 0,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ft_start,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ft_ordinary,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ft_initialescape,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ft_escape,
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews ft_escdecimal,
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews ft_bitstring,
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews ft_binary,
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews ft_octal,
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews ft_hex,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ft_dottedquad,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ft_dqdecimal,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ft_maybeslash,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ft_finishbitstring,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ft_bitlength,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ft_eatdot,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ft_at
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt} ft_state;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunttypedef enum {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt fw_start = 0,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt fw_ordinary,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt fw_copy,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt fw_bitstring,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt fw_newcurrent
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt} fw_state;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic char digitvalue[256] = {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt};
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic char hexdigits[16] = {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt '0', '1', '2', '3', '4', '5', '6', '7',
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt};
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic unsigned char maptolower[] = {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt};
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#define CONVERTTOASCII(c)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#define CONVERTFROMASCII(c)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#define INIT_OFFSETS(name, var, default) \
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (name->offsets != NULL) \
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt var = name->offsets; \
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else \
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt var = default;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#define SETUP_OFFSETS(name, var, default) \
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (name->offsets != NULL) \
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt var = name->offsets; \
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else { \
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt var = default; \
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt set_offsets(name, var, NULL); \
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt/*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Note: If additional attributes are added that should not be set for
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * empty names, MAKE_EMPTY() must be changed so it clears them.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#define MAKE_EMPTY(name) \
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdo { \
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->ndata = NULL; \
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->length = 0; \
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->labels = 0; \
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt} while (0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt/*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * A name is "bindable" if it can be set to point to a new value, i.e.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * name->ndata and name->length may be changed.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt#define BINDABLE(name) \
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt ((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt == 0)
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt/*
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt * This silliness is to avoid warnings about the const attribute of a string
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt * being discarded, as can happen (depending on the compiler and flags)
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt * when name.ndata or name.offsets is assigned to via a string literal.
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt * Unfortunately, gcc -Wwrite-strings produces incorrect warnings for
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt * assigning a const string to the ndata or offsets members in
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt * "const struct dns_name root", which (at least according to the ANSI
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt * Draft dated August 3, 1998) should have the effect of declaring all
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt * members of the struct as const.
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt */
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Huntstruct dns_constname {
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt dns_name_t name;
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt unsigned char const_ndata[2];
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt unsigned char const_offsets[1];
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt};
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Huntstatic struct dns_constname root = {
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt {
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt DNS_NAME_MAGIC,
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt root.const_ndata, 1, 1,
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt root.const_offsets, NULL,
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt {(void *)-1, (void *)-1},
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt {NULL, NULL}
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt },
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt { '\0', '\0' }, /* const_ndata */
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt { '\0' } /* const_offsets */
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt};
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt/* XXXDCL make const? */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_t *dns_rootname = &root.name;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic struct dns_constname wild = {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt DNS_NAME_MAGIC,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt wild.const_ndata, 2, 1,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt DNS_NAMEATTR_READONLY,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt wild.const_offsets, NULL,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt {(void *)-1, (void *)-1},
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt {NULL, NULL}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt },
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt { '\001', '*' }, /* const_ndata */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt { '\0' } /* const_offsets */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt};
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt/* XXXDCL make const? */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_t *dns_wildcardname = &wild.name;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic void
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntset_offsets(const dns_name_t *name, unsigned char *offsets,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt dns_name_t *set_name);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic void
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntcompact(dns_name_t *name, unsigned char *offsets);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt/*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Yes, get_bit and set_bit are lame. We define them here so they can
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * be inlined by smart compilers.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic inline unsigned int
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntget_bit(unsigned char *array, unsigned int idx) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned int byte, shift;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt byte = array[idx / 8];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt shift = 7 - (idx % 8);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return ((byte >> shift) & 0x01);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic inline void
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntset_bit(unsigned char *array, unsigned int idx, unsigned int bit) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned int shift, mask;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt shift = 7 - (idx % 8);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt mask = 1 << shift;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (bit != 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt array[idx / 8] |= mask;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt array[idx / 8] &= (~mask & 0xFF);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_labeltype_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_label_type(dns_label_t *label) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Get the type of 'label'.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(label != NULL);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(label->length > 0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(label->base[0] <= 63 ||
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt label->base[0] == DNS_LABELTYPE_BITSTRING);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (label->base[0] <= 63)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (dns_labeltype_ordinary);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (dns_labeltype_bitstring);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntunsigned int
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_label_countbits(dns_label_t *label) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned int count;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * The number of bits in a bitstring label.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(label != NULL);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(label->length > 2);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(label->base[0] == DNS_LABELTYPE_BITSTRING);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count = label->base[1];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count == 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count = 256;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (count);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_bitlabel_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_label_getbit(dns_label_t *label, unsigned int n) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned int count, bit;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * The 'n'th most significant bit of 'label'.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Notes:
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Numbering starts at 0.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(label != NULL);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(label->length > 2);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(label->base[0] == DNS_LABELTYPE_BITSTRING);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count = label->base[1];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count == 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count = 256;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(n < count);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt bit = get_bit(&label->base[2], n);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (bit == 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (dns_bitlabel_0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (dns_bitlabel_1);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntvoid
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_init(dns_name_t *name, unsigned char *offsets) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Initialize 'name'.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->magic = DNS_NAME_MAGIC;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->ndata = NULL;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->length = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->labels = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->attributes = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->offsets = offsets;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->buffer = NULL;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ISC_LINK_INIT(name, link);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ISC_LIST_INIT(name->list);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntvoid
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_invalidate(dns_name_t *name) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Make 'name' invalid.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(name));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->magic = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->ndata = NULL;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->length = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->labels = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->attributes = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->offsets = NULL;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->buffer = NULL;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ISC_LINK_INIT(name, link);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntvoid
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Dedicate a buffer for use with 'name'.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(name));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE((buffer != NULL && name->buffer == NULL) ||
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt (buffer == NULL));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->buffer = buffer;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntisc_boolean_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_hasbuffer(const dns_name_t *name) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Does 'name' have a dedicated buffer?
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(name));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (name->buffer != NULL)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (ISC_TRUE);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (ISC_FALSE);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntisc_boolean_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_isabsolute(const dns_name_t *name) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Does 'name' end in the root label?
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(name));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(name->labels > 0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (ISC_TRUE);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (ISC_FALSE);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntisc_boolean_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_iswildcard(const dns_name_t *name) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned char *ndata;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Is 'name' a wildcard name?
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(name));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(name->labels > 0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (name->length >= 2) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ndata = name->ndata;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (ndata[0] == 1 && ndata[1] == '*')
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (ISC_TRUE);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (ISC_FALSE);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntisc_boolean_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_requiresedns(const dns_name_t *name) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned int count, nrem;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned char *ndata;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt isc_boolean_t requiresedns = ISC_FALSE;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Does 'name' require EDNS for transmission?
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(name));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(name->labels > 0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ndata = name->ndata;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt nrem = name->length;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt while (nrem > 0) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count = *ndata++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt nrem--;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count == 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count > 63) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt INSIST(count == DNS_LABELTYPE_BITSTRING);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt requiresedns = ISC_TRUE;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt INSIST(nrem >= count);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt nrem -= count;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ndata += count;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (requiresedns);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntunsigned int
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned int length;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const unsigned char *s;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned int h = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned int g;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned char c;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Provide a hash value for 'name'.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(name));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (name->labels == 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt length = name->length;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (length > 16)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt length = 16;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * P. J. Weinberger's hash function, adapted from p. 436 of
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * _Compilers: Principles, Techniques, and Tools_, Aho, Sethi
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * and Ullman, Addison-Wesley, 1986, ISBN 0-201-10088-6.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt s = name->ndata;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (case_sensitive) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt while (length > 0) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt h = ( h << 4 ) + *s;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if ((g = ( h & 0xf0000000 )) != 0) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt h = h ^ (g >> 24);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt h = h ^ g;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt s++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt length--;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt while (length > 0) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt c = maptolower[*s];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt h = ( h << 4 ) + c;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if ((g = ( h & 0xf0000000 )) != 0) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt h = h ^ (g >> 24);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt h = h ^ g;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt s++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt length--;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (h);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_namereln_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt int *orderp,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned int *nlabelsp, unsigned int *nbitsp)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned int l1, l2, l, count1, count2, count;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned int b1, b2, n, nlabels, nbits;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt int cdiff, ldiff, chdiff;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned char *label1, *label2;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned char *offsets1, *offsets2;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt dns_offsets_t odata1, odata2;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt dns_namereln_t namereln = dns_namereln_none;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Determine the relative ordering under the DNSSEC order relation of
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * 'name1' and 'name2', and also determine the hierarchical
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * relationship of the names.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Note: It makes no sense for one of the names to be relative and the
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * other absolute. If both names are relative, then to be meaningfully
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * compared the caller must ensure that they are both relative to the
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * same domain.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(name1));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(name1->labels > 0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(name2));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(name2->labels > 0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(orderp != NULL);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(nlabelsp != NULL);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(nbitsp != NULL);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Either name1 is absolute and name2 is absolute, or neither is.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt SETUP_OFFSETS(name1, offsets1, odata1);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt SETUP_OFFSETS(name2, offsets2, odata2);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt nlabels = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt nbits = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt l1 = name1->labels;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt l2 = name2->labels;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ldiff = (int)l1 - (int)l2;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (ldiff < 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt l = l1;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt l = l2;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt while (l > 0) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt l--;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt l1--;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt l2--;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt label1 = &name1->ndata[offsets1[l1]];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt label2 = &name2->ndata[offsets2[l2]];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count1 = *label1++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count2 = *label2++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count1 <= 63 && count2 <= 63) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt cdiff = (int)count1 - (int)count2;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (cdiff < 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count = count1;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count = count2;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt while (count > 0) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt chdiff = (int)maptolower[*label1] -
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt (int)maptolower[*label2];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (chdiff != 0) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *orderp = chdiff;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt goto done;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count--;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt label1++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt label2++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (cdiff != 0) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *orderp = cdiff;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt goto done;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt nlabels++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (count1 == DNS_LABELTYPE_BITSTRING && count2 <= 63) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count2 == 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *orderp = 1;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *orderp = -1;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt goto done;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (count2 == DNS_LABELTYPE_BITSTRING && count1 <= 63) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count1 == 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *orderp = -1;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *orderp = 1;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt goto done;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt INSIST(count1 == DNS_LABELTYPE_BITSTRING &&
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count2 == DNS_LABELTYPE_BITSTRING);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count1 = *label1++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count1 == 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count1 = 256;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count2 = *label2++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count2 == 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count2 = 256;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count1 < count2) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt cdiff = -1;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count = count1;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count = count2;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count1 > count2)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt cdiff = 1;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt cdiff = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /* Yes, this loop is really slow! */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt for (n = 0; n < count; n++) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt b1 = get_bit(label1, n);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt b2 = get_bit(label2, n);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (b1 < b2) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *orderp = -1;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt goto done;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (b1 > b2) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *orderp = 1;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt goto done;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (nbits == 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt nlabels++;
f7f4730e563a2749629fe7fef4cd9513cd2bfab7Mark Andrews nbits++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
f7f4730e563a2749629fe7fef4cd9513cd2bfab7Mark Andrews if (cdiff != 0) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * If we're here, then we have two bitstrings
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * of differing length.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * If the name with the shorter bitstring
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * has any labels, then it must be greater
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * than the longer bitstring. This is a bit
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * counterintuitive. If the name with the
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * shorter bitstring has any more labels, then
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * the next label must be an ordinary label.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * It can't be a bitstring label because if it
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * were, then there would be room for it in
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * the current bitstring label (since all
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * bitstrings are canonicalized). Since
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * there's at least one more bit in the
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * name with the longer bitstring, and since
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * a bitlabel sorts before any ordinary label,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * the name with the longer bitstring must
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * be lexically before the one with the shorter
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * bitstring.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * On the other hand, if there are no more
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * labels in the name with the shorter
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * bitstring, then that name contains the
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * other name.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt namereln = dns_namereln_commonancestor;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (cdiff < 0) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (l1 > 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *orderp = 1;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *orderp = -1;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt namereln =
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt dns_namereln_contains;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (l2 > 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *orderp = -1;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *orderp = 1;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt namereln =
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt dns_namereln_subdomain;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt goto done;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt nbits = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *orderp = ldiff;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (ldiff < 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt namereln = dns_namereln_contains;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else if (ldiff > 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt namereln = dns_namereln_subdomain;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt namereln = dns_namereln_equal;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt done:
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *nlabelsp = nlabels;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *nbitsp = nbits;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (nlabels > 0 && namereln == dns_namereln_none)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt namereln = dns_namereln_commonancestor;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (namereln);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntint
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt int order;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned int nlabels, nbits;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Determine the relative ordering under the DNSSEC order relation of
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * 'name1' and 'name2'.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Note: It makes no sense for one of the names to be relative and the
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * other absolute. If both names are relative, then to be meaningfully
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * compared the caller must ensure that they are both relative to the
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * same domain.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt (void)dns_name_fullcompare(name1, name2, &order, &nlabels, &nbits);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (order);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntisc_boolean_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned int l, count;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned char c;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned char *label1, *label2;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Are 'name1' and 'name2' equal?
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Note: It makes no sense for one of the names to be relative and the
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * other absolute. If both names are relative, then to be meaningfully
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * compared the caller must ensure that they are both relative to the
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * same domain.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(name1));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(name2));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Either name1 is absolute and name2 is absolute, or neither is.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (name1->length != name2->length)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (ISC_FALSE);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt l = name1->labels;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (l != name2->labels)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (ISC_FALSE);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt label1 = name1->ndata;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt label2 = name2->ndata;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt while (l > 0) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt l--;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count = *label1++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count != *label2++)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (ISC_FALSE);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count <= 63) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt while (count > 0) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count--;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt c = maptolower[*label1++];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (c != maptolower[*label2++])
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (ISC_FALSE);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt INSIST(count == DNS_LABELTYPE_BITSTRING);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count = *label1++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count != *label2++)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (ISC_FALSE);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count == 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count = 256;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Number of bytes.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count = (count + 7) / 8;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt while (count > 0) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count--;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt c = *label1++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (c != *label2++)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (ISC_FALSE);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (ISC_TRUE);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntint
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned int l1, l2, l, count1, count2, count;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned char c1, c2;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned char *label1, *label2;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Compare two absolute names as rdata.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(name1));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(name1->labels > 0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(name2));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(name2->labels > 0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt l1 = name1->labels;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt l2 = name2->labels;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt l = (l1 < l2) ? l1 : l2;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt label1 = name1->ndata;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt label2 = name2->ndata;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt while (l > 0) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt l--;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count1 = *label1++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count2 = *label2++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count1 <= 63 && count2 <= 63) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count1 != count2)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return ((count1 < count2) ? -1 : 1);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count = count1;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt while (count > 0) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count--;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt c1 = maptolower[*label1++];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt c2 = maptolower[*label2++];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (c1 < c2)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (-1);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else if (c1 > c2)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (1);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (count1 == DNS_LABELTYPE_BITSTRING && count2 <= 63) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (1);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (count2 == DNS_LABELTYPE_BITSTRING && count1 <= 63) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (-1);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt INSIST(count1 == DNS_LABELTYPE_BITSTRING &&
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count2 == DNS_LABELTYPE_BITSTRING);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count2 = *label2++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count1 = *label1++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count1 != count2)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return ((count1 < count2) ? -1 : 1);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count1 == 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count1 = 256;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count2 == 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count2 = 256;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /* number of bytes */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count = (count1 + 7) / 8;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt while (count > 0) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count--;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt c1 = *label1++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt c2 = *label2++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (c1 != c2)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return ((c1 < c2) ? -1 : 1);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * If one name had more labels than the other, their common
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * prefix must have been different because the shorter name
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * ended with the root label and the longer one can't have
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * a root label in the middle of it. Therefore, if we get
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * to this point, the lengths must be equal.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt INSIST(l1 == l2);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntisc_boolean_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt int order;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned int nlabels, nbits;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt dns_namereln_t namereln;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Is 'name1' a subdomain of 'name2'?
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Note: It makes no sense for one of the names to be relative and the
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * other absolute. If both names are relative, then to be meaningfully
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * compared the caller must ensure that they are both relative to the
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * same domain.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt namereln = dns_name_fullcompare(name1, name2, &order, &nlabels,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt &nbits);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (namereln == dns_namereln_subdomain ||
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt namereln == dns_namereln_equal)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (ISC_TRUE);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (ISC_FALSE);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntisc_boolean_t
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Huntdns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt int order;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned int nlabels, nbits, labels;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt dns_name_t tname;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(name));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(name->labels > 0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(wname));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt labels = wname->labels;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(labels > 0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(dns_name_iswildcard(wname));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt dns_name_init(&tname, NULL);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (dns_name_fullcompare(name, &tname, &order, &nlabels, &nbits) ==
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt dns_namereln_subdomain)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (ISC_TRUE);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (ISC_FALSE);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntunsigned int
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_depth(const dns_name_t *name) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned int depth, count, nrem, n;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned char *ndata;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * The depth of 'name'.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(name));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (name->labels == 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt depth = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ndata = name->ndata;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt nrem = name->length;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt while (nrem > 0) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count = *ndata++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt nrem--;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count > 63) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt INSIST(count == DNS_LABELTYPE_BITSTRING);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt INSIST(nrem != 0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt n = *ndata++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt nrem--;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (n == 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt n = 256;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt depth += n;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count = n / 8;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (n % 8 != 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt depth++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (count == 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt INSIST(nrem >= count);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt nrem -= count;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ndata += count;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (depth);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntunsigned int
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_countlabels(const dns_name_t *name) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * How many labels does 'name' have?
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(name));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ENSURE(name->labels <= 128);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (name->labels);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntvoid
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned char *offsets;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt dns_offsets_t odata;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Make 'label' refer to the 'n'th least significant label of 'name'.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(name));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(name->labels > 0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(n < name->labels);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(label != NULL);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt SETUP_OFFSETS(name, offsets, odata);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt label->base = &name->ndata[offsets[n]];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (n == name->labels - 1)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt label->length = name->length - offsets[n];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt label->length = offsets[n + 1] - offsets[n];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntvoid
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_getlabelsequence(const dns_name_t *source,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned int first, unsigned int n,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt dns_name_t *target)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned char *offsets;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt dns_offsets_t odata;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Make 'target' refer to the 'n' labels including and following
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * 'first' in 'source'.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(source));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(target));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(source->labels > 0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(n > 0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(first < source->labels);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(first + n <= source->labels);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(BINDABLE(target));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt SETUP_OFFSETS(source, offsets, odata);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt target->ndata = &source->ndata[offsets[first]];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (first + n == source->labels) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt target->length = source->length - offsets[first];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt target->attributes |= DNS_NAMEATTR_ABSOLUTE;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt target->length = offsets[first + n] - offsets[first];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt target->labels = n;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * If source and target are the same, and we're making target
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * a prefix of source, the offsets table is correct already
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * so we don't need to call set_offsets().
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (target->offsets != NULL &&
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt (target != source || first != 0))
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt set_offsets(target, target->offsets, NULL);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntvoid
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_clone(dns_name_t *source, dns_name_t *target) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Make 'target' refer to the same name as 'source'.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(source));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(target));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(BINDABLE(target));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt target->ndata = source->ndata;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt target->length = source->length;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt target->labels = source->labels;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt target->attributes = source->attributes &
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt (unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC |
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt DNS_NAMEATTR_DYNOFFSETS);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (target->offsets != NULL && source->labels > 0) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (source->offsets != NULL)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt memcpy(target->offsets, source->offsets,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt source->labels);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt set_offsets(target, target->offsets, NULL);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntvoid
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_fromregion(dns_name_t *name, isc_region_t *r) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned char *offsets;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt dns_offsets_t odata;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned int len;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt isc_region_t r2;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Make 'name' refer to region 'r'.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(name));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(r != NULL);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(BINDABLE(name));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt INIT_OFFSETS(name, offsets, odata);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (name->buffer != NULL) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt isc_buffer_clear(name->buffer);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt isc_buffer_availableregion(name->buffer, &r2);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt len = (r->length < r2.length) ? r->length : r2.length;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (len > 255)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt len = 255;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt memcpy(r2.base, r->base, len);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->ndata = r2.base;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->length = len;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->ndata = r->base;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->length = (r->length <= 255) ? r->length : 255;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (r->length > 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt set_offsets(name, offsets, name);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->labels = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (name->buffer != NULL)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt isc_buffer_add(name->buffer, name->length);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntvoid
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_toregion(dns_name_t *name, isc_region_t *r) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Make 'r' refer to 'name'.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(name));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(r != NULL);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt r->base = name->ndata;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt r->length = name->length;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntisc_result_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt dns_name_t *origin, isc_boolean_t downcase,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt isc_buffer_t *target)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned char *ndata, *label;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt char *tdata;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt char c;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ft_state state, kind;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned int value, count, tbcount, bitlength, maxlength;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned int n1, n2, vlen, tlen, nrem, nused, digits, labels, tused;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt isc_boolean_t done, saw_bitstring;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned char dqchars[4];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt unsigned char *offsets;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt dns_offsets_t odata;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Convert the textual representation of a DNS name at source
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * into uncompressed wire form stored in target.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Notes:
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Relative domain names will have 'origin' appended to them
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * unless 'origin' is NULL, in which case relative domain names
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * will remain relative.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(VALID_NAME(name));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(ISC_BUFFER_VALID(source));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(isc_buffer_current(source) < isc_buffer_used(source));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt (target == NULL && name->buffer != NULL));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (target == NULL && name->buffer != NULL) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt target = name->buffer;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt isc_buffer_clear(target);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt REQUIRE(BINDABLE(name));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt INIT_OFFSETS(name, offsets, odata);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt offsets[0] = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Initialize things to make the compiler happy; they're not required.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt n1 = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt n2 = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt vlen = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt label = NULL;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt digits = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt value = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt tbcount = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt bitlength = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt maxlength = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt kind = ft_init;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Make 'name' empty in case of failure.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt MAKE_EMPTY(name);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Set up the state machine.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt tdata = (char *)source->base + source->current;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt tlen = isc_buffer_remaininglength(source);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt tused = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ndata = isc_buffer_used(target);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt nrem = isc_buffer_availablelength(target);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (nrem > 255)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt nrem = 255;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt nused = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt labels = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt done = ISC_FALSE;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt saw_bitstring = ISC_FALSE;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt state = ft_init;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt while (nrem > 0 && tlen > 0 && !done) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt c = *tdata++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt tlen--;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt tused++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt no_read:
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt switch (state) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt case ft_init:
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /*
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Is this the root name?
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (c == '.') {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (tlen != 0)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (DNS_R_EMPTYLABEL);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt labels++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *ndata++ = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt nrem--;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt nused++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt done = ISC_TRUE;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (c == '@' && tlen == 0) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt state = ft_at;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /* FALLTHROUGH */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt case ft_start:
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt label = ndata;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ndata++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt nrem--;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt nused++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt count = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (c == '\\') {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt state = ft_initialescape;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
kind = ft_ordinary;
state = ft_ordinary;
/* FALLTHROUGH */
case ft_ordinary:
if (c == '.') {
if (count == 0)
return (DNS_R_EMPTYLABEL);
*label = count;
labels++;
INSIST(labels <= 127);
offsets[labels] = nused;
if (tlen == 0) {
labels++;
*ndata++ = 0;
nrem--;
nused++;
done = ISC_TRUE;
}
state = ft_start;
} else if (c == '\\') {
state = ft_escape;
} else {
if (count >= 63)
return (DNS_R_LABELTOOLONG);
count++;
CONVERTTOASCII(c);
if (downcase)
c = maptolower[(int)c];
*ndata++ = c;
nrem--;
nused++;
}
break;
case ft_initialescape:
if (c == '[') {
saw_bitstring = ISC_TRUE;
kind = ft_bitstring;
state = ft_bitstring;
*label = DNS_LABELTYPE_BITSTRING;
label = ndata;
ndata++;
nrem--;
nused++;
break;
}
kind = ft_ordinary;
state = ft_escape;
/* FALLTHROUGH */
case ft_escape:
if (!isdigit(c & 0xff)) {
if (count >= 63)
return (DNS_R_LABELTOOLONG);
count++;
CONVERTTOASCII(c);
if (downcase)
c = maptolower[(int)c];
*ndata++ = c;
nrem--;
nused++;
state = ft_ordinary;
break;
}
digits = 0;
value = 0;
state = ft_escdecimal;
/* FALLTHROUGH */
case ft_escdecimal:
if (!isdigit(c & 0xff))
return (DNS_R_BADESCAPE);
value *= 10;
value += digitvalue[(int)c];
digits++;
if (digits == 3) {
if (value > 255)
return (DNS_R_BADESCAPE);
if (count >= 63)
return (DNS_R_LABELTOOLONG);
count++;
if (downcase)
value = maptolower[value];
*ndata++ = value;
nrem--;
nused++;
state = ft_ordinary;
}
break;
case ft_bitstring:
/* count is zero */
tbcount = 0;
value = 0;
if (c == 'b') {
vlen = 8;
maxlength = 256;
kind = ft_binary;
state = ft_binary;
} else if (c == 'o') {
vlen = 8;
maxlength = 256;
kind = ft_octal;
state = ft_octal;
} else if (c == 'x') {
vlen = 8;
maxlength = 256;
kind = ft_hex;
state = ft_hex;
} else if (isdigit(c & 0xff)) {
vlen = 32;
maxlength = 32;
n1 = 0;
n2 = 0;
digits = 0;
kind = ft_dottedquad;
state = ft_dqdecimal;
goto no_read;
} else
return (DNS_R_BADBITSTRING);
break;
case ft_binary:
if (c != '0' && c != '1') {
state = ft_maybeslash;
goto no_read;
}
value <<= 1;
if (c == '1')
value |= 1;
count++;
tbcount++;
if (tbcount > 256)
return (DNS_R_BITSTRINGTOOLONG);
if (count == 8) {
*ndata++ = value;
nrem--;
nused++;
count = 0;
}
break;
case ft_octal:
if (!isdigit(c & 0xff) || c == '9' || c == '8') {
state = ft_maybeslash;
goto no_read;
}
value <<= 3;
value += digitvalue[(int)c];
count += 3;
tbcount += 3;
/*
* The total bit count is tested against 258 instead
* of 256 because of the possibility that the bitstring
* label is exactly 256 bits long; on the last octal
* digit (which must be 4) tbcount is incremented
* from 255 to 258. This case is adequately handled
* later.
*/
if (tbcount > 258)
return (DNS_R_BITSTRINGTOOLONG);
if (count == 8) {
*ndata++ = value;
nrem--;
nused++;
count = 0;
} else if (count == 9) {
*ndata++ = (value >> 1);
nrem--;
nused++;
value &= 1;
count = 1;
} else if (count == 10) {
*ndata++ = (value >> 2);
nrem--;
nused++;
value &= 3;
count = 2;
}
break;
case ft_hex:
if (!isxdigit(c & 0xff)) {
state = ft_maybeslash;
goto no_read;
}
value <<= 4;
value += digitvalue[(int)c];
count += 4;
tbcount += 4;
if (tbcount > 256)
return (DNS_R_BITSTRINGTOOLONG);
if (count == 8) {
*ndata++ = value;
nrem--;
nused++;
count = 0;
}
break;
case ft_dottedquad:
if (c != '.' && n1 < 3)
return (DNS_R_BADDOTTEDQUAD);
dqchars[n1] = value;
n2 *= 256;
n2 += value;
n1++;
if (n1 == 4) {
tbcount = 32;
value = n2;
state = ft_maybeslash;
goto no_read;
}
value = 0;
digits = 0;
state = ft_dqdecimal;
break;
case ft_dqdecimal:
if (!isdigit(c & 0xff)) {
if (digits == 0 || value > 255)
return (DNS_R_BADDOTTEDQUAD);
state = ft_dottedquad;
goto no_read;
}
digits++;
if (digits > 3)
return (DNS_R_BADDOTTEDQUAD);
value *= 10;
value += digitvalue[(int)c];
break;
case ft_maybeslash:
bitlength = 0;
if (c == '/') {
state = ft_bitlength;
break;
}
/* FALLTHROUGH */
case ft_finishbitstring:
if (c == ']') {
if (tbcount == 0)
return (DNS_R_BADBITSTRING);
if (count > 0) {
n1 = count % 8;
if (n1 != 0)
value <<= (8 - n1);
}
if (bitlength != 0) {
if (bitlength > tbcount)
return (DNS_R_BADBITSTRING);
if (kind == ft_binary &&
bitlength != tbcount) {
return (DNS_R_BADBITSTRING);
} else if (kind == ft_octal) {
/*
* Figure out correct number
* of octal digits for the
* bitlength, and compare to
* what was given.
*/
n1 = bitlength / 3;
if (bitlength % 3 != 0)
n1++;
n2 = tbcount / 3;
/* tbcount % 3 == 0 */
if (n1 != n2)
return (DNS_R_BADBITSTRING);
/*
* Check that no bits extend
* past the end of the last
* byte that is included in
* the bitlength. Example:
* \[o036/8] == \[b00001111],
* which fits into just one
* byte, but the three octal
* digits actually specified
* two bytes worth of data,
* 9 bits, before the bitlength
* limited it back to one byte.
*
* n1 is the number of bytes
* necessary for the bitlength.
* n2 is the number of bytes
* encompassed by the octal
* digits. If they are not
* equal, then "value" holds
* the excess bits, which
* must be zero. If the bits
* are zero, then "count" is
* zero'ed to prevent the
* addition of another byte
* below.
*/
n1 = bitlength - 1 / 8;
n2 = tbcount - 1 / 8;
if (n1 != n2) {
if (value != 0)
return
(DNS_R_BADBITSTRING);
else
count = 0;
}
} else if (kind == ft_hex) {
/*
* Figure out correct number
* of hex digits for the
* bitlength, and compare to
* what was given.
*/
n1 = bitlength / 4;
if (bitlength % 4 != 0)
n1++;
n2 = tbcount / 4;
/* tbcount % 4 == 0 */
if (n1 != n2)
return (DNS_R_BADBITSTRING);
}
n1 = bitlength % vlen;
if (n1 != 0) {
/*
* Are the pad bits in the
* last 'vlen' bits zero?
*/
if ((value &
~((~0) << (vlen-n1))) != 0)
return (DNS_R_BADBITSTRING);
}
} else if (kind == ft_dottedquad)
bitlength = 32;
else if (tbcount > 256)
/*
* This can happen when an octal
* bitstring label of 86 octal digits
* is specified; tbcount will be 258.
* This is not trapped above because
* the bitstring label might be limited
* by a "/256" modifier.
*/
return (DNS_R_BADBITSTRING);
else
bitlength = tbcount;
if (count > 0) {
*ndata++ = value;
nrem--;
nused++;
}
if (kind == ft_dottedquad) {
n1 = bitlength / 8;
if (bitlength % 8 != 0)
n1++;
if (nrem < n1)
return (ISC_R_NOSPACE);
for (n2 = 0; n2 < n1; n2++) {
*ndata++ = dqchars[n2];
nrem--;
nused++;
}
}
if (bitlength == 256)
*label = 0;
else
*label = bitlength;
labels++;
INSIST(labels <= 127);
offsets[labels] = nused;
} else
return (DNS_R_BADBITSTRING);
state = ft_eatdot;
break;
case ft_bitlength:
if (!isdigit(c & 0xff)) {
if (bitlength == 0)
return (DNS_R_BADBITSTRING);
state = ft_finishbitstring;
goto no_read;
}
bitlength *= 10;
bitlength += digitvalue[(int)c];
if (bitlength > maxlength)
return (DNS_R_BADBITSTRING);
break;
case ft_eatdot:
if (c != '.')
return (DNS_R_BADBITSTRING);
if (tlen == 0) {
labels++;
*ndata++ = 0;
nrem--;
nused++;
done = ISC_TRUE;
}
state = ft_start;
break;
default:
FATAL_ERROR(__FILE__, __LINE__,
"Unexpected state %d", state);
/* Does not return. */
}
}
if (!done) {
if (nrem == 0)
return (ISC_R_NOSPACE);
INSIST(tlen == 0);
if (state != ft_ordinary && state != ft_eatdot &&
state != ft_at)
return (ISC_R_UNEXPECTEDEND);
if (state == ft_ordinary) {
INSIST(count != 0);
*label = count;
labels++;
INSIST(labels <= 127);
offsets[labels] = nused;
}
if (origin != NULL) {
if (nrem < origin->length)
return (ISC_R_NOSPACE);
label = origin->ndata;
n1 = origin->length;
nrem -= n1;
while (n1 > 0) {
n2 = *label++;
if (n2 <= 63) {
*ndata++ = n2;
n1 -= n2 + 1;
nused += n2 + 1;
while (n2 > 0) {
c = *label++;
if (downcase)
c = maptolower[(int)c];
*ndata++ = c;
n2--;
}
} else {
INSIST(n2 == DNS_LABELTYPE_BITSTRING);
*ndata++ = n2;
bitlength = *label++;
*ndata++ = bitlength;
if (bitlength == 0)
bitlength = 256;
n2 = bitlength / 8;
if (bitlength % 8 != 0)
n2++;
n1 -= n2 + 2;
nused += n2 + 2;
while (n2 > 0) {
*ndata++ = *label++;
n2--;
}
}
labels++;
if (n1 > 0) {
INSIST(labels <= 127);
offsets[labels] = nused;
}
}
if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
name->attributes |= DNS_NAMEATTR_ABSOLUTE;
}
} else
name->attributes |= DNS_NAMEATTR_ABSOLUTE;
name->ndata = (unsigned char *)target->base + target->used;
name->labels = labels;
name->length = nused;
if (saw_bitstring)
compact(name, offsets);
isc_buffer_forward(source, tused);
isc_buffer_add(target, name->length);
return (ISC_R_SUCCESS);
}
isc_result_t
dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
isc_buffer_t *target)
{
unsigned char *ndata;
char *tdata;
unsigned int nlen, tlen;
unsigned char c;
unsigned int trem, count;
unsigned int bytes, nibbles;
size_t i, len;
unsigned int labels;
isc_boolean_t saw_root = ISC_FALSE;
char num[4];
/*
* This function assumes the name is in proper uncompressed
* wire format.
*/
REQUIRE(VALID_NAME(name));
REQUIRE(name->labels > 0);
ndata = name->ndata;
nlen = name->length;
labels = name->labels;
tdata = (char *)target->base + target->used;
tlen = target->length - target->used;
trem = tlen;
/* Special handling for root label. */
if (nlen == 1 && labels == 1 && *ndata == 0) {
saw_root = ISC_TRUE;
labels = 0;
nlen = 0;
if (trem == 0)
return (ISC_R_NOSPACE);
*tdata++ = '.';
trem--;
omit_final_dot = ISC_FALSE;
}
while (labels > 0 && nlen > 0 && trem > 0) {
labels--;
count = *ndata++;
nlen--;
if (count == 0) {
saw_root = ISC_TRUE;
break;
}
if (count < 64) {
INSIST(nlen >= count);
while (count > 0) {
c = *ndata;
switch (c) {
case 0x22: /* '"' */
case 0x2E: /* '.' */
case 0x3B: /* ';' */
case 0x5C: /* '\\' */
/* Special modifiers in zone files. */
case 0x40: /* '@' */
case 0x24: /* '$' */
if (trem < 2)
return (ISC_R_NOSPACE);
*tdata++ = '\\';
CONVERTFROMASCII(c);
*tdata++ = c;
ndata++;
trem -= 2;
nlen--;
break;
default:
if (c > 0x20 && c < 0x7f) {
if (trem == 0)
return (ISC_R_NOSPACE);
CONVERTFROMASCII(c);
*tdata++ = c;
ndata++;
trem--;
nlen--;
} else {
if (trem < 4)
return (ISC_R_NOSPACE);
sprintf(tdata, "\\%03u",
c);
tdata += 4;
trem -= 4;
ndata++;
nlen--;
}
}
count--;
}
} else if (count == DNS_LABELTYPE_BITSTRING) {
if (trem < 3)
return (ISC_R_NOSPACE);
*tdata++ = '\\';
*tdata++ = '[';
*tdata++ = 'x';
trem -= 3;
INSIST(nlen > 0);
count = *ndata++;
if (count == 0)
count = 256;
nlen--;
len = sprintf(num, "%u", count); /* XXX */
INSIST(len <= 4);
bytes = count / 8;
if (count % 8 != 0)
bytes++;
INSIST(nlen >= bytes);
nibbles = count / 4;
if (count % 4 != 0)
nibbles++;
if (trem < nibbles)
return (ISC_R_NOSPACE);
trem -= nibbles;
nlen -= bytes;
while (nibbles > 0) {
c = *ndata++;
*tdata++ = hexdigits[(c >> 4)];
nibbles--;
if (nibbles != 0) {
*tdata++ = hexdigits[c & 0xf];
i++;
nibbles--;
}
}
if (trem < 2 + len)
return (ISC_R_NOSPACE);
*tdata++ = '/';
for (i = 0; i < len; i++)
*tdata++ = num[i];
*tdata++ = ']';
trem -= 2 + len;
} else {
FATAL_ERROR(__FILE__, __LINE__,
"Unexpected label type %02x", count);
/* Does not return. */
}
/*
* The following assumes names are absolute. If not, we
* fix things up later. Note that this means that in some
* cases one more byte of text buffer is required than is
* needed in the final output.
*/
if (trem == 0)
return (ISC_R_NOSPACE);
*tdata++ = '.';
trem--;
}
if (nlen != 0 && trem == 0)
return (ISC_R_NOSPACE);
INSIST(nlen == 0);
if (!saw_root || omit_final_dot)
trem++;
isc_buffer_add(target, tlen - trem);
return (ISC_R_SUCCESS);
}
isc_result_t
dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) {
unsigned char *sndata, *ndata;
unsigned int nlen, count, bytes, labels;
isc_buffer_t buffer;
/*
* Downcase 'source'.
*/
REQUIRE(VALID_NAME(source));
REQUIRE(VALID_NAME(name));
if (source == name) {
REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0);
isc_buffer_init(&buffer, source->ndata, source->length);
target = &buffer;
ndata = source->ndata;
} else {
REQUIRE(BINDABLE(name));
if (target == NULL && name->buffer != NULL) {
target = name->buffer;
isc_buffer_clear(name->buffer);
}
ndata = (unsigned char *)target->base + target->used;
name->ndata = ndata;
}
sndata = source->ndata;
nlen = source->length;
labels = source->labels;
if (nlen > (target->length - target->used)) {
MAKE_EMPTY(name);
return (ISC_R_NOSPACE);
}
while (labels > 0 && nlen > 0) {
labels--;
count = *sndata++;
*ndata++ = count;
nlen--;
if (count < 64) {
INSIST(nlen >= count);
while (count > 0) {
*ndata++ = maptolower[(*sndata++)];
nlen--;
count--;
}
} else if (count == DNS_LABELTYPE_BITSTRING) {
INSIST(nlen > 0);
count = *sndata++;
*ndata++ = count;
if (count == 0)
count = 256;
nlen--;
bytes = count / 8;
if (count % 8 != 0)
bytes++;
INSIST(nlen >= bytes);
nlen -= bytes;
while (bytes > 0) {
*ndata++ = *sndata++;
bytes--;
}
} else {
FATAL_ERROR(__FILE__, __LINE__,
"Unexpected label type %02x", count);
/* Does not return. */
}
}
if (source != name) {
name->labels = source->labels;
name->length = source->length;
if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
name->attributes = DNS_NAMEATTR_ABSOLUTE;
else
name->attributes = 0;
if (name->labels > 0 && name->offsets != NULL)
set_offsets(name, name->offsets, NULL);
}
isc_buffer_add(target, name->length);
return (ISC_R_SUCCESS);
}
static void
set_offsets(const dns_name_t *name, unsigned char *offsets,
dns_name_t *set_name)
{
unsigned int offset, count, length, nlabels, n;
unsigned char *ndata;
isc_boolean_t absolute;
ndata = name->ndata;
length = name->length;
offset = 0;
nlabels = 0;
absolute = ISC_FALSE;
while (offset != length) {
INSIST(nlabels < 128);
offsets[nlabels++] = offset;
count = *ndata++;
offset++;
if (count <= 63) {
offset += count;
ndata += count;
INSIST(offset <= length);
if (count == 0) {
absolute = ISC_TRUE;
break;
}
} else {
INSIST(count == DNS_LABELTYPE_BITSTRING);
n = *ndata++;
offset++;
if (n == 0)
n = 256;
count = n / 8;
if (n % 8 != 0)
count++;
offset += count;
ndata += count;
INSIST(offset <= length);
}
}
if (set_name != NULL) {
INSIST(set_name == name);
set_name->labels = nlabels;
set_name->length = offset;
if (absolute)
set_name->attributes |= DNS_NAMEATTR_ABSOLUTE;
else
set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
}
INSIST(nlabels == name->labels);
INSIST(offset == name->length);
}
static void
compact(dns_name_t *name, unsigned char *offsets) {
unsigned char *head, *curr, *last;
unsigned int count, n, bit;
unsigned int headbits, currbits, tailbits, newbits;
unsigned int headrem, newrem;
unsigned int headindex, currindex, tailindex, newindex;
unsigned char tail[32];
/*
* The caller MUST ensure that all bitstrings are correctly formatted
* and that the offsets table is valid.
*/
again:
memset(tail, 0, sizeof tail);
INSIST(name->labels != 0);
n = name->labels - 1;
while (n > 0) {
head = &name->ndata[offsets[n]];
if (head[0] == DNS_LABELTYPE_BITSTRING && head[1] != 0) {
if (n != 0) {
n--;
curr = &name->ndata[offsets[n]];
if (curr[0] != DNS_LABELTYPE_BITSTRING)
continue;
/*
* We have consecutive bitstrings labels, and
* the more significant label ('head') has
* space.
*/
currbits = curr[1];
if (currbits == 0)
currbits = 256;
currindex = 0;
headbits = head[1];
if (headbits == 0)
headbits = 256;
headindex = headbits;
count = 256 - headbits;
if (count > currbits)
count = currbits;
headrem = headbits % 8;
if (headrem != 0)
headrem = 8 - headrem;
if (headrem != 0) {
if (headrem > count)
headrem = count;
do {
bit = get_bit(&curr[2],
currindex);
set_bit(&head[2], headindex,
bit);
currindex++;
headindex++;
headbits++;
count--;
headrem--;
} while (headrem != 0);
}
tailindex = 0;
tailbits = 0;
while (count > 0) {
bit = get_bit(&curr[2], currindex);
set_bit(tail, tailindex, bit);
currindex++;
tailindex++;
tailbits++;
count--;
}
newbits = 0;
newindex = 0;
if (currindex < currbits) {
while (currindex < currbits) {
bit = get_bit(&curr[2],
currindex);
set_bit(&curr[2], newindex,
bit);
currindex++;
newindex++;
newbits++;
}
INSIST(newbits < 256);
curr[1] = newbits;
count = newbits / 8;
newrem = newbits % 8;
/* Zero remaining pad bits, if any. */
if (newrem != 0) {
count++;
newrem = 8 - newrem;
while (newrem > 0) {
set_bit(&curr[2],
newindex,
0);
newrem--;
newindex++;
}
}
curr += count + 2;
} else {
/* We got rid of curr. */
name->labels--;
}
/* copy head, then tail, then rest to curr. */
count = headbits + tailbits;
INSIST(count <= 256);
curr[0] = DNS_LABELTYPE_BITSTRING;
if (count == 256)
curr[1] = 0;
else
curr[1] = count;
curr += 2;
head += 2;
count = headbits / 8;
if (headbits % 8 != 0)
count++;
while (count > 0) {
*curr++ = *head++;
count--;
}
count = tailbits / 8;
if (tailbits % 8 != 0)
count++;
last = tail;
while (count > 0) {
*curr++ = *last++;
count--;
}
last = name->ndata + name->length;
while (head != last)
*curr++ = *head++;
name->length = (curr - name->ndata);
/*
* The offsets table may now be invalid.
*/
set_offsets(name, offsets, NULL);
goto again;
}
}
n--;
}
}
isc_result_t
dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
dns_decompress_t *dctx, isc_boolean_t downcase,
isc_buffer_t *target)
{
unsigned char *cdata, *ndata;
unsigned int cused; /* Bytes of compressed name data used */
unsigned int hops, nused, labels, n, nmax;
unsigned int current, new_current, biggest_pointer;
isc_boolean_t saw_bitstring, done;
fw_state state = fw_start;
unsigned int c;
unsigned char *offsets;
dns_offsets_t odata;
/*
* Copy the possibly-compressed name at source into target,
* decompressing it.
*/
REQUIRE(VALID_NAME(name));
if (target == NULL && name->buffer != NULL) {
target = name->buffer;
isc_buffer_clear(target);
}
REQUIRE(dctx != NULL);
REQUIRE(BINDABLE(name));
INIT_OFFSETS(name, offsets, odata);
/*
* Make 'name' empty in case of failure.
*/
MAKE_EMPTY(name);
/*
* Initialize things to make the compiler happy; they're not required.
*/
n = 0;
new_current = 0;
/*
* Set up.
*/
labels = 0;
hops = 0;
saw_bitstring = ISC_FALSE;
done = ISC_FALSE;
ndata = isc_buffer_used(target);
nused = 0;
/*
* Find the maximum number of uncompressed target name
* bytes we are willing to generate. This is the smaller
* of the available target buffer length and the
* maximum legal domain name length (255).
*/
nmax = isc_buffer_availablelength(target);
if (nmax > 255)
nmax = 255;
cdata = isc_buffer_current(source);
cused = 0;
current = source->current;
biggest_pointer = current;
/*
* Note: The following code is not optimized for speed, but
* rather for correctness. Speed will be addressed in the future.
*/
while (current < source->active && !done) {
c = *cdata++;
current++;
if (hops == 0)
cused++;
switch (state) {
case fw_start:
if (c < 64) {
labels++;
if (nused + c + 1 > nmax)
goto full;
nused += c + 1;
*ndata++ = c;
if (c == 0)
done = ISC_TRUE;
n = c;
state = fw_ordinary;
} else if (c >= 128 && c < 192) {
/*
* 14 bit local compression pointer.
* Local compression is no longer an
* IETF draft.
*/
return (DNS_R_BADLABELTYPE);
} else if (c >= 192) {
/*
* Ordinary 14-bit pointer.
*/
if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
0)
return (DNS_R_DISALLOWED);
new_current = c & 0x3F;
n = 1;
state = fw_newcurrent;
} else if (c == DNS_LABELTYPE_BITSTRING) {
labels++;
if (nused == nmax)
goto full;
nused++;
*ndata++ = c;
saw_bitstring = ISC_TRUE;
state = fw_bitstring;
} else if (c == DNS_LABELTYPE_GLOBALCOMP16) {
/*
* 16-bit pointer.
*/
if ((dctx->allowed & DNS_COMPRESS_GLOBAL16) ==
0)
return (DNS_R_DISALLOWED);
new_current = 0;
n = 2;
state = fw_newcurrent;
} else
return (DNS_R_BADLABELTYPE);
break;
case fw_ordinary:
if (downcase)
c = maptolower[c];
/* FALLTHROUGH */
case fw_copy:
*ndata++ = c;
n--;
if (n == 0)
state = fw_start;
break;
case fw_bitstring:
if (c == 0)
n = 256 / 8;
else
n = c / 8;
if ((c % 8) != 0)
n++;
if (nused + n + 1 > nmax)
goto full;
nused += n + 1;
*ndata++ = c;
state = fw_copy;
break;
case fw_newcurrent:
new_current *= 256;
new_current += c;
n--;
if (n != 0)
break;
if (new_current >= biggest_pointer)
return (DNS_R_BADPOINTER);
biggest_pointer = new_current;
current = new_current;
cdata = (unsigned char *)source->base +
current;
hops++;
if (hops > DNS_POINTER_MAXHOPS)
return (DNS_R_TOOMANYHOPS);
state = fw_start;
break;
default:
FATAL_ERROR(__FILE__, __LINE__,
"Unknown state %d", state);
/* Does not return. */
}
}
if (!done)
return (ISC_R_UNEXPECTEDEND);
name->ndata = (unsigned char *)target->base + target->used;
name->labels = labels;
name->length = nused;
name->attributes |= DNS_NAMEATTR_ABSOLUTE;
/*
* We should build the offsets table directly.
*/
if (name->offsets != NULL || saw_bitstring)
set_offsets(name, offsets, NULL);
if (saw_bitstring)
compact(name, offsets);
isc_buffer_forward(source, cused);
isc_buffer_add(target, name->length);
return (ISC_R_SUCCESS);
full:
if (nmax == 255)
/*
* The name did not fit even though we had a buffer
* big enough to fit a maximum-length name.
*/
return (DNS_R_FORMERR);
else
/*
* The name might fit if only the caller could give us a
* big enough buffer.
*/
return (ISC_R_NOSPACE);
}
isc_result_t
dns_name_towire(dns_name_t *name, dns_compress_t *cctx, isc_buffer_t *target) {
unsigned int methods;
isc_uint16_t offset;
dns_name_t gp, gs;
isc_boolean_t gf;
isc_uint16_t go;
unsigned char gb[257];
isc_buffer_t gws;
dns_offsets_t po, so, clo;
dns_name_t clname;
/*
* Convert 'name' into wire format, compressing it as specified by the
* compression context 'cctx', and storing the result in 'target'.
*/
REQUIRE(VALID_NAME(name));
REQUIRE(cctx != NULL);
/*
* If 'name' doesn't have an offsets table, make a clone which
* has one.
*/
if (name->offsets == NULL) {
dns_name_init(&clname, clo);
dns_name_clone(name, &clname);
name = &clname;
}
dns_name_init(&gp, po);
dns_name_init(&gs, so);
isc_buffer_init(&gws, gb, sizeof (gb));
offset = target->used; /*XXX*/
methods = dns_compress_getmethods(cctx);
if ((methods & DNS_COMPRESS_GLOBAL) != 0)
gf = dns_compress_findglobal(cctx, name, &gp, &gs, &go, &gws);
else
gf = ISC_FALSE;
/*
* Will the compression pointer reduce the message size?
*/
if (gf && (gp.length + ((go < 16384) ? 2 : 3)) >= name->length)
gf = ISC_FALSE;
if (gf) {
if (target->length - target->used < gp.length)
return (ISC_R_NOSPACE);
(void)memcpy((unsigned char *)target->base + target->used,
gp.ndata, (size_t)gp.length);
isc_buffer_add(target, gp.length);
if (go < 16384) {
go |= 0xc000;
if (target->length - target->used < 2)
return (ISC_R_NOSPACE);
isc_buffer_putuint16(target, go);
} else {
if (target->length - target->used < 3)
return (ISC_R_NOSPACE);
*((unsigned char*)target->base + target->used) =
DNS_LABELTYPE_GLOBALCOMP16;
isc_buffer_add(target, 1);
isc_buffer_putuint16(target, go);
}
if (gp.length != 0)
dns_compress_add(cctx, &gp, &gs, offset);
} else {
if (target->length - target->used < name->length)
return (ISC_R_NOSPACE);
(void)memcpy((unsigned char *)target->base + target->used,
name->ndata, (size_t)name->length);
isc_buffer_add(target, name->length);
dns_compress_add(cctx, name, NULL, offset);
}
return (ISC_R_SUCCESS);
}
isc_result_t
dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
isc_buffer_t *target)
{
unsigned char *ndata, *offsets;
unsigned int nrem, labels, prefix_length, length, offset;
isc_boolean_t copy_prefix = ISC_TRUE;
isc_boolean_t copy_suffix = ISC_TRUE;
isc_boolean_t saw_bitstring = ISC_FALSE;
isc_boolean_t absolute = ISC_FALSE;
dns_name_t tmp_name;
dns_offsets_t odata;
/*
* Concatenate 'prefix' and 'suffix'.
*/
REQUIRE(prefix == NULL || VALID_NAME(prefix));
REQUIRE(suffix == NULL || VALID_NAME(suffix));
REQUIRE(name == NULL || VALID_NAME(name));
if (prefix == NULL || prefix->labels == 0)
copy_prefix = ISC_FALSE;
if (suffix == NULL || suffix->labels == 0)
copy_suffix = ISC_FALSE;
if (copy_prefix &&
(prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
absolute = ISC_TRUE;
REQUIRE(!copy_suffix);
}
if (name == NULL) {
dns_name_init(&tmp_name, odata);
name = &tmp_name;
}
if (target == NULL && name->buffer != NULL) {
target = name->buffer;
isc_buffer_clear(name->buffer);
}
REQUIRE(BINDABLE(name));
/*
* IMPORTANT NOTE
*
* If the most-signficant label in prefix is a bitstring,
* and the least-signficant label in suffix is a bitstring,
* it's possible that compaction could convert them into
* one label. If this happens, then the final size will
* be three bytes less than nrem.
*
* We do not check for this special case, and handling it is
* a little messy; we can't just concatenate and compact,
* because we may only have 255 bytes but might need 258 bytes
* temporarily. There are ways to do this with only 255 bytes,
* which will be implemented later.
*
* For now, we simply reject these few cases as being too
* long.
*/
/*
* Set up.
*/
nrem = target->length - target->used;
ndata = (unsigned char *)target->base + target->used;
if (nrem > 255)
nrem = 255;
length = 0;
prefix_length = 0;
labels = 0;
if (copy_prefix) {
prefix_length = prefix->length;
length += prefix_length;
labels += prefix->labels;
}
if (copy_suffix) {
length += suffix->length;
labels += suffix->labels;
}
if (length > nrem) {
MAKE_EMPTY(name);
return (ISC_R_NOSPACE);
}
if (copy_suffix) {
if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
absolute = ISC_TRUE;
if (copy_prefix &&
suffix->ndata[0] == DNS_LABELTYPE_BITSTRING) {
/*
* We only need to call compact() if both the
* least-significant label of the suffix and the
* most-significant label of the prefix are both
* bitstrings.
*
* A further possible optimization, which we don't do,
* is to not compact() if the suffix bitstring is
* full. It will usually not be full, so I don't
* think this is worth it.
*/
if (prefix->offsets != NULL) {
offset = prefix->offsets[prefix->labels - 1];
if (prefix->ndata[offset] ==
DNS_LABELTYPE_BITSTRING)
saw_bitstring = ISC_TRUE;
} else {
/*
* We don't have an offsets table for prefix,
* and rather than spend the effort to make it
* we'll just compact(), which doesn't cost
* more than computing the offsets table if
* there is no bitstring in prefix.
*/
saw_bitstring = ISC_TRUE;
}
}
if (suffix == name && suffix->buffer == target)
memmove(ndata + prefix_length, suffix->ndata,
suffix->length);
else
memcpy(ndata + prefix_length, suffix->ndata,
suffix->length);
}
/*
* If 'prefix' and 'name' are the same object, and the object has
* a dedicated buffer, and we're using it, then we don't have to
* copy anything.
*/
if (copy_prefix && (prefix != name || prefix->buffer != target))
memcpy(ndata, prefix->ndata, prefix_length);
name->ndata = ndata;
name->labels = labels;
name->length = length;
if (absolute)
name->attributes = DNS_NAMEATTR_ABSOLUTE;
else
name->attributes = 0;
if (name->labels > 0 && (name->offsets != NULL || saw_bitstring)) {
INIT_OFFSETS(name, offsets, odata);
set_offsets(name, offsets, NULL);
if (saw_bitstring)
compact(name, offsets);
}
isc_buffer_add(target, name->length);
return (ISC_R_SUCCESS);
}
isc_result_t
dns_name_split(dns_name_t *name,
unsigned int suffixlabels, unsigned int nbits,
dns_name_t *prefix, dns_name_t *suffix)
{
dns_offsets_t name_odata, split_odata;
unsigned char *offsets, *splitoffsets;
isc_result_t result = ISC_R_SUCCESS;
unsigned int splitlabel, bitbytes, mod, len;
unsigned char *p, *src, *dst;
REQUIRE(VALID_NAME(name));
REQUIRE((nbits == 0 &&
suffixlabels > 0 && suffixlabels < name->labels) ||
(nbits != 0 &&
suffixlabels <= name->labels));
REQUIRE(prefix != NULL || suffix != NULL);
REQUIRE(prefix == NULL ||
(VALID_NAME(prefix) &&
prefix->buffer != NULL &&
BINDABLE(prefix)));
REQUIRE(suffix == NULL ||
(VALID_NAME(suffix) &&
suffix->buffer != NULL &&
BINDABLE(suffix)));
/*
* When splitting bitstring labels, if prefix and suffix have the same
* buffer, suffix will overwrite the ndata of prefix, corrupting it.
* If prefix has the ndata of name, then it modifies the bitstring
* label and suffix doesn't have the original available. This latter
* problem could be worked around if it is ever deemed desirable.
*/
REQUIRE(nbits == 0 || prefix == NULL || suffix == NULL ||
(prefix->buffer->base != suffix->buffer->base &&
prefix->buffer->base != name->ndata));
SETUP_OFFSETS(name, offsets, name_odata);
splitlabel = name->labels - suffixlabels;
p = &name->ndata[offsets[splitlabel] + 1];
/*
* When a bit count is specified, ensure that the label is a bitstring
* label and it has more bits than the requested slice.
*/
REQUIRE(nbits == 0 ||
(*(p - 1) == DNS_LABELTYPE_BITSTRING && nbits < 256 &&
(*p == 0 || *p > nbits)));
mod = nbits % 8;
if (prefix != NULL) {
if (nbits > 0) {
isc_buffer_clear(prefix->buffer);
/*
* '2' is for the DNS_LABELTYPE_BITSTRING id
* plus the existing number of bits byte.
*/
len = offsets[splitlabel] + 2;
src = name->ndata;
dst = prefix->buffer->base;
if (src != dst) {
/*
* If these are overlapping names ...
* wow. How bizarre could that be?
*/
INSIST(! (src <= dst && src + len > dst) ||
(dst <= src && dst + len > src));
memcpy(dst, src, len);
p = dst + len - 1;
}
/*
* Set the new bit count.
*/
if (*p == 0)
*p = 256 - nbits;
else
*p = *p - nbits;
/*
* Really one less than the bytes for the bits.
*/
bitbytes = (*p - 1) / 8 + 1;
prefix->length = len + bitbytes;
if (prefix->length > prefix->buffer->length ) {
dns_name_invalidate(prefix);
return(ISC_R_NOSPACE);
}
/*
* All of the bits now need to be shifted to the left
* to fill in the space taken by the removed bits.
* This is wonderfully easy when the number of removed
* bits is an integral multiple of 8, but of course
* life isn't always that easy.
*/
src += len + nbits / 8;
dst = p + 1;
len = bitbytes;
if (mod == 0) {
if ((void *)(name->ndata) ==
prefix->buffer->base &&
len > (unsigned int)(src - dst))
memmove(dst, src, len);
else
memcpy(dst, src, len);
} else {
while (len--) {
*dst = *src++ << mod;
/*
* The 0xff subexpression guards
* against arithmetic sign extension
* by the right shift.
*/
if (len > 0)
*dst++ |=
(*src >> (8 - mod)) &
~(0xFF << mod);
}
/*
* Et voila, the very last byte has
* automatically already had its padding
* fixed by the left shift.
*/
}
prefix->buffer->used = prefix->length;
prefix->ndata = prefix->buffer->base;
/*
* Yes, = is meant here, not ==. The intent is
* to have it set only when INSISTs are turned on,
* to doublecheck the result of set_offsets.
*/
INSIST(len = prefix->length);
INIT_OFFSETS(prefix, splitoffsets, split_odata);
set_offsets(prefix, splitoffsets, prefix);
INSIST(prefix->labels == splitlabel + 1 &&
prefix->length == len);
} else
dns_name_getlabelsequence(name, 0, splitlabel,
prefix);
}
if (suffix != NULL && result == ISC_R_SUCCESS) {
if (nbits > 0) {
bitbytes = (nbits - 1) / 8 + 1;
isc_buffer_clear(suffix->buffer);
/*
* The existing bitcount is in src.
* Set len to the number of bytes to be removed,
* and the suffix length to the number of bytes in
* the new name.
*/
src = &name->ndata[offsets[splitlabel] + 1];
len = (*src++ - 1) / 8 - (bitbytes - 1);
suffix->length = name->length -
offsets[splitlabel] - len;
INSIST(suffix->length > 0);
if (suffix->length > suffix->buffer->length) {
dns_name_invalidate(suffix);
return (ISC_R_NOSPACE);
}
/*
* First set up the bitstring label.
*/
dst = suffix->buffer->base;
*dst++ = DNS_LABELTYPE_BITSTRING;
*dst++ = nbits;
if (len > 0) {
/*
* Remember where the next label starts.
*/
p = src + bitbytes + len;
/*
* Some bytes are being removed from the
* middle of the name because of the truncation
* of bits in the bitstring label. Copy
* the bytes (whether full with 8 bits or not)
* that are being kept.
*/
for (len = bitbytes; len > 0; len--)
*dst++ = *src++;
/*
* Now just copy the rest of the labels of
* the name by adjusting src to point to
* the next label.
*
* 2 == label type byte + bitcount byte.
*/
len = suffix->length - bitbytes - 2;
src = p;
} else
len = suffix->length - 2;
/*
* XXX DCL better way to decide memcpy vs memmove?
*/
if (len > 0) {
if ((dst <= src && dst + len > src) ||
(src <= dst && src + len > dst))
memmove(dst, src, len);
else
memcpy(dst, src, len);
}
suffix->buffer->used = suffix->length;
suffix->ndata = suffix->buffer->base;
/*
* The byte that contains the end of the
* bitstring has its pad bytes (if any) masked
* to zero.
*/
if (mod)
suffix->ndata[bitbytes + 1] &=
0xFF << (8 - mod);
/*
* Yes, = is meant here, not ==. The intent is
* to have it set only when INSISTs are turned on,
* to doublecheck the result of set_offsets.
*/
INSIST(len = suffix->length);
INIT_OFFSETS(suffix, splitoffsets, split_odata);
set_offsets(suffix, splitoffsets, suffix);
INSIST(suffix->labels == suffixlabels &&
suffix->length == len);
} else
dns_name_getlabelsequence(name, splitlabel,
suffixlabels, suffix);
}
return (result);
}
isc_result_t
dns_name_splitatdepth(dns_name_t *name, unsigned int depth,
dns_name_t *prefix, dns_name_t *suffix)
{
unsigned int suffixlabels, nbits, label, count, n;
unsigned char *offsets, *ndata;
dns_offsets_t odata;
/*
* Split 'name' into two pieces at a certain depth.
*/
REQUIRE(VALID_NAME(name));
REQUIRE(name->labels > 0);
REQUIRE(depth > 0);
SETUP_OFFSETS(name, offsets, odata);
suffixlabels = 0;
nbits = 0;
label = name->labels;
do {
label--;
ndata = &name->ndata[offsets[label]];
count = *ndata++;
if (count > 63) {
INSIST(count == DNS_LABELTYPE_BITSTRING);
/*
* Get the number of bits in the bitstring label.
*/
n = *ndata++;
if (n == 0)
n = 256;
suffixlabels++;
if (n <= depth) {
/*
* This entire bitstring is in the suffix.
*/
depth -= n;
} else {
/*
* Only the first 'depth' bits of this
* bitstring are in the suffix.
*/
nbits = depth;
depth = 0;
}
} else {
suffixlabels++;
depth--;
}
} while (depth != 0 && label != 0);
/*
* If depth is not zero, then the caller violated the requirement
* that depth <= dns_name_depth(name).
*/
if (depth != 0) {
REQUIRE(depth <= dns_name_depth(name));
/*
* We should never get here!
*/
INSIST(0);
}
return (dns_name_split(name, suffixlabels, nbits, prefix, suffix));
}
isc_result_t
dns_name_dup(dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) {
/*
* Make 'target' a dynamically allocated copy of 'source'.
*/
REQUIRE(VALID_NAME(source));
REQUIRE(source->length > 0);
REQUIRE(VALID_NAME(target));
REQUIRE(BINDABLE(target));
/*
* Make 'target' empty in case of failure.
*/
MAKE_EMPTY(target);
target->ndata = isc_mem_get(mctx, source->length);
if (target->ndata == NULL)
return (ISC_R_NOMEMORY);
memcpy(target->ndata, source->ndata, source->length);
target->length = source->length;
target->labels = source->labels;
target->attributes = DNS_NAMEATTR_DYNAMIC;
if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
target->attributes |= DNS_NAMEATTR_ABSOLUTE;
if (target->offsets != NULL) {
if (source->offsets != NULL)
memcpy(target->offsets, source->offsets,
source->labels);
else
set_offsets(target, target->offsets, NULL);
}
return (ISC_R_SUCCESS);
}
isc_result_t
dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
dns_name_t *target)
{
/*
* Make 'target' a read-only dynamically allocated copy of 'source'.
* 'target' will also have a dynamically allocated offsets table.
*/
REQUIRE(VALID_NAME(source));
REQUIRE(source->length > 0);
REQUIRE(VALID_NAME(target));
REQUIRE(BINDABLE(target));
REQUIRE(target->offsets == NULL);
/*
* Make 'target' empty in case of failure.
*/
MAKE_EMPTY(target);
target->ndata = isc_mem_get(mctx, source->length + source->labels);
if (target->ndata == NULL)
return (ISC_R_NOMEMORY);
memcpy(target->ndata, source->ndata, source->length);
target->length = source->length;
target->labels = source->labels;
target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
DNS_NAMEATTR_READONLY;
if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
target->attributes |= DNS_NAMEATTR_ABSOLUTE;
target->offsets = target->ndata + source->length;
if (source->offsets != NULL)
memcpy(target->offsets, source->offsets, source->labels);
else
set_offsets(target, target->offsets, NULL);
return (ISC_R_SUCCESS);
}
void
dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
size_t size;
/*
* Free 'name'.
*/
REQUIRE(VALID_NAME(name));
REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
size = name->length;
if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0)
size += name->labels;
isc_mem_put(mctx, name->ndata, size);
dns_name_invalidate(name);
}
isc_result_t
dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) {
dns_name_t downname;
unsigned char data[256];
isc_buffer_t buffer;
isc_result_t result;
isc_region_t r;
/*
* Send 'name' in DNSSEC canonical form to 'digest'.
*/
REQUIRE(VALID_NAME(name));
REQUIRE(digest != NULL);
dns_name_init(&downname, NULL);
isc_buffer_init(&buffer, data, sizeof(data));
result = dns_name_downcase(name, &downname, &buffer);
if (result != ISC_R_SUCCESS)
return (result);
isc_buffer_usedregion(&buffer, &r);
return ((digest)(arg, &r));
}
isc_boolean_t
dns_name_dynamic(dns_name_t *name) {
REQUIRE(VALID_NAME(name));
/*
* Returns whether there is dynamic memory associated with this name.
*/
return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
ISC_TRUE : ISC_FALSE);
}
isc_result_t
dns_name_print(dns_name_t *name, FILE *stream) {
isc_result_t result;
isc_buffer_t b;
isc_region_t r;
char t[1024];
/*
* Print 'name' on 'stream'.
*/
REQUIRE(VALID_NAME(name));
isc_buffer_init(&b, t, sizeof(t));
result = dns_name_totext(name, ISC_FALSE, &b);
if (result != ISC_R_SUCCESS)
return (result);
isc_buffer_usedregion(&b, &r);
fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
return (ISC_R_SUCCESS);
}
void
dns_name_format(dns_name_t *name, char *cp, unsigned int size) {
isc_result_t result;
isc_buffer_t buf;
REQUIRE(size > 0);
/*
* Leave room for null termination after buffer.
*/
isc_buffer_init(&buf, cp, size - 1);
result = dns_name_totext(name, ISC_TRUE, &buf);
if (result == ISC_R_SUCCESS) {
/*
* Null terminate.
*/
isc_region_t r;
isc_buffer_usedregion(&buf, &r);
((char *) r.base)[r.length] = '\0';
} else
snprintf(cp, size, "<unknown>");
}