1 1.1 christos /* $NetBSD: rdata.c,v 1.1 2024/02/18 20:57:33 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 22 1.1 christos #include <isc/base64.h> 23 1.1 christos #include <isc/hex.h> 24 1.1 christos #include <isc/lex.h> 25 1.1 christos #include <isc/mem.h> 26 1.1 christos #include <isc/parseint.h> 27 1.1 christos #include <isc/print.h> 28 1.1 christos #include <isc/string.h> 29 1.1 christos #include <isc/util.h> 30 1.1 christos 31 1.1 christos #include <dns/callbacks.h> 32 1.1 christos #include <dns/cert.h> 33 1.1 christos #include <dns/compress.h> 34 1.1 christos #include <dns/dsdigest.h> 35 1.1 christos #include <dns/enumtype.h> 36 1.1 christos #include <dns/keyflags.h> 37 1.1 christos #include <dns/keyvalues.h> 38 1.1 christos #include <dns/message.h> 39 1.1 christos #include <dns/rcode.h> 40 1.1 christos #include <dns/rdata.h> 41 1.1 christos #include <dns/rdataclass.h> 42 1.1 christos #include <dns/rdatastruct.h> 43 1.1 christos #include <dns/rdatatype.h> 44 1.1 christos #include <dns/result.h> 45 1.1 christos #include <dns/secalg.h> 46 1.1 christos #include <dns/secproto.h> 47 1.1 christos #include <dns/time.h> 48 1.1 christos #include <dns/ttl.h> 49 1.1 christos 50 1.1 christos #define RETERR(x) \ 51 1.1 christos do { \ 52 1.1 christos isc_result_t _r = (x); \ 53 1.1 christos if (_r != ISC_R_SUCCESS) \ 54 1.1 christos return ((_r)); \ 55 1.1 christos } while (0) 56 1.1 christos 57 1.1 christos #define RETTOK(x) \ 58 1.1 christos do { \ 59 1.1 christos isc_result_t _r = (x); \ 60 1.1 christos if (_r != ISC_R_SUCCESS) { \ 61 1.1 christos isc_lex_ungettoken(lexer, &token); \ 62 1.1 christos return (_r); \ 63 1.1 christos } \ 64 1.1 christos } while (0) 65 1.1 christos 66 1.1 christos #define CHECK(op) \ 67 1.1 christos do { \ 68 1.1 christos result = (op); \ 69 1.1 christos if (result != ISC_R_SUCCESS) \ 70 1.1 christos goto cleanup; \ 71 1.1 christos } while (0) 72 1.1 christos 73 1.1 christos #define CHECKTOK(op) \ 74 1.1 christos do { \ 75 1.1 christos result = (op); \ 76 1.1 christos if (result != ISC_R_SUCCESS) { \ 77 1.1 christos isc_lex_ungettoken(lexer, &token); \ 78 1.1 christos goto cleanup; \ 79 1.1 christos } \ 80 1.1 christos } while (0) 81 1.1 christos 82 1.1 christos #define DNS_AS_STR(t) ((t).value.as_textregion.base) 83 1.1 christos 84 1.1 christos #define ARGS_FROMTEXT \ 85 1.1 christos int rdclass, dns_rdatatype_t type, isc_lex_t *lexer, \ 86 1.1 christos const dns_name_t *origin, unsigned int options, \ 87 1.1 christos isc_buffer_t *target, dns_rdatacallbacks_t *callbacks 88 1.1 christos 89 1.1 christos #define CALL_FROMTEXT rdclass, type, lexer, origin, options, target, callbacks 90 1.1 christos 91 1.1 christos #define ARGS_TOTEXT \ 92 1.1 christos dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, isc_buffer_t *target 93 1.1 christos 94 1.1 christos #define CALL_TOTEXT rdata, tctx, target 95 1.1 christos 96 1.1 christos #define ARGS_FROMWIRE \ 97 1.1 christos int rdclass, dns_rdatatype_t type, isc_buffer_t *source, \ 98 1.1 christos dns_decompress_t *dctx, unsigned int options, \ 99 1.1 christos isc_buffer_t *target 100 1.1 christos 101 1.1 christos #define CALL_FROMWIRE rdclass, type, source, dctx, options, target 102 1.1 christos 103 1.1 christos #define ARGS_TOWIRE \ 104 1.1 christos dns_rdata_t *rdata, dns_compress_t *cctx, isc_buffer_t *target 105 1.1 christos 106 1.1 christos #define CALL_TOWIRE rdata, cctx, target 107 1.1 christos 108 1.1 christos #define ARGS_COMPARE const dns_rdata_t *rdata1, const dns_rdata_t *rdata2 109 1.1 christos 110 1.1 christos #define CALL_COMPARE rdata1, rdata2 111 1.1 christos 112 1.1 christos #define ARGS_FROMSTRUCT \ 113 1.1 christos int rdclass, dns_rdatatype_t type, void *source, isc_buffer_t *target 114 1.1 christos 115 1.1 christos #define CALL_FROMSTRUCT rdclass, type, source, target 116 1.1 christos 117 1.1 christos #define ARGS_TOSTRUCT const dns_rdata_t *rdata, void *target, isc_mem_t *mctx 118 1.1 christos 119 1.1 christos #define CALL_TOSTRUCT rdata, target, mctx 120 1.1 christos 121 1.1 christos #define ARGS_FREESTRUCT void *source 122 1.1 christos 123 1.1 christos #define CALL_FREESTRUCT source 124 1.1 christos 125 1.1 christos #define ARGS_ADDLDATA \ 126 1.1 christos dns_rdata_t *rdata, dns_additionaldatafunc_t add, void *arg 127 1.1 christos 128 1.1 christos #define CALL_ADDLDATA rdata, add, arg 129 1.1 christos 130 1.1 christos #define ARGS_DIGEST dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg 131 1.1 christos 132 1.1 christos #define CALL_DIGEST rdata, digest, arg 133 1.1 christos 134 1.1 christos #define ARGS_CHECKOWNER \ 135 1.1 christos const dns_name_t *name, dns_rdataclass_t rdclass, \ 136 1.1 christos dns_rdatatype_t type, bool wildcard 137 1.1 christos 138 1.1 christos #define CALL_CHECKOWNER name, rdclass, type, wildcard 139 1.1 christos 140 1.1 christos #define ARGS_CHECKNAMES \ 141 1.1 christos dns_rdata_t *rdata, const dns_name_t *owner, dns_name_t *bad 142 1.1 christos 143 1.1 christos #define CALL_CHECKNAMES rdata, owner, bad 144 1.1 christos 145 1.1 christos /*% 146 1.1 christos * Context structure for the totext_ functions. 147 1.1 christos * Contains formatting options for rdata-to-text 148 1.1 christos * conversion. 149 1.1 christos */ 150 1.1 christos typedef struct dns_rdata_textctx { 151 1.1 christos const dns_name_t *origin; /*%< Current origin, or NULL. */ 152 1.1 christos dns_masterstyle_flags_t flags; /*%< DNS_STYLEFLAG_* */ 153 1.1 christos unsigned int width; /*%< Width of rdata column. */ 154 1.1 christos const char *linebreak; /*%< Line break string. */ 155 1.1 christos } dns_rdata_textctx_t; 156 1.1 christos 157 1.1 christos static isc_result_t 158 1.1 christos txt_totext(isc_region_t *source, bool quote, isc_buffer_t *target); 159 1.1 christos 160 1.1 christos static isc_result_t 161 1.1 christos txt_fromtext(isc_textregion_t *source, isc_buffer_t *target); 162 1.1 christos 163 1.1 christos static isc_result_t 164 1.1 christos txt_fromwire(isc_buffer_t *source, isc_buffer_t *target); 165 1.1 christos 166 1.1 christos static isc_result_t 167 1.1 christos commatxt_fromtext(isc_textregion_t *source, bool comma, isc_buffer_t *target); 168 1.1 christos 169 1.1 christos static isc_result_t 170 1.1 christos commatxt_totext(isc_region_t *source, bool quote, bool comma, 171 1.1 christos isc_buffer_t *target); 172 1.1 christos 173 1.1 christos static isc_result_t 174 1.1 christos multitxt_totext(isc_region_t *source, isc_buffer_t *target); 175 1.1 christos 176 1.1 christos static isc_result_t 177 1.1 christos multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target); 178 1.1 christos 179 1.1 christos static bool 180 1.1 christos name_prefix(dns_name_t *name, const dns_name_t *origin, dns_name_t *target); 181 1.1 christos 182 1.1 christos static unsigned int 183 1.1 christos name_length(const dns_name_t *name); 184 1.1 christos 185 1.1 christos static isc_result_t 186 1.1 christos str_totext(const char *source, isc_buffer_t *target); 187 1.1 christos 188 1.1 christos static isc_result_t 189 1.1 christos inet_totext(int af, uint32_t flags, isc_region_t *src, isc_buffer_t *target); 190 1.1 christos 191 1.1 christos static bool 192 1.1 christos buffer_empty(isc_buffer_t *source); 193 1.1 christos 194 1.1 christos static void 195 1.1 christos buffer_fromregion(isc_buffer_t *buffer, isc_region_t *region); 196 1.1 christos 197 1.1 christos static isc_result_t 198 1.1 christos uint32_tobuffer(uint32_t, isc_buffer_t *target); 199 1.1 christos 200 1.1 christos static isc_result_t 201 1.1 christos uint16_tobuffer(uint32_t, isc_buffer_t *target); 202 1.1 christos 203 1.1 christos static isc_result_t 204 1.1 christos uint8_tobuffer(uint32_t, isc_buffer_t *target); 205 1.1 christos 206 1.1 christos static isc_result_t 207 1.1 christos name_tobuffer(const dns_name_t *name, isc_buffer_t *target); 208 1.1 christos 209 1.1 christos static uint32_t 210 1.1 christos uint32_fromregion(isc_region_t *region); 211 1.1 christos 212 1.1 christos static uint16_t 213 1.1 christos uint16_fromregion(isc_region_t *region); 214 1.1 christos 215 1.1 christos static uint8_t 216 1.1 christos uint8_fromregion(isc_region_t *region); 217 1.1 christos 218 1.1 christos static uint8_t 219 1.1 christos uint8_consume_fromregion(isc_region_t *region); 220 1.1 christos 221 1.1 christos static isc_result_t 222 1.1 christos mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length); 223 1.1 christos 224 1.1 christos static int 225 1.1 christos hexvalue(char value); 226 1.1 christos 227 1.1 christos static int 228 1.1 christos decvalue(char value); 229 1.1 christos 230 1.1 christos static void 231 1.1 christos default_fromtext_callback(dns_rdatacallbacks_t *callbacks, const char *, ...) 232 1.1 christos ISC_FORMAT_PRINTF(2, 3); 233 1.1 christos 234 1.1 christos static void 235 1.1 christos fromtext_error(void (*callback)(dns_rdatacallbacks_t *, const char *, ...), 236 1.1 christos dns_rdatacallbacks_t *callbacks, const char *name, 237 1.1 christos unsigned long line, isc_token_t *token, isc_result_t result); 238 1.1 christos 239 1.1 christos static void 240 1.1 christos fromtext_warneof(isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks); 241 1.1 christos 242 1.1 christos static isc_result_t 243 1.1 christos rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, 244 1.1 christos isc_buffer_t *target); 245 1.1 christos 246 1.1 christos static void 247 1.1 christos warn_badname(const dns_name_t *name, isc_lex_t *lexer, 248 1.1 christos dns_rdatacallbacks_t *callbacks); 249 1.1 christos 250 1.1 christos static void 251 1.1 christos warn_badmx(isc_token_t *token, isc_lex_t *lexer, 252 1.1 christos dns_rdatacallbacks_t *callbacks); 253 1.1 christos 254 1.1 christos static uint16_t 255 1.1 christos uint16_consume_fromregion(isc_region_t *region); 256 1.1 christos 257 1.1 christos static isc_result_t 258 1.1 christos unknown_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, 259 1.1 christos isc_buffer_t *target); 260 1.1 christos 261 1.1 christos static isc_result_t generic_fromtext_key(ARGS_FROMTEXT); 262 1.1 christos 263 1.1 christos static isc_result_t generic_totext_key(ARGS_TOTEXT); 264 1.1 christos 265 1.1 christos static isc_result_t generic_fromwire_key(ARGS_FROMWIRE); 266 1.1 christos 267 1.1 christos static isc_result_t generic_fromstruct_key(ARGS_FROMSTRUCT); 268 1.1 christos 269 1.1 christos static isc_result_t generic_tostruct_key(ARGS_TOSTRUCT); 270 1.1 christos 271 1.1 christos static void generic_freestruct_key(ARGS_FREESTRUCT); 272 1.1 christos 273 1.1 christos static isc_result_t generic_fromtext_txt(ARGS_FROMTEXT); 274 1.1 christos 275 1.1 christos static isc_result_t generic_totext_txt(ARGS_TOTEXT); 276 1.1 christos 277 1.1 christos static isc_result_t generic_fromwire_txt(ARGS_FROMWIRE); 278 1.1 christos 279 1.1 christos static isc_result_t generic_fromstruct_txt(ARGS_FROMSTRUCT); 280 1.1 christos 281 1.1 christos static isc_result_t generic_tostruct_txt(ARGS_TOSTRUCT); 282 1.1 christos 283 1.1 christos static void generic_freestruct_txt(ARGS_FREESTRUCT); 284 1.1 christos 285 1.1 christos static isc_result_t 286 1.1 christos generic_txt_first(dns_rdata_txt_t *txt); 287 1.1 christos 288 1.1 christos static isc_result_t 289 1.1 christos generic_txt_next(dns_rdata_txt_t *txt); 290 1.1 christos 291 1.1 christos static isc_result_t 292 1.1 christos generic_txt_current(dns_rdata_txt_t *txt, dns_rdata_txt_string_t *string); 293 1.1 christos 294 1.1 christos static isc_result_t generic_totext_ds(ARGS_TOTEXT); 295 1.1 christos 296 1.1 christos static isc_result_t generic_tostruct_ds(ARGS_TOSTRUCT); 297 1.1 christos 298 1.1 christos static isc_result_t generic_fromtext_ds(ARGS_FROMTEXT); 299 1.1 christos 300 1.1 christos static isc_result_t generic_fromwire_ds(ARGS_FROMWIRE); 301 1.1 christos 302 1.1 christos static isc_result_t generic_fromstruct_ds(ARGS_FROMSTRUCT); 303 1.1 christos 304 1.1 christos static isc_result_t generic_fromtext_tlsa(ARGS_FROMTEXT); 305 1.1 christos 306 1.1 christos static isc_result_t generic_totext_tlsa(ARGS_TOTEXT); 307 1.1 christos 308 1.1 christos static isc_result_t generic_fromwire_tlsa(ARGS_FROMWIRE); 309 1.1 christos 310 1.1 christos static isc_result_t generic_fromstruct_tlsa(ARGS_FROMSTRUCT); 311 1.1 christos 312 1.1 christos static isc_result_t generic_tostruct_tlsa(ARGS_TOSTRUCT); 313 1.1 christos 314 1.1 christos static void generic_freestruct_tlsa(ARGS_FREESTRUCT); 315 1.1 christos 316 1.1 christos static isc_result_t generic_fromtext_in_svcb(ARGS_FROMTEXT); 317 1.1 christos static isc_result_t generic_totext_in_svcb(ARGS_TOTEXT); 318 1.1 christos static isc_result_t generic_fromwire_in_svcb(ARGS_FROMWIRE); 319 1.1 christos static isc_result_t generic_towire_in_svcb(ARGS_TOWIRE); 320 1.1 christos static isc_result_t generic_fromstruct_in_svcb(ARGS_FROMSTRUCT); 321 1.1 christos static isc_result_t generic_tostruct_in_svcb(ARGS_TOSTRUCT); 322 1.1 christos static void generic_freestruct_in_svcb(ARGS_FREESTRUCT); 323 1.1 christos static isc_result_t generic_additionaldata_in_svcb(ARGS_ADDLDATA); 324 1.1 christos static bool generic_checknames_in_svcb(ARGS_CHECKNAMES); 325 1.1 christos static isc_result_t 326 1.1 christos generic_rdata_in_svcb_first(dns_rdata_in_svcb_t *); 327 1.1 christos static isc_result_t 328 1.1 christos generic_rdata_in_svcb_next(dns_rdata_in_svcb_t *); 329 1.1 christos static void 330 1.1 christos generic_rdata_in_svcb_current(dns_rdata_in_svcb_t *, isc_region_t *); 331 1.1 christos 332 1.1 christos /*% INT16 Size */ 333 1.1 christos #define NS_INT16SZ 2 334 1.1 christos /*% IPv6 Address Size */ 335 1.1 christos #define NS_LOCATORSZ 8 336 1.1 christos 337 1.1 christos /* 338 1.1 christos * Active Directory gc._msdcs.<forest> prefix. 339 1.1 christos */ 340 1.1 christos static unsigned char gc_msdcs_data[] = "\002gc\006_msdcs"; 341 1.1 christos static unsigned char gc_msdcs_offset[] = { 0, 3 }; 342 1.1 christos 343 1.1 christos static dns_name_t const gc_msdcs = DNS_NAME_INITNONABSOLUTE(gc_msdcs_data, 344 1.1 christos gc_msdcs_offset); 345 1.1 christos 346 1.1 christos /*% 347 1.1 christos * convert presentation level address to network order binary form. 348 1.1 christos * \return 349 1.1 christos * 1 if `src' is a valid [RFC1884 2.2] address, else 0. 350 1.1 christos * \note 351 1.1 christos * (1) does not touch `dst' unless it's returning 1. 352 1.1 christos */ 353 1.1 christos static int 354 1.1 christos locator_pton(const char *src, unsigned char *dst) { 355 1.1 christos static const char xdigits_l[] = "0123456789abcdef", 356 1.1 christos xdigits_u[] = "0123456789ABCDEF"; 357 1.1 christos unsigned char tmp[NS_LOCATORSZ]; 358 1.1 christos unsigned char *tp = tmp, *endp; 359 1.1 christos const char *xdigits; 360 1.1 christos int ch, seen_xdigits; 361 1.1 christos unsigned int val; 362 1.1 christos 363 1.1 christos memset(tp, '\0', NS_LOCATORSZ); 364 1.1 christos endp = tp + NS_LOCATORSZ; 365 1.1 christos seen_xdigits = 0; 366 1.1 christos val = 0; 367 1.1 christos while ((ch = *src++) != '\0') { 368 1.1 christos const char *pch; 369 1.1 christos 370 1.1 christos pch = strchr((xdigits = xdigits_l), ch); 371 1.1 christos if (pch == NULL) { 372 1.1 christos pch = strchr((xdigits = xdigits_u), ch); 373 1.1 christos } 374 1.1 christos if (pch != NULL) { 375 1.1 christos val <<= 4; 376 1.1 christos val |= (pch - xdigits); 377 1.1 christos if (++seen_xdigits > 4) { 378 1.1 christos return (0); 379 1.1 christos } 380 1.1 christos continue; 381 1.1 christos } 382 1.1 christos if (ch == ':') { 383 1.1 christos if (!seen_xdigits) { 384 1.1 christos return (0); 385 1.1 christos } 386 1.1 christos if (tp + NS_INT16SZ > endp) { 387 1.1 christos return (0); 388 1.1 christos } 389 1.1 christos *tp++ = (unsigned char)(val >> 8) & 0xff; 390 1.1 christos *tp++ = (unsigned char)val & 0xff; 391 1.1 christos seen_xdigits = 0; 392 1.1 christos val = 0; 393 1.1 christos continue; 394 1.1 christos } 395 1.1 christos return (0); 396 1.1 christos } 397 1.1 christos if (seen_xdigits) { 398 1.1 christos if (tp + NS_INT16SZ > endp) { 399 1.1 christos return (0); 400 1.1 christos } 401 1.1 christos *tp++ = (unsigned char)(val >> 8) & 0xff; 402 1.1 christos *tp++ = (unsigned char)val & 0xff; 403 1.1 christos } 404 1.1 christos if (tp != endp) { 405 1.1 christos return (0); 406 1.1 christos } 407 1.1 christos memmove(dst, tmp, NS_LOCATORSZ); 408 1.1 christos return (1); 409 1.1 christos } 410 1.1 christos 411 1.1 christos static isc_result_t 412 1.1 christos name_duporclone(const dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) { 413 1.1 christos if (mctx != NULL) { 414 1.1 christos dns_name_dup(source, mctx, target); 415 1.1 christos } else { 416 1.1 christos dns_name_clone(source, target); 417 1.1 christos } 418 1.1 christos return (ISC_R_SUCCESS); 419 1.1 christos } 420 1.1 christos 421 1.1 christos static void * 422 1.1 christos mem_maybedup(isc_mem_t *mctx, void *source, size_t length) { 423 1.1 christos void *copy; 424 1.1 christos 425 1.1 christos if (mctx == NULL) { 426 1.1 christos return (source); 427 1.1 christos } 428 1.1 christos copy = isc_mem_allocate(mctx, length); 429 1.1 christos memmove(copy, source, length); 430 1.1 christos 431 1.1 christos return (copy); 432 1.1 christos } 433 1.1 christos 434 1.1 christos static isc_result_t 435 1.1 christos typemap_fromtext(isc_lex_t *lexer, isc_buffer_t *target, bool allow_empty) { 436 1.1 christos isc_token_t token; 437 1.1 christos unsigned char bm[8 * 1024]; /* 64k bits */ 438 1.1 christos dns_rdatatype_t covered, max_used; 439 1.1 christos int octet; 440 1.1 christos unsigned int max_octet, newend, end; 441 1.1 christos int window; 442 1.1 christos bool first = true; 443 1.1 christos 444 1.1 christos max_used = 0; 445 1.1 christos bm[0] = 0; 446 1.1 christos end = 0; 447 1.1 christos 448 1.1 christos do { 449 1.1 christos RETERR(isc_lex_getmastertoken(lexer, &token, 450 1.1 christos isc_tokentype_string, true)); 451 1.1 christos if (token.type != isc_tokentype_string) { 452 1.1 christos break; 453 1.1 christos } 454 1.1 christos RETTOK(dns_rdatatype_fromtext(&covered, 455 1.1 christos &token.value.as_textregion)); 456 1.1 christos if (covered > max_used) { 457 1.1 christos newend = covered / 8; 458 1.1 christos if (newend > end) { 459 1.1 christos memset(&bm[end + 1], 0, newend - end); 460 1.1 christos end = newend; 461 1.1 christos } 462 1.1 christos max_used = covered; 463 1.1 christos } 464 1.1 christos bm[covered / 8] |= (0x80 >> (covered % 8)); 465 1.1 christos first = false; 466 1.1 christos } while (1); 467 1.1 christos isc_lex_ungettoken(lexer, &token); 468 1.1 christos if (!allow_empty && first) { 469 1.1 christos return (DNS_R_FORMERR); 470 1.1 christos } 471 1.1 christos 472 1.1 christos for (window = 0; window < 256; window++) { 473 1.1 christos if (max_used < window * 256) { 474 1.1 christos break; 475 1.1 christos } 476 1.1 christos 477 1.1 christos max_octet = max_used - (window * 256); 478 1.1 christos if (max_octet >= 256) { 479 1.1 christos max_octet = 31; 480 1.1 christos } else { 481 1.1 christos max_octet /= 8; 482 1.1 christos } 483 1.1 christos 484 1.1 christos /* 485 1.1 christos * Find if we have a type in this window. 486 1.1 christos */ 487 1.1 christos for (octet = max_octet; octet >= 0; octet--) { 488 1.1 christos if (bm[window * 32 + octet] != 0) { 489 1.1 christos break; 490 1.1 christos } 491 1.1 christos } 492 1.1 christos if (octet < 0) { 493 1.1 christos continue; 494 1.1 christos } 495 1.1 christos RETERR(uint8_tobuffer(window, target)); 496 1.1 christos RETERR(uint8_tobuffer(octet + 1, target)); 497 1.1 christos RETERR(mem_tobuffer(target, &bm[window * 32], octet + 1)); 498 1.1 christos } 499 1.1 christos return (ISC_R_SUCCESS); 500 1.1 christos } 501 1.1 christos 502 1.1 christos static isc_result_t 503 1.1 christos typemap_totext(isc_region_t *sr, dns_rdata_textctx_t *tctx, 504 1.1 christos isc_buffer_t *target) { 505 1.1 christos unsigned int i, j, k; 506 1.1 christos unsigned int window, len; 507 1.1 christos bool first = true; 508 1.1 christos 509 1.1 christos for (i = 0; i < sr->length; i += len) { 510 1.1 christos if (tctx != NULL && 511 1.1 christos (tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) 512 1.1 christos { 513 1.1 christos RETERR(str_totext(tctx->linebreak, target)); 514 1.1 christos first = true; 515 1.1 christos } 516 1.1 christos INSIST(i + 2 <= sr->length); 517 1.1 christos window = sr->base[i]; 518 1.1 christos len = sr->base[i + 1]; 519 1.1 christos INSIST(len > 0 && len <= 32); 520 1.1 christos i += 2; 521 1.1 christos INSIST(i + len <= sr->length); 522 1.1 christos for (j = 0; j < len; j++) { 523 1.1 christos dns_rdatatype_t t; 524 1.1 christos if (sr->base[i + j] == 0) { 525 1.1 christos continue; 526 1.1 christos } 527 1.1 christos for (k = 0; k < 8; k++) { 528 1.1 christos if ((sr->base[i + j] & (0x80 >> k)) == 0) { 529 1.1 christos continue; 530 1.1 christos } 531 1.1 christos t = window * 256 + j * 8 + k; 532 1.1 christos if (!first) { 533 1.1 christos RETERR(str_totext(" ", target)); 534 1.1 christos } 535 1.1 christos first = false; 536 1.1 christos if (dns_rdatatype_isknown(t)) { 537 1.1 christos RETERR(dns_rdatatype_totext(t, target)); 538 1.1 christos } else { 539 1.1 christos char buf[sizeof("TYPE65535")]; 540 1.1 christos snprintf(buf, sizeof(buf), "TYPE%u", t); 541 1.1 christos RETERR(str_totext(buf, target)); 542 1.1 christos } 543 1.1 christos } 544 1.1 christos } 545 1.1 christos } 546 1.1 christos return (ISC_R_SUCCESS); 547 1.1 christos } 548 1.1 christos 549 1.1 christos static isc_result_t 550 1.1 christos typemap_test(isc_region_t *sr, bool allow_empty) { 551 1.1 christos unsigned int window, lastwindow = 0; 552 1.1 christos unsigned int len; 553 1.1 christos bool first = true; 554 1.1 christos unsigned int i; 555 1.1 christos 556 1.1 christos for (i = 0; i < sr->length; i += len) { 557 1.1 christos /* 558 1.1 christos * Check for overflow. 559 1.1 christos */ 560 1.1 christos if (i + 2 > sr->length) { 561 1.1 christos RETERR(DNS_R_FORMERR); 562 1.1 christos } 563 1.1 christos window = sr->base[i]; 564 1.1 christos len = sr->base[i + 1]; 565 1.1 christos i += 2; 566 1.1 christos /* 567 1.1 christos * Check that bitmap windows are in the correct order. 568 1.1 christos */ 569 1.1 christos if (!first && window <= lastwindow) { 570 1.1 christos RETERR(DNS_R_FORMERR); 571 1.1 christos } 572 1.1 christos /* 573 1.1 christos * Check for legal lengths. 574 1.1 christos */ 575 1.1 christos if (len < 1 || len > 32) { 576 1.1 christos RETERR(DNS_R_FORMERR); 577 1.1 christos } 578 1.1 christos /* 579 1.1 christos * Check for overflow. 580 1.1 christos */ 581 1.1 christos if (i + len > sr->length) { 582 1.1 christos RETERR(DNS_R_FORMERR); 583 1.1 christos } 584 1.1 christos /* 585 1.1 christos * The last octet of the bitmap must be non zero. 586 1.1 christos */ 587 1.1 christos if (sr->base[i + len - 1] == 0) { 588 1.1 christos RETERR(DNS_R_FORMERR); 589 1.1 christos } 590 1.1 christos lastwindow = window; 591 1.1 christos first = false; 592 1.1 christos } 593 1.1 christos if (i != sr->length) { 594 1.1 christos return (DNS_R_EXTRADATA); 595 1.1 christos } 596 1.1 christos if (!allow_empty && first) { 597 1.1 christos RETERR(DNS_R_FORMERR); 598 1.1 christos } 599 1.1 christos return (ISC_R_SUCCESS); 600 1.1 christos } 601 1.1 christos 602 1.1 christos static const char hexdigits[] = "0123456789abcdef"; 603 1.1 christos static const char decdigits[] = "0123456789"; 604 1.1 christos 605 1.1 christos #include "code.h" 606 1.1 christos 607 1.1 christos #define META 0x0001 608 1.1 christos #define RESERVED 0x0002 609 1.1 christos 610 1.1 christos /*** 611 1.1 christos *** Initialization 612 1.1 christos ***/ 613 1.1 christos 614 1.1 christos void 615 1.1 christos dns_rdata_init(dns_rdata_t *rdata) { 616 1.1 christos REQUIRE(rdata != NULL); 617 1.1 christos 618 1.1 christos rdata->data = NULL; 619 1.1 christos rdata->length = 0; 620 1.1 christos rdata->rdclass = 0; 621 1.1 christos rdata->type = 0; 622 1.1 christos rdata->flags = 0; 623 1.1 christos ISC_LINK_INIT(rdata, link); 624 1.1 christos /* ISC_LIST_INIT(rdata->list); */ 625 1.1 christos } 626 1.1 christos 627 1.1 christos void 628 1.1 christos dns_rdata_reset(dns_rdata_t *rdata) { 629 1.1 christos REQUIRE(rdata != NULL); 630 1.1 christos 631 1.1 christos REQUIRE(!ISC_LINK_LINKED(rdata, link)); 632 1.1 christos REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 633 1.1 christos 634 1.1 christos rdata->data = NULL; 635 1.1 christos rdata->length = 0; 636 1.1 christos rdata->rdclass = 0; 637 1.1 christos rdata->type = 0; 638 1.1 christos rdata->flags = 0; 639 1.1 christos } 640 1.1 christos 641 1.1 christos /*** 642 1.1 christos *** 643 1.1 christos ***/ 644 1.1 christos 645 1.1 christos void 646 1.1 christos dns_rdata_clone(const dns_rdata_t *src, dns_rdata_t *target) { 647 1.1 christos REQUIRE(src != NULL); 648 1.1 christos REQUIRE(target != NULL); 649 1.1 christos 650 1.1 christos REQUIRE(DNS_RDATA_INITIALIZED(target)); 651 1.1 christos 652 1.1 christos REQUIRE(DNS_RDATA_VALIDFLAGS(src)); 653 1.1 christos REQUIRE(DNS_RDATA_VALIDFLAGS(target)); 654 1.1 christos 655 1.1 christos target->data = src->data; 656 1.1 christos target->length = src->length; 657 1.1 christos target->rdclass = src->rdclass; 658 1.1 christos target->type = src->type; 659 1.1 christos target->flags = src->flags; 660 1.1 christos } 661 1.1 christos 662 1.1 christos /*** 663 1.1 christos *** Comparisons 664 1.1 christos ***/ 665 1.1 christos 666 1.1 christos int 667 1.1 christos dns_rdata_compare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2) { 668 1.1 christos int result = 0; 669 1.1 christos bool use_default = false; 670 1.1 christos 671 1.1 christos REQUIRE(rdata1 != NULL); 672 1.1 christos REQUIRE(rdata2 != NULL); 673 1.1 christos REQUIRE(rdata1->length == 0 || rdata1->data != NULL); 674 1.1 christos REQUIRE(rdata2->length == 0 || rdata2->data != NULL); 675 1.1 christos REQUIRE(DNS_RDATA_VALIDFLAGS(rdata1)); 676 1.1 christos REQUIRE(DNS_RDATA_VALIDFLAGS(rdata2)); 677 1.1 christos 678 1.1 christos if (rdata1->rdclass != rdata2->rdclass) { 679 1.1 christos return (rdata1->rdclass < rdata2->rdclass ? -1 : 1); 680 1.1 christos } 681 1.1 christos 682 1.1 christos if (rdata1->type != rdata2->type) { 683 1.1 christos return (rdata1->type < rdata2->type ? -1 : 1); 684 1.1 christos } 685 1.1 christos 686 1.1 christos COMPARESWITCH 687 1.1 christos 688 1.1 christos if (use_default) { 689 1.1 christos isc_region_t r1; 690 1.1 christos isc_region_t r2; 691 1.1 christos 692 1.1 christos dns_rdata_toregion(rdata1, &r1); 693 1.1 christos dns_rdata_toregion(rdata2, &r2); 694 1.1 christos result = isc_region_compare(&r1, &r2); 695 1.1 christos } 696 1.1 christos return (result); 697 1.1 christos } 698 1.1 christos 699 1.1 christos int 700 1.1 christos dns_rdata_casecompare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2) { 701 1.1 christos int result = 0; 702 1.1 christos bool use_default = false; 703 1.1 christos 704 1.1 christos REQUIRE(rdata1 != NULL); 705 1.1 christos REQUIRE(rdata2 != NULL); 706 1.1 christos REQUIRE(rdata1->length == 0 || rdata1->data != NULL); 707 1.1 christos REQUIRE(rdata2->length == 0 || rdata2->data != NULL); 708 1.1 christos REQUIRE(DNS_RDATA_VALIDFLAGS(rdata1)); 709 1.1 christos REQUIRE(DNS_RDATA_VALIDFLAGS(rdata2)); 710 1.1 christos 711 1.1 christos if (rdata1->rdclass != rdata2->rdclass) { 712 1.1 christos return (rdata1->rdclass < rdata2->rdclass ? -1 : 1); 713 1.1 christos } 714 1.1 christos 715 1.1 christos if (rdata1->type != rdata2->type) { 716 1.1 christos return (rdata1->type < rdata2->type ? -1 : 1); 717 1.1 christos } 718 1.1 christos 719 1.1 christos CASECOMPARESWITCH 720 1.1 christos 721 1.1 christos if (use_default) { 722 1.1 christos isc_region_t r1; 723 1.1 christos isc_region_t r2; 724 1.1 christos 725 1.1 christos dns_rdata_toregion(rdata1, &r1); 726 1.1 christos dns_rdata_toregion(rdata2, &r2); 727 1.1 christos result = isc_region_compare(&r1, &r2); 728 1.1 christos } 729 1.1 christos return (result); 730 1.1 christos } 731 1.1 christos 732 1.1 christos /*** 733 1.1 christos *** Conversions 734 1.1 christos ***/ 735 1.1 christos 736 1.1 christos void 737 1.1 christos dns_rdata_fromregion(dns_rdata_t *rdata, dns_rdataclass_t rdclass, 738 1.1 christos dns_rdatatype_t type, isc_region_t *r) { 739 1.1 christos REQUIRE(rdata != NULL); 740 1.1 christos REQUIRE(DNS_RDATA_INITIALIZED(rdata)); 741 1.1 christos REQUIRE(r != NULL); 742 1.1 christos 743 1.1 christos REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 744 1.1 christos 745 1.1 christos rdata->data = r->base; 746 1.1 christos rdata->length = r->length; 747 1.1 christos rdata->rdclass = rdclass; 748 1.1 christos rdata->type = type; 749 1.1 christos rdata->flags = 0; 750 1.1 christos } 751 1.1 christos 752 1.1 christos void 753 1.1 christos dns_rdata_toregion(const dns_rdata_t *rdata, isc_region_t *r) { 754 1.1 christos REQUIRE(rdata != NULL); 755 1.1 christos REQUIRE(r != NULL); 756 1.1 christos REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 757 1.1 christos 758 1.1 christos r->base = rdata->data; 759 1.1 christos r->length = rdata->length; 760 1.1 christos } 761 1.1 christos 762 1.1 christos isc_result_t 763 1.1 christos dns_rdata_fromwire(dns_rdata_t *rdata, dns_rdataclass_t rdclass, 764 1.1 christos dns_rdatatype_t type, isc_buffer_t *source, 765 1.1 christos dns_decompress_t *dctx, unsigned int options, 766 1.1 christos isc_buffer_t *target) { 767 1.1 christos isc_result_t result = ISC_R_NOTIMPLEMENTED; 768 1.1 christos isc_region_t region; 769 1.1 christos isc_buffer_t ss; 770 1.1 christos isc_buffer_t st; 771 1.1 christos bool use_default = false; 772 1.1 christos uint32_t activelength; 773 1.1 christos unsigned int length; 774 1.1 christos 775 1.1 christos REQUIRE(dctx != NULL); 776 1.1 christos if (rdata != NULL) { 777 1.1 christos REQUIRE(DNS_RDATA_INITIALIZED(rdata)); 778 1.1 christos REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 779 1.1 christos } 780 1.1 christos REQUIRE(source != NULL); 781 1.1 christos REQUIRE(target != NULL); 782 1.1 christos 783 1.1 christos if (type == 0) { 784 1.1 christos return (DNS_R_FORMERR); 785 1.1 christos } 786 1.1 christos 787 1.1 christos ss = *source; 788 1.1 christos st = *target; 789 1.1 christos 790 1.1 christos activelength = isc_buffer_activelength(source); 791 1.1 christos INSIST(activelength < 65536); 792 1.1 christos 793 1.1 christos FROMWIRESWITCH 794 1.1 christos 795 1.1 christos if (use_default) { 796 1.1 christos if (activelength > isc_buffer_availablelength(target)) { 797 1.1 christos result = ISC_R_NOSPACE; 798 1.1 christos } else { 799 1.1 christos isc_buffer_putmem(target, isc_buffer_current(source), 800 1.1 christos activelength); 801 1.1 christos isc_buffer_forward(source, activelength); 802 1.1 christos result = ISC_R_SUCCESS; 803 1.1 christos } 804 1.1 christos } 805 1.1 christos 806 1.1 christos /* 807 1.1 christos * Reject any rdata that expands out to more than DNS_RDATA_MAXLENGTH 808 1.1 christos * as we cannot transmit it. 809 1.1 christos */ 810 1.1 christos length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st); 811 1.1 christos if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH) { 812 1.1 christos result = DNS_R_FORMERR; 813 1.1 christos } 814 1.1 christos 815 1.1 christos /* 816 1.1 christos * We should have consumed all of our buffer. 817 1.1 christos */ 818 1.1 christos if (result == ISC_R_SUCCESS && !buffer_empty(source)) { 819 1.1 christos result = DNS_R_EXTRADATA; 820 1.1 christos } 821 1.1 christos 822 1.1 christos if (rdata != NULL && result == ISC_R_SUCCESS) { 823 1.1 christos region.base = isc_buffer_used(&st); 824 1.1 christos region.length = length; 825 1.1 christos dns_rdata_fromregion(rdata, rdclass, type, ®ion); 826 1.1 christos } 827 1.1 christos 828 1.1 christos if (result != ISC_R_SUCCESS) { 829 1.1 christos *source = ss; 830 1.1 christos *target = st; 831 1.1 christos } 832 1.1 christos return (result); 833 1.1 christos } 834 1.1 christos 835 1.1 christos isc_result_t 836 1.1 christos dns_rdata_towire(dns_rdata_t *rdata, dns_compress_t *cctx, 837 1.1 christos isc_buffer_t *target) { 838 1.1 christos isc_result_t result = ISC_R_NOTIMPLEMENTED; 839 1.1 christos bool use_default = false; 840 1.1 christos isc_region_t tr; 841 1.1 christos isc_buffer_t st; 842 1.1 christos 843 1.1 christos REQUIRE(rdata != NULL); 844 1.1 christos REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 845 1.1 christos 846 1.1 christos /* 847 1.1 christos * Some DynDNS meta-RRs have empty rdata. 848 1.1 christos */ 849 1.1 christos if ((rdata->flags & DNS_RDATA_UPDATE) != 0) { 850 1.1 christos INSIST(rdata->length == 0); 851 1.1 christos return (ISC_R_SUCCESS); 852 1.1 christos } 853 1.1 christos 854 1.1 christos st = *target; 855 1.1 christos 856 1.1 christos TOWIRESWITCH 857 1.1 christos 858 1.1 christos if (use_default) { 859 1.1 christos isc_buffer_availableregion(target, &tr); 860 1.1 christos if (tr.length < rdata->length) { 861 1.1 christos return (ISC_R_NOSPACE); 862 1.1 christos } 863 1.1 christos memmove(tr.base, rdata->data, rdata->length); 864 1.1 christos isc_buffer_add(target, rdata->length); 865 1.1 christos return (ISC_R_SUCCESS); 866 1.1 christos } 867 1.1 christos if (result != ISC_R_SUCCESS) { 868 1.1 christos *target = st; 869 1.1 christos INSIST(target->used < 65536); 870 1.1 christos dns_compress_rollback(cctx, (uint16_t)target->used); 871 1.1 christos } 872 1.1 christos return (result); 873 1.1 christos } 874 1.1 christos 875 1.1 christos /* 876 1.1 christos * If the binary data in 'src' is valid uncompressed wire format 877 1.1 christos * rdata of class 'rdclass' and type 'type', return ISC_R_SUCCESS 878 1.1 christos * and copy the validated rdata to 'dest'. Otherwise return an error. 879 1.1 christos */ 880 1.1 christos static isc_result_t 881 1.1 christos rdata_validate(isc_buffer_t *src, isc_buffer_t *dest, dns_rdataclass_t rdclass, 882 1.1 christos dns_rdatatype_t type) { 883 1.1 christos dns_decompress_t dctx; 884 1.1 christos isc_result_t result; 885 1.1 christos 886 1.1 christos dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE); 887 1.1 christos isc_buffer_setactive(src, isc_buffer_usedlength(src)); 888 1.1 christos result = dns_rdata_fromwire(NULL, rdclass, type, src, &dctx, 0, dest); 889 1.1 christos dns_decompress_invalidate(&dctx); 890 1.1 christos 891 1.1 christos return (result); 892 1.1 christos } 893 1.1 christos 894 1.1 christos static isc_result_t 895 1.1 christos unknown_fromtext(dns_rdataclass_t rdclass, dns_rdatatype_t type, 896 1.1 christos isc_lex_t *lexer, isc_mem_t *mctx, isc_buffer_t *target) { 897 1.1 christos isc_result_t result; 898 1.1 christos isc_buffer_t *buf = NULL; 899 1.1 christos isc_token_t token; 900 1.1 christos 901 1.1 christos if (type == 0 || dns_rdatatype_ismeta(type)) { 902 1.1 christos return (DNS_R_METATYPE); 903 1.1 christos } 904 1.1 christos 905 1.1 christos RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 906 1.1 christos false)); 907 1.1 christos if (token.value.as_ulong > 65535U) { 908 1.1 christos return (ISC_R_RANGE); 909 1.1 christos } 910 1.1 christos isc_buffer_allocate(mctx, &buf, token.value.as_ulong); 911 1.1 christos 912 1.1 christos if (token.value.as_ulong != 0U) { 913 1.1 christos result = isc_hex_tobuffer(lexer, buf, 914 1.1 christos (unsigned int)token.value.as_ulong); 915 1.1 christos if (result != ISC_R_SUCCESS) { 916 1.1 christos goto failure; 917 1.1 christos } 918 1.1 christos if (isc_buffer_usedlength(buf) != token.value.as_ulong) { 919 1.1 christos result = ISC_R_UNEXPECTEDEND; 920 1.1 christos goto failure; 921 1.1 christos } 922 1.1 christos } 923 1.1 christos 924 1.1 christos if (dns_rdatatype_isknown(type)) { 925 1.1 christos result = rdata_validate(buf, target, rdclass, type); 926 1.1 christos } else { 927 1.1 christos isc_region_t r; 928 1.1 christos isc_buffer_usedregion(buf, &r); 929 1.1 christos result = isc_buffer_copyregion(target, &r); 930 1.1 christos } 931 1.1 christos if (result != ISC_R_SUCCESS) { 932 1.1 christos goto failure; 933 1.1 christos } 934 1.1 christos 935 1.1 christos isc_buffer_free(&buf); 936 1.1 christos return (ISC_R_SUCCESS); 937 1.1 christos 938 1.1 christos failure: 939 1.1 christos isc_buffer_free(&buf); 940 1.1 christos return (result); 941 1.1 christos } 942 1.1 christos 943 1.1 christos isc_result_t 944 1.1 christos dns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t rdclass, 945 1.1 christos dns_rdatatype_t type, isc_lex_t *lexer, 946 1.1 christos const dns_name_t *origin, unsigned int options, 947 1.1 christos isc_mem_t *mctx, isc_buffer_t *target, 948 1.1 christos dns_rdatacallbacks_t *callbacks) { 949 1.1 christos isc_result_t result = ISC_R_NOTIMPLEMENTED; 950 1.1 christos isc_region_t region; 951 1.1 christos isc_buffer_t st; 952 1.1 christos isc_token_t token; 953 1.1 christos unsigned int lexoptions = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | 954 1.1 christos ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE; 955 1.1 christos char *name; 956 1.1 christos unsigned long line; 957 1.1 christos void (*callback)(dns_rdatacallbacks_t *, const char *, ...); 958 1.1 christos isc_result_t tresult; 959 1.1 christos unsigned int length; 960 1.1 christos bool unknown; 961 1.1 christos 962 1.1 christos REQUIRE(origin == NULL || dns_name_isabsolute(origin)); 963 1.1 christos if (rdata != NULL) { 964 1.1 christos REQUIRE(DNS_RDATA_INITIALIZED(rdata)); 965 1.1 christos REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 966 1.1 christos } 967 1.1 christos if (callbacks != NULL) { 968 1.1 christos REQUIRE(callbacks->warn != NULL); 969 1.1 christos REQUIRE(callbacks->error != NULL); 970 1.1 christos } 971 1.1 christos 972 1.1 christos st = *target; 973 1.1 christos 974 1.1 christos if (callbacks != NULL) { 975 1.1 christos callback = callbacks->error; 976 1.1 christos } else { 977 1.1 christos callback = default_fromtext_callback; 978 1.1 christos } 979 1.1 christos 980 1.1 christos result = isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring, 981 1.1 christos true); 982 1.1 christos if (result != ISC_R_SUCCESS) { 983 1.1 christos name = isc_lex_getsourcename(lexer); 984 1.1 christos line = isc_lex_getsourceline(lexer); 985 1.1 christos fromtext_error(callback, callbacks, name, line, NULL, result); 986 1.1 christos return (result); 987 1.1 christos } 988 1.1 christos 989 1.1 christos unknown = false; 990 1.1 christos if (token.type == isc_tokentype_string && 991 1.1 christos strcmp(DNS_AS_STR(token), "\\#") == 0) 992 1.1 christos { 993 1.1 christos /* 994 1.1 christos * If this is a TXT record '\#' could be a escaped '#'. 995 1.1 christos * Look to see if the next token is a number and if so 996 1.1 christos * treat it as a unknown record format. 997 1.1 christos */ 998 1.1 christos if (type == dns_rdatatype_txt) { 999 1.1 christos result = isc_lex_getmastertoken( 1000 1.1 christos lexer, &token, isc_tokentype_number, false); 1001 1.1 christos if (result == ISC_R_SUCCESS) { 1002 1.1 christos isc_lex_ungettoken(lexer, &token); 1003 1.1 christos } 1004 1.1 christos } 1005 1.1 christos 1006 1.1 christos if (result == ISC_R_SUCCESS) { 1007 1.1 christos unknown = true; 1008 1.1 christos result = unknown_fromtext(rdclass, type, lexer, mctx, 1009 1.1 christos target); 1010 1.1 christos } else { 1011 1.1 christos options |= DNS_RDATA_UNKNOWNESCAPE; 1012 1.1 christos } 1013 1.1 christos } else { 1014 1.1 christos isc_lex_ungettoken(lexer, &token); 1015 1.1 christos } 1016 1.1 christos 1017 1.1 christos if (!unknown) { 1018 1.1 christos FROMTEXTSWITCH 1019 1.1 christos 1020 1.1 christos /* 1021 1.1 christos * Consume to end of line / file. 1022 1.1 christos * If not at end of line initially set error code. 1023 1.1 christos * Call callback via fromtext_error once if there was an error. 1024 1.1 christos */ 1025 1.1 christos } 1026 1.1 christos do { 1027 1.1 christos name = isc_lex_getsourcename(lexer); 1028 1.1 christos line = isc_lex_getsourceline(lexer); 1029 1.1 christos tresult = isc_lex_gettoken(lexer, lexoptions, &token); 1030 1.1 christos if (tresult != ISC_R_SUCCESS) { 1031 1.1 christos if (result == ISC_R_SUCCESS) { 1032 1.1 christos result = tresult; 1033 1.1 christos } 1034 1.1 christos if (callback != NULL) { 1035 1.1 christos fromtext_error(callback, callbacks, name, line, 1036 1.1 christos NULL, result); 1037 1.1 christos } 1038 1.1 christos break; 1039 1.1 christos } else if (token.type != isc_tokentype_eol && 1040 1.1 christos token.type != isc_tokentype_eof) 1041 1.1 christos { 1042 1.1 christos if (result == ISC_R_SUCCESS) { 1043 1.1 christos result = DNS_R_EXTRATOKEN; 1044 1.1 christos } 1045 1.1 christos if (callback != NULL) { 1046 1.1 christos fromtext_error(callback, callbacks, name, line, 1047 1.1 christos &token, result); 1048 1.1 christos callback = NULL; 1049 1.1 christos } 1050 1.1 christos } else if (result != ISC_R_SUCCESS && callback != NULL) { 1051 1.1 christos fromtext_error(callback, callbacks, name, line, &token, 1052 1.1 christos result); 1053 1.1 christos break; 1054 1.1 christos } else { 1055 1.1 christos if (token.type == isc_tokentype_eof) { 1056 1.1 christos fromtext_warneof(lexer, callbacks); 1057 1.1 christos } 1058 1.1 christos break; 1059 1.1 christos } 1060 1.1 christos } while (1); 1061 1.1 christos 1062 1.1 christos length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st); 1063 1.1 christos if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH) { 1064 1.1 christos result = ISC_R_NOSPACE; 1065 1.1 christos } 1066 1.1 christos 1067 1.1 christos if (rdata != NULL && result == ISC_R_SUCCESS) { 1068 1.1 christos region.base = isc_buffer_used(&st); 1069 1.1 christos region.length = length; 1070 1.1 christos dns_rdata_fromregion(rdata, rdclass, type, ®ion); 1071 1.1 christos } 1072 1.1 christos if (result != ISC_R_SUCCESS) { 1073 1.1 christos *target = st; 1074 1.1 christos } 1075 1.1 christos return (result); 1076 1.1 christos } 1077 1.1 christos 1078 1.1 christos static isc_result_t 1079 1.1 christos unknown_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, 1080 1.1 christos isc_buffer_t *target) { 1081 1.1 christos isc_result_t result; 1082 1.1 christos char buf[sizeof("65535")]; 1083 1.1 christos isc_region_t sr; 1084 1.1 christos 1085 1.1 christos strlcpy(buf, "\\# ", sizeof(buf)); 1086 1.1 christos result = str_totext(buf, target); 1087 1.1 christos if (result != ISC_R_SUCCESS) { 1088 1.1 christos return (result); 1089 1.1 christos } 1090 1.1 christos 1091 1.1 christos dns_rdata_toregion(rdata, &sr); 1092 1.1 christos INSIST(sr.length < 65536); 1093 1.1 christos snprintf(buf, sizeof(buf), "%u", sr.length); 1094 1.1 christos result = str_totext(buf, target); 1095 1.1 christos if (result != ISC_R_SUCCESS) { 1096 1.1 christos return (result); 1097 1.1 christos } 1098 1.1 christos 1099 1.1 christos if (sr.length != 0U) { 1100 1.1 christos if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 1101 1.1 christos result = str_totext(" ( ", target); 1102 1.1 christos } else { 1103 1.1 christos result = str_totext(" ", target); 1104 1.1 christos } 1105 1.1 christos 1106 1.1 christos if (result != ISC_R_SUCCESS) { 1107 1.1 christos return (result); 1108 1.1 christos } 1109 1.1 christos 1110 1.1 christos if (tctx->width == 0) { /* No splitting */ 1111 1.1 christos result = isc_hex_totext(&sr, 0, "", target); 1112 1.1 christos } else { 1113 1.1 christos result = isc_hex_totext(&sr, tctx->width - 2, 1114 1.1 christos tctx->linebreak, target); 1115 1.1 christos } 1116 1.1 christos if (result == ISC_R_SUCCESS && 1117 1.1 christos (tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) 1118 1.1 christos { 1119 1.1 christos result = str_totext(" )", target); 1120 1.1 christos } 1121 1.1 christos } 1122 1.1 christos return (result); 1123 1.1 christos } 1124 1.1 christos 1125 1.1 christos static isc_result_t 1126 1.1 christos rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, 1127 1.1 christos isc_buffer_t *target) { 1128 1.1 christos isc_result_t result = ISC_R_NOTIMPLEMENTED; 1129 1.1 christos bool use_default = false; 1130 1.1 christos unsigned int cur; 1131 1.1 christos 1132 1.1 christos REQUIRE(rdata != NULL); 1133 1.1 christos REQUIRE(tctx->origin == NULL || dns_name_isabsolute(tctx->origin)); 1134 1.1 christos 1135 1.1 christos /* 1136 1.1 christos * Some DynDNS meta-RRs have empty rdata. 1137 1.1 christos */ 1138 1.1 christos if ((rdata->flags & DNS_RDATA_UPDATE) != 0) { 1139 1.1 christos INSIST(rdata->length == 0); 1140 1.1 christos return (ISC_R_SUCCESS); 1141 1.1 christos } 1142 1.1 christos 1143 1.1 christos if ((tctx->flags & DNS_STYLEFLAG_UNKNOWNFORMAT) != 0) { 1144 1.1 christos return (unknown_totext(rdata, tctx, target)); 1145 1.1 christos } 1146 1.1 christos 1147 1.1 christos cur = isc_buffer_usedlength(target); 1148 1.1 christos 1149 1.1 christos TOTEXTSWITCH 1150 1.1 christos 1151 1.1 christos if (use_default || (result == ISC_R_NOTIMPLEMENTED)) { 1152 1.1 christos unsigned int u = isc_buffer_usedlength(target); 1153 1.1 christos 1154 1.1 christos INSIST(u >= cur); 1155 1.1 christos isc_buffer_subtract(target, u - cur); 1156 1.1 christos result = unknown_totext(rdata, tctx, target); 1157 1.1 christos } 1158 1.1 christos 1159 1.1 christos return (result); 1160 1.1 christos } 1161 1.1 christos 1162 1.1 christos isc_result_t 1163 1.1 christos dns_rdata_totext(dns_rdata_t *rdata, const dns_name_t *origin, 1164 1.1 christos isc_buffer_t *target) { 1165 1.1 christos dns_rdata_textctx_t tctx; 1166 1.1 christos 1167 1.1 christos REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 1168 1.1 christos 1169 1.1 christos /* 1170 1.1 christos * Set up formatting options for single-line output. 1171 1.1 christos */ 1172 1.1 christos tctx.origin = origin; 1173 1.1 christos tctx.flags = 0; 1174 1.1 christos tctx.width = 60; 1175 1.1 christos tctx.linebreak = " "; 1176 1.1 christos return (rdata_totext(rdata, &tctx, target)); 1177 1.1 christos } 1178 1.1 christos 1179 1.1 christos isc_result_t 1180 1.1 christos dns_rdata_tofmttext(dns_rdata_t *rdata, const dns_name_t *origin, 1181 1.1 christos dns_masterstyle_flags_t flags, unsigned int width, 1182 1.1 christos unsigned int split_width, const char *linebreak, 1183 1.1 christos isc_buffer_t *target) { 1184 1.1 christos dns_rdata_textctx_t tctx; 1185 1.1 christos 1186 1.1 christos REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 1187 1.1 christos 1188 1.1 christos /* 1189 1.1 christos * Set up formatting options for formatted output. 1190 1.1 christos */ 1191 1.1 christos tctx.origin = origin; 1192 1.1 christos tctx.flags = flags; 1193 1.1 christos if (split_width == 0xffffffff) { 1194 1.1 christos tctx.width = width; 1195 1.1 christos } else { 1196 1.1 christos tctx.width = split_width; 1197 1.1 christos } 1198 1.1 christos 1199 1.1 christos if ((flags & DNS_STYLEFLAG_MULTILINE) != 0) { 1200 1.1 christos tctx.linebreak = linebreak; 1201 1.1 christos } else { 1202 1.1 christos if (split_width == 0xffffffff) { 1203 1.1 christos tctx.width = 60; /* Used for hex word length only. */ 1204 1.1 christos } 1205 1.1 christos tctx.linebreak = " "; 1206 1.1 christos } 1207 1.1 christos return (rdata_totext(rdata, &tctx, target)); 1208 1.1 christos } 1209 1.1 christos 1210 1.1 christos isc_result_t 1211 1.1 christos dns_rdata_fromstruct(dns_rdata_t *rdata, dns_rdataclass_t rdclass, 1212 1.1 christos dns_rdatatype_t type, void *source, isc_buffer_t *target) { 1213 1.1 christos isc_result_t result = ISC_R_NOTIMPLEMENTED; 1214 1.1 christos isc_buffer_t st; 1215 1.1 christos isc_region_t region; 1216 1.1 christos bool use_default = false; 1217 1.1 christos unsigned int length; 1218 1.1 christos 1219 1.1 christos REQUIRE(source != NULL); 1220 1.1 christos if (rdata != NULL) { 1221 1.1 christos REQUIRE(DNS_RDATA_INITIALIZED(rdata)); 1222 1.1 christos REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 1223 1.1 christos } 1224 1.1 christos 1225 1.1 christos st = *target; 1226 1.1 christos 1227 1.1 christos FROMSTRUCTSWITCH 1228 1.1 christos 1229 1.1 christos if (use_default) { 1230 1.1 christos (void)NULL; 1231 1.1 christos } 1232 1.1 christos 1233 1.1 christos length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st); 1234 1.1 christos if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH) { 1235 1.1 christos result = ISC_R_NOSPACE; 1236 1.1 christos } 1237 1.1 christos 1238 1.1 christos if (rdata != NULL && result == ISC_R_SUCCESS) { 1239 1.1 christos region.base = isc_buffer_used(&st); 1240 1.1 christos region.length = length; 1241 1.1 christos dns_rdata_fromregion(rdata, rdclass, type, ®ion); 1242 1.1 christos } 1243 1.1 christos if (result != ISC_R_SUCCESS) { 1244 1.1 christos *target = st; 1245 1.1 christos } 1246 1.1 christos return (result); 1247 1.1 christos } 1248 1.1 christos 1249 1.1 christos isc_result_t 1250 1.1 christos dns_rdata_tostruct(const dns_rdata_t *rdata, void *target, isc_mem_t *mctx) { 1251 1.1 christos isc_result_t result = ISC_R_NOTIMPLEMENTED; 1252 1.1 christos bool use_default = false; 1253 1.1 christos 1254 1.1 christos REQUIRE(rdata != NULL); 1255 1.1 christos REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 1256 1.1 christos REQUIRE((rdata->flags & DNS_RDATA_UPDATE) == 0); 1257 1.1 christos 1258 1.1 christos TOSTRUCTSWITCH 1259 1.1 christos 1260 1.1 christos if (use_default) { 1261 1.1 christos (void)NULL; 1262 1.1 christos } 1263 1.1 christos 1264 1.1 christos return (result); 1265 1.1 christos } 1266 1.1 christos 1267 1.1 christos void 1268 1.1 christos dns_rdata_freestruct(void *source) { 1269 1.1 christos dns_rdatacommon_t *common = source; 1270 1.1 christos REQUIRE(common != NULL); 1271 1.1 christos 1272 1.1 christos FREESTRUCTSWITCH 1273 1.1 christos } 1274 1.1 christos 1275 1.1 christos isc_result_t 1276 1.1 christos dns_rdata_additionaldata(dns_rdata_t *rdata, dns_additionaldatafunc_t add, 1277 1.1 christos void *arg) { 1278 1.1 christos isc_result_t result = ISC_R_NOTIMPLEMENTED; 1279 1.1 christos bool use_default = false; 1280 1.1 christos 1281 1.1 christos /* 1282 1.1 christos * Call 'add' for each name and type from 'rdata' which is subject to 1283 1.1 christos * additional section processing. 1284 1.1 christos */ 1285 1.1 christos 1286 1.1 christos REQUIRE(rdata != NULL); 1287 1.1 christos REQUIRE(add != NULL); 1288 1.1 christos REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 1289 1.1 christos 1290 1.1 christos ADDITIONALDATASWITCH 1291 1.1 christos 1292 1.1 christos /* No additional processing for unknown types */ 1293 1.1 christos if (use_default) { 1294 1.1 christos result = ISC_R_SUCCESS; 1295 1.1 christos } 1296 1.1 christos 1297 1.1 christos return (result); 1298 1.1 christos } 1299 1.1 christos 1300 1.1 christos isc_result_t 1301 1.1 christos dns_rdata_digest(dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg) { 1302 1.1 christos isc_result_t result = ISC_R_NOTIMPLEMENTED; 1303 1.1 christos bool use_default = false; 1304 1.1 christos isc_region_t r; 1305 1.1 christos 1306 1.1 christos /* 1307 1.1 christos * Send 'rdata' in DNSSEC canonical form to 'digest'. 1308 1.1 christos */ 1309 1.1 christos 1310 1.1 christos REQUIRE(rdata != NULL); 1311 1.1 christos REQUIRE(digest != NULL); 1312 1.1 christos REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 1313 1.1 christos 1314 1.1 christos DIGESTSWITCH 1315 1.1 christos 1316 1.1 christos if (use_default) { 1317 1.1 christos dns_rdata_toregion(rdata, &r); 1318 1.1 christos result = (digest)(arg, &r); 1319 1.1 christos } 1320 1.1 christos 1321 1.1 christos return (result); 1322 1.1 christos } 1323 1.1 christos 1324 1.1 christos bool 1325 1.1 christos dns_rdata_checkowner(const dns_name_t *name, dns_rdataclass_t rdclass, 1326 1.1 christos dns_rdatatype_t type, bool wildcard) { 1327 1.1 christos bool result; 1328 1.1 christos 1329 1.1 christos CHECKOWNERSWITCH 1330 1.1 christos return (result); 1331 1.1 christos } 1332 1.1 christos 1333 1.1 christos bool 1334 1.1 christos dns_rdata_checknames(dns_rdata_t *rdata, const dns_name_t *owner, 1335 1.1 christos dns_name_t *bad) { 1336 1.1 christos bool result; 1337 1.1 christos 1338 1.1 christos CHECKNAMESSWITCH 1339 1.1 christos return (result); 1340 1.1 christos } 1341 1.1 christos 1342 1.1 christos unsigned int 1343 1.1 christos dns_rdatatype_attributes(dns_rdatatype_t type) { 1344 1.1 christos RDATATYPE_ATTRIBUTE_SW 1345 1.1 christos if (type >= (dns_rdatatype_t)128 && type <= (dns_rdatatype_t)255) { 1346 1.1 christos return (DNS_RDATATYPEATTR_UNKNOWN | DNS_RDATATYPEATTR_META); 1347 1.1 christos } 1348 1.1 christos return (DNS_RDATATYPEATTR_UNKNOWN); 1349 1.1 christos } 1350 1.1 christos 1351 1.1 christos isc_result_t 1352 1.1 christos dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source) { 1353 1.1 christos unsigned int hash; 1354 1.1 christos unsigned int n; 1355 1.1 christos unsigned char a, b; 1356 1.1 christos 1357 1.1 christos n = source->length; 1358 1.1 christos 1359 1.1 christos if (n == 0) { 1360 1.1 christos return (DNS_R_UNKNOWN); 1361 1.1 christos } 1362 1.1 christos 1363 1.1 christos a = tolower((unsigned char)source->base[0]); 1364 1.1 christos b = tolower((unsigned char)source->base[n - 1]); 1365 1.1 christos 1366 1.1 christos hash = ((a + n) * b) % 256; 1367 1.1 christos 1368 1.1 christos /* 1369 1.1 christos * This switch block is inlined via \#define, and will use "return" 1370 1.1 christos * to return a result to the caller if it is a valid (known) 1371 1.1 christos * rdatatype name. 1372 1.1 christos */ 1373 1.1 christos RDATATYPE_FROMTEXT_SW(hash, source->base, n, typep); 1374 1.1 christos 1375 1.1 christos if (source->length > 4 && source->length < (4 + sizeof("65000")) && 1376 1.1 christos strncasecmp("type", source->base, 4) == 0) 1377 1.1 christos { 1378 1.1 christos char buf[sizeof("65000")]; 1379 1.1 christos char *endp; 1380 1.1 christos unsigned int val; 1381 1.1 christos 1382 1.1 christos /* 1383 1.1 christos * source->base is not required to be NUL terminated. 1384 1.1 christos * Copy up to remaining bytes and NUL terminate. 1385 1.1 christos */ 1386 1.1 christos snprintf(buf, sizeof(buf), "%.*s", (int)(source->length - 4), 1387 1.1 christos source->base + 4); 1388 1.1 christos val = strtoul(buf, &endp, 10); 1389 1.1 christos if (*endp == '\0' && val <= 0xffff) { 1390 1.1 christos *typep = (dns_rdatatype_t)val; 1391 1.1 christos return (ISC_R_SUCCESS); 1392 1.1 christos } 1393 1.1 christos } 1394 1.1 christos 1395 1.1 christos return (DNS_R_UNKNOWN); 1396 1.1 christos } 1397 1.1 christos 1398 1.1 christos isc_result_t 1399 1.1 christos dns_rdatatype_totext(dns_rdatatype_t type, isc_buffer_t *target) { 1400 1.1 christos RDATATYPE_TOTEXT_SW 1401 1.1 christos 1402 1.1 christos return (dns_rdatatype_tounknowntext(type, target)); 1403 1.1 christos } 1404 1.1 christos 1405 1.1 christos isc_result_t 1406 1.1 christos dns_rdatatype_tounknowntext(dns_rdatatype_t type, isc_buffer_t *target) { 1407 1.1 christos char buf[sizeof("TYPE65535")]; 1408 1.1 christos 1409 1.1 christos snprintf(buf, sizeof(buf), "TYPE%u", type); 1410 1.1 christos return (str_totext(buf, target)); 1411 1.1 christos } 1412 1.1 christos 1413 1.1 christos void 1414 1.1 christos dns_rdatatype_format(dns_rdatatype_t rdtype, char *array, unsigned int size) { 1415 1.1 christos isc_result_t result; 1416 1.1 christos isc_buffer_t buf; 1417 1.1 christos 1418 1.1 christos if (size == 0U) { 1419 1.1 christos return; 1420 1.1 christos } 1421 1.1 christos 1422 1.1 christos isc_buffer_init(&buf, array, size); 1423 1.1 christos result = dns_rdatatype_totext(rdtype, &buf); 1424 1.1 christos /* 1425 1.1 christos * Null terminate. 1426 1.1 christos */ 1427 1.1 christos if (result == ISC_R_SUCCESS) { 1428 1.1 christos if (isc_buffer_availablelength(&buf) >= 1) { 1429 1.1 christos isc_buffer_putuint8(&buf, 0); 1430 1.1 christos } else { 1431 1.1 christos result = ISC_R_NOSPACE; 1432 1.1 christos } 1433 1.1 christos } 1434 1.1 christos if (result != ISC_R_SUCCESS) { 1435 1.1 christos strlcpy(array, "<unknown>", size); 1436 1.1 christos } 1437 1.1 christos } 1438 1.1 christos 1439 1.1 christos /* 1440 1.1 christos * Private function. 1441 1.1 christos */ 1442 1.1 christos 1443 1.1 christos static unsigned int 1444 1.1 christos name_length(const dns_name_t *name) { 1445 1.1 christos return (name->length); 1446 1.1 christos } 1447 1.1 christos 1448 1.1 christos static isc_result_t 1449 1.1 christos commatxt_totext(isc_region_t *source, bool quote, bool comma, 1450 1.1 christos isc_buffer_t *target) { 1451 1.1 christos unsigned int tl; 1452 1.1 christos unsigned int n; 1453 1.1 christos unsigned char *sp; 1454 1.1 christos char *tp; 1455 1.1 christos isc_region_t region; 1456 1.1 christos 1457 1.1 christos isc_buffer_availableregion(target, ®ion); 1458 1.1 christos sp = source->base; 1459 1.1 christos tp = (char *)region.base; 1460 1.1 christos tl = region.length; 1461 1.1 christos 1462 1.1 christos n = *sp++; 1463 1.1 christos 1464 1.1 christos REQUIRE(n + 1 <= source->length); 1465 1.1 christos if (n == 0U) { 1466 1.1 christos REQUIRE(quote); 1467 1.1 christos } 1468 1.1 christos 1469 1.1 christos if (quote) { 1470 1.1 christos if (tl < 1) { 1471 1.1 christos return (ISC_R_NOSPACE); 1472 1.1 christos } 1473 1.1 christos *tp++ = '"'; 1474 1.1 christos tl--; 1475 1.1 christos } 1476 1.1 christos while (n--) { 1477 1.1 christos /* 1478 1.1 christos * \DDD space (0x20) if not quoting. 1479 1.1 christos */ 1480 1.1 christos if (*sp < (quote ? ' ' : '!') || *sp >= 0x7f) { 1481 1.1 christos if (tl < 4) { 1482 1.1 christos return (ISC_R_NOSPACE); 1483 1.1 christos } 1484 1.1 christos *tp++ = '\\'; 1485 1.1 christos *tp++ = '0' + ((*sp / 100) % 10); 1486 1.1 christos *tp++ = '0' + ((*sp / 10) % 10); 1487 1.1 christos *tp++ = '0' + (*sp % 10); 1488 1.1 christos sp++; 1489 1.1 christos tl -= 4; 1490 1.1 christos continue; 1491 1.1 christos } 1492 1.1 christos /* 1493 1.1 christos * Escape double quote and backslash. If we are not 1494 1.1 christos * enclosing the string in double quotes, also escape 1495 1.1 christos * at sign (@) and semicolon (;) unless comma is set. 1496 1.1 christos * If comma is set, then only escape commas (,). 1497 1.1 christos */ 1498 1.1 christos if (*sp == '"' || *sp == '\\' || (comma && *sp == ',') || 1499 1.1 christos (!comma && !quote && (*sp == '@' || *sp == ';'))) 1500 1.1 christos { 1501 1.1 christos if (tl < 2) { 1502 1.1 christos return (ISC_R_NOSPACE); 1503 1.1 christos } 1504 1.1 christos *tp++ = '\\'; 1505 1.1 christos tl--; 1506 1.1 christos /* 1507 1.1 christos * Perform comma escape processing. 1508 1.1 christos * ',' => '\\,' 1509 1.1 christos * '\' => '\\\\' 1510 1.1 christos */ 1511 1.1 christos if (comma && (*sp == ',' || *sp == '\\')) { 1512 1.1 christos if (tl < ((*sp == '\\') ? 3 : 2)) { 1513 1.1 christos return (ISC_R_NOSPACE); 1514 1.1 christos } 1515 1.1 christos *tp++ = '\\'; 1516 1.1 christos tl--; 1517 1.1 christos if (*sp == '\\') { 1518 1.1 christos *tp++ = '\\'; 1519 1.1 christos tl--; 1520 1.1 christos } 1521 1.1 christos } 1522 1.1 christos } 1523 1.1 christos if (tl < 1) { 1524 1.1 christos return (ISC_R_NOSPACE); 1525 1.1 christos } 1526 1.1 christos *tp++ = *sp++; 1527 1.1 christos tl--; 1528 1.1 christos } 1529 1.1 christos if (quote) { 1530 1.1 christos if (tl < 1) { 1531 1.1 christos return (ISC_R_NOSPACE); 1532 1.1 christos } 1533 1.1 christos *tp++ = '"'; 1534 1.1 christos tl--; 1535 1.1 christos POST(tl); 1536 1.1 christos } 1537 1.1 christos isc_buffer_add(target, (unsigned int)(tp - (char *)region.base)); 1538 1.1 christos isc_region_consume(source, *source->base + 1); 1539 1.1 christos return (ISC_R_SUCCESS); 1540 1.1 christos } 1541 1.1 christos 1542 1.1 christos static isc_result_t 1543 1.1 christos txt_totext(isc_region_t *source, bool quote, isc_buffer_t *target) { 1544 1.1 christos return (commatxt_totext(source, quote, false, target)); 1545 1.1 christos } 1546 1.1 christos 1547 1.1 christos static isc_result_t 1548 1.1 christos commatxt_fromtext(isc_textregion_t *source, bool comma, isc_buffer_t *target) { 1549 1.1 christos isc_region_t tregion; 1550 1.1 christos bool escape = false, comma_escape = false, seen_comma = false; 1551 1.1 christos unsigned int n, nrem; 1552 1.1 christos char *s; 1553 1.1 christos unsigned char *t; 1554 1.1 christos int d; 1555 1.1 christos int c; 1556 1.1 christos 1557 1.1 christos isc_buffer_availableregion(target, &tregion); 1558 1.1 christos s = source->base; 1559 1.1 christos n = source->length; 1560 1.1 christos t = tregion.base; 1561 1.1 christos nrem = tregion.length; 1562 1.1 christos if (nrem < 1) { 1563 1.1 christos return (ISC_R_NOSPACE); 1564 1.1 christos } 1565 1.1 christos /* 1566 1.1 christos * Length byte. 1567 1.1 christos */ 1568 1.1 christos nrem--; 1569 1.1 christos t++; 1570 1.1 christos /* 1571 1.1 christos * Maximum text string length. 1572 1.1 christos */ 1573 1.1 christos if (nrem > 255) { 1574 1.1 christos nrem = 255; 1575 1.1 christos } 1576 1.1 christos while (n-- != 0) { 1577 1.1 christos c = (*s++) & 0xff; 1578 1.1 christos if (escape && (d = decvalue((char)c)) != -1) { 1579 1.1 christos c = d; 1580 1.1 christos if (n == 0) { 1581 1.1 christos return (DNS_R_SYNTAX); 1582 1.1 christos } 1583 1.1 christos n--; 1584 1.1 christos if ((d = decvalue(*s++)) != -1) { 1585 1.1 christos c = c * 10 + d; 1586 1.1 christos } else { 1587 1.1 christos return (DNS_R_SYNTAX); 1588 1.1 christos } 1589 1.1 christos if (n == 0) { 1590 1.1 christos return (DNS_R_SYNTAX); 1591 1.1 christos } 1592 1.1 christos n--; 1593 1.1 christos if ((d = decvalue(*s++)) != -1) { 1594 1.1 christos c = c * 10 + d; 1595 1.1 christos } else { 1596 1.1 christos return (DNS_R_SYNTAX); 1597 1.1 christos } 1598 1.1 christos if (c > 255) { 1599 1.1 christos return (DNS_R_SYNTAX); 1600 1.1 christos } 1601 1.1 christos } else if (!escape && c == '\\') { 1602 1.1 christos escape = true; 1603 1.1 christos continue; 1604 1.1 christos } 1605 1.1 christos escape = false; 1606 1.1 christos /* 1607 1.1 christos * Level 1 escape processing complete. 1608 1.1 christos * If comma is set perform comma escape processing. 1609 1.1 christos * 1610 1.1 christos * Level 1 Level 2 ALPN's 1611 1.1 christos * h1\,h2 => h1,h2 => h1 and h2 1612 1.1 christos * h1\\,h2 => h1\,h2 => h1,h2 1613 1.1 christos * h1\\h2 => h1\h2 => h1h2 1614 1.1 christos * h1\\\\h2 => h1\\h2 => h1\h2 1615 1.1 christos */ 1616 1.1 christos if (comma && !comma_escape && c == ',') { 1617 1.1 christos seen_comma = true; 1618 1.1 christos break; 1619 1.1 christos } 1620 1.1 christos if (comma && !comma_escape && c == '\\') { 1621 1.1 christos comma_escape = true; 1622 1.1 christos continue; 1623 1.1 christos } 1624 1.1 christos comma_escape = false; 1625 1.1 christos if (nrem == 0) { 1626 1.1 christos return ((tregion.length <= 256U) ? ISC_R_NOSPACE 1627 1.1 christos : DNS_R_SYNTAX); 1628 1.1 christos } 1629 1.1 christos *t++ = c; 1630 1.1 christos nrem--; 1631 1.1 christos } 1632 1.1 christos 1633 1.1 christos /* 1634 1.1 christos * Incomplete escape processing? 1635 1.1 christos */ 1636 1.1 christos if (escape || (comma && comma_escape)) { 1637 1.1 christos return (DNS_R_SYNTAX); 1638 1.1 christos } 1639 1.1 christos 1640 1.1 christos if (comma) { 1641 1.1 christos /* 1642 1.1 christos * Disallow empty ALPN at start (",h1") or in the 1643 1.1 christos * middle ("h1,,h2"). 1644 1.1 christos */ 1645 1.1 christos if (s == source->base || (seen_comma && s == source->base + 1)) 1646 1.1 christos { 1647 1.1 christos return (DNS_R_SYNTAX); 1648 1.1 christos } 1649 1.1 christos isc_textregion_consume(source, s - source->base); 1650 1.1 christos /* 1651 1.1 christos * Disallow empty ALPN at end ("h1,"). 1652 1.1 christos */ 1653 1.1 christos if (seen_comma && source->length == 0) { 1654 1.1 christos return (DNS_R_SYNTAX); 1655 1.1 christos } 1656 1.1 christos } 1657 1.1 christos *tregion.base = (unsigned char)(t - tregion.base - 1); 1658 1.1 christos isc_buffer_add(target, *tregion.base + 1); 1659 1.1 christos return (ISC_R_SUCCESS); 1660 1.1 christos } 1661 1.1 christos 1662 1.1 christos static isc_result_t 1663 1.1 christos txt_fromtext(isc_textregion_t *source, isc_buffer_t *target) { 1664 1.1 christos return (commatxt_fromtext(source, false, target)); 1665 1.1 christos } 1666 1.1 christos 1667 1.1 christos static isc_result_t 1668 1.1 christos txt_fromwire(isc_buffer_t *source, isc_buffer_t *target) { 1669 1.1 christos unsigned int n; 1670 1.1 christos isc_region_t sregion; 1671 1.1 christos isc_region_t tregion; 1672 1.1 christos 1673 1.1 christos isc_buffer_activeregion(source, &sregion); 1674 1.1 christos if (sregion.length == 0) { 1675 1.1 christos return (ISC_R_UNEXPECTEDEND); 1676 1.1 christos } 1677 1.1 christos n = *sregion.base + 1; 1678 1.1 christos if (n > sregion.length) { 1679 1.1 christos return (ISC_R_UNEXPECTEDEND); 1680 1.1 christos } 1681 1.1 christos 1682 1.1 christos isc_buffer_availableregion(target, &tregion); 1683 1.1 christos if (n > tregion.length) { 1684 1.1 christos return (ISC_R_NOSPACE); 1685 1.1 christos } 1686 1.1 christos 1687 1.1 christos if (tregion.base != sregion.base) { 1688 1.1 christos memmove(tregion.base, sregion.base, n); 1689 1.1 christos } 1690 1.1 christos isc_buffer_forward(source, n); 1691 1.1 christos isc_buffer_add(target, n); 1692 1.1 christos return (ISC_R_SUCCESS); 1693 1.1 christos } 1694 1.1 christos 1695 1.1 christos /* 1696 1.1 christos * Conversion of TXT-like rdata fields without length limits. 1697 1.1 christos */ 1698 1.1 christos static isc_result_t 1699 1.1 christos multitxt_totext(isc_region_t *source, isc_buffer_t *target) { 1700 1.1 christos unsigned int tl; 1701 1.1 christos unsigned int n0, n; 1702 1.1 christos unsigned char *sp; 1703 1.1 christos char *tp; 1704 1.1 christos isc_region_t region; 1705 1.1 christos 1706 1.1 christos isc_buffer_availableregion(target, ®ion); 1707 1.1 christos sp = source->base; 1708 1.1 christos tp = (char *)region.base; 1709 1.1 christos tl = region.length; 1710 1.1 christos 1711 1.1 christos if (tl < 1) { 1712 1.1 christos return (ISC_R_NOSPACE); 1713 1.1 christos } 1714 1.1 christos *tp++ = '"'; 1715 1.1 christos tl--; 1716 1.1 christos do { 1717 1.1 christos n = source->length; 1718 1.1 christos n0 = source->length - 1; 1719 1.1 christos 1720 1.1 christos while (n--) { 1721 1.1 christos if (*sp < ' ' || *sp >= 0x7f) { 1722 1.1 christos if (tl < 4) { 1723 1.1 christos return (ISC_R_NOSPACE); 1724 1.1 christos } 1725 1.1 christos *tp++ = '\\'; 1726 1.1 christos *tp++ = '0' + ((*sp / 100) % 10); 1727 1.1 christos *tp++ = '0' + ((*sp / 10) % 10); 1728 1.1 christos *tp++ = '0' + (*sp % 10); 1729 1.1 christos sp++; 1730 1.1 christos tl -= 4; 1731 1.1 christos continue; 1732 1.1 christos } 1733 1.1 christos /* double quote, backslash */ 1734 1.1 christos if (*sp == '"' || *sp == '\\') { 1735 1.1 christos if (tl < 2) { 1736 1.1 christos return (ISC_R_NOSPACE); 1737 1.1 christos } 1738 1.1 christos *tp++ = '\\'; 1739 1.1 christos tl--; 1740 1.1 christos } 1741 1.1 christos if (tl < 1) { 1742 1.1 christos return (ISC_R_NOSPACE); 1743 1.1 christos } 1744 1.1 christos *tp++ = *sp++; 1745 1.1 christos tl--; 1746 1.1 christos } 1747 1.1 christos isc_region_consume(source, n0 + 1); 1748 1.1 christos } while (source->length != 0); 1749 1.1 christos if (tl < 1) { 1750 1.1 christos return (ISC_R_NOSPACE); 1751 1.1 christos } 1752 1.1 christos *tp++ = '"'; 1753 1.1 christos tl--; 1754 1.1 christos POST(tl); 1755 1.1 christos isc_buffer_add(target, (unsigned int)(tp - (char *)region.base)); 1756 1.1 christos return (ISC_R_SUCCESS); 1757 1.1 christos } 1758 1.1 christos 1759 1.1 christos static isc_result_t 1760 1.1 christos multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target) { 1761 1.1 christos isc_region_t tregion; 1762 1.1 christos bool escape; 1763 1.1 christos unsigned int n, nrem; 1764 1.1 christos char *s; 1765 1.1 christos unsigned char *t0, *t; 1766 1.1 christos int d; 1767 1.1 christos int c; 1768 1.1 christos 1769 1.1 christos s = source->base; 1770 1.1 christos n = source->length; 1771 1.1 christos escape = false; 1772 1.1 christos 1773 1.1 christos do { 1774 1.1 christos isc_buffer_availableregion(target, &tregion); 1775 1.1 christos t0 = t = tregion.base; 1776 1.1 christos nrem = tregion.length; 1777 1.1 christos if (nrem < 1) { 1778 1.1 christos return (ISC_R_NOSPACE); 1779 1.1 christos } 1780 1.1 christos 1781 1.1 christos while (n != 0) { 1782 1.1 christos --n; 1783 1.1 christos c = (*s++) & 0xff; 1784 1.1 christos if (escape && (d = decvalue((char)c)) != -1) { 1785 1.1 christos c = d; 1786 1.1 christos if (n == 0) { 1787 1.1 christos return (DNS_R_SYNTAX); 1788 1.1 christos } 1789 1.1 christos n--; 1790 1.1 christos if ((d = decvalue(*s++)) != -1) { 1791 1.1 christos c = c * 10 + d; 1792 1.1 christos } else { 1793 1.1 christos return (DNS_R_SYNTAX); 1794 1.1 christos } 1795 1.1 christos if (n == 0) { 1796 1.1 christos return (DNS_R_SYNTAX); 1797 1.1 christos } 1798 1.1 christos n--; 1799 1.1 christos if ((d = decvalue(*s++)) != -1) { 1800 1.1 christos c = c * 10 + d; 1801 1.1 christos } else { 1802 1.1 christos return (DNS_R_SYNTAX); 1803 1.1 christos } 1804 1.1 christos if (c > 255) { 1805 1.1 christos return (DNS_R_SYNTAX); 1806 1.1 christos } 1807 1.1 christos } else if (!escape && c == '\\') { 1808 1.1 christos escape = true; 1809 1.1 christos continue; 1810 1.1 christos } 1811 1.1 christos escape = false; 1812 1.1 christos *t++ = c; 1813 1.1 christos nrem--; 1814 1.1 christos if (nrem == 0) { 1815 1.1 christos break; 1816 1.1 christos } 1817 1.1 christos } 1818 1.1 christos if (escape) { 1819 1.1 christos return (DNS_R_SYNTAX); 1820 1.1 christos } 1821 1.1 christos 1822 1.1 christos isc_buffer_add(target, (unsigned int)(t - t0)); 1823 1.1 christos } while (n != 0); 1824 1.1 christos return (ISC_R_SUCCESS); 1825 1.1 christos } 1826 1.1 christos 1827 1.1 christos static bool 1828 1.1 christos name_prefix(dns_name_t *name, const dns_name_t *origin, dns_name_t *target) { 1829 1.1 christos int l1, l2; 1830 1.1 christos 1831 1.1 christos if (origin == NULL) { 1832 1.1 christos goto return_false; 1833 1.1 christos } 1834 1.1 christos 1835 1.1 christos if (dns_name_compare(origin, dns_rootname) == 0) { 1836 1.1 christos goto return_false; 1837 1.1 christos } 1838 1.1 christos 1839 1.1 christos if (!dns_name_issubdomain(name, origin)) { 1840 1.1 christos goto return_false; 1841 1.1 christos } 1842 1.1 christos 1843 1.1 christos l1 = dns_name_countlabels(name); 1844 1.1 christos l2 = dns_name_countlabels(origin); 1845 1.1 christos 1846 1.1 christos if (l1 == l2) { 1847 1.1 christos goto return_false; 1848 1.1 christos } 1849 1.1 christos 1850 1.1 christos /* Master files should be case preserving. */ 1851 1.1 christos dns_name_getlabelsequence(name, l1 - l2, l2, target); 1852 1.1 christos if (!dns_name_caseequal(origin, target)) { 1853 1.1 christos goto return_false; 1854 1.1 christos } 1855 1.1 christos 1856 1.1 christos dns_name_getlabelsequence(name, 0, l1 - l2, target); 1857 1.1 christos return (true); 1858 1.1 christos 1859 1.1 christos return_false: 1860 1.1 christos *target = *name; 1861 1.1 christos return (false); 1862 1.1 christos } 1863 1.1 christos 1864 1.1 christos static isc_result_t 1865 1.1 christos str_totext(const char *source, isc_buffer_t *target) { 1866 1.1 christos unsigned int l; 1867 1.1 christos isc_region_t region; 1868 1.1 christos 1869 1.1 christos isc_buffer_availableregion(target, ®ion); 1870 1.1 christos l = strlen(source); 1871 1.1 christos 1872 1.1 christos if (l > region.length) { 1873 1.1 christos return (ISC_R_NOSPACE); 1874 1.1 christos } 1875 1.1 christos 1876 1.1 christos memmove(region.base, source, l); 1877 1.1 christos isc_buffer_add(target, l); 1878 1.1 christos return (ISC_R_SUCCESS); 1879 1.1 christos } 1880 1.1 christos 1881 1.1 christos static isc_result_t 1882 1.1 christos inet_totext(int af, uint32_t flags, isc_region_t *src, isc_buffer_t *target) { 1883 1.1 christos char tmpbuf[64]; 1884 1.1 christos 1885 1.1 christos /* Note - inet_ntop doesn't do size checking on its input. */ 1886 1.1 christos if (inet_ntop(af, src->base, tmpbuf, sizeof(tmpbuf)) == NULL) { 1887 1.1 christos return (ISC_R_NOSPACE); 1888 1.1 christos } 1889 1.1 christos if (strlen(tmpbuf) > isc_buffer_availablelength(target)) { 1890 1.1 christos return (ISC_R_NOSPACE); 1891 1.1 christos } 1892 1.1 christos isc_buffer_putstr(target, tmpbuf); 1893 1.1 christos 1894 1.1 christos /* 1895 1.1 christos * An IPv6 address ending in "::" breaks YAML 1896 1.1 christos * parsing, so append 0 in that case. 1897 1.1 christos */ 1898 1.1 christos if (af == AF_INET6 && (flags & DNS_STYLEFLAG_YAML) != 0) { 1899 1.1 christos isc_region_t r; 1900 1.1 christos isc_buffer_usedregion(target, &r); 1901 1.1 christos if (r.length > 0 && r.base[r.length - 1] == ':') { 1902 1.1 christos if (isc_buffer_availablelength(target) == 0) { 1903 1.1 christos return (ISC_R_NOSPACE); 1904 1.1 christos } 1905 1.1 christos isc_buffer_putmem(target, (const unsigned char *)"0", 1906 1.1 christos 1); 1907 1.1 christos } 1908 1.1 christos } 1909 1.1 christos 1910 1.1 christos return (ISC_R_SUCCESS); 1911 1.1 christos } 1912 1.1 christos 1913 1.1 christos static bool 1914 1.1 christos buffer_empty(isc_buffer_t *source) { 1915 1.1 christos return ((source->current == source->active) ? true : false); 1916 1.1 christos } 1917 1.1 christos 1918 1.1 christos static void 1919 1.1 christos buffer_fromregion(isc_buffer_t *buffer, isc_region_t *region) { 1920 1.1 christos isc_buffer_init(buffer, region->base, region->length); 1921 1.1 christos isc_buffer_add(buffer, region->length); 1922 1.1 christos isc_buffer_setactive(buffer, region->length); 1923 1.1 christos } 1924 1.1 christos 1925 1.1 christos static isc_result_t 1926 1.1 christos uint32_tobuffer(uint32_t value, isc_buffer_t *target) { 1927 1.1 christos isc_region_t region; 1928 1.1 christos 1929 1.1 christos isc_buffer_availableregion(target, ®ion); 1930 1.1 christos if (region.length < 4) { 1931 1.1 christos return (ISC_R_NOSPACE); 1932 1.1 christos } 1933 1.1 christos isc_buffer_putuint32(target, value); 1934 1.1 christos return (ISC_R_SUCCESS); 1935 1.1 christos } 1936 1.1 christos 1937 1.1 christos static isc_result_t 1938 1.1 christos uint16_tobuffer(uint32_t value, isc_buffer_t *target) { 1939 1.1 christos isc_region_t region; 1940 1.1 christos 1941 1.1 christos if (value > 0xffff) { 1942 1.1 christos return (ISC_R_RANGE); 1943 1.1 christos } 1944 1.1 christos isc_buffer_availableregion(target, ®ion); 1945 1.1 christos if (region.length < 2) { 1946 1.1 christos return (ISC_R_NOSPACE); 1947 1.1 christos } 1948 1.1 christos isc_buffer_putuint16(target, (uint16_t)value); 1949 1.1 christos return (ISC_R_SUCCESS); 1950 1.1 christos } 1951 1.1 christos 1952 1.1 christos static isc_result_t 1953 1.1 christos uint8_tobuffer(uint32_t value, isc_buffer_t *target) { 1954 1.1 christos isc_region_t region; 1955 1.1 christos 1956 1.1 christos if (value > 0xff) { 1957 1.1 christos return (ISC_R_RANGE); 1958 1.1 christos } 1959 1.1 christos isc_buffer_availableregion(target, ®ion); 1960 1.1 christos if (region.length < 1) { 1961 1.1 christos return (ISC_R_NOSPACE); 1962 1.1 christos } 1963 1.1 christos isc_buffer_putuint8(target, (uint8_t)value); 1964 1.1 christos return (ISC_R_SUCCESS); 1965 1.1 christos } 1966 1.1 christos 1967 1.1 christos static isc_result_t 1968 1.1 christos name_tobuffer(const dns_name_t *name, isc_buffer_t *target) { 1969 1.1 christos isc_region_t r; 1970 1.1 christos dns_name_toregion(name, &r); 1971 1.1 christos return (isc_buffer_copyregion(target, &r)); 1972 1.1 christos } 1973 1.1 christos 1974 1.1 christos static uint32_t 1975 1.1 christos uint32_fromregion(isc_region_t *region) { 1976 1.1 christos uint32_t value; 1977 1.1 christos 1978 1.1 christos REQUIRE(region->length >= 4); 1979 1.1 christos value = (uint32_t)region->base[0] << 24; 1980 1.1 christos value |= (uint32_t)region->base[1] << 16; 1981 1.1 christos value |= (uint32_t)region->base[2] << 8; 1982 1.1 christos value |= (uint32_t)region->base[3]; 1983 1.1 christos return (value); 1984 1.1 christos } 1985 1.1 christos 1986 1.1 christos static uint16_t 1987 1.1 christos uint16_consume_fromregion(isc_region_t *region) { 1988 1.1 christos uint16_t r = uint16_fromregion(region); 1989 1.1 christos 1990 1.1 christos isc_region_consume(region, 2); 1991 1.1 christos return (r); 1992 1.1 christos } 1993 1.1 christos 1994 1.1 christos static uint16_t 1995 1.1 christos uint16_fromregion(isc_region_t *region) { 1996 1.1 christos REQUIRE(region->length >= 2); 1997 1.1 christos 1998 1.1 christos return ((region->base[0] << 8) | region->base[1]); 1999 1.1 christos } 2000 1.1 christos 2001 1.1 christos static uint8_t 2002 1.1 christos uint8_fromregion(isc_region_t *region) { 2003 1.1 christos REQUIRE(region->length >= 1); 2004 1.1 christos 2005 1.1 christos return (region->base[0]); 2006 1.1 christos } 2007 1.1 christos 2008 1.1 christos static uint8_t 2009 1.1 christos uint8_consume_fromregion(isc_region_t *region) { 2010 1.1 christos uint8_t r = uint8_fromregion(region); 2011 1.1 christos 2012 1.1 christos isc_region_consume(region, 1); 2013 1.1 christos return (r); 2014 1.1 christos } 2015 1.1 christos 2016 1.1 christos static isc_result_t 2017 1.1 christos mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) { 2018 1.1 christos isc_region_t tr; 2019 1.1 christos 2020 1.1 christos if (length == 0U) { 2021 1.1 christos return (ISC_R_SUCCESS); 2022 1.1 christos } 2023 1.1 christos 2024 1.1 christos isc_buffer_availableregion(target, &tr); 2025 1.1 christos if (length > tr.length) { 2026 1.1 christos return (ISC_R_NOSPACE); 2027 1.1 christos } 2028 1.1 christos if (tr.base != base) { 2029 1.1 christos memmove(tr.base, base, length); 2030 1.1 christos } 2031 1.1 christos isc_buffer_add(target, length); 2032 1.1 christos return (ISC_R_SUCCESS); 2033 1.1 christos } 2034 1.1 christos 2035 1.1 christos static int 2036 1.1 christos hexvalue(char value) { 2037 1.1 christos const char *s; 2038 1.1 christos unsigned char c; 2039 1.1 christos 2040 1.1 christos c = (unsigned char)value; 2041 1.1 christos 2042 1.1 christos if (!isascii(c)) { 2043 1.1 christos return (-1); 2044 1.1 christos } 2045 1.1 christos if (isupper(c)) { 2046 1.1 christos c = tolower(c); 2047 1.1 christos } 2048 1.1 christos if ((s = strchr(hexdigits, c)) == NULL) { 2049 1.1 christos return (-1); 2050 1.1 christos } 2051 1.1 christos return ((int)(s - hexdigits)); 2052 1.1 christos } 2053 1.1 christos 2054 1.1 christos static int 2055 1.1 christos decvalue(char value) { 2056 1.1 christos const char *s; 2057 1.1 christos 2058 1.1 christos /* 2059 1.1 christos * isascii() is valid for full range of int values, no need to 2060 1.1 christos * mask or cast. 2061 1.1 christos */ 2062 1.1 christos if (!isascii(value)) { 2063 1.1 christos return (-1); 2064 1.1 christos } 2065 1.1 christos if ((s = strchr(decdigits, value)) == NULL) { 2066 1.1 christos return (-1); 2067 1.1 christos } 2068 1.1 christos return ((int)(s - decdigits)); 2069 1.1 christos } 2070 1.1 christos 2071 1.1 christos static void 2072 1.1 christos default_fromtext_callback(dns_rdatacallbacks_t *callbacks, const char *fmt, 2073 1.1 christos ...) { 2074 1.1 christos va_list ap; 2075 1.1 christos 2076 1.1 christos UNUSED(callbacks); 2077 1.1 christos 2078 1.1 christos va_start(ap, fmt); 2079 1.1 christos vfprintf(stderr, fmt, ap); 2080 1.1 christos va_end(ap); 2081 1.1 christos fprintf(stderr, "\n"); 2082 1.1 christos } 2083 1.1 christos 2084 1.1 christos static void 2085 1.1 christos fromtext_warneof(isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks) { 2086 1.1 christos if (isc_lex_isfile(lexer) && callbacks != NULL) { 2087 1.1 christos const char *name = isc_lex_getsourcename(lexer); 2088 1.1 christos if (name == NULL) { 2089 1.1 christos name = "UNKNOWN"; 2090 1.1 christos } 2091 1.1 christos (*callbacks->warn)(callbacks, 2092 1.1 christos "%s:%lu: file does not end with newline", 2093 1.1 christos name, isc_lex_getsourceline(lexer)); 2094 1.1 christos } 2095 1.1 christos } 2096 1.1 christos 2097 1.1 christos static void 2098 1.1 christos warn_badmx(isc_token_t *token, isc_lex_t *lexer, 2099 1.1 christos dns_rdatacallbacks_t *callbacks) { 2100 1.1 christos const char *file; 2101 1.1 christos unsigned long line; 2102 1.1 christos 2103 1.1 christos if (lexer != NULL) { 2104 1.1 christos file = isc_lex_getsourcename(lexer); 2105 1.1 christos line = isc_lex_getsourceline(lexer); 2106 1.1 christos (*callbacks->warn)(callbacks, "%s:%u: warning: '%s': %s", file, 2107 1.1 christos line, DNS_AS_STR(*token), 2108 1.1 christos dns_result_totext(DNS_R_MXISADDRESS)); 2109 1.1 christos } 2110 1.1 christos } 2111 1.1 christos 2112 1.1 christos static void 2113 1.1 christos warn_badname(const dns_name_t *name, isc_lex_t *lexer, 2114 1.1 christos dns_rdatacallbacks_t *callbacks) { 2115 1.1 christos const char *file; 2116 1.1 christos unsigned long line; 2117 1.1 christos char namebuf[DNS_NAME_FORMATSIZE]; 2118 1.1 christos 2119 1.1 christos if (lexer != NULL) { 2120 1.1 christos file = isc_lex_getsourcename(lexer); 2121 1.1 christos line = isc_lex_getsourceline(lexer); 2122 1.1 christos dns_name_format(name, namebuf, sizeof(namebuf)); 2123 1.1 christos (*callbacks->warn)(callbacks, "%s:%u: warning: %s: %s", file, 2124 1.1 christos line, namebuf, 2125 1.1 christos dns_result_totext(DNS_R_BADNAME)); 2126 1.1 christos } 2127 1.1 christos } 2128 1.1 christos 2129 1.1 christos static void 2130 1.1 christos fromtext_error(void (*callback)(dns_rdatacallbacks_t *, const char *, ...), 2131 1.1 christos dns_rdatacallbacks_t *callbacks, const char *name, 2132 1.1 christos unsigned long line, isc_token_t *token, isc_result_t result) { 2133 1.1 christos if (name == NULL) { 2134 1.1 christos name = "UNKNOWN"; 2135 1.1 christos } 2136 1.1 christos 2137 1.1 christos if (token != NULL) { 2138 1.1 christos switch (token->type) { 2139 1.1 christos case isc_tokentype_eol: 2140 1.1 christos (*callback)(callbacks, "%s: %s:%lu: near eol: %s", 2141 1.1 christos "dns_rdata_fromtext", name, line, 2142 1.1 christos dns_result_totext(result)); 2143 1.1 christos break; 2144 1.1 christos case isc_tokentype_eof: 2145 1.1 christos (*callback)(callbacks, "%s: %s:%lu: near eof: %s", 2146 1.1 christos "dns_rdata_fromtext", name, line, 2147 1.1 christos dns_result_totext(result)); 2148 1.1 christos break; 2149 1.1 christos case isc_tokentype_number: 2150 1.1 christos (*callback)(callbacks, "%s: %s:%lu: near %lu: %s", 2151 1.1 christos "dns_rdata_fromtext", name, line, 2152 1.1 christos token->value.as_ulong, 2153 1.1 christos dns_result_totext(result)); 2154 1.1 christos break; 2155 1.1 christos case isc_tokentype_string: 2156 1.1 christos case isc_tokentype_qstring: 2157 1.1 christos (*callback)(callbacks, "%s: %s:%lu: near '%s': %s", 2158 1.1 christos "dns_rdata_fromtext", name, line, 2159 1.1 christos DNS_AS_STR(*token), 2160 1.1 christos dns_result_totext(result)); 2161 1.1 christos break; 2162 1.1 christos default: 2163 1.1 christos (*callback)(callbacks, "%s: %s:%lu: %s", 2164 1.1 christos "dns_rdata_fromtext", name, line, 2165 1.1 christos dns_result_totext(result)); 2166 1.1 christos break; 2167 1.1 christos } 2168 1.1 christos } else { 2169 1.1 christos (*callback)(callbacks, "dns_rdata_fromtext: %s:%lu: %s", name, 2170 1.1 christos line, dns_result_totext(result)); 2171 1.1 christos } 2172 1.1 christos } 2173 1.1 christos 2174 1.1 christos dns_rdatatype_t 2175 1.1 christos dns_rdata_covers(dns_rdata_t *rdata) { 2176 1.1 christos if (rdata->type == dns_rdatatype_rrsig) { 2177 1.1 christos return (covers_rrsig(rdata)); 2178 1.1 christos } 2179 1.1 christos return (covers_sig(rdata)); 2180 1.1 christos } 2181 1.1 christos 2182 1.1 christos bool 2183 1.1 christos dns_rdatatype_ismeta(dns_rdatatype_t type) { 2184 1.1 christos if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_META) != 0) { 2185 1.1 christos return (true); 2186 1.1 christos } 2187 1.1 christos return (false); 2188 1.1 christos } 2189 1.1 christos 2190 1.1 christos bool 2191 1.1 christos dns_rdatatype_issingleton(dns_rdatatype_t type) { 2192 1.1 christos if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_SINGLETON) != 0) 2193 1.1 christos { 2194 1.1 christos return (true); 2195 1.1 christos } 2196 1.1 christos return (false); 2197 1.1 christos } 2198 1.1 christos 2199 1.1 christos bool 2200 1.1 christos dns_rdatatype_notquestion(dns_rdatatype_t type) { 2201 1.1 christos if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_NOTQUESTION) != 2202 1.1 christos 0) 2203 1.1 christos { 2204 1.1 christos return (true); 2205 1.1 christos } 2206 1.1 christos return (false); 2207 1.1 christos } 2208 1.1 christos 2209 1.1 christos bool 2210 1.1 christos dns_rdatatype_questiononly(dns_rdatatype_t type) { 2211 1.1 christos if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_QUESTIONONLY) != 2212 1.1 christos 0) 2213 1.1 christos { 2214 1.1 christos return (true); 2215 1.1 christos } 2216 1.1 christos return (false); 2217 1.1 christos } 2218 1.1 christos 2219 1.1 christos bool 2220 1.1 christos dns_rdatatype_atcname(dns_rdatatype_t type) { 2221 1.1 christos if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_ATCNAME) != 0) { 2222 1.1 christos return (true); 2223 1.1 christos } 2224 1.1 christos return (false); 2225 1.1 christos } 2226 1.1 christos 2227 1.1 christos bool 2228 1.1 christos dns_rdatatype_atparent(dns_rdatatype_t type) { 2229 1.1 christos if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_ATPARENT) != 0) 2230 1.1 christos { 2231 1.1 christos return (true); 2232 1.1 christos } 2233 1.1 christos return (false); 2234 1.1 christos } 2235 1.1 christos 2236 1.1 christos bool 2237 1.1 christos dns_rdatatype_followadditional(dns_rdatatype_t type) { 2238 1.1 christos if ((dns_rdatatype_attributes(type) & 2239 1.1 christos DNS_RDATATYPEATTR_FOLLOWADDITIONAL) != 0) 2240 1.1 christos { 2241 1.1 christos return (true); 2242 1.1 christos } 2243 1.1 christos return (false); 2244 1.1 christos } 2245 1.1 christos 2246 1.1 christos bool 2247 1.1 christos dns_rdataclass_ismeta(dns_rdataclass_t rdclass) { 2248 1.1 christos if (rdclass == dns_rdataclass_reserved0 || 2249 1.1 christos rdclass == dns_rdataclass_none || rdclass == dns_rdataclass_any) 2250 1.1 christos { 2251 1.1 christos return (true); 2252 1.1 christos } 2253 1.1 christos 2254 1.1 christos return (false); /* Assume it is not a meta class. */ 2255 1.1 christos } 2256 1.1 christos 2257 1.1 christos bool 2258 1.1 christos dns_rdatatype_isdnssec(dns_rdatatype_t type) { 2259 1.1 christos if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_DNSSEC) != 0) { 2260 1.1 christos return (true); 2261 1.1 christos } 2262 1.1 christos return (false); 2263 1.1 christos } 2264 1.1 christos 2265 1.1 christos bool 2266 1.1 christos dns_rdatatype_iszonecutauth(dns_rdatatype_t type) { 2267 1.1 christos if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_ZONECUTAUTH) != 2268 1.1 christos 0) 2269 1.1 christos { 2270 1.1 christos return (true); 2271 1.1 christos } 2272 1.1 christos return (false); 2273 1.1 christos } 2274 1.1 christos 2275 1.1 christos bool 2276 1.1 christos dns_rdatatype_isknown(dns_rdatatype_t type) { 2277 1.1 christos if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_UNKNOWN) == 0) { 2278 1.1 christos return (true); 2279 1.1 christos } 2280 1.1 christos return (false); 2281 1.1 christos } 2282 1.1 christos 2283 1.1 christos void 2284 1.1 christos dns_rdata_exists(dns_rdata_t *rdata, dns_rdatatype_t type) { 2285 1.1 christos REQUIRE(rdata != NULL); 2286 1.1 christos REQUIRE(DNS_RDATA_INITIALIZED(rdata)); 2287 1.1 christos 2288 1.1 christos rdata->data = NULL; 2289 1.1 christos rdata->length = 0; 2290 1.1 christos rdata->flags = DNS_RDATA_UPDATE; 2291 1.1 christos rdata->type = type; 2292 1.1 christos rdata->rdclass = dns_rdataclass_any; 2293 1.1 christos } 2294 1.1 christos 2295 1.1 christos void 2296 1.1 christos dns_rdata_notexist(dns_rdata_t *rdata, dns_rdatatype_t type) { 2297 1.1 christos REQUIRE(rdata != NULL); 2298 1.1 christos REQUIRE(DNS_RDATA_INITIALIZED(rdata)); 2299 1.1 christos 2300 1.1 christos rdata->data = NULL; 2301 1.1 christos rdata->length = 0; 2302 1.1 christos rdata->flags = DNS_RDATA_UPDATE; 2303 1.1 christos rdata->type = type; 2304 1.1 christos rdata->rdclass = dns_rdataclass_none; 2305 1.1 christos } 2306 1.1 christos 2307 1.1 christos void 2308 1.1 christos dns_rdata_deleterrset(dns_rdata_t *rdata, dns_rdatatype_t type) { 2309 1.1 christos REQUIRE(rdata != NULL); 2310 1.1 christos REQUIRE(DNS_RDATA_INITIALIZED(rdata)); 2311 1.1 christos 2312 1.1 christos rdata->data = NULL; 2313 1.1 christos rdata->length = 0; 2314 1.1 christos rdata->flags = DNS_RDATA_UPDATE; 2315 1.1 christos rdata->type = type; 2316 1.1 christos rdata->rdclass = dns_rdataclass_any; 2317 1.1 christos } 2318 1.1 christos 2319 1.1 christos void 2320 1.1 christos dns_rdata_makedelete(dns_rdata_t *rdata) { 2321 1.1 christos REQUIRE(rdata != NULL); 2322 1.1 christos 2323 1.1 christos rdata->rdclass = dns_rdataclass_none; 2324 1.1 christos } 2325 1.1 christos 2326 1.1 christos const char * 2327 1.1 christos dns_rdata_updateop(dns_rdata_t *rdata, dns_section_t section) { 2328 1.1 christos REQUIRE(rdata != NULL); 2329 1.1 christos REQUIRE(DNS_RDATA_INITIALIZED(rdata)); 2330 1.1 christos 2331 1.1 christos switch (section) { 2332 1.1 christos case DNS_SECTION_PREREQUISITE: 2333 1.1 christos switch (rdata->rdclass) { 2334 1.1 christos case dns_rdataclass_none: 2335 1.1 christos switch (rdata->type) { 2336 1.1 christos case dns_rdatatype_any: 2337 1.1 christos return ("domain doesn't exist"); 2338 1.1 christos default: 2339 1.1 christos return ("rrset doesn't exist"); 2340 1.1 christos } 2341 1.1 christos case dns_rdataclass_any: 2342 1.1 christos switch (rdata->type) { 2343 1.1 christos case dns_rdatatype_any: 2344 1.1 christos return ("domain exists"); 2345 1.1 christos default: 2346 1.1 christos return ("rrset exists (value independent)"); 2347 1.1 christos } 2348 1.1 christos default: 2349 1.1 christos return ("rrset exists (value dependent)"); 2350 1.1 christos } 2351 1.1 christos case DNS_SECTION_UPDATE: 2352 1.1 christos switch (rdata->rdclass) { 2353 1.1 christos case dns_rdataclass_none: 2354 1.1 christos return ("delete"); 2355 1.1 christos case dns_rdataclass_any: 2356 1.1 christos switch (rdata->type) { 2357 1.1 christos case dns_rdatatype_any: 2358 1.1 christos return ("delete all rrsets"); 2359 1.1 christos default: 2360 1.1 christos return ("delete rrset"); 2361 1.1 christos } 2362 1.1 christos default: 2363 1.1 christos return ("add"); 2364 1.1 christos } 2365 1.1 christos } 2366 1.1 christos return ("invalid"); 2367 1.1 christos } 2368