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