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