Home | History | Annotate | Line # | Download | only in generic
      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, &region);
    123  1.1  christos 
    124  1.1  christos 	/*
    125  1.1  christos 	 * Type.
    126  1.1  christos 	 */
    127  1.1  christos 	type = uint16_fromregion(&region);
    128  1.1  christos 	isc_region_consume(&region, 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(&region);
    145  1.1  christos 	isc_region_consume(&region, 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(&region);
    154  1.1  christos 	isc_region_consume(&region, 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, &region);
    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, &region);
    203  1.1  christos 	RETERR(mem_tobuffer(target, region.base, 5));
    204  1.1  christos 	isc_region_consume(&region, 5);
    205  1.1  christos 
    206  1.1  christos 	dns_name_init(&name, NULL);
    207  1.1  christos 	dns_name_fromregion(&name, &region);
    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, &region1);
    224  1.1  christos 	dns_rdata_toregion(rdata2, &region2);
    225  1.1  christos 	return isc_region_compare(&region1, &region2);
    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, &region);
    245  1.1  christos 	return isc_buffer_copyregion(target, &region);
    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, &region);
    262  1.1  christos 	dsync->type = uint16_fromregion(&region);
    263  1.1  christos 	isc_region_consume(&region, 2);
    264  1.1  christos 	dsync->scheme = uint8_fromregion(&region);
    265  1.1  christos 	isc_region_consume(&region, 1);
    266  1.1  christos 	dsync->port = uint16_fromregion(&region);
    267  1.1  christos 	isc_region_consume(&region, 2);
    268  1.1  christos 	dns_name_fromregion(&name, &region);
    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, &region);
    301  1.1  christos 	isc_region_consume(&region, 5);
    302  1.1  christos 	dns_name_fromregion(&name, &region);
    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, &region);
    344  1.1  christos 	isc_region_consume(&region, 5);
    345  1.1  christos 	dns_name_init(&name, NULL);
    346  1.1  christos 	dns_name_fromregion(&name, &region);
    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