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