1 /*
2  * Copyright (C) 2004, 2007-2009, 2011, 2015  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /* $Id: nsec_47.c,v 1.15 2011/01/13 04:59:26 tbox Exp $ */
19 
20 /* reviewed: Wed Mar 15 18:21:15 PST 2000 by brister */
21 
22 /* RFC 3845 */
23 
24 #ifndef RDATA_GENERIC_NSEC_47_C
25 #define RDATA_GENERIC_NSEC_47_C
26 
27 /*
28  * The attributes do not include DNS_RDATATYPEATTR_SINGLETON
29  * because we must be able to handle a parent/child NSEC pair.
30  */
31 #define RRTYPE_NSEC_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC)
32 
33 static inline isc_result_t
fromtext_nsec(ARGS_FROMTEXT)34 fromtext_nsec(ARGS_FROMTEXT) {
35 	isc_token_t token;
36 	dns_name_t name;
37 	isc_buffer_t buffer;
38 
39 	REQUIRE(type == dns_rdatatype_nsec);
40 
41 	UNUSED(type);
42 	UNUSED(rdclass);
43 	UNUSED(callbacks);
44 
45 	/*
46 	 * Next domain.
47 	 */
48 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
49 				      ISC_FALSE));
50 	dns_name_init(&name, NULL);
51 	buffer_fromregion(&buffer, &token.value.as_region);
52 	if (origin == NULL)
53 		origin = dns_rootname;
54 	RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
55 
56 	return (typemap_fromtext(lexer, target, ISC_FALSE));
57 }
58 
59 static inline isc_result_t
totext_nsec(ARGS_TOTEXT)60 totext_nsec(ARGS_TOTEXT) {
61 	isc_region_t sr;
62 	dns_name_t name;
63 
64 	REQUIRE(rdata->type == dns_rdatatype_nsec);
65 	REQUIRE(rdata->length != 0);
66 
67 	UNUSED(tctx);
68 
69 	dns_name_init(&name, NULL);
70 	dns_rdata_toregion(rdata, &sr);
71 	dns_name_fromregion(&name, &sr);
72 	isc_region_consume(&sr, name_length(&name));
73 	RETERR(dns_name_totext(&name, ISC_FALSE, target));
74 	return (typemap_totext(&sr, NULL, target));
75 }
76 
77 static /* inline */ isc_result_t
fromwire_nsec(ARGS_FROMWIRE)78 fromwire_nsec(ARGS_FROMWIRE) {
79 	isc_region_t sr;
80 	dns_name_t name;
81 
82 	REQUIRE(type == dns_rdatatype_nsec);
83 
84 	UNUSED(type);
85 	UNUSED(rdclass);
86 
87 	dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
88 
89 	dns_name_init(&name, NULL);
90 	RETERR(dns_name_fromwire(&name, source, dctx, options, target));
91 
92 	isc_buffer_activeregion(source, &sr);
93 	RETERR(typemap_test(&sr, ISC_FALSE));
94 	RETERR(mem_tobuffer(target, sr.base, sr.length));
95 	isc_buffer_forward(source, sr.length);
96 	return (ISC_R_SUCCESS);
97 }
98 
99 static inline isc_result_t
towire_nsec(ARGS_TOWIRE)100 towire_nsec(ARGS_TOWIRE) {
101 	isc_region_t sr;
102 	dns_name_t name;
103 	dns_offsets_t offsets;
104 
105 	REQUIRE(rdata->type == dns_rdatatype_nsec);
106 	REQUIRE(rdata->length != 0);
107 
108 	dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
109 	dns_name_init(&name, offsets);
110 	dns_rdata_toregion(rdata, &sr);
111 	dns_name_fromregion(&name, &sr);
112 	isc_region_consume(&sr, name_length(&name));
113 	RETERR(dns_name_towire(&name, cctx, target));
114 
115 	return (mem_tobuffer(target, sr.base, sr.length));
116 }
117 
118 static inline int
compare_nsec(ARGS_COMPARE)119 compare_nsec(ARGS_COMPARE) {
120 	isc_region_t r1;
121 	isc_region_t r2;
122 
123 	REQUIRE(rdata1->type == rdata2->type);
124 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
125 	REQUIRE(rdata1->type == dns_rdatatype_nsec);
126 	REQUIRE(rdata1->length != 0);
127 	REQUIRE(rdata2->length != 0);
128 
129 	dns_rdata_toregion(rdata1, &r1);
130 	dns_rdata_toregion(rdata2, &r2);
131 	return (isc_region_compare(&r1, &r2));
132 }
133 
134 static inline isc_result_t
fromstruct_nsec(ARGS_FROMSTRUCT)135 fromstruct_nsec(ARGS_FROMSTRUCT) {
136 	dns_rdata_nsec_t *nsec = source;
137 	isc_region_t region;
138 
139 	REQUIRE(type == dns_rdatatype_nsec);
140 	REQUIRE(source != NULL);
141 	REQUIRE(nsec->common.rdtype == type);
142 	REQUIRE(nsec->common.rdclass == rdclass);
143 	REQUIRE(nsec->typebits != NULL || nsec->len == 0);
144 
145 	UNUSED(type);
146 	UNUSED(rdclass);
147 
148 	dns_name_toregion(&nsec->next, &region);
149 	RETERR(isc_buffer_copyregion(target, &region));
150 
151 	region.base = nsec->typebits;
152 	region.length = nsec->len;
153 	RETERR(typemap_test(&region, ISC_FALSE));
154 	return (mem_tobuffer(target, nsec->typebits, nsec->len));
155 }
156 
157 static inline isc_result_t
tostruct_nsec(ARGS_TOSTRUCT)158 tostruct_nsec(ARGS_TOSTRUCT) {
159 	isc_region_t region;
160 	dns_rdata_nsec_t *nsec = target;
161 	dns_name_t name;
162 
163 	REQUIRE(rdata->type == dns_rdatatype_nsec);
164 	REQUIRE(target != NULL);
165 	REQUIRE(rdata->length != 0);
166 
167 	nsec->common.rdclass = rdata->rdclass;
168 	nsec->common.rdtype = rdata->type;
169 	ISC_LINK_INIT(&nsec->common, link);
170 
171 	dns_name_init(&name, NULL);
172 	dns_rdata_toregion(rdata, &region);
173 	dns_name_fromregion(&name, &region);
174 	isc_region_consume(&region, name_length(&name));
175 	dns_name_init(&nsec->next, NULL);
176 	RETERR(name_duporclone(&name, mctx, &nsec->next));
177 
178 	nsec->len = region.length;
179 	nsec->typebits = mem_maybedup(mctx, region.base, region.length);
180 	if (nsec->typebits == NULL)
181 		goto cleanup;
182 
183 	nsec->mctx = mctx;
184 	return (ISC_R_SUCCESS);
185 
186  cleanup:
187 	if (mctx != NULL)
188 		dns_name_free(&nsec->next, mctx);
189 	return (ISC_R_NOMEMORY);
190 }
191 
192 static inline void
freestruct_nsec(ARGS_FREESTRUCT)193 freestruct_nsec(ARGS_FREESTRUCT) {
194 	dns_rdata_nsec_t *nsec = source;
195 
196 	REQUIRE(source != NULL);
197 	REQUIRE(nsec->common.rdtype == dns_rdatatype_nsec);
198 
199 	if (nsec->mctx == NULL)
200 		return;
201 
202 	dns_name_free(&nsec->next, nsec->mctx);
203 	if (nsec->typebits != NULL)
204 		isc_mem_free(nsec->mctx, nsec->typebits);
205 	nsec->mctx = NULL;
206 }
207 
208 static inline isc_result_t
additionaldata_nsec(ARGS_ADDLDATA)209 additionaldata_nsec(ARGS_ADDLDATA) {
210 	REQUIRE(rdata->type == dns_rdatatype_nsec);
211 
212 	UNUSED(rdata);
213 	UNUSED(add);
214 	UNUSED(arg);
215 
216 	return (ISC_R_SUCCESS);
217 }
218 
219 static inline isc_result_t
digest_nsec(ARGS_DIGEST)220 digest_nsec(ARGS_DIGEST) {
221 	isc_region_t r;
222 
223 	REQUIRE(rdata->type == dns_rdatatype_nsec);
224 
225 	dns_rdata_toregion(rdata, &r);
226 	return ((digest)(arg, &r));
227 }
228 
229 static inline isc_boolean_t
checkowner_nsec(ARGS_CHECKOWNER)230 checkowner_nsec(ARGS_CHECKOWNER) {
231 
232        REQUIRE(type == dns_rdatatype_nsec);
233 
234        UNUSED(name);
235        UNUSED(type);
236        UNUSED(rdclass);
237        UNUSED(wildcard);
238 
239        return (ISC_TRUE);
240 }
241 
242 static inline isc_boolean_t
checknames_nsec(ARGS_CHECKNAMES)243 checknames_nsec(ARGS_CHECKNAMES) {
244 
245 	REQUIRE(rdata->type == dns_rdatatype_nsec);
246 
247 	UNUSED(rdata);
248 	UNUSED(owner);
249 	UNUSED(bad);
250 
251 	return (ISC_TRUE);
252 }
253 
254 static inline int
casecompare_nsec(ARGS_COMPARE)255 casecompare_nsec(ARGS_COMPARE) {
256 	isc_region_t region1;
257 	isc_region_t region2;
258 	dns_name_t name1;
259 	dns_name_t name2;
260 	int order;
261 
262 	REQUIRE(rdata1->type == rdata2->type);
263 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
264 	REQUIRE(rdata1->type == dns_rdatatype_nsec);
265 	REQUIRE(rdata1->length != 0);
266 	REQUIRE(rdata2->length != 0);
267 
268 	dns_name_init(&name1, NULL);
269 	dns_name_init(&name2, NULL);
270 
271 	dns_rdata_toregion(rdata1, &region1);
272 	dns_rdata_toregion(rdata2, &region2);
273 
274 	dns_name_fromregion(&name1, &region1);
275 	dns_name_fromregion(&name2, &region2);
276 
277 	order = dns_name_rdatacompare(&name1, &name2);
278 	if (order != 0)
279 		return (order);
280 
281 	isc_region_consume(&region1, name_length(&name1));
282 	isc_region_consume(&region2, name_length(&name2));
283 
284 	return (isc_region_compare(&region1, &region2));
285 }
286 #endif	/* RDATA_GENERIC_NSEC_47_C */
287