xref: /netbsd-src/external/mpl/bind/dist/lib/dns/rdata/ch_3/a_1.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
1 /*	$NetBSD: a_1.c,v 1.9 2025/01/26 16:25:30 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 /* by Bjorn.Victor@it.uu.se, 2005-05-07 */
17 /* Based on generic/soa_6.c and generic/mx_15.c */
18 
19 #ifndef RDATA_CH_3_A_1_C
20 #define RDATA_CH_3_A_1_C
21 
22 #include <isc/net.h>
23 
24 #define RRTYPE_A_ATTRIBUTES (0)
25 
26 static isc_result_t
27 fromtext_ch_a(ARGS_FROMTEXT) {
28 	isc_token_t token;
29 	dns_name_t name;
30 	isc_buffer_t buffer;
31 
32 	REQUIRE(type == dns_rdatatype_a);
33 	REQUIRE(rdclass == dns_rdataclass_ch); /* 3 */
34 
35 	UNUSED(type);
36 	UNUSED(callbacks);
37 
38 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
39 				      false));
40 
41 	/* get domain name */
42 	dns_name_init(&name, NULL);
43 	buffer_fromregion(&buffer, &token.value.as_region);
44 	if (origin == NULL) {
45 		origin = dns_rootname;
46 	}
47 	RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
48 	if ((options & DNS_RDATA_CHECKNAMES) != 0 &&
49 	    (options & DNS_RDATA_CHECKREVERSE) != 0)
50 	{
51 		bool ok;
52 		ok = dns_name_ishostname(&name, false);
53 		if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) {
54 			RETTOK(DNS_R_BADNAME);
55 		}
56 		if (!ok && callbacks != NULL) {
57 			warn_badname(&name, lexer, callbacks);
58 		}
59 	}
60 
61 	/* 16-bit octal address */
62 	RETERR(isc_lex_getoctaltoken(lexer, &token, false));
63 	if (token.value.as_ulong > 0xffffU) {
64 		RETTOK(ISC_R_RANGE);
65 	}
66 	return uint16_tobuffer(token.value.as_ulong, target);
67 }
68 
69 static isc_result_t
70 totext_ch_a(ARGS_TOTEXT) {
71 	isc_region_t region;
72 	dns_name_t name;
73 	dns_name_t prefix;
74 	unsigned int opts;
75 	char buf[sizeof("0177777")];
76 	uint16_t addr;
77 
78 	REQUIRE(rdata->type == dns_rdatatype_a);
79 	REQUIRE(rdata->rdclass == dns_rdataclass_ch); /* 3 */
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 	dns_name_fromregion(&name, &region);
87 	isc_region_consume(&region, name_length(&name));
88 	addr = uint16_fromregion(&region);
89 
90 	opts = name_prefix(&name, tctx->origin, &prefix) ? DNS_NAME_OMITFINALDOT
91 							 : 0;
92 	RETERR(dns_name_totext(&prefix, opts, target));
93 
94 	snprintf(buf, sizeof(buf), "%o", addr); /* note octal */
95 	RETERR(str_totext(" ", target));
96 	return str_totext(buf, target);
97 }
98 
99 static isc_result_t
100 fromwire_ch_a(ARGS_FROMWIRE) {
101 	isc_region_t sregion;
102 	isc_region_t tregion;
103 	dns_name_t name;
104 
105 	REQUIRE(type == dns_rdatatype_a);
106 	REQUIRE(rdclass == dns_rdataclass_ch);
107 
108 	UNUSED(type);
109 	UNUSED(rdclass);
110 
111 	dctx = dns_decompress_setpermitted(dctx, true);
112 
113 	dns_name_init(&name, NULL);
114 
115 	RETERR(dns_name_fromwire(&name, source, dctx, target));
116 
117 	isc_buffer_activeregion(source, &sregion);
118 	isc_buffer_availableregion(target, &tregion);
119 	if (sregion.length < 2) {
120 		return ISC_R_UNEXPECTEDEND;
121 	}
122 	if (tregion.length < 2) {
123 		return ISC_R_NOSPACE;
124 	}
125 
126 	memmove(tregion.base, sregion.base, 2);
127 	isc_buffer_forward(source, 2);
128 	isc_buffer_add(target, 2);
129 
130 	return ISC_R_SUCCESS;
131 }
132 
133 static isc_result_t
134 towire_ch_a(ARGS_TOWIRE) {
135 	dns_name_t name;
136 	dns_offsets_t offsets;
137 	isc_region_t sregion;
138 	isc_region_t tregion;
139 
140 	REQUIRE(rdata->type == dns_rdatatype_a);
141 	REQUIRE(rdata->rdclass == dns_rdataclass_ch);
142 	REQUIRE(rdata->length != 0);
143 
144 	dns_compress_setpermitted(cctx, true);
145 
146 	dns_name_init(&name, offsets);
147 
148 	dns_rdata_toregion(rdata, &sregion);
149 
150 	dns_name_fromregion(&name, &sregion);
151 	isc_region_consume(&sregion, name_length(&name));
152 	RETERR(dns_name_towire(&name, cctx, target, NULL));
153 
154 	isc_buffer_availableregion(target, &tregion);
155 	if (tregion.length < 2) {
156 		return ISC_R_NOSPACE;
157 	}
158 
159 	memmove(tregion.base, sregion.base, 2);
160 	isc_buffer_add(target, 2);
161 	return ISC_R_SUCCESS;
162 }
163 
164 static int
165 compare_ch_a(ARGS_COMPARE) {
166 	dns_name_t name1;
167 	dns_name_t name2;
168 	isc_region_t region1;
169 	isc_region_t region2;
170 	int order;
171 
172 	REQUIRE(rdata1->type == rdata2->type);
173 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
174 	REQUIRE(rdata1->type == dns_rdatatype_a);
175 	REQUIRE(rdata1->rdclass == dns_rdataclass_ch);
176 	REQUIRE(rdata1->length != 0);
177 	REQUIRE(rdata2->length != 0);
178 
179 	dns_name_init(&name1, NULL);
180 	dns_name_init(&name2, NULL);
181 
182 	dns_rdata_toregion(rdata1, &region1);
183 	dns_rdata_toregion(rdata2, &region2);
184 
185 	dns_name_fromregion(&name1, &region1);
186 	dns_name_fromregion(&name2, &region2);
187 	isc_region_consume(&region1, name_length(&name1));
188 	isc_region_consume(&region2, name_length(&name2));
189 
190 	order = dns_name_rdatacompare(&name1, &name2);
191 	if (order != 0) {
192 		return order;
193 	}
194 
195 	order = memcmp(region1.base, region2.base, 2);
196 	if (order != 0) {
197 		order = (order < 0) ? -1 : 1;
198 	}
199 	return order;
200 }
201 
202 static isc_result_t
203 fromstruct_ch_a(ARGS_FROMSTRUCT) {
204 	dns_rdata_ch_a_t *a = source;
205 	isc_region_t region;
206 
207 	REQUIRE(type == dns_rdatatype_a);
208 	REQUIRE(a != NULL);
209 	REQUIRE(a->common.rdtype == type);
210 	REQUIRE(a->common.rdclass == rdclass);
211 
212 	UNUSED(type);
213 	UNUSED(rdclass);
214 
215 	dns_name_toregion(&a->ch_addr_dom, &region);
216 	RETERR(isc_buffer_copyregion(target, &region));
217 
218 	return uint16_tobuffer(ntohs(a->ch_addr), target);
219 }
220 
221 static isc_result_t
222 tostruct_ch_a(ARGS_TOSTRUCT) {
223 	dns_rdata_ch_a_t *a = target;
224 	isc_region_t region;
225 	dns_name_t name;
226 
227 	REQUIRE(rdata->type == dns_rdatatype_a);
228 	REQUIRE(rdata->rdclass == dns_rdataclass_ch);
229 	REQUIRE(rdata->length != 0);
230 
231 	a->common.rdclass = rdata->rdclass;
232 	a->common.rdtype = rdata->type;
233 	ISC_LINK_INIT(&a->common, link);
234 
235 	dns_rdata_toregion(rdata, &region);
236 
237 	dns_name_init(&name, NULL);
238 	dns_name_fromregion(&name, &region);
239 	isc_region_consume(&region, name_length(&name));
240 
241 	dns_name_init(&a->ch_addr_dom, NULL);
242 	name_duporclone(&name, mctx, &a->ch_addr_dom);
243 	a->ch_addr = htons(uint16_fromregion(&region));
244 	a->mctx = mctx;
245 	return ISC_R_SUCCESS;
246 }
247 
248 static void
249 freestruct_ch_a(ARGS_FREESTRUCT) {
250 	dns_rdata_ch_a_t *a = source;
251 
252 	REQUIRE(a != NULL);
253 	REQUIRE(a->common.rdtype == dns_rdatatype_a);
254 
255 	if (a->mctx == NULL) {
256 		return;
257 	}
258 
259 	dns_name_free(&a->ch_addr_dom, a->mctx);
260 	a->mctx = NULL;
261 }
262 
263 static isc_result_t
264 additionaldata_ch_a(ARGS_ADDLDATA) {
265 	REQUIRE(rdata->type == dns_rdatatype_a);
266 	REQUIRE(rdata->rdclass == dns_rdataclass_ch);
267 
268 	UNUSED(rdata);
269 	UNUSED(owner);
270 	UNUSED(add);
271 	UNUSED(arg);
272 
273 	return ISC_R_SUCCESS;
274 }
275 
276 static isc_result_t
277 digest_ch_a(ARGS_DIGEST) {
278 	isc_region_t r;
279 	dns_name_t name;
280 
281 	REQUIRE(rdata->type == dns_rdatatype_a);
282 	REQUIRE(rdata->rdclass == dns_rdataclass_ch);
283 
284 	dns_rdata_toregion(rdata, &r);
285 	dns_name_init(&name, NULL);
286 	dns_name_fromregion(&name, &r);
287 	isc_region_consume(&r, name_length(&name));
288 	RETERR(dns_name_digest(&name, digest, arg));
289 	return (digest)(arg, &r);
290 }
291 
292 static bool
293 checkowner_ch_a(ARGS_CHECKOWNER) {
294 	REQUIRE(type == dns_rdatatype_a);
295 	REQUIRE(rdclass == dns_rdataclass_ch);
296 
297 	UNUSED(type);
298 
299 	return dns_name_ishostname(name, wildcard);
300 }
301 
302 static bool
303 checknames_ch_a(ARGS_CHECKNAMES) {
304 	isc_region_t region;
305 	dns_name_t name;
306 
307 	REQUIRE(rdata->type == dns_rdatatype_a);
308 	REQUIRE(rdata->rdclass == dns_rdataclass_ch);
309 
310 	UNUSED(owner);
311 
312 	dns_rdata_toregion(rdata, &region);
313 	dns_name_init(&name, NULL);
314 	dns_name_fromregion(&name, &region);
315 	if (!dns_name_ishostname(&name, false)) {
316 		if (bad != NULL) {
317 			dns_name_clone(&name, bad);
318 		}
319 		return false;
320 	}
321 
322 	return true;
323 }
324 
325 static int
326 casecompare_ch_a(ARGS_COMPARE) {
327 	return compare_ch_a(rdata1, rdata2);
328 }
329 #endif /* RDATA_CH_3_A_1_C */
330