soa_6.c 10.7 KB
Newer Older
1
/*
Automatic Updater's avatar
Automatic Updater committed
2
 * Copyright (C) 2004, 2007, 2009, 2011  Internet Systems Consortium, Inc. ("ISC")
Mark Andrews's avatar
Mark Andrews committed
3
 * Copyright (C) 1998-2002  Internet Software Consortium.
4
 *
Automatic Updater's avatar
Automatic Updater committed
5
 * Permission to use, copy, modify, and/or distribute this software for any
6 7
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
8
 *
Mark Andrews's avatar
Mark Andrews committed
9 10 11 12 13 14 15
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
16 17
 */

Mark Andrews's avatar
Mark Andrews committed
18
/* $Id$ */
Michael Graff's avatar
Michael Graff committed
19

20
/* Reviewed: Thu Mar 16 15:18:32 PST 2000 by explorer */
Mark Andrews's avatar
Mark Andrews committed
21

22 23
#ifndef RDATA_GENERIC_SOA_6_C
#define RDATA_GENERIC_SOA_6_C
24

25 26
#define RRTYPE_SOA_ATTRIBUTES (DNS_RDATATYPEATTR_SINGLETON)

27
static inline isc_result_t
David Lawrence's avatar
David Lawrence committed
28
fromtext_soa(ARGS_FROMTEXT) {
29 30 31 32
	isc_token_t token;
	dns_name_t name;
	isc_buffer_t buffer;
	int i;
33
	isc_uint32_t n;
34
	isc_boolean_t ok;
35

Mark Andrews's avatar
Mark Andrews committed
36
	REQUIRE(type == 6);
Mark Andrews's avatar
Mark Andrews committed
37

38 39
	UNUSED(type);
	UNUSED(rdclass);
40
	UNUSED(callbacks);
41

Michael Graff's avatar
Michael Graff committed
42
	origin = (origin != NULL) ? origin : dns_rootname;
43

44
	for (i = 0; i < 2; i++) {
45 46 47
		RETERR(isc_lex_getmastertoken(lexer, &token,
					      isc_tokentype_string,
					      ISC_FALSE));
48

49
		dns_name_init(&name, NULL);
50
		buffer_fromregion(&buffer, &token.value.as_region);
51
		RETTOK(dns_name_fromtext(&name, &buffer, origin,
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
					 options, target));
		ok = ISC_TRUE;
		if ((options & DNS_RDATA_CHECKNAMES) != 0)
			switch (i) {
			case 0:
				ok = dns_name_ishostname(&name, ISC_FALSE);
				break;
			case 1:
				ok = dns_name_ismailbox(&name);
				break;

			}
		if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0)
			RETTOK(DNS_R_BADNAME);
		if (!ok && callbacks != NULL)
			warn_badname(&name, lexer, callbacks);
Mark Andrews's avatar
Mark Andrews committed
68
	}
69

70 71
	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
				      ISC_FALSE));
72
	RETERR(uint32_tobuffer(token.value.as_ulong, target));
Michael Graff's avatar
Michael Graff committed
73

74
	for (i = 0; i < 4; i++) {
75 76 77
		RETERR(isc_lex_getmastertoken(lexer, &token,
					      isc_tokentype_string,
					      ISC_FALSE));
78
		RETTOK(dns_counter_fromtext(&token.value.as_textregion, &n));
79
		RETERR(uint32_tobuffer(n, target));
80
	}
81

82
	return (ISC_R_SUCCESS);
83 84
}

David Lawrence's avatar
David Lawrence committed
85
static const char *soa_fieldnames[5] = {
86
	"serial", "refresh", "retry", "expire", "minimum"
Michael Graff's avatar
Michael Graff committed
87
};
88

89
static inline isc_result_t
David Lawrence's avatar
David Lawrence committed
90
totext_soa(ARGS_TOTEXT) {
91 92 93 94 95 96
	isc_region_t dregion;
	dns_name_t mname;
	dns_name_t rname;
	dns_name_t prefix;
	isc_boolean_t sub;
	int i;
97
	isc_boolean_t multiline;
98
	isc_boolean_t comment;
99

Mark Andrews's avatar
Mark Andrews committed
100
	REQUIRE(rdata->type == 6);
101
	REQUIRE(rdata->length != 0);
102

103
	multiline = ISC_TF((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0);
Mark Andrews's avatar
Mark Andrews committed
104
	if (multiline)
105
		comment = ISC_TF((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0);
Mark Andrews's avatar
Mark Andrews committed
106 107
	else
		comment = ISC_FALSE;
Automatic Updater's avatar
Automatic Updater committed
108

109

110 111 112 113 114 115 116 117 118 119 120 121
	dns_name_init(&mname, NULL);
	dns_name_init(&rname, NULL);
	dns_name_init(&prefix, NULL);

	dns_rdata_toregion(rdata, &dregion);

	dns_name_fromregion(&mname, &dregion);
	isc_region_consume(&dregion, name_length(&mname));

	dns_name_fromregion(&rname, &dregion);
	isc_region_consume(&dregion, name_length(&rname));

122
	sub = name_prefix(&mname, tctx->origin, &prefix);
123
	RETERR(dns_name_totext(&prefix, sub, target));
124

125
	RETERR(str_totext(" ", target));
126

127
	sub = name_prefix(&rname, tctx->origin, &prefix);
128
	RETERR(dns_name_totext(&prefix, sub, target));
129

130 131
	if (multiline)
		RETERR(str_totext(" (" , target));
132 133
	RETERR(str_totext(tctx->linebreak, target));

134
	for (i = 0; i < 5; i++) {
Mark Andrews's avatar
Mark Andrews committed
135
		char buf[sizeof("0123456789 ; ")];
136 137
		unsigned long num;
		num = uint32_fromregion(&dregion);
Michael Graff's avatar
Michael Graff committed
138
		isc_region_consume(&dregion, 4);
Mark Andrews's avatar
Mark Andrews committed
139
		sprintf(buf, comment ? "%-10lu ; " : "%lu", num);
140
		RETERR(str_totext(buf, target));
Mark Andrews's avatar
Mark Andrews committed
141
		if (comment) {
142 143 144 145 146
			RETERR(str_totext(soa_fieldnames[i], target));
			/* Print times in week/day/hour/minute/second form */
			if (i >= 1) {
				RETERR(str_totext(" (", target));
				RETERR(dns_ttl_totext(num, ISC_TRUE, target));
Michael Graff's avatar
Michael Graff committed
147
				RETERR(str_totext(")", target));
148 149
			}
			RETERR(str_totext(tctx->linebreak, target));
150
		} else if (i < 4) {
Mark Andrews's avatar
Mark Andrews committed
151
			RETERR(str_totext(tctx->linebreak, target));
152
		}
153
	}
154

155
	if (multiline)
156
		RETERR(str_totext(")", target));
157

158
	return (ISC_R_SUCCESS);
159 160
}

161
static inline isc_result_t
David Lawrence's avatar
David Lawrence committed
162
fromwire_soa(ARGS_FROMWIRE) {
Automatic Updater's avatar
Automatic Updater committed
163 164
	dns_name_t mname;
	dns_name_t rname;
165 166
	isc_region_t sregion;
	isc_region_t tregion;
Mark Andrews's avatar
Mark Andrews committed
167

Michael Graff's avatar
Michael Graff committed
168
	REQUIRE(type == 6);
169

170 171 172
	UNUSED(type);
	UNUSED(rdclass);

173
	dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
Mark Andrews's avatar
Mark Andrews committed
174

Automatic Updater's avatar
Automatic Updater committed
175 176
	dns_name_init(&mname, NULL);
	dns_name_init(&rname, NULL);
177

Automatic Updater's avatar
Automatic Updater committed
178 179
	RETERR(dns_name_fromwire(&mname, source, dctx, options, target));
	RETERR(dns_name_fromwire(&rname, source, dctx, options, target));
180

181 182
	isc_buffer_activeregion(source, &sregion);
	isc_buffer_availableregion(target, &tregion);
183

Mark Andrews's avatar
Mark Andrews committed
184
	if (sregion.length < 20)
185
		return (ISC_R_UNEXPECTEDEND);
186
	if (tregion.length < 20)
187
		return (ISC_R_NOSPACE);
188 189 190 191

	memcpy(tregion.base, sregion.base, 20);
	isc_buffer_forward(source, 20);
	isc_buffer_add(target, 20);
Michael Graff's avatar
Michael Graff committed
192

193
	return (ISC_R_SUCCESS);
194 195
}

196
static inline isc_result_t
David Lawrence's avatar
David Lawrence committed
197
towire_soa(ARGS_TOWIRE) {
198 199 200 201
	isc_region_t sregion;
	isc_region_t tregion;
	dns_name_t mname;
	dns_name_t rname;
202 203
	dns_offsets_t moffsets;
	dns_offsets_t roffsets;
204

Mark Andrews's avatar
Mark Andrews committed
205
	REQUIRE(rdata->type == 6);
206
	REQUIRE(rdata->length != 0);
207

208
	dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
Mark Andrews's avatar
Mark Andrews committed
209

210 211
	dns_name_init(&mname, moffsets);
	dns_name_init(&rname, roffsets);
212 213

	dns_rdata_toregion(rdata, &sregion);
Michael Graff's avatar
Michael Graff committed
214

215 216
	dns_name_fromregion(&mname, &sregion);
	isc_region_consume(&sregion, name_length(&mname));
217
	RETERR(dns_name_towire(&mname, cctx, target));
218 219 220

	dns_name_fromregion(&rname, &sregion);
	isc_region_consume(&sregion, name_length(&rname));
221
	RETERR(dns_name_towire(&rname, cctx, target));
222

223
	isc_buffer_availableregion(target, &tregion);
224
	if (tregion.length < 20)
225
		return (ISC_R_NOSPACE);
226 227 228

	memcpy(tregion.base, sregion.base, 20);
	isc_buffer_add(target, 20);
229
	return (ISC_R_SUCCESS);
230 231
}

232
static inline int
David Lawrence's avatar
David Lawrence committed
233
compare_soa(ARGS_COMPARE) {
234 235 236 237
	isc_region_t region1;
	isc_region_t region2;
	dns_name_t name1;
	dns_name_t name2;
238
	int order;
239

Mark Andrews's avatar
Mark Andrews committed
240
	REQUIRE(rdata1->type == rdata2->type);
241
	REQUIRE(rdata1->rdclass == rdata2->rdclass);
Mark Andrews's avatar
Mark Andrews committed
242
	REQUIRE(rdata1->type == 6);
243 244
	REQUIRE(rdata1->length != 0);
	REQUIRE(rdata2->length != 0);
245 246 247 248 249

	dns_name_init(&name1, NULL);
	dns_name_init(&name2, NULL);

	dns_rdata_toregion(rdata1, &region1);
250
	dns_rdata_toregion(rdata2, &region2);
251 252 253 254

	dns_name_fromregion(&name1, &region1);
	dns_name_fromregion(&name2, &region2);

255 256 257
	order = dns_name_rdatacompare(&name1, &name2);
	if (order != 0)
		return (order);
258

259 260
	isc_region_consume(&region1, name_length(&name1));
	isc_region_consume(&region2, name_length(&name2));
261 262 263 264 265 266 267

	dns_name_init(&name1, NULL);
	dns_name_init(&name2, NULL);

	dns_name_fromregion(&name1, &region1);
	dns_name_fromregion(&name2, &region2);

268 269 270
	order = dns_name_rdatacompare(&name1, &name2);
	if (order != 0)
		return (order);
271

272 273
	isc_region_consume(&region1, name_length(&name1));
	isc_region_consume(&region2, name_length(&name2));
274

275
	return (isc_region_compare(&region1, &region2));
276 277
}

278
static inline isc_result_t
David Lawrence's avatar
David Lawrence committed
279
fromstruct_soa(ARGS_FROMSTRUCT) {
280 281
	dns_rdata_soa_t *soa = source;
	isc_region_t region;
Mark Andrews's avatar
Mark Andrews committed
282

Michael Graff's avatar
Michael Graff committed
283
	REQUIRE(type == 6);
284 285 286 287
	REQUIRE(source != NULL);
	REQUIRE(soa->common.rdtype == type);
	REQUIRE(soa->common.rdclass == rdclass);

288
	UNUSED(type);
289 290
	UNUSED(rdclass);

291 292
	dns_name_toregion(&soa->origin, &region);
	RETERR(isc_buffer_copyregion(target, &region));
293
	dns_name_toregion(&soa->contact, &region);
294 295 296 297 298 299
	RETERR(isc_buffer_copyregion(target, &region));
	RETERR(uint32_tobuffer(soa->serial, target));
	RETERR(uint32_tobuffer(soa->refresh, target));
	RETERR(uint32_tobuffer(soa->retry, target));
	RETERR(uint32_tobuffer(soa->expire, target));
	return (uint32_tobuffer(soa->minimum, target));
300 301
}

302
static inline isc_result_t
David Lawrence's avatar
David Lawrence committed
303
tostruct_soa(ARGS_TOSTRUCT) {
Mark Andrews's avatar
Mark Andrews committed
304 305
	isc_region_t region;
	dns_rdata_soa_t *soa = target;
306
	dns_name_t name;
307
	isc_result_t result;
Michael Graff's avatar
Michael Graff committed
308

Mark Andrews's avatar
Mark Andrews committed
309
	REQUIRE(rdata->type == 6);
310
	REQUIRE(target != NULL);
311
	REQUIRE(rdata->length != 0);
Mark Andrews's avatar
Mark Andrews committed
312

313
	soa->common.rdclass = rdata->rdclass;
314 315
	soa->common.rdtype = rdata->type;
	ISC_LINK_INIT(&soa->common, link);
Mark Andrews's avatar
Mark Andrews committed
316

317

Mark Andrews's avatar
Mark Andrews committed
318
	dns_rdata_toregion(rdata, &region);
Michael Graff's avatar
Michael Graff committed
319 320

	dns_name_init(&name, NULL);
321 322 323
	dns_name_fromregion(&name, &region);
	isc_region_consume(&region, name_length(&name));
	dns_name_init(&soa->origin, NULL);
324
	RETERR(name_duporclone(&name, mctx, &soa->origin));
325 326 327

	dns_name_fromregion(&name, &region);
	isc_region_consume(&region, name_length(&name));
328 329
	dns_name_init(&soa->contact, NULL);
	result = name_duporclone(&name, mctx, &soa->contact);
330 331
	if (result != ISC_R_SUCCESS)
		goto cleanup;
332

Mark Andrews's avatar
Mark Andrews committed
333 334
	soa->serial = uint32_fromregion(&region);
	isc_region_consume(&region, 4);
Michael Graff's avatar
Michael Graff committed
335

Mark Andrews's avatar
Mark Andrews committed
336 337
	soa->refresh = uint32_fromregion(&region);
	isc_region_consume(&region, 4);
Michael Graff's avatar
Michael Graff committed
338

Mark Andrews's avatar
Mark Andrews committed
339 340
	soa->retry = uint32_fromregion(&region);
	isc_region_consume(&region, 4);
Michael Graff's avatar
Michael Graff committed
341

Mark Andrews's avatar
Mark Andrews committed
342 343
	soa->expire = uint32_fromregion(&region);
	isc_region_consume(&region, 4);
Michael Graff's avatar
Michael Graff committed
344

Mark Andrews's avatar
Mark Andrews committed
345
	soa->minimum = uint32_fromregion(&region);
346

347
	soa->mctx = mctx;
348
	return (ISC_R_SUCCESS);
349 350 351 352 353

 cleanup:
	if (mctx != NULL)
		dns_name_free(&soa->origin, mctx);
	return (ISC_R_NOMEMORY);
354
}
355

356
static inline void
David Lawrence's avatar
David Lawrence committed
357
freestruct_soa(ARGS_FREESTRUCT) {
358 359 360 361
	dns_rdata_soa_t *soa = source;

	REQUIRE(source != NULL);
	REQUIRE(soa->common.rdtype == 6);
Michael Graff's avatar
Michael Graff committed
362

363 364 365
	if (soa->mctx == NULL)
		return;

366
	dns_name_free(&soa->origin, soa->mctx);
367
	dns_name_free(&soa->contact, soa->mctx);
368
	soa->mctx = NULL;
369
}
370

371
static inline isc_result_t
David Lawrence's avatar
David Lawrence committed
372
additionaldata_soa(ARGS_ADDLDATA) {
373
	UNUSED(rdata);
Michael Graff's avatar
Michael Graff committed
374 375
	UNUSED(add);
	UNUSED(arg);
376

Michael Graff's avatar
Michael Graff committed
377
	REQUIRE(rdata->type == 6);
378

379
	return (ISC_R_SUCCESS);
380 381
}

382
static inline isc_result_t
David Lawrence's avatar
David Lawrence committed
383
digest_soa(ARGS_DIGEST) {
Bob Halley's avatar
Bob Halley committed
384 385 386 387 388 389
	isc_region_t r;
	dns_name_t name;

	REQUIRE(rdata->type == 6);

	dns_rdata_toregion(rdata, &r);
Michael Graff's avatar
Michael Graff committed
390

Bob Halley's avatar
Bob Halley committed
391 392
	dns_name_init(&name, NULL);
	dns_name_fromregion(&name, &r);
Michael Graff's avatar
Michael Graff committed
393
	RETERR(dns_name_digest(&name, digest, arg));
Bob Halley's avatar
Bob Halley committed
394
	isc_region_consume(&r, name_length(&name));
Michael Graff's avatar
Michael Graff committed
395

Bob Halley's avatar
Bob Halley committed
396 397
	dns_name_init(&name, NULL);
	dns_name_fromregion(&name, &r);
Michael Graff's avatar
Michael Graff committed
398
	RETERR(dns_name_digest(&name, digest, arg));
Bob Halley's avatar
Bob Halley committed
399 400 401 402 403
	isc_region_consume(&r, name_length(&name));

	return ((digest)(arg, &r));
}

404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443
static inline isc_boolean_t
checkowner_soa(ARGS_CHECKOWNER) {

	REQUIRE(type == 6);

	UNUSED(name);
	UNUSED(type);
	UNUSED(rdclass);
	UNUSED(wildcard);

	return (ISC_TRUE);
}

static inline isc_boolean_t
checknames_soa(ARGS_CHECKNAMES) {
	isc_region_t region;
	dns_name_t name;

	REQUIRE(rdata->type == 6);

	UNUSED(owner);

	dns_rdata_toregion(rdata, &region);
	dns_name_init(&name, NULL);
	dns_name_fromregion(&name, &region);
	if (!dns_name_ishostname(&name, ISC_FALSE)) {
		if (bad != NULL)
			dns_name_clone(&name, bad);
		return (ISC_FALSE);
	}
	isc_region_consume(&region, name_length(&name));
	dns_name_fromregion(&name, &region);
	if (!dns_name_ismailbox(&name)) {
		if (bad != NULL)
			dns_name_clone(&name, bad);
		return (ISC_FALSE);
	}
	return (ISC_TRUE);
}

444 445 446 447 448
static inline int
casecompare_soa(ARGS_COMPARE) {
	return (compare_soa(rdata1, rdata2));
}

449
#endif	/* RDATA_GENERIC_SOA_6_C */