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