1/*	$NetBSD: t_master.c,v 1.3.4.1 2012/06/05 21:15:53 bouyer Exp $	*/
2
3/*
4 * Copyright (C) 2004, 2005, 2007, 2009, 2011  Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1998-2001, 2003  Internet Software Consortium.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20/* Id: t_master.c,v 1.41 2011/03/12 04:59:46 tbox Exp  */
21
22#include <config.h>
23
24#include <ctype.h>
25#include <stdlib.h>
26
27#include <isc/buffer.h>
28#include <isc/mem.h>
29#include <isc/string.h>		/* Required for HP/UX (and others?) */
30#include <isc/util.h>
31
32#include <dns/callbacks.h>
33#include <dns/master.h>
34#include <dns/name.h>
35#include <dns/rdataclass.h>
36#include <dns/rdataset.h>
37#include <dns/result.h>
38
39#include <tests/t_api.h>
40
41#define	BUFLEN		255
42#define	BIGBUFLEN	(64 * 1024)
43
44static isc_result_t
45t1_add_callback(void *arg, dns_name_t *owner, dns_rdataset_t *dataset);
46
47isc_mem_t	*T1_mctx;
48char		*Tokens[T_MAXTOKS + 1];
49
50static isc_result_t
51t1_add_callback(void *arg, dns_name_t *owner, dns_rdataset_t *dataset) {
52	char buf[BIGBUFLEN];
53	isc_buffer_t target;
54	isc_result_t result;
55
56	UNUSED(arg);
57
58	isc_buffer_init(&target, buf, BIGBUFLEN);
59	result = dns_rdataset_totext(dataset, owner, ISC_FALSE, ISC_FALSE,
60				     &target);
61	if (result != ISC_R_SUCCESS)
62		t_info("dns_rdataset_totext: %s\n", dns_result_totext(result));
63
64	return(result);
65}
66
67static int
68test_master(char *testfile, char *origin, char *class, isc_result_t exp_result)
69{
70	int			result;
71	int			len;
72	isc_result_t		isc_result;
73	isc_result_t		dns_result;
74	dns_name_t		dns_origin;
75	isc_buffer_t		source;
76	isc_buffer_t		target;
77	unsigned char		name_buf[BUFLEN];
78	dns_rdatacallbacks_t	callbacks;
79	dns_rdataclass_t	rdataclass;
80	isc_textregion_t	textregion;
81
82	if (T1_mctx == NULL)
83		isc_result = isc_mem_create(0, 0, &T1_mctx);
84	else
85		isc_result = ISC_R_SUCCESS;
86	if (isc_result != ISC_R_SUCCESS) {
87		t_info("isc_mem_create failed %d\n", isc_result);
88		return(T_UNRESOLVED);
89	}
90
91	len = strlen(origin);
92	isc_buffer_init(&source, origin, len);
93	isc_buffer_add(&source, len);
94	isc_buffer_setactive(&source, len);
95	isc_buffer_init(&target, name_buf, BUFLEN);
96	dns_name_init(&dns_origin, NULL);
97	dns_result = dns_name_fromtext(&dns_origin, &source, dns_rootname,
98				       0, &target);
99	if (dns_result != ISC_R_SUCCESS) {
100		t_info("dns_name_fromtext failed %s\n",
101				dns_result_totext(dns_result));
102		return(T_UNRESOLVED);
103	}
104
105	dns_rdatacallbacks_init_stdio(&callbacks);
106	callbacks.add = t1_add_callback;
107
108	textregion.base = class;
109	textregion.length = strlen(class);
110
111	dns_result = dns_rdataclass_fromtext(&rdataclass, &textregion);
112	if (dns_result != ISC_R_SUCCESS) {
113		t_info("dns_rdataclass_fromtext failed %s\n",
114				dns_result_totext(dns_result));
115		return(T_UNRESOLVED);
116	}
117
118	dns_result = dns_master_loadfile(	testfile,
119						&dns_origin,
120						&dns_origin,
121						rdataclass,
122						ISC_TRUE,
123						&callbacks,
124						T1_mctx);
125
126	if (dns_result == exp_result)
127		result = T_PASS;
128	else {
129		t_info("dns_master_loadfile: got %s, expected %s\n",
130			dns_result_totext(dns_result),
131			dns_result_totext(exp_result));
132		result = T_FAIL;
133	}
134	return(result);
135}
136
137static int
138test_master_x(const char *filename) {
139	FILE		*fp;
140	char		*p;
141	int		line;
142	int		cnt;
143	int		result;
144
145	result = T_UNRESOLVED;
146
147	fp = fopen(filename, "r");
148	if (fp != NULL) {
149		line = 0;
150		while ((p = t_fgetbs(fp)) != NULL) {
151
152			++line;
153
154			/*
155			 * Skip comment lines.
156			 */
157			if ((isspace(*p & 0xff)) || (*p == '#')) {
158				(void)free(p);
159				continue;
160			}
161
162			/*
163			 * Name of data file, origin, zclass, expected result.
164			 */
165			cnt = t_bustline(p, Tokens);
166			if (cnt == 4) {
167				result = test_master(Tokens[0], Tokens[1],
168					     Tokens[2],
169					     t_dns_result_fromtext(Tokens[3]));
170			} else {
171				t_info("bad format in %s at line %d\n",
172				       filename, line);
173			}
174
175			(void)free(p);
176		}
177		(void)fclose(fp);
178	} else {
179		t_info("Missing datafile %s\n", filename);
180	}
181	return(result);
182}
183
184static const char *a1 =	"dns_master_loadfile loads a valid master file and "
185			"returns ISC_R_SUCCESS";
186static void
187t1(void) {
188	int	result;
189	t_assert("dns_master_loadfile", 1, T_REQUIRED, "%s", a1);
190	result = test_master_x("dns_master_load_1_data");
191	t_result(result);
192}
193
194static const char *a2 =
195	"dns_master_loadfile returns ISC_R_UNEXPECTEDEND when the "
196	"masterfile input ends unexpectedly";
197
198static void
199t2(void) {
200	int	result;
201	t_assert("dns_master_loadfile", 2, T_REQUIRED, "%s", a2);
202	result = test_master_x("dns_master_load_2_data");
203	t_result(result);
204}
205
206static const char *a3 =	"dns_master_loadfile returns DNS_R_NOOWNER when the "
207			"an ownername is not specified";
208
209static void
210t3() {
211	int	result;
212	t_assert("dns_master_loadfile", 3, T_REQUIRED, "%s", a3);
213	result = test_master_x("dns_master_load_3_data");
214	t_result(result);
215}
216
217static const char *a4 =	"dns_master_loadfile accepts broken zone files "
218			"where the first record has an undefined TTL, "
219			"as long as it is a SOA";
220
221static void
222t4() {
223	int	result;
224	t_assert("dns_master_loadfile", 4, T_REQUIRED, "%s", a4);
225	result = test_master_x("dns_master_load_4_data");
226	t_result(result);
227}
228
229static const char *a5 =	"dns_master_loadfile returns DNS_R_BADCLASS when the "
230			"the record class did not match the zone class";
231
232static void
233t5() {
234	int	result;
235
236	t_assert("dns_master_loadfile", 5, T_REQUIRED, "%s", a5);
237	result = test_master_x("dns_master_load_5_data");
238
239	t_result(result);
240}
241
242static const char *a6 =
243	"dns_master_loadfile understands DNSKEY RR specifications "
244	"containing key material";
245
246static void
247t6() {
248	int	result;
249
250	t_assert("dns_master_loadfile", 6, T_REQUIRED, "%s", a6);
251	result = test_master_x("dns_master_load_6_data");
252
253	t_result(result);
254}
255
256static const char *a7 =
257	"dns_master_loadfile understands DNSKEY RR specifications "
258	"containing no key material";
259
260static void
261t7() {
262	int	result;
263
264	t_assert("dns_master_loadfile", 7, T_REQUIRED, "%s", a7);
265	result = test_master_x("dns_master_load_7_data");
266
267	t_result(result);
268}
269
270static const char *a8 =
271	"dns_master_loadfile understands $INCLUDE";
272
273static void
274t8() {
275	int	result;
276
277	t_assert("dns_master_loadfile", 8, T_REQUIRED, "%s", a8);
278	result = test_master_x("dns_master_load_8_data");
279
280	t_result(result);
281}
282
283static const char *a9 =
284	"dns_master_loadfile understands $INCLUDE with failure";
285
286static void
287t9() {
288	int	result;
289
290	t_assert("dns_master_loadfile", 9, T_REQUIRED, "%s", a9);
291	result = test_master_x("dns_master_load_9_data");
292
293	t_result(result);
294}
295
296static const char *a10 =
297	"dns_master_loadfile non-empty blank lines";
298
299static void
300t10() {
301	int	result;
302
303	t_assert("dns_master_loadfile", 10, T_REQUIRED, "%s", a10);
304	result = test_master_x("dns_master_load_10_data");
305
306	t_result(result);
307}
308
309static const char *a11 =
310	"dns_master_loadfile allow leading zeros in SOA";
311
312static void
313t11() {
314	int	result;
315
316	t_assert("dns_master_loadfile", 11, T_REQUIRED, "%s", a11);
317	result = test_master_x("dns_master_load_11_data");
318
319	t_result(result);
320}
321
322
323testspec_t	T_testlist[] = {
324	{	t1,	"ISC_R_SUCCESS"		},
325	{	t2,	"ISC_R_UNEXPECTEDEND"	},
326	{	t3,	"DNS_NOOWNER"		},
327	{	t4,	"DNS_NOTTL"		},
328	{	t5,	"DNS_BADCLASS"		},
329	{	t6,	"DNSKEY RR 1"		},
330	{	t7,	"DNSKEY RR 2"		},
331	{	t8,	"$INCLUDE"		},
332	{	t9,	"$INCLUDE w/ DNS_BADCLASS"	},
333	{	t10,	"non empty blank lines"	},
334	{	t11,	"leading zeros in serial"	},
335	{	NULL,	NULL			}
336};
337
338