name.c revision 6585d8782b2e20caf7b71f264afa4beb8a3fdf98
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson/*
499b34cea04a46823d003d4c0520c8b03e8513cbBrian Wellington * Copyright (C) 1998-2001 Internet Software Consortium.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson * Permission to use, copy, modify, and distribute this software for any
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson * purpose with or without fee is hereby granted, provided that the above
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson * copyright notice and this permission notice appear in all copies.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
15a44745412679c30a6d022733925af70a38b715David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
15a44745412679c30a6d022733925af70a38b715David Lawrence * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
15a44745412679c30a6d022733925af70a38b715David Lawrence * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
15a44745412679c30a6d022733925af70a38b715David Lawrence * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
15a44745412679c30a6d022733925af70a38b715David Lawrence * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
15a44745412679c30a6d022733925af70a38b715David Lawrence * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15a44745412679c30a6d022733925af70a38b715David Lawrence * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
15a44745412679c30a6d022733925af70a38b715David Lawrence * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson */
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence/* $Id: name.c,v 1.133 2002/03/14 00:36:06 bwelling Exp $ */
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson#include <config.h>
f80ea74e1984e0b1dbe48dd86ecdd3a2380393cbBob Halley
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <ctype.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence
fc8a6561cbb0a1fea849950a3217aacd3b8f1eacDavid Lawrence#include <isc/buffer.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <isc/mem.h>
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson#include <isc/print.h>
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson#include <isc/string.h>
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson#include <isc/util.h>
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson#include <dns/compress.h>
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson#include <dns/name.h>
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson#include <dns/result.h>
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington
09f22ac5b09e70bc526015f37168ba33e21ea91fDavid Lawrence#define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencetypedef enum {
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence ft_init = 0,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson ft_start,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson ft_ordinary,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson ft_initialescape,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson ft_escape,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson ft_escdecimal,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson ft_bitstring,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson ft_binary,
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence ft_octal,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson ft_hex,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson ft_dottedquad,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson ft_dqdecimal,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson ft_maybeslash,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson ft_finishbitstring,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson ft_bitlength,
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence ft_eatdot,
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence ft_at
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson} ft_state;
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencetypedef enum {
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence fw_start = 0,
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence fw_ordinary,
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson fw_copy,
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington fw_bitstring,
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson fw_newcurrent
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson} fw_state;
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafssonstatic char digitvalue[256] = {
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
8f79820c6930ee5ef6b4a54f36d2559400bdf47dAndreas Gustafsson -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson};
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssonstatic char hexdigits[16] = {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence '0', '1', '2', '3', '4', '5', '6', '7',
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson};
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssonstatic unsigned char maptolower[] = {
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson};
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson#define CONVERTTOASCII(c)
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews#define CONVERTFROMASCII(c)
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews#define INIT_OFFSETS(name, var, default) \
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if (name->offsets != NULL) \
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson var = name->offsets; \
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson else \
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence var = default;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson#define SETUP_OFFSETS(name, var, default) \
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson if (name->offsets != NULL) \
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson var = name->offsets; \
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson else { \
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson var = default; \
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson set_offsets(name, var, NULL); \
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson }
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson/*
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson * Note: If additional attributes are added that should not be set for
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson * empty names, MAKE_EMPTY() must be changed so it clears them.
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson */
f80ea74e1984e0b1dbe48dd86ecdd3a2380393cbBob Halley#define MAKE_EMPTY(name) \
f80ea74e1984e0b1dbe48dd86ecdd3a2380393cbBob Halleydo { \
f80ea74e1984e0b1dbe48dd86ecdd3a2380393cbBob Halley name->ndata = NULL; \
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson name->length = 0; \
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson name->labels = 0; \
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson} while (0);
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson/*
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson * A name is "bindable" if it can be set to point to a new value, i.e.
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson * name->ndata and name->length may be changed.
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson */
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington#define BINDABLE(name) \
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington ((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington == 0)
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington/*
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington * Note that the name data must be a char array, not a string
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington * literal, to avoid compiler warnings about discarding
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington * the const attribute of a string.
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington */
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssonstatic unsigned char root_ndata[] = { '\0' };
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssonstatic unsigned char root_offsets[] = { 0 };
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssonstatic dns_name_t root =
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson{
a6733246eafeb43755ce6d7ec3627ac4209cbccbMark Andrews DNS_NAME_MAGIC,
a6733246eafeb43755ce6d7ec3627ac4209cbccbMark Andrews root_ndata, 1, 1,
a6733246eafeb43755ce6d7ec3627ac4209cbccbMark Andrews DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson root_offsets, NULL,
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington {(void *)-1, (void *)-1},
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson {NULL, NULL}
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence};
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson/* XXXDCL make const? */
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas GustafssonLIBDNS_EXTERNAL_DATA dns_name_t *dns_rootname = &root;
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafssonstatic unsigned char wild_ndata[] = { '\001', '*' };
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graffstatic unsigned char wild_offsets[] = { 0 };
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssonstatic dns_name_t wild =
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson{
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson DNS_NAME_MAGIC,
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson wild_ndata, 2, 1,
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson DNS_NAMEATTR_READONLY,
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson wild_offsets, NULL,
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington {(void *)-1, (void *)-1},
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington {NULL, NULL}
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington};
5e387b9ce6bafdfadedb5b34e4c33a4404e5d589Brian Wellington
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson/* XXXDCL make const? */
f80ea74e1984e0b1dbe48dd86ecdd3a2380393cbBob HalleyLIBDNS_EXTERNAL_DATA dns_name_t *dns_wildcardname = &wild;
f80ea74e1984e0b1dbe48dd86ecdd3a2380393cbBob Halley
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafssonstatic void
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssonset_offsets(const dns_name_t *name, unsigned char *offsets,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson dns_name_t *set_name);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssonstatic void
f80ea74e1984e0b1dbe48dd86ecdd3a2380393cbBob Halleycompact(dns_name_t *name, unsigned char *offsets);
f80ea74e1984e0b1dbe48dd86ecdd3a2380393cbBob Halley
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson/*
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson * Yes, get_bit and set_bit are lame. We define them here so they can
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson * be inlined by smart compilers.
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews */
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafssonstatic inline unsigned int
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafssonget_bit(unsigned char *array, unsigned int idx) {
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson unsigned int byte, shift;
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews byte = array[idx / 8];
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews shift = 7 - (idx % 8);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson return ((byte >> shift) & 0x01);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson}
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafssonstatic inline void
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssonset_bit(unsigned char *array, unsigned int idx, unsigned int bit) {
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson unsigned int shift, mask;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson shift = 7 - (idx % 8);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson mask = 1 << shift;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson if (bit != 0)
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson array[idx / 8] |= mask;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson else
5e387b9ce6bafdfadedb5b34e4c33a4404e5d589Brian Wellington array[idx / 8] &= (~mask & 0xFF);
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington}
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
f80ea74e1984e0b1dbe48dd86ecdd3a2380393cbBob Halleydns_labeltype_t
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrencedns_label_type(dns_label_t *label) {
f80ea74e1984e0b1dbe48dd86ecdd3a2380393cbBob Halley /*
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Get the type of 'label'.
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson */
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson REQUIRE(label != NULL);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson REQUIRE(label->length > 0);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson REQUIRE(label->base[0] <= 63 ||
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson label->base[0] == DNS_LABELTYPE_BITSTRING);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson if (label->base[0] <= 63)
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson return (dns_labeltype_ordinary);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson else
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson return (dns_labeltype_bitstring);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson}
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssonunsigned int
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssondns_label_countbits(dns_label_t *label) {
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson unsigned int count;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson /*
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson * The number of bits in a bitstring label.
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson */
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson REQUIRE(label != NULL);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson REQUIRE(label->length > 2);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson REQUIRE(label->base[0] == DNS_LABELTYPE_BITSTRING);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson count = label->base[1];
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson if (count == 0)
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews count = 256;
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson return (count);
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews}
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssondns_bitlabel_t
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafssondns_label_getbit(dns_label_t *label, unsigned int n) {
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington unsigned int count, bit;
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington /*
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington * The 'n'th most significant bit of 'label'.
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington *
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington * Notes:
5dbf258e2c780189fa30d51a872d8edb372e5589Bob Halley * Numbering starts at 0.
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson */
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson REQUIRE(label != NULL);
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson REQUIRE(label->length > 2);
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson REQUIRE(label->base[0] == DNS_LABELTYPE_BITSTRING);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson count = label->base[1];
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson if (count == 0)
b120e39deac3e9c323cdc7801ed2313f8ebbb744Andreas Gustafsson count = 256;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson REQUIRE(n < count);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson bit = get_bit(&label->base[2], n);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson if (bit == 0)
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson return (dns_bitlabel_0);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson return (dns_bitlabel_1);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson}
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellingtonvoid
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellingtondns_name_init(dns_name_t *name, unsigned char *offsets) {
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington /*
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington * Initialize 'name'.
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington */
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington DNS_NAME_INIT(name, offsets);
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington}
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssonvoid
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrencedns_name_reset(dns_name_t *name) {
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson REQUIRE(VALID_NAME(name));
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson REQUIRE(BINDABLE(name));
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence DNS_NAME_RESET(name);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson}
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssonvoid
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafssondns_name_invalidate(dns_name_t *name) {
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson /*
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson * Make 'name' invalid.
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington */
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington REQUIRE(VALID_NAME(name));
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson name->magic = 0;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson name->ndata = NULL;
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson name->length = 0;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence name->labels = 0;
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson name->attributes = 0;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson name->offsets = NULL;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson name->buffer = NULL;
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson ISC_LINK_INIT(name, link);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson}
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellingtonvoid
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellingtondns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) {
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson /*
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington * Dedicate a buffer for use with 'name'.
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington */
bd703253b745aaec6e45a60108bec513bf79bd2cBrian Wellington
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington REQUIRE(VALID_NAME(name));
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington REQUIRE((buffer != NULL && name->buffer == NULL) ||
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington (buffer == NULL));
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington name->buffer = buffer;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson}
8f79820c6930ee5ef6b4a54f36d2559400bdf47dAndreas Gustafsson
8f79820c6930ee5ef6b4a54f36d2559400bdf47dAndreas Gustafssonisc_boolean_t
8f79820c6930ee5ef6b4a54f36d2559400bdf47dAndreas Gustafssondns_name_hasbuffer(const dns_name_t *name) {
618a5e4923c3d064c1cc0f1866e27e8ddca90700Andreas Gustafsson /*
618a5e4923c3d064c1cc0f1866e27e8ddca90700Andreas Gustafsson * Does 'name' have a dedicated buffer?
618a5e4923c3d064c1cc0f1866e27e8ddca90700Andreas Gustafsson */
618a5e4923c3d064c1cc0f1866e27e8ddca90700Andreas Gustafsson
618a5e4923c3d064c1cc0f1866e27e8ddca90700Andreas Gustafsson REQUIRE(VALID_NAME(name));
7acfb3bcd29db4f19aa42690826e57dafdd28cdaAndreas Gustafsson
618a5e4923c3d064c1cc0f1866e27e8ddca90700Andreas Gustafsson if (name->buffer != NULL)
618a5e4923c3d064c1cc0f1866e27e8ddca90700Andreas Gustafsson return (ISC_TRUE);
8f79820c6930ee5ef6b4a54f36d2559400bdf47dAndreas Gustafsson
8f79820c6930ee5ef6b4a54f36d2559400bdf47dAndreas Gustafsson return (ISC_FALSE);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence}
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence
8f79820c6930ee5ef6b4a54f36d2559400bdf47dAndreas Gustafssonisc_boolean_t
8f79820c6930ee5ef6b4a54f36d2559400bdf47dAndreas Gustafssondns_name_isabsolute(const dns_name_t *name) {
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Does 'name' end in the root label?
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
8f79820c6930ee5ef6b4a54f36d2559400bdf47dAndreas Gustafsson
8f79820c6930ee5ef6b4a54f36d2559400bdf47dAndreas Gustafsson REQUIRE(VALID_NAME(name));
618a5e4923c3d064c1cc0f1866e27e8ddca90700Andreas Gustafsson
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
8f79820c6930ee5ef6b4a54f36d2559400bdf47dAndreas Gustafsson return (ISC_TRUE);
8f79820c6930ee5ef6b4a54f36d2559400bdf47dAndreas Gustafsson return (ISC_FALSE);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson}
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssonisc_boolean_t
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssondns_name_iswildcard(const dns_name_t *name) {
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson unsigned char *ndata;
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence /*
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson * Is 'name' a wildcard name?
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson */
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson REQUIRE(VALID_NAME(name));
8f79820c6930ee5ef6b4a54f36d2559400bdf47dAndreas Gustafsson REQUIRE(name->labels > 0);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson if (name->length >= 2) {
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson ndata = name->ndata;
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews if (ndata[0] == 1 && ndata[1] == '*')
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence return (ISC_TRUE);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson }
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson return (ISC_FALSE);
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews}
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssonisc_boolean_t
f80ea74e1984e0b1dbe48dd86ecdd3a2380393cbBob Halleydns_name_requiresedns(const dns_name_t *name) {
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson unsigned int count, nrem;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson unsigned char *ndata;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson isc_boolean_t requiresedns = ISC_FALSE;
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson /*
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson * Does 'name' require EDNS for transmission?
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson */
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
e485d16462b0a66b835107fae04fe9d562e77af0Bob Halley REQUIRE(VALID_NAME(name));
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson REQUIRE(name->labels > 0);
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson ndata = name->ndata;
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson nrem = name->length;
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson while (nrem > 0) {
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson count = *ndata++;
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson nrem--;
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson if (count == 0)
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson break;
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson if (count > 63) {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence INSIST(count == DNS_LABELTYPE_BITSTRING);
8f79820c6930ee5ef6b4a54f36d2559400bdf47dAndreas Gustafsson requiresedns = ISC_TRUE;
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson break;
8f79820c6930ee5ef6b4a54f36d2559400bdf47dAndreas Gustafsson }
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson INSIST(nrem >= count);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson nrem -= count;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson ndata += count;
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson }
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson return (requiresedns);
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson}
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafssonstatic inline unsigned int
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssonname_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence unsigned int length;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson const unsigned char *s;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson unsigned int h = 0;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson unsigned char c;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson length = name->length;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson if (length > 16)
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson length = 16;
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson /*
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews * This hash function is similar to the one Ousterhout
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews * uses in Tcl.
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews */
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews s = name->ndata;
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews if (case_sensitive) {
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews while (length > 0) {
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews h += ( h << 3 ) + *s;
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews s++;
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews length--;
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews }
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson } else {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence while (length > 0) {
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson c = maptolower[*s];
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence h += ( h << 3 ) + c;
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson s++;
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews length--;
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews }
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson }
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson return (h);
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson}
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssonunsigned int
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssondns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson /*
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson * Provide a hash value for 'name'.
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson */
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson REQUIRE(VALID_NAME(name));
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence if (name->labels == 0)
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson return (0);
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson return (name_hash(name, case_sensitive));
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson}
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrenceunsigned int
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrencedns_name_hashbylabel(dns_name_t *name, isc_boolean_t case_sensitive) {
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson unsigned char *offsets;
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson dns_offsets_t odata;
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson dns_name_t tname;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence unsigned int h = 0;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence unsigned int i;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson /*
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence * Provide a hash value for 'name'.
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence */
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson REQUIRE(VALID_NAME(name));
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence if (name->labels == 0)
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson return (0);
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence else if (name->labels == 1)
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence return (name_hash(name, case_sensitive));
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence SETUP_OFFSETS(name, offsets, odata);
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence DNS_NAME_INIT(&tname, NULL);
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson tname.labels = 1;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence h = 0;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence for (i = 0; i < name->labels; i++) {
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence tname.ndata = name->ndata + offsets[i];
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence if (i == name->labels - 1)
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence tname.length = name->length - offsets[i];
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence else
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence tname.length = offsets[i + 1] - offsets[i];
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence h += name_hash(&tname, case_sensitive);
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence }
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence return (h);
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence}
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrencedns_namereln_t
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrencedns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence int *orderp,
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson unsigned int *nlabelsp, unsigned int *nbitsp)
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson{
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson unsigned int l1, l2, l, count1, count2, count;
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson unsigned int b1, b2, n, nlabels, nbits;
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson int cdiff, ldiff, chdiff;
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson unsigned char *label1, *label2;
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson unsigned char *offsets1, *offsets2;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence dns_offsets_t odata1, odata2;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence dns_namereln_t namereln = dns_namereln_none;
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence /*
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence * Determine the relative ordering under the DNSSEC order relation of
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence * 'name1' and 'name2', and also determine the hierarchical
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence * relationship of the names.
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence *
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson * Note: It makes no sense for one of the names to be relative and the
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson * other absolute. If both names are relative, then to be meaningfully
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson * compared the caller must ensure that they are both relative to the
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson * same domain.
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson */
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson REQUIRE(VALID_NAME(name1));
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson REQUIRE(VALID_NAME(name2));
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson REQUIRE(orderp != NULL);
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff REQUIRE(nlabelsp != NULL);
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence REQUIRE(nbitsp != NULL);
82ca33427bdd4f3bc4ed3431e86bd810fe751674Andreas Gustafsson /*
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence * Either name1 is absolute and name2 is absolute, or neither is.
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson */
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson SETUP_OFFSETS(name1, offsets1, odata1);
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence SETUP_OFFSETS(name2, offsets2, odata2);
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson nlabels = 0;
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson nbits = 0;
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson l1 = name1->labels;
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson l2 = name2->labels;
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson ldiff = (int)l1 - (int)l2;
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson if (ldiff < 0)
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews l = l1;
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews else
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews l = l2;
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews while (l > 0) {
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews l--;
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews l1--;
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews l2--;
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews label1 = &name1->ndata[offsets1[l1]];
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews label2 = &name2->ndata[offsets2[l2]];
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence count1 = *label1++;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence count2 = *label2++;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence if (count1 <= 63 && count2 <= 63) {
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence cdiff = (int)count1 - (int)count2;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence if (cdiff < 0)
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence count = count1;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence else
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence count = count2;
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews while (count > 0) {
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews chdiff = (int)maptolower[*label1] -
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson (int)maptolower[*label2];
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson if (chdiff != 0) {
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson *orderp = chdiff;
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson goto done;
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson }
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson count--;
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff label1++;
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson label2++;
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson }
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff if (cdiff != 0) {
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff *orderp = cdiff;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence goto done;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence }
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence nlabels++;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence } else if (count1 == DNS_LABELTYPE_BITSTRING && count2 <= 63) {
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence if (count2 == 0)
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence *orderp = 1;
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson else
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff *orderp = -1;
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson goto done;
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson } else if (count2 == DNS_LABELTYPE_BITSTRING && count1 <= 63) {
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson if (count1 == 0)
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson *orderp = -1;
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson else
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson *orderp = 1;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson goto done;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence } else {
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson INSIST(count1 == DNS_LABELTYPE_BITSTRING &&
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence count2 == DNS_LABELTYPE_BITSTRING);
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson count1 = *label1++;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson if (count1 == 0)
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson count1 = 256;
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson count2 = *label2++;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson if (count2 == 0)
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence count2 = 256;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence if (count1 < count2) {
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson cdiff = -1;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson count = count1;
951c247f2923f667c5c97355b31dc564bd540bfeDavid Lawrence } else {
951c247f2923f667c5c97355b31dc564bd540bfeDavid Lawrence count = count2;
951c247f2923f667c5c97355b31dc564bd540bfeDavid Lawrence if (count1 > count2)
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson cdiff = 1;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence else
951c247f2923f667c5c97355b31dc564bd540bfeDavid Lawrence cdiff = 0;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence }
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence /* Yes, this loop is really slow! */
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence for (n = 0; n < count; n++) {
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence b1 = get_bit(label1, n);
951c247f2923f667c5c97355b31dc564bd540bfeDavid Lawrence b2 = get_bit(label2, n);
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence if (b1 < b2) {
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence *orderp = -1;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence goto done;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence } else if (b1 > b2) {
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence *orderp = 1;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence goto done;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence }
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence if (nbits == 0)
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence nlabels++;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence nbits++;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence }
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence if (cdiff != 0) {
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence /*
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence * If we're here, then we have two bitstrings
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence * of differing length.
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence *
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence * If the name with the shorter bitstring
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence * has any labels, then it must be greater
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence * than the longer bitstring. This is a bit
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence * counterintuitive. If the name with the
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence * shorter bitstring has any more labels, then
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence * the next label must be an ordinary label.
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence * It can't be a bitstring label because if it
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson * were, then there would be room for it in
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson * the current bitstring label (since all
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson * bitstrings are canonicalized). Since
951c247f2923f667c5c97355b31dc564bd540bfeDavid Lawrence * there's at least one more bit in the
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence * name with the longer bitstring, and since
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence * a bitlabel sorts before any ordinary label,
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence * the name with the longer bitstring must
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence * be lexically before the one with the shorter
951c247f2923f667c5c97355b31dc564bd540bfeDavid Lawrence * bitstring.
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson *
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence * On the other hand, if there are no more
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence * labels in the name with the shorter
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson * bitstring, then that name contains the
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson * other name.
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson */
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson namereln = dns_namereln_commonancestor;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson if (cdiff < 0) {
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson if (l1 > 0)
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson *orderp = 1;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence else {
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson *orderp = -1;
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson namereln =
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson dns_namereln_contains;
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson }
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson } else {
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson if (l2 > 0)
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews *orderp = -1;
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews else {
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson *orderp = 1;
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson namereln =
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson dns_namereln_subdomain;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence }
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson }
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson goto done;
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson }
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson nbits = 0;
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson }
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence }
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson *orderp = ldiff;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson if (ldiff < 0)
951c247f2923f667c5c97355b31dc564bd540bfeDavid Lawrence namereln = dns_namereln_contains;
951c247f2923f667c5c97355b31dc564bd540bfeDavid Lawrence else if (ldiff > 0)
951c247f2923f667c5c97355b31dc564bd540bfeDavid Lawrence namereln = dns_namereln_subdomain;
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson else
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson namereln = dns_namereln_equal;
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson
951c247f2923f667c5c97355b31dc564bd540bfeDavid Lawrence done:
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson *nlabelsp = nlabels;
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson *nbitsp = nbits;
951c247f2923f667c5c97355b31dc564bd540bfeDavid Lawrence
951c247f2923f667c5c97355b31dc564bd540bfeDavid Lawrence if (nlabels > 0 && namereln == dns_namereln_none)
951c247f2923f667c5c97355b31dc564bd540bfeDavid Lawrence namereln = dns_namereln_commonancestor;
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson return (namereln);
951c247f2923f667c5c97355b31dc564bd540bfeDavid Lawrence}
951c247f2923f667c5c97355b31dc564bd540bfeDavid Lawrence
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrenceint
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssondns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson int order;
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson unsigned int nlabels, nbits;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson /*
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson * Determine the relative ordering under the DNSSEC order relation of
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson * 'name1' and 'name2'.
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson *
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson * Note: It makes no sense for one of the names to be relative and the
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * other absolute. If both names are relative, then to be meaningfully
9b0e18da3d5c2290f90b285d122d368173f17c63Andreas Gustafsson * compared the caller must ensure that they are both relative to the
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson * same domain.
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson */
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews (void)dns_name_fullcompare(name1, name2, &order, &nlabels, &nbits);
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews return (order);
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews}
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrewsisc_boolean_t
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrewsdns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews unsigned int l, count;
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews unsigned char c;
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews unsigned char *label1, *label2;
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews /*
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews * Are 'name1' and 'name2' equal?
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews *
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews * Note: It makes no sense for one of the names to be relative and the
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews * other absolute. If both names are relative, then to be meaningfully
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews * compared the caller must ensure that they are both relative to the
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews * same domain.
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews */
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews REQUIRE(VALID_NAME(name1));
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence REQUIRE(VALID_NAME(name2));
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence /*
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence * Either name1 is absolute and name2 is absolute, or neither is.
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence */
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence if (name1->length != name2->length)
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews return (ISC_FALSE);
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews l = name1->labels;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence if (l != name2->labels)
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence return (ISC_FALSE);
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence label1 = name1->ndata;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence label2 = name2->ndata;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence while (l > 0) {
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews l--;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence count = *label1++;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence if (count != *label2++)
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence return (ISC_FALSE);
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence if (count <= 63) {
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence while (count > 0) {
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence count--;
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence c = maptolower[*label1++];
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence if (c != maptolower[*label2++])
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence return (ISC_FALSE);
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence }
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence } else {
03609d0b8f6e458d6bd4b460f4eb3f7270f487efDavid Lawrence INSIST(count == DNS_LABELTYPE_BITSTRING);
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews count = *label1++;
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews if (count != *label2++)
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews return (ISC_FALSE);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson if (count == 0)
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson count = 256;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson /*
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson * Number of bytes.
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson */
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff count = (count + 7) / 8;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence while (count > 0) {
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff count--;
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson c = *label1++;
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff if (c != *label2++)
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson return (ISC_FALSE);
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson }
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff }
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson }
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson return (ISC_TRUE);
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson}
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafssonint
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrencedns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson unsigned int l1, l2, l, count1, count2, count;
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson unsigned char c1, c2;
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson unsigned char *label1, *label2;
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson /*
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson * Compare two absolute names as rdata.
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson */
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson REQUIRE(VALID_NAME(name1));
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson REQUIRE(name1->labels > 0);
a928d619170d61da40c3bff29800ff73709140daAndreas Gustafsson REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence REQUIRE(VALID_NAME(name2));
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson REQUIRE(name2->labels > 0);
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson l1 = name1->labels;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson l2 = name2->labels;
l = (l1 < l2) ? l1 : l2;
label1 = name1->ndata;
label2 = name2->ndata;
while (l > 0) {
l--;
count1 = *label1++;
count2 = *label2++;
if (count1 <= 63 && count2 <= 63) {
if (count1 != count2)
return ((count1 < count2) ? -1 : 1);
count = count1;
while (count > 0) {
count--;
c1 = maptolower[*label1++];
c2 = maptolower[*label2++];
if (c1 < c2)
return (-1);
else if (c1 > c2)
return (1);
}
} else if (count1 == DNS_LABELTYPE_BITSTRING && count2 <= 63) {
return (1);
} else if (count2 == DNS_LABELTYPE_BITSTRING && count1 <= 63) {
return (-1);
} else {
INSIST(count1 == DNS_LABELTYPE_BITSTRING &&
count2 == DNS_LABELTYPE_BITSTRING);
count2 = *label2++;
count1 = *label1++;
if (count1 != count2)
return ((count1 < count2) ? -1 : 1);
if (count1 == 0)
count1 = 256;
if (count2 == 0)
count2 = 256;
/* number of bytes */
count = (count1 + 7) / 8;
while (count > 0) {
count--;
c1 = *label1++;
c2 = *label2++;
if (c1 != c2)
return ((c1 < c2) ? -1 : 1);
}
}
}
/*
* If one name had more labels than the other, their common
* prefix must have been different because the shorter name
* ended with the root label and the longer one can't have
* a root label in the middle of it. Therefore, if we get
* to this point, the lengths must be equal.
*/
INSIST(l1 == l2);
return (0);
}
isc_boolean_t
dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
int order;
unsigned int nlabels, nbits;
dns_namereln_t namereln;
/*
* Is 'name1' a subdomain of 'name2'?
*
* Note: It makes no sense for one of the names to be relative and the
* other absolute. If both names are relative, then to be meaningfully
* compared the caller must ensure that they are both relative to the
* same domain.
*/
namereln = dns_name_fullcompare(name1, name2, &order, &nlabels,
&nbits);
if (namereln == dns_namereln_subdomain ||
namereln == dns_namereln_equal)
return (ISC_TRUE);
return (ISC_FALSE);
}
isc_boolean_t
dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
int order;
unsigned int nlabels, nbits, labels;
dns_name_t tname;
REQUIRE(VALID_NAME(name));
REQUIRE(name->labels > 0);
REQUIRE(VALID_NAME(wname));
labels = wname->labels;
REQUIRE(labels > 0);
REQUIRE(dns_name_iswildcard(wname));
DNS_NAME_INIT(&tname, NULL);
dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
if (dns_name_fullcompare(name, &tname, &order, &nlabels, &nbits) ==
dns_namereln_subdomain)
return (ISC_TRUE);
return (ISC_FALSE);
}
unsigned int
dns_name_depth(const dns_name_t *name) {
unsigned int depth, count, nrem, n;
unsigned char *ndata;
/*
* The depth of 'name'.
*/
REQUIRE(VALID_NAME(name));
if (name->labels == 0)
return (0);
depth = 0;
ndata = name->ndata;
nrem = name->length;
while (nrem > 0) {
count = *ndata++;
nrem--;
if (count > 63) {
INSIST(count == DNS_LABELTYPE_BITSTRING);
INSIST(nrem != 0);
n = *ndata++;
nrem--;
if (n == 0)
n = 256;
depth += n;
count = n / 8;
if (n % 8 != 0)
count++;
} else {
depth++;
if (count == 0)
break;
}
INSIST(nrem >= count);
nrem -= count;
ndata += count;
}
return (depth);
}
unsigned int
dns_name_countlabels(const dns_name_t *name) {
/*
* How many labels does 'name' have?
*/
REQUIRE(VALID_NAME(name));
ENSURE(name->labels <= 128);
return (name->labels);
}
void
dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
unsigned char *offsets;
dns_offsets_t odata;
/*
* Make 'label' refer to the 'n'th least significant label of 'name'.
*/
REQUIRE(VALID_NAME(name));
REQUIRE(name->labels > 0);
REQUIRE(n < name->labels);
REQUIRE(label != NULL);
SETUP_OFFSETS(name, offsets, odata);
label->base = &name->ndata[offsets[n]];
if (n == name->labels - 1)
label->length = name->length - offsets[n];
else
label->length = offsets[n + 1] - offsets[n];
}
void
dns_name_getlabelsequence(const dns_name_t *source,
unsigned int first, unsigned int n,
dns_name_t *target)
{
unsigned char *offsets;
dns_offsets_t odata;
unsigned int firstoffset, endoffset;
/*
* Make 'target' refer to the 'n' labels including and following
* 'first' in 'source'.
*/
REQUIRE(VALID_NAME(source));
REQUIRE(VALID_NAME(target));
REQUIRE(first <= source->labels);
REQUIRE(first + n <= source->labels);
REQUIRE(BINDABLE(target));
SETUP_OFFSETS(source, offsets, odata);
if (first == source->labels)
firstoffset = source->length;
else
firstoffset = offsets[first];
if (first + n == source->labels)
endoffset = source->length;
else
endoffset = offsets[first + n];
target->ndata = &source->ndata[firstoffset];
target->length = endoffset - firstoffset;
if (first + n == source->labels && n > 0 &&
(source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
target->attributes |= DNS_NAMEATTR_ABSOLUTE;
else
target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
target->labels = n;
/*
* If source and target are the same, and we're making target
* a prefix of source, the offsets table is correct already
* so we don't need to call set_offsets().
*/
if (target->offsets != NULL &&
(target != source || first != 0))
set_offsets(target, target->offsets, NULL);
}
void
dns_name_clone(dns_name_t *source, dns_name_t *target) {
/*
* Make 'target' refer to the same name as 'source'.
*/
REQUIRE(VALID_NAME(source));
REQUIRE(VALID_NAME(target));
REQUIRE(BINDABLE(target));
target->ndata = source->ndata;
target->length = source->length;
target->labels = source->labels;
target->attributes = source->attributes &
(unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC |
DNS_NAMEATTR_DYNOFFSETS);
if (target->offsets != NULL && source->labels > 0) {
if (source->offsets != NULL)
memcpy(target->offsets, source->offsets,
source->labels);
else
set_offsets(target, target->offsets, NULL);
}
}
void
dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
unsigned char *offsets;
dns_offsets_t odata;
unsigned int len;
isc_region_t r2;
/*
* Make 'name' refer to region 'r'.
*/
REQUIRE(VALID_NAME(name));
REQUIRE(r != NULL);
REQUIRE(BINDABLE(name));
INIT_OFFSETS(name, offsets, odata);
if (name->buffer != NULL) {
isc_buffer_clear(name->buffer);
isc_buffer_availableregion(name->buffer, &r2);
len = (r->length < r2.length) ? r->length : r2.length;
if (len > DNS_NAME_MAXWIRE)
len = DNS_NAME_MAXWIRE;
memcpy(r2.base, r->base, len);
name->ndata = r2.base;
name->length = len;
} else {
name->ndata = r->base;
name->length = (r->length <= DNS_NAME_MAXWIRE) ?
r->length : DNS_NAME_MAXWIRE;
}
if (r->length > 0)
set_offsets(name, offsets, name);
else {
name->labels = 0;
name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
}
if (name->buffer != NULL)
isc_buffer_add(name->buffer, name->length);
}
void
dns_name_toregion(dns_name_t *name, isc_region_t *r) {
/*
* Make 'r' refer to 'name'.
*/
REQUIRE(VALID_NAME(name));
REQUIRE(r != NULL);
DNS_NAME_TOREGION(name, r);
}
isc_result_t
dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
dns_name_t *origin, isc_boolean_t downcase,
isc_buffer_t *target)
{
unsigned char *ndata, *label;
char *tdata;
char c;
ft_state state, kind;
unsigned int value, count, tbcount, bitlength, maxlength;
unsigned int n1, n2, vlen, tlen, nrem, nused, digits, labels, tused;
isc_boolean_t done, saw_bitstring;
unsigned char dqchars[4];
unsigned char *offsets;
dns_offsets_t odata;
/*
* Convert the textual representation of a DNS name at source
* into uncompressed wire form stored in target.
*
* Notes:
* Relative domain names will have 'origin' appended to them
* unless 'origin' is NULL, in which case relative domain names
* will remain relative.
*/
REQUIRE(VALID_NAME(name));
REQUIRE(ISC_BUFFER_VALID(source));
REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
(target == NULL && name->buffer != NULL));
if (target == NULL && name->buffer != NULL) {
target = name->buffer;
isc_buffer_clear(target);
}
REQUIRE(BINDABLE(name));
INIT_OFFSETS(name, offsets, odata);
offsets[0] = 0;
/*
* Initialize things to make the compiler happy; they're not required.
*/
n1 = 0;
n2 = 0;
vlen = 0;
label = NULL;
digits = 0;
value = 0;
count = 0;
tbcount = 0;
bitlength = 0;
maxlength = 0;
kind = ft_init;
/*
* Make 'name' empty in case of failure.
*/
MAKE_EMPTY(name);
/*
* Set up the state machine.
*/
tdata = (char *)source->base + source->current;
tlen = isc_buffer_remaininglength(source);
tused = 0;
ndata = isc_buffer_used(target);
nrem = isc_buffer_availablelength(target);
if (nrem > 255)
nrem = 255;
nused = 0;
labels = 0;
done = ISC_FALSE;
saw_bitstring = ISC_FALSE;
state = ft_init;
while (nrem > 0 && tlen > 0 && !done) {
c = *tdata++;
tlen--;
tused++;
no_read:
switch (state) {
case ft_init:
/*
* Is this the root name?
*/
if (c == '.') {
if (tlen != 0)
return (DNS_R_EMPTYLABEL);
labels++;
*ndata++ = 0;
nrem--;
nused++;
done = ISC_TRUE;
break;
}
if (c == '@' && tlen == 0) {
state = ft_at;
break;
}
/* FALLTHROUGH */
case ft_start:
label = ndata;
ndata++;
nrem--;
nused++;
count = 0;
if (c == '\\') {
state = ft_initialescape;
break;
}
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(ISC_BUFFER_VALID(target));
ndata = name->ndata;
nlen = name->length;
labels = name->labels;
tdata = isc_buffer_used(target);
tlen = isc_buffer_availablelength(target);
trem = tlen;
if (labels == 0 && nlen == 0) {
/*
* Special handling for an empty name.
*/
if (trem == 0)
return (ISC_R_NOSPACE);
/*
* The names of these booleans are misleading in this case.
* This empty name is not necessarily from the root node of
* the DNS root zone, nor is a final dot going to be included.
* They need to be set this way, though, to keep the "@"
* from being trounced.
*/
saw_root = ISC_TRUE;
omit_final_dot = ISC_FALSE;
*tdata++ = '@';
trem--;
/*
* Skip the while() loop.
*/
nlen = 0;
} else if (nlen == 1 && labels == 1 && *ndata == '\0') {
/*
* Special handling for the root label.
*/
if (trem == 0)
return (ISC_R_NOSPACE);
saw_root = ISC_TRUE;
omit_final_dot = ISC_FALSE;
*tdata++ = '.';
trem--;
/*
* Skip the while() loop.
*/
nlen = 0;
}
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 0x28: /* '(' */
case 0x29: /* ')' */
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];
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);
/* NOTREACHED */
}
/*
* 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);
if (!saw_root || omit_final_dot)
trem++;
isc_buffer_add(target, tlen - trem);
return (ISC_R_SUCCESS);
}
isc_result_t
dns_name_tofilenametext(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;
char num[4];
/*
* This function assumes the name is in proper uncompressed
* wire format.
*/
REQUIRE(VALID_NAME(name));
REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
REQUIRE(ISC_BUFFER_VALID(target));
ndata = name->ndata;
nlen = name->length;
labels = name->labels;
tdata = isc_buffer_used(target);
tlen = isc_buffer_availablelength(target);
trem = tlen;
if (nlen == 1 && labels == 1 && *ndata == '\0') {
/*
* Special handling for the root label.
*/
if (trem == 0)
return (ISC_R_NOSPACE);
omit_final_dot = ISC_FALSE;
*tdata++ = '.';
trem--;
/*
* Skip the while() loop.
*/
nlen = 0;
}
while (labels > 0 && nlen > 0 && trem > 0) {
labels--;
count = *ndata++;
nlen--;
if (count == 0)
break;
if (count < 64) {
INSIST(nlen >= count);
while (count > 0) {
c = *ndata;
if ((c >= 0x30 && c <= 0x39) || /* digit */
(c >= 0x41 && c <= 0x5A) || /* uppercase */
(c >= 0x61 && c <= 0x7A) || /* lowercase */
c == 0x2D || /* hyphen */
c == 0x5F) /* underscore */
{
if (trem == 0)
return (ISC_R_NOSPACE);
/* downcase */
if (c >= 0x41 && c <= 0x5A)
c += 0x20;
CONVERTFROMASCII(c);
*tdata++ = c;
ndata++;
trem--;
nlen--;
} else {
if (trem < 3)
return (ISC_R_NOSPACE);
sprintf(tdata, "%%%02X", c);
tdata += 3;
trem -= 3;
ndata++;
nlen--;
}
count--;
}
} else if (count == DNS_LABELTYPE_BITSTRING) {
if (trem < 3)
return (ISC_R_NOSPACE);
*tdata++ = '%';
*tdata++ = 'x';
trem -= 2;
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);
/* NOTREACHED */
}
/*
* 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);
if (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 > DNS_NAME_MAXWIRE)
nmax = DNS_NAME_MAXWIRE;
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) {
offsets[labels] = nused;
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) {
offsets[labels] = nused;
labels++;
if (nused == nmax)
goto full;
nused++;
*ndata++ = c;
saw_bitstring = ISC_TRUE;
state = fw_bitstring;
} 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;
if (saw_bitstring)
compact(name, offsets);
isc_buffer_forward(source, cused);
isc_buffer_add(target, name->length);
return (ISC_R_SUCCESS);
full:
if (nmax == DNS_NAME_MAXWIRE)
/*
* The name did not fit even though we had a buffer
* big enough to fit a maximum-length name.
*/
return (DNS_R_NAMETOOLONG);
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; /* Global compression prefix */
isc_boolean_t gf; /* Global compression target found */
isc_uint16_t go; /* Global compression offset */
dns_offsets_t 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, NULL);
offset = target->used; /*XXX*/
methods = dns_compress_getmethods(cctx);
if ((methods & DNS_COMPRESS_GLOBAL14) != 0)
gf = dns_compress_findglobal(cctx, name, &gp, &go);
else
gf = ISC_FALSE;
/*
* If the offset is too high for 14 bit global compression, we're
* out of luck.
*/
if (gf && go >= 0x4000)
gf = ISC_FALSE;
/*
* Will the compression pointer reduce the message size?
*/
if (gf && (gp.length + 2) >= 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);
go |= 0xc000;
if (target->length - target->used < 2)
return (ISC_R_NOSPACE);
isc_buffer_putuint16(target, go);
if (gp.length != 0)
dns_compress_add(cctx, name, &gp, 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, name, 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));
/*
* XXX 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 > DNS_NAME_MAXWIRE)
nrem = DNS_NAME_MAXWIRE;
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 > DNS_NAME_MAXWIRE) {
MAKE_EMPTY(name);
return (DNS_R_NAMETOOLONG);
}
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, prefix_odata, suffix_odata;
unsigned char *offsets, *prefix_offsets = NULL, *suffix_offsets;
isc_result_t result = ISC_R_SUCCESS;
unsigned int splitlabel, bitbytes, mod, len;
unsigned char *p, *src, *dst;
isc_boolean_t maybe_compact_prefix = ISC_FALSE;
REQUIRE(VALID_NAME(name));
REQUIRE(suffixlabels > 0);
REQUIRE((nbits == 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;
/*
* Make p point at the count byte of the bitstring label,
* if there is one (p will not be used if we are not
* splitting bits).
*/
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. Also, when a bitstring
* label being split is maximal length, compaction
* might be necessary on the prefix.
*/
if (*p == 0) {
maybe_compact_prefix = ISC_TRUE;
*p = 256 - nbits;
} else
*p = *p - nbits;
/*
* Calculate the number of bytes necessary to hold
* all of the bits left in the prefix.
*/
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) {
memmove(dst, src, len);
} else {
/*
* p is adjusted to point to the last byte of
* the starting bitstring label to make it
* cheap to determine when bits from the next
* byte should be shifted into the low order
* bits of the current byte.
*/
p = src + (mod + *p - 1) / 8;
while (len--) {
*dst = *src++ << mod;
/*
* The 0xff subexpression guards
* against arithmetic sign extension
* by the right shift.
*/
if (src <= p)
*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, prefix_offsets, prefix_odata);
set_offsets(prefix, prefix_offsets, 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 == 0 ? 256 : *src) - 1) / 8;
len -= (bitbytes - 1);
src++;
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;
if (len > 0)
memmove(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 bits (if any) masked
* to zero.
*/
if (mod != 0)
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, suffix_offsets, suffix_odata);
set_offsets(suffix, suffix_offsets, suffix);
INSIST(suffix->labels == suffixlabels &&
suffix->length == len);
} else
dns_name_getlabelsequence(name, splitlabel,
suffixlabels, suffix);
}
/*
* Compacting the prefix can't be done until after the suffix is
* set, because it would screw up the offsets table of 'name'
* when 'name' == 'prefix'.
*/
if (maybe_compact_prefix && splitlabel > 0 &&
prefix->ndata[prefix_offsets[splitlabel - 1]] ==
DNS_LABELTYPE_BITSTRING)
compact(prefix, prefix_offsets);
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>");
}
isc_result_t
dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
unsigned char *ndata;
/*
* Make dest a copy of source.
*/
REQUIRE(VALID_NAME(source));
REQUIRE(VALID_NAME(dest));
REQUIRE(target != NULL || dest->buffer != NULL);
if (target == NULL) {
target = dest->buffer;
isc_buffer_clear(dest->buffer);
}
REQUIRE(BINDABLE(dest));
/*
* Set up.
*/
if (target->length - target->used < source->length)
return (ISC_R_NOSPACE);
ndata = (unsigned char *)target->base + target->used;
dest->ndata = target->base;
memcpy(ndata, source->ndata, source->length);
dest->ndata = ndata;
dest->labels = source->labels;
dest->length = source->length;
if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
dest->attributes = DNS_NAMEATTR_ABSOLUTE;
else
dest->attributes = 0;
if (dest->labels > 0 && dest->offsets != NULL) {
if (source->offsets != NULL)
memcpy(dest->offsets, source->offsets, source->labels);
else
set_offsets(dest, dest->offsets, NULL);
}
isc_buffer_add(target, dest->length);
return (ISC_R_SUCCESS);
}