1/*
2 * Copyright (C) 2004, 2005, 2007, 2009  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: name_test.c,v 1.43 2009/09/02 23:48:01 tbox Exp $ */
19
20#include <config.h>
21
22#include <stdlib.h>
23
24#include <isc/commandline.h>
25#include <isc/string.h>
26#include <isc/util.h>
27
28#include <dns/fixedname.h>
29#include <dns/result.h>
30
31static void
32print_wirename(isc_region_t *name) {
33	unsigned char *ccurr, *cend;
34
35	if (name->length == 0) {
36		printf("<empty wire name>\n");
37		return;
38	}
39	ccurr = name->base;
40	cend = ccurr + name->length;
41	while (ccurr != cend)
42		printf("%02x ", *ccurr++);
43	printf("\n");
44}
45
46static void
47print_name(dns_name_t *name) {
48	isc_result_t result;
49	isc_buffer_t source;
50	isc_region_t r;
51	char s[1000];
52
53	isc_buffer_init(&source, s, sizeof(s));
54	if (dns_name_countlabels(name) > 0)
55		result = dns_name_totext(name, ISC_FALSE, &source);
56	else
57		result = ISC_R_SUCCESS;
58	if (result == ISC_R_SUCCESS) {
59		isc_buffer_usedregion(&source, &r);
60		if (r.length > 0)
61			printf("%.*s\n", (int)r.length, r.base);
62		else
63			printf("<empty text name>\n");
64	} else
65		printf("error: %s\n", dns_result_totext(result));
66}
67
68int
69main(int argc, char *argv[]) {
70	char s[1000];
71	isc_result_t result;
72	dns_fixedname_t wname, wname2, oname, compname, downname;
73	isc_buffer_t source;
74	isc_region_t r;
75	dns_name_t *name, *origin, *comp, *down;
76	unsigned int downcase = 0;
77	size_t len;
78	isc_boolean_t quiet = ISC_FALSE;
79	isc_boolean_t concatenate = ISC_FALSE;
80	isc_boolean_t got_name = ISC_FALSE;
81	isc_boolean_t check_absolute = ISC_FALSE;
82	isc_boolean_t check_wildcard = ISC_FALSE;
83	isc_boolean_t test_downcase = ISC_FALSE;
84	isc_boolean_t inplace = ISC_FALSE;
85	isc_boolean_t want_split = ISC_FALSE;
86	unsigned int labels, split_label = 0;
87	dns_fixedname_t fprefix, fsuffix;
88	dns_name_t *prefix, *suffix;
89	int ch;
90
91	while ((ch = isc_commandline_parse(argc, argv, "acdiqs:w")) != -1) {
92		switch (ch) {
93		case 'a':
94			check_absolute = ISC_TRUE;
95			break;
96		case 'c':
97			concatenate = ISC_TRUE;
98			break;
99		case 'd':
100			test_downcase = ISC_TRUE;
101			break;
102		case 'i':
103			inplace = ISC_TRUE;
104			break;
105		case 'q':
106			quiet = ISC_TRUE;
107			break;
108		case 's':
109			want_split = ISC_TRUE;
110			split_label = atoi(isc_commandline_argument);
111			break;
112		case 'w':
113			check_wildcard = ISC_TRUE;
114			break;
115		}
116	}
117
118	argc -= isc_commandline_index;
119	argv += isc_commandline_index;
120
121	if (argc > 0) {
122		if (strcasecmp("none", argv[0]) == 0)
123			origin = NULL;
124		else {
125			len = strlen(argv[0]);
126			isc_buffer_init(&source, argv[0], len);
127			isc_buffer_add(&source, len);
128			dns_fixedname_init(&oname);
129			origin = &oname.name;
130			result = dns_name_fromtext(origin, &source,
131						   dns_rootname, 0, NULL);
132			if (result != 0) {
133				fprintf(stderr,
134					"dns_name_fromtext() failed: %d\n",
135					result);
136				exit(1);
137			}
138		}
139	} else if (concatenate)
140		origin = NULL;
141	else
142		origin = dns_rootname;
143
144	if (argc >= 1) {
145		if (strcasecmp("none", argv[1]) == 0)
146			comp = NULL;
147		else {
148			len = strlen(argv[1]);
149			isc_buffer_init(&source, argv[1], len);
150			isc_buffer_add(&source, len);
151			dns_fixedname_init(&compname);
152			comp = &compname.name;
153			result = dns_name_fromtext(comp, &source, origin,
154						   0, NULL);
155			if (result != 0) {
156				fprintf(stderr,
157					"dns_name_fromtext() failed: %d\n",
158					result);
159				exit(1);
160			}
161		}
162	} else
163		comp = NULL;
164
165	dns_fixedname_init(&wname);
166	name = dns_fixedname_name(&wname);
167	dns_fixedname_init(&wname2);
168	while (fgets(s, sizeof(s), stdin) != NULL) {
169		len = strlen(s);
170		if (len > 0U && s[len - 1] == '\n') {
171			s[len - 1] = '\0';
172			len--;
173		}
174		isc_buffer_init(&source, s, len);
175		isc_buffer_add(&source, len);
176
177		if (len > 0U)
178			result = dns_name_fromtext(name, &source, origin,
179						   downcase, NULL);
180		else {
181			if (name == dns_fixedname_name(&wname))
182				dns_fixedname_init(&wname);
183			else
184				dns_fixedname_init(&wname2);
185			result = ISC_R_SUCCESS;
186		}
187
188		if (result != ISC_R_SUCCESS) {
189			printf("%s\n", dns_result_totext(result));
190			if (name == dns_fixedname_name(&wname))
191				dns_fixedname_init(&wname);
192			else
193				dns_fixedname_init(&wname2);
194			continue;
195		}
196
197		if (check_absolute && dns_name_countlabels(name) > 0) {
198			if (dns_name_isabsolute(name))
199				printf("absolute\n");
200			else
201				printf("relative\n");
202		}
203		if (check_wildcard && dns_name_countlabels(name) > 0) {
204			if (dns_name_iswildcard(name))
205				printf("wildcard\n");
206			else
207				printf("not wildcard\n");
208		}
209		dns_name_toregion(name, &r);
210		if (!quiet) {
211			print_wirename(&r);
212			printf("%u labels, %u bytes.\n",
213			       dns_name_countlabels(name), r.length);
214		}
215
216		if (concatenate) {
217			if (got_name) {
218				printf("Concatenating.\n");
219				result = dns_name_concatenate(&wname.name,
220							      &wname2.name,
221							      &wname2.name,
222							      NULL);
223				name = &wname2.name;
224				if (result == ISC_R_SUCCESS) {
225					if (check_absolute &&
226					    dns_name_countlabels(name) > 0) {
227						if (dns_name_isabsolute(name))
228							printf("absolute\n");
229						else
230							printf("relative\n");
231					}
232					if (check_wildcard &&
233					    dns_name_countlabels(name) > 0) {
234						if (dns_name_iswildcard(name))
235							printf("wildcard\n");
236						else
237							printf("not "
238							       "wildcard\n");
239					}
240					dns_name_toregion(name, &r);
241					if (!quiet) {
242						print_wirename(&r);
243						printf("%u labels, "
244						       "%u bytes.\n",
245						   dns_name_countlabels(name),
246						       r.length);
247					}
248				} else
249					printf("%s\n",
250					       dns_result_totext(result));
251				got_name = ISC_FALSE;
252			} else
253				got_name = ISC_TRUE;
254		}
255		isc_buffer_init(&source, s, sizeof(s));
256		if (dns_name_countlabels(name) > 0)
257			result = dns_name_totext(name, ISC_FALSE, &source);
258		else
259			result = ISC_R_SUCCESS;
260		if (result == ISC_R_SUCCESS) {
261			isc_buffer_usedregion(&source, &r);
262			if (r.length > 0)
263				printf("%.*s\n", (int)r.length, r.base);
264			else
265				printf("<empty text name>\n");
266			if (!quiet) {
267				printf("%u bytes.\n", source.used);
268			}
269		} else
270			printf("%s\n", dns_result_totext(result));
271
272		if (test_downcase) {
273			if (inplace) {
274				down = name;
275			} else {
276				dns_fixedname_init(&downname);
277				down = dns_fixedname_name(&downname);
278			}
279			result = dns_name_downcase(name, down, NULL);
280			INSIST(result == ISC_R_SUCCESS);
281			if (!quiet) {
282				dns_name_toregion(down, &r);
283				print_wirename(&r);
284				printf("%u labels, %u bytes.\n",
285				       dns_name_countlabels(down),
286				       r.length);
287			}
288			isc_buffer_init(&source, s, sizeof(s));
289			print_name(down);
290		}
291
292		if (comp != NULL && dns_name_countlabels(name) > 0) {
293			int order;
294			unsigned int nlabels;
295			dns_namereln_t namereln;
296
297			namereln = dns_name_fullcompare(name, comp, &order,
298							&nlabels);
299			if (!quiet) {
300				if (order < 0)
301					printf("<");
302				else if (order > 0)
303					printf(">");
304				else
305					printf("=");
306				switch (namereln) {
307				case dns_namereln_contains:
308					printf(", contains");
309					break;
310				case dns_namereln_subdomain:
311					printf(", subdomain");
312					break;
313				case dns_namereln_commonancestor:
314					printf(", common ancestor");
315					break;
316				default:
317					break;
318				}
319				if (namereln != dns_namereln_none &&
320				    namereln != dns_namereln_equal)
321					printf(", nlabels = %u", nlabels);
322				printf("\n");
323			}
324			printf("dns_name_equal() returns %s\n",
325			       dns_name_equal(name, comp) ? "TRUE" : "FALSE");
326		}
327
328		labels = dns_name_countlabels(name);
329		if (want_split && split_label < labels) {
330			dns_fixedname_init(&fprefix);
331			prefix = dns_fixedname_name(&fprefix);
332			dns_fixedname_init(&fsuffix);
333			suffix = dns_fixedname_name(&fsuffix);
334			printf("splitting at label %u: ", split_label);
335			dns_name_split(name, split_label, prefix, suffix);
336			printf("\n    prefix = ");
337			print_name(prefix);
338			printf("    suffix = ");
339			print_name(suffix);
340		}
341
342		if (concatenate) {
343			if (got_name)
344				name = &wname2.name;
345			else
346				name = &wname.name;
347		}
348	}
349
350	return (0);
351}
352