1998-12-12 20:48:14 +00:00
|
|
|
/*
|
2018-02-23 09:53:12 +01:00
|
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
2000-08-01 01:33:37 +00:00
|
|
|
*
|
2021-06-03 08:37:05 +02:00
|
|
|
* SPDX-License-Identifier: MPL-2.0
|
|
|
|
*
|
2016-06-27 14:56:38 +10:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
2020-09-14 16:20:40 -07:00
|
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
2018-02-23 09:53:12 +01:00
|
|
|
*
|
|
|
|
* See the COPYRIGHT file distributed with this work for additional
|
|
|
|
* information regarding copyright ownership.
|
1998-12-12 20:48:14 +00:00
|
|
|
*/
|
1998-12-12 19:25:20 +00:00
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*! \file */
|
2000-06-22 22:00:42 +00:00
|
|
|
|
1998-12-04 02:27:01 +00:00
|
|
|
#include <ctype.h>
|
2018-03-28 14:19:37 +02:00
|
|
|
#include <inttypes.h>
|
2018-04-17 08:29:14 -07:00
|
|
|
#include <stdbool.h>
|
2005-09-10 01:02:08 +00:00
|
|
|
#include <stdlib.h>
|
1998-12-04 02:27:01 +00:00
|
|
|
|
2000-04-04 20:10:29 +00:00
|
|
|
#include <isc/buffer.h>
|
2003-07-25 02:22:26 +00:00
|
|
|
#include <isc/hash.h>
|
2000-05-08 14:38:29 +00:00
|
|
|
#include <isc/mem.h>
|
2005-09-09 06:17:03 +00:00
|
|
|
#include <isc/once.h>
|
2000-04-12 19:07:12 +00:00
|
|
|
#include <isc/print.h>
|
2015-12-09 19:07:20 +05:30
|
|
|
#include <isc/random.h>
|
2021-10-04 17:14:53 +02:00
|
|
|
#include <isc/result.h>
|
2000-05-08 14:38:29 +00:00
|
|
|
#include <isc/string.h>
|
2005-09-09 06:17:03 +00:00
|
|
|
#include <isc/thread.h>
|
2000-04-28 01:12:23 +00:00
|
|
|
#include <isc/util.h>
|
1998-12-04 02:27:01 +00:00
|
|
|
|
1999-01-06 20:04:41 +00:00
|
|
|
#include <dns/compress.h>
|
2009-03-11 07:02:34 +00:00
|
|
|
#include <dns/fixedname.h>
|
2001-01-03 00:05:15 +00:00
|
|
|
#include <dns/name.h>
|
1998-12-04 02:27:01 +00:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
#define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
|
1998-12-04 02:27:01 +00:00
|
|
|
|
|
|
|
typedef enum {
|
1999-01-06 05:41:20 +00:00
|
|
|
ft_init = 0,
|
|
|
|
ft_start,
|
|
|
|
ft_ordinary,
|
|
|
|
ft_initialescape,
|
|
|
|
ft_escape,
|
|
|
|
ft_escdecimal,
|
1999-01-27 23:39:40 +00:00
|
|
|
ft_at
|
1999-01-06 05:41:20 +00:00
|
|
|
} ft_state;
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
typedef enum { fw_start = 0, fw_ordinary, fw_newcurrent } fw_state;
|
1998-12-04 02:27:01 +00:00
|
|
|
|
|
|
|
static char digitvalue[256] = {
|
2020-02-12 13:59:18 +01:00
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
|
1998-12-04 02:27:01 +00:00
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
|
2020-02-12 13:59:18 +01:00
|
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
|
1998-12-04 02:27:01 +00:00
|
|
|
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
|
|
|
|
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
|
|
|
|
};
|
|
|
|
|
|
|
|
static unsigned char maptolower[] = {
|
2020-02-12 13:59:18 +01:00
|
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
|
|
|
|
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
|
|
|
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
|
|
|
|
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
|
|
|
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
|
|
|
|
0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
|
|
|
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73,
|
|
|
|
0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
|
|
|
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
|
|
|
|
0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
|
|
|
|
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
|
|
|
|
0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
|
|
|
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b,
|
|
|
|
0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
|
|
|
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
|
|
|
|
0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
|
|
|
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb,
|
|
|
|
0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
|
|
|
|
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3,
|
|
|
|
0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
|
|
|
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
|
|
|
|
0xfc, 0xfd, 0xfe, 0xff
|
1998-12-04 02:27:01 +00:00
|
|
|
};
|
|
|
|
|
1998-12-05 01:42:30 +00:00
|
|
|
#define CONVERTTOASCII(c)
|
|
|
|
#define CONVERTFROMASCII(c)
|
|
|
|
|
2016-08-29 18:52:49 +05:30
|
|
|
#define INIT_OFFSETS(name, var, default_offsets) \
|
2020-02-12 13:59:18 +01:00
|
|
|
if ((name)->offsets != NULL) \
|
|
|
|
var = (name)->offsets; \
|
|
|
|
else \
|
2016-08-29 18:52:49 +05:30
|
|
|
var = (default_offsets);
|
1999-01-09 00:33:15 +00:00
|
|
|
|
2016-08-29 18:52:49 +05:30
|
|
|
#define SETUP_OFFSETS(name, var, default_offsets) \
|
2020-02-16 17:34:24 +01:00
|
|
|
if ((name)->offsets != NULL) { \
|
2020-02-12 13:59:18 +01:00
|
|
|
var = (name)->offsets; \
|
2020-02-16 17:34:24 +01:00
|
|
|
} else { \
|
2020-02-12 13:59:18 +01:00
|
|
|
var = (default_offsets); \
|
|
|
|
set_offsets(name, var, NULL); \
|
1999-01-09 00:33:15 +00:00
|
|
|
}
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*%
|
1999-08-12 20:26:45 +00:00
|
|
|
* Note: If additional attributes are added that should not be set for
|
|
|
|
* empty names, MAKE_EMPTY() must be changed so it clears them.
|
|
|
|
*/
|
2020-02-12 13:59:18 +01:00
|
|
|
#define MAKE_EMPTY(name) \
|
|
|
|
do { \
|
|
|
|
name->ndata = NULL; \
|
|
|
|
name->length = 0; \
|
|
|
|
name->labels = 0; \
|
|
|
|
name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
|
|
|
|
} while (0);
|
1999-08-12 20:26:45 +00:00
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*%
|
1999-08-19 23:26:16 +00:00
|
|
|
* A name is "bindable" if it can be set to point to a new value, i.e.
|
|
|
|
* name->ndata and name->length may be changed.
|
|
|
|
*/
|
2020-02-12 13:59:18 +01:00
|
|
|
#define BINDABLE(name) \
|
|
|
|
((name->attributes & \
|
|
|
|
(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC)) == 0)
|
1999-08-19 23:26:16 +00:00
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*%
|
2001-01-11 21:07:21 +00:00
|
|
|
* Note that the name data must be a char array, not a string
|
|
|
|
* literal, to avoid compiler warnings about discarding
|
|
|
|
* the const attribute of a string.
|
2000-06-01 18:26:56 +00:00
|
|
|
*/
|
2017-11-13 16:58:12 +11:00
|
|
|
static unsigned char root_ndata[] = { "" };
|
2001-01-11 21:07:21 +00:00
|
|
|
static unsigned char root_offsets[] = { 0 };
|
|
|
|
|
2017-11-13 16:58:12 +11:00
|
|
|
static dns_name_t root = DNS_NAME_INITABSOLUTE(root_ndata, root_offsets);
|
2021-06-10 08:06:48 +02:00
|
|
|
const dns_name_t *dns_rootname = &root;
|
2001-01-11 21:07:21 +00:00
|
|
|
|
2017-11-13 16:58:12 +11:00
|
|
|
static unsigned char wild_ndata[] = { "\001*" };
|
2001-01-11 21:07:21 +00:00
|
|
|
static unsigned char wild_offsets[] = { 0 };
|
|
|
|
|
2020-02-13 14:44:37 -08:00
|
|
|
static dns_name_t const wild = DNS_NAME_INITNONABSOLUTE(wild_ndata,
|
|
|
|
wild_offsets);
|
1999-08-12 07:48:16 +00:00
|
|
|
|
2021-06-10 08:06:48 +02:00
|
|
|
const dns_name_t *dns_wildcardname = &wild;
|
1999-08-12 07:48:16 +00:00
|
|
|
|
2005-09-09 06:17:03 +00:00
|
|
|
/*
|
|
|
|
* dns_name_t to text post-conversion procedure.
|
|
|
|
*/
|
2018-08-07 16:46:53 +02:00
|
|
|
static thread_local dns_name_totextfilter_t *totext_filter_proc = NULL;
|
2005-09-09 06:17:03 +00:00
|
|
|
|
2020-02-14 08:14:03 +01:00
|
|
|
static void
|
|
|
|
set_offsets(const dns_name_t *name, unsigned char *offsets,
|
|
|
|
dns_name_t *set_name);
|
2000-06-01 18:26:56 +00:00
|
|
|
|
1998-12-04 02:27:01 +00:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_init(dns_name_t *name, unsigned char *offsets) {
|
1998-12-04 02:27:01 +00:00
|
|
|
/*
|
1999-08-12 20:26:45 +00:00
|
|
|
* Initialize 'name'.
|
1998-12-04 02:27:01 +00:00
|
|
|
*/
|
2001-01-03 00:05:15 +00:00
|
|
|
DNS_NAME_INIT(name, offsets);
|
1999-01-06 05:41:20 +00:00
|
|
|
}
|
|
|
|
|
2000-07-14 19:12:54 +00:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_reset(dns_name_t *name) {
|
2000-07-14 19:12:54 +00:00
|
|
|
REQUIRE(VALID_NAME(name));
|
|
|
|
REQUIRE(BINDABLE(name));
|
|
|
|
|
2001-01-03 00:05:15 +00:00
|
|
|
DNS_NAME_RESET(name);
|
2000-07-14 19:12:54 +00:00
|
|
|
}
|
|
|
|
|
1999-01-06 05:41:20 +00:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_invalidate(dns_name_t *name) {
|
1999-01-06 05:41:20 +00:00
|
|
|
/*
|
|
|
|
* Make 'name' invalid.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(name));
|
|
|
|
|
|
|
|
name->magic = 0;
|
1998-12-04 02:27:01 +00:00
|
|
|
name->ndata = NULL;
|
|
|
|
name->length = 0;
|
|
|
|
name->labels = 0;
|
1999-02-06 01:26:00 +00:00
|
|
|
name->attributes = 0;
|
1999-01-09 00:33:15 +00:00
|
|
|
name->offsets = NULL;
|
1999-03-08 18:55:28 +00:00
|
|
|
name->buffer = NULL;
|
1999-01-09 00:33:15 +00:00
|
|
|
ISC_LINK_INIT(name, link);
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_isvalid(const dns_name_t *name) {
|
2013-05-07 13:54:58 -07:00
|
|
|
unsigned char *ndata, *offsets;
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int offset, count, length, nlabels;
|
2013-05-07 13:54:58 -07:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (!VALID_NAME(name)) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2013-05-07 13:54:58 -07:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (name->length > 255U || name->labels > 127U) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2013-05-07 13:54:58 -07:00
|
|
|
|
|
|
|
ndata = name->ndata;
|
|
|
|
length = name->length;
|
|
|
|
offsets = name->offsets;
|
|
|
|
offset = 0;
|
|
|
|
nlabels = 0;
|
|
|
|
|
|
|
|
while (offset != length) {
|
|
|
|
count = *ndata;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (count > 63U) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (offsets != NULL && offsets[nlabels] != offset) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2013-05-07 13:54:58 -07:00
|
|
|
|
|
|
|
nlabels++;
|
|
|
|
offset += count + 1;
|
|
|
|
ndata += count + 1;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (offset > length) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2013-05-07 13:54:58 -07:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (count == 0) {
|
2013-05-07 13:54:58 -07:00
|
|
|
break;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2013-05-07 13:54:58 -07:00
|
|
|
}
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (nlabels != name->labels || offset != name->length) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2013-05-07 13:54:58 -07:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2013-05-07 13:54:58 -07:00
|
|
|
}
|
|
|
|
|
1999-03-08 18:55:28 +00:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) {
|
1999-03-08 18:55:28 +00:00
|
|
|
/*
|
2000-06-06 17:47:54 +00:00
|
|
|
* Dedicate a buffer for use with 'name'.
|
1999-03-08 18:55:28 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(name));
|
2020-02-12 13:59:18 +01:00
|
|
|
REQUIRE((buffer != NULL && name->buffer == NULL) || (buffer == NULL));
|
1999-03-08 18:55:28 +00:00
|
|
|
|
|
|
|
name->buffer = buffer;
|
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_hasbuffer(const dns_name_t *name) {
|
1999-03-08 18:55:28 +00:00
|
|
|
/*
|
|
|
|
* Does 'name' have a dedicated buffer?
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(name));
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (name->buffer != NULL) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-03-08 18:55:28 +00:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
1999-03-08 18:55:28 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_isabsolute(const dns_name_t *name) {
|
1998-12-04 02:27:01 +00:00
|
|
|
/*
|
|
|
|
* Does 'name' end in the root label?
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(name));
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
|
|
|
|
2004-02-27 20:41:51 +00:00
|
|
|
#define hyphenchar(c) ((c) == 0x2d)
|
2020-02-13 14:44:37 -08:00
|
|
|
#define asterchar(c) ((c) == 0x2a)
|
2020-02-12 13:59:18 +01:00
|
|
|
#define alphachar(c) \
|
|
|
|
(((c) >= 0x41 && (c) <= 0x5a) || ((c) >= 0x61 && (c) <= 0x7a))
|
2020-02-13 14:44:37 -08:00
|
|
|
#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
|
2004-02-27 20:41:51 +00:00
|
|
|
#define borderchar(c) (alphachar(c) || digitchar(c))
|
|
|
|
#define middlechar(c) (borderchar(c) || hyphenchar(c))
|
|
|
|
#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_ismailbox(const dns_name_t *name) {
|
2004-02-27 20:41:51 +00:00
|
|
|
unsigned char *ndata, ch;
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int n;
|
|
|
|
bool first;
|
2004-02-27 20:41:51 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(name));
|
|
|
|
REQUIRE(name->labels > 0);
|
|
|
|
REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
|
|
|
|
|
2008-04-01 23:47:10 +00:00
|
|
|
/*
|
2004-02-27 20:41:51 +00:00
|
|
|
* Root label.
|
|
|
|
*/
|
2020-02-13 21:48:23 +01:00
|
|
|
if (name->length == 1) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-02-27 20:41:51 +00:00
|
|
|
|
|
|
|
ndata = name->ndata;
|
|
|
|
n = *ndata++;
|
2004-04-19 21:47:43 +00:00
|
|
|
INSIST(n <= 63);
|
2004-02-27 20:41:51 +00:00
|
|
|
while (n--) {
|
|
|
|
ch = *ndata++;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (!domainchar(ch)) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-02-27 20:41:51 +00:00
|
|
|
}
|
2008-04-01 23:47:10 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (ndata == name->ndata + name->length) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-02-27 20:41:51 +00:00
|
|
|
|
|
|
|
/*
|
2021-05-04 17:21:52 +02:00
|
|
|
* RFC952/RFC1123 hostname.
|
2004-02-27 20:41:51 +00:00
|
|
|
*/
|
|
|
|
while (ndata < (name->ndata + name->length)) {
|
|
|
|
n = *ndata++;
|
2004-04-19 21:47:43 +00:00
|
|
|
INSIST(n <= 63);
|
2018-04-17 08:29:14 -07:00
|
|
|
first = true;
|
2004-02-27 20:41:51 +00:00
|
|
|
while (n--) {
|
|
|
|
ch = *ndata++;
|
|
|
|
if (first || n == 0) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (!borderchar(ch)) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-02-27 20:41:51 +00:00
|
|
|
} else {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (!middlechar(ch)) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-02-27 20:41:51 +00:00
|
|
|
}
|
2018-04-17 08:29:14 -07:00
|
|
|
first = false;
|
2004-02-27 20:41:51 +00:00
|
|
|
}
|
|
|
|
}
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2004-02-27 20:41:51 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_ishostname(const dns_name_t *name, bool wildcard) {
|
2004-02-27 20:41:51 +00:00
|
|
|
unsigned char *ndata, ch;
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int n;
|
|
|
|
bool first;
|
2004-02-27 20:41:51 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(name));
|
|
|
|
REQUIRE(name->labels > 0);
|
|
|
|
REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
|
2008-04-01 23:47:10 +00:00
|
|
|
|
|
|
|
/*
|
2004-02-27 20:41:51 +00:00
|
|
|
* Root label.
|
|
|
|
*/
|
2020-02-13 21:48:23 +01:00
|
|
|
if (name->length == 1) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-02-27 20:41:51 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Skip wildcard if this is a ownername.
|
|
|
|
*/
|
|
|
|
ndata = name->ndata;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (wildcard && ndata[0] == 1 && ndata[1] == '*') {
|
2004-02-27 20:41:51 +00:00
|
|
|
ndata += 2;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-02-27 20:41:51 +00:00
|
|
|
|
|
|
|
/*
|
2021-05-04 17:21:52 +02:00
|
|
|
* RFC952/RFC1123 hostname.
|
2004-02-27 20:41:51 +00:00
|
|
|
*/
|
|
|
|
while (ndata < (name->ndata + name->length)) {
|
|
|
|
n = *ndata++;
|
2004-04-19 21:47:43 +00:00
|
|
|
INSIST(n <= 63);
|
2018-04-17 08:29:14 -07:00
|
|
|
first = true;
|
2004-02-27 20:41:51 +00:00
|
|
|
while (n--) {
|
|
|
|
ch = *ndata++;
|
|
|
|
if (first || n == 0) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (!borderchar(ch)) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-02-27 20:41:51 +00:00
|
|
|
} else {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (!middlechar(ch)) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-02-27 20:41:51 +00:00
|
|
|
}
|
2018-04-17 08:29:14 -07:00
|
|
|
first = false;
|
2004-02-27 20:41:51 +00:00
|
|
|
}
|
|
|
|
}
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2004-02-27 20:41:51 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_iswildcard(const dns_name_t *name) {
|
1999-08-12 01:29:03 +00:00
|
|
|
unsigned char *ndata;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Is 'name' a wildcard name?
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(name));
|
|
|
|
REQUIRE(name->labels > 0);
|
|
|
|
|
|
|
|
if (name->length >= 2) {
|
|
|
|
ndata = name->ndata;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (ndata[0] == 1 && ndata[1] == '*') {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-12 01:29:03 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
1999-08-12 01:29:03 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_internalwildcard(const dns_name_t *name) {
|
2005-01-09 23:40:04 +00:00
|
|
|
unsigned char *ndata;
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int count;
|
|
|
|
unsigned int label;
|
2005-01-09 23:40:04 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Does 'name' contain a internal wildcard?
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(name));
|
|
|
|
REQUIRE(name->labels > 0);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Skip first label.
|
|
|
|
*/
|
|
|
|
ndata = name->ndata;
|
|
|
|
count = *ndata++;
|
|
|
|
INSIST(count <= 63);
|
|
|
|
ndata += count;
|
|
|
|
label = 1;
|
|
|
|
/*
|
|
|
|
* Check all but the last of the remaining labels.
|
|
|
|
*/
|
|
|
|
while (label + 1 < name->labels) {
|
|
|
|
count = *ndata++;
|
|
|
|
INSIST(count <= 63);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (count == 1 && *ndata == '*') {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-01-09 23:40:04 +00:00
|
|
|
ndata += count;
|
|
|
|
label++;
|
|
|
|
}
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2005-01-09 23:40:04 +00:00
|
|
|
}
|
|
|
|
|
2001-12-04 01:32:44 +00:00
|
|
|
unsigned int
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_hash(const dns_name_t *name, bool case_sensitive) {
|
2015-12-09 19:07:20 +05:30
|
|
|
unsigned int length;
|
|
|
|
|
2001-12-04 01:32:44 +00:00
|
|
|
/*
|
|
|
|
* Provide a hash value for 'name'.
|
|
|
|
*/
|
|
|
|
REQUIRE(VALID_NAME(name));
|
|
|
|
|
2019-05-09 15:50:57 +07:00
|
|
|
if (name->labels == 0) {
|
2001-12-04 01:32:44 +00:00
|
|
|
return (0);
|
2019-05-09 15:50:57 +07:00
|
|
|
}
|
2001-12-04 01:32:44 +00:00
|
|
|
|
2015-12-09 19:07:20 +05:30
|
|
|
length = name->length;
|
2019-05-09 15:50:57 +07:00
|
|
|
if (length > 16) {
|
2015-12-09 19:07:20 +05:30
|
|
|
length = 16;
|
2019-05-09 15:50:57 +07:00
|
|
|
}
|
2015-12-09 19:07:20 +05:30
|
|
|
|
Fix the rbt hashtable and grow it when setting max-cache-size
There were several problems with rbt hashtable implementation:
1. Our internal hashing function returns uint64_t value, but it was
silently truncated to unsigned int in dns_name_hash() and
dns_name_fullhash() functions. As the SipHash 2-4 higher bits are
more random, we need to use the upper half of the return value.
2. The hashtable implementation in rbt.c was using modulo to pick the
slot number for the hash table. This has several problems because
modulo is: a) slow, b) oblivious to patterns in the input data. This
could lead to very uneven distribution of the hashed data in the
hashtable. Combined with the single-linked lists we use, it could
really hog-down the lookup and removal of the nodes from the rbt
tree[a]. The Fibonacci Hashing is much better fit for the hashtable
function here. For longer description, read "Fibonacci Hashing: The
Optimization that the World Forgot"[b] or just look at the Linux
kernel. Also this will make Diego very happy :).
3. The hashtable would rehash every time the number of nodes in the rbt
tree would exceed 3 * (hashtable size). The overcommit will make the
uneven distribution in the hashtable even worse, but the main problem
lies in the rehashing - every time the database grows beyond the
limit, each subsequent rehashing will be much slower. The mitigation
here is letting the rbt know how big the cache can grown and
pre-allocate the hashtable to be big enough to actually never need to
rehash. This will consume more memory at the start, but since the
size of the hashtable is capped to `1 << 32` (e.g. 4 mio entries), it
will only consume maximum of 32GB of memory for hashtable in the
worst case (and max-cache-size would need to be set to more than
4TB). Calling the dns_db_adjusthashsize() will also cap the maximum
size of the hashtable to the pre-computed number of bits, so it won't
try to consume more gigabytes of memory than available for the
database.
FIXME: What is the average size of the rbt node that gets hashed? I
chose the pagesize (4k) as initial value to precompute the size of
the hashtable, but the value is based on feeling and not any real
data.
For future work, there are more places where we use result of the hash
value modulo some small number and that would benefit from Fibonacci
Hashing to get better distribution.
Notes:
a. A doubly linked list should be used here to speedup the removal of
the entries from the hashtable.
b. https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization-that-the-world-forgot-or-a-better-alternative-to-integer-modulo/
2020-07-16 10:29:54 +02:00
|
|
|
/* High bits are more random. */
|
2020-07-16 17:30:44 +02:00
|
|
|
return (isc_hash32(name->ndata, length, case_sensitive));
|
2001-12-04 01:32:44 +00:00
|
|
|
}
|
|
|
|
|
2003-07-25 02:22:26 +00:00
|
|
|
unsigned int
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_fullhash(const dns_name_t *name, bool case_sensitive) {
|
2003-07-25 02:22:26 +00:00
|
|
|
/*
|
|
|
|
* Provide a hash value for 'name'.
|
|
|
|
*/
|
|
|
|
REQUIRE(VALID_NAME(name));
|
|
|
|
|
2019-05-09 15:50:57 +07:00
|
|
|
if (name->labels == 0) {
|
2003-07-25 02:22:26 +00:00
|
|
|
return (0);
|
2019-05-09 15:50:57 +07:00
|
|
|
}
|
2003-07-25 02:22:26 +00:00
|
|
|
|
Fix the rbt hashtable and grow it when setting max-cache-size
There were several problems with rbt hashtable implementation:
1. Our internal hashing function returns uint64_t value, but it was
silently truncated to unsigned int in dns_name_hash() and
dns_name_fullhash() functions. As the SipHash 2-4 higher bits are
more random, we need to use the upper half of the return value.
2. The hashtable implementation in rbt.c was using modulo to pick the
slot number for the hash table. This has several problems because
modulo is: a) slow, b) oblivious to patterns in the input data. This
could lead to very uneven distribution of the hashed data in the
hashtable. Combined with the single-linked lists we use, it could
really hog-down the lookup and removal of the nodes from the rbt
tree[a]. The Fibonacci Hashing is much better fit for the hashtable
function here. For longer description, read "Fibonacci Hashing: The
Optimization that the World Forgot"[b] or just look at the Linux
kernel. Also this will make Diego very happy :).
3. The hashtable would rehash every time the number of nodes in the rbt
tree would exceed 3 * (hashtable size). The overcommit will make the
uneven distribution in the hashtable even worse, but the main problem
lies in the rehashing - every time the database grows beyond the
limit, each subsequent rehashing will be much slower. The mitigation
here is letting the rbt know how big the cache can grown and
pre-allocate the hashtable to be big enough to actually never need to
rehash. This will consume more memory at the start, but since the
size of the hashtable is capped to `1 << 32` (e.g. 4 mio entries), it
will only consume maximum of 32GB of memory for hashtable in the
worst case (and max-cache-size would need to be set to more than
4TB). Calling the dns_db_adjusthashsize() will also cap the maximum
size of the hashtable to the pre-computed number of bits, so it won't
try to consume more gigabytes of memory than available for the
database.
FIXME: What is the average size of the rbt node that gets hashed? I
chose the pagesize (4k) as initial value to precompute the size of
the hashtable, but the value is based on feeling and not any real
data.
For future work, there are more places where we use result of the hash
value modulo some small number and that would benefit from Fibonacci
Hashing to get better distribution.
Notes:
a. A doubly linked list should be used here to speedup the removal of
the entries from the hashtable.
b. https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization-that-the-world-forgot-or-a-better-alternative-to-integer-modulo/
2020-07-16 10:29:54 +02:00
|
|
|
/* High bits are more random. */
|
2020-07-16 17:30:44 +02:00
|
|
|
return (isc_hash32(name->ndata, name->length, case_sensitive));
|
2003-07-25 02:22:26 +00:00
|
|
|
}
|
|
|
|
|
1999-02-16 08:18:44 +00:00
|
|
|
dns_namereln_t
|
2000-06-01 18:26:56 +00:00
|
|
|
dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
|
2020-02-13 14:44:37 -08:00
|
|
|
int *orderp, unsigned int *nlabelsp) {
|
|
|
|
unsigned int l1, l2, l, count1, count2, count, nlabels;
|
|
|
|
int cdiff, ldiff, chdiff;
|
1998-12-04 02:27:01 +00:00
|
|
|
unsigned char *label1, *label2;
|
1999-01-09 00:33:15 +00:00
|
|
|
unsigned char *offsets1, *offsets2;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_offsets_t odata1, odata2;
|
1999-02-16 08:18:44 +00:00
|
|
|
dns_namereln_t namereln = dns_namereln_none;
|
1998-12-04 02:27:01 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Determine the relative ordering under the DNSSEC order relation of
|
1999-02-16 08:18:44 +00:00
|
|
|
* 'name1' and 'name2', and also determine the hierarchical
|
|
|
|
* relationship of the names.
|
|
|
|
*
|
|
|
|
* Note: It makes no sense for one of the names to be relative and the
|
|
|
|
* other absolute. If both names are relative, then to be meaningfully
|
|
|
|
* compared the caller must ensure that they are both relative to the
|
|
|
|
* same domain.
|
1998-12-04 02:27:01 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(name1));
|
|
|
|
REQUIRE(VALID_NAME(name2));
|
1999-02-16 08:18:44 +00:00
|
|
|
REQUIRE(orderp != NULL);
|
|
|
|
REQUIRE(nlabelsp != NULL);
|
|
|
|
/*
|
|
|
|
* Either name1 is absolute and name2 is absolute, or neither is.
|
|
|
|
*/
|
1999-05-18 22:05:40 +00:00
|
|
|
REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
|
|
|
|
(name2->attributes & DNS_NAMEATTR_ABSOLUTE));
|
1998-12-04 02:27:01 +00:00
|
|
|
|
2021-10-14 10:33:24 +02:00
|
|
|
if (name1 == name2) {
|
2013-06-18 18:14:28 -07:00
|
|
|
*orderp = 0;
|
2014-09-27 11:41:44 +10:00
|
|
|
*nlabelsp = name1->labels;
|
2013-06-18 18:14:28 -07:00
|
|
|
return (dns_namereln_equal);
|
|
|
|
}
|
|
|
|
|
1999-01-09 00:33:15 +00:00
|
|
|
SETUP_OFFSETS(name1, offsets1, odata1);
|
|
|
|
SETUP_OFFSETS(name2, offsets2, odata2);
|
|
|
|
|
1999-02-16 08:18:44 +00:00
|
|
|
nlabels = 0;
|
1998-12-04 02:27:01 +00:00
|
|
|
l1 = name1->labels;
|
|
|
|
l2 = name2->labels;
|
2012-10-06 14:20:45 +10:00
|
|
|
if (l2 > l1) {
|
1998-12-04 02:27:01 +00:00
|
|
|
l = l1;
|
2012-10-06 14:20:45 +10:00
|
|
|
ldiff = 0 - (l2 - l1);
|
|
|
|
} else {
|
1998-12-04 02:27:01 +00:00
|
|
|
l = l2;
|
2012-10-06 14:20:45 +10:00
|
|
|
ldiff = l1 - l2;
|
|
|
|
}
|
1998-12-04 02:27:01 +00:00
|
|
|
|
2015-12-09 19:07:20 +05:30
|
|
|
offsets1 += l1;
|
|
|
|
offsets2 += l2;
|
|
|
|
|
2021-10-14 10:33:24 +02:00
|
|
|
while (l > 0) {
|
1998-12-04 02:27:01 +00:00
|
|
|
l--;
|
2015-12-09 19:07:20 +05:30
|
|
|
offsets1--;
|
|
|
|
offsets2--;
|
|
|
|
label1 = &name1->ndata[*offsets1];
|
|
|
|
label2 = &name2->ndata[*offsets2];
|
1998-12-04 02:27:01 +00:00
|
|
|
count1 = *label1++;
|
|
|
|
count2 = *label2++;
|
|
|
|
|
2002-08-27 04:53:43 +00:00
|
|
|
/*
|
|
|
|
* We dropped bitstring labels, and we don't support any
|
|
|
|
* other extended label types.
|
|
|
|
*/
|
|
|
|
INSIST(count1 <= 63 && count2 <= 63);
|
|
|
|
|
|
|
|
cdiff = (int)count1 - (int)count2;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (cdiff < 0) {
|
2002-08-27 04:53:43 +00:00
|
|
|
count = count1;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2002-08-27 04:53:43 +00:00
|
|
|
count = count2;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-08-27 04:53:43 +00:00
|
|
|
|
2015-12-09 08:54:04 -08:00
|
|
|
/* Loop unrolled for performance */
|
2021-10-14 10:33:24 +02:00
|
|
|
while (count > 3) {
|
2015-12-09 19:07:20 +05:30
|
|
|
chdiff = (int)maptolower[label1[0]] -
|
|
|
|
(int)maptolower[label2[0]];
|
|
|
|
if (chdiff != 0) {
|
|
|
|
*orderp = chdiff;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
chdiff = (int)maptolower[label1[1]] -
|
|
|
|
(int)maptolower[label2[1]];
|
|
|
|
if (chdiff != 0) {
|
|
|
|
*orderp = chdiff;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
chdiff = (int)maptolower[label1[2]] -
|
|
|
|
(int)maptolower[label2[2]];
|
|
|
|
if (chdiff != 0) {
|
|
|
|
*orderp = chdiff;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
chdiff = (int)maptolower[label1[3]] -
|
|
|
|
(int)maptolower[label2[3]];
|
|
|
|
if (chdiff != 0) {
|
|
|
|
*orderp = chdiff;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
count -= 4;
|
|
|
|
label1 += 4;
|
|
|
|
label2 += 4;
|
|
|
|
}
|
2021-10-14 10:33:24 +02:00
|
|
|
while (count-- > 0) {
|
2015-12-09 08:54:04 -08:00
|
|
|
chdiff = (int)maptolower[*label1++] -
|
|
|
|
(int)maptolower[*label2++];
|
2002-08-27 04:53:43 +00:00
|
|
|
if (chdiff != 0) {
|
|
|
|
*orderp = chdiff;
|
1999-02-16 08:18:44 +00:00
|
|
|
goto done;
|
|
|
|
}
|
2002-08-27 04:53:43 +00:00
|
|
|
}
|
|
|
|
if (cdiff != 0) {
|
|
|
|
*orderp = cdiff;
|
1999-02-16 08:18:44 +00:00
|
|
|
goto done;
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
2002-08-27 04:53:43 +00:00
|
|
|
nlabels++;
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
|
|
|
|
1999-02-16 08:18:44 +00:00
|
|
|
*orderp = ldiff;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (ldiff < 0) {
|
1999-02-16 08:18:44 +00:00
|
|
|
namereln = dns_namereln_contains;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else if (ldiff > 0) {
|
1999-02-16 08:18:44 +00:00
|
|
|
namereln = dns_namereln_subdomain;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
1999-02-16 08:18:44 +00:00
|
|
|
namereln = dns_namereln_equal;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2015-12-09 19:07:20 +05:30
|
|
|
*nlabelsp = nlabels;
|
|
|
|
return (namereln);
|
1999-02-16 08:18:44 +00:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
done:
|
1999-02-16 08:18:44 +00:00
|
|
|
*nlabelsp = nlabels;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (nlabels > 0) {
|
1999-02-16 08:18:44 +00:00
|
|
|
namereln = dns_namereln_commonancestor;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-02-16 08:18:44 +00:00
|
|
|
|
|
|
|
return (namereln);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
|
|
|
|
int order;
|
2003-10-25 00:31:12 +00:00
|
|
|
unsigned int nlabels;
|
1999-02-16 08:18:44 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Determine the relative ordering under the DNSSEC order relation of
|
|
|
|
* 'name1' and 'name2'.
|
|
|
|
*
|
|
|
|
* Note: It makes no sense for one of the names to be relative and the
|
|
|
|
* other absolute. If both names are relative, then to be meaningfully
|
|
|
|
* compared the caller must ensure that they are both relative to the
|
|
|
|
* same domain.
|
|
|
|
*/
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2003-10-25 00:31:12 +00:00
|
|
|
(void)dns_name_fullcompare(name1, name2, &order, &nlabels);
|
1999-02-16 08:18:44 +00:00
|
|
|
|
|
|
|
return (order);
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
|
|
|
|
unsigned int l, count;
|
|
|
|
unsigned char c;
|
1999-05-18 22:05:40 +00:00
|
|
|
unsigned char *label1, *label2;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Are 'name1' and 'name2' equal?
|
|
|
|
*
|
|
|
|
* Note: It makes no sense for one of the names to be relative and the
|
|
|
|
* other absolute. If both names are relative, then to be meaningfully
|
|
|
|
* compared the caller must ensure that they are both relative to the
|
|
|
|
* same domain.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(name1));
|
|
|
|
REQUIRE(VALID_NAME(name2));
|
|
|
|
/*
|
|
|
|
* Either name1 is absolute and name2 is absolute, or neither is.
|
|
|
|
*/
|
|
|
|
REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
|
|
|
|
(name2->attributes & DNS_NAMEATTR_ABSOLUTE));
|
|
|
|
|
2021-10-14 10:33:24 +02:00
|
|
|
if (name1 == name2) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2013-06-18 18:14:28 -07:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (name1->length != name2->length) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-05-18 22:05:40 +00:00
|
|
|
|
|
|
|
l = name1->labels;
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (l != name2->labels) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-05-18 22:05:40 +00:00
|
|
|
|
|
|
|
label1 = name1->ndata;
|
|
|
|
label2 = name2->ndata;
|
2021-10-14 10:33:24 +02:00
|
|
|
while (l-- > 0) {
|
1999-05-18 22:05:40 +00:00
|
|
|
count = *label1++;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (count != *label2++) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-08-27 04:53:43 +00:00
|
|
|
|
|
|
|
INSIST(count <= 63); /* no bitstring support */
|
|
|
|
|
2015-12-09 08:54:04 -08:00
|
|
|
/* Loop unrolled for performance */
|
2021-10-14 10:33:24 +02:00
|
|
|
while (count > 3) {
|
2015-12-09 23:45:23 +00:00
|
|
|
c = maptolower[label1[0]];
|
2020-02-13 21:48:23 +01:00
|
|
|
if (c != maptolower[label2[0]]) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2015-12-09 23:45:23 +00:00
|
|
|
c = maptolower[label1[1]];
|
2020-02-13 21:48:23 +01:00
|
|
|
if (c != maptolower[label2[1]]) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2015-12-09 23:45:23 +00:00
|
|
|
c = maptolower[label1[2]];
|
2020-02-13 21:48:23 +01:00
|
|
|
if (c != maptolower[label2[2]]) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2015-12-09 23:45:23 +00:00
|
|
|
c = maptolower[label1[3]];
|
2020-02-13 21:48:23 +01:00
|
|
|
if (c != maptolower[label2[3]]) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2015-12-09 19:07:20 +05:30
|
|
|
count -= 4;
|
|
|
|
label1 += 4;
|
|
|
|
label2 += 4;
|
|
|
|
}
|
2021-10-14 10:33:24 +02:00
|
|
|
while (count-- > 0) {
|
2002-08-27 04:53:43 +00:00
|
|
|
c = maptolower[*label1++];
|
2020-02-13 21:48:23 +01:00
|
|
|
if (c != maptolower[*label2++]) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-05-18 22:05:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
1999-05-18 22:05:40 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
|
2005-03-04 02:56:21 +00:00
|
|
|
/*
|
|
|
|
* Are 'name1' and 'name2' equal?
|
|
|
|
*
|
|
|
|
* Note: It makes no sense for one of the names to be relative and the
|
|
|
|
* other absolute. If both names are relative, then to be meaningfully
|
|
|
|
* compared the caller must ensure that they are both relative to the
|
|
|
|
* same domain.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(name1));
|
|
|
|
REQUIRE(VALID_NAME(name2));
|
|
|
|
/*
|
|
|
|
* Either name1 is absolute and name2 is absolute, or neither is.
|
|
|
|
*/
|
|
|
|
REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
|
|
|
|
(name2->attributes & DNS_NAMEATTR_ABSOLUTE));
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (name1->length != name2->length) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-03-04 02:56:21 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (memcmp(name1->ndata, name2->ndata, name1->length) != 0) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-03-04 02:56:21 +00:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2005-03-04 02:56:21 +00:00
|
|
|
}
|
|
|
|
|
1999-02-15 05:44:22 +00:00
|
|
|
int
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
|
|
|
|
unsigned int l1, l2, l, count1, count2, count;
|
|
|
|
unsigned char c1, c2;
|
1999-02-15 05:44:22 +00:00
|
|
|
unsigned char *label1, *label2;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Compare two absolute names as rdata.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(name1));
|
|
|
|
REQUIRE(name1->labels > 0);
|
|
|
|
REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
|
|
|
|
REQUIRE(VALID_NAME(name2));
|
|
|
|
REQUIRE(name2->labels > 0);
|
|
|
|
REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
|
|
|
|
|
|
|
|
l1 = name1->labels;
|
|
|
|
l2 = name2->labels;
|
|
|
|
|
|
|
|
l = (l1 < l2) ? l1 : l2;
|
|
|
|
|
|
|
|
label1 = name1->ndata;
|
|
|
|
label2 = name2->ndata;
|
|
|
|
while (l > 0) {
|
|
|
|
l--;
|
|
|
|
count1 = *label1++;
|
|
|
|
count2 = *label2++;
|
2002-08-27 04:53:43 +00:00
|
|
|
|
|
|
|
/* no bitstring support */
|
|
|
|
INSIST(count1 <= 63 && count2 <= 63);
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (count1 != count2) {
|
2002-08-27 04:53:43 +00:00
|
|
|
return ((count1 < count2) ? -1 : 1);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-08-27 04:53:43 +00:00
|
|
|
count = count1;
|
|
|
|
while (count > 0) {
|
|
|
|
count--;
|
|
|
|
c1 = maptolower[*label1++];
|
|
|
|
c2 = maptolower[*label2++];
|
2020-02-13 21:48:23 +01:00
|
|
|
if (c1 < c2) {
|
2002-08-27 04:53:43 +00:00
|
|
|
return (-1);
|
2020-02-13 21:48:23 +01:00
|
|
|
} else if (c1 > c2) {
|
2002-08-27 04:53:43 +00:00
|
|
|
return (1);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-02-15 05:44:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-03-20 19:33:20 +00:00
|
|
|
/*
|
|
|
|
* If one name had more labels than the other, their common
|
|
|
|
* prefix must have been different because the shorter name
|
|
|
|
* ended with the root label and the longer one can't have
|
|
|
|
* a root label in the middle of it. Therefore, if we get
|
|
|
|
* to this point, the lengths must be equal.
|
|
|
|
*/
|
1999-02-15 05:44:22 +00:00
|
|
|
INSIST(l1 == l2);
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
|
|
|
|
int order;
|
|
|
|
unsigned int nlabels;
|
1999-02-16 08:18:44 +00:00
|
|
|
dns_namereln_t namereln;
|
1998-12-04 02:27:01 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Is 'name1' a subdomain of 'name2'?
|
|
|
|
*
|
|
|
|
* Note: It makes no sense for one of the names to be relative and the
|
|
|
|
* other absolute. If both names are relative, then to be meaningfully
|
|
|
|
* compared the caller must ensure that they are both relative to the
|
|
|
|
* same domain.
|
|
|
|
*/
|
|
|
|
|
2003-10-25 00:31:12 +00:00
|
|
|
namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
|
1999-02-16 08:18:44 +00:00
|
|
|
if (namereln == dns_namereln_subdomain ||
|
2020-02-13 21:48:23 +01:00
|
|
|
namereln == dns_namereln_equal) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1998-12-04 02:27:01 +00:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
|
|
|
|
int order;
|
2003-10-25 00:31:12 +00:00
|
|
|
unsigned int nlabels, labels;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_t tname;
|
2000-02-02 20:11:55 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(name));
|
2000-03-29 18:49:36 +00:00
|
|
|
REQUIRE(name->labels > 0);
|
2000-02-02 20:11:55 +00:00
|
|
|
REQUIRE(VALID_NAME(wname));
|
2000-03-29 18:49:36 +00:00
|
|
|
labels = wname->labels;
|
|
|
|
REQUIRE(labels > 0);
|
2000-02-02 20:11:55 +00:00
|
|
|
REQUIRE(dns_name_iswildcard(wname));
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
#if defined(__clang__) && \
|
|
|
|
(__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
|
2012-12-01 21:32:31 +11:00
|
|
|
memset(&tname, 0, sizeof(tname));
|
2020-02-13 21:48:23 +01:00
|
|
|
#endif /* if defined(__clang__) && (__clang_major__ < 3 || (__clang_major__ == \
|
|
|
|
* 3 \
|
|
|
|
* && __clang_minor__ < 2)) */
|
2001-01-03 00:05:15 +00:00
|
|
|
DNS_NAME_INIT(&tname, NULL);
|
2000-02-02 20:11:55 +00:00
|
|
|
dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
|
2003-10-25 00:31:12 +00:00
|
|
|
if (dns_name_fullcompare(name, &tname, &order, &nlabels) ==
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_namereln_subdomain)
|
|
|
|
{
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2000-02-02 20:11:55 +00:00
|
|
|
}
|
|
|
|
|
1998-12-04 02:27:01 +00:00
|
|
|
unsigned int
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_countlabels(const dns_name_t *name) {
|
1998-12-04 02:27:01 +00:00
|
|
|
/*
|
|
|
|
* How many labels does 'name' have?
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(name));
|
|
|
|
|
|
|
|
ENSURE(name->labels <= 128);
|
|
|
|
|
|
|
|
return (name->labels);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
|
1999-01-09 00:33:15 +00:00
|
|
|
unsigned char *offsets;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_offsets_t odata;
|
1999-01-09 00:33:15 +00:00
|
|
|
|
1998-12-04 02:27:01 +00:00
|
|
|
/*
|
|
|
|
* Make 'label' refer to the 'n'th least significant label of 'name'.
|
|
|
|
*/
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1998-12-04 02:27:01 +00:00
|
|
|
REQUIRE(VALID_NAME(name));
|
1999-01-06 05:41:20 +00:00
|
|
|
REQUIRE(name->labels > 0);
|
1998-12-04 02:27:01 +00:00
|
|
|
REQUIRE(n < name->labels);
|
|
|
|
REQUIRE(label != NULL);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-01-09 00:33:15 +00:00
|
|
|
SETUP_OFFSETS(name, offsets, odata);
|
|
|
|
|
|
|
|
label->base = &name->ndata[offsets[n]];
|
2020-02-13 21:48:23 +01:00
|
|
|
if (n == name->labels - 1) {
|
1999-01-09 00:33:15 +00:00
|
|
|
label->length = name->length - offsets[n];
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
1999-01-09 00:33:15 +00:00
|
|
|
label->length = offsets[n + 1] - offsets[n];
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_name_getlabelsequence(const dns_name_t *source, unsigned int first,
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int n, dns_name_t *target) {
|
2017-04-22 08:25:10 +05:30
|
|
|
unsigned char *p, l;
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int firstoffset, endoffset;
|
|
|
|
unsigned int i;
|
1999-01-09 00:33:15 +00:00
|
|
|
|
1998-12-04 02:27:01 +00:00
|
|
|
/*
|
|
|
|
* Make 'target' refer to the 'n' labels including and following
|
|
|
|
* 'first' in 'source'.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(source));
|
1999-04-09 01:27:54 +00:00
|
|
|
REQUIRE(VALID_NAME(target));
|
2000-08-22 00:46:54 +00:00
|
|
|
REQUIRE(first <= source->labels);
|
2010-05-12 05:40:32 +00:00
|
|
|
REQUIRE(n <= source->labels - first); /* note first+n could overflow */
|
1999-08-19 23:26:16 +00:00
|
|
|
REQUIRE(BINDABLE(target));
|
1998-12-04 02:27:01 +00:00
|
|
|
|
2017-04-22 08:25:10 +05:30
|
|
|
p = source->ndata;
|
2021-10-14 10:33:24 +02:00
|
|
|
if (first == source->labels) {
|
2000-08-22 00:46:54 +00:00
|
|
|
firstoffset = source->length;
|
2017-04-22 08:25:10 +05:30
|
|
|
} else {
|
|
|
|
for (i = 0; i < first; i++) {
|
|
|
|
l = *p;
|
|
|
|
p += l + 1;
|
|
|
|
}
|
2017-09-07 12:57:55 +10:00
|
|
|
firstoffset = (unsigned int)(p - source->ndata);
|
2017-04-22 08:25:10 +05:30
|
|
|
}
|
2000-08-22 00:46:54 +00:00
|
|
|
|
2021-10-14 10:33:24 +02:00
|
|
|
if (first + n == source->labels) {
|
2000-08-22 00:46:54 +00:00
|
|
|
endoffset = source->length;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2017-04-22 08:25:10 +05:30
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
l = *p;
|
|
|
|
p += l + 1;
|
|
|
|
}
|
2017-09-07 12:57:55 +10:00
|
|
|
endoffset = (unsigned int)(p - source->ndata);
|
2017-04-22 08:25:10 +05:30
|
|
|
}
|
2000-08-22 00:46:54 +00:00
|
|
|
|
|
|
|
target->ndata = &source->ndata[firstoffset];
|
|
|
|
target->length = endoffset - firstoffset;
|
2008-04-01 23:47:10 +00:00
|
|
|
|
2000-08-22 00:46:54 +00:00
|
|
|
if (first + n == source->labels && n > 0 &&
|
2020-02-13 14:44:37 -08:00
|
|
|
(source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
|
|
|
|
{
|
2000-08-22 00:46:54 +00:00
|
|
|
target->attributes |= DNS_NAMEATTR_ABSOLUTE;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
1999-02-06 01:26:00 +00:00
|
|
|
target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-08-22 00:46:54 +00:00
|
|
|
|
1998-12-04 02:27:01 +00:00
|
|
|
target->labels = n;
|
|
|
|
|
2000-04-26 23:22:53 +00:00
|
|
|
/*
|
|
|
|
* If source and target are the same, and we're making target
|
|
|
|
* a prefix of source, the offsets table is correct already
|
|
|
|
* so we don't need to call set_offsets().
|
|
|
|
*/
|
2020-02-13 21:48:23 +01:00
|
|
|
if (target->offsets != NULL && (target != source || first != 0)) {
|
2000-06-01 18:26:56 +00:00
|
|
|
set_offsets(target, target->offsets, NULL);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
|
|
|
|
1999-04-24 02:03:07 +00:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_clone(const dns_name_t *source, dns_name_t *target) {
|
1999-04-24 02:03:07 +00:00
|
|
|
/*
|
|
|
|
* Make 'target' refer to the same name as 'source'.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(source));
|
|
|
|
REQUIRE(VALID_NAME(target));
|
1999-08-19 23:26:16 +00:00
|
|
|
REQUIRE(BINDABLE(target));
|
1999-04-24 02:03:07 +00:00
|
|
|
|
|
|
|
target->ndata = source->ndata;
|
|
|
|
target->length = source->length;
|
|
|
|
target->labels = source->labels;
|
2020-02-13 14:44:37 -08:00
|
|
|
target->attributes = source->attributes &
|
|
|
|
(unsigned int)~(DNS_NAMEATTR_READONLY |
|
|
|
|
DNS_NAMEATTR_DYNAMIC |
|
|
|
|
DNS_NAMEATTR_DYNOFFSETS);
|
1999-04-24 02:03:07 +00:00
|
|
|
if (target->offsets != NULL && source->labels > 0) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (source->offsets != NULL) {
|
2014-01-08 16:27:10 -08:00
|
|
|
memmove(target->offsets, source->offsets,
|
|
|
|
source->labels);
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2000-06-01 18:26:56 +00:00
|
|
|
set_offsets(target, target->offsets, NULL);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-04-24 02:03:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-12-04 02:27:01 +00:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
|
1999-01-09 00:33:15 +00:00
|
|
|
unsigned char *offsets;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_offsets_t odata;
|
|
|
|
unsigned int len;
|
|
|
|
isc_region_t r2;
|
1999-01-09 00:33:15 +00:00
|
|
|
|
1998-12-04 02:27:01 +00:00
|
|
|
/*
|
|
|
|
* Make 'name' refer to region 'r'.
|
|
|
|
*/
|
|
|
|
|
1999-01-09 00:33:15 +00:00
|
|
|
REQUIRE(VALID_NAME(name));
|
1998-12-04 02:27:01 +00:00
|
|
|
REQUIRE(r != NULL);
|
1999-08-19 23:26:16 +00:00
|
|
|
REQUIRE(BINDABLE(name));
|
1998-12-04 02:27:01 +00:00
|
|
|
|
1999-01-09 00:33:15 +00:00
|
|
|
INIT_OFFSETS(name, offsets, odata);
|
|
|
|
|
1999-04-28 03:03:56 +00:00
|
|
|
if (name->buffer != NULL) {
|
|
|
|
isc_buffer_clear(name->buffer);
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_availableregion(name->buffer, &r2);
|
1999-04-28 03:03:56 +00:00
|
|
|
len = (r->length < r2.length) ? r->length : r2.length;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (len > DNS_NAME_MAXWIRE) {
|
2000-10-11 17:44:18 +00:00
|
|
|
len = DNS_NAME_MAXWIRE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (len != 0) {
|
2017-12-06 21:00:14 +11:00
|
|
|
memmove(r2.base, r->base, len);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-04-28 03:03:56 +00:00
|
|
|
name->ndata = r2.base;
|
|
|
|
name->length = len;
|
|
|
|
} else {
|
|
|
|
name->ndata = r->base;
|
2020-02-12 13:59:18 +01:00
|
|
|
name->length = (r->length <= DNS_NAME_MAXWIRE)
|
|
|
|
? r->length
|
|
|
|
: DNS_NAME_MAXWIRE;
|
1999-04-28 03:03:56 +00:00
|
|
|
}
|
1998-12-04 02:27:01 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (r->length > 0) {
|
2000-06-01 18:26:56 +00:00
|
|
|
set_offsets(name, offsets, name);
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
1998-12-04 02:27:01 +00:00
|
|
|
name->labels = 0;
|
1999-02-23 02:25:41 +00:00
|
|
|
name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
|
|
|
|
}
|
1999-04-28 03:03:56 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (name->buffer != NULL) {
|
1999-04-28 03:03:56 +00:00
|
|
|
isc_buffer_add(name->buffer, name->length);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_toregion(const dns_name_t *name, isc_region_t *r) {
|
1998-12-04 02:27:01 +00:00
|
|
|
/*
|
|
|
|
* Make 'r' refer to 'name'.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(name));
|
|
|
|
REQUIRE(r != NULL);
|
|
|
|
|
2001-01-04 20:00:57 +00:00
|
|
|
DNS_NAME_TOREGION(name, r);
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
1999-01-06 05:41:20 +00:00
|
|
|
dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
|
2011-01-13 01:59:28 +00:00
|
|
|
const dns_name_t *origin, unsigned int options,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_buffer_t *target) {
|
2011-03-11 06:11:27 +00:00
|
|
|
unsigned char *ndata, *label = NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
char *tdata;
|
|
|
|
char c;
|
|
|
|
ft_state state;
|
|
|
|
unsigned int value = 0, count = 0;
|
|
|
|
unsigned int n1 = 0, n2 = 0;
|
|
|
|
unsigned int tlen, nrem, nused, digits = 0, labels, tused;
|
|
|
|
bool done;
|
1999-01-09 00:33:15 +00:00
|
|
|
unsigned char *offsets;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_offsets_t odata;
|
|
|
|
bool downcase;
|
1998-12-04 02:27:01 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert the textual representation of a DNS name at source
|
|
|
|
* into uncompressed wire form stored in target.
|
|
|
|
*
|
|
|
|
* Notes:
|
|
|
|
* Relative domain names will have 'origin' appended to them
|
|
|
|
* unless 'origin' is NULL, in which case relative domain names
|
|
|
|
* will remain relative.
|
|
|
|
*/
|
|
|
|
|
1999-01-09 00:33:15 +00:00
|
|
|
REQUIRE(VALID_NAME(name));
|
2000-05-25 23:57:25 +00:00
|
|
|
REQUIRE(ISC_BUFFER_VALID(source));
|
|
|
|
REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
|
2002-05-29 00:27:53 +00:00
|
|
|
(target == NULL && ISC_BUFFER_VALID(name->buffer)));
|
2008-04-01 23:47:10 +00:00
|
|
|
|
2018-10-11 11:57:57 +02:00
|
|
|
downcase = ((options & DNS_NAME_DOWNCASE) != 0);
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
|
1999-03-08 18:55:28 +00:00
|
|
|
if (target == NULL && name->buffer != NULL) {
|
|
|
|
target = name->buffer;
|
|
|
|
isc_buffer_clear(target);
|
|
|
|
}
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
|
1999-08-19 23:26:16 +00:00
|
|
|
REQUIRE(BINDABLE(name));
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-01-09 00:33:15 +00:00
|
|
|
INIT_OFFSETS(name, offsets, odata);
|
1999-02-06 01:26:00 +00:00
|
|
|
offsets[0] = 0;
|
1999-01-09 00:33:15 +00:00
|
|
|
|
1998-12-04 02:27:01 +00:00
|
|
|
/*
|
1999-08-12 20:26:45 +00:00
|
|
|
* Make 'name' empty in case of failure.
|
1998-12-04 02:27:01 +00:00
|
|
|
*/
|
1999-08-12 20:26:45 +00:00
|
|
|
MAKE_EMPTY(name);
|
1998-12-04 02:27:01 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up the state machine.
|
|
|
|
*/
|
1999-01-06 05:41:20 +00:00
|
|
|
tdata = (char *)source->base + source->current;
|
2000-05-25 23:57:25 +00:00
|
|
|
tlen = isc_buffer_remaininglength(source);
|
1999-01-06 05:41:20 +00:00
|
|
|
tused = 0;
|
2000-05-25 23:57:25 +00:00
|
|
|
ndata = isc_buffer_used(target);
|
|
|
|
nrem = isc_buffer_availablelength(target);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (nrem > 255) {
|
1998-12-04 02:27:01 +00:00
|
|
|
nrem = 255;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-01-13 19:17:22 +00:00
|
|
|
nused = 0;
|
1998-12-04 02:27:01 +00:00
|
|
|
labels = 0;
|
2018-04-17 08:29:14 -07:00
|
|
|
done = false;
|
1999-01-06 05:41:20 +00:00
|
|
|
state = ft_init;
|
1998-12-04 02:27:01 +00:00
|
|
|
|
|
|
|
while (nrem > 0 && tlen > 0 && !done) {
|
|
|
|
c = *tdata++;
|
|
|
|
tlen--;
|
1999-01-06 05:41:20 +00:00
|
|
|
tused++;
|
1998-12-04 02:27:01 +00:00
|
|
|
|
|
|
|
switch (state) {
|
1999-01-06 05:41:20 +00:00
|
|
|
case ft_init:
|
1998-12-04 02:27:01 +00:00
|
|
|
/*
|
|
|
|
* Is this the root name?
|
|
|
|
*/
|
|
|
|
if (c == '.') {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (tlen != 0) {
|
1998-12-04 02:27:01 +00:00
|
|
|
return (DNS_R_EMPTYLABEL);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1998-12-04 02:27:01 +00:00
|
|
|
labels++;
|
|
|
|
*ndata++ = 0;
|
|
|
|
nrem--;
|
1999-01-13 19:17:22 +00:00
|
|
|
nused++;
|
2018-04-17 08:29:14 -07:00
|
|
|
done = true;
|
1998-12-04 02:27:01 +00:00
|
|
|
break;
|
|
|
|
}
|
1999-02-06 01:26:00 +00:00
|
|
|
if (c == '@' && tlen == 0) {
|
|
|
|
state = ft_at;
|
|
|
|
break;
|
1999-01-27 23:39:40 +00:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2021-10-11 12:09:16 +02:00
|
|
|
FALLTHROUGH;
|
1999-01-06 05:41:20 +00:00
|
|
|
case ft_start:
|
1998-12-04 02:27:01 +00:00
|
|
|
label = ndata;
|
|
|
|
ndata++;
|
|
|
|
nrem--;
|
1999-01-13 19:17:22 +00:00
|
|
|
nused++;
|
1998-12-04 02:27:01 +00:00
|
|
|
count = 0;
|
|
|
|
if (c == '\\') {
|
1999-01-06 05:41:20 +00:00
|
|
|
state = ft_initialescape;
|
1998-12-04 02:27:01 +00:00
|
|
|
break;
|
|
|
|
}
|
1999-01-06 05:41:20 +00:00
|
|
|
state = ft_ordinary;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (nrem == 0) {
|
2002-08-02 00:25:15 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2021-10-11 12:09:16 +02:00
|
|
|
FALLTHROUGH;
|
1999-01-06 05:41:20 +00:00
|
|
|
case ft_ordinary:
|
1998-12-04 02:27:01 +00:00
|
|
|
if (c == '.') {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (count == 0) {
|
1998-12-04 02:27:01 +00:00
|
|
|
return (DNS_R_EMPTYLABEL);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1998-12-04 02:27:01 +00:00
|
|
|
*label = count;
|
|
|
|
labels++;
|
1999-02-06 01:26:00 +00:00
|
|
|
INSIST(labels <= 127);
|
|
|
|
offsets[labels] = nused;
|
1998-12-04 02:27:01 +00:00
|
|
|
if (tlen == 0) {
|
|
|
|
labels++;
|
|
|
|
*ndata++ = 0;
|
|
|
|
nrem--;
|
1999-01-13 19:17:22 +00:00
|
|
|
nused++;
|
2018-04-17 08:29:14 -07:00
|
|
|
done = true;
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
1999-01-06 05:41:20 +00:00
|
|
|
state = ft_start;
|
1998-12-04 02:27:01 +00:00
|
|
|
} else if (c == '\\') {
|
1999-01-06 05:41:20 +00:00
|
|
|
state = ft_escape;
|
1998-12-04 02:27:01 +00:00
|
|
|
} else {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (count >= 63) {
|
1998-12-04 02:27:01 +00:00
|
|
|
return (DNS_R_LABELTOOLONG);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1998-12-04 02:27:01 +00:00
|
|
|
count++;
|
1998-12-05 01:42:30 +00:00
|
|
|
CONVERTTOASCII(c);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (downcase) {
|
2014-04-11 13:25:49 +02:00
|
|
|
c = maptolower[c & 0xff];
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1998-12-04 02:27:01 +00:00
|
|
|
*ndata++ = c;
|
|
|
|
nrem--;
|
1999-01-13 19:17:22 +00:00
|
|
|
nused++;
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
|
|
|
break;
|
1999-01-06 05:41:20 +00:00
|
|
|
case ft_initialescape:
|
1998-12-04 02:27:01 +00:00
|
|
|
if (c == '[') {
|
2002-08-27 04:53:43 +00:00
|
|
|
/*
|
|
|
|
* This looks like a bitstring label, which
|
|
|
|
* was deprecated. Intentionally drop it.
|
|
|
|
*/
|
|
|
|
return (DNS_R_BADLABELTYPE);
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
1999-01-06 05:41:20 +00:00
|
|
|
state = ft_escape;
|
2011-03-11 06:11:27 +00:00
|
|
|
POST(state);
|
2021-10-11 12:09:16 +02:00
|
|
|
FALLTHROUGH;
|
1999-01-06 05:41:20 +00:00
|
|
|
case ft_escape:
|
2021-04-14 09:19:20 +02:00
|
|
|
if (!isdigit((unsigned char)c)) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (count >= 63) {
|
1998-12-04 02:27:01 +00:00
|
|
|
return (DNS_R_LABELTOOLONG);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1998-12-04 02:27:01 +00:00
|
|
|
count++;
|
1998-12-05 01:42:30 +00:00
|
|
|
CONVERTTOASCII(c);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (downcase) {
|
2014-04-11 13:25:49 +02:00
|
|
|
c = maptolower[c & 0xff];
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1998-12-04 02:27:01 +00:00
|
|
|
*ndata++ = c;
|
|
|
|
nrem--;
|
1999-01-13 19:17:22 +00:00
|
|
|
nused++;
|
1999-01-06 05:41:20 +00:00
|
|
|
state = ft_ordinary;
|
1998-12-04 02:27:01 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
digits = 0;
|
|
|
|
value = 0;
|
1999-01-06 05:41:20 +00:00
|
|
|
state = ft_escdecimal;
|
2021-10-11 12:09:16 +02:00
|
|
|
FALLTHROUGH;
|
1999-01-06 05:41:20 +00:00
|
|
|
case ft_escdecimal:
|
2021-04-14 09:19:20 +02:00
|
|
|
if (!isdigit((unsigned char)c)) {
|
1998-12-04 02:27:01 +00:00
|
|
|
return (DNS_R_BADESCAPE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1998-12-04 02:27:01 +00:00
|
|
|
value *= 10;
|
2014-04-11 13:25:49 +02:00
|
|
|
value += digitvalue[c & 0xff];
|
1998-12-04 02:27:01 +00:00
|
|
|
digits++;
|
|
|
|
if (digits == 3) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (value > 255) {
|
1998-12-04 02:27:01 +00:00
|
|
|
return (DNS_R_BADESCAPE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (count >= 63) {
|
1998-12-04 02:27:01 +00:00
|
|
|
return (DNS_R_LABELTOOLONG);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1998-12-04 02:27:01 +00:00
|
|
|
count++;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (downcase) {
|
1998-12-04 02:27:01 +00:00
|
|
|
value = maptolower[value];
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1998-12-04 02:27:01 +00:00
|
|
|
*ndata++ = value;
|
|
|
|
nrem--;
|
1999-01-13 19:17:22 +00:00
|
|
|
nused++;
|
1999-01-06 05:41:20 +00:00
|
|
|
state = ft_ordinary;
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2020-02-12 13:59:18 +01:00
|
|
|
FATAL_ERROR(__FILE__, __LINE__, "Unexpected state %d",
|
|
|
|
state);
|
1999-01-06 05:41:20 +00:00
|
|
|
/* Does not return. */
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
|
|
|
}
|
1999-01-06 05:41:20 +00:00
|
|
|
|
1998-12-04 02:27:01 +00:00
|
|
|
if (!done) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (nrem == 0) {
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-01-06 05:41:20 +00:00
|
|
|
INSIST(tlen == 0);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (state != ft_ordinary && state != ft_at) {
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_UNEXPECTEDEND);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-01-06 05:41:20 +00:00
|
|
|
if (state == ft_ordinary) {
|
|
|
|
INSIST(count != 0);
|
2021-05-18 15:51:51 +10:00
|
|
|
INSIST(label != NULL);
|
1998-12-04 02:27:01 +00:00
|
|
|
*label = count;
|
|
|
|
labels++;
|
1999-02-06 01:26:00 +00:00
|
|
|
INSIST(labels <= 127);
|
|
|
|
offsets[labels] = nused;
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
1999-01-06 05:41:20 +00:00
|
|
|
if (origin != NULL) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (nrem < origin->length) {
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1998-12-04 02:27:01 +00:00
|
|
|
label = origin->ndata;
|
|
|
|
n1 = origin->length;
|
|
|
|
nrem -= n1;
|
2011-03-11 06:11:27 +00:00
|
|
|
POST(nrem);
|
1998-12-04 02:27:01 +00:00
|
|
|
while (n1 > 0) {
|
1999-02-06 01:26:00 +00:00
|
|
|
n2 = *label++;
|
2002-08-27 04:53:43 +00:00
|
|
|
INSIST(n2 <= 63); /* no bitstring support */
|
|
|
|
*ndata++ = n2;
|
|
|
|
n1 -= n2 + 1;
|
|
|
|
nused += n2 + 1;
|
|
|
|
while (n2 > 0) {
|
|
|
|
c = *label++;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (downcase) {
|
2014-04-11 13:25:49 +02:00
|
|
|
c = maptolower[c & 0xff];
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-08-27 04:53:43 +00:00
|
|
|
*ndata++ = c;
|
|
|
|
n2--;
|
1999-02-06 01:26:00 +00:00
|
|
|
}
|
|
|
|
labels++;
|
|
|
|
if (n1 > 0) {
|
|
|
|
INSIST(labels <= 127);
|
|
|
|
offsets[labels] = nused;
|
|
|
|
}
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
2020-02-13 21:48:23 +01:00
|
|
|
if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
|
1999-02-06 01:26:00 +00:00
|
|
|
name->attributes |= DNS_NAMEATTR_ABSOLUTE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
}
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
1999-02-06 01:26:00 +00:00
|
|
|
name->attributes |= DNS_NAMEATTR_ABSOLUTE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1998-12-04 02:27:01 +00:00
|
|
|
|
1999-01-06 05:41:20 +00:00
|
|
|
name->ndata = (unsigned char *)target->base + target->used;
|
1998-12-04 02:27:01 +00:00
|
|
|
name->labels = labels;
|
1999-01-13 19:17:22 +00:00
|
|
|
name->length = nused;
|
1998-12-04 02:27:01 +00:00
|
|
|
|
1999-01-06 05:41:20 +00:00
|
|
|
isc_buffer_forward(source, tused);
|
|
|
|
isc_buffer_add(target, name->length);
|
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
2018-04-17 08:29:14 -07:00
|
|
|
dns_name_totext(const dns_name_t *name, bool omit_final_dot,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_buffer_t *target) {
|
2010-07-09 05:13:15 +00:00
|
|
|
unsigned int options = DNS_NAME_MASTERFILE;
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (omit_final_dot) {
|
2010-07-09 05:13:15 +00:00
|
|
|
options |= DNS_NAME_OMITFINALDOT;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2010-07-09 05:13:15 +00:00
|
|
|
return (dns_name_totext2(name, options, target));
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_toprincipal(const dns_name_t *name, isc_buffer_t *target) {
|
2010-07-09 05:13:15 +00:00
|
|
|
return (dns_name_totext2(name, DNS_NAME_OMITFINALDOT, target));
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2015-02-27 15:08:38 +11:00
|
|
|
dns_name_totext2(const dns_name_t *name, unsigned int options,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_buffer_t *target) {
|
1998-12-04 02:27:01 +00:00
|
|
|
unsigned char *ndata;
|
2020-02-13 14:44:37 -08:00
|
|
|
char *tdata;
|
|
|
|
unsigned int nlen, tlen;
|
|
|
|
unsigned char c;
|
|
|
|
unsigned int trem, count;
|
|
|
|
unsigned int labels;
|
|
|
|
bool saw_root = false;
|
|
|
|
unsigned int oused;
|
2018-10-11 11:57:57 +02:00
|
|
|
bool omit_final_dot = ((options & DNS_NAME_OMITFINALDOT) != 0);
|
1998-12-04 02:27:01 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* This function assumes the name is in proper uncompressed
|
|
|
|
* wire format.
|
|
|
|
*/
|
1999-01-06 05:41:20 +00:00
|
|
|
REQUIRE(VALID_NAME(name));
|
2000-08-16 22:18:20 +00:00
|
|
|
REQUIRE(ISC_BUFFER_VALID(target));
|
1998-12-04 02:27:01 +00:00
|
|
|
|
2019-09-27 10:05:27 +02:00
|
|
|
oused = target->used;
|
|
|
|
|
1998-12-04 02:27:01 +00:00
|
|
|
ndata = name->ndata;
|
|
|
|
nlen = name->length;
|
|
|
|
labels = name->labels;
|
2000-08-16 22:18:20 +00:00
|
|
|
tdata = isc_buffer_used(target);
|
|
|
|
tlen = isc_buffer_availablelength(target);
|
1998-12-04 02:27:01 +00:00
|
|
|
|
|
|
|
trem = tlen;
|
|
|
|
|
2000-07-31 23:09:49 +00:00
|
|
|
if (labels == 0 && nlen == 0) {
|
|
|
|
/*
|
|
|
|
* Special handling for an empty name.
|
|
|
|
*/
|
2020-02-13 21:48:23 +01:00
|
|
|
if (trem == 0) {
|
2000-07-31 23:09:49 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-07-31 23:09:49 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The names of these booleans are misleading in this case.
|
|
|
|
* This empty name is not necessarily from the root node of
|
|
|
|
* the DNS root zone, nor is a final dot going to be included.
|
|
|
|
* They need to be set this way, though, to keep the "@"
|
|
|
|
* from being trounced.
|
|
|
|
*/
|
2018-04-17 08:29:14 -07:00
|
|
|
saw_root = true;
|
|
|
|
omit_final_dot = false;
|
2000-07-31 23:09:49 +00:00
|
|
|
*tdata++ = '@';
|
|
|
|
trem--;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Skip the while() loop.
|
|
|
|
*/
|
1998-12-04 02:27:01 +00:00
|
|
|
nlen = 0;
|
2000-07-31 23:09:49 +00:00
|
|
|
} else if (nlen == 1 && labels == 1 && *ndata == '\0') {
|
|
|
|
/*
|
|
|
|
* Special handling for the root label.
|
|
|
|
*/
|
2020-02-13 21:48:23 +01:00
|
|
|
if (trem == 0) {
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-07-31 23:09:49 +00:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
saw_root = true;
|
|
|
|
omit_final_dot = false;
|
1998-12-04 02:27:01 +00:00
|
|
|
*tdata++ = '.';
|
|
|
|
trem--;
|
2000-07-31 23:09:49 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Skip the while() loop.
|
|
|
|
*/
|
|
|
|
nlen = 0;
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
2000-07-31 23:09:49 +00:00
|
|
|
|
1998-12-04 02:27:01 +00:00
|
|
|
while (labels > 0 && nlen > 0 && trem > 0) {
|
|
|
|
labels--;
|
|
|
|
count = *ndata++;
|
|
|
|
nlen--;
|
|
|
|
if (count == 0) {
|
2018-04-17 08:29:14 -07:00
|
|
|
saw_root = true;
|
1998-12-04 02:27:01 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (count < 64) {
|
|
|
|
INSIST(nlen >= count);
|
|
|
|
while (count > 0) {
|
|
|
|
c = *ndata;
|
|
|
|
switch (c) {
|
2010-07-09 05:13:15 +00:00
|
|
|
/* Special modifiers in zone files. */
|
|
|
|
case 0x40: /* '@' */
|
|
|
|
case 0x24: /* '$' */
|
2020-02-12 13:59:18 +01:00
|
|
|
if ((options & DNS_NAME_MASTERFILE) ==
|
2020-02-13 21:48:23 +01:00
|
|
|
0) {
|
2010-07-09 05:13:15 +00:00
|
|
|
goto no_escape;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2021-10-11 12:09:16 +02:00
|
|
|
FALLTHROUGH;
|
1998-12-04 02:27:01 +00:00
|
|
|
case 0x22: /* '"' */
|
2001-04-19 18:39:42 +00:00
|
|
|
case 0x28: /* '(' */
|
|
|
|
case 0x29: /* ')' */
|
1998-12-04 02:27:01 +00:00
|
|
|
case 0x2E: /* '.' */
|
|
|
|
case 0x3B: /* ';' */
|
|
|
|
case 0x5C: /* '\\' */
|
2020-02-13 21:48:23 +01:00
|
|
|
if (trem < 2) {
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1998-12-04 02:27:01 +00:00
|
|
|
*tdata++ = '\\';
|
1999-05-05 16:51:05 +00:00
|
|
|
CONVERTFROMASCII(c);
|
1998-12-04 02:27:01 +00:00
|
|
|
*tdata++ = c;
|
|
|
|
ndata++;
|
|
|
|
trem -= 2;
|
|
|
|
nlen--;
|
|
|
|
break;
|
2010-07-09 05:13:15 +00:00
|
|
|
no_escape:
|
1998-12-04 02:27:01 +00:00
|
|
|
default:
|
|
|
|
if (c > 0x20 && c < 0x7f) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (trem == 0) {
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-05-05 16:51:05 +00:00
|
|
|
CONVERTFROMASCII(c);
|
1998-12-04 02:27:01 +00:00
|
|
|
*tdata++ = c;
|
|
|
|
ndata++;
|
|
|
|
trem--;
|
|
|
|
nlen--;
|
|
|
|
} else {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (trem < 4) {
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-07-20 01:46:49 +00:00
|
|
|
*tdata++ = 0x5c;
|
2020-02-13 14:44:37 -08:00
|
|
|
*tdata++ = 0x30 +
|
|
|
|
((c / 100) % 10);
|
|
|
|
*tdata++ = 0x30 +
|
|
|
|
((c / 10) % 10);
|
2005-07-20 01:46:49 +00:00
|
|
|
*tdata++ = 0x30 + (c % 10);
|
1998-12-04 02:27:01 +00:00
|
|
|
trem -= 4;
|
|
|
|
ndata++;
|
|
|
|
nlen--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
count--;
|
|
|
|
}
|
2003-10-17 03:46:46 +00:00
|
|
|
} else {
|
1999-01-06 05:41:20 +00:00
|
|
|
FATAL_ERROR(__FILE__, __LINE__,
|
|
|
|
"Unexpected label type %02x", count);
|
2000-07-31 23:09:49 +00:00
|
|
|
/* NOTREACHED */
|
1999-01-06 05:41:20 +00:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1998-12-04 02:27:01 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2020-02-13 21:48:23 +01:00
|
|
|
if (trem == 0) {
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1998-12-04 02:27:01 +00:00
|
|
|
*tdata++ = '.';
|
|
|
|
trem--;
|
|
|
|
}
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (nlen != 0 && trem == 0) {
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-07-31 23:09:49 +00:00
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
if (!saw_root || omit_final_dot) {
|
1998-12-04 02:27:01 +00:00
|
|
|
trem++;
|
2016-05-26 21:23:19 +02:00
|
|
|
tdata--;
|
|
|
|
}
|
|
|
|
if (trem > 0) {
|
|
|
|
*tdata = 0;
|
|
|
|
}
|
1999-01-06 05:41:20 +00:00
|
|
|
isc_buffer_add(target, tlen - trem);
|
1998-12-04 02:27:01 +00:00
|
|
|
|
2019-12-02 11:42:50 +01:00
|
|
|
if (totext_filter_proc != NULL) {
|
|
|
|
return ((totext_filter_proc)(target, oused));
|
|
|
|
}
|
2005-09-09 06:17:03 +00:00
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
|
|
|
|
2001-03-27 22:57:48 +00:00
|
|
|
isc_result_t
|
2018-04-17 08:29:14 -07:00
|
|
|
dns_name_tofilenametext(const dns_name_t *name, bool omit_final_dot,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_buffer_t *target) {
|
2001-03-27 22:57:48 +00:00
|
|
|
unsigned char *ndata;
|
2020-02-13 14:44:37 -08:00
|
|
|
char *tdata;
|
|
|
|
unsigned int nlen, tlen;
|
|
|
|
unsigned char c;
|
|
|
|
unsigned int trem, count;
|
|
|
|
unsigned int labels;
|
2001-03-27 22:57:48 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2020-02-13 21:48:23 +01:00
|
|
|
if (trem == 0) {
|
2001-03-27 22:57:48 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-03-27 22:57:48 +00:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
omit_final_dot = false;
|
2001-03-27 22:57:48 +00:00
|
|
|
*tdata++ = '.';
|
|
|
|
trem--;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Skip the while() loop.
|
|
|
|
*/
|
|
|
|
nlen = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (labels > 0 && nlen > 0 && trem > 0) {
|
|
|
|
labels--;
|
|
|
|
count = *ndata++;
|
|
|
|
nlen--;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (count == 0) {
|
2001-03-27 22:57:48 +00:00
|
|
|
break;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-03-27 22:57:48 +00:00
|
|
|
if (count < 64) {
|
|
|
|
INSIST(nlen >= count);
|
|
|
|
while (count > 0) {
|
|
|
|
c = *ndata;
|
|
|
|
if ((c >= 0x30 && c <= 0x39) || /* digit */
|
2020-02-12 13:59:18 +01:00
|
|
|
(c >= 0x41 && c <= 0x5A) || /* uppercase */
|
2001-03-27 22:57:48 +00:00
|
|
|
(c >= 0x61 && c <= 0x7A) || /* lowercase */
|
|
|
|
c == 0x2D || /* hyphen */
|
|
|
|
c == 0x5F) /* underscore */
|
|
|
|
{
|
2020-02-13 21:48:23 +01:00
|
|
|
if (trem == 0) {
|
2001-03-27 22:57:48 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-03-27 23:43:15 +00:00
|
|
|
/* downcase */
|
2020-02-13 21:48:23 +01:00
|
|
|
if (c >= 0x41 && c <= 0x5A) {
|
2001-03-27 23:43:15 +00:00
|
|
|
c += 0x20;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-03-27 22:57:48 +00:00
|
|
|
CONVERTFROMASCII(c);
|
|
|
|
*tdata++ = c;
|
|
|
|
ndata++;
|
|
|
|
trem--;
|
|
|
|
nlen--;
|
|
|
|
} else {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (trem < 4) {
|
2001-03-27 22:57:48 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-09-13 00:14:37 -07:00
|
|
|
snprintf(tdata, trem, "%%%02X", c);
|
2001-03-27 22:57:48 +00:00
|
|
|
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.
|
|
|
|
*/
|
2020-02-13 21:48:23 +01:00
|
|
|
if (trem == 0) {
|
2001-03-27 22:57:48 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-03-27 22:57:48 +00:00
|
|
|
*tdata++ = '.';
|
|
|
|
trem--;
|
|
|
|
}
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (nlen != 0 && trem == 0) {
|
2001-03-27 22:57:48 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-03-27 22:57:48 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (omit_final_dot) {
|
2001-03-27 22:57:48 +00:00
|
|
|
trem++;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-03-27 22:57:48 +00:00
|
|
|
|
|
|
|
isc_buffer_add(target, tlen - trem);
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
1999-08-26 21:07:38 +00:00
|
|
|
isc_result_t
|
2016-12-30 15:45:08 +11:00
|
|
|
dns_name_downcase(const dns_name_t *source, dns_name_t *name,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_buffer_t *target) {
|
1999-08-26 21:07:38 +00:00
|
|
|
unsigned char *sndata, *ndata;
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int nlen, count, labels;
|
|
|
|
isc_buffer_t buffer;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-26 21:07:38 +00:00
|
|
|
/*
|
|
|
|
* Downcase 'source'.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(source));
|
1999-08-20 17:01:06 +00:00
|
|
|
REQUIRE(VALID_NAME(name));
|
1999-08-26 21:07:38 +00:00
|
|
|
if (source == name) {
|
|
|
|
REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0);
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_init(&buffer, source->ndata, source->length);
|
1999-08-26 21:07:38 +00:00
|
|
|
target = &buffer;
|
|
|
|
ndata = source->ndata;
|
|
|
|
} else {
|
|
|
|
REQUIRE(BINDABLE(name));
|
2002-05-29 00:27:53 +00:00
|
|
|
REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
|
|
|
|
(target == NULL && ISC_BUFFER_VALID(name->buffer)));
|
2002-05-28 03:39:46 +00:00
|
|
|
if (target == NULL) {
|
1999-08-26 21:07:38 +00:00
|
|
|
target = name->buffer;
|
|
|
|
isc_buffer_clear(name->buffer);
|
|
|
|
}
|
|
|
|
ndata = (unsigned char *)target->base + target->used;
|
|
|
|
name->ndata = ndata;
|
|
|
|
}
|
1999-08-20 17:01:06 +00:00
|
|
|
|
1999-08-26 21:07:38 +00:00
|
|
|
sndata = source->ndata;
|
|
|
|
nlen = source->length;
|
|
|
|
labels = source->labels;
|
|
|
|
|
|
|
|
if (nlen > (target->length - target->used)) {
|
|
|
|
MAKE_EMPTY(name);
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
1999-08-26 21:07:38 +00:00
|
|
|
}
|
1999-08-20 17:01:06 +00:00
|
|
|
|
|
|
|
while (labels > 0 && nlen > 0) {
|
|
|
|
labels--;
|
1999-08-26 21:07:38 +00:00
|
|
|
count = *sndata++;
|
|
|
|
*ndata++ = count;
|
1999-08-20 17:01:06 +00:00
|
|
|
nlen--;
|
|
|
|
if (count < 64) {
|
|
|
|
INSIST(nlen >= count);
|
|
|
|
while (count > 0) {
|
1999-08-26 21:07:38 +00:00
|
|
|
*ndata++ = maptolower[(*sndata++)];
|
1999-08-20 17:01:06 +00:00
|
|
|
nlen--;
|
|
|
|
count--;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
FATAL_ERROR(__FILE__, __LINE__,
|
|
|
|
"Unexpected label type %02x", count);
|
|
|
|
/* Does not return. */
|
|
|
|
}
|
|
|
|
}
|
1999-08-26 21:07:38 +00:00
|
|
|
|
|
|
|
if (source != name) {
|
|
|
|
name->labels = source->labels;
|
|
|
|
name->length = source->length;
|
2020-02-13 21:48:23 +01:00
|
|
|
if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
|
1999-08-26 21:07:38 +00:00
|
|
|
name->attributes = DNS_NAMEATTR_ABSOLUTE;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
1999-08-26 21:07:38 +00:00
|
|
|
name->attributes = 0;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (name->labels > 0 && name->offsets != NULL) {
|
2000-06-01 18:26:56 +00:00
|
|
|
set_offsets(name, name->offsets, NULL);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-26 21:07:38 +00:00
|
|
|
}
|
|
|
|
|
2000-03-23 17:56:24 +00:00
|
|
|
isc_buffer_add(target, name->length);
|
|
|
|
|
1999-08-26 21:07:38 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-08-20 17:01:06 +00:00
|
|
|
}
|
|
|
|
|
1998-12-04 02:27:01 +00:00
|
|
|
static void
|
2000-06-01 18:26:56 +00:00
|
|
|
set_offsets(const dns_name_t *name, unsigned char *offsets,
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_t *set_name) {
|
|
|
|
unsigned int offset, count, length, nlabels;
|
1998-12-04 02:27:01 +00:00
|
|
|
unsigned char *ndata;
|
2020-02-13 14:44:37 -08:00
|
|
|
bool absolute;
|
1998-12-04 02:27:01 +00:00
|
|
|
|
|
|
|
ndata = name->ndata;
|
2000-04-26 23:22:53 +00:00
|
|
|
length = name->length;
|
1998-12-04 02:27:01 +00:00
|
|
|
offset = 0;
|
|
|
|
nlabels = 0;
|
2018-04-17 08:29:14 -07:00
|
|
|
absolute = false;
|
2021-10-14 10:33:24 +02:00
|
|
|
while (offset != length) {
|
1998-12-04 02:27:01 +00:00
|
|
|
INSIST(nlabels < 128);
|
1999-01-09 00:33:15 +00:00
|
|
|
offsets[nlabels++] = offset;
|
2017-04-22 08:25:10 +05:30
|
|
|
count = *ndata;
|
2002-08-27 04:53:43 +00:00
|
|
|
INSIST(count <= 63);
|
2017-04-22 08:25:10 +05:30
|
|
|
offset += count + 1;
|
|
|
|
ndata += count + 1;
|
2002-08-27 04:53:43 +00:00
|
|
|
INSIST(offset <= length);
|
2021-10-14 10:33:24 +02:00
|
|
|
if (count == 0) {
|
2018-04-17 08:29:14 -07:00
|
|
|
absolute = true;
|
2002-08-27 04:53:43 +00:00
|
|
|
break;
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
|
|
|
}
|
2000-06-01 18:26:56 +00:00
|
|
|
if (set_name != NULL) {
|
|
|
|
INSIST(set_name == name);
|
|
|
|
|
|
|
|
set_name->labels = nlabels;
|
|
|
|
set_name->length = offset;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (absolute) {
|
2000-06-01 18:26:56 +00:00
|
|
|
set_name->attributes |= DNS_NAMEATTR_ABSOLUTE;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2000-06-01 18:26:56 +00:00
|
|
|
set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-02-06 01:26:00 +00:00
|
|
|
}
|
1998-12-04 02:27:01 +00:00
|
|
|
INSIST(nlabels == name->labels);
|
1999-01-09 01:17:09 +00:00
|
|
|
INSIST(offset == name->length);
|
1998-12-04 02:27:01 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
1999-01-06 05:41:20 +00:00
|
|
|
dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
|
2004-02-27 20:41:51 +00:00
|
|
|
dns_decompress_t *dctx, unsigned int options,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_buffer_t *target) {
|
1999-01-06 05:41:20 +00:00
|
|
|
unsigned char *cdata, *ndata;
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int cused; /* Bytes of compressed name data used */
|
|
|
|
unsigned int nused, labels, n, nmax;
|
|
|
|
unsigned int current, new_current, biggest_pointer;
|
|
|
|
bool done;
|
|
|
|
fw_state state = fw_start;
|
|
|
|
unsigned int c;
|
1999-01-09 00:33:15 +00:00
|
|
|
unsigned char *offsets;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_offsets_t odata;
|
|
|
|
bool downcase;
|
|
|
|
bool seen_pointer;
|
1999-01-06 05:41:20 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy the possibly-compressed name at source into target,
|
2006-12-07 06:57:46 +00:00
|
|
|
* decompressing it. Loop prevention is performed by checking
|
|
|
|
* the new pointer against biggest_pointer.
|
1999-01-06 05:41:20 +00:00
|
|
|
*/
|
|
|
|
|
1999-01-09 00:33:15 +00:00
|
|
|
REQUIRE(VALID_NAME(name));
|
2002-05-29 00:27:53 +00:00
|
|
|
REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
|
|
|
|
(target == NULL && ISC_BUFFER_VALID(name->buffer)));
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
|
2018-10-11 11:57:57 +02:00
|
|
|
downcase = ((options & DNS_NAME_DOWNCASE) != 0);
|
2004-02-27 20:41:51 +00:00
|
|
|
|
1999-03-08 18:55:28 +00:00
|
|
|
if (target == NULL && name->buffer != NULL) {
|
|
|
|
target = name->buffer;
|
|
|
|
isc_buffer_clear(target);
|
|
|
|
}
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
|
1999-01-06 20:04:41 +00:00
|
|
|
REQUIRE(dctx != NULL);
|
1999-08-19 23:26:16 +00:00
|
|
|
REQUIRE(BINDABLE(name));
|
1999-01-06 05:41:20 +00:00
|
|
|
|
1999-01-09 00:33:15 +00:00
|
|
|
INIT_OFFSETS(name, offsets, odata);
|
|
|
|
|
1999-01-06 05:41:20 +00:00
|
|
|
/*
|
1999-08-12 20:26:45 +00:00
|
|
|
* Make 'name' empty in case of failure.
|
1999-01-06 05:41:20 +00:00
|
|
|
*/
|
1999-08-12 20:26:45 +00:00
|
|
|
MAKE_EMPTY(name);
|
1999-01-06 05:41:20 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize things to make the compiler happy; they're not required.
|
|
|
|
*/
|
|
|
|
n = 0;
|
|
|
|
new_current = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up.
|
|
|
|
*/
|
|
|
|
labels = 0;
|
2018-04-17 08:29:14 -07:00
|
|
|
done = false;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-06-09 22:01:55 +00:00
|
|
|
ndata = isc_buffer_used(target);
|
1999-01-13 19:17:22 +00:00
|
|
|
nused = 0;
|
2018-04-17 08:29:14 -07:00
|
|
|
seen_pointer = false;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-06-09 22:01:55 +00:00
|
|
|
/*
|
|
|
|
* 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);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (nmax > DNS_NAME_MAXWIRE) {
|
2000-10-11 17:44:18 +00:00
|
|
|
nmax = DNS_NAME_MAXWIRE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-06-09 22:01:55 +00:00
|
|
|
cdata = isc_buffer_current(source);
|
1999-01-06 05:41:20 +00:00
|
|
|
cused = 0;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-01-06 05:41:20 +00:00
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
1999-02-15 23:59:36 +00:00
|
|
|
while (current < source->active && !done) {
|
1999-01-06 05:41:20 +00:00
|
|
|
c = *cdata++;
|
|
|
|
current++;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (!seen_pointer) {
|
1999-01-06 05:41:20 +00:00
|
|
|
cused++;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-01-06 05:41:20 +00:00
|
|
|
|
|
|
|
switch (state) {
|
|
|
|
case fw_start:
|
|
|
|
if (c < 64) {
|
2001-02-13 00:07:25 +00:00
|
|
|
offsets[labels] = nused;
|
1999-01-06 05:41:20 +00:00
|
|
|
labels++;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (nused + c + 1 > nmax) {
|
2000-06-09 22:01:55 +00:00
|
|
|
goto full;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-01-13 19:17:22 +00:00
|
|
|
nused += c + 1;
|
1999-01-06 05:41:20 +00:00
|
|
|
*ndata++ = c;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (c == 0) {
|
2018-04-17 08:29:14 -07:00
|
|
|
done = true;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-01-06 05:41:20 +00:00
|
|
|
n = c;
|
|
|
|
state = fw_ordinary;
|
1999-02-24 06:31:35 +00:00
|
|
|
} else if (c >= 128 && c < 192) {
|
|
|
|
/*
|
|
|
|
* 14 bit local compression pointer.
|
2000-03-23 05:18:46 +00:00
|
|
|
* Local compression is no longer an
|
|
|
|
* IETF draft.
|
1999-02-24 06:31:35 +00:00
|
|
|
*/
|
2000-03-23 05:18:46 +00:00
|
|
|
return (DNS_R_BADLABELTYPE);
|
1999-01-06 05:41:20 +00:00
|
|
|
} else if (c >= 192) {
|
1999-01-06 20:04:41 +00:00
|
|
|
/*
|
|
|
|
* Ordinary 14-bit pointer.
|
|
|
|
*/
|
2020-02-12 13:59:18 +01:00
|
|
|
if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
|
|
|
|
0) {
|
1999-01-06 20:04:41 +00:00
|
|
|
return (DNS_R_DISALLOWED);
|
2018-10-11 11:57:57 +02:00
|
|
|
}
|
1999-01-06 05:41:20 +00:00
|
|
|
new_current = c & 0x3F;
|
|
|
|
state = fw_newcurrent;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
1999-01-06 05:41:20 +00:00
|
|
|
return (DNS_R_BADLABELTYPE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-01-06 05:41:20 +00:00
|
|
|
break;
|
|
|
|
case fw_ordinary:
|
2020-02-13 21:48:23 +01:00
|
|
|
if (downcase) {
|
1999-01-06 05:41:20 +00:00
|
|
|
c = maptolower[c];
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-01-06 05:41:20 +00:00
|
|
|
*ndata++ = c;
|
|
|
|
n--;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (n == 0) {
|
1999-01-06 05:41:20 +00:00
|
|
|
state = fw_start;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-01-06 05:41:20 +00:00
|
|
|
break;
|
|
|
|
case fw_newcurrent:
|
|
|
|
new_current *= 256;
|
|
|
|
new_current += c;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (new_current >= biggest_pointer) {
|
1999-02-24 06:31:35 +00:00
|
|
|
return (DNS_R_BADPOINTER);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-02-24 06:31:35 +00:00
|
|
|
biggest_pointer = new_current;
|
|
|
|
current = new_current;
|
2006-12-07 06:57:46 +00:00
|
|
|
cdata = (unsigned char *)source->base + current;
|
2018-04-17 08:29:14 -07:00
|
|
|
seen_pointer = true;
|
1999-02-24 06:31:35 +00:00
|
|
|
state = fw_start;
|
1999-01-06 05:41:20 +00:00
|
|
|
break;
|
|
|
|
default:
|
2020-02-12 13:59:18 +01:00
|
|
|
FATAL_ERROR(__FILE__, __LINE__, "Unknown state %d",
|
|
|
|
state);
|
1999-01-06 05:41:20 +00:00
|
|
|
/* Does not return. */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (!done) {
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_UNEXPECTEDEND);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-01-06 05:41:20 +00:00
|
|
|
|
|
|
|
name->ndata = (unsigned char *)target->base + target->used;
|
|
|
|
name->labels = labels;
|
1999-01-13 19:17:22 +00:00
|
|
|
name->length = nused;
|
1999-02-06 01:26:00 +00:00
|
|
|
name->attributes |= DNS_NAMEATTR_ABSOLUTE;
|
1999-01-06 05:41:20 +00:00
|
|
|
|
|
|
|
isc_buffer_forward(source, cused);
|
|
|
|
isc_buffer_add(target, name->length);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2000-06-09 22:01:55 +00:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
full:
|
2020-02-13 21:48:23 +01:00
|
|
|
if (nmax == DNS_NAME_MAXWIRE) {
|
2000-06-09 22:01:55 +00:00
|
|
|
/*
|
|
|
|
* The name did not fit even though we had a buffer
|
|
|
|
* big enough to fit a maximum-length name.
|
|
|
|
*/
|
2000-07-13 18:10:18 +00:00
|
|
|
return (DNS_R_NAMETOOLONG);
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2000-06-09 22:01:55 +00:00
|
|
|
/*
|
|
|
|
* The name might fit if only the caller could give us a
|
|
|
|
* big enough buffer.
|
|
|
|
*/
|
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-01-06 05:41:20 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_buffer_t *target) {
|
2017-09-13 09:24:34 +10:00
|
|
|
return (dns_name_towire2(name, cctx, target, NULL));
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_name_towire2(const dns_name_t *name, dns_compress_t *cctx,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_buffer_t *target, uint16_t *comp_offsetp) {
|
|
|
|
unsigned int methods;
|
|
|
|
uint16_t offset;
|
|
|
|
dns_name_t gp; /* Global compression prefix */
|
|
|
|
bool gf; /* Global compression target found */
|
|
|
|
uint16_t go; /* Global compression offset */
|
2001-02-12 05:22:34 +00:00
|
|
|
dns_offsets_t clo;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_t clname;
|
1999-02-22 07:24:05 +00:00
|
|
|
|
1999-01-06 05:41:20 +00:00
|
|
|
/*
|
|
|
|
* 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);
|
2002-05-29 00:27:53 +00:00
|
|
|
REQUIRE(ISC_BUFFER_VALID(target));
|
1999-01-06 05:41:20 +00:00
|
|
|
|
2017-09-13 09:24:34 +10:00
|
|
|
/*
|
|
|
|
* If this exact name was already rendered before, and the
|
|
|
|
* offset of the previously rendered name is passed to us, write
|
|
|
|
* a compression pointer directly.
|
|
|
|
*/
|
|
|
|
methods = dns_compress_getmethods(cctx);
|
|
|
|
if (comp_offsetp != NULL && *comp_offsetp < 0x4000 &&
|
|
|
|
(name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
|
2020-02-13 14:44:37 -08:00
|
|
|
(methods & DNS_COMPRESS_GLOBAL14) != 0)
|
|
|
|
{
|
2021-10-14 10:33:24 +02:00
|
|
|
if (target->length - target->used < 2) {
|
2017-09-13 09:24:34 +10:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-09-13 09:24:34 +10:00
|
|
|
offset = *comp_offsetp;
|
|
|
|
offset |= 0xc000;
|
|
|
|
isc_buffer_putuint16(target, offset);
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2000-04-26 23:22:53 +00:00
|
|
|
/*
|
|
|
|
* If 'name' doesn't have an offsets table, make a clone which
|
|
|
|
* has one.
|
|
|
|
*/
|
|
|
|
if (name->offsets == NULL) {
|
2020-02-12 13:59:18 +01:00
|
|
|
#if defined(__clang__) && \
|
|
|
|
(__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
|
2012-12-01 21:32:31 +11:00
|
|
|
memset(&clname, 0, sizeof(clname));
|
2020-02-13 21:48:23 +01:00
|
|
|
#endif /* if defined(__clang__) && (__clang_major__ < 3 || (__clang_major__ == \
|
|
|
|
* 3 \
|
|
|
|
* && __clang_minor__ < 2)) */
|
2001-01-03 00:05:15 +00:00
|
|
|
DNS_NAME_INIT(&clname, clo);
|
2000-04-26 23:22:53 +00:00
|
|
|
dns_name_clone(name, &clname);
|
|
|
|
name = &clname;
|
|
|
|
}
|
2001-02-12 05:22:34 +00:00
|
|
|
DNS_NAME_INIT(&gp, NULL);
|
1999-02-22 07:24:05 +00:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
offset = target->used; /*XXX*/
|
1999-02-22 07:24:05 +00:00
|
|
|
|
2006-12-04 01:54:53 +00:00
|
|
|
if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
|
2020-02-13 14:44:37 -08:00
|
|
|
(methods & DNS_COMPRESS_GLOBAL14) != 0)
|
|
|
|
{
|
2001-02-12 18:07:52 +00:00
|
|
|
gf = dns_compress_findglobal(cctx, name, &gp, &go);
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2018-04-17 08:29:14 -07:00
|
|
|
gf = false;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-02-22 07:24:05 +00:00
|
|
|
|
2000-12-28 00:43:12 +00:00
|
|
|
/*
|
|
|
|
* If the offset is too high for 14 bit global compression, we're
|
|
|
|
* out of luck.
|
|
|
|
*/
|
2021-10-14 10:33:24 +02:00
|
|
|
if (gf && go >= 0x4000) {
|
2018-04-17 08:29:14 -07:00
|
|
|
gf = false;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-12-28 00:43:12 +00:00
|
|
|
|
1999-04-28 03:03:56 +00:00
|
|
|
/*
|
|
|
|
* Will the compression pointer reduce the message size?
|
|
|
|
*/
|
2020-02-13 21:48:23 +01:00
|
|
|
if (gf && (gp.length + 2) >= name->length) {
|
2018-04-17 08:29:14 -07:00
|
|
|
gf = false;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-04-28 03:03:56 +00:00
|
|
|
|
1999-02-22 07:24:05 +00:00
|
|
|
if (gf) {
|
2021-10-14 10:33:24 +02:00
|
|
|
if (target->length - target->used < gp.length) {
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-12-06 21:00:14 +11:00
|
|
|
if (gp.length != 0) {
|
|
|
|
unsigned char *base = target->base;
|
|
|
|
(void)memmove(base + target->used, gp.ndata,
|
|
|
|
(size_t)gp.length);
|
|
|
|
}
|
1999-02-22 07:24:05 +00:00
|
|
|
isc_buffer_add(target, gp.length);
|
2021-10-14 10:33:24 +02:00
|
|
|
if (target->length - target->used < 2) {
|
2000-12-28 00:43:12 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-09-13 09:24:34 +10:00
|
|
|
isc_buffer_putuint16(target, go | 0xc000);
|
|
|
|
if (gp.length != 0) {
|
2001-01-04 19:25:59 +00:00
|
|
|
dns_compress_add(cctx, name, &gp, offset);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (comp_offsetp != NULL) {
|
2017-09-13 09:24:34 +10:00
|
|
|
*comp_offsetp = offset;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-09-13 09:24:34 +10:00
|
|
|
} else if (comp_offsetp != NULL) {
|
|
|
|
*comp_offsetp = go;
|
|
|
|
}
|
1999-02-22 07:24:05 +00:00
|
|
|
} else {
|
2021-10-14 10:33:24 +02:00
|
|
|
if (target->length - target->used < name->length) {
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-12-06 21:00:14 +11:00
|
|
|
if (name->length != 0) {
|
|
|
|
unsigned char *base = target->base;
|
|
|
|
(void)memmove(base + target->used, name->ndata,
|
|
|
|
(size_t)name->length);
|
|
|
|
}
|
1999-02-22 07:24:05 +00:00
|
|
|
isc_buffer_add(target, name->length);
|
2001-01-04 19:25:59 +00:00
|
|
|
dns_compress_add(cctx, name, name, offset);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (comp_offsetp != NULL) {
|
2017-09-13 09:24:34 +10:00
|
|
|
*comp_offsetp = offset;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-02-22 07:24:05 +00:00
|
|
|
}
|
2017-09-13 09:24:34 +10:00
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-02-22 07:24:05 +00:00
|
|
|
}
|
1999-01-06 05:41:20 +00:00
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
2016-12-30 15:45:08 +11:00
|
|
|
dns_name_concatenate(const dns_name_t *prefix, const dns_name_t *suffix,
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_t *name, isc_buffer_t *target) {
|
1999-03-11 00:44:17 +00:00
|
|
|
unsigned char *ndata, *offsets;
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int nrem, labels, prefix_length, length;
|
|
|
|
bool copy_prefix = true;
|
|
|
|
bool copy_suffix = true;
|
|
|
|
bool absolute = false;
|
|
|
|
dns_name_t tmp_name;
|
|
|
|
dns_offsets_t odata;
|
1999-03-08 18:55:28 +00:00
|
|
|
|
|
|
|
/*
|
1999-03-11 00:44:17 +00:00
|
|
|
* Concatenate 'prefix' and 'suffix'.
|
1999-03-08 18:55:28 +00:00
|
|
|
*/
|
1999-02-22 07:24:05 +00:00
|
|
|
|
1999-03-11 00:44:17 +00:00
|
|
|
REQUIRE(prefix == NULL || VALID_NAME(prefix));
|
|
|
|
REQUIRE(suffix == NULL || VALID_NAME(suffix));
|
|
|
|
REQUIRE(name == NULL || VALID_NAME(name));
|
2002-05-29 00:27:53 +00:00
|
|
|
REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
|
2020-02-12 13:59:18 +01:00
|
|
|
(target == NULL && name != NULL &&
|
|
|
|
ISC_BUFFER_VALID(name->buffer)));
|
2020-02-13 21:48:23 +01:00
|
|
|
if (prefix == NULL || prefix->labels == 0) {
|
2018-04-17 08:29:14 -07:00
|
|
|
copy_prefix = false;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (suffix == NULL || suffix->labels == 0) {
|
2018-04-17 08:29:14 -07:00
|
|
|
copy_suffix = false;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2020-02-12 13:59:18 +01:00
|
|
|
if (copy_prefix && (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
|
2018-04-17 08:29:14 -07:00
|
|
|
absolute = true;
|
1999-03-11 00:44:17 +00:00
|
|
|
REQUIRE(!copy_suffix);
|
|
|
|
}
|
|
|
|
if (name == NULL) {
|
2001-01-03 00:05:15 +00:00
|
|
|
DNS_NAME_INIT(&tmp_name, odata);
|
1999-03-11 00:44:17 +00:00
|
|
|
name = &tmp_name;
|
|
|
|
}
|
2002-05-29 00:27:53 +00:00
|
|
|
if (target == NULL) {
|
|
|
|
INSIST(name->buffer != NULL);
|
1999-03-08 18:55:28 +00:00
|
|
|
target = name->buffer;
|
1999-03-11 00:44:17 +00:00
|
|
|
isc_buffer_clear(name->buffer);
|
1999-03-08 18:55:28 +00:00
|
|
|
}
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
|
1999-08-19 23:26:16 +00:00
|
|
|
REQUIRE(BINDABLE(name));
|
1999-02-22 07:24:05 +00:00
|
|
|
|
1999-03-08 18:55:28 +00:00
|
|
|
/*
|
|
|
|
* Set up.
|
|
|
|
*/
|
1999-02-22 07:24:05 +00:00
|
|
|
nrem = target->length - target->used;
|
|
|
|
ndata = (unsigned char *)target->base + target->used;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (nrem > DNS_NAME_MAXWIRE) {
|
2000-10-11 17:44:18 +00:00
|
|
|
nrem = DNS_NAME_MAXWIRE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-03-11 00:44:17 +00:00
|
|
|
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;
|
|
|
|
}
|
2000-10-11 17:44:18 +00:00
|
|
|
if (length > DNS_NAME_MAXWIRE) {
|
2000-07-13 18:10:18 +00:00
|
|
|
MAKE_EMPTY(name);
|
|
|
|
return (DNS_R_NAMETOOLONG);
|
|
|
|
}
|
1999-03-11 00:44:17 +00:00
|
|
|
if (length > nrem) {
|
1999-08-12 20:26:45 +00:00
|
|
|
MAKE_EMPTY(name);
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
1999-03-11 00:44:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (copy_suffix) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
|
2018-04-17 08:29:14 -07:00
|
|
|
absolute = true;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-01-20 17:58:47 -08:00
|
|
|
memmove(ndata + prefix_length, suffix->ndata, suffix->length);
|
1999-03-11 00:44:17 +00:00
|
|
|
}
|
1999-02-22 07:24:05 +00:00
|
|
|
|
1999-03-08 18:55:28 +00:00
|
|
|
/*
|
1999-03-11 00:44:17 +00:00
|
|
|
* 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.
|
1999-03-08 18:55:28 +00:00
|
|
|
*/
|
2020-02-13 21:48:23 +01:00
|
|
|
if (copy_prefix && (prefix != name || prefix->buffer != target)) {
|
2014-01-08 16:27:10 -08:00
|
|
|
memmove(ndata, prefix->ndata, prefix_length);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-01-06 05:41:20 +00:00
|
|
|
|
1999-03-11 00:44:17 +00:00
|
|
|
name->ndata = ndata;
|
1999-02-22 07:24:05 +00:00
|
|
|
name->labels = labels;
|
1999-03-11 00:44:17 +00:00
|
|
|
name->length = length;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (absolute) {
|
1999-03-11 00:44:17 +00:00
|
|
|
name->attributes = DNS_NAMEATTR_ABSOLUTE;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
1999-03-11 00:44:17 +00:00
|
|
|
name->attributes = 0;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-02-22 07:24:05 +00:00
|
|
|
|
2002-08-27 04:53:43 +00:00
|
|
|
if (name->labels > 0 && name->offsets != NULL) {
|
1999-03-11 00:44:17 +00:00
|
|
|
INIT_OFFSETS(name, offsets, odata);
|
2000-06-01 18:26:56 +00:00
|
|
|
set_offsets(name, offsets, NULL);
|
1999-03-08 18:55:28 +00:00
|
|
|
}
|
1999-02-22 07:24:05 +00:00
|
|
|
|
|
|
|
isc_buffer_add(target, name->length);
|
1999-03-08 18:55:28 +00:00
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-01-06 05:41:20 +00:00
|
|
|
}
|
1999-04-23 04:58:43 +00:00
|
|
|
|
2003-10-25 00:31:12 +00:00
|
|
|
void
|
2016-12-30 15:45:08 +11:00
|
|
|
dns_name_split(const dns_name_t *name, unsigned int suffixlabels,
|
1999-04-23 04:58:43 +00:00
|
|
|
dns_name_t *prefix, dns_name_t *suffix)
|
|
|
|
|
|
|
|
{
|
2002-08-27 04:53:43 +00:00
|
|
|
unsigned int splitlabel;
|
1999-04-23 04:58:43 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(name));
|
2000-10-14 04:38:22 +00:00
|
|
|
REQUIRE(suffixlabels > 0);
|
2016-06-22 10:49:25 +02:00
|
|
|
REQUIRE(suffixlabels <= name->labels);
|
1999-04-23 04:58:43 +00:00
|
|
|
REQUIRE(prefix != NULL || suffix != NULL);
|
2020-02-12 13:59:18 +01:00
|
|
|
REQUIRE(prefix == NULL || (VALID_NAME(prefix) && BINDABLE(prefix)));
|
|
|
|
REQUIRE(suffix == NULL || (VALID_NAME(suffix) && BINDABLE(suffix)));
|
1999-04-23 04:58:43 +00:00
|
|
|
|
|
|
|
splitlabel = name->labels - suffixlabels;
|
2000-11-27 19:45:45 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (prefix != NULL) {
|
2002-08-27 04:53:43 +00:00
|
|
|
dns_name_getlabelsequence(name, 0, splitlabel, prefix);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-04-23 04:58:43 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (suffix != NULL) {
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_name_getlabelsequence(name, splitlabel, suffixlabels,
|
|
|
|
suffix);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-04-23 04:58:43 +00:00
|
|
|
|
2003-10-25 00:31:12 +00:00
|
|
|
return;
|
2000-02-25 01:06:54 +00:00
|
|
|
}
|
|
|
|
|
2019-11-01 08:24:35 -05:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_dup(const dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) {
|
1999-08-31 22:09:52 +00:00
|
|
|
/*
|
|
|
|
* Make 'target' a dynamically allocated copy of 'source'.
|
|
|
|
*/
|
|
|
|
|
1999-06-12 01:08:16 +00:00
|
|
|
REQUIRE(VALID_NAME(source));
|
|
|
|
REQUIRE(source->length > 0);
|
1999-07-03 20:51:31 +00:00
|
|
|
REQUIRE(VALID_NAME(target));
|
1999-08-19 23:26:16 +00:00
|
|
|
REQUIRE(BINDABLE(target));
|
1999-06-12 01:08:16 +00:00
|
|
|
|
1999-08-12 20:26:45 +00:00
|
|
|
/*
|
|
|
|
* Make 'target' empty in case of failure.
|
|
|
|
*/
|
|
|
|
MAKE_EMPTY(target);
|
1999-07-03 20:51:31 +00:00
|
|
|
|
1999-06-12 01:08:16 +00:00
|
|
|
target->ndata = isc_mem_get(mctx, source->length);
|
|
|
|
|
2014-01-08 16:27:10 -08:00
|
|
|
memmove(target->ndata, source->ndata, source->length);
|
1999-06-12 01:08:16 +00:00
|
|
|
|
|
|
|
target->length = source->length;
|
|
|
|
target->labels = source->labels;
|
1999-08-19 23:26:16 +00:00
|
|
|
target->attributes = DNS_NAMEATTR_DYNAMIC;
|
2020-02-13 21:48:23 +01:00
|
|
|
if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
|
1999-06-12 01:08:16 +00:00
|
|
|
target->attributes |= DNS_NAMEATTR_ABSOLUTE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-03-30 00:57:06 +00:00
|
|
|
if (target->offsets != NULL) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (source->offsets != NULL) {
|
2014-01-08 16:27:10 -08:00
|
|
|
memmove(target->offsets, source->offsets,
|
|
|
|
source->labels);
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2000-06-01 18:26:56 +00:00
|
|
|
set_offsets(target, target->offsets, NULL);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-03-30 00:57:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2016-12-30 15:45:08 +11:00
|
|
|
dns_name_dupwithoffsets(const dns_name_t *source, isc_mem_t *mctx,
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_t *target) {
|
2000-03-30 00:57:06 +00:00
|
|
|
/*
|
|
|
|
* 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);
|
|
|
|
|
2014-01-08 16:27:10 -08:00
|
|
|
memmove(target->ndata, source->ndata, source->length);
|
2000-03-30 00:57:06 +00:00
|
|
|
|
|
|
|
target->length = source->length;
|
|
|
|
target->labels = source->labels;
|
|
|
|
target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
|
2020-02-12 13:59:18 +01:00
|
|
|
DNS_NAMEATTR_READONLY;
|
2020-02-13 21:48:23 +01:00
|
|
|
if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
|
2000-03-30 00:57:06 +00:00
|
|
|
target->attributes |= DNS_NAMEATTR_ABSOLUTE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-03-30 00:57:06 +00:00
|
|
|
target->offsets = target->ndata + source->length;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (source->offsets != NULL) {
|
2014-01-08 16:27:10 -08:00
|
|
|
memmove(target->offsets, source->offsets, source->labels);
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2000-06-01 18:26:56 +00:00
|
|
|
set_offsets(target, target->offsets, NULL);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-06-12 01:08:16 +00:00
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-06-12 01:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
|
2000-03-30 00:57:06 +00:00
|
|
|
size_t size;
|
|
|
|
|
1999-06-12 01:08:16 +00:00
|
|
|
/*
|
|
|
|
* Free 'name'.
|
|
|
|
*/
|
|
|
|
|
1999-08-31 22:09:52 +00:00
|
|
|
REQUIRE(VALID_NAME(name));
|
|
|
|
REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
|
|
|
|
|
2000-03-30 00:57:06 +00:00
|
|
|
size = name->length;
|
2020-02-13 21:48:23 +01:00
|
|
|
if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0) {
|
2000-03-30 00:57:06 +00:00
|
|
|
size += name->labels;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-03-30 00:57:06 +00:00
|
|
|
isc_mem_put(mctx, name->ndata, size);
|
1999-06-12 01:08:16 +00:00
|
|
|
dns_name_invalidate(name);
|
|
|
|
}
|
1999-08-31 22:09:52 +00:00
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_digest(const dns_name_t *name, dns_digestfunc_t digest, void *arg) {
|
|
|
|
dns_name_t downname;
|
1999-08-31 22:09:52 +00:00
|
|
|
unsigned char data[256];
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_buffer_t buffer;
|
|
|
|
isc_result_t result;
|
|
|
|
isc_region_t r;
|
1999-08-31 22:09:52 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Send 'name' in DNSSEC canonical form to 'digest'.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(name));
|
|
|
|
REQUIRE(digest != NULL);
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
#if defined(__clang__) && \
|
|
|
|
(__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
|
2012-12-01 21:32:31 +11:00
|
|
|
memset(&downname, 0, sizeof(downname));
|
2020-02-13 21:48:23 +01:00
|
|
|
#endif /* if defined(__clang__) && (__clang_major__ < 3 || (__clang_major__ == \
|
|
|
|
* 3 \
|
|
|
|
* && __clang_minor__ < 2)) */
|
2001-01-03 00:05:15 +00:00
|
|
|
DNS_NAME_INIT(&downname, NULL);
|
2012-10-06 14:20:45 +10:00
|
|
|
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_init(&buffer, data, sizeof(data));
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-31 22:09:52 +00:00
|
|
|
result = dns_name_downcase(name, &downname, &buffer);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
1999-08-31 22:09:52 +00:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_usedregion(&buffer, &r);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-31 22:09:52 +00:00
|
|
|
return ((digest)(arg, &r));
|
|
|
|
}
|
1999-10-13 22:45:17 +00:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_dynamic(const dns_name_t *name) {
|
1999-10-13 22:45:17 +00:00
|
|
|
REQUIRE(VALID_NAME(name));
|
|
|
|
|
1999-10-17 19:22:50 +00:00
|
|
|
/*
|
|
|
|
* Returns whether there is dynamic memory associated with this name.
|
|
|
|
*/
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ? true : false);
|
1999-10-13 22:45:17 +00:00
|
|
|
}
|
1999-10-17 19:22:50 +00:00
|
|
|
|
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_print(const dns_name_t *name, FILE *stream) {
|
1999-10-17 19:22:50 +00:00
|
|
|
isc_result_t result;
|
|
|
|
isc_buffer_t b;
|
|
|
|
isc_region_t r;
|
2020-02-13 14:44:37 -08:00
|
|
|
char t[1024];
|
1999-10-17 19:22:50 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Print 'name' on 'stream'.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(name));
|
|
|
|
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_init(&b, t, sizeof(t));
|
2018-04-17 08:29:14 -07:00
|
|
|
result = dns_name_totext(name, false, &b);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
1999-10-17 19:22:50 +00:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_usedregion(&b, &r);
|
1999-10-17 19:22:50 +00:00
|
|
|
fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
2000-04-11 19:11:46 +00:00
|
|
|
|
2005-09-09 06:17:03 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_settotextfilter(dns_name_totextfilter_t *proc) {
|
2005-09-10 01:02:08 +00:00
|
|
|
/*
|
|
|
|
* If we already have been here set / clear as appropriate.
|
|
|
|
*/
|
2019-12-02 11:42:50 +01:00
|
|
|
if (totext_filter_proc != NULL && proc != NULL) {
|
|
|
|
if (totext_filter_proc == proc) {
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
2005-09-10 01:02:08 +00:00
|
|
|
}
|
2019-12-02 11:42:50 +01:00
|
|
|
if (proc == NULL && totext_filter_proc != NULL) {
|
|
|
|
totext_filter_proc = NULL;
|
|
|
|
return (ISC_R_SUCCESS);
|
2005-09-10 01:02:08 +00:00
|
|
|
}
|
2008-04-01 23:47:10 +00:00
|
|
|
|
2019-12-02 11:42:50 +01:00
|
|
|
totext_filter_proc = proc;
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
2005-09-09 06:17:03 +00:00
|
|
|
}
|
|
|
|
|
2000-04-11 19:11:46 +00:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_format(const dns_name_t *name, char *cp, unsigned int size) {
|
2000-04-11 19:11:46 +00:00
|
|
|
isc_result_t result;
|
|
|
|
isc_buffer_t buf;
|
|
|
|
|
|
|
|
REQUIRE(size > 0);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
/*
|
|
|
|
* Leave room for null termination after buffer.
|
|
|
|
*/
|
|
|
|
isc_buffer_init(&buf, cp, size - 1);
|
2018-04-17 08:29:14 -07:00
|
|
|
result = dns_name_totext(name, true, &buf);
|
2000-04-11 19:11:46 +00:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
2019-08-08 13:52:44 +10:00
|
|
|
isc_buffer_putuint8(&buf, (uint8_t)'\0');
|
|
|
|
} else {
|
2000-04-11 19:11:46 +00:00
|
|
|
snprintf(cp, size, "<unknown>");
|
2019-08-08 13:52:44 +10:00
|
|
|
}
|
2000-04-11 19:11:46 +00:00
|
|
|
}
|
2001-01-03 00:05:15 +00:00
|
|
|
|
2009-03-11 07:02:34 +00:00
|
|
|
/*
|
|
|
|
* dns_name_tostring() -- similar to dns_name_format() but allocates its own
|
|
|
|
* memory.
|
|
|
|
*/
|
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_tostring(const dns_name_t *name, char **target, isc_mem_t *mctx) {
|
2009-03-11 07:02:34 +00:00
|
|
|
isc_result_t result;
|
|
|
|
isc_buffer_t buf;
|
|
|
|
isc_region_t reg;
|
2020-02-13 14:44:37 -08:00
|
|
|
char *p, txt[DNS_NAME_FORMATSIZE];
|
2009-03-11 07:02:34 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(name));
|
2009-03-11 23:47:35 +00:00
|
|
|
REQUIRE(target != NULL && *target == NULL);
|
2009-03-11 07:02:34 +00:00
|
|
|
|
|
|
|
isc_buffer_init(&buf, txt, sizeof(txt));
|
2018-04-17 08:29:14 -07:00
|
|
|
result = dns_name_totext(name, false, &buf);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2009-03-11 07:02:34 +00:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-03-11 07:02:34 +00:00
|
|
|
|
|
|
|
isc_buffer_usedregion(&buf, ®);
|
|
|
|
p = isc_mem_allocate(mctx, reg.length + 1);
|
2020-02-12 13:59:18 +01:00
|
|
|
memmove(p, (char *)reg.base, (int)reg.length);
|
2009-03-11 07:02:34 +00:00
|
|
|
p[reg.length] = '\0';
|
|
|
|
|
|
|
|
*target = p;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* dns_name_fromstring() -- convert directly from a string to a name,
|
|
|
|
* allocating memory as needed
|
|
|
|
*/
|
|
|
|
isc_result_t
|
2009-09-01 17:36:51 +00:00
|
|
|
dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_mem_t *mctx) {
|
2011-01-13 01:59:28 +00:00
|
|
|
return (dns_name_fromstring2(target, src, dns_rootname, options, mctx));
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_name_fromstring2(dns_name_t *target, const char *src,
|
|
|
|
const dns_name_t *origin, unsigned int options,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_mem_t *mctx) {
|
|
|
|
isc_result_t result;
|
|
|
|
isc_buffer_t buf;
|
2009-03-11 07:02:34 +00:00
|
|
|
dns_fixedname_t fn;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_t *name;
|
2009-03-11 07:02:34 +00:00
|
|
|
|
2009-09-01 17:36:51 +00:00
|
|
|
REQUIRE(src != NULL);
|
|
|
|
|
2012-12-08 12:48:57 +11:00
|
|
|
isc_buffer_constinit(&buf, src, strlen(src));
|
2009-03-11 07:02:34 +00:00
|
|
|
isc_buffer_add(&buf, strlen(src));
|
2020-02-13 21:48:23 +01:00
|
|
|
if (BINDABLE(target) && target->buffer != NULL) {
|
2011-01-13 01:59:28 +00:00
|
|
|
name = target;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2018-03-28 14:38:09 +02:00
|
|
|
name = dns_fixedname_initname(&fn);
|
2011-01-13 01:59:28 +00:00
|
|
|
}
|
2009-03-11 07:02:34 +00:00
|
|
|
|
2011-01-13 01:59:28 +00:00
|
|
|
result = dns_name_fromtext(name, &buf, origin, options, NULL);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2009-03-11 07:02:34 +00:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-03-11 07:02:34 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (name != target) {
|
2011-01-13 01:59:28 +00:00
|
|
|
result = dns_name_dupwithoffsets(name, mctx, target);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-03-11 07:02:34 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2021-05-21 17:17:23 -07:00
|
|
|
void
|
2021-05-21 17:20:44 -07:00
|
|
|
dns_name_copy(const dns_name_t *source, dns_name_t *dest) {
|
2021-05-21 17:17:23 -07:00
|
|
|
isc_buffer_t *target = NULL;
|
2021-05-21 15:30:00 +02:00
|
|
|
unsigned char *ndata = NULL;
|
2001-01-03 00:05:15 +00:00
|
|
|
|
2021-05-21 17:17:23 -07:00
|
|
|
REQUIRE(VALID_NAME(source));
|
|
|
|
REQUIRE(VALID_NAME(dest));
|
2001-01-03 00:05:15 +00:00
|
|
|
REQUIRE(BINDABLE(dest));
|
|
|
|
|
2021-05-21 17:17:23 -07:00
|
|
|
target = dest->buffer;
|
2001-01-03 00:05:15 +00:00
|
|
|
|
2021-05-21 17:17:23 -07:00
|
|
|
REQUIRE(target != NULL);
|
|
|
|
REQUIRE(target->length >= source->length);
|
|
|
|
|
|
|
|
isc_buffer_clear(target);
|
|
|
|
|
|
|
|
ndata = (unsigned char *)target->base;
|
2001-01-03 00:05:15 +00:00
|
|
|
dest->ndata = target->base;
|
|
|
|
|
2019-09-10 14:36:41 +02:00
|
|
|
if (source->length != 0) {
|
2017-12-06 21:00:14 +11:00
|
|
|
memmove(ndata, source->ndata, source->length);
|
2019-09-10 14:36:41 +02:00
|
|
|
}
|
2001-01-03 00:05:15 +00:00
|
|
|
|
|
|
|
dest->ndata = ndata;
|
|
|
|
dest->labels = source->labels;
|
|
|
|
dest->length = source->length;
|
2019-09-10 14:36:41 +02:00
|
|
|
if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
|
2001-01-03 00:05:15 +00:00
|
|
|
dest->attributes = DNS_NAMEATTR_ABSOLUTE;
|
2019-09-10 14:36:41 +02:00
|
|
|
} else {
|
2001-01-03 00:05:15 +00:00
|
|
|
dest->attributes = 0;
|
2019-09-10 14:36:41 +02:00
|
|
|
}
|
2001-01-03 00:05:15 +00:00
|
|
|
|
|
|
|
if (dest->labels > 0 && dest->offsets != NULL) {
|
2021-05-21 15:30:00 +02:00
|
|
|
if (source->offsets != NULL && source->labels != 0) {
|
2014-01-08 16:27:10 -08:00
|
|
|
memmove(dest->offsets, source->offsets, source->labels);
|
2019-09-10 14:36:41 +02:00
|
|
|
} else {
|
2001-12-28 20:59:27 +00:00
|
|
|
set_offsets(dest, dest->offsets, NULL);
|
2019-09-10 14:36:41 +02:00
|
|
|
}
|
2001-01-03 00:05:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_buffer_add(target, dest->length);
|
2019-09-10 14:36:41 +02:00
|
|
|
}
|
|
|
|
|
2015-08-25 14:46:06 +10:00
|
|
|
/*
|
|
|
|
* Service Discovery Prefixes RFC 6763.
|
|
|
|
*/
|
2020-02-12 13:59:18 +01:00
|
|
|
static unsigned char b_dns_sd_udp_data[] = "\001b\007_dns-sd\004_udp";
|
2015-08-25 14:46:06 +10:00
|
|
|
static unsigned char b_dns_sd_udp_offsets[] = { 0, 2, 10 };
|
2020-02-12 13:59:18 +01:00
|
|
|
static unsigned char db_dns_sd_udp_data[] = "\002db\007_dns-sd\004_udp";
|
2015-08-25 14:46:06 +10:00
|
|
|
static unsigned char db_dns_sd_udp_offsets[] = { 0, 3, 11 };
|
2020-02-12 13:59:18 +01:00
|
|
|
static unsigned char r_dns_sd_udp_data[] = "\001r\007_dns-sd\004_udp";
|
2015-08-25 14:46:06 +10:00
|
|
|
static unsigned char r_dns_sd_udp_offsets[] = { 0, 2, 10 };
|
2020-02-12 13:59:18 +01:00
|
|
|
static unsigned char dr_dns_sd_udp_data[] = "\002dr\007_dns-sd\004_udp";
|
2015-08-25 14:46:06 +10:00
|
|
|
static unsigned char dr_dns_sd_udp_offsets[] = { 0, 3, 11 };
|
2020-02-12 13:59:18 +01:00
|
|
|
static unsigned char lb_dns_sd_udp_data[] = "\002lb\007_dns-sd\004_udp";
|
2015-08-25 14:46:06 +10:00
|
|
|
static unsigned char lb_dns_sd_udp_offsets[] = { 0, 3, 11 };
|
|
|
|
|
2017-11-13 16:58:12 +11:00
|
|
|
static dns_name_t const dns_sd[] = {
|
2017-11-14 14:48:41 +11:00
|
|
|
DNS_NAME_INITNONABSOLUTE(b_dns_sd_udp_data, b_dns_sd_udp_offsets),
|
2017-11-13 16:58:12 +11:00
|
|
|
DNS_NAME_INITNONABSOLUTE(db_dns_sd_udp_data, db_dns_sd_udp_offsets),
|
|
|
|
DNS_NAME_INITNONABSOLUTE(r_dns_sd_udp_data, r_dns_sd_udp_offsets),
|
|
|
|
DNS_NAME_INITNONABSOLUTE(dr_dns_sd_udp_data, dr_dns_sd_udp_offsets),
|
|
|
|
DNS_NAME_INITNONABSOLUTE(lb_dns_sd_udp_data, lb_dns_sd_udp_offsets)
|
2015-08-25 14:46:06 +10:00
|
|
|
};
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_isdnssd(const dns_name_t *name) {
|
|
|
|
size_t i;
|
2015-08-25 14:46:06 +10:00
|
|
|
dns_name_t prefix;
|
|
|
|
|
|
|
|
if (dns_name_countlabels(name) > 3U) {
|
|
|
|
dns_name_init(&prefix, NULL);
|
|
|
|
dns_name_getlabelsequence(name, 0, 3, &prefix);
|
2020-02-13 18:16:57 +01:00
|
|
|
for (i = 0; i < (sizeof(dns_sd) / sizeof(dns_sd[0])); i++) {
|
|
|
|
if (dns_name_equal(&prefix, &dns_sd[i])) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2020-02-13 18:16:57 +01:00
|
|
|
}
|
|
|
|
}
|
2015-08-25 14:46:06 +10:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2015-08-25 14:46:06 +10:00
|
|
|
}
|
2016-03-08 10:11:23 +11:00
|
|
|
|
|
|
|
static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 };
|
|
|
|
static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 };
|
|
|
|
static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 };
|
|
|
|
|
|
|
|
static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA";
|
|
|
|
|
|
|
|
static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA";
|
|
|
|
static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA";
|
|
|
|
static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA";
|
|
|
|
static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA";
|
|
|
|
static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA";
|
|
|
|
static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA";
|
|
|
|
static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA";
|
|
|
|
static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA";
|
|
|
|
static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA";
|
|
|
|
static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA";
|
|
|
|
static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA";
|
|
|
|
static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA";
|
|
|
|
static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA";
|
|
|
|
static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA";
|
|
|
|
static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA";
|
|
|
|
static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA";
|
|
|
|
|
|
|
|
static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA";
|
|
|
|
|
|
|
|
static dns_name_t const rfc1918names[] = {
|
2017-11-13 16:58:12 +11:00
|
|
|
DNS_NAME_INITABSOLUTE(inaddr10, inaddr10_offsets),
|
|
|
|
DNS_NAME_INITABSOLUTE(inaddr16172, inaddr172_offsets),
|
|
|
|
DNS_NAME_INITABSOLUTE(inaddr17172, inaddr172_offsets),
|
|
|
|
DNS_NAME_INITABSOLUTE(inaddr18172, inaddr172_offsets),
|
|
|
|
DNS_NAME_INITABSOLUTE(inaddr19172, inaddr172_offsets),
|
|
|
|
DNS_NAME_INITABSOLUTE(inaddr20172, inaddr172_offsets),
|
|
|
|
DNS_NAME_INITABSOLUTE(inaddr21172, inaddr172_offsets),
|
|
|
|
DNS_NAME_INITABSOLUTE(inaddr22172, inaddr172_offsets),
|
|
|
|
DNS_NAME_INITABSOLUTE(inaddr23172, inaddr172_offsets),
|
|
|
|
DNS_NAME_INITABSOLUTE(inaddr24172, inaddr172_offsets),
|
|
|
|
DNS_NAME_INITABSOLUTE(inaddr25172, inaddr172_offsets),
|
|
|
|
DNS_NAME_INITABSOLUTE(inaddr26172, inaddr172_offsets),
|
|
|
|
DNS_NAME_INITABSOLUTE(inaddr27172, inaddr172_offsets),
|
|
|
|
DNS_NAME_INITABSOLUTE(inaddr28172, inaddr172_offsets),
|
|
|
|
DNS_NAME_INITABSOLUTE(inaddr29172, inaddr172_offsets),
|
|
|
|
DNS_NAME_INITABSOLUTE(inaddr30172, inaddr172_offsets),
|
|
|
|
DNS_NAME_INITABSOLUTE(inaddr31172, inaddr172_offsets),
|
|
|
|
DNS_NAME_INITABSOLUTE(inaddr168192, inaddr192_offsets)
|
2016-03-08 10:11:23 +11:00
|
|
|
};
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_isrfc1918(const dns_name_t *name) {
|
2016-03-08 10:11:23 +11:00
|
|
|
size_t i;
|
|
|
|
|
2020-02-13 18:16:57 +01:00
|
|
|
for (i = 0; i < (sizeof(rfc1918names) / sizeof(*rfc1918names)); i++) {
|
|
|
|
if (dns_name_issubdomain(name, &rfc1918names[i])) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2020-02-13 18:16:57 +01:00
|
|
|
}
|
|
|
|
}
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2016-03-08 10:11:23 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned char ulaoffsets[] = { 0, 2, 4, 8, 13 };
|
|
|
|
static unsigned char ip6fc[] = "\001c\001f\003ip6\004ARPA";
|
|
|
|
static unsigned char ip6fd[] = "\001d\001f\003ip6\004ARPA";
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
static dns_name_t const ulanames[] = { DNS_NAME_INITABSOLUTE(ip6fc, ulaoffsets),
|
|
|
|
DNS_NAME_INITABSOLUTE(ip6fd,
|
|
|
|
ulaoffsets) };
|
2016-03-08 10:11:23 +11:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_isula(const dns_name_t *name) {
|
2016-03-08 10:11:23 +11:00
|
|
|
size_t i;
|
|
|
|
|
2020-02-13 18:16:57 +01:00
|
|
|
for (i = 0; i < (sizeof(ulanames) / sizeof(*ulanames)); i++) {
|
|
|
|
if (dns_name_issubdomain(name, &ulanames[i])) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2020-02-13 18:16:57 +01:00
|
|
|
}
|
|
|
|
}
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2016-03-08 10:11:23 +11:00
|
|
|
}
|
2017-09-28 16:40:45 +10:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Use a simple table as we don't want all the locale stuff
|
|
|
|
* associated with ishexdigit().
|
|
|
|
*/
|
2020-02-12 13:59:18 +01:00
|
|
|
const char ishex[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
2017-09-28 16:40:45 +10:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_istat(const dns_name_t *name) {
|
|
|
|
unsigned char len;
|
2017-09-28 16:40:45 +10:00
|
|
|
const unsigned char *ndata;
|
|
|
|
|
|
|
|
REQUIRE(VALID_NAME(name));
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (name->labels < 1) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-09-28 16:40:45 +10:00
|
|
|
|
|
|
|
ndata = name->ndata;
|
|
|
|
len = ndata[0];
|
|
|
|
INSIST(len <= name->length);
|
|
|
|
ndata++;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Is there at least one trust anchor reported and is the
|
2018-07-04 10:19:53 +10:00
|
|
|
* label length consistent with a trust-anchor-telemetry label.
|
2017-09-28 16:40:45 +10:00
|
|
|
*/
|
|
|
|
if ((len < 8) || (len - 3) % 5 != 0) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2017-09-28 16:40:45 +10:00
|
|
|
}
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
if (ndata[0] != '_' || maptolower[ndata[1]] != 't' ||
|
2020-02-13 14:44:37 -08:00
|
|
|
maptolower[ndata[2]] != 'a')
|
|
|
|
{
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2017-09-28 16:40:45 +10:00
|
|
|
}
|
|
|
|
ndata += 3;
|
|
|
|
len -= 3;
|
|
|
|
|
|
|
|
while (len > 0) {
|
|
|
|
INSIST(len >= 5);
|
|
|
|
if (ndata[0] != '-' || !ishex[ndata[1]] || !ishex[ndata[2]] ||
|
2020-02-13 14:44:37 -08:00
|
|
|
!ishex[ndata[3]] || !ishex[ndata[4]])
|
|
|
|
{
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2017-09-28 16:40:45 +10:00
|
|
|
}
|
|
|
|
ndata += 5;
|
|
|
|
len -= 5;
|
|
|
|
}
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2017-09-28 16:40:45 +10:00
|
|
|
}
|