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