1 /* $NetBSD: srv_33.c,v 1.9 2025/01/26 16:25:35 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 /* RFC2782 */ 17 18 #ifndef RDATA_IN_1_SRV_33_C 19 #define RDATA_IN_1_SRV_33_C 20 21 #define RRTYPE_SRV_ATTRIBUTES (DNS_RDATATYPEATTR_FOLLOWADDITIONAL) 22 23 static isc_result_t 24 fromtext_in_srv(ARGS_FROMTEXT) { 25 isc_token_t token; 26 dns_name_t name; 27 isc_buffer_t buffer; 28 bool ok; 29 30 REQUIRE(type == dns_rdatatype_srv); 31 REQUIRE(rdclass == dns_rdataclass_in); 32 33 UNUSED(type); 34 UNUSED(rdclass); 35 UNUSED(callbacks); 36 37 /* 38 * Priority. 39 */ 40 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 41 false)); 42 if (token.value.as_ulong > 0xffffU) { 43 RETTOK(ISC_R_RANGE); 44 } 45 RETERR(uint16_tobuffer(token.value.as_ulong, target)); 46 47 /* 48 * Weight. 49 */ 50 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 51 false)); 52 if (token.value.as_ulong > 0xffffU) { 53 RETTOK(ISC_R_RANGE); 54 } 55 RETERR(uint16_tobuffer(token.value.as_ulong, target)); 56 57 /* 58 * Port. 59 */ 60 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 61 false)); 62 if (token.value.as_ulong > 0xffffU) { 63 RETTOK(ISC_R_RANGE); 64 } 65 RETERR(uint16_tobuffer(token.value.as_ulong, target)); 66 67 /* 68 * Target. 69 */ 70 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 71 false)); 72 dns_name_init(&name, NULL); 73 buffer_fromregion(&buffer, &token.value.as_region); 74 if (origin == NULL) { 75 origin = dns_rootname; 76 } 77 RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); 78 ok = true; 79 if ((options & DNS_RDATA_CHECKNAMES) != 0) { 80 ok = dns_name_ishostname(&name, false); 81 } 82 if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) { 83 RETTOK(DNS_R_BADNAME); 84 } 85 if (!ok && callbacks != NULL) { 86 warn_badname(&name, lexer, callbacks); 87 } 88 return ISC_R_SUCCESS; 89 } 90 91 static isc_result_t 92 totext_in_srv(ARGS_TOTEXT) { 93 isc_region_t region; 94 dns_name_t name; 95 dns_name_t prefix; 96 unsigned int opts; 97 char buf[sizeof("64000")]; 98 unsigned short num; 99 100 REQUIRE(rdata->type == dns_rdatatype_srv); 101 REQUIRE(rdata->rdclass == dns_rdataclass_in); 102 REQUIRE(rdata->length != 0); 103 104 dns_name_init(&name, NULL); 105 dns_name_init(&prefix, NULL); 106 107 /* 108 * Priority. 109 */ 110 dns_rdata_toregion(rdata, ®ion); 111 num = uint16_fromregion(®ion); 112 isc_region_consume(®ion, 2); 113 snprintf(buf, sizeof(buf), "%u", num); 114 RETERR(str_totext(buf, target)); 115 RETERR(str_totext(" ", target)); 116 117 /* 118 * Weight. 119 */ 120 num = uint16_fromregion(®ion); 121 isc_region_consume(®ion, 2); 122 snprintf(buf, sizeof(buf), "%u", num); 123 RETERR(str_totext(buf, target)); 124 RETERR(str_totext(" ", target)); 125 126 /* 127 * Port. 128 */ 129 num = uint16_fromregion(®ion); 130 isc_region_consume(®ion, 2); 131 snprintf(buf, sizeof(buf), "%u", num); 132 RETERR(str_totext(buf, target)); 133 RETERR(str_totext(" ", target)); 134 135 /* 136 * Target. 137 */ 138 dns_name_fromregion(&name, ®ion); 139 opts = name_prefix(&name, tctx->origin, &prefix) ? DNS_NAME_OMITFINALDOT 140 : 0; 141 return dns_name_totext(&prefix, opts, target); 142 } 143 144 static isc_result_t 145 fromwire_in_srv(ARGS_FROMWIRE) { 146 dns_name_t name; 147 isc_region_t sr; 148 149 REQUIRE(type == dns_rdatatype_srv); 150 REQUIRE(rdclass == dns_rdataclass_in); 151 152 UNUSED(type); 153 UNUSED(rdclass); 154 155 dctx = dns_decompress_setpermitted(dctx, false); 156 157 dns_name_init(&name, NULL); 158 159 /* 160 * Priority, weight, port. 161 */ 162 isc_buffer_activeregion(source, &sr); 163 if (sr.length < 6) { 164 return ISC_R_UNEXPECTEDEND; 165 } 166 RETERR(mem_tobuffer(target, sr.base, 6)); 167 isc_buffer_forward(source, 6); 168 169 /* 170 * Target. 171 */ 172 return dns_name_fromwire(&name, source, dctx, target); 173 } 174 175 static isc_result_t 176 towire_in_srv(ARGS_TOWIRE) { 177 dns_name_t name; 178 dns_offsets_t offsets; 179 isc_region_t sr; 180 181 REQUIRE(rdata->type == dns_rdatatype_srv); 182 REQUIRE(rdata->length != 0); 183 184 dns_compress_setpermitted(cctx, false); 185 /* 186 * Priority, weight, port. 187 */ 188 dns_rdata_toregion(rdata, &sr); 189 RETERR(mem_tobuffer(target, sr.base, 6)); 190 isc_region_consume(&sr, 6); 191 192 /* 193 * Target. 194 */ 195 dns_name_init(&name, offsets); 196 dns_name_fromregion(&name, &sr); 197 return dns_name_towire(&name, cctx, target, NULL); 198 } 199 200 static int 201 compare_in_srv(ARGS_COMPARE) { 202 dns_name_t name1; 203 dns_name_t name2; 204 isc_region_t region1; 205 isc_region_t region2; 206 int order; 207 208 REQUIRE(rdata1->type == rdata2->type); 209 REQUIRE(rdata1->rdclass == rdata2->rdclass); 210 REQUIRE(rdata1->type == dns_rdatatype_srv); 211 REQUIRE(rdata1->rdclass == dns_rdataclass_in); 212 REQUIRE(rdata1->length != 0); 213 REQUIRE(rdata2->length != 0); 214 215 /* 216 * Priority, weight, port. 217 */ 218 order = memcmp(rdata1->data, rdata2->data, 6); 219 if (order != 0) { 220 return order < 0 ? -1 : 1; 221 } 222 223 /* 224 * Target. 225 */ 226 dns_name_init(&name1, NULL); 227 dns_name_init(&name2, NULL); 228 229 dns_rdata_toregion(rdata1, ®ion1); 230 dns_rdata_toregion(rdata2, ®ion2); 231 232 isc_region_consume(®ion1, 6); 233 isc_region_consume(®ion2, 6); 234 235 dns_name_fromregion(&name1, ®ion1); 236 dns_name_fromregion(&name2, ®ion2); 237 238 return dns_name_rdatacompare(&name1, &name2); 239 } 240 241 static isc_result_t 242 fromstruct_in_srv(ARGS_FROMSTRUCT) { 243 dns_rdata_in_srv_t *srv = source; 244 isc_region_t region; 245 246 REQUIRE(type == dns_rdatatype_srv); 247 REQUIRE(rdclass == dns_rdataclass_in); 248 REQUIRE(srv != NULL); 249 REQUIRE(srv->common.rdtype == type); 250 REQUIRE(srv->common.rdclass == rdclass); 251 252 UNUSED(type); 253 UNUSED(rdclass); 254 255 RETERR(uint16_tobuffer(srv->priority, target)); 256 RETERR(uint16_tobuffer(srv->weight, target)); 257 RETERR(uint16_tobuffer(srv->port, target)); 258 dns_name_toregion(&srv->target, ®ion); 259 return isc_buffer_copyregion(target, ®ion); 260 } 261 262 static isc_result_t 263 tostruct_in_srv(ARGS_TOSTRUCT) { 264 isc_region_t region; 265 dns_rdata_in_srv_t *srv = target; 266 dns_name_t name; 267 268 REQUIRE(rdata->rdclass == dns_rdataclass_in); 269 REQUIRE(rdata->type == dns_rdatatype_srv); 270 REQUIRE(srv != NULL); 271 REQUIRE(rdata->length != 0); 272 273 srv->common.rdclass = rdata->rdclass; 274 srv->common.rdtype = rdata->type; 275 ISC_LINK_INIT(&srv->common, link); 276 277 dns_name_init(&name, NULL); 278 dns_rdata_toregion(rdata, ®ion); 279 srv->priority = uint16_fromregion(®ion); 280 isc_region_consume(®ion, 2); 281 srv->weight = uint16_fromregion(®ion); 282 isc_region_consume(®ion, 2); 283 srv->port = uint16_fromregion(®ion); 284 isc_region_consume(®ion, 2); 285 dns_name_fromregion(&name, ®ion); 286 dns_name_init(&srv->target, NULL); 287 name_duporclone(&name, mctx, &srv->target); 288 srv->mctx = mctx; 289 return ISC_R_SUCCESS; 290 } 291 292 static void 293 freestruct_in_srv(ARGS_FREESTRUCT) { 294 dns_rdata_in_srv_t *srv = source; 295 296 REQUIRE(srv != NULL); 297 REQUIRE(srv->common.rdclass == dns_rdataclass_in); 298 REQUIRE(srv->common.rdtype == dns_rdatatype_srv); 299 300 if (srv->mctx == NULL) { 301 return; 302 } 303 304 dns_name_free(&srv->target, srv->mctx); 305 srv->mctx = NULL; 306 } 307 308 static isc_result_t 309 additionaldata_in_srv(ARGS_ADDLDATA) { 310 char buf[sizeof("_65000._tcp")]; 311 dns_fixedname_t fixed; 312 dns_name_t name; 313 dns_offsets_t offsets; 314 isc_region_t region; 315 uint16_t port; 316 isc_result_t result; 317 318 REQUIRE(rdata->type == dns_rdatatype_srv); 319 REQUIRE(rdata->rdclass == dns_rdataclass_in); 320 321 UNUSED(owner); 322 323 dns_name_init(&name, offsets); 324 dns_rdata_toregion(rdata, ®ion); 325 isc_region_consume(®ion, 4); 326 port = uint16_fromregion(®ion); 327 isc_region_consume(®ion, 2); 328 dns_name_fromregion(&name, ®ion); 329 330 if (dns_name_equal(&name, dns_rootname)) { 331 return ISC_R_SUCCESS; 332 } 333 334 result = (add)(arg, &name, dns_rdatatype_a, NULL DNS__DB_FILELINE); 335 if (result != ISC_R_SUCCESS) { 336 return result; 337 } 338 339 dns_fixedname_init(&fixed); 340 snprintf(buf, sizeof(buf), "_%u._tcp", port); 341 result = dns_name_fromstring(dns_fixedname_name(&fixed), buf, NULL, 0, 342 NULL); 343 if (result != ISC_R_SUCCESS) { 344 return ISC_R_SUCCESS; 345 } 346 347 result = dns_name_concatenate(dns_fixedname_name(&fixed), &name, 348 dns_fixedname_name(&fixed), NULL); 349 if (result != ISC_R_SUCCESS) { 350 return ISC_R_SUCCESS; 351 } 352 353 return (add)(arg, dns_fixedname_name(&fixed), dns_rdatatype_tlsa, 354 NULL DNS__DB_FILELINE); 355 } 356 357 static isc_result_t 358 digest_in_srv(ARGS_DIGEST) { 359 isc_region_t r1, r2; 360 dns_name_t name; 361 362 REQUIRE(rdata->type == dns_rdatatype_srv); 363 REQUIRE(rdata->rdclass == dns_rdataclass_in); 364 365 dns_rdata_toregion(rdata, &r1); 366 r2 = r1; 367 isc_region_consume(&r2, 6); 368 r1.length = 6; 369 RETERR((digest)(arg, &r1)); 370 dns_name_init(&name, NULL); 371 dns_name_fromregion(&name, &r2); 372 return dns_name_digest(&name, digest, arg); 373 } 374 375 static bool 376 checkowner_in_srv(ARGS_CHECKOWNER) { 377 REQUIRE(type == dns_rdatatype_srv); 378 REQUIRE(rdclass == dns_rdataclass_in); 379 380 UNUSED(name); 381 UNUSED(type); 382 UNUSED(rdclass); 383 UNUSED(wildcard); 384 385 return true; 386 } 387 388 static bool 389 checknames_in_srv(ARGS_CHECKNAMES) { 390 isc_region_t region; 391 dns_name_t name; 392 393 REQUIRE(rdata->type == dns_rdatatype_srv); 394 REQUIRE(rdata->rdclass == dns_rdataclass_in); 395 396 UNUSED(owner); 397 398 dns_rdata_toregion(rdata, ®ion); 399 isc_region_consume(®ion, 6); 400 dns_name_init(&name, NULL); 401 dns_name_fromregion(&name, ®ion); 402 if (!dns_name_ishostname(&name, false)) { 403 if (bad != NULL) { 404 dns_name_clone(&name, bad); 405 } 406 return false; 407 } 408 return true; 409 } 410 411 static int 412 casecompare_in_srv(ARGS_COMPARE) { 413 return compare_in_srv(rdata1, rdata2); 414 } 415 416 #endif /* RDATA_IN_1_SRV_33_C */ 417