/src/bind9/lib/dns/rdata/generic/soa_6.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) Internet Systems Consortium, Inc. ("ISC") |
3 | | * |
4 | | * SPDX-License-Identifier: MPL-2.0 |
5 | | * |
6 | | * This Source Code Form is subject to the terms of the Mozilla Public |
7 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
8 | | * file, you can obtain one at https://mozilla.org/MPL/2.0/. |
9 | | * |
10 | | * See the COPYRIGHT file distributed with this work for additional |
11 | | * information regarding copyright ownership. |
12 | | */ |
13 | | |
14 | | #ifndef RDATA_GENERIC_SOA_6_C |
15 | | #define RDATA_GENERIC_SOA_6_C |
16 | | |
17 | 16.0k | #define RRTYPE_SOA_ATTRIBUTES (DNS_RDATATYPEATTR_SINGLETON) |
18 | | |
19 | | static isc_result_t |
20 | 1.49k | fromtext_soa(ARGS_FROMTEXT) { |
21 | 1.49k | isc_token_t token; |
22 | 1.49k | isc_buffer_t buffer; |
23 | 1.49k | int i; |
24 | 1.49k | uint32_t n; |
25 | 1.49k | bool ok; |
26 | | |
27 | 1.49k | REQUIRE(type == dns_rdatatype_soa); |
28 | | |
29 | 1.49k | UNUSED(type); |
30 | 1.49k | UNUSED(rdclass); |
31 | 1.49k | UNUSED(callbacks); |
32 | | |
33 | 1.49k | if (origin == NULL) { |
34 | 282 | origin = dns_rootname; |
35 | 282 | } |
36 | | |
37 | 4.35k | for (i = 0; i < 2; i++) { |
38 | 2.95k | dns_fixedname_t fn; |
39 | 2.95k | dns_name_t *name = dns_fixedname_initname(&fn); |
40 | | |
41 | 2.95k | RETERR(isc_lex_getmastertoken(lexer, &token, |
42 | 2.95k | isc_tokentype_string, false)); |
43 | | |
44 | 2.88k | buffer_fromregion(&buffer, &token.value.as_region); |
45 | 2.88k | RETTOK(dns_name_fromtext(name, &buffer, origin, options)); |
46 | 2.86k | RETTOK(dns_name_towire(name, NULL, target)); |
47 | 2.86k | ok = true; |
48 | 2.86k | if ((options & DNS_RDATA_CHECKNAMES) != 0) { |
49 | 0 | switch (i) { |
50 | 0 | case 0: |
51 | 0 | ok = dns_name_ishostname(name, false); |
52 | 0 | break; |
53 | 0 | case 1: |
54 | 0 | ok = dns_name_ismailbox(name); |
55 | 0 | break; |
56 | 0 | } |
57 | 0 | } |
58 | 2.86k | if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) { |
59 | 0 | RETTOK(DNS_R_BADNAME); |
60 | 0 | } |
61 | 2.86k | if (!ok && callbacks != NULL) { |
62 | 0 | warn_badname(name, lexer, callbacks); |
63 | 0 | } |
64 | 2.86k | } |
65 | | |
66 | 1.40k | RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, |
67 | 1.40k | false)); |
68 | 1.38k | RETERR(uint32_tobuffer(token.value.as_ulong, target)); |
69 | | |
70 | 6.26k | for (i = 0; i < 4; i++) { |
71 | 5.08k | RETERR(isc_lex_getmastertoken(lexer, &token, |
72 | 5.08k | isc_tokentype_string, false)); |
73 | 4.96k | RETTOK(dns_counter_fromtext(&token.value.as_textregion, &n)); |
74 | 4.88k | RETERR(uint32_tobuffer(n, target)); |
75 | 4.88k | } |
76 | | |
77 | 1.18k | return ISC_R_SUCCESS; |
78 | 1.38k | } |
79 | | |
80 | | static const char *soa_fieldnames[5] = { "serial", "refresh", "retry", "expire", |
81 | | "minimum" }; |
82 | | |
83 | | static isc_result_t |
84 | 1.79k | totext_soa(ARGS_TOTEXT) { |
85 | 1.79k | isc_region_t dregion; |
86 | 1.79k | dns_name_t mname; |
87 | 1.79k | dns_name_t rname; |
88 | 1.79k | dns_name_t prefix; |
89 | 1.79k | unsigned int opts; |
90 | 1.79k | int i; |
91 | 1.79k | bool multiline; |
92 | 1.79k | bool comm; |
93 | | |
94 | 1.79k | REQUIRE(rdata->type == dns_rdatatype_soa); |
95 | 1.79k | REQUIRE(rdata->length != 0); |
96 | | |
97 | 1.79k | multiline = ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0); |
98 | 1.79k | if (multiline) { |
99 | 71 | comm = ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0); |
100 | 1.72k | } else { |
101 | 1.72k | comm = false; |
102 | 1.72k | } |
103 | | |
104 | 1.79k | dns_name_init(&mname); |
105 | 1.79k | dns_name_init(&rname); |
106 | 1.79k | dns_name_init(&prefix); |
107 | | |
108 | 1.79k | dns_rdata_toregion(rdata, &dregion); |
109 | | |
110 | 1.79k | dns_name_fromregion(&mname, &dregion); |
111 | 1.79k | isc_region_consume(&dregion, name_length(&mname)); |
112 | | |
113 | 1.79k | dns_name_fromregion(&rname, &dregion); |
114 | 1.79k | isc_region_consume(&dregion, name_length(&rname)); |
115 | | |
116 | 1.79k | opts = name_prefix(&mname, tctx->origin, &prefix) |
117 | 1.79k | ? DNS_NAME_OMITFINALDOT |
118 | 1.79k | : 0; |
119 | 1.79k | RETERR(dns_name_totext(&prefix, opts, target)); |
120 | | |
121 | 1.79k | RETERR(str_totext(" ", target)); |
122 | | |
123 | 1.79k | opts = name_prefix(&rname, tctx->origin, &prefix) |
124 | 1.79k | ? DNS_NAME_OMITFINALDOT |
125 | 1.79k | : 0; |
126 | 1.79k | RETERR(dns_name_totext(&prefix, opts, target)); |
127 | | |
128 | 1.79k | if (multiline) { |
129 | 71 | RETERR(str_totext(" (", target)); |
130 | 71 | } |
131 | 1.79k | RETERR(str_totext(tctx->linebreak, target)); |
132 | | |
133 | 10.7k | for (i = 0; i < 5; i++) { |
134 | 8.98k | char buf[sizeof("0123456789 ; ")]; |
135 | 8.98k | unsigned long num; |
136 | 8.98k | num = uint32_fromregion(&dregion); |
137 | 8.98k | isc_region_consume(&dregion, 4); |
138 | 8.98k | snprintf(buf, sizeof(buf), comm ? "%-10lu ; " : "%lu", num); |
139 | 8.98k | RETERR(str_totext(buf, target)); |
140 | 8.98k | if (comm) { |
141 | 355 | RETERR(str_totext(soa_fieldnames[i], target)); |
142 | | /* Print times in week/day/hour/minute/second form */ |
143 | 355 | if (i >= 1) { |
144 | 284 | RETERR(str_totext(" (", target)); |
145 | 284 | RETERR(dns_ttl_totext(num, true, true, target)); |
146 | 284 | RETERR(str_totext(")", target)); |
147 | 284 | } |
148 | 355 | RETERR(str_totext(tctx->linebreak, target)); |
149 | 8.63k | } else if (i < 4) { |
150 | 6.90k | RETERR(str_totext(tctx->linebreak, target)); |
151 | 6.90k | } |
152 | 8.98k | } |
153 | | |
154 | 1.79k | if (multiline) { |
155 | 71 | RETERR(str_totext(")", target)); |
156 | 71 | } |
157 | | |
158 | 1.79k | return ISC_R_SUCCESS; |
159 | 1.79k | } |
160 | | |
161 | | static isc_result_t |
162 | 2.16k | fromwire_soa(ARGS_FROMWIRE) { |
163 | 2.16k | dns_name_t mname; |
164 | 2.16k | dns_name_t rname; |
165 | 2.16k | isc_region_t sregion; |
166 | 2.16k | isc_region_t tregion; |
167 | | |
168 | 2.16k | REQUIRE(type == dns_rdatatype_soa); |
169 | | |
170 | 2.16k | UNUSED(type); |
171 | 2.16k | UNUSED(rdclass); |
172 | | |
173 | 2.16k | dns_decompress_setpermitted(dctx, true); |
174 | | |
175 | 2.16k | dns_name_init(&mname); |
176 | 2.16k | dns_name_init(&rname); |
177 | | |
178 | 2.16k | RETERR(dns_name_fromwire(&mname, source, dctx, target)); |
179 | 2.04k | RETERR(dns_name_fromwire(&rname, source, dctx, target)); |
180 | | |
181 | 1.86k | isc_buffer_activeregion(source, &sregion); |
182 | 1.86k | isc_buffer_availableregion(target, &tregion); |
183 | | |
184 | 1.86k | if (sregion.length < 20) { |
185 | 14 | return ISC_R_UNEXPECTEDEND; |
186 | 14 | } |
187 | 1.85k | if (tregion.length < 20) { |
188 | 76 | return ISC_R_NOSPACE; |
189 | 76 | } |
190 | | |
191 | 1.77k | memmove(tregion.base, sregion.base, 20); |
192 | 1.77k | isc_buffer_forward(source, 20); |
193 | 1.77k | isc_buffer_add(target, 20); |
194 | | |
195 | 1.77k | return ISC_R_SUCCESS; |
196 | 1.85k | } |
197 | | |
198 | | static int |
199 | 3.23k | compare_soa(ARGS_COMPARE) { |
200 | 3.23k | isc_region_t region1; |
201 | 3.23k | isc_region_t region2; |
202 | 3.23k | dns_name_t name1; |
203 | 3.23k | dns_name_t name2; |
204 | 3.23k | int order; |
205 | | |
206 | 3.23k | REQUIRE(rdata1->type == rdata2->type); |
207 | 3.23k | REQUIRE(rdata1->rdclass == rdata2->rdclass); |
208 | 3.23k | REQUIRE(rdata1->type == dns_rdatatype_soa); |
209 | 3.23k | REQUIRE(rdata1->length != 0); |
210 | 3.23k | REQUIRE(rdata2->length != 0); |
211 | | |
212 | 3.23k | dns_name_init(&name1); |
213 | 3.23k | dns_name_init(&name2); |
214 | | |
215 | 3.23k | dns_rdata_toregion(rdata1, ®ion1); |
216 | 3.23k | dns_rdata_toregion(rdata2, ®ion2); |
217 | | |
218 | 3.23k | dns_name_fromregion(&name1, ®ion1); |
219 | 3.23k | dns_name_fromregion(&name2, ®ion2); |
220 | | |
221 | 3.23k | order = dns_name_rdatacompare(&name1, &name2); |
222 | 3.23k | if (order != 0) { |
223 | 677 | return order; |
224 | 677 | } |
225 | | |
226 | 2.56k | isc_region_consume(®ion1, name_length(&name1)); |
227 | 2.56k | isc_region_consume(®ion2, name_length(&name2)); |
228 | | |
229 | 2.56k | dns_name_init(&name1); |
230 | 2.56k | dns_name_init(&name2); |
231 | | |
232 | 2.56k | dns_name_fromregion(&name1, ®ion1); |
233 | 2.56k | dns_name_fromregion(&name2, ®ion2); |
234 | | |
235 | 2.56k | order = dns_name_rdatacompare(&name1, &name2); |
236 | 2.56k | if (order != 0) { |
237 | 235 | return order; |
238 | 235 | } |
239 | | |
240 | 2.32k | isc_region_consume(®ion1, name_length(&name1)); |
241 | 2.32k | isc_region_consume(®ion2, name_length(&name2)); |
242 | | |
243 | 2.32k | return isc_region_compare(®ion1, ®ion2); |
244 | 2.56k | } |
245 | | |
246 | | static isc_result_t |
247 | 0 | fromstruct_soa(ARGS_FROMSTRUCT) { |
248 | 0 | dns_rdata_soa_t *soa = source; |
249 | 0 | isc_region_t region; |
250 | |
|
251 | 0 | REQUIRE(type == dns_rdatatype_soa); |
252 | 0 | REQUIRE(soa != NULL); |
253 | 0 | REQUIRE(soa->common.rdtype == type); |
254 | 0 | REQUIRE(soa->common.rdclass == rdclass); |
255 | |
|
256 | 0 | UNUSED(type); |
257 | 0 | UNUSED(rdclass); |
258 | |
|
259 | 0 | dns_name_toregion(&soa->origin, ®ion); |
260 | 0 | RETERR(isc_buffer_copyregion(target, ®ion)); |
261 | 0 | dns_name_toregion(&soa->contact, ®ion); |
262 | 0 | RETERR(isc_buffer_copyregion(target, ®ion)); |
263 | 0 | RETERR(uint32_tobuffer(soa->serial, target)); |
264 | 0 | RETERR(uint32_tobuffer(soa->refresh, target)); |
265 | 0 | RETERR(uint32_tobuffer(soa->retry, target)); |
266 | 0 | RETERR(uint32_tobuffer(soa->expire, target)); |
267 | 0 | return uint32_tobuffer(soa->minimum, target); |
268 | 0 | } |
269 | | |
270 | | static isc_result_t |
271 | 2 | tostruct_soa(ARGS_TOSTRUCT) { |
272 | 2 | isc_region_t region; |
273 | 2 | dns_rdata_soa_t *soa = target; |
274 | 2 | dns_name_t name; |
275 | | |
276 | 2 | REQUIRE(rdata->type == dns_rdatatype_soa); |
277 | 2 | REQUIRE(soa != NULL); |
278 | 2 | REQUIRE(rdata->length != 0); |
279 | | |
280 | 2 | DNS_RDATACOMMON_INIT(soa, rdata->type, rdata->rdclass); |
281 | | |
282 | 2 | dns_rdata_toregion(rdata, ®ion); |
283 | | |
284 | 2 | dns_name_init(&name); |
285 | 2 | dns_name_fromregion(&name, ®ion); |
286 | 2 | isc_region_consume(®ion, name_length(&name)); |
287 | 2 | dns_name_init(&soa->origin); |
288 | 2 | dns_name_clone(&name, &soa->origin); |
289 | | |
290 | 2 | dns_name_fromregion(&name, ®ion); |
291 | 2 | isc_region_consume(®ion, name_length(&name)); |
292 | 2 | dns_name_init(&soa->contact); |
293 | 2 | dns_name_clone(&name, &soa->contact); |
294 | | |
295 | 2 | soa->serial = uint32_fromregion(®ion); |
296 | 2 | isc_region_consume(®ion, 4); |
297 | | |
298 | 2 | soa->refresh = uint32_fromregion(®ion); |
299 | 2 | isc_region_consume(®ion, 4); |
300 | | |
301 | 2 | soa->retry = uint32_fromregion(®ion); |
302 | 2 | isc_region_consume(®ion, 4); |
303 | | |
304 | 2 | soa->expire = uint32_fromregion(®ion); |
305 | 2 | isc_region_consume(®ion, 4); |
306 | | |
307 | 2 | soa->minimum = uint32_fromregion(®ion); |
308 | | |
309 | 2 | return ISC_R_SUCCESS; |
310 | 2 | } |
311 | | |
312 | | static isc_result_t |
313 | 0 | additionaldata_soa(ARGS_ADDLDATA) { |
314 | 0 | REQUIRE(rdata->type == dns_rdatatype_soa); |
315 | |
|
316 | 0 | UNUSED(rdata); |
317 | 0 | UNUSED(owner); |
318 | 0 | UNUSED(add); |
319 | 0 | UNUSED(arg); |
320 | |
|
321 | 0 | return ISC_R_SUCCESS; |
322 | 0 | } |
323 | | |
324 | | static isc_result_t |
325 | 0 | digest_soa(ARGS_DIGEST) { |
326 | 0 | isc_region_t r; |
327 | 0 | dns_name_t name; |
328 | |
|
329 | 0 | REQUIRE(rdata->type == dns_rdatatype_soa); |
330 | |
|
331 | 0 | dns_rdata_toregion(rdata, &r); |
332 | |
|
333 | 0 | dns_name_init(&name); |
334 | 0 | dns_name_fromregion(&name, &r); |
335 | 0 | RETERR(dns_name_digest(&name, digest, arg)); |
336 | 0 | isc_region_consume(&r, name_length(&name)); |
337 | |
|
338 | 0 | dns_name_init(&name); |
339 | 0 | dns_name_fromregion(&name, &r); |
340 | 0 | RETERR(dns_name_digest(&name, digest, arg)); |
341 | 0 | isc_region_consume(&r, name_length(&name)); |
342 | |
|
343 | 0 | return (digest)(arg, &r); |
344 | 0 | } |
345 | | |
346 | | static bool |
347 | 0 | checkowner_soa(ARGS_CHECKOWNER) { |
348 | 0 | REQUIRE(type == dns_rdatatype_soa); |
349 | |
|
350 | 0 | UNUSED(name); |
351 | 0 | UNUSED(type); |
352 | 0 | UNUSED(rdclass); |
353 | 0 | UNUSED(wildcard); |
354 | |
|
355 | 0 | return true; |
356 | 0 | } |
357 | | |
358 | | static bool |
359 | 0 | checknames_soa(ARGS_CHECKNAMES) { |
360 | 0 | isc_region_t region; |
361 | 0 | dns_name_t name; |
362 | |
|
363 | 0 | REQUIRE(rdata->type == dns_rdatatype_soa); |
364 | |
|
365 | 0 | UNUSED(owner); |
366 | |
|
367 | 0 | dns_rdata_toregion(rdata, ®ion); |
368 | 0 | dns_name_init(&name); |
369 | 0 | dns_name_fromregion(&name, ®ion); |
370 | 0 | if (!dns_name_ishostname(&name, false)) { |
371 | 0 | if (bad != NULL) { |
372 | 0 | dns_name_clone(&name, bad); |
373 | 0 | } |
374 | 0 | return false; |
375 | 0 | } |
376 | 0 | isc_region_consume(®ion, name_length(&name)); |
377 | 0 | dns_name_fromregion(&name, ®ion); |
378 | 0 | if (!dns_name_ismailbox(&name)) { |
379 | 0 | if (bad != NULL) { |
380 | 0 | dns_name_clone(&name, bad); |
381 | 0 | } |
382 | 0 | return false; |
383 | 0 | } |
384 | 0 | return true; |
385 | 0 | } |
386 | | |
387 | | static int |
388 | 0 | casecompare_soa(ARGS_COMPARE) { |
389 | 0 | return compare_soa(rdata1, rdata2); |
390 | 0 | } |
391 | | |
392 | | #endif /* RDATA_GENERIC_SOA_6_C */ |