1 /* $NetBSD: nsec_47.c,v 1.1 2024/02/18 20:57:43 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 3845 */
17
18 #ifndef RDATA_GENERIC_NSEC_47_C
19 #define RDATA_GENERIC_NSEC_47_C
20
21 /*
22 * The attributes do not include DNS_RDATATYPEATTR_SINGLETON
23 * because we must be able to handle a parent/child NSEC pair.
24 */
25 #define RRTYPE_NSEC_ATTRIBUTES \
26 (DNS_RDATATYPEATTR_DNSSEC | DNS_RDATATYPEATTR_ZONECUTAUTH | \
27 DNS_RDATATYPEATTR_ATCNAME)
28
29 static isc_result_t
fromtext_nsec(ARGS_FROMTEXT)30 fromtext_nsec(ARGS_FROMTEXT) {
31 isc_token_t token;
32 dns_name_t name;
33 isc_buffer_t buffer;
34
35 REQUIRE(type == dns_rdatatype_nsec);
36
37 UNUSED(type);
38 UNUSED(rdclass);
39 UNUSED(callbacks);
40
41 /*
42 * Next domain.
43 */
44 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
45 false));
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
53 return (typemap_fromtext(lexer, target, false));
54 }
55
56 static isc_result_t
totext_nsec(ARGS_TOTEXT)57 totext_nsec(ARGS_TOTEXT) {
58 isc_region_t sr;
59 dns_name_t name;
60
61 REQUIRE(rdata->type == dns_rdatatype_nsec);
62 REQUIRE(rdata->length != 0);
63
64 UNUSED(tctx);
65
66 dns_name_init(&name, NULL);
67 dns_rdata_toregion(rdata, &sr);
68 dns_name_fromregion(&name, &sr);
69 isc_region_consume(&sr, name_length(&name));
70 RETERR(dns_name_totext(&name, false, target));
71 /*
72 * Don't leave a trailing space when there's no typemap present.
73 */
74 if (sr.length > 0) {
75 RETERR(str_totext(" ", target));
76 }
77 return (typemap_totext(&sr, NULL, target));
78 }
79
80 static isc_result_t
fromwire_nsec(ARGS_FROMWIRE)81 fromwire_nsec(ARGS_FROMWIRE) {
82 isc_region_t sr;
83 dns_name_t name;
84
85 REQUIRE(type == dns_rdatatype_nsec);
86
87 UNUSED(type);
88 UNUSED(rdclass);
89
90 dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
91
92 dns_name_init(&name, NULL);
93 RETERR(dns_name_fromwire(&name, source, dctx, options, target));
94
95 isc_buffer_activeregion(source, &sr);
96 RETERR(typemap_test(&sr, false));
97 RETERR(mem_tobuffer(target, sr.base, sr.length));
98 isc_buffer_forward(source, sr.length);
99 return (ISC_R_SUCCESS);
100 }
101
102 static isc_result_t
towire_nsec(ARGS_TOWIRE)103 towire_nsec(ARGS_TOWIRE) {
104 isc_region_t sr;
105 dns_name_t name;
106 dns_offsets_t offsets;
107
108 REQUIRE(rdata->type == dns_rdatatype_nsec);
109 REQUIRE(rdata->length != 0);
110
111 dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
112 dns_name_init(&name, offsets);
113 dns_rdata_toregion(rdata, &sr);
114 dns_name_fromregion(&name, &sr);
115 isc_region_consume(&sr, name_length(&name));
116 RETERR(dns_name_towire(&name, cctx, target));
117
118 return (mem_tobuffer(target, sr.base, sr.length));
119 }
120
121 static int
compare_nsec(ARGS_COMPARE)122 compare_nsec(ARGS_COMPARE) {
123 isc_region_t r1;
124 isc_region_t r2;
125
126 REQUIRE(rdata1->type == rdata2->type);
127 REQUIRE(rdata1->rdclass == rdata2->rdclass);
128 REQUIRE(rdata1->type == dns_rdatatype_nsec);
129 REQUIRE(rdata1->length != 0);
130 REQUIRE(rdata2->length != 0);
131
132 dns_rdata_toregion(rdata1, &r1);
133 dns_rdata_toregion(rdata2, &r2);
134 return (isc_region_compare(&r1, &r2));
135 }
136
137 static isc_result_t
fromstruct_nsec(ARGS_FROMSTRUCT)138 fromstruct_nsec(ARGS_FROMSTRUCT) {
139 dns_rdata_nsec_t *nsec = source;
140 isc_region_t region;
141
142 REQUIRE(type == dns_rdatatype_nsec);
143 REQUIRE(nsec != NULL);
144 REQUIRE(nsec->common.rdtype == type);
145 REQUIRE(nsec->common.rdclass == rdclass);
146 REQUIRE(nsec->typebits != NULL || nsec->len == 0);
147
148 UNUSED(type);
149 UNUSED(rdclass);
150
151 dns_name_toregion(&nsec->next, ®ion);
152 RETERR(isc_buffer_copyregion(target, ®ion));
153
154 region.base = nsec->typebits;
155 region.length = nsec->len;
156 RETERR(typemap_test(®ion, false));
157 return (mem_tobuffer(target, nsec->typebits, nsec->len));
158 }
159
160 static isc_result_t
tostruct_nsec(ARGS_TOSTRUCT)161 tostruct_nsec(ARGS_TOSTRUCT) {
162 isc_region_t region;
163 dns_rdata_nsec_t *nsec = target;
164 dns_name_t name;
165
166 REQUIRE(rdata->type == dns_rdatatype_nsec);
167 REQUIRE(nsec != NULL);
168 REQUIRE(rdata->length != 0);
169
170 nsec->common.rdclass = rdata->rdclass;
171 nsec->common.rdtype = rdata->type;
172 ISC_LINK_INIT(&nsec->common, link);
173
174 dns_name_init(&name, NULL);
175 dns_rdata_toregion(rdata, ®ion);
176 dns_name_fromregion(&name, ®ion);
177 isc_region_consume(®ion, name_length(&name));
178 dns_name_init(&nsec->next, NULL);
179 RETERR(name_duporclone(&name, mctx, &nsec->next));
180
181 nsec->len = region.length;
182 nsec->typebits = mem_maybedup(mctx, region.base, region.length);
183 if (nsec->typebits == NULL) {
184 goto cleanup;
185 }
186
187 nsec->mctx = mctx;
188 return (ISC_R_SUCCESS);
189
190 cleanup:
191 if (mctx != NULL) {
192 dns_name_free(&nsec->next, mctx);
193 }
194 return (ISC_R_NOMEMORY);
195 }
196
197 static void
freestruct_nsec(ARGS_FREESTRUCT)198 freestruct_nsec(ARGS_FREESTRUCT) {
199 dns_rdata_nsec_t *nsec = source;
200
201 REQUIRE(nsec != NULL);
202 REQUIRE(nsec->common.rdtype == dns_rdatatype_nsec);
203
204 if (nsec->mctx == NULL) {
205 return;
206 }
207
208 dns_name_free(&nsec->next, nsec->mctx);
209 if (nsec->typebits != NULL) {
210 isc_mem_free(nsec->mctx, nsec->typebits);
211 }
212 nsec->mctx = NULL;
213 }
214
215 static isc_result_t
additionaldata_nsec(ARGS_ADDLDATA)216 additionaldata_nsec(ARGS_ADDLDATA) {
217 REQUIRE(rdata->type == dns_rdatatype_nsec);
218
219 UNUSED(rdata);
220 UNUSED(add);
221 UNUSED(arg);
222
223 return (ISC_R_SUCCESS);
224 }
225
226 static isc_result_t
digest_nsec(ARGS_DIGEST)227 digest_nsec(ARGS_DIGEST) {
228 isc_region_t r;
229
230 REQUIRE(rdata->type == dns_rdatatype_nsec);
231
232 dns_rdata_toregion(rdata, &r);
233 return ((digest)(arg, &r));
234 }
235
236 static bool
checkowner_nsec(ARGS_CHECKOWNER)237 checkowner_nsec(ARGS_CHECKOWNER) {
238 REQUIRE(type == dns_rdatatype_nsec);
239
240 UNUSED(name);
241 UNUSED(type);
242 UNUSED(rdclass);
243 UNUSED(wildcard);
244
245 return (true);
246 }
247
248 static bool
checknames_nsec(ARGS_CHECKNAMES)249 checknames_nsec(ARGS_CHECKNAMES) {
250 REQUIRE(rdata->type == dns_rdatatype_nsec);
251
252 UNUSED(rdata);
253 UNUSED(owner);
254 UNUSED(bad);
255
256 return (true);
257 }
258
259 static int
casecompare_nsec(ARGS_COMPARE)260 casecompare_nsec(ARGS_COMPARE) {
261 isc_region_t region1;
262 isc_region_t region2;
263 dns_name_t name1;
264 dns_name_t name2;
265 int order;
266
267 REQUIRE(rdata1->type == rdata2->type);
268 REQUIRE(rdata1->rdclass == rdata2->rdclass);
269 REQUIRE(rdata1->type == dns_rdatatype_nsec);
270 REQUIRE(rdata1->length != 0);
271 REQUIRE(rdata2->length != 0);
272
273 dns_name_init(&name1, NULL);
274 dns_name_init(&name2, NULL);
275
276 dns_rdata_toregion(rdata1, ®ion1);
277 dns_rdata_toregion(rdata2, ®ion2);
278
279 dns_name_fromregion(&name1, ®ion1);
280 dns_name_fromregion(&name2, ®ion2);
281
282 order = dns_name_rdatacompare(&name1, &name2);
283 if (order != 0) {
284 return (order);
285 }
286
287 isc_region_consume(®ion1, name_length(&name1));
288 isc_region_consume(®ion2, name_length(&name2));
289
290 return (isc_region_compare(®ion1, ®ion2));
291 }
292 #endif /* RDATA_GENERIC_NSEC_47_C */
293