1/*	$NetBSD: csync_62.c,v 1.8 2024/02/21 22:52:12 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/* RFC 7477 */
17
18#ifndef RDATA_GENERIC_CSYNC_62_C
19#define RDATA_GENERIC_CSYNC_62_C
20
21#define RRTYPE_CSYNC_ATTRIBUTES 0
22
23static isc_result_t
24fromtext_csync(ARGS_FROMTEXT) {
25	isc_token_t token;
26
27	REQUIRE(type == dns_rdatatype_csync);
28
29	UNUSED(type);
30	UNUSED(rdclass);
31	UNUSED(origin);
32	UNUSED(options);
33	UNUSED(callbacks);
34
35	/* Serial. */
36	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
37				      false));
38	RETERR(uint32_tobuffer(token.value.as_ulong, target));
39
40	/* Flags. */
41	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
42				      false));
43	if (token.value.as_ulong > 0xffffU) {
44		RETTOK(ISC_R_RANGE);
45	}
46	RETERR(uint16_tobuffer(token.value.as_ulong, target));
47
48	/* Type Map */
49	return (typemap_fromtext(lexer, target, true));
50}
51
52static isc_result_t
53totext_csync(ARGS_TOTEXT) {
54	unsigned long num;
55	char buf[sizeof("0123456789")]; /* Also TYPE65535 */
56	isc_region_t sr;
57
58	REQUIRE(rdata->type == dns_rdatatype_csync);
59	REQUIRE(rdata->length >= 6);
60
61	UNUSED(tctx);
62
63	dns_rdata_toregion(rdata, &sr);
64
65	num = uint32_fromregion(&sr);
66	isc_region_consume(&sr, 4);
67	snprintf(buf, sizeof(buf), "%lu", num);
68	RETERR(str_totext(buf, target));
69
70	RETERR(str_totext(" ", target));
71
72	num = uint16_fromregion(&sr);
73	isc_region_consume(&sr, 2);
74	snprintf(buf, sizeof(buf), "%lu", num);
75	RETERR(str_totext(buf, target));
76
77	/*
78	 * Don't leave a trailing space when there's no typemap present.
79	 */
80	if (sr.length > 0) {
81		RETERR(str_totext(" ", target));
82	}
83	return (typemap_totext(&sr, NULL, target));
84}
85
86static isc_result_t
87fromwire_csync(ARGS_FROMWIRE) {
88	isc_region_t sr;
89
90	REQUIRE(type == dns_rdatatype_csync);
91
92	UNUSED(type);
93	UNUSED(rdclass);
94	UNUSED(options);
95	UNUSED(dctx);
96
97	/*
98	 * Serial + Flags
99	 */
100	isc_buffer_activeregion(source, &sr);
101	if (sr.length < 6) {
102		return (ISC_R_UNEXPECTEDEND);
103	}
104
105	RETERR(mem_tobuffer(target, sr.base, 6));
106	isc_buffer_forward(source, 6);
107	isc_region_consume(&sr, 6);
108
109	RETERR(typemap_test(&sr, true));
110
111	RETERR(mem_tobuffer(target, sr.base, sr.length));
112	isc_buffer_forward(source, sr.length);
113	return (ISC_R_SUCCESS);
114}
115
116static isc_result_t
117towire_csync(ARGS_TOWIRE) {
118	REQUIRE(rdata->type == dns_rdatatype_csync);
119	REQUIRE(rdata->length >= 6);
120
121	UNUSED(cctx);
122
123	return (mem_tobuffer(target, rdata->data, rdata->length));
124}
125
126static int
127compare_csync(ARGS_COMPARE) {
128	isc_region_t r1;
129	isc_region_t r2;
130
131	REQUIRE(rdata1->type == rdata2->type);
132	REQUIRE(rdata1->rdclass == rdata2->rdclass);
133	REQUIRE(rdata1->type == dns_rdatatype_csync);
134	REQUIRE(rdata1->length >= 6);
135	REQUIRE(rdata2->length >= 6);
136
137	dns_rdata_toregion(rdata1, &r1);
138	dns_rdata_toregion(rdata2, &r2);
139	return (isc_region_compare(&r1, &r2));
140}
141
142static isc_result_t
143fromstruct_csync(ARGS_FROMSTRUCT) {
144	dns_rdata_csync_t *csync = source;
145	isc_region_t region;
146
147	REQUIRE(type == dns_rdatatype_csync);
148	REQUIRE(csync != NULL);
149	REQUIRE(csync->common.rdtype == type);
150	REQUIRE(csync->common.rdclass == rdclass);
151	REQUIRE(csync->typebits != NULL || csync->len == 0);
152
153	UNUSED(type);
154	UNUSED(rdclass);
155
156	RETERR(uint32_tobuffer(csync->serial, target));
157	RETERR(uint16_tobuffer(csync->flags, target));
158
159	region.base = csync->typebits;
160	region.length = csync->len;
161	RETERR(typemap_test(&region, true));
162	return (mem_tobuffer(target, csync->typebits, csync->len));
163}
164
165static isc_result_t
166tostruct_csync(ARGS_TOSTRUCT) {
167	isc_region_t region;
168	dns_rdata_csync_t *csync = target;
169
170	REQUIRE(rdata->type == dns_rdatatype_csync);
171	REQUIRE(csync != NULL);
172	REQUIRE(rdata->length != 0);
173
174	csync->common.rdclass = rdata->rdclass;
175	csync->common.rdtype = rdata->type;
176	ISC_LINK_INIT(&csync->common, link);
177
178	dns_rdata_toregion(rdata, &region);
179
180	csync->serial = uint32_fromregion(&region);
181	isc_region_consume(&region, 4);
182
183	csync->flags = uint16_fromregion(&region);
184	isc_region_consume(&region, 2);
185
186	csync->len = region.length;
187	csync->typebits = mem_maybedup(mctx, region.base, region.length);
188	if (csync->typebits == NULL) {
189		goto cleanup;
190	}
191
192	csync->mctx = mctx;
193	return (ISC_R_SUCCESS);
194
195cleanup:
196	return (ISC_R_NOMEMORY);
197}
198
199static void
200freestruct_csync(ARGS_FREESTRUCT) {
201	dns_rdata_csync_t *csync = source;
202
203	REQUIRE(csync != NULL);
204	REQUIRE(csync->common.rdtype == dns_rdatatype_csync);
205
206	if (csync->mctx == NULL) {
207		return;
208	}
209
210	if (csync->typebits != NULL) {
211		isc_mem_free(csync->mctx, csync->typebits);
212	}
213	csync->mctx = NULL;
214}
215
216static isc_result_t
217additionaldata_csync(ARGS_ADDLDATA) {
218	REQUIRE(rdata->type == dns_rdatatype_csync);
219
220	UNUSED(rdata);
221	UNUSED(owner);
222	UNUSED(add);
223	UNUSED(arg);
224
225	return (ISC_R_SUCCESS);
226}
227
228static isc_result_t
229digest_csync(ARGS_DIGEST) {
230	isc_region_t r;
231
232	REQUIRE(rdata->type == dns_rdatatype_csync);
233
234	dns_rdata_toregion(rdata, &r);
235	return ((digest)(arg, &r));
236}
237
238static bool
239checkowner_csync(ARGS_CHECKOWNER) {
240	REQUIRE(type == dns_rdatatype_csync);
241
242	UNUSED(name);
243	UNUSED(type);
244	UNUSED(rdclass);
245	UNUSED(wildcard);
246
247	return (true);
248}
249
250static bool
251checknames_csync(ARGS_CHECKNAMES) {
252	REQUIRE(rdata->type == dns_rdatatype_csync);
253
254	UNUSED(rdata);
255	UNUSED(owner);
256	UNUSED(bad);
257
258	return (true);
259}
260
261static int
262casecompare_csync(ARGS_COMPARE) {
263	isc_region_t region1;
264	isc_region_t region2;
265
266	REQUIRE(rdata1->type == rdata2->type);
267	REQUIRE(rdata1->rdclass == rdata2->rdclass);
268	REQUIRE(rdata1->type == dns_rdatatype_csync);
269	REQUIRE(rdata1->length >= 6);
270	REQUIRE(rdata2->length >= 6);
271
272	dns_rdata_toregion(rdata1, &region1);
273	dns_rdata_toregion(rdata2, &region2);
274	return (isc_region_compare(&region1, &region2));
275}
276#endif /* RDATA_GENERIC_CSYNC_62_C */
277