name.c revision 72bdbe3c70f415a717f59f72d04590d70acb380e
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews/*
499b34cea04a46823d003d4c0520c8b03e8513cbBrian Wellington * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Copyright (C) 1998-2003 Internet Software Consortium.
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews *
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * Permission to use, copy, modify, and distribute this software for any
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * purpose with or without fee is hereby granted, provided that the above
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * copyright notice and this permission notice appear in all copies.
15a44745412679c30a6d022733925af70a38b715David Lawrence *
15a44745412679c30a6d022733925af70a38b715David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
15a44745412679c30a6d022733925af70a38b715David Lawrence * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15a44745412679c30a6d022733925af70a38b715David Lawrence * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
15a44745412679c30a6d022733925af70a38b715David Lawrence * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15a44745412679c30a6d022733925af70a38b715David Lawrence * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15a44745412679c30a6d022733925af70a38b715David Lawrence * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15a44745412679c30a6d022733925af70a38b715David Lawrence * PERFORMANCE OF THIS SOFTWARE.
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
dcc7ea97174501f0409c0c919b3ca04083e4e1b8Andreas Gustafsson/* $Id: name.c,v 1.154 2005/09/10 01:02:08 marka Exp $ */
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews/*! \file */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
92ef1a9b9dbd48ecb507b42ac62c15afefdaf838David Lawrence#include <config.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#include <ctype.h>
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#include <stdlib.h>
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#include <isc/buffer.h>
e21d199dca95aff5d50f133d6b064309e209af00Brian Wellington#include <isc/hash.h>
e43b9a20054cdda6946ab758e1c2005f2b25641aBrian Wellington#include <isc/mem.h>
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#include <isc/once.h>
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#include <isc/print.h>
8b61d2012063306528286680bd9f086fa868d86eMark Andrews#include <isc/string.h>
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#include <isc/thread.h>
19d1b1667d073850d4366352aaf8319efc5debeeBrian Wellington#include <isc/util.h>
19d1b1667d073850d4366352aaf8319efc5debeeBrian Wellington
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews#include <dns/compress.h>
09f22ac5b09e70bc526015f37168ba33e21ea91fDavid Lawrence#include <dns/name.h>
19d1b1667d073850d4366352aaf8319efc5debeeBrian Wellington#include <dns/result.h>
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
92ef1a9b9dbd48ecb507b42ac62c15afefdaf838David Lawrence#define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
92ef1a9b9dbd48ecb507b42ac62c15afefdaf838David Lawrence
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewstypedef enum {
92ef1a9b9dbd48ecb507b42ac62c15afefdaf838David Lawrence ft_init = 0,
92ef1a9b9dbd48ecb507b42ac62c15afefdaf838David Lawrence ft_start,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews ft_ordinary,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews ft_initialescape,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews ft_escape,
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews ft_escdecimal,
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews ft_at
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews} ft_state;
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Grafftypedef enum {
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff fw_start = 0,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews fw_ordinary,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews fw_copy,
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff fw_newcurrent
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff} fw_state;
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graffstatic char digitvalue[256] = {
46993e1d9d18410a5852b7d990338b70b158855cMichael Graff -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff};
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graffstatic unsigned char maptolower[] = {
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
19d1b1667d073850d4366352aaf8319efc5debeeBrian Wellington 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0ad8ee89c532951a55b7de25317eeca2c3b2ed63Andreas Gustafsson 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0ad8ee89c532951a55b7de25317eeca2c3b2ed63Andreas Gustafsson 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
f53848e17123569387b279578f0100dca5407da5Mark Andrews 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews};
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#define CONVERTTOASCII(c)
59abb512d344bfa09012cc11b7d814966f035da4Mark Andrews#define CONVERTFROMASCII(c)
559bb1016f1b00a3661cb2790dc837a977057b86Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#define INIT_OFFSETS(name, var, default) \
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (name->offsets != NULL) \
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews var = name->offsets; \
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews else \
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews var = default;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#define SETUP_OFFSETS(name, var, default) \
8b61d2012063306528286680bd9f086fa868d86eMark Andrews if (name->offsets != NULL) \
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson var = name->offsets; \
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews else { \
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews var = default; \
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews set_offsets(name, var, NULL); \
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews }
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews/*%
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Note: If additional attributes are added that should not be set for
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * empty names, MAKE_EMPTY() must be changed so it clears them.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews */
46993e1d9d18410a5852b7d990338b70b158855cMichael Graff#define MAKE_EMPTY(name) \
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graffdo { \
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews name->ndata = NULL; \
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews name->length = 0; \
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews name->labels = 0; \
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews} while (0);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews/*%
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews * A name is "bindable" if it can be set to point to a new value, i.e.
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * name->ndata and name->length may be changed.
8b61d2012063306528286680bd9f086fa868d86eMark Andrews */
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews#define BINDABLE(name) \
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews ((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews == 0)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
46993e1d9d18410a5852b7d990338b70b158855cMichael Graff/*%
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff * Note that the name data must be a char array, not a string
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * literal, to avoid compiler warnings about discarding
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * the const attribute of a string.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsstatic unsigned char root_ndata[] = { '\0' };
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsstatic unsigned char root_offsets[] = { 0 };
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsstatic dns_name_t root =
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews{
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews DNS_NAME_MAGIC,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews root_ndata, 1, 1,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews root_offsets, NULL,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews {(void *)-1, (void *)-1},
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews {NULL, NULL}
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff};
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews/* XXXDCL make const? */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark AndrewsLIBDNS_EXTERNAL_DATA dns_name_t *dns_rootname = &root;
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrewsstatic unsigned char wild_ndata[] = { '\001', '*' };
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graffstatic unsigned char wild_offsets[] = { 0 };
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews
5e387b9ce6bafdfadedb5b34e4c33a4404e5d589Brian Wellingtonstatic dns_name_t wild =
5e387b9ce6bafdfadedb5b34e4c33a4404e5d589Brian Wellington{
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews DNS_NAME_MAGIC,
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews wild_ndata, 2, 1,
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews DNS_NAMEATTR_READONLY,
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews wild_offsets, NULL,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews {(void *)-1, (void *)-1},
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews {NULL, NULL}
46993e1d9d18410a5852b7d990338b70b158855cMichael Graff};
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews/* XXXDCL make const? */
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark AndrewsLIBDNS_EXTERNAL_DATA dns_name_t *dns_wildcardname = &wild;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsunsigned int
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsdns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews/*
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews * dns_name_t to text post-conversion procedure.
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews */
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews#ifdef ISC_PLATFORM_USETHREADS
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsstatic isc_thread_key_t totext_filter_proc_key;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsstatic isc_once_t once = ISC_ONCE_INIT;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews#else
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrewsstatic dns_name_totextfilter_t totext_filter_proc = NULL;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews#endif
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
8b61d2012063306528286680bd9f086fa868d86eMark Andrewsstatic void
8b61d2012063306528286680bd9f086fa868d86eMark Andrewsset_offsets(const dns_name_t *name, unsigned char *offsets,
8b61d2012063306528286680bd9f086fa868d86eMark Andrews dns_name_t *set_name);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsvoid
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsdns_name_init(dns_name_t *name, unsigned char *offsets) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews /*
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * Initialize 'name'.
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews DNS_NAME_INIT(name, offsets);
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington}
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsvoid
8b61d2012063306528286680bd9f086fa868d86eMark Andrewsdns_name_reset(dns_name_t *name) {
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews REQUIRE(VALID_NAME(name));
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington REQUIRE(BINDABLE(name));
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington DNS_NAME_RESET(name);
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington}
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellingtonvoid
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellingtondns_name_invalidate(dns_name_t *name) {
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington /*
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington * Make 'name' invalid.
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington */
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington REQUIRE(VALID_NAME(name));
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington name->magic = 0;
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington name->ndata = NULL;
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington name->length = 0;
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington name->labels = 0;
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington name->attributes = 0;
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington name->offsets = NULL;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews name->buffer = NULL;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews ISC_LINK_INIT(name, link);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews}
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsvoid
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsdns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews /*
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington * Dedicate a buffer for use with 'name'.
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews */
8b61d2012063306528286680bd9f086fa868d86eMark Andrews
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews REQUIRE(VALID_NAME(name));
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE((buffer != NULL && name->buffer == NULL) ||
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews (buffer == NULL));
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews name->buffer = buffer;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews}
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsisc_boolean_t
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsdns_name_hasbuffer(const dns_name_t *name) {
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews /*
8b61d2012063306528286680bd9f086fa868d86eMark Andrews * Does 'name' have a dedicated buffer?
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews */
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews REQUIRE(VALID_NAME(name));
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews if (name->buffer != NULL)
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews return (ISC_TRUE);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews return (ISC_FALSE);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews}
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsisc_boolean_t
4be19dcd14cea678511f1d1b269ab89273e987eeMark Andrewsdns_name_isabsolute(const dns_name_t *name) {
4be19dcd14cea678511f1d1b269ab89273e987eeMark Andrews
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews /*
4be19dcd14cea678511f1d1b269ab89273e987eeMark Andrews * Does 'name' end in the root label?
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews */
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews REQUIRE(VALID_NAME(name));
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews return (ISC_TRUE);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews return (ISC_FALSE);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews}
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews#define hyphenchar(c) ((c) == 0x2d)
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington#define asterchar(c) ((c) == 0x2a)
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews || ((c) >= 0x61 && (c) <= 0x7a))
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews#define borderchar(c) (alphachar(c) || digitchar(c))
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews#define middlechar(c) (borderchar(c) || hyphenchar(c))
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
8b61d2012063306528286680bd9f086fa868d86eMark Andrews
8b61d2012063306528286680bd9f086fa868d86eMark Andrewsisc_boolean_t
8b61d2012063306528286680bd9f086fa868d86eMark Andrewsdns_name_ismailbox(const dns_name_t *name) {
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews unsigned char *ndata, ch;
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews unsigned int n;
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews isc_boolean_t first;
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews REQUIRE(VALID_NAME(name));
f53848e17123569387b279578f0100dca5407da5Mark Andrews REQUIRE(name->labels > 0);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews /*
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews * Root label.
8b61d2012063306528286680bd9f086fa868d86eMark Andrews */
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews if (name->length == 1)
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews return (ISC_TRUE);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews ndata = name->ndata;
8b61d2012063306528286680bd9f086fa868d86eMark Andrews n = *ndata++;
8b61d2012063306528286680bd9f086fa868d86eMark Andrews INSIST(n <= 63);
8b61d2012063306528286680bd9f086fa868d86eMark Andrews while (n--) {
8b61d2012063306528286680bd9f086fa868d86eMark Andrews ch = *ndata++;
4be19dcd14cea678511f1d1b269ab89273e987eeMark Andrews if (!domainchar(ch))
4be19dcd14cea678511f1d1b269ab89273e987eeMark Andrews return (ISC_FALSE);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews }
4be19dcd14cea678511f1d1b269ab89273e987eeMark Andrews
4be19dcd14cea678511f1d1b269ab89273e987eeMark Andrews if (ndata == name->ndata + name->length)
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews return (ISC_FALSE);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews /*
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews * RFC292/RFC1123 hostname.
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews while (ndata < (name->ndata + name->length)) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews n = *ndata++;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews INSIST(n <= 63);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews first = ISC_TRUE;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews while (n--) {
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington ch = *ndata++;
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington if (first || n == 0) {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (!borderchar(ch))
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews return (ISC_FALSE);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews } else {
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews if (!middlechar(ch))
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews return (ISC_FALSE);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews }
8b61d2012063306528286680bd9f086fa868d86eMark Andrews first = ISC_FALSE;
8b61d2012063306528286680bd9f086fa868d86eMark Andrews }
8b61d2012063306528286680bd9f086fa868d86eMark Andrews }
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews return (ISC_TRUE);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews}
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsisc_boolean_t
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsdns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews unsigned char *ndata, ch;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews unsigned int n;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_boolean_t first;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE(VALID_NAME(name));
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE(name->labels > 0);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews /*
8b61d2012063306528286680bd9f086fa868d86eMark Andrews * Root label.
8b61d2012063306528286680bd9f086fa868d86eMark Andrews */
8b61d2012063306528286680bd9f086fa868d86eMark Andrews if (name->length == 1)
8b61d2012063306528286680bd9f086fa868d86eMark Andrews return (ISC_TRUE);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews /*
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Skip wildcard if this is a ownername.
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews ndata = name->ndata;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (wildcard && ndata[0] == 1 && ndata[1] == '*')
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews ndata += 2;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews /*
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * RFC292/RFC1123 hostname.
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews while (ndata < (name->ndata + name->length)) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews n = *ndata++;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews INSIST(n <= 63);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews first = ISC_TRUE;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews while (n--) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews ch = *ndata++;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews if (first || n == 0) {
8b61d2012063306528286680bd9f086fa868d86eMark Andrews if (!borderchar(ch))
8b61d2012063306528286680bd9f086fa868d86eMark Andrews return (ISC_FALSE);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews } else {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews if (!middlechar(ch))
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews return (ISC_FALSE);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews }
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews first = ISC_FALSE;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews }
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff }
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff return (ISC_TRUE);
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff}
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsisc_boolean_t
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsdns_name_iswildcard(const dns_name_t *name) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews unsigned char *ndata;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews /*
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Is 'name' a wildcard name?
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews */
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews REQUIRE(VALID_NAME(name));
8b61d2012063306528286680bd9f086fa868d86eMark Andrews REQUIRE(name->labels > 0);
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews if (name->length >= 2) {
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews ndata = name->ndata;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (ndata[0] == 1 && ndata[1] == '*')
5e387b9ce6bafdfadedb5b34e4c33a4404e5d589Brian Wellington return (ISC_TRUE);
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews }
5e387b9ce6bafdfadedb5b34e4c33a4404e5d589Brian Wellington
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews return (ISC_FALSE);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews}
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrewsisc_boolean_t
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrewsdns_name_internalwildcard(const dns_name_t *name) {
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews unsigned char *ndata;
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews unsigned int count;
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews unsigned int label;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews /*
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews * Does 'name' contain a internal wildcard?
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews */
8b61d2012063306528286680bd9f086fa868d86eMark Andrews
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews REQUIRE(VALID_NAME(name));
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews REQUIRE(name->labels > 0);
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews /*
668eb43f1f24c887b6972f6a1610b4b38b281080Brian Wellington * Skip first label.
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews */
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews ndata = name->ndata;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews count = *ndata++;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews INSIST(count <= 63);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews ndata += count;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews label = 1;
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews /*
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Check all but the last of the remaining labels.
8b61d2012063306528286680bd9f086fa868d86eMark Andrews */
8b61d2012063306528286680bd9f086fa868d86eMark Andrews while (label + 1 < name->labels) {
390b2077fc751105e40174ceaa1ce34ef06e7dd4Mark Andrews count = *ndata++;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews INSIST(count <= 63);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence if (count == 1 && *ndata == '*')
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews return (ISC_TRUE);
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews ndata += count;
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews label++;
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews }
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews return (ISC_FALSE);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews}
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellingtonstatic inline unsigned int
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellingtonname_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington unsigned int length;
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington const unsigned char *s;
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington unsigned int h = 0;
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington unsigned char c;
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington length = name->length;
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington if (length > 16)
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington length = 16;
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington /*
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington * This hash function is similar to the one Ousterhout
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington * uses in Tcl.
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington */
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington s = name->ndata;
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington if (case_sensitive) {
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington while (length > 0) {
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington h += ( h << 3 ) + *s;
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington s++;
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington length--;
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington }
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington } else {
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington while (length > 0) {
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson c = maptolower[*s];
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson h += ( h << 3 ) + c;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson s++;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson length--;
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington }
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington }
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington
ac6afcd0caf72aaa2a537e0003de30b363b4a68bBrian Wellington return (h);
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington}
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellingtonunsigned int
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellingtondns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington /*
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * Provide a hash value for 'name'.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews */
97f26b88f62b10a9c26a91ebe8387d2e498c2d00Andreas Gustafsson REQUIRE(VALID_NAME(name));
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews if (name->labels == 0)
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews return (0);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews return (name_hash(name, case_sensitive));
97f26b88f62b10a9c26a91ebe8387d2e498c2d00Andreas Gustafsson}
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrewsunsigned int
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrewsdns_name_fullhash(dns_name_t *name, isc_boolean_t case_sensitive) {
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews /*
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * Provide a hash value for 'name'.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews */
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews REQUIRE(VALID_NAME(name));
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews if (name->labels == 0)
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews return (0);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews return (isc_hash_calc((const unsigned char *)name->ndata,
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews name->length, case_sensitive));
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews}
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrewsunsigned int
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrewsdns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews /*
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * This function was deprecated due to the breakage of the name space
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * convention. We only keep this internally to provide binary backward
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * compatibility.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews */
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews REQUIRE(VALID_NAME(name));
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews return (dns_name_fullhash(name, case_sensitive));
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews}
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrewsunsigned int
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrewsdns_name_hashbylabel(dns_name_t *name, isc_boolean_t case_sensitive) {
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews unsigned char *offsets;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews dns_offsets_t odata;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews dns_name_t tname;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews unsigned int h = 0;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews unsigned int i;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews /*
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * Provide a hash value for 'name'.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews */
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews REQUIRE(VALID_NAME(name));
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews if (name->labels == 0)
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews return (0);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews else if (name->labels == 1)
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews return (name_hash(name, case_sensitive));
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews SETUP_OFFSETS(name, offsets, odata);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews DNS_NAME_INIT(&tname, NULL);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews tname.labels = 1;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews h = 0;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews for (i = 0; i < name->labels; i++) {
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews tname.ndata = name->ndata + offsets[i];
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews if (i == name->labels - 1)
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews tname.length = name->length - offsets[i];
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews else
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews tname.length = offsets[i + 1] - offsets[i];
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews h += name_hash(&tname, case_sensitive);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews }
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews return (h);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews}
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrewsdns_namereln_t
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrewsdns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews int *orderp, unsigned int *nlabelsp)
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews{
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews unsigned int l1, l2, l, count1, count2, count, nlabels;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews int cdiff, ldiff, chdiff;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews unsigned char *label1, *label2;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews unsigned char *offsets1, *offsets2;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews dns_offsets_t odata1, odata2;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews dns_namereln_t namereln = dns_namereln_none;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews /*
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * Determine the relative ordering under the DNSSEC order relation of
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * 'name1' and 'name2', and also determine the hierarchical
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * relationship of the names.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews *
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * Note: It makes no sense for one of the names to be relative and the
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * other absolute. If both names are relative, then to be meaningfully
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * compared the caller must ensure that they are both relative to the
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * same domain.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews */
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews REQUIRE(VALID_NAME(name1));
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews REQUIRE(VALID_NAME(name2));
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews REQUIRE(orderp != NULL);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews REQUIRE(nlabelsp != NULL);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews /*
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * Either name1 is absolute and name2 is absolute, or neither is.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews */
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews SETUP_OFFSETS(name1, offsets1, odata1);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews SETUP_OFFSETS(name2, offsets2, odata2);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews nlabels = 0;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews l1 = name1->labels;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews l2 = name2->labels;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews ldiff = (int)l1 - (int)l2;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews if (ldiff < 0)
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews l = l1;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews else
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews l = l2;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews while (l > 0) {
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews l--;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews l1--;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews l2--;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews label1 = &name1->ndata[offsets1[l1]];
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews label2 = &name2->ndata[offsets2[l2]];
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews count1 = *label1++;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews count2 = *label2++;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews /*
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * We dropped bitstring labels, and we don't support any
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * other extended label types.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews */
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews INSIST(count1 <= 63 && count2 <= 63);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews cdiff = (int)count1 - (int)count2;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews if (cdiff < 0)
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews count = count1;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews else
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews count = count2;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews while (count > 0) {
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews chdiff = (int)maptolower[*label1] -
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews (int)maptolower[*label2];
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews if (chdiff != 0) {
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews *orderp = chdiff;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews goto done;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews }
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews count--;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews label1++;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews label2++;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews }
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews if (cdiff != 0) {
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews *orderp = cdiff;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews goto done;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews }
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews nlabels++;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews }
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews *orderp = ldiff;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews if (ldiff < 0)
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews namereln = dns_namereln_contains;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews else if (ldiff > 0)
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews namereln = dns_namereln_subdomain;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews else
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews namereln = dns_namereln_equal;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews done:
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews *nlabelsp = nlabels;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews if (nlabels > 0 && namereln == dns_namereln_none)
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews namereln = dns_namereln_commonancestor;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews return (namereln);
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews}
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrewsint
056141f2878d1046306ef0ba035263a00de57f98Mark Andrewsdns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
6ef15459b8fd3fc8b5672da4ad72c19a755dbe45Mark Andrews int order;
6ef15459b8fd3fc8b5672da4ad72c19a755dbe45Mark Andrews unsigned int nlabels;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews /*
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews * Determine the relative ordering under the DNSSEC order relation of
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews * 'name1' and 'name2'.
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews *
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * Note: It makes no sense for one of the names to be relative and the
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * other absolute. If both names are relative, then to be meaningfully
e21d199dca95aff5d50f133d6b064309e209af00Brian Wellington * compared the caller must ensure that they are both relative to the
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington * same domain.
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington */
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington (void)dns_name_fullcompare(name1, name2, &order, &nlabels);
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews return (order);
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews}
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrewsisc_boolean_t
056141f2878d1046306ef0ba035263a00de57f98Mark Andrewsdns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews unsigned int l, count;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews unsigned char c;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews unsigned char *label1, *label2;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews /*
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews * Are 'name1' and 'name2' equal?
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews *
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews * Note: It makes no sense for one of the names to be relative and the
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews * other absolute. If both names are relative, then to be meaningfully
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews * compared the caller must ensure that they are both relative to the
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews * same domain.
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews */
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews REQUIRE(VALID_NAME(name1));
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews REQUIRE(VALID_NAME(name2));
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews /*
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews * Either name1 is absolute and name2 is absolute, or neither is.
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews */
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews if (name1->length != name2->length)
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews return (ISC_FALSE);
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews l = name1->labels;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews if (l != name2->labels)
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews return (ISC_FALSE);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews label1 = name1->ndata;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews label2 = name2->ndata;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews while (l > 0) {
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews l--;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews count = *label1++;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews if (count != *label2++)
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews return (ISC_FALSE);
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews INSIST(count <= 63); /* no bitstring support */
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews while (count > 0) {
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews count--;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews c = maptolower[*label1++];
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews if (c != maptolower[*label2++])
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews return (ISC_FALSE);
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews }
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews }
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews return (ISC_TRUE);
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews}
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrewsisc_boolean_t
056141f2878d1046306ef0ba035263a00de57f98Mark Andrewsdns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews /*
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews * Are 'name1' and 'name2' equal?
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews *
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews * Note: It makes no sense for one of the names to be relative and the
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews * other absolute. If both names are relative, then to be meaningfully
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews * compared the caller must ensure that they are both relative to the
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews * same domain.
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews */
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews REQUIRE(VALID_NAME(name1));
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews REQUIRE(VALID_NAME(name2));
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews /*
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews * Either name1 is absolute and name2 is absolute, or neither is.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews */
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews if (name1->length != name2->length)
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews return (ISC_FALSE);
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews if (memcmp(name1->ndata, name2->ndata, name1->length) != 0)
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews return (ISC_FALSE);
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews return (ISC_TRUE);
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews}
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrewsint
056141f2878d1046306ef0ba035263a00de57f98Mark Andrewsdns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews unsigned int l1, l2, l, count1, count2, count;
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington unsigned char c1, c2;
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington unsigned char *label1, *label2;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews /*
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews * Compare two absolute names as rdata.
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews */
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews REQUIRE(VALID_NAME(name1));
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews REQUIRE(name1->labels > 0);
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews REQUIRE(VALID_NAME(name2));
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews REQUIRE(name2->labels > 0);
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington l1 = name1->labels;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews l2 = name2->labels;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews l = (l1 < l2) ? l1 : l2;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews label1 = name1->ndata;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews label2 = name2->ndata;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews while (l > 0) {
19d1b1667d073850d4366352aaf8319efc5debeeBrian Wellington l--;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews count1 = *label1++;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews count2 = *label2++;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
04c22ceaf2d3812eaab69d79958d0e0d62048cd2Mark Andrews /* no bitstring support */
668eb43f1f24c887b6972f6a1610b4b38b281080Brian Wellington INSIST(count1 <= 63 && count2 <= 63);
668eb43f1f24c887b6972f6a1610b4b38b281080Brian Wellington
668eb43f1f24c887b6972f6a1610b4b38b281080Brian Wellington if (count1 != count2)
04c22ceaf2d3812eaab69d79958d0e0d62048cd2Mark Andrews return ((count1 < count2) ? -1 : 1);
04c22ceaf2d3812eaab69d79958d0e0d62048cd2Mark Andrews count = count1;
04c22ceaf2d3812eaab69d79958d0e0d62048cd2Mark Andrews while (count > 0) {
04c22ceaf2d3812eaab69d79958d0e0d62048cd2Mark Andrews count--;
04c22ceaf2d3812eaab69d79958d0e0d62048cd2Mark Andrews c1 = maptolower[*label1++];
04c22ceaf2d3812eaab69d79958d0e0d62048cd2Mark Andrews c2 = maptolower[*label2++];
04c22ceaf2d3812eaab69d79958d0e0d62048cd2Mark Andrews if (c1 < c2)
04c22ceaf2d3812eaab69d79958d0e0d62048cd2Mark Andrews return (-1);
04c22ceaf2d3812eaab69d79958d0e0d62048cd2Mark Andrews else if (c1 > c2)
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews return (1);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews }
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews }
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews /*
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews * If one name had more labels than the other, their common
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * prefix must have been different because the shorter name
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * ended with the root label and the longer one can't have
94baac869a70b529a24ff23d8dc899faa5d4fdc4Brian Wellington * a root label in the middle of it. Therefore, if we get
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * to this point, the lengths must be equal.
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews INSIST(l1 == l2);
04c22ceaf2d3812eaab69d79958d0e0d62048cd2Mark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews return (0);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews}
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsisc_boolean_t
04c22ceaf2d3812eaab69d79958d0e0d62048cd2Mark Andrewsdns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
04c22ceaf2d3812eaab69d79958d0e0d62048cd2Mark Andrews int order;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews unsigned int nlabels;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews dns_namereln_t namereln;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington /*
8b61d2012063306528286680bd9f086fa868d86eMark Andrews * Is 'name1' a subdomain of 'name2'?
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews *
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * Note: It makes no sense for one of the names to be relative and the
e21d199dca95aff5d50f133d6b064309e209af00Brian Wellington * other absolute. If both names are relative, then to be meaningfully
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington * compared the caller must ensure that they are both relative to the
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington * same domain.
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington */
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (namereln == dns_namereln_subdomain ||
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews namereln == dns_namereln_equal)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews return (ISC_TRUE);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews return (ISC_FALSE);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews}
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsisc_boolean_t
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsdns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews int order;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews unsigned int nlabels, labels;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews dns_name_t tname;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews REQUIRE(VALID_NAME(name));
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews REQUIRE(name->labels > 0);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews REQUIRE(VALID_NAME(wname));
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews labels = wname->labels;
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff REQUIRE(labels > 0);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews REQUIRE(dns_name_iswildcard(wname));
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
c27767a7b946f4c6f08d33129691e2d6339e8350Brian Wellington DNS_NAME_INIT(&tname, NULL);
c27767a7b946f4c6f08d33129691e2d6339e8350Brian Wellington dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if (dns_name_fullcompare(name, &tname, &order, &nlabels) ==
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_namereln_subdomain)
dcc7ea97174501f0409c0c919b3ca04083e4e1b8Andreas Gustafsson return (ISC_TRUE);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews return (ISC_FALSE);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews}
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrewsunsigned int
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrewsdns_name_countlabels(const dns_name_t *name) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews /*
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * How many labels does 'name' have?
04c22ceaf2d3812eaab69d79958d0e0d62048cd2Mark Andrews */
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews REQUIRE(VALID_NAME(name));
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews ENSURE(name->labels <= 128);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews return (name->labels);
94baac869a70b529a24ff23d8dc899faa5d4fdc4Brian Wellington}
94baac869a70b529a24ff23d8dc899faa5d4fdc4Brian Wellington
559bb1016f1b00a3661cb2790dc837a977057b86Mark Andrewsvoid
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsdns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews unsigned char *offsets;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_offsets_t odata;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews /*
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Make 'label' refer to the 'n'th least significant label of 'name'.
46993e1d9d18410a5852b7d990338b70b158855cMichael Graff */
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews REQUIRE(VALID_NAME(name));
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews REQUIRE(name->labels > 0);
94baac869a70b529a24ff23d8dc899faa5d4fdc4Brian Wellington REQUIRE(n < name->labels);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews REQUIRE(label != NULL);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
559bb1016f1b00a3661cb2790dc837a977057b86Mark Andrews SETUP_OFFSETS(name, offsets, odata);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington label->base = &name->ndata[offsets[n]];
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington if (n == name->labels - 1)
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington label->length = name->length - offsets[n];
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington else
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington label->length = offsets[n + 1] - offsets[n];
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews}
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrewsvoid
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrewsdns_name_getlabelsequence(const dns_name_t *source,
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews unsigned int first, unsigned int n,
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews dns_name_t *target)
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews{
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews unsigned char *offsets;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_offsets_t odata;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews unsigned int firstoffset, endoffset;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews /*
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Make 'target' refer to the 'n' labels including and following
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews * 'first' in 'source'.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews */
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
04c22ceaf2d3812eaab69d79958d0e0d62048cd2Mark Andrews REQUIRE(VALID_NAME(source));
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews REQUIRE(VALID_NAME(target));
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews REQUIRE(first <= source->labels);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews REQUIRE(first + n <= source->labels);
7ed73313b1c129c7134d7d33beb82c85bd6d1df4Mark Andrews REQUIRE(BINDABLE(target));
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
04c22ceaf2d3812eaab69d79958d0e0d62048cd2Mark Andrews SETUP_OFFSETS(source, offsets, odata);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews if (first == source->labels)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews firstoffset = source->length;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews else
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington firstoffset = offsets[first];
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (first + n == source->labels)
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews endoffset = source->length;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews else
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews endoffset = offsets[first + n];
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews target->ndata = &source->ndata[firstoffset];
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews target->length = endoffset - firstoffset;
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (first + n == source->labels && n > 0 &&
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews target->attributes |= DNS_NAMEATTR_ABSOLUTE;
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington else
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
8b61d2012063306528286680bd9f086fa868d86eMark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews target->labels = n;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews /*
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews * If source and target are the same, and we're making target
559bb1016f1b00a3661cb2790dc837a977057b86Mark Andrews * a prefix of source, the offsets table is correct already
559bb1016f1b00a3661cb2790dc837a977057b86Mark Andrews * so we don't need to call set_offsets().
559bb1016f1b00a3661cb2790dc837a977057b86Mark Andrews */
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (target->offsets != NULL &&
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews (target != source || first != 0))
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews set_offsets(target, target->offsets, NULL);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews}
559bb1016f1b00a3661cb2790dc837a977057b86Mark Andrews
e43b9a20054cdda6946ab758e1c2005f2b25641aBrian Wellingtonvoid
e43b9a20054cdda6946ab758e1c2005f2b25641aBrian Wellingtondns_name_clone(dns_name_t *source, dns_name_t *target) {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews /*
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews * Make 'target' refer to the same name as 'source'.
8b61d2012063306528286680bd9f086fa868d86eMark Andrews */
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews REQUIRE(VALID_NAME(source));
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews REQUIRE(VALID_NAME(target));
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews REQUIRE(BINDABLE(target));
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews target->ndata = source->ndata;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews target->length = source->length;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews target->labels = source->labels;
e43b9a20054cdda6946ab758e1c2005f2b25641aBrian Wellington target->attributes = source->attributes &
e43b9a20054cdda6946ab758e1c2005f2b25641aBrian Wellington (unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC |
e43b9a20054cdda6946ab758e1c2005f2b25641aBrian Wellington DNS_NAMEATTR_DYNOFFSETS);
e43b9a20054cdda6946ab758e1c2005f2b25641aBrian Wellington if (target->offsets != NULL && source->labels > 0) {
e43b9a20054cdda6946ab758e1c2005f2b25641aBrian Wellington if (source->offsets != NULL)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews memcpy(target->offsets, source->offsets,
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews source->labels);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews else
e43b9a20054cdda6946ab758e1c2005f2b25641aBrian Wellington set_offsets(target, target->offsets, NULL);
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff }
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews}
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graffvoid
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrewsdns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews unsigned char *offsets;
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff dns_offsets_t odata;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews unsigned int len;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_region_t r2;
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews /*
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews * Make 'name' refer to region 'r'.
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff */
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews REQUIRE(VALID_NAME(name));
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff REQUIRE(r != NULL);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews REQUIRE(BINDABLE(name));
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
e43b9a20054cdda6946ab758e1c2005f2b25641aBrian Wellington INIT_OFFSETS(name, offsets, odata);
e43b9a20054cdda6946ab758e1c2005f2b25641aBrian Wellington
e43b9a20054cdda6946ab758e1c2005f2b25641aBrian Wellington if (name->buffer != NULL) {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_buffer_clear(name->buffer);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_buffer_availableregion(name->buffer, &r2);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews len = (r->length < r2.length) ? r->length : r2.length;
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence if (len > DNS_NAME_MAXWIRE)
559bb1016f1b00a3661cb2790dc837a977057b86Mark Andrews len = DNS_NAME_MAXWIRE;
559bb1016f1b00a3661cb2790dc837a977057b86Mark Andrews memcpy(r2.base, r->base, len);
559bb1016f1b00a3661cb2790dc837a977057b86Mark Andrews name->ndata = r2.base;
559bb1016f1b00a3661cb2790dc837a977057b86Mark Andrews name->length = len;
559bb1016f1b00a3661cb2790dc837a977057b86Mark Andrews } else {
559bb1016f1b00a3661cb2790dc837a977057b86Mark Andrews name->ndata = r->base;
559bb1016f1b00a3661cb2790dc837a977057b86Mark Andrews name->length = (r->length <= DNS_NAME_MAXWIRE) ?
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews r->length : DNS_NAME_MAXWIRE;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews }
559bb1016f1b00a3661cb2790dc837a977057b86Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (r->length > 0)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews set_offsets(name, offsets, name);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews else {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews name->labels = 0;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews }
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (name->buffer != NULL)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_buffer_add(name->buffer, name->length);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews}
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrewsvoid
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrewsdns_name_toregion(dns_name_t *name, isc_region_t *r) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews /*
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews * Make 'r' refer to 'name'.
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews */
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews REQUIRE(VALID_NAME(name));
e43b9a20054cdda6946ab758e1c2005f2b25641aBrian Wellington REQUIRE(r != NULL);
e43b9a20054cdda6946ab758e1c2005f2b25641aBrian Wellington
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews DNS_NAME_TOREGION(name, r);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews}
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafssonisc_result_t
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafssondns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson dns_name_t *origin, unsigned int options,
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson isc_buffer_t *target)
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson{
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson unsigned char *ndata, *label;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson char *tdata;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson char c;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson ft_state state, kind;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson unsigned int value, count, tbcount, bitlength, maxlength;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson unsigned int n1, n2, vlen, tlen, nrem, nused, digits, labels, tused;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson isc_boolean_t done;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson unsigned char *offsets;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson dns_offsets_t odata;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson isc_boolean_t downcase;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson /*
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson * Convert the textual representation of a DNS name at source
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson * into uncompressed wire form stored in target.
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson *
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson * Notes:
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson * Relative domain names will have 'origin' appended to them
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson * unless 'origin' is NULL, in which case relative domain names
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson * will remain relative.
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson */
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson REQUIRE(VALID_NAME(name));
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson REQUIRE(ISC_BUFFER_VALID(source));
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson (target == NULL && ISC_BUFFER_VALID(name->buffer)));
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews if (target == NULL && name->buffer != NULL) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews target = name->buffer;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_buffer_clear(target);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews }
8b61d2012063306528286680bd9f086fa868d86eMark Andrews
8b61d2012063306528286680bd9f086fa868d86eMark Andrews REQUIRE(BINDABLE(name));
390b2077fc751105e40174ceaa1ce34ef06e7dd4Mark Andrews
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews INIT_OFFSETS(name, offsets, odata);
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews offsets[0] = 0;
8f17525ebc8ab06446b613f56972dcf063548141Andreas Gustafsson
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson /*
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson * Initialize things to make the compiler happy; they're not required.
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson */
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews n1 = 0;
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews n2 = 0;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews vlen = 0;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews label = NULL;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews digits = 0;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews value = 0;
59abb512d344bfa09012cc11b7d814966f035da4Mark Andrews count = 0;
6850cdd4497424c9d42ade487edfde9fb9a47de9Brian Wellington tbcount = 0;
59abb512d344bfa09012cc11b7d814966f035da4Mark Andrews bitlength = 0;
84a47e20aedd16ba86feb25848732338ad618b16Brian Wellington maxlength = 0;
84a47e20aedd16ba86feb25848732338ad618b16Brian Wellington kind = ft_init;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews /*
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews * Make 'name' empty in case of failure.
8b61d2012063306528286680bd9f086fa868d86eMark Andrews */
8b61d2012063306528286680bd9f086fa868d86eMark Andrews MAKE_EMPTY(name);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington /*
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington * Set up the state machine.
6850cdd4497424c9d42ade487edfde9fb9a47de9Brian Wellington */
84a47e20aedd16ba86feb25848732338ad618b16Brian Wellington tdata = (char *)source->base + source->current;
84a47e20aedd16ba86feb25848732338ad618b16Brian Wellington tlen = isc_buffer_remaininglength(source);
84a47e20aedd16ba86feb25848732338ad618b16Brian Wellington tused = 0;
2483a850e8b82230331defb0e22c67f6b46cfb38Brian Wellington ndata = isc_buffer_used(target);
84a47e20aedd16ba86feb25848732338ad618b16Brian Wellington nrem = isc_buffer_availablelength(target);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews if (nrem > 255)
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews nrem = 255;
7ed73313b1c129c7134d7d33beb82c85bd6d1df4Mark Andrews nused = 0;
7ed73313b1c129c7134d7d33beb82c85bd6d1df4Mark Andrews labels = 0;
7ed73313b1c129c7134d7d33beb82c85bd6d1df4Mark Andrews done = ISC_FALSE;
7ed73313b1c129c7134d7d33beb82c85bd6d1df4Mark Andrews state = ft_init;
7ed73313b1c129c7134d7d33beb82c85bd6d1df4Mark Andrews
7ed73313b1c129c7134d7d33beb82c85bd6d1df4Mark Andrews while (nrem > 0 && tlen > 0 && !done) {
7ed73313b1c129c7134d7d33beb82c85bd6d1df4Mark Andrews c = *tdata++;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews tlen--;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews tused++;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence switch (state) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews case ft_init:
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews /*
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Is this the root name?
8b61d2012063306528286680bd9f086fa868d86eMark Andrews */
8b61d2012063306528286680bd9f086fa868d86eMark Andrews if (c == '.') {
8b61d2012063306528286680bd9f086fa868d86eMark Andrews if (tlen != 0)
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews return (DNS_R_EMPTYLABEL);
0ad8ee89c532951a55b7de25317eeca2c3b2ed63Andreas Gustafsson labels++;
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews *ndata++ = 0;
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews nrem--;
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews nused++;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson done = ISC_TRUE;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson break;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson }
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson if (c == '@' && tlen == 0) {
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson state = ft_at;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson break;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson }
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson /* FALLTHROUGH */
0ad8ee89c532951a55b7de25317eeca2c3b2ed63Andreas Gustafsson case ft_start:
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews label = ndata;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews ndata++;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews nrem--;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews nused++;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews count = 0;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (c == '\\') {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews state = ft_initialescape;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews break;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews }
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews kind = ft_ordinary;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews state = ft_ordinary;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (nrem == 0)
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff return (ISC_R_NOSPACE);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews /* FALLTHROUGH */
2c12768b4306035c208afc92bace4f3501f051f7Michael Sawyer case ft_ordinary:
390b2077fc751105e40174ceaa1ce34ef06e7dd4Mark Andrews if (c == '.') {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (count == 0)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews return (DNS_R_EMPTYLABEL);
8b61d2012063306528286680bd9f086fa868d86eMark Andrews *label = count;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews labels++;
f53848e17123569387b279578f0100dca5407da5Mark Andrews INSIST(labels <= 127);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews offsets[labels] = nused;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (tlen == 0) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews labels++;
0ad8ee89c532951a55b7de25317eeca2c3b2ed63Andreas Gustafsson *ndata++ = 0;
0ad8ee89c532951a55b7de25317eeca2c3b2ed63Andreas Gustafsson nrem--;
0ad8ee89c532951a55b7de25317eeca2c3b2ed63Andreas Gustafsson nused++;
0ad8ee89c532951a55b7de25317eeca2c3b2ed63Andreas Gustafsson done = ISC_TRUE;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson }
0ad8ee89c532951a55b7de25317eeca2c3b2ed63Andreas Gustafsson state = ft_start;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson } else if (c == '\\') {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews state = ft_escape;
559bb1016f1b00a3661cb2790dc837a977057b86Mark Andrews } else {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (count >= 63)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews return (DNS_R_LABELTOOLONG);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews count++;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence CONVERTTOASCII(c);
84d982f168ca104186490a93190c8e28d333026dMark Andrews if (downcase)
f53848e17123569387b279578f0100dca5407da5Mark Andrews c = maptolower[(int)c];
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson *ndata++ = c;
f53848e17123569387b279578f0100dca5407da5Mark Andrews nrem--;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews nused++;
f53848e17123569387b279578f0100dca5407da5Mark Andrews }
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews break;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews case ft_initialescape:
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (c == '[') {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews /*
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * This looks like a bitstring label, which
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * was deprecated. Intentionally drop it.
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff */
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews return (DNS_R_BADLABELTYPE);
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff }
390b2077fc751105e40174ceaa1ce34ef06e7dd4Mark Andrews kind = ft_ordinary;
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews state = ft_escape;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews /* FALLTHROUGH */
8b61d2012063306528286680bd9f086fa868d86eMark Andrews case ft_escape:
8b61d2012063306528286680bd9f086fa868d86eMark Andrews if (!isdigit(c & 0xff)) {
e02884167b7c969b56413f76c48c3802c4dca14dAndreas Gustafsson if (count >= 63)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews return (DNS_R_LABELTOOLONG);
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews count++;
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews CONVERTTOASCII(c);
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews if (downcase)
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews c = maptolower[(int)c];
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews *ndata++ = c;
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews nrem--;
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews nused++;
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews state = ft_ordinary;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson break;
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews }
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson digits = 0;
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews value = 0;
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews state = ft_escdecimal;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson /* FALLTHROUGH */
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews case ft_escdecimal:
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews if (!isdigit(c & 0xff))
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews return (DNS_R_BADESCAPE);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews value *= 10;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews value += digitvalue[(int)c];
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews digits++;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (digits == 3) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (value > 255)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews return (DNS_R_BADESCAPE);
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff if (count >= 63)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews return (DNS_R_LABELTOOLONG);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews count++;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (downcase)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews value = maptolower[value];
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff *ndata++ = value;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews nrem--;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews nused++;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence state = ft_ordinary;
8b61d2012063306528286680bd9f086fa868d86eMark Andrews }
8b61d2012063306528286680bd9f086fa868d86eMark Andrews break;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews default:
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews FATAL_ERROR(__FILE__, __LINE__,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews "Unexpected state %d", state);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews /* Does not return. */
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews }
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews }
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (!done) {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (nrem == 0)
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence return (ISC_R_NOSPACE);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence INSIST(tlen == 0);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence if (state != ft_ordinary && state != ft_at)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews return (ISC_R_UNEXPECTEDEND);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (state == ft_ordinary) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews INSIST(count != 0);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews *label = count;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews labels++;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews INSIST(labels <= 127);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews offsets[labels] = nused;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews }
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (origin != NULL) {
46993e1d9d18410a5852b7d990338b70b158855cMichael Graff if (nrem < origin->length)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews return (ISC_R_NOSPACE);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews label = origin->ndata;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews n1 = origin->length;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews nrem -= n1;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson while (n1 > 0) {
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews n2 = *label++;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews INSIST(n2 <= 63); /* no bitstring support */
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews *ndata++ = n2;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews n1 -= n2 + 1;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews nused += n2 + 1;
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff while (n2 > 0) {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence c = *label++;
390b2077fc751105e40174ceaa1ce34ef06e7dd4Mark Andrews if (downcase)
8b61d2012063306528286680bd9f086fa868d86eMark Andrews c = maptolower[(int)c];
8b61d2012063306528286680bd9f086fa868d86eMark Andrews *ndata++ = c;
4be19dcd14cea678511f1d1b269ab89273e987eeMark Andrews n2--;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews }
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews labels++;
0ad8ee89c532951a55b7de25317eeca2c3b2ed63Andreas Gustafsson if (n1 > 0) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews INSIST(labels <= 127);
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson offsets[labels] = nused;
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews }
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews }
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews name->attributes |= DNS_NAMEATTR_ABSOLUTE;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews }
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews } else
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews name->attributes |= DNS_NAMEATTR_ABSOLUTE;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
390b2077fc751105e40174ceaa1ce34ef06e7dd4Mark Andrews name->ndata = (unsigned char *)target->base + target->used;
8b61d2012063306528286680bd9f086fa868d86eMark Andrews name->labels = labels;
8b61d2012063306528286680bd9f086fa868d86eMark Andrews name->length = nused;
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews isc_buffer_forward(source, tused);
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews isc_buffer_add(target, name->length);
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff return (ISC_R_SUCCESS);
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff}
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#ifdef ISC_PLATFORM_USETHREADS
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsstatic void
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewstotext_filter_proc_key_init(void) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews RUNTIME_CHECK(isc_key_create(&totext_filter_proc_key, free) == 0);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews}
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews#endif
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews
390b2077fc751105e40174ceaa1ce34ef06e7dd4Mark Andrewsisc_result_t
8b61d2012063306528286680bd9f086fa868d86eMark Andrewsdns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
8b61d2012063306528286680bd9f086fa868d86eMark Andrews isc_buffer_t *target)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews{
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews unsigned char *ndata;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews char *tdata;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews unsigned int nlen, tlen;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews unsigned char c;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews unsigned int trem, count;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews unsigned int labels;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_boolean_t saw_root = ISC_FALSE;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews unsigned int oused = target->used;
46993e1d9d18410a5852b7d990338b70b158855cMichael Graff#ifdef ISC_PLATFORM_USETHREADS
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_name_totextfilter_t *mem;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_name_totextfilter_t totext_filter_proc = NULL;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_result_t result;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#endif
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington /*
c27767a7b946f4c6f08d33129691e2d6339e8350Brian Wellington * This function assumes the name is in proper uncompressed
c27767a7b946f4c6f08d33129691e2d6339e8350Brian Wellington * wire format.
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington */
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington REQUIRE(VALID_NAME(name));
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews REQUIRE(ISC_BUFFER_VALID(target));
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews#ifdef ISC_PLATFORM_USETHREADS
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews result = isc_once_do(&once, totext_filter_proc_key_init);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (result != ISC_R_SUCCESS)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews return (result);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#endif
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews ndata = name->ndata;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews nlen = name->length;
390b2077fc751105e40174ceaa1ce34ef06e7dd4Mark Andrews labels = name->labels;
8b61d2012063306528286680bd9f086fa868d86eMark Andrews tdata = isc_buffer_used(target);
8b61d2012063306528286680bd9f086fa868d86eMark Andrews tlen = isc_buffer_availablelength(target);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews trem = tlen;
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews if (labels == 0 && nlen == 0) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews /*
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Special handling for an empty name.
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson */
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson if (trem == 0)
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson return (ISC_R_NOSPACE);
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson /*
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson * The names of these booleans are misleading in this case.
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson * This empty name is not necessarily from the root node of
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson * the DNS root zone, nor is a final dot going to be included.
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson * They need to be set this way, though, to keep the "@"
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * from being trounced.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews */
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews saw_root = ISC_TRUE;
46993e1d9d18410a5852b7d990338b70b158855cMichael Graff omit_final_dot = ISC_FALSE;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews *tdata++ = '@';
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews trem--;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews /*
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews * Skip the while() loop.
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews */
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews nlen = 0;
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews } else if (nlen == 1 && labels == 1 && *ndata == '\0') {
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews /*
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Special handling for the root label.
8b61d2012063306528286680bd9f086fa868d86eMark Andrews */
8b61d2012063306528286680bd9f086fa868d86eMark Andrews if (trem == 0)
8b61d2012063306528286680bd9f086fa868d86eMark Andrews return (ISC_R_NOSPACE);
8b61d2012063306528286680bd9f086fa868d86eMark Andrews
8b61d2012063306528286680bd9f086fa868d86eMark Andrews saw_root = ISC_TRUE;
8b61d2012063306528286680bd9f086fa868d86eMark Andrews omit_final_dot = ISC_FALSE;
8b61d2012063306528286680bd9f086fa868d86eMark Andrews *tdata++ = '.';
8b61d2012063306528286680bd9f086fa868d86eMark Andrews trem--;
8b61d2012063306528286680bd9f086fa868d86eMark Andrews
8b61d2012063306528286680bd9f086fa868d86eMark Andrews /*
* Skip the while() loop.
*/
nlen = 0;
}
while (labels > 0 && nlen > 0 && trem > 0) {
labels--;
count = *ndata++;
nlen--;
if (count == 0) {
saw_root = ISC_TRUE;
break;
}
if (count < 64) {
INSIST(nlen >= count);
while (count > 0) {
c = *ndata;
switch (c) {
case 0x22: /* '"' */
case 0x28: /* '(' */
case 0x29: /* ')' */
case 0x2E: /* '.' */
case 0x3B: /* ';' */
case 0x5C: /* '\\' */
/* Special modifiers in zone files. */
case 0x40: /* '@' */
case 0x24: /* '$' */
if (trem < 2)
return (ISC_R_NOSPACE);
*tdata++ = '\\';
CONVERTFROMASCII(c);
*tdata++ = c;
ndata++;
trem -= 2;
nlen--;
break;
default:
if (c > 0x20 && c < 0x7f) {
if (trem == 0)
return (ISC_R_NOSPACE);
CONVERTFROMASCII(c);
*tdata++ = c;
ndata++;
trem--;
nlen--;
} else {
if (trem < 4)
return (ISC_R_NOSPACE);
*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_key_getspecific(totext_filter_proc_key);
if (mem)
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 hops, 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;
/*
* Copy the possibly-compressed name at source into target,
* decompressing it.
*/
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;
hops = 0;
done = ISC_FALSE;
ndata = isc_buffer_used(target);
nused = 0;
/*
* Find the maximum number of uncompressed target name
* bytes we are willing to generate. This is the smaller
* of the available target buffer length and the
* maximum legal domain name length (255).
*/
nmax = isc_buffer_availablelength(target);
if (nmax > DNS_NAME_MAXWIRE)
nmax = DNS_NAME_MAXWIRE;
cdata = isc_buffer_current(source);
cused = 0;
current = source->current;
biggest_pointer = current;
/*
* Note: The following code is not optimized for speed, but
* rather for correctness. Speed will be addressed in the future.
*/
while (current < source->active && !done) {
c = *cdata++;
current++;
if (hops == 0)
cused++;
switch (state) {
case fw_start:
if (c < 64) {
offsets[labels] = nused;
labels++;
if (nused + c + 1 > nmax)
goto full;
nused += c + 1;
*ndata++ = c;
if (c == 0)
done = ISC_TRUE;
n = c;
state = fw_ordinary;
} else if (c >= 128 && c < 192) {
/*
* 14 bit local compression pointer.
* Local compression is no longer an
* IETF draft.
*/
return (DNS_R_BADLABELTYPE);
} else if (c >= 192) {
/*
* Ordinary 14-bit pointer.
*/
if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
0)
return (DNS_R_DISALLOWED);
new_current = c & 0x3F;
n = 1;
state = fw_newcurrent;
} else
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;
hops++;
if (hops > DNS_POINTER_MAXHOPS)
return (DNS_R_TOOMANYHOPS);
state = fw_start;
break;
default:
FATAL_ERROR(__FILE__, __LINE__,
"Unknown state %d", state);
/* Does not return. */
}
}
if (!done)
return (ISC_R_UNEXPECTEDEND);
name->ndata = (unsigned char *)target->base + target->used;
name->labels = labels;
name->length = nused;
name->attributes |= DNS_NAMEATTR_ABSOLUTE;
isc_buffer_forward(source, cused);
isc_buffer_add(target, name->length);
return (ISC_R_SUCCESS);
full:
if (nmax == DNS_NAME_MAXWIRE)
/*
* The name did not fit even though we had a buffer
* big enough to fit a maximum-length name.
*/
return (DNS_R_NAMETOOLONG);
else
/*
* The name might fit if only the caller could give us a
* big enough buffer.
*/
return (ISC_R_NOSPACE);
}
isc_result_t
dns_name_towire(dns_name_t *name, dns_compress_t *cctx, isc_buffer_t *target) {
unsigned int methods;
isc_uint16_t offset;
dns_name_t gp; /* Global compression prefix */
isc_boolean_t gf; /* Global compression target found */
isc_uint16_t go; /* Global compression offset */
dns_offsets_t clo;
dns_name_t clname;
/*
* Convert 'name' into wire format, compressing it as specified by the
* compression context 'cctx', and storing the result in 'target'.
*/
REQUIRE(VALID_NAME(name));
REQUIRE(cctx != NULL);
REQUIRE(ISC_BUFFER_VALID(target));
/*
* If 'name' doesn't have an offsets table, make a clone which
* has one.
*/
if (name->offsets == NULL) {
DNS_NAME_INIT(&clname, clo);
dns_name_clone(name, &clname);
name = &clname;
}
DNS_NAME_INIT(&gp, NULL);
offset = target->used; /*XXX*/
methods = dns_compress_getmethods(cctx);
if ((methods & DNS_COMPRESS_GLOBAL14) != 0)
gf = dns_compress_findglobal(cctx, name, &gp, &go);
else
gf = ISC_FALSE;
/*
* If the offset is too high for 14 bit global compression, we're
* out of luck.
*/
if (gf && go >= 0x4000)
gf = ISC_FALSE;
/*
* Will the compression pointer reduce the message size?
*/
if (gf && (gp.length + 2) >= name->length)
gf = ISC_FALSE;
if (gf) {
if (target->length - target->used < gp.length)
return (ISC_R_NOSPACE);
(void)memcpy((unsigned char *)target->base + target->used,
gp.ndata, (size_t)gp.length);
isc_buffer_add(target, gp.length);
go |= 0xc000;
if (target->length - target->used < 2)
return (ISC_R_NOSPACE);
isc_buffer_putuint16(target, go);
if (gp.length != 0)
dns_compress_add(cctx, name, &gp, offset);
} else {
if (target->length - target->used < name->length)
return (ISC_R_NOSPACE);
(void)memcpy((unsigned char *)target->base + target->used,
name->ndata, (size_t)name->length);
isc_buffer_add(target, name->length);
dns_compress_add(cctx, name, name, offset);
}
return (ISC_R_SUCCESS);
}
isc_result_t
dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
isc_buffer_t *target)
{
unsigned char *ndata, *offsets;
unsigned int nrem, labels, prefix_length, length;
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;
if (suffix == name && suffix->buffer == target)
memmove(ndata + prefix_length, suffix->ndata,
suffix->length);
else
memcpy(ndata + prefix_length, suffix->ndata,
suffix->length);
}
/*
* If 'prefix' and 'name' are the same object, and the object has
* a dedicated buffer, and we're using it, then we don't have to
* copy anything.
*/
if (copy_prefix && (prefix != name || prefix->buffer != target))
memcpy(ndata, prefix->ndata, prefix_length);
name->ndata = ndata;
name->labels = labels;
name->length = length;
if (absolute)
name->attributes = DNS_NAMEATTR_ABSOLUTE;
else
name->attributes = 0;
if (name->labels > 0 && name->offsets != NULL) {
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(dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) {
/*
* Make 'target' a dynamically allocated copy of 'source'.
*/
REQUIRE(VALID_NAME(source));
REQUIRE(source->length > 0);
REQUIRE(VALID_NAME(target));
REQUIRE(BINDABLE(target));
/*
* Make 'target' empty in case of failure.
*/
MAKE_EMPTY(target);
target->ndata = isc_mem_get(mctx, source->length);
if (target->ndata == NULL)
return (ISC_R_NOMEMORY);
memcpy(target->ndata, source->ndata, source->length);
target->length = source->length;
target->labels = source->labels;
target->attributes = DNS_NAMEATTR_DYNAMIC;
if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
target->attributes |= DNS_NAMEATTR_ABSOLUTE;
if (target->offsets != NULL) {
if (source->offsets != NULL)
memcpy(target->offsets, source->offsets,
source->labels);
else
set_offsets(target, target->offsets, NULL);
}
return (ISC_R_SUCCESS);
}
isc_result_t
dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
dns_name_t *target)
{
/*
* Make 'target' a read-only dynamically allocated copy of 'source'.
* 'target' will also have a dynamically allocated offsets table.
*/
REQUIRE(VALID_NAME(source));
REQUIRE(source->length > 0);
REQUIRE(VALID_NAME(target));
REQUIRE(BINDABLE(target));
REQUIRE(target->offsets == NULL);
/*
* Make 'target' empty in case of failure.
*/
MAKE_EMPTY(target);
target->ndata = isc_mem_get(mctx, source->length + source->labels);
if (target->ndata == NULL)
return (ISC_R_NOMEMORY);
memcpy(target->ndata, source->ndata, source->length);
target->length = source->length;
target->labels = source->labels;
target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
DNS_NAMEATTR_READONLY;
if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
target->attributes |= DNS_NAMEATTR_ABSOLUTE;
target->offsets = target->ndata + source->length;
if (source->offsets != NULL)
memcpy(target->offsets, source->offsets, source->labels);
else
set_offsets(target, target->offsets, NULL);
return (ISC_R_SUCCESS);
}
void
dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
size_t size;
/*
* Free 'name'.
*/
REQUIRE(VALID_NAME(name));
REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
size = name->length;
if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0)
size += name->labels;
isc_mem_put(mctx, name->ndata, size);
dns_name_invalidate(name);
}
isc_result_t
dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) {
dns_name_t downname;
unsigned char data[256];
isc_buffer_t buffer;
isc_result_t result;
isc_region_t r;
/*
* Send 'name' in DNSSEC canonical form to 'digest'.
*/
REQUIRE(VALID_NAME(name));
REQUIRE(digest != NULL);
DNS_NAME_INIT(&downname, NULL);
isc_buffer_init(&buffer, data, sizeof(data));
result = dns_name_downcase(name, &downname, &buffer);
if (result != ISC_R_SUCCESS)
return (result);
isc_buffer_usedregion(&buffer, &r);
return ((digest)(arg, &r));
}
isc_boolean_t
dns_name_dynamic(dns_name_t *name) {
REQUIRE(VALID_NAME(name));
/*
* Returns whether there is dynamic memory associated with this name.
*/
return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
ISC_TRUE : ISC_FALSE);
}
isc_result_t
dns_name_print(dns_name_t *name, FILE *stream) {
isc_result_t result;
isc_buffer_t b;
isc_region_t r;
char t[1024];
/*
* Print 'name' on 'stream'.
*/
REQUIRE(VALID_NAME(name));
isc_buffer_init(&b, t, sizeof(t));
result = dns_name_totext(name, ISC_FALSE, &b);
if (result != ISC_R_SUCCESS)
return (result);
isc_buffer_usedregion(&b, &r);
fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
return (ISC_R_SUCCESS);
}
isc_result_t
dns_name_settotextfilter(dns_name_totextfilter_t proc) {
#ifdef ISC_PLATFORM_USETHREADS
isc_result_t result;
dns_name_totextfilter_t *mem;
result = isc_once_do(&once, 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_key_getspecific(totext_filter_proc_key);
if (mem != NULL && proc != NULL) {
*mem = proc;
return (ISC_R_SUCCESS);
}
if (proc == NULL) {
free(mem);
if (isc_key_setspecific(totext_filter_proc_key, NULL) != 0)
result = ISC_R_UNEXPECTED;
return (result);
}
/*
* We use malloc because Windows can't automatically free the
* memory and we don't want to trigger a INSIST at exit.
*/
mem = malloc(sizeof(dns_name_totextfilter_t));
if (mem == NULL)
return (ISC_R_NOMEMORY);
*mem = proc;
if (isc_key_setspecific(totext_filter_proc_key, mem) != 0)
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>");
}
isc_result_t
dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
unsigned char *ndata;
/*
* Make dest a copy of source.
*/
REQUIRE(VALID_NAME(source));
REQUIRE(VALID_NAME(dest));
REQUIRE(target != NULL || dest->buffer != NULL);
if (target == NULL) {
target = dest->buffer;
isc_buffer_clear(dest->buffer);
}
REQUIRE(BINDABLE(dest));
/*
* Set up.
*/
if (target->length - target->used < source->length)
return (ISC_R_NOSPACE);
ndata = (unsigned char *)target->base + target->used;
dest->ndata = target->base;
memcpy(ndata, source->ndata, source->length);
dest->ndata = ndata;
dest->labels = source->labels;
dest->length = source->length;
if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
dest->attributes = DNS_NAMEATTR_ABSOLUTE;
else
dest->attributes = 0;
if (dest->labels > 0 && dest->offsets != NULL) {
if (source->offsets != NULL)
memcpy(dest->offsets, source->offsets, source->labels);
else
set_offsets(dest, dest->offsets, NULL);
}
isc_buffer_add(target, dest->length);
return (ISC_R_SUCCESS);
}