Home | History | Annotate | Line # | Download | only in generic
      1 /*	$NetBSD: amtrelay_260.c,v 1.1 2024/02/18 20:57:40 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_AMTRELAY_260_C
     17 #define RDATA_GENERIC_AMTRELAY_260_C
     18 
     19 #include <string.h>
     20 
     21 #include <isc/net.h>
     22 
     23 #define RRTYPE_AMTRELAY_ATTRIBUTES (0)
     24 
     25 static isc_result_t
     26 fromtext_amtrelay(ARGS_FROMTEXT) {
     27 	isc_token_t token;
     28 	dns_name_t name;
     29 	isc_buffer_t buffer;
     30 	unsigned int discovery;
     31 	unsigned int gateway;
     32 	struct in_addr addr;
     33 	unsigned char addr6[16];
     34 	isc_region_t region;
     35 
     36 	REQUIRE(type == dns_rdatatype_amtrelay);
     37 
     38 	UNUSED(type);
     39 	UNUSED(rdclass);
     40 	UNUSED(callbacks);
     41 
     42 	/*
     43 	 * Precedence.
     44 	 */
     45 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
     46 				      false));
     47 	if (token.value.as_ulong > 0xffU) {
     48 		RETTOK(ISC_R_RANGE);
     49 	}
     50 	RETERR(uint8_tobuffer(token.value.as_ulong, target));
     51 
     52 	/*
     53 	 * Discovery.
     54 	 */
     55 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
     56 				      false));
     57 	if (token.value.as_ulong > 1U) {
     58 		RETTOK(ISC_R_RANGE);
     59 	}
     60 	discovery = token.value.as_ulong;
     61 
     62 	/*
     63 	 * Gateway type.
     64 	 */
     65 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
     66 				      false));
     67 	if (token.value.as_ulong > 0x7fU) {
     68 		RETTOK(ISC_R_RANGE);
     69 	}
     70 	RETERR(uint8_tobuffer(token.value.as_ulong | (discovery << 7), target));
     71 	gateway = token.value.as_ulong;
     72 
     73 	if (gateway == 0) {
     74 		return (ISC_R_SUCCESS);
     75 	}
     76 
     77 	if (gateway > 3) {
     78 		return (ISC_R_NOTIMPLEMENTED);
     79 	}
     80 
     81 	/*
     82 	 * Gateway.
     83 	 */
     84 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
     85 				      false));
     86 
     87 	switch (gateway) {
     88 	case 1:
     89 		if (inet_pton(AF_INET, DNS_AS_STR(token), &addr) != 1) {
     90 			RETTOK(DNS_R_BADDOTTEDQUAD);
     91 		}
     92 		isc_buffer_availableregion(target, &region);
     93 		if (region.length < 4) {
     94 			return (ISC_R_NOSPACE);
     95 		}
     96 		memmove(region.base, &addr, 4);
     97 		isc_buffer_add(target, 4);
     98 		return (ISC_R_SUCCESS);
     99 
    100 	case 2:
    101 		if (inet_pton(AF_INET6, DNS_AS_STR(token), addr6) != 1) {
    102 			RETTOK(DNS_R_BADAAAA);
    103 		}
    104 		isc_buffer_availableregion(target, &region);
    105 		if (region.length < 16) {
    106 			return (ISC_R_NOSPACE);
    107 		}
    108 		memmove(region.base, addr6, 16);
    109 		isc_buffer_add(target, 16);
    110 		return (ISC_R_SUCCESS);
    111 
    112 	case 3:
    113 		dns_name_init(&name, NULL);
    114 		buffer_fromregion(&buffer, &token.value.as_region);
    115 		if (origin == NULL) {
    116 			origin = dns_rootname;
    117 		}
    118 		return (dns_name_fromtext(&name, &buffer, origin, options,
    119 					  target));
    120 	default:
    121 		UNREACHABLE();
    122 	}
    123 }
    124 
    125 static isc_result_t
    126 totext_amtrelay(ARGS_TOTEXT) {
    127 	isc_region_t region;
    128 	dns_name_t name;
    129 	char buf[sizeof("0 255 ")];
    130 	unsigned char precedence;
    131 	unsigned char discovery;
    132 	unsigned char gateway;
    133 	const char *space;
    134 
    135 	UNUSED(tctx);
    136 
    137 	REQUIRE(rdata->type == dns_rdatatype_amtrelay);
    138 	REQUIRE(rdata->length >= 2);
    139 
    140 	if ((rdata->data[1] & 0x7f) > 3U) {
    141 		return (ISC_R_NOTIMPLEMENTED);
    142 	}
    143 
    144 	/*
    145 	 * Precedence.
    146 	 */
    147 	dns_rdata_toregion(rdata, &region);
    148 	precedence = uint8_fromregion(&region);
    149 	isc_region_consume(&region, 1);
    150 	snprintf(buf, sizeof(buf), "%u ", precedence);
    151 	RETERR(str_totext(buf, target));
    152 
    153 	/*
    154 	 * Discovery and Gateway type.
    155 	 */
    156 	gateway = uint8_fromregion(&region);
    157 	discovery = gateway >> 7;
    158 	gateway &= 0x7f;
    159 	space = (gateway != 0U) ? " " : "";
    160 	isc_region_consume(&region, 1);
    161 	snprintf(buf, sizeof(buf), "%u %u%s", discovery, gateway, space);
    162 	RETERR(str_totext(buf, target));
    163 
    164 	/*
    165 	 * Gateway.
    166 	 */
    167 	switch (gateway) {
    168 	case 0:
    169 		break;
    170 	case 1:
    171 		return (inet_totext(AF_INET, tctx->flags, &region, target));
    172 
    173 	case 2:
    174 		return (inet_totext(AF_INET6, tctx->flags, &region, target));
    175 
    176 	case 3:
    177 		dns_name_init(&name, NULL);
    178 		dns_name_fromregion(&name, &region);
    179 		return (dns_name_totext(&name, false, target));
    180 
    181 	default:
    182 		UNREACHABLE();
    183 	}
    184 	return (ISC_R_SUCCESS);
    185 }
    186 
    187 static isc_result_t
    188 fromwire_amtrelay(ARGS_FROMWIRE) {
    189 	dns_name_t name;
    190 	isc_region_t region;
    191 
    192 	REQUIRE(type == dns_rdatatype_amtrelay);
    193 
    194 	UNUSED(type);
    195 	UNUSED(rdclass);
    196 
    197 	dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
    198 
    199 	isc_buffer_activeregion(source, &region);
    200 	if (region.length < 2) {
    201 		return (ISC_R_UNEXPECTEDEND);
    202 	}
    203 
    204 	switch (region.base[1] & 0x7f) {
    205 	case 0:
    206 		if (region.length != 2) {
    207 			return (DNS_R_FORMERR);
    208 		}
    209 		isc_buffer_forward(source, region.length);
    210 		return (mem_tobuffer(target, region.base, region.length));
    211 
    212 	case 1:
    213 		if (region.length != 6) {
    214 			return (DNS_R_FORMERR);
    215 		}
    216 		isc_buffer_forward(source, region.length);
    217 		return (mem_tobuffer(target, region.base, region.length));
    218 
    219 	case 2:
    220 		if (region.length != 18) {
    221 			return (DNS_R_FORMERR);
    222 		}
    223 		isc_buffer_forward(source, region.length);
    224 		return (mem_tobuffer(target, region.base, region.length));
    225 
    226 	case 3:
    227 		RETERR(mem_tobuffer(target, region.base, 2));
    228 		isc_buffer_forward(source, 2);
    229 		dns_name_init(&name, NULL);
    230 		return (dns_name_fromwire(&name, source, dctx, options,
    231 					  target));
    232 
    233 	default:
    234 		isc_buffer_forward(source, region.length);
    235 		return (mem_tobuffer(target, region.base, region.length));
    236 	}
    237 }
    238 
    239 static isc_result_t
    240 towire_amtrelay(ARGS_TOWIRE) {
    241 	isc_region_t region;
    242 
    243 	REQUIRE(rdata->type == dns_rdatatype_amtrelay);
    244 	REQUIRE(rdata->length != 0);
    245 
    246 	UNUSED(cctx);
    247 
    248 	dns_rdata_toregion(rdata, &region);
    249 	return (mem_tobuffer(target, region.base, region.length));
    250 }
    251 
    252 static int
    253 compare_amtrelay(ARGS_COMPARE) {
    254 	isc_region_t region1;
    255 	isc_region_t region2;
    256 
    257 	REQUIRE(rdata1->type == rdata2->type);
    258 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
    259 	REQUIRE(rdata1->type == dns_rdatatype_amtrelay);
    260 	REQUIRE(rdata1->length >= 2);
    261 	REQUIRE(rdata2->length >= 2);
    262 
    263 	dns_rdata_toregion(rdata1, &region1);
    264 	dns_rdata_toregion(rdata2, &region2);
    265 
    266 	return (isc_region_compare(&region1, &region2));
    267 }
    268 
    269 static isc_result_t
    270 fromstruct_amtrelay(ARGS_FROMSTRUCT) {
    271 	dns_rdata_amtrelay_t *amtrelay = source;
    272 	isc_region_t region;
    273 	uint32_t n;
    274 
    275 	REQUIRE(type == dns_rdatatype_amtrelay);
    276 	REQUIRE(amtrelay != NULL);
    277 	REQUIRE(amtrelay->common.rdtype == type);
    278 	REQUIRE(amtrelay->common.rdclass == rdclass);
    279 
    280 	UNUSED(type);
    281 	UNUSED(rdclass);
    282 
    283 	RETERR(uint8_tobuffer(amtrelay->precedence, target));
    284 	n = (amtrelay->discovery ? 0x80 : 0) | amtrelay->gateway_type;
    285 	RETERR(uint8_tobuffer(n, target));
    286 
    287 	switch (amtrelay->gateway_type) {
    288 	case 0:
    289 		return (ISC_R_SUCCESS);
    290 
    291 	case 1:
    292 		n = ntohl(amtrelay->in_addr.s_addr);
    293 		return (uint32_tobuffer(n, target));
    294 
    295 	case 2:
    296 		return (mem_tobuffer(target, amtrelay->in6_addr.s6_addr, 16));
    297 		break;
    298 
    299 	case 3:
    300 		dns_name_toregion(&amtrelay->gateway, &region);
    301 		return (isc_buffer_copyregion(target, &region));
    302 		break;
    303 
    304 	default:
    305 		return (mem_tobuffer(target, amtrelay->data, amtrelay->length));
    306 	}
    307 }
    308 
    309 static isc_result_t
    310 tostruct_amtrelay(ARGS_TOSTRUCT) {
    311 	isc_region_t region;
    312 	dns_rdata_amtrelay_t *amtrelay = target;
    313 	dns_name_t name;
    314 	uint32_t n;
    315 
    316 	REQUIRE(rdata->type == dns_rdatatype_amtrelay);
    317 	REQUIRE(amtrelay != NULL);
    318 	REQUIRE(rdata->length >= 2);
    319 
    320 	amtrelay->common.rdclass = rdata->rdclass;
    321 	amtrelay->common.rdtype = rdata->type;
    322 	ISC_LINK_INIT(&amtrelay->common, link);
    323 
    324 	dns_name_init(&amtrelay->gateway, NULL);
    325 	amtrelay->data = NULL;
    326 
    327 	dns_name_init(&name, NULL);
    328 	dns_rdata_toregion(rdata, &region);
    329 
    330 	amtrelay->precedence = uint8_fromregion(&region);
    331 	isc_region_consume(&region, 1);
    332 
    333 	amtrelay->gateway_type = uint8_fromregion(&region);
    334 	amtrelay->discovery = (amtrelay->gateway_type & 0x80) != 0;
    335 	amtrelay->gateway_type &= 0x7f;
    336 	isc_region_consume(&region, 1);
    337 
    338 	switch (amtrelay->gateway_type) {
    339 	case 0:
    340 		break;
    341 
    342 	case 1:
    343 		n = uint32_fromregion(&region);
    344 		amtrelay->in_addr.s_addr = htonl(n);
    345 		isc_region_consume(&region, 4);
    346 		break;
    347 
    348 	case 2:
    349 		memmove(amtrelay->in6_addr.s6_addr, region.base, 16);
    350 		isc_region_consume(&region, 16);
    351 		break;
    352 
    353 	case 3:
    354 		dns_name_fromregion(&name, &region);
    355 		RETERR(name_duporclone(&name, mctx, &amtrelay->gateway));
    356 		isc_region_consume(&region, name_length(&name));
    357 		break;
    358 
    359 	default:
    360 		if (region.length != 0) {
    361 			amtrelay->data = mem_maybedup(mctx, region.base,
    362 						      region.length);
    363 			if (amtrelay->data == NULL) {
    364 				return (ISC_R_NOMEMORY);
    365 			}
    366 		}
    367 		amtrelay->length = region.length;
    368 	}
    369 	amtrelay->mctx = mctx;
    370 	return (ISC_R_SUCCESS);
    371 }
    372 
    373 static void
    374 freestruct_amtrelay(ARGS_FREESTRUCT) {
    375 	dns_rdata_amtrelay_t *amtrelay = source;
    376 
    377 	REQUIRE(amtrelay != NULL);
    378 	REQUIRE(amtrelay->common.rdtype == dns_rdatatype_amtrelay);
    379 
    380 	if (amtrelay->mctx == NULL) {
    381 		return;
    382 	}
    383 
    384 	if (amtrelay->gateway_type == 3) {
    385 		dns_name_free(&amtrelay->gateway, amtrelay->mctx);
    386 	}
    387 
    388 	if (amtrelay->data != NULL) {
    389 		isc_mem_free(amtrelay->mctx, amtrelay->data);
    390 	}
    391 
    392 	amtrelay->mctx = NULL;
    393 }
    394 
    395 static isc_result_t
    396 additionaldata_amtrelay(ARGS_ADDLDATA) {
    397 	REQUIRE(rdata->type == dns_rdatatype_amtrelay);
    398 
    399 	UNUSED(rdata);
    400 	UNUSED(add);
    401 	UNUSED(arg);
    402 
    403 	return (ISC_R_SUCCESS);
    404 }
    405 
    406 static isc_result_t
    407 digest_amtrelay(ARGS_DIGEST) {
    408 	isc_region_t region;
    409 
    410 	REQUIRE(rdata->type == dns_rdatatype_amtrelay);
    411 
    412 	dns_rdata_toregion(rdata, &region);
    413 	return ((digest)(arg, &region));
    414 }
    415 
    416 static bool
    417 checkowner_amtrelay(ARGS_CHECKOWNER) {
    418 	REQUIRE(type == dns_rdatatype_amtrelay);
    419 
    420 	UNUSED(name);
    421 	UNUSED(type);
    422 	UNUSED(rdclass);
    423 	UNUSED(wildcard);
    424 
    425 	return (true);
    426 }
    427 
    428 static bool
    429 checknames_amtrelay(ARGS_CHECKNAMES) {
    430 	REQUIRE(rdata->type == dns_rdatatype_amtrelay);
    431 
    432 	UNUSED(rdata);
    433 	UNUSED(owner);
    434 	UNUSED(bad);
    435 
    436 	return (true);
    437 }
    438 
    439 static int
    440 casecompare_amtrelay(ARGS_COMPARE) {
    441 	isc_region_t region1;
    442 	isc_region_t region2;
    443 	dns_name_t name1;
    444 	dns_name_t name2;
    445 
    446 	REQUIRE(rdata1->type == rdata2->type);
    447 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
    448 	REQUIRE(rdata1->type == dns_rdatatype_amtrelay);
    449 	REQUIRE(rdata1->length >= 2);
    450 	REQUIRE(rdata2->length >= 2);
    451 
    452 	dns_rdata_toregion(rdata1, &region1);
    453 	dns_rdata_toregion(rdata2, &region2);
    454 
    455 	if (memcmp(region1.base, region2.base, 2) != 0 ||
    456 	    (region1.base[1] & 0x7f) != 3)
    457 	{
    458 		return (isc_region_compare(&region1, &region2));
    459 	}
    460 
    461 	dns_name_init(&name1, NULL);
    462 	dns_name_init(&name2, NULL);
    463 
    464 	isc_region_consume(&region1, 2);
    465 	isc_region_consume(&region2, 2);
    466 
    467 	dns_name_fromregion(&name1, &region1);
    468 	dns_name_fromregion(&name2, &region2);
    469 
    470 	return (dns_name_rdatacompare(&name1, &name2));
    471 }
    472 
    473 #endif /* RDATA_GENERIC_AMTRELAY_260_C */
    474