xref: /openbsd-src/usr.bin/dig/lib/dns/rdata/generic/soa_6.c (revision 1fb015a8af3a7e9b85db2510147a155826ef04d9)
15185a700Sflorian /*
25185a700Sflorian  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
35185a700Sflorian  *
45185a700Sflorian  * Permission to use, copy, modify, and/or distribute this software for any
55185a700Sflorian  * purpose with or without fee is hereby granted, provided that the above
65185a700Sflorian  * copyright notice and this permission notice appear in all copies.
75185a700Sflorian  *
85185a700Sflorian  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
95185a700Sflorian  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
105185a700Sflorian  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
115185a700Sflorian  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
125185a700Sflorian  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
135185a700Sflorian  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
145185a700Sflorian  * PERFORMANCE OF THIS SOFTWARE.
155185a700Sflorian  */
165185a700Sflorian 
17*1fb015a8Sflorian /* $Id: soa_6.c,v 1.9 2020/09/14 08:40:43 florian Exp $ */
185185a700Sflorian 
195185a700Sflorian /* Reviewed: Thu Mar 16 15:18:32 PST 2000 by explorer */
205185a700Sflorian 
215185a700Sflorian #ifndef RDATA_GENERIC_SOA_6_C
225185a700Sflorian #define RDATA_GENERIC_SOA_6_C
235185a700Sflorian 
245185a700Sflorian static const char *soa_fieldnames[5] = {
255185a700Sflorian 	"serial", "refresh", "retry", "expire", "minimum"
265185a700Sflorian };
275185a700Sflorian 
285185a700Sflorian static inline isc_result_t
totext_soa(ARGS_TOTEXT)295185a700Sflorian totext_soa(ARGS_TOTEXT) {
305185a700Sflorian 	isc_region_t dregion;
315185a700Sflorian 	dns_name_t mname;
325185a700Sflorian 	dns_name_t rname;
335185a700Sflorian 	dns_name_t prefix;
34*1fb015a8Sflorian 	int sub;
355185a700Sflorian 	int i;
36*1fb015a8Sflorian 	int multiline;
37*1fb015a8Sflorian 	int comm;
385185a700Sflorian 
395185a700Sflorian 	REQUIRE(rdata->type == dns_rdatatype_soa);
405185a700Sflorian 	REQUIRE(rdata->length != 0);
415185a700Sflorian 
42*1fb015a8Sflorian 	multiline = (tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0;
435185a700Sflorian 	if (multiline)
44*1fb015a8Sflorian 		comm = (tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0;
455185a700Sflorian 	else
46*1fb015a8Sflorian 		comm = 0;
475185a700Sflorian 
485185a700Sflorian 	dns_name_init(&mname, NULL);
495185a700Sflorian 	dns_name_init(&rname, NULL);
505185a700Sflorian 	dns_name_init(&prefix, NULL);
515185a700Sflorian 
525185a700Sflorian 	dns_rdata_toregion(rdata, &dregion);
535185a700Sflorian 
545185a700Sflorian 	dns_name_fromregion(&mname, &dregion);
555185a700Sflorian 	isc_region_consume(&dregion, name_length(&mname));
565185a700Sflorian 
575185a700Sflorian 	dns_name_fromregion(&rname, &dregion);
585185a700Sflorian 	isc_region_consume(&dregion, name_length(&rname));
595185a700Sflorian 
605185a700Sflorian 	sub = name_prefix(&mname, tctx->origin, &prefix);
615185a700Sflorian 	RETERR(dns_name_totext(&prefix, sub, target));
625185a700Sflorian 
63873f12b9Sflorian 	RETERR(isc_str_tobuffer(" ", target));
645185a700Sflorian 
655185a700Sflorian 	sub = name_prefix(&rname, tctx->origin, &prefix);
665185a700Sflorian 	RETERR(dns_name_totext(&prefix, sub, target));
675185a700Sflorian 
685185a700Sflorian 	if (multiline)
69873f12b9Sflorian 		RETERR(isc_str_tobuffer(" (" , target));
70873f12b9Sflorian 	RETERR(isc_str_tobuffer(tctx->linebreak, target));
715185a700Sflorian 
725185a700Sflorian 	for (i = 0; i < 5; i++) {
735185a700Sflorian 		char buf[sizeof("0123456789 ; ")];
745185a700Sflorian 		unsigned long num;
755185a700Sflorian 		num = uint32_fromregion(&dregion);
765185a700Sflorian 		isc_region_consume(&dregion, 4);
775185a700Sflorian 		snprintf(buf, sizeof(buf), comm ? "%-10lu ; " : "%lu", num);
78873f12b9Sflorian 		RETERR(isc_str_tobuffer(buf, target));
795185a700Sflorian 		if (comm) {
80873f12b9Sflorian 			RETERR(isc_str_tobuffer(soa_fieldnames[i], target));
815185a700Sflorian 			/* Print times in week/day/hour/minute/second form */
825185a700Sflorian 			if (i >= 1) {
83873f12b9Sflorian 				RETERR(isc_str_tobuffer(" (", target));
84*1fb015a8Sflorian 				RETERR(dns_ttl_totext(num, 1, target));
85873f12b9Sflorian 				RETERR(isc_str_tobuffer(")", target));
865185a700Sflorian 			}
87873f12b9Sflorian 			RETERR(isc_str_tobuffer(tctx->linebreak, target));
885185a700Sflorian 		} else if (i < 4) {
89873f12b9Sflorian 			RETERR(isc_str_tobuffer(tctx->linebreak, target));
905185a700Sflorian 		}
915185a700Sflorian 	}
925185a700Sflorian 
935185a700Sflorian 	if (multiline)
94873f12b9Sflorian 		RETERR(isc_str_tobuffer(")", target));
955185a700Sflorian 
965185a700Sflorian 	return (ISC_R_SUCCESS);
975185a700Sflorian }
985185a700Sflorian 
995185a700Sflorian static inline isc_result_t
fromwire_soa(ARGS_FROMWIRE)1005185a700Sflorian fromwire_soa(ARGS_FROMWIRE) {
1015185a700Sflorian 	dns_name_t mname;
1025185a700Sflorian 	dns_name_t rname;
1035185a700Sflorian 	isc_region_t sregion;
1045185a700Sflorian 	isc_region_t tregion;
1055185a700Sflorian 
1065185a700Sflorian 	REQUIRE(type == dns_rdatatype_soa);
1075185a700Sflorian 
1085185a700Sflorian 	UNUSED(type);
1095185a700Sflorian 	UNUSED(rdclass);
1105185a700Sflorian 
1115185a700Sflorian 	dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
1125185a700Sflorian 
1135185a700Sflorian 	dns_name_init(&mname, NULL);
1145185a700Sflorian 	dns_name_init(&rname, NULL);
1155185a700Sflorian 
1165185a700Sflorian 	RETERR(dns_name_fromwire(&mname, source, dctx, options, target));
1175185a700Sflorian 	RETERR(dns_name_fromwire(&rname, source, dctx, options, target));
1185185a700Sflorian 
1195185a700Sflorian 	isc_buffer_activeregion(source, &sregion);
1205185a700Sflorian 	isc_buffer_availableregion(target, &tregion);
1215185a700Sflorian 
1225185a700Sflorian 	if (sregion.length < 20)
1235185a700Sflorian 		return (ISC_R_UNEXPECTEDEND);
1245185a700Sflorian 	if (tregion.length < 20)
1255185a700Sflorian 		return (ISC_R_NOSPACE);
1265185a700Sflorian 
1275185a700Sflorian 	memmove(tregion.base, sregion.base, 20);
1285185a700Sflorian 	isc_buffer_forward(source, 20);
1295185a700Sflorian 	isc_buffer_add(target, 20);
1305185a700Sflorian 
1315185a700Sflorian 	return (ISC_R_SUCCESS);
1325185a700Sflorian }
1335185a700Sflorian 
1345185a700Sflorian static inline isc_result_t
towire_soa(ARGS_TOWIRE)1355185a700Sflorian towire_soa(ARGS_TOWIRE) {
1365185a700Sflorian 	isc_region_t sregion;
1375185a700Sflorian 	isc_region_t tregion;
1385185a700Sflorian 	dns_name_t mname;
1395185a700Sflorian 	dns_name_t rname;
1405185a700Sflorian 	dns_offsets_t moffsets;
1415185a700Sflorian 	dns_offsets_t roffsets;
1425185a700Sflorian 
1435185a700Sflorian 	REQUIRE(rdata->type == dns_rdatatype_soa);
1445185a700Sflorian 	REQUIRE(rdata->length != 0);
1455185a700Sflorian 
1465185a700Sflorian 	dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
1475185a700Sflorian 
1485185a700Sflorian 	dns_name_init(&mname, moffsets);
1495185a700Sflorian 	dns_name_init(&rname, roffsets);
1505185a700Sflorian 
1515185a700Sflorian 	dns_rdata_toregion(rdata, &sregion);
1525185a700Sflorian 
1535185a700Sflorian 	dns_name_fromregion(&mname, &sregion);
1545185a700Sflorian 	isc_region_consume(&sregion, name_length(&mname));
1555185a700Sflorian 	RETERR(dns_name_towire(&mname, cctx, target));
1565185a700Sflorian 
1575185a700Sflorian 	dns_name_fromregion(&rname, &sregion);
1585185a700Sflorian 	isc_region_consume(&sregion, name_length(&rname));
1595185a700Sflorian 	RETERR(dns_name_towire(&rname, cctx, target));
1605185a700Sflorian 
1615185a700Sflorian 	isc_buffer_availableregion(target, &tregion);
1625185a700Sflorian 	if (tregion.length < 20)
1635185a700Sflorian 		return (ISC_R_NOSPACE);
1645185a700Sflorian 
1655185a700Sflorian 	memmove(tregion.base, sregion.base, 20);
1665185a700Sflorian 	isc_buffer_add(target, 20);
1675185a700Sflorian 	return (ISC_R_SUCCESS);
1685185a700Sflorian }
1695185a700Sflorian 
1705185a700Sflorian static inline isc_result_t
fromstruct_soa(ARGS_FROMSTRUCT)1715185a700Sflorian fromstruct_soa(ARGS_FROMSTRUCT) {
1725185a700Sflorian 	dns_rdata_soa_t *soa = source;
1735185a700Sflorian 	isc_region_t region;
1745185a700Sflorian 
1755185a700Sflorian 	REQUIRE(type == dns_rdatatype_soa);
1765185a700Sflorian 	REQUIRE(source != NULL);
1775185a700Sflorian 	REQUIRE(soa->common.rdtype == type);
1785185a700Sflorian 	REQUIRE(soa->common.rdclass == rdclass);
1795185a700Sflorian 
1805185a700Sflorian 	UNUSED(type);
1815185a700Sflorian 	UNUSED(rdclass);
1825185a700Sflorian 
1835185a700Sflorian 	dns_name_toregion(&soa->origin, &region);
1845185a700Sflorian 	RETERR(isc_buffer_copyregion(target, &region));
1855185a700Sflorian 	dns_name_toregion(&soa->contact, &region);
1865185a700Sflorian 	RETERR(isc_buffer_copyregion(target, &region));
1875185a700Sflorian 	RETERR(uint32_tobuffer(soa->serial, target));
1885185a700Sflorian 	RETERR(uint32_tobuffer(soa->refresh, target));
1895185a700Sflorian 	RETERR(uint32_tobuffer(soa->retry, target));
1905185a700Sflorian 	RETERR(uint32_tobuffer(soa->expire, target));
1915185a700Sflorian 	return (uint32_tobuffer(soa->minimum, target));
1925185a700Sflorian }
1935185a700Sflorian 
1945185a700Sflorian static inline isc_result_t
tostruct_soa(ARGS_TOSTRUCT)1955185a700Sflorian tostruct_soa(ARGS_TOSTRUCT) {
1965185a700Sflorian 	isc_region_t region;
1975185a700Sflorian 	dns_rdata_soa_t *soa = target;
1985185a700Sflorian 	dns_name_t name;
1995185a700Sflorian 	isc_result_t result;
2005185a700Sflorian 
2015185a700Sflorian 	REQUIRE(rdata->type == dns_rdatatype_soa);
2025185a700Sflorian 	REQUIRE(target != NULL);
2035185a700Sflorian 	REQUIRE(rdata->length != 0);
2045185a700Sflorian 
2055185a700Sflorian 	soa->common.rdclass = rdata->rdclass;
2065185a700Sflorian 	soa->common.rdtype = rdata->type;
2075185a700Sflorian 	ISC_LINK_INIT(&soa->common, link);
2085185a700Sflorian 
2095185a700Sflorian 	dns_rdata_toregion(rdata, &region);
2105185a700Sflorian 
2115185a700Sflorian 	dns_name_init(&name, NULL);
2125185a700Sflorian 	dns_name_fromregion(&name, &region);
2135185a700Sflorian 	isc_region_consume(&region, name_length(&name));
2145185a700Sflorian 	dns_name_init(&soa->origin, NULL);
2155185a700Sflorian 	RETERR(name_duporclone(&name, &soa->origin));
2165185a700Sflorian 
2175185a700Sflorian 	dns_name_fromregion(&name, &region);
2185185a700Sflorian 	isc_region_consume(&region, name_length(&name));
2195185a700Sflorian 	dns_name_init(&soa->contact, NULL);
2205185a700Sflorian 	result = name_duporclone(&name, &soa->contact);
2215185a700Sflorian 	if (result != ISC_R_SUCCESS)
2225185a700Sflorian 		goto cleanup;
2235185a700Sflorian 
2245185a700Sflorian 	soa->serial = uint32_fromregion(&region);
2255185a700Sflorian 	isc_region_consume(&region, 4);
2265185a700Sflorian 
2275185a700Sflorian 	soa->refresh = uint32_fromregion(&region);
2285185a700Sflorian 	isc_region_consume(&region, 4);
2295185a700Sflorian 
2305185a700Sflorian 	soa->retry = uint32_fromregion(&region);
2315185a700Sflorian 	isc_region_consume(&region, 4);
2325185a700Sflorian 
2335185a700Sflorian 	soa->expire = uint32_fromregion(&region);
2345185a700Sflorian 	isc_region_consume(&region, 4);
2355185a700Sflorian 
2365185a700Sflorian 	soa->minimum = uint32_fromregion(&region);
2375185a700Sflorian 
2385185a700Sflorian 	return (ISC_R_SUCCESS);
2395185a700Sflorian 
2405185a700Sflorian  cleanup:
2415185a700Sflorian 	dns_name_free(&soa->origin);
2425185a700Sflorian 	return (ISC_R_NOMEMORY);
2435185a700Sflorian }
2445185a700Sflorian 
2455185a700Sflorian static inline void
freestruct_soa(ARGS_FREESTRUCT)2465185a700Sflorian freestruct_soa(ARGS_FREESTRUCT) {
2475185a700Sflorian 	dns_rdata_soa_t *soa = source;
2485185a700Sflorian 
2495185a700Sflorian 	REQUIRE(source != NULL);
2505185a700Sflorian 	REQUIRE(soa->common.rdtype == dns_rdatatype_soa);
2515185a700Sflorian 
2525185a700Sflorian 	dns_name_free(&soa->origin);
2535185a700Sflorian 	dns_name_free(&soa->contact);
2545185a700Sflorian }
2555185a700Sflorian 
2565185a700Sflorian #endif	/* RDATA_GENERIC_SOA_6_C */
257