xref: /freebsd/contrib/ldns/drill/drill_util.c (revision 69d94f4c7608e41505996559367450706e91fbb8)
1 /*
2  * util.c
3  * some handy function needed in drill and not implemented
4  * in ldns
5  * (c) 2005 NLnet Labs
6  *
7  * See the file LICENSE for the license
8  *
9  */
10 
11 #include "drill.h"
12 #include <ldns/ldns.h>
13 
14 #include <errno.h>
15 
16 static int
17 read_line(FILE *input, char *line, size_t len)
18 {
19 	int i;
20 	int c;
21 
22 	for (i = 0; i < (int)len-1; i++) {
23 		c = getc(input);
24 		if (c == EOF) {
25 			return -1;
26 		} else if (c != '\n') {
27 			line[i] = c;
28 		} else {
29 			break;
30 		}
31 	}
32 	line[i] = '\0';
33 	return i;
34 }
35 
36 /* key_list must be initialized with ldns_rr_list_new() */
37 ldns_status
38 read_key_file(const char *filename, ldns_rr_list *key_list, bool silently)
39 {
40 	int line_len = 0;
41 	int line_nr = 0;
42 	int key_count = 0;
43 	char line[LDNS_MAX_LINELEN];
44 	ldns_status status;
45 	FILE *input_file;
46 	ldns_rr *rr;
47 
48 	input_file = fopen(filename, "r");
49 	if (!input_file) {
50 		if (! silently) {
51 			fprintf(stderr, "Error opening %s: %s\n",
52 				filename, strerror(errno));
53 		}
54 		return LDNS_STATUS_ERR;
55 	}
56 	while (line_len >= 0) {
57 		line_len = (int) read_line(input_file, line, sizeof(line));
58 		line_nr++;
59 		if (line_len > 0 && line[0] != ';') {
60 			status = ldns_rr_new_frm_str(&rr, line, 0, NULL, NULL);
61 			if (status != LDNS_STATUS_OK) {
62 				if (! silently) {
63 					fprintf(stderr,
64 						"Error parsing DNSKEY RR "
65 						"in line %d: %s\n", line_nr,
66 						ldns_get_errorstr_by_id(status)
67 						);
68 				}
69 			} else if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_DNSKEY ||
70 					   ldns_rr_get_type(rr) == LDNS_RR_TYPE_DS) {
71 				ldns_rr_list_push_rr(key_list, rr);
72 				key_count++;
73 			} else {
74 				ldns_rr_free(rr);
75 			}
76 		}
77 	}
78 	fclose(input_file);
79 	if (key_count > 0) {
80 		return LDNS_STATUS_OK;
81 	} else {
82 		/*fprintf(stderr, "No keys read\n");*/
83 		return LDNS_STATUS_ERR;
84 	}
85 }
86 
87 ldns_rdf *
88 ldns_rdf_new_addr_frm_str(char *str)
89 {
90 	ldns_rdf *a;
91 
92 	a = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, str);
93 	if (!a) {
94 		/* maybe ip6 */
95 		a = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, str);
96 		if (!a) {
97 			return NULL;
98 		}
99 	}
100 	return a;
101 }
102 
103 static inline void
104 local_print_ds(FILE* out, const char* pre, ldns_rr* ds)
105 {
106 	if (out && ds) {
107 		fprintf(out, "%s", pre);
108 		ldns_rr_print(out, ds);
109 		ldns_rr_free(ds);
110 	}
111 }
112 
113 /*
114  * For all keys in a packet print the DS
115  */
116 void
117 print_ds_of_keys(ldns_pkt *p)
118 {
119 	ldns_rr_list *keys;
120 	uint16_t i;
121 	ldns_rr *ds;
122 
123 	/* TODO fix the section stuff, here or in ldns */
124 	keys = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_DNSKEY,
125 			LDNS_SECTION_ANSWER);
126 
127 	/* this also returns the question section rr, which does not
128 	 * have any data.... and this inturn crashes everything */
129 
130 	if (keys) {
131 		for (i = 0; i < ldns_rr_list_rr_count(keys); i++) {
132 			fprintf(stdout, ";\n; equivalent DS records for key %u:\n",
133 				(unsigned int)ldns_calc_keytag(ldns_rr_list_rr(keys, i)));
134 
135 			ds = ldns_key_rr2ds(ldns_rr_list_rr(keys, i), LDNS_SHA1);
136 			local_print_ds(stdout, "; sha1: ", ds);
137 			ds = ldns_key_rr2ds(ldns_rr_list_rr(keys, i), LDNS_SHA256);
138 			local_print_ds(stdout, "; sha256: ", ds);
139 		}
140 		ldns_rr_list_deep_free(keys);
141 	}
142 }
143 
144 static void
145 print_class_type(FILE *fp, ldns_rr *r)
146 {
147 	ldns_lookup_table *lt;
148         lt = ldns_lookup_by_id(ldns_rr_classes, ldns_rr_get_class(r));
149         if (lt) {
150                	fprintf(fp, " %s", lt->name);
151         } else {
152         	fprintf(fp, " CLASS%d", ldns_rr_get_class(r));
153         }
154 	/* okay not THE way - but the quickest */
155 	switch (ldns_rr_get_type(r)) {
156 		case LDNS_RR_TYPE_RRSIG:
157 			fprintf(fp, " RRSIG ");
158 			break;
159 		case LDNS_RR_TYPE_DNSKEY:
160 			fprintf(fp, " DNSKEY ");
161 			break;
162 		case LDNS_RR_TYPE_DS:
163 			fprintf(fp, " DS ");
164 			break;
165 		default:
166 			break;
167 	}
168 }
169 
170 
171 void
172 print_ds_abbr(FILE *fp, ldns_rr *ds)
173 {
174 	if (!ds || (ldns_rr_get_type(ds) != LDNS_RR_TYPE_DS)) {
175 		return;
176 	}
177 
178 	ldns_rdf_print(fp, ldns_rr_owner(ds));
179 	fprintf(fp, " %d", (int)ldns_rr_ttl(ds));
180 	print_class_type(fp, ds);
181 	ldns_rdf_print(fp, ldns_rr_rdf(ds, 0)); fprintf(fp, " ");
182 	ldns_rdf_print(fp, ldns_rr_rdf(ds, 1)); fprintf(fp, " ");
183 	ldns_rdf_print(fp, ldns_rr_rdf(ds, 2)); fprintf(fp, " ");
184 	ldns_rdf_print(fp, ldns_rr_rdf(ds, 3)); fprintf(fp, " ");
185 }
186 
187 /* print some of the elements of a signature */
188 void
189 print_rrsig_abbr(FILE *fp, ldns_rr *sig) {
190 	if (!sig || (ldns_rr_get_type(sig) != LDNS_RR_TYPE_RRSIG)) {
191 		return;
192 	}
193 
194 	ldns_rdf_print(fp, ldns_rr_owner(sig));
195 	fprintf(fp, " %d", (int)ldns_rr_ttl(sig));
196 	print_class_type(fp, sig);
197 
198 	/* print a number of rdf's */
199 	/* typecovered */
200 	ldns_rdf_print(fp, ldns_rr_rdf(sig, 0)); fprintf(fp, " ");
201 	/* algo */
202 	ldns_rdf_print(fp, ldns_rr_rdf(sig, 1)); fprintf(fp, " ");
203 	/* labels */
204 	ldns_rdf_print(fp, ldns_rr_rdf(sig, 2)); fprintf(fp, " (\n\t\t\t");
205 	/* expir */
206 	ldns_rdf_print(fp, ldns_rr_rdf(sig, 4)); fprintf(fp, " ");
207 	/* incep */
208 	ldns_rdf_print(fp, ldns_rr_rdf(sig, 5)); fprintf(fp, " ");
209 	/* key-id */
210 	ldns_rdf_print(fp, ldns_rr_rdf(sig, 6)); fprintf(fp, " ");
211 	/* key owner */
212 	ldns_rdf_print(fp, ldns_rr_rdf(sig, 7)); fprintf(fp, ")");
213 }
214 
215 void
216 print_dnskey_abbr(FILE *fp, ldns_rr *key)
217 {
218         if (!key || (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY)) {
219                 return;
220         }
221 
222         ldns_rdf_print(fp, ldns_rr_owner(key));
223         fprintf(fp, " %d", (int)ldns_rr_ttl(key));
224 	print_class_type(fp, key);
225 
226         /* print a number of rdf's */
227         /* flags */
228         ldns_rdf_print(fp, ldns_rr_rdf(key, 0)); fprintf(fp, " ");
229         /* proto */
230         ldns_rdf_print(fp, ldns_rr_rdf(key, 1)); fprintf(fp, " ");
231         /* algo */
232         ldns_rdf_print(fp, ldns_rr_rdf(key, 2));
233 
234 	if (ldns_rdf2native_int16(ldns_rr_rdf(key, 0)) == 256) {
235 		fprintf(fp, " ;{id = %u (zsk), size = %db}", (unsigned int)ldns_calc_keytag(key),
236 				(int)ldns_rr_dnskey_key_size(key));
237 		return;
238 	}
239 	if (ldns_rdf2native_int16(ldns_rr_rdf(key, 0)) == 257) {
240 		fprintf(fp, " ;{id = %u (ksk), size = %db}", (unsigned int)ldns_calc_keytag(key),
241 				(int)ldns_rr_dnskey_key_size(key));
242 		return;
243 	}
244 	fprintf(fp, " ;{id = %u, size = %db}", (unsigned int)ldns_calc_keytag(key),
245 			(int)ldns_rr_dnskey_key_size(key));
246 }
247 
248 void
249 print_rr_list_abbr(FILE *fp, ldns_rr_list *rrlist, const char *usr)
250 {
251 	size_t i;
252 	ldns_rr_type tp;
253 
254 	for(i = 0; i < ldns_rr_list_rr_count(rrlist); i++) {
255 		tp = ldns_rr_get_type(ldns_rr_list_rr(rrlist, i));
256 		if (i == 0 && tp != LDNS_RR_TYPE_RRSIG) {
257 			if (usr) {
258 				fprintf(fp, "%s ", usr);
259 			}
260 		}
261 		switch(tp) {
262 		case LDNS_RR_TYPE_DNSKEY:
263 			print_dnskey_abbr(fp, ldns_rr_list_rr(rrlist, i));
264 			break;
265 		case LDNS_RR_TYPE_RRSIG:
266 			print_rrsig_abbr(fp, ldns_rr_list_rr(rrlist, i));
267 			break;
268 		case LDNS_RR_TYPE_DS:
269 			print_ds_abbr(fp, ldns_rr_list_rr(rrlist, i));
270 			break;
271 		default:
272 			/* not handled */
273 			break;
274 		}
275 		fputs("\n", fp);
276 	}
277 }
278 
279 void *
280 xmalloc(size_t s)
281 {
282 	void *p;
283 
284 	p = malloc(s);
285 	if (!p) {
286 		printf("Mem failure\n");
287 		exit(EXIT_FAILURE);
288 	}
289 	return p;
290 }
291 
292 void *
293 xrealloc(void *p, size_t size)
294 {
295 	void *q;
296 
297 	q = realloc(p, size);
298 	if (!q) {
299 		printf("Mem failure\n");
300 		exit(EXIT_FAILURE);
301 	}
302 	return q;
303 }
304 
305 void
306 xfree(void *p)
307 {
308 	if (p) {
309 	        free(p);
310 	}
311 }
312