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