1/* $NetBSD: srv_33.c,v 1.1 2024/02/18 20:57:46 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 23static isc_result_t 24fromtext_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 91static isc_result_t 92totext_in_srv(ARGS_TOTEXT) { 93 isc_region_t region; 94 dns_name_t name; 95 dns_name_t prefix; 96 bool sub; 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 sub = name_prefix(&name, tctx->origin, &prefix); 140 return (dns_name_totext(&prefix, sub, target)); 141} 142 143static isc_result_t 144fromwire_in_srv(ARGS_FROMWIRE) { 145 dns_name_t name; 146 isc_region_t sr; 147 148 REQUIRE(type == dns_rdatatype_srv); 149 REQUIRE(rdclass == dns_rdataclass_in); 150 151 UNUSED(type); 152 UNUSED(rdclass); 153 154 dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); 155 156 dns_name_init(&name, NULL); 157 158 /* 159 * Priority, weight, port. 160 */ 161 isc_buffer_activeregion(source, &sr); 162 if (sr.length < 6) { 163 return (ISC_R_UNEXPECTEDEND); 164 } 165 RETERR(mem_tobuffer(target, sr.base, 6)); 166 isc_buffer_forward(source, 6); 167 168 /* 169 * Target. 170 */ 171 return (dns_name_fromwire(&name, source, dctx, options, target)); 172} 173 174static isc_result_t 175towire_in_srv(ARGS_TOWIRE) { 176 dns_name_t name; 177 dns_offsets_t offsets; 178 isc_region_t sr; 179 180 REQUIRE(rdata->type == dns_rdatatype_srv); 181 REQUIRE(rdata->length != 0); 182 183 dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); 184 /* 185 * Priority, weight, port. 186 */ 187 dns_rdata_toregion(rdata, &sr); 188 RETERR(mem_tobuffer(target, sr.base, 6)); 189 isc_region_consume(&sr, 6); 190 191 /* 192 * Target. 193 */ 194 dns_name_init(&name, offsets); 195 dns_name_fromregion(&name, &sr); 196 return (dns_name_towire(&name, cctx, target)); 197} 198 199static int 200compare_in_srv(ARGS_COMPARE) { 201 dns_name_t name1; 202 dns_name_t name2; 203 isc_region_t region1; 204 isc_region_t region2; 205 int order; 206 207 REQUIRE(rdata1->type == rdata2->type); 208 REQUIRE(rdata1->rdclass == rdata2->rdclass); 209 REQUIRE(rdata1->type == dns_rdatatype_srv); 210 REQUIRE(rdata1->rdclass == dns_rdataclass_in); 211 REQUIRE(rdata1->length != 0); 212 REQUIRE(rdata2->length != 0); 213 214 /* 215 * Priority, weight, port. 216 */ 217 order = memcmp(rdata1->data, rdata2->data, 6); 218 if (order != 0) { 219 return (order < 0 ? -1 : 1); 220 } 221 222 /* 223 * Target. 224 */ 225 dns_name_init(&name1, NULL); 226 dns_name_init(&name2, NULL); 227 228 dns_rdata_toregion(rdata1, ®ion1); 229 dns_rdata_toregion(rdata2, ®ion2); 230 231 isc_region_consume(®ion1, 6); 232 isc_region_consume(®ion2, 6); 233 234 dns_name_fromregion(&name1, ®ion1); 235 dns_name_fromregion(&name2, ®ion2); 236 237 return (dns_name_rdatacompare(&name1, &name2)); 238} 239 240static isc_result_t 241fromstruct_in_srv(ARGS_FROMSTRUCT) { 242 dns_rdata_in_srv_t *srv = source; 243 isc_region_t region; 244 245 REQUIRE(type == dns_rdatatype_srv); 246 REQUIRE(rdclass == dns_rdataclass_in); 247 REQUIRE(srv != NULL); 248 REQUIRE(srv->common.rdtype == type); 249 REQUIRE(srv->common.rdclass == rdclass); 250 251 UNUSED(type); 252 UNUSED(rdclass); 253 254 RETERR(uint16_tobuffer(srv->priority, target)); 255 RETERR(uint16_tobuffer(srv->weight, target)); 256 RETERR(uint16_tobuffer(srv->port, target)); 257 dns_name_toregion(&srv->target, ®ion); 258 return (isc_buffer_copyregion(target, ®ion)); 259} 260 261static isc_result_t 262tostruct_in_srv(ARGS_TOSTRUCT) { 263 isc_region_t region; 264 dns_rdata_in_srv_t *srv = target; 265 dns_name_t name; 266 267 REQUIRE(rdata->rdclass == dns_rdataclass_in); 268 REQUIRE(rdata->type == dns_rdatatype_srv); 269 REQUIRE(srv != NULL); 270 REQUIRE(rdata->length != 0); 271 272 srv->common.rdclass = rdata->rdclass; 273 srv->common.rdtype = rdata->type; 274 ISC_LINK_INIT(&srv->common, link); 275 276 dns_name_init(&name, NULL); 277 dns_rdata_toregion(rdata, ®ion); 278 srv->priority = uint16_fromregion(®ion); 279 isc_region_consume(®ion, 2); 280 srv->weight = uint16_fromregion(®ion); 281 isc_region_consume(®ion, 2); 282 srv->port = uint16_fromregion(®ion); 283 isc_region_consume(®ion, 2); 284 dns_name_fromregion(&name, ®ion); 285 dns_name_init(&srv->target, NULL); 286 RETERR(name_duporclone(&name, mctx, &srv->target)); 287 srv->mctx = mctx; 288 return (ISC_R_SUCCESS); 289} 290 291static void 292freestruct_in_srv(ARGS_FREESTRUCT) { 293 dns_rdata_in_srv_t *srv = source; 294 295 REQUIRE(srv != NULL); 296 REQUIRE(srv->common.rdclass == dns_rdataclass_in); 297 REQUIRE(srv->common.rdtype == dns_rdatatype_srv); 298 299 if (srv->mctx == NULL) { 300 return; 301 } 302 303 dns_name_free(&srv->target, srv->mctx); 304 srv->mctx = NULL; 305} 306 307static isc_result_t 308additionaldata_in_srv(ARGS_ADDLDATA) { 309 char buf[sizeof("_65000._tcp")]; 310 dns_fixedname_t fixed; 311 dns_name_t name; 312 dns_offsets_t offsets; 313 isc_region_t region; 314 uint16_t port; 315 isc_result_t result; 316 317 REQUIRE(rdata->type == dns_rdatatype_srv); 318 REQUIRE(rdata->rdclass == dns_rdataclass_in); 319 320 dns_name_init(&name, offsets); 321 dns_rdata_toregion(rdata, ®ion); 322 isc_region_consume(®ion, 4); 323 port = uint16_fromregion(®ion); 324 isc_region_consume(®ion, 2); 325 dns_name_fromregion(&name, ®ion); 326 327 if (dns_name_equal(&name, dns_rootname)) { 328 return (ISC_R_SUCCESS); 329 } 330 331 result = (add)(arg, &name, dns_rdatatype_a); 332 if (result != ISC_R_SUCCESS) { 333 return (result); 334 } 335 336 dns_fixedname_init(&fixed); 337 snprintf(buf, sizeof(buf), "_%u._tcp", port); 338 result = dns_name_fromstring2(dns_fixedname_name(&fixed), buf, NULL, 0, 339 NULL); 340 if (result != ISC_R_SUCCESS) { 341 return (ISC_R_SUCCESS); 342 } 343 344 result = dns_name_concatenate(dns_fixedname_name(&fixed), &name, 345 dns_fixedname_name(&fixed), NULL); 346 if (result != ISC_R_SUCCESS) { 347 return (ISC_R_SUCCESS); 348 } 349 350 return ((add)(arg, dns_fixedname_name(&fixed), dns_rdatatype_tlsa)); 351} 352 353static isc_result_t 354digest_in_srv(ARGS_DIGEST) { 355 isc_region_t r1, r2; 356 dns_name_t name; 357 358 REQUIRE(rdata->type == dns_rdatatype_srv); 359 REQUIRE(rdata->rdclass == dns_rdataclass_in); 360 361 dns_rdata_toregion(rdata, &r1); 362 r2 = r1; 363 isc_region_consume(&r2, 6); 364 r1.length = 6; 365 RETERR((digest)(arg, &r1)); 366 dns_name_init(&name, NULL); 367 dns_name_fromregion(&name, &r2); 368 return (dns_name_digest(&name, digest, arg)); 369} 370 371static bool 372checkowner_in_srv(ARGS_CHECKOWNER) { 373 REQUIRE(type == dns_rdatatype_srv); 374 REQUIRE(rdclass == dns_rdataclass_in); 375 376 UNUSED(name); 377 UNUSED(type); 378 UNUSED(rdclass); 379 UNUSED(wildcard); 380 381 return (true); 382} 383 384static bool 385checknames_in_srv(ARGS_CHECKNAMES) { 386 isc_region_t region; 387 dns_name_t name; 388 389 REQUIRE(rdata->type == dns_rdatatype_srv); 390 REQUIRE(rdata->rdclass == dns_rdataclass_in); 391 392 UNUSED(owner); 393 394 dns_rdata_toregion(rdata, ®ion); 395 isc_region_consume(®ion, 6); 396 dns_name_init(&name, NULL); 397 dns_name_fromregion(&name, ®ion); 398 if (!dns_name_ishostname(&name, false)) { 399 if (bad != NULL) { 400 dns_name_clone(&name, bad); 401 } 402 return (false); 403 } 404 return (true); 405} 406 407static int 408casecompare_in_srv(ARGS_COMPARE) { 409 return (compare_in_srv(rdata1, rdata2)); 410} 411 412#endif /* RDATA_IN_1_SRV_33_C */ 413