1 /* $NetBSD: a_1.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 /* 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
fromtext_ch_a(ARGS_FROMTEXT)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
totext_ch_a(ARGS_TOTEXT)70 totext_ch_a(ARGS_TOTEXT) {
71 isc_region_t region;
72 dns_name_t name;
73 dns_name_t prefix;
74 bool sub;
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, ®ion);
86 dns_name_fromregion(&name, ®ion);
87 isc_region_consume(®ion, name_length(&name));
88 addr = uint16_fromregion(®ion);
89
90 sub = name_prefix(&name, tctx->origin, &prefix);
91 RETERR(dns_name_totext(&prefix, sub, target));
92
93 snprintf(buf, sizeof(buf), "%o", addr); /* note octal */
94 RETERR(str_totext(" ", target));
95 return (str_totext(buf, target));
96 }
97
98 static isc_result_t
fromwire_ch_a(ARGS_FROMWIRE)99 fromwire_ch_a(ARGS_FROMWIRE) {
100 isc_region_t sregion;
101 isc_region_t tregion;
102 dns_name_t name;
103
104 REQUIRE(type == dns_rdatatype_a);
105 REQUIRE(rdclass == dns_rdataclass_ch);
106
107 UNUSED(type);
108 UNUSED(rdclass);
109
110 dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
111
112 dns_name_init(&name, NULL);
113
114 RETERR(dns_name_fromwire(&name, source, dctx, options, target));
115
116 isc_buffer_activeregion(source, &sregion);
117 isc_buffer_availableregion(target, &tregion);
118 if (sregion.length < 2) {
119 return (ISC_R_UNEXPECTEDEND);
120 }
121 if (tregion.length < 2) {
122 return (ISC_R_NOSPACE);
123 }
124
125 memmove(tregion.base, sregion.base, 2);
126 isc_buffer_forward(source, 2);
127 isc_buffer_add(target, 2);
128
129 return (ISC_R_SUCCESS);
130 }
131
132 static isc_result_t
towire_ch_a(ARGS_TOWIRE)133 towire_ch_a(ARGS_TOWIRE) {
134 dns_name_t name;
135 dns_offsets_t offsets;
136 isc_region_t sregion;
137 isc_region_t tregion;
138
139 REQUIRE(rdata->type == dns_rdatatype_a);
140 REQUIRE(rdata->rdclass == dns_rdataclass_ch);
141 REQUIRE(rdata->length != 0);
142
143 dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
144
145 dns_name_init(&name, offsets);
146
147 dns_rdata_toregion(rdata, &sregion);
148
149 dns_name_fromregion(&name, &sregion);
150 isc_region_consume(&sregion, name_length(&name));
151 RETERR(dns_name_towire(&name, cctx, target));
152
153 isc_buffer_availableregion(target, &tregion);
154 if (tregion.length < 2) {
155 return (ISC_R_NOSPACE);
156 }
157
158 memmove(tregion.base, sregion.base, 2);
159 isc_buffer_add(target, 2);
160 return (ISC_R_SUCCESS);
161 }
162
163 static int
compare_ch_a(ARGS_COMPARE)164 compare_ch_a(ARGS_COMPARE) {
165 dns_name_t name1;
166 dns_name_t name2;
167 isc_region_t region1;
168 isc_region_t region2;
169 int order;
170
171 REQUIRE(rdata1->type == rdata2->type);
172 REQUIRE(rdata1->rdclass == rdata2->rdclass);
173 REQUIRE(rdata1->type == dns_rdatatype_a);
174 REQUIRE(rdata1->rdclass == dns_rdataclass_ch);
175 REQUIRE(rdata1->length != 0);
176 REQUIRE(rdata2->length != 0);
177
178 dns_name_init(&name1, NULL);
179 dns_name_init(&name2, NULL);
180
181 dns_rdata_toregion(rdata1, ®ion1);
182 dns_rdata_toregion(rdata2, ®ion2);
183
184 dns_name_fromregion(&name1, ®ion1);
185 dns_name_fromregion(&name2, ®ion2);
186 isc_region_consume(®ion1, name_length(&name1));
187 isc_region_consume(®ion2, name_length(&name2));
188
189 order = dns_name_rdatacompare(&name1, &name2);
190 if (order != 0) {
191 return (order);
192 }
193
194 order = memcmp(region1.base, region2.base, 2);
195 if (order != 0) {
196 order = (order < 0) ? -1 : 1;
197 }
198 return (order);
199 }
200
201 static isc_result_t
fromstruct_ch_a(ARGS_FROMSTRUCT)202 fromstruct_ch_a(ARGS_FROMSTRUCT) {
203 dns_rdata_ch_a_t *a = source;
204 isc_region_t region;
205
206 REQUIRE(type == dns_rdatatype_a);
207 REQUIRE(a != NULL);
208 REQUIRE(a->common.rdtype == type);
209 REQUIRE(a->common.rdclass == rdclass);
210
211 UNUSED(type);
212 UNUSED(rdclass);
213
214 dns_name_toregion(&a->ch_addr_dom, ®ion);
215 RETERR(isc_buffer_copyregion(target, ®ion));
216
217 return (uint16_tobuffer(ntohs(a->ch_addr), target));
218 }
219
220 static isc_result_t
tostruct_ch_a(ARGS_TOSTRUCT)221 tostruct_ch_a(ARGS_TOSTRUCT) {
222 dns_rdata_ch_a_t *a = target;
223 isc_region_t region;
224 dns_name_t name;
225
226 REQUIRE(rdata->type == dns_rdatatype_a);
227 REQUIRE(rdata->rdclass == dns_rdataclass_ch);
228 REQUIRE(rdata->length != 0);
229
230 a->common.rdclass = rdata->rdclass;
231 a->common.rdtype = rdata->type;
232 ISC_LINK_INIT(&a->common, link);
233
234 dns_rdata_toregion(rdata, ®ion);
235
236 dns_name_init(&name, NULL);
237 dns_name_fromregion(&name, ®ion);
238 isc_region_consume(®ion, name_length(&name));
239
240 dns_name_init(&a->ch_addr_dom, NULL);
241 RETERR(name_duporclone(&name, mctx, &a->ch_addr_dom));
242 a->ch_addr = htons(uint16_fromregion(®ion));
243 a->mctx = mctx;
244 return (ISC_R_SUCCESS);
245 }
246
247 static void
freestruct_ch_a(ARGS_FREESTRUCT)248 freestruct_ch_a(ARGS_FREESTRUCT) {
249 dns_rdata_ch_a_t *a = source;
250
251 REQUIRE(a != NULL);
252 REQUIRE(a->common.rdtype == dns_rdatatype_a);
253
254 if (a->mctx == NULL) {
255 return;
256 }
257
258 dns_name_free(&a->ch_addr_dom, a->mctx);
259 a->mctx = NULL;
260 }
261
262 static isc_result_t
additionaldata_ch_a(ARGS_ADDLDATA)263 additionaldata_ch_a(ARGS_ADDLDATA) {
264 REQUIRE(rdata->type == dns_rdatatype_a);
265 REQUIRE(rdata->rdclass == dns_rdataclass_ch);
266
267 UNUSED(rdata);
268 UNUSED(add);
269 UNUSED(arg);
270
271 return (ISC_R_SUCCESS);
272 }
273
274 static isc_result_t
digest_ch_a(ARGS_DIGEST)275 digest_ch_a(ARGS_DIGEST) {
276 isc_region_t r;
277 dns_name_t name;
278
279 REQUIRE(rdata->type == dns_rdatatype_a);
280 REQUIRE(rdata->rdclass == dns_rdataclass_ch);
281
282 dns_rdata_toregion(rdata, &r);
283 dns_name_init(&name, NULL);
284 dns_name_fromregion(&name, &r);
285 isc_region_consume(&r, name_length(&name));
286 RETERR(dns_name_digest(&name, digest, arg));
287 return ((digest)(arg, &r));
288 }
289
290 static bool
checkowner_ch_a(ARGS_CHECKOWNER)291 checkowner_ch_a(ARGS_CHECKOWNER) {
292 REQUIRE(type == dns_rdatatype_a);
293 REQUIRE(rdclass == dns_rdataclass_ch);
294
295 UNUSED(type);
296
297 return (dns_name_ishostname(name, wildcard));
298 }
299
300 static bool
checknames_ch_a(ARGS_CHECKNAMES)301 checknames_ch_a(ARGS_CHECKNAMES) {
302 isc_region_t region;
303 dns_name_t name;
304
305 REQUIRE(rdata->type == dns_rdatatype_a);
306 REQUIRE(rdata->rdclass == dns_rdataclass_ch);
307
308 UNUSED(owner);
309
310 dns_rdata_toregion(rdata, ®ion);
311 dns_name_init(&name, NULL);
312 dns_name_fromregion(&name, ®ion);
313 if (!dns_name_ishostname(&name, false)) {
314 if (bad != NULL) {
315 dns_name_clone(&name, bad);
316 }
317 return (false);
318 }
319
320 return (true);
321 }
322
323 static int
casecompare_ch_a(ARGS_COMPARE)324 casecompare_ch_a(ARGS_COMPARE) {
325 return (compare_ch_a(rdata1, rdata2));
326 }
327 #endif /* RDATA_CH_3_A_1_C */
328