name.c revision c80fef792a864f08453128230216fb079a69500b
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley/*
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC")
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * Copyright (C) 1998-2003 Internet Software Consortium.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
ec5347e2c775f027573ce5648b910361aa926c01Automatic Updater * Permission to use, copy, modify, and/or distribute this software for any
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley * purpose with or without fee is hereby granted, provided that the above
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley * copyright notice and this permission notice appear in all copies.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * PERFORMANCE OF THIS SOFTWARE.
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley */
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley
28a8f5b0de57d269cf2845c69cb6abe18cbd3b3aMark Andrews/* $Id$ */
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley/*! \file */
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉#include <config.h>
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt#include <ctype.h>
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt#include <stdlib.h>
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt#include <isc/buffer.h>
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉#include <isc/hash.h>
78576fe0db75332cd956b037d90dad0c7e09b005Tatuya JINMEI 神明達哉#include <isc/mem.h>
cfb605168d7403d3c967eec1b761519712e11ce3Mark Andrews#include <isc/once.h>
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉#include <isc/print.h>
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley#include <isc/string.h>
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley#include <isc/thread.h>
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews#include <isc/util.h>
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington#include <dns/compress.h>
9cd6d409b78a6f833b681c13a68fbdc7c024fe66David Lawrence#include <dns/fixedname.h>
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley#include <dns/name.h>
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt#include <dns/result.h>
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews#define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence
364a82f7c25b62967678027043425201a5e5171aBob Halleytypedef enum {
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley ft_init = 0,
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt ft_start,
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt ft_ordinary,
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt ft_initialescape,
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt ft_escape,
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 ft_escdecimal,
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 ft_at
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉} ft_state;
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉typedef enum {
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 fw_start = 0,
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 fw_ordinary,
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 fw_copy,
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 fw_newcurrent
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉} fw_state;
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉static char digitvalue[256] = {
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉};
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉static unsigned char maptolower[] = {
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
7de2c6e6d51f38daeb2d346f3f21dc01ccece6daEvan Hunt 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
7de2c6e6d51f38daeb2d346f3f21dc01ccece6daEvan Hunt 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
435532822dc571a904207d8176e063cc8731eef5Bob Halley 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
7de2c6e6d51f38daeb2d346f3f21dc01ccece6daEvan Hunt 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
785d1541b6ec7c6939ec8ebf409db367943bab5fAndreas Gustafsson 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
7de2c6e6d51f38daeb2d346f3f21dc01ccece6daEvan Hunt 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
9d99e3fda11eb8549a2bc7d5af31b7630ed68162Mark Andrews 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
7de2c6e6d51f38daeb2d346f3f21dc01ccece6daEvan Hunt 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
435532822dc571a904207d8176e063cc8731eef5Bob Halley 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
7de2c6e6d51f38daeb2d346f3f21dc01ccece6daEvan Hunt 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews};
7de2c6e6d51f38daeb2d346f3f21dc01ccece6daEvan Hunt
7de2c6e6d51f38daeb2d346f3f21dc01ccece6daEvan Hunt#define CONVERTTOASCII(c)
7de2c6e6d51f38daeb2d346f3f21dc01ccece6daEvan Hunt#define CONVERTFROMASCII(c)
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews
7de2c6e6d51f38daeb2d346f3f21dc01ccece6daEvan Hunt#define INIT_OFFSETS(name, var, default) \
7de2c6e6d51f38daeb2d346f3f21dc01ccece6daEvan Hunt if (name->offsets != NULL) \
7de2c6e6d51f38daeb2d346f3f21dc01ccece6daEvan Hunt var = name->offsets; \
7de2c6e6d51f38daeb2d346f3f21dc01ccece6daEvan Hunt else \
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt var = default;
7de2c6e6d51f38daeb2d346f3f21dc01ccece6daEvan Hunt
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley#define SETUP_OFFSETS(name, var, default) \
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley if (name->offsets != NULL) \
4423c99613db1399dbb5c51e86ef0d351a1418c2Mark Andrews var = name->offsets; \
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews else { \
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews var = default; \
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt set_offsets(name, var, NULL); \
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley }
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley/*%
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley * Note: If additional attributes are added that should not be set for
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington * empty names, MAKE_EMPTY() must be changed so it clears them.
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews */
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley#define MAKE_EMPTY(name) \
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halleydo { \
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley name->ndata = NULL; \
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley name->length = 0; \
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley name->labels = 0; \
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley} while (0);
dcf8825fd74f3f83b1882af4793270083b125ee5David Lawrence
dcf8825fd74f3f83b1882af4793270083b125ee5David Lawrence/*%
dcf8825fd74f3f83b1882af4793270083b125ee5David Lawrence * A name is "bindable" if it can be set to point to a new value, i.e.
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley * name->ndata and name->length may be changed.
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley */
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley#define BINDABLE(name) \
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley ((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley == 0)
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley/*%
9cd6d409b78a6f833b681c13a68fbdc7c024fe66David Lawrence * Note that the name data must be a char array, not a string
9cd6d409b78a6f833b681c13a68fbdc7c024fe66David Lawrence * literal, to avoid compiler warnings about discarding
9cd6d409b78a6f833b681c13a68fbdc7c024fe66David Lawrence * the const attribute of a string.
9cd6d409b78a6f833b681c13a68fbdc7c024fe66David Lawrence */
9cd6d409b78a6f833b681c13a68fbdc7c024fe66David Lawrencestatic unsigned char root_ndata[] = { '\0' };
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrewsstatic unsigned char root_offsets[] = { 0 };
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halleystatic dns_name_t root =
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley{
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley DNS_NAME_MAGIC,
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington root_ndata, 1, 1,
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington root_offsets, NULL,
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington {(void *)-1, (void *)-1},
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington {NULL, NULL}
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington};
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington/* XXXDCL make const? */
64a84169d7eed05486b10be90afea58f4af146f9Brian WellingtonLIBDNS_EXTERNAL_DATA dns_name_t *dns_rootname = &root;
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington
70c91849c3a3d808125d690a46af5fd225a4c291Andreas Gustafssonstatic unsigned char wild_ndata[] = { '\001', '*' };
2d67fbd786284ed570031fa82fc9807b0413aa3fBrian Wellingtonstatic unsigned char wild_offsets[] = { 0 };
2d67fbd786284ed570031fa82fc9807b0413aa3fBrian Wellington
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellingtonstatic dns_name_t wild =
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington{
9efa0d2ae311157ed1cce3c16129579111b1e3b0Andreas Gustafsson DNS_NAME_MAGIC,
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington wild_ndata, 2, 1,
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington DNS_NAMEATTR_READONLY,
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington wild_offsets, NULL,
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews {(void *)-1, (void *)-1},
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington {NULL, NULL}
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington};
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington/* XXXDCL make const? */
64a84169d7eed05486b10be90afea58f4af146f9Brian WellingtonLIBDNS_EXTERNAL_DATA dns_name_t *dns_wildcardname = &wild;
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellingtonunsigned int
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellingtondns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive);
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington/*
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington * dns_name_t to text post-conversion procedure.
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington */
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington#ifdef ISC_PLATFORM_USETHREADS
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellingtonstatic int thread_key_initialized = 0;
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellingtonstatic isc_mutex_t thread_key_mutex;
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrewsstatic isc_mem_t *thread_key_mctx = NULL;
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellingtonstatic isc_thread_key_t totext_filter_proc_key;
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellingtonstatic isc_once_t once = ISC_ONCE_INIT;
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington#else
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellingtonstatic dns_name_totextfilter_t totext_filter_proc = NULL;
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington#endif
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellingtonstatic void
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellingtonset_offsets(const dns_name_t *name, unsigned char *offsets,
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson dns_name_t *set_name);
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellington
64a84169d7eed05486b10be90afea58f4af146f9Brian Wellingtonvoid
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halleydns_name_init(dns_name_t *name, unsigned char *offsets) {
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley /*
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley * Initialize 'name'.
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley */
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley DNS_NAME_INIT(name, offsets);
eb2c85b103e3fccebddf59619216ba26af98bcd1Bob Halley}
f3f22040a8c4835227e1a3abc54454556d4c47abBrian Wellington
ece3d6c35693f9e2145434b0bf14e8b752cdeee8Michael Graffvoid
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halleydns_name_reset(dns_name_t *name) {
ece3d6c35693f9e2145434b0bf14e8b752cdeee8Michael Graff REQUIRE(VALID_NAME(name));
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley REQUIRE(BINDABLE(name));
f3f22040a8c4835227e1a3abc54454556d4c47abBrian Wellington
4423c99613db1399dbb5c51e86ef0d351a1418c2Mark Andrews DNS_NAME_RESET(name);
4423c99613db1399dbb5c51e86ef0d351a1418c2Mark Andrews}
4423c99613db1399dbb5c51e86ef0d351a1418c2Mark Andrews
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halleyvoid
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halleydns_name_invalidate(dns_name_t *name) {
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley /*
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley * Make 'name' invalid.
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley */
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley REQUIRE(VALID_NAME(name));
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley
2f3cfa8c0212e47f92f6c45459d9ee0ba8aa0045Bob Halley name->magic = 0;
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley name->ndata = NULL;
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley name->length = 0;
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley name->labels = 0;
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley name->attributes = 0;
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley name->offsets = NULL;
2f3cfa8c0212e47f92f6c45459d9ee0ba8aa0045Bob Halley name->buffer = NULL;
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley ISC_LINK_INIT(name, link);
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley}
e08daafffce8fb74ffca8ecf5772e334299ccf76Bob Halley
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrewsisc_boolean_t
4423c99613db1399dbb5c51e86ef0d351a1418c2Mark Andrewsdns_name_isvalid(const dns_name_t *name) {
4423c99613db1399dbb5c51e86ef0d351a1418c2Mark Andrews unsigned char *ndata, *offsets;
4423c99613db1399dbb5c51e86ef0d351a1418c2Mark Andrews unsigned int offset, count, length, nlabels;
4423c99613db1399dbb5c51e86ef0d351a1418c2Mark Andrews
4423c99613db1399dbb5c51e86ef0d351a1418c2Mark Andrews if (!VALID_NAME(name))
4423c99613db1399dbb5c51e86ef0d351a1418c2Mark Andrews return (ISC_FALSE);
602274b30f17281b8af0608016eadd0816d3eca6Mark Andrews
602274b30f17281b8af0608016eadd0816d3eca6Mark Andrews if (name->length > 255U || name->labels > 127U)
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews return (ISC_FALSE);
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews ndata = name->ndata;
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews length = name->length;
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews offsets = name->offsets;
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews offset = 0;
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews nlabels = 0;
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews while (offset != length) {
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews count = *ndata;
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews if (count > 63U)
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews return (ISC_FALSE);
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews if (offsets != NULL && offsets[nlabels] != offset)
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews return (ISC_FALSE);
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews nlabels++;
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews offset += count + 1;
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews ndata += count + 1;
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews if (offset > length)
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews return (ISC_FALSE);
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews if (count == 0)
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews break;
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews }
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews if (nlabels != name->labels || offset != name->length)
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews return (ISC_FALSE);
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews return (ISC_TRUE);
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews}
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrewsvoid
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrewsdns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) {
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews /*
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews * Dedicate a buffer for use with 'name'.
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews */
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews REQUIRE(VALID_NAME(name));
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews REQUIRE((buffer != NULL && name->buffer == NULL) ||
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews (buffer == NULL));
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews name->buffer = buffer;
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews}
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrewsisc_boolean_t
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrewsdns_name_hasbuffer(const dns_name_t *name) {
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews /*
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews * Does 'name' have a dedicated buffer?
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews */
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews REQUIRE(VALID_NAME(name));
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews if (name->buffer != NULL)
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews return (ISC_TRUE);
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews return (ISC_FALSE);
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews}
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrewsisc_boolean_t
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrewsdns_name_isabsolute(const dns_name_t *name) {
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews /*
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews * Does 'name' end in the root label?
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews */
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews REQUIRE(VALID_NAME(name));
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews return (ISC_TRUE);
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews return (ISC_FALSE);
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews}
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews#define hyphenchar(c) ((c) == 0x2d)
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews#define asterchar(c) ((c) == 0x2a)
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
7de2c6e6d51f38daeb2d346f3f21dc01ccece6daEvan Hunt || ((c) >= 0x61 && (c) <= 0x7a))
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
4f082b58b17ce39087930d5affc2ada90ef386e6Mark Andrews#define borderchar(c) (alphachar(c) || digitchar(c))
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews#define middlechar(c) (borderchar(c) || hyphenchar(c))
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrewsisc_boolean_t
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrewsdns_name_ismailbox(const dns_name_t *name) {
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews unsigned char *ndata, ch;
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews unsigned int n;
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews isc_boolean_t first;
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews REQUIRE(VALID_NAME(name));
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews REQUIRE(name->labels > 0);
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews /*
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews * Root label.
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews */
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews if (name->length == 1)
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews return (ISC_TRUE);
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews ndata = name->ndata;
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews n = *ndata++;
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews INSIST(n <= 63);
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews while (n--) {
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews ch = *ndata++;
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews if (!domainchar(ch))
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews return (ISC_FALSE);
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews }
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews if (ndata == name->ndata + name->length)
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews return (ISC_FALSE);
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews /*
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews * RFC292/RFC1123 hostname.
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews */
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews while (ndata < (name->ndata + name->length)) {
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews n = *ndata++;
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews INSIST(n <= 63);
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews first = ISC_TRUE;
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews while (n--) {
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews ch = *ndata++;
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews if (first || n == 0) {
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews if (!borderchar(ch))
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews return (ISC_FALSE);
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews } else {
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews if (!middlechar(ch))
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews return (ISC_FALSE);
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews }
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews first = ISC_FALSE;
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews }
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews }
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews return (ISC_TRUE);
4f082b58b17ce39087930d5affc2ada90ef386e6Mark Andrews}
7de2c6e6d51f38daeb2d346f3f21dc01ccece6daEvan Hunt
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrewsisc_boolean_t
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrewsdns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard) {
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews unsigned char *ndata, ch;
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews unsigned int n;
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews isc_boolean_t first;
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews REQUIRE(VALID_NAME(name));
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews REQUIRE(name->labels > 0);
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews /*
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews * Root label.
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews */
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews if (name->length == 1)
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews return (ISC_TRUE);
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews
4f082b58b17ce39087930d5affc2ada90ef386e6Mark Andrews /*
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews * Skip wildcard if this is a ownername.
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews */
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews ndata = name->ndata;
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews if (wildcard && ndata[0] == 1 && ndata[1] == '*')
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews ndata += 2;
4f082b58b17ce39087930d5affc2ada90ef386e6Mark Andrews
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews /*
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews * RFC292/RFC1123 hostname.
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews */
cc32d38366fa680fc29f9fb17bd3ebe515835445Mark Andrews while (ndata < (name->ndata + name->length)) {
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt n = *ndata++;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt INSIST(n <= 63);
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt first = ISC_TRUE;
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User while (n--) {
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt ch = *ndata++;
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User if (first || n == 0) {
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt if (!borderchar(ch))
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User return (ISC_FALSE);
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User } else {
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User if (!middlechar(ch))
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User return (ISC_FALSE);
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User }
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User first = ISC_FALSE;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt }
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt }
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt return (ISC_TRUE);
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt}
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Huntisc_boolean_t
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox Userdns_name_iswildcard(const dns_name_t *name) {
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt unsigned char *ndata;
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User /*
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User * Is 'name' a wildcard name?
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User */
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User REQUIRE(VALID_NAME(name));
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User REQUIRE(name->labels > 0);
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User if (name->length >= 2) {
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User ndata = name->ndata;
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User if (ndata[0] == 1 && ndata[1] == '*')
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User return (ISC_TRUE);
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User }
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User return (ISC_FALSE);
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User}
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox Userisc_boolean_t
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox Userdns_name_internalwildcard(const dns_name_t *name) {
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User unsigned char *ndata;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt unsigned int count;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt unsigned int label;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt /*
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews * Does 'name' contain a internal wildcard?
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews */
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews REQUIRE(VALID_NAME(name));
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews REQUIRE(name->labels > 0);
0a00c3eb03464988821a0b6817b63ddb3c090890Tinderbox User
0a00c3eb03464988821a0b6817b63ddb3c090890Tinderbox User /*
0a00c3eb03464988821a0b6817b63ddb3c090890Tinderbox User * Skip first label.
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews */
0a00c3eb03464988821a0b6817b63ddb3c090890Tinderbox User ndata = name->ndata;
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews count = *ndata++;
0a00c3eb03464988821a0b6817b63ddb3c090890Tinderbox User INSIST(count <= 63);
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews ndata += count;
0a00c3eb03464988821a0b6817b63ddb3c090890Tinderbox User label = 1;
0a00c3eb03464988821a0b6817b63ddb3c090890Tinderbox User /*
0a00c3eb03464988821a0b6817b63ddb3c090890Tinderbox User * Check all but the last of the remaining labels.
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews */
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews while (label + 1 < name->labels) {
0a00c3eb03464988821a0b6817b63ddb3c090890Tinderbox User count = *ndata++;
0a00c3eb03464988821a0b6817b63ddb3c090890Tinderbox User INSIST(count <= 63);
0a00c3eb03464988821a0b6817b63ddb3c090890Tinderbox User if (count == 1 && *ndata == '*')
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews return (ISC_TRUE);
0a00c3eb03464988821a0b6817b63ddb3c090890Tinderbox User ndata += count;
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews label++;
0a00c3eb03464988821a0b6817b63ddb3c090890Tinderbox User }
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews return (ISC_FALSE);
0a00c3eb03464988821a0b6817b63ddb3c090890Tinderbox User}
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews
0a00c3eb03464988821a0b6817b63ddb3c090890Tinderbox Userstatic inline unsigned int
0a00c3eb03464988821a0b6817b63ddb3c090890Tinderbox Username_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews unsigned int length;
0a00c3eb03464988821a0b6817b63ddb3c090890Tinderbox User const unsigned char *s;
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews unsigned int h = 0;
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews unsigned char c;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt length = name->length;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt if (length > 16)
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt length = 16;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt /*
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * This hash function is similar to the one Ousterhout
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * uses in Tcl.
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt */
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt s = name->ndata;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt if (case_sensitive) {
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt while (length > 0) {
6f85ff3aac98187ff140bad192d01a6cfd31cf1cMark Andrews h += ( h << 3 ) + *s;
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews s++;
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews length--;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt }
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt } else {
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt while (length > 0) {
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt c = maptolower[*s];
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt h += ( h << 3 ) + c;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt s++;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt length--;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt }
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt }
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt return (h);
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt}
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Huntunsigned int
67adc03ef81fb610f8df093b17f55275ee816754Evan Huntdns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt /*
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * Provide a hash value for 'name'.
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt */
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt REQUIRE(VALID_NAME(name));
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt if (name->labels == 0)
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt return (0);
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User return (name_hash(name, case_sensitive));
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User}
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Huntunsigned int
67adc03ef81fb610f8df093b17f55275ee816754Evan Huntdns_name_fullhash(dns_name_t *name, isc_boolean_t case_sensitive) {
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt /*
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * Provide a hash value for 'name'.
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt */
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt REQUIRE(VALID_NAME(name));
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt if (name->labels == 0)
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt return (0);
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt return (isc_hash_calc((const unsigned char *)name->ndata,
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt name->length, case_sensitive));
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt}
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Huntunsigned int
67adc03ef81fb610f8df093b17f55275ee816754Evan Huntdns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt /*
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * This function was deprecated due to the breakage of the name space
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * convention. We only keep this internally to provide binary backward
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * compatibility.
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt */
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt REQUIRE(VALID_NAME(name));
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt return (dns_name_fullhash(name, case_sensitive));
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt}
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Huntunsigned int
67adc03ef81fb610f8df093b17f55275ee816754Evan Huntdns_name_hashbylabel(dns_name_t *name, isc_boolean_t case_sensitive) {
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt unsigned char *offsets;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt dns_offsets_t odata;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt dns_name_t tname;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt unsigned int h = 0;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt unsigned int i;
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews /*
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews * Provide a hash value for 'name'.
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews */
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews REQUIRE(VALID_NAME(name));
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews if (name->labels == 0)
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews return (0);
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews else if (name->labels == 1)
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews return (name_hash(name, case_sensitive));
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews SETUP_OFFSETS(name, offsets, odata);
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews DNS_NAME_INIT(&tname, NULL);
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews tname.labels = 1;
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews h = 0;
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews for (i = 0; i < name->labels; i++) {
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews tname.ndata = name->ndata + offsets[i];
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews if (i == name->labels - 1)
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews tname.length = name->length - offsets[i];
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews else
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews tname.length = offsets[i + 1] - offsets[i];
d8c1e4eccf5bf88a3b4f8dc4a24391b5712bb3a3Mark Andrews h += name_hash(&tname, case_sensitive);
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt }
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt return (h);
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt}
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Huntdns_namereln_t
67adc03ef81fb610f8df093b17f55275ee816754Evan Huntdns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt int *orderp, unsigned int *nlabelsp)
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt{
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt unsigned int l1, l2, l, count1, count2, count, nlabels;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt int cdiff, ldiff, chdiff;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt unsigned char *label1, *label2;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt unsigned char *offsets1, *offsets2;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt dns_offsets_t odata1, odata2;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt dns_namereln_t namereln = dns_namereln_none;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt /*
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * Determine the relative ordering under the DNSSEC order relation of
b99bfa184bc9375421b5df915eea7dfac6a68a99Evan Hunt * 'name1' and 'name2', and also determine the hierarchical
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * relationship of the names.
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt *
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * Note: It makes no sense for one of the names to be relative and the
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * other absolute. If both names are relative, then to be meaningfully
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * compared the caller must ensure that they are both relative to the
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * same domain.
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt */
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt REQUIRE(VALID_NAME(name1));
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt REQUIRE(VALID_NAME(name2));
b99bfa184bc9375421b5df915eea7dfac6a68a99Evan Hunt REQUIRE(orderp != NULL);
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt REQUIRE(nlabelsp != NULL);
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt /*
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * Either name1 is absolute and name2 is absolute, or neither is.
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt */
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt if (name1 == name2) {
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt *orderp = 0;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt return (dns_namereln_equal);
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User }
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt SETUP_OFFSETS(name1, offsets1, odata1);
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt SETUP_OFFSETS(name2, offsets2, odata2);
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt nlabels = 0;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt l1 = name1->labels;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt l2 = name2->labels;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt if (l2 > l1) {
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt l = l1;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt ldiff = 0 - (l2 - l1);
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt } else {
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt l = l2;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt ldiff = l1 - l2;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt }
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt while (l > 0) {
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt l--;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt l1--;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt l2--;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt label1 = &name1->ndata[offsets1[l1]];
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt label2 = &name2->ndata[offsets2[l2]];
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt count1 = *label1++;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt count2 = *label2++;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt /*
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * We dropped bitstring labels, and we don't support any
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * other extended label types.
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt */
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt INSIST(count1 <= 63 && count2 <= 63);
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt cdiff = (int)count1 - (int)count2;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt if (cdiff < 0)
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt count = count1;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt else
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User count = count2;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt while (count > 0) {
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt chdiff = (int)maptolower[*label1] -
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt (int)maptolower[*label2];
b99bfa184bc9375421b5df915eea7dfac6a68a99Evan Hunt if (chdiff != 0) {
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt *orderp = chdiff;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt goto done;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt }
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt count--;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt label1++;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt label2++;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt }
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt if (cdiff != 0) {
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt *orderp = cdiff;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt goto done;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt }
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt nlabels++;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt }
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt *orderp = ldiff;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt if (ldiff < 0)
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt namereln = dns_namereln_contains;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt else if (ldiff > 0)
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt namereln = dns_namereln_subdomain;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt else
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User namereln = dns_namereln_equal;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt done:
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt *nlabelsp = nlabels;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt if (nlabels > 0 && namereln == dns_namereln_none)
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt namereln = dns_namereln_commonancestor;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt return (namereln);
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt}
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Huntint
67adc03ef81fb610f8df093b17f55275ee816754Evan Huntdns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt int order;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt unsigned int nlabels;
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt /*
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * Determine the relative ordering under the DNSSEC order relation of
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * 'name1' and 'name2'.
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt *
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * Note: It makes no sense for one of the names to be relative and the
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * other absolute. If both names are relative, then to be meaningfully
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * compared the caller must ensure that they are both relative to the
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * same domain.
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt */
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt (void)dns_name_fullcompare(name1, name2, &order, &nlabels);
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt return (order);
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt}
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
67adc03ef81fb610f8df093b17f55275ee816754Evan Huntisc_boolean_t
67adc03ef81fb610f8df093b17f55275ee816754Evan Huntdns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt unsigned int l, count;
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt unsigned char c;
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt unsigned char *label1, *label2;
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 /*
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 * Are 'name1' and 'name2' equal?
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 *
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 * Note: It makes no sense for one of the names to be relative and the
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 * other absolute. If both names are relative, then to be meaningfully
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 * compared the caller must ensure that they are both relative to the
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 * same domain.
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 */
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 REQUIRE(VALID_NAME(name1));
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 REQUIRE(VALID_NAME(name2));
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 /*
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 * Either name1 is absolute and name2 is absolute, or neither is.
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 */
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 if (name1 == name2)
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 return (ISC_TRUE);
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 if (name1->length != name2->length)
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 return (ISC_FALSE);
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 l = name1->labels;
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 if (l != name2->labels)
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 return (ISC_FALSE);
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 label1 = name1->ndata;
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 label2 = name2->ndata;
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt while (l > 0) {
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt l--;
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt count = *label1++;
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt if (count != *label2++)
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt return (ISC_FALSE);
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt INSIST(count <= 63); /* no bitstring support */
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt while (count > 0) {
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt count--;
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt c = maptolower[*label1++];
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt if (c != maptolower[*label2++])
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt return (ISC_FALSE);
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt }
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt }
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt return (ISC_TRUE);
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt}
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt
64ecc88345766e124e1fb053dbf4e36550471f83Evan Huntisc_boolean_t
64ecc88345766e124e1fb053dbf4e36550471f83Evan Huntdns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt /*
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt * Are 'name1' and 'name2' equal?
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt *
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt * Note: It makes no sense for one of the names to be relative and the
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt * other absolute. If both names are relative, then to be meaningfully
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt * compared the caller must ensure that they are both relative to the
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt * same domain.
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt */
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt REQUIRE(VALID_NAME(name1));
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt REQUIRE(VALID_NAME(name2));
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt /*
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt * Either name1 is absolute and name2 is absolute, or neither is.
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt */
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt if (name1->length != name2->length)
64ecc88345766e124e1fb053dbf4e36550471f83Evan Hunt return (ISC_FALSE);
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 if (memcmp(name1->ndata, name2->ndata, name1->length) != 0)
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 return (ISC_FALSE);
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 return (ISC_TRUE);
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉}
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉
64ecc88345766e124e1fb053dbf4e36550471f83Evan Huntint
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 unsigned int l1, l2, l, count1, count2, count;
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 unsigned char c1, c2;
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 unsigned char *label1, *label2;
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 /*
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 * Compare two absolute names as rdata.
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 */
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 REQUIRE(VALID_NAME(name1));
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 REQUIRE(name1->labels > 0);
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 REQUIRE(VALID_NAME(name2));
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews REQUIRE(name2->labels > 0);
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews l1 = name1->labels;
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews l2 = name2->labels;
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews l = (l1 < l2) ? l1 : l2;
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews label1 = name1->ndata;
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews label2 = name2->ndata;
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews while (l > 0) {
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews l--;
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews count1 = *label1++;
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews count2 = *label2++;
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews /* no bitstring support */
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews INSIST(count1 <= 63 && count2 <= 63);
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews if (count1 != count2)
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews return ((count1 < count2) ? -1 : 1);
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews count = count1;
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews while (count > 0) {
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews count--;
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews c1 = maptolower[*label1++];
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews c2 = maptolower[*label2++];
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews if (c1 < c2)
0ffaee887ff5674b8c3bb0435ae838f641981706Mark Andrews return (-1);
else if (c1 > c2)
return (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;
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);
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, 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));
#if defined(__clang__) && \
( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
memset(&tname, 0, sizeof(tname));
#endif
DNS_NAME_INIT(&tname, NULL);
dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
if (dns_name_fullcompare(name, &tname, &order, &nlabels) ==
dns_namereln_subdomain)
return (ISC_TRUE);
return (ISC_FALSE);
}
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(n <= source->labels - first); /* note first+n could overflow */
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(const 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)
memmove(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;
memmove(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,
const dns_name_t *origin, unsigned int options,
isc_buffer_t *target)
{
unsigned char *ndata, *label = NULL;
char *tdata;
char c;
ft_state state;
unsigned int value = 0, count = 0;
unsigned int n1 = 0, n2 = 0;
unsigned int tlen, nrem, nused, digits = 0, labels, tused;
isc_boolean_t done;
unsigned char *offsets;
dns_offsets_t odata;
isc_boolean_t downcase;
/*
* 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 && ISC_BUFFER_VALID(name->buffer)));
downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
if (target == NULL && name->buffer != NULL) {
target = name->buffer;
isc_buffer_clear(target);
}
REQUIRE(BINDABLE(name));
INIT_OFFSETS(name, offsets, odata);
offsets[0] = 0;
/*
* 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;
state = ft_init;
while (nrem > 0 && tlen > 0 && !done) {
c = *tdata++;
tlen--;
tused++;
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;
}
state = ft_ordinary;
if (nrem == 0)
return (ISC_R_NOSPACE);
/* 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[c & 0xff];
*ndata++ = c;
nrem--;
nused++;
}
break;
case ft_initialescape:
if (c == '[') {
/*
* This looks like a bitstring label, which
* was deprecated. Intentionally drop it.
*/
return (DNS_R_BADLABELTYPE);
}
state = ft_escape;
POST(state);
/* FALLTHROUGH */
case ft_escape:
if (!isdigit(c & 0xff)) {
if (count >= 63)
return (DNS_R_LABELTOOLONG);
count++;
CONVERTTOASCII(c);
if (downcase)
c = maptolower[c & 0xff];
*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[c & 0xff];
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;
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_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;
POST(nrem);
while (n1 > 0) {
n2 = *label++;
INSIST(n2 <= 63); /* no bitstring support */
*ndata++ = n2;
n1 -= n2 + 1;
nused += n2 + 1;
while (n2 > 0) {
c = *label++;
if (downcase)
c = maptolower[c & 0xff];
*ndata++ = c;
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;
isc_buffer_forward(source, tused);
isc_buffer_add(target, name->length);
return (ISC_R_SUCCESS);
}
#ifdef ISC_PLATFORM_USETHREADS
static void
free_specific(void *arg) {
dns_name_totextfilter_t *mem = arg;
isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
/* Stop use being called again. */
(void)isc_thread_key_setspecific(totext_filter_proc_key, NULL);
}
static void
thread_key_mutex_init(void) {
RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS);
}
static isc_result_t
totext_filter_proc_key_init(void) {
isc_result_t result;
/*
* We need the call to isc_once_do() to support profiled mutex
* otherwise thread_key_mutex could be initialized at compile time.
*/
result = isc_once_do(&once, thread_key_mutex_init);
if (result != ISC_R_SUCCESS)
return (result);
if (!thread_key_initialized) {
LOCK(&thread_key_mutex);
if (thread_key_mctx == NULL)
result = isc_mem_create2(0, 0, &thread_key_mctx, 0);
if (result != ISC_R_SUCCESS)
goto unlock;
isc_mem_setname(thread_key_mctx, "threadkey", NULL);
isc_mem_setdestroycheck(thread_key_mctx, ISC_FALSE);
if (!thread_key_initialized &&
isc_thread_key_create(&totext_filter_proc_key,
free_specific) != 0) {
result = ISC_R_FAILURE;
isc_mem_detach(&thread_key_mctx);
} else
thread_key_initialized = 1;
unlock:
UNLOCK(&thread_key_mutex);
}
return (result);
}
#endif
isc_result_t
dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
isc_buffer_t *target)
{
unsigned int options = DNS_NAME_MASTERFILE;
if (omit_final_dot)
options |= DNS_NAME_OMITFINALDOT;
return (dns_name_totext2(name, options, target));
}
isc_result_t
dns_name_toprincipal(dns_name_t *name, isc_buffer_t *target) {
return (dns_name_totext2(name, DNS_NAME_OMITFINALDOT, target));
}
isc_result_t
dns_name_totext2(dns_name_t *name, unsigned int options, isc_buffer_t *target)
{
unsigned char *ndata;
char *tdata;
unsigned int nlen, tlen;
unsigned char c;
unsigned int trem, count;
unsigned int labels;
isc_boolean_t saw_root = ISC_FALSE;
unsigned int oused = target->used;
#ifdef ISC_PLATFORM_USETHREADS
dns_name_totextfilter_t *mem;
dns_name_totextfilter_t totext_filter_proc = NULL;
isc_result_t result;
#endif
isc_boolean_t omit_final_dot =
ISC_TF(options & DNS_NAME_OMITFINALDOT);
/*
* This function assumes the name is in proper uncompressed
* wire format.
*/
REQUIRE(VALID_NAME(name));
REQUIRE(ISC_BUFFER_VALID(target));
#ifdef ISC_PLATFORM_USETHREADS
result = totext_filter_proc_key_init();
if (result != ISC_R_SUCCESS)
return (result);
#endif
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) {
/* Special modifiers in zone files. */
case 0x40: /* '@' */
case 0x24: /* '$' */
if ((options & DNS_NAME_MASTERFILE) == 0)
goto no_escape;
/* FALLTHROUGH */
case 0x22: /* '"' */
case 0x28: /* '(' */
case 0x29: /* ')' */
case 0x2E: /* '.' */
case 0x3B: /* ';' */
case 0x5C: /* '\\' */
if (trem < 2)
return (ISC_R_NOSPACE);
*tdata++ = '\\';
CONVERTFROMASCII(c);
*tdata++ = c;
ndata++;
trem -= 2;
nlen--;
break;
no_escape:
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);
*tdata++ = 0x5c;
*tdata++ = 0x30 +
((c / 100) % 10);
*tdata++ = 0x30 +
((c / 10) % 10);
*tdata++ = 0x30 + (c % 10);
trem -= 4;
ndata++;
nlen--;
}
}
count--;
}
} 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);
#ifdef ISC_PLATFORM_USETHREADS
mem = isc_thread_key_getspecific(totext_filter_proc_key);
if (mem != NULL)
totext_filter_proc = *mem;
#endif
if (totext_filter_proc != NULL)
return ((*totext_filter_proc)(target, oused, saw_root));
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 labels;
/*
* 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 {
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, 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));
REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
(target == NULL && ISC_BUFFER_VALID(name->buffer)));
if (target == 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 {
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;
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++;
INSIST(count <= 63);
offset += count;
ndata += count;
INSIST(offset <= length);
if (count == 0) {
absolute = ISC_TRUE;
break;
}
}
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);
}
isc_result_t
dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
dns_decompress_t *dctx, unsigned int options,
isc_buffer_t *target)
{
unsigned char *cdata, *ndata;
unsigned int cused; /* Bytes of compressed name data used */
unsigned int nused, labels, n, nmax;
unsigned int current, new_current, biggest_pointer;
isc_boolean_t done;
fw_state state = fw_start;
unsigned int c;
unsigned char *offsets;
dns_offsets_t odata;
isc_boolean_t downcase;
isc_boolean_t seen_pointer;
/*
* Copy the possibly-compressed name at source into target,
* decompressing it. Loop prevention is performed by checking
* the new pointer against biggest_pointer.
*/
REQUIRE(VALID_NAME(name));
REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
(target == NULL && ISC_BUFFER_VALID(name->buffer)));
downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
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;
done = ISC_FALSE;
ndata = isc_buffer_used(target);
nused = 0;
seen_pointer = ISC_FALSE;
/*
* 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 (!seen_pointer)
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
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_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;
seen_pointer = ISC_TRUE;
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;
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(const 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);
REQUIRE(ISC_BUFFER_VALID(target));
/*
* If 'name' doesn't have an offsets table, make a clone which
* has one.
*/
if (name->offsets == NULL) {
#if defined(__clang__) && \
( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
memset(&clname, 0, sizeof(clname));
#endif
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 ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
(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)memmove((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)memmove((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;
isc_boolean_t copy_prefix = ISC_TRUE;
isc_boolean_t copy_suffix = ISC_TRUE;
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));
REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
(target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer)));
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) {
INSIST(name->buffer != NULL);
target = name->buffer;
isc_buffer_clear(name->buffer);
}
REQUIRE(BINDABLE(name));
/*
* 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;
memmove(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))
memmove(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) {
INIT_OFFSETS(name, offsets, odata);
set_offsets(name, offsets, NULL);
}
isc_buffer_add(target, name->length);
return (ISC_R_SUCCESS);
}
void
dns_name_split(dns_name_t *name, unsigned int suffixlabels,
dns_name_t *prefix, dns_name_t *suffix)
{
unsigned int splitlabel;
REQUIRE(VALID_NAME(name));
REQUIRE(suffixlabels > 0);
REQUIRE(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)));
splitlabel = name->labels - suffixlabels;
if (prefix != NULL)
dns_name_getlabelsequence(name, 0, splitlabel, prefix);
if (suffix != NULL)
dns_name_getlabelsequence(name, splitlabel,
suffixlabels, suffix);
return;
}
isc_result_t
dns_name_dup(const 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);
memmove(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)
memmove(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);
memmove(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)
memmove(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);
#if defined(__clang__) && \
( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
memset(&downname, 0, sizeof(downname));
#endif
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);
}
isc_result_t
dns_name_settotextfilter(dns_name_totextfilter_t proc) {
#ifdef ISC_PLATFORM_USETHREADS
isc_result_t result;
dns_name_totextfilter_t *mem;
int res;
result = totext_filter_proc_key_init();
if (result != ISC_R_SUCCESS)
return (result);
/*
* If we already have been here set / clear as appropriate.
* Otherwise allocate memory.
*/
mem = isc_thread_key_getspecific(totext_filter_proc_key);
if (mem != NULL && proc != NULL) {
*mem = proc;
return (ISC_R_SUCCESS);
}
if (proc == NULL) {
isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
res = isc_thread_key_setspecific(totext_filter_proc_key, NULL);
if (res != 0)
result = ISC_R_UNEXPECTED;
return (result);
}
mem = isc_mem_get(thread_key_mctx, sizeof(*mem));
if (mem == NULL)
return (ISC_R_NOMEMORY);
*mem = proc;
if (isc_thread_key_setspecific(totext_filter_proc_key, mem) != 0) {
isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
result = ISC_R_UNEXPECTED;
}
return (result);
#else
totext_filter_proc = proc;
return (ISC_R_SUCCESS);
#endif
}
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>");
}
/*
* dns_name_tostring() -- similar to dns_name_format() but allocates its own
* memory.
*/
isc_result_t
dns_name_tostring(dns_name_t *name, char **target, isc_mem_t *mctx) {
isc_result_t result;
isc_buffer_t buf;
isc_region_t reg;
char *p, txt[DNS_NAME_FORMATSIZE];
REQUIRE(VALID_NAME(name));
REQUIRE(target != NULL && *target == NULL);
isc_buffer_init(&buf, txt, sizeof(txt));
result = dns_name_totext(name, ISC_FALSE, &buf);
if (result != ISC_R_SUCCESS)
return (result);
isc_buffer_usedregion(&buf, &reg);
p = isc_mem_allocate(mctx, reg.length + 1);
memmove(p, (char *) reg.base, (int) reg.length);
p[reg.length] = '\0';
*target = p;
return (ISC_R_SUCCESS);
}
/*
* dns_name_fromstring() -- convert directly from a string to a name,
* allocating memory as needed
*/
isc_result_t
dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options,
isc_mem_t *mctx)
{
return (dns_name_fromstring2(target, src, dns_rootname, options, mctx));
}
isc_result_t
dns_name_fromstring2(dns_name_t *target, const char *src,
const dns_name_t *origin, unsigned int options,
isc_mem_t *mctx)
{
isc_result_t result;
isc_buffer_t buf;
dns_fixedname_t fn;
dns_name_t *name;
REQUIRE(src != NULL);
isc_buffer_constinit(&buf, src, strlen(src));
isc_buffer_add(&buf, strlen(src));
if (BINDABLE(target) && target->buffer != NULL)
name = target;
else {
dns_fixedname_init(&fn);
name = dns_fixedname_name(&fn);
}
result = dns_name_fromtext(name, &buf, origin, options, NULL);
if (result != ISC_R_SUCCESS)
return (result);
if (name != target)
result = dns_name_dupwithoffsets(name, mctx, target);
return (result);
}
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;
memmove(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)
memmove(dest->offsets, source->offsets, source->labels);
else
set_offsets(dest, dest->offsets, NULL);
}
isc_buffer_add(target, dest->length);
return (ISC_R_SUCCESS);
}
void
dns_name_destroy(void) {
#ifdef ISC_PLATFORM_USETHREADS
RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init)
== ISC_R_SUCCESS);
LOCK(&thread_key_mutex);
if (thread_key_initialized) {
isc_mem_detach(&thread_key_mctx);
isc_thread_key_delete(totext_filter_proc_key);
thread_key_initialized = 0;
}
UNLOCK(&thread_key_mutex);
#endif
}