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