1 1.1 christos /* $NetBSD: dsync_66.c,v 1.2 2026/01/29 18:37:52 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 #ifndef RDATA_GENERIC_DSYNC_66_C 17 1.1 christos #define RDATA_GENERIC_DSYNC_66_C 18 1.1 christos 19 1.1 christos #include <string.h> 20 1.1 christos 21 1.1 christos #include <isc/net.h> 22 1.1 christos 23 1.1 christos #include <dns/dsync.h> 24 1.1 christos #include <dns/fixedname.h> 25 1.1 christos 26 1.1 christos #define RRTYPE_DSYNC_ATTRIBUTES (0) 27 1.1 christos 28 1.1 christos static isc_result_t 29 1.1 christos fromtext_dsync(ARGS_FROMTEXT) { 30 1.1 christos isc_token_t token; 31 1.1 christos isc_result_t result; 32 1.1 christos dns_fixedname_t fn; 33 1.1 christos dns_name_t *name = dns_fixedname_initname(&fn); 34 1.1 christos isc_buffer_t buffer; 35 1.1 christos dns_rdatatype_t rrtype; 36 1.1 christos dns_dsyncscheme_t scheme; 37 1.1 christos bool ok = true; 38 1.1 christos 39 1.1 christos REQUIRE(type == dns_rdatatype_dsync); 40 1.1 christos 41 1.1 christos UNUSED(type); 42 1.1 christos UNUSED(rdclass); 43 1.1 christos UNUSED(callbacks); 44 1.1 christos 45 1.1 christos /* 46 1.1 christos * RRtype 47 1.1 christos */ 48 1.1 christos RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 49 1.1 christos false)); 50 1.1 christos result = dns_rdatatype_fromtext(&rrtype, &token.value.as_textregion); 51 1.1 christos if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) { 52 1.1 christos char *e = NULL; 53 1.1 christos long i = strtol(DNS_AS_STR(token), &e, 10); 54 1.1 christos if (i < 0 || i > 65535) { 55 1.1 christos RETTOK(ISC_R_RANGE); 56 1.1 christos } 57 1.1 christos if (*e != 0) { 58 1.1 christos RETTOK(result); 59 1.1 christos } 60 1.1 christos rrtype = (dns_rdatatype_t)i; 61 1.1 christos } 62 1.1 christos RETERR(uint16_tobuffer(rrtype, target)); 63 1.1 christos 64 1.1 christos /* 65 1.1 christos * Scheme 66 1.1 christos */ 67 1.1 christos RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 68 1.1 christos false)); 69 1.1 christos RETERR(dns_dsyncscheme_fromtext(&scheme, &token.value.as_textregion)); 70 1.1 christos RETERR(uint8_tobuffer(scheme, target)); 71 1.1 christos 72 1.1 christos /* 73 1.1 christos * Port 74 1.1 christos */ 75 1.1 christos RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 76 1.1 christos false)); 77 1.1 christos if (token.value.as_ulong > 0xffffU) { 78 1.1 christos RETTOK(ISC_R_RANGE); 79 1.1 christos } 80 1.1 christos RETERR(uint16_tobuffer(token.value.as_ulong, target)); 81 1.1 christos 82 1.1 christos /* 83 1.1 christos * Target 84 1.1 christos */ 85 1.1 christos RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 86 1.1 christos false)); 87 1.1 christos 88 1.1 christos buffer_fromregion(&buffer, &token.value.as_region); 89 1.1 christos if (origin == NULL) { 90 1.1 christos origin = dns_rootname; 91 1.1 christos } 92 1.1 christos RETTOK(dns_name_fromtext(name, &buffer, origin, options, target)); 93 1.1 christos if ((options & DNS_RDATA_CHECKNAMES) != 0) { 94 1.1 christos ok = dns_name_ishostname(name, false); 95 1.1 christos } 96 1.1 christos if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) { 97 1.1 christos RETTOK(DNS_R_BADNAME); 98 1.1 christos } 99 1.1 christos if (!ok && callbacks != NULL) { 100 1.1 christos warn_badname(name, lexer, callbacks); 101 1.1 christos } 102 1.1 christos return ISC_R_SUCCESS; 103 1.1 christos } 104 1.1 christos 105 1.1 christos static isc_result_t 106 1.1 christos totext_dsync(ARGS_TOTEXT) { 107 1.1 christos isc_region_t region; 108 1.1 christos dns_name_t name; 109 1.1 christos dns_name_t prefix; 110 1.1 christos unsigned int opts; 111 1.1 christos char buf[sizeof("TYPE64000")]; 112 1.1 christos unsigned short num; 113 1.1 christos dns_rdatatype_t type; 114 1.1 christos dns_dsyncscheme_t scheme; 115 1.1 christos 116 1.1 christos REQUIRE(rdata->type == dns_rdatatype_dsync); 117 1.1 christos REQUIRE(rdata->length != 0); 118 1.1 christos 119 1.1 christos dns_name_init(&name, NULL); 120 1.1 christos dns_name_init(&prefix, NULL); 121 1.1 christos 122 1.1 christos dns_rdata_toregion(rdata, ®ion); 123 1.1 christos 124 1.1 christos /* 125 1.1 christos * Type. 126 1.1 christos */ 127 1.1 christos type = uint16_fromregion(®ion); 128 1.1 christos isc_region_consume(®ion, 2); 129 1.1 christos /* 130 1.1 christos * XXXAG We should have something like dns_rdatatype_isknown() 131 1.1 christos * that does the right thing with type 0. 132 1.1 christos */ 133 1.1 christos if (dns_rdatatype_isknown(type) && type != 0) { 134 1.1 christos RETERR(dns_rdatatype_totext(type, target)); 135 1.1 christos } else { 136 1.1 christos snprintf(buf, sizeof(buf), "TYPE%u", type); 137 1.1 christos RETERR(str_totext(buf, target)); 138 1.1 christos } 139 1.1 christos RETERR(str_totext(" ", target)); 140 1.1 christos 141 1.1 christos /* 142 1.1 christos * Scheme. 143 1.1 christos */ 144 1.1 christos scheme = uint8_fromregion(®ion); 145 1.1 christos isc_region_consume(®ion, 1); 146 1.1 christos RETERR(dns_dsyncscheme_totext(scheme, target)); 147 1.1 christos 148 1.1 christos RETERR(str_totext(" ", target)); 149 1.1 christos 150 1.1 christos /* 151 1.1 christos * Port 152 1.1 christos */ 153 1.1 christos num = uint16_fromregion(®ion); 154 1.1 christos isc_region_consume(®ion, 2); 155 1.1 christos snprintf(buf, sizeof(buf), "%u", num); 156 1.1 christos RETERR(str_totext(buf, target)); 157 1.1 christos 158 1.1 christos RETERR(str_totext(" ", target)); 159 1.1 christos 160 1.1 christos /* 161 1.1 christos * Target 162 1.1 christos */ 163 1.1 christos dns_name_fromregion(&name, ®ion); 164 1.1 christos opts = name_prefix(&name, tctx->origin, &prefix) ? DNS_NAME_OMITFINALDOT 165 1.1 christos : 0; 166 1.1 christos return dns_name_totext(&prefix, opts, target); 167 1.1 christos } 168 1.1 christos 169 1.1 christos static isc_result_t 170 1.1 christos fromwire_dsync(ARGS_FROMWIRE) { 171 1.1 christos dns_name_t name; 172 1.1 christos isc_region_t sregion; 173 1.1 christos 174 1.1 christos REQUIRE(type == dns_rdatatype_dsync); 175 1.1 christos 176 1.1 christos UNUSED(type); 177 1.1 christos UNUSED(rdclass); 178 1.1 christos 179 1.1 christos dctx = dns_decompress_setpermitted(dctx, false); 180 1.1 christos 181 1.1 christos dns_name_init(&name, NULL); 182 1.1 christos 183 1.1 christos isc_buffer_activeregion(source, &sregion); 184 1.1 christos if (sregion.length < 5) { 185 1.1 christos return ISC_R_UNEXPECTEDEND; 186 1.1 christos } 187 1.1 christos RETERR(mem_tobuffer(target, sregion.base, 5)); 188 1.1 christos isc_buffer_forward(source, 5); 189 1.1 christos return dns_name_fromwire(&name, source, dctx, target); 190 1.1 christos } 191 1.1 christos 192 1.1 christos static isc_result_t 193 1.1 christos towire_dsync(ARGS_TOWIRE) { 194 1.1 christos dns_name_t name; 195 1.1 christos isc_region_t region; 196 1.1 christos 197 1.1 christos REQUIRE(rdata->type == dns_rdatatype_dsync); 198 1.1 christos REQUIRE(rdata->length != 0); 199 1.1 christos 200 1.1 christos dns_compress_setpermitted(cctx, false); 201 1.1 christos 202 1.1 christos dns_rdata_toregion(rdata, ®ion); 203 1.1 christos RETERR(mem_tobuffer(target, region.base, 5)); 204 1.1 christos isc_region_consume(®ion, 5); 205 1.1 christos 206 1.1 christos dns_name_init(&name, NULL); 207 1.1 christos dns_name_fromregion(&name, ®ion); 208 1.1 christos 209 1.1 christos return dns_name_towire(&name, cctx, target, NULL); 210 1.1 christos } 211 1.1 christos 212 1.1 christos static int 213 1.1 christos compare_dsync(ARGS_COMPARE) { 214 1.1 christos isc_region_t region1; 215 1.1 christos isc_region_t region2; 216 1.1 christos 217 1.1 christos REQUIRE(rdata1->type == rdata2->type); 218 1.1 christos REQUIRE(rdata1->rdclass == rdata2->rdclass); 219 1.1 christos REQUIRE(rdata1->type == dns_rdatatype_dsync); 220 1.1 christos REQUIRE(rdata1->length != 0); 221 1.1 christos REQUIRE(rdata2->length != 0); 222 1.1 christos 223 1.1 christos dns_rdata_toregion(rdata1, ®ion1); 224 1.1 christos dns_rdata_toregion(rdata2, ®ion2); 225 1.1 christos return isc_region_compare(®ion1, ®ion2); 226 1.1 christos } 227 1.1 christos 228 1.1 christos static isc_result_t 229 1.1 christos fromstruct_dsync(ARGS_FROMSTRUCT) { 230 1.1 christos dns_rdata_dsync_t *dsync = source; 231 1.1 christos isc_region_t region; 232 1.1 christos 233 1.1 christos REQUIRE(type == dns_rdatatype_dsync); 234 1.1 christos REQUIRE(dsync != NULL); 235 1.1 christos REQUIRE(dsync->common.rdtype == type); 236 1.1 christos REQUIRE(dsync->common.rdclass == rdclass); 237 1.1 christos 238 1.1 christos UNUSED(type); 239 1.1 christos UNUSED(rdclass); 240 1.1 christos 241 1.1 christos RETERR(uint16_tobuffer(dsync->type, target)); 242 1.1 christos RETERR(uint16_tobuffer(dsync->scheme, target)); 243 1.1 christos RETERR(uint16_tobuffer(dsync->port, target)); 244 1.1 christos dns_name_toregion(&dsync->target, ®ion); 245 1.1 christos return isc_buffer_copyregion(target, ®ion); 246 1.1 christos } 247 1.1 christos 248 1.1 christos static isc_result_t 249 1.1 christos tostruct_dsync(ARGS_TOSTRUCT) { 250 1.1 christos isc_region_t region; 251 1.1 christos dns_rdata_dsync_t *dsync = target; 252 1.1 christos dns_name_t name; 253 1.1 christos 254 1.1 christos REQUIRE(rdata->type == dns_rdatatype_dsync); 255 1.1 christos REQUIRE(dsync != NULL); 256 1.1 christos REQUIRE(rdata->length != 0); 257 1.1 christos 258 1.1 christos DNS_RDATACOMMON_INIT(dsync, rdata->type, rdata->rdclass); 259 1.1 christos 260 1.1 christos dns_name_init(&name, NULL); 261 1.1 christos dns_rdata_toregion(rdata, ®ion); 262 1.1 christos dsync->type = uint16_fromregion(®ion); 263 1.1 christos isc_region_consume(®ion, 2); 264 1.1 christos dsync->scheme = uint8_fromregion(®ion); 265 1.1 christos isc_region_consume(®ion, 1); 266 1.1 christos dsync->port = uint16_fromregion(®ion); 267 1.1 christos isc_region_consume(®ion, 2); 268 1.1 christos dns_name_fromregion(&name, ®ion); 269 1.1 christos dns_name_init(&dsync->target, NULL); 270 1.1 christos name_duporclone(&name, mctx, &dsync->target); 271 1.1 christos dsync->mctx = mctx; 272 1.1 christos return ISC_R_SUCCESS; 273 1.1 christos } 274 1.1 christos 275 1.1 christos static void 276 1.1 christos freestruct_dsync(ARGS_FREESTRUCT) { 277 1.1 christos dns_rdata_dsync_t *dsync = source; 278 1.1 christos 279 1.1 christos REQUIRE(dsync != NULL); 280 1.1 christos REQUIRE(dsync->common.rdtype == dns_rdatatype_dsync); 281 1.1 christos 282 1.1 christos if (dsync->mctx == NULL) { 283 1.1 christos return; 284 1.1 christos } 285 1.1 christos 286 1.1 christos dns_name_free(&dsync->target, dsync->mctx); 287 1.1 christos dsync->mctx = NULL; 288 1.1 christos } 289 1.1 christos 290 1.1 christos static isc_result_t 291 1.1 christos additionaldata_dsync(ARGS_ADDLDATA) { 292 1.1 christos dns_name_t name; 293 1.1 christos isc_region_t region; 294 1.1 christos 295 1.1 christos REQUIRE(rdata->type == dns_rdatatype_dsync); 296 1.1 christos 297 1.1 christos UNUSED(owner); 298 1.1 christos 299 1.1 christos dns_name_init(&name, NULL); 300 1.1 christos dns_rdata_toregion(rdata, ®ion); 301 1.1 christos isc_region_consume(®ion, 5); 302 1.1 christos dns_name_fromregion(&name, ®ion); 303 1.1 christos 304 1.1 christos if (dns_name_equal(&name, dns_rootname)) { 305 1.1 christos return ISC_R_SUCCESS; 306 1.1 christos } 307 1.1 christos 308 1.1 christos return (add)(arg, &name, dns_rdatatype_a, NULL DNS__DB_FILELINE); 309 1.1 christos } 310 1.1 christos 311 1.1 christos static isc_result_t 312 1.1 christos digest_dsync(ARGS_DIGEST) { 313 1.1 christos isc_region_t r1; 314 1.1 christos 315 1.1 christos REQUIRE(rdata->type == dns_rdatatype_dsync); 316 1.1 christos 317 1.1 christos dns_rdata_toregion(rdata, &r1); 318 1.1 christos return (digest)(arg, &r1); 319 1.1 christos } 320 1.1 christos 321 1.1 christos static bool 322 1.1 christos checkowner_dsync(ARGS_CHECKOWNER) { 323 1.1 christos REQUIRE(type == dns_rdatatype_dsync); 324 1.1 christos 325 1.1 christos UNUSED(name); 326 1.1 christos UNUSED(rdclass); 327 1.1 christos UNUSED(type); 328 1.1 christos UNUSED(wildcard); 329 1.1 christos 330 1.1 christos return true; 331 1.1 christos } 332 1.1 christos 333 1.1 christos static bool 334 1.1 christos checknames_dsync(ARGS_CHECKNAMES) { 335 1.1 christos isc_region_t region; 336 1.1 christos dns_name_t name; 337 1.1 christos 338 1.1 christos REQUIRE(rdata->type == dns_rdatatype_dsync); 339 1.1 christos REQUIRE(rdata->length > 5); 340 1.1 christos 341 1.1 christos UNUSED(owner); 342 1.1 christos 343 1.1 christos dns_rdata_toregion(rdata, ®ion); 344 1.1 christos isc_region_consume(®ion, 5); 345 1.1 christos dns_name_init(&name, NULL); 346 1.1 christos dns_name_fromregion(&name, ®ion); 347 1.1 christos if (!dns_name_ishostname(&name, false)) { 348 1.1 christos if (bad != NULL) { 349 1.1 christos dns_name_clone(&name, bad); 350 1.1 christos } 351 1.1 christos return false; 352 1.1 christos } 353 1.1 christos return true; 354 1.1 christos } 355 1.1 christos 356 1.1 christos static int 357 1.1 christos casecompare_dsync(ARGS_COMPARE) { 358 1.1 christos return compare_dsync(rdata1, rdata2); 359 1.1 christos } 360 1.1 christos 361 1.1 christos #endif /* RDATA_GENERIC_DSYNC_66_C */ 362