1 1.1 christos /* $NetBSD: name.c,v 1.1 2024/02/18 20:57:32 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1 christos * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 1.1 christos * 6 1.1 christos * SPDX-License-Identifier: MPL-2.0 7 1.1 christos * 8 1.1 christos * This Source Code Form is subject to the terms of the Mozilla Public 9 1.1 christos * License, v. 2.0. If a copy of the MPL was not distributed with this 10 1.1 christos * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 1.1 christos * 12 1.1 christos * See the COPYRIGHT file distributed with this work for additional 13 1.1 christos * information regarding copyright ownership. 14 1.1 christos */ 15 1.1 christos 16 1.1 christos /*! \file */ 17 1.1 christos 18 1.1 christos #include <ctype.h> 19 1.1 christos #include <inttypes.h> 20 1.1 christos #include <stdbool.h> 21 1.1 christos #include <stdlib.h> 22 1.1 christos 23 1.1 christos #include <isc/buffer.h> 24 1.1 christos #include <isc/hash.h> 25 1.1 christos #include <isc/mem.h> 26 1.1 christos #include <isc/once.h> 27 1.1 christos #include <isc/print.h> 28 1.1 christos #include <isc/random.h> 29 1.1 christos #include <isc/string.h> 30 1.1 christos #include <isc/thread.h> 31 1.1 christos #include <isc/util.h> 32 1.1 christos 33 1.1 christos #include <dns/compress.h> 34 1.1 christos #include <dns/fixedname.h> 35 1.1 christos #include <dns/name.h> 36 1.1 christos #include <dns/result.h> 37 1.1 christos 38 1.1 christos #define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC) 39 1.1 christos 40 1.1 christos typedef enum { 41 1.1 christos ft_init = 0, 42 1.1 christos ft_start, 43 1.1 christos ft_ordinary, 44 1.1 christos ft_initialescape, 45 1.1 christos ft_escape, 46 1.1 christos ft_escdecimal, 47 1.1 christos ft_at 48 1.1 christos } ft_state; 49 1.1 christos 50 1.1 christos typedef enum { fw_start = 0, fw_ordinary, fw_newcurrent } fw_state; 51 1.1 christos 52 1.1 christos static char digitvalue[256] = { 53 1.1 christos -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/ 54 1.1 christos -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/ 55 1.1 christos -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/ 56 1.1 christos 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/ 57 1.1 christos -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/ 58 1.1 christos -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/ 59 1.1 christos -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/ 60 1.1 christos -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/ 61 1.1 christos -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62 1.1 christos -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 63 1.1 christos -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 64 1.1 christos -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65 1.1 christos -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 66 1.1 christos -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 67 1.1 christos -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 68 1.1 christos -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/ 69 1.1 christos }; 70 1.1 christos 71 1.1 christos static unsigned char maptolower[] = { 72 1.1 christos 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 73 1.1 christos 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 74 1.1 christos 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 75 1.1 christos 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 76 1.1 christos 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 77 1.1 christos 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 78 1.1 christos 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 79 1.1 christos 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 80 1.1 christos 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 81 1.1 christos 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 82 1.1 christos 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 83 1.1 christos 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 84 1.1 christos 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 85 1.1 christos 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 86 1.1 christos 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 87 1.1 christos 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 88 1.1 christos 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 89 1.1 christos 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 90 1.1 christos 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 91 1.1 christos 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 92 1.1 christos 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 93 1.1 christos 0xfc, 0xfd, 0xfe, 0xff 94 1.1 christos }; 95 1.1 christos 96 1.1 christos #define CONVERTTOASCII(c) 97 1.1 christos #define CONVERTFROMASCII(c) 98 1.1 christos 99 1.1 christos #define INIT_OFFSETS(name, var, default_offsets) \ 100 1.1 christos if ((name)->offsets != NULL) \ 101 1.1 christos var = (name)->offsets; \ 102 1.1 christos else \ 103 1.1 christos var = (default_offsets); 104 1.1 christos 105 1.1 christos #define SETUP_OFFSETS(name, var, default_offsets) \ 106 1.1 christos if ((name)->offsets != NULL) { \ 107 1.1 christos var = (name)->offsets; \ 108 1.1 christos } else { \ 109 1.1 christos var = (default_offsets); \ 110 1.1 christos set_offsets(name, var, NULL); \ 111 1.1 christos } 112 1.1 christos 113 1.1 christos /*% 114 1.1 christos * Note: If additional attributes are added that should not be set for 115 1.1 christos * empty names, MAKE_EMPTY() must be changed so it clears them. 116 1.1 christos */ 117 1.1 christos #define MAKE_EMPTY(name) \ 118 1.1 christos do { \ 119 1.1 christos name->ndata = NULL; \ 120 1.1 christos name->length = 0; \ 121 1.1 christos name->labels = 0; \ 122 1.1 christos name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \ 123 1.1 christos } while (0) 124 1.1 christos 125 1.1 christos /*% 126 1.1 christos * A name is "bindable" if it can be set to point to a new value, i.e. 127 1.1 christos * name->ndata and name->length may be changed. 128 1.1 christos */ 129 1.1 christos #define BINDABLE(name) \ 130 1.1 christos ((name->attributes & \ 131 1.1 christos (DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC)) == 0) 132 1.1 christos 133 1.1 christos /*% 134 1.1 christos * Note that the name data must be a char array, not a string 135 1.1 christos * literal, to avoid compiler warnings about discarding 136 1.1 christos * the const attribute of a string. 137 1.1 christos */ 138 1.1 christos static unsigned char root_ndata[] = { "" }; 139 1.1 christos static unsigned char root_offsets[] = { 0 }; 140 1.1 christos 141 1.1 christos static dns_name_t root = DNS_NAME_INITABSOLUTE(root_ndata, root_offsets); 142 1.1 christos LIBDNS_EXTERNAL_DATA const dns_name_t *dns_rootname = &root; 143 1.1 christos 144 1.1 christos static unsigned char wild_ndata[] = { "\001*" }; 145 1.1 christos static unsigned char wild_offsets[] = { 0 }; 146 1.1 christos 147 1.1 christos static dns_name_t const wild = DNS_NAME_INITNONABSOLUTE(wild_ndata, 148 1.1 christos wild_offsets); 149 1.1 christos 150 1.1 christos LIBDNS_EXTERNAL_DATA const dns_name_t *dns_wildcardname = &wild; 151 1.1 christos 152 1.1 christos /* 153 1.1 christos * dns_name_t to text post-conversion procedure. 154 1.1 christos */ 155 1.1 christos ISC_THREAD_LOCAL dns_name_totextfilter_t *totext_filter_proc = NULL; 156 1.1 christos 157 1.1 christos static void 158 1.1 christos set_offsets(const dns_name_t *name, unsigned char *offsets, 159 1.1 christos dns_name_t *set_name); 160 1.1 christos 161 1.1 christos void 162 1.1 christos dns_name_init(dns_name_t *name, unsigned char *offsets) { 163 1.1 christos /* 164 1.1 christos * Initialize 'name'. 165 1.1 christos */ 166 1.1 christos DNS_NAME_INIT(name, offsets); 167 1.1 christos } 168 1.1 christos 169 1.1 christos void 170 1.1 christos dns_name_reset(dns_name_t *name) { 171 1.1 christos REQUIRE(VALID_NAME(name)); 172 1.1 christos REQUIRE(BINDABLE(name)); 173 1.1 christos 174 1.1 christos DNS_NAME_RESET(name); 175 1.1 christos } 176 1.1 christos 177 1.1 christos void 178 1.1 christos dns_name_invalidate(dns_name_t *name) { 179 1.1 christos /* 180 1.1 christos * Make 'name' invalid. 181 1.1 christos */ 182 1.1 christos 183 1.1 christos REQUIRE(VALID_NAME(name)); 184 1.1 christos 185 1.1 christos name->magic = 0; 186 1.1 christos name->ndata = NULL; 187 1.1 christos name->length = 0; 188 1.1 christos name->labels = 0; 189 1.1 christos name->attributes = 0; 190 1.1 christos name->offsets = NULL; 191 1.1 christos name->buffer = NULL; 192 1.1 christos ISC_LINK_INIT(name, link); 193 1.1 christos INSIST(name->ht == NULL); 194 1.1 christos } 195 1.1 christos 196 1.1 christos bool 197 1.1 christos dns_name_isvalid(const dns_name_t *name) { 198 1.1 christos unsigned char *ndata, *offsets; 199 1.1 christos unsigned int offset, count, length, nlabels; 200 1.1 christos 201 1.1 christos if (!VALID_NAME(name)) { 202 1.1 christos return (false); 203 1.1 christos } 204 1.1 christos 205 1.1 christos if (name->length > 255U || name->labels > 127U) { 206 1.1 christos return (false); 207 1.1 christos } 208 1.1 christos 209 1.1 christos ndata = name->ndata; 210 1.1 christos length = name->length; 211 1.1 christos offsets = name->offsets; 212 1.1 christos offset = 0; 213 1.1 christos nlabels = 0; 214 1.1 christos 215 1.1 christos while (offset != length) { 216 1.1 christos count = *ndata; 217 1.1 christos if (count > 63U) { 218 1.1 christos return (false); 219 1.1 christos } 220 1.1 christos if (offsets != NULL && offsets[nlabels] != offset) { 221 1.1 christos return (false); 222 1.1 christos } 223 1.1 christos 224 1.1 christos nlabels++; 225 1.1 christos offset += count + 1; 226 1.1 christos ndata += count + 1; 227 1.1 christos if (offset > length) { 228 1.1 christos return (false); 229 1.1 christos } 230 1.1 christos 231 1.1 christos if (count == 0) { 232 1.1 christos break; 233 1.1 christos } 234 1.1 christos } 235 1.1 christos 236 1.1 christos if (nlabels != name->labels || offset != name->length) { 237 1.1 christos return (false); 238 1.1 christos } 239 1.1 christos 240 1.1 christos return (true); 241 1.1 christos } 242 1.1 christos 243 1.1 christos void 244 1.1 christos dns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) { 245 1.1 christos /* 246 1.1 christos * Dedicate a buffer for use with 'name'. 247 1.1 christos */ 248 1.1 christos 249 1.1 christos REQUIRE(VALID_NAME(name)); 250 1.1 christos REQUIRE((buffer != NULL && name->buffer == NULL) || (buffer == NULL)); 251 1.1 christos 252 1.1 christos name->buffer = buffer; 253 1.1 christos } 254 1.1 christos 255 1.1 christos bool 256 1.1 christos dns_name_hasbuffer(const dns_name_t *name) { 257 1.1 christos /* 258 1.1 christos * Does 'name' have a dedicated buffer? 259 1.1 christos */ 260 1.1 christos 261 1.1 christos REQUIRE(VALID_NAME(name)); 262 1.1 christos 263 1.1 christos if (name->buffer != NULL) { 264 1.1 christos return (true); 265 1.1 christos } 266 1.1 christos 267 1.1 christos return (false); 268 1.1 christos } 269 1.1 christos 270 1.1 christos bool 271 1.1 christos dns_name_isabsolute(const dns_name_t *name) { 272 1.1 christos /* 273 1.1 christos * Does 'name' end in the root label? 274 1.1 christos */ 275 1.1 christos 276 1.1 christos REQUIRE(VALID_NAME(name)); 277 1.1 christos 278 1.1 christos if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) { 279 1.1 christos return (true); 280 1.1 christos } 281 1.1 christos return (false); 282 1.1 christos } 283 1.1 christos 284 1.1 christos #define hyphenchar(c) ((c) == 0x2d) 285 1.1 christos #define asterchar(c) ((c) == 0x2a) 286 1.1 christos #define alphachar(c) \ 287 1.1 christos (((c) >= 0x41 && (c) <= 0x5a) || ((c) >= 0x61 && (c) <= 0x7a)) 288 1.1 christos #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39) 289 1.1 christos #define borderchar(c) (alphachar(c) || digitchar(c)) 290 1.1 christos #define middlechar(c) (borderchar(c) || hyphenchar(c)) 291 1.1 christos #define domainchar(c) ((c) > 0x20 && (c) < 0x7f) 292 1.1 christos 293 1.1 christos bool 294 1.1 christos dns_name_ismailbox(const dns_name_t *name) { 295 1.1 christos unsigned char *ndata, ch; 296 1.1 christos unsigned int n; 297 1.1 christos bool first; 298 1.1 christos 299 1.1 christos REQUIRE(VALID_NAME(name)); 300 1.1 christos REQUIRE(name->labels > 0); 301 1.1 christos REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE); 302 1.1 christos 303 1.1 christos /* 304 1.1 christos * Root label. 305 1.1 christos */ 306 1.1 christos if (name->length == 1) { 307 1.1 christos return (true); 308 1.1 christos } 309 1.1 christos 310 1.1 christos ndata = name->ndata; 311 1.1 christos n = *ndata++; 312 1.1 christos INSIST(n <= 63); 313 1.1 christos while (n--) { 314 1.1 christos ch = *ndata++; 315 1.1 christos if (!domainchar(ch)) { 316 1.1 christos return (false); 317 1.1 christos } 318 1.1 christos } 319 1.1 christos 320 1.1 christos if (ndata == name->ndata + name->length) { 321 1.1 christos return (false); 322 1.1 christos } 323 1.1 christos 324 1.1 christos /* 325 1.1 christos * RFC952/RFC1123 hostname. 326 1.1 christos */ 327 1.1 christos while (ndata < (name->ndata + name->length)) { 328 1.1 christos n = *ndata++; 329 1.1 christos INSIST(n <= 63); 330 1.1 christos first = true; 331 1.1 christos while (n--) { 332 1.1 christos ch = *ndata++; 333 1.1 christos if (first || n == 0) { 334 1.1 christos if (!borderchar(ch)) { 335 1.1 christos return (false); 336 1.1 christos } 337 1.1 christos } else { 338 1.1 christos if (!middlechar(ch)) { 339 1.1 christos return (false); 340 1.1 christos } 341 1.1 christos } 342 1.1 christos first = false; 343 1.1 christos } 344 1.1 christos } 345 1.1 christos return (true); 346 1.1 christos } 347 1.1 christos 348 1.1 christos bool 349 1.1 christos dns_name_ishostname(const dns_name_t *name, bool wildcard) { 350 1.1 christos unsigned char *ndata, ch; 351 1.1 christos unsigned int n; 352 1.1 christos bool first; 353 1.1 christos 354 1.1 christos REQUIRE(VALID_NAME(name)); 355 1.1 christos REQUIRE(name->labels > 0); 356 1.1 christos REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE); 357 1.1 christos 358 1.1 christos /* 359 1.1 christos * Root label. 360 1.1 christos */ 361 1.1 christos if (name->length == 1) { 362 1.1 christos return (true); 363 1.1 christos } 364 1.1 christos 365 1.1 christos /* 366 1.1 christos * Skip wildcard if this is a ownername. 367 1.1 christos */ 368 1.1 christos ndata = name->ndata; 369 1.1 christos if (wildcard && ndata[0] == 1 && ndata[1] == '*') { 370 1.1 christos ndata += 2; 371 1.1 christos } 372 1.1 christos 373 1.1 christos /* 374 1.1 christos * RFC292/RFC1123 hostname. 375 1.1 christos */ 376 1.1 christos while (ndata < (name->ndata + name->length)) { 377 1.1 christos n = *ndata++; 378 1.1 christos INSIST(n <= 63); 379 1.1 christos first = true; 380 1.1 christos while (n--) { 381 1.1 christos ch = *ndata++; 382 1.1 christos if (first || n == 0) { 383 1.1 christos if (!borderchar(ch)) { 384 1.1 christos return (false); 385 1.1 christos } 386 1.1 christos } else { 387 1.1 christos if (!middlechar(ch)) { 388 1.1 christos return (false); 389 1.1 christos } 390 1.1 christos } 391 1.1 christos first = false; 392 1.1 christos } 393 1.1 christos } 394 1.1 christos return (true); 395 1.1 christos } 396 1.1 christos 397 1.1 christos bool 398 1.1 christos dns_name_iswildcard(const dns_name_t *name) { 399 1.1 christos unsigned char *ndata; 400 1.1 christos 401 1.1 christos /* 402 1.1 christos * Is 'name' a wildcard name? 403 1.1 christos */ 404 1.1 christos 405 1.1 christos REQUIRE(VALID_NAME(name)); 406 1.1 christos REQUIRE(name->labels > 0); 407 1.1 christos 408 1.1 christos if (name->length >= 2) { 409 1.1 christos ndata = name->ndata; 410 1.1 christos if (ndata[0] == 1 && ndata[1] == '*') { 411 1.1 christos return (true); 412 1.1 christos } 413 1.1 christos } 414 1.1 christos 415 1.1 christos return (false); 416 1.1 christos } 417 1.1 christos 418 1.1 christos bool 419 1.1 christos dns_name_internalwildcard(const dns_name_t *name) { 420 1.1 christos unsigned char *ndata; 421 1.1 christos unsigned int count; 422 1.1 christos unsigned int label; 423 1.1 christos 424 1.1 christos /* 425 1.1 christos * Does 'name' contain a internal wildcard? 426 1.1 christos */ 427 1.1 christos 428 1.1 christos REQUIRE(VALID_NAME(name)); 429 1.1 christos REQUIRE(name->labels > 0); 430 1.1 christos 431 1.1 christos /* 432 1.1 christos * Skip first label. 433 1.1 christos */ 434 1.1 christos ndata = name->ndata; 435 1.1 christos count = *ndata++; 436 1.1 christos INSIST(count <= 63); 437 1.1 christos ndata += count; 438 1.1 christos label = 1; 439 1.1 christos /* 440 1.1 christos * Check all but the last of the remaining labels. 441 1.1 christos */ 442 1.1 christos while (label + 1 < name->labels) { 443 1.1 christos count = *ndata++; 444 1.1 christos INSIST(count <= 63); 445 1.1 christos if (count == 1 && *ndata == '*') { 446 1.1 christos return (true); 447 1.1 christos } 448 1.1 christos ndata += count; 449 1.1 christos label++; 450 1.1 christos } 451 1.1 christos return (false); 452 1.1 christos } 453 1.1 christos 454 1.1 christos unsigned int 455 1.1 christos dns_name_hash(const dns_name_t *name, bool case_sensitive) { 456 1.1 christos unsigned int length; 457 1.1 christos 458 1.1 christos /* 459 1.1 christos * Provide a hash value for 'name'. 460 1.1 christos */ 461 1.1 christos REQUIRE(VALID_NAME(name)); 462 1.1 christos 463 1.1 christos if (name->labels == 0) { 464 1.1 christos return (0); 465 1.1 christos } 466 1.1 christos 467 1.1 christos length = name->length; 468 1.1 christos if (length > 16) { 469 1.1 christos length = 16; 470 1.1 christos } 471 1.1 christos 472 1.1 christos /* High bits are more random. */ 473 1.1 christos return (isc_hash32(name->ndata, length, case_sensitive)); 474 1.1 christos } 475 1.1 christos 476 1.1 christos unsigned int 477 1.1 christos dns_name_fullhash(const dns_name_t *name, bool case_sensitive) { 478 1.1 christos /* 479 1.1 christos * Provide a hash value for 'name'. 480 1.1 christos */ 481 1.1 christos REQUIRE(VALID_NAME(name)); 482 1.1 christos 483 1.1 christos if (name->labels == 0) { 484 1.1 christos return (0); 485 1.1 christos } 486 1.1 christos 487 1.1 christos /* High bits are more random. */ 488 1.1 christos return (isc_hash32(name->ndata, name->length, case_sensitive)); 489 1.1 christos } 490 1.1 christos 491 1.1 christos dns_namereln_t 492 1.1 christos dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2, 493 1.1 christos int *orderp, unsigned int *nlabelsp) { 494 1.1 christos unsigned int l1, l2, l, count1, count2, count, nlabels; 495 1.1 christos int cdiff, ldiff, chdiff; 496 1.1 christos unsigned char *label1, *label2; 497 1.1 christos unsigned char *offsets1, *offsets2; 498 1.1 christos dns_offsets_t odata1, odata2; 499 1.1 christos dns_namereln_t namereln = dns_namereln_none; 500 1.1 christos 501 1.1 christos /* 502 1.1 christos * Determine the relative ordering under the DNSSEC order relation of 503 1.1 christos * 'name1' and 'name2', and also determine the hierarchical 504 1.1 christos * relationship of the names. 505 1.1 christos * 506 1.1 christos * Note: It makes no sense for one of the names to be relative and the 507 1.1 christos * other absolute. If both names are relative, then to be meaningfully 508 1.1 christos * compared the caller must ensure that they are both relative to the 509 1.1 christos * same domain. 510 1.1 christos */ 511 1.1 christos 512 1.1 christos REQUIRE(VALID_NAME(name1)); 513 1.1 christos REQUIRE(VALID_NAME(name2)); 514 1.1 christos REQUIRE(orderp != NULL); 515 1.1 christos REQUIRE(nlabelsp != NULL); 516 1.1 christos /* 517 1.1 christos * Either name1 is absolute and name2 is absolute, or neither is. 518 1.1 christos */ 519 1.1 christos REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) == 520 1.1 christos (name2->attributes & DNS_NAMEATTR_ABSOLUTE)); 521 1.1 christos 522 1.1 christos if (ISC_UNLIKELY(name1 == name2)) { 523 1.1 christos *orderp = 0; 524 1.1 christos *nlabelsp = name1->labels; 525 1.1 christos return (dns_namereln_equal); 526 1.1 christos } 527 1.1 christos 528 1.1 christos SETUP_OFFSETS(name1, offsets1, odata1); 529 1.1 christos SETUP_OFFSETS(name2, offsets2, odata2); 530 1.1 christos 531 1.1 christos nlabels = 0; 532 1.1 christos l1 = name1->labels; 533 1.1 christos l2 = name2->labels; 534 1.1 christos if (l2 > l1) { 535 1.1 christos l = l1; 536 1.1 christos ldiff = 0 - (l2 - l1); 537 1.1 christos } else { 538 1.1 christos l = l2; 539 1.1 christos ldiff = l1 - l2; 540 1.1 christos } 541 1.1 christos 542 1.1 christos offsets1 += l1; 543 1.1 christos offsets2 += l2; 544 1.1 christos 545 1.1 christos while (ISC_LIKELY(l > 0)) { 546 1.1 christos l--; 547 1.1 christos offsets1--; 548 1.1 christos offsets2--; 549 1.1 christos label1 = &name1->ndata[*offsets1]; 550 1.1 christos label2 = &name2->ndata[*offsets2]; 551 1.1 christos count1 = *label1++; 552 1.1 christos count2 = *label2++; 553 1.1 christos 554 1.1 christos /* 555 1.1 christos * We dropped bitstring labels, and we don't support any 556 1.1 christos * other extended label types. 557 1.1 christos */ 558 1.1 christos INSIST(count1 <= 63 && count2 <= 63); 559 1.1 christos 560 1.1 christos cdiff = (int)count1 - (int)count2; 561 1.1 christos if (cdiff < 0) { 562 1.1 christos count = count1; 563 1.1 christos } else { 564 1.1 christos count = count2; 565 1.1 christos } 566 1.1 christos 567 1.1 christos /* Loop unrolled for performance */ 568 1.1 christos while (ISC_LIKELY(count > 3)) { 569 1.1 christos chdiff = (int)maptolower[label1[0]] - 570 1.1 christos (int)maptolower[label2[0]]; 571 1.1 christos if (chdiff != 0) { 572 1.1 christos *orderp = chdiff; 573 1.1 christos goto done; 574 1.1 christos } 575 1.1 christos chdiff = (int)maptolower[label1[1]] - 576 1.1 christos (int)maptolower[label2[1]]; 577 1.1 christos if (chdiff != 0) { 578 1.1 christos *orderp = chdiff; 579 1.1 christos goto done; 580 1.1 christos } 581 1.1 christos chdiff = (int)maptolower[label1[2]] - 582 1.1 christos (int)maptolower[label2[2]]; 583 1.1 christos if (chdiff != 0) { 584 1.1 christos *orderp = chdiff; 585 1.1 christos goto done; 586 1.1 christos } 587 1.1 christos chdiff = (int)maptolower[label1[3]] - 588 1.1 christos (int)maptolower[label2[3]]; 589 1.1 christos if (chdiff != 0) { 590 1.1 christos *orderp = chdiff; 591 1.1 christos goto done; 592 1.1 christos } 593 1.1 christos count -= 4; 594 1.1 christos label1 += 4; 595 1.1 christos label2 += 4; 596 1.1 christos } 597 1.1 christos while (ISC_LIKELY(count-- > 0)) { 598 1.1 christos chdiff = (int)maptolower[*label1++] - 599 1.1 christos (int)maptolower[*label2++]; 600 1.1 christos if (chdiff != 0) { 601 1.1 christos *orderp = chdiff; 602 1.1 christos goto done; 603 1.1 christos } 604 1.1 christos } 605 1.1 christos if (cdiff != 0) { 606 1.1 christos *orderp = cdiff; 607 1.1 christos goto done; 608 1.1 christos } 609 1.1 christos nlabels++; 610 1.1 christos } 611 1.1 christos 612 1.1 christos *orderp = ldiff; 613 1.1 christos if (ldiff < 0) { 614 1.1 christos namereln = dns_namereln_contains; 615 1.1 christos } else if (ldiff > 0) { 616 1.1 christos namereln = dns_namereln_subdomain; 617 1.1 christos } else { 618 1.1 christos namereln = dns_namereln_equal; 619 1.1 christos } 620 1.1 christos *nlabelsp = nlabels; 621 1.1 christos return (namereln); 622 1.1 christos 623 1.1 christos done: 624 1.1 christos *nlabelsp = nlabels; 625 1.1 christos if (nlabels > 0) { 626 1.1 christos namereln = dns_namereln_commonancestor; 627 1.1 christos } 628 1.1 christos 629 1.1 christos return (namereln); 630 1.1 christos } 631 1.1 christos 632 1.1 christos int 633 1.1 christos dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) { 634 1.1 christos int order; 635 1.1 christos unsigned int nlabels; 636 1.1 christos 637 1.1 christos /* 638 1.1 christos * Determine the relative ordering under the DNSSEC order relation of 639 1.1 christos * 'name1' and 'name2'. 640 1.1 christos * 641 1.1 christos * Note: It makes no sense for one of the names to be relative and the 642 1.1 christos * other absolute. If both names are relative, then to be meaningfully 643 1.1 christos * compared the caller must ensure that they are both relative to the 644 1.1 christos * same domain. 645 1.1 christos */ 646 1.1 christos 647 1.1 christos (void)dns_name_fullcompare(name1, name2, &order, &nlabels); 648 1.1 christos 649 1.1 christos return (order); 650 1.1 christos } 651 1.1 christos 652 1.1 christos bool 653 1.1 christos dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) { 654 1.1 christos unsigned int l, count; 655 1.1 christos unsigned char c; 656 1.1 christos unsigned char *label1, *label2; 657 1.1 christos 658 1.1 christos /* 659 1.1 christos * Are 'name1' and 'name2' equal? 660 1.1 christos * 661 1.1 christos * Note: It makes no sense for one of the names to be relative and the 662 1.1 christos * other absolute. If both names are relative, then to be meaningfully 663 1.1 christos * compared the caller must ensure that they are both relative to the 664 1.1 christos * same domain. 665 1.1 christos */ 666 1.1 christos 667 1.1 christos REQUIRE(VALID_NAME(name1)); 668 1.1 christos REQUIRE(VALID_NAME(name2)); 669 1.1 christos /* 670 1.1 christos * Either name1 is absolute and name2 is absolute, or neither is. 671 1.1 christos */ 672 1.1 christos REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) == 673 1.1 christos (name2->attributes & DNS_NAMEATTR_ABSOLUTE)); 674 1.1 christos 675 1.1 christos if (ISC_UNLIKELY(name1 == name2)) { 676 1.1 christos return (true); 677 1.1 christos } 678 1.1 christos 679 1.1 christos if (name1->length != name2->length) { 680 1.1 christos return (false); 681 1.1 christos } 682 1.1 christos 683 1.1 christos l = name1->labels; 684 1.1 christos 685 1.1 christos if (l != name2->labels) { 686 1.1 christos return (false); 687 1.1 christos } 688 1.1 christos 689 1.1 christos label1 = name1->ndata; 690 1.1 christos label2 = name2->ndata; 691 1.1 christos while (ISC_LIKELY(l-- > 0)) { 692 1.1 christos count = *label1++; 693 1.1 christos if (count != *label2++) { 694 1.1 christos return (false); 695 1.1 christos } 696 1.1 christos 697 1.1 christos INSIST(count <= 63); /* no bitstring support */ 698 1.1 christos 699 1.1 christos /* Loop unrolled for performance */ 700 1.1 christos while (ISC_LIKELY(count > 3)) { 701 1.1 christos c = maptolower[label1[0]]; 702 1.1 christos if (c != maptolower[label2[0]]) { 703 1.1 christos return (false); 704 1.1 christos } 705 1.1 christos c = maptolower[label1[1]]; 706 1.1 christos if (c != maptolower[label2[1]]) { 707 1.1 christos return (false); 708 1.1 christos } 709 1.1 christos c = maptolower[label1[2]]; 710 1.1 christos if (c != maptolower[label2[2]]) { 711 1.1 christos return (false); 712 1.1 christos } 713 1.1 christos c = maptolower[label1[3]]; 714 1.1 christos if (c != maptolower[label2[3]]) { 715 1.1 christos return (false); 716 1.1 christos } 717 1.1 christos count -= 4; 718 1.1 christos label1 += 4; 719 1.1 christos label2 += 4; 720 1.1 christos } 721 1.1 christos while (ISC_LIKELY(count-- > 0)) { 722 1.1 christos c = maptolower[*label1++]; 723 1.1 christos if (c != maptolower[*label2++]) { 724 1.1 christos return (false); 725 1.1 christos } 726 1.1 christos } 727 1.1 christos } 728 1.1 christos 729 1.1 christos return (true); 730 1.1 christos } 731 1.1 christos 732 1.1 christos bool 733 1.1 christos dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) { 734 1.1 christos /* 735 1.1 christos * Are 'name1' and 'name2' equal? 736 1.1 christos * 737 1.1 christos * Note: It makes no sense for one of the names to be relative and the 738 1.1 christos * other absolute. If both names are relative, then to be meaningfully 739 1.1 christos * compared the caller must ensure that they are both relative to the 740 1.1 christos * same domain. 741 1.1 christos */ 742 1.1 christos 743 1.1 christos REQUIRE(VALID_NAME(name1)); 744 1.1 christos REQUIRE(VALID_NAME(name2)); 745 1.1 christos /* 746 1.1 christos * Either name1 is absolute and name2 is absolute, or neither is. 747 1.1 christos */ 748 1.1 christos REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) == 749 1.1 christos (name2->attributes & DNS_NAMEATTR_ABSOLUTE)); 750 1.1 christos 751 1.1 christos if (name1->length != name2->length) { 752 1.1 christos return (false); 753 1.1 christos } 754 1.1 christos 755 1.1 christos if (memcmp(name1->ndata, name2->ndata, name1->length) != 0) { 756 1.1 christos return (false); 757 1.1 christos } 758 1.1 christos 759 1.1 christos return (true); 760 1.1 christos } 761 1.1 christos 762 1.1 christos int 763 1.1 christos dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) { 764 1.1 christos unsigned int l1, l2, l, count1, count2, count; 765 1.1 christos unsigned char c1, c2; 766 1.1 christos unsigned char *label1, *label2; 767 1.1 christos 768 1.1 christos /* 769 1.1 christos * Compare two absolute names as rdata. 770 1.1 christos */ 771 1.1 christos 772 1.1 christos REQUIRE(VALID_NAME(name1)); 773 1.1 christos REQUIRE(name1->labels > 0); 774 1.1 christos REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0); 775 1.1 christos REQUIRE(VALID_NAME(name2)); 776 1.1 christos REQUIRE(name2->labels > 0); 777 1.1 christos REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0); 778 1.1 christos 779 1.1 christos l1 = name1->labels; 780 1.1 christos l2 = name2->labels; 781 1.1 christos 782 1.1 christos l = (l1 < l2) ? l1 : l2; 783 1.1 christos 784 1.1 christos label1 = name1->ndata; 785 1.1 christos label2 = name2->ndata; 786 1.1 christos while (l > 0) { 787 1.1 christos l--; 788 1.1 christos count1 = *label1++; 789 1.1 christos count2 = *label2++; 790 1.1 christos 791 1.1 christos /* no bitstring support */ 792 1.1 christos INSIST(count1 <= 63 && count2 <= 63); 793 1.1 christos 794 1.1 christos if (count1 != count2) { 795 1.1 christos return ((count1 < count2) ? -1 : 1); 796 1.1 christos } 797 1.1 christos count = count1; 798 1.1 christos while (count > 0) { 799 1.1 christos count--; 800 1.1 christos c1 = maptolower[*label1++]; 801 1.1 christos c2 = maptolower[*label2++]; 802 1.1 christos if (c1 < c2) { 803 1.1 christos return (-1); 804 1.1 christos } else if (c1 > c2) { 805 1.1 christos return (1); 806 1.1 christos } 807 1.1 christos } 808 1.1 christos } 809 1.1 christos 810 1.1 christos /* 811 1.1 christos * If one name had more labels than the other, their common 812 1.1 christos * prefix must have been different because the shorter name 813 1.1 christos * ended with the root label and the longer one can't have 814 1.1 christos * a root label in the middle of it. Therefore, if we get 815 1.1 christos * to this point, the lengths must be equal. 816 1.1 christos */ 817 1.1 christos INSIST(l1 == l2); 818 1.1 christos 819 1.1 christos return (0); 820 1.1 christos } 821 1.1 christos 822 1.1 christos bool 823 1.1 christos dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) { 824 1.1 christos int order; 825 1.1 christos unsigned int nlabels; 826 1.1 christos dns_namereln_t namereln; 827 1.1 christos 828 1.1 christos /* 829 1.1 christos * Is 'name1' a subdomain of 'name2'? 830 1.1 christos * 831 1.1 christos * Note: It makes no sense for one of the names to be relative and the 832 1.1 christos * other absolute. If both names are relative, then to be meaningfully 833 1.1 christos * compared the caller must ensure that they are both relative to the 834 1.1 christos * same domain. 835 1.1 christos */ 836 1.1 christos 837 1.1 christos namereln = dns_name_fullcompare(name1, name2, &order, &nlabels); 838 1.1 christos if (namereln == dns_namereln_subdomain || 839 1.1 christos namereln == dns_namereln_equal) 840 1.1 christos { 841 1.1 christos return (true); 842 1.1 christos } 843 1.1 christos 844 1.1 christos return (false); 845 1.1 christos } 846 1.1 christos 847 1.1 christos bool 848 1.1 christos dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) { 849 1.1 christos int order; 850 1.1 christos unsigned int nlabels, labels; 851 1.1 christos dns_name_t tname; 852 1.1 christos 853 1.1 christos REQUIRE(VALID_NAME(name)); 854 1.1 christos REQUIRE(name->labels > 0); 855 1.1 christos REQUIRE(VALID_NAME(wname)); 856 1.1 christos labels = wname->labels; 857 1.1 christos REQUIRE(labels > 0); 858 1.1 christos REQUIRE(dns_name_iswildcard(wname)); 859 1.1 christos 860 1.1 christos DNS_NAME_INIT(&tname, NULL); 861 1.1 christos dns_name_getlabelsequence(wname, 1, labels - 1, &tname); 862 1.1 christos if (dns_name_fullcompare(name, &tname, &order, &nlabels) == 863 1.1 christos dns_namereln_subdomain) 864 1.1 christos { 865 1.1 christos return (true); 866 1.1 christos } 867 1.1 christos return (false); 868 1.1 christos } 869 1.1 christos 870 1.1 christos unsigned int 871 1.1 christos dns_name_countlabels(const dns_name_t *name) { 872 1.1 christos /* 873 1.1 christos * How many labels does 'name' have? 874 1.1 christos */ 875 1.1 christos 876 1.1 christos REQUIRE(VALID_NAME(name)); 877 1.1 christos 878 1.1 christos ENSURE(name->labels <= 128); 879 1.1 christos 880 1.1 christos return (name->labels); 881 1.1 christos } 882 1.1 christos 883 1.1 christos void 884 1.1 christos dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) { 885 1.1 christos unsigned char *offsets; 886 1.1 christos dns_offsets_t odata; 887 1.1 christos 888 1.1 christos /* 889 1.1 christos * Make 'label' refer to the 'n'th least significant label of 'name'. 890 1.1 christos */ 891 1.1 christos 892 1.1 christos REQUIRE(VALID_NAME(name)); 893 1.1 christos REQUIRE(name->labels > 0); 894 1.1 christos REQUIRE(n < name->labels); 895 1.1 christos REQUIRE(label != NULL); 896 1.1 christos 897 1.1 christos SETUP_OFFSETS(name, offsets, odata); 898 1.1 christos 899 1.1 christos label->base = &name->ndata[offsets[n]]; 900 1.1 christos if (n == name->labels - 1) { 901 1.1 christos label->length = name->length - offsets[n]; 902 1.1 christos } else { 903 1.1 christos label->length = offsets[n + 1] - offsets[n]; 904 1.1 christos } 905 1.1 christos } 906 1.1 christos 907 1.1 christos void 908 1.1 christos dns_name_getlabelsequence(const dns_name_t *source, unsigned int first, 909 1.1 christos unsigned int n, dns_name_t *target) { 910 1.1 christos unsigned char *p, l; 911 1.1 christos unsigned int firstoffset, endoffset; 912 1.1 christos unsigned int i; 913 1.1 christos 914 1.1 christos /* 915 1.1 christos * Make 'target' refer to the 'n' labels including and following 916 1.1 christos * 'first' in 'source'. 917 1.1 christos */ 918 1.1 christos 919 1.1 christos REQUIRE(VALID_NAME(source)); 920 1.1 christos REQUIRE(VALID_NAME(target)); 921 1.1 christos REQUIRE(first <= source->labels); 922 1.1 christos REQUIRE(n <= source->labels - first); /* note first+n could overflow */ 923 1.1 christos REQUIRE(BINDABLE(target)); 924 1.1 christos 925 1.1 christos p = source->ndata; 926 1.1 christos if (ISC_UNLIKELY(first == source->labels)) { 927 1.1 christos firstoffset = source->length; 928 1.1 christos } else { 929 1.1 christos for (i = 0; i < first; i++) { 930 1.1 christos l = *p; 931 1.1 christos p += l + 1; 932 1.1 christos } 933 1.1 christos firstoffset = (unsigned int)(p - source->ndata); 934 1.1 christos } 935 1.1 christos 936 1.1 christos if (ISC_LIKELY(first + n == source->labels)) { 937 1.1 christos endoffset = source->length; 938 1.1 christos } else { 939 1.1 christos for (i = 0; i < n; i++) { 940 1.1 christos l = *p; 941 1.1 christos p += l + 1; 942 1.1 christos } 943 1.1 christos endoffset = (unsigned int)(p - source->ndata); 944 1.1 christos } 945 1.1 christos 946 1.1 christos target->ndata = &source->ndata[firstoffset]; 947 1.1 christos target->length = endoffset - firstoffset; 948 1.1 christos 949 1.1 christos if (first + n == source->labels && n > 0 && 950 1.1 christos (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 951 1.1 christos { 952 1.1 christos target->attributes |= DNS_NAMEATTR_ABSOLUTE; 953 1.1 christos } else { 954 1.1 christos target->attributes &= ~DNS_NAMEATTR_ABSOLUTE; 955 1.1 christos } 956 1.1 christos 957 1.1 christos target->labels = n; 958 1.1 christos 959 1.1 christos /* 960 1.1 christos * If source and target are the same, and we're making target 961 1.1 christos * a prefix of source, the offsets table is correct already 962 1.1 christos * so we don't need to call set_offsets(). 963 1.1 christos */ 964 1.1 christos if (target->offsets != NULL && (target != source || first != 0)) { 965 1.1 christos set_offsets(target, target->offsets, NULL); 966 1.1 christos } 967 1.1 christos } 968 1.1 christos 969 1.1 christos void 970 1.1 christos dns_name_clone(const dns_name_t *source, dns_name_t *target) { 971 1.1 christos /* 972 1.1 christos * Make 'target' refer to the same name as 'source'. 973 1.1 christos */ 974 1.1 christos 975 1.1 christos REQUIRE(VALID_NAME(source)); 976 1.1 christos REQUIRE(VALID_NAME(target)); 977 1.1 christos REQUIRE(BINDABLE(target)); 978 1.1 christos 979 1.1 christos target->ndata = source->ndata; 980 1.1 christos target->length = source->length; 981 1.1 christos target->labels = source->labels; 982 1.1 christos target->attributes = source->attributes & 983 1.1 christos (unsigned int)~(DNS_NAMEATTR_READONLY | 984 1.1 christos DNS_NAMEATTR_DYNAMIC | 985 1.1 christos DNS_NAMEATTR_DYNOFFSETS); 986 1.1 christos if (target->offsets != NULL && source->labels > 0) { 987 1.1 christos if (source->offsets != NULL) { 988 1.1 christos memmove(target->offsets, source->offsets, 989 1.1 christos source->labels); 990 1.1 christos } else { 991 1.1 christos set_offsets(target, target->offsets, NULL); 992 1.1 christos } 993 1.1 christos } 994 1.1 christos } 995 1.1 christos 996 1.1 christos void 997 1.1 christos dns_name_fromregion(dns_name_t *name, const isc_region_t *r) { 998 1.1 christos unsigned char *offsets; 999 1.1 christos dns_offsets_t odata; 1000 1.1 christos unsigned int len; 1001 1.1 christos isc_region_t r2; 1002 1.1 christos 1003 1.1 christos /* 1004 1.1 christos * Make 'name' refer to region 'r'. 1005 1.1 christos */ 1006 1.1 christos 1007 1.1 christos REQUIRE(VALID_NAME(name)); 1008 1.1 christos REQUIRE(r != NULL); 1009 1.1 christos REQUIRE(BINDABLE(name)); 1010 1.1 christos 1011 1.1 christos INIT_OFFSETS(name, offsets, odata); 1012 1.1 christos 1013 1.1 christos if (name->buffer != NULL) { 1014 1.1 christos isc_buffer_clear(name->buffer); 1015 1.1 christos isc_buffer_availableregion(name->buffer, &r2); 1016 1.1 christos len = (r->length < r2.length) ? r->length : r2.length; 1017 1.1 christos if (len > DNS_NAME_MAXWIRE) { 1018 1.1 christos len = DNS_NAME_MAXWIRE; 1019 1.1 christos } 1020 1.1 christos if (len != 0) { 1021 1.1 christos memmove(r2.base, r->base, len); 1022 1.1 christos } 1023 1.1 christos name->ndata = r2.base; 1024 1.1 christos name->length = len; 1025 1.1 christos } else { 1026 1.1 christos name->ndata = r->base; 1027 1.1 christos name->length = (r->length <= DNS_NAME_MAXWIRE) 1028 1.1 christos ? r->length 1029 1.1 christos : DNS_NAME_MAXWIRE; 1030 1.1 christos } 1031 1.1 christos 1032 1.1 christos if (r->length > 0) { 1033 1.1 christos set_offsets(name, offsets, name); 1034 1.1 christos } else { 1035 1.1 christos name->labels = 0; 1036 1.1 christos name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; 1037 1.1 christos } 1038 1.1 christos 1039 1.1 christos if (name->buffer != NULL) { 1040 1.1 christos isc_buffer_add(name->buffer, name->length); 1041 1.1 christos } 1042 1.1 christos } 1043 1.1 christos 1044 1.1 christos void 1045 1.1 christos dns_name_toregion(const dns_name_t *name, isc_region_t *r) { 1046 1.1 christos /* 1047 1.1 christos * Make 'r' refer to 'name'. 1048 1.1 christos */ 1049 1.1 christos 1050 1.1 christos REQUIRE(VALID_NAME(name)); 1051 1.1 christos REQUIRE(r != NULL); 1052 1.1 christos 1053 1.1 christos DNS_NAME_TOREGION(name, r); 1054 1.1 christos } 1055 1.1 christos 1056 1.1 christos isc_result_t 1057 1.1 christos dns_name_fromtext(dns_name_t *name, isc_buffer_t *source, 1058 1.1 christos const dns_name_t *origin, unsigned int options, 1059 1.1 christos isc_buffer_t *target) { 1060 1.1 christos unsigned char *ndata, *label = NULL; 1061 1.1 christos char *tdata; 1062 1.1 christos char c; 1063 1.1 christos ft_state state; 1064 1.1 christos unsigned int value = 0, count = 0; 1065 1.1 christos unsigned int n1 = 0, n2 = 0; 1066 1.1 christos unsigned int tlen, nrem, nused, digits = 0, labels, tused; 1067 1.1 christos bool done; 1068 1.1 christos unsigned char *offsets; 1069 1.1 christos dns_offsets_t odata; 1070 1.1 christos bool downcase; 1071 1.1 christos 1072 1.1 christos /* 1073 1.1 christos * Convert the textual representation of a DNS name at source 1074 1.1 christos * into uncompressed wire form stored in target. 1075 1.1 christos * 1076 1.1 christos * Notes: 1077 1.1 christos * Relative domain names will have 'origin' appended to them 1078 1.1 christos * unless 'origin' is NULL, in which case relative domain names 1079 1.1 christos * will remain relative. 1080 1.1 christos */ 1081 1.1 christos 1082 1.1 christos REQUIRE(VALID_NAME(name)); 1083 1.1 christos REQUIRE(ISC_BUFFER_VALID(source)); 1084 1.1 christos REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) || 1085 1.1 christos (target == NULL && ISC_BUFFER_VALID(name->buffer))); 1086 1.1 christos 1087 1.1 christos downcase = ((options & DNS_NAME_DOWNCASE) != 0); 1088 1.1 christos 1089 1.1 christos if (target == NULL && name->buffer != NULL) { 1090 1.1 christos target = name->buffer; 1091 1.1 christos isc_buffer_clear(target); 1092 1.1 christos } 1093 1.1 christos 1094 1.1 christos REQUIRE(BINDABLE(name)); 1095 1.1 christos 1096 1.1 christos INIT_OFFSETS(name, offsets, odata); 1097 1.1 christos offsets[0] = 0; 1098 1.1 christos 1099 1.1 christos /* 1100 1.1 christos * Make 'name' empty in case of failure. 1101 1.1 christos */ 1102 1.1 christos MAKE_EMPTY(name); 1103 1.1 christos 1104 1.1 christos /* 1105 1.1 christos * Set up the state machine. 1106 1.1 christos */ 1107 1.1 christos tdata = (char *)source->base + source->current; 1108 1.1 christos tlen = isc_buffer_remaininglength(source); 1109 1.1 christos tused = 0; 1110 1.1 christos ndata = isc_buffer_used(target); 1111 1.1 christos nrem = isc_buffer_availablelength(target); 1112 1.1 christos if (nrem > 255) { 1113 1.1 christos nrem = 255; 1114 1.1 christos } 1115 1.1 christos nused = 0; 1116 1.1 christos labels = 0; 1117 1.1 christos done = false; 1118 1.1 christos state = ft_init; 1119 1.1 christos 1120 1.1 christos while (nrem > 0 && tlen > 0 && !done) { 1121 1.1 christos c = *tdata++; 1122 1.1 christos tlen--; 1123 1.1 christos tused++; 1124 1.1 christos 1125 1.1 christos switch (state) { 1126 1.1 christos case ft_init: 1127 1.1 christos /* 1128 1.1 christos * Is this the root name? 1129 1.1 christos */ 1130 1.1 christos if (c == '.') { 1131 1.1 christos if (tlen != 0) { 1132 1.1 christos return (DNS_R_EMPTYLABEL); 1133 1.1 christos } 1134 1.1 christos labels++; 1135 1.1 christos *ndata++ = 0; 1136 1.1 christos nrem--; 1137 1.1 christos nused++; 1138 1.1 christos done = true; 1139 1.1 christos break; 1140 1.1 christos } 1141 1.1 christos if (c == '@' && tlen == 0) { 1142 1.1 christos state = ft_at; 1143 1.1 christos break; 1144 1.1 christos } 1145 1.1 christos 1146 1.1 christos FALLTHROUGH; 1147 1.1 christos case ft_start: 1148 1.1 christos label = ndata; 1149 1.1 christos ndata++; 1150 1.1 christos nrem--; 1151 1.1 christos nused++; 1152 1.1 christos count = 0; 1153 1.1 christos if (c == '\\') { 1154 1.1 christos state = ft_initialescape; 1155 1.1 christos break; 1156 1.1 christos } 1157 1.1 christos state = ft_ordinary; 1158 1.1 christos if (nrem == 0) { 1159 1.1 christos return (ISC_R_NOSPACE); 1160 1.1 christos } 1161 1.1 christos FALLTHROUGH; 1162 1.1 christos case ft_ordinary: 1163 1.1 christos if (c == '.') { 1164 1.1 christos if (count == 0) { 1165 1.1 christos return (DNS_R_EMPTYLABEL); 1166 1.1 christos } 1167 1.1 christos *label = count; 1168 1.1 christos labels++; 1169 1.1 christos INSIST(labels <= 127); 1170 1.1 christos offsets[labels] = nused; 1171 1.1 christos if (tlen == 0) { 1172 1.1 christos labels++; 1173 1.1 christos *ndata++ = 0; 1174 1.1 christos nrem--; 1175 1.1 christos nused++; 1176 1.1 christos done = true; 1177 1.1 christos } 1178 1.1 christos state = ft_start; 1179 1.1 christos } else if (c == '\\') { 1180 1.1 christos state = ft_escape; 1181 1.1 christos } else { 1182 1.1 christos if (count >= 63) { 1183 1.1 christos return (DNS_R_LABELTOOLONG); 1184 1.1 christos } 1185 1.1 christos count++; 1186 1.1 christos CONVERTTOASCII(c); 1187 1.1 christos if (downcase) { 1188 1.1 christos c = maptolower[c & 0xff]; 1189 1.1 christos } 1190 1.1 christos *ndata++ = c; 1191 1.1 christos nrem--; 1192 1.1 christos nused++; 1193 1.1 christos } 1194 1.1 christos break; 1195 1.1 christos case ft_initialescape: 1196 1.1 christos if (c == '[') { 1197 1.1 christos /* 1198 1.1 christos * This looks like a bitstring label, which 1199 1.1 christos * was deprecated. Intentionally drop it. 1200 1.1 christos */ 1201 1.1 christos return (DNS_R_BADLABELTYPE); 1202 1.1 christos } 1203 1.1 christos state = ft_escape; 1204 1.1 christos POST(state); 1205 1.1 christos FALLTHROUGH; 1206 1.1 christos case ft_escape: 1207 1.1 christos if (!isdigit((unsigned char)c)) { 1208 1.1 christos if (count >= 63) { 1209 1.1 christos return (DNS_R_LABELTOOLONG); 1210 1.1 christos } 1211 1.1 christos count++; 1212 1.1 christos CONVERTTOASCII(c); 1213 1.1 christos if (downcase) { 1214 1.1 christos c = maptolower[c & 0xff]; 1215 1.1 christos } 1216 1.1 christos *ndata++ = c; 1217 1.1 christos nrem--; 1218 1.1 christos nused++; 1219 1.1 christos state = ft_ordinary; 1220 1.1 christos break; 1221 1.1 christos } 1222 1.1 christos digits = 0; 1223 1.1 christos value = 0; 1224 1.1 christos state = ft_escdecimal; 1225 1.1 christos FALLTHROUGH; 1226 1.1 christos case ft_escdecimal: 1227 1.1 christos if (!isdigit((unsigned char)c)) { 1228 1.1 christos return (DNS_R_BADESCAPE); 1229 1.1 christos } 1230 1.1 christos value *= 10; 1231 1.1 christos value += digitvalue[c & 0xff]; 1232 1.1 christos digits++; 1233 1.1 christos if (digits == 3) { 1234 1.1 christos if (value > 255) { 1235 1.1 christos return (DNS_R_BADESCAPE); 1236 1.1 christos } 1237 1.1 christos if (count >= 63) { 1238 1.1 christos return (DNS_R_LABELTOOLONG); 1239 1.1 christos } 1240 1.1 christos count++; 1241 1.1 christos if (downcase) { 1242 1.1 christos value = maptolower[value]; 1243 1.1 christos } 1244 1.1 christos *ndata++ = value; 1245 1.1 christos nrem--; 1246 1.1 christos nused++; 1247 1.1 christos state = ft_ordinary; 1248 1.1 christos } 1249 1.1 christos break; 1250 1.1 christos default: 1251 1.1 christos FATAL_ERROR(__FILE__, __LINE__, "Unexpected state %d", 1252 1.1 christos state); 1253 1.1 christos /* Does not return. */ 1254 1.1 christos } 1255 1.1 christos } 1256 1.1 christos 1257 1.1 christos if (!done) { 1258 1.1 christos if (nrem == 0) { 1259 1.1 christos return (ISC_R_NOSPACE); 1260 1.1 christos } 1261 1.1 christos INSIST(tlen == 0); 1262 1.1 christos if (state != ft_ordinary && state != ft_at) { 1263 1.1 christos return (ISC_R_UNEXPECTEDEND); 1264 1.1 christos } 1265 1.1 christos if (state == ft_ordinary) { 1266 1.1 christos INSIST(count != 0); 1267 1.1 christos INSIST(label != NULL); 1268 1.1 christos *label = count; 1269 1.1 christos labels++; 1270 1.1 christos INSIST(labels <= 127); 1271 1.1 christos offsets[labels] = nused; 1272 1.1 christos } 1273 1.1 christos if (origin != NULL) { 1274 1.1 christos if (nrem < origin->length) { 1275 1.1 christos return (ISC_R_NOSPACE); 1276 1.1 christos } 1277 1.1 christos label = origin->ndata; 1278 1.1 christos n1 = origin->length; 1279 1.1 christos nrem -= n1; 1280 1.1 christos POST(nrem); 1281 1.1 christos while (n1 > 0) { 1282 1.1 christos n2 = *label++; 1283 1.1 christos INSIST(n2 <= 63); /* no bitstring support */ 1284 1.1 christos *ndata++ = n2; 1285 1.1 christos n1 -= n2 + 1; 1286 1.1 christos nused += n2 + 1; 1287 1.1 christos while (n2 > 0) { 1288 1.1 christos c = *label++; 1289 1.1 christos if (downcase) { 1290 1.1 christos c = maptolower[c & 0xff]; 1291 1.1 christos } 1292 1.1 christos *ndata++ = c; 1293 1.1 christos n2--; 1294 1.1 christos } 1295 1.1 christos labels++; 1296 1.1 christos if (n1 > 0) { 1297 1.1 christos INSIST(labels <= 127); 1298 1.1 christos offsets[labels] = nused; 1299 1.1 christos } 1300 1.1 christos } 1301 1.1 christos if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) { 1302 1.1 christos name->attributes |= DNS_NAMEATTR_ABSOLUTE; 1303 1.1 christos } 1304 1.1 christos } 1305 1.1 christos } else { 1306 1.1 christos name->attributes |= DNS_NAMEATTR_ABSOLUTE; 1307 1.1 christos } 1308 1.1 christos 1309 1.1 christos name->ndata = (unsigned char *)target->base + target->used; 1310 1.1 christos name->labels = labels; 1311 1.1 christos name->length = nused; 1312 1.1 christos 1313 1.1 christos isc_buffer_forward(source, tused); 1314 1.1 christos isc_buffer_add(target, name->length); 1315 1.1 christos 1316 1.1 christos return (ISC_R_SUCCESS); 1317 1.1 christos } 1318 1.1 christos 1319 1.1 christos isc_result_t 1320 1.1 christos dns_name_totext(const dns_name_t *name, bool omit_final_dot, 1321 1.1 christos isc_buffer_t *target) { 1322 1.1 christos unsigned int options = DNS_NAME_MASTERFILE; 1323 1.1 christos 1324 1.1 christos if (omit_final_dot) { 1325 1.1 christos options |= DNS_NAME_OMITFINALDOT; 1326 1.1 christos } 1327 1.1 christos return (dns_name_totext2(name, options, target)); 1328 1.1 christos } 1329 1.1 christos 1330 1.1 christos isc_result_t 1331 1.1 christos dns_name_toprincipal(const dns_name_t *name, isc_buffer_t *target) { 1332 1.1 christos return (dns_name_totext2(name, DNS_NAME_OMITFINALDOT, target)); 1333 1.1 christos } 1334 1.1 christos 1335 1.1 christos isc_result_t 1336 1.1 christos dns_name_totext2(const dns_name_t *name, unsigned int options, 1337 1.1 christos isc_buffer_t *target) { 1338 1.1 christos unsigned char *ndata; 1339 1.1 christos char *tdata; 1340 1.1 christos unsigned int nlen, tlen; 1341 1.1 christos unsigned char c; 1342 1.1 christos unsigned int trem, count; 1343 1.1 christos unsigned int labels; 1344 1.1 christos bool saw_root = false; 1345 1.1 christos unsigned int oused; 1346 1.1 christos bool omit_final_dot = ((options & DNS_NAME_OMITFINALDOT) != 0); 1347 1.1 christos 1348 1.1 christos /* 1349 1.1 christos * This function assumes the name is in proper uncompressed 1350 1.1 christos * wire format. 1351 1.1 christos */ 1352 1.1 christos REQUIRE(VALID_NAME(name)); 1353 1.1 christos REQUIRE(ISC_BUFFER_VALID(target)); 1354 1.1 christos 1355 1.1 christos oused = target->used; 1356 1.1 christos 1357 1.1 christos ndata = name->ndata; 1358 1.1 christos nlen = name->length; 1359 1.1 christos labels = name->labels; 1360 1.1 christos tdata = isc_buffer_used(target); 1361 1.1 christos tlen = isc_buffer_availablelength(target); 1362 1.1 christos 1363 1.1 christos trem = tlen; 1364 1.1 christos 1365 1.1 christos if (labels == 0 && nlen == 0) { 1366 1.1 christos /* 1367 1.1 christos * Special handling for an empty name. 1368 1.1 christos */ 1369 1.1 christos if (trem == 0) { 1370 1.1 christos return (ISC_R_NOSPACE); 1371 1.1 christos } 1372 1.1 christos 1373 1.1 christos /* 1374 1.1 christos * The names of these booleans are misleading in this case. 1375 1.1 christos * This empty name is not necessarily from the root node of 1376 1.1 christos * the DNS root zone, nor is a final dot going to be included. 1377 1.1 christos * They need to be set this way, though, to keep the "@" 1378 1.1 christos * from being trounced. 1379 1.1 christos */ 1380 1.1 christos saw_root = true; 1381 1.1 christos omit_final_dot = false; 1382 1.1 christos *tdata++ = '@'; 1383 1.1 christos trem--; 1384 1.1 christos 1385 1.1 christos /* 1386 1.1 christos * Skip the while() loop. 1387 1.1 christos */ 1388 1.1 christos nlen = 0; 1389 1.1 christos } else if (nlen == 1 && labels == 1 && *ndata == '\0') { 1390 1.1 christos /* 1391 1.1 christos * Special handling for the root label. 1392 1.1 christos */ 1393 1.1 christos if (trem == 0) { 1394 1.1 christos return (ISC_R_NOSPACE); 1395 1.1 christos } 1396 1.1 christos 1397 1.1 christos saw_root = true; 1398 1.1 christos omit_final_dot = false; 1399 1.1 christos *tdata++ = '.'; 1400 1.1 christos trem--; 1401 1.1 christos 1402 1.1 christos /* 1403 1.1 christos * Skip the while() loop. 1404 1.1 christos */ 1405 1.1 christos nlen = 0; 1406 1.1 christos } 1407 1.1 christos 1408 1.1 christos while (labels > 0 && nlen > 0 && trem > 0) { 1409 1.1 christos labels--; 1410 1.1 christos count = *ndata++; 1411 1.1 christos nlen--; 1412 1.1 christos if (count == 0) { 1413 1.1 christos saw_root = true; 1414 1.1 christos break; 1415 1.1 christos } 1416 1.1 christos if (count < 64) { 1417 1.1 christos INSIST(nlen >= count); 1418 1.1 christos while (count > 0) { 1419 1.1 christos c = *ndata; 1420 1.1 christos switch (c) { 1421 1.1 christos /* Special modifiers in zone files. */ 1422 1.1 christos case 0x40: /* '@' */ 1423 1.1 christos case 0x24: /* '$' */ 1424 1.1 christos if ((options & DNS_NAME_MASTERFILE) == 1425 1.1 christos 0) 1426 1.1 christos { 1427 1.1 christos goto no_escape; 1428 1.1 christos } 1429 1.1 christos FALLTHROUGH; 1430 1.1 christos case 0x22: /* '"' */ 1431 1.1 christos case 0x28: /* '(' */ 1432 1.1 christos case 0x29: /* ')' */ 1433 1.1 christos case 0x2E: /* '.' */ 1434 1.1 christos case 0x3B: /* ';' */ 1435 1.1 christos case 0x5C: /* '\\' */ 1436 1.1 christos if (trem < 2) { 1437 1.1 christos return (ISC_R_NOSPACE); 1438 1.1 christos } 1439 1.1 christos *tdata++ = '\\'; 1440 1.1 christos CONVERTFROMASCII(c); 1441 1.1 christos *tdata++ = c; 1442 1.1 christos ndata++; 1443 1.1 christos trem -= 2; 1444 1.1 christos nlen--; 1445 1.1 christos break; 1446 1.1 christos no_escape: 1447 1.1 christos default: 1448 1.1 christos if (c > 0x20 && c < 0x7f) { 1449 1.1 christos if (trem == 0) { 1450 1.1 christos return (ISC_R_NOSPACE); 1451 1.1 christos } 1452 1.1 christos CONVERTFROMASCII(c); 1453 1.1 christos *tdata++ = c; 1454 1.1 christos ndata++; 1455 1.1 christos trem--; 1456 1.1 christos nlen--; 1457 1.1 christos } else { 1458 1.1 christos if (trem < 4) { 1459 1.1 christos return (ISC_R_NOSPACE); 1460 1.1 christos } 1461 1.1 christos *tdata++ = 0x5c; 1462 1.1 christos *tdata++ = 0x30 + 1463 1.1 christos ((c / 100) % 10); 1464 1.1 christos *tdata++ = 0x30 + 1465 1.1 christos ((c / 10) % 10); 1466 1.1 christos *tdata++ = 0x30 + (c % 10); 1467 1.1 christos trem -= 4; 1468 1.1 christos ndata++; 1469 1.1 christos nlen--; 1470 1.1 christos } 1471 1.1 christos } 1472 1.1 christos count--; 1473 1.1 christos } 1474 1.1 christos } else { 1475 1.1 christos FATAL_ERROR(__FILE__, __LINE__, 1476 1.1 christos "Unexpected label type %02x", count); 1477 1.1 christos UNREACHABLE(); 1478 1.1 christos } 1479 1.1 christos 1480 1.1 christos /* 1481 1.1 christos * The following assumes names are absolute. If not, we 1482 1.1 christos * fix things up later. Note that this means that in some 1483 1.1 christos * cases one more byte of text buffer is required than is 1484 1.1 christos * needed in the final output. 1485 1.1 christos */ 1486 1.1 christos if (trem == 0) { 1487 1.1 christos return (ISC_R_NOSPACE); 1488 1.1 christos } 1489 1.1 christos *tdata++ = '.'; 1490 1.1 christos trem--; 1491 1.1 christos } 1492 1.1 christos 1493 1.1 christos if (nlen != 0 && trem == 0) { 1494 1.1 christos return (ISC_R_NOSPACE); 1495 1.1 christos } 1496 1.1 christos 1497 1.1 christos if (!saw_root || omit_final_dot) { 1498 1.1 christos trem++; 1499 1.1 christos tdata--; 1500 1.1 christos } 1501 1.1 christos if (trem > 0) { 1502 1.1 christos *tdata = 0; 1503 1.1 christos } 1504 1.1 christos isc_buffer_add(target, tlen - trem); 1505 1.1 christos 1506 1.1 christos if (totext_filter_proc != NULL) { 1507 1.1 christos return ((totext_filter_proc)(target, oused)); 1508 1.1 christos } 1509 1.1 christos 1510 1.1 christos return (ISC_R_SUCCESS); 1511 1.1 christos } 1512 1.1 christos 1513 1.1 christos isc_result_t 1514 1.1 christos dns_name_tofilenametext(const dns_name_t *name, bool omit_final_dot, 1515 1.1 christos isc_buffer_t *target) { 1516 1.1 christos unsigned char *ndata; 1517 1.1 christos char *tdata; 1518 1.1 christos unsigned int nlen, tlen; 1519 1.1 christos unsigned char c; 1520 1.1 christos unsigned int trem, count; 1521 1.1 christos unsigned int labels; 1522 1.1 christos 1523 1.1 christos /* 1524 1.1 christos * This function assumes the name is in proper uncompressed 1525 1.1 christos * wire format. 1526 1.1 christos */ 1527 1.1 christos REQUIRE(VALID_NAME(name)); 1528 1.1 christos REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0); 1529 1.1 christos REQUIRE(ISC_BUFFER_VALID(target)); 1530 1.1 christos 1531 1.1 christos ndata = name->ndata; 1532 1.1 christos nlen = name->length; 1533 1.1 christos labels = name->labels; 1534 1.1 christos tdata = isc_buffer_used(target); 1535 1.1 christos tlen = isc_buffer_availablelength(target); 1536 1.1 christos 1537 1.1 christos trem = tlen; 1538 1.1 christos 1539 1.1 christos if (nlen == 1 && labels == 1 && *ndata == '\0') { 1540 1.1 christos /* 1541 1.1 christos * Special handling for the root label. 1542 1.1 christos */ 1543 1.1 christos if (trem == 0) { 1544 1.1 christos return (ISC_R_NOSPACE); 1545 1.1 christos } 1546 1.1 christos 1547 1.1 christos omit_final_dot = false; 1548 1.1 christos *tdata++ = '.'; 1549 1.1 christos trem--; 1550 1.1 christos 1551 1.1 christos /* 1552 1.1 christos * Skip the while() loop. 1553 1.1 christos */ 1554 1.1 christos nlen = 0; 1555 1.1 christos } 1556 1.1 christos 1557 1.1 christos while (labels > 0 && nlen > 0 && trem > 0) { 1558 1.1 christos labels--; 1559 1.1 christos count = *ndata++; 1560 1.1 christos nlen--; 1561 1.1 christos if (count == 0) { 1562 1.1 christos break; 1563 1.1 christos } 1564 1.1 christos if (count < 64) { 1565 1.1 christos INSIST(nlen >= count); 1566 1.1 christos while (count > 0) { 1567 1.1 christos c = *ndata; 1568 1.1 christos if ((c >= 0x30 && c <= 0x39) || /* digit */ 1569 1.1 christos (c >= 0x41 && c <= 0x5A) || /* uppercase */ 1570 1.1 christos (c >= 0x61 && c <= 0x7A) || /* lowercase */ 1571 1.1 christos c == 0x2D || /* hyphen */ 1572 1.1 christos c == 0x5F) /* underscore */ 1573 1.1 christos { 1574 1.1 christos if (trem == 0) { 1575 1.1 christos return (ISC_R_NOSPACE); 1576 1.1 christos } 1577 1.1 christos /* downcase */ 1578 1.1 christos if (c >= 0x41 && c <= 0x5A) { 1579 1.1 christos c += 0x20; 1580 1.1 christos } 1581 1.1 christos CONVERTFROMASCII(c); 1582 1.1 christos *tdata++ = c; 1583 1.1 christos ndata++; 1584 1.1 christos trem--; 1585 1.1 christos nlen--; 1586 1.1 christos } else { 1587 1.1 christos if (trem < 4) { 1588 1.1 christos return (ISC_R_NOSPACE); 1589 1.1 christos } 1590 1.1 christos snprintf(tdata, trem, "%%%02X", c); 1591 1.1 christos tdata += 3; 1592 1.1 christos trem -= 3; 1593 1.1 christos ndata++; 1594 1.1 christos nlen--; 1595 1.1 christos } 1596 1.1 christos count--; 1597 1.1 christos } 1598 1.1 christos } else { 1599 1.1 christos FATAL_ERROR(__FILE__, __LINE__, 1600 1.1 christos "Unexpected label type %02x", count); 1601 1.1 christos UNREACHABLE(); 1602 1.1 christos } 1603 1.1 christos 1604 1.1 christos /* 1605 1.1 christos * The following assumes names are absolute. If not, we 1606 1.1 christos * fix things up later. Note that this means that in some 1607 1.1 christos * cases one more byte of text buffer is required than is 1608 1.1 christos * needed in the final output. 1609 1.1 christos */ 1610 1.1 christos if (trem == 0) { 1611 1.1 christos return (ISC_R_NOSPACE); 1612 1.1 christos } 1613 1.1 christos *tdata++ = '.'; 1614 1.1 christos trem--; 1615 1.1 christos } 1616 1.1 christos 1617 1.1 christos if (nlen != 0 && trem == 0) { 1618 1.1 christos return (ISC_R_NOSPACE); 1619 1.1 christos } 1620 1.1 christos 1621 1.1 christos if (omit_final_dot) { 1622 1.1 christos trem++; 1623 1.1 christos } 1624 1.1 christos 1625 1.1 christos isc_buffer_add(target, tlen - trem); 1626 1.1 christos 1627 1.1 christos return (ISC_R_SUCCESS); 1628 1.1 christos } 1629 1.1 christos 1630 1.1 christos isc_result_t 1631 1.1 christos dns_name_downcase(const dns_name_t *source, dns_name_t *name, 1632 1.1 christos isc_buffer_t *target) { 1633 1.1 christos unsigned char *sndata, *ndata; 1634 1.1 christos unsigned int nlen, count, labels; 1635 1.1 christos isc_buffer_t buffer; 1636 1.1 christos 1637 1.1 christos /* 1638 1.1 christos * Downcase 'source'. 1639 1.1 christos */ 1640 1.1 christos 1641 1.1 christos REQUIRE(VALID_NAME(source)); 1642 1.1 christos REQUIRE(VALID_NAME(name)); 1643 1.1 christos if (source == name) { 1644 1.1 christos REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0); 1645 1.1 christos isc_buffer_init(&buffer, source->ndata, source->length); 1646 1.1 christos target = &buffer; 1647 1.1 christos ndata = source->ndata; 1648 1.1 christos } else { 1649 1.1 christos REQUIRE(BINDABLE(name)); 1650 1.1 christos REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) || 1651 1.1 christos (target == NULL && ISC_BUFFER_VALID(name->buffer))); 1652 1.1 christos if (target == NULL) { 1653 1.1 christos target = name->buffer; 1654 1.1 christos isc_buffer_clear(name->buffer); 1655 1.1 christos } 1656 1.1 christos ndata = (unsigned char *)target->base + target->used; 1657 1.1 christos name->ndata = ndata; 1658 1.1 christos } 1659 1.1 christos 1660 1.1 christos sndata = source->ndata; 1661 1.1 christos nlen = source->length; 1662 1.1 christos labels = source->labels; 1663 1.1 christos 1664 1.1 christos if (nlen > (target->length - target->used)) { 1665 1.1 christos MAKE_EMPTY(name); 1666 1.1 christos return (ISC_R_NOSPACE); 1667 1.1 christos } 1668 1.1 christos 1669 1.1 christos while (labels > 0 && nlen > 0) { 1670 1.1 christos labels--; 1671 1.1 christos count = *sndata++; 1672 1.1 christos *ndata++ = count; 1673 1.1 christos nlen--; 1674 1.1 christos if (count < 64) { 1675 1.1 christos INSIST(nlen >= count); 1676 1.1 christos while (count > 0) { 1677 1.1 christos *ndata++ = maptolower[(*sndata++)]; 1678 1.1 christos nlen--; 1679 1.1 christos count--; 1680 1.1 christos } 1681 1.1 christos } else { 1682 1.1 christos FATAL_ERROR(__FILE__, __LINE__, 1683 1.1 christos "Unexpected label type %02x", count); 1684 1.1 christos /* Does not return. */ 1685 1.1 christos } 1686 1.1 christos } 1687 1.1 christos 1688 1.1 christos if (source != name) { 1689 1.1 christos name->labels = source->labels; 1690 1.1 christos name->length = source->length; 1691 1.1 christos if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) { 1692 1.1 christos name->attributes = DNS_NAMEATTR_ABSOLUTE; 1693 1.1 christos } else { 1694 1.1 christos name->attributes = 0; 1695 1.1 christos } 1696 1.1 christos if (name->labels > 0 && name->offsets != NULL) { 1697 1.1 christos set_offsets(name, name->offsets, NULL); 1698 1.1 christos } 1699 1.1 christos } 1700 1.1 christos 1701 1.1 christos isc_buffer_add(target, name->length); 1702 1.1 christos 1703 1.1 christos return (ISC_R_SUCCESS); 1704 1.1 christos } 1705 1.1 christos 1706 1.1 christos static void 1707 1.1 christos set_offsets(const dns_name_t *name, unsigned char *offsets, 1708 1.1 christos dns_name_t *set_name) { 1709 1.1 christos unsigned int offset, count, length, nlabels; 1710 1.1 christos unsigned char *ndata; 1711 1.1 christos bool absolute; 1712 1.1 christos 1713 1.1 christos ndata = name->ndata; 1714 1.1 christos length = name->length; 1715 1.1 christos offset = 0; 1716 1.1 christos nlabels = 0; 1717 1.1 christos absolute = false; 1718 1.1 christos while (ISC_LIKELY(offset != length)) { 1719 1.1 christos INSIST(nlabels < 128); 1720 1.1 christos offsets[nlabels++] = offset; 1721 1.1 christos count = *ndata; 1722 1.1 christos INSIST(count <= 63); 1723 1.1 christos offset += count + 1; 1724 1.1 christos ndata += count + 1; 1725 1.1 christos INSIST(offset <= length); 1726 1.1 christos if (ISC_UNLIKELY(count == 0)) { 1727 1.1 christos absolute = true; 1728 1.1 christos break; 1729 1.1 christos } 1730 1.1 christos } 1731 1.1 christos if (set_name != NULL) { 1732 1.1 christos INSIST(set_name == name); 1733 1.1 christos 1734 1.1 christos set_name->labels = nlabels; 1735 1.1 christos set_name->length = offset; 1736 1.1 christos if (absolute) { 1737 1.1 christos set_name->attributes |= DNS_NAMEATTR_ABSOLUTE; 1738 1.1 christos } else { 1739 1.1 christos set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; 1740 1.1 christos } 1741 1.1 christos } 1742 1.1 christos INSIST(nlabels == name->labels); 1743 1.1 christos INSIST(offset == name->length); 1744 1.1 christos } 1745 1.1 christos 1746 1.1 christos isc_result_t 1747 1.1 christos dns_name_fromwire(dns_name_t *name, isc_buffer_t *source, 1748 1.1 christos dns_decompress_t *dctx, unsigned int options, 1749 1.1 christos isc_buffer_t *target) { 1750 1.1 christos unsigned char *cdata, *ndata; 1751 1.1 christos unsigned int cused; /* Bytes of compressed name data used */ 1752 1.1 christos unsigned int nused, labels, n, nmax; 1753 1.1 christos unsigned int current, new_current, biggest_pointer; 1754 1.1 christos bool done; 1755 1.1 christos fw_state state = fw_start; 1756 1.1 christos unsigned int c; 1757 1.1 christos unsigned char *offsets; 1758 1.1 christos dns_offsets_t odata; 1759 1.1 christos bool downcase; 1760 1.1 christos bool seen_pointer; 1761 1.1 christos 1762 1.1 christos /* 1763 1.1 christos * Copy the possibly-compressed name at source into target, 1764 1.1 christos * decompressing it. Loop prevention is performed by checking 1765 1.1 christos * the new pointer against biggest_pointer. 1766 1.1 christos */ 1767 1.1 christos 1768 1.1 christos REQUIRE(VALID_NAME(name)); 1769 1.1 christos REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) || 1770 1.1 christos (target == NULL && ISC_BUFFER_VALID(name->buffer))); 1771 1.1 christos 1772 1.1 christos downcase = ((options & DNS_NAME_DOWNCASE) != 0); 1773 1.1 christos 1774 1.1 christos if (target == NULL && name->buffer != NULL) { 1775 1.1 christos target = name->buffer; 1776 1.1 christos isc_buffer_clear(target); 1777 1.1 christos } 1778 1.1 christos 1779 1.1 christos REQUIRE(dctx != NULL); 1780 1.1 christos REQUIRE(BINDABLE(name)); 1781 1.1 christos 1782 1.1 christos INIT_OFFSETS(name, offsets, odata); 1783 1.1 christos 1784 1.1 christos /* 1785 1.1 christos * Make 'name' empty in case of failure. 1786 1.1 christos */ 1787 1.1 christos MAKE_EMPTY(name); 1788 1.1 christos 1789 1.1 christos /* 1790 1.1 christos * Initialize things to make the compiler happy; they're not required. 1791 1.1 christos */ 1792 1.1 christos n = 0; 1793 1.1 christos new_current = 0; 1794 1.1 christos 1795 1.1 christos /* 1796 1.1 christos * Set up. 1797 1.1 christos */ 1798 1.1 christos labels = 0; 1799 1.1 christos done = false; 1800 1.1 christos 1801 1.1 christos ndata = isc_buffer_used(target); 1802 1.1 christos nused = 0; 1803 1.1 christos seen_pointer = false; 1804 1.1 christos 1805 1.1 christos /* 1806 1.1 christos * Find the maximum number of uncompressed target name 1807 1.1 christos * bytes we are willing to generate. This is the smaller 1808 1.1 christos * of the available target buffer length and the 1809 1.1 christos * maximum legal domain name length (255). 1810 1.1 christos */ 1811 1.1 christos nmax = isc_buffer_availablelength(target); 1812 1.1 christos if (nmax > DNS_NAME_MAXWIRE) { 1813 1.1 christos nmax = DNS_NAME_MAXWIRE; 1814 1.1 christos } 1815 1.1 christos 1816 1.1 christos cdata = isc_buffer_current(source); 1817 1.1 christos cused = 0; 1818 1.1 christos 1819 1.1 christos current = source->current; 1820 1.1 christos biggest_pointer = current; 1821 1.1 christos 1822 1.1 christos /* 1823 1.1 christos * Note: The following code is not optimized for speed, but 1824 1.1 christos * rather for correctness. Speed will be addressed in the future. 1825 1.1 christos */ 1826 1.1 christos 1827 1.1 christos while (current < source->active && !done) { 1828 1.1 christos c = *cdata++; 1829 1.1 christos current++; 1830 1.1 christos if (!seen_pointer) { 1831 1.1 christos cused++; 1832 1.1 christos } 1833 1.1 christos 1834 1.1 christos switch (state) { 1835 1.1 christos case fw_start: 1836 1.1 christos if (c < 64) { 1837 1.1 christos offsets[labels] = nused; 1838 1.1 christos labels++; 1839 1.1 christos if (nused + c + 1 > nmax) { 1840 1.1 christos goto full; 1841 1.1 christos } 1842 1.1 christos nused += c + 1; 1843 1.1 christos *ndata++ = c; 1844 1.1 christos if (c == 0) { 1845 1.1 christos done = true; 1846 1.1 christos } 1847 1.1 christos n = c; 1848 1.1 christos state = fw_ordinary; 1849 1.1 christos } else if (c >= 128 && c < 192) { 1850 1.1 christos /* 1851 1.1 christos * 14 bit local compression pointer. 1852 1.1 christos * Local compression is no longer an 1853 1.1 christos * IETF draft. 1854 1.1 christos */ 1855 1.1 christos return (DNS_R_BADLABELTYPE); 1856 1.1 christos } else if (c >= 192) { 1857 1.1 christos /* 1858 1.1 christos * Ordinary 14-bit pointer. 1859 1.1 christos */ 1860 1.1 christos if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) == 1861 1.1 christos 0) 1862 1.1 christos { 1863 1.1 christos return (DNS_R_DISALLOWED); 1864 1.1 christos } 1865 1.1 christos new_current = c & 0x3F; 1866 1.1 christos state = fw_newcurrent; 1867 1.1 christos } else { 1868 1.1 christos return (DNS_R_BADLABELTYPE); 1869 1.1 christos } 1870 1.1 christos break; 1871 1.1 christos case fw_ordinary: 1872 1.1 christos if (downcase) { 1873 1.1 christos c = maptolower[c]; 1874 1.1 christos } 1875 1.1 christos *ndata++ = c; 1876 1.1 christos n--; 1877 1.1 christos if (n == 0) { 1878 1.1 christos state = fw_start; 1879 1.1 christos } 1880 1.1 christos break; 1881 1.1 christos case fw_newcurrent: 1882 1.1 christos new_current *= 256; 1883 1.1 christos new_current += c; 1884 1.1 christos if (new_current >= biggest_pointer) { 1885 1.1 christos return (DNS_R_BADPOINTER); 1886 1.1 christos } 1887 1.1 christos biggest_pointer = new_current; 1888 1.1 christos current = new_current; 1889 1.1 christos cdata = (unsigned char *)source->base + current; 1890 1.1 christos seen_pointer = true; 1891 1.1 christos state = fw_start; 1892 1.1 christos break; 1893 1.1 christos default: 1894 1.1 christos FATAL_ERROR(__FILE__, __LINE__, "Unknown state %d", 1895 1.1 christos state); 1896 1.1 christos /* Does not return. */ 1897 1.1 christos } 1898 1.1 christos } 1899 1.1 christos 1900 1.1 christos if (!done) { 1901 1.1 christos return (ISC_R_UNEXPECTEDEND); 1902 1.1 christos } 1903 1.1 christos 1904 1.1 christos name->ndata = (unsigned char *)target->base + target->used; 1905 1.1 christos name->labels = labels; 1906 1.1 christos name->length = nused; 1907 1.1 christos name->attributes |= DNS_NAMEATTR_ABSOLUTE; 1908 1.1 christos 1909 1.1 christos isc_buffer_forward(source, cused); 1910 1.1 christos isc_buffer_add(target, name->length); 1911 1.1 christos 1912 1.1 christos return (ISC_R_SUCCESS); 1913 1.1 christos 1914 1.1 christos full: 1915 1.1 christos if (nmax == DNS_NAME_MAXWIRE) { 1916 1.1 christos /* 1917 1.1 christos * The name did not fit even though we had a buffer 1918 1.1 christos * big enough to fit a maximum-length name. 1919 1.1 christos */ 1920 1.1 christos return (DNS_R_NAMETOOLONG); 1921 1.1 christos } else { 1922 1.1 christos /* 1923 1.1 christos * The name might fit if only the caller could give us a 1924 1.1 christos * big enough buffer. 1925 1.1 christos */ 1926 1.1 christos return (ISC_R_NOSPACE); 1927 1.1 christos } 1928 1.1 christos } 1929 1.1 christos 1930 1.1 christos isc_result_t 1931 1.1 christos dns_name_towire(const dns_name_t *name, dns_compress_t *cctx, 1932 1.1 christos isc_buffer_t *target) { 1933 1.1 christos return (dns_name_towire2(name, cctx, target, NULL)); 1934 1.1 christos } 1935 1.1 christos 1936 1.1 christos isc_result_t 1937 1.1 christos dns_name_towire2(const dns_name_t *name, dns_compress_t *cctx, 1938 1.1 christos isc_buffer_t *target, uint16_t *comp_offsetp) { 1939 1.1 christos unsigned int methods; 1940 1.1 christos uint16_t offset; 1941 1.1 christos dns_name_t gp; /* Global compression prefix */ 1942 1.1 christos bool gf; /* Global compression target found */ 1943 1.1 christos uint16_t go; /* Global compression offset */ 1944 1.1 christos dns_offsets_t clo; 1945 1.1 christos dns_name_t clname; 1946 1.1 christos 1947 1.1 christos /* 1948 1.1 christos * Convert 'name' into wire format, compressing it as specified by the 1949 1.1 christos * compression context 'cctx', and storing the result in 'target'. 1950 1.1 christos */ 1951 1.1 christos 1952 1.1 christos REQUIRE(VALID_NAME(name)); 1953 1.1 christos REQUIRE(cctx != NULL); 1954 1.1 christos REQUIRE(ISC_BUFFER_VALID(target)); 1955 1.1 christos 1956 1.1 christos /* 1957 1.1 christos * If this exact name was already rendered before, and the 1958 1.1 christos * offset of the previously rendered name is passed to us, write 1959 1.1 christos * a compression pointer directly. 1960 1.1 christos */ 1961 1.1 christos methods = dns_compress_getmethods(cctx); 1962 1.1 christos if (comp_offsetp != NULL && *comp_offsetp < 0x4000 && 1963 1.1 christos (name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 && 1964 1.1 christos (methods & DNS_COMPRESS_GLOBAL14) != 0) 1965 1.1 christos { 1966 1.1 christos if (ISC_UNLIKELY(target->length - target->used < 2)) { 1967 1.1 christos return (ISC_R_NOSPACE); 1968 1.1 christos } 1969 1.1 christos offset = *comp_offsetp; 1970 1.1 christos offset |= 0xc000; 1971 1.1 christos isc_buffer_putuint16(target, offset); 1972 1.1 christos return (ISC_R_SUCCESS); 1973 1.1 christos } 1974 1.1 christos 1975 1.1 christos /* 1976 1.1 christos * If 'name' doesn't have an offsets table, make a clone which 1977 1.1 christos * has one. 1978 1.1 christos */ 1979 1.1 christos if (name->offsets == NULL) { 1980 1.1 christos DNS_NAME_INIT(&clname, clo); 1981 1.1 christos dns_name_clone(name, &clname); 1982 1.1 christos name = &clname; 1983 1.1 christos } 1984 1.1 christos DNS_NAME_INIT(&gp, NULL); 1985 1.1 christos 1986 1.1 christos offset = target->used; /*XXX*/ 1987 1.1 christos 1988 1.1 christos if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 && 1989 1.1 christos (methods & DNS_COMPRESS_GLOBAL14) != 0) 1990 1.1 christos { 1991 1.1 christos gf = dns_compress_findglobal(cctx, name, &gp, &go); 1992 1.1 christos } else { 1993 1.1 christos gf = false; 1994 1.1 christos } 1995 1.1 christos 1996 1.1 christos /* 1997 1.1 christos * If the offset is too high for 14 bit global compression, we're 1998 1.1 christos * out of luck. 1999 1.1 christos */ 2000 1.1 christos if (gf && ISC_UNLIKELY(go >= 0x4000)) { 2001 1.1 christos gf = false; 2002 1.1 christos } 2003 1.1 christos 2004 1.1 christos /* 2005 1.1 christos * Will the compression pointer reduce the message size? 2006 1.1 christos */ 2007 1.1 christos if (gf && (gp.length + 2) >= name->length) { 2008 1.1 christos gf = false; 2009 1.1 christos } 2010 1.1 christos 2011 1.1 christos if (gf) { 2012 1.1 christos if (ISC_UNLIKELY(target->length - target->used < gp.length)) { 2013 1.1 christos return (ISC_R_NOSPACE); 2014 1.1 christos } 2015 1.1 christos if (gp.length != 0) { 2016 1.1 christos unsigned char *base = target->base; 2017 1.1 christos (void)memmove(base + target->used, gp.ndata, 2018 1.1 christos (size_t)gp.length); 2019 1.1 christos } 2020 1.1 christos isc_buffer_add(target, gp.length); 2021 1.1 christos if (ISC_UNLIKELY(target->length - target->used < 2)) { 2022 1.1 christos return (ISC_R_NOSPACE); 2023 1.1 christos } 2024 1.1 christos isc_buffer_putuint16(target, go | 0xc000); 2025 1.1 christos if (gp.length != 0) { 2026 1.1 christos dns_compress_add(cctx, name, &gp, offset); 2027 1.1 christos if (comp_offsetp != NULL) { 2028 1.1 christos *comp_offsetp = offset; 2029 1.1 christos } 2030 1.1 christos } else if (comp_offsetp != NULL) { 2031 1.1 christos *comp_offsetp = go; 2032 1.1 christos } 2033 1.1 christos } else { 2034 1.1 christos if (ISC_UNLIKELY(target->length - target->used < name->length)) 2035 1.1 christos { 2036 1.1 christos return (ISC_R_NOSPACE); 2037 1.1 christos } 2038 1.1 christos if (name->length != 0) { 2039 1.1 christos unsigned char *base = target->base; 2040 1.1 christos (void)memmove(base + target->used, name->ndata, 2041 1.1 christos (size_t)name->length); 2042 1.1 christos } 2043 1.1 christos isc_buffer_add(target, name->length); 2044 1.1 christos dns_compress_add(cctx, name, name, offset); 2045 1.1 christos if (comp_offsetp != NULL) { 2046 1.1 christos *comp_offsetp = offset; 2047 1.1 christos } 2048 1.1 christos } 2049 1.1 christos 2050 1.1 christos return (ISC_R_SUCCESS); 2051 1.1 christos } 2052 1.1 christos 2053 1.1 christos isc_result_t 2054 1.1 christos dns_name_concatenate(const dns_name_t *prefix, const dns_name_t *suffix, 2055 1.1 christos dns_name_t *name, isc_buffer_t *target) { 2056 1.1 christos unsigned char *ndata, *offsets; 2057 1.1 christos unsigned int nrem, labels, prefix_length, length; 2058 1.1 christos bool copy_prefix = true; 2059 1.1 christos bool copy_suffix = true; 2060 1.1 christos bool absolute = false; 2061 1.1 christos dns_name_t tmp_name; 2062 1.1 christos dns_offsets_t odata; 2063 1.1 christos 2064 1.1 christos /* 2065 1.1 christos * Concatenate 'prefix' and 'suffix'. 2066 1.1 christos */ 2067 1.1 christos 2068 1.1 christos REQUIRE(prefix == NULL || VALID_NAME(prefix)); 2069 1.1 christos REQUIRE(suffix == NULL || VALID_NAME(suffix)); 2070 1.1 christos REQUIRE(name == NULL || VALID_NAME(name)); 2071 1.1 christos REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) || 2072 1.1 christos (target == NULL && name != NULL && 2073 1.1 christos ISC_BUFFER_VALID(name->buffer))); 2074 1.1 christos if (prefix == NULL || prefix->labels == 0) { 2075 1.1 christos copy_prefix = false; 2076 1.1 christos } 2077 1.1 christos if (suffix == NULL || suffix->labels == 0) { 2078 1.1 christos copy_suffix = false; 2079 1.1 christos } 2080 1.1 christos if (copy_prefix && (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) { 2081 1.1 christos absolute = true; 2082 1.1 christos REQUIRE(!copy_suffix); 2083 1.1 christos } 2084 1.1 christos if (name == NULL) { 2085 1.1 christos DNS_NAME_INIT(&tmp_name, odata); 2086 1.1 christos name = &tmp_name; 2087 1.1 christos } 2088 1.1 christos if (target == NULL) { 2089 1.1 christos INSIST(name->buffer != NULL); 2090 1.1 christos target = name->buffer; 2091 1.1 christos isc_buffer_clear(name->buffer); 2092 1.1 christos } 2093 1.1 christos 2094 1.1 christos REQUIRE(BINDABLE(name)); 2095 1.1 christos 2096 1.1 christos /* 2097 1.1 christos * Set up. 2098 1.1 christos */ 2099 1.1 christos nrem = target->length - target->used; 2100 1.1 christos ndata = (unsigned char *)target->base + target->used; 2101 1.1 christos if (nrem > DNS_NAME_MAXWIRE) { 2102 1.1 christos nrem = DNS_NAME_MAXWIRE; 2103 1.1 christos } 2104 1.1 christos length = 0; 2105 1.1 christos prefix_length = 0; 2106 1.1 christos labels = 0; 2107 1.1 christos if (copy_prefix) { 2108 1.1 christos prefix_length = prefix->length; 2109 1.1 christos length += prefix_length; 2110 1.1 christos labels += prefix->labels; 2111 1.1 christos } 2112 1.1 christos if (copy_suffix) { 2113 1.1 christos length += suffix->length; 2114 1.1 christos labels += suffix->labels; 2115 1.1 christos } 2116 1.1 christos if (length > DNS_NAME_MAXWIRE) { 2117 1.1 christos MAKE_EMPTY(name); 2118 1.1 christos return (DNS_R_NAMETOOLONG); 2119 1.1 christos } 2120 1.1 christos if (length > nrem) { 2121 1.1 christos MAKE_EMPTY(name); 2122 1.1 christos return (ISC_R_NOSPACE); 2123 1.1 christos } 2124 1.1 christos 2125 1.1 christos if (copy_suffix) { 2126 1.1 christos if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) { 2127 1.1 christos absolute = true; 2128 1.1 christos } 2129 1.1 christos memmove(ndata + prefix_length, suffix->ndata, suffix->length); 2130 1.1 christos } 2131 1.1 christos 2132 1.1 christos /* 2133 1.1 christos * If 'prefix' and 'name' are the same object, and the object has 2134 1.1 christos * a dedicated buffer, and we're using it, then we don't have to 2135 1.1 christos * copy anything. 2136 1.1 christos */ 2137 1.1 christos if (copy_prefix && (prefix != name || prefix->buffer != target)) { 2138 1.1 christos memmove(ndata, prefix->ndata, prefix_length); 2139 1.1 christos } 2140 1.1 christos 2141 1.1 christos name->ndata = ndata; 2142 1.1 christos name->labels = labels; 2143 1.1 christos name->length = length; 2144 1.1 christos if (absolute) { 2145 1.1 christos name->attributes = DNS_NAMEATTR_ABSOLUTE; 2146 1.1 christos } else { 2147 1.1 christos name->attributes = 0; 2148 1.1 christos } 2149 1.1 christos 2150 1.1 christos if (name->labels > 0 && name->offsets != NULL) { 2151 1.1 christos INIT_OFFSETS(name, offsets, odata); 2152 1.1 christos set_offsets(name, offsets, NULL); 2153 1.1 christos } 2154 1.1 christos 2155 1.1 christos isc_buffer_add(target, name->length); 2156 1.1 christos 2157 1.1 christos return (ISC_R_SUCCESS); 2158 1.1 christos } 2159 1.1 christos 2160 1.1 christos void 2161 1.1 christos dns_name_split(const dns_name_t *name, unsigned int suffixlabels, 2162 1.1 christos dns_name_t *prefix, dns_name_t *suffix) 2163 1.1 christos 2164 1.1 christos { 2165 1.1 christos unsigned int splitlabel; 2166 1.1 christos 2167 1.1 christos REQUIRE(VALID_NAME(name)); 2168 1.1 christos REQUIRE(suffixlabels > 0); 2169 1.1 christos REQUIRE(suffixlabels <= name->labels); 2170 1.1 christos REQUIRE(prefix != NULL || suffix != NULL); 2171 1.1 christos REQUIRE(prefix == NULL || (VALID_NAME(prefix) && BINDABLE(prefix))); 2172 1.1 christos REQUIRE(suffix == NULL || (VALID_NAME(suffix) && BINDABLE(suffix))); 2173 1.1 christos 2174 1.1 christos splitlabel = name->labels - suffixlabels; 2175 1.1 christos 2176 1.1 christos if (prefix != NULL) { 2177 1.1 christos dns_name_getlabelsequence(name, 0, splitlabel, prefix); 2178 1.1 christos } 2179 1.1 christos 2180 1.1 christos if (suffix != NULL) { 2181 1.1 christos dns_name_getlabelsequence(name, splitlabel, suffixlabels, 2182 1.1 christos suffix); 2183 1.1 christos } 2184 1.1 christos 2185 1.1 christos return; 2186 1.1 christos } 2187 1.1 christos 2188 1.1 christos void 2189 1.1 christos dns_name_dup(const dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) { 2190 1.1 christos /* 2191 1.1 christos * Make 'target' a dynamically allocated copy of 'source'. 2192 1.1 christos */ 2193 1.1 christos 2194 1.1 christos REQUIRE(VALID_NAME(source)); 2195 1.1 christos REQUIRE(source->length > 0); 2196 1.1 christos REQUIRE(VALID_NAME(target)); 2197 1.1 christos REQUIRE(BINDABLE(target)); 2198 1.1 christos 2199 1.1 christos /* 2200 1.1 christos * Make 'target' empty in case of failure. 2201 1.1 christos */ 2202 1.1 christos MAKE_EMPTY(target); 2203 1.1 christos 2204 1.1 christos target->ndata = isc_mem_get(mctx, source->length); 2205 1.1 christos 2206 1.1 christos memmove(target->ndata, source->ndata, source->length); 2207 1.1 christos 2208 1.1 christos target->length = source->length; 2209 1.1 christos target->labels = source->labels; 2210 1.1 christos target->attributes = DNS_NAMEATTR_DYNAMIC; 2211 1.1 christos if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) { 2212 1.1 christos target->attributes |= DNS_NAMEATTR_ABSOLUTE; 2213 1.1 christos } 2214 1.1 christos if (target->offsets != NULL) { 2215 1.1 christos if (source->offsets != NULL) { 2216 1.1 christos memmove(target->offsets, source->offsets, 2217 1.1 christos source->labels); 2218 1.1 christos } else { 2219 1.1 christos set_offsets(target, target->offsets, NULL); 2220 1.1 christos } 2221 1.1 christos } 2222 1.1 christos } 2223 1.1 christos 2224 1.1 christos isc_result_t 2225 1.1 christos dns_name_dupwithoffsets(const dns_name_t *source, isc_mem_t *mctx, 2226 1.1 christos dns_name_t *target) { 2227 1.1 christos /* 2228 1.1 christos * Make 'target' a read-only dynamically allocated copy of 'source'. 2229 1.1 christos * 'target' will also have a dynamically allocated offsets table. 2230 1.1 christos */ 2231 1.1 christos 2232 1.1 christos REQUIRE(VALID_NAME(source)); 2233 1.1 christos REQUIRE(source->length > 0); 2234 1.1 christos REQUIRE(VALID_NAME(target)); 2235 1.1 christos REQUIRE(BINDABLE(target)); 2236 1.1 christos REQUIRE(target->offsets == NULL); 2237 1.1 christos 2238 1.1 christos /* 2239 1.1 christos * Make 'target' empty in case of failure. 2240 1.1 christos */ 2241 1.1 christos MAKE_EMPTY(target); 2242 1.1 christos 2243 1.1 christos target->ndata = isc_mem_get(mctx, source->length + source->labels); 2244 1.1 christos 2245 1.1 christos memmove(target->ndata, source->ndata, source->length); 2246 1.1 christos 2247 1.1 christos target->length = source->length; 2248 1.1 christos target->labels = source->labels; 2249 1.1 christos target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS | 2250 1.1 christos DNS_NAMEATTR_READONLY; 2251 1.1 christos if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) { 2252 1.1 christos target->attributes |= DNS_NAMEATTR_ABSOLUTE; 2253 1.1 christos } 2254 1.1 christos target->offsets = target->ndata + source->length; 2255 1.1 christos if (source->offsets != NULL) { 2256 1.1 christos memmove(target->offsets, source->offsets, source->labels); 2257 1.1 christos } else { 2258 1.1 christos set_offsets(target, target->offsets, NULL); 2259 1.1 christos } 2260 1.1 christos 2261 1.1 christos return (ISC_R_SUCCESS); 2262 1.1 christos } 2263 1.1 christos 2264 1.1 christos void 2265 1.1 christos dns_name_free(dns_name_t *name, isc_mem_t *mctx) { 2266 1.1 christos size_t size; 2267 1.1 christos 2268 1.1 christos /* 2269 1.1 christos * Free 'name'. 2270 1.1 christos */ 2271 1.1 christos 2272 1.1 christos REQUIRE(VALID_NAME(name)); 2273 1.1 christos REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0); 2274 1.1 christos 2275 1.1 christos size = name->length; 2276 1.1 christos if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0) { 2277 1.1 christos size += name->labels; 2278 1.1 christos } 2279 1.1 christos isc_mem_put(mctx, name->ndata, size); 2280 1.1 christos dns_name_invalidate(name); 2281 1.1 christos } 2282 1.1 christos 2283 1.1 christos isc_result_t 2284 1.1 christos dns_name_digest(const dns_name_t *name, dns_digestfunc_t digest, void *arg) { 2285 1.1 christos dns_name_t downname; 2286 1.1 christos unsigned char data[256]; 2287 1.1 christos isc_buffer_t buffer; 2288 1.1 christos isc_result_t result; 2289 1.1 christos isc_region_t r; 2290 1.1 christos 2291 1.1 christos /* 2292 1.1 christos * Send 'name' in DNSSEC canonical form to 'digest'. 2293 1.1 christos */ 2294 1.1 christos 2295 1.1 christos REQUIRE(VALID_NAME(name)); 2296 1.1 christos REQUIRE(digest != NULL); 2297 1.1 christos 2298 1.1 christos DNS_NAME_INIT(&downname, NULL); 2299 1.1 christos 2300 1.1 christos isc_buffer_init(&buffer, data, sizeof(data)); 2301 1.1 christos 2302 1.1 christos result = dns_name_downcase(name, &downname, &buffer); 2303 1.1 christos if (result != ISC_R_SUCCESS) { 2304 1.1 christos return (result); 2305 1.1 christos } 2306 1.1 christos 2307 1.1 christos isc_buffer_usedregion(&buffer, &r); 2308 1.1 christos 2309 1.1 christos return ((digest)(arg, &r)); 2310 1.1 christos } 2311 1.1 christos 2312 1.1 christos bool 2313 1.1 christos dns_name_dynamic(const dns_name_t *name) { 2314 1.1 christos REQUIRE(VALID_NAME(name)); 2315 1.1 christos 2316 1.1 christos /* 2317 1.1 christos * Returns whether there is dynamic memory associated with this name. 2318 1.1 christos */ 2319 1.1 christos 2320 1.1 christos return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ? true : false); 2321 1.1 christos } 2322 1.1 christos 2323 1.1 christos isc_result_t 2324 1.1 christos dns_name_print(const dns_name_t *name, FILE *stream) { 2325 1.1 christos isc_result_t result; 2326 1.1 christos isc_buffer_t b; 2327 1.1 christos isc_region_t r; 2328 1.1 christos char t[1024]; 2329 1.1 christos 2330 1.1 christos /* 2331 1.1 christos * Print 'name' on 'stream'. 2332 1.1 christos */ 2333 1.1 christos 2334 1.1 christos REQUIRE(VALID_NAME(name)); 2335 1.1 christos 2336 1.1 christos isc_buffer_init(&b, t, sizeof(t)); 2337 1.1 christos result = dns_name_totext(name, false, &b); 2338 1.1 christos if (result != ISC_R_SUCCESS) { 2339 1.1 christos return (result); 2340 1.1 christos } 2341 1.1 christos isc_buffer_usedregion(&b, &r); 2342 1.1 christos fprintf(stream, "%.*s", (int)r.length, (char *)r.base); 2343 1.1 christos 2344 1.1 christos return (ISC_R_SUCCESS); 2345 1.1 christos } 2346 1.1 christos 2347 1.1 christos isc_result_t 2348 1.1 christos dns_name_settotextfilter(dns_name_totextfilter_t *proc) { 2349 1.1 christos /* 2350 1.1 christos * If we already have been here set / clear as appropriate. 2351 1.1 christos */ 2352 1.1 christos if (totext_filter_proc != NULL && proc != NULL) { 2353 1.1 christos if (totext_filter_proc == proc) { 2354 1.1 christos return (ISC_R_SUCCESS); 2355 1.1 christos } 2356 1.1 christos } 2357 1.1 christos if (proc == NULL && totext_filter_proc != NULL) { 2358 1.1 christos totext_filter_proc = NULL; 2359 1.1 christos return (ISC_R_SUCCESS); 2360 1.1 christos } 2361 1.1 christos 2362 1.1 christos totext_filter_proc = proc; 2363 1.1 christos 2364 1.1 christos return (ISC_R_SUCCESS); 2365 1.1 christos } 2366 1.1 christos 2367 1.1 christos void 2368 1.1 christos dns_name_format(const dns_name_t *name, char *cp, unsigned int size) { 2369 1.1 christos isc_result_t result; 2370 1.1 christos isc_buffer_t buf; 2371 1.1 christos 2372 1.1 christos REQUIRE(size > 0); 2373 1.1 christos 2374 1.1 christos /* 2375 1.1 christos * Leave room for null termination after buffer. 2376 1.1 christos */ 2377 1.1 christos isc_buffer_init(&buf, cp, size - 1); 2378 1.1 christos result = dns_name_totext(name, true, &buf); 2379 1.1 christos if (result == ISC_R_SUCCESS) { 2380 1.1 christos isc_buffer_putuint8(&buf, (uint8_t)'\0'); 2381 1.1 christos } else { 2382 1.1 christos snprintf(cp, size, "<unknown>"); 2383 1.1 christos } 2384 1.1 christos } 2385 1.1 christos 2386 1.1 christos /* 2387 1.1 christos * dns_name_tostring() -- similar to dns_name_format() but allocates its own 2388 1.1 christos * memory. 2389 1.1 christos */ 2390 1.1 christos isc_result_t 2391 1.1 christos dns_name_tostring(const dns_name_t *name, char **target, isc_mem_t *mctx) { 2392 1.1 christos isc_result_t result; 2393 1.1 christos isc_buffer_t buf; 2394 1.1 christos isc_region_t reg; 2395 1.1 christos char *p, txt[DNS_NAME_FORMATSIZE]; 2396 1.1 christos 2397 1.1 christos REQUIRE(VALID_NAME(name)); 2398 1.1 christos REQUIRE(target != NULL && *target == NULL); 2399 1.1 christos 2400 1.1 christos isc_buffer_init(&buf, txt, sizeof(txt)); 2401 1.1 christos result = dns_name_totext(name, false, &buf); 2402 1.1 christos if (result != ISC_R_SUCCESS) { 2403 1.1 christos return (result); 2404 1.1 christos } 2405 1.1 christos 2406 1.1 christos isc_buffer_usedregion(&buf, ®); 2407 1.1 christos p = isc_mem_allocate(mctx, reg.length + 1); 2408 1.1 christos memmove(p, (char *)reg.base, (int)reg.length); 2409 1.1 christos p[reg.length] = '\0'; 2410 1.1 christos 2411 1.1 christos *target = p; 2412 1.1 christos return (ISC_R_SUCCESS); 2413 1.1 christos } 2414 1.1 christos 2415 1.1 christos /* 2416 1.1 christos * dns_name_fromstring() -- convert directly from a string to a name, 2417 1.1 christos * allocating memory as needed 2418 1.1 christos */ 2419 1.1 christos isc_result_t 2420 1.1 christos dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options, 2421 1.1 christos isc_mem_t *mctx) { 2422 1.1 christos return (dns_name_fromstring2(target, src, dns_rootname, options, mctx)); 2423 1.1 christos } 2424 1.1 christos 2425 1.1 christos isc_result_t 2426 1.1 christos dns_name_fromstring2(dns_name_t *target, const char *src, 2427 1.1 christos const dns_name_t *origin, unsigned int options, 2428 1.1 christos isc_mem_t *mctx) { 2429 1.1 christos isc_result_t result; 2430 1.1 christos isc_buffer_t buf; 2431 1.1 christos dns_fixedname_t fn; 2432 1.1 christos dns_name_t *name; 2433 1.1 christos 2434 1.1 christos REQUIRE(src != NULL); 2435 1.1 christos 2436 1.1 christos isc_buffer_constinit(&buf, src, strlen(src)); 2437 1.1 christos isc_buffer_add(&buf, strlen(src)); 2438 1.1 christos if (BINDABLE(target) && target->buffer != NULL) { 2439 1.1 christos name = target; 2440 1.1 christos } else { 2441 1.1 christos name = dns_fixedname_initname(&fn); 2442 1.1 christos } 2443 1.1 christos 2444 1.1 christos result = dns_name_fromtext(name, &buf, origin, options, NULL); 2445 1.1 christos if (result != ISC_R_SUCCESS) { 2446 1.1 christos return (result); 2447 1.1 christos } 2448 1.1 christos 2449 1.1 christos if (name != target) { 2450 1.1 christos result = dns_name_dupwithoffsets(name, mctx, target); 2451 1.1 christos } 2452 1.1 christos return (result); 2453 1.1 christos } 2454 1.1 christos 2455 1.1 christos static isc_result_t 2456 1.1 christos name_copy(const dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) { 2457 1.1 christos unsigned char *ndata = NULL; 2458 1.1 christos 2459 1.1 christos /* 2460 1.1 christos * Make dest a copy of source. 2461 1.1 christos */ 2462 1.1 christos 2463 1.1 christos REQUIRE(BINDABLE(dest)); 2464 1.1 christos 2465 1.1 christos /* 2466 1.1 christos * Set up. 2467 1.1 christos */ 2468 1.1 christos if (target->length - target->used < source->length) { 2469 1.1 christos return (ISC_R_NOSPACE); 2470 1.1 christos } 2471 1.1 christos 2472 1.1 christos ndata = (unsigned char *)target->base + target->used; 2473 1.1 christos dest->ndata = target->base; 2474 1.1 christos 2475 1.1 christos if (source->length != 0) { 2476 1.1 christos memmove(ndata, source->ndata, source->length); 2477 1.1 christos } 2478 1.1 christos 2479 1.1 christos dest->ndata = ndata; 2480 1.1 christos dest->labels = source->labels; 2481 1.1 christos dest->length = source->length; 2482 1.1 christos if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) { 2483 1.1 christos dest->attributes = DNS_NAMEATTR_ABSOLUTE; 2484 1.1 christos } else { 2485 1.1 christos dest->attributes = 0; 2486 1.1 christos } 2487 1.1 christos 2488 1.1 christos if (dest->labels > 0 && dest->offsets != NULL) { 2489 1.1 christos if (source->offsets != NULL && source->labels != 0) { 2490 1.1 christos memmove(dest->offsets, source->offsets, source->labels); 2491 1.1 christos } else { 2492 1.1 christos set_offsets(dest, dest->offsets, NULL); 2493 1.1 christos } 2494 1.1 christos } 2495 1.1 christos 2496 1.1 christos isc_buffer_add(target, dest->length); 2497 1.1 christos 2498 1.1 christos return (ISC_R_SUCCESS); 2499 1.1 christos } 2500 1.1 christos 2501 1.1 christos isc_result_t 2502 1.1 christos dns_name_copy(const dns_name_t *source, dns_name_t *dest, 2503 1.1 christos isc_buffer_t *target) { 2504 1.1 christos REQUIRE(VALID_NAME(source)); 2505 1.1 christos REQUIRE(VALID_NAME(dest)); 2506 1.1 christos REQUIRE(target != NULL); 2507 1.1 christos 2508 1.1 christos return (name_copy(source, dest, target)); 2509 1.1 christos } 2510 1.1 christos 2511 1.1 christos void 2512 1.1 christos dns_name_copynf(const dns_name_t *source, dns_name_t *dest) { 2513 1.1 christos REQUIRE(VALID_NAME(source)); 2514 1.1 christos REQUIRE(VALID_NAME(dest)); 2515 1.1 christos REQUIRE(dest->buffer != NULL); 2516 1.1 christos 2517 1.1 christos isc_buffer_clear(dest->buffer); 2518 1.1 christos RUNTIME_CHECK(name_copy(source, dest, dest->buffer) == ISC_R_SUCCESS); 2519 1.1 christos } 2520 1.1 christos 2521 1.1 christos /* 2522 1.1 christos * Service Discovery Prefixes RFC 6763. 2523 1.1 christos */ 2524 1.1 christos static unsigned char b_dns_sd_udp_data[] = "\001b\007_dns-sd\004_udp"; 2525 1.1 christos static unsigned char b_dns_sd_udp_offsets[] = { 0, 2, 10 }; 2526 1.1 christos static unsigned char db_dns_sd_udp_data[] = "\002db\007_dns-sd\004_udp"; 2527 1.1 christos static unsigned char db_dns_sd_udp_offsets[] = { 0, 3, 11 }; 2528 1.1 christos static unsigned char r_dns_sd_udp_data[] = "\001r\007_dns-sd\004_udp"; 2529 1.1 christos static unsigned char r_dns_sd_udp_offsets[] = { 0, 2, 10 }; 2530 1.1 christos static unsigned char dr_dns_sd_udp_data[] = "\002dr\007_dns-sd\004_udp"; 2531 1.1 christos static unsigned char dr_dns_sd_udp_offsets[] = { 0, 3, 11 }; 2532 1.1 christos static unsigned char lb_dns_sd_udp_data[] = "\002lb\007_dns-sd\004_udp"; 2533 1.1 christos static unsigned char lb_dns_sd_udp_offsets[] = { 0, 3, 11 }; 2534 1.1 christos 2535 1.1 christos static dns_name_t const dns_sd[] = { 2536 1.1 christos DNS_NAME_INITNONABSOLUTE(b_dns_sd_udp_data, b_dns_sd_udp_offsets), 2537 1.1 christos DNS_NAME_INITNONABSOLUTE(db_dns_sd_udp_data, db_dns_sd_udp_offsets), 2538 1.1 christos DNS_NAME_INITNONABSOLUTE(r_dns_sd_udp_data, r_dns_sd_udp_offsets), 2539 1.1 christos DNS_NAME_INITNONABSOLUTE(dr_dns_sd_udp_data, dr_dns_sd_udp_offsets), 2540 1.1 christos DNS_NAME_INITNONABSOLUTE(lb_dns_sd_udp_data, lb_dns_sd_udp_offsets) 2541 1.1 christos }; 2542 1.1 christos 2543 1.1 christos bool 2544 1.1 christos dns_name_isdnssd(const dns_name_t *name) { 2545 1.1 christos size_t i; 2546 1.1 christos dns_name_t prefix; 2547 1.1 christos 2548 1.1 christos if (dns_name_countlabels(name) > 3U) { 2549 1.1 christos dns_name_init(&prefix, NULL); 2550 1.1 christos dns_name_getlabelsequence(name, 0, 3, &prefix); 2551 1.1 christos for (i = 0; i < (sizeof(dns_sd) / sizeof(dns_sd[0])); i++) { 2552 1.1 christos if (dns_name_equal(&prefix, &dns_sd[i])) { 2553 1.1 christos return (true); 2554 1.1 christos } 2555 1.1 christos } 2556 1.1 christos } 2557 1.1 christos 2558 1.1 christos return (false); 2559 1.1 christos } 2560 1.1 christos 2561 1.1 christos static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 }; 2562 1.1 christos static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 }; 2563 1.1 christos static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 }; 2564 1.1 christos 2565 1.1 christos static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA"; 2566 1.1 christos 2567 1.1 christos static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA"; 2568 1.1 christos static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA"; 2569 1.1 christos static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA"; 2570 1.1 christos static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA"; 2571 1.1 christos static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA"; 2572 1.1 christos static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA"; 2573 1.1 christos static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA"; 2574 1.1 christos static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA"; 2575 1.1 christos static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA"; 2576 1.1 christos static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA"; 2577 1.1 christos static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA"; 2578 1.1 christos static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA"; 2579 1.1 christos static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA"; 2580 1.1 christos static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA"; 2581 1.1 christos static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA"; 2582 1.1 christos static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA"; 2583 1.1 christos 2584 1.1 christos static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA"; 2585 1.1 christos 2586 1.1 christos static dns_name_t const rfc1918names[] = { 2587 1.1 christos DNS_NAME_INITABSOLUTE(inaddr10, inaddr10_offsets), 2588 1.1 christos DNS_NAME_INITABSOLUTE(inaddr16172, inaddr172_offsets), 2589 1.1 christos DNS_NAME_INITABSOLUTE(inaddr17172, inaddr172_offsets), 2590 1.1 christos DNS_NAME_INITABSOLUTE(inaddr18172, inaddr172_offsets), 2591 1.1 christos DNS_NAME_INITABSOLUTE(inaddr19172, inaddr172_offsets), 2592 1.1 christos DNS_NAME_INITABSOLUTE(inaddr20172, inaddr172_offsets), 2593 1.1 christos DNS_NAME_INITABSOLUTE(inaddr21172, inaddr172_offsets), 2594 1.1 christos DNS_NAME_INITABSOLUTE(inaddr22172, inaddr172_offsets), 2595 1.1 christos DNS_NAME_INITABSOLUTE(inaddr23172, inaddr172_offsets), 2596 1.1 christos DNS_NAME_INITABSOLUTE(inaddr24172, inaddr172_offsets), 2597 1.1 christos DNS_NAME_INITABSOLUTE(inaddr25172, inaddr172_offsets), 2598 1.1 christos DNS_NAME_INITABSOLUTE(inaddr26172, inaddr172_offsets), 2599 1.1 christos DNS_NAME_INITABSOLUTE(inaddr27172, inaddr172_offsets), 2600 1.1 christos DNS_NAME_INITABSOLUTE(inaddr28172, inaddr172_offsets), 2601 1.1 christos DNS_NAME_INITABSOLUTE(inaddr29172, inaddr172_offsets), 2602 1.1 christos DNS_NAME_INITABSOLUTE(inaddr30172, inaddr172_offsets), 2603 1.1 christos DNS_NAME_INITABSOLUTE(inaddr31172, inaddr172_offsets), 2604 1.1 christos DNS_NAME_INITABSOLUTE(inaddr168192, inaddr192_offsets) 2605 1.1 christos }; 2606 1.1 christos 2607 1.1 christos bool 2608 1.1 christos dns_name_isrfc1918(const dns_name_t *name) { 2609 1.1 christos size_t i; 2610 1.1 christos 2611 1.1 christos for (i = 0; i < (sizeof(rfc1918names) / sizeof(*rfc1918names)); i++) { 2612 1.1 christos if (dns_name_issubdomain(name, &rfc1918names[i])) { 2613 1.1 christos return (true); 2614 1.1 christos } 2615 1.1 christos } 2616 1.1 christos return (false); 2617 1.1 christos } 2618 1.1 christos 2619 1.1 christos static unsigned char ulaoffsets[] = { 0, 2, 4, 8, 13 }; 2620 1.1 christos static unsigned char ip6fc[] = "\001c\001f\003ip6\004ARPA"; 2621 1.1 christos static unsigned char ip6fd[] = "\001d\001f\003ip6\004ARPA"; 2622 1.1 christos 2623 1.1 christos static dns_name_t const ulanames[] = { DNS_NAME_INITABSOLUTE(ip6fc, ulaoffsets), 2624 1.1 christos DNS_NAME_INITABSOLUTE(ip6fd, 2625 1.1 christos ulaoffsets) }; 2626 1.1 christos 2627 1.1 christos bool 2628 1.1 christos dns_name_isula(const dns_name_t *name) { 2629 1.1 christos size_t i; 2630 1.1 christos 2631 1.1 christos for (i = 0; i < (sizeof(ulanames) / sizeof(*ulanames)); i++) { 2632 1.1 christos if (dns_name_issubdomain(name, &ulanames[i])) { 2633 1.1 christos return (true); 2634 1.1 christos } 2635 1.1 christos } 2636 1.1 christos return (false); 2637 1.1 christos } 2638 1.1 christos 2639 1.1 christos /* 2640 1.1 christos * Use a simple table as we don't want all the locale stuff 2641 1.1 christos * associated with ishexdigit(). 2642 1.1 christos */ 2643 1.1 christos const char ishex[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2644 1.1 christos 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2645 1.1 christos 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2646 1.1 christos 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 2647 1.1 christos 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2648 1.1 christos 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2649 1.1 christos 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2650 1.1 christos 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 2651 1.1 christos 2652 1.1 christos bool 2653 1.1 christos dns_name_istat(const dns_name_t *name) { 2654 1.1 christos unsigned char len; 2655 1.1 christos const unsigned char *ndata; 2656 1.1 christos 2657 1.1 christos REQUIRE(VALID_NAME(name)); 2658 1.1 christos 2659 1.1 christos if (name->labels < 1) { 2660 1.1 christos return (false); 2661 1.1 christos } 2662 1.1 christos 2663 1.1 christos ndata = name->ndata; 2664 1.1 christos len = ndata[0]; 2665 1.1 christos INSIST(len <= name->length); 2666 1.1 christos ndata++; 2667 1.1 christos 2668 1.1 christos /* 2669 1.1 christos * Is there at least one trust anchor reported and is the 2670 1.1 christos * label length consistent with a trust-anchor-telemetry label. 2671 1.1 christos */ 2672 1.1 christos if ((len < 8) || (len - 3) % 5 != 0) { 2673 1.1 christos return (false); 2674 1.1 christos } 2675 1.1 christos 2676 1.1 christos if (ndata[0] != '_' || maptolower[ndata[1]] != 't' || 2677 1.1 christos maptolower[ndata[2]] != 'a') 2678 1.1 christos { 2679 1.1 christos return (false); 2680 1.1 christos } 2681 1.1 christos ndata += 3; 2682 1.1 christos len -= 3; 2683 1.1 christos 2684 1.1 christos while (len > 0) { 2685 1.1 christos INSIST(len >= 5); 2686 1.1 christos if (ndata[0] != '-' || !ishex[ndata[1]] || !ishex[ndata[2]] || 2687 1.1 christos !ishex[ndata[3]] || !ishex[ndata[4]]) 2688 1.1 christos { 2689 1.1 christos return (false); 2690 1.1 christos } 2691 1.1 christos ndata += 5; 2692 1.1 christos len -= 5; 2693 1.1 christos } 2694 1.1 christos return (true); 2695 1.1 christos } 2696