rdata_test.c 53.5 KB
Newer Older
1
/*
2
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3
 *
4 5 6
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 8 9
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
10 11 12 13
 */

#include <config.h>

Evan Hunt's avatar
Evan Hunt committed
14 15 16 17 18
#if HAVE_CMOCKA

#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
19

20
#include <stdbool.h>
Evan Hunt's avatar
Evan Hunt committed
21 22
#include <stdlib.h>
#include <string.h>
23 24
#include <unistd.h>

Evan Hunt's avatar
Evan Hunt committed
25 26 27
#define UNIT_TESTING
#include <cmocka.h>

28
#include <isc/hex.h>
29
#include <isc/lex.h>
30
#include <isc/print.h>
Evan Hunt's avatar
Evan Hunt committed
31
#include <isc/stdio.h>
32
#include <isc/types.h>
Evan Hunt's avatar
Evan Hunt committed
33
#include <isc/util.h>
34 35 36 37 38

#include <dns/rdata.h>

#include "dnstest.h"

39 40 41 42 43 44 45 46 47 48
/*
 * An array of these structures is passed to compare_ok().
 */
struct compare_ok {
	const char *text1;		/* text passed to fromtext_*() */
	const char *text2;		/* text passed to fromtext_*() */
	int answer;			/* -1, 0, 1 */
	int lineno;			/* source line defining this RDATA */
};
typedef struct compare_ok compare_ok_t;
49

Evan Hunt's avatar
Evan Hunt committed
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
static int
_setup(void **state) {
	isc_result_t result;

	UNUSED(state);

	result = dns_test_begin(NULL, false);
	assert_int_equal(result, ISC_R_SUCCESS);

	return (0);
}

static int
_teardown(void **state) {
	UNUSED(state);

	dns_test_end();

	return (0);
}

71 72 73
/*
 * An array of these structures is passed to check_text_ok().
 */
Evan Hunt's avatar
Evan Hunt committed
74
typedef struct text_ok {
75 76 77
	const char *text_in;		/* text passed to fromtext_*() */
	const char *text_out;		/* text expected from totext_*();
					   NULL indicates text_in is invalid */
Evan Hunt's avatar
Evan Hunt committed
78
} text_ok_t;
79 80 81 82

/*
 * An array of these structures is passed to check_wire_ok().
 */
Evan Hunt's avatar
Evan Hunt committed
83
typedef struct wire_ok {
84 85
	unsigned char data[512];	/* RDATA in wire format */
	size_t len;			/* octets of data to parse */
Evan Hunt's avatar
Evan Hunt committed
86 87
	bool ok;			/* is this RDATA valid? */
} wire_ok_t;
88

89 90 91 92 93
#define COMPARE(r1, r2, answer) \
	{ r1, r2, answer, __LINE__ }
#define COMPARE_SENTINEL() \
	{ NULL, NULL, 0, __LINE__ }

94
#define TEXT_VALID_CHANGED(data_in, data_out) \
Evan Hunt's avatar
Evan Hunt committed
95 96 97
				{ data_in, data_out }
#define TEXT_VALID(data)	{ data, data }
#define TEXT_INVALID(data)	{ data, NULL }
98 99 100 101 102
#define TEXT_SENTINEL()		TEXT_INVALID(NULL)

#define VARGC(...)		(sizeof((unsigned char[]){ __VA_ARGS__ }))
#define WIRE_TEST(ok, ...)	{					      \
					{ __VA_ARGS__ }, VARGC(__VA_ARGS__),  \
Evan Hunt's avatar
Evan Hunt committed
103
					ok				      \
104
				}
105 106 107
#define WIRE_VALID(...)		WIRE_TEST(true, __VA_ARGS__)
#define WIRE_INVALID(...)	WIRE_TEST(false, __VA_ARGS__)
#define WIRE_SENTINEL()		WIRE_TEST(false)
108 109 110 111 112 113 114 115 116 117 118

/*
 * Test whether converting rdata to a type-specific struct and then back to
 * rdata results in the same uncompressed wire form.  This checks whether
 * tostruct_*() and fromstruct_*() routines for given RR class and type behave
 * consistently.
 *
 * This function is called for every correctly processed input RDATA, from both
 * check_text_ok_single() and check_wire_ok_single().
 */
static void
Evan Hunt's avatar
Evan Hunt committed
119
check_struct_conversions(dns_rdata_t *rdata, size_t structsize) {
120 121 122 123 124
	dns_rdataclass_t rdclass = rdata->rdclass;
	dns_rdatatype_t type = rdata->type;
	isc_result_t result;
	isc_buffer_t target;
	void *rdata_struct;
Evan Hunt's avatar
Evan Hunt committed
125
	char buf[1024];
126 127

	rdata_struct = isc_mem_allocate(mctx, structsize);
Evan Hunt's avatar
Evan Hunt committed
128
	assert_non_null(rdata_struct);
129 130 131 132 133

	/*
	 * Convert from uncompressed wire form into type-specific struct.
	 */
	result = dns_rdata_tostruct(rdata, rdata_struct, NULL);
Evan Hunt's avatar
Evan Hunt committed
134 135
	assert_int_equal(result, ISC_R_SUCCESS);

136 137 138 139 140 141
	/*
	 * Convert from type-specific struct into uncompressed wire form.
	 */
	isc_buffer_init(&target, buf, sizeof(buf));
	result = dns_rdata_fromstruct(NULL, rdclass, type, rdata_struct,
				      &target);
Evan Hunt's avatar
Evan Hunt committed
142 143
	assert_int_equal(result, ISC_R_SUCCESS);

144 145 146
	/*
	 * Ensure results are consistent.
	 */
Evan Hunt's avatar
Evan Hunt committed
147 148 149
	assert_int_equal(isc_buffer_usedlength(&target), rdata->length);

	assert_memory_equal(buf, rdata->data, rdata->length);
150 151 152 153 154

	isc_mem_free(mctx, rdata_struct);
}

/*
155 156 157
 * Check whether converting supplied text form RDATA into uncompressed wire
 * form succeeds (tests fromtext_*()).  If so, try converting it back into text
 * form and see if it results in the original text (tests totext_*()).
158 159 160
 */
static void
check_text_ok_single(const text_ok_t *text_ok, dns_rdataclass_t rdclass,
161 162
		     dns_rdatatype_t type, size_t structsize)
{
163
	dns_rdata_t rdata = DNS_RDATA_INIT;
164 165
	unsigned char buf_fromtext[1024];
	char buf_totext[1024] = { 0 };
166
	isc_buffer_t target;
167 168 169
	isc_result_t result;

	/*
170
	 * Try converting text form RDATA into uncompressed wire form.
171
	 */
172 173
	result = dns_test_rdatafromstring(&rdata, rdclass, type, buf_fromtext,
					  sizeof(buf_fromtext),
Evan Hunt's avatar
Evan Hunt committed
174
					  text_ok->text_in, false);
175 176 177
	/*
	 * Check whether result is as expected.
	 */
178
	if (text_ok->text_out != NULL) {
Evan Hunt's avatar
Evan Hunt committed
179
		assert_int_equal(result, ISC_R_SUCCESS);
180
	} else {
Evan Hunt's avatar
Evan Hunt committed
181
		assert_int_not_equal(result, ISC_R_SUCCESS);
182
	}
Evan Hunt's avatar
Evan Hunt committed
183

184
	/*
185 186
	 * If text form RDATA was not parsed correctly, performing any
	 * additional checks is pointless.
187
	 */
188 189 190 191 192 193 194 195 196
	if (result != ISC_R_SUCCESS) {
		return;
	}
	/*
	 * Try converting uncompressed wire form RDATA back into text form and
	 * check whether the resulting text is the same as the original one.
	 */
	isc_buffer_init(&target, buf_totext, sizeof(buf_totext));
	result = dns_rdata_totext(&rdata, NULL, &target);
Evan Hunt's avatar
Evan Hunt committed
197 198 199
	assert_int_equal(result, ISC_R_SUCCESS);
	assert_string_equal(buf_totext, text_ok->text_out);

200 201 202 203
	/*
	 * Perform two-way conversion checks between uncompressed wire form and
	 * type-specific struct.
	 */
Evan Hunt's avatar
Evan Hunt committed
204
	check_struct_conversions(&rdata, structsize);
205 206 207
}

/*
208 209
 * Test whether supplied wire form RDATA is properly handled as being either
 * valid or invalid for an RR of given rdclass and type.
210 211 212
 */
static void
check_wire_ok_single(const wire_ok_t *wire_ok, dns_rdataclass_t rdclass,
213 214
		     dns_rdatatype_t type, size_t structsize)
{
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
	isc_buffer_t source, target;
	unsigned char buf[1024];
	dns_decompress_t dctx;
	isc_result_t result;
	dns_rdata_t rdata;

	/*
	 * Set up len-octet buffer pointing at data.
	 */
	isc_buffer_constinit(&source, wire_ok->data, wire_ok->len);
	isc_buffer_add(&source, wire_ok->len);
	isc_buffer_setactive(&source, wire_ok->len);
	/*
	 * Initialize target structures.
	 */
	isc_buffer_init(&target, buf, sizeof(buf));
	dns_rdata_init(&rdata);
	/*
	 * Try converting wire data into uncompressed wire form.
	 */
	dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY);
	result = dns_rdata_fromwire(&rdata, rdclass, type, &source, &dctx, 0,
				    &target);
	dns_decompress_invalidate(&dctx);
	/*
	 * Check whether result is as expected.
	 */
242
	if (wire_ok->ok) {
Evan Hunt's avatar
Evan Hunt committed
243
		assert_int_equal(result, ISC_R_SUCCESS);
244
	} else {
Evan Hunt's avatar
Evan Hunt committed
245
		assert_int_not_equal(result, ISC_R_SUCCESS);
246
	}
247
	/*
248 249
	 * If data was parsed correctly, perform two-way conversion checks
	 * between uncompressed wire form and type-specific struct.
250
	 */
251
	if (result == ISC_R_SUCCESS) {
Evan Hunt's avatar
Evan Hunt committed
252
		check_struct_conversions(&rdata, structsize);
253
	}
254 255
}

256
/*
257 258 259 260
 * Test fromtext_*() and totext_*() routines for given RR class and type for
 * each text form RDATA in the supplied array.  See the comment for
 * check_text_ok_single() for an explanation of how exactly these routines are
 * tested.
261
 */
262 263
static void
check_text_ok(const text_ok_t *text_ok, dns_rdataclass_t rdclass,
264 265
	      dns_rdatatype_t type, size_t structsize)
{
266
	size_t i;
267

268 269 270
	/*
	 * Check all entries in the supplied array.
	 */
271
	for (i = 0; text_ok[i].text_in != NULL; i++) {
272
		check_text_ok_single(&text_ok[i], rdclass, type, structsize);
273
	}
274 275 276 277 278 279 280 281 282 283
}

/*
 * For each wire form RDATA in the supplied array, check whether it is properly
 * handled as being either valid or invalid for an RR of given rdclass and
 * type, then check whether trying to process a zero-length wire data buffer
 * yields the expected result.  This checks whether the fromwire_*() routine
 * for given RR class and type behaves as expected.
 */
static void
284
check_wire_ok(const wire_ok_t *wire_ok, bool empty_ok,
285
	      dns_rdataclass_t rdclass, dns_rdatatype_t type,
286 287
	      size_t structsize)
{
288 289 290 291 292 293
	wire_ok_t empty_wire = WIRE_TEST(empty_ok);
	size_t i;

	/*
	 * Check all entries in the supplied array.
	 */
294
	for (i = 0; wire_ok[i].len != 0; i++) {
295
		check_wire_ok_single(&wire_ok[i], rdclass, type, structsize);
296
	}
297 298 299 300 301 302 303

	/*
	 * Check empty wire data.
	 */
	check_wire_ok_single(&empty_wire, rdclass, type, structsize);
}

304 305 306 307 308 309 310 311 312 313 314 315 316 317
/*
 * Check that two records compare as expected with dns_rdata_compare().
 */
static void
check_compare_ok_single(const compare_ok_t *compare_ok,
			dns_rdataclass_t rdclass, dns_rdatatype_t type)
{
	dns_rdata_t rdata1 = DNS_RDATA_INIT, rdata2 = DNS_RDATA_INIT;
	unsigned char buf1[1024], buf2[1024];
	isc_result_t result;
	int answer;

	result = dns_test_rdatafromstring(&rdata1, rdclass, type,
					  buf1, sizeof(buf1),
Evan Hunt's avatar
Evan Hunt committed
318 319 320 321 322
					  compare_ok->text1, false);
	if (result != ISC_R_SUCCESS) {
		fail_msg("# line %d: '%s': expected success, got failure",
			 compare_ok->lineno, compare_ok->text1);
	}
323 324 325

	result = dns_test_rdatafromstring(&rdata2, rdclass, type,
					  buf2, sizeof(buf2),
Evan Hunt's avatar
Evan Hunt committed
326
					  compare_ok->text2, false);
327

Evan Hunt's avatar
Evan Hunt committed
328 329 330 331
	if (result != ISC_R_SUCCESS) {
		fail_msg("# line %d: '%s': expected success, got failure",
			 compare_ok->lineno, compare_ok->text2);
	}
332 333

	answer = dns_rdata_compare(&rdata1, &rdata2);
Evan Hunt's avatar
Evan Hunt committed
334 335 336 337 338 339
	if (compare_ok->answer == 0 && answer != 0) {
		fail_msg("# line %d: dns_rdata_compare('%s', '%s'): "
			 "expected equal, got %s",
			 compare_ok->lineno,
			 compare_ok->text1, compare_ok->text2,
			 (answer > 0) ? "greater than" : "less than");
340
	}
Evan Hunt's avatar
Evan Hunt committed
341 342 343 344 345 346
	if (compare_ok->answer < 0 && answer >= 0) {
		fail_msg("# line %d: dns_rdata_compare('%s', '%s'): "
			 "expected less than, got %s",
			 compare_ok->lineno,
			 compare_ok->text1, compare_ok->text2,
			 (answer == 0) ? "equal" : "greater than");
347
	}
Evan Hunt's avatar
Evan Hunt committed
348 349 350 351 352 353
	if (compare_ok->answer > 0 && answer <= 0) {
		fail_msg("line %d: dns_rdata_compare('%s', '%s'): "
			 "expected greater than, got %s",
			 compare_ok->lineno,
			 compare_ok->text1, compare_ok->text2,
			 (answer == 0) ? "equal" : "less than");
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
	}
}

/*
 * Check that all the records sets in compare_ok compare as expected
 * with dns_rdata_compare().
 */
static void
check_compare_ok(const compare_ok_t *compare_ok,
		 dns_rdataclass_t rdclass, dns_rdatatype_t type)
{
	size_t i;
	/*
	 * Check all entries in the supplied array.
	 */
	for (i = 0; compare_ok[i].text1 != NULL; i++) {
		check_compare_ok_single(&compare_ok[i], rdclass, type);
	}
}

374
/*
375
 * Test whether supplied sets of text form and/or wire form RDATA are handled
Evan Hunt's avatar
Evan Hunt committed
376
 * as expected.
377 378 379
 *
 * The empty_ok argument denotes whether an attempt to parse a zero-length wire
 * data buffer should succeed or not (it is valid for some RR types).  There is
380
 * no point in performing a similar check for empty text form RDATA, because
381 382 383 384 385
 * dns_rdata_fromtext() returns ISC_R_UNEXPECTEDEND before calling fromtext_*()
 * for the given RR class and type.
 */
static void
check_rdata(const text_ok_t *text_ok, const wire_ok_t *wire_ok,
386
	    const compare_ok_t *compare_ok,
387
	    bool empty_ok, dns_rdataclass_t rdclass,
388 389 390
	    dns_rdatatype_t type, size_t structsize)
{
	if (text_ok != NULL) {
391
		check_text_ok(text_ok, rdclass, type, structsize);
392 393
	}
	if (wire_ok != NULL) {
394
		check_wire_ok(wire_ok, empty_ok, rdclass, type, structsize);
395
	}
396 397 398
	if (compare_ok != NULL) {
		check_compare_ok(compare_ok, rdclass, type);
	}
399 400
}

Evan Hunt's avatar
Evan Hunt committed
401 402 403
/* APL RDATA manipulations */
static void
apl(void **state) {
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 444 445 446 447 448 449 450
	text_ok_t text_ok[] = {
		/* empty list */
		TEXT_VALID(""),
		/* min,max prefix IPv4 */
		TEXT_VALID("1:0.0.0.0/0"),
		TEXT_VALID("1:127.0.0.1/32"),
		/* min,max prefix IPv6 */
		TEXT_VALID("2:::/0"),
		TEXT_VALID("2:::1/128"),
		/* negated */
		TEXT_VALID("!1:0.0.0.0/0"),
		TEXT_VALID("!1:127.0.0.1/32"),
		TEXT_VALID("!2:::/0"),
		TEXT_VALID("!2:::1/128"),
		/* bits set after prefix length - not disallowed */
		TEXT_VALID("1:127.0.0.0/0"),
		TEXT_VALID("2:8000::/0"),
		/* multiple */
		TEXT_VALID("1:0.0.0.0/0 1:127.0.0.1/32"),
		TEXT_VALID("1:0.0.0.0/0 !1:127.0.0.1/32"),
		/* family 0, prefix 0, positive */
		TEXT_VALID("\\# 4 00000000"),
		/* family 0, prefix 0, negative */
		TEXT_VALID("\\# 4 00000080"),
		/* prefix too long */
		TEXT_INVALID("1:0.0.0.0/33"),
		TEXT_INVALID("2:::/129"),
		/*
		 * Sentinel.
		 */
		TEXT_SENTINEL()
	};
	wire_ok_t wire_ok[] = {
		/* zero length */
		WIRE_VALID(),
		/* prefix too big IPv4 */
		WIRE_INVALID(0x00, 0x01, 33U, 0x00),
		/* prefix too big IPv6 */
		WIRE_INVALID(0x00, 0x02, 129U, 0x00),
		/* trailing zero octet in afdpart */
		WIRE_INVALID(0x00, 0x00, 0x00, 0x01, 0x00),
		/*
		 * Sentinel.
		 */
		WIRE_SENTINEL()
	};

Evan Hunt's avatar
Evan Hunt committed
451
	UNUSED(state);
452

453
	check_rdata(text_ok, wire_ok, NULL, true, dns_rdataclass_in,
454 455 456
		    dns_rdatatype_apl, sizeof(dns_rdata_in_apl_t));
}

Evan Hunt's avatar
Evan Hunt committed
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
/*
 * http://broadband-forum.org/ftp/pub/approved-specs/af-saa-0069.000.pdf
 *
 * ATMA RR’s have the following RDATA format:
 *
 *                                           1  1  1  1  1  1
 *             0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
 *          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 *          |          FORMAT       |                       |
 *          +--+--+--+--+--+--+--+--+                       |
 *          /                    ADDRESS                    /
 *          |                                               |
 *          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 *
 * The fields have the following meaning:
 *
 * * FORMAT: One octet that indicates the format of ADDRESS. The two
 *   possible values for FORMAT are value 0 indicating ATM End System Address
 *   (AESA) format and value 1 indicating E.164 format.
 *
 * * ADDRESS: Variable length string of octets containing the ATM address of
 *   the node to which this RR pertains.
 *
 * When the format value is 0, indicating that the address is in AESA format,
 * the address is coded as described in ISO 8348/AD 2 using the preferred
 * binary encoding of the ISO NSAP format. When the format value is 1,
 * indicating that the address is in E.164 format, the Address/Number Digits
 * appear in the order in which they would be entered on a numeric keypad.
 * Digits are coded in IA5 characters with the leftmost bit of each digit set
 * to 0.  This ATM address appears in ATM End System Address Octets field (AESA
 * format) or the Address/Number Digits field (E.164 format) of the Called
 * party number information element [ATMUNI3.1]. Subaddress information is
 * intentionally not included because E.164 subaddress information is used for
 * routing.
 *
 * ATMA RRs cause no additional section processing.
 */
static void
atma(void **state) {
Mark Andrews's avatar
Mark Andrews committed
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559
	text_ok_t text_ok[] = {
		TEXT_VALID("00"),
		TEXT_VALID_CHANGED("0.0", "00"),
		/*
		 * multiple consecutive periods
		 */
		TEXT_INVALID("0..0"),
		/*
		 * trailing period
		 */
		TEXT_INVALID("00."),
		/*
		 * leading period
		 */
		TEXT_INVALID(".00"),
		/*
		 * Not full octets.
		 */
		TEXT_INVALID("000"),
		/*
		 * E.164
		 */
		TEXT_VALID("+61200000000"),
		/*
		 * E.164 with periods
		 */
		TEXT_VALID_CHANGED("+61.2.0000.0000", "+61200000000"),
		/*
		 * E.164 with period at end
		 */
		TEXT_INVALID("+61200000000."),
		/*
		 * E.164 with multiple consecutive periods
		 */
		TEXT_INVALID("+612..00000000"),
		/*
		 * E.164 with period before the leading digit.
		 */
		TEXT_INVALID("+.61200000000"),
		/*
		 * Sentinel.
		 */
		TEXT_SENTINEL()
	};
	wire_ok_t wire_ok[] = {
		/*
		 * Too short.
		 */
		WIRE_INVALID(0x00),
		WIRE_INVALID(0x01),
		/*
		 * all digits
		 */
		WIRE_VALID(0x01, '6', '1', '2', '0', '0', '0'),
		/*
		 * non digit
		 */
		WIRE_INVALID(0x01, '+', '6', '1', '2', '0', '0', '0'),
		/*
		 * Sentinel.
		 */
		WIRE_SENTINEL()
	};

Evan Hunt's avatar
Evan Hunt committed
560
	UNUSED(state);
Mark Andrews's avatar
Mark Andrews committed
561

562
	check_rdata(text_ok, wire_ok, NULL, false, dns_rdataclass_in,
Mark Andrews's avatar
Mark Andrews committed
563 564 565
		    dns_rdatatype_atma, sizeof(dns_rdata_in_atma_t));
}

Mark Andrews's avatar
Mark Andrews committed
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
/* ATMRELAY RDATA manipulations */
static void
atmrelay(void **state) {
	text_ok_t text_ok[] = {
		TEXT_INVALID(""),
		TEXT_INVALID("0"),
		TEXT_INVALID("0 0"),
		/* gatway type 0 */
		TEXT_VALID("0 0 0"),
		TEXT_VALID("0 1 0"),
		TEXT_INVALID("0 2 0"),		/* discovery out of range */
		TEXT_VALID("255 1 0"),		/* max precendence */
		TEXT_INVALID("256 1 0"),	/* precedence out of range */

		/* IPv4 gateway */
		TEXT_INVALID("0 0 1"),		/* no addresss */
		TEXT_VALID("0 0 1 0.0.0.0"),
		TEXT_INVALID("0 0 1 0.0.0.0 x"), /* extra */
		TEXT_INVALID("0 0 1 0.0.0.0.0"), /* bad addresss */
		TEXT_INVALID("0 0 1 ::"),	/* bad addresss */
		TEXT_INVALID("0 0 1 ."),	/* bad addresss */

		/* IPv6 gateway */
		TEXT_INVALID("0 0 2"),		/* no addresss */
		TEXT_VALID("0 0 2 ::"),
		TEXT_INVALID("0 0 2 :: xx"),	/* extra */
		TEXT_INVALID("0 0 2 0.0.0.0"),	/* bad addresss */
		TEXT_INVALID("0 0 2 ."),	/* bad addresss */

		/* hostname gateway */
		TEXT_INVALID("0 0 3"),		/* no name */
		/* IPv4 is a valid name */
		TEXT_VALID_CHANGED("0 0 3 0.0.0.0", "0 0 3 0.0.0.0."),
		/* IPv6 is a valid name */
		TEXT_VALID_CHANGED("0 0 3 ::", "0 0 3 ::."),
		TEXT_VALID_CHANGED("0 0 3 example", "0 0 3 example."),
		TEXT_VALID("0 0 3 example."),
		TEXT_INVALID("0 0 3 example. x"), /* extra */

		/* unknown gateway */
		TEXT_VALID("\\# 2 0004"),
		TEXT_VALID("\\# 2 0084"),
		TEXT_VALID("\\# 2 007F"),
		TEXT_VALID("\\# 3 000400"),
		TEXT_VALID("\\# 3 008400"),
		TEXT_VALID("\\# 3 00FF00"),

		/*
		 * Sentinel.
		 */
		TEXT_SENTINEL()
	};
	wire_ok_t wire_ok[] = {
		WIRE_INVALID(0x00),
		WIRE_VALID(0x00, 0x00),
		WIRE_VALID(0x00, 0x80),
		WIRE_INVALID(0x00, 0x00, 0x00),
		WIRE_INVALID(0x00, 0x80, 0x00),

		WIRE_INVALID(0x00, 0x01),
		WIRE_INVALID(0x00, 0x01, 0x00),
		WIRE_INVALID(0x00, 0x01, 0x00, 0x00),
		WIRE_INVALID(0x00, 0x01, 0x00, 0x00, 0x00),
		WIRE_VALID(0x00, 0x01, 0x00, 0x00, 0x00, 0x00),
		WIRE_INVALID(0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00),

		WIRE_INVALID(0x00, 0x02),
		WIRE_INVALID(0x00, 0x02, 0x00),
		WIRE_VALID(0x00, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04,
			   0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11,
			   0x12, 0x13, 0x14, 0x15),
		WIRE_INVALID(0x00, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04,
			     0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11,
			     0x12, 0x13, 0x14, 0x15, 0x16),

		WIRE_INVALID(0x00, 0x03),
		WIRE_VALID(0x00, 0x03, 0x00),
		WIRE_INVALID(0x00, 0x03, 0x00, 0x00),	/* extra */

		WIRE_VALID(0x00, 0x04),
		WIRE_VALID(0x00, 0x04, 0x00),
		/*
		 * Sentinel.
		 */
		WIRE_SENTINEL()
	};

	UNUSED(state);

	check_rdata(text_ok, wire_ok, NULL, false, dns_rdataclass_in,
		    dns_rdatatype_atmrelay, sizeof(dns_rdata_atmrelay_t));
}

659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722
/*
 * CSYNC tests.
 *
 * RFC 7477:
 *
 * 2.1.  The CSYNC Resource Record Format
 *
 * 2.1.1.  The CSYNC Resource Record Wire Format
 *
 *    The CSYNC RDATA consists of the following fields:
 *
 *                           1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
 *       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *      |                          SOA Serial                           |
 *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *      |       Flags                   |            Type Bit Map       /
 *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *      /                     Type Bit Map (continued)                  /
 *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *
 * 2.1.1.1.  The SOA Serial Field
 *
 *    The SOA Serial field contains a copy of the 32-bit SOA serial number
 *    from the child zone.  If the soaminimum flag is set, parental agents
 *    querying children's authoritative servers MUST NOT act on data from
 *    zones advertising an SOA serial number less than this value.  See
 *    [RFC1982] for properly implementing "less than" logic.  If the
 *    soaminimum flag is not set, parental agents MUST ignore the value in
 *    the SOA Serial field.  Clients can set the field to any value if the
 *    soaminimum flag is unset, such as the number zero.
 *
 * (...)
 *
 * 2.1.1.2.  The Flags Field
 *
 *    The Flags field contains 16 bits of boolean flags that define
 *    operations that affect the processing of the CSYNC record.  The flags
 *    defined in this document are as follows:
 *
 *       0x00 0x01: "immediate"
 *
 *       0x00 0x02: "soaminimum"
 *
 *    The definitions for how the flags are to be used can be found in
 *    Section 3.
 *
 *    The remaining flags are reserved for use by future specifications.
 *    Undefined flags MUST be set to 0 by CSYNC publishers.  Parental
 *    agents MUST NOT process a CSYNC record if it contains a 1 value for a
 *    flag that is unknown to or unsupported by the parental agent.
 *
 * 2.1.1.2.1.  The Type Bit Map Field
 *
 *    The Type Bit Map field indicates the record types to be processed by
 *    the parental agent, according to the procedures in Section 3.  The
 *    Type Bit Map field is encoded in the same way as the Type Bit Map
 *    field of the NSEC record, described in [RFC4034], Section 4.1.2.  If
 *    a bit has been set that a parental agent implementation does not
 *    understand, the parental agent MUST NOT act upon the record.
 *    Specifically, a parental agent must not simply copy the data, and it
 *    must understand the semantics associated with a bit in the Type Bit
 *    Map field that has been set to 1.
 */
Evan Hunt's avatar
Evan Hunt committed
723 724
static void
csync(void **state) {
725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780
	text_ok_t text_ok[] = {
		TEXT_INVALID(""),
		TEXT_INVALID("0"),
		TEXT_VALID("0 0"),
		TEXT_VALID("0 0 A"),
		TEXT_VALID("0 0 NS"),
		TEXT_VALID("0 0 AAAA"),
		TEXT_VALID("0 0 A AAAA"),
		TEXT_VALID("0 0 A NS AAAA"),
		TEXT_INVALID("0 0 A NS AAAA BOGUS"),
		TEXT_SENTINEL()
	};
	wire_ok_t wire_ok[] = {
		/*
		 * Short.
		 */
		WIRE_INVALID(0x00),
		/*
		 * Short.
		 */
		WIRE_INVALID(0x00, 0x00),
		/*
		 * Short.
		 */
		WIRE_INVALID(0x00, 0x00, 0x00),
		/*
		 * Short.
		 */
		WIRE_INVALID(0x00, 0x00, 0x00, 0x00),
		/*
		 * Short.
		 */
		WIRE_INVALID(0x00, 0x00, 0x00, 0x00, 0x00),
		/*
		 * Serial + flags only.
		 */
		WIRE_VALID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
		/*
		 * Bad type map.
		 */
		WIRE_INVALID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
		/*
		 * Bad type map.
		 */
		WIRE_INVALID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
		/*
		 * Good type map.
		 */
		WIRE_VALID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
			   0x02),
		/*
		 * Sentinel.
		 */
		WIRE_SENTINEL()
	};

Evan Hunt's avatar
Evan Hunt committed
781
	UNUSED(state);
782

783
	check_rdata(text_ok, wire_ok, NULL, false, dns_rdataclass_in,
784 785 786
		    dns_rdatatype_csync, sizeof(dns_rdata_csync_t));
}

787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841
/*
 * DOA tests.
 *
 * draft-durand-doa-over-dns-03:
 *
 * 3.2.  DOA RDATA Wire Format
 *
 *        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 *     0: |                                                               |
 *        |                        DOA-ENTERPRISE                         |
 *        |                                                               |
 *        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 *     4: |                                                               |
 *        |                           DOA-TYPE                            |
 *        |                                                               |
 *        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 *     8: |         DOA-LOCATION          |         DOA-MEDIA-TYPE        /
 *        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 *    10: /                                                               /
 *        /                  DOA-MEDIA-TYPE (continued)                   /
 *        /                                                               /
 *        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 *        /                                                               /
 *        /                           DOA-DATA                            /
 *        /                                                               /
 *        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 *
 *    DOA-ENTERPRISE: a 32-bit unsigned integer in network order.
 *
 *    DOA-TYPE: a 32-bit unsigned integer in network order.
 *
 *    DOA-LOCATION: an 8-bit unsigned integer.
 *
 *    DOA-MEDIA-TYPE: A <character-string> (see [RFC1035]).  The first
 *    octet of the <character-string> contains the number of characters to
 *    follow.
 *
 *    DOA-DATA: A variable length blob of binary data.  The length of the
 *    DOA-DATA is not contained within the wire format of the RR and has to
 *    be computed from the RDLENGTH of the entire RR once other fields have
 *    been taken into account.
 *
 * 3.3.  DOA RDATA Presentation Format
 *
 *    The DOA-ENTERPRISE field is presented as an unsigned 32-bit decimal
 *    integer with range 0 - 4,294,967,295.
 *
 *    The DOA-TYPE field is presented as an unsigned 32-bit decimal integer
 *    with range 0 - 4,294,967,295.
 *
 *    The DOA-LOCATION field is presented as an unsigned 8-bit decimal
 *    integer with range 0 - 255.
 *
 *    The DOA-MEDIA-TYPE field is presented as a single <character-string>.
 *
842
 *    The DOA-DATA is presented as Base64 encoded data [RFC4648] unless the
843
 *    DOA-DATA is empty in which case it is presented as a single dash
844 845
 *    character ("-", ASCII 45).  White space is permitted within Base64
 *    data.
846
 */
Evan Hunt's avatar
Evan Hunt committed
847 848
static void
doa(void **state) {
849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995
	text_ok_t text_ok[] = {
		/*
		 * Valid, non-empty DOA-DATA.
		 */
		TEXT_VALID("0 0 1 \"text/plain\" Zm9v"),
		/*
		 * Valid, non-empty DOA-DATA with whitespace in between.
		 */
		TEXT_VALID_CHANGED("0 0 1 \"text/plain\" Zm 9v",
				   "0 0 1 \"text/plain\" Zm9v"),
		/*
		 * Valid, unquoted DOA-MEDIA-TYPE, non-empty DOA-DATA.
		 */
		TEXT_VALID_CHANGED("0 0 1 text/plain Zm9v",
				   "0 0 1 \"text/plain\" Zm9v"),
		/*
		 * Invalid, quoted non-empty DOA-DATA.
		 */
		TEXT_INVALID("0 0 1 \"text/plain\" \"Zm9v\""),
		/*
		 * Valid, empty DOA-DATA.
		 */
		TEXT_VALID("0 0 1 \"text/plain\" -"),
		/*
		 * Invalid, quoted empty DOA-DATA.
		 */
		TEXT_INVALID("0 0 1 \"text/plain\" \"-\""),
		/*
		 * Invalid, missing "-" in empty DOA-DATA.
		 */
		TEXT_INVALID("0 0 1 \"text/plain\""),
		/*
		 * Valid, undefined DOA-LOCATION.
		 */
		TEXT_VALID("0 0 100 \"text/plain\" Zm9v"),
		/*
		 * Invalid, DOA-LOCATION too big.
		 */
		TEXT_INVALID("0 0 256 \"text/plain\" ZM9v"),
		/*
		 * Valid, empty DOA-MEDIA-TYPE, non-empty DOA-DATA.
		 */
		TEXT_VALID("0 0 2 \"\" aHR0cHM6Ly93d3cuaXNjLm9yZy8="),
		/*
		 * Valid, empty DOA-MEDIA-TYPE, empty DOA-DATA.
		 */
		TEXT_VALID("0 0 1 \"\" -"),
		/*
		 * Valid, DOA-MEDIA-TYPE with a space.
		 */
		TEXT_VALID("0 0 1 \"plain text\" Zm9v"),
		/*
		 * Invalid, missing DOA-MEDIA-TYPE.
		 */
		TEXT_INVALID("1234567890 1234567890 1"),
		/*
		 * Valid, DOA-DATA over 255 octets.
		 */
		TEXT_VALID("1234567890 1234567890 1 \"image/gif\" "
			   "R0lGODlhKAAZAOMCAGZmZgBmmf///zOZzMz//5nM/zNmmWbM"
			   "/5nMzMzMzACZ/////////////////////yH5BAEKAA8ALAAA"
			   "AAAoABkAAATH8IFJK5U2a4337F5ogRkpnoCJrly7PrCKyh8c"
			   "3HgAhzT35MDbbtO7/IJIHbGiOiaTxVTpSVWWLqNq1UVyapNS"
			   "1wd3OAxug0LhnCubcVhsxysQnOt4ATpvvzHlFzl1AwODhWeF"
			   "AgRpen5/UhheAYMFdUB4SFcpGEGGdQeCAqBBLTuSk30EeXd9"
			   "pEsAbKGxjHqDSE0Sp6ixN4N1BJmbc7lIhmsBich1awPAjkY1"
			   "SZR8bJWrz382SGqIBQQFQd4IsUTaX+ceuudPEQA7"),
		/*
		 * Invalid, bad Base64 in DOA-DATA.
		 */
		TEXT_INVALID("1234567890 1234567890 1 \"image/gif\" R0lGODl"),
		/*
		 * Sentinel.
		 */
		TEXT_SENTINEL()
	};
	wire_ok_t wire_ok[] = {
		/*
		 * Valid, empty DOA-MEDIA-TYPE, empty DOA-DATA.
		 */
		WIRE_VALID(0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78,
			   0x01, 0x00),
		/*
		 * Invalid, missing DOA-MEDIA-TYPE.
		 */
		WIRE_INVALID(0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78,
			     0x01),
		/*
		 * Invalid, malformed DOA-MEDIA-TYPE length.
		 */
		WIRE_INVALID(0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78,
			     0x01, 0xff),
		/*
		 * Valid, empty DOA-DATA.
		 */
		WIRE_VALID(0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78,
			   0x01, 0x03, 0x66, 0x6f, 0x6f),
		/*
		 * Valid, non-empty DOA-DATA.
		 */
		WIRE_VALID(0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78,
			   0x01, 0x03, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72),
		/*
		 * Valid, DOA-DATA over 255 octets.
		 */
		WIRE_VALID(0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78,
			   0x01, 0x06, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79,
			   0x00, 0x66, 0x99, 0xff, 0xff, 0xff, 0x33, 0x99,
			   0xcc, 0xcc, 0xff, 0xff, 0x99, 0xcc, 0xff, 0x33,
			   0x66, 0x99, 0x66, 0xcc, 0xff, 0x99, 0xcc, 0xcc,
			   0xcc, 0xcc, 0xcc, 0x00, 0x99, 0xff, 0xff, 0xff,
			   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
			   0xff, 0xff, 0xff, 0xff, 0xff, 0x21, 0xf9, 0x04,
			   0x01, 0x0a, 0x00, 0x0f, 0x00, 0x2c, 0x00, 0x00,
			   0x00, 0x00, 0x28, 0x00, 0x19, 0x00, 0x00, 0x04,
			   0xc7, 0xf0, 0x81, 0x49, 0x2b, 0x95, 0x36, 0x6b,
			   0x8d, 0xf7, 0xec, 0x5e, 0x68, 0x81, 0x19, 0x29,
			   0x9e, 0x80, 0x89, 0xae, 0x5c, 0xbb, 0x3e, 0xb0,
			   0x8a, 0xca, 0x1f, 0x1c, 0xdc, 0x78, 0x00, 0x87,
			   0x34, 0xf7, 0xe4, 0xc0, 0xdb, 0x6e, 0xd3, 0xbb,
			   0xfc, 0x82, 0x48, 0x1d, 0xb1, 0xa2, 0x3a, 0x26,
			   0x93, 0xc5, 0x54, 0xe9, 0x49, 0x55, 0x96, 0x2e,
			   0xa3, 0x6a, 0xd5, 0x45, 0x72, 0x6a, 0x93, 0x52,
			   0xd7, 0x07, 0x77, 0x38, 0x0c, 0x6e, 0x83, 0x42,
			   0xe1, 0x9c, 0x2b, 0x9b, 0x71, 0x58, 0x6c, 0xc7,
			   0x2b, 0x10, 0x9c, 0xeb, 0x78, 0x01, 0x3a, 0x6f,
			   0xbf, 0x31, 0xe5, 0x17, 0x39, 0x75, 0x03, 0x03,
			   0x83, 0x85, 0x67, 0x85, 0x02, 0x04, 0x69, 0x7a,
			   0x7e, 0x7f, 0x52, 0x18, 0x5e, 0x01, 0x83, 0x05,
			   0x75, 0x40, 0x78, 0x48, 0x57, 0x29, 0x18, 0x41,
			   0x86, 0x75, 0x07, 0x82, 0x02, 0xa0, 0x41, 0x2d,
			   0x3b, 0x92, 0x93, 0x7d, 0x04, 0x79, 0x77, 0x7d,
			   0xa4, 0x4b, 0x00, 0x6c, 0xa1, 0xb1, 0x8c, 0x7a,
			   0x83, 0x48, 0x4d, 0x12, 0xa7, 0xa8, 0xb1, 0x37,
			   0x83, 0x75, 0x04, 0x99, 0x9b, 0x73, 0xb9, 0x48,
			   0x86, 0x6b, 0x01, 0x89, 0xc8, 0x75, 0x6b, 0x03,
			   0xc0, 0x8e, 0x46, 0x35, 0x49, 0x94, 0x7c, 0x6c,
			   0x95, 0xab, 0xcf, 0x7f, 0x36, 0x48, 0x6a, 0x88,
			   0x05, 0x04, 0x05, 0x41, 0xde, 0x08, 0xb1, 0x44,
			   0xda, 0x5f, 0xe7, 0x1e, 0xba, 0xe7, 0x4f, 0x11,
			   0x00, 0x3b),
		/*
		 * Sentinel.
		 */
		WIRE_SENTINEL()
	};

Evan Hunt's avatar
Evan Hunt committed
996
	UNUSED(state);
997

998
	check_rdata(text_ok, wire_ok, NULL, false, dns_rdataclass_in,
999 1000 1001
		    dns_rdatatype_doa, sizeof(dns_rdata_doa_t));
}

1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
/*
 * EDNS Client Subnet tests.
 *
 * RFC 7871:
 *
 * 6.  Option Format
 *
 *    This protocol uses an EDNS0 [RFC6891] option to include client
 *    address information in DNS messages.  The option is structured as
 *    follows:
 *
 *                 +0 (MSB)                            +1 (LSB)
 *       +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 *    0: |                          OPTION-CODE                          |
 *       +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 *    2: |                         OPTION-LENGTH                         |
 *       +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 *    4: |                            FAMILY                             |
 *       +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 *    6: |     SOURCE PREFIX-LENGTH      |     SCOPE PREFIX-LENGTH       |
 *       +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 *    8: |                           ADDRESS...                          /
 *       +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 *
 *    o  (Defined in [RFC6891]) OPTION-CODE, 2 octets, for ECS is 8 (0x00
 *       0x08).
 *
 *    o  (Defined in [RFC6891]) OPTION-LENGTH, 2 octets, contains the
 *       length of the payload (everything after OPTION-LENGTH) in octets.
 *
 *    o  FAMILY, 2 octets, indicates the family of the address contained in
 *       the option, using address family codes as assigned by IANA in
 *       Address Family Numbers [Address_Family_Numbers].
 *
 *    The format of the address part depends on the value of FAMILY.  This
 *    document only defines the format for FAMILY 1 (IPv4) and FAMILY 2
 *    (IPv6), which are as follows:
 *
 *    o  SOURCE PREFIX-LENGTH, an unsigned octet representing the leftmost
 *       number of significant bits of ADDRESS to be used for the lookup.
 *       In responses, it mirrors the same value as in the queries.
 *
 *    o  SCOPE PREFIX-LENGTH, an unsigned octet representing the leftmost
 *       number of significant bits of ADDRESS that the response covers.
 *       In queries, it MUST be set to 0.
 *
 *    o  ADDRESS, variable number of octets, contains either an IPv4 or
 *       IPv6 address, depending on FAMILY, which MUST be truncated to the
 *       number of bits indicated by the SOURCE PREFIX-LENGTH field,
 *       padding with 0 bits to pad to the end of the last octet needed.
 *
 *    o  A server receiving an ECS option that uses either too few or too
 *       many ADDRESS octets, or that has non-zero ADDRESS bits set beyond
 *       SOURCE PREFIX-LENGTH, SHOULD return FORMERR to reject the packet,
 *       as a signal to the software developer making the request to fix
 *       their implementation.
 *
 *    All fields are in network byte order ("big-endian", per [RFC1700],
 *    Data Notation).
 */
Evan Hunt's avatar
Evan Hunt committed
1062 1063
static void
edns_client_subnet(void **state) {
1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157
	wire_ok_t wire_ok[] = {
		/*
		 * Option code with no content.
		 */
		WIRE_INVALID(0x00, 0x08, 0x00, 0x00),
		/*
		 * Option code family 0, source 0, scope 0.
		 */
		WIRE_VALID(0x00, 0x08, 0x00, 0x04,
			   0x00, 0x00, 0x00, 0x00),
		/*
		 * Option code family 1 (IPv4), source 0, scope 0.
		 */
		WIRE_VALID(0x00, 0x08, 0x00, 0x04,
			   0x00, 0x01, 0x00, 0x00),
		/*
		 * Option code family 2 (IPv6) , source 0, scope 0.
		 */
		WIRE_VALID(0x00, 0x08, 0x00, 0x04,
			   0x00, 0x02, 0x00, 0x00),
		/*
		 * Extra octet.
		 */
		WIRE_INVALID(0x00, 0x08, 0x00, 0x05,
			     0x00, 0x00, 0x00, 0x00,
			     0x00),
		/*
		 * Source too long for IPv4.
		 */
		WIRE_INVALID(0x00, 0x08, 0x00,    8,
			     0x00, 0x01,   33, 0x00,
			     0x00, 0x00, 0x00, 0x00),
		/*
		 * Source too long for IPv6.
		 */
		WIRE_INVALID(0x00, 0x08, 0x00,   20,
			     0x00, 0x02,  129, 0x00,
			     0x00, 0x00, 0x00, 0x00,
			     0x00, 0x00, 0x00, 0x00,
			     0x00, 0x00, 0x00, 0x00,
			     0x00, 0x00, 0x00, 0x00),
		/*
		 * Scope too long for IPv4.
		 */
		WIRE_INVALID(0x00, 0x08, 0x00,    8,
			     0x00, 0x01, 0x00,   33,
			     0x00, 0x00, 0x00, 0x00),
		/*
		 * Scope too long for IPv6.
		 */
		WIRE_INVALID(0x00, 0x08, 0x00,   20,
			     0x00, 0x02, 0x00,  129,
			     0x00, 0x00, 0x00, 0x00,
			     0x00, 0x00, 0x00, 0x00,
			     0x00, 0x00, 0x00, 0x00,
			     0x00, 0x00, 0x00, 0x00),
		/*
		 * When family=0, source and scope should be 0.
		 */
		WIRE_VALID(0x00, 0x08, 0x00,    4,
			   0x00, 0x00, 0x00, 0x00),
		/*
		 * When family=0, source and scope should be 0.
		 */
		WIRE_INVALID(0x00, 0x08, 0x00,    5,
			     0x00, 0x00, 0x01, 0x00,
			     0x00),
		/*
		 * When family=0, source and scope should be 0.
		 */
		WIRE_INVALID(0x00, 0x08, 0x00,    5,
			     0x00, 0x00, 0x00, 0x01,
			     0x00),
		/*
		 * Length too short for source IPv4.
		 */
		WIRE_INVALID(0x00, 0x08, 0x00,    7,
			     0x00, 0x01,   32, 0x00,
			     0x00, 0x00, 0x00),
		/*
		 * Length too short for source IPv6.
		 */
		WIRE_INVALID(0x00, 0x08, 0x00,   19,
			     0x00, 0x02,  128, 0x00,
			     0x00, 0x00, 0x00, 0x00,
			     0x00, 0x00, 0x00, 0x00,
			     0x00, 0x00, 0x00, 0x00,
			     0x00, 0x00, 0x00),
		/*
		 * Sentinel.
		 */
		WIRE_SENTINEL()
	};

Evan Hunt's avatar
Evan Hunt committed
1158
	UNUSED(state);
1159

1160
	check_rdata(NULL, wire_ok, NULL, true, dns_rdataclass_in,
1161 1162 1163
		    dns_rdatatype_opt, sizeof(dns_rdata_opt_t));
}

Mark Andrews's avatar
Mark Andrews committed
1164 1165 1166 1167 1168 1169 1170 1171 1172
/*
 * http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt
 *
 * The RDATA portion of both the NIMLOC and EID records contains
 * uninterpreted binary data.  The representation in the text master file
 * is an even number of hex characters (0 to 9, a to f), case is not
 * significant.  For readability, whitespace may be included in the value
 * field and should be ignored when reading a master file.
 */
Evan Hunt's avatar
Evan Hunt committed
1173 1174
static void
eid(void **state) {
Mark Andrews's avatar
Mark Andrews committed
1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195
	text_ok_t text_ok[] = {
		TEXT_VALID("AABBCC"),
		TEXT_VALID_CHANGED("AA bb cc", "AABBCC"),
		TEXT_INVALID("aab"),
		/*
		 * Sentinel.
		 */
		TEXT_SENTINEL()
	};
	wire_ok_t wire_ok[] = {
		/*
		 * Too short.
		 */
		WIRE_INVALID(),
		WIRE_VALID(0x00),
		/*
		 * Sentinel.
		 */
		WIRE_SENTINEL()
	};

Evan Hunt's avatar
Evan Hunt committed
1196
	UNUSED(state);
Mark Andrews's avatar
Mark Andrews committed
1197

1198
	check_rdata(text_ok, wire_ok, NULL, false, dns_rdataclass_in,
Mark Andrews's avatar
Mark Andrews committed
1199 1200 1201
		    dns_rdatatype_eid, sizeof(dns_rdata_in_eid_t));
}

1202
/*
Evan Hunt's avatar
Evan Hunt committed
1203
 * test that an oversized HIP record will be rejected
1204
 */
Evan Hunt's avatar
Evan Hunt committed
1205 1206
static void
hip(void **state) {
1207 1208 1209 1210 1211 1212 1213 1214 1215 1216
	unsigned char hipwire[DNS_RDATA_MAXLENGTH] = {
				    0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
				    0x04, 0x41, 0x42, 0x43, 0x44, 0x00 };
	unsigned char buf[1024*1024];
	isc_buffer_t source, target;
	dns_rdata_t rdata;
	dns_decompress_t dctx;
	isc_result_t result;
	size_t i;

Evan Hunt's avatar
Evan Hunt committed
1217
	UNUSED(state);
1218

1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236
	/*
	 * Fill the rest of input buffer with compression pointers.
	 */
	for (i = 12; i < sizeof(hipwire) - 2; i += 2) {
		hipwire[i] = 0xc0;
		hipwire[i+1] = 0x06;
	}

	isc_buffer_init(&source, hipwire, sizeof(hipwire));
	isc_buffer_add(&source, sizeof(hipwire));
	isc_buffer_setactive(&source, i);
	isc_buffer_init(&target, buf, sizeof(buf));
	dns_rdata_init(&rdata);
	dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY);
	result = dns_rdata_fromwire(&rdata, dns_rdataclass_in,
				    dns_rdatatype_hip, &source, &dctx,
				    0, &target);
	dns_decompress_invalidate(&dctx);
Evan Hunt's avatar
Evan Hunt committed
1237
	assert_int_equal(result, DNS_R_FORMERR);
1238 1239
}

1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300
/*
 * ISDN tests.
 *
 * RFC 1183:
 *
 * 3.2. The ISDN RR
 *
 *    The ISDN RR is defined with mnemonic ISDN and type code 20 (decimal).
 *
 *    An ISDN (Integrated Service Digital Network) number is simply a
 *    telephone number.  The intent of the members of the CCITT is to
 *    upgrade all telephone and data network service to a common service.
 *
 *    The numbering plan (E.163/E.164) is the same as the familiar
 *    international plan for POTS (an un-official acronym, meaning Plain
 *    Old Telephone Service).  In E.166, CCITT says "An E.163/E.164
 *    telephony subscriber may become an ISDN subscriber without a number
 *    change."
 *
 *    ISDN has the following format:
 *
 *    <owner> <ttl> <class> ISDN <ISDN-address> <sa>
 *
 *    The <ISDN-address> field is required; <sa> is optional.
 *
 *    <ISDN-address> identifies the ISDN number of <owner> and DDI (Direct
 *    Dial In) if any, as defined by E.164 [8] and E.163 [7], the ISDN and
 *    PSTN (Public Switched Telephone Network) numbering plan.  E.163
 *    defines the country codes, and E.164 the form of the addresses.  Its
 *    format in master files is a <character-string> syntactically
 *    identical to that used in TXT and HINFO.
 *
 *    <sa> specifies the subaddress (SA).  The format of <sa> in master
 *    files is a <character-string> syntactically identical to that used in
 *    TXT and HINFO.
 *
 *    The format of ISDN is class insensitive.  ISDN RRs cause no
 *    additional section processing.
 *
 *    The <ISDN-address> is a string of characters, normally decimal
 *    digits, beginning with the E.163 country code and ending with the DDI
 *    if any.  Note that ISDN, in Q.931, permits any IA5 character in the
 *    general case.
 *
 *    The <sa> is a string of hexadecimal digits.  For digits 0-9, the
 *    concrete encoding in the Q.931 call setup information element is
 *    identical to BCD.
 *
 *    For example:
 *
 *    Relay.Prime.COM.   IN   ISDN      150862028003217
 *    sh.Prime.COM.      IN   ISDN      150862028003217 004
 *
 *    (Note: "1" is the country code for the North American Integrated
 *    Numbering Area, i.e., the system of "area codes" familiar to people
 *    in those countries.)
 *
 *    The RR data is the ASCII representation of the digits.  It is encoded
 *    as one or two <character-string>s, i.e., count followed by
 *    characters.
 */
Evan Hunt's avatar
Evan Hunt committed
1301 1302
static void
isdn(void **state) {
1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323
	wire_ok_t wire_ok[] = {
		/*
		 * "".
		 */
		WIRE_VALID(0x00),
		/*
		 * "\001".
		 */
		WIRE_VALID(0x01, 0x01),
		/*
		 * "\001" "".
		 */
		WIRE_VALID(0x01, 0x01, 0x00),
		/*
		 * "\001" "\001".
		 */
		WIRE_VALID(0x01, 0x01, 0x01, 0x01),
		/*
		 * Sentinel.
		 */
		WIRE_SENTINEL()
1324 1325
	};

Evan Hunt's avatar
Evan Hunt committed
1326
	UNUSED(state);
1327

1328
	check_rdata(NULL, wire_ok, NULL, false, dns_rdataclass_in,
1329
		    dns_rdatatype_isdn, sizeof(dns_rdata_isdn_t));
1330 1331
}

Mark Andrews's avatar
Mark Andrews committed
1332 1333 1334 1335 1336 1337 1338 1339 1340
/*
 * http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt
 *
 * The RDATA portion of both the NIMLOC and EID records contains
 * uninterpreted binary data.  The representation in the text master file
 * is an even number of hex characters (0 to 9, a to f), case is not
 * significant.  For readability, whitespace may be included in the value
 * field and should be ignored when reading a master file.
 */
Evan Hunt's avatar
Evan Hunt committed
1341 1342
static void
nimloc(void **state) {
Mark Andrews's avatar
Mark Andrews committed
1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363
	text_ok_t text_ok[] = {
		TEXT_VALID("AABBCC"),
		TEXT_VALID_CHANGED("AA bb cc", "AABBCC"),
		TEXT_INVALID("aab"),
		/*
		 * Sentinel.
		 */
		TEXT_SENTINEL()
	};
	wire_ok_t wire_ok[] = {
		/*
		 * Too short.
		 */
		WIRE_INVALID(),
		WIRE_VALID(0x00),
		/*
		 * Sentinel.
		 */
		WIRE_SENTINEL()
	};

Evan Hunt's avatar
Evan Hunt committed
1364
	UNUSED(state);
Mark Andrews's avatar
Mark Andrews committed
1365

1366
	check_rdata(text_ok, wire_ok, NULL, false, dns_rdataclass_in,
Mark Andrews's avatar
Mark Andrews committed
1367 1368 1369
		    dns_rdatatype_nimloc, sizeof(dns_rdata_in_nimloc_t));
}

1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435
/*
 * NSEC tests.
 *
 * RFC 4034:
 *
 * 4.1.  NSEC RDATA Wire Format
 *
 *   The RDATA of the NSEC RR is as shown below:
 *
 *                         1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
 *     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    /                      Next Domain Name                         /
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    /                       Type Bit Maps                           /
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *
 * 4.1.1.  The Next Domain Name Field
 *
 *    The Next Domain field contains the next owner name (in the canonical
 *    ordering of the zone) that has authoritative data or contains a
 *    delegation point NS RRset; see Section 6.1 for an explanation of
 *    canonical ordering.  The value of the Next Domain Name field in the
 *    last NSEC record in the zone is the name of the zone apex (the owner
 *    name of the zone's SOA RR).  This indicates that the owner name of
 *    the NSEC RR is the last name in the canonical ordering of the zone.
 *
 *    A sender MUST NOT use DNS name compression on the Next Domain Name
 *    field when transmitting an NSEC RR.
 *
 *    Owner names of RRsets for which the given zone is not authoritative
 *    (such as glue records) MUST NOT be listed in the Next Domain Name
 *    unless at least one authoritative RRset exists at the same owner
 *    name.
 *
 * 4.1.2.  The Type Bit Maps Field
 *
 *    The Type Bit Maps field identifies the RRset types that exist at the
 *    NSEC RR's owner name.
 *
 *    The RR type space is split into 256 window blocks, each representing
 *    the low-order 8 bits of the 16-bit RR type space.  Each block that
 *    has at least one active RR type is encoded using a single octet
 *    window number (from 0 to 255), a single octet bitmap length (from 1
 *    to 32) indicating the number of octets used for the window block's
 *    bitmap, and up to 32 octets (256 bits) of bitmap.
 *
 *    Blocks are present in the NSEC RR RDATA in increasing numerical
 *    order.
 *
 *       Type Bit Maps Field = ( Window Block # | Bitmap Length | Bitmap )+
 *
 *       where "|" denotes concatenation.
 *
 *    Each bitmap encodes the low-order 8 bits of RR types within the
 *    window block, in network bit order.  The first bit is bit 0.  For
 *    window block 0, bit 1 corresponds to RR type 1 (A), bit 2 corresponds
 *    to RR type 2 (NS), and so forth.  For window block 1, bit 1
 *    corresponds to RR type 257, and bit 2 to RR type 258.  If a bit is
 *    set, it indicates that an RRset of that type is present for the NSEC
 *    RR's owner name.  If a bit is clear, it indicates that no RRset of
 *    that type is present for the NSEC RR's owner name.
 *
 *    Bits representing pseudo-types MUST be clear, as they do not appear
 *    in zone data.  If encountered, they MUST be ignored upon being read.
 */
Evan Hunt's avatar
Evan Hunt committed
1436 1437
static void
nsec(void **state) {
1438 1439 1440 1441 1442
	text_ok_t text_ok[] = {
		TEXT_INVALID(""),
		TEXT_INVALID("."),
		TEXT_VALID(". RRSIG"),
		TEXT_SENTINEL()
1443
	};
1444 1445 1446 1447 1448 1449
	wire_ok_t wire_ok[] = {
		WIRE_INVALID(0x00),
		WIRE_INVALID(0x00, 0x00),
		WIRE_INVALID(0x00, 0x00, 0x00),
		WIRE_VALID(0x00, 0x00, 0x01, 0x02),
		WIRE_INVALID()
1450 1451
	};

Evan Hunt's avatar
Evan Hunt committed
1452
	UNUSED(state);
1453

1454
	check_rdata(text_ok, wire_ok, NULL, false, dns_rdataclass_in,
1455
		    dns_rdatatype_nsec, sizeof(dns_rdata_nsec_t));
1456 1457
}

1458 1459 1460 1461 1462
/*
 * NSEC3 tests.
 *
 * RFC 5155.
 */
Evan Hunt's avatar
Evan Hunt committed
1463 1464
static void
nsec3(void **state) {
1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477
	text_ok_t text_ok[] = {
		TEXT_INVALID(""),
		TEXT_INVALID("."),
		TEXT_INVALID(". RRSIG"),
		TEXT_INVALID("1 0 10 76931F"),
		TEXT_INVALID("1 0 10 76931F IMQ912BREQP1POLAH3RMONG;UED541AS"),
		TEXT_INVALID("1 0 10 76931F IMQ912BREQP1POLAH3RMONG;UED541AS A RRSIG"),
		TEXT_VALID("1 0 10 76931F AJHVGTICN6K0VDA53GCHFMT219SRRQLM A RRSIG"),
		TEXT_VALID("1 0 10 76931F AJHVGTICN6K0VDA53GCHFMT219SRRQLM"),
		TEXT_VALID("1 0 10 - AJHVGTICN6K0VDA53GCHFMT219SRRQLM"),
		TEXT_SENTINEL()
	};

Evan Hunt's avatar
Evan Hunt committed
1478
	UNUSED(state);
1479