1/*	$NetBSD: rt_21.c,v 1.8 2024/02/21 22:52:14 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/* RFC1183 */
17
18#ifndef RDATA_GENERIC_RT_21_C
19#define RDATA_GENERIC_RT_21_C
20
21#define RRTYPE_RT_ATTRIBUTES (0)
22
23static isc_result_t
24fromtext_rt(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_rt);
31
32	UNUSED(type);
33	UNUSED(rdclass);
34	UNUSED(callbacks);
35
36	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
37				      false));
38	if (token.value.as_ulong > 0xffffU) {
39		RETTOK(ISC_R_RANGE);
40	}
41	RETERR(uint16_tobuffer(token.value.as_ulong, target));
42
43	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
44				      false));
45
46	dns_name_init(&name, NULL);
47	buffer_fromregion(&buffer, &token.value.as_region);
48	if (origin == NULL) {
49		origin = dns_rootname;
50	}
51	RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
52	ok = true;
53	if ((options & DNS_RDATA_CHECKNAMES) != 0) {
54		ok = dns_name_ishostname(&name, false);
55	}
56	if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) {
57		RETTOK(DNS_R_BADNAME);
58	}
59	if (!ok && callbacks != NULL) {
60		warn_badname(&name, lexer, callbacks);
61	}
62	return (ISC_R_SUCCESS);
63}
64
65static isc_result_t
66totext_rt(ARGS_TOTEXT) {
67	isc_region_t region;
68	dns_name_t name;
69	dns_name_t prefix;
70	bool sub;
71	char buf[sizeof("64000")];
72	unsigned short num;
73
74	REQUIRE(rdata->type == dns_rdatatype_rt);
75	REQUIRE(rdata->length != 0);
76
77	dns_name_init(&name, NULL);
78	dns_name_init(&prefix, NULL);
79
80	dns_rdata_toregion(rdata, &region);
81	num = uint16_fromregion(&region);
82	isc_region_consume(&region, 2);
83	snprintf(buf, sizeof(buf), "%u", num);
84	RETERR(str_totext(buf, target));
85	RETERR(str_totext(" ", target));
86	dns_name_fromregion(&name, &region);
87	sub = name_prefix(&name, tctx->origin, &prefix);
88	return (dns_name_totext(&prefix, sub, target));
89}
90
91static isc_result_t
92fromwire_rt(ARGS_FROMWIRE) {
93	dns_name_t name;
94	isc_region_t sregion;
95	isc_region_t tregion;
96
97	REQUIRE(type == dns_rdatatype_rt);
98
99	UNUSED(type);
100	UNUSED(rdclass);
101
102	dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
103
104	dns_name_init(&name, NULL);
105
106	isc_buffer_activeregion(source, &sregion);
107	isc_buffer_availableregion(target, &tregion);
108	if (tregion.length < 2) {
109		return (ISC_R_NOSPACE);
110	}
111	if (sregion.length < 2) {
112		return (ISC_R_UNEXPECTEDEND);
113	}
114	memmove(tregion.base, sregion.base, 2);
115	isc_buffer_forward(source, 2);
116	isc_buffer_add(target, 2);
117	return (dns_name_fromwire(&name, source, dctx, options, target));
118}
119
120static isc_result_t
121towire_rt(ARGS_TOWIRE) {
122	dns_name_t name;
123	dns_offsets_t offsets;
124	isc_region_t region;
125	isc_region_t tr;
126
127	REQUIRE(rdata->type == dns_rdatatype_rt);
128	REQUIRE(rdata->length != 0);
129
130	dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
131	isc_buffer_availableregion(target, &tr);
132	dns_rdata_toregion(rdata, &region);
133	if (tr.length < 2) {
134		return (ISC_R_NOSPACE);
135	}
136	memmove(tr.base, region.base, 2);
137	isc_region_consume(&region, 2);
138	isc_buffer_add(target, 2);
139
140	dns_name_init(&name, offsets);
141	dns_name_fromregion(&name, &region);
142
143	return (dns_name_towire(&name, cctx, target));
144}
145
146static int
147compare_rt(ARGS_COMPARE) {
148	dns_name_t name1;
149	dns_name_t name2;
150	isc_region_t region1;
151	isc_region_t region2;
152	int order;
153
154	REQUIRE(rdata1->type == rdata2->type);
155	REQUIRE(rdata1->rdclass == rdata2->rdclass);
156	REQUIRE(rdata1->type == dns_rdatatype_rt);
157	REQUIRE(rdata1->length != 0);
158	REQUIRE(rdata2->length != 0);
159
160	order = memcmp(rdata1->data, rdata2->data, 2);
161	if (order != 0) {
162		return (order < 0 ? -1 : 1);
163	}
164
165	dns_name_init(&name1, NULL);
166	dns_name_init(&name2, NULL);
167
168	dns_rdata_toregion(rdata1, &region1);
169	dns_rdata_toregion(rdata2, &region2);
170
171	isc_region_consume(&region1, 2);
172	isc_region_consume(&region2, 2);
173
174	dns_name_fromregion(&name1, &region1);
175	dns_name_fromregion(&name2, &region2);
176
177	return (dns_name_rdatacompare(&name1, &name2));
178}
179
180static isc_result_t
181fromstruct_rt(ARGS_FROMSTRUCT) {
182	dns_rdata_rt_t *rt = source;
183	isc_region_t region;
184
185	REQUIRE(type == dns_rdatatype_rt);
186	REQUIRE(rt != NULL);
187	REQUIRE(rt->common.rdtype == type);
188	REQUIRE(rt->common.rdclass == rdclass);
189
190	UNUSED(type);
191	UNUSED(rdclass);
192
193	RETERR(uint16_tobuffer(rt->preference, target));
194	dns_name_toregion(&rt->host, &region);
195	return (isc_buffer_copyregion(target, &region));
196}
197
198static isc_result_t
199tostruct_rt(ARGS_TOSTRUCT) {
200	isc_region_t region;
201	dns_rdata_rt_t *rt = target;
202	dns_name_t name;
203
204	REQUIRE(rdata->type == dns_rdatatype_rt);
205	REQUIRE(rt != NULL);
206	REQUIRE(rdata->length != 0);
207
208	rt->common.rdclass = rdata->rdclass;
209	rt->common.rdtype = rdata->type;
210	ISC_LINK_INIT(&rt->common, link);
211
212	dns_name_init(&name, NULL);
213	dns_rdata_toregion(rdata, &region);
214	rt->preference = uint16_fromregion(&region);
215	isc_region_consume(&region, 2);
216	dns_name_fromregion(&name, &region);
217	dns_name_init(&rt->host, NULL);
218	name_duporclone(&name, mctx, &rt->host);
219
220	rt->mctx = mctx;
221	return (ISC_R_SUCCESS);
222}
223
224static void
225freestruct_rt(ARGS_FREESTRUCT) {
226	dns_rdata_rt_t *rt = source;
227
228	REQUIRE(rt != NULL);
229	REQUIRE(rt->common.rdtype == dns_rdatatype_rt);
230
231	if (rt->mctx == NULL) {
232		return;
233	}
234
235	dns_name_free(&rt->host, rt->mctx);
236	rt->mctx = NULL;
237}
238
239static isc_result_t
240additionaldata_rt(ARGS_ADDLDATA) {
241	dns_name_t name;
242	dns_offsets_t offsets;
243	isc_region_t region;
244	isc_result_t result;
245
246	REQUIRE(rdata->type == dns_rdatatype_rt);
247
248	UNUSED(owner);
249
250	dns_name_init(&name, offsets);
251	dns_rdata_toregion(rdata, &region);
252	isc_region_consume(&region, 2);
253	dns_name_fromregion(&name, &region);
254
255	result = (add)(arg, &name, dns_rdatatype_x25, NULL);
256	if (result != ISC_R_SUCCESS) {
257		return (result);
258	}
259	result = (add)(arg, &name, dns_rdatatype_isdn, NULL);
260	if (result != ISC_R_SUCCESS) {
261		return (result);
262	}
263	return ((add)(arg, &name, dns_rdatatype_a, NULL));
264}
265
266static isc_result_t
267digest_rt(ARGS_DIGEST) {
268	isc_region_t r1, r2;
269	isc_result_t result;
270	dns_name_t name;
271
272	REQUIRE(rdata->type == dns_rdatatype_rt);
273
274	dns_rdata_toregion(rdata, &r1);
275	r2 = r1;
276	isc_region_consume(&r2, 2);
277	r1.length = 2;
278	result = (digest)(arg, &r1);
279	if (result != ISC_R_SUCCESS) {
280		return (result);
281	}
282	dns_name_init(&name, NULL);
283	dns_name_fromregion(&name, &r2);
284	return (dns_name_digest(&name, digest, arg));
285}
286
287static bool
288checkowner_rt(ARGS_CHECKOWNER) {
289	REQUIRE(type == dns_rdatatype_rt);
290
291	UNUSED(name);
292	UNUSED(type);
293	UNUSED(rdclass);
294	UNUSED(wildcard);
295
296	return (true);
297}
298
299static bool
300checknames_rt(ARGS_CHECKNAMES) {
301	isc_region_t region;
302	dns_name_t name;
303
304	REQUIRE(rdata->type == dns_rdatatype_rt);
305
306	UNUSED(owner);
307
308	dns_rdata_toregion(rdata, &region);
309	isc_region_consume(&region, 2);
310	dns_name_init(&name, NULL);
311	dns_name_fromregion(&name, &region);
312	if (!dns_name_ishostname(&name, false)) {
313		if (bad != NULL) {
314			dns_name_clone(&name, bad);
315		}
316		return (false);
317	}
318	return (true);
319}
320
321static int
322casecompare_rt(ARGS_COMPARE) {
323	return (compare_rt(rdata1, rdata2));
324}
325
326#endif /* RDATA_GENERIC_RT_21_C */
327